 Microsoft C Optimizing Compiler - v6.0


 CHRTDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\CHRTDEMO.C

 #include <stdlib.h>
 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #include <graph.h>
 #include <pgchart.h>
 #include "chrtdemo.h"

 /* Structures for system configuration and chart environment. */
 struct videoconfig vc;
 chartenv ce;

 /* Category variables.  */
 short cCat;
 char _far *aCat[MAXVALUES];

 /* Series variables.  */
 short cSeries;
 short _far acSeries[MAXSERIES];
 char _far *aSeriesName[MAXSERIES];

 /* Temporary holding array for all data. Data values for multi-series
  * bar, column, and line charts remain here. Data for other kinds of
  * charts are transferred to the arrays below.
  */
 float _far aValue[MAXSERIES][MAXVALUES];

 /* Data values for single-series charts. First array is used for
  * bar, column, line, and pie. First and second are both used for
  * single-series scatter.
  */
 float _far axValue[MAXVALUES];
 float _far ayValue[MAXVALUES];

 /* Data values for multi-series scatter charts.  */
 float _far axValueMS[MAXVALUES][MAXVALUES];
 float _far ayValueMS[MAXVALUES][MAXVALUES];

 /* Exploded flags for pie chart.  */
 short _far aExplode[MAXVALUES];

 /* Variable used to track control and screen position.  */
 struct SCREENINFO si;

 /* Colors of menus and prompts. */
 struct tagColor co;

 /* Flags to indicate whether to use imported or default data.  */
 BOOL fDefault = TRUE;

 /* Arrays of strings used by the Menu function. The first string is the
  * menu title. The next non-null strings are the menu selections. A null
  * string indicates the end of the list.
  */
 char *pszChartOpt[] =
     { "Options", "Screen Mode", "Windows", "Titles",
       "Axis (X and Y)", "Legend", "Fonts", "Reset", "" };

 char *pszChartType[] =
     { "Type", "Bar", "Column", "Line", "Scatter", "Pie", "" };

 char *pszMainMenu[] =
     { "Main Menu", "Demo", "View Chart", "Chart Type", "Options",
       "Show Chart Data", "Quit", "" };

 /* Sample data.  */
 #define O_JUICE 0
 #define I_TEA   1
 #define H_CHOC  2
 #define TEMPERATURE  3

 char _far *aQuarters[] =
     { "First", "Second", "Third", "Fourth" };

 char _far *aMonths[] =
     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

 float _far aSales[3][12] =
 {
     {  3.6F,  3.2F,  3.3F,  3.4F,  3.1F,  2.9F,
        3.0F,  3.6F,  3.2F,  3.3F,  3.5F,  3.9F },
     {  1.0F,  1.3F,  1.4F,  1.7F,  2.2F,  2.9F,
        2.9F,  3.1F,  2.6F,  1.8F,  1.1F,  1.2F },
     {  2.4F,  2.3F,  2.0F,  1.6F,  1.3F,  1.0F,
        0.9F,  0.8F,  1.1F,  1.4F,  1.9F,  2.5F }
 };

 float _far aTemperature[12] =
     {  2.9F,  3.2F,  3.9F,  4.8F,  6.0F,  6.5F,
        7.0F,  7.2F,  6.0F,  4.7F,  4.1F,  3.0F };

 char _far *aSalesTitles[] =
     { "Orange Juice Sales", "Iced Tea Sales", "Hot Chocolate Sales" };

 char *TempTitle = "Average Temperature";

 int main()
 {
     Initialize();
     MainMenu();

     /* Reset the video mode and screen colors prior to leaving. */
     _setvideomode( _DEFAULTMODE );
     _settextcolor( co.InfoColor );
     _clearscreen( _GCLEARSCREEN );

     return 0;
 }

 /*  ChartOptions - Gets chart options.
  *
  *  Params: None
  */
 void ChartOptions()
 {
     int iChoice;

     PushTitle( pszChartOpt[0] );
     while( (iChoice = Menu( pszChartOpt )) != ESCAPE )
     {

         /* Get chart options.  */
         switch( iChoice )
         {

             /* Branch to the appropriate menu.  */
             case 1:
                 ScreenMode();
                 break;

             case 2:
                 Windows();
                 break;

             case 3:
                 Titles();
                 break;

             case 4:
                 Axes();
                 break;

             case 5:
                 Legend();
                 break;

             case 6:
                 FontOptions();
                 break;

             case 7:
                 ResetOptions();
                 break;

         }
     }
     PopTitle();
 }

 /*  ChartType - Gets chart type.
  *
  *  Params: None
  */
 void ChartType()
 {
     int iChoice;

     /* Get chart type.  */
     PushTitle( pszChartType[0] );
     iChoice = Menu( pszChartType );

     if( iChoice != ESCAPE )
     {
         /* Set the chart type, and get the chart style.  */
         ce.charttype = iChoice;
         switch( iChoice )
         {

             case 1:
             case 2:
                 iChoice = BlankMenu( "Style", "Plain Bars", "Stacked Bars" );
                 break;

             case 3:
             case 4:
                 iChoice = BlankMenu( "Style", "Lines-Points", "Points Only" )
                 break;

             case 5:
                 iChoice = BlankMenu( "Style", "Percent", "No Percent" );
         }

         if( iChoice != ESCAPE)
             ce.chartstyle = iChoice;

         /* Set default data without changing environment defaults.  */
         DefaultData( ce.charttype, ce.chartstyle, FALSE );
         PopTitle();
     }
     PopTitle();
 }

 /*  ClearData - Clears category and value data.
  *
  *  Params: fConfirm - flag specifying whether to query for confirmation
  */
 void ClearData( BOOL fConfirm )
 {
     char chResponse = 'Y';
     int iCat;

     WrtForm( 18 );

     /* Query for confirmation.  */
     if( fConfirm )
         chResponse = InputCh( "Are you sure? ", "YN\x1b" );

     if( chResponse == 'Y' )
     {

         /* Clear all relevant data.  */
         for( iCat = 0; iCat < cCat; iCat++ )
             aCat[iCat] = NULL;
         cCat = 0;
         cSeries = 0;
     }
 }

 /*  DefaultData - Initializes default data for each kind of chart.
  *
  *  Params: iType - Chart type to be initialized
  *          iStyle - Chart style
  *          fClear - Signal to clear all defaults
  */
 void DefaultData( short iType, short iStyle, BOOL fClear )
 {
     int iCat, iValue, iSubValue, iSeries;

     /* Call default chart to clear old values.  */
     if( fClear )
         _pg_defaultchart( &ce, iType, iStyle );

     /* Initialize category titles.  */
     cCat = 12;
     for( iCat = 0; iCat < cCat; iCat++ )
         aCat[iCat] = aMonths[iCat];

     switch( ce.charttype )
     {

         /* Initialize data for each chart type.  */
         case _PG_BARCHART:

             strcpy( ce.maintitle.title, "Orange Juice and Iced Tea Sales" );
             cSeries = 2;
             for( iSeries = 0; iSeries < cSeries; iSeries++ )
             {
                 aSeriesName[iSeries] = aSalesTitles[iSeries];
                 acSeries[iSeries] = cCat;
                 for( iValue = 0; iValue < cCat; iValue++ )
                     aValue[iSeries][iValue]  = (float)aSales[iSeries][iValue]
             }
             break;

         case _PG_COLUMNCHART:

             strcpy( ce.maintitle.title, "Orange Juice Sales" );
             cSeries = 1;
             for( iSeries = 0; iSeries < cSeries; iSeries++ )
             {
                 aSeriesName[iSeries] = aSalesTitles[iSeries];
                 acSeries[iSeries] = cCat;
                 for( iValue = 0; iValue < cCat; iValue++ )
                     aValue[iSeries][iValue]  = (float)aSales[iSeries][iValue]
             }
             break;

         case _PG_LINECHART:

             strcpy( ce.maintitle.title, "Beverage Sales" );
             cSeries = 3;
             for( iSeries = 0; iSeries < cSeries; iSeries++ )
             {
                 aSeriesName[iSeries] = aSalesTitles[iSeries];
                 acSeries[iSeries] = cCat;
                 for( iValue = 0; iValue < cCat; iValue++ )
                     aValue[iSeries][iValue] = (float)aSales[iSeries][iValue];
             }
             break;

         case _PG_SCATTERCHART:

             strcpy( ce.maintitle.title,
                     "Average Temperature Compared to Beverage Sales" );
             /* ce.chartstyle = _PG_POINTONLY; */
             cSeries = 4;

             aSeriesName[0] = aSalesTitles[I_TEA];
             aSeriesName[2] = aSalesTitles[H_CHOC];
             acSeries[0] = acSeries[1] = acSeries[2] = acSeries[3] = 12;
             for( iValue = 0; iValue < 12; iValue++ )
             {
                 aValue[0][iValue]  = (float)aSales[I_TEA][iValue] ;
                 aValue[1][iValue]  = (float)aSales[TEMPERATURE][iValue] ;
                 aValue[2][iValue]  = (float)aSales[H_CHOC][iValue] ;
                 aValue[3][iValue]  = (float)aSales[TEMPERATURE][iValue] ;
             }
             break;

         case _PG_PIECHART:
         default:

             strcpy( ce.maintitle.title, "Iced Tea Sales" );
             cCat = 4;
             for( iCat = 0; iCat < cCat; iCat++ )
                 aCat[iCat] = aQuarters[iCat];

             cSeries = 1;
             aSeriesName[0] = aSalesTitles[I_TEA];
             acSeries[0] = cCat;

             for( iValue = 0; iValue < cCat; iValue++ )
             {
                 aValue[0][iValue] = 0.0;
                 for( iSubValue = 0; iSubValue < 3; iSubValue++ )
                     aValue[0][iValue] += (float)aSales[I_TEA][iSubValue * iVa
             }
             aExplode[3] = 1;
             break;
     }
 }

 /*  Demo - Displays a series of sample charts.
  *
  *  Params: None
  */
 void Demo()
 {
     int  cValue;
     palettetype palette_struct;

     /* Display the sample data in spreadsheet form. */
     ShowSampleData();

     DefaultData( _PG_PIECHART, _PG_NOPERCENT, TRUE );

     /* Set video mode and draw charts. For each chart, set default
      * data and modify any desired environment fields. If error,
      * terminate demo.
      */
     _setvideomode( si.mode );

     cValue = 4;
     strcpy( ce.subtitle.title, "Default Pie Chart" );
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     strcpy( ce.subtitle.title, "Customized Pie Chart" );
     ce.chartstyle = _PG_PERCENT;
     ce.legend.place = _PG_BOTTOM;
     if (si.fColor)
     {
         ce.maintitle.titlecolor = ce.subtitle.titlecolor = 0;
         ce.chartwindow.background = 1;
         ce.datawindow.background = ce.legend.legendwindow.background = 6;
         ce.legend.textcolor = 1;
     }
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     cValue = 12;
     DefaultData( _PG_BARCHART, _PG_PLAINBARS, TRUE );
     strcpy( ce.subtitle.title, "Default Bar Chart" );
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     strcpy( ce.subtitle.title, "Customized Stacked Bar Chart" );
     strcpy( ce.xaxis.axistitle.title, "Sales in Thousands" );
     strcpy( ce.yaxis.axistitle.title, "Month" );
     ce.chartstyle = _PG_STACKEDBARS;
     ce.legend.place = _PG_RIGHT;
     ce.xaxis.ticdecimals = 2;
     if (si.fColor)
     {
         ce.maintitle.titlecolor = ce.subtitle.titlecolor = 12;
         ce.chartwindow.background = 7;
         ce.datawindow.background = 8;
         ce.legend.textcolor = 0;
         ce.legend.legendwindow.background = 8;
         ce.legend.autosize = FALSE;
         ce.legend.legendwindow.y1 = vc.numypixels - 85;
         ce.legend.legendwindow.y2 = vc.numypixels - 45;
     }
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     DefaultData( _PG_COLUMNCHART, _PG_PLAINBARS, TRUE );
     strcpy( ce.subtitle.title, "Default Column Chart" );
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     strcpy( ce.subtitle.title, "Customized Column Chart" );
     strcpy( ce.xaxis.axistitle.title, "Month" );
     strcpy( ce.yaxis.axistitle.title, "Sales in Thousands" );
     ce.legend.place = _PG_BOTTOM;
     if (si.fColor)
     {
         ce.maintitle.titlecolor     = 0;
         ce.subtitle.titlecolor     = 0;
         ce.chartwindow.background = 8;
         ce.datawindow.background = 2;
         ce.legend.legendwindow.background = 10;
     }
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     DefaultData( _PG_LINECHART, _PG_POINTANDLINE, TRUE );
     strcpy( ce.subtitle.title, "Default Line Chart" );
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     strcpy( ce.subtitle.title, "Customized Line Chart" );
     strcpy( ce.xaxis.axistitle.title, "Month" );
     strcpy( ce.yaxis.axistitle.title, "Sales in Thousands" );
     ce.legend.place = _PG_RIGHT;
     if (si.fColor)
     {
         ce.maintitle.titlecolor = 1;
         ce.subtitle.titlecolor = 1;
         ce.chartwindow.background = 3;
         ce.datawindow.background = 7;
         ce.legend.legendwindow.background = 7;
         ce.legend.autosize = FALSE;
         ce.legend.legendwindow.y1 = vc.numypixels - 85;
         ce.legend.legendwindow.y2 = vc.numypixels - 45;
     }
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     DefaultData( _PG_SCATTERCHART, _PG_POINTONLY, TRUE );
     strcpy( ce.subtitle.title, "Default Scatter Chart" );
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     cSeries = 4;
     strcpy( ce.subtitle.title, "Customized Scatter Chart" );
     strcpy( ce.xaxis.axistitle.title, "Sales in Thousands" );
     strcpy( ce.yaxis.axistitle.title, "Average Temperature" );
     ce.legend.place = _PG_RIGHT;
     if (si.fColor)
     {
         ce.maintitle.titlecolor = 0;
         ce.subtitle.titlecolor = 0;
         ce.chartwindow.background = 4;
         ce.datawindow.background = 8;
         ce.legend.legendwindow.background = 8;
         ce.legend.autosize = FALSE;
         ce.legend.legendwindow.y1 = vc.numypixels - 85;
         ce.legend.legendwindow.y2 = vc.numypixels - 45;
     }
     if( ViewChart() )
         return;
     else
         _clearscreen( _GCLEARSCREEN );

     DefaultData( _PG_BARCHART, _PG_PERCENT, TRUE );
 }

 /*  FindVideoMode - Finds the "best" video mode for the adaptor in use.
  *
  *  Params: vc - structure of type struct videoconfig
  *
  *  Returns: Best mode
  */
 int FindVideoMode( struct videoconfig vc )
 {
     switch( vc.adapter )
     {
         case _CGA:
         case _OCGA:
             return _HRESBW;
         case _EGA:
                 case _OEGA:
                         return( vc.monitor == _MONO ) ? _ERESNOCOLOR : _ERESC
         case _VGA:
         case _OVGA:
         case _MCGA:
             return _VRES16COLOR;
         case _HGC:
             return _HERCMONO;
         default:
             return _DEFAULTMODE;
     }
 }

 /*  Initialize - Does various initialization tasks.
  *
  *  Params: None
  */
 void Initialize( void )
 {
     int iSeries, iValue;

     /* Initialize all value arrays to missing.  */
     for( iSeries = 0; iSeries < MAXSERIES; iSeries++ )
     {

         axValue[iSeries] = _PG_MISSINGVALUE;
         ayValue[iSeries] = _PG_MISSINGVALUE;

         for( iValue = 0; iValue < MAXVALUES; iValue++ )
             aValue[iSeries][iValue] = _PG_MISSINGVALUE;

         for( iValue = 0; iValue < MAXVALUES; iValue++ )
         {
             axValueMS[iSeries][iValue] = _PG_MISSINGVALUE;
             ayValueMS[iSeries][iValue] = _PG_MISSINGVALUE;
         }
     }

     /* Initialize zero sets. */
     cSeries = 0;

     /* Initialize default chart environment, screen mode, and data.  */
     _pg_initchart();
     _getvideoconfig( &vc );

     /* Find the best available mode for display.
      * Don't set 256 color, medium resolution (_MRES256COLOR).
      */
     si.mode = FindVideoMode( vc );

     if( si.mode == _TEXTMONO )
     {
         _clearscreen( _GCLEARSCREEN );
         _outtext( "No graphics available.  Can't run chart demo." );
         exit( 1 );
     }

     SetDisplayColors();

     SetGraphMode( si.mode );
     DefaultData( _PG_BARCHART, _PG_PLAINBARS, TRUE );

     _setvideomode( _DEFAULTMODE );


 }

 /*  MainMenu - Manages the main menu.
  *
  *  Params: None
  */
 void MainMenu( void )
 {
     int iChoice;
     char chResponse = 'Y';
     char chVerify;

     PushTitle( pszMainMenu[0] );
     do
     {
         /* If the user selects Quit, iChoice will contain 6.  If the
          *   user presses ESCAPE, iChoice will be ESCAPE, which is
          *   equal to 27.  In any case, we can test both conditions
          *   by checking to see whether iChoice is less than 6.
          */
         while( (iChoice = Menu( pszMainMenu )) < 6 )
         {
             /* Get main menu selection.  */
             switch( iChoice )
             {

                 case 1:
                     /* Display demo charts.  */
                     Demo();
                     _setvideomode( _DEFAULTMODE );
                     break;

                 case 2:
                     /* Set graphics video mode, display current chart,
                      * and restore text video mode.
                      */
                     _setvideomode( si.mode );
                     ViewChart();
                     _setvideomode( _DEFAULTMODE );
                     break;

                 case 3:
                     /* Get chart type and style.  */
                     ChartType();
                     break;

                 case 4:
                     /* Get chart options.  */
                     ChartOptions();
                     break;
                 case 5:
                     /* Show chart data. */
                     ShowChartData();
                     break;

             }

         }

         /* If the user is trying to leave the program using the ESCAPE
          *   key, we must verify the choice.  This is done to prevent
          *   an eager typist from pressing ESCAPE one time too often
          *   and exiting at an unanticipated point.
          */
         if( iChoice == ESCAPE )
         {
             Help( "Press \"Q\" to Actually Quit", co.InputColor );

             putchar( BEEP );
             _settextposition( si.help - 1, 32 );
             chVerify = getch();
             if( tolower( chVerify ) != 'q' )
                 iChoice = 0;
             else
                 iChoice = 6;
         }

     } while( iChoice != 6 );
     PopTitle();
 }

 /*  ResetOptions - After confirmation, resets chart options to default.
  *
  *  Params: None
  */
 void ResetOptions()
 {
     char chResponse;

     /* Prompt for confirmation before setting default environment.  */
     ClrForm();
     Help( "Type  'Y' to reset all options, 'N' to keep them.", co.InputColor
     chResponse = InputCh( "Are you sure? ", "YN\x1b" );
     if( chResponse == 'Y' )
         _pg_defaultchart( &ce, 1, 1 );

 }

 /*  SetGraphMode - Tests the specified graphics mode and sets the xMax
  *  and yMax values in the si (Screen Information) structure.
  *
  *  Params: mode number
  *
  *  Return: FALSE if mode invalid, TRUE if valid
  */
 BOOL SetGraphMode(int mode)
 {
     if (!_setvideomode( mode ) )
         return FALSE;
     else
     {
         _getvideoconfig ( &vc );
         if( !vc.numxpixels )
             return FALSE;
         si.xMax = vc.numxpixels;
         si.yMax = vc.numypixels;
         si.mode = mode;

         /* Set flag to indicate whether multiple colors are available.  */
         si.fColor = iscolor( mode );

         return TRUE;
     }
 }

 /*  ShowChartData - Displays the data in the chart environment.
  *
  *  Params: None
  */
 void ShowChartData()
 {
     int iRow = 2;
     struct _fontinfo fd;
     static char *szContinue =
         "Press any key to continue, ESC to return to the menu.";

     _clearscreen( _GCLEARSCREEN );
     SprintAt( iRow++, 1, "short      charttype =  %d", ce.charttype );
     SprintAt( iRow++, 1, "short      chartstyle = %d", ce.chartstyle );
     SprintAt( iRow++, 1, "windowtype chartwindow =" );
     iRow = ShowWindowType( iRow, 1, ce.chartwindow );
     SprintAt( iRow++, 1, "windowtype datawindow =" );
     iRow = ShowWindowType( iRow, 1, ce.datawindow );
     SprintAt( ++iRow, 1, szContinue );
     if( getch() == ESCAPE )
         return;

     iRow = 2;
     _clearscreen( _GCLEARSCREEN );
     SprintAt( iRow++, 1, "titletype  maintitle =" );
     iRow = ShowTitleType( iRow, 1, ce.maintitle );
     SprintAt( iRow++, 1, "titletype   subtitle =" );
     iRow = ShowTitleType( iRow, 1, ce.subtitle );
     SprintAt( ++iRow, 1, szContinue );
     if( getch() == ESCAPE )
         return;

     iRow = 2;
     _clearscreen( _GCLEARSCREEN );
     SprintAt( iRow++, 1, "axistype       xaxis =" );
     iRow = ShowAxisType( iRow, 1, ce.xaxis );
     SprintAt( ++iRow, 1, szContinue );
     if( getch() == ESCAPE )
         return;

     iRow = 2;
     _clearscreen( _GCLEARSCREEN );
     SprintAt( iRow++, 1, "axistype       yaxis =" );
     iRow = ShowAxisType( iRow, 1, ce.yaxis );
     SprintAt( ++iRow, 1, szContinue );
     if( getch() == ESCAPE )
         return;

     iRow = 2;
     _clearscreen( _GCLEARSCREEN );
     SprintAt( iRow++, 1, "legendtype     legend =" );
     iRow = ShowLegendType( iRow, 1, ce.legend );
     SprintAt( ++iRow, 1, szContinue );
     if( getch() == ESCAPE )
         return;

     iRow = 2;
     _clearscreen( _GCLEARSCREEN );
     if( _getfontinfo( &fd ) != -1 )
     {
         SprintAt( iRow++, 1, "struct _fontinfo =" );
         iRow = ShowFontInfo( iRow, 1, fd );
         SprintAt( ++iRow, 1, "Press any key to continue . . ." );
         getch();
     }
 }

 /*  ShowAxisType - Displays data in a variable of type "axistype".
  *
  *  Params: iRow - Row at which to start
  *          iCol - Column from which to indent
  *          theAxis - Variable of type "axistype" to display
  *
  *  Return: Next available row
  */
 int ShowAxisType( int iRow, int iCol, axistype theAxis )
 {
     SprintAt( iRow++, iCol + 5, "short        .grid = %d", theAxis.grid );
     SprintAt( iRow++, iCol + 5, "short   .gridstyle = %d", theAxis.gridstyle
     SprintAt( iRow++, iCol + 5, "titletype axistitle=" );
     iRow = ShowTitleType( iRow, iCol + 5, theAxis.axistitle );
     SprintAt( iRow++, iCol + 5, "short   .axiscolor = %d", theAxis.axiscolor
     SprintAt( iRow++, iCol + 5, "short     .labeled = %s",
         (theAxis.labeled) ? "TRUE" : "FALSE" );
     SprintAt( iRow++, iCol + 5, "short   .rangetype = %d", theAxis.rangetype
     SprintAt( iRow++, iCol + 5, "float     .logbase = %f", theAxis.logbase );
     SprintAt( iRow++, iCol + 5, "short   .autoscale = %s",
         (theAxis.autoscale) ? "TRUE" : "FALSE" );
     SprintAt( iRow++, iCol + 5, "float    .scalemin = %f", theAxis.scalemin )
     SprintAt( iRow++, iCol + 5, "float    .scalemax = %f", theAxis.scalemax )
     SprintAt( iRow++, iCol + 5, "float .scalefactor = %f", theAxis.scalefacto
     iRow = ShowTitleType( iRow, iCol + 5, theAxis.scaletitle );
     SprintAt( iRow++, iCol + 5, "float  .ticinterval = %f", theAxis.ticinterv
     SprintAt( iRow++, iCol + 5, "short    .ticformat = %d", theAxis.ticformat
     SprintAt( iRow++, iCol + 5, "short  .ticdecimals = %d", theAxis.ticdecima

     return iRow;
 }

 /*  ShowFontInfo - Displays data in a variable of type "_fontinfo".
  *
  *  Params: iRow - Row at which to start
  *          iCol - Column from which to indent
  *          theFont - Variable of type "_fontinfo" to display
  *
  *  Return: Next available row
  */
 int ShowFontInfo( int iRow, int iCol, struct _fontinfo theFont )
 {
     SprintAt( iRow++, iCol + 5, "int          .type = %d", theFont.type );
     SprintAt( iRow++, iCol + 5, "int        .ascent = %d", theFont.ascent );
     SprintAt( iRow++, iCol + 5, "int      .pixwidth = %d", theFont.pixwidth )
     SprintAt( iRow++, iCol + 5, "int     .pixheight = %d", theFont.pixheight
     SprintAt( iRow++, iCol + 5, "int      .avgwidth = %d", theFont.avgwidth )
     SprintAt( iRow++, iCol + 5, "char     .filename = %s", theFont.filename )
     SprintAt( iRow++, iCol + 5, "char     .facename = %s", theFont.facename )

     return iRow;
 }

 /*  ShowLegendType - Displays data in a variable of type "legendtype".
  *
  *  Params: iRow - Row at which to start
  *          iCol - Column from which to indent
  *          theLegend - Variable of type "legendtype" to display
  *
  *  Return: Next available row
  */
 int ShowLegendType( int iRow, int iCol, legendtype theLegend )
 {
     SprintAt( iRow++, iCol + 5, "short      .legend = %s",
               (theLegend.legend) ? "TRUE" : "FALSE" );
     SprintAt( iRow++, iCol + 5, "short       .place = %d", theLegend.place );
     SprintAt( iRow++, iCol + 5, "short   .textcolor = %d", theLegend.textcolo
     SprintAt( iRow++, iCol + 5, "short    .autosize = %d", theLegend.autosize
     SprintAt( iRow++, iCol + 5, "windowtype legendwindow =" );
     iRow = ShowWindowType( iRow, iCol + 5, theLegend.legendwindow );

     return iRow;
 }

 /*  ShowSampleData - Displays the sample data for the demo.
  *
  *  Params: None
  */
 void ShowSampleData()
 {
     int  iCat, y, iSeries, iValue;
     char szTmp[80];

     /* Display data in table format. */
     _clearscreen( _GCLEARSCREEN );
     PrintAt( 1, 40 - strlen(szTmp) / 2, "Data in Table Format", -1 );

     /* Write titles and draw separator line. */
     y = 3;
     for( iCat = 1; iCat <= 12; iCat++ )
     PrintAt( y, iCat * 6, aMonths[iCat - 1], -1 );

     memset( szTmp, '-', 69 );
     szTmp[69] = 0;
     PrintAt( ++y, 6, szTmp, -1 );

     /* Write data. */
     for( iSeries = 1; iSeries <= 3; iSeries++ )
     {
         PrintAt( y += 2, 4, aSalesTitles[iSeries - 1], -1 );
         y += 2;
         for( iValue = 1; iValue <= 12; iValue++ )
         {
             sprintf( szTmp, "%#3.2f", aSales[iSeries - 1][iValue - 1] );
             PrintAt( y, iValue * 6, (char _far *)szTmp, -1 );
         }
     }
     PrintAt( y += 2, 4, TempTitle, -1 );
     y += 2;
     for( iValue = 1; iValue <= 12; iValue++ )
     {
         sprintf( szTmp, "%#3.1f", aTemperature[iValue - 1] );
         PrintAt( y, iValue * 6, szTmp, -1 );
     }

     PrintAt( y += 2, 1, "Press any key to continue . . .", -1 );
     getche();
 }

 /*  ShowTitleType - Displays data in a variable of type "titletype".
  *
  *  Params: iRow - Row at which to start
  *          iCol - Column from which to indent
  *          theTitle - Variable of type "titletype" to display
  *
  *  Return: Next available row
  */
 int ShowTitleType( int iRow, int iCol, titletype theTitle )
 {
     SprintAt( iRow++, iCol + 5, "char    .title[%d] = \"%s\"", _PG_TITLELEN,
                  theTitle.title );
     SprintAt( iRow++, iCol + 5, "short  .titlecolor = %d", theTitle.titlecolo
     SprintAt( iRow++, iCol + 5, "short     .justify = %d", theTitle.justify )

     return iRow;
 }

 /*  ShowWindowType - Displays data in a variable of type "windowtype".
  *
  *  Params: iRow - Row at which to start
  *          iCol - Column from which to indent
  *          theWindow - Variable of type "windowtype" to display
  *
  *  Return: Next available row
  */
 int ShowWindowType( int iRow, int iCol, windowtype theWindow )
 {
     SprintAt( iRow++, iCol + 5, "short          .x1 = %d", theWindow.x1 );
     SprintAt( iRow++, iCol + 5, "short          .y1 = %d", theWindow.y1 );
     SprintAt( iRow++, iCol + 5, "short          .x2 = %d", theWindow.x2 );
     SprintAt( iRow++, iCol + 5, "short          .y2 = %d", theWindow.y2 );
     SprintAt( iRow++, iCol + 5, "short      .border = %d", theWindow.border )
     SprintAt( iRow++, iCol + 5, "short  .background = %d", theWindow.backgrou
     SprintAt( iRow++, iCol + 5, "short .borderstyle = %d", theWindow.borderst
     SprintAt( iRow++, iCol + 5, "short .bordercolor = %d", theWindow.borderco

     return iRow;
 }

 /*  ShowError - Displays error message for one of the chart library
  *  errors.
  *
  *  Params: iErr - Error number
  */
 void ShowError( int iErr )
 {
     char szTmp[50];

     /* Change to text screen.  */
     _setvideomode( _DEFAULTMODE );

     /* Select the error text.  */
     switch( iErr )
     {
         case _PG_NOTINITIALIZED:
             strcpy( szTmp, "Chart Library Not Initialized" );
             break;
         case _PG_BADSCREENMODE:
             strcpy( szTmp, "Invalid Screen Mode" );
             break;
         case _PG_BADCHARTTYPE:
             strcpy( szTmp, "Invalid Chart Type" );
             break;
         case _PG_BADCHARTSTYLE:
             strcpy( szTmp, "Invalid Chart Style" );
             break;
         case _PG_BADLEGENDWINDOW:
             strcpy( szTmp, "Invalid Legend Window" );
             break;
         case _PG_BADDATAWINDOW:
             strcpy( szTmp, "No Room for Data window" );
             break;
         case _PG_BADCHARTWINDOW:
             strcpy( szTmp, "Invalid Chart window coordinates" );
             break;
         case _PG_NOMEMORY:
             strcpy( szTmp, "Not Enough Memory for Data Arrays" );
             break;
         case _PG_BADLOGBASE:
             strcpy( szTmp, "X or Y log base <= 0" );
             break;
         case _PG_BADSCALEFACTOR:
             strcpy( szTmp, "X or Y scale factor = 0" );
             break;
         case _PG_TOOSMALLN:
             strcpy( szTmp, "Too few data values" );
             break;
         case _PG_TOOFEWSERIES:
             strcpy( szTmp, "No data series specified" );
             break;
         default:
             strcpy( szTmp, "Unknown error" );
     }

     ErrorMsg( szTmp );
 }

 /*  ViewChart - Draws the current chart.
  *
  *  Params: None
  */
 int ViewChart()
 {
     int cValue, iValue, iSeries, iErr;

     /* Make sure some data exists.  */
     if( cSeries <= 0 )
     {
         fDefault = TRUE;
         DefaultData( ce.charttype, ce.chartstyle, FALSE );
     }

     /* Find the longest series.  */
     cValue = 0;
     for( iSeries = 0; iSeries < cSeries; iSeries++ )
         if( acSeries[iSeries] > cValue )
             cValue = acSeries[iSeries];

     _setvideomode( si.mode );


     /* Process depending on the type of chart.  */
     switch( ce.charttype )
     {

         case _PG_PIECHART:
         case _PG_BARCHART:
         case _PG_COLUMNCHART:
         case _PG_LINECHART:

             /* Initialize data and draw pie chart or single-series bar,
              * column, or line chart.
              */
             if( (cSeries == 1) ||( ce.charttype == _PG_PIECHART) )
             {

                 /* Transfer data into a single-dimension array.  */
                 for( iValue = 0; iValue < cValue; iValue++ )
                    axValue[iValue] = aValue[0][iValue];

                 /* Draw chart.  */
                 if( ce.charttype == _PG_PIECHART )
                     iErr = _pg_chartpie( &ce, aCat, axValue,
                                          aExplode, cValue );
                 else
                     iErr = _pg_chart( &ce, aCat, axValue, cValue );
             }
             /* If multiple-series, then data is OK. Just draw chart.  */
             else
                 iErr = _pg_chartms( &ce, aCat, (float _far *)aValue,
                                     cSeries, cValue, cValue, aSeriesName );
             break;

         case _PG_SCATTERCHART:

             /* Make sure there are enough data sets.  */
             if( cSeries == 1 )
             {
                 _setvideomode( _DEFAULTMODE );
                 si.help = 10;
                 ErrorMsg( "Too few value data columns for scatter chart." );
                 return 1;

             }
             /* If it's a single-series scatter, transfer data to one-
              * dimensional arrays and make chart call.
              */
             else if( cSeries == 2 )
             {
                 for( iValue = 0; iValue < cValue; iValue++ )
                 {
                     axValue[iValue] = aValue[0][iValue];
                     ayValue[iValue] = aValue[1][iValue];
                 }
                 cSeries = 1;
                 iErr = _pg_chartscatter( &ce, axValue, ayValue, cValue );

             }
             /* If it's a multiple-series scatter, transfer odd columns to
              * X-axis data array and even columns to Y-axis array and make
              * chart call.
              */
             else
             {

                 for( iSeries = 1; iSeries < cSeries; iSeries += 2 )
                 {
                     aSeriesName[iSeries / 2] = aSeriesName[iSeries - 1];
                     for( iValue = 0; iValue < cValue; iValue++ )
                     {
                         axValueMS[iSeries / 2][iValue] =
                             aValue[iSeries - 1][iValue];
                         ayValueMS[iSeries / 2][iValue] =
                             aValue[iSeries][iValue];
                     }
                 }
                 cSeries /= 2;

                 iErr = _pg_chartscatterms( &ce, (float _far *)axValueMS,
                                            (float _far *)ayValueMS,
                                            cSeries, cValue, cValue,
                                            aSeriesName );
             }
     }

     if( !fDefault )
         ClearData( FALSE );

     /* If error, show it, else wait for keypress with chart on screen.  */
     if( iErr )
     {
         ShowError( iErr );
         return iErr;
     }
     else
         return ( getch() == ESCAPE );   /* ESCAPE means stop demo */
 }


 CHRTOPT.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\CHRTOPT.C

 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #include <graph.h>
 #include <pgchart.h>
 #include "chrtdemo.h"

 /* Structures for system configuration and chart environment. */
 extern struct videoconfig vc;
 extern chartenv ce;

 /* Variable used to track control and screen position.  */
 extern struct SCREENINFO si;

 /* Colors of menus and prompts. */
 extern struct tagColor co;

 /* Arrays of strings used by the Menu function. The first string is the
  * menu title. The next non-null strings are the menu selections. A null
  * string indicates the end of the list.
  */
 char *pszAxes[] =
     { "Axis", "X Axis", "Y Axis", "" };

 char *pszAxis[] =
     { "? Options", "Grid", "Axis Title", "Color",
       "Range Type", "Scale", "Tic Marks", "" };

 char *pszAuto[] =
     { "Auto", "Auto", "Manual", "" };

 char *pszBorder[] =
     { "Type", "Color", "Style", "" };

 char *pszChartWindow[] =
     { "Chart", "Size", "Color (Background)", "Border", "" };

 char *pszDataWindow[] =
     { "Data", "Color (Background)", "Border", "" };

 char * pszFontOpt[] =
     { "Font Options", "Change Typeface", "Set Character Size", "" };

 char *pszJustify[] =
     { "Justify", "Left", "Center", "Right", "" };

 char *pszLegendWindow[] =
     { "Options", "Place", "Text Color", "Size", "Color (Background)",
       "Border", "" };

 char *pszPlace[] =
     { "Place", "Right", "Bottom", "Overlay", "" };

 char *pszScale[] =
     { "Scale", "Low (Min)", "High (Max)", "Scale Factor", "Title", "" };

 char *pszSize[] =
     { "Size", "Top", "Left", "Bottom", "Right", "" };

 char *pszTic[] =
     { "Tic Type", "Interval", "Format", "Decimals", "" };

 char *pszTitleOpt[] =
     { "", "Text", "Color", "Justify", "" };

 char *pszTitles[] =
     { "Title", "Main Title", "Sub Title", "" };

 char *pszTypeface[] =
     { "Type Faces", "Courier", "Helv", "Tms Rmn", "Modern", "Script",
            "Roman", "None", "" };

 char *pszWindows[] =
     { "Window", "Chart Window", "Data Window", "" };

 /*  Axes - Selects X or Y axis.
  *
  *  Params: none
  */
 void Axes()
 {
     int iChoice;
     static axistype *patAxis[2] = { &ce.xaxis, &ce.yaxis };

     /* Get menu choice and call appropriate axis Menu. */
     PushTitle( pszAxes[0] );
     Help( "Choose 'X' or 'Y' Axis", co.InputColor );
     while( (iChoice = Menu( pszAxes )) != ESCAPE )
     {
         /* Modify axis title, depending on choice. */
         pszAxis[0][0] = (--iChoice == 0) ? 'X' : 'Y';

         /* Obtain axis information for appropriate axis. */
         Axis( patAxis[iChoice] );
     }
     PopTitle();
 }

 /*  Axis - Selects axis options.
  *
  *  Params: pat - Pointer to axistype variable
  */
 void Axis( axistype *pat )
 {
     int iChoice;

     PushTitle( pszAxis[0] );
     while( (iChoice = Menu( pszAxis )) != ESCAPE )
     {

         /* Get Axis option.  */
         switch( iChoice )
         {
             case 1:
                 /* Grid or not? */
                 iChoice = BlankMenu( "Grid", "Grid", "No Grid" );
                 switch( iChoice )
                 {

                     case 1:
                         /* If yes, set grid flag and get the grid style. */
                         pat->grid = TRUE;
                         Help( "Enter a number in the range 0-10.",
                             co.InputColor );
                         pat->gridstyle =
                             InputInt( "Grid Style? ", pat->gridstyle, 0, 10 )
                         break;

                     case 2:
                         /* If no, clear grid flag.  */
                         pat->grid = FALSE;
                 }
                 PopTitle();
                 break;

             case 2:
                 /* Select axis title options. */
                 pszTitleOpt[0] = "Axis Title";
                 TitleOpt( &pat->axistitle );
                 break;

             case 3:
                 /* Select color. */
                 Help( "Enter a number in the range 0-15.", co.InputColor );
                 pat->axiscolor =
                     InputInt( "Axis Color? ", pat->axiscolor, 0, 15 );
                 break;

             case 4:
                 /* Get the axis range.  */
                 AxisRange( pat );
                 break;

             case 5:
                 /* Get the axis scale.  */
                 AxisScale( pat );
                 break;

             case 6:
                 /* Get axis tic mark options.  */
                 AxisTics( pat );
                 break;

         }
     }
     PopTitle();
 }

 /*  AxisRange - Selects range for an axis.
  *
  *  Params: pat - pointer to axistype variable
  */
 void AxisRange( axistype *pat )
 {
     int iChoice;

     iChoice = BlankMenu( "Range Type", "Normal", "Log" );
     switch( iChoice )
     {
         case 1:
             /* Set range type to linear.  */
             pat->rangetype = _PG_LINEARAXIS;
             break;

         case 2:
             /* Set range type to log, then query for log base.  */
             pat->rangetype = _PG_LOGAXIS;
             Help( "Enter a value greater than or equal 2.", co.InputColor );
             pat->logbase = (float)InputInt( "Log base? ",
                                             (int)pat->logbase, 2, 0 );
             break;
     }
     PopTitle();
 }

 /*  AxisScale - Selects scale options for an axis.
  *
  *  Params: pat - pointer to axistype variable
  */
 void AxisScale( axistype *pat )
 {
     int iChoice;

     PushTitle( pszAuto[0] );
     iChoice = Menu( pszAuto );
     switch( iChoice )
     {

         case 1:
             /* Set AutoScale flag.  */
             pat->autoscale = TRUE;
             break;

         case 2:

             /* Clear AutoScale flag and get scale options.  */
             pat->autoscale = FALSE;
             PushTitle( pszScale[0] );
             while( (iChoice = Menu( pszScale )) != ESCAPE )
             {

                 switch( iChoice )
                 {

                     case 1:
                         /* Query for scale minimum.  */
                         Help( "Enter the range minimum value.", co.InputColor
                         pat->scalemin =
                             (float)InputInt( "Minimum? ",
                                              (int)pat->scalemin, 1, 0 );
                         break;

                     case 2:
                         /* Query for scale maximum.  */
                         Help( "Enter the range maximum value.", co.InputColor
                         pat->scalemin =
                             (float)InputInt( "Minimum? ",
                                              (int)pat->scalemin, 1, 0 );
                         break;

                     case 3:
                         /* Query for scale factor.  */
                         Help( "Enter scale factor (must be 1 or greater).",
                                  co.InputColor );
                         pat->scalefactor =
                             (float)InputInt( "Scale Factor? ",
                                              (int)pat->scalefactor, 1, 0 );
                         break;

                     case 4:
                         /* Modify scale title, then use menu to get
                          * title options.
                          */
                         pszTitleOpt[0] = "Scale Title";
                         TitleOpt( &pat->scaletitle );

                 }
             }
             PopTitle();
     }
     PopTitle();
 }

 /*  AxisTics - Selects tic options for an axis.
  *
  *  Params: pat - pointer to axistype variable
  */
 void AxisTics( axistype *pat )
 {
     int iChoice;

     PushTitle( pszTic[0] );
     while( (iChoice = Menu( pszTic )) != ESCAPE )
     {
         switch( iChoice )
         {

             case 1:
                 /* Query for tic interval.  */
                 Help( "Enter distance in data units.", co.InputColor );
                 pat->ticinterval =
                     InputFloat( "Distance between tic marks? ",
                                pat->ticinterval );
                 pat->autoscale = FALSE;
                 break;

             case 2:
                 /* Query for tic format.  */
                 iChoice = BlankMenu( "Tic Format", "Normal", "Log" );
                 if( iChoice != ESCAPE )
                     pat->ticformat = iChoice;
                 break;

             case 3:
                 /* Query for number of decimal places per tic.  */
                 pat->ticdecimals =
                     InputInt( "Enter decimal places (0 to 9). ",
                                pat->ticdecimals, 0, 9 );
                 pat->autoscale = FALSE;
                 break;
         }

     }
     PopTitle();
 }

 /*  Border - Specifies border information for a window.
  *
  *  Params: pwt - Pointer to windowtype variable
  */
 void Border( windowtype *pwt )
 {
     int iChoice;

     /* Ask whether a border is wanted.  */
     iChoice = BlankMenu( "Border", "Border", "No Border" );
     switch( iChoice )
     {

         case 1:

             /* If border, set Border flag and query for border options.  */
             pwt->border= TRUE;
             PushTitle( pszBorder[0] );
             while( (iChoice = Menu( pszBorder )) != ESCAPE )
             {
                 switch( iChoice )
                 {
                     case 1:
                         /* Query for border color.  */
                         Help( "Enter a color in the range 0-15.",
                             co.InputColor );
                         pwt->bordercolor =
                             InputInt( "Border color? ",
                                        pwt->bordercolor, 0, 15 );
                         break;

                     case 2:
                         /* Query for border style.  */
                         Help( "Enter a style in the range 0-10.", co.InputCol
                         pwt->borderstyle =
                             InputInt( "Border style? ",
                                        pwt->borderstyle, 0, 10 );
                 }
             }
             PopTitle();
             break;

         case 2:
             /* If no border, clear Border flag.  */
             pwt->border= FALSE;
     }
     PopTitle();
 }

 /*  ChangeTypeface - Allow the user to specify a new type face.
  *
  *  Params: iFaceIndex - index of last typeface
  *
  *  Return: index of new typeface
  */

 int ChangeTypeface( int iFaceIndex )
 {
     int iChoice;

     /* Get menu choice and call appropriate axis Menu. */
     PushTitle( pszFontOpt[0] );
     Help( "Choose one of the type faces listed.", co.InputColor );

     if( (iChoice = Menu( pszTypeface ) - 1) != ESCAPE )
     {
         /* If the user wants the system font, unregister the other fonts. */
         if( iChoice == NOFONT )
             _unregisterfonts();

         /* If the user wants any font but the system font, make sure the
          *   fonts are registered.
          */
         else
         {
             /* If last face was NOFONT, register fonts. */
             if( iFaceIndex == NOFONT )
             {
                 /* Assumes font files are in current directory.
                  * Could be enhanced to handle any directory.
                  */
                 if( _registerfonts( "*.FON" ) < 0 )
                     ErrorMsg( "Font files must be in current directory" );
                 else
                     iFaceIndex = iChoice;
             }
             else
                 iFaceIndex = iChoice;
         }
     }

     PopTitle();
     return iFaceIndex;
 }

 /*  ChooseFont - Chooses a font from the font library.
  *
  *  Params: WhichFont - A member of the set [COURIER, HELV, TMS_RMN,
  *                        MODERN, SCRIPT, ROMAN, NOFONT]
  *          Height    - The desired height of the text (in pixels)
  */

 void ChooseFont( int WhichFont, int Height )
 {
     static char *FontIds[] =
     {
         "courier", "helv", "tms rmn", "modern", "script", "roman"
     };
     char SetCommand[30];

     /* Construct the command to send to _setfont. */
     sprintf( SetCommand, "t'%s'h%dw0b", FontIds[WhichFont], Height );

     if( _setfont( SetCommand ) < 0 )
     {
         _outtext( "Could not set. Try different font or size" );
         getch();
     }
 }

 /*  ChartWindow - Gets chart window information.
  *
  *  Params: None
  */
 void ChartWindow()
 {
     int iChoice;

     PushTitle( pszChartWindow[0] );
     while( (iChoice = Menu( pszChartWindow )) != ESCAPE )
     {

         /* Get window options.  */
         switch( iChoice )
         {

             case 1:
                 /* Get window size.  */
                 WindowSize( &ce.chartwindow );
                 break;

             case 2:
                 /* Query for background color.  */
                 Help( "Enter a number in the range 0-15", co.InputColor );
                 ce.chartwindow.background =
                     InputInt( "Background Color? ", ce.chartwindow.background
                               0, 15 );
                 break;

             case 3:

                 /* Get border options.  */
                 Border( &ce.chartwindow );

         }
     }
     PopTitle();
 }

 /*  DataWindow - Geta data window information.
  *
  *  Params: None
  */
 void DataWindow()
 {
     int iChoice;

     PushTitle( pszDataWindow[0] );
     while( (iChoice = Menu( pszDataWindow )) != ESCAPE )
     {

         /* Get data window menu options.  */
         switch( iChoice )
         {

             case 1:
                 /* Query for background color.  */
                 Help( "Enter a number in the range 0-15", co.InputColor );
                 ce.datawindow.background =
                     InputInt( "Background Color? ",
                                ce.datawindow.background,
                                0, 15 );
                 break;

             case 2:
                 /* Get border options.  */
                 Border( &ce.datawindow );
                 break;

         }
     }
     PopTitle();
 }

 /*  FontOptions - Allows the user to modify the font used for display.
  *
  *  Params: None
  */

 void FontOptions()
 {
     int iChoice;
     static int iFaceIndex = NOFONT;
     static int iTypeSize = 8;

     /* Get menu choice and call appropriate axis Menu. */
     PushTitle( pszFontOpt[0] );

     while( (iChoice = Menu( pszFontOpt )) != ESCAPE )
     {
         switch( iChoice )
         {
             /* Change Typeface. */
             case 1:
                 iFaceIndex = ChangeTypeface( iFaceIndex );
                 ChooseFont( iFaceIndex, iTypeSize );
                 break;

             /* Change Type Size. */
             case 2:

                 if( iFaceIndex == NOFONT )
                 {
                     ErrorMsg( "Select a font first" );
                     break;
                 }

                 iTypeSize = InputInt( "Enter a type size. ", iTypeSize,
                                        8, 128 );

                 ChooseFont( iFaceIndex, iTypeSize );
                 break;

             default:
                 break;
         }
     }
     PopTitle();
 }

 /*  Justify - Gets title justification option.
  *
  *  Params: Pointer to titletype variable
  */
 void Justify( titletype *ptt )
 {
     int iChoice;

     PushTitle( pszJustify[0] );
     iChoice = Menu( pszJustify );
     switch( iChoice )
     {

         /* Set justification.  */
         case 1:
         case 2:
         case 3:
             ptt->justify = iChoice;
     }
     PopTitle();
 }

 /*  Legend - Asks whether a legend is desired, and if so, gets
  *  legend options.
  *
  *  Params: None
  */
 void Legend()
 {
     int iChoice;

     /* Is legend desired?  */
     iChoice = BlankMenu( "Legend", "Legend", "No Legend" );
     switch( iChoice )
     {
         case 1:
             /* If legend, set legend flag and get options.  */
             ce.legend.legend = TRUE;
             PushTitle( pszLegendWindow[0] );
             do
             {
                 iChoice = Menu( pszLegendWindow );
                 switch( iChoice )
                 {

                     case 1:
                         /* Get legend place.  */
                         LegendPlace();
                         break;

                     case 2:
                         /* Query for legend color.  */
                         Help( "Enter a number in the range 0-15.", co.InputCo
                         ce.legend.textcolor =
                             InputInt( "Text color? ",
                                        ce.legend.textcolor,
                                        0, 15 );
                         break;

                     case 3:
                         /* Get auto or manual sizing.  */
                         PushTitle( "Auto Legend" );
                         iChoice = Menu( pszAuto );

                         /* Set or clear the autosize flag. If manual
                          * sizing was selected, get legend size.
                          */
                         switch( iChoice )
                         {
                             case 1:
                                 ce.legend.autosize = TRUE;
                                 break;

                             case 2:
                                 ce.legend.autosize = FALSE;
                                 WindowSize( &ce.legend.legendwindow );
                         }
                         PopTitle();
                         break;

                     case 4:
                         /* Query for background color.  */
                         Help( "Type a number in the range 0-15.", co.InputCol
                         ce.legend.legendwindow.background =
                             InputInt( "Background color? ",
                                        ce.legend.legendwindow.background,
                                        0, 15 );
                         break;

                     case 5:
                         /* Get border options for legend window.  */
                         Border( &ce.legend.legendwindow );
                 }

             } while( iChoice != ESCAPE );
             PopTitle();
             break;

         case 2:
             /* If no legend wanted, clear flag.  */
             ce.legend.legend = FALSE;

     }
     PopTitle();
 }

 /*  LegendPlace - Gets legend placement option.
  *
  *  Params: None
  */
 void LegendPlace()
 {
     int iChoice;

     /* Get legend placement.  */
     PushTitle( pszPlace[0] );
     iChoice = Menu( pszPlace );
     switch( iChoice )
     {

         case 1:
             ce.legend.place = _PG_RIGHT;
             break;

         case 2:
             ce.legend.place = _PG_BOTTOM;
             break;

         case 3:
             ce.legend.place = _PG_OVERLAY;
     }
     PopTitle();
 }

 /*  ScreenMode - Gets a new screen mode.
  *
  *  Params: None
  */
 void ScreenMode()
 {
     int iMode, i;
     char szTmp[80], szHlp[80];
     static int iLegal[5][11] =
     {
         { 3, 4, 5, 6 },
         { 4, 4, 5, 6, 64 },
         { 4, 4, 5, 6, 19 },
         { 7, 4, 5, 6, 13, 14, 15, 16 },
         { 10, 4, 5, 6, 13, 14, 15, 16, 17, 18, 19 }
     };
     int iAdaptor;

     PushTitle( "Screen Mode" );

     /* Show appropriate help line for adaptor.  */
     switch( vc.adapter )
     {
         case _HGC:
             PopTitle();
             return;
         case _CGA:
             iAdaptor = 0;
             break;
         case _OCGA:
             iAdaptor = 1;
             break;
         case _MCGA:
             iAdaptor = 2;
             break;
         case _EGA:
         case _OEGA:
             if( vc.adapter == _MONO )
             {
                 PopTitle();
                 return;
             }
             else
                 iAdaptor = 3;
             break;
         case _VGA:
         case _OVGA:
             iAdaptor = 4;
             break;
     }

     /* Form the help line (which gives the choices legal for
      * the adaptor sensed in the user's machine).
      */
     for( iMode = 0, szHlp[0] = '\0'; iMode <= iLegal[iAdaptor][0]; ++iMode )
     {
         if( iMode == 0 )
             strcpy( szTmp, "Enter " );
         else if( iMode < iLegal[iAdaptor][0] )
             sprintf( szTmp, "%d, ", iLegal[iAdaptor][iMode] );
         else
             sprintf( szTmp, "or %d", iLegal[iAdaptor][iMode] );
         strcat( szHlp, szTmp );
     }

     WrtForm( 18 );
     Help( szHlp, co.InputColor );

     /* Query for screen mode. */
     for( ;; )
     {
         iMode = InputInt( "Screen Mode? ", si.mode, 1, 64 );
         for( i = 1; i <= iLegal[iAdaptor][0]; ++i ) /* Test legal values    *
             if( iMode == iLegal[iAdaptor][i] )      /* If a match is found  *
                 break;                              /* Terminate for loop   *
         if( iMode == iLegal[iAdaptor][i] )          /* If it's a match,     *
             break;                                  /* terminate do loop,   *
         else                                        /* otherwise BEEP, and  *
             putchar( BEEP );                        /* solicit correct data *
     }

     PopTitle();
     if( SetGraphMode( iMode ) )
         _setvideomode( _DEFAULTMODE );
     else
         ShowError( _PG_BADSCREENMODE );

     /* Force rescaling of the chart by resetting the window
      * rectangles for the chart and data windows to zero size.
      */
     ce.chartwindow.x1 = ce.chartwindow.x2 = ce.chartwindow.y1 =
         ce.chartwindow.y2 = 0;
     ce.datawindow = ce.chartwindow;
 }

 /*  TitleOpt - Gets title options.
  *
  *  Params: ptt - Pointer to titletype variable
  */
 void TitleOpt( titletype *ptt )
 {
     int iChoice;

     PushTitle( pszTitleOpt[0] );
     do
     {
         iChoice = Menu( pszTitleOpt );
         switch( iChoice )
         {

             case 1:
                 /* Query for title text.  */
                 Help( "70 characters maximum length.", co.InputColor );
                 InputStr( "Enter Text: ", ptt->title );
                 break;

             case 2:
                 /* Query for title color color.  */
                 Help( "Enter a number in the range 0-15.", co.InputColor );
                 ptt->titlecolor =
                     InputInt( "Title Color? ", ptt->titlecolor, 0, 15 );
                 break;

             case 3:
                 /* Get justify option.  */
                 Justify( ptt );
         }
         ClrHelp();

     } while( iChoice != ESCAPE );
     PopTitle();
 }

 /*  Titles - Manages Main and Sub title menus.
  *
  *  Params: None
  */
 void Titles()
 {
     int iChoice;

     PushTitle( pszTitles[0] );
     do
     {
         iChoice = Menu( pszTitles );
         switch( iChoice )
         {

             case 1:
                 /* Fix menu title and get options for main title.  */
                 pszTitleOpt[0] = "MainTitle";
                 TitleOpt( &ce.maintitle );
                 break;

             case 2:
                 /* Fix menu title and get options for subtitle.  */
                 pszTitleOpt[0] = "Sub Title";
                 TitleOpt( &ce.subtitle );
         }
     } while( iChoice != ESCAPE );
     PopTitle();
 }

 /*  Windows - Selects chart or data window, and gets options for either.
  *
  *  Params: None
  */
 void Windows()
 {
     int iChoice;

     PushTitle( pszWindows[0] );
     do
     {

         /* Select window and get options for it.  */
         iChoice = Menu( pszWindows );
         switch( iChoice )
         {

             case 1:
                 ChartWindow();
                 break;

             case 2:
                 DataWindow();

         }
     } while( iChoice != ESCAPE );
     PopTitle();
 }

 /*  WindowSize - Gets coordinates for window location and size.
  *
  *  Params: pwt - pointer to windowtype variable
  */
 void WindowSize( windowtype *pwt )
 {
     int iChoice;

     /* Get window size settings.  */
     PushTitle( pszSize[0] );
     do
     {
         /* Query for top, bottom, left, or right of window.  */
         iChoice = Menu( pszSize );
         switch( iChoice )
         {

             case 1:
                 Help( "Enter window top in pixels.", co.InputColor );
                 pwt->y1 = InputInt( "Top? ", pwt->y1, 0, si.yMax );
                 break;

             case 2:
                 Help( "Enter window Left in pixels.", co.InputColor );
                 pwt->x1 = InputInt( "Left? ", pwt->x1, 0, si.xMax );
                 break;

             case 3:
                 Help( "Enter window bottom in pixels.", co.InputColor );
                 pwt->y2 = InputInt( "Bottom? ", pwt->y2, 0, si.yMax );
                 break;

             case 4:
                 Help( "Enter window right in pixels.", co.InputColor );
                 pwt->x2 = InputInt( "Right? ", pwt->x2, 0, si.xMax );
         }
     } while( iChoice != ESCAPE );
     PopTitle();
 }


 CHRTSUPT.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\CHRTSUPT.C

 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <conio.h>
 #include <graph.h>
 #include <pgchart.h>
 #include "chrtdemo.h"

 /* Variables to manage menus.  */
 int cMenuLevel = 0;                 /* Current menu level   */
 char *szMenuTitles[10];             /* Stack of menu titles */

 char *pszBlankMenu[4];

 /* Variables used to track control and screen position.  */
 extern struct SCREENINFO si;

 /* Colors of menus and prompts. */
 extern struct tagColor co;

 /*  BlankMenu - Gets responses to two specified choices.
  *
  *  Params: pchTitle - Menu title string
  *          pchChoice1 - Selection 1 string
  *          pchChoice2 - Selection 2 string
  *
  *  Return: Number of choice, or ESCAPE
  */
 int BlankMenu( char *pchTitle, char *pchChoice1, char *pchChoice2 )
 {
     int iChoice;

     /* Initialize title and selections.  */
     pszBlankMenu[0] = pchTitle;
     pszBlankMenu[1] = pchChoice1;
     pszBlankMenu[2] = pchChoice2;
     pszBlankMenu[3] = "\0";
     PushTitle( pszBlankMenu[0]);

     while( TRUE )
     {
         /* Accept only first letter of either selection, or ESC.  */
         iChoice = Menu( pszBlankMenu );
         switch( iChoice )
         {
             case 1:
             case 2:
             case ESCAPE:
                 return iChoice;
         }
     }
 }

 /*  ClrForm - Clears the center of the screen form.
  *
  *  Params: None
  */
 void ClrForm()
 {

     /* Set partial screen window and clear it, then reset full screen.  */
     _settextwindow( si.top, 1, si.bot, 80 );
     _clearscreen( _GWINDOW );
     _settextwindow( 1, 1, 25, 80 );

 }

 /*  ClrHelp - Clears the current help line.
  *
  *  Params: None
  */
 void ClrHelp()
 {
     /* Decrement the help line counter and clear the line.  */
     _settextwindow( --si.help, 1, si.help, 80 );
     _clearscreen( _GWINDOW );
     _settextwindow( 1, 1, 25, 80 );
 }

 /*  ErrorMsg - Displays an error message.
  *
  *  Params: pchMsg - error message string
  */
 void ErrorMsg( char *pchMsg )
 {

     /* Beep, set error color, and display error message and continue prompt.
     putch( BEEP );
     Help( pchMsg, co.ErrorColor );
     Help( "Press any key to continue.", co.ErrorColor );

     /* Wait for keypress and clear help lines.  */
     getch();
     ClrHelp();
     ClrHelp();

 }

 /*  Help - Displays a help line on the screen.
  *
  *  Params: pchMsg - error message string
  *          sColor - color for message
  */
 void Help( char *pchMsg, short sColor )
 {

     struct rccoord rcCursor;

     /* Save current cursor position.  */
     rcCursor = _gettextposition();

     /* Print out help line and increment Helpline position variable.  */
     PrintAt( si.help++, 5, pchMsg, sColor );

     /* Restore cursor position.  */
     _settextposition( rcCursor.row, rcCursor.col );

 }

 /*  InputCh - Prompts for and returns a character of input.
  *
  *  Params: pchPrompt - Prompt string
  *          pchAccept - String of acceptable characters (case insensitive)
  *
  *  Return: Character entered
  */
 int InputCh( char *pchPrompt, char *pchAccept )
 {
     int chResponse;

     /* Display prompt.  */
     PrintAt( si.mid, 10, pchPrompt, co.InputColor );

     /* Loop until response is valid.  */
     while( TRUE )
     {
         chResponse = toupper( getch() );

         /* Display and return if acceptable character, or beep if not.  */
         if( *strchr( pchAccept, chResponse) )
         {
             _settextcolor( co.InfoColor );
             putch( chResponse );
             return chResponse;
         }
         else
             putch( BEEP );
     }
 }

 /*  InputInt - Prompts for and returns an integer value within a
  *  specified range.
  *
  *  Params: pchPrompt - Prompt string
  *          iOld - Previous value
  *          iMin - Minimum value of range
  *          iMax - Maximum value of range
  *
  *  Return: integer input by user
  */
 int InputInt( char *pchPrompt, int iOld, int iMin, int iMax )
 {
     int i;
     char szTmp[70];

     /* Prompt for a string input and convert to an integer until a
      * value in the specified range is given. Then return the value.
      */
     do
     {
         InputStr( pchPrompt, itoa( iOld, szTmp, 10) );
         i = atoi( szTmp );
     } while( !InRange( i, iMin, iMax) );
     return i;
 }

 /*  InputFloat - Prompts for and returns a float value.
  *
  *  Params: pchPrompt - Prompt string
  *          fOld - Previous value
  *
  *  Return: float input by user
  */
 float InputFloat( char *pchPrompt, float fOld )
 {
     char szTmp[70];

     /* Prompt for a string input and convert to a float. */
     sprintf( szTmp, "%f", fOld );
     InputStr( pchPrompt, szTmp );
     return (float)atof( szTmp );
 }

 /*  InputStr - Prompts for a string. Displays the previous string
  *  until the first character is given. Then replaces it with new
  *  entry.
  *
  *  Params: pchPrompt - Prompt string
  *          pchOld - Charater buffer containing previous string; it
  *            must be long enough to hold new string
  *
  *  Return: pointer to pchOld, which now contains new string
  */
 char *InputStr( char *pchPrompt, char *pchOld )
 {
     char szTmp[81];
     int x = 5, y = si.mid, ch;

     /* Display prompt in center of form.  */
     ClrForm();
     PrintAt( y, x, pchPrompt, co.InputColor );
     x += strlen( pchPrompt );

     /* Print the old value for reference.  */
     _outtext( pchOld );
     _settextposition( y, x );

     /* Wait for input. When received, clear old string.  */
     while( !(ch = kbhit()) )
         ;
     memset( szTmp, ' ', 80 );
     szTmp[80] = '\0';
     PrintAt( y, x, szTmp, -1 );

     /* Get new string. If string entered, return it. If null string
      * (ENTER key pressed), return old value.
      */
     _settextcolor( co.InfoColor );
     _settextposition( y, x );
     szTmp[0] = 70;             /* Maximum length to be read */

     cgets( szTmp );
     if( szTmp[1] > 0 )         /* Are any characters read?  */
     {
         strcpy( pchOld, &szTmp[2] );
         return &szTmp[2];
     }
     else
     {
         _settextposition( y, x );
         return pchOld;
     }
 }

 /*  InRange - Checks an integer to see if it is in a specified range.
  *
  *  Params: iValue - Integer to check
  *          iMin - Minimum value of range
  *          iMax - Maximim value of range
  *
  *  Return: TRUE if in range, FALSE if not
  */
 BOOL InRange( int Value, int iMin, int iMax )
 {
     /* Check range and return true if valid, false if not. Note that
      * (iMin >= iMax) is taken as a signal to check only the minimum
      * value; there is no maximum.
      */
     if( Value >= iMin )
         if( (Value <= iMax) || (iMin >= iMax) )
             return TRUE;
     else
     {
         ErrorMsg( "Invalid value." );
         return FALSE;
     }
 }

 /*  Menu - Draws menu on screen and returns choice number.
  *
  *  Params: array of menu strings
  *
  *  Return: number corresponding to the choice made from the menu
  */
 int Menu( char *pszMenuList[] )
 {
     int iItem, cItem, yItem, x = 10;
     int chResponse;

     /* Count menu items.  */
     for( cItem = 1; *pszMenuList[cItem]; cItem++ )
         ;
     --cItem;


     /* Clear the form and print the items in the menu.  */
     WrtForm( 10 + cItem );
     for( iItem = 1, yItem = 8; iItem <= cItem; iItem++, yItem++ )
     {
         PrintAt( yItem, x, pszMenuList[iItem], co.InputColor );
         PrintChar( yItem, x, pszMenuList[iItem][0], co.HiliteColor );
     }
     ++yItem;

     /* Display prompt and help.  */
     if( strcmpi( pszMenuList[0], "main menu" ) )    /* If not the main menu *
         Help( "Type the first letter of your selection or ESC to back up.",
                   co.InputColor );
     else
         Help( "Type the first letter of your selection or \"Q\" to quit.",
                   co.InputColor );

     PrintAt( yItem, x += 5, "Choice? ", co.InfoColor );
     x += 8;

     /* Loop until a valid choice is made. Beep at invalid choices.  */
     while( TRUE )
     {
         _settextposition( yItem, x );
         chResponse = toupper( getch() );

         /* Back up for ESC.  */
         if( chResponse == 27 )
         {
             ClrHelp();
             return ESCAPE;
         }

         /* Search first letters of choices for a match. If found, return
          * choice and clear help line.
          */
         for( iItem = 1; iItem <= cItem; iItem++ )
         {
             if( chResponse == toupper( pszMenuList[iItem][0]) )
             {
                 putch( chResponse );
                 ClrHelp();
                 return iItem;
             }
         }

         /* If we get here, no valid choice was found, so beep and repeat.  */
         putch( BEEP );
     }
 }

 /*  PopTitle - Pops a menu title from the menu stack.
  *
  *  Params: None
  */
 void PopTitle()
 {
     szMenuTitles[--cMenuLevel] = "";
 }

 /*  PrintAt - Prints a string at the row/column coordinates
  *            specified, in the specified color.
  *
  *  Params: row        - row at which to begin output of string
  *          col        - column at which to begin output of string
  *          lpszString - zero (null) terminated string
  *          sColor     - color in which to output string (-1 if
  *                       PrintAt should leave color alone)
  */
 void PrintAt( int row, int column, char _far *lpszString, short sColor )
 {
     if( sColor != -1 )
         _settextcolor( sColor );
     _settextposition( row, column );
     _outtext( lpszString );
 }

 /*  PrintChar - Prints a character at the row/column coordinates
  *              specified, in the specified color.
  *
  *  Params: row        - row at which to begin output of string
  *          col        - column at which to begin output of string
  *          cChar      - character to print
  *          sColor     - color in which to output string (-1 if
  *                       PrintChar should leave color alone)
  */
 void PrintChar(int row, int column, char cChar, short sColor)
 {
     char szTiny[2];

     szTiny[0] = cChar;
     szTiny[1] = '\0';
     PrintAt( row, column, szTiny, sColor );
 }

 /*  PushTitle - Pushes a menu title on to the menu stack.
  *
  *  Params: pchTitle - title string to push
  */
 void PushTitle( char *pchTitle )
 {
     szMenuTitles[cMenuLevel++] = pchTitle;
 }

 /*  SetDisplayColors - Set the colors to values appropriate to the display
  *                     adaptor being used.
  *
  * Parms: None
  */
 void SetDisplayColors()
 {
     if( ismono( si.mode ) )
     {
         co.InputColor  = M_INPUTCOLOR;
         co.HiliteColor = M_HILITECOLOR;
         co.FormColor   = M_FORMCOLOR;
         co.TitleColor  = M_TITLECOLOR;
         co.ErrorColor  = M_ERRORCOLOR;
         co.InfoColor   = M_INFOCOLOR;
     }
     else
     {
         co.InputColor  = C_INPUTCOLOR;
         co.HiliteColor = C_HILITECOLOR;
         co.FormColor   = C_FORMCOLOR;
         co.TitleColor  = C_TITLECOLOR;
         co.ErrorColor  = C_ERRORCOLOR;
         co.InfoColor   = C_INFOCOLOR;
     }
 }

 /*  SprintAt - Format a string, using sprintf() and output to screen
  *             using PrintAt.
  *
  *  Parms: iRow  - Row at which to begin display
  *         iCol  - Column at which to begin display
  *         szFmt - Format string (see run-time library documentation for
  *                 correct formation of a format string)
  *         ...   - Variables to output
  */
 void SprintAt( int iRow, int iCol, char * szFmt, ... )
 {
     char szTmp[81];
     va_list Marker;
     va_list saveMarker;

     va_start( Marker, szFmt );
     saveMarker = Marker;
     vsprintf( szTmp, szFmt, Marker );
     va_end( Marker );

     PrintAt( iRow, iCol, szTmp, -1 );
 }

 /*  WrtForm - Displays screen form.
  *
  *  Params: yBot - Row number of the bottom row
  */
 void WrtForm( int yBot )
 {
     int i;
     char szTmp[81];

     /* Print message in upper right.  */
     _clearscreen( _GCLEARSCREEN );
     PrintAt( 1, 55, "Presentation Graphics Demo", co.TitleColor );

     /* Clear the top separator line.  */
     memset( szTmp, ' ', 79 );
     szTmp[79] = 0;

     /* Display each level of the menu title.  */
     _settextposition( 5, 5 );
     for( i = 0; i < cMenuLevel; i++ )
     {
         if( i )
             _outtext( " - " );
         _outtext( szMenuTitles[i] );
     }

     /* Display the top separator line.  */
     memset( szTmp, 196, 80 );
     szTmp[80] = 0;
     PrintAt( 6, 1, szTmp, co.FormColor );

     /* Display the bottom separator line.  */
     PrintAt( yBot, 1, szTmp, co.FormColor );

     /* Set the global screen variables.  */

     si.help = yBot + 1;
     si.top = 7;
     si.bot = yBot - 1;
     si.mid = (si.top + si.bot) / 2;
 }


 GRDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\GRDEMO.C

 /* GRDEMO.C - Demonstrates capabilities of the Microsoft graphics library.
  * Uses MENU module to display menus. Uses TURTLE module for Turtle
  * graphics. This program runs only in DOS and requires GRAPHICS.LIB.
  */

 #include <graph.h>
 #include <math.h>
 #include <malloc.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <conio.h>
 #include <time.h>
 #include "turtle.h"
 #include "menu.h"

 /* Function prototypes */
 int  main( void );
 void Circles( void );
 void Sphere( void );
 int  Polygons( void );
 int  Spiral( int angle, double inc );
 int  InSpiral( double side, int angle, int inc );
 void Bug( void );
 void Adjust( void );
 void Diamond( double xy );

 /* Returns a random number between min and max, which must be in
  * integer range.
  */
 #define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

 /* Constants */
 #define PI      3.141593
 #define LASTATR 15
 #define NLASTATR 14

 /* Array and enum for main menu */
 ITEM mnuMain[] =
 {                    /* Highlight Char  Pos */
     { 0, "Quit"            },   /* Q     0  */
     { 0, "Circles"         },   /* C     0  */
     { 0, "Rotating Sphere" },   /* R     0  */
     { 0, "Tunnel"          },   /* T     0  */
     { 0, "Spiral"          },   /* S     0  */
     { 0, "Inverted Spiral" },   /* I     0  */
     { 0, "Bug"             },   /* B     0  */
     { 0, "Adjust Window"   },   /* A     0  */
     { 0, "Mode Change"     },   /* M     0  */
     { 0, ""                }
 };

 /* Define constants (0, 1, 2,...) for menu choices */
 enum CHOICES
 {
     QUIT, CIRCLES, SPHERE, TUNNEL, SPIRAL, INSPIRAL, BUG, ADJUST, CHANGE
 };

 /* Arrays of video mode menu items and of corresponding mode numbers.
  * Each has a temporary array containing all items, and a pointer version
  * including all except Olivetti.
  */
 ITEM mnuModesT[] =
 {                    /* Highlight Char  Pos */
     { 0, "ORESCOLOR "   },      /* O     0  */
     { 4, "MRES4COLOR "  },      /* 4     4  */
     { 4, "MRESNOCOLOR"  },      /* N     4  */
     { 4, "HRESBW"       },      /* B     4  */
     { 0, "MRES16COLOR"  },      /* M     0  */
     { 0, "HRES16COLOR"  },      /* H     0  */
     { 0, "ERESCOLOR"    },      /* E     0  */
     { 4, "VRES2COLOR"   },      /* 2     4  */
     { 0, "VRES16COLOR"  },      /* V     0  */
     { 1, "MRES256COLOR" },      /* R     4  */
     { 0, ""             }
 };
 ITEM *mnuModes = &mnuModesT[1];  /* Default is no Olivetti mode */

 int aModesT[] =
 {
     _ORESCOLOR,
     _MRES4COLOR,
     _MRESNOCOLOR,
     _HRESBW,
     _MRES16COLOR,
     _HRES16COLOR,
     _ERESCOLOR,
     _VRES2COLOR,
     _VRES16COLOR,
     _MRES256COLOR,
     _TEXTMONO,
     _ERESNOCOLOR,
     _HERCMONO
 };
 int *aModes = &aModesT[1];              /* Default is no Olivetti mode */

 /* Global video configuration */
 struct videoconfig vc;

 int main()
 {
     int rowMid, colMid;
     int fColor, fFirstTime = TRUE;
     int iMode, iMainCur = 0, iModesCur = 0;

     _displaycursor( _GCURSOROFF );
     _getvideoconfig( &vc );
     rowMid = vc.numtextrows / 2;
     colMid = vc.numtextcols / 2;

     /* Select best graphics mode, adjust menus, set color flag. Note
      * that this requires checking both the adapter and the mode.
      */
     switch( vc.adapter )
     {
         case _OCGA:
             mnuModes = &mnuModesT[0];           /* Turn on Olivetti mode */
             aModes = &aModesT[0];
         case _CGA:
             mnuModesT[4].achItem[0] = '\0';     /* Turn off EGA modes    */
             iMode = _MRES4COLOR;
             break;
         case _HGC:
             mnuModesT[7].achItem[0] = '\0';
             iMode = _HERCMONO;
             break;
         case _OEGA:
             mnuModes = &mnuModesT[0];           /* Turn on Olivetti mode */
             aModes = &aModesT[0];
         case _EGA:
             mnuModesT[7].achItem[0] = '\0';     /* Turn off VGA modes    */
             if( vc.memory > 64 )
                 iMode = _ERESCOLOR;
             else
                 iMode = _HRES16COLOR;
             break;
         case _OVGA:
             mnuModes = &mnuModesT[0];           /* Turn on Olivetti mode */
             aModes = &aModesT[0];
         case _VGA:
             iMode = _VRES16COLOR;
             break;
         case _MCGA:
             iMode = _MRES256COLOR;
             break;
         case _MDPA:
         default:
             puts( "No graphics mode available.\n" );
             return TRUE;
     }
     switch( vc.mode )
     {
         case _TEXTBW80:
         case _TEXTBW40:
             fColor = FALSE;
             break;
         case _TEXTMONO:
         case _ERESNOCOLOR:
         case _HERCMONO:
             fColor = FALSE;
             if( iMode != _HERCMONO )
                 iMode = _ERESNOCOLOR;
             mnuMain[8].achItem[0] = '\0';       /* Turn off mode change */
             break;
         default:
             fColor = TRUE;
             break;
     }

     /* Find current mode in mode array. */
     for( iModesCur = 0; aModes[iModesCur] != iMode; iModesCur++ )
         ;

     /* Seed randomizer with time. */
     srand( (unsigned)time( NULL ) );

     while( TRUE )
     {
         /* Set text mode and optionally clear the screen to blue. */
         _setvideomode(_DEFAULTMODE );
         if( fColor )
             _setbkcolor( (long)_TBLUE );
         _clearscreen( _GCLEARSCREEN );

         /* Select from menu. */
         iMainCur = Menu( rowMid, colMid, mnuMain, iMainCur );

         /* Set graphics mode and initialize turtle graphics. Put border
          * on window.
          */
         if( iMainCur != CHANGE )
         {
             _setvideomode( iMode );
             _displaycursor( _GCURSOROFF );
             _getvideoconfig( &vc );
             InitTurtle( &vc );
             Rectangle( 2 * tc.xMax, 2 * tc.yMax );
         }

         /* Branch to menu choice. */
         switch( iMainCur )
         {
             case QUIT:
                 _setvideomode( _DEFAULTMODE );
                 return FALSE;
             case CIRCLES:
                 Circles();
                 break;
             case SPHERE:
                 Sphere();
                 break;
             case TUNNEL:
                 PenDown( FALSE );
                 MoveTo( -tc.xMax * .2, tc.yMax * .15 );
                 PenDown( TRUE );
                 Polygons();
                 while( !GetKey( NO_WAIT ) )
                     NextColorValue( DEFAULT );   /* Rotate palette */
                 break;
             case SPIRAL:
                 if( Spiral( getrandom( 30, 80 ), (double)getrandom( 1, 5 ) )
                     break;
                 while( !GetKey( NO_WAIT ) )
                     NextColorValue( DEFAULT );
                 break;
             case INSPIRAL:
                 NextColorIndex( 0 );
                 if( InSpiral( (double)getrandom( 8, 20 ),
                               getrandom( 4, 22 ),
                               getrandom( 3, 31 ) ) )
                     break;
                 while( !GetKey( NO_WAIT ) )
                     NextColorValue( DEFAULT );
                 break;
             case BUG:
                 Bug();
                 break;
             case ADJUST:
                 Adjust();
                 continue;
             case CHANGE:
                 if( fColor )
                     _setbkcolor( (long)_TBLUE );
                 _clearscreen( _GCLEARSCREEN );

                 iModesCur = Menu( rowMid, colMid, mnuModes, iModesCur );
                 iMode = aModes[iModesCur];
                 if( vc.adapter == _MCGA )
                     switch( iMode )
                     {
                         case _MRES16COLOR:
                         case _HRES16COLOR:
                         case _ERESCOLOR:
                         case _VRES16COLOR:
                             _settextposition( 1, 22 );
                             _outtext( "Mode not recognized" );
                             iMode = _MRES256COLOR;
                     }
                 break;
         }
     }
 }

 /* Circles - Draw circles of varying sizes and colors on screen in a
  * round pattern.
  *
  * Params: None
  *
  * Return: None
  *
  * Uses:   tc
  */
 void Circles()
 {
     double x, y, xyRadius;
     int fFill, fPenDown;

     /* Initialize and save pen and fill flags. */
     if( tc.cci <= 4 )
         fFill = SetFill( FALSE );
     else
         fFill = SetFill( TRUE );
     fPenDown = PenDown( FALSE );

     while( TRUE )
     {
         /* Draw circles. */
         for( xyRadius = 10.0; xyRadius <= 130.0; xyRadius++ )
         {
             x = (tc.xMax - 30) * atan( sin( xyRadius / PI ) );
             y = (tc.yMax - 30) * atan( cos( xyRadius / PI ) );
             MoveTo( x, y );
             PenColor( NextColorIndex( DEFAULT ) );
             Circle( xyRadius );
             if( GetKey( NO_WAIT ) )
             {
                 PenDown( fPenDown );
                 SetFill( fFill );
                 return;
             }
         }

         /* For palette modes (except 256 color), start over. */
         if( tc.ccv == 64 || tc.ccv == 16 )
         {
             _clearscreen( _GCLEARSCREEN );
             SetFill( FALSE );
             MoveTo( 0.0, 0.0 );
             PenColor( WHITE );
             Rectangle( 2 * tc.xMax, 2 * tc.yMax );
             SetFill( fFill );
             NextColorValue( DEFAULT );
         }
     }
 }

 /* Sphere - Draw and fill slices of a sphere. Rotate colors in EGA+ modes
  * with more than 4 color indexes.
  *
  * Params: None
  *
  * Return: None
  *
  * Uses:   tc
  */
 void Sphere()
 {
     double xCur, xSize, ySize, xInc;
     short ciBorder, fFill;

     ySize = xSize = tc.yMax * 0.9 * 2;
     fFill = SetFill( FALSE );
     NextColorIndex( 0 );
     xInc = xSize / 14;
     ciBorder = PenColor( DEFAULT );
     BorderColor( ciBorder );

     /* Draw slices. */
     for( xCur = xInc; xCur <= xSize; xCur += xInc * 2 )
         Ellipse( xCur, ySize );
     SetFill( TRUE );
     PenDown( FALSE );
     Turn( 90 );
     xSize /= 2;
     MoveTo( xSize - xInc, 0.0 );

     NextColorValue( LIMITED );

     /* Fill slices. */
     while( tc.xCur >= (-xSize + xInc))
     {
         PenColor( NextColorIndex( DEFAULT ) );
         FillIn();
         Move( -xInc );
     }

     while( !GetKey( NO_WAIT ) )
         NextColorValue( LIMITED );

     PenDown( TRUE );
     SetFill( fFill );
 }

 /* Polygons - Draws polygons (starting with triangle) of increasing
  * size by incrementing the number of sides without changing the
  * length of sides. Make sure pen is down.
  *
  * Params: None
  *
  * Return: 1 for user interrupt, 0 for edge of screen encountered
  *
  * Uses:   tc
  */
 int Polygons()
 {
     int cSides = 3, atrib = 1;
     double dxy = tc.yUnit;

     while( TRUE )
     {
         PenColor( NextColorIndex( DEFAULT ) );
         if( !Poly( cSides++, dxy += 1.5 ) )
             return FALSE;
         if( GetKey( NO_WAIT ) )
             return TRUE;
     }
 }

 /* Spiral - Draw a spiral by incrementing the length of each side
  * of a rotating figure.
  *
  * Params: ang - determines tightness
  *         xyInc - determines size of sides
  *
  * Return: 1 for user interrupt, 0 for edge of screen encountered
  *
  * Uses:   tc
  */
 int Spiral( int ang, double xyInc )
 {
     double xy = tc.yUnit;

     while( TRUE )
     {
         PenColor( NextColorIndex( DEFAULT ) );
         if( !Move( xy += xyInc ) )
             return FALSE;
         Turn( ang );
         if( GetKey( NO_WAIT ) )
             return TRUE;
     }
 }

 /* InSpiral - Draw an inverted spiral by increasing each angle
  * of a rotating figure while keeping the length of sides constant.
  *
  * Params: xy - determines size
  *         ang - initial angle determines shape
  *         angInc - determines tightness and shape
  *
  * Return: 1 for user interrupt, 0 for edge of screen encountered
  */
 int InSpiral( double xy, int ang, int angInc )
 {
     while( TRUE )
     {
         PenColor( NextColorIndex( DEFAULT ) );
         if( !Move( xy ) )
             return FALSE;
         Turn( ang += angInc );
         if( GetKey( NO_WAIT ))
             return TRUE;
     }
 }

 /* Bug - Draws a winged bug on the screen. Then moves it randomly
  * around the screen.
  *
  * Params: None
  *
  * Return: None
  *
  * Uses:   tc
  */
 void Bug()
 {

     static unsigned char uTopWing[] = { 0x81, 0x3c, 0xc3, 0x66,
                                         0x66, 0x0f, 0xf0, 0x18 };
     static unsigned char uBotWing[] = { 0x66, 0x0f, 0xf0, 0x18,
                                         0x81, 0x3c, 0xc3, 0x66 };
     char *buffer;               /* Buffer for image */

     /* Draw bug. */
     PenDown( FALSE );
     SetFill( TRUE );
     Move( 40.0 );               /* Draw and fill front wings */
     Turn( 90 );
     Move( 80.0 );
     PenColor( 1 );
     _setfillmask( uTopWing );
     Ellipse( 172.0, 70.0 );
     Turn( 180 );
     Move( 160.0 );
     Ellipse( 172.0, 70.0 );
     Turn(-90 );
     MoveTo( 0.0, 0.0 );
     Move( 25.0 );               /* Draw and fill back wings */
     Turn( 90 );
     Move( 70.0 );
     PenColor( 2 );
     _setfillmask( uBotWing );
     Ellipse( 150.0, 70.0 );
     Turn( 180 );
     Move( 140.0 );
     Ellipse( 150.0, 70.0 );
     Turn(-90 );
     MoveTo( 0.0, 0.0 );
     _setfillmask( NULL );       /* Draw body */
     PenColor( 3 );
     BorderColor( 3 );
     Ellipse( 52.0, 220.0 );
     PenColor( 1 );              /* Drill eyes */
     BorderColor( 1 );
     SetFill( FALSE );
     Move( 90.0 );
     Turn( 90 );
     Move( 22.0 );
     Circle( 20.0 );
     PenColor( 0 );
     FillIn();
     PenColor( 1 );
     Turn( 180 );
     Move( 44.0 );
     Circle( 20.0 );
     PenColor( 0 );
     FillIn();

     /* Move into position - top-right of image. */
     MoveTo( 0.0, 0.0 );
     TurnTo( 0 );
     Move( 120.0 );
     Turn( -90 );
     Move( 175.0 );
     Turn( 90 );

     /* Size image and allocate memory for it. */
     buffer = (char *)malloc( (size_t)ImageSize( 350.0, 240.0 ) );
     GetImage( 350.0, 240.0, buffer );

     /* Move randomly, adjusting at edges. */
     while( !GetKey( NO_WAIT ) )
     {
         if( tc.xCur <= (-tc.xMax + 15.0) )
             TurnTo( 90 );
         else if( tc.yCur <= (-tc.yMax + 15.0) )
             TurnTo( 180 );
         else if( tc.xCur >= (tc.xMax - 365.0) )
             TurnTo( 270 );
         else if( tc.yCur >= (tc.yMax - 255.0) )
             TurnTo( 0 );
         else
             Turn( getrandom( -20, 20 ) );
         Move( 3.0 );
         PutImage( buffer, _GPSET );
     }
     free( (char *)buffer );
 }

 /* Adjust - Allow the user to interactively adjust the display window.
  * Unshifted direction keys adjust the window size. Shifted direction
  * keys move the window. The numeric keypad plus and minus keys adjust
  * aspect without changing the window. A window frame and a diamond give
  * visual feedback on adjustments.
  *
  * Params: None
  *
  * Return: None
  *
  * Uses:   tc and vc
  */
 #define WININC 4
 void Adjust()
 {
     short iWriteMode;
     double xyRadius = 400.0, xEdge, yEdge;
     char achT[40];

     /* Display instructions. */
     _clearscreen( _GCLEARSCREEN );
     _settextposition( 2, 2 );
     _outtext(" Grey PLUS and MINUS Adjust aspect" );
     _settextposition( 3, 2 );
     _outtext(" Cursor keys         Size window" );
     _settextposition( 4, 2 );
     _outtext(" SHIFT cursor keys   Move window" );
     _settextposition( 5, 2 );
     _outtext(" ENTER               Finished" );

     /* Save old write mode and set XOR so you can erase figures by
      * redrawing. This allows lines to overwrite text without erasing.
      */
     iWriteMode = _getwritemode();
     _setwritemode( _GXOR );

     while( TRUE )
     {
         /* Display data. */
         _settextposition( 6, 2 );
         sprintf( achT, " ratio=%1.2f  xMax=%.f  yMax=%.f",
                  tc.yxRatio, tc.xMax, tc.yMax );
         _outtext( achT );

         /* Calculate current box edges. */
         xEdge = 2 * tc.xMax;
         yEdge = 2 * tc.yMax;

         /* Draw border rectangle and diamond that illustrates ratio. */
         Rectangle( xEdge, yEdge );
         Diamond( xyRadius );

         switch( GetKey( CLEAR_WAIT ) )
         {
             /* Adjust aspect. */
             case N_MINUS:
                 if( tc.yxRatio > 0.4 )
                     tc.yxRatio = (tc.xMax - (WININC * tc.yUnit)) / tc.yMax;
                 break;

             case N_PLUS:
                 if( tc.yxRatio < 8.0 )
                     tc.yxRatio = (tc.xMax + (WININC * tc.yUnit)) / tc.yMax;
                 break;

             /* Adjust window size. */
             case U_RT:
                 if( tc.xsLeft < (vc.numxpixels / 3) )
                     tc.xsLeft += WININC;
                 if( tc.xsRight > (vc.numxpixels - (vc.numxpixels / 3)) )
                     tc.xsRight -= WININC;
                 break;
             case U_LT:
                 if( tc.xsLeft )
                     tc.xsLeft -= WININC;
                 if( tc.xsRight < vc.numxpixels )
                     tc.xsRight += WININC;
                 break;
             case U_DN:
                 if( tc.ysTop < (vc.numypixels / 3) )
                     tc.ysTop += WININC;
                 if( tc.ysBot > (vc.numypixels - (vc.numypixels / 3)) )
                     tc.ysBot -= WININC;
                 break;
             case U_UP:
                 if( tc.ysTop )
                     tc.ysTop -= WININC;
                 if( tc.ysBot < vc.numypixels )
                     tc.ysBot += WININC;
                 break;

             /* Adjust window position. */
             case S_LT:
                 if( tc.xsLeft )
                 {
                     tc.xsLeft -= WININC;
                     tc.xsRight -= WININC;
                 }
                 break;
             case S_RT:
                 if( tc.xsRight < vc.numxpixels )
                 {
                     tc.xsLeft += WININC;
                     tc.xsRight += WININC;
                 }
                 break;
             case S_UP:
                 if( tc.ysTop )
                 {
                     tc.ysTop -= WININC;
                     tc.ysBot -= WININC;
                 }
                 break;
             case S_DN:
                 if( tc.ysBot < vc.numypixels )
                 {
                     tc.ysTop += WININC;
                     tc.ysBot += WININC;
                 }
                 break;

             /* Finished. */
             case ENTER:
                 _setwritemode( iWriteMode );
                 return;

             /* Ignore unknown key. */
             default:
                 break;
         }
         /* Redraw figures to erase them. Reset defaults. */
         Rectangle( xEdge, yEdge );
         Diamond( xyRadius );
         Home();
     }
 }

 /* Routine used by Adjust to draw its diamond. */
 void Diamond( double xy )
 {
         PenDown( FALSE );
         MoveTo( 0.0, xy );
         PenDown( TRUE );
         MoveTo( xy, 0.0 );
         MoveTo( 0.0, -xy );
         MoveTo( -xy, 0.0 );
         MoveTo( 0.0, xy );
         PenDown( FALSE );
         MoveTo( 0.0, 0.0 );
         PenDown( TRUE );
 }


 MENU.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\MENU.C

 /* MENU - Module of functions to put menus on the screen and handle keyboard
  * input. To use it, include the MENU.H file in your program. The following
  * functions are public:
  *
  *   Menu       -   Puts a menu on screen and reads input for it
  *   Box        -   Puts a box on screen (fill it yourself)
  *   GetKey     -   Gets ASCII or function key
  *   _outchar   -   Displays character using current text position and color
  *
  * The following structures are defined:
  *
  *   MENU       -   Defines menu colors, box type, and centering
  *   ITEM       -   Defines text of menu item and index of highlight characte
  *
  * The global variable "mnuAtrib" has type MENU. Change this variable to
  * change menu appearance.
  */

 #include <string.h>
 #include <stddef.h>
 #include <ctype.h>
 #include <graph.h>
 #include <bios.h>
 #include "menu.h"

 /* Prototype for internal function */
 static void Itemize( int row, int col, int fCur, ITEM itm, int cBlank );

 /* Default menu attribute. The default works for color or B&W. You can
  * override the default value by defining your own MENU variable and
  * assigning it to mnuAtrib, or you can modify specific fields at
  * run time. For example, you could use a different attribute for color
  * than for black and white.
  */
 MENU mnuAtrib =
 {
     _TBLACK, _TBLACK, _TWHITE, _TBRIGHTWHITE, _TBRIGHTWHITE,
     _TWHITE, _TWHITE, _TBLACK, _TWHITE, _TBLACK,
     TRUE,
     'Ú', '¿', 'Ù', 'À', '³', 'Ä'
 };

 /* Menu - Puts menu on screen and reads menu input from keyboard. When a
  * highlighted hot key or ENTER is pressed, returns the index of the
  * selected menu item.
  *
  * Params: row and col - If "fCentered" attribute of "mnuAtrib" is true,
  *           center row and column of menu; otherwise top left of menu
  *         aItem - array of structure containing the text of each item
  *           and the index of the highlighted hot key
  *         iCur - index of the current selection--pass 0 for first item,
  *           or maintain a static value
  *
  * Return: The index of the selected item
  *
  * Uses:   mnuAtrib
  */
 int Menu( int row, int col, ITEM aItem[], int iCur )
 {
     int cItem, cchItem = 2; /* Counts of items and chars per item       */
     int i, iPrev;           /* Indexes - temporary and previous         */
     int acchItem[MAXITEM];  /* Array of counts of character in items    */
     char *pchT;             /* Temporary character pointer              */
     char achHilite[36];     /* Array for highlight characters           */
     unsigned uKey;          /* Unsigned key code                        */
     long bgColor;           /* Screen color, position, and cursor       */
     short fgColor;
     struct rccoord rc;
     unsigned fCursor;

     /* Save screen information. */
     fCursor = _displaycursor( _GCURSOROFF );
     bgColor = _getbkcolor();
     fgColor = _gettextcolor();
     rc = _gettextposition();

     /* Count items, find longest, and put count of each in array. Also,
      * put the highlighted character from each in a string.
      */
     for( cItem = 0; aItem[cItem].achItem[0]; cItem++ )
     {
         acchItem[cItem] = strlen( aItem[cItem].achItem );
         cchItem = (acchItem[cItem] > cchItem) ? acchItem[cItem] : cchItem;
         i = aItem[cItem].iHilite;
         achHilite[cItem] = aItem[cItem].achItem[i];
     }
     cchItem += 2;
     achHilite[cItem] = 0;          /* Null-terminate and lowercase string  */
     strlwr( achHilite );

     /* Adjust if centered, and draw menu box. */
     if( mnuAtrib.fCentered )
     {
         row -= cItem / 2;
         col -= cchItem / 2;
     }
     Box( row++, col++, cItem, cchItem );

     /* Put items on menu. */
     for( i = 0; i < cItem; i++ )
     {
         if( i == iCur )
             Itemize( row + i, col, TRUE, aItem[i], cchItem - acchItem[i] );
         else
             Itemize( row + i, col, FALSE, aItem[i], cchItem - acchItem[i] );
     }

     while( TRUE )
     {
         /* Wait until a uKey is pressed, then evaluate it. */
         uKey = GetKey( WAIT );
         switch( uKey )
         {
             case U_UP:                      /* Up key       */
                 iPrev = iCur;
                 iCur = (iCur > 0) ? (--iCur % cItem) : cItem - 1;
                 break;
             case U_DN:                      /* Down key     */
                 iPrev = iCur;
                 iCur = (iCur < cItem) ? (++iCur % cItem) : 0;
                 break;
             default:
                 if( uKey > 256 )            /* Ignore unknown function key  *
                     continue;
                 pchT = strchr( achHilite, (char)tolower( uKey ) );
                 if( pchT != NULL )          /* If in highlight string,      *
                     iCur = pchT - achHilite;/*   evaluate and fall through  *
                 else
                     continue;               /* Ignore unknown ASCII key     *
             case ENTER:
                 _setbkcolor( bgColor );
                 _settextcolor( fgColor );
                 _settextposition( rc.row, rc.col );
                 _displaycursor( fCursor );
                 return iCur;
         }
         /* Redisplay current and previous. */
         Itemize( row + iCur, col,
                  TRUE, aItem[iCur], cchItem - acchItem[iCur] );
         Itemize( row + iPrev, col,
                  FALSE, aItem[iPrev], cchItem - acchItem[iPrev] );
     }
 }

 /* Box - Draw menu box, filling interior with blanks of the border color.
  *
  * Params: row and col - upper left of box
  *         rowLast and colLast - height and width
  *
  * Return: None
  *
  * Uses:   mnuAtrib
  */
 void Box( int row, int col, int rowLast, int colLast )
 {
     int i;
     char achT[MAXITEM + 2];         /* Temporary array of characters */

     /* Set color and position. */
     _settextposition( row, col );
     _settextcolor( mnuAtrib.fgBorder );
     _setbkcolor( mnuAtrib.bgBorder );

     /* Draw box top. */
     achT[0] = mnuAtrib.chNW;
     memset( achT + 1, mnuAtrib.chEW, colLast );
     achT[colLast + 1] = mnuAtrib.chNE;
     achT[colLast + 2] = 0;
     _outtext( achT );

     /* Draw box sides and center. */
     achT[0] = mnuAtrib.chNS;
     memset( achT + 1, ' ', colLast );
     achT[colLast + 1] = mnuAtrib.chNS;
     achT[colLast + 2] = 0;
     for( i = 1; i <= rowLast; ++i )
     {
         _settextposition( row + i, col );
         _outtext( achT );
     }

     /* Draw box bottom. */
     _settextposition( row + rowLast + 1, col );
     achT[0] = mnuAtrib.chSW;
     memset( achT + 1, mnuAtrib.chEW, colLast );
     achT[colLast + 1] = mnuAtrib.chSE;
     achT[colLast + 2] = 0;
     _outtext( achT );
 }

 /* Itemize - Display one selection (item) of a menu. This function
  * is normally only used internally by Menu.
  *
  * Params: row and col - top left of menu
  *         fCur - flag set if item is current selection
  *         itm - structure containing item text and index of highlight
  *         cBlank - count of blanks to fill
  *
  * Return: none
  *
  * Uses:   mnuAtrib
  */
 void Itemize( int row, int col, int fCur, ITEM itm, int cBlank )
 {
     int i;
     char achT[MAXITEM];             /* Temporary array of characters */

     /* Set text position and color. */
     _settextposition( row, col );
     if( fCur )
     {
         _settextcolor( mnuAtrib.fgSelect );
         _setbkcolor( mnuAtrib.bgSelect );
     }
     else
     {
         _settextcolor( mnuAtrib.fgNormal );
         _setbkcolor( mnuAtrib.bgNormal );
     }

     /* Display item and fill blanks. */
     strcat( strcpy( achT, " " ), itm.achItem );
     _outtext( achT );
     memset( achT, ' ', cBlank-- );
     achT[cBlank] = 0;
     _outtext( achT );

     /* Set position and color of highlight character, then display it. */
     i = itm.iHilite;
     _settextposition( row, col + i + 1 );
     if( fCur )
     {
         _settextcolor( mnuAtrib.fgSelHilite );
         _setbkcolor( mnuAtrib.bgSelHilite );
     }
     else
     {
         _settextcolor( mnuAtrib.fgNormHilite );
         _setbkcolor( mnuAtrib.bgNormHilite );
     }
     _outchar( itm.achItem[i] );
 }

 /* GetKey - Gets a key from the keyboard. This routine distinguishes
  * between ASCII keys and function or control keys with different shift
  * states. It also accepts a flag to return immediately if no key is
  * available.
  *
  * Params: fWait - Code to indicate how to handle keyboard buffer:
  *   NO_WAIT     Return 0 if no key in buffer, else return key
  *   WAIT        Return first key if available, else wait for key
  *   CLEAR_WAIT  Throw away any key in buffer and wait for new key
  *
  * Return: One of the following:
  *
  *   Keytype                                High Byte    Low Byte
  *   -------                                ---------    --------
  *   No key available (only with NO_WAIT)       0           0
  *   ASCII value                                0        ASCII code
  *   Unshifted function or keypad               1        scan code
  *   Shifted function or keypad                 2        scan code
  *   CTRL function or keypad                    3        scan code
  *   ALT function or keypad                     4        scan code
  *
  * Note:   getkey cannot return codes for keys not recognized by BIOS
  *         int 16, such as the CTRL-UP or the 5 key on the numeric keypad.
  */
 unsigned GetKey( int fWait )
 {
     unsigned uKey, uShift;

     /* If CLEAR_WAIT, drain the keyboard buffer. */
     if( fWait == CLEAR_WAIT )
         while( _bios_keybrd( _KEYBRD_READY ) )
             _bios_keybrd( _KEYBRD_READ );

     /* If NO_WAIT, return 0 if there is no key ready. */
     if( !fWait && !_bios_keybrd( _KEYBRD_READY ) )
         return FALSE;

     /* Get key code. */
     uKey = _bios_keybrd( _KEYBRD_READ );

     /* If low byte is not zero, it's an ASCII key. Check scan code to see
      * if it's on the numeric keypad. If not, clear high byte and return.
      */
     if( uKey & 0x00ff )
         if( (uKey >> 8) < 69 )
             return( uKey & 0x00ff );

     /* For function keys and numeric keypad, put scan code in low byte
      * and shift state codes in high byte.
      */
     uKey >>= 8;
     uShift = _bios_keybrd( _KEYBRD_SHIFTSTATUS ) & 0x000f;
     switch( uShift )
     {
         case 0:
             return( 0x0100 | uKey );  /* None (1)    */
         case 1:
         case 2:
         case 3:
             return( 0x0200 | uKey );  /* Shift (2)   */
         case 4:
             return( 0x0300 | uKey );  /* Control (3) */
         case 8:
             return( 0x0400 | uKey );  /* Alt (4)     */
     }
 }

 /* _outchar - Display a character. This is the character equivalent of
  * _outtext. It is affected by _settextposition, _settextcolor, and
  * _setbkcolor. It should not be used in loops. Build strings and then
  * _outtext to show multiple characters.
  *
  * Params: out - character to be displayed
  *
  * Return: none
  */
 void _outchar( char out )
 {
     static char achT[2] = " ";      /* Temporary array of characters */

     achT[0] = out;
     _outtext( achT );
 }


 SNAP.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\SNAP.C

 /* Snap - An OS/2 screen capture utility
  *
  * Snap starts a background process containing a keyboard monitor.
  * The monitor checks for a hot key (ALT-*). If found, a thread is
  * launched to write the screen to a file. Various command line options
  * allow you to specify capture behavior or to deinstall the program.
  *
  * To compile, use the following command line:
  *
  *   cl /MT /G2s snap.c
  */

 /* Function prototypes */
 int  Monitor( void );
 void Snap( unsigned long _far *arg );
 void BackError( char *msgErr );
 void Syntax( void );
 void EvalOptions( int argc, char **argv );

 /* Define constants to enable function groups in OS2 include files */
 #define INCL_NOCOMMON
 #define INCL_NOPM
 #define INCL_KBD            // KBDKEYINFO
 #define INCL_VIO            // Vio functions
 #define INCL_DOSMEMMGR      // DosGetShrSeg, DosAllocShrSeg,
 #define INCL_DOSMONITORS    // DosMon functions
 #define INCL_DOSMISC        // DosGetEnv
 #define INCL_DOSSEMAPHORES  // DosSem functions
 #define INCL_DOSPROCESS     // DosBeep, DosSetPrty
 #define INCL_DOSINFOSEG     // DosGetInfoSeg
 #include <os2.h>

 #include <malloc.h>         // malloc, free
 #include <process.h>        // _beginthread, _endthread, exit, spawnl
 #include <string.h>         // strcpy, strcat
 #include <stdlib.h>         // atoi, itoa, _MAX_PATH
 #include <stddef.h>         // _threadid variable
 #include <stdio.h>          // puts, fopen, fwrite, etc.
 #include <conio.h>          // kbhit

 #define CON  0              // Handle for the console device
 #define FAIL -1             // Fail to start thread

 #define STAR    0x37        // Scan code for * on numeric keypad
 #define RELEASE 0x40        // Bit mask for key release

 /* Name and structure for shared memory data */
 char szShrSeg[] = { "\\SHAREMEM\\SNAP.DAT" };
 struct SHARED
 {
     BOOL  fSound;               // Sound flag
     BOOL  fAppend;              // Append flag
     BOOL  fInstall;             // Install flag
     SHORT cScreen;              // Count of screens
     LONG  lfWait;               // Wait semaphore
     CHAR  achSnap[_MAX_PATH];   // Snap file name
 } _far *pshrSnap = 0;           // Initialize offset to 0. Segment will
                                 // be initialized by system call.

 /* Count in bytes of shared segment */
 #define C_SHARESEG sizeof( struct SHARED )

 void main( int argc, char **argv )
 {
     USHORT offCmd;              // Dummy for DosGetEnv
     CHAR   *pchSnapExe = 0;     // Pointer to name of executable file
                                 //   (offset initialized to 0)

     /* Try to get shared segment (note how selector value is placed
      * directly in the segment word of the pointer address). There are
      * three possibilities:
      *
      *   - We can't get memory. This means SNAP is not installed,
      *     so we must allocate the memory and exec ourself in the
      *     background to install the monitor.
      *   - We can get memory and we are not installed. This means
      *     we have been execed by previous process to install monitor.
      *   - We can get memory and we are already installed. This means
      *     we were just called to modify options.
      */
     if( DosGetShrSeg( szShrSeg, (PSEL)&pshrSnap + 1 ) )
     {
         /* Segment doesn't exist, so try to allocate it. */
         if( DosAllocShrSeg( C_SHARESEG, szShrSeg, (PSEL)&pshrSnap + 1 ) )
         {
             puts( "Can't allocate shared memory" );
             exit( 1 );
         }
         else
         {
             /* This is the first time through, so we must execute
              * ourself to do installation. First set defaults, then
              * modify for options.
              */
             pshrSnap->fSound = TRUE;
             pshrSnap->fAppend = TRUE;
             pshrSnap->cScreen = 0;
             pshrSnap->fInstall = FALSE;
             strcpy( pshrSnap->achSnap, "SNAP.IMG" );
             DosSemSet( &pshrSnap->lfWait );
             EvalOptions( argc, argv );

             /* Get our own path name from the end of the environment
              * segment. This is the most reliable way to get the full
              * path name of the current file, since the extension is
              * ommitted from argv[0].
              */
             DosGetEnv( (PUSHORT)&pchSnapExe + 1, &offCmd );

             /* Adjust forward until we point to full path of .EXE file. */
             while( *pchSnapExe++ || *pchSnapExe )
                 ;
             ++pchSnapExe;

             /* Spawn ourself as a background process. Can't install
              * monitor now because we are in foreground. A background
              * process needs to install the monitor.
              */
             if( spawnl( P_DETACH, pchSnapExe, pchSnapExe, NULL ) == -1 )
             {
                 puts( "Can't start background process" );
                 exit( 1 );
             }
             puts( "Snap installed" );
             Syntax();

             /* Wait for background child process to report receiving
              * shared data.
              */
             DosSemWait( &pshrSnap->lfWait, SEM_INDEFINITE_WAIT );
         }
     }
     else
     {
         /* Already installed. We are being run to evaluate options and
          * modify behavior accordingly.
          */
         if( pshrSnap->fInstall )
             if( argc == 1 )
                 puts( "Snap already installed" );
             else
                 EvalOptions( argc, argv );
         else
         {
             /* Not installed, so we were execed by original SNAP to
              * install monitor. Tell parent we have received data, set
              * install flag, and install monitor.
              */
             DosSemClear( &pshrSnap->lfWait );

             /* Set installed flag and start monitor. */
             pshrSnap->fInstall = TRUE;

             exit( Monitor() );
         }
     }
 }

 /* Monitor routine checks keystrokes as they occur and calls
  * the Snap thread if the hot key is pressed.
  *
  * Params: None
  *
  * Return: 1 if error, 0 if deinstalled
  *
  * Uses:   pshrSnap - Shared memory structure
  */
 int Monitor()
 {
     #define BUFSIZE 128             // Size for monitor buffers:
                                     //   64 minimum, 128 recommended
     #define STACKSIZE 2048          // 2K minimum for any system call

     PMONIN pmnin;
     PMONOUT pmnout;

     struct KEYPACKET                // KBD monitor data record
     {
         USHORT fMon;
         KBDKEYINFO kki;
         USHORT fDD;
     } keyBuff;
     USHORT ckeyBuff = sizeof( keyBuff );

     HMONITOR hKeyMon;               // Keyboard handle from monitor open
     PGINFOSEG pGIS = 0, pLIS = 0;   // Information segment structures
     LONG  lfSnap = FALSE;           // Semaphore for each Snap thread

     /* Allocate space for monitor read/write buffers and mark size. */
     pmnin = (PMONIN)malloc( BUFSIZE );
     pmnin->cb = BUFSIZE;
     pmnout = (PMONOUT)malloc( BUFSIZE );
     pmnout->cb = BUFSIZE;

     /* Register monitor to the keyboard device (KBD$). */
     if( DosMonOpen( "KBD$", &hKeyMon ) )
     {
         BackError( "Can't open monitor" );
         return 1;
     }

     /* Get information segments (all we really need is ID of current
      * screen group from Global Information Segment).
      */
     DosGetInfoSeg( (PSEL)&pGIS + 1, (PSEL)&pLIS + 1 );

     /* Register the monitor buffers to the current screen group */
     if( DosMonReg( hKeyMon, (PBYTE)pmnin, (PBYTE)pmnout,
                    MONITOR_DEFAULT, pGIS->sgCurrent ) )
     {
         BackError( "Can't register monitor" );
         return 1;
     }

     /* Make process time critical so keys are interpreted without delay. */
     DosSetPrty( PRTYS_PROCESS, PRTYC_TIMECRITICAL, 0, 0 );

     /* Monitor loop - read into monitor buffer and examine. Take action
      * if hot key, otherwise pass on to device driver.
      */
     while( pshrSnap->fInstall )
     {
         DosMonRead( (PBYTE)pmnin, IO_WAIT, (PBYTE)&keyBuff, &ckeyBuff );

         /* Snap if ALT+STAR is down. */
         if( ((keyBuff.kki.chScan == STAR) || (keyBuff.kki.chScan == 0x2a)) &&
             (keyBuff.kki.fsState & ALT) &&
             (!(keyBuff.fDD & RELEASE)) )
         {
             /* Make sure last thread is finished */
             DosSemWait( &lfSnap, SEM_INDEFINITE_WAIT );
             if( (_beginthread( Snap, NULL, STACKSIZE,
                                (PVOID)&lfSnap )) == FAIL )
                 BackError( "Can't start screen capture thread" );
             else
                 DosSemSet( &lfSnap );
         }
         else
             /* Pass the key through if it is not the hot key */
             DosMonWrite( (PBYTE)pmnout, (PBYTE)&keyBuff, ckeyBuff );
     }

     /* Close monitor */
     free( pmnin );
     free( pmnout );
     DosMonClose( hKeyMon );
     return 0;
 }

 /* Screen capture routine (run as a thread). Does a pop-up to get access
  * to the current screen. Reads characters from the screen into a buffer.
  * Then filters trailing spaces as it writes buffer to a file.
  *
  * Params: plfSnap - pointer to flag indicated snap status
  *
  * Return: none
  *
  * Uses:   pshrSnap - Shared memory structure
  */
 void Snap( ULONG _far *plfSnap )
 {
     enum { NOTE_B = 494, NOTE_C = 523, NOTE_F = 698 };
     CHAR   *pchScreen;              // Buffer for captured screen
     USHORT cbScreen;                // Count of bytes in buffer
     FILE   *sFile;                  // File stream
     USHORT usLine, usPos, usWidth;
     CHAR   ach[5];
     USHORT fWait = VP_WAIT | VP_TRANSPARENT;
     VIOMODEINFO vmi = { sizeof( vmi ) };

     if( pshrSnap->fSound )
         DosBeep( NOTE_F, NOTE_C );

     /* Pop up to current screen and check its size. */
     VioPopUp( &fWait, CON );
     VioGetMode( &vmi, CON );

     /* Allocate memory for a full screen plus one byte */
     cbScreen = vmi.col * vmi.row;
     pchScreen = malloc( cbScreen + 1 );

     /* Read screen and end popup */
     VioReadCharStr( pchScreen, &cbScreen, 0, 0, CON );
     VioEndPopUp( 0 );

     /* Increment screen count (4 digits or less) and convert to string. */
     pshrSnap->cScreen = (pshrSnap->cScreen + 1) % 9999;
     itoa( pshrSnap->cScreen, ach, 10 );

     /* Make numbered file name if appropriate. */
     if( !pshrSnap->fAppend )
         strcat( strcat( strcpy( pshrSnap->achSnap, "SNAP" ), ach ), ".IMG" );

     /* Open file and write buffer to it a line at a time */
     if( (sFile = fopen( pshrSnap->achSnap, "at" )) == NULL )
     {
         BackError( "Can't open file" );
         --pshrSnap->cScreen;
     }
     else
     {
         if( pshrSnap->fAppend )
         {
             /* Not using fprintf reduces overhead. */
             fputs( "**** Screen ", sFile );
             fputs( ach, sFile );
             fputs( " ****\n", sFile );
         }

         for( usLine = 0, usPos = 0; usLine < vmi.row; usLine++ )
         {
             /* Throw away trailing spaces */
             for( usWidth = vmi.col;
                  (pchScreen[usPos + usWidth - 1] == ' ' ) && usWidth;
                  usWidth-- )
                 ;
             /* Write line and newline */
             fwrite( pchScreen + usPos, 1, usWidth, sFile );
             fputc( '\n', sFile );
             usPos += vmi.col;
         }
         fclose( sFile );
     }
     if( pshrSnap->fSound )
         DosBeep( NOTE_C, NOTE_B );

     /* Free memory and let parent know we are done */
     free( pchScreen );
     DosSemClear( plfSnap );
 }

 /* Displays an error message from within a background process or thread.
  * The monitor is in the background and has no screen group, so it must
  * use VioPopUp to get access to the screen.
  *
  * Params: msgErr - error message string
  *
  * Return: None
  */
 void BackError( char *pchErr )
 {
     USHORT fWait = VP_WAIT | VP_TRANSPARENT;

     VioPopUp( &fWait, CON );
     puts( pchErr );
     puts( "Press any key to continue . . ." );
     while( !kbhit() )
         ;
     VioEndPopUp( CON );
 }

 /* Displays syntax.
  *
  * Params: None
  *
  * Return: None
  */
 void Syntax()
 {
     puts( "\nOptions: " );
     puts( "\t/H\t  Display help." );
     puts( "\t/S\t  Turn sound on (default)." );
     puts( "\t/Q\t  Turn sound off." );
     puts( "\t/D\t  Deinstall." );
     puts( "\t/A [path] Append each screen to a file (complete path allowed)."
     puts( "\t\t  If no file given, default is SNAP.IMG in current directory"
     puts( "\t\t  Resets screen number to 1." );
     puts( "\t/N [num]  Create numbered file for each screen." );
     puts( "\t\t  Example: SNAP1.IMG, SNAP2.IMG in current directory." );
     puts( "\t\t  Resets screen number to 1 or to num if given." );
 }

 /* Evaluate command-line options.
  *
  * Params: argc - Number of arguments
  *         argv - Pointer to argument list
  *
  * Return: none
  *
  * Uses: Shared memory structure - pshrSnap
  */
 void EvalOptions( int argc, char **argv )
 {
     SHORT i;

     /* Look for and handle arguments */
     for(  i = 1; i < argc; i++ )
     {
         if( argv[i][0] == '/' || argv[i][0] == '-' )
         {
             switch( argv[i][1] )
             {
                 case 'A':
                 case 'a':
                     pshrSnap->fAppend = TRUE;
                     pshrSnap->cScreen = 0;
                     if( (argv[++i]) &&
                         (argv[i][0] != '/') &&
                         (argv[i][0] != '-') )

                     {
                         strcpy( pshrSnap->achSnap, argv[i] );
                         puts( "Append mode - name set" );
                     }
                     else
                         puts( "Append mode" );
                     break;

                 case 'N':
                 case 'n':
                     pshrSnap->fAppend = FALSE;
                     puts( "Numbered file mode" );
                     if( (argv[++i]) &&
                         (argv[i][0] != '/') &&
                         (argv[i][0] != '-') )
                     {
                         pshrSnap->cScreen = (atoi( argv[i] ) % 9999) - 1;
                     }
                     else
                         pshrSnap->cScreen = 0;
                     break;

                 case 'Q':
                 case 'q':
                     pshrSnap->fSound = FALSE;
                     puts( "Sound off" );
                     break;

                 case 'S'  :
                 case 's'  :
                     pshrSnap->fSound = TRUE;
                     puts( "Sound on" );
                     break;

                 case 'D':
                 case 'd':
                     if( pshrSnap->fInstall )
                     {
                         pshrSnap->fInstall = FALSE;
                         puts( "Deinstalling" );
                     }
                     else
                         exit( 0 );
                     break;

                 case 'H'  :
                 case 'h'  :
                     if( pshrSnap->fInstall )
                         Syntax();
                     break;
             }
         }
     }
 }


 SORTDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\SORTDEMO.C

 /* SORTDEMO -This program graphically demonstrates six common sorting
  * algorithms. It prints 25 or 43 horizontal bars of different lengths
  * in random order, then sorts the bars from shortest to longest.
  * The program can beep to generate different pitches, depending on the
  * length and position of the bar.
  *
  * The program can be created for DOS or OS/2. To create for OS/2, define
  * the symbol OS2. Command lines for DOS and OS/2 are shown below:
  *
  * DOS:
  *    cl /Lr sortdemo.c graphics.lib
  *
  * OS/2:
  *    cl /Lp /DOS2 sortdemo.c grtextp.lib
  */

 #include <graph.h>          // _outtext, _settextcolor, _settextposition
 #include <string.h>         // strlen
 #include <stdio.h>          // sprintf
 #include <conio.h>          // getch
 #include <stdlib.h>         // srand, rand, toupper
 #include <malloc.h>         // malloc, free
 #include <time.h>           // time, clock

 enum BOOL { FALSE, TRUE };

 /* Structure type for colored bars */
 typedef struct _BAR
 {
     char len;
     char clr;
 } BAR;

 /* Structure type for screen cells */
 typedef struct _CELL
 {
     char chChar;
     char chAttr;
 } CELL;

 /* Function prototypes */
 void main( void  );
 void Cls( void  );
 void InitMenu( void  );             // Menu Functions
 void DrawFrame( int iTop, int Left, int Width, int Height );
 void RunMenu( void  );
 void DrawTime( int iCurrentRow );
 void InitBars( void  );             // Bar functions
 void ReInitBars( void  );
 void DrawBar( int iRow );
 void SwapBars( int iRow1, int iRow2 );
 void Swaps( BAR *one, BAR *two );
 void InsertionSort( void  );        // Sort functions
 void BubbleSort( void  );
 void HeapSort( void  );
 void PercolateUp( int iMaxLevel );
 void PercolateDown( int iMaxLevel );
 void ExchangeSort( void  );
 void ShellSort( void  );
 void QuickSort( int iLow, int iHigh );
 void Beep( int frequency, int duration );
 void Sleep( clock_t wait );

 /* Macro */
 #define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))
 #define _outtextxy( ach, x, y )   { _settextposition( y, x ); \
                                     _outtext( ach ); }

 /* Constants */
 #define ESC        27
 #define BLANK      32
 #define BLOCK      223
 #define TOP        1
 #define FIRSTMENU  (TOP + 6)
 #define LEFTCOLUMN 48
 #define PROMPTPOS  27
 #define WIDTH      (80 - LEFTCOLUMN)
 #define HEIGHT     (cszMenu + 2)
 #define MENUCOLOR  15
 #define BLANKCOLOR 7
 #define BACKCOLOR  0L
 #define PAUSELIMIT 900

 /* Global variables */
 clock_t clStart, clFinish, clPause = 30L;
 int fSound, iCurChoice, iSwaps, iCompares, cRow;

 BAR abarWork[43], abarPerm[43]; // Temporary and permanent sort arrays

 char *aszMenu[] =
 {
     "",
     "       C Sorting Demo",
     "",
     "              Time  Swap  Comp",
     "",
     "Insertion",
     "Bubble",
     "Heap",
     "Exchange",
     "Shell",
     "Quick",
     "",
     "Toggle Sound: ",
     "",
     "Pause Factor: ",
     "<   (Slower)",
     ">   (Faster)",
     "",
     "Type first character of",
     "choice ( I B H E S Q T < > )",
     "or ESC key to end program: "
     "",
 };
 int cszMenu = sizeof( aszMenu ) / sizeof( aszMenu[0] );

 void main()
 {
     cRow = _settextrows( 43 );
     _clearscreen( _GCLEARSCREEN );
     _displaycursor( _GCURSOROFF );
     InitBars();
     InitMenu();
     RunMenu();                     // Respond to menu until quit
     _setvideomode( _DEFAULTMODE );
 }


 /* InitMenu - Calls the DrawFrame procedure to draw the frame around the
  * sort menu, then prints the different options stored in the menu array.
  */
 void InitMenu()
 {
     int  i;
     char ach[15];

     _settextcolor( MENUCOLOR );
     _setbkcolor( BACKCOLOR );
     DrawFrame( TOP, LEFTCOLUMN - 3, WIDTH + 3, HEIGHT );
     for( i = 0; i < cszMenu; i++ )
         _outtextxy( aszMenu[i], LEFTCOLUMN, TOP + i + 1 );

     /* Print the current value for Sound. */
     if( fSound )
         strcpy( ach, "ON " );
     else
         strcpy( ach, "OFF" );

     _outtextxy( ach, LEFTCOLUMN + 14, cszMenu - 7 );
     sprintf( ach, "%3.3u", clPause / 30 );
     _outtextxy( ach, LEFTCOLUMN + 14, cszMenu - 5 );

     /* Erase the speed option if the length of the pause is at a limit. */
     strcpy( ach, "            " );
     if( clPause == PAUSELIMIT )
         _outtextxy( ach, LEFTCOLUMN, cszMenu - 4 );
     if( clPause == 0L )
         _outtextxy( ach, LEFTCOLUMN, cszMenu - 3 );
 }


 /* DrawFrame - Draws a rectangular frame using the double-line box
  * characters. The parameters iTop, iLeft, iWidth, and iHeight are
  * the row and column arguments for the upper-left and lower-right
  * corners of the frame.
  */
 void DrawFrame( int iTop, int iLeft, int iWidth, int iHeight )
 {
     enum { ULEFT = 201, URIGHT = 187,
            LLEFT = 200, LRIGHT = 188, VERTICAL = 186, HORIZONTAL = 205
          };
     int iRow;
     char achTmp[80];

     memset( achTmp, HORIZONTAL, iWidth );
     achTmp[0] = ULEFT;
     achTmp[iWidth - 1] = URIGHT;
     achTmp[iWidth] = '\0';
     _outtextxy( achTmp, iLeft, iTop );

     memset( achTmp, BLANK, iWidth );
     achTmp[0] = VERTICAL;
     achTmp[iWidth - 1] = VERTICAL;
     for(  iRow = iTop + 1; iRow <= iHeight; iRow++ )
         _outtextxy( achTmp, iLeft, iRow );

     memset( achTmp, HORIZONTAL, iWidth );
     achTmp[0] = LLEFT;
     achTmp[iWidth - 1] = LRIGHT;
     _outtextxy( achTmp, iLeft, iTop + iHeight );
 }


 /* RunMenu - The RunMenu procedure first calls the ReInitBars
  * procedure to make sure the abarWork is in its unsorted form, then
  * prompts the user to make one of the following choices:
  *
  *  - Run one of the sorting algorithms
  *  - Toggle sound on or off
  *  - Increase or decrease speed
  *  - End the program
  */
 void RunMenu()
 {
     char    ch;

     while( TRUE )
     {
         iSwaps = iCompares = 0;
         _settextposition( TOP + cszMenu, LEFTCOLUMN + PROMPTPOS );
         _displaycursor( _GCURSORON );
         ch = getch();
         _displaycursor( _GCURSOROFF );

         /* Branch to the appropriate procedure depending on the key. */
         switch( toupper( ch ) )
         {
             case 'I':
                 iCurChoice = 0;
                 ReInitBars();
                 InsertionSort();
                 DrawTime( 0 );   // Print final time
                 break;
             case 'B':
                 iCurChoice = 1;
                 ReInitBars();
                 BubbleSort();
                 DrawTime( 0 );
                 break;

             case 'H':
                 iCurChoice = 2;
                 ReInitBars();
                 HeapSort();
                 DrawTime( 0 );
                 break;

             case 'E':
                 iCurChoice = 3;
                 ReInitBars();
                 ExchangeSort();
                 DrawTime( 0 );
                 break;

             case 'S':
                 iCurChoice = 4;
                 ReInitBars();
                 ShellSort();
                 DrawTime( 0 );
                 break;

             case 'Q':
                 iCurChoice = 5;
                 ReInitBars();
                 QuickSort( 0, cRow );
                 DrawTime( 0 );
                 break;

             case '>':
                 /* Decrease pause length to speed up sorting time, then
                  * redraw the menu to clear any timing results (since
                  * they won't compare with future results).
                  */
                 if( clPause )
                     clPause -= 30L;
                 InitMenu();
                 break;

             case '<':
                 /* Increase pause length to slow down sorting time. */
                 if( clPause <= 900L )
                     clPause += 30L;
                 InitMenu();
                 break;

             case 'T':
                 fSound = !fSound;
                 InitMenu();
                 break;

             case ESC:
                 return;

             default:        // Unknown key ignored
                 break;
         }
     }
 }


 /* DrawTime - Prints seconds elapsed since the given sorting routine
  * started. Note that this time includes both the time it takes to redraw
  * the bars plus the pause while Beep plays a note, and thus is not an
  * accurate indication of sorting speed.
  */
 void DrawTime( int iCurrentRow )
 {
     char achTiming[80];

     _settextcolor( MENUCOLOR );
     clFinish = clock();

     sprintf( achTiming, "%7.2f  %4.i  %4.i",
              (float)(clFinish - clStart) / CLOCKS_PER_SEC,
              iSwaps, iCompares );

     /* Print the number of seconds elapsed */
     _outtextxy( achTiming, LEFTCOLUMN + 11, FIRSTMENU + iCurChoice );
     if( fSound )
     {
         Beep( 60 * iCurrentRow, 75 );   // Play note
         Sleep( clPause - 75L );         // Pause adjusted for note duration
     }
     else
         Sleep( clPause );               // Pause
 }


 /* InitBars - Initializes the bar arrays and the menu box.
  */
 void InitBars()
 {
     struct videoconfig vc;
     int aTemp[43], iRow, iRowMax, iRand, iColorMax, iLength;

     /* Seed the random-number generator. */
     srand( (unsigned)time( NULL ) );
     fSound = TRUE;
     clPause = 30L;

     /* If monochrome or color burst disabled, use one color */
     _getvideoconfig( &vc );
     if( (vc.monitor == _MONO) || (vc.mode == _TEXTBW80) ||
                                  (vc.mode == _TEXTBW40) )
         iColorMax = 1;
     else
         iColorMax = 15;

     /* Randomize an array of rows. */
     for( iRow = 0; iRow < cRow; iRow++ )
         aTemp[iRow] = iRow + 1;
     iRowMax = cRow - 1;
     for( iRow = 0; iRow < cRow; iRow++ )
     {
         /* Find a random element in aTemp between 0 and iRowMax,
          * then assign the value in that element to iLength.
          */
         iRand = GetRandom( 0, iRowMax );
         iLength = aTemp[iRand];

         /* Overwrite the value in aTemp[iRand] with the value in
          * aTemp[iRowMax] so the value in aTemp[iRand] is
          * chosen only once.
          */
         aTemp[iRand] = aTemp[iRowMax];

         /* Decrease the value of iRowMax so that aTemp[iRowMax] can't
          * be chosen on the next pass through the loop.
          */
         --iRowMax;
         abarPerm[iRow].len = iLength;
         if( iColorMax == 1 )
             abarPerm[iRow].clr = BLANKCOLOR;
         else
             abarPerm[iRow].clr = iLength % iColorMax + 1;
     }

     /* Assign permanent sort values to temporary and draw unsorted bars. */
     ReInitBars();
 }


 /* ReInitBars - Restores the array abarWork to its original unsorted
  * state and draws the unsorted bars.
  */
 void ReInitBars()
 {
     int iRow;

     clStart = clock();
     for( iRow = 0; iRow < cRow; iRow++ )
     {
         abarWork[iRow] = abarPerm[iRow];
         DrawBar( iRow );
     }
 }


 /* DrawBar - Prints a bar at a specified row by first blanking the
  * old bar, then drawing a new bar having the length and color given in
  * the work array.
  */
 void DrawBar( int iRow )
 {
     int  cSpace;
     char achT[43];

     memset( achT, BLOCK, abarWork[iRow].len );
     cSpace = cRow - abarWork[iRow].len;
     memset( achT + abarWork[iRow].len, ' ', cSpace );
     achT[cRow] = '\0';
     _settextcolor( abarWork[iRow].clr );
     _outtextxy( achT, 0, iRow + 1 );
 }


 /* SwapBars - Calls DrawBar twice to switch the two bars in iRow1 and
  * iRow2, then calls DrawTime to update the time.
  */
 void SwapBars( int iRow1, int iRow2 )
 {
     DrawBar( iRow1 );
     DrawBar( iRow2 );
     DrawTime( iRow1 );
 }


 /* Swaps - Exchanges two bar structures.
  */
 void Swaps( BAR *bar1, BAR *bar2 )
 {
     BAR barTmp;

     ++iSwaps;
     barTmp = *bar1;
     *bar1  = *bar2;
     *bar2  = barTmp;
 }


 /* InsertionSort - InsertionSort compares the length of each element
  * with the lengths of all the preceding elements. When the appropriate
  * place for the new element is found, the element is inserted and
  * all the other elements are moved down one place.
  */
 void InsertionSort()
 {
     BAR barTemp;
     int iRow, iRowTmp, iLength;

     /* Start at the top. */
     for( iRow = 0; iRow < cRow; iRow++ )
     {
         barTemp = abarWork[iRow];
         iLength = barTemp.len;

         /* As long as the length of the temporary element is greater than
          * the length of the original, keep shifting the elements down.
          */
         for( iRowTmp = iRow; iRowTmp; iRowTmp-- )
         {
             iCompares++;
             if( abarWork[iRowTmp - 1].len > iLength )
             {
                 ++iSwaps;
                 abarWork[iRowTmp] = abarWork[iRowTmp - 1];
                 DrawBar( iRowTmp );         // Print the new bar
                 DrawTime( iRowTmp );        // Print the elapsed time

             }
             else                            // Otherwise, exit
                 break;
         }

         /* Insert the original bar in the temporary position. */
         abarWork[iRowTmp] = barTemp;
         DrawBar( iRowTmp );
         DrawTime( iRowTmp );
     }
 }


 /* BubbleSort - BubbleSort cycles through the elements, comparing
  * adjacent elements and swapping pairs that are out of order. It
  * continues to do this until no out-of-order pairs are found.
  */
 void BubbleSort()
 {
     int iRow, iSwitch, iLimit = cRow;

     /* Move the longest bar down to the bottom until all are in order. */
     do
     {
         iSwitch = 0;
         for( iRow = 0; iRow < iLimit; iRow++ )
         {
             /* If two adjacent elements are out of order, swap their values
              * and redraw those two bars.
              */
             iCompares++;
             if( abarWork[iRow].len > abarWork[iRow + 1].len )
             {
                 Swaps( &abarWork[iRow], &abarWork[iRow + 1] );
                 SwapBars( iRow, iRow + 1 );
                 iSwitch = iRow;
             }
         }

         /* Sort on next pass only to where the last switch was made. */
         iLimit = iSwitch;
     } while( iSwitch );
 }


 /* HeapSort - HeapSort (also called TreeSort) works by calling
  * PercolateUp and PercolateDown. PercolateUp organizes the elements
  * into a "heap" or "tree," which has the properties shown below:
  *
  *                             element[1]
  *                           /            \
  *                element[2]                element[3]
  *               /          \              /          \
  *         element[4]     element[5]   element[6]    element[7]
  *         /        \     /        \   /        \    /        \
  *        ...      ...   ...      ... ...      ...  ...      ...
  *
  *
  * Each "parent node" is greater than each of its "child nodes"; for
  * example, element[1] is greater than element[2] or element[3];
  * element[4] is greater than element[5] or element[6], and so forth.
  * Therefore, once the first loop in HeapSort is finished, the
  * largest element is in element[1].
  *
  * The second loop rebuilds the heap (with PercolateDown), but starts
  * at the top and works down, moving the largest elements to the bottom.
  * This has the effect of moving the smallest elements to the top and
  * sorting the heap.
  */
 void HeapSort()
 {
     int i;

     for( i = 1; i < cRow; i++ )
         PercolateUp( i );

     for( i = cRow - 1; i > 0; i-- )
     {
         Swaps( &abarWork[0], &abarWork[i] );
         SwapBars( 0, i );
         PercolateDown( i - 1 );
     }
 }


 /* PercolateUp - Converts elements into a "heap" with the largest
  * element at the top (see the diagram above).
  */
 void PercolateUp( int iMaxLevel )
 {
     int i = iMaxLevel, iParent;

     /* Move the value in abarWork[iMaxLevel] up the heap until it has
      * reached its proper node (that is, until it is greater than either
      * of its child nodes, or until it has reached 1, the top of the heap).
      */
     while( i )
     {
         iParent = i / 2;    // Get the subscript for the parent node

         iCompares++;
         if( abarWork[i].len > abarWork[iParent].len )
         {
             /* The value at the current node is bigger than the value at
              * its parent node, so swap these two array elements.
              */
             Swaps( &abarWork[iParent], &abarWork[i] );
             SwapBars( iParent, i );
             i = iParent;
         }
         else
             /* Otherwise, the element has reached its proper place in the
              * heap, so exit this procedure.
              */
             break;
     }
 }


 /* PercolateDown - Converts elements to a "heap" with the largest elements
  * at the bottom. When this is done to a reversed heap (largest elements
  * at top), it has the effect of sorting the elements.
  */
 void PercolateDown( int iMaxLevel )
 {
     int iChild, i = 0;

     /* Move the value in abarWork[0] down the heap until it has reached
      * its proper node (that is, until it is less than its parent node
      * or until it has reached iMaxLevel, the bottom of the current heap).
      */
     while( TRUE )
     {
         /* Get the subscript for the child node. */
         iChild = 2 * i;

         /* Reached the bottom of the heap, so exit this procedure. */
         if( iChild > iMaxLevel )
             break;

         /* If there are two child nodes, find out which one is bigger. */
         if( iChild + 1 <= iMaxLevel )
         {
             iCompares++;
             if( abarWork[iChild + 1].len > abarWork[iChild].len )
                 iChild++;
         }

         iCompares++;
         if( abarWork[i].len < abarWork[iChild].len )
         {
             /* Move the value down since it is still not bigger than
              * either one of its children.
              */
             Swaps( &abarWork[i], &abarWork[iChild] );
             SwapBars( i, iChild );
             i = iChild;
         }
         else
             /* Otherwise, abarWork has been restored to a heap from 1 to
              * iMaxLevel, so exit.
              */
             break;
     }
 }


 /* ExchangeSort - The ExchangeSort compares each element--starting with
  * the first--with every following element. If any of the following
  * elements is smaller than the current element, it is exchanged with
  * the current element and the process is repeated for the next element.
  */
 void ExchangeSort()
 {
     int iRowCur, iRowMin, iRowNext;

     for( iRowCur = 0; iRowCur < cRow; iRowCur++ )
     {
         iRowMin = iRowCur;
         for( iRowNext = iRowCur; iRowNext < cRow; iRowNext++ )
         {
             iCompares++;
             if( abarWork[iRowNext].len < abarWork[iRowMin].len )
             {
                 iRowMin = iRowNext;
                 DrawTime( iRowNext );
             }
         }

         /* If a row is shorter than the current row, swap those two
          * array elements.
          */
         if( iRowMin > iRowCur )
         {
             Swaps( &abarWork[iRowCur], &abarWork[iRowMin] );
             SwapBars( iRowCur, iRowMin );
         }
     }
 }


 /* ShellSort - ShellSort is similar to the BubbleSort. However, it
  * begins by comparing elements that are far apart (separated by the
  * value of the iOffset variable, which is initially half the distance
  * between the first and last element), then comparing elements that
  * are closer together. When iOffset is one, the last iteration of
  * is merely a bubble sort.
  */
 void ShellSort()
 {
     int iOffset, iSwitch, iLimit, iRow;

     /* Set comparison offset to half the number of bars. */
     iOffset = cRow / 2;

     while( iOffset )
     {
         /* Loop until offset gets to zero. */
         iLimit = cRow - iOffset;
         do
         {
             iSwitch = FALSE;     // Assume no switches at this offset.

             /* Compare elements and switch ones out of order. */
             for( iRow = 0; iRow <= iLimit; iRow++ )
             {
                 iCompares++;
                 if( abarWork[iRow].len > abarWork[iRow + iOffset].len )
                 {
                     Swaps( &abarWork[iRow], &abarWork[iRow + iOffset] );
                     SwapBars( iRow, iRow + iOffset );
                     iSwitch = iRow;
                 }
             }

             /* Sort on next pass only to where last switch was made. */
             iLimit = iSwitch - iOffset;
         } while( iSwitch );

         /* No switches at last offset, try one half as big. */
         iOffset = iOffset / 2;
     }
 }


 /* QuickSort - QuickSort works by picking a random "pivot" element,
  * then moving every element that is bigger to one side of the pivot,
  * and every element that is smaller to the other side. QuickSort is
  * then called recursively with the two subdivisions created by the pivot.
  * Once the number of elements in a subdivision reaches two, the recursive
  * calls end and the array is sorted.
  */
 void QuickSort( int iLow, int iHigh )
 {
     int iUp, iDown, iBreak;

     if( iLow < iHigh )
     {
         /* Only two elements in this subdivision; swap them if they are
          * out of order, then end recursive calls.
          */
         if( (iHigh - iLow) == 1 )
         {
             iCompares++;
             if( abarWork[iLow].len > abarWork[iHigh].len )
             {
                 Swaps( &abarWork[iLow], &abarWork[iHigh] );
                 SwapBars( iLow, iHigh );
             }
         }
         else
         {
             iBreak = abarWork[iHigh].len;
             do
             {
                 /* Move in from both sides towards the pivot element. */
                 iUp = iLow;
                 iDown = iHigh;
                 iCompares++;
                 while( (iUp < iDown) && (abarWork[iUp].len <= iBreak) )
                     iUp++;
                 iCompares++;
                 while( (iDown > iUp) && (abarWork[iDown].len >= iBreak) )
                     iDown--;
                 /* If we haven't reached the pivot, it means that two
                  * elements on either side are out of order, so swap them.
                  */
                 if( iUp < iDown )
                 {
                     Swaps( &abarWork[iUp], &abarWork[iDown] );
                     SwapBars( iUp, iDown );
                 }
             } while ( iUp < iDown );

             /* Move pivot element back to its proper place in the array. */
             Swaps( &abarWork[iUp], &abarWork[iHigh] );
             SwapBars( iUp, iHigh );

             /* Recursively call the QuickSort procedure (pass the smaller
              * subdivision first to use less stack space).
              */
             if( (iUp - iLow) < (iHigh - iUp) )
             {
                 QuickSort( iLow, iUp - 1 );
                 QuickSort( iUp + 1, iHigh );
             }
             else
             {
                 QuickSort( iUp + 1, iHigh );
                 QuickSort( iLow, iUp - 1 );
             }
         }
     }
 }

 /* Beep - Sounds the speaker for a time specified in microseconds by
  * duration at a pitch specified in hertz by frequency.
  */
 void Beep( int frequency, int duration )
 {
 /* Use system call for OS/2 */
 #if defined( OS2 )
 #define INCL_NOCOMMON
 #define INCL_NOPM
 #define INCL_DOSPROCESS
 #include <os2.h>
     DosBeep( frequency, duration );
 #else
 /* Define procedure for DOS */
     int control;

     /* If frequency is 0, Beep doesn't try to make a sound. It
      * just sleeps for the duration.
      */
     if( frequency )
     {
         /* 75 is about the shortest reliable duration of a sound. */
         if( duration < 75 )
             duration = 75;

         /* Prepare timer by sending 10111100 to port 43. */
         outp( 0x43, 0xb6 );

         /* Divide input frequency by timer ticks per second and
          * write (byte by byte) to timer.
          */
         frequency = (unsigned)(1193180L / frequency);
         outp( 0x42, (char)frequency );
         outp( 0x42, (char)(frequency >> 8) );

         /* Save speaker control byte. */
         control = inp( 0x61 );

         /* Turn on the speaker (with bits 0 and 1). */
         outp( 0x61, control | 0x3 );
     }

     Sleep( (clock_t)duration );

     /* Turn speaker back on if necessary. */
     if( frequency )
         outp( 0x61, control );

              /* DOS version */
 }

 /* Pauses for a specified number of microseconds. */
 void Sleep( clock_t wait )
 {
     clock_t goal;

     goal = wait + clock();
     while( goal >= clock() )
         ;
 }


 TURTLE.C
 CD-ROM Disc Path:   \SAMPCODE\C\MSC60\TURTLE.C

 /* TURTLE - Module of functions to implement turtle graphics. Turtle graphics
  * is a model for specifying relative movements of an imaginary pointer whose
  * direction, color, visibility, and other attributes are given default
  * values using turtle functions. To use the turtle module, include TURTLE.H
  * in your program. The following functions (many defined as macros)
  * are public :
  *
  *   InitTurtle      - Initiate turtle graphics
  *   Home            - Reset turtle defaults
  *   PenDown         - Set pen visibility
  *   SetFill         - Set fill state
  *   PenColor        - Set pen color index
  *   BorderColor     - Set border color index
  *   Turn            - Set direction relative to current
  *   TurnTo          - Set absolute direction
  *   Move            - Move in current direction
  *   MoveTo          - Move to absolute location
  *   Poly            - Draw a polygon
  *   Circle          - Draw a circle with center at current location
  *   Ellipse         - Draw an ellipse with center at current location
  *   Rectangle       - Draw a rectangle with center at current location
  *   ImageSize       - Get size of rectangle with top-left origin
  *   GetImage        - Get rectangular image with top-left origin
  *   PutImage        - Put rectangular image with top-left origin
  *   FillIn          - Fill from the current location to border
  *   NextColorIndex  - Rotate to next color index
  *   NextColorValue  - Rotate to next color value
  *   OnScreen        - Report whether current location is on screen
  *   RGB             - Combine Red, Green, and Blue elements of color value
  *
  * The TURTLE structure, the "tc" global variable (having TURTLE type), and
  * "vlColors" variable are defined. However, these are not normally used
  * directly by the programmer.
  */

 #include <graph.h>
 #include <math.h>
 #include <string.h>
 #include "turtle.h"

 #define PI       3.141593

 long cvlColors[256];            /* Array of long color values              */

 TURTLE tc = { 1.39 };    /* Initial aspect - adjust for your screen */

 /* InitTurtle - Initializes all turtle defaults. This function should be
  * called at least once (after _setvideomode and _getvideoconfig) and
  * additionally after any change to a new graphics mode.
  *
  * Params: vc - pointer to videoconfig structure
  *
  * Return: 0 if fail, 1 if success
  *
  * Uses:   tc structure variable cvlColors array
  */
 short InitTurtle( struct videoconfig *vc )
 {
     int i;
     unsigned cvuInc, cvuRed, cvuGreen, cvuBlue; /* Unsigned portions of */
     static int mode = -1;                       /*   color values       */

     /* Terminate if not graphics mode. */
     if( !vc->numxpixels )
         return 0;

     /* If mode has changed, set window coordinates. */
     if( mode != vc->mode )
     {
         mode = vc->mode;
         tc.xsLeft = tc.ysTop = 0;
         tc.xsRight = vc->numxpixels - 1;
         tc.ysBot = vc->numypixels - 1;
     }

     /* Set palette flag. */
     switch( vc->adapter )
     {
         case _MDPA:
         case _CGA:
         case _OCGA:
         case _HGC:
             tc.fPalette = FALSE;
             break;
         default:
             tc.fPalette = TRUE;
             break;
     }

     /* Set palette defaults. */
     switch( vc->mode )
     {
         case _HRESBW:
         case _HERCMONO:
         case _ERESNOCOLOR:
         case _ORESCOLOR:
         case _VRES2COLOR:
             tc.ccv = 0;
             tc.cci = 2;
             return Home();
         case _MRES256COLOR:        /* Active bits in this order:          */
             cvuInc = 12;
             tc.ccv = tc.cci = 125; /* ???????? ??bbbbbb ??gggggg ??rrrrrr */
             break;
         case _ERESCOLOR:
             if( vc->memory == 64 )
             {
                 cvuInc = 32;
                 tc.ccv = 16;       /* ???????? ??????Bb ??????Gg ??????Rr */
                 tc.cci = 4;
                 break;
             } /* Else fall through */
         case _VRES16COLOR:
             cvuInc = 16;
             tc.ccv = 64;           /* ???????? ??????bb ??????gg ??????rr */
             tc.cci = 16;
             break;
         case _MRES4COLOR:
         case _MRESNOCOLOR:
             cvuInc = 32;
             tc.ccv = 16;           /* ???????? ??????Bb ??????Gg ??????Rr */
             tc.cci = 4;
             break;
         case _MRES16COLOR:
         case _HRES16COLOR:
             cvuInc = 32;
             tc.cci = tc.ccv = 16;  /* ???????? ??????Bb ??????Gg ??????Rr */
             break;
     }

     /* Fill palette arrays. */
     for( i = 0, cvuBlue = 0; cvuBlue < 64; cvuBlue += cvuInc )
         for( cvuGreen = 0; cvuGreen < 64; cvuGreen += cvuInc )
             for( cvuRed = 0; cvuRed < 64; cvuRed += cvuInc )
                 {
                     cvlColors[i] = RGB( cvuRed, cvuGreen, cvuBlue );
                     /* Special case of 6 bits for 16 colors (RGBI).
                      * If both bits are on for any color, intensity is set.
                      * If one bit is set for a color, that color is on.
                      */
                     if( cvuInc == 32 )
                         cvlColors[i + 8] = cvlColors[i] | (cvlColors[i] >> 1)
                     i++;
                 }
     cvlColors[tc.ccv - 1] = _BRIGHTWHITE;
     NextColorValue( DEFAULT );
     return Home();
 }

 /* Home - Resets turtle defaults. This function can be called if you have
  * not changed the video mode, but you want to put the turtle back in
  * the center of the window and restore all defaults. For example, you can
  * change the absolute window corners and then call it to set a new
  * turtle window.
  *
  * Params: None
  *
  * Return: 0 if fail, 1 if success
  *
  * Uses:   tc
  */
 short Home()
 {
     struct _wxycoord xy1, xy2;

     _setviewport( tc.xsLeft, tc.ysTop, tc.xsRight, tc.ysBot );

     /* Set the window based on screen height 1000 and width based on
      * aspect ratio.
      */
     tc.yMax = 500.0;
     tc.xMax = tc.yMax * tc.yxRatio;
     if( !_setwindow( FALSE, -tc.xMax, -tc.yMax, tc.xMax, tc.yMax ) )
         return 0;

     /* Calculate the unit size of 1 pixel using Y axis. */
     xy1 = _getwindowcoord( 1, 1 );
     xy2 = _getwindowcoord( 1, 2 );
     tc.yUnit = xy2.wy - xy1.wy;

     /* Set defaults for current pixel, angle, pen state and fill state. */
     tc.xCur = tc.yCur = 0.0;
     _moveto_w( tc.xCur, tc.yCur );
     TurnTo( 0 );
     PenDown( TRUE );
     SetFill( FALSE );

     /* Make white the last color index and set pen and border to it. */
     _remappalette( WHITE, _BRIGHTWHITE );
     BorderColor( WHITE );
     PenColor( WHITE );
     _setbkcolor( _BLACK );
     return 1;
 }

 /* PenDown - Sets the visibility of the pen used by Move and MoveTo. The
  * state can be TRUE (visible), FALSE (invisible), or DEFAULT (return
  * current without changing).
  *
  * Params: fPenDown
  *
  * Return: current pen state
  *
  * Uses:   tc
  */
 int PenDown( int fPenDown )
 {
     switch( fPenDown )
     {
         case DEFAULT:
             break;
         case FALSE:
             tc.fPenDown = FALSE;
             break;
         default:
             tc.fPenDown = TRUE;
             break;
     }
     return tc.fPenDown;
 }

 /* SetFill - Determines the state of filling figures such as Rectangle,
  * Circle, and Ellipse. State can be TRUE (fill inside), FALSE (border
  * only), or DEFAULT (return current fill state).
  *
  * Params: fFill
  *
  * Return: current fill state
  *
  * Uses:   tc
  */
 short SetFill( short fFill )
 {
     switch( fFill )
     {
         case DEFAULT:
             break;
         case _GBORDER:
         case FALSE:
             tc.fFill = _GBORDER;
             break;
         default:
             tc.fFill = _GFILLINTERIOR;
             break;
     }
     return tc.fFill;
 }

 /* PenColor - Sets the color index of the pen.
  *
  * Params: ciCur - any color index of DEFAULT to return without changing
  *
  * Return: current pen color index
  *
  * Uses:   tc
  */
 short PenColor( short ciCur )
 {
     if( ciCur != DEFAULT )
         _setcolor( tc.ciCur = ciCur );
     return tc.ciCur;
 }

 /* BorderColor - Sets the color index of the border that will be recognized
  * by fills.
  *
  * Params: ciBorder - any color index of DEFAULT to return without changing
  *
  * Return: current border color index
  *
  * Uses:   tc
  */
 short BorderColor( short border )
 {
     if( border != DEFAULT )
         tc.ciBorder = border;
     return tc.ciBorder;
 }

 /* Turn - Sets a new direction relative to the current direction.
  *
  * Params: angCur - a positive (clockwise) or negative (counterclockwise)
  *           angle in degrees
  *
  * Return: new current absolute angle
  *
  * Uses:   tc
  */
 short Turn( short angCur )
 {
     return( tc.angCur = ((tc.angCur + angCur) % CIRCUMFERENCE) );
 }

 /* TurnTo - Sets a new absolute direction.
  *
  * Params: angCur - a positive (clockwise) or negative (counterclockwise)
  *           angle in degrees (0 points to 12 o'clock)
  *
  * Return: new current absolute angle
  *
  * Uses:   tc
  */
 short TurnTo( short angCur )
 {
     if( angCur < 0 )
         return( tc.angCur = 360 - (angCur % CIRCUMFERENCE) );
     else
         return( tc.angCur = angCur % CIRCUMFERENCE );
 }

 /* Move - Moves from the current position in the current direction for a
  * specified distance. A line is drawn if the pen is down. The current
  * position is reset to the destination.
  *
  * Params: dxy - difference between current xy and new xy
  *
  * Return: 0 if new position is off screen, nonzero if on screen
  *
  * Uses:   tc
  */
 short Move( double dxy )
 {
     double dx, dy;          /* Differences of X and Y */
     double angT;

     /* Calculate new X and Y positions. */
     angT = (tc.angCur - 90) * (PI / HALFCIRCUMFERENCE);
     dx = dxy * cos( angT );
     dy = dxy * sin( angT );

     /* Move, drawing if pen down, then update position */
     if( tc.fPenDown )
         _lineto_w( tc.xCur + dx, tc.yCur + dy );
     else
         _moveto_w( tc.xCur + dx, tc.yCur + dy );
     tc.xCur += dx;
     tc.yCur += dy;
     return OnScreen();
 }

 /* MoveTo - Moves from the current position to a specified position. A
  * line is drawn if the pen is down. The current position is reset to the
  * destination. The current direction is not changed.
  *
  * Params: x and y - destination position
  *
  * Return: 0 if new position is off screen, nonzero if on screen
  *
  * Uses:   tc
  */
 short MoveTo( double x, double y )
 {
     if( tc.fPenDown )
         _lineto_w( x, y );
     else
         _moveto_w( x, y );
     tc.xCur = x;
     tc.yCur = y;
     return OnScreen();
 }

 /* Poly - Draws a polygon.
  *
  * Params: cSide - count of polygon sides
  *         dxySide - distance of each side
  *
  * Return: 0 if any part of polygon is off screen, nonzero if on screen
  */
 short Poly( int cSide, double dxySide )
 {
     short i, angT, fPen, ret = TRUE;

     /* Make sure pen is down (restore pen state when done). */
     fPen = PenDown( TRUE );

     /* Calculate angle, then draw each side. */
     angT = 360 / cSide;
     for( i = 1; i <= cSide; i++ )
     {
         ret = Move( dxySide ) && ret;
         Turn( angT );
     }
     PenDown( fPen );
     return ret;
 }

 /* NextColorIndex - Rotate to next color index. First attribute (normally
  * background) and last attribute (white) are skipped.
  *
  * Params: ciCur - Specify DEFAULT to use color index from last call,
  *           or specify a new color to rotate from
  *
  * Return: rotated color index
  *
  * Uses:   tc
  */
 short NextColorIndex( short ciCur )
 {
     static short ciPrev = 0;    /* Static to retain index between calls */

     /* Assign new current if given. */
     if( ciCur != DEFAULT )
         ciPrev = ciCur;

     /* Toggle for two-color modes, rotate for multi-color modes. */
     if( tc.cci == 2 )
         return( ciPrev = !ciPrev );
     else
         return( ciPrev = (++ciPrev % (tc.cci - 1)) );
 }

 /* NextColorValue - Rotate to next color value for adapters (EGA
  * and higher) that support remappable palettes.
  *
  * Params: fAction - DEFAULT (rotate all) or LIMITED (rotate first 14 only)
  *
  * Return: None
  *
  * Uses:   tc
  */
 void NextColorValue( int fAction )
 {
     static int icvCur = 1;  /* Current index into color value array */
     static int ciCur = 1;   /* Current color index                  */
     int icvT;               /* Temporary index into color values    */
     int i;

     /* Ignore modes with no palette values. */
     if( !tc.fPalette || !tc.ccv )
         return;

     /* Increment and rotate color value index. */
     icvT = (++icvCur % (tc.ccv - 2)) + 1;


     /* DEFAULT - Remap all color indexes, 14 at a time. For most modes,
      * this is all the indexes  except first and last. For 256-color
      * mode, rotating all available indexes would be too slow.
      */
     if( fAction == DEFAULT )
         for( i = 1; i <= 14; i++ )
             _remappalette( (ciCur++ % (tc.cci - 2)) + 1,
                            cvlColors[(icvT++ % (tc.ccv - 2)) + 1] );

     /* LIMITED - Rotate only the first 14 color indexes. */
     else
         for( i = 1; i <= 14; i++ )
             _remappalette( i, cvlColors[(icvT++ % (tc.ccv - 1)) + 1] );
 }
 Microsoft Quick-C Sample Code


 ARGV.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\ARGV.C

 /* ARGV.C: Demonstrate accessing command-line arguments. */
 #include <stdio.h>

 void show_args( char *argument );

 int main( int argc, char *argv[] )
 {
    int count;
    for( count=0; count < argc; count++ )
       show_args( argv[count] );
    return 0;
 }

 void show_args( char *argument )
 {
    printf( "%s\n", argument );
 }


 ARGV1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\ARGV1.C

 /* ARGV1.C: Demonstrate null pointers. */
 #include <stdio.h>

 void show_args( char *argument );

 int main( int argc, char **argv )
 {
    while( *argv )
       show_args( *(argv++) );
    return 0;
 }

 void show_args( char *argument )
 {
    printf( "%s\n", argument );
 }


 ARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\ARRAY.C

 /* ARRAY.C: Demonstrate one-dimensional array. */
 #include <stdio.h>

 main()
 {
    int j;
    int i_array[3];

    i_array[0] = 176;
    i_array[1] = 4069;
    i_array[2] = 303;

    printf( "--- Values --------     --- Addresses -------\n\n" );

    for( j = 0; j < 3; j = j + 1 )
    {
       printf( "i_array[%d] = %d", j, i_array[j] );
       printf( "\t&i_array[%d] = %u\n", j, &i_array[j] );
    }

 }


 BAR.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BAR.C

 /* BAR.C:  Create sample bar chart. */
 #include <conio.h>
 #include <string.h>
 #include <graph.h>
 #include <pgchart.h>
 #define MONTHS 12
 typedef enum {FALSE, TRUE} boolean;
 float far value[MONTHS] =
 {
    33.0, 27.0, 42.0, 64.0,106.0,157.0,
   182.0,217.0,128.0, 62.0, 43.0, 36.0
 };
 char far *category[MONTHS] =
 {
   "Jan", "Feb", "Mar", "Apr",
   "May", "Jun", "Jly", "Aug",
   "Sep", "Oct", "Nov", "Dec"
 };

 main()
 {
   chartenv env;
   int mode = _VRES16COLOR;
   /* Set highest video mode available */
   while(!_setvideomode( mode ))
      mode--;
   if(mode == _TEXTMONO)
      return(0);

   /* Initialize chart library and a default bar chart */
   _pg_initchart();

   _pg_defaultchart( &env, _PG_BARCHART, _PG_PLAINBARS
 );
   /* Add titles and some chart options */
   strcpy( env.maintitle.title, "Good Neighbor Grocery" );
   env.maintitle.titlecolor = 6;
   env.maintitle.justify = _PG_RIGHT;
   strcpy( env.subtitle.title, "Orange Juice Sales" );
   env.subtitle.titlecolor = 6;
   env.subtitle.justify = _PG_RIGHT;
   strcpy( env.yaxis.axistitle.title, "Months" );
   strcpy( env.xaxis.axistitle.title, "Quantity (cases)" );
   env.chartwindow.border = FALSE;

   /* Parameters for call to _pg_chart are:
    *    env        - Environment variable
    *    category   - Category labels
    *    value      - Data to chart
    *    MONTHS     - Number of data values */

   if(_pg_chart( &env, category, value, MONTHS ))
   {
      _setvideomode( _DEFAULTMODE );
      _outtext( "Error:  can't draw chart" );
   }
   else
   {
       getch();
       _setvideomode( _DEFAULTMODE );
    }
    return(0);
 }


 BEEP.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BEEP.C

 /* BEEP.C: Demonstrate simple function */
 #include <stdio.h>

 void beep( void);

 main()
 {
    printf( "Time to beep\n" );
    beep();
    printf( "All done\n" );
 }

 void beep( void )
 {
    printf( "Beep!\a\n" );
 }


 BEEP1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BEEP1.C

 /* BEEP1.C: Demonstrate passing arguments */
 #include <stdio.h>

 void beep( int num_beep );

 main()
 {
    printf( "Time to beep\n" );
    beep( 5 );
    printf( "All done\n" );
 }

 void beep( int num_beep )
 {
    while( num_beep > 0  )
    {
       printf( "Beep!\a\n" );
       num_beep = num_beep - 1;
    }
 }


 BEEPER.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BEEPER.C

 /* BEEPER.C: Demonstrate simple function */
 #include <stdio.h>

 void beep( void);

 main()
 {
    printf( "Time to beep\n" );
    beep();
    printf( "All done\n" );
 }

 void beep( void )
 {
    printf( "Beep!\a\n" );
 }


 BEEPER1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BEEPER1.C

 /* BEEPER1.C: Demonstrate passing arguments */
 #include <stdio.h>

 void beep( int num_beep );

 main()
 {
    printf( "Time to beep\n" );
    beep( 5 );
    printf( "All done\n" );
 }

 void beep( int num_beep )
 {
    while( num_beep > 0  )
    {
       printf( "Beep!\a\n" );
       num_beep = num_beep - 1;
    }
 }


 BITWISE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BITWISE.C

 /* BITWISE.C: Demonstrate bitwise operators. */
 #include <stdio.h>

 main()
 {
    printf( "255 & 15 = %d\n", 255 & 15 );
    printf( "255 | 15 = %d\n", 255 | 15 );
    printf( "255 ^ 15 = %d\n", 255 ^ 15 );
    printf( "2 << 2   = %d\n", 2 << 2 );
    printf( "16 >> 2  = %d\n", 16 >> 2 );
    printf( "~2       = %d\n", ~2 );
 }


 BREAKER.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BREAKER.C

 /* BREAKER.C: Demonstrate break statement. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press any key. Press Tab to quit.\n" );
    while( 1 )
    {
       ch = getche();
       if( ch == '\t' )
       {
          printf( "\a\nYou pressed Tab\n" );
          break;
       }
    }
 }


 BREAKER1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\BREAKER1.C

 /* BREAKER1.C: Break only exits one loop. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press any key. Press Enter to quit.\n" );
    do
    {
       while( ( ch = getche() ) != '\r' )
       {
          if( ch == '\t' )
          {
             printf( "\a\nYou pressed Tab\n" );
             break;
          }
       }
    } while( ch != '\r' );
    printf( "\nBye bye." );
 }


 CGA.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\CGA.C

 /* CGA.C: Demonstrates CGA colors */
 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>

 long bkcolor[8] =
    {_BLACK, _BLUE, _GREEN, _CYAN,
     _RED, _MAGENTA, _BROWN, _WHITE};

 char *bkcolor_name [] =
    {"_BLACK", "_BLUE", "_GREEN", "_CYAN",
    "_RED", "_MAGENTA", "_BROWN", "_WHITE"};

 main()
 {
    int i, j, k;
    _setvideomode( _MRES4COLOR );
    for( i=0; i<= 3; i++ )
    {
       _selectpalette( i );
       for( k=0; k <= 7; k++ )
       {
          _setbkcolor( bkcolor[k] );
          for( j=0; j<=3; j++ )
          {
             _settextposition( 1, 1 );
             printf( "background color: %8s\n", bkcolor_name[k] );
             printf( "palette: %d\ncolor: %d\n", i, j );
             _setcolor( j );
             _rectangle( _GFILLINTERIOR, 160, 100, 320, 200 );
                getch();
          }
       }
    }
    _setvideomode( _DEFAULTMODE );
 }


 COLOR.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\COLOR.C

  /* COLOR.C: Sets a medium resolution mode with maximum color choices */
 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <conio.h>
 struct videoconfig vc;

 main()
 {
    if( _setvideomode( _MRES256COLOR ) )
       ;
    else if( _setvideomode( _MRES16COLOR ) )
       ;
    else if( _setvideomode( _MRES4COLOR ) )
       ;
    else   {
       printf( "Error: No color graphics capability\n" );
       exit( 0 );
    }

    _getvideoconfig( &vc );

    printf( "%d available colors\n", vc.numcolors );
    printf( "%d horizontal pixels\n", vc.numxpixels );
    printf( "%d vertical pixels\n", vc.numypixels );

    getch();
    _clearscreen( _GCLEARSCREEN );
    _setvideomode( _DEFAULTMODE );
 }


 COLTEXT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\COLTEXT.C

 /* COLTEXT.C: Displays text in color */
 #include <stdio.h>
 #include <conio.h>
 #include <graph.h>

 char buffer [80];

 main()
 {
    int blink,fgd;
    long bgd;

    _clearscreen( _GCLEARSCREEN );
    printf( "Text color attributes:\n" );

    for( blink=0; blink<=16; blink+=16 )
    {
       for( bgd=0; bgd<8; bgd++ )
       {
          _setbkcolor( bgd );
          _settextposition( bgd + ((blink / 16) * 9) + 3, 1 );
          _settextcolor( 7 );
          sprintf( buffer, "Bgd: %d Fgd:", bgd );
          _outtext( buffer );

          for( fgd=0; fgd<16; fgd++ )
          {
             _settextcolor( fgd+blink );
             sprintf( buffer, " %2d ", fgd+blink );
             _outtext( buffer );
          }
       }
    }
    getch();
    _setvideomode( _DEFAULTMODE );
 }


 CONT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\CONT.C

 /* CONT.C: Demonstrate continue statement. */
 #include <stdio.h>

 main()
 {
    int count;
    for( count = 0; count < 10; count++ )
    {
       if( count > 3 )
          continue;
       printf( "count = %d\n", count );
    }
    printf( "Done!\n" );
 }


 CONVERT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\CONVERT.C

 /* CONVERT.C: Demonstrate type conversions. */
 #include <stdio.h>

 main()
 {
    char c_val = 10;
    int i_val = 20;
    long l_val = 64000;
    float f_val = 3.1;
    int result;

    result = c_val + i_val + l_val + f_val;  /* Error! */

    printf( "%d\n", result );
 }


 COPYFILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\COPYFILE.C

 /* COPYFILE.C: Demonstrate malloc and free functions */

 <stdio.h>     /* printf function and NULL */
 <io.h>        /* low-level I/O functions */
 <conio.h>     /* getch function */
 <sys\types.h> /* struct members used in stat.h */
 <sys\stat.h>  /* S_ constants */
 <fcntl.h>     /* O_ constants */
 <malloc.h>    /* malloc function */
 <errno.h>     /* errno global variable */

 int copyfile( char *source, char *destin );

 main( int argc, char *argv[] )
 {
    if( argc == 3 )
       if( copyfile( argv[1], argv[2] ) )
          printf( "Copy failed\n" );
       else
          printf( "Copy successful\n" );
    else
       printf( "  SYNTAX: COPYFILE <source> <target>\n" );

    return 0;
 }

 int copyfile( char *source, char *target )
 {
    char *buf;
    int hsource, htarget, ch;
    unsigned count = 50000;

    if( (hsource = open( source, O_BINARY | O_RDONLY )) == - 1 )
       return errno;
    htarget = open( target, O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
                            S_IREAD | S_IWRITE );
    if( errno == EEXIST )
    {
       cputs( "Target exists. Overwrite? " );
       ch = getch();
       if( (ch == 'y') || (ch == 'Y') )
          htarget = open( target, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
                                  S_IREAD | S_IWRITE );
       printf( "\n" );
    }
    if( htarget == -1 )
       return errno;

    if( filelength( hsource ) < count )
       count = (int)filelength( hsource );

    buf = (char *)malloc( (size_t)count );

    if( buf == NULL )
    {
       count = _memmax();
       buf = (char *)malloc( (size_t)count );
       if( buf == NULL )
          return ENOMEM;
    }

    while( !eof( hsource ) )
    {
       if( (count = read( hsource, buf, count )) == -1 )
          return errno;
       if( (count = write( htarget, buf, count )) == - 1 )
          return errno;
    }

    close( hsource );
    close( htarget );
    free( buf );
    return 0;
 }


 DECRMENT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\DECRMENT.C

 /* DECRMENT.C: Demonstrate prefix and postfix operators. */
 #include <stdio.h>

 main()
 {
    int val, sample = 3, proton = 3;
    val = sample--;
    printf( "val = %d  sample = %d\n", val, sample );
    val = --proton;
    printf( "val = %d  proton = %d\n", val, proton );
 }


 DEFINED.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\DEFINED.C

 /* DEFINED.C: Demonstrate defined operator. */

 #define DEBUG 12345

 main()
 {
    #if defined( DEBUG )
       printf( "Hi\n" );
    #endif
 }


 DO.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\DO.C

 /* DO.C: Demonstrate do loop. */

 #include <stdio.h>

 main()
 {
    int test = 10;
    do
    {
       printf( "test = %d\n", test );
       test = test - 2;
    }  while( test > 0 );
 }


 EGA.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\EGA.C

 /* EGA.C: Demonstrates EGA palettes */
 #include <stdio.h>
 #include <conio.h>
 #include <graph.h>

 main()
 {
    _setvideomode( _ERESCOLOR );
    _setcolor( 4 );
    _rectangle( _GFILLINTERIOR, 50, 50, 200, 200 );

    _settextposition( 1, 1 );
    printf( "Normal palette\n" );
    printf( "Press a key" );
    getch();

    _remappalette( 4, _BLUE );

    _settextposition( 1, 1 );
    printf( "Remapped palette\n" );
    printf( "Press a key" );
    getch();

    _remappalette( 4, _RED );

    _settextposition( 1, 1 );
    printf( "Restored palette\n" );
    printf( "Press a key to clear the screen" );
    getch();

    _clearscreen( _GCLEARSCREEN );
    _setvideomode( _DEFAULTMODE );
 }


 ELSE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\ELSE.C

 /* ELSE.C: Demonstrate else clause. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getch();
    if( ch == 'b' )
       printf( "Beep!\a\n" );
    else
       printf( "Bye bye\n" );
 }


 ELSE1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\ELSE1.C

 /* ELSE1.C: Demonstrate else-if construct. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getch();
    if( ch == 'b' )
       printf( "Beep!\a\n" );
    else
       if( ch == '\r' )
          printf( "Enter\n" );
    else
       printf( "Bye bye\n" );
 }


 EMPLOY1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\EMPLOY1.C

 /* EMPLOY1.C: Demonstrate structure pointers. */
 #include <stdio.h>


 struct employee
 {
    char name[10];
    int months;
    float wage;
 };

 void display( struct employee *e_ptr  );

 main()
 {
    static struct employee jones =
       {
       "Jones, J",
       77,
       13.68
       };

    display( &jones );
 }

 void display( struct employee *e_ptr )
 {
    printf( "Name: %s\n", e_ptr->name );
    printf( "Months of service: %d\n", e_ptr->months );
    printf( "Hourly wage: %6.2f\n", e_ptr->wage );
 }


 EMPLOYEE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\EMPLOYEE.C

 /* EMPLOYEE.C: Demonstrate structures. */
 #include <stdio.h>
 #include <string.h>

 struct employee
 {
    char name[10];
    int months;
    float wage;
 };

 void display( struct employee show );

 main()
 {
    struct employee jones;

    strcpy( jones.name, "Jones, J" );
    jones.months = 77;
    jones.wage = 13.68;

    display( jones );
 }

 void display( struct employee show )
 {
    printf( "Name: %s\n", show.name );
    printf( "Months of service: %d\n", show.months );
    printf( "Hourly wage: %6.2f\n", show.wage );
 }


 FILE1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FILE1.C

 /* FILE1.C: Visibility in multiple source files.
 */

 int chico = 20, harpo = 30;
 extern void yonder( void );

 main()
 {
    yonder();
 }


 FILE2.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FILE2.C

 /* FILE2.C: Visibility in multiple source files.
 */

 #include <stdio.h>

 void yonder( void )
 {
    extern int chico, harpo;
    printf( "chico = %d, harpo = %d\n", chico, harpo );
 }


 FORLOOP.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FORLOOP.C

 /* FORLOOP.C: Demonstrate for loop. */

 #include <stdio.h>

 main()
 {
    int test;
    for( test = 10; test > 0; test = test - 2 )
       printf( "test = %d\n", test );
 }


 FORLOOP1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FORLOOP1.C

 /* FORLOOP1.C: Demonstrate multiple expressions. */

 #include <stdio.h>

 main()
 {
    int a, b;
    for( a = 256, b = 1; b < 512; a = a / 2, b = b * 2 )
       printf( "a = %d  b = %d\n", a, b );
 }


 FORLOOP2.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FORLOOP2.C

 /* FORLOOP2.C: Demonstrate similarity of for and while.
 */

 #include <stdio.h>

 main()
 {
    int count;

    for( count = 0; count < 10; count++ )
       printf( "count = %d\n", count );

    count = 0;
    while( count < 10 )
    {
       printf( "count = %d\n", count );
       count++;
    }

 }


 FUNCPTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FUNCPTR.C

 /* FUNCPTR.C: Demonstrate function pointers. */
 #include <stdio.h>

 main()
 {
    int (*func_ptr) ();
    func_ptr = printf;
    (*func_ptr) ( "Curiouser and curiouser...\n" );
 }


 FUNCPTR1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\FUNCPTR1.C

 /* FUNCPTR1.C: Passing function pointers as arguments. */
 #include <stdio.h>

 void gimme_func( void (*func_ptr) () );

 main()
 {
    gimme_func( puts );
    gimme_func( printf );
 }

 void gimme_func( void (*func_ptr) () )
 {
    (*func_ptr) ( "Ausgezeichnet!" );
 }


 GRAPHIC.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\GRAPHIC.C

 /* GRAPHIC.C: Displays every graphics mode */
 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>

 struct videoconfig screen;
 int modes[12] =
 {
    _MRES4COLOR, _MRESNOCOLOR, _HRESBW,
    _HERCMONO,
    _MRES16COLOR, _HRES16COLOR, _ERESNOCOLOR, _ERESCOLOR,
    _VRES2COLOR, _VRES16COLOR, _MRES256COLOR, _ORESCOLOR
 };

 void print_menu( void );
 void show_mode( char );

 main()
 {
    char key;
    print_menu();
    while( (key = getch()) != 'x' )
       show_mode( key );
 }

 void print_menu( void )
 {
    _setvideomode( _DEFAULTMODE );
    _clearscreen( _GCLEARSCREEN );
    printf( "Please choose a graphics mode\nType 'x' to exit.\n\n" );
    printf( "0 _MRES4COLOR\n1 _MRESNOCOLOR\n2 _HRESBW\n" );
    printf( "3 _HERCMONO\n4 _MRES16COLOR\n5 _HRES16COLOR\n" );
    printf( "6 _ERESNOCOLOR\n7 _ERESCOLOR\n" );
    printf( "8 _VRES2COLOR\n9 _VRES16COLOR\na _MRES256COLOR\n" );
    printf( "b _ORESCOLOR\n" );
 }

 void show_mode( char which )
 {
    int nc, i;
    int height, width;
    int mode = which;

    if( mode < '0' || mode > '9' )
       if( mode == 'a' )
          mode = '9' + 1;
       else if( mode == 'b' )
          mode = '9' + 2;
       else
          return;

    if( _setvideomode( modes[mode - '0'] ) )
    {
       _getvideoconfig( &screen );
       nc = screen.numcolors;
       width = screen.numxpixels/nc;
       height = screen.numypixels/2;
       for( i = 0; i < nc; i++ )
       {
          _setcolor( i );
          _rectangle( _GFILLINTERIOR, i * width, 0, (i + 1) * width, height );
       }
    }
    else
    {
       printf( " \nVideo mode %c is not available.\n", which);
       printf( "Please press a key.\n" );
    }
    getch();
    _setvideomode( _DEFAULTMODE );
    print_menu();
 }


 HORIZON.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\HORIZON.C

 /* HORIZON.C: VGA graphics with cycling of 256 colors */
 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <graph.h>

 #define RED 0x0000003FL
 #define GRN 0x00003F00L
 #define BLU 0x003F0000L
 #define WHT 0x003F3F3FL
 #define STEP 21

 struct videoconfig screen;
 long int rainbow[512];

 main()
 {
    int i;
    long int col, gray;

    if( _setvideomode( _MRES256COLOR ) == 0 )
    {
       printf("This program requires a VGA card.\n" );
       exit( 0 );
    }
    for( col = 0; col < 64; col++ )
    {
       gray = col | (col << 8) | (col << 16);
       rainbow[col] = rainbow[col + 256] = BLU & gray;
       rainbow[col + 64] = rainbow[col + 64 + 256] = BLU | gray;
       rainbow[col + 128] = rainbow[col + 128 + 256] = RED | (WHT & ~gray);
       rainbow[col + 192] = rainbow[col + 192 + 256] = RED & ~gray;
    }
    _setvieworg( 160, 85 );

    for( i = 0; i < 255; i++ )
    {
       _setcolor( 255 - i );
       _moveto( i, i - 255 );
       _lineto( -i, 255 - i );
       _moveto( -i, i - 255 );
       _lineto( i, 255 - i );
       _ellipse( _GBORDER, -i, -i / 2, i, i / 2 );
    }
    for( i = 0; !kbhit(); i += STEP, i %= 256 )
       _remapallpalette( &(rainbow[i]) );

    _setvideomode( _DEFAULTMODE );
 }


 IFF.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\IFF.C

 /* IFF.C: Demonstrate if statement. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getche();
    if( ch == 'b' )
       printf( "Beep!\a\n" );
 }


 INPUT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\INPUT.C

 /* INPUT.C: Reads keyboard. */
 #include <stdio.h>
 #include <conio.h>
 #include <ctype.h>

 main()
 {
    int num, c;
    char name[80];
    float rb;

    puts( "** Type \"Name:\" and your name" );
    scanf( "Name: %40s", name );
    printf( "** You typed this:\n%s", name );
    puts( "\n\n** Try again, with the gets function." );
    fflush( stdin );
    gets( name );
    printf( "** You typed this:\n%s\n", name );

    printf( "\n** Now type an integer.\n" );
    scanf( "%i", &num );
    sprintf( name, "** You typed this number: %i\n", num );
    puts( name );

    fflush( stdin );
    printf( "** Enter a floating-point value.\n" );
    scanf( "%f", &rb );
    printf( "** The answer is %f or %e\n", rb, rb );

    printf( "** Continue? Y or N\n" );

    do
    {
       c = getch();
       c = tolower( c );
    } while( c != 'y' && c != 'n' );
 }


 MACRO.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\MACRO.C

 /* MACRO.C: Demonstrate macros. */

 #include <stdio.h>
 #define ABS(value)  ( (value) >= 0 ? (value) : -(value) )

 main()
 {
    int val = -20;
    printf( "result = %d\n", ABS(val) );
 }


 NFORMAT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\NFORMAT.C

 /* NFORMAT.C: Prints numbers and a string. */
 #include <stdio.h>
 #include <string.h>

 main()
 {
    int    a = -765,
           b = 1,
           c = 44000,
           d = 33;
    float  e = 1.33E8,
           f = -0.1234567,
           g = 12345.6789,
           h = 1.0;
    char   i[80];

    strcpy( i, "word 1, word 2, word 3, word 4, word 5" );

    printf( "Unformatted:\n%d %d %d %d\n", a, b, c, d );
    printf( "%f %f %f %f\n", e, f, g, h );
    printf( "%s\n", i );
 }


 NOT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\NOT.C

 /* NOT.C: Demonstrate logical NOT operator. */
 #include <stdio.h>

 main()
 {
   int val = 0;
   if( !val )
      printf( "val is zero" );
 }


 OLDSTYLE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\OLDSTYLE.C

 /* OLDSTYLE.C: Old-style function. */
 #include <stdio.h>
 #define PI 3.14

 float sphere();

 main()
 {
    float volume;
    int radius = 3;
    volume = sphere( radius );
    printf( "Volume: %f\n", volume );
 }

 float sphere( rad )
 int rad;
 {
    float result;
    result = rad * rad * rad;
    result = 4 * PI * result;
    result = result / 3;
    return result;
 }


 PARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PARRAY.C

 /* PARRAY.C: Demonstrate pointer to array. */
 #include <stdio.h>

 int i_array[] = { 25, 300, 2, 12 };

 main()
 {
    int *ptr;
    int count;
    ptr = &i_array[0];
    for( count = 0; count < 4 ; count++ )
    {
       printf( "i_array[%d] = %d\n", count, *ptr );
       ptr++;
    }
 }


 PARRAY1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PARRAY1.C

 /* PARRAY1.C: Compact version of PARRAY.C. */
 #include <stdio.h>

 int i_array[] = { 25, 300, 2, 12 };

 main()
 {
    int count;
    int *ptr = i_array;
    for( count = 0; count < 4 ; count++ )
       printf( "i_array[%d] = %d\n", count, *ptr++ );
 }


 PFUNC.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PFUNC.C

 /* PFUNC.C: Passing pointers to a function. */
 #include <stdio.h>

 void swap( int *ptr1, int *ptr2 );

 main()
 {
    int first = 1, second = 3;
    int *ptr = &second;
    printf( "first: %d  second: %d\n", first, *ptr );
    swap( &first, ptr );
    printf( "first: %d  second: %d\n", first, *ptr );
 }

 void swap( int *ptr1, int *ptr2 )
 {
    int temp;
    temp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = temp;
 }


 PIE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PIE.C

 /* PIE.C:  Create sample pie chart.  */
 #include <conio.h>
 #include <string.h>
 #include <graph.h>
 #include <pgchart.h>

 #define MONTHS 12

 typedef enum {FALSE, TRUE} boolean;

 float far value[MONTHS] =
 {
    33.0, 27.0, 42.0, 64.0,106.0,157.0,
   182.0,217.0,128.0, 62.0, 43.0, 36.0
 };
 char far *category[MONTHS] =
 {
   "Jan", "Feb", "Mar", "Apr",
   "May", "Jun", "Jly", "Aug",
   "Sep", "Oct", "Nov", "Dec"
 };
 short far explode[MONTHS] = {0};

 main()
 {
   chartenv env;
   int mode = _VRES16COLOR;

   /* Set highest video mode available */
   while(!_setvideomode( mode ))
      mode--;
   if(mode == _TEXTMONO)
      return( 0 );

   /* Initialize chart library and a default pie chart */
   _pg_initchart();
   _pg_defaultchart( &env, _PG_PIECHART, _PG_PERCENT );

   /* Add titles and some chart options */
   strcpy( env.maintitle.title, "Good Neighbor Grocery" );
   env.maintitle.titlecolor = 6;
   env.maintitle.justify = _PG_RIGHT;
   strcpy( env.subtitle.title, "Orange Juice Sales" );
   env.subtitle.titlecolor = 6;
   env.subtitle.justify = _PG_RIGHT;
   env.chartwindow.border = FALSE;

   /* Parameters for call to _pg_chartpie are:
    *
    *    env        - Environment variable
    *    category   - Category labels
    *    value      - Data to chart
    *    explode    - Separated pieces
    *    MONTHS     - Number of data values
    */

   if(_pg_chartpie( &env, category, value,
                     explode, MONTHS ))
   {
      _setvideomode( _DEFAULTMODE );
      _outtext( "Error:  can't draw chart" );
   }
   else
   {
      getch();
      _setvideomode( _DEFAULTMODE );
   }
   return( 0 );
 }


 POINTER.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\POINTER.C

 /* POINTER.C: Demonstrate pointer basics. */
 #include <stdio.h>

 main()
 {
    int val = 25;
    int *ptr;
    ptr = &val;
    printf( " val = %d\n", val );
    printf( "*ptr = %d\n\n", *ptr );
    printf( "&val = %u\n", &val );
    printf( " ptr = %d\n", ptr );
 }


 POWER2.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\POWER2.C

 /* POWER2.C */
 #include <stdio.h>

 int power2( int num, int power );

 void main( void )
 {
    printf( "3 times 2 to the power of 5 is %d\n", \
            power2( 3, 5) );
 }

 int power2( int num, int power )
 {
    _asm
    {
       mov ax, num    ; Get first argument
       mov cx, power  ; Get second argument
       shl ax, cl     ; AX = AX * ( 2 to the power of CL )
    }
    /* Return with result in AX */
 }


 PRTESC.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PRTESC.C

 /* PRTESC.C: Prints escape characters \",\n, and \t. */
 #include <stdio.h>
 #include <string.h>

 main()
 {
    char b[80];
    int i,j;

    strcpy( b, "and seven years ago\n" );
    printf( "\"Four score\n" );
    printf( b );
    printf( "\tone tab\n\t\ttwo tabs\n\t\t\tthree tabs\n" );
    i = sizeof( b );
    j = strlen( b );
    printf( "Size is %d\nLength is %d.\n", i, j );
 }


 PRTSTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PRTSTR.C

 /* PRTSTR.C: Prints strings. */
 #include <stdio.h>
 #include <string.h>

 main()
 {
    char aline[80], more[80];
    char *strptr;

    /* aline = "Another line."; */
    /* Note: This causes a compiler error */

    strcpy( aline, "Another line." );
    strcpy( more, aline );
    strptr = aline;
    strcat( aline, "dog" );
    printf( "A line of text." );
    printf( aline );
    printf( more );
    printf( strptr );
 }


 PSTRING.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PSTRING.C

 /* PSTRING.C: Demonstrate pointer to a string. */

 #include <stdio.h>

 main()
 {
    int count;
    static char name[] = "john";
    char *ptr = name;
    for( count = 0; count < 4; count++ )
    {
       printf( "name[%d]: %c\n", count, *ptr++ );
    }
 }


 PSTRING1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PSTRING1.C

 /* PSTRING1.C: Look for null at string's end.  */
 #include <stdio.h>

 main()
 {
    char name[] = "john";
    char *ptr = name;
    while( *ptr )
       printf( "*ptr = %c\n", *ptr++ );
 }


 PSTRING2.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PSTRING2.C

 /* PSTRING2.C: Demonstrate strings and array notation. */
 #include <stdio.h>
 #include <string.h>

 main()
 {
    int count;
    char name[] = "john";
    for( count = 0; count < strlen( name ); count++ )
       printf( "name[%d]: %c\n", count, name[count] );
 }


 PSTRING3.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PSTRING3.C

 /* PSTRING3.C: Strings and pointer notation.  */
 #include <stdio.h>
 #include <string.h>

 main()
 {
    int count;
    char name[] = "john";
    for( count = 0; count < strlen( name ); count++ )
       printf( "*(name+%d) = %c\n", count, *(name+count) );
 }


 PTRPTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\PTRPTR.C

 /* PTRPTR.C: Demonstrate a pointer to a pointer. */
 #include <stdio.h>

 main()
 {
    int val = 501;
    int *ptr = &val;
    int **ptr_ptr = &ptr;
    printf( "val = %d\n", **ptr_ptr );
 }


 QCSORT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\QCSORT.C

 /* QCSORT.C: Demonstrate sorting array of pointers. */

 #include <stdio.h>
 #define SIZE 4

 void sort( int size, double *p[] );
 void show( int size, double *p[], double dd[] );

 main()
 {
    int x;
    double d[] = { 3.333, 1.111, 2.222, 4.444 };
    double *d_ptr[SIZE];
    for( x = 0; x < SIZE; x++ )
       d_ptr[x] = &d[x];
    show( SIZE, d_ptr, d );
    sort( SIZE, d_ptr );
    show( SIZE, d_ptr, d );
 }

 void sort( int size, double *p[] )
 {
    int x, x1;
    double *temp;
    for( x = 0; x < size - 1; x++ )
       for( x1 = x + 1; x1 < size; x1++ )
       {
          if( *p[x] > *p[x1] )
          {
             temp = p[x1];
             p[x1] = p[x];
             p[x] = temp;
          }
       }
 }

 void show( int size, double *p[], double dd[] )
 {
    int x;
    printf( "------------------------" );
    printf( "------------------------\n" );
    for( x = 0; x < size; x++ )
    {
       printf( "*d_ptr[%d] = %1.3f   ", x, *p[x]);
       printf( "d_ptr[%d] = %u ", x, p[x]);
       printf( "  d[%d] = %1.3f\n", x, dd[x] );
    }
 }


 QCSORT1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\QCSORT1.C

 /* QCSORT1.C: Demonstrate sort with pointer notation. */

 #include <stdio.h>
 #define SIZE 4

 void sort( int size, double **p );
 void show( int size, double **p, double dd[] );

 main()
 {
    int x;
    double d[] = { 3.333, 1.111, 2.222, 4.444 };
    double *d_ptr[SIZE];
    for( x = 0; x < SIZE; x++ )
       d_ptr[x] = &d[x];
    show( SIZE, d_ptr, d );
    sort( SIZE, d_ptr );
    show( SIZE, d_ptr, d );
 }

 void sort( int size, double **p )
 {
    int x, x1;
    double *temp;
    for( x = 0; x < size - 1; x++ )
       for( x1 = x + 1; x1 < size; x1++ )
       {
          if( **(p+x) > **(p+x1) )
          {
             temp = *(p+x1);
             *(p+x1) = *(p+x);
             *(p+x) = temp;
          }
       }
 }

 void show( int size, double **p, double dd[] )
 {
    int x;
    printf( "------------------------" );
    printf( "------------------------\n" );
    for( x = 0; x < size; x++ )
    {
       printf( "*d_ptr[%d] = %1.3f   ", x, **(p+x) );
       printf( "d_ptr[%d] = %u ", x, *(p+x) );
       printf( "  d[%d] = %1.3f\n", x, dd[x] );
    }
 }


 RDFILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\RDFILE.C

 /* RDFILE.C: Reads a file and prints characters to the screen. */
 #include <stdio.h>

 main()
 {
    int c;
    FILE *fp;

    if( fp = fopen( "c:\\testfile.asc", "rb" ) )
    {
       while( (c = fgetc( fp )) != EOF )
          printf( " %c\t%d\n", c, c );
       printf( "\nEnd of file marker: %d", c );
       fclose( fp );
    }
    else
       printf( "Error in opening file\n" );
 }


 REALG.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\REALG.C

 /* REALG.C: Example of real-coordinate graphics */
 #include <stdio.h>
 #include <conio.h>
 #include <graph.h>

 #define TRUE 1
 #define FALSE 0

 int four_colors( void );
 void three_graphs( void );
 void grid_shape( void );

 int halfx, halfy;
 struct videoconfig screen;
 double bananas[] =
 {   -0.3, -0.2, -0.224, -0.1, -0.5, +0.21, +2.9,
    +0.3, +0.2, 0.0, -0.885, -1.1, -0.3, -0.2,
    +.001, +.005, +0.14, 0.0, -0.9, -0.13, +0.3
 };

 main()
 {
    if( four_colors() )
       three_graphs();
    else
       printf( "This program requires a CGA, EGA, or VGA graphics card.\n" );
 }

 int four_colors( void )
 {
    _getvideoconfig( &screen );
    switch( screen.adapter )
    {
       case _CGA:
       case _OCGA:
          _setvideomode( _MRES4COLOR );
          break;
       case _EGA:
       case _OEGA:
          _setvideomode( _ERESCOLOR );
          break;
       case _VGA:
       case _OVGA:
          _setvideomode( _VRES16COLOR );
          break;
       default:
          return( FALSE );
    }
    _getvideoconfig( &screen );
    return( TRUE );
 }

 void three_graphs( void )
 {
    int xwidth, yheight, cols, rows;
    struct _wxycoord upleft, botright;

    _clearscreen( _GCLEARSCREEN );
    xwidth = screen.numxpixels;
    yheight = screen.numypixels;
    halfx = xwidth/2;
    halfy = yheight/2;
    cols = screen.numtextcols;
    rows = screen.numtextrows;

    /* first window */
    _setviewport( 0, 0, halfx-1, halfy-1 );
    _settextwindow( 1, 1, rows/2, cols/2 );
    _setwindow( FALSE, -2.0, -2.0, 2.0, 2.0 );
    grid_shape();
    _rectangle( _GBORDER, 0, 0, halfx-1, halfy-1 );

    /* second window */
    _setviewport( halfx, 0, xwidth-1, halfy-1 );
    _settextwindow( 1, cols/2+1, rows/2, cols );
    _setwindow( FALSE, -3.0, -3.0, 3.0, 3.0 );
    grid_shape();
    _rectangle_w( _GBORDER, -3.0, -3.0, 3.0, 3.0 );

    /* third window */
    _setviewport( 0, halfy, xwidth-1, yheight-1 );
    _settextwindow( rows/2+1, 1, rows, cols );
    _setwindow( TRUE, -3.0, -1.5, 1.5, 1.5 );
    grid_shape();
    upleft.wx = -3.0;
    upleft.wy = -1.5;
    botright.wx = 1.5;
    botright.wy = 1.5;
    _rectangle_wxy( _GBORDER, &upleft, &botright );

    getch();
    _setvideomode( _DEFAULTMODE );
 }

 void grid_shape( void )
 {
    int i, numc, x1, y1, x2, y2;
    double x, y;
    char txt[80];

    numc = screen.numcolors;
    for( i = 1; i < numc; i++ )
    {
       _settextposition( i, 2 );
       _settextcolor( i );
       sprintf( txt, "Color %d", i );
       _outtext( txt );
    }

    _setcolor( 1 );
    _rectangle_w( _GBORDER, -1.0, -1.0, 1.0, 1.0 );
    _rectangle_w( _GBORDER, -1.02, -1.02, 1.02, 1.02 );

    for( x = -0.9, i = 0; x < 0.9; x += 0.1 )
    {
       _setcolor( 2 );
       _moveto_w( x, -1.0 );
       _lineto_w( x, 1.0 );
       _moveto_w( -1.0, x );
       _lineto_w( 1.0, x );

       _setcolor( 3 );
       _moveto_w( x - 0.1, bananas[i++] );
       _lineto_w( x, bananas[i] );
    }
    _moveto_w( 0.9, bananas[i++] );
    _lineto_w( 1.0, bananas[i] );
 }


 RWFILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\RWFILE.C

 /* RWFILE.C: Reads and writes a file. */
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <io.h>

 #define BUFF 512

 main()
 {
    char inbuffer[BUFF];
    char outbuffer[BUFF];
    int infile, outfile, length, num;

    strcpy( outbuffer, "Happy Birthday." );
    length = strlen( outbuffer );
    length++;

    if( (outfile = open( "testfile.bin",
       O_CREAT | O_WRONLY | O_BINARY,  S_IWRITE )) != -1 )
    {
       if( (num = write( outfile, outbuffer, length )) == -1 )
          perror( "Error in writing" );
       printf( "\nBytes written to file: %d\n", num );
       close( outfile );
    }
    else
       perror( "Error opening outfile" );

    if( (infile = open( "testfile.bin", O_RDONLY | O_BINARY )) != -1  )
    {
       while( length = read( infile, inbuffer, BUFF ) )
          printf( "%d bytes received so far.\n", length );
       close( infile );
       printf( "%s\n", inbuffer );
    }
    else
       perror( "Error opening infile" );
 }


 SAMPLER.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SAMPLER.C

 /* SAMPLER.C: Display sample text in various fonts. */
 #include <stdio.h>
 #include <conio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <string.h>

 #define NFONTS 6

 main()
 {
   static unsigned char *text[2*NFONTS] =
   {
       "COURIER",        "courier",
       "HELV",           "helv",
       "TMS RMN",        "tms rmn",
       "MODERN",         "modern",
       "SCRIPT",         "script",
       "ROMAN",          "roman"
   };
   static unsigned char *face[NFONTS] =
   {
       "t'courier'",
       "t'helv'",
       "t'tms rmn'",
       "t'modern'",
       "t'script'",
       "t'roman'"
   };
   static unsigned char list[20];
   struct videoconfig vc;
   int mode = _VRES16COLOR;
   register i;

   /*  Read header info from all .FON files in
    *  current directory   */
   if(_registerfonts( "*.FON" )<0 )
   {
      _outtext("Error:  can't register fonts");
      exit( 0 );
   }

   /*   Set highest available video mode */
   while( !_setvideomode( mode ) )
      mode--;
   if( mode == _TEXTMONO )
      exit ( 0 );

   /*   Copy video configuration into structure vc */
   _getvideoconfig( &vc );

   /*   Display six lines of sample text */
   for( i = 0; i<NFONTS; i++ )
   {
      strcpy( list, face[i] );
      strcat( list, "h30w24b" );

      if( !_setfont( list ) )
      {
          _setcolor( i + 1 );
          _moveto( 0, (i * vc.numypixels) / NFONTS );
          _outgtext( text[i * 2] );
          _moveto( vc.numxpixels / 2,
                      (i * vc.numypixels) / NFONTS );
          _outgtext( text[(i * 2) + 1] );
      }
      else
      {
          _setvideomode( _DEFAULTMODE );
          _outtext( "Error:  can't set font" );
          exit( 0 );
      }
   }
   getch();
   _setvideomode( _DEFAULTMODE );

   /* Return memory when finished with fonts */
   _unregisterfonts();
   exit( 0 );
 }


 SCATTER.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SCATTER.C

 /* SCATTER.C:  Create sample scatter diagram. */

 #include <conio.h>
 #include <string.h>
 #include <graph.h>
 #include <pgchart.h>

 #define MONTHS 12
 typedef enum {FALSE, TRUE} boolean;

 /* Orange juice sales */

 float far xvalue[MONTHS] =
 {
    33.0, 27.0, 42.0, 64.0,106.0,157.0,
   182.0,217.0,128.0, 62.0, 43.0, 36.0
 };
 /* Hot chocolate sales */

 float far yvalue[MONTHS] =
 {
   37.0, 37.0, 30.0, 19.0, 10.0,  5.0,
    2.0,  1.0,  7.0, 15.0, 28.0, 39.0
 };

 main()
 {
   chartenv env;
   int mode = _VRES16COLOR;

   /* Set highest video mode available */

   while(!_setvideomode( mode ))
      mode--;
   if(mode == _TEXTMONO)
      return(0);

   /* Initialize chart library and default
    * scatter diagram
    */

   _pg_initchart();

   _pg_defaultchart( &env, _PG_SCATTERCHART,
                     _PG_POINTONLY );

   /* Add titles and some chart options */

   strcpy( env.maintitle.title, "Good Neighbor Grocery" );
   env.maintitle.titlecolor = 6;
   env.maintitle.justify = _PG_RIGHT;
   strcpy( env.subtitle.title,
           "Orange Juice vs Hot Chocolate" );
   env.subtitle.titlecolor = 6;
   env.subtitle.justify = _PG_RIGHT;
   env.yaxis.grid = TRUE;
   strcpy( env.xaxis.axistitle.title,
           "Orange Juice Sales" );
   strcpy( env.yaxis.axistitle.title,
           "Hot Chocolate Sales" );
   env.chartwindow.border = FALSE;

   /* Parameters for call to _pg_chartscatter are:
    *    env        - Environment variable
    *    xvalue     - X-axis data
    *    yvalue     - Y-axis data
    *    MONTHS     - Number of data values
    */

   if(_pg_chartscatter( &env, xvalue,
                         yvalue, MONTHS ))
   {
      _setvideomode( _DEFAULTMODE );
      _outtext( "Error:  can't draw chart" );
   }
   else
   {
      getch();
      _setvideomode( _DEFAULTMODE );
   }
   return(0);
 }


 SHOWME.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SHOWME.C

 /* SHOWME.C: Demonstrate passing by value. */
 #include <stdio.h>

 void showme( int a, int b, int c );

 main()
 {
    int x = 10, y = 20, z = 30;
    showme( z, y, x );
 }

 void showme( int a, int b, int c )
 {
    printf( "a=%d b=%d c=%d", a, b, c );
 }


 SHOWMORE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SHOWMORE.C

 /* SHOWMORE.C: Demonstrate passing by value. */
 #include <stdio.h>

 void showme( int any, int old, int name );

 main()
 {
    int x = 10, y = 20, z = 30;
    showme( z, y, x );
    printf( "  z=%d   y=%d    x=%d\n", z, y, x );
 }

 void showme( int any, int old, int name )
 {
    printf( "any=%d old=%d name=%d\n", any, old, name );
    any = 55;
    old = 66;
    name = 77;
    printf( "any=%d old=%d name=%d\n", any, old, name );
 }


 SINE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SINE.C

 /*  SINE.C: Illustrates basic graphics commands */
 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <math.h>
 #include <conio.h>
 #define PI 3.14159

 void graphics_mode( void );
 void draw_lines( void );
 void sine_wave( void );
 void draw_shapes( void );
 void end_program( void );
 int newx( int );
 int newy( int );

 struct videoconfig myscreen;
 int maxx, maxy;
 unsigned char diagmask[8] =
 { 0x93, 0xC9, 0x64, 0xB2, 0x59, 0x2C, 0x96, 0x4B };
 unsigned char linemask[8] =
 { 0xFF, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0xCC };

 main()
 {
    graphics_mode();
    draw_lines();
    sine_wave();
    draw_shapes();
    end_program();
 }

 void graphics_mode( void )
 {
    _getvideoconfig( &myscreen );
    switch( myscreen.adapter )
    {
       case _CGA:
          _setvideomode( _HRESBW );
          break;
       case _OCGA:
          _setvideomode( _ORESCOLOR );
          break;
       case _EGA:
       case _OEGA:
          if( myscreen.monitor == _MONO )
             _setvideomode( _ERESNOCOLOR );
          else
             _setvideomode( _ERESCOLOR );
          break;
       case _VGA:
       case _OVGA:
       case _MCGA:
          _setvideomode( _VRES2COLOR );
          break;
       case _HGC:
          _setvideomode( _HERCMONO );
          break;
       default:
          printf( "This program requires a CGA, EGA, VGA, or Hercules card\n"
          exit( 0 );
    }
    _getvideoconfig( &myscreen );
    maxx = myscreen.numxpixels - 1;
    maxy = myscreen.numypixels - 1;
 }

 int newx( int xcoord )
 {
    int nx;
    float tempx;
    tempx = ((float) maxx)/ 1000.0;
    tempx = ((float) xcoord) * tempx + 0.5;
    return( (int) tempx );
 }

 int newy( int ycoord )
 {
    int ny;
    float tempy;
    tempy = ((float) maxy)/ 1000.0;
    tempy = ((float) ycoord) * tempy + 0.5;
    return( (int) tempy );
 }

 void sine_wave( void )
 {
    int locx, locy;
    double i, rad;

    for( i = 0.0; i < 1000.0; i += 3.0 )
    {
       rad = -sin( (PI * (float) i) / 250.0 );
       locx = newx( (int) i );
       locy = newy( (int) (rad * 250.0) );
       _setpixel( locx, locy );
    }
 }

 void draw_shapes( void )
 {
    _setlinestyle( 0xFFFF );
    _setfillmask( diagmask );
    _rectangle( _GBORDER, newx(50), newy(-325), newx(200), newy(-425) );
    _rectangle( _GFILLINTERIOR, newx(550), newy(-325), newx(700), newy(-425) )

    _setfillmask( linemask );
    _ellipse( _GBORDER, newx(50), newy(325), newx(200), newy(425) );
    _ellipse( _GFILLINTERIOR, newx(550), newy(325), newx(700), newy(425) );
 }

 void end_program( void )
 {
    getch();
    _setvideomode( _DEFAULTMODE );
 }

 void draw_lines( void )
 {
    _rectangle( _GBORDER, 0, 0, maxx, maxy );
    /* _setcliprgn( 20, 20, maxx - 20, maxy - 20 ); */
    _setvieworg( 0, newy( 500 ) );

    _moveto( 0, 0 );
    _lineto( newx( 1000 ), 0 );
    _setlinestyle( 0xAA3C );
    _moveto( 0, newy( -250) );
    _lineto( newx( 1000 ), newy( -250 ) );

    _setlinestyle( 0x8888 );
    _moveto( 0, newy( 250 ) );
    _lineto( newx( 1000 ), newy( 250 ) );
 }


 STATIC.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\STATIC.C

 /* STATIC.C: Demonstrate static variables. */

 #include <stdio.h>

 void add_val( int value );

 main()
 {
    add_val( 1 );
    add_val( 5 );
    add_val( 20 );
 }

 void add_val( int value )
 {
    static int methuselah;
    if( value == 1 )
       methuselah = 0;
    methuselah = methuselah + value;
    printf( "methuselah = %d\n", methuselah );
 }


 STRING.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\STRING.C

 /* STRING.C: Demonstrate string arrays. */
 #include <stdio.h>

 main()
 {
    int j;
    char c_array[] = "Hello";

    printf( "--- Values --------     --- Addresses -------\n\n" );

    for( j = 0; j < 6; j = j + 1 )
    {
       printf( "c_array[%d]   = %x %c", j, c_array[j], c_array[j] );
       printf( "\t&c_array[%d]    = %u\n", j, &c_array[j] );
    }
 }


 SVBIN.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SVBIN.C

 /* SVBIN.C: Saves integer variables in binary format. */
 #include <stdio.h>
 #define ASIZE 10

 main()
 {
    FILE *ap;
    int zebra[ASIZE], acopy[ASIZE], bcopy[ASIZE];
    int i;

    for( i = 0; i < ASIZE; i++ )
       zebra[i] = 7700 + i;

    if( (ap = fopen( "binfile", "wb" )) != NULL )
    {
       fwrite( zebra, sizeof(zebra), 1, ap );
       fclose( ap );
    }
    else
       perror( "Write error" );

    if( (ap = fopen( "morebin", "wb" )) != NULL )
    {
       fwrite( &zebra[0], sizeof(zebra[0]), ASIZE, ap );
       fclose( ap );
    }
    else
       perror( "Write error" );

    if( (ap = fopen( "binfile", "rb" )) != NULL )
    {
       printf( "Hexadecimal values in binfile:\n" );
       while( (i = fgetc( ap )) != EOF )
          printf( "%02X ", i );
       rewind( ap );
       fread( acopy, sizeof(acopy), 1, ap );
       rewind( ap );
       fread( &bcopy[0], sizeof( bcopy[0] ), ASIZE, ap);
       for( i=0; i<ASIZE; i++ )
          printf( "\nItem %d = %d\t%d", i, acopy[i], bcopy[i] );
       fclose( ap );

    }
    else
       perror( "Read error" );

 }


 SVTEXT.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SVTEXT.C

 /* SVTEXT.C: Save integer variables as text. */
 #include <stdio.h>

 int list[] = { 53, -23456, 50, 500, 5000, -99 };
 extern int errno;
 char fname[] = "numtext";
 char temp[81];

 main()
 {
    FILE *fptr;
    int i;

    if( (fptr = fopen( "numtext","wt" )) != NULL )
    {
       for( i=0; i<6; i++ )
          fprintf( fptr, "Item %d: %6d \n", i, list[i] );
       fclose( fptr );
    }
    else
       printf( "Error: Couldn't create file.\n" );

    if( (fptr = fopen( "badname", "rt" )) != NULL )
    {
       /* do nothing */
    }
    else
    {
       printf( "Error number: %d\n\t", errno );
       perror( "Couldn't open file BADNAME\n\t" );
    }

    if( (fptr = fopen( fname, "rt" )) != NULL )
    {
       list[0] = 0;
       fscanf( fptr, "Item %d: %d \n", &i, &list[0] );
       printf( "Values read from file:\t %d %d\n", i, list[0] );
       fgets( temp, 80, fptr );
       printf( "String from file: \t%s\n", temp );
       while( (i = fgetc( fptr )) != '\n' )
          printf( "char: %c \t ASCII: %d \n", i, i );
       rewind( fptr );
       printf( "Rewind to start -->\t%s", fgets( temp, 80, fptr ) );
       fclose( fptr );
    }
    else
       printf( "Trouble opening %s \n", fname );
 }


 SWITCH.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\SWITCH.C

 /* SWITCH.C: Demonstrate switch statement. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getch();
    switch( ch )
    {
       case 'b':
          printf( "Beep!\a\n" );
          break;
       case '\r':
          printf( "Enter\n" );
          break;
       default:
          printf( "Bye bye" );
          break;
    }
 }


 TWODIM.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\TWODIM.C

 /* TWODIM.C: Demonstrate multidimensional arrays. */

 #include <stdio.h>

 main()
 {
    int j, k;
    int i_array[2][3] = { { 176, 4069, 303 }, { 6, 55, 777 } };

    printf( "--- Values --------     --- Addresses -------\n\n" );

    for( j = 0; j < 2; j = j + 1 )
    {
       for( k = 0; k < 3; k = k + 1 )
       {
          printf( "i_array[%d][%d] = %d", j, k, i_array[j][k] );
          printf( "\t&i_array[%d][%d] = %u\n", j, k, &i_array[j][k] );
       }
       printf( "\n" );
    }

 }


 TYPES.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\TYPES.C

 /* TYPES.C: Illustrate basic data types. */
 #include <stdio.h>

 main()
 {
    char char_val        = 'a';
    int int_val         = 543;
    float float_val     = 11.1;
    double double_val   = 66.123456789;
    printf( "char_val   = %c\n", char_val );
    printf( "int_val    = %d\n", int_val );
    printf( "float_val  = %f\n", float_val );
    printf( "double_val = %2.9f\n", double_val );
 }


 VISIBLE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\VISIBLE.C

 /* VISIBLE.C: Demonstrate local visibility. */

 #include <stdio.h>
 void be_bop( void );

 main()
 {
    int val = 10;
    be_bop();
 }

 void be_bop( void )
 {
    printf( "val = %d", val ); /* Error! */
 }


 VISIBLE1.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\VISIBLE1.C

 /* VISIBLE1.C: Demonstrate local visibility. */

 #include <stdio.h>

 void be_bop( int param );

 main()
 {
    int val = 10;
    be_bop( val );
 }

 void be_bop( int param )
 {
    printf( "%d\n", param );
 }


 VISIBLE2.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\VISIBLE2.C

 /* VISIBLE2.C: Demonstrate external visibility.
 */

 #include <stdio.h>

 void be_bop( int param );

 main()
 {
    be_bop( val ); /* Error! */
 }

 int val = 10;

 void be_bop( int param )
 {
    printf( "val = %d\n", param );
 }


 VOLUME.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\VOLUME.C

 /* VOLUME.C: Calculate sphere's volume. */
 #include <stdio.h>
 #define PI 3.14

 float sphere( int rad );

 main()
 {
    float volume;
    int radius = 3;
    volume = sphere( radius );
    printf( "Volume: %f\n", volume );
 }

 float sphere( int rad )
 {
    float result;
    result = rad * rad * rad;
    result = 4 * PI * result;
    result = result / 3;
    return result;
 }


 WHILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\WHILE.C

 /* WHILE.C: Demonstrate while loop. */

 #include <stdio.h>

 main()
 {
    int test = 10;

    while( test > 0 )
    {
       printf( "test = %d\n", test );
       test = test - 2;
    }
 }


 WRFILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC\QC25\WRFILE.C

 /* WRFILE.C: Creates and writes to a disk file. */
 #include <stdio.h>

 main()
 {
    FILE *fp;

    if( (fp = fopen( "c:\\testfile.asc","w" )) != NULL )
    {
       fputs( "Example string", fp );
       fputc( '\n', fp );
       fclose( fp );
    }
    else
       printf( "error message\n" );
 }
 Proficient C - Sample Code


 ANSI_CPR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\ANSI_CPR.C

 /*
  *        ansi_cpr -- report where the cursor is located
  *        The position information is placed in the keyboard buffer
  *        in the form ESC[rr;ccR where ESC is the value of the
  *        ESCAPE character (\033) and r and c represent
  *        decimal values of row and column data.
  */

 #include <local\ansi.h>

 void
 ansi_cpr(row, col)
 int        *row,
         *col;
 {
         int i;

         /* request a cursor position report */
         ANSI_DSR;

         /* toss the ESC and '[' */
         (void) getkey();
         (void) getkey();

         /* read the row number */
         *row = 10 * (getkey() - '0');
         *row = *row + getkey() - '0';

         /* toss the ';' separator */
         (void) getkey();

         /* read the column number */
         *col = 10 * (getkey() - '0');
         *col = *col + getkey() - '0';

         /* toss the trailing ('R') and return */
         (void) getkey();
         (void) getkey();
         return;
 }


 ANSI_TST.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\ANSI_TST.C

 /*
  *        ansi_tst -- verify that the ANSI.SYS driver is loaded
  *        (prints message and exits is ANSI driver not working)
  */

 #include <stdio.h>
 #include <local\ansi.h>
 #include <local\video.h>

 #define TST_ROW        2
 #define TST_COL        75

 void
 ansi_tst()
 {
         int row, col;
         static char *help[] = {
                 "\n",
                 "ANSI.SYS device driver not loaded:\n",
                 "  1. Copy ANSI.SYS to your system disk.\n",
                 "  2. Add the line device=ansi.sys to your\n",
                 "     CONFIG.SYS file and reboot your machine.\n",
                 NULL
         };
         char **msg;

         extern int getstate();
         extern int readcur(int *, int *, int);

         getstate();
         ANSI_CUP(TST_ROW, TST_COL);
         readcur(&row, &col, Vpage);
         if (row != TST_ROW - 1 || col != TST_COL - 1) {
                 for (msg = help; *msg != NULL; ++msg)
                         fputs(*msg, stderr);
                 exit(1);
         }

         return;
 }


 BEEP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\BEEP.C

 /*
  *        beep -- sound the terminal beeper
  */

 #include <stdio.h>

 #define BEL        7

 void
 beep()
 {
         putchar(BEL);
 }


 CAT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\CAT.C

 /*
  *        cat -- concatenate files
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         int ch;
         char *cp;
         FILE *fp;
         BOOLEAN errflag, silent;
         static char pgm[MAXNAME + 1] = { "cat" };

         extern void getpname(char *, char *);
         extern int fcopy(FILE *, FILE *);
         extern int getopt(int, char **, char *);
         extern int optind;
         extern char *optarg;

         /* use an alias if one is given to this program */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* process optional arguments, if any */
         errflag = FALSE;
         silent = FALSE;
         while ((ch = getopt(argc, argv, "s")) != EOF)
                 switch (ch) {
                 case 's':
                         /* don't complain about non-existent files */
                         silent = TRUE;
                         break;
                 case '?':
                         /* say what? */
                         errflag = TRUE;
                         break;
                 }
         if (errflag == TRUE) {
                 fprintf(stderr, "Usage: %s [-s] file...\n", pgm);
                 exit(1);
         }

         /* process any remaining arguments */
         argc -= optind;
         argv += optind;
         if (argc == 0)
                 /* no file names -- use standard input */
                 if (fcopy(stdin, stdout) != 0) {
                         fprintf(stderr, "error copying stdin");
                         exit(2);
                 }
                 else
                         exit(0);

         /* copy the contents of each named file to standard output */
         for (; argc-- > 0; ++argv) {
                 if ((fp = fopen(*argv, "r")) == NULL) {
                         if (silent == FALSE)
                                 fprintf(stderr, "%s: can't open %s\n",
                                         pgm, *argv);
                         continue;
                 }
                 if (fcopy(fp, stdout) != 0) {
                         fprintf(stderr, "%s: Error while copying %s",
                                 pgm, *argv);
                         exit(3);
                 }
                 if (fclose(fp) != 0) {
                         fprintf(stderr, "%s: Error closing %s",
                                 pgm, *argv);
                         exit(4);
                 }
         }

         exit(0);
 }


 CLRSCRN.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\CLRSCRN.C

 /*
  *        clrscrn -- clear the "visual" screen page
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>
 #include <local\video.h>

 int
 clrscrn(a)
 unsigned int a;        /* video attribute for new lines */
 {
         union REGS inregs, outregs;

         inregs.h.ah = SCROLL_UP;
         inregs.h.al = 0;                /* blank entire window */
         inregs.h.bh = a;                /* use specified attribute */
         inregs.h.bl = 0;
         inregs.x.cx = 0;                /* upper left corner */
         inregs.h.dh = Maxrow[Vmode] - 1;/* bottom screen row */
         inregs.h.dl = Maxcol[Vmode] - 1;/* rightmost column */
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 CLRW.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\CLRW.C

 /*
  *        clrw -- clear specified region of "visual" screen page
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 clrw(t, l, b, r, a)
 int t;                /* top row of region to clear */
 int l;                /* left column */
 int b;                /* bottom row */
 int r;                /* right column */
 unsigned char a;/* attribute for cleared region */
 {
         union REGS inregs, outregs;

         inregs.h.ah = SCROLL_UP;/* scroll visual page up */
         inregs.h.al = 0;        /* blank entire window */
         inregs.h.bh = a;        /* attribute of blank lines */
         inregs.h.bl = 0;
         inregs.h.ch = t;        /* upper left of scroll region */
         inregs.h.cl = l;
         inregs.h.dh = b;        /* lower right of scroll region */
         inregs.h.dl = r;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 COLORNUM.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\COLORNUM.C

 /*
  *        colornum -- return the IBM number for the color
  *        presented as a string; return -1 if no match.
  */

 #include <stdio.h>
 #include <string.h>
 #include <local\ibmcolor.h>

 #define NCHARS        3

 int
 colornum(name)
 char *name;
 {
         register int n;
         static struct color_st {
                 char *c_name;
                 int c_num;
         } colortab[] = {
                 "black",        IBM_BLACK,
                 "blue",                IBM_BLUE,
                 "green",        IBM_GREEN,
                 "cyan",                IBM_CYAN,
                 "red",                IBM_RED,
                 "magenta",        IBM_MAGENTA,
                 "brown",        IBM_BROWN,
                 "white",        IBM_WHITE,
                 "normal",        IBM_NORMAL,
                 "bright",        IBM_BRIGHT,
                 "light",        IBM_BRIGHT,
                 "bold",                IBM_BRIGHT,
                 "yellow",        IBM_BROWN + IBM_BRIGHT,
                 "blink",        IBM_BLINK,
                 "reverse",        IBM_REVERSE,
                 "invisible",        IBM_INVISIBLE,
                 NULL,                (-1)
         };

         (void) strlwr(name);
         for (n = 0; colortab[n].c_name != NULL; ++n)
                 if ((strncmp(name, colortab[n].c_name, NCHARS)) == 0)
                         return (colortab[n].c_num);
         return (-1);
 }


 CP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\03DOS\CP.C

 /*
  *        cp -- a simplified copy command
  */

 #include <stdio.h>

 main()
 {
         int ch;

         while ((ch = getc(stdin)) != EOF)
                 putc(ch, stdout);
         exit(0);
 }


 CPBLK.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\11SCREEN\CPBLK.C

 /*
  *        cpblk -- copy a block of characters and attributes
  *        while eliminating "snow" on a standard CGA display
  */

 #include <conio.h>
 #include <memory.h>

 #define BLKCNT        10
 #define VSTAT        0x3DA
 #define VRBIT        8
 #define WRDCNT        200
 #define NBYTES        (2 * WRDCNT)

 /* macro to synchronize with vertical retrace period */
 #define VSYNC        while ((inp(VSTAT) & VRBIT) == VRBIT); \
                 while ((inp(VSTAT) & VRBIT) != VRBIT)

 int
 cpblk(src_os, src_seg, dest_os, dest_seg)
 unsigned int src_os, src_seg, dest_os, dest_seg;
 {
         register int i;
         int n;
         register int delta;

         n = 0;
         delta = 0;
         for (i = 0; i < BLKCNT ; ++i) {
                 /* copy a block of words during vertical retrace */
                 VSYNC;
                 movedata(src_seg, src_os + delta,
                         dest_seg, dest_os + delta, NBYTES);
                 n += WRDCNT;

                 /* adjust buffer offset */
                 delta += NBYTES;
         }

         return (n);
 }


 CURBACK.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\CURBACK.C

 /*
  *        curback -- move cursor back (left); return the
  *        value of the new column position
  */

 #include <local\bioslib.h>

 int
 curback(n, pg)
 int n, pg;
 {
         int r, c;

         /*
          *        move the cursor left by up to n positions but
          *        not past the beginning of the current line
          */
         readcur(&r, &c, pg);
         if (c - n < 0)
                 c = 0;
         putcur(r, c, pg);
         return (c);
 }


 CURSOR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\CURSOR.C

 /*
  *        cursor -- interactively set cursor shape
  */

 #include <dos.h>
 #include <stdlib.h>
 #include <local\video.h>
 #include <local\keydefs.h>

 /* additional drawing characters (others are defined in video.h) */
 #define DOT        254
 #define NO_DOT        196
 #define D_POINT        31
 #define R_POINT 16
 #define L_POINT 17

 /* dimensions of the help frame */
 #define BOX_Y        6
 #define BOX_X        30

 /* upper-left row and column of big cursor */
 int Ulr;
 int Ulc;
 int Mid;

 /* cursor scan-line-selection modes */
 typedef enum { STARTSCAN, ENDSCAN } CMODE;

 int
 main()
 {
         int i, j;
         int ch;
         int start, end;
         int height, width;
         static char spoint[] = { "Start\020" }; /* contains right pointer */
         static char epoint[] = { "\021Stop" };        /* contains left pointe
         static char title[] = { "CURSOR: Control cursor shape (V1.0)" };
         unsigned char
                 oldattr,        /* video attribute upon entry */
                 headattr,        /* video attribute of header */
                 attr,                 /* primary video attribute */
                 standout;        /* highlighting video attribute */
         CMODE mode;

         static void drawdspy(int, int, int, int, int);
         static void drawstart(int, char *);
         static void drawend(int, int, char *);
         static void drawactive(int, int, CMODE);
         static void showhelp(int, int);

         /* get video information and initialize */
         getstate();
         Mid = Vwidth / 2;
         readca(&ch, &oldattr, Vpage);        /* preserve user's video attribu
         getctype(&start, &end, Vpage);        /* and cursor shape */
         headattr = (WHT << 4) | BLK;

         /* set parameters based on video mode (default = CGA) */
         height = width = 8;        /* use an 8 by 8 block character cell */
         attr = (BLU << 4) | CYAN | BRIGHT;
         standout = YEL;
         if (Vmode == MDA_M80) {
                 /* uses a 14 by 9 dot block character cell */
                 height = 14;
                 width = 9;
                 attr = NORMAL;
                 standout = BWHT;
         }
         setctype(height + 1, height + 1);        /* cursor off */

         /* basic text and layout */
         Ulr = 2;
         Ulc = Mid - width / 2;
         clrscrn(attr);
         putcur(0, 0, Vpage);
         writeca(' ', headattr, Vwidth, Vpage);
         putcur(0, Mid - strlen(title) / 2, Vpage);
         writestr(title, Vpage);
         showhelp(Ulr + height + 1, Mid - BOX_X / 2);

         /* interactively select cursor shape */
         mode = STARTSCAN;
         drawdspy(start, end, standout, width, height);
         drawstart(start, spoint);
         drawend(end, width, epoint);
         drawactive(height, width, mode);
         while (1) {
                 switch (ch = getkey()) {
                 case K_UP:
                         /* move up one scan line */
                         if (mode == STARTSCAN)
                                 drawstart(start--, "      ");
                         else
                                 drawend(end--, width, "     ");
                         break;
                 case K_DOWN:
                         /* move down one scan line */
                         if (mode == STARTSCAN)
                                 drawstart(start++, "      ");
                         else
                                 drawend(end++, width, "     ");
                         break;
                 case K_LEFT:
                         /* starting scan-line-selection mode */
                         mode = STARTSCAN;
                         drawactive(height, width, mode);
                         continue;
                 case K_RIGHT:
                         /* ending scan-line-selection mode */
                         mode = ENDSCAN;
                         drawactive(height, width, mode);
                         continue;
                 case K_RETURN:
                         /* set the new cursor shape */
                         setctype(start, end);
                         clrscrn(oldattr);
                         putcur(0, 0, Vpage);
                         exit(0);
                 }

                 /* make corrections at cursor image boundaries */
                 if (start < 0)
                         start = 0;
                 else if (start > height)
                         start = height;
                 if (end < 0)
                         end = 0;
                 else if (end >= height)
                         end = height - 1;

                 /* show updated cursor shape and pointers */
                 drawdspy(start, end, standout, width, height);
                 drawstart(start, spoint);
                 drawend(end, width, epoint);
         }

         exit(0);
 } /* end main() */


 /*
  *        drawdspy -- draw a magnified image of a cursor with the
  *        currently active scan lines depicted as a sequence of dots
  *        and inactive lines depicted as straight lines
  */

 static void
 drawdspy(s, e, a, w, h)
 int s;        /* starting scan line */
 int e;        /* ending scan line */
 int a;        /* video attribute */
 int w;        /* width */
 int h;        /* height */
 {
         int i;

         /* display an exploded image of each scan line */
         for (i = 0; i < h; ++i) {
                 putcur(Ulr + i, Ulc, Vpage);
                 if (s >= h)
                         /* cursor is effectively off */
                         writeca(NO_DOT, a, w, Vpage);
                 else if ((s <= e && i >= s && i <= e) || /* a full block */
                         (s > e && (i <= e || i >= s)))         /* a split blo
                         writeca(DOT, a, w, Vpage);
                 else
                         /* outside start/end range */
                         writeca(NO_DOT, a, w, Vpage);
         }
 } /* end drawdspy() */


 /*
  *        drawstart -- display a pointer to the displayed starting
  *        scan line in the magnified cursor image
  */

 static void
 drawstart(s, sp)
 int s;                /* starting scan line number */
 char *sp;        /* visual pointer to the displayed starting scan line */
 {
         putcur(Ulr + s, Ulc - strlen(sp), Vpage);
         putstr(sp, Vpage);
 } /* end drawstart() */


 /*
  *        drawend -- display a pointer to the displayed ending
  *        scan line in the magnified cursor image
  */

 static void
 drawend(e, w, ep)
 int e;                /* ending scan line number */
 int w;                /* width of the cursor image */
 char *ep;        /* visual pointer to the displayed ending scan line */
 {
         putcur(Ulr + e, Ulc + w, Vpage);
         putstr(ep, Vpage);
 } /* end drawend() */

 static void
 drawactive(h, w, m)
 int h, w;
 CMODE m;
 {
         int col;

         /* clear active selector row */
         putcur(Ulr - 1, Ulc, Vpage);
         writec(' ', w, Vpage);

         /* point to active selector */
         col = (m == STARTSCAN) ? 0 : w - 1;
         putcur(Ulr - 1, Ulc + col, Vpage);
         writec(D_POINT, 1, Vpage);
 } /* end drawactive() */

 /*
  *        showhelp -- display a set of instructions about the
  *        use of the cursor program in a fine-ruled box
  */

 static void
 showhelp(r, c)
 int r, c;        /* upper-left corner of help frame */
 {
         static char title[] = { " Instructions " };
         extern int drawbox(int, int, int, int, int);

         /* fine-ruled box */
         clrw(r, c, r + BOX_Y, c + BOX_X, (WHT << 4) | GRN | BRIGHT);
         drawbox(r, c, r + BOX_Y, c + BOX_X, Vpage);

         /* centered title */
         putcur(r, c + (BOX_X - strlen(title)) / 2, Vpage);
         putstr(title, Vpage);

         /* display symbols and text using brute-force positioning */
         putcur(r + 2, c + 2, Vpage);
         put_ch(LEFTARROW, Vpage);
         put_ch(RIGHTARROW, Vpage);
         putstr("  Change selection mode", Vpage);
         putcur(r + 3, c + 2, Vpage);
         put_ch(UPARROW, Vpage);
         put_ch(DOWNARROW, Vpage);
         putstr("  Select scan lines", Vpage);
         putcur(r + 4, c + 2, Vpage);
         put_ch(L_POINT, Vpage);
         put_ch(LRC11, Vpage);
         putstr("  Set shape and exit", Vpage);
 } /* end showhelp() */


 DELAY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\DELAY.C

 /*
  *        delay -- provide a delay of ** approximately ** the
  *        specified duration (resolution is about 0.055 second)
  */

 #include <local\timer.h>

 void
 delay(d)
 float d;        /* duration in seconds and fractional seconds */
 {
         long ticks, then;
         extern long getticks();

         /* convert duration to number of PC clock ticks */
         ticks = d * TICKRATE;

         /* delay for the specified interval */
         then = getticks() + ticks;
         while (1)
                 if (getticks() >= then)
                         break;
 }


 DRAWBOX.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\DRAWBOX.C

 /*
  *        drawbox -- create a box with IBM line-drawing characters
  */

 #include <local\video.h>

 int
 drawbox(top, lft, btm, rgt, pg)
 int top, lft, btm, rgt, pg;
 {
         int i;
         int x;        /* interior line length for top and bottom segments */

         x = rgt - lft - 1;

         /* draw the top row */
         putcur(top, lft, pg);
         put_ch(ULC11, pg);
         writec(HBAR1, x, pg);
         putcur(top, rgt, pg);
         put_ch(URC11, pg);

         /* draw the sides */
         for (i = 1; i < btm - top; ++i)
         {
                 putcur(top + i, lft, pg);
                 put_ch(VBAR1, pg);
                 putcur(top + i, rgt, pg);
                 put_ch(VBAR1, pg);
         }

         /* draw the bottom row */
         putcur(btm, lft, pg);
         put_ch(LLC11, pg);
         writec(HBAR1, x, pg);
         putcur(btm, rgt, pg);
         put_ch(LRC11, pg);
 }


 DRVPATH.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\DRVPATH.C

 /*
  *        drvpath -- convert a drive name to a full pathname
  */

 #include <stdio.h>
 #include <dos.h>
 #include <string.h>
 #include <ctype.h>
 #include <local\doslib.h>

 char *
 drvpath(path)
 char path[];        /* path string */
                 /* must be large enough to hold a full DOS path + NUL */
 {
         union REGS inregs, outregs;
         static int drive(char);

         /* patch root directory onto drive name */
         strcat(path, "\\");

         /* set current directory path for drive from DOS */
         inregs.h.ah = GET_CUR_DIR;
         inregs.h.dl = drive(path[0]);                /* convert to drive numb
         inregs.x.si = (unsigned)&path[3];        /* start of return string */
         intdos(&inregs, &outregs);

         return (outregs.x.cflag ? (char *)NULL : path);
 }

 static int
 drive(dltr)
 char dltr;        /* drive letter */
 {
         /* 'A' (or 'a') => 1, 'B' (or 'b') => 2, etc. */
         return (tolower(dltr) - 'a' + 1);
 }


 DSPYTYPE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\11SCREEN\DSPYTYPE.C

 /*
  *        dspytype -- determine display adapter type
  */

 #include <stdio.h>
 #include <dos.h>
 #include <local\bioslib.h>
 #include <local\video.h>

 #define MDA_SEG        0xB000
 #define CGA_SEG 0xB800

 main()
 {
         extern int memchk(unsigned int, unsigned int);
         int mdaflag, egaflag, cgaflag;
         int ega_mem, ega_mode;
         unsigned int features, switches;
         static int memtab[] = {
                 64, 128, 192, 256
         };

         mdaflag = egaflag = cgaflag = 0;

         /* look for display adapters */
         if (ega_info(&ega_mem, &ega_mode, &features, &switches))
                 ++egaflag;
         fputs("Enhanced graphics adapter ", stdout);
         if (egaflag) {
                 fputs("installed\n", stdout);
                 fprintf(stdout, "EGA memory size = %d-KB\n", memtab[ega_mem])
                 fprintf(stdout, "EGA is in %s mode\n",
                         ega_mode ? "monochrome" : "color");
         }
         else
                 fputs("not installed\n", stdout);

         if (egaflag && ega_mode == 0) {
                 /* look for IBM monochrome memory */
                 if (memchk(MDA_SEG, 0))
                         ++mdaflag;
         }
         else {
                 /* look for IBM monochrome memory */
                 if (memchk(CGA_SEG, 0))
                         ++cgaflag;
         }
         fputs("Monochrome adapter ", stdout);
         if (mdaflag)
                 fputs("installed\n", stdout);
         else
                 fputs("not installed\n", stdout);
         fputs("Color/graphics adapter ", stdout);
         if (cgaflag)
                 fputs("installed\n", stdout);
         else
                 fputs("not installed\n", stdout);

         /* report video settings */
         getstate();
         fprintf(stdout, "mode=%d width=%d page=%d\n", Vmode, Vwidth, Vpage);

         exit(0);
 }


 DUMP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\10DUMP\DUMP.C

 /*
  *        dump -- display contents of non-ASCII files in hex byte and
  *        ASCII character forms (like the DOS debug dump option)
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <io.h>
 #include <local\std.h>

 #define STDINPUT        0
 #define LINEWIDTH        80

 main(argc,argv)
 int argc;
 char *argv[];
 {
         int ch;
         BOOLEAN        sflag = FALSE,
                 vflag = FALSE,
                 errflag = FALSE;
         int fd;
         static char pgm[MAXNAME + 1] = { "dump" };

         extern int getopt(int, char **, char *);
         extern char *optarg;
         extern int optind, opterr;
         extern void getpname(char *, char *);
         extern int hexdump(int, BOOLEAN);
         extern void fatal(char *, char *, int);

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         while ((ch = getopt(argc, argv, "sv")) != EOF)
                 switch (ch) {
                 case 's': /* strip -- convert all non-ASCII to '.' */
                         sflag = TRUE;
                         break;
                 case 'v': /* verbose -- tell user what's happening */
                         vflag = TRUE;
                         break;
                 case '?': /* bad option */
                         errflag = TRUE;
                         break;
                 }

         if (errflag == TRUE) {
                 fprintf(stderr, "Usage: %s [-sv] [file...]\n", pgm);
                 exit(1);
         }

         if (optind == argc) {
                 if (setmode(STDINPUT, O_BINARY) == -1)
                         fatal(pgm, "Cannot set binary mode", 2);
                 hexdump(STDINPUT, sflag);
                 exit(0);
         }

         for ( ; optind < argc; ++optind) {
                 if ((fd = open(argv[optind], O_BINARY | O_RDONLY)) == -1) {
                         fprintf(stderr,
                                 "%s: Error opening %s -- ", pgm, argv[optind]
                         perror("");
                         continue;
                 }
                 if (vflag == TRUE)
                         fprintf(stdout, "\n%s:\n", argv[optind]);
                 if (hexdump(fd, sflag) == FAILURE) {
                         fprintf(stderr,
                                 "%s: Error reading %s -- ", pgm, argv[optind]
                         perror("");
                 }
                 if (close(fd) == -1)
                         fatal(pgm, "Error closing input file", 3);
         }

         exit(0);
 }


 EGA_INFO.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\EGA_INFO.C

 /*
  *        ega_info -- gather information about an EGA;
  *        return a non-zero value if one is found
  */

 #include <dos.h>
 #include <local\bioslib.h>

 #define EGA_INFO 0x10
 #define NMODES        2
 #define NMEMSIZ        4

 int
 ega_info(memsize, mode, features, switches)
 int *memsize;                /* EGA memory size indicator: 0 = 64K */
                         /* 1 = 128K; 2 = 192K; 3 = 256K */
 int *mode;                /* 0 = color mode; 1 = mono mode */
                         /* use getstate function to find out which mode */
 unsigned int
         *features,        /* feature bit settings */
         *switches;        /* EGA switch settings */
 {
         int result = 0;
         union REGS inregs, outregs;

         /* request EGA information */
         inregs.h.ah = ALT_FUNCTION;
         inregs.h.bl = EGA_INFO;
         int86(VIDEO_IO, &inregs, &outregs);

         *memsize = outregs.h.bl;
         *mode = outregs.h.bh;
         *features = outregs.h.ch;
         *switches = outregs.h.cl;

         /* return non-zero if EGA installed */
         if (*memsize >= 0 && *memsize < NMEMSIZ && *mode >= 0 && *mode < NMOD
                 result = 1;
         return (result);
 }


 EQUIPCHK.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\EQUIPCHK.C

 /*
  *        equipchk -- get equipment list
  */

 #include <dos.h>
 #include <local\bioslib.h>
 #include <local\equip.h>

 struct EQUIP Eq;

 int
 equipchk()
 {
         union REGS inregs, outregs;

         /* call BIOS equipment check routine */
         int86(EQUIP_CK, &inregs, &outregs);

         /* extract data from returned data word */
         Eq.nprint  = (outregs.x.ax & 0xC000) / 0x8000;
         Eq.game_io = ((outregs.x.ax & 0x1000) / 0x1000) ? 1 : 0;
         Eq.nrs232  = (outregs.x.ax & 0x0E00) /0x0200;
         Eq.ndrive  = ((outregs.x.ax & 0x00C0) / 0x0040) + 1;
         Eq.vmode   = (outregs.x.ax & 0x0030) / 0x0010;
         Eq.basemem = ((outregs.x.ax & 0x000C) / 0x0004) + 1;
         Eq.disksys = outregs.x.ax & 0x0001 == 1;

         return (outregs.x.cflag);
 }


 FATAL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\FATAL.C

 /*
  *  fatal -- issue a diagnostic message and terminate
  */

 #include <stdio.h>
 #include <stdlib.h>

 void
 fatal(pname, mesg, errlevel)
 char *pname;        /* program name */
 char *mesg;        /* message text */
 int errlevel;        /* errorlevel (exit code) */
 {
         /* display error message */
         fputs(pname, stderr);
         fputc(':', stderr);
         fputc(' ', stderr);
         fputs(mesg, stderr);

         /* return to DOS with the specified errorlevel */
         exit(errlevel);
 }


 FCONFIG.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\FCONFIG.C

 /*
  *        fconfig -- return a FILE pointer to a local or
  *        global configuration file, or NULL if none found
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <local\std.h>

 FILE *
 fconfig(varname, fname)
 char *varname;
 char *fname;
 {
         FILE *fp;
         char pname[MAXPATH + 1];
         char *p;

         /* look for a local configuration file */
         if ((fp = fopen(fname, "r")) != NULL)
                 return (fp);

         /* look for a directory variable */
         if ((p = getenv(strupr(varname))) != NULL) {
                 strcpy(pname, p);
                 strcat(pname, "\\");
                 strcat(pname, fname);
                 if ((fp = fopen(pname, "r")) != NULL)
                         return (fp);
         }

         /* didn't find anything to read */
         return (NULL);
 }


 FCOPY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\FCOPY.C

 /*
  *        fcopy -- copy input stream (fin) to output stream
  *        (fout) and return an indication of success or failure
  */

 #include <stdio.h>

 #define BUFLEN        1024

 int
 fcopy(fin, fout)
 FILE *fin, *fout;
 {
         int errcount = 0;
         char line[BUFLEN];
         register char *s;

         while ((s = fgets(line, BUFLEN, fin)) != NULL)
                 if (fputs(s, fout) == EOF)
                         ++errcount;
         if (ferror(fin))
                 ++errcount;
         return (errcount);        /* 0 if all went well */
 }


 FIRST_FM.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\FIRST_FM.C

 /*
  *        first_fm - find first file match in work directory
  */

 #include <dos.h>
 #include <local\doslib.h>

 int
 first_fm(path, fa)
 char *path;        /* pathname of directory */
 int fa;                /* attribute(s) of file to match */
 {
         union REGS inregs, outregs;

         /* find first matching file */
         inregs.h.ah = FIND_FIRST;
         inregs.x.cx = fa;
         inregs.x.dx = (unsigned int)path;
         (void)intdos(&inregs, &outregs);

         return (outregs.x.cflag);
 }


 GETCTYPE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\GETCTYPE.C

 /*
  *        getctype -- pass back cursor type info (scan lines)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 #define LO_NIBBLE        0x0F

 int
 getctype(start_scan, end_scan, pg)
 int *start_scan;/* starting scan line */
 int *end_scan;        /* ending scan line */
 int pg;                /* "visual" page */
 {
         union REGS inregs, outregs;

         inregs.h.bh = pg;
         inregs.h.ah = GET_CUR;

         int86(VIDEO_IO, &inregs, &outregs);

         /* end_scan = low 4 bits of cl */
         *end_scan = outregs.h.cl & LO_NIBBLE;

         /* starting_scan = low 4 bits of ah */
         *start_scan = outregs.h.ch & LO_NIBBLE;

         return (outregs.x.cflag);
 }


 GETDRIVE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\GETDRIVE.C

 /*
  *        getdrive -- return the number of the default drive
  */

 #include <dos.h>
 #include <local\doslib.h>

 int getdrive()
 {
         return (bdos(CURRENT_DISK, 0, 0));
 }


 GETKEY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\GETKEY.C

 /*
  *        getkey -- return a code for single combo keystrokes
  *        - returns a unique code for each keystroke or combination
  *        - ignores "Ctrl-Break" input
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\doslib.h>
 #include <local\keydefs.h>

 int
 getkey()
 {
         int ch;

         /* normal key codes */
         if ((ch = bdos(KEYIN, 0, 0) & LOBYTE) != '\0')
                 return (ch);

         /* convert scan codes to unique internal codes */
         return ((bdos(KEYIN, 0, 0) & LOBYTE) | XF);
 }


 GETNAME.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\GETNAME.C

 /*
  *        getname -- strip drive identifier and directory node
  *        list, if any, from a pathname;  returns a pointer to
  *        the resulting filename[.ext] string or NULL for error
  */

 #include <stdio.h>
 #include <sys\types.h>
 #include <sys\stat.h>

 #define MAXFSPEC 13

 char *
 getname(path)
 char *path;        /* string to modify */
 {
         register char *cp;        /* character pointer */
         struct stat buf;

         /* try to get information about the pathname */
         if (stat(path, &buf) != 0)
                 return (NULL);        /* bad pathname */

         /* locate the end of the pathname string */
         cp = path;
         while (*cp != '\0')
                 ++cp;
         --cp;                /* went one too far */

         /* find the start of the filename part */
         while (cp > path && *cp != '\\' && *cp != ':' && *cp != '/')
                 --cp;
         if (cp > path)
                 ++cp;        /* on a separator (\, :, or /) -- move one past

         /* return the full filespec (filename[.ext]) */
         return (cp);
 }


 GETOPT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\GETOPT.C

 /*
  *      Copyright (c) 1984, 1985 AT&T
  *      All Rights Reserved
  *
  *      ----- Author's Note -----
  *      getopt() is reproduced with permission of the AT&T UNIX(R) System
  *      Toolchest. This is a public domain version of getopt(3) that is
  *      distributed to registered Toolchest participants.
  *      Defining DOS_MODS alters the code slightly to obtain compatibility
  *      with DOS and support libraries provided with most DOS C compilers.
  */

 #define DOS_MODS

 #if defined (DOS_MODS)
         /* getopt() for DOS */
 #else
 #ident  "@(#)getopt.c   1.9"
 #endif

 /*      3.0 SID #       1.2     */
 /*LINTLIBRARY*/
 #define NULL    0
 #define EOF     (-1)

 /*
  *      For this to work under versions of DOS prior to 3.00, argv[0]
  *      must be set in main() to point to a valid program name or a
  *      reasonable substitute string.   (ARH, 10-8-86)
  */
 #define ERR(s, c)       if(opterr){\
         char errbuf[2];\
         errbuf[0] = c; errbuf[1] = '\n';\
         (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
         (void) write(2, s, (unsigned)strlen(s));\
         (void) write(2, errbuf, 2);}

 #if defined (DOS_MODS)
 /* permit function prototyping under DOS */
 #include <stdlib.h>
 #include <string.h>
 #else
 /* standard UNIX declarations */
 extern int strcmp();
 extern char *strchr();
 /*
  *      The following line was moved here from the ERR definition
  *      to prevent a "duplicate definition" error message when the
  *      code is compiled under DOS.  (ARH, 10-8-86)
  */
 extern int strlen(), write();
 #endif

 int     opterr = 1;
 int     optind = 1;
 int     optopt;
 char    *optarg;

 int
 getopt(argc, argv, opts)
 int     argc;
 char    **argv, *opts;
 {
         static int sp = 1;
         register int c;
         register char *cp;

         if(sp == 1)
                 if(optind >= argc ||
                    argv[optind][0] != '-' || argv[optind][1] == '\0')
                         return(EOF);
                 else if(strcmp(argv[optind], "--") == NULL) {
                         optind++;
                         return(EOF);
                 }
         optopt = c = argv[optind][sp];
         if(c == ':' || (cp=strchr(opts, c)) == NULL) {
                 ERR(": illegal option -- ", c);
                 if(argv[optind][++sp] == '\0') {
                         optind++;
                         sp = 1;
                 }
                 return('?');
         }
         if(*++cp == ':') {
                 if(argv[optind][sp+1] != '\0')
                         optarg = &argv[optind++][sp+1];
                 else if(++optind >= argc) {
                         ERR(": option requires an argument -- ", c);
                         sp = 1;
                         return('?');
                 } else
                         optarg = argv[optind++];
                 sp = 1;
         } else {
                 if(argv[optind][++sp] == '\0') {
                         sp = 1;
                         optind++;
                 }
                 optarg = NULL;
         }
         return(c);
 }


 GETPNAME.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\GETPNAME.C

 /*
  *        getpname -- extract the base name of a program from
  *        the pathname string (deletes a drive specifier, any
  *        leading path node information, and the extension)
  */

 #include <stdio.h>
 #include <ctype.h>

 char *
 getpname(path, pname)
 char *path;        /* full or relative pathname */
 char *pname;        /* program name pointer */
 {
         register char *cp;

         /* find the end of the pathname string */
         cp = path;         /* start of pathname */
         while (*cp != '\0')
                 ++cp;
         --cp;                /* went one too far */

         /* find the start of the filename part */
         while (cp > path && *cp != '\\' && *cp != ':' && *cp != '/')
                 --cp;
         if (cp > path)
                 ++cp;        /* move off the pathname separator */

         /* copy the filename part only */
         while ((*pname = tolower(*cp)) != '.' && *pname != '\0') {
                 ++cp;
                 ++pname;
         }
         *pname = '\0';
 }


 GETREPLY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\GETREPLY.C

 /*
  *        getreply -- display a message and wait for a reply
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>
 #include <ctype.h>
 #include <local\std.h>
 #include <local\keydefs.h>
 #include "linebuf.h"

 char *
 getreply(row, col, width, mesg, lp, size, attr, pg)
 short row, col, width;        /* window location and width */
 char *mesg;                /* message text */
 LINEBUF *lp;                /* line pointer */
 short size;                /* size of line buffer */
 short attr;                /* video attribute for response field */
 short pg;                /* active display page */
 {
         int n, k, len;
         short mfw;        /* message field width */
         short rfw;        /* response field width */
         short ccol;        /* visible cursor column */
         int msgflag;        /* non-zero after a message is displayed */
         char *cp;        /* character pointer */
         char *wp;        /* pointer to window start */
         char *tmp;        /* temporary char pointer */

         extern int writemsg(short, short, short, char *, char *, short);

         /* display the prompt string and calculate response field width */
         putcur(row, col, pg);
         mfw = writemsg(row, col, width, mesg, NULL, pg);
         rfw = width - mfw;
         writea(attr, rfw, pg);

         /* collect the user's response */
         memset(lp->l_buf, '\0', size);
         wp = cp = lp->l_buf;
         putcur(row, col + mfw, pg);
         msgflag = 0;
         while ((k = getkey()) != K_RETURN) {
                 if (msgflag) {
                         /* clear old messages */
                         errmsg("");
                         putcur(row, ccol, pg);
                         msgflag = 0;
                 }
                 if (isascii(k) && isprint(k)) {
                         len = strlen(cp);
                         if (cp + len - lp->l_buf < size - 1) {
                                 memcpy(cp + 1, cp, len);
                                 *cp = k;
                                 ++cp;
                         }
                         else {
                                 errmsg("input buffer full");
                                 ++msgflag;
                         }
                 }
                 else
                         switch (k) {
                         case K_LEFT:
                                 /* move left one character */
                                 if (cp > lp->l_buf)
                                         --cp;
                                 break;
                         case K_RIGHT:
                                 /* move right one character */
                                 if (*cp != '\0')
                                         ++cp;
                                 break;
                         case K_UP:
                                 /* pop a line off the stack */
                                 if (lp->l_prev != NULL) {
                                         lp = lp->l_prev;
                                         wp = cp = lp->l_buf;
                                 }
                                 break;
                         case K_DOWN:
                                 /* push a line onto the stack */
                                 if (lp->l_next != NULL) {
                                         lp = lp->l_next;
                                         wp = cp = lp->l_buf;
                                 }
                                 break;
                         case K_HOME:
                                 /* beginning of buffer */
                                 cp = lp->l_buf;
                                 break;
                         case K_END:
                                 /* end of buffer */
                                 while (*cp != '\0')
                                         ++cp;
                                 break;
                         case K_CTRLH:
                                 if (cp > lp->l_buf) {
                                         tmp = cp - 1;
                                         memcpy(tmp, cp, strlen(tmp));
                                         --cp;
                                 }
                                 break;
                         case K_DEL:
                                 /* delete character at cursor */
                                 memcpy(cp, cp + 1, strlen(cp));
                                 break;
                         case K_ESC:
                                 /* cancel current input */
                                 lp->l_buf[0] = '\0';
                                 putcur(row, col, pg);
                                 writec(' ', width, pg);
                                 return (NULL);
                         default:
                                 errmsg("unknown command");
                                 ++msgflag;
                                 break;
                         }

                 /* adjust the window pointer if necessary */
                 if (cp < wp)
                         wp = cp;
                 else if (cp >= wp + rfw)
                         wp = cp + 1 - rfw;

                 /* display the reply window */
                 ccol = col + mfw;
                 writemsg(row, ccol, rfw, wp, NULL, pg);

                 /* reposition the cursor */
                 ccol = col + mfw + (cp - wp);
                 putcur(row, ccol, pg);
         }
         putcur(row, col, pg);
         writec(' ', width, pg);        /* blank message area */
         return (lp->l_buf);
 }


 GETSTATE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\GETSTATE.C

 /*
  *        getstate -- update video state structure
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 /* current video state/mode information */
 short Vmode;
 short Vwidth;
 short Vpage;

 /*
  *        video tables -- these tables of video parameters use
  *        a value of -1 to indicate that an item is not supported
  *        and 0 to indicate that an item has a variable value.
  */

 /* video limit tables */
 short Maxrow[] = {
         /* CGA modes */
         25, 25, 25, 25, 25, 25, 25,
         /* MDA mode */
         25,
         /* PCjr modes */
         25, 25, 25,
         /* not used */
         -1, -1,
         /* EGA modes */
         25, 25, 25, 25, 43
 };

 short Maxcol[] = {
         /* CGA modes */
         40, 40, 80, 80, 40, 40, 80,
         /* MDA mode */
         80,
         /* PCjr modes */
         -1, 40, 80,
         /* not used */
         -1, -1,
         /* EGA modes */
         80, 80, 80, 80
 };

 short Maxpage[] = {
         /* CGA modes */
         8, 8, 4, 4, 1, 1, 1,
         /* MDA mode */
         1,
         /* PCjr modes */
         0, 0, 0,
         /* not used */
         -1, -1,
         /* EGA modes */
         8, 4, 1, 1
 };

 int
 getstate()
 {
         union REGS inregs, outregs;

         inregs.h.ah = GET_STATE;
         int86(VIDEO_IO, &inregs, &outregs);

         Vmode = outregs.h.al;
         Vwidth = outregs.h.ah;
         Vpage = outregs.h.bh;

         return (outregs.x.cflag);
 }


 GETSTR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\GETSTR.C

 /*
  *        getstr -- get a string from the keyboard
  */

 #include <stdio.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\video.h>
 #include <local\keydefs.h>

 char *
 getstr(buf, width)
 char *buf;
 int width;
 {
         int row, col;
         char *cp;

         /* function prototypes */
         extern int putcur(int, int, int);
         extern int readcur(int *, int *, int);
         extern int writec(char, int, int);
         extern int getkey();

         /* gather keyboard input into a string buffer */
         cp = buf;
         while ((*cp = getkey()) != K_RETURN && cp - buf < width) {
                 switch (*cp) {
                 case K_CTRLH:
                         /* destructive backspace */
                         if (cp > buf) {
                                 readcur(&row, &col, Vpage);
                                 putcur(row, col - 1, Vpage);
                                 writec(' ', 1, Vpage);
                                 --cp;
                         }
                         continue;
                 case K_ESC:
                         /* cancel string input operation */
                         return (char *)NULL;
                 }
                 put_ch(*cp, Vpage);
                 ++cp;
         }
         *cp = '\0';
         return (buf);
 }


 GETTICKS.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\GETTICKS.C

 /*
  *        getticks -- get the current bios clock ticks value
  */

 #include <dos.h>
 #include <local\bioslib.h>

 long
 getticks()
 {
         long count;
         union REGS inregs, outregs;

         /* get BIOS time of day as no. of ticks since midnight */
         inregs.h.ah = 0;
         int86(TOD, &inregs, &outregs);

         /* correct for possible rollover at 24 hours */
         count = (outregs.h.al != 0) ? 0x01800B0L : 0;

         /* add current day ticks */
         count += (outregs.x.dx + (outregs.x.cx << 16));

         return (count);
 }


 GETXLINE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\GETXLINE.C

 /*
  *        getxline -- get a line of text while expanding tabs,
  *        put text into an array, and return a pointer to the
  *        resulting null-terminated line
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <local\std.h>

 char *
 getxline(buf, size, fin)
 char *buf;
 int size;
 FILE *fin;
 {
         register int ch;        /* input character */
         register char *cp;        /* character pointer */

         extern BOOLEAN tabstop(int);

         cp = buf;
         while (--size > 0 && (ch = fgetc(fin)) != EOF) {
                 if (ch == '\n') {
                         *cp++ = ch;
                         break;
                 }
                 else if (ch == '\t')
                         do {
                                 *cp = ' ';
                         } while (--size > 0 && (tabstop(++cp - buf) == FALSE)
                 else
                         *cp++ = ch & ASCII;
         }
         *cp = '\0';
         return ((ch == EOF && cp == buf) ? NULL : buf);
 }


 HEX.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\HEX.C

 /*
  *        hex.c -- hex conversions routines
  */

 #define NIBBLE        0x000F

 char hextab[] = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
 };

 /*
  *        byte2hex -- convert a byte to a string
  *        representation of its hexadecimal value
  */

 char *
 byte2hex(data, buf)
 unsigned char data;
 char *buf;
 {
         register char *cp;

         cp = buf;
         *cp++ = hextab[(data >> 4) & NIBBLE];
         *cp++ = hextab[data & NIBBLE];
         *cp = '\0';

         return (buf);
 } /* end byte2hex() */

 /*
  *        word2hex -- convert a word to a string
  *        representation of its hexadecimal value
  */

 char *
 word2hex(data, buf)
 unsigned int data;
 char *buf;
 {
         register char *cp;

         cp = buf;
         *cp++ = hextab[(data >> 12) & NIBBLE];
         *cp++ = hextab[(data >> 8) & NIBBLE];
         *cp++ = hextab[(data >> 4) & NIBBLE];
         *cp++ = hextab[data & NIBBLE];
         *cp = '\0';

         return (buf);
 } /* end word2hex() */


 HEX.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\10DUMP\HEX.C

 /*
  *        hex.c -- hex conversions routines
  */

 #define NIBBLE        0x000F
 #define BYTE        0x00FF
 #define WORD        0xFFFF

 char hextab[] = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
 };

 /*
  *        byte2hex -- convert a byte to a string
  *        representation of its hexadecimal value
  */

 char *
 byte2hex(data, buf)
 unsigned char data;
 char *buf;
 {
         char *cp;
         unsigned int d;

         d = data & BYTE;
         cp = buf;
         *cp++ = hextab[(d >> 4) & NIBBLE];
         *cp++ = hextab[d & NIBBLE];
         *cp = '\0';

         return (buf);
 }

 /*
  *        word2hex -- convert a word to a string
  *        representation of its hexadecimal value
  */

 char *
 word2hex(data, buf)
 unsigned int data;
 char *buf;
 {
         char *cp;
         unsigned int d;

         d = data & WORD;
         cp = buf;
         *cp++ = hextab[(d >> 12) & NIBBLE];
         *cp++ = hextab[(d >> 8) & NIBBLE];
         *cp++ = hextab[(d >> 4) & NIBBLE];
         *cp++ = hextab[d & NIBBLE];
         *cp = '\0';

         return (buf);
 }


 HEXDUMP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\10DUMP\HEXDUMP.C

 /*
  *        hexdump -- read data from an open file and "dump"
  *        it in side-by-side hex and ASCII to standard output
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <local\std.h>

 #define LINEWIDTH        80
 #define NBYTES                16
 #define WORD                0xFFFF
 #define RGHTMARK        179
 #define LEFTMARK        179
 #define DEL                0x7F

 int hexdump(fd, strip)
 int fd;
 BOOLEAN strip;
 {
         unsigned char i;
         int n;                        /* bytes per read operation */
         unsigned long offset;        /* bytes from start of file */
         char inbuf[BUFSIZ + 1], outbuf[LINEWIDTH + 1];
         char hexbuf[5];
         register char *inp, *outp;

         extern char *byte2hex(unsigned char, char *);
         extern char *word2hex(unsigned int, char *);

         offset = 0;
         while ((n = read(fd, inbuf, BUFSIZ)) != 0) {
                 if (n == -1)
                         return FAILURE;
                 inp = inbuf;
                 while (inp < inbuf + n) {
                         outp = outbuf;

                         /* offset in hex */
                         outp += sprintf(outp, "%08lX",
                                 offset + (unsigned long)(inp - inbuf));
                         *outp++ = ' ';

                         /* block of bytes in hex */
                         for (i = 0; i < NBYTES; ++i) {
                                 *outp++ = ' ';
                                 strcpy(outp, byte2hex(*inp++, hexbuf));
                                 outp += 2;
                         }
                         *outp++ = ' ';
                         *outp++ = ' ';
                         *outp++ = (strip == TRUE) ? '|' : LEFTMARK;

                         /* same block of bytes in ASCII */
                         inp -= NBYTES;
                         for (i = 0; i < NBYTES; ++i) {
                                 if (strip == TRUE && (*inp < ' ' || *inp >= D
                                         *outp = '.';
                                 else if (iscntrl(*inp))
                                         *outp = '.';
                                 else
                                         *outp = *inp;
                                 ++inp;
                                 ++outp;
                         }
                         *outp++ = (strip == TRUE) ? '|' : RGHTMARK;
                         *outp++ = '\n';
                         *outp = '\0';
                         fputs(outbuf, stdout);
                 }
                 offset += n;
         }
         return SUCCESS;
 }


 INTERVAL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\INTERVAL.C

 /*
  *        interval -- report the interval given in seconds as
  *        a human-readable null-terminated string
  */

 #include <stdio.h>

 char *
 interval(seconds, buf)
 long seconds;
 char *buf;
 {
         int hh, mm, ss;
         long remainder;

         /* calculate the values */
         hh = seconds / 3600;
         remainder = seconds % 3600;
         mm = remainder / 60;
         ss = remainder - (mm * 60);
         sprintf(buf, "%02d:%02d:%02d\0", hh, mm, ss);

         return (buf);
 }


 ISCOLOR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\ISCOLOR.C

 /*
  *        iscolor -- return TRUE if a color display system is
  *        in use and is set to one of the text modes
  */

 #include <local\std.h>
 #include <local\video.h>

 BOOLEAN
 iscolor()
 {
         getstate();
         if (Vmode != CGA_C40 || Vmode != CGA_C80)
                 return TRUE;
         return FALSE;
 }


 KBD_STAT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\KBD_STAT.C

 /*
  *        kbd_stat -- return the keyboard status
  *        word (bit-significant)
  */

 #include <dos.h>
 #include <local\bioslib.h>
 #include <local\keybdlib.h>

 unsigned char
 kbd_stat()
 {
         union REGS inregs, outregs;

         inregs.h.ah = KBD_STATUS;
         int86(KEYBD_IO, &inregs, &outregs);

         return ((unsigned char)(outregs.h.al));
 }


 KEYREADY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\KEYREADY.C

 /*
  *        keyready -- non-zero if the keyboard buffer
  *        has any codes waiting
  */

 #include <dos.h>
 #include <local\doslib.h>

 int
 keyready()
 {
         union REGS inregs, outregs;

         inregs.h.ah = CH_READY;
         intdos(&inregs, &outregs);

         return (outregs.h.al);
 }


 LAST_CH.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\LAST_CH.C

 /*
  *        last_ch -- return a copy of the last character
  *        before the NUL byte in a string
  */

 char
 last_ch(s)
 char *s;
 {
         register char *cp;

         /* find end of s */
         cp = s;
         while (*cp != '\0')
                 ++cp;

         /* return previous character */
         --cp;
         return (*cp);
 }


 LINES.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\LINES.C

 /*
  *        lines -- send newlines to the output stream
  */

 #include <stdio.h>
 #include <stdlib.h>

 int
 lines(n, fp)
 int n;
 FILE *fp;
 {
         register int i;

         for (i = 0; i < n; ++i)
                 if (putc('\n', fp) == EOF && ferror(fp))
                         break;

         /* return number of newlines emitted */
         return (i);
 }


 LS.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\LS.C

 /*
  *        ls -- display a directory listing
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <memory.h>
 #include <dos.h>
 #include <direct.h>
 #include <signal.h>
 #include <search.h>
 #include <local\std.h>
 #include <local\doslib.h>
 #include "ls.h"

 /* allocation quantities */
 #define N_FILES        256
 #define N_DIRS        16

 /* global data */
 int Multicol = 0;
 int Filetype = 0;
 int Hidden = 0;
 int Longlist = 0;
 int Reverse = 0;
 int Modtime = 0;

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int ch, i;
         int errflag;                /* error flag */
         char *ep;                /* environment pointer */
         int status = 0;                /* return status value */
         int fileattr;                /* file attribute number */
         struct DTA buf;                /* private disk buffer */
         char path[MAXPATH + 1];        /* working pathname */
         struct OUTBUF *fp, *fq;        /* pointers to file array */
         char **dp, **dq;        /* pointer to directory pointer array */
         int fbc = 1;                /* file memory block allocation count */
         int dbc = 1;                /* directory memory block allocation coun
         int nfiles;                /* number of file elements */
         int ndirs;                /* number of directory elements */

         static char pgm[MAXNAME + 1] = { "ls" };

         /* function prototypes */
         void getpname(char *, char *);
         extern int getopt(int, char **, char *);
         extern int optind, opterr;
         extern char *optarg;
         extern char *drvpath(char *);
         extern void fatal(char *, char *, int);
         extern void setdta(char *);
         extern int first_fm(char *, int);
         extern int next_fm();
         extern int ls_fcomp(struct OUTBUF *, struct OUTBUF *);
         extern int ls_dcomp(char *, char *);
         extern int ls_single(struct OUTBUF *, int);
         extern int ls_multi(struct OUTBUF *, int);
         extern int ls_dirx(char *, char *);
         int bailout();

         /* guarantee that needed DOS services are available */
         if (_osmajor < 2)
                 fatal(pgm, "ls requires DOS 2.00 or later", 1);

         /* get program name from DOS (version 3.00 and later) */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* useful aliases (DOS version 3.00 and later) */
         if (strcmp(pgm, "lc") == 0)
                 ++Multicol;
         if (strcmp(pgm, "lf") == 0) {
                 ++Multicol;
                 ++Filetype;
         }

         /* prepare for emergencies */
         if (signal(SIGINT, bailout) == (int(*)())-1) {
                 perror("Can't set SIGINT");
                 exit(2);
         }

         /* process optional arguments first */
         errflag = 0;
         while ((ch = getopt(argc, argv, "aCFlrt")) != EOF)
                 switch (ch) {
                 case 'a':
                         /* all files (hidden, system, etc.) */
                         ++Hidden;
                         break;
                 case 'C':
                         ++Multicol;
                         break;
                 case 'F':
                         /* show file types (/=directory, *=executable) */
                         ++Filetype;
                         break;
                 case 'l':
                         /* long list (overrides multicolumn) */
                         ++Longlist;
                         break;
                 case 'r':
                         /* reverse sort */
                         ++Reverse;
                         break;
                 case 't':
                         /* sort by file modification time */
                         ++Modtime;
                         break;
                 case '?':
                         errflag = TRUE;
                         break;
                 }
         argc -= optind;
         argv += optind;

         /* check for command-line errors */
         if (argc < 0 || errflag) {
                 fprintf(stderr, "Usage: %s [-aCFlrt] [pathname ...]", pgm);
                 exit(3);
         }

         /* allocate initial file and directory storage areas */
         dp = dq = (char **)malloc(N_DIRS * sizeof (char *));
         if (dp == NULL)
                 fatal(pgm, "Out of memory", 4);
         fp = fq = (struct OUTBUF *)malloc(N_FILES * sizeof (struct OUTBUF));
         if (fp == NULL)
                 fatal(pgm, "Out of memory", 4);
         nfiles = ndirs = 0;

         /* use current directory if no args */
         if (argc == 0) {
                 if (getcwd(path, MAXPATH) == NULL)
                         fatal(pgm, "Cannot get current directory", 5);
                 *dq = path;
                 ndirs = 1;
         }
         else {
                 /* use arguments as file and directory names */
                 for ( ; argc-- > 0; ++argv) {
                         strcpy(path, *argv);
                         if (path[0] == '\\') {
                                 /* prepend default drive name */
                                 memcpy(path + 2, path, strlen(path) + 1);
                                 path[0] = 'a' + getdrive();
                                 path[1] = ':';
                         }
                         if (path[1] == ':' && path[2] == '\0' && drvpath(path
                                 fprintf(stderr, "%s: Cannot get drive path",
                                 continue;
                         }

                         /* establish private disk transfer area */
                         setdta((char *)&buf);

                         /* set file attribute for search */
                         if (Hidden)
                                 fileattr = SUBDIR | HIDDEN | SYSTEM | READONL
                         else
                                 fileattr = SUBDIR;
                         if (first_fm(path, fileattr) != 0 && path[3] != '\0')
                                 fprintf(stderr, "%s -- No such file or direct
                                 continue;
                         }
                         if ((buf.d_attr & SUBDIR) == SUBDIR || path[3] == '\0
                                 /* path is a (sub)directory */
                                 *dq = strdup(path);
                                 if (++ndirs == dbc * N_DIRS) {
                                         ++dbc;        /* increase space requi
                                         dp = (char **)realloc(dp, dbc * N_DIR
                                         if (dp == NULL)
                                                 fatal(pgm, "Out of memory", 4
                                         dq = dp + dbc * N_DIRS;
                                 }
                                 else
                                         ++dq;
                         }
                         else {
                                 fq->o_name = strdup(path);
                                 fq->o_mode = buf.d_attr;
                                 fq->o_date = buf.d_mdate;
                                 fq->o_time = buf.d_mtime;
                                 fq->o_size = buf.d_fsize;
                                 if (++nfiles == fbc * N_FILES) {
                                         ++fbc;
                                         fp = (struct OUTBUF *)realloc(fp, fbc
                                         if (fp == NULL)
                                                 fatal(pgm, "Out of memory", 4
                                         fq = fp + fbc * N_FILES;
                                 }
                                 else
                                         ++fq;
                         }
                 }
         }

         /* output file list, if any */
         if (nfiles > 0) {
                 qsort(fp, nfiles, sizeof(struct OUTBUF), ls_fcomp);
                 if (Longlist)
                         ls_long(fp, nfiles);
                 else if (Multicol)
                         ls_multi(fp, nfiles);
                 else
                         ls_single(fp, nfiles);
                 putchar('\n');
         }
         free(fp);

         /* output directory lists, if any */
         if (ndirs == 1 && nfiles == 0) {
                 /* expand directory and output without header */
                 if (ls_dirx(pgm, *dp))
                         fprintf(stderr, "%s -- empty directory\n", strlwr(*dp
         }
         else if (ndirs > 0) {
                 /* expand each directory and output with headers */
                 dq = dp;
                 qsort(dp, ndirs, sizeof(char *), ls_dcomp);
                 while (ndirs-- > 0) {
                         fprintf(stdout, "%s:\n", strlwr(*dq));
                         if (ls_dirx(pgm, *dq++))
                                 fprintf(stderr, "%s -- empty directory\n",
                                         strlwr(*dq));
                         putchar('\n');
                 }
         }

         exit(0);
 }

 /*
  *        bailout -- optionally terminate upon interrupt
  */
 int
 bailout()
 {
         char ch;

         signal(SIGINT, bailout);
         printf("\nTerminate directory listing? ");
         scanf("%1s", &ch);
         if (ch == 'y' || ch == 'Y')
                 exit(1);
 }


 LS_DIRX.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\LS_DIRX.C

 /*
  *        ls_dirx -- expand the contents of a directory using
  *        the DOS first/next matching file functions
  */

 #define DEBUG

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <malloc.h>
 #include <dos.h>
 #include <direct.h>
 #include <signal.h>
 #include <search.h>
 #include <local\std.h>
 #include <local\doslib.h>
 #include "ls.h"

 #define NFILES        1024

 extern int Recursive;
 extern int Longlist;
 extern int Multicol;
 extern int Hidden;

 int
 ls_dirx(pname, namep)
 char *pname;
 char *namep;
 {
         int status = 0;                        /* function return value */
         int n;                                /* number of items found */
         int fileattr;                        /* attributes of file-matching *
         struct DTA buf;                        /* disk transfer area */
         struct OUTBUF *bp, *bq;                /* output buffer pointers */
         char path[MAXPATH + 1];                /* working path string */

         extern void setdta(char *);
         extern int first_fm(char *, int);
         extern int next_fm();
         extern int ls_fcomp(struct OUTBUF *, struct OUTBUF *);
         extern char last_ch(char *);

         /* allocate a buffer */
         bp = bq = (struct OUTBUF *)malloc(NFILES * sizeof(struct OUTBUF));
         if (bp == NULL)
                 fatal(pname, "Out of memory");

         /* form name for directory search */
         strcpy(path, namep);
         if (last_ch(path) != '\\')
                 strcat(path, "\\");
         strcat(path, "*.*");

         /* list the files found */
         n = 0;
         /* establish a private DTA */
         setdta((char *)&buf);
         /* select file attributes */
         if (Hidden)
                 fileattr = SUBDIR | HIDDEN | SYSTEM | READONLY;
         else
                 fileattr = SUBDIR;
         if (first_fm(path, fileattr) == 0) {
                 /* add file or directory to the buffer */
                 do {
                         if (!Hidden && buf.d_fname[0] == '.')
                                 continue;
                         bq->o_name = strdup(buf.d_fname);
                         bq->o_mode = buf.d_attr;
                         bq->o_size = buf.d_fsize;
                         bq->o_date = buf.d_mdate;
                         bq->o_time = buf.d_mtime;
                         ++bq;
                         ++n;
                         setdta((char *)&buf);        /* reset to our DTA */
                 } while (next_fm() == 0);

                 if (n > 0) {
                         /* got some -- sort and list them */
                         qsort(bp, n, sizeof(struct OUTBUF), ls_fcomp);
                         if (Longlist)
                                 ls_long(bp, n);
                         else if (Multicol)
                                 ls_multi(bp, n);
                         else
                                 ls_single(bp, n);
                 }
         }
         else
                 ++status;
         free(bp);

         return (status);
 }


 LS_FCOMP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\LS_FCOMP.C

 /*
  *        ls_fcomp -- file and directory comparison functions
  */

 #include <string.h>
 #include "ls.h"

 extern int Modtime;
 extern int Reverse;


 /*
  *        ls_fcomp -- compare two "file" items
  */

 int
 ls_fcomp(s1, s2)
 struct OUTBUF *s1, *s2;
 {
         int result;

         if (Modtime) {
                 if ((result = s1->o_date - s2->o_date) == 0)
                         result = s1->o_time - s2->o_time;
         }
         else
                 result = strcmp(s1->o_name, s2->o_name);

         return (Reverse ? -result : result);
 } /* end_fcomp() */


 /*
  *        dcomp -- compare two "directory" items
  */

 int
 ls_dcomp(s1, s2)
 char *s1, *s2;
 {
         int result;

         result = strcmp(s1, s2);

         return (Reverse ? -result : result);
 } /* end ls_dcomp() */


 LS_LIST.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\LS_LIST.C

 /*
  *        ls_list -- list functions (long, single, multi) for ls
  */

 #include <stdio.h>
 #include <string.h>
 #include "ls.h"

 #define MAXCOL                80
 #define MONTH_SHIFT        5
 #define MONTH_MASK        0x0F
 #define DAY_MASK        0x1F
 #define YEAR_SHIFT        9
 #define DOS_EPOCH        80
 #define HOUR_SHIFT        11
 #define HOUR_MASK        0x1F
 #define MINUTE_SHIFT        5
 #define MINUTE_MASK        0x3F

 extern int Filetype;

 /*
  *        ls_long -- list items in "long" format (mode time size name)
  */

 int
 ls_long(buf, nelem)
 struct OUTBUF *buf;
 int nelem;
 {
         int n = 0;
         char modebuf[5];
         static void modestr(unsigned short, char *);

         while (nelem-- > 0) {
                 /* convert mode number to a string */
                 modestr(buf->o_mode, modebuf);
                 printf("%s ", modebuf);

                 /* display file size in bytes */
                 if ((buf->o_mode & SUBDIR) == SUBDIR)
                         printf("        ");
                 else
                         printf("%7ld ", buf->o_size);

                 /* convert date and time values to formatted presentation */
                 printf("%02d-%02d-%02d ", (buf->o_date >> MONTH_SHIFT) & MONT
                         buf->o_date & DAY_MASK, (buf->o_date >> YEAR_SHIFT) +
                 printf("%02d:%02d ", (buf->o_time >> HOUR_SHIFT) & HOUR_MASK,
                         (buf->o_time >> MINUTE_SHIFT) & MINUTE_MASK);

                 /* display filenames as lowercase strings */
                 printf("%s\n", strlwr(buf->o_name));

                 ++buf;
                 ++n;
         }

         /* tell caller how many entries were printed */
         return (n);
 } /* end ls_long() */


 /*
  *        ls_single -- list items in a single column
  */

 int
 ls_single(buf, nelem)
 struct OUTBUF *buf;
 int nelem;
 {
         int n = 0;

         while (nelem-- > 0) {
                 printf("%s", strlwr(buf->o_name));
                 if (Filetype && (buf->o_mode & SUBDIR) == SUBDIR)
                         putchar('\\');
                 putchar('\n');
                 ++buf;
                 ++n;
         }

         /* tell caller how many entries were printed */
         return (n);
 } /* end ls_single() */


 /*
  *        ls_multi -- list items in multiple columns that
  *        vary in width and number based on longest item size
  */

 int
 ls_multi(buf, nelem)
 struct OUTBUF *buf;
 int nelem;
 {
         int i, j;
         int errcount = 0;
         struct OUTBUF *tmp;        /* temporary buffer pointer */
         struct OUTBUF *base;        /* buffer pointer for multi-col output */
         int n;                        /* number of items in list */
         int len, maxlen;        /* pathname lengths */
         int ncols;                /* number of columns to output */
         int nlines;                /* number of lines to output */

         /*
          *  get length of longest pathname and calculate number
          *  of columns and lines (col width = maxlen + 1)
          */
         tmp = buf;
         n = 0;
         maxlen = 0;
         for (tmp = buf, n = 0; n < nelem; ++tmp, ++n)
                 if ((len = strlen(tmp->o_name)) > maxlen)
                         maxlen = len;
         /*
          *  use width of screen - 1 to allow for newline at end of
          *  line and leave two spaces between entries (one for optional
          *  file type flag)
          */
         ncols = (MAXCOL - 1) / (maxlen + 2);
         nlines = n / ncols;
         if (n % ncols)
                 ++nlines;

         /* output multi-column list */
         base = buf;
         for (i = 0; i < nlines; ++i) {
                 tmp = base;
                 for (j = 0; j < ncols; ++j) {
                         len = maxlen + 2;
                         len -= printf("%s", strlwr(tmp->o_name));
                         if (Filetype && (tmp->o_mode & SUBDIR) == SUBDIR) {
                                 putchar('\\');
                                 --len;
                         }
                         while (len-- > 0)
                                 putchar(' ');
                         tmp += nlines;
                         if (tmp - buf >= nelem)
                                 break;
                 }
                 putchar('\n');
                 ++base;
         }

         return (errcount);
 } /* end ls_multi() */


 static void
 modestr(mode, s)
 unsigned short mode;        /* file mode number */
 char s[];                /* mode string buffer */
 {

         /* fill in the mode string to show what's set */
         s[0] = (mode & SUBDIR) == SUBDIR ? 'd' : '-';
         s[1] = (mode & HIDDEN) == HIDDEN ? 'h' : '-';
         s[2] = (mode & SYSTEM) == SYSTEM ? 's' : '-';
         s[3] = (mode & READONLY) == READONLY ? 'r' : '-';
         s[4] = '\0';
 } /* end modestr() */


 MEMCHK.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\MEMCHK.C

 /*
  *        memchk -- look for random-access memory at
  *        a specified location; return non-zero if found
  */

 #include <dos.h>
 #include <memory.h>

 int
 memchk(seg, os)
 unsigned int seg;
 unsigned int os;
 {
         unsigned char tstval, oldval, newval;
         unsigned int ds;
         struct SREGS segregs;

         /* get value of current data segment */
         segread(&segregs);
         ds = segregs.ds;

         /* save current contents of test location */
         movedata(seg, os, ds, (unsigned int)&oldval, 1);

         /* copy a known value into test location */
         tstval = 0xFC;
         movedata(ds, (unsigned int)&tstval, seg, os, 1);

         /* read test value back and comapre to value written */
         movedata(seg, os, ds, (unsigned int)&newval, 1);
         if (newval != tstval)
                 return (0);

         /* restore original contents of test location */
         movedata(ds, (unsigned int)&oldval, seg, os, 1);

         return (1);
 }


 MEMSIZE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\MEMSIZE.C

 /*
  *        memsize -- get memory size
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 memsize()
 {
         union REGS inregs, outregs;

         return (int86(MEM_SIZE, &inregs, &outregs));
 }


 MENUMODE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\MENUMODE.C

 /*
  *  menumode -- process user commands interactively
  */

 #include <stdio.h>
 #include <local\ansi.h>
 #include <local\ibmcolor.h>
 #include <local\keydefs.h>

 /* maximum color number */
 #define MAX_CNUM        15

 void
 menumode()
 {
         register int ch;
         int foreground, background, border;
         extern void setattr(POSITION, int);
         extern void sc_cmds(int, int, int);

         /* default attributes */
         foreground = IBM_WHITE;
         background = IBM_BLACK;
         border = IBM_BLACK;

         ANSI_SGR(ANSI_NORMAL);
         setattr(FGND, foreground);
         setattr(BKGND, background);
         ANSI_ED;
         palette(0, border);
         sc_cmds(foreground, background, border);
         while ((ch = getkey()) != K_RETURN) {
                 switch (ch) {
                 case K_F1:
                         /* decrement foreground color */
                         if (--foreground < 0)
                                 foreground = MAX_CNUM;
                         break;
                 case K_F2:
                         /* increment foreground color */
                         if (++foreground > MAX_CNUM)
                                 foreground = 0;
                         break;
                 case K_F3:
                         /* decrement background color */
                         if (--background < 0)
                                 background = MAX_CNUM;
                         break;
                 case K_F4:
                         /* increment background color */
                         if (++background > MAX_CNUM)
                                 background = 0;
                         break;
                 case K_F5:
                         /* decrement border color */
                         if (--border < 0)
                                 border = MAX_CNUM;
                         break;
                 case K_F6:
                         /* increment border color number */
                         if (++border > MAX_CNUM)
                                 border = 0;
                         break;
                 default:
                         continue;
                 }
                 ANSI_SGR(ANSI_NORMAL);
                 setattr(FGND, foreground);
                 setattr(BKGND, background);
                 palette(0, border);
                 ANSI_ED;
                 sc_cmds(foreground, background, border);
         }
         return;
 }


 MESSAGE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\MESSAGE.C

 /*
  *        message -- routines used to display and clear
  *        messages in a reserved message area
  */

 #include "message.h"

 MESSAGE Ml;
 extern int writec(char, int, int);

 /*
  *        set up the message-line manager
  */

 void
 initmsg(r, c, w, a, pg)
 int r;                        /* message row */
 int c;                        /* message column */
 int w;                        /* width of message field */
 unsigned char a;        /* message field video attribute */
 int pg;                        /* active page for messages */
 {
         MESSAGE *mp;
         void clrmsg();

         mp = &Ml;
         mp->m_row = r;
         mp->m_col = c;
         mp->m_wid = w;
         mp->m_attr = a;
         mp->m_pg = pg;
         mp->m_flag = 1;
         clrmsg();
 }


 /*
  *        showmsg -- display a message and set the message flag
  */

 void
 showmsg(msg)
 char *msg;
 {
         MESSAGE *mp;

         mp = &Ml;
         putcur(mp->m_row, mp->m_col, mp->m_pg);
         writec(' ', mp->m_wid, mp->m_pg);
         putstr(msg, mp->m_pg);
         mp->m_flag = 1;
         return;
 }


 /*
  *        clrmsg -- erase the message area and reset the message flag
  */

 void
 clrmsg()
 {
         MESSAGE *mp;

         mp = &Ml;
         if (mp->m_flag != 0) {
                 putcur(mp->m_row, mp->m_col, mp->m_pg);
                 writec(' ', mp->m_wid, mp->m_pg);
                 mp->m_flag = 0;
         }
         return;
 }


 MX.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\07CONFIG\MX.C

 /*
  *        mx -- control Epson MX-series printer
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>
 #include <local\printer.h>

 extern PRINTER prt;        /* printer data */

 main(argc, argv)
 int argc;
 char **argv;
 {
         int ch, font;
         BOOLEAN errflag;        /* option error */
         BOOLEAN clrflag;        /* clear special fonts */
         BOOLEAN rflag;                /* hardware reset */
         BOOLEAN tflag;                /* top-of-form */
         FILE *fout;
         static char pgm[MAXNAME + 1] = { "mx" };

         extern void fatal(char *, char *, int);
         extern char *getpname(char *, char *);
         extern int getopt(int, char **, char *);
         extern char *optarg;
         extern int optind, opterr;
         extern int setprnt();
         extern int clrprnt(FILE *);
         extern int setfont(int, FILE *);

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         if (setprnt() == -1) {
                 fprintf(stderr, "%s: Bad printer configuration\n", pgm);
                 exit(1);
         }

         /* interpret command line */
         errflag = clrflag = rflag = tflag = FALSE;
         font = 0;
         fout = stdprn;
         while ((ch = getopt(argc, argv, "bcdefino:prtu")) != EOF) {
                 switch (ch) {
                 case 'b':
                         /* set bold */
                         font |= EMPHASIZED;
                         break;
                 case 'c':
                         /* set compressed */
                         font |= CONDENSED;
                         break;
                 case 'd':
                         /* set double strike */
                         font |= DOUBLE;
                         break;
                 case 'e':
                         /* set double strike */
                         font |= EXPANDED;
                         break;
                 case 'i':
                         /* set italic */
                         font |= ITALICS;
                         break;
                 case 'n':
                         /* set normal (clear all special fonts) */
                         clrflag = TRUE;
                         break;
                 case 'o':
                         /* use specified output stream */
                         if ((fout = fopen(optarg, "w")) == NULL)
                                 fatal(pgm, "cannot open output stream", 1);
                         break;
                 case 'p':
                         /* preview control strings on stdout */
                         fout = stdout;
                         break;
                 case 'r':
                         /* hardware reset */
                         rflag = TRUE;
                         break;
                 case 't':
                         /* top of form */
                         tflag = TRUE;
                         break;
                 case 'u':
                         /* set underline */
                         font |= UNDERLINE;
                         break;
                 case '?':
                         /* unknown option */
                         errflag = TRUE;
                         break;
                 }
         }

         /* report errors, if any */
         if (errflag == TRUE || argc == 1) {
                 fprintf(stderr, "Usage: %s -option\n", pgm);
                 fprintf(stderr,
                         "b=bold, c=compressed, d=double strike, e=expanded\n"
                 fprintf(stderr,
                         "i=italic, n=normal, o file=output to file\n");
                 fprintf(stderr,
                         "p=preview, r=reset, t=top-of-form, u=underline\n");
                 exit(2);
         }

         /* do hardware reset and formfeed first */
         if (rflag == TRUE)
                 fputs(prt.p_init, fout);
         else if (tflag == TRUE)
                 fputc('\f', fout);

         /* clear or set the aggregate font */
         if (clrflag == TRUE)
                 clrprnt(fout);
         else if (setfont(font, fout) == FAILURE) {
                 fprintf(stderr, "%s: Bad font spec\n", pgm);
                 exit(3);
         }

         exit(0);
 }


 NEXT_FM.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\NEXT_FM.C

 /*
  *        next_fm - find next file match in work directory
  */

 #include <dos.h>
 #include <local\doslib.h>

 int
 next_fm()
 {
         union REGS inregs, outregs;

         /* find next matching file */
         inregs.h.ah = FIND_NEXT;
         (void)intdos(&inregs, &outregs);

         return (outregs.x.cflag);
 }


 NLERASE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\NLERASE.C

 /*
  *        nlerase -- replace the first newline in a string
  *        with a null character
  */

 char *
 nlerase(s)
 char *s;
 {
         register char *cp;

         cp = s;
         while (*cp != '\n' && *cp != '\0')
                 ++cp;
         *cp = '\0';

         return (s);
 }


 NOTES1.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\04STDLIB\NOTES1.C

 /*
  *        notes1 -- add an entry to a "notes" text file
  *
  *        version 1: appends new data to NOTES.TXT in the
  *        current directory -- uses local date/time stamp
  *        as a header for each new entry
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #include <local\std.h>

 main()
 {
         FILE *fp;
         static char notesfile[MAXPATH + 1] = { "notes.txt" };
         char ch;
         long ltime;
         static char pgm[MAXNAME + 1] = { "notes1" };

         extern void fatal(char *, char *, int);

         /* try to open notes file in current directory */
         if ((fp = fopen(notesfile, "a")) == NULL)
                 fatal(pgm, notesfile, 1);

         /* append a header and date/time tag */
         ltime = time(NULL);
         fprintf(stderr, "Appending to %s: %s",
                  notesfile, ctime(&ltime));
         fprintf(fp, "%s", ctime(&ltime));

         /* append new text */
         while ((ch = getchar()) != EOF)
                 putc(ch, fp);

         /* clean up */
         if (fclose(fp))
                 fatal(pgm, notesfile, 2);
         exit(0);
 }


 NOTES2.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\04STDLIB\NOTES2.C

 /*
  *        notes2 -- add a date/time stamped entry to a
  *        "notes" data file.  Allow user to optionally
  *        edit the data file upon completion of the entry.
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #include <signal.h>
 #include <process.h>
 #include <local\std.h>

 /* length of date/time string */
 #define DT_STR        26

 main(argc, argv)
 int argc;
 char **argv;
 {
         int n;                /* number of lines added */
         int exitcode = 0;
         FILE *fp;
         static char notesfile[MAXPATH + 1] = { "notes.txt" };
         static char editname[MAXPATH + 1] = { "edlin" };
         char ch;
         char dt_stamp[DT_STR];
         char *s;
         long ltime;
         static char pgm[MAXNAME + 1] = { "notes3" };

         extern void fatal(char *, char *, int);
         extern void getpname(char *, char *);
         static int addtxt(FILE *, FILE *);

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* locate the "notes" database file and open it */
         if (argc > 1)
                 strcpy(notesfile, *++argv);
         else if (s = getenv("NOTESFILE"))
                 strcpy(notesfile, s);
         if ((fp = fopen(notesfile, "a")) == NULL)
                 fatal(pgm, notesfile, 1);

         /* disable Ctrl-Break interrupt */
         if (signal(SIGINT, SIG_IGN) == (int(*)())-1)
                 perror("Cannot set signal");

         /* append a header and date/time tag */
         ltime = time(NULL);
         strcpy(dt_stamp, ctime(&ltime));
         fprintf(stderr, "Appending to %s: %s", notesfile, dt_stamp);
         fprintf(fp, "\n%s", dt_stamp);

         /* add text to notes file */
         if ((n = addtxt(stdin, fp)) == 0) {
                 fputs("No new text", stderr);
                 if (fclose(fp))
                         fatal(pgm, notesfile, 2);
                 exit(0);
         }
         else
                 fprintf(stderr, "%d line(s) added to %s\n", n, notesfile);
         if (fclose(fp))
                 fatal(pgm, notesfile, 2);

         /* optionally edit text in the notes file */
         fprintf(stderr, "E + ENTER to edit; ENTER alone to quit: ");
         while ((ch = tolower(getchar())) != '\n')
                 if (ch = 'e') {
                         if (s = getenv("EDITOR"))
                                 strcpy(editname, s);
                         if ((exitcode = spawnlp(P_WAIT, editname, editname,
                                 notesfile, NULL)) == -1)
                                 fatal(pgm, editname, 3);
                 }
         exit(exitcode);
 }

 /*
  *        addtxt -- append new text to notes file
  */
 static int addtxt(fin, fout)
 FILE *fin, *fout;
 {
         int ch;
         int col = 0;        /* column */
         int n = 0;        /* number of lines added */

         while ((ch = fgetc(fin)) != EOF) {
                 if (ch == '.' && col == 0) {
                         ch = fgetc(fin); /* trash the newline */
                         break;
                 }
                 fputc(ch, fout);
                 if (ch == '\n') {
                         col = 0;
                         ++n;
                 }
                 else
                         ++col;
         }
         return (n);
 }


 PALETTE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\PALETTE.C

 /*
  *        palette        -- set graphics color values or border color
  */

 #include <dos.h>
 #include <local\bioslib.h>

 int
 palette(id, color)
 unsigned int id, color;
 {
         union REGS inregs, outregs;

         inregs.h.ah = PALETTE;
         inregs.h.bh = id;
         inregs.h.bl = color;
         int86(VIDEO_IO, &inregs, &outregs);

         return(outregs.x.cflag);
 }


 PARSE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\PARSE.C

 /*
  *        parse -- process a list of attribute specifications
  */

 #include <stdio.h>
 #include <local\ansi.h>
 #include <local\std.h>
 #include <local\ibmcolor.h>

 /* buffer length for string comparisons */
 #define NCHARS        3
 #define C_MASK        0x7

 void
 parse(nargs, argvec)
 int nargs;        /* number of argument vectors */
 char *argvec[];        /* pointer to the argument vector array */
 {
         int i, intensity;
         int attribute;
         POSITION pos;
         char str[NCHARS + 1];
         extern int colornum(char *);
         extern void setattr(POSITION, int);

         /* clear all attributes */
         ANSI_SGR(ANSI_NORMAL);

         /* look for a single attribute specification */
         if (nargs == 2) {
                 attribute = colornum(argvec[1]);
                 switch (attribute) {
                 case IBM_NORMAL:
                         palette(0, IBM_BLACK);
                         return;
                 case IBM_REVERSE:
                         ANSI_SGR(ANSI_REVERSE);
                         palette(0, IBM_WHITE);
                         return;
                 case IBM_INVISIBLE:
                         ANSI_SGR(ANSI_INVISIBLE);
                         return;
                 case IBM_BLINK:
                         ANSI_SGR(ANSI_BLINK);
                         return;
                 }
         }

         /* must be separate attribute specifications */
         pos = FGND;
         intensity = 0;
         for (i = 1; i < nargs; ++i) {
                 attribute = colornum(argvec[i]);
                 if (attribute == -1) {
                         ANSI_ED;
                         fprintf(stderr, "\nIllegal parameter\n");
                         exit (2);
                 }
                 if (attribute == IBM_BRIGHT) {
                         intensity = IBM_BRIGHT;
                         continue;
                 }
                 setattr(pos, attribute | intensity);
                 if (pos == FGND)
                         pos = BKGND;
                 else if (pos == BKGND)
                         pos = BDR;
                 intensity = 0;
         }
         return;
 }


 PR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR.C

 /*
  *        pr -- file printer
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <dos.h>
 #include <local\std.h>
 #include "print.h"

 char Pagelist[MAXLINE];

 main(argc, argv)
 int argc;
 char **argv;
 {
         int ch;
         BOOLEAN errflag;
         extern PRINT pcnf;
         static char pgm[MAXNAME + 1] = { "pr" };

         extern char *getpname(char *, char *);
         extern int getopt(int, char **, char *);
         extern char *optarg;
         extern int optind, opterr;
         extern int pr_gcnf(char *);
         extern pr_file(char *, int, char **);
         extern void pr_help(char *);
         extern void fixtabs(int);
         extern int setprnt();

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* do configuration */
         if (pr_gcnf(pgm) != 0) {
                 fprintf(stderr, "%s: Configuration error", pgm);
                 exit(2);
         }
         if (setprnt() == -1) {
                 fprintf(stderr, "%s: Bad printer configuration\n", pgm);
                 exit(1);
         }
         fixtabs(pcnf.p_tabint);

         /* process command-line arguments */
         while ((ch = getopt(argc, argv, "efgh:l:no:ps:w:")) != EOF) {
                 switch (ch) {
                 case 'e':
                         /* force "Epson-compatible " printer mode */
                         pcnf.p_mode = 1;
                         break;
                 case 'f':
                         /* use formfeed to eject a page */
                         pcnf.p_ff = 1;
                         break;
                 case 'g':
                         /* force "generic" printer mode */
                         pcnf.p_mode = 0;
                         break;
                 case 'h':
                         /* use specified header */
                         strcpy(pcnf.p_hdr, optarg);
                         break;
                 case 'l':
                         /* set lines per page */
                         pcnf.p_len = atoi(optarg);
                         break;
                 case 'n':
                         /* enable line numbering */
                         pcnf.p_lnum = 1;
                         break;
                 case 'o':
                         /* set left margin */
                         pcnf.p_lmarg = atoi(optarg);
                         break;
                 case 'p':
                         /* preview output on screen */
                         strcpy(pcnf.p_dest, "");
                         break;
                 case 's':
                         /* output selected pages */
                         strcpy(Pagelist, optarg);
                         break;
                 case 'w':
                         /* set page width in columns */
                         pcnf.p_wid = atoi(optarg);
                         break;
                 case '?':
                         /* unknown option */
                         errflag = TRUE;
                         break;
                 }
         }
         if (errflag == TRUE) {
                 pr_help(pgm);
                 exit(3);
         }

         /* print the files */
         pr_file(pgm, argc - optind, argv += optind);

         exit(0);
 }


 PRINTER.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\PRINTER.C

 /*
  *        printer -- interface functions for printer
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\printer.h>

 PRINTER prt;        /* printer data */

 /*
  *        setprnt -- install printer codes from configuration
  *        file for printer (defaults to Epson MX/FX series)
  */

 #define NSELEM        13

 int
 setprnt()
 {
         int n;
         char *s, line[MAXLINE];
         FILE *fp, *fconfig(char *, char *);

         /* use local or global config file, if any */
         if ((fp = fconfig("CONFIG", "printer.cnf")) != NULL) {
                 n = 0;
                 while (fgets(line, MAXLINE, fp) != NULL) {
                         if ((s = strtok(line, " \t\n")) == NULL)
                                 return (-1);
                         switch (n) {
                         case 0:
                                 strcpy(prt.p_init, s);
                                 break;
                         case 1:
                                 strcpy(prt.p_bold, s);
                                 break;
                         case 2:
                                 strcpy(prt.p_ds, s);
                                 break;
                         case 3:
                                 strcpy(prt.p_ital, s);
                                 break;
                         case 4:
                                 strcpy(prt.p_cmp, s);
                                 break;
                         case 5:
                                 strcpy(prt.p_exp, s);
                                 break;
                         case 6:
                                 strcpy(prt.p_ul, s);
                                 break;
                         case 7:
                                 strcpy(prt.p_xbold, s);
                                 break;
                         case 8:
                                 strcpy(prt.p_xds, s);
                                 break;
                         case 9:
                                 strcpy(prt.p_xital, s);
                                 break;
                         case 10:
                                 strcpy(prt.p_xcmp, s);
                                 break;
                         case 11:
                                 strcpy(prt.p_xexp, s);
                                 break;
                         case 12:
                                 strcpy(prt.p_xul, s);
                                 break;
                         default:
                                 /* too many lines */
                                 return (-1);
                         }
                         ++n;
                 }
                 if (n != NSELEM)
                         /* probably not enough lines */
                         return (-1);
         }

         /* or use Epson defaults */
         strcpy(prt.p_init, "\033@");        /* hardware reset */
         strcpy(prt.p_bold, "\033E");        /* emphasized mode */
         strcpy(prt.p_ds, "\033G");        /* double-strike mode */
         strcpy(prt.p_ital, "\0334");        /* italic mode */
         strcpy(prt.p_cmp, "\017");        /* condensed mode */
         strcpy(prt.p_exp, "\016");        /* expanded mode */
         strcpy(prt.p_ul, "\033-1");        /* underline mode */
         strcpy(prt.p_xbold, "\033F");        /* cancel emphasized mode */
         strcpy(prt.p_xds, "\033H");        /* cancel double-strike mode */
         strcpy(prt.p_xital, "\0335");        /* cancel italic mode */
         strcpy(prt.p_xcmp, "\022");        /* cancel condensed mode */
         strcpy(prt.p_xexp, "\024");        /* cancel expanded mode */
         strcpy(prt.p_xul, "\033-0");        /* cancel underline mode */

         return (0);
 }

 /*
  *        clrprnt -- clear printer options to default values
  *        (clears individual options to avoid the "paper creep"
  *        that occurs with repeated printer resets and to avoid
  *        changing the printer's notion of top-of-form position)
  */

 int
 clrprnt(fout)
 FILE *fout;
 {
         fputs(prt.p_xbold, fout);        /* cancel emphasized mode */
         fputs(prt.p_xds, fout);                /* cancel double-strike mode *
         fputs(prt.p_xital, fout);        /* cancel italic mode */
         fputs(prt.p_xcmp, fout);        /* cancel condensed mode */
         fputs(prt.p_xexp, fout);        /* cancel expanded mode */
         fputs(prt.p_xul, fout);                /* cancel underline mode */
 } /* end clrprnt() */

 /*
  *        setfont -- set the printing font to the type specified
  *        by the argument (may be a compound font specification)
  */

 int
 setfont(ftype, fout)
 int ftype;        /* font type specifier */
 FILE *fout;        /* output stream */
 {
         clrprnt(fout);
         if ((ftype & CONDENSED) == CONDENSED)
                 if ((ftype & DOUBLE) == DOUBLE ||
                         (ftype & EMPHASIZED) == EMPHASIZED)
                         return FAILURE;
                 else if (*prt.p_cmp)
                         fputs(prt.p_cmp, fout);
         if (*prt.p_ds && (ftype & DOUBLE) == DOUBLE)
                 fputs(prt.p_ds, fout);
         if (*prt.p_bold && (ftype & EMPHASIZED) == EMPHASIZED)
                 fputs(prt.p_bold, fout);
         if (*prt.p_exp && (ftype & EXPANDED) == EXPANDED)
                 fputs(prt.p_exp, fout);
         if (*prt.p_ital && (ftype & ITALICS) == ITALICS)
                 fputs(prt.p_ital, fout);
         if (*prt.p_ul && (ftype & UNDERLINE) == UNDERLINE)
                 fputs(prt.p_ul, fout);

         return SUCCESS;
 } /* end setfont() */


 PRTSTR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\07CONFIG\PRTSTR.C

 /*
  *        prtstr -- send text string(s) to standard printer
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         int ch;
         BOOLEAN errflag, lineflag;
         static char pgm[MAXNAME + 1] = { "prtstr" };
         FILE *fout;

         extern char *getpname(char *, char *);
         extern int getopt(int, char **, char *);
         extern int optind, opterr;
         extern char *optarg;

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* process options, if any */
         errflag = FALSE;
         lineflag = TRUE;
         fout = stdprn;
         while ((ch = getopt(argc, argv, "np")) != EOF)
                 switch (ch) {
                 case 'n':
                         /* don't emit the trailing newline */
                         lineflag = FALSE;
                         break;
                 case 'p':
                         /* preview on stdout */
                         fout = stdout;
                         break;
                 case '?':
                         /* bad option */
                         errflag = TRUE;
                         break;
                 }
         if (errflag == TRUE) {
                 fprintf(stderr, "Usage: %s [-np] [string...]\n");
                 exit(1);
         }

         /* print the string(s) */
         argc -= optind;
         argv += optind;
         while (argc-- > 1 ) {
                 fputs(*argv++, fout);
                 fputc(' ', fout);
         }
         fputs(*argv++, fout);
         if (lineflag == TRUE)
                 fputc(' ', fout);
         if (lineflag == TRUE)
                 fputc('\n', fout);

         exit(0);
 }


 PR_CPY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR_CPY.C

 /*
  *        pr_cpy -- copy input stream to output stream
  */

 #include <stdio.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\printer.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <time.h>
 #include "print.h"

 extern PRINT pcnf;
 extern char Pagelist[MAXLINE];
 extern long Highest;

 int
 pr_cpy(fin, fout, fname)
 FILE *fin;
 FILE *fout;
 char *fname;
 {
         int errcount = 0;
         unsigned int p_line;        /* page-relative line number */
         long f_line;                /* file-relative line number */
         long f_page;                /* file-relative page number */
         int lnlen;                /* line length */
         char line[MAXLINE];        /* input line buffer */
         struct stat tbuf;        /* file information */
         long ltime;                /* date and time */
         FILE *fnull, *fx;        /* additional output file pointers */

         extern void mkslist(char *);        /* make a selection list */
         extern int selected(long);        /* is item in the list? */
         extern int spaces(int, FILE *);        /* emit string of spaces */
         extern int setfont(int, FILE *);/* set printer font type */
         extern int clrprnt(FILE *);        /* clear special fonts */
         extern int lines(int, FILE *);        /* emit string of blank lines *
         static int fit(int, int);        /* will line fit on page? */
         extern int pr_line(char *, FILE *, unsigned int);

         /* install page selection list, if any */
         if (Pagelist[0] != '\0') {
                 /* open the NUL device for dumping output */
                 if ((fnull = fopen("NUL", "w")) == NULL) {
                         perror("Error opening NUL device");
                         exit(1);
                 }
                 mkslist(Pagelist);
         }
         else
                 Highest = BIGGEST;

         /* get date and time stamp */
         if (*fname == '\0')
                 /* using stdin -- use today's date and time */
                 ltime = time(NULL);
         else {
                 if (stat(fname, &tbuf) == -1)
                         return (-1);
                 /* use file's modification time */
                 ltime = tbuf.st_mtime;
         }
         p_line = 0;
         f_line = 1;
         f_page = 1;
         while ((lnlen = pr_getln(line, MAXLINE, fin)) > 0 ) {
                 /* if formfeed or no room for line, eject page */
                 if (line[0] == '\f' || !fit(lnlen, p_line)) {
                         /* to top of next page */
                         if (pcnf.p_ff == 0)
                                 lines(pcnf.p_len - p_line, fx);
                         else
                                 fputc('\f', fx);
                         p_line = 0;
                 }

                 /* if at top of page, print the header */
                 if (p_line == 0) {
                         if (f_page > Highest)
                                 break;
                         fx = selected(f_page) ? fout : fnull;
                         p_line += lines(pcnf.p_top1, fx);
                         if (pcnf.p_mode != 0)
                                 setfont(EMPHASIZED, fx);
                         spaces(pcnf.p_lmarg, fx);
                         if (*pcnf.p_hdr != '\0')
                                 fprintf(fx, "%s  ", pcnf.p_hdr);
                         else if (*fname != '\0')
                                 fprintf(fx, "%s  ", strupr(fname));
                         fprintf(fx, "Page %u  ", f_page++);
                         fputs(ctime(&ltime), fx);
                         ++p_line;
                         if (pcnf.p_mode != 0)
                                 setfont(pcnf.p_font, fx);
                         p_line += lines(pcnf.p_top2, fx);
                 }

                 /* OK to output the line */
                 if (line[0] != '\f')
                         p_line += pr_line(line, fx, f_line++);
         }
         if (ferror(fin) != 0)
                 ++errcount;
         if (p_line > 0 && p_line < pcnf.p_len)
                 if (pcnf.p_ff == 0)
                         lines(pcnf.p_len - p_line, fx);
                 else
                         fputc('\f', fx);

         if (pcnf.p_mode != 0)
                 clrprnt(fx);
         return (errcount);
 }

 /*
  *        fit -- return non-zero value if enough physical
  *        lines are available on the current page to take
  *        the current logical line of text
  */

 NFLDWIDTH  8        /* width of number field */

 static int
 fit(len, ln)
 int len, ln;
 {
         int need, left;        /* physical lines */
         int cols;        /* columns of actual output */
         int lw;                /* displayable line width */

         /* total need (columns -> physical lines) */
         cols = len + (pcnf.p_lnum > 0 ? NFLDWIDTH : 0);
         lw = pcnf.p_wid - pcnf.p_lmarg - pcnf.p_rmarg;
         need = 1 + cols / lw;

         /* lines remaining on page */
         left = pcnf.p_len - ln - pcnf.p_btm;

         return (need <= left ? 1 : 0);
 }


 PR_FILE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR_FILE.C

 /*
  *        pr_file -- process each filename or standard input
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>
 #include "print.h"

 int
 pr_file(pname, ac, av)
 char *pname;
 int ac;
 char **av;
 {
         int ch, errcount = 0;
         FILE *fin, *fout;
         extern PRINT pcnf;

         extern void fatal(char *, char *, int);
         extern int pr_cpy(FILE *, FILE *, char *);

         /* open output stream only if not already open */
         if (*pcnf.p_dest == '\0' || strcmp(pcnf.p_dest, "CON") == 0)
                 fout = stdout;
         else if (strcmp(pcnf.p_dest, "PRN") == 0)
                 fout = stdprn;
         else if (strcmp(pcnf.p_dest, "AUX") == 0)
                 fout = stdaux;
         else
                 if ((fout = fopen(pcnf.p_dest, "w")) == NULL)
                         fatal(pname, "Error open destination stream", 1);

         /* prepare input stream */
         if (ac == 0)
                 pr_cpy(stdin, fout, "");
         else {
                 for (; ac > 0; --ac, ++av) {
                         if ((fin = fopen(*av, "r")) == NULL) {
                                 fprintf(stderr, "%s: Error opening %s",
                                         pname, *av);
                                 continue;
                         }
                         if (pr_cpy(fin, fout, *av) == -1) {
                                 fprintf(stderr, "%s: Cannot stat %s",
                                         pname, *av);
                                 continue;
                         }
                         if (fclose(fin) == EOF)
                                 fatal(pname, "Error closing input file", 2);
                 }
         }

         return (errcount);
 }


 PR_GCNF.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR_GCNF.C

 /*
  *        pr_gcnf -- get configuration for pr program
  */

 #include <stdio.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\printer.h>
 #include "print.h"

 /* expected number of configuration items */
 #define N_NBR        12

 PRINT pcnf;

 int
 pr_gcnf(pname)
 char *pname;
 {
         char line[MAXLINE];
         char *s;
         int cnf[N_NBR];
         int n, errcount, good;
         FILE *fp, *fconfig(char *, char *);

         /* get configuration file values, if any */
         n = good = errcount = 0;
         if ((fp = fconfig("CONFIG", "pr.cnf")) != NULL) {
                 while (n < N_NBR && (s = fgets(line, MAXLINE, fp)) != NULL) {
                         cnf[n] = atoi(s);
                         ++n;
                 }
                 if ((s = fgets(line, MAXLINE, fp)) == NULL)
                         ++errcount;
                 else
                         strcpy(pcnf.p_dest, strtok(line, " \t\n"));
                 if (n != N_NBR)
                         ++errcount;
                 if (errcount == 0)
                         good = 1;
                 if (fclose(fp) == -1)
                         fatal(pname, "cannot close config file");
         }

         /* use config data is good; use defaults otherwise */
         pcnf.p_top1 = good ? cnf[0]: TOP1;
         pcnf.p_top2 = good ? cnf[1] : TOP2;
         pcnf.p_btm = good ? cnf[2] : BOTTOM;
         pcnf.p_wid = good ? cnf[3] : MAXPCOL;
         pcnf.p_lmarg = good ? cnf[4] : MARGIN;
         pcnf.p_rmarg = good ? cnf[5] : MARGIN;
         pcnf.p_len = good ? cnf[6] : PAGELEN;
         pcnf.p_lpi = good ? cnf[7] : LPI;
         pcnf.p_mode = good ? cnf[8] : 0;
         pcnf.p_lnum = good ? cnf[9] : 0;
         pcnf.p_ff = good ? cnf[10] : 0;
         pcnf.p_tabint = good ? cnf[11] : TABSPEC;
         if (!good)
                 strcpy(pcnf.p_dest, "PRN");
         if (pcnf.p_mode == 1)
                 pcnf.p_font = CONDENSED;
         strcpy(pcnf.p_hdr, "");

         return (errcount);
 }


 PR_GETLN.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR_GETLN.C

 /*
  *        pr_getln -- get a line of text while expanding tabs;
  *        put text into an array and return the length of the line
  *        including termination to the calling function.
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>

 int
 pr_getln(s, lim, fin)
 char *s;
 int lim;
 FILE *fin;
 {
         int ch;
         register char *cp;

         extern int tabstop();        /* query tabstop array */

         cp = s;
         while (--lim > 0 && (ch = fgetc(fin)) != EOF && ch != '\n' && ch != '
                 if (ch == '\t')
                         /* loop and store spaces until next tabstop */
                         do
                                 *cp++ = ' ';
                         while (--lim > 0 && tabstop(cp - s) == 0);
                 else
                         *cp++ = ch;
         }
         if (ch == EOF && cp - s == 0)
                 ;
         else if (ch == EOF || ch == '\n')
                 *cp++ = '\n';        /* assure correct line termination */
         else if (ch == '\f' && cp - s == 0) {
                 *cp++ = '\f';
                 fgetc(fin);        /* toss the trailing newline */
         }
         *cp = '\0';

         return (cp - s);
 }


 PR_HELP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR_HELP.C

 /*
  *        pr_help -- display an abbreviated manual page
  */

 #include <stdio.h>
 #include <local\std.h>

 void
 pr_help(pname)
 char *pname;
 {
         static char *m_str[] = {
                 "The following options may be used singly or in combination:"
                 "-e\t set Epson-compatible mode",
                 "-f\t use formfeed to eject a page (default is newlines)",
                 "-g\t use generic printer mode",
                 "-h hdr\t use specified header instead of file name",
                 "-l len\t set page length in lines (default = 66)",
                 "-n\t enable line numbering (default = off)",
                 "-o cols\t offset from left edge in columns (default = 5)",
                 "-p\t preview output on screen (may be redirected)",
                 "-s list\t print only selected pages",
                 "-w cols\t line width in columns (default = 80)"
         };
         int i, n = sizeof (m_str)/ sizeof (char *);

         fprintf(stderr, "Usage: %s [options] file...\n\n", pname);
         for (i = 0; i < n; ++i)
                 fprintf(stderr, "%s\n", m_str[i]);

         return;
 }


 PR_LINE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\09PRINT\PR_LINE.C

 /*
  *        pr_line -- ouput a buffered logical line and
  *        return a count of physical lines produced
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>
 #include "print.h"

 int
 pr_line(s, fout, rline)
 char *s;                /* buffered line of text */
 FILE *fout;                /* output stream */
 unsigned int rline;        /* file-relative line number */
 {
         int c_cnt;        /* character position in output line */
         int nlines;        /* number of lines output */
         extern PRINT pcnf;

         extern int spaces(int, FILE *);        /* emit string of spaces */

         nlines = 1;
         c_cnt = 0;

         /* output the left indentation, if any */
         c_cnt += spaces(pcnf.p_lmarg, fout);

         /* output the line number if numbering enabled */
         if (pcnf.p_lnum != 0)
                 c_cnt += fprintf(fout, "%6u  ", rline);

         /* output the text of the line */
         while (*s != '\0') {
                 if (c_cnt > (pcnf.p_wid - pcnf.p_rmarg)) {
                         fputc('\n', fout);
                         ++nlines;
                         c_cnt = 0;
                         c_cnt = spaces(pcnf.p_lmarg, fout);
                 }
                 fputc(*s, fout);
                 ++s;
                 ++c_cnt;
         }

         return (nlines);
 }


 PUTCUR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\PUTCUR.C

 /*
  *        putcur -- put cursor at specified position (row, col)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 putcur(r, c, pg)
 unsigned int
         r,        /* row */
         c,        /* column */
         pg;        /* screen page for writes */
 {
         union REGS inregs, outregs;

         inregs.h.ah = CUR_POS;
         inregs.h.bh = pg & 0x07;
         inregs.h.dh = r & 0xFF;
         inregs.h.dl = c & 0xFF;

         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 } /* end putcur() */


 PUTFLD.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\PUTFLD.C

 /*
  *        putfld -- display a string in the prevailing
  *        video attribute while compressing runs of a
  *        single character, and pad the field to full width
  *        with spaces if necessary
  */

 int
 putfld(s, w, pg)
 register char *s;        /* string to write */
 int w;                        /* field width */
 int pg;                        /* screen page for writes */
 {
         int r, c, cols;
         register int n;

         extern int putcur(int, int, int);
         extern int readcur(int *, int *, int);
         extern int writec(unsigned char, int, int);

         /* get starting (current) position */
         readcur(&r, &c, pg);

         /* write the string */
         for (n = 0; *s != '\0' && n < w; s += cols, n += cols) {
                 putcur(r, c + n, pg);
                 /* compress runs to a single call on writec() */
                 cols = 1;
                 while (*(s + cols) == *s && n + cols < w)
                         ++cols;
                 writec(*s, cols, pg);
         }

         /* pad the field, if necessary */
         if (n < w) {
                 putcur(r, c + n, pg);
                 writec(' ', w - n, pg);
         }

         return (w - n);
 }


 PUTSTR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\PUTSTR.C

 /*
  *        putstr -- display a character string in the
  *        prevailing video attribute and return number
  *        characters displayed
  */

 int
 putstr(s, pg)
 register char *s;
 unsigned int pg;
 {
         unsigned int r, c, c0;

         readcur(&r, &c, pg);
         for (c0 = c; *s != '\0'; ++s, ++c) {
                 putcur(r, c, pg);
                 writec(*s, 1, pg);
         }
         putcur(r, c, pg);
         return (c - c0);
 }


 PUT_CH.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\PUT_CH.C

 /*
  *        put_ch -- display a character in the prevailing video
  *        attribute and advance the cursor position
  */

 #include <local\video.h>

 int
 put_ch(ch, pg)
 register char ch;
 int pg;
 {
         int r, c, c0;

         readcur(&r, &c, pg);
         writec(ch, 1, pg);
         putcur(r, ++c, pg);
         return (1);
 }


 PWD.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\PWD.C

 /*
  *        pwd -- print (display actually) the current directory pathname
  */

 #include <stdio.h>
 #include <direct.h>
 #include <local\std.h>

 main()
 {
         char *path;

         if ((path = getcwd(NULL, MAXPATH)) == NULL) {
                 perror("Error getting current directory");
                 exit(1);
         }
         printf("%s\n", path);
         exit(0);
 }

 _setargv()
 {
 }

 _setenvp()
 {
 }

 _nullcheck()
 {
 }


 READCA.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\READCA.C

 /*
  *        readca -- read character and attribute at current position
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int readca(ch, attr, pg)
 unsigned char *ch;
 unsigned char *attr;
 unsigned int pg;        /* screen page for reads */
 {
         union REGS inregs, outregs;

         inregs.h.ah = READ_CHAR_ATTR;
         inregs.h.bh = pg;                /* display page */

         int86(VIDEO_IO, &inregs, &outregs);

         *ch = outregs.h.al;                /* character */
         *attr = outregs.h.ah;                /* attribute */

         /* return the value in AX register */
         return (outregs.x.cflag);
 } /* end readca() */


 READCUR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\READCUR.C

 /*
  *        readcur        -- pass back the cursor position (row, col)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 unsigned int readcur(row, col, pg)
 unsigned int *row;        /* current row */
 unsigned int *col;        /* current column */
 unsigned int pg;        /* screen page */
 {
         union REGS inregs, outregs;

         inregs.h.ah = GET_CUR;
         inregs.h.bh = pg;

         int86(VIDEO_IO, &inregs, &outregs);

         *col = outregs.h.dl;                /* col */
         *row = outregs.h.dh;                /* row */

         return (outregs.x.cflag);
 } /* end readcur() */


 READDOT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\READDOT.C

 /*
  *        readdot -- read the value of a pixel
  *        (in graphics mode only)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 readdot(row, col, dcolor)
 int row, col;
 int *dcolor;        /* pointer to dot color */
 {
         union REGS inregs, outregs;

         inregs.h.ah = READ_DOT;
         inregs.x.cx = col;
         inregs.x.dx = row;
         int86(VIDEO_IO, &inregs, &outregs);
         *dcolor = outregs.h.al;

         return (outregs.x.cflag);
 }


 REPLAY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\03DOS\REPLAY.C

 /*
  *        replay -- echo the command-line arguments
  *        to standard output
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         int i;
         char **p;
         static char pgm[MAXNAME + 1] = { "replay" };

         void getpname(char *, char *);

         /* get program name from DOS (version 3.00 and later) */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* check for arguments */
         if (argc == 1)
                 exit(1);        /* none given */

         /* echo the argument list, one per line */
         p = argv;
         printf("%s arguments:\n\n", pgm);
         for (--argc, ++argv; argc > 0; --argc, ++argv)
                 printf("argv[%d] -> %s\n", argv - p, *argv);
         exit(0);
 } /* end main() */


 RM.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\RM.C

 /*
  *        rm -- remove file(s)
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <ctype.h>
 #include <io.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int ch;
         BOOLEAN errflag,
                 iflag;

         static char pgm[MAXNAME + 1] = { "rm" };
         extern void getpname(char *, char *);
         static void do_rm(char *, char *, BOOLEAN);
         extern int getopt(int, char **, char *);
         extern int optind, opterr;
         extern char *optarg;

         /* get program name from DOS (version 3.00 and later) */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* process optional arguments first */
         errflag = iflag = FALSE;
         while ((ch = getopt(argc, argv, "i")) != EOF)
                 switch (ch) {
                 case 'i':
                         /* interactive -- requires confirmation */
                         iflag = TRUE;
                         break;
                 case '?':
                         /* say what? */
                         errflag = TRUE;
                         break;
                 }
         argc -= optind;
         argv += optind;

         if (argc <= 0 || errflag == TRUE) {
                 fprintf(stderr, "%s [-i] file(s)\n", pgm);
                 exit(1);
         }

         /* process remaining arguments */
         for (; argc-- > 0; ++argv)
                 do_rm(pgm, *argv, iflag);

         exit(0);
 } /* end main() */

 /*
  *        do_rm -- remove a file
  */

 static void
 do_rm(pname, fname, iflag)
 char *pname, *fname;
 BOOLEAN iflag;
 {
         int result = 0;
         struct stat statbuf;
         static BOOLEAN affirm();

         if (iflag == TRUE) {
                 fprintf(stderr, "%s (y/n): ", fname);
                 if (affirm() == FALSE)
                         return;
         }
         if ((result = unlink(fname)) == -1) {
                 fprintf(stderr, "%s: ", pname);
                 perror(fname);
         }
         return;
 }

 /*
  *        affirm -- return TRUE if the first character of the
  *        user's response is 'y' or FALSE otherwise
  */

 #define MAXSTR        64

 static BOOLEAN
 affirm()
 {
         char line[MAXSTR + 1];
         char *response;

         response = fgets(line, MAXSTR, stdin);
         return (tolower(*response) == 'y' ? TRUE : FALSE);
 }


 RUN_ONCE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\04STDLIB\RUN_ONCE.C

 /*
  *        run_once -- run a program one time and then
  *        "hang" the system to prevent unwanted use
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <process.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char *argv[];
 {
         extern void fatal(char *, char *, int);

         /* skip over the program name */
         ++argv;

         /* run the specified command line [pgmname arg(s)] */
         if (spawnvp(P_WAIT, *argv, argv) == -1)
                 fatal("run_once", "Error running specified program", 1);
         fprintf(stderr, "Please turn off the power to the computer.\n");

         /* do nothing */
         FOREVER
                 ;
 }


 SB_BOX.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_BOX.C

 /*
  *        sb_box -- draw a box around the perimeter of a window
  *        using the appropriate IBM graphics characters
  */

 #include <local\sbuf.h>
 #include <local\video.h>
 #include <local\box.h>

 int
 sb_box(win, type, attr)
 struct REGION *win;
 short type;
 unsigned char attr;
 {
         register short r;        /* row index */
         short x;                /* interior horizontal line length */
         short maxr, maxc;        /* maximum row and col values */
         BOXTYPE *boxp;                /* pointer to box drawing character str
         static BOXTYPE box[] = {
                 '+',   '+',   '+',   '+',   '-',   '-',   '|',   '|',
                 ULC11, URC11, LLC11, LRC11, HBAR1, HBAR1, VBAR1, VBAR1,
                 ULC22, URC22, LLC22, LRC22, HBAR2, HBAR2, VBAR2, VBAR2,
                 ULC12, URC12, LLC12, LRC12, HBAR1, HBAR1, VBAR2, VBAR2,
                 ULC21, URC21, LLC21, LRC21, HBAR2, HBAR2, VBAR1, VBAR1,
                 BLOCK, BLOCK, BLOCK, BLOCK, HBART, HBARB, BLOCK, BLOCK
         };

         boxp = &box[type];
         maxc = win->c1 - win->c0;
         maxr = win->r1 - win->r0;
         x = maxc - 1;

         /* draw top row */
         sb_move(win, 0, 0);
         sb_wca(win, boxp->ul, attr, 1);
         sb_move(win, 0, 1);
         sb_wca(win, boxp->tbar, attr, x);
         sb_move(win, 0, maxc);
         sb_wca(win, boxp->ur, attr, 1);

         /* draw left and right sides */
         for (r = 1; r < maxr; ++r) {
                 sb_move(win, r, 0);
                 sb_wca(win, boxp->lbar, attr, 1);
                 sb_move(win, r, maxc);
                 sb_wca(win, boxp->rbar, attr, 1);
         }

         /* draw bottom row */
         sb_move(win, maxr, 0);
         sb_wca(win, boxp->ll, attr, 1);
         sb_move(win, maxr, 1);
         sb_wca(win, boxp->bbar, attr, x);
         sb_move(win, maxr, maxc);
         sb_wca(win, boxp->lr, attr, 1);

         return SB_OK;
 }


 SB_FILL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_FILL.C

 /*
  *         sb_fill -- fill region routines
  */

 #include <local\sbuf.h>

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];

 /*
  *        sb_fill -- set all cells in a specified region
  *        to the same character/attribute value
  */

 int
 sb_fill(win, ch, attr)
 struct REGION *win;
 unsigned char ch;        /* fill character */
 unsigned char attr;        /* fill attribute */
 {
         register int i, j;
         unsigned short ca;

         ca = (attr << 8) | ch;
         for (i = win->sr0; i <= win->sr1; ++i) {
                 for (j = win->sc0; j <= win->sc1; ++j)
                         Scrnbuf[i][j].cap = ca;
                 if (win->sc0 < Sbuf.lcol[i])
                         Sbuf.lcol[i] = win->sc0;
                 if (win->sc1 > Sbuf.rcol[i])
                         Sbuf.rcol[i] = win->sc1;
         }
         Sbuf.flags |= SB_DELTA;

         return SB_OK;
 }


 /*
  *        sb_fillc -- set all cells in a specified region
  *        to the same character value; leave attributes undisturbed
  */

 int
 sb_fillc(win, ch)
 struct REGION *win;
 unsigned char ch;        /* fill character */
 {
         register int i, j;

         for (i = win->sr0; i <= win->sr1; ++i) {
                 for (j = win->sc0; j <= win->sc1; ++j)
                         Scrnbuf[i][j].b.ch = ch;
                 if (win->sc0 < Sbuf.lcol[i])
                         Sbuf.lcol[i] = win->sc0;
                 if (win->sc1 > Sbuf.rcol[i])
                         Sbuf.rcol[i] = win->sc1;
         }
         Sbuf.flags |= SB_DELTA;

         return SB_OK;
 }


 /*
  *        sb_filla -- set all cells in a specified region
  *        to the same attribute value; leave characters undisturbed
  */

 int
 sb_filla(win, attr)
 struct REGION *win;
 unsigned char attr;        /* fill attribute */
 {
         register int i, j;

         for (i = win->sr0; i <= win->sr1; ++i) {
                 for (j = win->sc0; j <= win->sc1; ++j)
                         Scrnbuf[i][j].b.attr = attr;
                 if (win->sc0 < Sbuf.lcol[i])
                         Sbuf.lcol[i] = win->sc0;
                 if (win->sc1 > Sbuf.rcol[i])
                         Sbuf.rcol[i] = win->sc1;
         }
         Sbuf.flags |= SB_DELTA;

         return SB_OK;
 }


 SB_INIT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_INIT.C

 /*
  *        sb_init -- initialize the buffered screen interface
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\sbuf.h>

 /* global data declarations */
 struct BUFFER Sbuf;                        /* control information */
 union CELL Scrnbuf[SB_ROWS][SB_COLS];        /* screen buffer array */

 int
 sb_init()
 {
         int i;
         char *um;        /* update mode */

         /* set initial parameter values */
         Sbuf.bp = &Scrnbuf[0][0];
         Sbuf.row = Sbuf.col = 0;
         for (i = 0; i < SB_ROWS; ++i) {
                 Sbuf.lcol[i] = SB_COLS;
                 Sbuf.rcol[i] = 0;
         }
         Sbuf.flags = 0;

         /* set screen update mode */
         um = strupr(getenv("UPDATEMODE"));
         if (um == NULL || strcmp(um, "BIOS") == 0)
                 Sbuf.flags &= ~SB_DIRECT;
         else if (strcmp(um, "DIRECT") == 0)
                 Sbuf.flags |= SB_DIRECT;
         else
                 return SB_ERR;

         return SB_OK;
 }


 SB_MOVE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_MOVE.C

 /*
  *        sb_move -- move the screen buffer "cursor"
  */

 #include <local\sbuf.h>

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];

 int
 sb_move(win, r, c)
 struct REGION *win;        /* window pointer */
 register short r, c;        /* buffer row and column */
 {
         /* don't change anything if request is out of range */
         if (r < 0 || r > win->r1 - win->r0 || c < 0 || c > win->c1 - win->c0)
                 return SB_ERR;
         win->row = r;
         win->col = c;
         Sbuf.row = r + win->r0;
         Sbuf.col = c + win->c0;
         return SB_OK;
 }


 SB_NEW.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_NEW.C

 /*
  *        sb_new -- prepare a new window (rectangular region)
  *        and return a pointer to it
  */

 #include <stdio.h>
 #include <malloc.h>
 #include <local\sbuf.h>

 struct REGION *
 sb_new(top, left, height, width)
 int top;        /* top row */
 int left;        /* left column */
 int height;        /* total rows */
 int width;        /* total columns */
 {
         struct REGION *new;

         /* allocate the control data structure */
         new = (struct REGION *)malloc(sizeof (struct REGION));
         if (new != NULL) {
                 new->r0 = new->sr0 = top;
                 new->r1 = new->sr1 = top + height - 1;
                 new->c0 = new->sc0 = left;
                 new->c1 = new->sc1 = left + width - 1;
                 new->row = new->col = 0;
                 new->wflags = 0;
         }
         return (new);
 }


 SB_PUT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_PUT.C

 /*
  *        sb_put -- routines to put characters and strings into the
  *        screen buffer; the cursor location is altered
  */

 #include <local\sbuf.h>
 #include <ctype.h>

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];

 /*
  *        sb_putc -- put a character into a screen buffer window
  */

 int
 sb_putc(win, ch)
 struct REGION *win;
 unsigned char ch;
 {
         short cmax, rmax;
         short lim;
         short noscroll = 0, puterr = 0;

         /* calculate screen buffer position and limits */
         cmax = win->c1 - win->c0;
         rmax = win->r1 - win->r0;
         Sbuf.row = win->r0 + win->row;
         Sbuf.col = win->c0 + win->col;

         /* process the character */
         switch (ch) {
         case '\b':
                 /* non-destructive backspace */
                 if (win->col > 0) {
                         --win->col;
                         Sbuf.col = win->c0 + win->col;
                         return SB_OK;
                 }
                 else
                         return SB_ERR;
         case '\n':
                 /* clear trailing line segment */
                 while (win->col < cmax)
                         if (sb_putc(win, ' ') == SB_ERR)
                                 ++puterr;
                 break;
         case '\t':
                 /* convert tab to required number of spaces */
                 lim = win->col + 8 - (win->col & 0x7);
                 while (win->col < lim)
                         if (sb_putc(win, ' ') == SB_ERR)
                                 ++puterr;
                 break;
         default:
                 /* if printable ASCII, place the character in the buffer */
                 if (isascii(ch) && isprint(ch))
                         Scrnbuf[Sbuf.row][Sbuf.col].b.ch = ch;
                 if (Sbuf.col < Sbuf.lcol[Sbuf.row])
                         Sbuf.lcol[Sbuf.row] = Sbuf.col;
                 if (Sbuf.col > Sbuf.rcol[Sbuf.row])
                         Sbuf.rcol[Sbuf.row] = Sbuf.col;
                 break;
         }

         /* update the cursor position */
         if (win->col < cmax)
                 ++win->col;
         else if (win->row < rmax) {
                 win->col = 0;
                 ++win->row;
         }
         else if ((win->wflags & SB_SCROLL) == SB_SCROLL) {
                 sb_scrl(win, 1);
                 win->col = 0;
                 win->row = rmax;
         }
         else
                 ++noscroll;

         /* update screen buffer position */
         Sbuf.row = win->r0 + win->row;
         Sbuf.col = win->c0 + win->col;
         Sbuf.flags |= SB_DELTA;

         return ((noscroll || puterr) ? SB_ERR : SB_OK);
 } /* end sb_putc() */


 /*
  *        sb_puts -- put a string into the screen buffer
  */

 int
 sb_puts(win, s)
 struct REGION *win;
 unsigned char *s;
 {
         while (*s)
                 if (sb_putc(win, *s++) == SB_ERR)
                         return SB_ERR;
         return SB_OK;
 } /* end sb_puts() */


 SB_READ.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_READ.C

 /*
  *        sb_read -- read character/attribute data
  */

 #include <local\sbuf.h>

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];

 unsigned char
 sb_ra(win)
 struct REGION *win;        /* window pointer */
 {
         return (Scrnbuf[win->r0 + win->row][win->c0 + win->col].b.attr);
 } /* end sb_ra() */


 /*
  *        sb_rc -- read character from current location in screen buffer
  */

 unsigned char
 sb_rc(win)
 struct REGION *win;        /* window pointer */
 {
         return (Scrnbuf[win->r0 + win->row][win->c0 + win->col].b.ch);
 } /* end sb_rc() */


 /*
  *        sb_rca -- read character/attribute pair from current
  *        location in screen buffer
  */

 unsigned short
 sb_rca(win)
 struct REGION *win;        /* window pointer */
 {
         return (Scrnbuf[win->r0 + win->row][win->c0 + win->col].cap);
 } /* end sb_rca() */


 SB_SCRL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_SCRL.C

 /*
  *        sb_scrl -- scrolling routines
  */

 #include <local\sbuf.h>

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];


 /*
  *        sb_scrl -- scroll the specified window
  *        n lines (direction indicated by sign)
  */

 int
 sb_scrl(win, n)
 struct REGION *win;
 short n;                /* number of rows to scroll */
 {
         register short r, c;

         if (n == 0)
                 /* clear the entire region to spaces */
                 sb_fillc(win, ' ');
         else if (n > 0) {
                 /* scroll n rows up */
                 for (r = win->sr0; r <= win->sr1 - n; ++r) {
                         for (c = win->sc0; c <= win->sc1; ++c)
                                 Scrnbuf[r][c] = Scrnbuf[r + n][c];
                         if (win->sc0 < Sbuf.lcol[r])
                                 Sbuf.lcol[r] = win->sc0;
                         if (win->sc1 > Sbuf.rcol[r])
                                 Sbuf.rcol[r] = win->sc1;
                 }
                 for ( ; r <= win->sr1; ++r) {
                         for (c = win->sc0; c <= win->sc1; ++c)
                                 Scrnbuf[r][c].b.ch = ' ';
                         if (win->sc0 < Sbuf.lcol[r])
                                 Sbuf.lcol[r] = win->sc0;
                         if (win->sc1 > Sbuf.rcol[r])
                                 Sbuf.rcol[r] = win->sc1;
                 }
         }
         else {
                 /* scroll n rows down */
                 n = -n;
                 for (r = win->sr1; r >= win->sr0 + n; --r) {
                         for (c = win->sc0; c <= win->sc1; ++c)
                                 Scrnbuf[r][c] = Scrnbuf[r - n][c];
                         if (win->sc0 < Sbuf.lcol[r])
                                 Sbuf.lcol[r] = win->sc0;
                         if (win->sc1 > Sbuf.rcol[r])
                                 Sbuf.rcol[r] = win->sc1;
                 }
                 for ( ; r >= win->sr0; --r) {
                         for (c = win->sc0; c <= win->sc1; ++c)
                                 Scrnbuf[r][c].b.ch = ' ';
                         if (win->sc0 < Sbuf.lcol[r])
                                 Sbuf.lcol[r] = win->sc0;
                         if (win->sc1 > Sbuf.rcol[r])
                                 Sbuf.rcol[r] = win->sc1;
                 }
         }
         Sbuf.flags |= SB_DELTA;
         return SB_OK;
 } /* end sb_scrl() */


 /*
  *        sb_set_scrl -- set the scroll region boundaries
  */

 int
 sb_set_scrl(win, top, left, bottom, right)
 struct REGION *win;        /* window pointer */
 short top, left;        /* upper-left corner */
 short bottom, right;        /* lower-left corner */
 {
         if (top < 0 || left < 0 ||
                 bottom > win->r1 - win->r0 || right > win->c1 - win->c0)
                 return SB_ERR;
         win->sr0 = win->r0 + top;
         win->sc0 = win->c0 + left;
         win->sr1 = win->r0 + bottom - 1;
         win->sc1 = win->c0 + right - 1;
         return SB_OK;
 } /* end sb_set_scrl() */


 SB_SHOW.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_SHOW.C

 /*
  *        sb_show -- copy the screen buffer to display memory
  */

 #include <stdio.h>
 #include <dos.h>
 #include <memory.h>
 #include <local\sbuf.h>
 #include <local\video.h>

 #define        MDA_SEG        0xB000
 #define        CGA_SEG        0xB800
 #define NBYTES        (2 * SB_COLS)

 /* macro to synchronize with vertical retrace period */
 #define VSTAT        0x3DA
 #define VRBIT        8
 #define VSYNC        while ((inp(VSTAT) & VRBIT) == VRBIT); \
                 while ((inp(VSTAT) & VRBIT) != VRBIT)

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];

 int
 sb_show(pg)
 short pg;
 {
         register short r, c;
         short n;
         short count, ncols;
         unsigned int src_os, dest_os;
         struct SREGS segregs;

         if ((Sbuf.flags & SB_DIRECT) == SB_DIRECT) {
                 /* use the direct-screen interface */
                 segread(&segregs);

                 /* determine extent of changes */
                 n = 0;
                 for (r = 0; r < SB_ROWS; ++r)
                         if (Sbuf.lcol[r] <= Sbuf.rcol[r])
                                 ++n;
                 src_os = dest_os = 0;
                 if (n <= 2)
                         /* copy only rows that contain changes */
                         for (r = 0; r < SB_ROWS; ++r) {
                                 if (Sbuf.lcol[r] <= Sbuf.rcol[r]) {
                                         /* copy blocks during vertical retrac
                                         VSYNC;
                                         movedata(segregs.ds,
                                                 (unsigned)&Scrnbuf[0][0] + sr
                                                 CGA_SEG, dest_os, NBYTES);
                                         Sbuf.lcol[r] = SB_COLS;
                                         Sbuf.rcol[r] = 0;
                                 }
                                 src_os += SB_COLS;
                                 dest_os += NBYTES;
                         }
                 else {
                         /* copy the entire buffer */
                         count = 3 * NBYTES;
                         ncols = 3 * SB_COLS;
                         for (r = 0; r < SB_ROWS - 1; r += 3) {
                                 VSYNC;
                                 movedata(segregs.ds, (unsigned)&Scrnbuf[0][0]
                                         + src_os, CGA_SEG, dest_os, count);
                                 src_os += ncols;
                                 dest_os += count;
                         }
                         VSYNC;
                         movedata(segregs.ds, (unsigned)&Scrnbuf[0][0] + src_o
                                 CGA_SEG, dest_os, NBYTES);
                         for (r = 0; r < SB_ROWS; ++r) {
                                 Sbuf.lcol[r] = SB_COLS;
                                 Sbuf.rcol[r] = 0;
                         }
                 }
         }
         else
                 /* use the BIOS video interface */
                 for (r = 0; r < SB_ROWS; ++r)
                         /* copy only changed portions of lines */
                         if (Sbuf.lcol[r] < SB_COLS && Sbuf.rcol[r] > 0) {
                                 for (c = Sbuf.lcol[r]; c <= Sbuf.rcol[r]; ++c
                                         putcur(r, c, pg);
                                         writeca(Scrnbuf[r][c].b.ch,
                                                 Scrnbuf[r][c].b.attr, 1, pg);
                                 }
                                 Sbuf.lcol[r] = SB_COLS;
                                 Sbuf.rcol[r] = 0;
                         }

         /* the display now matches the buffer -- clear flag bit */
         Sbuf.flags &= ~SB_DELTA;

         return SB_OK;
 }


 SB_TEST.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_TEST.C

 /*
  *        sb_test -- driver for screen-buffer interface functions
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <local\std.h>
 #include <local\keydefs.h>
 #include <local\sbuf.h>
 #include <local\video.h>
 #include <local\box.h>
 #include "sb_test.h"

 #define BEL 7

 extern struct BUFFER Sbuf;

 main(argc, argv)
 int argc;
 char *argv[];
 {
         char *s, line[MAXLINE];
         int k;
         short i;
         FILE *fp;
         char fname[MAXPATH];
         struct REGION *cmnd, *stat, *text, *help, *curwin;
         unsigned char cmndattr, statattr, textattr, helpattr, curattr;
         unsigned char ch, userattr;

         /* function prototypes */
         int sb_init();
         int sb_move(struct REGION *, short, short);
         struct REGION *sb_new(short, short, short, short);
         int sb_putc(struct REGION *, unsigned char);
         int sb_puts(struct REGION *, char *);
         int sb_show(short);
         int sb_fill(struct REGION *, unsigned char, unsigned char);
         char *get_fname(struct REGION *, char *, short);

         getstate();
         readca(&ch, &userattr, Vpage);

         /* set up the screen buffer */
         if (sb_init() == SB_ERR) {
                 fprintf(stderr, "Bad UPDATEMODE value in environment\n");
                 exit(1);
         }

         /* set up windows and scrolling regions */
         cmnd = sb_new(CMND_ROW, CMND_COL, CMND_HT, CMND_WID);
         stat = sb_new(STAT_ROW, STAT_COL, STAT_HT, STAT_WID);
         text = sb_new(TEXT_ROW, TEXT_COL, TEXT_HT, TEXT_WID);
         help = sb_new(HELP_ROW, HELP_COL, HELP_HT, HELP_WID);
         text->wflags |= SB_SCROLL;
         sb_set_scrl(help, 1, 1, HELP_HT - 1, HELP_WID - 1);

         /* display each primary window in its own attribute */
         cmndattr = GRN;
         statattr = (WHT << 4) | BLK;
         textattr = (BLU << 4) | CYAN;
         helpattr = (GRN << 4) | YEL;
         sb_fill(cmnd, ' ', cmndattr);
         if (sb_move(cmnd, 0, 0) == SB_OK)
                 sb_puts(cmnd, "SB_TEST (Version 1.0)");
         sb_fill(stat, ' ', statattr);
         if (sb_move(stat, 0, 0) == SB_OK)
                 sb_puts(stat, "*** STATUS AREA ***");
         for (i = 0; i <= text->r1 - text->r0; ++i) {
                 sb_move(text, i, 0);
                 sb_wca(text, i + 'a', textattr,
                         text->c1 - text->c0 + 1);
         }
         if (sb_move(text, 10, 25) == SB_OK)
                 sb_puts(text, " *** TEXT DISPLAY AREA *** ");
         sb_show(Vpage);
         curwin = text;
         curattr = textattr;

         /* respond to user commands */
         while ((k = getkey()) != K_ESC) {
                 switch (k) {
                 case K_UP:
                         sb_scrl(curwin, 1);
                         break;
                 case K_DOWN:
                         sb_scrl(curwin, -1);
                         break;
                 case K_PGUP:
                         sb_scrl(curwin, curwin->sr1 - curwin->sr0);
                         break;
                 case K_PGDN:
                         sb_scrl(curwin, -(curwin->sr1 - curwin->sr0));
                         break;
                 case K_ALTC:
                         /* clear the current window */
                         sb_fill(curwin, ' ', curattr);
                         break;
                 case K_ALTH:
                         /* display help */
                         curwin = help;
                         curattr = helpattr;
                         for (i = 0; i < help->r1 - help->r0; ++i) {
                                 sb_move(help, i, 0);
                                 sb_wca(help, i + 'a', helpattr,
                                         help->c1 - help->c0 + 1);
                         }
                         sb_box(help, BOXBLK, helpattr);
                         break;
                 case K_ALTS:
                         /* fill the command area with letters */
                         curwin = stat;
                         curattr = statattr;
                         sb_fill(stat, 's', statattr);
                         break;
                 case K_ALTT:
                         /* fill the text area */
                         curwin = text;
                         curattr = textattr;
                         for (i = 0; i <= text->r1 - text->r0; ++i) {
                                 sb_move(text, i, 0);
                                 sb_wca(text, i + 'a', textattr,
                                         text->c1 - text->c0 + 1);
                         }
                         break;
                 case K_ALTR:
                         /* read a file into the current window */
                         sb_fill(stat, ' ', statattr);
                         sb_move(stat, 0, 0);
                         sb_puts(stat, "File to read: ");
                         sb_show(Vpage);
                         (void)get_fname(stat, fname, MAXPATH);
                         if ((fp = fopen(fname, "r")) == NULL) {
                                 sb_fill(stat, ' ', statattr);
                                 sb_move(stat, 0, 0);
                                 sb_puts(stat, "Cannot open ");
                                 sb_puts(stat, fname);
                         }
                         else {
                                 sb_fill(stat, ' ', statattr);
                                 sb_move(stat, 0, 0);
                                 sb_puts(stat, "File: ");
                                 sb_puts(stat, fname);
                                 sb_show(Vpage);
                                 sb_fill(text, ' ', textattr);
                                 sb_move(text, 0, 0);
                                 putcur(text->r0, text->c0, Vpage);
                                 while ((s = fgets(line, MAXLINE, fp)) != NULL
                                         if (sb_puts(text, s) == SB_ERR) {
                                                 clrscrn(userattr);
                                                 putcur(0, 0, Vpage);
                                                 fprintf(stderr, "puts error\n
                                                 exit(1);
                                         }
                                         sb_show(Vpage);
                                 }
                                 if (ferror(fp)) {
                                         putcur(text->r0, text->c0, Vpage);
                                         fprintf(stderr, "Error reading file\n
                                 }
                                 fclose(fp);
                         }
                         break;
                 default:
                         /* say what? */
                         fputc(BEL, stderr);
                         continue;
                 }
                 if ((Sbuf.flags & SB_DELTA) == SB_DELTA)
                         sb_show(Vpage);
         }

         clrscrn(userattr);
         putcur(0, 0, Vpage);
         exit(0);
 }

 /*
  *        get_fname -- get a filename from the user
  */

 char *
 get_fname(win, path, lim)
 struct REGION *win;
 char *path;
 short lim;
 {
         int ch;
         char *s;

         s = path;
         sb_show(Vpage);
         while ((ch = getch()) != K_RETURN) {
                 if (ch == '\b')
                         --s;
                 else {
                         sb_putc(win, ch);
                         *s++ = ch;
                 }
                 sb_show(Vpage);
         }
         *s = '\0';
         return (path);
 }


 SB_WRITE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\12SBUF\SB_WRITE.C

 /*
  *        sb_write -- screen buffer write routines
  */

 #include <local\sbuf.h>

 extern struct BUFFER Sbuf;
 extern union CELL Scrnbuf[SB_ROWS][SB_COLS];

 /*
  *        sb_wa -- write an attribute to a region of the screen buffer
  */

 int
 sb_wa(win, attr, n)
 struct REGION *win;        /* window pointer */
 unsigned char attr;        /* attribute */
 short n;                /* repetition count */
 {
         short i;
         short row;
         short col;

         i = n;
         row = win->r0 + win->row;
         col = win->c0 + win->col;
         while (i--)
                 Scrnbuf[row][col + i].b.attr = attr;

         /* marked the changed region */
         if (col < Sbuf.lcol[row])
                 Sbuf.lcol[row] = col;
         if (col + n > Sbuf.rcol[row])
                 Sbuf.rcol[row] = col + n;
         Sbuf.flags |= SB_DELTA;

         return (i == 0) ? SB_OK : SB_ERR;
 } /* end sb_wa() */


 /*
  *        sb_wc -- write a character to a region of the screen buffer
  */

 int
 sb_wc(win, ch, n)
 struct REGION *win;        /* window pointer */
 unsigned char ch;        /* character */
 short n;                /* repetition count */
 {
         short i;
         short row;
         short col;

         i = n;
         row = win->r0 + win->row;
         col = win->c0 + win->col;
         while (i--)
                 Scrnbuf[row][col + i].b.ch = ch;

         /* marked the changed region */
         if (col < Sbuf.lcol[row])
                 Sbuf.lcol[row] = col;
         if (col + n > Sbuf.rcol[row])
                 Sbuf.rcol[row] = col + n;
         Sbuf.flags |= SB_DELTA;

         return (i == 0 ? SB_OK : SB_ERR);
 } /* end sb_wc() */


 /*
  *        sb_wca -- write a character/attribute pair to a region
  *        of the screen buffer
  */

 int
 sb_wca(win, ch, attr, n)
 struct REGION *win;        /* window pointer */
 unsigned char ch;        /* character */
 unsigned char attr;        /* attribute */
 short n;                /* repetition count */
 {
         int i;
         short row;
         short col;

         i = n;
         row = win->r0 + win->row;
         col = win->c0 + win->col;
         while (i--)
                 Scrnbuf[row][col + i].cap = (attr << 8) | ch;

         /* marked the changed region */
         if (col < Sbuf.lcol[row])
                 Sbuf.lcol[row] = col;
         if (col + n > Sbuf.rcol[row])
                 Sbuf.rcol[row] = col + n;
         Sbuf.flags |= SB_DELTA;

         return (i == 0 ? SB_OK : SB_ERR);
 } /* end sb_wca() */


 SC.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\SC.C

 /*
  *        SetColor (sc) -- set foreground, background, and border
  *        attributes on systems equipped with color display systems
  *
  *        Usage:        sc [foreground [background [border]]]
  *                sc [attribute]
  */

 #include <stdio.h>
 #include <dos.h>
 #include <local\std.h>
 #include <local\ansi.h>
 #include <local\ibmcolor.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         extern void ansi_tst();
         extern BOOLEAN iscolor();
         extern void setattr(POSITION, int);
         extern void menumode();
         extern parse(int, char **);

         ansi_tst();
         if (iscolor() == FALSE) {
                 fprintf(stderr, "\n\nSystem not in a color text mode.\n");
                 fprintf(stderr, "Use the MODE command to set the mode.\n");
                 exit(2);
         }

         /* process either batch or interactive commands */
         if (argc > 1)
                 /* batch mode processing */
                 parse(argc, argv);
         else
                 /* no command-line args -- interactive mode */
                 menumode();

         ANSI_ED;
         exit (0);
 }


 SCROLL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\SCROLL.C

 /*
  *        scroll -- scroll a region of the "visual" screen
  *        page up or down by n rows (0 = initialize region)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 scroll(t, l, b, r, n, a)
 int t;        /* top row of scroll region */
 int l;        /* left column */
 int b;        /* bottom row */
 int r;        /* right column */
 int n;        /* number of lines to scroll */
         /* sign indicates direction to scroll */
         /* 0 means scroll all lines in the region (initialize) */
 unsigned char a;/* attribute for new lines */
 {
         union REGS inregs, outregs;

         if (n < 0) {
                 /* scroll visual page down n lines */
                 inregs.h.ah = SCROLL_DN;
                 inregs.h.al = -n;
         }
         else {
                 /* scroll visual page up n lines */
                 inregs.h.ah = SCROLL_UP;
                 inregs.h.al = n;
         }
         inregs.h.bh = a;        /* attribute of blank lines */
         inregs.h.bl = 0;
         inregs.h.ch = t;        /* upper-left of scroll region */
         inregs.h.cl = l;
         inregs.h.dh = b;        /* lower-right of scroll region */
         inregs.h.dl = r;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 SC_CMDS.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\SC_CMDS.C

 /*
  *        sc_cmds -- display command summary
  */

 #include <stdio.h>
 #include <local\ansi.h>

 void
 sc_cmds(fg, bkg, bdr)
 int fg, bkg, bdr;
 {
         static char *color_xlat[] = {
                 "Black (0)", "Blue (1)", "Green (2)", "Cyan (3)",
                 "Red (4)", "Magenta (5)", "Brown (6)", "White (7)",
                 "Grey (8)", "Light blue (9)", "Light green (10)",
                 "Light cyan (11)", "Light red (12)", "Light magenta (13)",
                 "Yellow (14)", "Bright white (15)"
         };

         ANSI_CUP(2, 29);
         fputs("*** SetColor (SC) ***", stdout);
         ANSI_CUP(4, 17);
         fputs("Attribute  Decrement  Increment  Current Value", stdout);
         ANSI_CUP(5, 17);
         fputs("---------  ---------  ---------  -------------", stdout);
         ANSI_CUP(6, 17);
         fputs("Foreground    F1         F2", stdout);
         ANSI_CUP(7, 17);
         fputs("Background    F3         F4", stdout);
         ANSI_CUP(8, 17);
         fputs("Border        F5         F6", stdout);
         ANSI_CUP(6, 50);
         fputs(color_xlat[fg], stdout);
         ANSI_CUP(7, 50);
         fputs(color_xlat[bkg], stdout);
         ANSI_CUP(8, 50);
         fputs(color_xlat[bdr], stdout);
         ANSI_CUP(10, 17);
         fputs("Type RETURN to exit. SetColor/Version 2.2", stdout);
         return;
 }


 SELECT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\SELECT.C

 /*
  *        select -- functions to create a selection table and
  *        to determine whether an item is an entry in the table
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>

 #define NRANGES        10
 #define NDIGITS        5

 struct slist_st {
         long int s_min;
         long int s_max;
 } Slist[NRANGES + 1];

 long Highest = 0;

 /*
  *        mkslist -- create the selection lookup table
  */

 int
 mkslist(list)
 char *list;
 {
         int i;
         char *listp, *s;
         long tmp;

         static long save_range();

         /* fill in table of selected items */
         if (*list == '\0') {
                 /* if no list, select all */
                 Slist[0].s_min = 0;
                 Slist[0].s_max = Highest = BIGGEST;
                 Slist[1].s_min = -1;
         }
         else {
                 listp = list;
                 for (i = 0; i < NRANGES; ++i) {
                         if ((s = strtok(listp, ", \t")) == NULL)
                                 break;
                         if ((tmp = save_range(i, s)) > Highest)
                                 Highest = tmp;
                         listp = NULL;
                 }
                 Slist[i].s_min = -1;
         }
         return (0);
 } /* end mkslist() */

 /*
  *        selected -- return non-zero value if the number
  *        argument is a member of the selection list
  */

 int
 selected(n)
 unsigned int n;
 {
         int i;

         /* look for converted number in selection list */
         for (i = 0; Slist[i].s_min != -1; ++i)
                 if (n >= Slist[i].s_min && n <= Slist[i].s_max)
                         return (1);
         return (0);
 } /* end selected() */

 /*
  *        save_range -- convert a string number spec to a
  *        numeric range in the selection table and return
  *        the highest number in the range
  */

 static long
 save_range(n, s)
 int n;
 char *s;
 {
         int radix = 10;
         char *cp, num[NDIGITS + 1];

         /* get the first (and possibly only) number */
         cp = num;
         while (*s != '\0' && *s != '-')
                 *cp++ = *s++;
         *cp = '\0';
         Slist[n].s_min = atol(num);
         if (*s == '\0')
                 /* pretty narrow range, huh? */
                 return (Slist[n].s_max = Slist[n].s_min);

         /* get the second number */
         if (*++s == '\0')
                 /* unspecified top end of range */
                 Slist[n].s_max = BIGGEST;
         else {
                 cp = num;
                 while (*s != '\0' && *s != '-')
                         *cp++ = *s++;
                 *cp = '\0';
                 Slist[n].s_max = atol(num);
         }
         return (Slist[n].s_max);
 } /* end save_range() */


 SETATTR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\SETATTR.C

 /*
  *        setattr -- execute an attribute update
  */

 #include <stdio.h>
 #include <local\ansi.h>
 #include <local\ibmcolor.h>

 #define C_MASK        0x7

 void
 setattr(pos, attr)
 POSITION pos;        /* attribute position */
 int attr;        /* composite attribute number (base attr | intensity) */
 {
         static int ibm2ansi[] = {
                 ANSI_BLACK, ANSI_BLUE, ANSI_GREEN, ANSI_CYAN,
                 ANSI_RED, ANSI_MAGENTA, ANSI_BROWN, ANSI_WHITE
         };

         switch (pos) {
         case FGND:
                 if (attr & IBM_BRIGHT)
                         ANSI_SGR(ANSI_BOLD);
                 ANSI_SGR(ibm2ansi[attr & C_MASK] + ANSI_FOREGROUND);
                 break;
         case BKGND:
                 if (attr & IBM_BRIGHT)
                         ANSI_SGR(ANSI_BLINK);
                 ANSI_SGR(ibm2ansi[attr & C_MASK] + ANSI_BACKGROUND);
                 break;
         case BDR:
                 palette(0, attr);
                 break;
         }
         return;
 }


 SETCTYPE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\SETCTYPE.C

 /*
  *        setctype -- set the cursor start and end raster scan lines
  */

 #include <dos.h>
 #include <local\bioslib.h>

 #define LO_NIBBLE        0x0F
 #define CURSOR_OFF        0x2
 #define MAXSCANLN        15

 int
 setctype(start, end)
 int start;        /* starting raster scan line */
 int end;        /* ending raster scan line */
 {
         union REGS inregs, outregs;

         inregs.h.ah = CUR_TYPE;
         inregs.h.ch = start & LO_NIBBLE;
         inregs.h.cl = end & LO_NIBBLE;
         if (start >= MAXSCANLN) {
                 inregs.h.ah |= CURSOR_OFF;
                 inregs.h.al = MAXSCANLN;
         }
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 SETDTA.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\SETDTA.C

 /*
  *        setdta -- tell DOS where to do disk transfers
  */

 #include <dos.h>
 #include <local\doslib.h>

 void
 setdta(bp)
 char *bp;        /* pointer to byte-aligned disk transfer area */
 {
         union REGS inregs, outregs;

         inregs.h.ah = SET_DTA;
         inregs.x.dx = (unsigned int)bp;
         (void)intdos(&inregs, &outregs);
 }


 SETFREQ.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\SETFREQ.C

 /*
  *        setfreq -- sets PC's tone generator to run
  *        continuously at the specified frequency
  */

 #include <conio.h>
 #include <local\timer.h>

 void
 setfreq(f)
 unsigned f;        /* frequency in Hertz (approximate) */
 {
         unsigned divisor = TIMER_CLK / f;

         outp(TIMER_CTRL, TIMER_PREP);                /* prepare timer */
         outp(TIMER_COUNT, (divisor & 0xFF));        /* low byte of divisor */
         outp(TIMER_COUNT, (divisor >> 8));        /* high byte of divisor */
 }


 SETMYDIR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\03DOS\SETMYDIR.C

 /*
  *        setmydir -- try to change the DOS environment
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         register char **p;
         static char var[] = { "MYDIR" };
         static char pgm[MAXNAME + 1] = { "setmydir" };
         extern void fatal(char *, char *, int);
         extern void getpname(char *, char *);

         /* use an alias if one is given to this program */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* try to add the MYDIR variable to the environment */
         if (putenv("MYDIR=c:\\mydir") == -1)
                 fatal(pgm, "Error changing environment", 1);

         /* display the environment for this process */
         for (p = environ; *p; p++) {
                 printf("%s\n", *p);
         }

         exit(0);
 }


 SETPAGE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\SETPAGE.C

 /*
  *        setpage -- select "visual" screen page for viewing
  *        (the "active" page is the one being written to)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>
 #include <local\video.h>

 int
 setpage(pg)
 int pg;        /* visual screen page number */
 {
         union REGS inregs, outregs;

         /* check page number against table */
         if (Maxpage[Vmode] > 0 && (pg < 0 || pg >= Maxpage[Vmode]))
                 return (-1);

         /* change the visual page */
         inregs.h.ah = SET_PAGE;
         inregs.h.al = pg;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 SETVMODE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\SETVMODE.C

 /*
  *        setvmode -- set the video mode
  *        (color/graphics systems only)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 /***********************************************************
 *
 * mode # (m)        description
 * ------------- ---------------------------------
 * PC MODES:
 *         0        40x25 Mono text        (c/g default)
 *         1        40x25 Color text
 *        2        80x25 Mono text
 *        3        80x25 Color text
 *        4        320x200 4-color graphics (med res)
 *        5        320x200 Mono graphics (med res)
 *        6        640x200 2-color graphics (hi res)
 *        7        80x25 on monochrome adapter
 *
 * PCjr MODES:
 *        8        160x200 16-color graphics
 *        9        320x200 16-color graphics
 *        10        640x200 4-color fraphics
 *
 * EGA MODES:
 *        13        320x200 16-color graphics
 *        14        620x200 16-color graphics
 *        15        640x350 mono graphics
 *        16        640x350 color graphics (4- or 16-color)
 ***********************************************************/

 int
 setvmode(vmode)
 unsigned int vmode;        /* user-specified mode number */
 {
         union REGS inregs, outregs;

         inregs.h.ah = SET_MODE;
         inregs.h.al = vmode;        /* value not checked */
         int86(VIDEO_IO, &inregs, &outregs);

         /* update video structure */
         getstate();

         return (outregs.x.cflag);
 }


 SHOW.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\10DUMP\SHOW.C

 /*
  *        show -- a filter that displays the contents of a file
  *        in a way that is guaranteed to be displayable
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <io.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         int ch;
         FILE *fp;
         BOOLEAN sflag = FALSE;        /* strip non-ASCII characters */
         BOOLEAN vflag = FALSE;        /* verbose mode */
         BOOLEAN wflag = FALSE;        /* filter typical word processing codes
         BOOLEAN errflag = FALSE;
         static char pgm[] = { "show" };

         extern int getopt(int, char **, char *);
         extern char *optarg;
         extern int optind, opterr;
         extern int showit(FILE *, BOOLEAN, BOOLEAN);
         extern void fatal(char *, char *, int);

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         while ((ch = getopt(argc, argv, "svw")) != EOF) {
                 switch (ch) {
                 case 's': /* strip non-ASCII characters */
                         sflag = TRUE;
                         break;
                 case 'v': /* verbose */
                         vflag = TRUE;
                         break;
                 case 'w': /* use word-processing conventions */
                         wflag = sflag = TRUE;
                         break;
                 case '?':
                         errflag = TRUE;
                         break;
                 }
         }

         /* check for errors */
         if (errflag == TRUE) {
                 fprintf(stderr, "Usage: %s [-sv] [file...]\n", pgm);
                 exit(1);
         }

         /* if no file names, use standard input */
         if (optind == argc) {
                 if (setmode(fileno(stdin), O_BINARY) == -1)
                         fatal(pgm, "Cannot set binary mode on stdin", 2);
                 showit(stdin, sflag, wflag);
                 exit(0);
         }

         /* otherwise, process remainder of command line */
         for ( ; optind < argc; ++optind) {
                 if ((fp = fopen(argv[optind], "rb")) == NULL) {
                         fprintf(stderr,
                                 "%s: Error opening %s\n", pgm, argv[optind]);
                         perror("");
                         continue;
                 }
                 if (vflag == TRUE)
                         fprintf(stdout, "\n%s:\n", argv[optind]);
                 if (showit(fp, sflag, wflag) != 0) {
                         fprintf(stderr,
                                 "%s: Error reading %s\n", pgm, argv[optind]);
                         perror("");
                 }
                 if (fclose(fp) == EOF)
                         fatal(pgm, "Error closing input file", 2);
         }

         exit(0);
 }


 SHOWENV.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\03DOS\SHOWENV.C

 /*
  *        showenv        -- display the values of any DOS variables
  *        named on the invocation command line
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>

 main(argc, argv, envp)
 int argc;
 char **argv;
 char **envp;
 {
         register char *ep;
         static char pgm[MAXNAME + 1] = { "showenv" };
         extern void getpname(char *, char *);

         /* use an alias if one is given to this program */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* if no arguments, show full environment list */
         if (argc == 1)
                 for (; *envp; ++envp)
                         printf("%s\n", *envp);
         else {
                 /*
                  *  treat all args as DOS variable names and
                  *  display values of only specified variables
                  */
                 ++argv;        /* skip past command name */
                 --argc;
                 while (argc > 0) {
                         if ((ep = getenv(strupr(*argv))) == NULL)
                                 fprintf(stderr, "%s not defined\n", *argv);
                         else
                                 printf("%s=%s\n", *argv, ep);
                         ++argv;
                         --argc;
                 }
         }
         exit(0);
 }


 SHOWIT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\10DUMP\SHOWIT.C

 /*
  *        showit -- make non-printable characters in
  *        the stream fp visible (or optionally strip them)
  */

 #include <stdio.h>
 #include <ctype.h>
 #include <local\std.h>

 int
 showit(fp, strip, wp)
 FILE *fp;
 BOOLEAN strip;        /* strip non-ASCII codes */
 BOOLEAN wp;        /* filter typical word processing codes */
 {
         int ch;

         clearerr(fp);
         while ((ch = getc(fp)) != EOF)
                 if (isascii(ch) && (isprint(ch) || isspace(ch)))
                         switch (ch) {
                         case '\r':
                                 if (wp == TRUE) {
                                         if ((ch = getc(fp)) != '\n')
                                                 ungetc(ch, fp);
                                         putchar('\r');
                                         putchar('\n');
                                 }
                                 else
                                         putchar(ch);
                                 break;
                         default:
                                 putchar(ch);
                                 break;
                         }
                 else if (strip == FALSE)
                         printf("\\%02X", ch);
                 else if (wp == TRUE && isprint(ch & ASCII))
                         putchar(ch & ASCII);
         return (ferror(fp));
 }


 SHOWTABS.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\07CONFIG\SHOWTABS.C

 /*
  *        showtabs -- graphically display tabstop settings
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <local\std.h>

 #define MAXCOL          80
 #define TABWIDTH  8

 extern long Highest;

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int ch, i;
         int interval, tablist[MAXLINE + 1], *p;
         char *tabstr;
         BOOLEAN errflag, fflag, vflag;
         static char pgm[MAXNAME + 1] = { "showtabs" };

         extern char *getpname(char *, char *);
         extern int getopt(int, char **, char *);
         extern char *optarg;
         extern int optind, opterr;
         extern int mkslist(char *);
         extern int selected(long);
         extern void fixtabs(int);
         extern void vartabs(int *);
         extern int tabstop(int);

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* process command-line options */
         errflag = fflag = vflag = FALSE;
         interval = 0;
         while ((ch = getopt(argc, argv, "f:v:")) != EOF) {
                 switch (ch) {
                 case 'f':
                         /* used fixed tabbing interval */
                         if (vflag == FALSE) {
                                 fflag = TRUE;
                                 interval = atoi(optarg);
                         }
                         break;
                 case 'v':
                         /* use list of tabs */
                         if (fflag == FALSE) {
                                 vflag = TRUE;
                                 strcpy(tabstr, optarg);
                         }
                         break;
                 case '?':
                         errflag = TRUE;
                         break;
                 }
         }
         if (errflag == TRUE) {
                 fprintf(stderr, "Usage: %s [-f interval | -v tablist]\n", pgm
                 exit(2);
         }

         /* set the tabstops */
         if (vflag == TRUE) {
                 /* user-supplied variable tab list */
                 mkslist(tabstr);
                 p = tablist;
                 for (i = 0; i < MAXLINE && i < Highest; ++i)
                         *p++ = selected((long)i + 1) ? i : 0;
                 *p = -1;        /* terminate the list */
                 vartabs(tablist);
         }
         else if (fflag == TRUE)
                 /* user-supplied fixed tabbing interval */
                 fixtabs(interval);
         else
                 /* hardware default tabbing interval*/
                 fixtabs(TABWIDTH);

         /* display current tabs settings */
         for (i = 0; i < MAXCOL; ++i)
                 if (tabstop(i))
                         fputc('T', stdout);
                 else if ((i + 1) % 10 == 0)
                         fputc('+', stdout);
                 else
                         fputc('-', stdout);
         fputc('\n', stdout);

         exit(0);
 }


 SOUND.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\SOUND.C

 /*
  *        sound -- produce a constant tone for a specified duration
  */

 #include <local\sound.h>

 void
 sound(f, dur)
 unsigned int f;        /* frequency of pitch in hertz */
 float dur;        /* in seconds and tenths of seconds */
 {
         extern void setfreq(unsigned int);
         extern void delay(float);

         /* set frequency in hertz */
         setfreq(f);

         /* turn the speaker on for specified duration */
         SPKR_ON;
         delay(dur);
         SPKR_OFF;
 }


 SOUNDS.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\SOUNDS.C

 /*
  *        sounds -- make various sounds on demand
  */

 #include <stdio.h>
 #include <conio.h>
 #include <math.h>

 #define ESC        27

 extern void sound(unsigned int, float);

 main()
 {
         int ch;

         fprintf(stderr, "1=warble 2=error 3=confirm 4=warn\n");
         fprintf(stderr, "Esc=quit\n");
         while ((ch = getch()) != ESC)
                 switch (ch) {
                 case '1':
                         warble();
                         break;
                 case '2':
                         error();
                         break;
                 case '3':
                         confirm();
                         break;
                 case '4':
                         warn();
                         break;
                 }
         exit(0);
 }

 #define CYCLES        3
 #define LOTONE        600
 #define HITONE        1200
 #define PERIOD        0.1

 warble()
 {
         int i;

         for (i = 0; i < 2 * CYCLES; ++i)
                 if (i % 2)
                         sound(LOTONE, PERIOD);
                 else
                         sound(HITONE, PERIOD);
 }

 error()
 {
         float d = 0.15;

         sound(440, d);
         sound(220, d);
 }

 confirm()
 {
         float d = 0.15;

         sound(440, d);
         sound(880, d);
 }

 warn()
 {
         float d = 0.2;

         sound(100, d);
 }


 SPACES.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\SPACES.C

 /*
  *        spaces -- send spaces (blanks) to the output stream
  */

 #include <stdio.h>
 #include <stdlib.h>

 int
 spaces(n, fp)
 int n;
 FILE *fp;
 {
         register int i;

         for (i = 0; i < n; ++i)
                 if (putc(' ', fp) == EOF && ferror(fp))
                         break;

         /* return number of spaces emitted */
         return (i);
 }


 SPKR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\SPKR.C

 /*
  *        spkr -- turn speaker ON/OFF
  *
  *                no args => OFF
  *                any arg(s) => ON
  */

 #include <local\sound.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         /* turn speaker on or off */
         if (argc == 1)
                 SPKR_OFF;
         else
                 SPKR_ON;
         exit(0);
 }


 ST.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\11SCREEN\ST.C

 /*
  *        st -- screen test using cpblk function
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <ctype.h>
 #include <dos.h>
 #include <local\std.h>
 #include <local\video.h>

 #define CG_SEG                0xB800
 #define MONO_SEG        0xB000
 #define NBYTES                0x1000
 #define PAGESIZ                (NBYTES / 2)
 #define PG0_OS                0
 #define PG1_OS                PG0_OS + NBYTES
 #define ESC                27
 #define MAXSCAN                14

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int i;
         int k;                                /* user command character */
         int ca;                                /* character/attribute word */
         int ch;                                /* character value read */
         int row, col;                        /* cursor position upon entry */
         int c_start, c_end;                /* cursor scan lines */
         unsigned char attr;                /* saved video attribute */
         unsigned dseg;                        /* destination buffer segment *
         unsigned os;                        /* page offset in bytes */
         static unsigned sbuf[NBYTES];        /* screen buffer */
         unsigned *bp;                        /* screen element pointer */
         unsigned sseg;                        /* source segment */
         int special;                        /* use special copy routine */
         int apg, vpg;                        /* active and visual display pag

         /* segment register values */
         struct SREGS segregs;

         extern void swap_int(int *, int *);

         static char pgm[] = { "st" };        /* program name */

         /* save user's current video state */
         getstate();
         readcur(&row, &col, Vpage);
         putcur(row - 1, 0, Vpage);
         readca(&ch, &attr, Vpage);
         getctype(&c_start, &c_end, Vpage);
         setctype(MAXSCAN, c_end);
         clrscrn(attr);
         putcur(1, 1, Vpage);

         /* initialize destination segment */
         special = 1;
         fputs("ScreenTest (ST): ", stderr);
         if (Vmode == CGA_C80 || Vmode == CGA_M80) {
                 dseg = CG_SEG;
                 fprintf(stderr, "Using CGA mode %d", Vmode);
         }
         else if (Vmode == MDA_M80) {
                 dseg = MONO_SEG;
                 fprintf(stderr, "Using MDA (mode %d)", Vmode);
                 special = 0;
         } else
                 fprintf(stderr, "%s: Requires 80-column text mode\n", pgm);

         /* process command-line arguments */
         if (argc > 2) {
                 fprintf(stderr, "Usage: %s [x]\n", pgm);
                 exit(2);
         }
         else if (argc == 2)
                 special = 0;        /* bypass special block move */

         /* get data segment value */
         segread(&segregs);
         sseg = segregs.ds;

         /* set up "active" and "visual" display pages */
         apg = 1;        /* page being written to */
         vpg = 0;        /* page being viewed */

         /* display buffers on the user's command */
         fprintf(stderr, " -- Type printable text; Esc=exit");
         while ((k = getkey()) != ESC) {
                 if (isascii(k) && isprint(k)) {
                         /* fill the buffer */
                         ca = ((k % 0xEF) << 8) | k;
                         for (bp = sbuf; bp - sbuf < PAGESIZ; ++bp)
                                 *bp = ca;
                         if (Vmode == MDA_M80)
                                 os = 0;
                         else
                                 os = (apg == 0) ? PG0_OS : PG1_OS;
                         if (special)
                                 cpblk(sbuf, sseg, os, dseg);
                         else
                                 movedata(sseg, sbuf, dseg, os, NBYTES);
                         if (Vmode != MDA_M80) {
                                 swap_int(&apg, &vpg);
                                 setpage(vpg);
                         }
                 }
                 else {
                         clrscrn(attr);
                         putcur(0, 0, Vpage);
                         writestr(" Type printable text; Esc = exit ", vpg);
                 }
         }

         /* restore user's video conditions and return to DOS */
         setpage(Vpage);
         clrscrn(attr);
         putcur(0, 0, Vpage);
         setctype(c_start, c_end);
         exit(0);
 }


 STRDUP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\STRDUP.C

 /*
  *        strdup -- duplicate a string
  */

 #include <stdio.h>
 #include <malloc.h>
 #include <string.h>

 char *
 strdup(str)
 char *str;
 {
         char *buf;

         buf = malloc(strlen(str) + 1);
         return (buf == NULL ? buf : strcpy(buf, str));
 }


 STRING.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\STRING.C

 /*
  *        string -- emit a sequence of n repetitions of the
  *        character ch
  */

 #include <stdio.h>
 #include <stdlib.h>

 int
 string(n, ch, fp)
 int n;
 char ch;
 FILE *fp;
 {
         register int i;

         for (i = 0; i < n; ++i)
                 if (fputc(ch, fp) == EOF && ferror(fp))
                         break;

         /* return number of actual repetitions */
         return (i);
 }


 SWAP_INT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\11SCREEN\SWAP_INT.C

 /*
  *        swap_int -- exchange the values of the two integers
  */

 void
 swap_int(p1, p2)
 register int *p1;
 register int *p2;
 {
         int tmp;

         /* exchange the values */
         tmp = *p1;
         *p1 = *p2;
         *p2 = tmp;
 }


 SWEEP.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\SWEEP.C

 /*
  *        sweep -- produce a sound that sweeps from
  *        a low to a high frequency repeatedly until a
  *        key is pressed
  */

 #include <conio.h>
 #include <local\sound.h>

 main()
 {
         unsigned int f;
         int d, n;
         extern void setfreq(unsigned int);

         SPKR_ON;
         while (1) {
                 /* give user a way out */
                 if (kbhit())
                         break;
                 n = 10;
                 for (f = 100; f <= 5000; f += n) {
                         setfreq(f);
                         d = 1000;
                         /* fake a short delay (machine dependednt) */
                         while (d-- > 0)
                                 ;
                         n += 10;
                 }
         }
         SPKR_OFF;
         exit(0);
 }


 TABS.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\TABS.C

 /*
  *        tabs -- a group of cooperating functions that set
  *        and report the settings of "tabstops"
  */

 #include <local\std.h>

 static char Tabstops[MAXLINE];

 /*
  *        fixtabs -- set up fixed-interval tabstops
  */
 void
 fixtabs(interval)
 register int interval;
 {
         register int i;

         for (i = 0; i < MAXLINE; i++)
                 Tabstops[i] = (i % interval == 0) ? 1 : 0;
 } /* end fixtabs() */

 /*
  *        vartabs -- set up variable tabstops from an array
  *        integers terminated by a -1 entry
  */
 void
 vartabs(list)
 int *list;
 {
         register int i;

         /* initialize the tabstop array */
         for (i = 0; i < MAXLINE; ++i)
                 Tabstops[i] = 0;

         /* set user-sprcified tabstops */
         while (*list != -1)
                 Tabstops[*++list] = 1;
 } /* end vartabs() */

 /*
  *        tabstop -- return non-zero if col is a tabstop
  */
 int
 tabstop(col)
 register int col;
 {
         return (col >= MAXLINE ? 1 : Tabstops[col]);
 } /* end tabstop() */


 TEE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\TEE.C

 /*
  *        tee -- a "pipe fitter" for DOS
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>

 main(argc, argv)
 int argc;
 char *argv[];
 {
         register int ch, n;
         static char openmode[] = { "w" };
         static char pgm[MAXPATH + 1] = { "tee" };
         FILE *fp[_NFILE];        /* array of file pointers */

         extern int getopt(int, char **, char *);
         extern int optind, opterr;
         extern char *optarg;
         extern void getpname(char *, char *);

         /* check for an alias */
         if (_osmajor >= 3)
                 getpname(argv[0], pgm);

         /* process command-line options, if any */
         while ((ch = getopt(argc, argv, "a")) != EOF)
                 switch (ch) {
                 case 'a':
                         strcpy(openmode, "a");
                         break;
                 case '?':
                         break;
                 }
         n = argc -= optind;
         argv += optind;

         /* check for errors */
         if (argc > _NFILE) {
                 fprintf(stderr, "Too many files (max = %d)\n", _NFILE);
                 exit(1);
         }

         /* open the output file(s) */
         for (n = 0; n < argc; ++n) {
                 if ((fp[n] = fopen(argv[n], openmode)) == NULL) {
                         fprintf(stderr, "Cannot open %s\n", argv[n]);
                         continue;
                 }
         }

         /* copy input to stdout plus opened file(s) */
         while ((ch = getchar()) != EOF) {
                 putchar(ch);
                 for (n = 0; n < argc; ++n)
                         if (fp[n] != NULL)
                                 fputc(ch, fp[n]);
         }

         /* close file(s) */
         if (fcloseall() == -1) {
                 fprintf(stderr, "Error closing a file\n");
                 exit(2);
         }

         exit(0);
 }


 TIMEDATA.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\04STDLIB\TIMEDATA.C

 /*
  *        timedata -- time zone and time value tests
  */

 #include <stdio.h>
 #include <time.h>

 main()
 {
         long now;
         struct tm *tbuf;

         /* get TZ data into global variables */
         tzset();

         /* display the global time values */
         printf("daylight savings time flag = %d\n", daylight);
         printf("difference (in seconds) from GMT = %ld\n", timezone);
         printf("standard time zone string is %s\n", tzname[0]);
         printf("daylight time zone string is %s\n", tzname[1]);

         /*
          *  display the current date and time values for
          *  local and universal time
          */
         now = time(NULL);
         printf("\nctime():\t%s\n", ctime(&now));
         tbuf = localtime(&now);
         printf("local time:\t%s\n", asctime(tbuf));
         tbuf = gmtime(&now);
         printf("universal time:\t%s\n", asctime(tbuf));

         exit(0);
 }


 TIMER.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\TIMER.C

 /*
  *        timer -- general purpose timer program; uses the
  *        PC's intra-application communication area (ICA) as
  *        a time and date buffer
  */

 #include <dos.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <memory.h>
 #include <local\std.h>

 #define NBYTES                16
 #define ICA_SEG        0x4F
 #define MAXTNUM                3
 #define TIMEMASK        0x3FFFFFFF
 #define FLAGBIT                0x80000000
 #define IDBIT                0x40000000

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int ch;
         char *cp;
         int tn;                        /* timer number */
         int errflag;                /* error flag */
         int eflag;                /* elapsed time flag */
         int sflag;                /* start timer flag */
         char dest[MAXPATH + 1];        /* destination file name */
         char timestr[MAXLINE];        /* buffer for elapsed time string */
         long now;                /* current time */
         long then;                /* previously recorded time */
         FILE *fout;
         unsigned long tdata[MAXTNUM];

         struct SREGS segregs;

         static char pgm[MAXNAME + 1] = { "timer" };

         static void usage(char *, char *);
         extern char interval(long, char *);
         extern char *getpname(char *, char *);
         extern int getopt(int, char **, char *);
         extern int optind, opterr;
         extern char *optarg;

         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* process optional arguments */
         fout = stdout;
         tn = 0;
         errflag = eflag = sflag = 0;
         while ((ch = getopt(argc, argv, "0123ef:s")) != EOF) {
                 switch (ch) {
                 case 'e':
                         /* report elapsed timing */
                         ++eflag;
                         break;
                 case 'f':
                         /* use specified log file or stream */
                         strcpy(dest, optarg);
                         if ((fout = fopen(dest, "a")) == NULL) {
                                 fprintf(stderr, "%s: Cannot open %s\n",
                                         pgm, dest);
                                 exit(1);
                         }
                         break;
                 case 's':
                         /* start (or restart) timing an interval */
                         ++sflag;
                         break;
                 case '0':
                 case '1':
                 case '2':
                 case '3':
                         /* use specified timer */
                         tn = ch - 0x30;
                         break;
                 case '?':
                         /* bad option flag */
                         ++errflag;
                         break;
                 }
         }
         argc -= optind;
         argv += optind;

         /* check for errors */
         if (errflag > 0 || argc > 0)
                 usage(pgm, "Bad command line option(s)");

         segread(&segregs);

         /* report current date and time */
         now = time(NULL);
         fprintf(fout, "%s", ctime(&now));

         /* control and report timer data */
         if (eflag) {
                 /* report elapsed time for specified timer */
                 movedata(ICA_SEG, 0, segregs.ds, tdata, NBYTES);
                 then = tdata[tn];
                 if ((then & FLAGBIT) != FLAGBIT || (then & IDBIT) != IDBIT) {
                         fprintf(stderr, "Timer database corrupted or not set\
                         exit(1);
                 }
                 interval(now - (then & TIMEMASK), timestr);
                 fprintf(stdout, "Elapsed time = %s\n", timestr);
         }
         if (sflag) {
                 /* start (or restart) specified timer */
                 movedata(ICA_SEG, 0, segregs.ds, tdata, NBYTES);
                 tdata[tn] = (now & TIMEMASK) | FLAGBIT | IDBIT;
                 movedata(segregs.ds, tdata, ICA_SEG, 0, NBYTES);
         }
         fputc('\n', fout);

         exit(0);
 }

 /*
  *        usage -- display a usage message and exit
  *        with an error indication
  */

 static void
 usage(pname, mesg)
 char *pname;
 char *mesg;
 {
         fprintf(stderr, "%s\n", mesg);
         fprintf(stderr, "Usage: %s [-efs#]\n", pname);
         fprintf(stderr, "\t-e \tshow an elapsed time (must use start first)\n
         fprintf(stderr, "\t-f file\tappend output to specified file\n");
         fprintf(stderr, "\t-s \tstart (or restart) an interval timer\n");
         fprintf(stderr, "\t-# \tselect a timer (0 to 3; default is 0)\n");
         exit(2);
 }


 TONE.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\TONE.C

 /*
  *        tone -- set the frequency of the sound generator
  */

 #include <stdio.h>

 main(argc, argv)
 int argc;
 char **argv;
 {
         extern void setfreq(unsigned int);

         if (argc != 2) {
                 fprintf(stderr, "Usage: tone hertz\n");
                 exit(1);
         }

         /* set the frequency in Hertz */
         setfreq(atoi(*++argv));
         exit(0);
 }


 TOUCH.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\08FILE\TOUCH.C

 /*
  *        touch -- update modification time of file(s)
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <sys\utime.h>
 #include <io.h>
 #include <errno.h>
 #include <local\std.h>

 /* error return -- big enough not to be mistaken for a bad file count */
 #define ERR        0x7FFF

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int ch;
         int i;
         int badcount;                /* # of files that can't be updated */
         struct stat statbuf;        /* buffer for stat results */
         BOOLEAN errflag,        /* error flag */
                 cflag,                /* creation flag */
                 vflag;                /* verbose flag */
         FILE *fp;

         static char pgm[MAXNAME + 1] = { "touch" };
         extern int getopt(int, char **, char *);
         extern int optind, opterr;
         extern char *optarg;
         extern void getpname(char *, char *);
         static void usage(char *);

         /* get program name from DOS (version 3.00 and later) */
         if (_osmajor >= 3)
                 getpname(argv[0], pgm);

         /* process optional arguments first */
         errflag = cflag = vflag = FALSE;
         badcount = 0;
         while ((ch = getopt(argc, argv, "cv")) != EOF)
                 switch (ch) {
                 case 'c':
                         /* don't create files */
                         cflag = TRUE;
                         break;
                 case 'v':
                         /* verbose -- report activity */
                         vflag = TRUE;
                         break;
                 case '?':
                         errflag = TRUE;
                         break;
                 }
         argc -= optind;
         argv += optind;

         /* check for errors including no file names */
         if (errflag == TRUE || argc <= 0) {
                 usage(pgm);
                 exit(ERR);
         }

         /* update modification times of files */
         for (; argc-- > 0; ++argv) {
                 if (stat(*argv, &statbuf) == -1) {
                         /* file doesn't exist */
                         if (cflag == TRUE) {
                                 /* don't create it */
                                 ++badcount;
                                 continue;
                         }
                         else if ((fp = fopen(*argv, "w")) == NULL) {
                                 fprintf(stderr, "%s: Cannot create %s\n",
                                         pgm, *argv);
                                 ++badcount;
                                 continue;
                         }
                         else {
                                 if (fclose(fp) == EOF) {
                                         perror("Error closing file");
                                         exit(ERR);
                                 }
                                 if (stat(*argv, &statbuf) == -1) {
                                         fprintf(stderr, "%s: Cannot stat %s\n
                                         ++badcount;
                                         continue;
                                 }
                         }
                 }
                 if (utime(*argv, NULL) == -1) {
                         ++badcount;
                         perror("Error updating date/time stamp");
                         continue;
                 }
                 if (vflag == TRUE)
                         fprintf(stderr, "Touched file %s\n", *argv);
         }

         exit(badcount);
 } /* end main() */

 /*
  *        usage -- display an informative usage message
  */

 static void
 usage(pname)
 char *pname;
 {
         fprintf(stderr, "Usage: %s [-cv] file ...\n", pname);
         fprintf(stderr, "\t-c  Do not create any files\n");
         fprintf(stderr, "\t-v  Verbose mode -- report activities\n");
 } /* end usage() */

 /*
  *        dummy functions to show how to save a little space
  */

 _setenvp()
 {
 }

 #ifndef DEBUG
 _nullcheck()
 {
 }
 #endif


 TSTREPLY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\06USER\TSTREPLY.C

 /*
  *        tstreply -- test the getreply function
  */

 #include <stdio.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\video.h>
 #include "linebuf.h"

 #define INPUT_ROW        0
 #define INPUT_COL        40
 #define WIDTH                40

 int Apage = 0;
 BOOLEAN Silent = FALSE;

 main(argc, argv)
 int argc;
 char *argv[];
 {
         unsigned int r, c, ch, attr, revattr;
         char reply[MAXPATH + 1];
         LINEBUF buf;

         extern char *getreply(short, short, short,
                 char *, LINEBUF *, short, short, short);

         /* process command line */
         if (argc == 2 && strcmp(argv[1], "-s") == 0)
                 Silent = TRUE;
         else if (argc > 2) {
                 fprintf(stderr, "Usage: tstreply [-s]\n");
                 exit(1);
         }

         /* initial setup */
         getstate();
         readca(&ch, &attr, Apage);
         revattr = ((attr << 4) | (attr >> 4)) & 0x77;
         clrscrn(attr);
         putcur(0, 0, Apage);
         writestr("TSTREPLY", Apage);
         putcur(1, 0, Apage);
         writec(HLINE, Maxcol[Vmode] - 1, Apage);
         buf.l_buf = reply;
         buf.l_next = buf.l_prev = (LINEBUF *)NULL;

         /* demo getreply() */

         if (getreply(INPUT_ROW, INPUT_COL, WIDTH, "File: ", &buf,
                 MAXPATH, revattr, 0) == NULL) {
                 putcur(INPUT_ROW, INPUT_COL, Apage);
                 writeca(' ', attr, WIDTH, Apage);
                 putcur(2, 0, Apage);
                 fprintf(stderr, "input aborted\n");
                 exit(1);
         }
         putcur(INPUT_ROW, INPUT_COL, Apage);
         writeca(' ', attr, WIDTH, Apage);
         putcur(2, 0, Apage);
         fprintf(stderr, "reply = %s\n", reply);
         exit(0);
 }

 #define MSG_ROW        24
 #define MSG_COL        0

 int
 errmsg(mesg)
 char *mesg;
 {
         int n;
         extern void sound(unsigned int, float);

         putcur(MSG_ROW, MSG_COL, Apage);
         if ((n = strlen(mesg)) > 0) {
                 writestr(mesg, Apage);
                 if (Silent == FALSE)
                         sound(100, 0.2);
         }
         else
                 writec(' ', Maxcol[Vmode] - 1 - MSG_COL, Apage);
         return (n);
 }


 TSTSEL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\07CONFIG\TSTSEL.C

 /*
  *        tstsel -- test driver for the "select" functions
  */

 #include <stdio.h>
 #include <local\std.h>

 #define MAXTEST        20
 #define NRANGES        10
 #define NDIGITS        5

 extern struct slist_st {
         long int s_min;
         long int s_max;
 } Slist[NRANGES + 1];

 main (argc, argv)
 int argc;
 char **argv;
 {
         int i;
         extern int mkslist(char *);
         extern int selected(unsigned int);
         static void showlist();

         if (argc != 2) {
                 fprintf(stderr, "Usage: tstsel list\n");
                 exit(1);
         }
         printf("argv[1] = %s\n", argv[1]);
         mkslist(argv[1]);
         showlist();
         for (i = 0; i < MAXTEST; ++i)
                 printf("%2d -> %s\n", i, selected(i) ? "YES" : "NO");
         exit(0);
 }

 /*
  *        showlist -- display the contents of the select list
  */

 static void
 showlist()
 {
         int i;

         /* scan the selection list and display values */
         for (i = 0; i <= NRANGES; ++i)
                 printf("%2d %5ld %5ld\n", i, Slist[i].s_min, Slist[i].s_max);
 }


 USERATTR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\13ANSI\USERATTR.C

 /*
  *        userattr -- set video attributes to user-specified values
  *        (DOS environment parameters) or to reasonable defaults and
  *        return success or a failure indication for bad attributes
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\ansi.h>
 #include <local\ibmcolor.h>

 int
 userattr(foreground, background, border)
 char *foreground, *background, *border;
 {
         register char *s;
         static int attrset(POSITION, char *);

         if ((s = getenv("FGND")) == NULL)
                 s = foreground;
         if (attrset(FGND, s) == -1)
                 return FAILURE;

         if ((s = getenv("BKGND")) == NULL)
                 s = background;
         if (attrset(BKGND, s) == -1)
                 return FAILURE;

         if ((s = getenv("BORDER")) == NULL)
                 s = border;
         if (attrset(BDR, s) == -1)
                 return FAILURE;

         return SUCCESS;
 }

 /*
  *        attrset -- parse the color spec and try to set it.
  *        return 0 if OK and -1 upon error (bad color number)
  */
 static int
 attrset(apos, str)
 POSITION apos;
 register char *str;
 {
         register int attr;
         extern int colornum(char *);
         extern void setattr(POSITION, int);

         if ((attr = colornum(strtok(str, " \t"))) == IBM_BRIGHT)
                 attr |= colornum(strtok(NULL, " \t"));
         if (attr >= 0)
                 setattr(apos, attr);
         else
                 return (-1);
         return (0);
 }


 VER.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\DOS\VER.C

 /*
  *        ver -- get the MS-DOS (or PC-DOS) version number
  */

 #include <local\doslib.h>

 /************************************************************
 *  For MS-DOS versions prior to 2.00, the low byte (AL) of
 *  the return value is zero.  For versions 2.00 and beyond,
 *  the low byte is the major version number and the high
 *  byte (AH) is the minor version number.
 ************************************************************/

 int ver()
 {
         return(bdos(DOS_VERSION, 0, 0));
 }


 VF.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\VF.C

 /*
  *        vf -- view a file using a full-screen window onto
  *        an in-memory text file buffer
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\video.h>
 #include "vf.h"

 extern int setctype(int, int);
 int Startscan, Endscan;        /* cursor scan line range */
 unsigned char Attr;        /* primary display attribute */
 unsigned char Revattr;        /* reverse video for highlighting */
 unsigned char Usrattr;        /* user's original attribute */

 main(argc, argv)
 int argc;
 char **argv;
 {
         int ch;
         unsigned char chr;
         BOOLEAN errflag;
         BOOLEAN numbers;
         int errcode;
         FILE *fp;
         extern char *optarg;
         extern int optind;
         static char pgm[MAXNAME + 1] = { "vf" };

         /* function prototypes */
         void clean();
         extern clrscrn(unsigned char);
         extern void getpname(char *, char *);
         extern void fixtabs(int);
         extern void initmsg(int, int, int, unsigned char, int);
         extern int getopt(int, char **, char *);
         extern int vf_cmd(FILE *, char *, BOOLEAN);
         extern int readca(unsigned char *, unsigned char *, unsigned int);
         extern int getctype(int *, int *, int);

         errcode = 0;
         fixtabs(TABWIDTH);

         /* get program name from DOS (version 3.00 and later) */
         if (_osmajor >= 3)
                 getpname(*argv, pgm);

         /* be sure we have needed DOS support */
         if (_osmajor < 2) {
                 fprintf(stderr, "%s requires DOS 2.00 or later\n", pgm);
                 exit(1);
         }

         /* process optional arguments first */
         errflag = numbers = FALSE;
         while ((ch = getopt(argc, argv, "n")) != EOF)
                 switch (ch) {
                 case 'n':
                         /* turn on line numbering */
                         numbers = TRUE;
                         break;
                 case '?':
                         /* bad option */
                         errflag = TRUE;
                         break;
                 }

         /* check for command-line errors */
         argc -= optind;
         argv += optind;
         if (errflag == TRUE || argc == 0) {
                 fprintf(stderr, "Usage: %s [-n] file...\n", pgm);
                 exit(1);
         }

         /* get current video attribute and set VF attributes */
         getstate();
         readca(&chr, &Usrattr, Vpage);        /* save user's attribute settin
         /*
          * These colors are modified from those presented in the
          * book so that VF will work on all monochrome and
          * color systems the same way -- change them to suit
          * your own shade of reality and operating conditions
          */
         Attr = Usrattr;                        /* basic text attributes */
         /* reverse video for highlighting */
         Revattr = ((Attr & 0x7) << 4) | (Attr >> 4);
         clrscrn(Attr);

         /* save user's cursor shape and turn cursor off */
         getctype(&Startscan, &Endscan, Vpage);
         setctype(MAXSCAN, MAXSCAN);

         /* set up the message line manager */
         initmsg(MSGROW, MSGCOL, Maxcol[Vmode] - MSGCOL, Attr, Vpage);

         /* display first screen page */
         putcur(0, 0, Vpage);
         putstr("ViewFile/1.0  H=Help Q=Quit Esc=Next", Vpage);
         putcur(1, 0, Vpage);
         writea(Revattr, Maxcol[Vmode], Vpage);

         for (; argc-- > 0; ++argv) {
                 if ((fp = fopen(*argv, "r")) == NULL) {
                         fprintf(stderr, "%s: cannot open %s -- ", pgm, *argv)
                         perror("");
                         ++errcode;
                         continue;
                 }
                 if (vf_cmd(fp, *argv, numbers) != 0)
                         break;
                 fclose(fp);
         }
         clean();
         exit(errcode);
 }


 /*
  *        clean -- restore the user's original conditions
  */

 void
 clean()
 {
         /* set screen to user's attribute */
         clrscrn(Usrattr);
         putcur(0, 0, Vpage);

         /* restore user's cursor shape */
         setctype(Startscan, Endscan);
 }


 VF_CMD.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\VF_CMD.C

 /*
  *        vf_cmd -- ViewFile command processor
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <local\std.h>
 #include <local\keydefs.h>
 #include <local\video.h>
 #include "vf.h"
 #include "message.h"

 extern unsigned char Attr;

 int
 vf_cmd(fp, fname, numbers)
 FILE *fp;
 char *fname;
 BOOLEAN numbers;
 {
         register int i;                /* general index */
         unsigned int offset;        /* horizontal scroll offset */
         unsigned int n;                /* relative line number */
         int memerr;                /* flag for memory allocation errors */
         char *s, lbuf[MAXLINE];        /* input line buffer and pointer */
         int k;                        /* key code (see keydefs.h) */
         int radix = 10;                /* base for number-to-character conver
         char number[17];        /* buffer for conversions */
         int errcount = 0;        /* error counter */
         DNODE *tmp;                /* pointer to buffer control nodes */
         DIRECTION srchdir;        /* search direction */
         char *ss;                /* pointer to search string */
         static char srchstr[MAXSTR] = { "" };        /* search string buffer
         DNODE *head;                /* pointer to starting node of text buffe
         DNODE *current;                /* pointer to the current node (text l
         static DNODE *freelist;        /* pointer to starting node of "free"
                                 /* initialized to 0 at runtime; retains value

         /* function prototypes */
         static void prtshift(int, int);
         extern DNODE *vf_mklst();
         extern DNODE *vf_alloc(int);
         extern DNODE *vf_ins(DNODE *, DNODE *);
         extern DNODE *vf_del(DNODE *, DNODE *);
         extern DNODE *search(DNODE *, DIRECTION, char *);
         extern DNODE *gotoln(DNODE *);
         extern char *getxline(char *, int, FILE *);
         extern char *getsstr(char *);
         extern int clrscrn(unsigned char);
         extern void showhelp(unsigned char);
         extern void clrmsg();
         extern void vf_dspy(DNODE *, DNODE *, int, BOOLEAN);
         extern int putstr(char *, int);
         extern int writec(char, int, int);
         extern char *nlerase(char *);

         /* display the file name */
         offset = 0;
         putcur(HEADROW, 0, Vpage);
         writec(' ', Maxcol[Vmode], Vpage);
         putstr("File: ", Vpage);
         putstr(fname, Vpage);

         /* establish the text buffer */
         memerr = 0;
         if ((head = vf_mklst()) == NULL)
                 ++memerr;
         if (freelist == NULL && (freelist = vf_alloc(N_NODES)) == NULL)
                 ++memerr;
         if (memerr) {
                 clean();
                 fprintf(stderr, "Memory allocation error\n");
                 exit(1);
         }

         /* read the file into the buffer */
         current = head;
         n = 0;
         while ((s = getxline(lbuf, MAXLINE, fp)) != NULL) {
                 /* add a node to the list */
                 if ((freelist = vf_ins(current, freelist)) == NULL)
                         ++memerr;
                 current = current->d_next;

                 /* save the received text in a line buffer */
                 if ((current->d_line = strdup(nlerase(s))) == NULL)
                         ++memerr;
                 if (memerr) {
                         clean();
                         fprintf(stderr, "File too big to load\n");
                         exit(1);
                 }
                 current->d_lnum = ++n;
                 current->d_flags = 0;
         }

         /* show the file size as a count of lines */
         putstr(" (", Vpage);
         putstr(itoa(current->d_lnum, number, radix), Vpage);
         putstr(" lines)", Vpage);
         prtshift(offset, Vpage);
         current = head->d_next;
         vf_dspy(head, current, offset, numbers);

         /* process user commands */
         while ((k = getkey()) != K_ESC) {
                 clrmsg();
                 switch (k) {
                 case 'b':
                 case 'B':
                 case K_HOME:
                         current = head->d_next;
                         break;
                 case 'e':
                 case 'E':
                 case K_END:
                         current = head->d_prev;
                         i = NROWS - 1;
                         while (i-- > 0)
                                 if (current->d_prev != head->d_next)
                                         current = current->d_prev;
                         break;
                 case K_PGUP:
                 case 'u':
                 case 'U':
                         i = NROWS - OVERLAP;
                         while (i-- > 0)
                                 if (current != head->d_next)
                                         current = current->d_prev;
                         break;
                 case K_PGDN:
                 case 'd':
                 case 'D':
                         i = NROWS - OVERLAP;
                         while (i-- > 0)
                                 if (current != head->d_prev)
                                         current = current->d_next;
                         break;
                 case K_UP:
                 case '-':
                         if (current == head->d_next)
                                 continue;
                         current = current->d_prev;
                         break;
                 case K_DOWN:
                 case '+':
                         if (current == head->d_prev)
                                 continue;
                         current = current->d_next;
                         break;
                 case K_RIGHT:
                 case '>':
                 case '.':
                         if (offset < MAXLINE - SHIFTWIDTH)
                                 offset += SHIFTWIDTH;
                         prtshift(offset, Vpage);
                         break;
                 case K_LEFT:
                 case '<':
                 case ',':
                         if ((offset -= SHIFTWIDTH) < 0)
                                 offset = 0;
                         prtshift(offset, Vpage);
                         break;
                 case K_ALTG:
                 case 'g':
                 case 'G':
                         if ((tmp = gotoln(head)) == NULL)
                                 continue;
                         current = tmp;
                         break;
                 case K_ALTH:
                 case 'h':
                 case 'H':
                 case '?':
                         showhelp(Attr);
                         break;
                 case K_ALTN:
                 case 'n':
                 case 'N':
                         numbers = (numbers == TRUE) ? FALSE : TRUE;
                         break;
                 case K_ALTQ:
                 case 'q':
                 case 'Q':
                         clrscrn(Attr);
                         putcur(0, 0, Vpage);
                         return (-1);
                 case 'r':
                 case 'R':
                 case '\\':
                         srchdir = BACKWARD;
                         ss = getsstr(srchstr);
                         if (ss == NULL)
                                 /* cancel search */
                                 break;
                         if (strlen(ss) > 0)
                                 strcpy(srchstr, ss);
                         if ((tmp = search(current, srchdir, srchstr)) == NULL
                                 continue;
                         current = tmp;
                         break;
                 case 's':
                 case 'S':
                 case '/':
                         srchdir = FORWARD;
                         ss = getsstr(srchstr);
                         if (ss == NULL)
                                 /* cancel search */
                                 break;
                         if (strlen(ss) > 0)
                                 strcpy(srchstr, ss);
                         if ((tmp = search(current, srchdir, srchstr)) == NULL
                                 continue;
                         current = tmp;
                         break;
                 default:
                         /* ignore all other keys */
                         continue;
                 }
                 vf_dspy(head, current, offset, numbers);
         }
         clrmsg();

         /* release the allocated text buffer memory */
         while (head->d_next != head) {
                 /* release text buffer */
                 free(head->d_next->d_line);

                 /* put node back on the freelist */
                 freelist = vf_del(head->d_next, freelist);
         }
         /* release the list header node */
         free((char *)head);

         return (errcount);
 }

 /*
  *        prtshift -- display the number of columns of horizontal shift
  */

 #define SHFTDSP        5

 static void
 prtshift(amt, pg)
 int amt, pg;
 {
         char number[17];
         int radix = 10;

         /* clear the shift display area */
         putcur(1, Maxcol[Vmode] - 1 - SHFTDSP, pg);
         writec(' ', SHFTDSP, pg);

         /* display the new shift amount, if any */
         if (amt > 0) {
                 putstr(itoa(amt, number, radix), pg);
                 putstr("->", pg);
         }
 }


 VF_DSPY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\VF_DSPY.C

 /*
  *        vf_dspy -- display a screen page
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <local\video.h>
 #include <local\std.h>
 #include <local\bioslib.h>
 #include "vf.h"

 /* number field width */
 #define NFW        8

 void
 vf_dspy(buf, lp, os, numbers)
 DNODE *buf;
 register DNODE *lp;
 int os;
 BOOLEAN numbers;
 {
         register int i;
         int j;
         int textwidth;
         char *cp;
         char nbuf[NFW + 1];

         textwidth = Maxcol[Vmode];
         if (numbers == TRUE)
                 textwidth -= NFW;

         for (i = 0; i < NROWS; ++i) {
                 putcur(TOPROW + i, 0, Vpage);
                 cp = lp->d_line;
                 if (numbers == TRUE) {
                         sprintf(nbuf, "%6u", lp->d_lnum);
                         putfld(nbuf, NFW, Vpage);
                         putcur(TOPROW + i, NFW, Vpage);
                 }
                 if (os < strlen(cp))
                         putfld(cp + os, textwidth, Vpage);
                 else
                         writec(' ', textwidth, Vpage);
                 if (lp == buf->d_prev) {
                         ++i;
                         break;        /* no more displayable lines */
                 }
                 else
                         lp = lp->d_next;
         }

         /* clear and mark any unused lines */
         for ( ; i < NROWS; ++i) {
                 putcur(i + TOPROW, 0, Vpage);
                 writec(' ', Maxcol[Vmode], Vpage);
                 writec('~', 1, Vpage);
         }
         return;
 }


 VF_LIST.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\VF_LIST.C

 /*
  *        vf_list -- linked list management functions
  */

 #include <stdio.h>
 #include <malloc.h>
 #include "vf.h"

 /*
  *        vf_mklst -- create a new list by allocating a node,
  *        making it point to itself, and setting its values
  *        to zero (appropriately cast)
  */

 DNODE *
 vf_mklst()
 {
         DNODE *new;

         new = (DNODE *)malloc(sizeof (DNODE));
         if (new != NULL) {
                 new->d_next = new;
                 new->d_prev = new;
                 new->d_lnum = new->d_flags = 0;
                 new->d_line = (char *)NULL;
         }
         return (new);
 } /* end vf_mklst() */


 /*
  *        vf_alloc -- create a pool of available nodes
  */

 DNODE *
 vf_alloc(n)
 int n;
 {
         register DNODE *new;
         register DNODE *tmp;

         /* allocate a block of n nodes */
         new = (DNODE *)malloc(n * sizeof (DNODE));

         /* if allocation OK, string the nodes in one direction */
         if (new != NULL) {
                 for (tmp = new; 1 + tmp - new < n; tmp = tmp->d_next)
                         tmp->d_next = tmp + 1;
                 tmp->d_next = (DNODE *)NULL;
         }

         return (new);        /* pointer to free list */
 } /* end vf_alloc() */


 /*
  *        vf_ins -- insert a node into a list after the specified node
  */

 DNODE *
 vf_ins(node, avail)
 DNODE *node, *avail;
 {
         DNODE *tmp;
         DNODE *vf_alloc(int);

         /*
          *  check freelist -- get another block of nodes
          *  if the list is almost empty
          */
         if (avail->d_next == NULL)
                 if ((avail->d_next = vf_alloc(N_NODES)) == NULL)
                         /* not enough memory */
                         return (DNODE *)NULL;

         /* get a node from the freelist */
         tmp = avail;
         avail = avail->d_next;

         /* insert the node into the list after node */
         tmp->d_prev = node;
         tmp->d_next = node->d_next;
         node->d_next->d_prev = tmp;
         node->d_next = tmp;

         /* point to next node in the freelist */
         return (avail);
 } /* end vf_ins() */


 /*
  *        vf_del -- delete a node from a list
  */

 DNODE *
 vf_del(node, avail)
 DNODE *node, *avail;
 {
         /* unlink the node from the list */
         node->d_prev->d_next = node->d_next;
         node->d_next->d_prev = node->d_prev;

         /* return the deleted node to the freelist */
         node->d_next = avail;
         avail = node;

         /* point to the new freelist node */
         return (avail);
 } /* end vf_del() */


 VF_SRCH.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\VF_SRCH.C

 /*
  *        vf_srch -- search functions
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>
 #include "vf.h"

 /*
  *        search -- search for a literal string in the buffer
  */

 DNODE *
 search(buf, dir, str)
 DNODE *buf;
 DIRECTION dir;
 char *str;
 {
         int n;
         register DNODE *lp;
         register char *cp;

         extern void showmsg(char *);

         /* try to find a match -- wraps around buffer boundaries */
         n = strlen(str);
         lp = (dir == FORWARD) ? buf->d_next : buf->d_prev;
         while (lp != buf) {
                 if ((cp = lp->d_line) != NULL)        /* skip over header nod
                         while (*cp != '\n' && *cp != '\0') {
                                 if (strncmp(cp, str, n) == 0)
                                         return (lp);
                                 ++cp;
                         }
                 lp = (dir == FORWARD) ? lp->d_next : lp->d_prev;
         }
         showmsg("Not found");
         return ((DNODE *)NULL);
 }


 /*
  *        getsstr -- prompt the user for a search string
  */

 extern int Startscan, Endscan;

 char *
 getsstr(str)
 char *str;
 {
         char line[MAXSTR];
         char *resp;

         extern int putstr(char *, int);
         extern char *getstr(char *, int);
         extern int put_ch(char, int);
         extern void showmsg(char *);
         extern void clrmsg();

         static char prompt[] = { "Search for: " };

         /* get search string */
         showmsg(prompt);
         setctype(Startscan, Endscan);                /* cursor on */
         resp = getstr(line, MAXSTR - strlen(prompt));
         setctype(MAXSCAN, MAXSCAN);                /* cursor off */
         if (resp == NULL)
                 return (char *)NULL;
         if (strlen(resp) == 0)
                 return (str);
         showmsg(resp);
         return (resp);
 }


 VF_UTIL.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\14VIEW\VF_UTIL.C

 /*
  *        vf_util -- utility functions for ViewFile
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <local\std.h>
 #include <local\video.h>
 #include <local\keydefs.h>
 #include "vf.h"

 extern int Startscan, Endscan;

 #define NDIGITS        6

 /*
  *        gotoln -- jump to an absolute line number
  */

 DNODE *
 gotoln(buf)
 DNODE *buf;
 {
         register int ln;
         register DNODE *lp;
         char line[NDIGITS + 1];

         extern void showmsg(char *);
         extern char *getstr(char *, int);

         /* get line number from user */
         showmsg("Line number: ");
         setctype(Startscan, Endscan);                        /* cursor on */
         ln = atoi(getstr(line, NDIGITS + 1));
         setctype(MAXSCAN, MAXSCAN);                        /* cursor off */

         /* check boundary conditions */
         if (ln > buf->d_prev->d_lnum || ln <= 0) {
                 showmsg("Line out of range");
                 return ((DNODE *)NULL);
         }

         /* find the line */
         for (lp = buf->d_next; ln != lp->d_lnum; lp = lp->d_next)
                 ;
         return (lp);
 }


 /*
  *        showhelp -- display a help frame
  */

 #define HELPROW        TOPROW + 3
 #define HELPCOL        10
 #define VBORDER        1
 #define HBORDER        2

 void
 showhelp(textattr)
 unsigned char textattr;        /* attribute of text area */
 {
         register int i, n;
         int nlines, ncols;
         unsigned char helpattr;
         static char *help[] = {
                 "PgUp (U)        Scroll up the file one screen page",
                 "PgDn (D)        Scroll down the file one screen page",
                 "Up arrow (-)    Scroll up in the file one line",
                 "Down arrow (+)  Scroll down in the file one line",
                 "Right arrow (>) Scroll right by 20 columns",
                 "Left arrow (<)  Scroll left by 20 columns",
                 "Home (B)        Go to beginning of file buffer",
                 "End (E)         Go to end of file buffer",
                 "Alt-g (G)       Go to a specified line in the buffer",
                 "Alt-h (H or ?)  Display this help frame",
                 "Alt-n (N)       Toggle line-numbering feature",
                 "\\ (R)           Reverse search for a literal text string",
                 "/ (S)           Search forward for a literal text string",
                 "Esc             Next file from list (quits if none)",
                 "Alt-q (Q)       Quit",
                 "--------------------------------------------------------",
                 "            << Press a key to continue >>",
                 (char *)NULL
         };

         /* prepare help window */
         ncols = 0;
         for (i = 0; help[i] != (char *)NULL; ++i)
                 if ((n = strlen(help[i])) > ncols)
                         ncols = n;
         nlines = i - 1;
         --ncols;
         helpattr = (RED << 4) | BWHT;
         clrw(HELPROW - VBORDER, HELPCOL - HBORDER,
                 HELPROW + nlines + VBORDER, HELPCOL + ncols + HBORDER,
                 helpattr);
         drawbox(HELPROW - VBORDER, HELPCOL - HBORDER,
                 HELPROW + nlines + VBORDER, HELPCOL + ncols + HBORDER,
                 Vpage);

         /* display the help text */
         for (i = 0; help[i] != (char *)NULL; ++i) {
                 putcur(HELPROW + i, HELPCOL, Vpage);
                 putstr(help[i], Vpage);
         }

         /* pause until told by a keypress to proceed */
         getkey();

         /* restore help display area to the text attribute */
         clrw(HELPROW - VBORDER, HELPCOL - HBORDER,
                 HELPROW + nlines + VBORDER, HELPCOL + ncols + HBORDER,
                 textattr);
 }


 WARN.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\UTIL\WARN.C

 /*
  *        warn -- display a warning message in a highly
  *        visible place; return number of characters written
  */

 #include <stdio.h>

 int
 warn(pname, mesg)
 char *pname, *mesg;
 {
         return (fprintf(stderr, "%s: %s\n", pname, mesg));
 }


 WRITEA.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITEA.C

 /*
  *        writea -- write attribute only to screen memory (faked by
  *        reading char and attr and writing back the original
  *        character and the new attribute at each position)
  */

 #include <local\std.h>

 int writea(a, n, pg)
 unsigned char a;/* video attribute */
 int n;                /* number of positions to write */
 int pg;                /* screen page */
 {
         int i;
         int status;
         unsigned short chx, attrx;
         unsigned short r, c;

         /* get starting (current) position */
         status = 0;
         status = readcur(&r, &c, pg);
         for (i = 0; i < n; ++i) {
                 status += putcur(r, c + i, pg);
                 status += readca(&chx, &attrx, pg);
                 status += writeca(chx, a, 1, pg);
         }

         /* restore cursor position */
         status += putcur(r, c, pg);

         return (status);
 }


 WRITEC.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITEC.C

 /*
  *        writec -- write a character only
  *        (leave attribute undisturbed)
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 writec(ch, count, pg)
 unsigned char ch;        /* character */
 int count;                /* repetitions */
 int pg;                        /* screen page for writes */
 {
         union REGS inregs, outregs;

         inregs.h.ah = WRITE_CHAR;
         inregs.h.al = ch;
         inregs.h.bh = pg;
         inregs.x.cx = count;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 WRITECA.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITECA.C

 /*
  *        writeca -- write character and attribute to the screen
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 writeca(ch, attr, count, pg)
 unsigned char ch;        /* character */
 unsigned char attr;        /* attribute */
 int count;                /* number of repetitions */
 int pg;                        /* screen page for writes */
 {
         union REGS inregs, outregs;

         inregs.h.ah = WRITE_CHAR_ATTR;
         inregs.h.al = ch;
         inregs.h.bh = pg;
         inregs.h.bl = attr;
         inregs.x.cx = count;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 WRITEDOT.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITEDOT.C

 /*
  *        writedot -- display a dot at the specified position
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 writedot(r, c, color)
 int r, c;        /* row and column cordinate */
 int color;        /* dot (pixel) color */
 {
         union REGS inregs, outregs;

         inregs.h.ah = WRITE_DOT;
         inregs.h.al = color;
         inregs.x.cx = c;
         inregs.x.dx = r;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }


 WRITEMSG.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITEMSG.C

 /*
  *        writemsg -- displays a message in a field of the prevailing
  *        video attribute and returns the number of displayable message
  *        characters written; truncates the message if its too long
  *        to fit in the field
  */

 #include <stdio.h>
 #include <local\std.h>

 int writemsg(r, c, w, s1, s2, pg)
 int r, c, w ;
 char *s1, *s2;
 int pg;
 {
         int n = 0;
         char *cp;

         /* display first part of the message */
         if (s1 != NULL)
                 for (cp = s1; *cp != '\0' && n < w; ++n, ++cp) {
                         putcur(r, c + n, pg);
                         writec(*cp, 1, pg);
                 }

         /* display second part of the message */
         if (s2 != NULL)
                 for (cp = s2; *cp != '\0' && n < w; ++n, ++cp) {
                         putcur(r, c + n, pg);
                         writec(*cp, 1, pg);
                 }

         /* pad the remainder of the field, if any, with spaces */
         if (n < w) {
                 putcur(r, c + n, pg);
                 writec(' ', w - n, pg);
         }

         return (n);
 }


 WRITESTR.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITESTR.C

 /*
  *        writestr -- write a string in
  *        the prevailing video attribute
  */

 #include <local\std.h>

 int
 writestr(s, pg)
 register char *s;        /* string to write */
 unsigned int pg;        /* screen page for writes */
 {
         unsigned int r, c, c0;

         readcur(&r, &c, pg);
         for (c0 = c; *s != '\0'; ++s, ++c) {
                 putcur(r, c, pg);
                 writec(*s, 1, pg);
         }

         /* restore cursor position and return # of characters displayed */
         putcur(r, c0, pg);
         return (c - c0);
 }


 WRITETTY.C
 CD-ROM Disc Path:   \SAMPCODE\PROF_C\05OSLIB\BIOS\WRITETTY.C

 /*
  *        writetty -- write to screen using TTY interface
  */

 #include <dos.h>
 #include <local\std.h>
 #include <local\bioslib.h>

 int
 writetty(ch, attr, pg)
 unsigned char ch;        /* character */
 unsigned char attr;        /* video attribute */
 int pg;                        /* screen page for writes */
 {
         union REGS inregs, outregs;

         inregs.h.ah = WRITE_TTY;
         inregs.h.al = ch;
         inregs.h.bl = attr;
         inregs.h.bh = pg;
         int86(VIDEO_IO, &inregs, &outregs);

         return (outregs.x.cflag);
 }
 Quick-C Programming - Sample Code


 12_10A.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\12_10A.C

 #include "texed.h"
 menu()
 {
     struct key_struct *kp, *Read_kbd();
     int cur_key, cur_move;

     kp = Read_kbd();
     cur_key = kp->key;
     cur_move = kp->move;
     if (cur_key == ERROR)
         return (cur_move);
     return (cur_key);
 }


 12_10B.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\12_10B.C

 #include "texed.h"
 struct key_struct *Read_key()
 {
     struct key_struct k;

     k.key = getch();
     if (k.key == ERROR)
     k.move = getch();
         return (&k);
 }


 12_8A.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\12_8A.C

 #define OK 1
 #define ERROR 0
 menu()
 {
     struct key_struct {
         char key;
         unsigned char move;
     } *kp, *Read_kbd();
     int cur_key, cur_move;

     kp = Read_kbd();
     cur_key = kp->key;
     cur_move = kp->move;
     if (cur_key == ERROR)
         return (cur_move);
     return (cur_key);
 }


 12_8B.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\12_8B.C

 #define OK 1
 #define ERROR 0
 struct key_struct {
     char key;
     unsigned char move;
 };

 struct key_struct *Read_key()
 {
     struct key_struct k;

     k.key = getch();
     if (k.key == ERROR)
         k.move = getch();
     return (&k);
 }


 ACME.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\ACME.C

 /* acme.c  --     illustrate an assortment of the     */
 /*                C library string-handling routines  */

 <stdio.h>         /* for NULL */
 <string.h>        /* for strchr(), et al */

 #define NAME_PATTERN \
 "first<space>last  or\n\
 first<space>middle<space>last"

 #define ADDRESS_PATTERN \
 "number<space>street<comma><space>city<comma>"

 char Buf[BUFSIZ];        /* global I/O buffer */

 main()
 {
     char *ocp, *cp, *first, *last, *street, *city;
     void Prompt(), Cant();

     printf("Acme Employment Questionaire\n");

     /*
      * Expect first<space>last or
      *        first<space>middle<space>last
      */
     Prompt("Full Name");
      /* search forward for a space */
     if ((cp = strchr(Buf,' ')) == NULL)
         Cant("First Name", NAME_PATTERN);
     *cp = '\0';
     first = strdup(Buf);
     *cp = ' ';

      /* Search back from end for a space */
     if ((cp = strrchr(Buf,' ')) == NULL)
         Cant("Last Name", NAME_PATTERN);
     last = strdup(++cp);

     /*
      * Expect number<space>street<comma><space>city<comma>
      */
     Prompt("Full Address");
      /* search forward for a comma */
     if ((cp = strchr(Buf,',')) == NULL)
         Cant("Street", ADDRESS_PATTERN);
     *cp = '\0';
     street = strdup(Buf);

      /* Search forward from last comma for next comma */
     if ((ocp = strchr(++cp,',')) == NULL)
         Cant("City", ADDRESS_PATTERN);
     *ocp = '\0';
     city = strdup(++cp);

     printf("\n\nYou Entered:\n");
     printf("\tFirst Name: \"%s\"\n", first);
     printf("\tLast Name:  \"%s\"\n", last);
     printf("\tStreet:     \"%s\"\n", street);
     printf("\tCity:       \"%s\"\n", city);

 }

 void Cant(char *what, char *pattern)
 {
     printf("\n\n\bFormat Error!!!\n");
     printf("Can't parse your %s.\n", what );
     printf("Expected an entry of the form:\n\n");
     printf("%s\n\nAborted\n", pattern);
     exit(1);
 }

 void Prompt(char *str)
 {
     while (1)
         {
         printf("\n%s: ", str );
         if (gets(Buf) == NULL || *Buf == '\0')
             {
             printf("Do you wish to quit? ");
             if (gets(Buf) == NULL || *Buf == 'y')
                 exit (0);
             continue;
             }
         break;
         }
 }


 ALERT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\ALERT.C

 /* alert.c -- sounds alarm by calling a        */
 /*            beep() function with a parameter */

 main()
 {
     void beep(times);  /* function declaration */
     printf("*** Alert! Alert! ***\n");
     beep(3);     /* call beep() with parameter */
 }

 void beep(times)
     int times;   /* declare function parameter */
 {
     int count;

     /* check that parameter is between 1 and 4 */
     if ((times < 1) || (times > 4))
         {
         printf("Error in beep(): %d beeps specified.\n",
                 times);
         printf("Specify one to four beeps");
         }
     else /* sound the beeps */
         for (count = 1; count <= times; count++)
             printf("\a");  /* "alert" escape sequence */
 }


 ALLCOLOR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\ALLCOLOR.C

 /* allcolor.c -- shows _ERESCOLOR 64-color palette     */
 /* If you load graphics.qlb, no program list is needed.*/

 /*  Hit <g> to advance left palette, <G> to go back.   */
 /*  Hit <h> to advance right palette, <H> to go back.  */
 /*  Hit <Esc> to quit                                  */
 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>
 #define MAXCOLORS 64
 #define ESC '\033'
 long Ega_to_vga(int);   /* color value conversion */

 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _ERESCOLOR;
     int xmax, ymax;
     int c1 = 1;
     int c2 = 4;
     char left[11];
     char right[11];
     int lpos, rpos;
     char ch;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
     {
         fprintf(stderr,"%d mode not supported\n", mode);
         exit(1);
     }
     _getvideoconfig(&vc);
     _setlogorg(vc.numxpixels/2, vc.numypixels/2);

     xmax = vc.numxpixels / 2 - 1;
     ymax = vc.numypixels / 2 - 1;
     lpos = vc.numxpixels/32 - 5;
     rpos = lpos + vc.numxpixels / 16;
     _setcolor(1);
     _rectangle(_GFILLINTERIOR, -xmax, -ymax, 0, ymax);
     _setcolor(4);
     _rectangle(_GFILLINTERIOR, 1, -ymax, xmax, ymax);
     sprintf(left,"<-G %2d g->", c1);
     sprintf(right,"<-H %2d h->", c2);
     _settextcolor(6);
     _settextposition(0, 0);
     _outtext("Press Esc to quit");
     _settextposition(24, lpos);
     _outtext(left);
     _settextposition(24, rpos);
     _outtext(right);
     while ((ch = getch()) != ESC)
     {
         switch (ch)
         {
             case 'g': c1 = (c1 + 1) % MAXCOLORS;
                       _remappalette(1, Ega_to_vga(c1));
                       break;
             case 'G': c1 = (c1 - 1) % MAXCOLORS;
                       _remappalette(1, Ega_to_vga(c1));
                       break;
             case 'h': c2 = (c2 + 1) % MAXCOLORS;
                       _remappalette(4, Ega_to_vga(c2));
                       break;
             case 'H': c2 = (c2 - 1) % MAXCOLORS;
                       _remappalette(4, Ega_to_vga(c2));
                       break;
         }
         sprintf(left,"<-G %2d ->g", c1);
         sprintf(right,"<-H %2d ->h", c2);
         _settextposition(0, 0);
         _outtext("Press Esc to quit");
         _settextposition(24, lpos);
         _outtext(left);
         _settextposition(24, rpos);
         _outtext(right);
     }
     _setvideomode(_DEFAULTMODE);
 }
 long Ega_to_vga(egacolor)
 int egacolor;       /* ega color value */
 {
     static long vgavals[6] = {0x2A0000L, 0x002A00L, 0x00002AL,
                               0x150000L, 0x001500L, 0x000015L};
     long vgacolor = 0L; /* vga color value */
     int bit;

     for (bit = 0; bit < 6; bit++)
         vgacolor += ((egacolor >> bit) &1) * vgavals[bit];
     return (vgacolor);
 }


 ALLVGA.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\ALLVGA.C

 /* allvga.c -- shows _MRES256COLOR 256K colors         */
 /* If you load graphics.qlb, no program list is needed.*/

 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <conio.h>
 #define FULLBRIGHT 64
 #define ESC '\033'
 char label[2][7] = {"ACTIVE", "      "};

 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _MRES256COLOR;
     int xmax, ymax;
     static long colors[2] = {_BLUE, _RED};
     char left[11];
     char right[11];
     int lpos, rpos;
     char ch;
     unsigned long blue = _BLUE >> 16;
     unsigned long green = 0L;
     unsigned long red = 0L;
     long color;
     short palnum = 0;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
         {
         fprintf(stderr,"%d mode not supported\n", mode);
         exit(1);
         }
     _getvideoconfig(&vc);
     _setlogorg(vc.numxpixels/2, vc.numypixels/2);

     xmax = vc.numxpixels / 2 - 1;
     ymax = vc.numypixels / 2 - 1;
     lpos = vc.numxpixels / 32 - 5;
     rpos = lpos + vc.numxpixels/16;
     _remappalette(2, _RED);
     _setcolor(1);
     _rectangle(_GFILLINTERIOR, -xmax, -ymax, 0, ymax);
     _setcolor(2);
     _rectangle(_GFILLINTERIOR, 1, -ymax, xmax, ymax);
     sprintf(left," %6lxH ", colors[0]);
     sprintf(right," %6lxH ", colors[1]);
     _settextcolor(6);
     _settextposition(1, 1);
     _outtext("Press Tab to toggle panels, Esc to quit.");
     _settextposition(2, 1);
     _outtext("B increases blue level, b decreases it. ");
     _settextposition(3, 1);
     _outtext("G and g control green, R and r red.     ");
     _settextposition(24, lpos);
     _outtext(left);
     _settextposition(24, rpos);
     _outtext(right);
     _settextposition(5, 7);
     _outtext(label[0]);
     _settextposition(5, 27);
     _outtext(label[1]);
     while ((ch = getch()) != ESC)
         {
         switch (ch)
             {
             case '\t': _settextposition(5, 27);
                        _outtext(label[palnum]);
                        palnum ^= 1;
                        blue = (colors[palnum] << 16) & 0x3F;
                        green = (colors[palnum] << 8) & 0x3F;
                        red = colors[palnum] & 0x3F;
                        _settextposition(5, 7);
                        _outtext(label[palnum]);
                        break;
             case 'B':  blue = (blue + 1) % FULLBRIGHT;
                        colors[palnum] = blue << 16 |
                                green << 8 | red;
                        _remappalette(palnum + 1, colors[palnum]);

                        break;
             case 'b':  blue = (blue - 1) % FULLBRIGHT;
                        colors[palnum] = blue << 16 |
                                green << 8 | red;
                        _remappalette(palnum + 1, colors[palnum]);

                        break;
             case 'G':  green = (green + 1) % FULLBRIGHT;
                        colors[palnum] = blue << 16 |
                                green << 8 | red;
                        _remappalette(palnum + 1, colors[palnum]);

                        break;
             case 'g':  green = (green - 1) % FULLBRIGHT;
                        colors[palnum] = blue << 16 |
                                green << 8 | red;
                        _remappalette(palnum + 1, colors[palnum]);

                        break;
             case 'R':  red = (red + 1) % FULLBRIGHT;
                        colors[palnum] = blue << 16 |
                                green << 8 | red;
                        _remappalette(palnum + 1, colors[palnum]);

                        break;
             case 'r':  red = (red - 1) % FULLBRIGHT;
                        colors[palnum] = blue << 16 |
                                green << 8 | red;
                        _remappalette(palnum + 1, colors[palnum]);

                        break;

             }
         sprintf(left," %6lxH ", colors[0]);
         sprintf(right," %6lxH ", colors[1]);
         _settextposition(24, lpos);
         _outtext(left);
         _settextposition(24, rpos);
         _outtext(right);
         }
     _setvideomode(_DEFAULTMODE);
 }


 ALPHABET.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\ALPHABET.C


 /* ALPHABET.C -- uses for loop to         */
 /*               print lowercase alphabet */

 main()
 {
     int i;
     for (i = 'a'; i <= 'z'; i++)
         {
         printf("%c", i);
         }
 }



 ANIMATE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\ANIMATE.C


 /* ANIMATE.C -- animate a graphics character */
 /*              until a key is pressed       */

 /* Special characters */
 #define RTARROW 175
 #define LFTARROW 174
 #define BLANK 32
 #define BACKSPACE 8

 main()
 {
     int pos, i, j = 1;
     while ( !kbhit() )
         {
         pos = 1;
         while (pos < 79)
             {
             putch(RTARROW);
             i = 1;
             while (i < 1000)
                 {
                 j = i + 10;
                 i++;
                 }
             putch(BACKSPACE);
             putch(BLANK);
             pos++;
             }
         while (pos > 1)
             {
             putch(LFTARROW);
             i = 1;
             while (i < 1000)
                 {
                 j = i + 10;
                 i++;
                 }
             putch(BACKSPACE);
             putch(BLANK);
             putch(BACKSPACE);
             putch(BACKSPACE);
             pos--;
             }
         }
 }



 ARRAY1.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\ARRAY1.C

 /* array1.c -- how to declare arrays legally         */

 #define SIZEOARRAY 26

 main()
 {
     char  initials[26];
     int   num_men[26], num_women[SIZEOARRAY];
     float ages[SIZEOARRAY * 2];
 }


 ARROW.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\ARROW.C

 /* arrow.c -- fill inside and outside of a line       */
 /*            drawing                                 */
 /* If you load graphics.qlb, no program list is needed*/

 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>
 #define ESC '\033'
 BKCOLS 16   /* use 16 background colors */
 long Bkcolors[BKCOLS] = {_BLACK, _BLUE, _GREEN, _CYAN,
                  _RED, _MAGENTA, _BROWN, _WHITE,
                  _GRAY, _LIGHTBLUE, _LIGHTGREEN,
                  _LIGHTCYAN, _LIGHTRED, _LIGHTMAGENTA,
                  _LIGHTYELLOW,_BRIGHTWHITE };
 char Mask[8] = {0x90, 0x68, 0x34, 0x19, 0x19, 0x34, 0x68,
                 0x90};
 char Outmask[8] = {0xff, 0x80, 0x80, 0x80, 0xff, 0x08, 0x08,
                    0x08};
 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _MRES4COLOR;
     float x1, y1, x2, y2, x3, y3, y4, x5, y5;
     long bk = _BLUE;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
         {
         printf("Can't set mode %d.\n", mode);
         exit(1);
         }
     _getvideoconfig(&vc);

     x1 = 0.1 * vc.numxpixels;
     x2 = 0.7 * vc.numxpixels;
     x3 = 0.6 * vc.numxpixels;
     x5 = 0.9 * vc.numxpixels;
     y1 = 0.45 * vc.numypixels;
     y2 = 0.55 * vc.numypixels;
     y3 = 0.3 * vc.numypixels;
     y4 = 0.7 * vc.numypixels;
     y5 = 0.5 * vc.numypixels;
     _selectpalette(0);
     _setcolor(1);
     _moveto(x1, y1);
     _lineto(x2, y1);
     _lineto(x3, y3);
     _lineto(x5, y5);
     _lineto(x3, y4);
     _lineto(x2, y2);
     _lineto(x1, y2);
     _lineto(x1, y1);
     _setcolor(2);
     _setfillmask(Mask);
     _floodfill(x2, y5, 1) ;
     _setcolor(3);
     _setfillmask(Outmask);     /* restores default mask */
     _floodfill(5, 5, 1) ;
     _settextcolor(1);
     _settextposition(23, 0);
     _outtext("Press <enter> to change background.");
     _settextposition(24, 0);
     _outtext("Press <esc> to end.");
     while (getch() != ESC)
         _setbkcolor(Bkcolors[++bk % BKCOLS]);
     _setvideomode(_DEFAULTMODE);
 }


 ASGNKEY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\ASGNKEY.C

 /*   asgnkey.c -- uses ansi.sys to assign meanings   */
 /*                to several function keys.          */
 /*  Note: This requires ANSI.SYS to be installed.    */

 #define KASSIGN(K, S) printf("\033[0;%d;\"%s\";13p", K, S)
 /* This macro assigns string S to key K */
 #define F5 63
 #define F6 64
 #define F7 65
 #define F8 66
 #define F9 67
 #define F10 68
 main()
 {
      KASSIGN(F5, "DIR *.C");
      KASSIGN(F6, "DIR *.H");
      KASSIGN(F7, "DIR *.OBJ");
      KASSIGN(F8, "DIR *.EXE");
      KASSIGN(F9, "DIR /W");
      KASSIGN(F10, "CD \\");
 }


 ASIMOV.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\ASIMOV.C

 /* asimov.c -- illustrates how to initialize an      */
 /*             array with starting values            */

 #define MAXL 16
 char Letters[MAXL] = {
     'e', 'I', 'a', 'N', 'o', 'R', 'O', 'o',
     'u', 't', 'o', 'R', 'l', 'o', 'B', 'b',
 };

 main()
 {
     int num, i;

     printf("Guess my identity with numbers.\n");
     printf("(any non number quits)\n\n");

     while (scanf("%d", &num) == 1)
         {
         if (num <= 0)
             {
             printf("Guesses must be above zero\n");
             continue;
             }
         for (i = 1; i <= num; ++i)
             {
             printf("%c", Letters[(i * num) % MAXL]);
             }
         printf("\n");
         }
 }


 ATTRIB.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\ATTRIB.C

 /* attrib.c -- this program illustrates attributes */
 /* program list: attrib.c, scrfun.c                */
 /* user include files: scrn.h                      */
 /* Note: activate Screen Swapping On in Debug menu */
 #include <stdio.h>
 #include <conio.h>
 #include "scrn.h"
 #define PAGE 0
 #define ESC '\033'
 char *Format = "This message is displayed using an "
                "attribute value of %2X hex (%s).";
 int Get_attrib(char *);
 void Print_attr(char *, unsigned char, unsigned char);

 main()
 {

     int attribute;       /* value of attribute */
     char attr_str[9];    /* attr. in string form */
     char mesg[80];

     Clearscr();
     Home();
     printf("Enter an attribute as an 8-digit binary "
            "number, such as 00000111, and see a\n"
            "message displayed using that attribute."
            "Hit <Esc> to quit.\n"
            "Attribute = ");
     while ((attribute = Get_attrib(attr_str)) != -1)
         {
         Setcurs(10,0,PAGE);
         sprintf(mesg, Format, attribute, attr_str);
         Print_attr(mesg, attribute, PAGE);
         Setcurs(2, 12, PAGE);
         printf("         ");  /* clear old display */
         Setcurs(2, 12, PAGE);
         }
     Clearscr();
 }

 /* The following function reads in a binary number    */
 /* as a sequence of 1s and 0s. It places the 1 and 0  */
 /* characters in a string whose address is passed as  */
 /* an argument. It returns the numeric value of the   */
 /* binary number. Bad input is summarily rejected.    */
 /* The function returns -1 when you press Esc.        */

 int Get_attrib(a_str)
 char a_str[];     /* attribute as binary string */
 {
     int attrib[8];
     int index = 7;
     int ch;
     int attribute = 0; /* attrib. as numeric value */
     int pow;

     a_str[8] = '\0';  /* terminate string */
     while ((index >= 0) &&  (ch = getch()) != ESC)
         {
         if (ch != '0' && ch != '1')  /* bad input */
             putch('\a');
         else
             {
             putch(ch);
             a_str[index] = ch;      /* string form */
             attrib[index--] = ch - '0'; /* numeric */
             }
         }
     if (ch == ESC)
         return (-1);
     else            /* convert numeric array to a number */
         {
         for(index = 0, pow = 1; index < 8;
                                   index++, pow *= 2)
             attribute += attrib[index] * pow;
         return attribute;
         }
 }

 /* The following function prints the string str using */
 /* attribute attr on the indicated page.              */
 /* It uses functions from the scrfun.c file.          */

 void Print_attr(str, attr, page)
 char *str;
 unsigned char attr, page;
 {
     while (*str != '\0')
         {
         Write_ch_atr(*str++, attr , page, 1);
         Cursrt();
         }
 }


 AVGTEMP.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\AVGTEMP.C

 /* avgtemp.c -- finds average temperature */
 /*              for the week              */

 main()
 {
     int t1, t2, t3, t4, t5, t6, t7;
     float avg;

     printf("Enter the high temperature for:\n");
     printf("Monday: ");
     scanf("%d", &t1);
     printf("Tuesday: ");
     scanf("%d", &t2);
     printf("Wednesday: ");
     scanf("%d", &t3);
     printf("Thursday: ");
     scanf("%d", &t4);
     printf("Friday: ");
     scanf("%d", &t5);
     printf("Saturday: ");
     scanf("%d", &t6);
     printf("Sunday: ");
     scanf("%d", &t7);

     /* calculate and display average */
     avg = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7.0;
           /* divide by 7.0 to ensure float result */
     printf("The average high temperature for");
     printf(" this week was %5.2f degrees.\n", avg);
 }


 BACKWARD.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\BACKWARD.C

 /* backward.c -- the backwards word displayer         */

 #include <stdio.h>
 #define SIZE 5
 char word[SIZE] = "trap";
 main()
 {
     unsigned int index;

     printf("%s backwards is ", word);
     for (index = SIZE - 2; index >= 0; index--)
         putchar(word[index]);
     putchar('\n');
 }



 BADPUTC.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\BADPUTC.C

 /* badputc.c -- misusing putc()                  */

 #include <stdio.h>
 main()
 {
     FILE *fp;
     int ch;

     if ((fp = fopen("junk", "w")) == NULL)
         exit(1);

     while ((ch = getchar()) != EOF)
         putc(fp, ch);
     fclose(fp);
 }



 BADREF.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\BADREF.C

 /* badref.c -- misusing a pointer                     */
 main()
 {
     char name[81];
     char *pt_ch;

     printf("Enter your first name: -> ");
     scanf("%s", name);
     *pt_ch = name[1];
     printf("The second letter of your name is %c\n",
             *pt_ch );
 }



 BADSIGN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\BADSIGN.C

 /* badsign.c -- uncaught typo                 */

 main()
 {
     int i;
     int j = 1;

     for (i = 0; i < 10; i++)
         {
         j =+ 10;         /* transposed += */
         printf("%4d ", j);
         }
     printf("\n");
 }



 BIFFRED.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\BIFFRED.C

 /* biffred.c  --  strings in the string pool can be */
 /*                manipulated via pointers          */

 char Start[] = "start";

 main()
 {
     char *cp;
     int pass;

     for (pass = 0; pass < 2; ++pass)
         {
         printf("My name is FRED\n");

         cp = Start;

         while (*cp != 'F')
             ++cp;

         *cp   = 'B';
         *++cp = 'I';
         *++cp = 'F';
         *++cp = 'F';
         }
 }


 BITOUT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\BITOUT.C

 /* bitout.c  -- compiles one way on an IBM-PC and      */
 /*              another on a 68000 chip-based machine  */

 CHIP_80286    /* don't define on a 68000 machine */
 #include <stdio.h>

 main()
 {
     int num;

     printf("Enter an integer number and I will print"
            " it out in binary\nNumber: ");

     if (scanf("%d", &num) != 1)
         {
         fprintf(stderr, "Not an integer\n");
         exit(1);
         }
     Bitout(num);
 }

 Bitout(unsigned int num)
 {
     int i, j;
     unsigned char *cp;

     cp = (char *)&num;

 defined(CHIP_80286)    /* IBM-PC */
     for (i = 1; i >= 0; --i)
 #endif
 !defined(CHIP_80286)   /* otherwise 68000 machine */
     for (i = 0; i < 4; ++i)
 #endif
         {
         for (j = 7; j >= 0; --j)
             putchar((cp[i] & (1 << j)) ? '1' : '0');
         }
     putchar('\n');
 }


 BITWISE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\BITWISE.C

 /* bitwise.c -- demonstrate the bitwise operators */

 #include <stdio.h>

 main()
 {
     unsigned int val1, val2, result;
     int ch;
     extern void show();

     while(1)
         {
         printf("\nval1: ");
         if (scanf("%d", &val1) != 1)
             break;

         printf("val2: ");
         if (scanf("%d", &val2) != 1)
             break;

         printf("\tval1   = ");
         show(val1);
         printf("\tval2   = ");
         show(val2);

         printf("Bitwise Operator: ");
         while ((ch = getchar()) == '\n')
             {
             continue;
             }
         if (ch == EOF)
             break;
         switch (ch)
             {
             case '&':
                 result = val1 & val2;
                 printf("Executing: result = val1 & val2;\n");
                 break;
             case '|':
                 result = val1 |= val2;
                 printf("Executing: result = val1 | val2;\n");
                 break;
             case '^':
                 result = val1 ^= val2;
                 printf("Executing: result = val1 ^ val2;\n");
                 break;
             case '~':
                 result = ~val1;
                 printf("Executing: result = ~val1;\n");
                 printf("\tresult = ");
                 show(result);
                 result = ~val2;
                 printf("Executing: result = ~val2;\n");
                 break;
             case '<':
                 result = val1 <<= val2;
                 printf("Executing: result = val1 <<val2;\n");
                 break;
             case '>':
                 result = val1 >>= val2;
                 printf("Executing: result = val1 >>val2;\n");
                 break;
             case 'q':
             case 'Q':
                 return(0);
               default:
                 continue;
             }
         printf("\tresult = ");
         show(result);
         }
 }

 void bitout(unsigned char num[])
 {
     int bytes = 2, i, j;

     /* IBM PC stores ints low/hi. */
     for (i = bytes-1; i >= 0; --i)
         {
         for (j = 7; j >= 0; --j)
             {
             putchar((num[i]&(1<<j))?'1':'0');
             }
         }
 }

 void show(unsigned int val)
 {
     extern void bitout();

     printf("(%05u decimal)", val);
     bitout(&val);
     printf(" binary\n");
 }


 BLANK.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\BLANK.C

 /* blank.c -- blanks MDA screen                        */
 /* program list -- blank.c (outp() not in core lib)    */

 #include <conio.h>
 CONTROLREG 0x3B8 /* control register MDA */
 #define DEFAULTSET 0x29
 #define VIDEOOFF 0x21
 main()
 {
     outp(CONTROLREG, VIDEOOFF);
     getch();
     outp(CONTROLREG, DEFAULTSET);
 }


 BOX.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\BOX.C

 /* box.c  --  demonstrate the result of initializing  */
 /*            a three-dimensional array               */

 main()
 {
     static int cube[3][3][3] = {
         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
         13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
         23, 24, 25, 26, 27 };
     int plane;
     extern void Draw_plane();

     for (plane = 0; plane < 3; ++plane)
         {
         Draw_plane(cube, plane);
         }
 }

 void Draw_plane(int box[3][3][3], int slice)
     {
     int row, col;

     printf("Plane[%d] =\n", slice);
     for (row = 0; row < 3; ++row)
         {
         for (col = 0; col < 3; ++col)
             {
             printf( "%2d ", box[slice][row][col]);
             }
         printf("\n");
         }
     printf("\n");
 }


 BREAK.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\BREAK.C

 /* break.c -- shows how to get out of loop with BREAK */

 #include <stdio.h>
 #define TRUE 1

 main()
 {
     int number;
     while (TRUE) /* endless loop */
         {
         /* get a random number between 0 and 32767 */
         number = rand();
         printf("%d\n", number);

         /* break out of loop if random number */
         /* is greater than 32000              */
         if (number > 32000)
             break; /* exit WHILE loop */
         }
     printf("Broken out of WHILE loop.\n");
 }


 BUBSORT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\BUBSORT.C

 /* bubsort.c  --  passing an array to a function  */
 /*                affects the original array      */

 #define NUMINTS 6

 extern void Bub_sort();
 extern void Triple();

 main()
 {
     int num = 2, i;
     static int list[NUMINTS] = { 6, 5, 4, 3, 2, 1 };

     printf("num before Triple = %d\n", num);
     Triple(num);
     printf("num after Triple  = %d\n", num);
     printf("list[0] before Triple = %d\n", list[0]);
     Triple(list[0]);
     printf("list[0] after Triple  = %d\n", list[0]);

     printf("Before sorting -> ");
     for (i = 0; i < NUMINTS; ++i)
         {
         printf("%d ", list[i]);
         }
     printf("\n");

     Bub_sort(list);
     printf("After sorting ->  ");
     for (i = 0; i < NUMINTS; ++i)
         {
         printf("%d ", list[i]);
         }
     printf("\n");

 }

 void Triple(int x)  /* function doesn't affect original */
 {
     x *= 3;
 }

 void Bub_sort(int vals[NUMINTS]) /* function changes original */
 {
     int i, j, temp;

     for (i = (NUMINTS - 1); i > 0; --i)
         {
         for (j = 0; j < i; ++j)
             {
             if (vals[j] > vals[j+1])
                 {
                 temp      = vals[j];
                 vals[j]   = vals[j+1];
                 vals[j+1] = temp;
                 }
             }
         }
 }


 BUG.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\BUG.C

 /* bug.c  --  shows how different levels of debugging  */
 /*            output can be produced using #if         */

 DEBUG_LEVEL 2      /* 0 = none, 1-2 for debug  */
 #include <stdio.h>

 main()
 {
     int ret;

 #if (DEBUG_LEVEL == 2)
     fprintf(stderr, "Entering main()\n");
 #endif

 #if (DEBUG_LEVEL == 1)
     fprintf(stderr, "Calling sub()\n");
 #endif

     ret = sub();

 #if (DEBUG_LEVEL == 1)
     fprintf(stderr, "sub() returned %d\n", ret);
 #endif

 #if (DEBUG_LEVEL == 2)
     fprintf(stderr, "Leaving main()\n");
 #endif

 }

 sub()
 {
     return (5);
 }


 CARD.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\CARD.C

 /* card.c  --  demonstrates how to declare structures  */
 /*             and how to use structure members        */

 <stdio.h>      /* for NULL  and stdin */
 <string.h>     /* for strdup()        */

 #define MAXN 79

 struct cardstruct {                 /* global pattern */
     char *first, *last, *middle;
     long street_num;
     char *street, *city, *state;
     long zip;
     int  area_code;
     long phone;
 };

 main()
 {
     char *Str_Input();
     long Lint_Input();
     struct cardstruct card1;

     card1.first         = Str_Input("First Name");
     card1.last          = Str_Input("Last Name");
     card1.middle        = Str_Input("Middle Name");
     card1.street_num    = Lint_Input("Street Number");
     card1.street        = Str_Input("Street Name");
     card1.city          = Str_Input("City");
     card1.state         = Str_Input("State");
     card1.zip           = Lint_Input("Zip Code");
     card1.area_code     = (int)Lint_Input("Area Code");
     card1.phone         = Lint_Input("Phone Number");

     printf("\n\n");
     printf("%s %s %s\n", card1.first, card1.middle,
             card1.last);
     printf("%ld %s, %s, %s %ld\n", card1.street_num,
             card1.street, card1.city, card1.state,
             card1.zip);
     printf("(%d) %ld\n", card1.area_code, card1.phone);

     return (0);
     }

 char *Str_Input(char *prompt)
     {
     char buf[MAXN+1], *ptr;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     buf[strlen(buf) - 1] = '\0'; /* strip '\n' */
     if (strlen(buf) == 0)
         exit(0);
     if ((ptr = strdup(buf)) == NULL)
         exit(0);
     return (ptr);
 }

 long Lint_Input(char *prompt)
 {
     char buf[MAXN + 1];
     long num;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     if (sscanf(buf, "%ld", &num) != 1)
         exit(0);
     return (num);
 }


 CARD2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\CARD2.C

 /* card2.c --  demonstrates structure assignment and   */
 /*             how to pass a structure to a function   */

 <stdio.h>      /* for NULL  and stdin */
 <string.h>     /* for strdup()        */

 #define MAXN 79

 struct cardstruct {                 /* global pattern */
     char *first, *last, *middle;
     long street_num;
     char *street, *city, *state;
     long zip;
     int  area_code;
     long phone;
 };

 main()
 {
     int  i;
     char *Str_Input();
     long Lint_Input();
     struct cardstruct card1, card2;

     for (i = 0; i < 2; i++) /* do twice */
         {
         printf("\nCard %d:\n\n", i + 1);

         card1.first         = Str_Input("First Name");
         card1.last          = Str_Input("Last Name");
         card1.middle        = Str_Input("Middle Name");
         card1.street_num    = Lint_Input("Street Number");
         card1.street        = Str_Input("Street Name");
         card1.city          = Str_Input("City");
         card1.state         = Str_Input("State");
         card1.zip           = Lint_Input("Zip Code");
         card1.area_code     = (int)Lint_Input("Area Code");
         card1.phone         = Lint_Input("Phone Number");

         if (i == 0)
             card2 = card1;      /* structure assignment */
         }
     Showcard(card2);
     Showcard(card1);

 }

 Showcard(struct cardstruct card)
 {
     printf("\n\n");

     printf("%s %s %s\n", card.first, card.middle,
             card.last);
     printf("%ld %s, %s, %s %ld\n", card.street_num,
             card.street, card.city, card.state,
             card.zip);
     printf("(%d) %ld\n", card.area_code, card.phone);
 }

 char *Str_Input(char *prompt)
 {
     char buf[MAXN + 1], *ptr;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     buf[strlen(buf) - 1] = '\0'; /* strip '\n' */
     if (strlen(buf) == 0)
         exit(0);
     if ((ptr = strdup(buf)) == NULL)
         exit(0);
     return (ptr);
 }

 long Lint_Input(char *prompt)
 {
     char buf[MAXN + 1];
     long num;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     if (sscanf(buf, "%ld", &num) != 1)
         exit(0);
     return (num);
 }


 CARD3.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\CARD3.C

 /* card3.c --  demonstrates pointers to structures     */

 <stdio.h>      /* for NULL  and stdin */
 <string.h>     /* for strdup()        */

 #define MAXN 79

 struct cardstruct {                 /* global pattern */
     char *first, *last, *middle;
     long street_num;
     char *street, *city, *state;
     long zip;
     int  area_code;
     long phone;
 };

 main()
 {
     int  i;
     char *Str_Input();
     long Lint_Input();
     struct cardstruct card1, card2;

     for (i = 0; i < 2; i++) /* do twice */
         {
         printf("\nCard %d:\n\n", i + 1);

         card1.first         = Str_Input("First Name");
         card1.last          = Str_Input("Last Name");
         card1.middle        = Str_Input("Middle Name");
         card1.street_num    = Lint_Input("Street Number");
         card1.street        = Str_Input("Street Name");
         card1.city          = Str_Input("City");
         card1.state         = Str_Input("State");
         card1.zip           = Lint_Input("Zip Code");
         card1.area_code     = (int)Lint_Input("Area Code");
         card1.phone         = Lint_Input("Phone Number");

         if (i == 0)
             card2 = card1;
         }
     Showcard(&card2);     /* pass addresses of structures */
     Showcard(&card1);

     return (0);
 }

 Showcard(cardptr)
 struct cardstruct *cardptr; /* pointer receives an address */
     {
     printf("\n\n");

     printf("%s %s %s\n", cardptr->first, cardptr->middle,
             cardptr->last);
     printf("%ld %s, %s, %s %ld\n", cardptr->street_num,
             cardptr->street, cardptr->city, cardptr->state,
             cardptr->zip);
     printf("(%d) %ld\n", cardptr->area_code, cardptr->phone);
     }

 char *Str_Input(char *prompt)
     {
     char buf[MAXN + 1], *ptr;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     buf[strlen(buf) - 1] = '\0'; /* strip '\n' */
     if (strlen(buf) == 0)
         exit(0);
     if ((ptr = strdup(buf)) == NULL)
         exit(0);
     return (ptr);
 }

 long Lint_Input(char *prompt)
 {
     char buf[MAXN + 1];
     long num;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     if (sscanf(buf, "%ld", &num) != 1)
         exit(0);
     return (num);
 }


 CCOPY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\CCOPY.C

 /* ccopy.c  --  Copies a file, cutting blank lines and  */
 /*              leading space from lines of copy        */

 <stdio.h>        /* for FILE, BUFSIZ, NULL */
 <ctype.h>        /* for iswhite()          */

 main(argc, argv)
 int argc;
 char *argv[];
 {
     FILE *fp_in, *fp_out;
     char buf[BUFSIZ];
     char *cp;

     if (argc != 3)
         {
         printf("usage: ccopy infile outfile\n");
         exit(1);
         }
     if ((fp_in = fopen(argv[1], "r")) == NULL)
         {
         printf("Can't open %s for reading.\n", argv[1]);
         exit(1);
         }
     if ((fp_out = fopen(argv[2], "w")) == NULL)
         {
         printf("Can't open %s for writing.\n", argv[2]);
         exit(1);
         }

     printf("Copying and Crushing: %s->%s ...",
             argv[1], argv[2]);

     while (fgets(buf, BUFSIZ, fp_in) != NULL)
         {
         cp = buf;
         if (*cp == '\n')    /* blank line */
             continue;
         while (isspace(*cp))
             {
             ++cp;
             }
         if (*cp == '\0')    /* empty line */
             continue;
         if (fputs(cp, fp_out) == EOF)
             {
             printf("\nError writing %s.\n", argv[2]);
             exit(1);
             }
         }
     printf("Done\n");
 }


 CCOPY2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\CCOPY2.C

 /* ccopy2.c  -- copies a file, cutting blank lines and    */
 /*              leading space from lines of copy          */

 /*              Modified to demonstrate stdout and stderr */

 <stdio.h>        /* for FILE, BUFSIZ, NULL */
 <ctype.h>        /* for iswhite()          */

 main(argc, argv)
 int argc;
 char *argv[];
 {
     FILE *fp_in, *fp_out;
     char buf[BUFSIZ];
     char *cp;

     if (argc < 2)
         {
         fprintf(stderr, "usage: ccopy infile {outfile}\n");
         exit(1);
         }
     if ((fp_in = fopen(argv[1], "r")) == NULL)
         {
         fprintf(stderr, "\"%s\": Can't open.\n", argv[1]);
         exit(1);
         }
     if (argc == 3)
         {
         if ((fp_out = fopen(argv[2], "w")) == NULL)
             {
             fprintf(stderr, "\"%s\": Can't open.\n", argv[2]);
             exit(1);
             }
         }
     else
         fp_out = stdout;

     while (fgets(buf, BUFSIZ, fp_in) != NULL)
         {
         cp = buf;
         if (*cp == '\n')    /* blank line */
             continue;
         while (isspace(*cp))
             {
             ++cp;
             }
         if (*cp == '\0')    /* empty line */
             continue;
         if (fputs(cp, fp_out) == EOF)
             {
             fprintf(stderr, "Error writing.\n");
             exit(1);
             }
         }
     if (! feof(fp_in))      /* error reading? */
         {
         fprintf(stderr, "\"%s\": Error reading.\n", argv[1]);
         exit(1);
         }
 }


 CH2000.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\CH2000.C

 /* ch2000.c -- fill screen with 2000 characters        */
 /*    This program demonstrates direct memory access   */
 /*    of video memory.  It is set up for the MDA.      */
 /*    Assign CGAMEM instead of MONMEM to screen for    */
 /*    CGA and CGA-compatible modes.                    */
 /*    Press a key to fill; press Esc to quit.          */
 /* Note: activate Screen Swapping On in Debug menu     */

 #include <conio.h>
 #include "scrn.h"
 typedef unsigned short (far * VIDMEM);
 MONMEM ((VIDMEM) (0xB000L << 16)) /* monochrome */
 CGAMEM ((VIDMEM) (0xB800L << 16)) /* cga, ega */
 #define ESC '\033'
 #define CHARS 2000
 AMASK 0xFF   /* keep attribute in range */
 main()
 {
      unsigned ch;          /* character to be displayed */
      unsigned attrib = 7;  /* initial attribute         */
      VIDMEM screen;        /* pointer to video RAM      */
      int offset;           /* location on screen        */

      screen = MONMEM;      /* monochrome initialization */
      while ((ch = getch()) != ESC)
      {
         for (offset = 0; offset < CHARS; offset++)
           *(screen + offset) = ((attrib++ & AMASK) << 8)
      }
 }


 CH2001.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\CH2001.C

 /* ch2001.c -- fill screen with 2000 characters        */
 /*    This program demonstrates direct memory access   */
 /*    of video memory.  It uses the current video mode */
 /*    value to select the proper video RAM address.    */
 /*    Press a key to fill; press Esc to quit.          */
 /* Program list: ch2001.c, scrfun.lib                  */
 /* Note: activate Screen Swapping On in Debug menu     */

 #include <conio.h>
 #include "scrn.h"
 typedef unsigned short (far * VIDMEM);
 MONMEM ((VIDMEM) (0xB000L << 16)) /* monochrome */
 CGAMEM ((VIDMEM) (0xB800L << 16)) /* cga, ega */
 #define ESC '\033'
 #define CHARS 2000
 #define AMASK 0xFF
 main()
 {
      unsigned ch, mode;
      unsigned attrib = 7;
      VIDMEM screen;         /* pointer to video RAM */
      int offset;

      if ((mode = Getvmode()) == TEXTMONO)
           screen = MONMEM;
      else if (mode == TEXTC80 || mode == TEXTBW80)
           screen = CGAMEM;
      else
           exit(1);
      while ((ch = getch()) != ESC)
           {
           for (offset = 0; offset < CHARS; offset++)
               *(screen + offset) = ((attrib++ & AMASK) << 8) | ch;
           }
 }


 CHANGE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\CHANGE.C

 /* change.c  -- a changemaking program demonstrates   */
 /*              how pointers advance the correct      */
 /*              number of bytes based on type         */

 #define NCOINS (4)
 CENT (0x9b)  /* IBM PC cent character */
 #define WAIT printf("(Press any key to continue)"); \
              getch(); printf("\n\n")

 main()
 {
     static int coins[NCOINS] = {25, 10, 5, 1};
     int *coin_ptr, i = 0;
     int pennies1, pennies2, count;
     float amount;

     printf("Enter an amount and I will ");
     printf(" give you change.\nAmount: ");
     if (scanf("%f", &amount) != 1)
         {
         printf("I don't know how to change that!\n");
         exit(1);
         }
     pennies2 = pennies1 = (int)(amount * 100.0);

     coin_ptr = coins;
     for (i = 0; i < NCOINS; ++i)
         {
         WAIT;
         count = 0;
         while ((pennies1 -= coins[i]) >= -1)
             ++count;
         if (count > 0)
             {
             printf("%4d %2d%c", count, coins[i], CENT);
             printf(" coins by array offset.\n");
             }
         if (pennies1 == 0)
             break;
         pennies1 += coins[i];

         count = 0;
         while ((pennies2 -= *coin_ptr) >= -1)
             ++count;
         if (count > 0)
             {
             printf("%4d %2d%c", count, *coin_ptr, CENT);
             printf(" coins by pointer indirection.\n");
             }
         if (pennies2 == 0)
             break;
         pennies2 += *coin_ptr;
         ++coin_ptr;
         }
 }


 CHANGE2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\CHANGE2.C

 /* change2.c -- modified to demonstrate passing       */
 /*              an address to a function              */

 #define NCOINS (4)
 CENT (0x9b)  /* IBM PC cent character */

 main()
 {
     static int coins[NCOINS] = {25, 10, 5, 1};
     int pennies;
     float amount;

     printf("Enter an amount and I will ");
     printf(" give you change.\nAmount: ");
     if (scanf("%f", &amount) != 1)
         {
         printf("I don't know how to change that!\n");
         exit(1);
         }
     pennies = (int)(amount * 100.0);

     Show_change( coins, &coins[NCOINS], pennies);

 }

 Show_change( int amts[], int *end, int due)
 {
     int count;

     while ( amts < end )    /* compare pointers */
         {
         count = 0;
         while ((due -= *amts) >= -1)
             {
             ++count;
             }
         if (count > 0)
             printf("%4d %2d%c\n", count, *amts, CENT);
         if (due == 0)
             break;
         due += *amts;

         ++amts;             /* increment a pointer */
         }
 }


 CHARS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\CHARS.C

 /* chars.c -- shows some variables of type char */
 /*            as both characters and integers   */

 main()
 {
     char ch1 = 'A', ch2 = 'a';

     printf("The character %c has ASCII code %d\n", ch1, ch1);
     printf("If you add ten, you get %c\n", ch1 + 10);
     printf("The character %c has ASCII code %d\n", ch2, ch2);
 }


 CHOOSE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\CHOOSE.C

 /* choose.c   --  an array of pointers to functions   */
 /*                used to create a menu               */

 void Choice1(), Choice2(), Choice3();

 void (*Dochoice[3])() = {Choice1, Choice2, Choice3};

 main()
     {
     int ch;

     printf("Select 1, 2 or 3: ");
     ch = getch(); putch(ch);
     ch -= '1';
     if (ch < 0 || ch > 2)
         printf("\nNo such choice.\n");
     else
         Dochoice[ch]();

 }

 void Choice1(void)
 {
         printf("\nThis is choice 1\n");
 }

 void Choice2(void)
 {
         printf("\nThis is choice 2\n");
 }

 void Choice3(void)
 {
         printf("\nThis is choice 3\n");
 }


 COL256.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\COL256.C

 /*  col256.c  -- show 256 colors in mode 19             */
 /* If you load graphics.qlb, no program list is needed. */

 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>
 #define ESC '\033'
 #define ROWS 16
 #define COLS 16
 main()
 {
     struct videoconfig vc;
     int mode = _MRES256COLOR;
     short xmax, ymax;           /* screen size */
     short xcs[ROWS][COLS];      /* coordinates of the */
     short ycs[ROWS][COLS];      /* 256 rectangles     */
     short row, col;


     if (_setvideomode(mode) == 0)
         {
         fprintf(stderr, "%d mode not supported\n", mode);
         exit(1);
         }
     _getvideoconfig(&vc);

     xmax = vc.numxpixels - 1;
     ymax = vc.numypixels - 1;

     /* Compute an interior point for each rectangle. */
     for (col = 0; col < COLS; col++)
         for (row = 0; row < ROWS; row++)
             {
             xcs[row][col] =  col * xmax / COLS + 5;
             ycs[row][col] =  row * ymax / ROWS + 5;

             }

     /* draw outside boundary */
     _setcolor(1);
     _rectangle(_GBORDER, 0, 0, xmax, ymax);

     /* draw gridwork */
     for (col = 1; col < COLS ; col++)
         {
         _moveto(col * (xmax + 1) / COLS, 0);
         _lineto(col * (xmax + 1) / COLS, ymax);
         }
     for (row = 1; row < ROWS;  row++)
         {
         _moveto(0, row * (ymax + 1) / ROWS);
         _lineto(xmax, row * (ymax + 1) / ROWS);
         }

     /*  fill in rectangles with palette colors */
     for (col = 0; col < COLS; col++)
         for (row = 0; row < ROWS; row++)
             {
             _setcolor(row * ROWS + col);
             _floodfill(xcs[row][col], ycs[row][col],1);
             }

     /* terminate program */
     getch();
     _setvideomode(_DEFAULTMODE);
 }


 CONDITN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\CONDITN.C

 /* conditn.c -- attempt to use conditional op */

 main()
 {
     int n, m;

     n = 2;
     m = (n != 2) : 0 ? 1;  /* almost right */
     printf("%d\n", m);
 }


 CONTINUE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\CONTINUE.C

 /* continue.c -- shows CONTINUE in loop */

 main()
 {
     int sw = 0;
     char ch;
     while (1) /* endless loop */
     {
         /* print current status */
         if (sw)
             printf("\nSwitch is ON\n");
         else
             printf("\nSwitch is OFF\n");

         printf("Do you want to quit? ");
         if (ch = getche() == 'y')
             break;    /* exit loop on yes */

         printf("\nDo you want to toggle the switch? ");
         if (ch = getche() != 'y')
             continue; /* restart loop on yes */

         sw = !sw;     /* toggle switch */
         }
 }


 CONTROL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\CONTROL.C

 /* control.c  --  demonstrate string justification */
 /*                using printf()                   */

 char Some_text[] = "Some Text";
 char Left_control[] =    "<<%-15s>>";
 char Right_control[] =    "<<%15s>>";

 main()
 {
     char ch;

     while (1)
         {
         printf("Select l)eft r)ight or q)uit: ");
         ch = getch();
         putch( ch );

         printf("\n\n");
         switch((int) ch)
             {
             case 'l':
             case 'L':
                 printf(Left_control, Some_text);
                 break;
             case 'r':
             case 'R':
                 printf(Right_control, Some_text);
                 break;
             case 'q':
             case 'Q':
                 exit (0);
             default:
                 printf("Huh?");
                 break;
             }
         printf("\n\n");
         }
 }


 CONVERT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\CONVERT.C

 /* convert.c -- converts Farenheit temprature       */
 /*              to Centigrade; gets value from user */

 main()
 {
     float ftemp, ctemp;

     printf("What is the temprature in Farenheit? ");
     scanf("%f", &ftemp);
     ctemp = (ftemp - 32.0) * 5 / 9.0;

     printf("The temprature in Centigrade is %5.2f", ctemp);
 }


 DBLBAR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\DBLBAR.C

 /* dblbar.c -- prints header using */
 /*             line() function     */

 #define DOUBLE_BAR 205

 main()
 {
     void line();       /* declare line() function */

     line(10);          /* call line() function    */
     printf("dblbar.c -- prints header using\n");
     printf("line() function\n");
     line(50);          /* call line() again       */
 }

 void line()            /* function definition     */
 {
     int pos;
     for (pos = 1; pos <= 40; pos++)
         putch(DOUBLE_BAR);
     printf("\n");
 }


 DEBUG.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\DEBUG.C


 /* DEBUG.C -- for practice with debugger */

 main()
 {
     char response;
     int number, max_numbers = 5, count = 0, total = 0;
     float average;

     printf("Continue (y/n)? ");
     response = getche();
     while ((response != 'n') && (count < max_numbers))
         printf("\nEnter a number: ");
         scanf("%d", &number);
         total += number;
         printf("Continue (y/n)? ");
         response = getche();
     average = total / count;
     printf("\nTotal is %d\n", total);
     printf("Average is %f\n", average);
 }



 DIALOG.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\DIALOG.C

 /* dialog.c  -- a conversation using gets() and puts()  */

 <stdio.h>          /* for NULL and BUFSIZ */

 #define THE_QUESTION \
 "And what is your view on the current price of corn\n\
 and the stability of our trade import balance?"

 main()
 {
     char name[BUFSIZ],
          buf[BUFSIZ];
     extern char *gets();

     name[0] = '\0';         /* clear the name */

     puts("\n\nHi there. And what is your name?");

     if (gets(name) != NULL && name[0] != '\0')
         {
         printf("\nPleased to meet you, %s.\n", name);
         puts(THE_QUESTION);

         /*
          * force an extra <enter> before replying.
          */
         do
             {
             if (gets(buf) == NULL)
                 break;

             } while (*buf != '\0');     /* wait for empty line */

         puts("Sorry. I needed to think about that.");
         printf("Nice talking to you, %s.\n", name);
         }
     else
         puts("How rude!");

     puts("Goodbye.");
 }


 DIGSUM.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\DIGSUM.C

 /* digsum.c -- sum digits in input                    */
 #include <stdio.h>
 main()
 {
     int ch;
     int digits = 0;  /* number of digits in input */
     int others = 0;  /* number of non-digits in input */


     while ((ch = getchar()) != EOF)
     if (ch <= '0' && ch >= '9')
             others++;
         else
             digits++;
     printf("digits = %d, others = %d", digits, others);
 }


 DIRX.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\DIRX.C

 /* dirx.c  --  directory examples  */

 #include <direct.h>
 #include <stdio.h>

 #define SUBDIR "SUBDIR"
 #define SUBSUBDIR "SUBSUB"

 main()
 {
     char *current_dir;
     void Err();

     if ((current_dir = getcwd(NULL, 0)) == NULL)
         Err("getcwd()", "Can't get current directory.");

     if (mkdir(SUBDIR) != 0)
         Err( SUBSUBDIR, "Can't make directory." );

     if (chdir(SUBDIR) != 0)
         Err( SUBDIR, "Can't cd into directory." );

     if (mkdir(SUBSUBDIR) != 0)
         Err( SUBSUBDIR, "Can't make directory." );

     if (chdir(current_dir) != 0)
         Err( SUBDIR, "Can't cd back to." );

     if (rmdir(SUBDIR) != 0)
         Err( SUBDIR, "Can't remove directory." );

 }

 void Err(char *what, char *msg)
 {
     fprintf(stderr, "\"%s\": %s\n", what, msg );
     exit (1);
 }


 DO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\DO.C


 /* DO.C -- a simple do-while loop */

 main()
 {
     int i = 1;
     do
         {
         printf("%d\n", i);
         i++;
         }
     while (i < 11);
     printf("Done!\n");
 }



 DOTS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\DOTS.C

 /* dots.c -- illustrates the _setcolor(), _setpixel(), */
 /*           and _selectpalette() functions from the   */
 /*           QuickC graphics library                   */
 /* If you load graphics.qlb, no program list is needed */

 #include <conio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #define ESC '\033'
 BKCOLS 8      /* number of background colors */
 PALNUM 4      /* number of palettes */
 long Bkcolors[BKCOLS] = {_BLACK, _BLUE, _GREEN, _CYAN, _RED,
                          _MAGENTA, _BROWN, _WHITE};
 main (argc, argv)
 int argc;
 char *argv[];
 {
      struct videoconfig vc;
      unsigned int col, row;
      short color = 0;
      int bkc_index = 1;  /* blue background */
      short palette = 0;  /* red, green, brown */
      int firstcol, firstrow, lastrow, lastcol;
      int mode = _MRES4COLOR;
      int ch;

      if (argc > 1)
           mode = atoi(argv[1]);

      if (_setvideomode(mode) == 0)
      {
           printf("Can't do that mode.\n");
           exit(1);
      }
      _getvideoconfig(&vc);
      firstcol = vc.numxpixels / 5;
      firstrow = vc.numypixels / 5;
      lastcol = 4 * vc.numxpixels / 5;
      lastrow = 4 * vc.numypixels / 5;
      _selectpalette(palette);
      _setbkcolor (Bkcolors[bkc_index]);
      for (col = firstcol; col <= lastcol; ++col)
      {
           _setcolor((++color / 3) % vc.numcolors);
           for (row = firstrow; row <= lastrow; ++row)
                _setpixel(col, row);
      }
      while ((ch = getch()) != ESC)
      {
           if (ch == 'p')
                 _selectpalette(++palette % PALNUM);
           else if (ch == 'b')
                 _setbkcolor(Bkcolors[++bkc_index % BKCOLS]);
      }
      _setvideomode(_DEFAULTMODE);  /* reset orig. mode */
 }


 DOWHILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\DOWHILE.C

 /* dowhile.c -- misuse of do while loop     */

 main()
 {
     int i = 0;

     do while (i < 10)
         {
         printf("Happy Fourth of July!\n");
         i++;
         }
     printf("VOOOM\n");
 }



 DOWHILE2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\DOWHILE2.C

 /* dowhile2.c -- ok use of do while loop     */

 main()
 {
     int i = 0;

     do
         {
         printf("Happy Fourth of July!\n");
         i++;
         } while (i < 10) ;
     printf("VOOOM\n");
 }


 DRAWCHAR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\DRAWCHAR.C

 /* drawchar.c -- drawing module for grafdraw.c         */
 /* translates keystrokes to graphic characters,        */
 /* manages cursor control and function keys            */

 #include <conio.h>
 #include "keys.h"
 #include "scrn.h"
 #include "grafchar.h"
 extern unsigned char Grchr[];  /* defined in grafchar.c */

 void Draw_chars()
 {
     int ch, chout;
     unsigned char attrib = NORMAL;
     unsigned char draw = TRUE;

     chout = Grchr[0];  /* default graphics character */
     while ((ch = getch()) != ESC)
         {
         if (ch >= '0' && ch <= '_')
             chout = Grchr[ch - '0'];
             /* this maps the 0 key to the first */
             /* graphics character, etc.         */
         else if (ch == SPACE)
             chout = SPACE;
         else if (ch == 0) /* process cursor keys */
             {             /* and function keys   */
             ch = getch();
             switch (ch)
                 {
                 case PU : draw = FALSE;
                           break;
                 case PD : draw = TRUE;
                           break;
                 case UP : if (draw)
                               Write_ch_atr(chout, attrib,
                                            PAGE, 1);
                           if (!Cursup())
                               putch(BEEP);
                           break;
                 case DN : if (draw)
                               Write_ch_atr(chout, attrib,
                                            PAGE, 1);
                           if (!Cursdn_lim(BOTLINE))
                               putch(BEEP);
                           break;
                 case LT : if (draw)
                               Write_ch_atr(chout, attrib,
                                            PAGE, 1);
                           if (!Curslt())
                               putch(BEEP);
                           break;
                 case RT : if (draw)
                               Write_ch_atr(chout, attrib,
                                            PAGE, 1);
                           if (!Cursrt())
                               putch(BEEP);
                           break;
                 case F1 : attrib = NORMAL; break;
                 case F2 : attrib = VIDREV; break;
                 case F3 : attrib ^= BLINK; break;
                 case F4 : attrib ^= INTENSE; break;
                 default : putch(BEEP);
                 }
             }
         }
 }


 EGATOVGA.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\EGATOVGA.C

 /* egatovga.c -- converts ega color values to vga      */
 /*               color values.                         */

 long Ega_to_vga(egacolor)
 int egacolor;        /* ega color value */
 {
     static long vgavals[6] = {0x2a0000L, 0x002a00L,
                          0x00002aL, 0x150000L,
                          0x001500L, 0x000015L};
      /* array holds VGA equivalents to EGA bits */
     long vgacolor = 0L; /* vga color value */
     int bit;

     /* convert each bit to equivalent, and sum */
     for (bit = 0; bit < 6; bit++)
         vgacolor += ((egacolor >> bit) &1) * vgavals[bit];
     return (vgacolor);
 }


 EGGS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\EGGS.C

 /*  eggs.c -- draws colorful eggs                                      */
 /*  This program illustrates use of the video configuration            */
 /*  structure, the _ellipse() function, the effect of over-            */
 /*  lapping solid figures, and a the use of logical coordinates.       */
 /*  If you load graphics.qlb, no program list is needed.               */

 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <conio.h>
 #define ESC '\033'

 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _MRES4COLOR;
     short xcent[3], ycent[3]; /* egg centers */
     short xsize, ysize;       /* egg limits  */
     int egg;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
     {
         printf("Can't open mode %d\n", mode);
         exit(1);
     }
     _getvideoconfig(&vc);
     xsize = 0.3 * vc.numxpixels;
     ysize = 0.3 * vc.numypixels;
     xcent[0] = 0.3 * vc.numxpixels;
     xcent[1] = 0.5 * vc.numxpixels;
     xcent[2] = 0.7 * vc.numxpixels;
     ycent[0] = ycent[2] = 0.4 * vc.numypixels;
     ycent[1] = 0.6 * vc.numypixels;

     _selectpalette(0);
     _setbkcolor(_MAGENTA);
     for (egg = 0; egg < 3; egg++)
     {
         _setlogorg(xcent[egg], ycent[egg]);
         _setcolor(egg + 1);
         _ellipse(_GFILLINTERIOR, -xsize, -ysize, xsize, ysize);
     }
     _settextposition(24, 0);
     _settextcolor(1);
     _outtext("Strike any key to terminate.");
     getch();
     _setvideomode(_DEFAULTMODE);
 }


 ERR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\ERR.C

 /* err.c  --  illustrates __FILE__ and __LINE__ in */
 /*            tracing a small program              */

 #define ERR printf("Tracing: \"%s\" line %d\n",\
                     __FILE__, __LINE__);
 main()
 {
     ERR
     err1();
     ERR
     err2();
     ERR
 }

 err1()
 {
     ERR
     err2();
 }

 err2()
 {
     ERR
 }


 EXPO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\EXPO.C

 /* expo.c -- uses exp() function to  */
 /*            calculate powers       */

 main()
 {
     int expo(number, power);
     int number, power;

     printf("Enter a number: ");
     scanf("%d", &number);
     printf("Raise to what power? ");
     scanf("%d", &power);

     printf("Result: %d", expo(number, power));
 }

 int expo(number, power)
 {
     int count, value;
     int total = 1;      /* store value of calculation */
     if (power < 0)      /* reject negative exponents  */
         {
         printf("Error in expo(): negative exponent\n");
         return(0);
         }

     if (power == 0) /* any number to 0 power is 1 */
         return(1);

     if (power == 1) /* any number to 1 power is itself */
         return(number);

     /* calculate for power > 1 */
     for (count = 1; count <= power; count++)
         total *= number;
     return(total);
 }


 EXTERNAL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\EXTERNAL.C

 /* external.c -- shows an external variable */

 #define PI 3.14159
 int length; /* external (global) variable */
             /* declared before main ()    */

 main()
     {
     void square(), triangle(), circle();

     printf("What length do you want to use? ");
     scanf("%d", &length);

     square();   /* calculate areas */
     triangle();
     circle();
     }

 void square()
     {
     float area;
     area = length * length;
     printf("A square with sides of %d has an area of %f\n",
             length, area);
     }

 void triangle()
     {
     float area;
     area = (length * length) / 2;
     printf("A right triangle with sides of %d has an area %f\n",
             length, area);
     }

 void circle()
     {
     float area;
     area = (length * length * PI);
     printf("A circle with radius of %d has area of %f\n",
             length, area);
     }


 FIELDS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\FIELDS.C

 /* fields.c -- shows the same number with different */
 /*             field widths and number of decimals  */

 main()
 {
     float f = 123.4560;

     printf("%12.6f\n", f);
     printf("%8.4f\n", f);
     printf("%8.3f\n", f);
     printf("%8.2f\n", f);
 }


 FILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\FILE.C

 /* file.c  --  the file I/O routines for texed */

 Load_file()
 {
     printf("\nLoading ..... done.\n");
 }

 Save_file()
 {
     printf("\nSaving ...... done.\n");
 }


 FLOATS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\FLOATS.C

 /* floats.c  -- show floating values in regular */
 /*              and exponential format          */

 main()
 {
     float f1 = 2500.125, f2 = 0.0033, f3 = -50.99;

     printf("%f\t %e\n\n", f1, f1);
     printf("%f\t %e\n\n", f2, f2);
     printf("%f\t %e\n", f3, f3);
 }


 FMENU.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\FMENU.C

 /* fmenu.c  --  demonstrates file renaming, etc. */

 #include <direct.h>
 #include <stdio.h>
 #include <string.h>

 #define MAXPATH (80)
 char From_name[MAXPATH],
      To_name[MAXPATH];

 int Input(char *prompt, char buf[])
 {
     printf("%s: ", prompt);
     if (gets(buf) == NULL || *buf == '\0')
         return (0);
     return (1);
 }
 void Rename(void)
 {
     printf("->Rename/move\n");
     if (!Input("From", From_name)) return;
     if (!Input("To", To_name)) return;
     if (rename(From_name, To_name) != 0)
         perror("RENAME");
     else
         printf("Renamed: \"%s\" -> \"%s\"\n",
                 From_name, To_name);
 }
 void Remove(void)
 {
     printf("->Remove\n");
     if (!Input("Remove", From_name)) return;
     if (!Input("Are You Sure", To_name)) return;
     if (*To_name != 'y' && *To_name != 'Y')
         return;
     if (remove(From_name) != 0)
         perror(From_name);
     else
         printf("Removed: \"%s\"\n", From_name);
 }
 void Maketemp(void)
 {
     printf("->Maketemp\n");
     if (!Input("In What Directory", From_name))
         return;
     (void)strcat(From_name, "\\XXXXXX");
     if (mktemp(From_name) == NULL)
         printf("Can't create a unique name.\n");
     else
         printf("Created: \"%s\"\n", From_name);
 }
 void Quit(void)
 {
     printf("->Quit\n");
     if (!Input("Are You Sure", From_name))
         return;
     if (*From_name != 'y' && *From_name != 'Y')
         return;
     exit(0);
 }

 main()
 {
     static void (*doit[])() = {Rename, Remove, Maketemp, Quit};
     int ch;

     while (1)
         {
         printf("--------------------------------------------\n");
         printf("1) Rename/move a file or rename a directory.\n");
         printf("2) Remove a file.\n");
         printf("3) Make a unique temporary file.\n");
         printf("4) Quit.\n");
         printf("--------------------------------------------\n");
         printf("Select: ");

         do
             {
             ch = getchar();
             } while (ch < '1' || ch > '4');
         getchar();    /* gobble trailing newline */
         printf("%c\n\n", ch);
         ch -= '1';
         doit[ch]();
         }
 }


 FORLOOP.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\FORLOOP.C


 /* FORLOOP.C -- a simple for loop that   */
 /*              counts to ten            */

 main()
 {
     int i;
     for (i = 1; i <= 10; i++)
         {
         printf("%d\n",i);  /* body of loop */
         }
     printf("All done!\n");
     /* executed when i > 10 */
 }



 FORMATS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\FORMATS.C

 /* formats.c -- shows what happens when format */
 /*              doesn't match data type        */

 main()
 {
     int i = 5;
     printf("As integer:      %d\n", i);
     printf("As long integer: %ld\n", i);
     printf("As exponential:  %e\n", i);
     printf("As float:        %f\n", i);
 }


 GALAX.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\GALAX.C

 /* GALAX.C -- creates an ellipse by selecting */
 /*              from random pixels            */

 <graph.h> /* for graphics */
 <math.h>  /* for sqrt() */
 <conio.h> /* for kbhit() */

 main()
 {
     int pixels, radius = 50;
     double center_x = 320, center_y = 100,
         xpos, ypos;
     srand(0);
     _setvideomode(_HRESBW);
     _setcolor(1);
     for (pixels = 1; pixels < 25000; pixels++)
         {
         /* draws filled ellipse, due */
         /* to dimensions of hires screen */
         /* generate random location */
         xpos = rand() % 639;
         ypos = rand() % 199;
         if (sqrt /* is distance within radius? */
               ((xpos - center_x) * (xpos - center_x)
               + (ypos - center_y) * (ypos - center_y))
               < radius)
            _setpixel(xpos, ypos);
         if (kbhit() )
              break; /* exit if key pressed */
         }
     getch(); /* freeze screen until key pressed */
     _setvideomode(_DEFAULTMODE);
 }


 GETCH.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\GETCH.C

 /*     getch.c -- using getch()             */
 #include <conio.h>
 main()
 {
     int count = 1;

     printf("Please enter a word.\n");
     while (getch() != '\r')
         printf("%d.. ", count++);
     printf("\n%d characters altogether\n", count - 1);
 }


 GETCHAR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\GETCHAR.C

 /*      getchar.c -- using getchar()         */

 #include <stdio.h>
 main()
 {
     int count = 1;

     printf("Please enter a word.\n");
     while (getchar() != '\n')       /* here it is */
         printf("%d.. ", count++);
     printf("\n%d characters altogether\n", count - 1);
 }


 GETCHE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\GETCHE.C

 /*     getche.c -- using getche()             */
 <conio.h>     /* note different file included */
 main()
 {
     int count = 1;

     printf("Please enter a word.\n");
     while (getche() != '\r')    /* changed comparison */
         printf("%d.. ", count++);
     printf("\n%d characters altogether\n", count - 1);
 }


 GETCLOSE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\GETCLOSE.C

 /* getclose.c -- a number game using */
 /*               random numbers      */

 #define TRUE 1
 #define FALSE 0

     /* external variables */
     int number,     /* total number in current game   */
         moves,      /* number of moves in current game*/
         target,     /* target number to reach         */
         done,       /* true if game is over           */
         score,      /* score of current game          */
         wins = 0,   /* number of games won            */
         losses = 0, /* number of games lost           */
         total = 0;  /* total score                    */

     char move;

     /* function prototype declarations */
     void intro(void);       /* tell player about game   */
     char getyn(void);       /* get yes/no response      */
     int  random(int num);   /* random between 1 and num */
     void new_target(void);  /* target number for game   */
     char get_move(void);    /* get player's move        */
     void do_move(void);     /* generate num from move   */
     void check_move(void);  /* won, lost, or continue?  */
     void show_score(void);  /* show score for game      */
     void show_total(void);  /* show total score         */

 main()
 {
     intro();         /* print instructions */

     while (TRUE)     /* new games until user quits */
         {
         printf("\nDo you want to continue? ");
         if (getyn() != 'y')
             break;   /* exit program */

         done = FALSE;
         number = moves = score = 0;
         new_target();  /* target number for this game */
         while (!done)  /* play one game */
             {
             get_move();/* user selects random number  */
             do_move(); /* generate random number      */
                        /* and add                     */
             check_move();  /* win, lose, or continue? */
             }
         show_score();  /* score for this game */
         show_total();  /* total score         */
         }
 }

 void intro(void)
 {
     printf("Welcome to Getclose\n\n");
     printf("The object of this game is to\n");
     printf("try to get as close to the target\n");
     printf("number as possible in as few\n");
     printf("moves as possible by choosing from\n");
     printf("various ranges of random numbers.\n");
     printf("You score if you get within 4 of the\n");
     printf("target; a 100 point bonus for hitting\n");
     printf("the target, but no score if you go over.\n\n");
     }

 char getyn(void)
                     /* get yes or no answer      */
                     /* repeats until valid entry */
 {
     char ch;  /* character to read and return */

     while (TRUE)
         {
         printf(" (y or n) ");
         ch = getche();
         printf("\n");
         if ((ch == 'y') || (ch == 'n'))
         /* valid response, break out of loop */
             break;
         /* give error message and loop again */
         printf("please enter ");
         }
     return(ch);
     }

 int random(int num)
     /* generate random number between 1 and num     */
     /* doesn't use library function srand() because */
     /* we don't want the same seed each time        */
 {
     long seconds, result;
     time(&seconds);   /* randomize with system time */
     return (abs ((int)seconds * rand() % num) + 1);
 }

 void new_target(void)
              /* generate a new target number */
              /* between 50 and 99            */
 {
     target = 50 + random(49);
     printf("\nYour target for this game is %d\n",
         target);
 }

 char get_move(void)
     {
     while (TRUE)
         {
         printf("\nPick a random number from 1 to\n");
         printf("a) 5  b) 10  c) 25  d) 50  e) 100 ");
         move = getche();
         if ((move >= 'a') && (move <= 'e'))
             {
             ++moves; /* count the move */
             break;   /* valid response */
             }
         /* invalid response, try again */
         printf("\nPlease type a, b, c, d, or e\n");
         }
 }

 void do_move(void)
     {
     int num = 0;  /* random value to obtain */
     switch (move)
         {
         case 'a' :
             num = random(5);
             break;
         case 'b' :
             num = random(10);
             break;
         case 'c' :
             num = random(25);
             break;
         case 'd' :
             num = random(50);
             break;
         case 'e' :
             num = random(100);
             break;
         }
     number += num;  /* add new number to total */
     printf("\n\nYou got a %d. Number is now: %d ", num, number);
     printf("(Target is %d)\n", target);
 }

 void check_move(void)
 {
     int temp;
     if (number > target)
         {
         printf("\nYou went over! ");
         printf("No score this game.\n");
         losses++;
         done = TRUE; /* to break out of loop */
         }
     if (number == target)
         {
         printf("\nYou hit the target ");
         printf("for 100 bonus points!\n");
         score = (100 / moves) + 100;
         total += score;
         wins++;
         done = TRUE;
         }
     if ((number >= (target - 4)) && (number < target))
         {
         temp = 100 / moves;
         /* does player want to go for broke? */
         printf("\nTake %d points (y) or continue (n)? ",
             temp);
         if (getyn() == 'y')
             {
             score = temp;
             total += score;
             wins++;
             done = TRUE;
             }
        }
 }

 void show_score(void)
 {
     printf("\nYou scored %d points in %d moves.\n",
         score, moves);
 }

 void show_total(void)
 {
     printf("You have won %d games ", wins);
     printf("and lost %d.\n", losses);
     printf("Your total score is %d\n", total);
 }


 GETPUT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\GETPUT.C

 /*  getput.c -- illustrates _getimage(), _putimage(), */
 /*              the image-background interaction, and */
 /*              the aspect ratio                      */
 /* If you load graphics.qlb, no program list is needed*/

 #include <stdio.h>
 <stdlib.h>  /* declares malloc()  */
 #include <graph.h>
 #include <conio.h>
 #define ESC '\033'

 /* The following variables describe various          */
 /* coordinates and sizes.                            */
 /* They are declared externally so that they can be  */
 /* shared easily by several functions.               */
 int X1, Yb1, X2, Y2, Xdelta, Xside, Yside; /* image  */
 int Xmid, Xmax, Ymid, Ymax;           /* background  */
 int Xps, Xpr, Xand, Xor, Xxor, Ytop, Ybot; /* copies */
 int X[3], Y[3];
 float Ar;    /* aspect ratio */

 struct videoconfig Vc;
 char Mask[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0};
 void Initialize(void), Drawfig(void),
       Drawbackground(void), Drawcopies(void);

 main(argc, argv)
 int argc;
 char *argv[];
 {
     int mode = _MRES4COLOR;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
     {
         fprintf(stderr, "Can't handle mode %d\n", mode);
         exit(1);
     }
     Initialize();
     Drawfig();
     Drawbackground();
     Drawcopies();
     _settextposition(1, 1);
     _outtext("Press a key to end");
     _settextposition(3, 1);
     _outtext("_GPSET _GPRESET _GAND");
     _settextposition(11, 5);
     _outtext("_GOR _GXOR");
     getch();
     _setvideomode(_DEFAULTMODE);
 }

 void Initialize()
 {
     _getvideoconfig(&Vc);
     Ar = (float) (10 * Vc.numypixels)/
           (6.5 * Vc.numxpixels);
     _setlogorg(0, 0);
     Xmid = Vc.numxpixels / 2;
     Ymid = Vc.numypixels / 2;
     Xmax = Vc.numxpixels - 1;
     Ymax = Vc.numypixels - 1;
     /* locate three background rectangles */
     X[0] = Xmid;
     Y[0] = 0;
     X[1] = Xmid;
     Y[1] = Ymid;
     X[2] = 0;
     Y[2] = Ymid;
     X1 = 0.2 * Vc.numxpixels;
     Yb1 = 0.2 * Vc.numypixels;
     Xdelta = 0.033 * Vc.numxpixels;
     Xside = 3 * Xdelta;
     Yside = 3 * Ar * Xdelta;
     X2 = X1 + Xside;
     Y2 = Yb1 + Yside;
     /* offsets for _putimage() */
     Xps = .05 * Vc.numxpixels;
     Xpr = .20 * Vc.numxpixels;
     Xand = 0.35 * Vc.numxpixels;
     Xor = .10 * Vc.numxpixels;
     Xxor = .30 * Vc.numxpixels;
     Ytop = .05 * Vc.numypixels;
     Ybot = 2 * Ytop + Yside;
     _selectpalette(0);
 }

 void Drawfig()
 {
     _setcolor(1);
     _rectangle(_GFILLINTERIOR, X1, Yb1,
                X1 + Xdelta , Y2);
     _setcolor(2);
     _rectangle(_GFILLINTERIOR,X1 + Xdelta + 1, Yb1,
                X1 + 2 * Xdelta, Y2);
     _setcolor(3);
     _rectangle(_GFILLINTERIOR,X1 +  2 * Xdelta + 1,
                Yb1, X2, Y2);

 }

 void Drawbackground()
 {
     _setfillmask(Mask);
     _setcolor(1);
     _rectangle(_GFILLINTERIOR, Xmid, 0, Xmax - 1, Ymid - 1);
     _setcolor(2);
     _rectangle(_GFILLINTERIOR, Xmid, Ymid, Xmax, Ymax);
     _setcolor (3);
     _rectangle(_GFILLINTERIOR, 0, Ymid, Xmid - 1, Ymax);

 }

 void Drawcopies()
 {
     int quad;   /* quadrant used */
     char far *storage;

     storage = (char far *) malloc((unsigned)_imagesize(
                X1, Yb1, X2, Y2));
     _getimage(X1, Yb1, X2, Y2, storage);

     for (quad = 0; quad < 3; quad++)
         {
         _putimage(X[quad] + Xps, Y[quad] + Ytop,
                   storage, _GPSET);
         _putimage(X[quad] + Xpr, Y[quad] + Ytop,
                   storage, _GPRESET);
         _putimage (X[quad] + Xand, Y[quad] + Ytop,
                    storage, _GAND);
         _putimage (X[quad] + Xor, Y[quad] + Ybot,
                    storage, _GOR);
         _putimage(X[quad] + Xxor, Y[quad] + Ybot,
                   storage, _GXOR);
         }
 }


 GETYN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\GETYN.C

 /* getyn.c -- calls char function getyn()    */
 /*               with error checking         */

 #define TRUE 1

 main()
 {
     char ch;
     char getyn();

     printf("Do you want to continue? ");
     if ((ch = getyn()) == 'y')
         printf("Answer was y\n");
     else
         printf("Answer was n\n");
     printf("Value of ch was %c\n", ch);
 }

 char getyn()
 {
     char ch;
     while (TRUE)
         {
         printf(" (y or n) ");
         ch = getche();
         printf("\n");
         if ((ch == 'y') || (ch == 'n'))
         /* valid response, break out of loop */
             break;
         /* give error message and loop again */
         printf("please enter ");
         }
     return(ch);
 }


 GRAPHBOX.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\GRAPHBOX.C


 /* GRAPHBOX.C -- defined to use PC-specific */
 /*               graphics characters        */

 #define NL 10
 #define CR 13
 #define BLANK 32
 #define UPLEFT 201
 #define UPRIGHT 187
 #define LOWLEFT 200
 #define LOWRIGHT 188
 #define LINE 205
 #define SIDE 186

 main()
 {
     int i, j, height, width;

     /* get height and width from user */
     printf("How high a box do you want? ");
     scanf("%d", &height);
     printf("How wide do you want it to be? ");
     scanf("%d", &width);

     /* draw top of box */
     putch(UPLEFT);
     for (i = 0; i < (width - 2); i++)
         putch(LINE);
     putch(UPRIGHT);
     putch(NL);
     putch(CR); /* go to next line */

     /* draw sides of box */
     for (i = 0; i < height - 2; i++)  /* outer loop */
         {
         putch(SIDE); /* left side */
         for (j = 0; j < (width - 2); j++) /* inner loop */
             {
             putch(BLANK);
             }
         putch(SIDE); /* right side */
         putch(NL);
         putch(CR); /* move to next line */
         }

     /* draw bottom of box */
     putch(LOWLEFT);
     for (i = 0; i < (width - 2); i++)
         putch(LINE);
     putch(LOWRIGHT);
     putch(NL);
     putch(CR); /* box is done, move cursor to new line */
 }



 GRAPHCHA.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\GRAPHCHA.C

 /*   grafchar.c -- draws graphics characters with      */
 /*                 attributes on the screen            */
 /*  Program list : grafchar.c, initstuf.c, drawchar.c, */
 /*                  scrfun.c                           */
 /*  User include files: keys.h, scrn.h, grafchar.h     */
 /*  Note: activate Screen Swapping On in Debug menu    */

 #include "grafchar.h"
 unsigned char Grchr[NUMCHARS];  /* to store graphics set */
 void Init_stuff(void);      /* in initstuf.c */
 void Draw_chars(void);      /* in drawchar.c */

 main()
 {
     Init_stuff();  /* initialize vital elements */
     Draw_chars();  /* map keys to graphics characters */
 }


 HARDWARE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\HARDWARE.C

 /* hardware.c -- shows a mixture of int, */
 /*               float, and char types   */

 main()
 {
     int threads    = 8;       /* threads per inch */
     float length   = 1.25,    /* length in inches */
           diameter = 0.425,   /* diameter in inches */
           price    = 0.89;    /* price per hundred */
     char bin = 'A';           /* kept in bin A */
     long quantity = 42300;    /* number in bin */

     printf("Screws: %d threads/inch\n%f inches long\n",
             threads, length);
     printf("%f diameter\n\n", diameter);
     printf("Price per 100: %f\n", price);
     printf("Stored in bin: %c\nQuantity on hand: %ld",
             bin, quantity);
 }


 HELLO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\HELLO.C

 /* hello.c  --  legal ways to initialize strings as */
 /*              arrays of char values               */

 char Gphrase[] = {
     'H','e','l','l','o','\n','\0' };    /* global initialization */

 main()
 {
     static char gphrase[] = {
         'h','e','l','l','o','\n','\0' };    /* local initialization */

     printf("Global: %s\n", Gphrase);
     printf("Local:  %s\n", gphrase);

 }


 HELP.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\HELP.C

 /*  help.c -- uses paging and direct memory access    */
 /*            to display a help screen                */
 /*  Program list: help.c, writestr.c, writechr.c,     */
 /*                scrfun.c                            */
 /*  User include files: scrn.h, color.h               */
 /*  Note: activate Screen Swapping On in Debug menu   */

 #include <stdio.h>
 #include <conio.h>
 #include "color.h"
 #include "scrn.h"
 typedef unsigned int (far * VIDMEM);
 #define CGAMEM ((VIDMEM) (0xB800L << 16))
 #define PAGESIZE 2000
 #define PAGEOFFSET  0x800L
 #define ESC '\033'
 #define ATTR1 (BG_BLUE | YELLOW)
 #define ATTR2 (BG_YELLOW | BLUE)
 #define ATTR3 (BG_RED | YELLOW | BLINK | INTENSE)
 #define CH1  (unsigned short) '\xB1'
 char *str1 = "Press ? key for help.";
 char *str2 = "Press Enter key to return.";
 char *str3 = "Press Esc key to quit.";
 char *str4 = "\xB1HELP!\xB1";
 void Write_chars(VIDMEM, unsigned short, unsigned
                     short, unsigned short);
 void Write_str(VIDMEM, unsigned short, char *);

 main()
 {
     int ch;
     unsigned char page = 0;
     unsigned char mode;

     mode = Getvmode();
     if (mode != TEXTC80 && mode != TEXTBW80)
     {
         printf("Only modes 2 and 3 supported. Bye.\n");
         exit(1);
     }
     Setpage (page);
     Write_chars(CGAMEM, '\0', ATTR2, PAGESIZE);
     Write_str(CGAMEM + 2 * COLS, ATTR1, str1);
     Write_str(CGAMEM + 2 * COLS, ATTR1, str1);
     Write_str(CGAMEM + 22 * COLS, ATTR1, str3);
     Write_chars(CGAMEM + PAGEOFFSET, '\0', ATTR1, PAGESIZE);
     Write_str(CGAMEM + PAGEOFFSET + 20 * COLS, ATTR2, str2);
     Write_str(CGAMEM + PAGEOFFSET + 22 * COLS, ATTR1, str3);
     Write_chars(CGAMEM + PAGEOFFSET + 10 * COLS + 36,
                 CH1, ATTR3, 7);
     Write_str(CGAMEM + PAGEOFFSET + 11 * COLS + 36,
               ATTR3, str4);
     Write_chars(CGAMEM + PAGEOFFSET + 12 * COLS + 36,
                 CH1, ATTR3, 7);

     while ((ch = getch()) != ESC)
         {
         if (ch == '?' && page == 0)
             Setpage (page = 1);
         else if (ch == '\r' && page == 1)
             Setpage(page = 0);
         }
     Write_chars(CGAMEM, '\0', NORMAL, PAGESIZE);
     Write_chars(CGAMEM + PAGEOFFSET, '\0', NORMAL, PAGESIZE);
 }


 HEXOUT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\HEXOUT.C

 /* hexout.c --  print a floating point variable in */
 /*              hexadecimal format                 */

 extern void Hexout();

 main()
 {
     float fary[1];

     printf("Enter a floating point number\n");
     printf("(Any nonnumeric entry quits)\n\n");
     while (scanf("%f", &fary[0]) == 1)
         {
         Hexout(fary);
         }
     return (0);
 }

 void Hexout(unsigned char chary[])
 {
     int i;

     for (i = 0; i < sizeof(float); ++i)
         {
         printf("%02X ", chary[i]);
         }
     printf("\n\n");
 }


 IBMIQ.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\IBMIQ.C

 /* ibmiq.c -- a short dialog                          */

 #include <stdio.h>
 main()
 {
     char name[80];
     int iq;

     printf("Enter your first name: -> ");
     scanf("%s", name);
     printf("Enter your IQ: -> ");
     scanf("%d", iq);
     printf("Well, %s, my IQ is %d!", name, 2 * iq - 1 );
 }


 IF.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\IF.C

 /* if.c -- simple IF statement */

 char ch;
 main()
 {
     printf("Do you want to continue y/n? "); /* prompt */
     if (ch = getche() == 'y')
         printf("\nLet's continue ...\n");    /* if true */
     printf("\nAll done.\n");                 /* always executed */
 }


 IFELSE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\IFELSE.C

 /* ifelse.c -- IF with ELSE */

 char ch;
 int num;
 main()
 {
     printf("Are you a new user? y/n? ");
     if (ch = getche() == 'y')
         {
         /* executed if IF is true */
         printf("\n\nYou must register to use this\n");
         printf("bulletin board. Please read\n");
         printf("Bulletin #1 first. Thank You.\n");
         }
     else
         /* executed if IF is false */
         {
         printf("\n\nEnter your secret number: ");
         scanf("d", &num);
         }
 }


 INCDEC.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\INCDEC.C

 /* incdec.c -- shows effect of            */
 /*             increments and decrements  */

 main()
 {
     int a = 10;

     printf("a is %d\n", a);
     printf("++a is %d\n", ++a);
     printf("--a sets a back to %d\n", --a);
 }


 INDEXER.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\INDEXER.C

 /* indexer.c -- use indices to display an array      */

 #include <stdio.h>
 int code1[] = {2, 4, 6, 8};
 int code2[] = {1, 3, 7, 9};
 int code3[] = {5, 10, 15, 20};
 main()
 {
     int index;
     int size = (sizeof code2) / (sizeof (int));

     for ( index = 1; index <= size; size++)
        printf("%3d ", code2[index]);
     putchar('\n');
 }



 INDEXER2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\INDEXER2.C

 /* indexer2.c -- use indices to display an array      */

 #include <stdio.h>
 int code1[] = {2, 4, 6, 8};
 int code2[] = {1, 3, 7, 9};
 int code3[] = {5, 10, 15, 20};
 main()
 {
     int index;
     int size = (sizeof code2) / (sizeof (int));
                 /* get number of elements in array */

     for ( index = 1; index <= size; index++)
        printf("%3d ", code2[index]);
     putchar('\n');
 }


 INFLATE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\INFLATE.C


 /* INFLATE.C -- shows multiple initialization */
 /*              and calculations in for loop  */

 main()
 {
     int year;
     float value, rate;
     printf("What do you think the inflation rate will be?");
     scanf("%f", &rate);
     printf("If the dollar is worth 100 cents in 1987\n");
     printf("and the inflation rate is %2.2f, then:\n", rate);

     for (year=1988, value = 1.0; year <=1999;
          value *= (1.0 - rate),
          printf("in %d the dollar will be worth", year),
          printf(" %2.0f cents\n", value * 100),
          ++year
          );
 }



 INITSTUF.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\INITSTUF.C

 /*  initstuf.c -- initializing module for grafchar.c */
 /*  assign graphics character codes to an array      */
 /*  and initialize screen                            */

 "scrn.h"   /* Clearscr(), Home(), Setcurs() */
 #include "grafchar.h"
 extern unsigned char Grchr[];  /* defined in grafchar.c */
 void Print_attr(char *, unsigned char, unsigned char);
 void Init_stuff()
 {
     int i;

     /* initialize array with graphics characters */
     for (i = 0; i < NUMCHARS; i++)
         Grchr[i] = GCSTART + i;
     Clearscr();
     Home();

     /*   show key meanings at bottom of screen */
     Setcurs(BOTLINE + 1, 0, PAGE);
     for (i = 0; i < 40; i++) /* graphics chars */
     {
         putch(Grchr[i]);
         putch(SPACE);
     }
     Setcurs(BOTLINE + 2, 0, PAGE);
     for (i = 0; i < 40; i++)  /* key assignments */
     {
         putch('0' + i);
         putch(SPACE);
     }
     Setcurs(BOTLINE + 3, 0, PAGE);
     for (i = 40; i < NUMCHARS; i++) /* second row */
     {
         putch(Grchr[i]);
         putch(SPACE);
     }
         /* show function key assignments */
     printf(" SPACE : ERASE  PgUp : No Draw ");
     printf(" PgDn : Draw  ESC : Quit");
     Setcurs(BOTLINE + 4, 0, PAGE);
     for (i = 40; i < NUMCHARS; i++) /* second row */
     {
         putch('0' + i);
         putch(SPACE);
     }
        /* more function key assignments */
     Print_attr("F1 : Normal ", NORMAL, PAGE);
     Print_attr("F2 : Reverse Video ", VIDREV, PAGE);
     Setcurs(BOTLINE + 5, 16, PAGE);
     Print_attr("F3 : Blinking ", NORMAL | BLINK, PAGE);
     Print_attr("F4 : Intense ", NORMAL | INTENSE, PAGE);
     Home();
 }

 void Print_attr(str, attr, page)
 char *str;
 unsigned char attr, page;
 {
     while (*str != '\0')
     {
         Write_ch_atr(*str++, attr, page, 1);
         Cursrt();
     }
 }


 INTVARS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\INTVARS.C

 /* intvars.c -- declare, define, and print */
 /*              some integer variables     */

 main()
 {
     /* declare variables */
     int length, beam;
     unsigned int displacement;
     /* assign values to variables */
     length = 824;
     beam = 118;
     displacement = 41676;

     /* print out values */
     printf("The battleship Bismarck was %d feet long",
             length);
     printf(" with a beam of %d feet,\n", beam);
     printf("and displaced %u tons.\n", displacement);
 }


 INVERT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\INVERT.C

 /* invert.c  --  combines character classification and */
 /*               transformation to invert text         */

 <stdio.h>         /* for NULL           */
 <ctype.h>         /* for toupper, et al */

 main()
 {
     char buf[BUFSIZ];
     int i;

     printf("Type in a line of text and I will invert it.\n");

     if (gets(buf) == NULL)
         exit(1);

     /* Print the string backwards. */
     for (i = (strlen(buf) -1); i >= 0; --i)
         {
         if (isupper(buf[i]))            /* upper to lower */
             putchar(tolower(buf[i]));
         else if (islower(buf[i]))       /* lower to upper */
             putchar(toupper(buf[i]));
         else
             putchar(buf[i]);
         }
     putchar('\n');

 }


 KEYS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\KEYS.C

 /* keys.c  --   The keyboard input-handling routines  */
 /*              for the texed editor.                 */

 Edit_file()
 {
     char ch;

     printf("\nYou are now in the editor.\n");
     printf("Press 'Q' to exit back to main menu.\n");

     do
         {
         ch = getch();
         putch(ch);
         } while (ch != 'Q');

     printf("\n\n");
 }


 L2WORDS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\L2WORDS.C

 /* l2words.c  --  employ an array of pointers to   */
 /*                strings to bust a line of text   */
 /*                into its component words         */

 <stdio.h>          /* for NULL and BUFSIZ */

 main()
 {
     char **Line2words();    /* declare function type */
     char **list;            /* pointer to pointer    */
     char buf[BUFSIZ];       /* buffer for input      */
     int  count, i, quote_flag;

     printf("Enter a line of text and I will break\n");
     printf("it up for you.\n");

     if (gets(buf) == NULL)
         exit(1);

     list = Line2words(buf, &count);

     for (i = 0; i < count; i++)
         {
         quote_flag = 0;
         printf("<");
         if (list[i] != buf)
             {
             if( list[i][-1] == '"')    /* negative subscript */
                 {
                 ++quote_flag;
                 printf("\"");
                 }
             }
         printf("%s", list[i]);

         if (quote_flag)
             printf("\"");

         printf(">\n");
         }
 }

 #define MAXW 64

 char **Line2words(char *line, int  *count)
 {
     static char *words[MAXW];
     int  index;

     index = 0;        /* zero internal index */

     while (*line != '\0')
         {
         /* turn spaces and tabs into zeros */
         if (*line == ' ' || *line == '\t')
             {
             *(line++) = '\0';
             continue;
             }
         words[index] = line++;    /* found a word */

         /* is it quoted? */
         if ( *(words[index]) == '"')
             {
             /* Yes, advance pointer to just past quote. */
             ++words[index];

             /* find next quote. */
             while (*line && *line != '"')
                 {
                 ++line;
                 }

             /* and turn it into a '\0'. */
             if (*line)
                 *(line++) = '\0';
             }
         else
             {
             /* otherwise skip to next space */
             while (*line && *line != ' ' && *line != '\t')
                 {
                 ++line;
                 }
             }
         if (++index == MAXW)
             break;
         }
     *count = index;        /* set count via pointer   */
     return (words);        /* return address of array */
 }


 LEFTSTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\LEFTSTR.C

 /* leftstr.c -- a C version of BASIC's LEFT$ */

 #include <stdio.h>

 char *Leftstr(char *str, int cnt)
 {
     static char *cp = NULL;
     char *malloc();

     if (cnt > strlen(str))
         cnt = strlen(str);
     if (cp != NULL)
         free(cp);
     if ((cp = malloc(cnt + 1)) == NULL)
         return (NULL);
     strncpy(cp, str, cnt);
     return (cp);
 }


 LINES.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\LINES.C

 /* lines.c -- calls line() with */
 /*            five parameters   */

 #include <graph.h>

 main()
 {
     void line (x1, y1, x2, y2, color);

     int x1, x2, y1, y2, i, color;

     _setvideomode(_MRES16COLOR); /* 320 x 200  16 col. */
     srand(2);                    /* new random seed    */
     for (i = 0; i < 100; i++)
         {
         x1 = rand() % 319;       /* random coordinates */
         x2 = rand() % 319;
         y1 = rand() % 199;
         y2 = rand() % 199;
         color = (rand() % 14) + 1; /* random color 1-15 */
         line(x1, y1, x2, y2, color); /* draw a line   */
         }
     while(!kbhit() ); /* wait for key to be hit */

     _setvideomode(_DEFAULTMODE); /* restore video mode */
 }

 void line (x1, y1, x2, y2, color)
 int x1, y1, x2, y2, color;
 {
     _moveto(x1, y1); /* position at first endpoint   */
     _setcolor(color);
     _lineto(x2, y2); /* draw line to second endpoint */
 }


 LINES43.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\LINES43.C

 /* lines43.c -- leaves EGA in 43-line mode */

 #include <dos.h>
 #include <conio.h>
 #define VIDEO 0x10
 #define SETVMODE 0
 CHAR_GEN 0x11   /* an EGA BIOS function number */
 #define ROM8X8   0x12
 #define BLOCK 0
 #define TEXTC80 3

 main()
 {
      union REGS reg;

      reg.h.ah = SETVMODE;    /* set text mode */
      reg.h.al = TEXTC80;
      int86(VIDEO, &reg, &reg);

      reg.h.ah = CHAR_GEN;   /* char generator routine */
      reg.h.al = ROM8X8;  /* use 8x8 ROM character box */
      reg.h.bl = BLOCK;   /* copy to block 0 */
      int86(VIDEO, &reg, &reg);
 }


 LINE_CNT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\LINE_CNT.C

 /*  line_cnt.c -- An overly active line counter       */
 #include <stdio.h>
 main()
 {
     int ch;
     int lines = 0;

     while ( (ch = getchar() ) != EOF )
         if ( ch = '\n')
             lines++;
     printf("There were %d lines\n", lines);
 }



 LOCAL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\LOCAL.C

 /* local.c -- local variables defined */
 /*            within functions        */

 main()
     {
     int n = 12;
     int func1(), funct2();
     printf("n in main(): val %d ", n);
     printf("address %d\n", &n);

     printf("Calling func1()\n");
     func1();
     printf("Calling func2()\n");
     func2();
     }

 int func1()
     {
     int n = 8; /* local variable */
     printf("n in func1(): val %d ", n);
     printf("address %d\n", &n);
     }

 int func2()
     {
     int n = 20; /* local variable */
     printf("n in func2(): val %d ", n);
     printf("address %d\n", &n);
     }


 M.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\M.C

 /* m.c -- draw a letter M        */
 /*        using IF and CONTINUE  */

 /* define characters */

 CH 'M'    /* character to "draw" with */
 #define BLANK ' '
 #define NL 10
 #define CR 13
 LEFT 20   /* left side of M   */
 RIGHT 46  /* right side of M  */
 BOTTOM 22 /* last line to use */
 main()
 {
     int pos, line;
     /* space to left side */
     for (line = 1; line <= BOTTOM; line++)
         {
         for (pos = 1; pos < LEFT; pos++)
             {
             putch(BLANK);
             }
         putch(CH); /* draw left side */

         /* are we past midpoint? */
         if (line > ((RIGHT - LEFT) / 2))
             {
             /* yes, so just draw right side */
             for (pos = LEFT; pos < RIGHT; pos++)
                 {
                 putch(BLANK);
                 }
             putch(CH);
             putch(NL);
             putch(CR);
             continue; /* start loop over, do next line */
             }
             /* not past midpoint, check for interior */
         for (pos = LEFT; pos < RIGHT; pos++)
             {
             if ((pos == (LEFT + line )) ||
                  (pos == (RIGHT - line )))
                 putch(CH);
             else
                 putch(BLANK);
             }
        putch(CH);
        putch(NL);
        putch(CR); /* could also use printf("\n"); */
        }
 }


 MAGIC.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\MAGIC.C

 /* magic.c  --  demonstrate use of a two-dimensional  */
 /*              array of type int                     */

 main()
 {
     static int square[3][3] = { 5, 8, 3, 4, 2, 0, 7, 1, 6 };
     int zrow = 1, zcol = 2;  /* location of the zero */
     int num, row, col, i , j, rowdist, coldist;

     while (1)
         {
         printf("Swap what with zero?\n");
         printf("(Q to quit)\n");

         /* Print the square. */
         for (i = 0; i < 3; ++i)
             {
             for (j = 0; j < 3; ++j)
                 {
                 printf(" %d ", square[i][j] );
                 }
             printf("\n");
             }

         /* Input the user number. */
         if ((num = getch()) == 'Q')
             exit(0);
         num -= '0';
         if (num < 1 || num > 9)
             {
             printf("Not a legal number.\n\n");
             continue;
             }

         /* Find that square. */
         for (row = 0; row < 3; ++row)
             {
             for(col = 0; col < 3; ++col)
                 {
                 if (num == square[row][col])
                     {
                     goto GOTIT;
                     }
                 }
             }
 GOTIT:
         /* Check for a legal move. */
         if (row > 2 || col > 2)
             {
             printf("Bad Box Specification\n\n");
             continue;
             }
         rowdist = zrow - row;
         if (rowdist < 0)
             rowdist *= -1;
         coldist = zcol - col;
         if (coldist < 0)
             coldist *= -1;
         if (rowdist > 1 || coldist > 1)
             {
             printf("Not A Neighbor\n\n");
             continue;
             }

         /* Make the move. */
         square[zrow][zcol] = square[row][col];
         square[row][col] = 0;
         zrow = row;
         zcol = col;

         /* See if done, and solved. */
         for (i = 0; i < 3; ++i)
             {
             for (j = 0; j < 3; ++j)
                 {
                 if (square[i][j] != ((i * 3) + j))
                     {
                     break;
                     }
                 }
             }
         if ((i * j) == 9)
             break;
         }
     printf("\n\aYOU GOT IT !!!\n");
 }


 MASKS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\MASKS.C

 /*  masks.c -- illustrates _setfillmask() and         */
 /*             _floodfill()                           */
 /* Program list: masks.c                              */
 /* If you load graphics.qlb, no program list is needed*/

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <graph.h>
 unsigned char Inversemask[8];
 unsigned char Masks[3][8] = {
             {0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00},
             {0xff,0x80,0x80,0x80,0xff,0x08,0x08,0x08},
             {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa}};
 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _MRES4COLOR;
     short xc, yc;
     short box, i;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
     {
         fprintf(stderr,"Can't set mode %d\n", mode);
         exit(1);
     }
     _getvideoconfig(&vc);
     xc = vc.numxpixels / 2;
     yc = vc.numypixels / 2;
     for (i = 0; i < 8; i++)
         Inversemask[i] = ~Masks[1][i];
     _setlogorg(xc, yc);
     _selectpalette(0);
     _setcolor(1);
     _rectangle(_GBORDER, -xc + 1, -yc + 1, xc - 1, yc - 1);
     _moveto(-xc + 1, -yc / 3);
     _lineto(xc -1, -yc / 3);
     _moveto(-xc + 1, yc / 3);
     _lineto(xc -1, yc / 3);
     for (box = 0; box < 3; box++)
     {
          _setcolor(box + 1);
          _setfillmask(Masks[box]);
          _floodfill(0, (box - 1) * yc / 2, 1);
     }
     _settextposition(5, 10);
     _outtext("Press a key to continue");
     getch();
     _setcolor(3);
     _setfillmask(Inversemask);
     _floodfill (0, 0, 1);
     _setcolor(2);
     _setfillmask(Masks[0]);
     _floodfill(0, yc / 2, 1);
     _settextposition(5, 10);
     _outtext("Press a key to terminate");
     getch();
     _setvideomode(_DEFAULTMODE);
 }


 MATH.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\MATH.C

 /* math.c -- shows arithmetic and       */
 /*           precedence via expressions */

 main()
 {
     int a = 10, b = 4, c = 2;

     /* simple arithmetic expressions */
     printf("99 + 2 = %d\n", 99 + 2);  /* ints */
     printf("5 - 12 = %d\n", 5 - 12);
     printf("7.25 + 3.5 = %f\n", 7.25 + 3.5);
                                         /* floats */

     /* compare presedence on these */
     printf("20 * 20 + 40 = %d\n", 20 * 20 + 40);
     printf("20 * (20 + 40) = %d\n", 20 * (20 + 40));
     printf("a * a - c + b = %d\n", a * a - c + b);
     printf("a * (a - (c + b)) = %d\n",
             a * (a - (c + b)));

     /* compare integer and float division */

     printf("Integers: 5 / 2 = %d\n", 5 / 2);
     printf("Floats: 5.0 / 2.0 = %f\n", 5.0 / 2.0);
 }


 MATHTEST.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\MATHTEST.C

 /* mathtest.c -- driver for do_math()                 */
 /* Program list: mathtest.c (to link math functions)  */

 #include <stdio.h>
 double do_math(double);
 main()
 {
     double input, result;

     printf("Enter a number: ");
     while (scanf("%lf", &input) == 1)
         {
         result = do_math(input);
         printf("input = %.2e, result = %.2e\n", input,
                 result);
         printf("Next number (q to quit): ");
         }
 }

 #include <math.h>
 double do_math(x)
 double x;
 {
     return (sin (x) * exp (-x));
 }



 MENU.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\MENU.C

 /*  menu.c -- uses ansi.sys for cursor control and   */
 /*            for video reverse in a sample menu     */
 /*  Note: Requires that ANSI.SYS be installed.       */

 #include <conio.h>
 ITEMS 5           /* number of menu items */
 UP 72             /* scan code for up arrow */
 DOWN 80           /* scan code for down arrow */
 VIDREV "\033[7m"  /* reverse video attribute */
 ATTOFF "\033[0m"  /* turn attributes off   */
 ED()   printf("\033[2J")  /* erase display */
 HOME() printf("\033[H")  /* home the cursor */
 CUU(Y) printf("\033[%dA",Y);  /* cursor up */
 CUD(Y) printf("\033[%dB",Y);  /* cursor down */

 char *Menu[ITEMS] = {"Add a number to the list",
                      "Delete a number from the list",
                      "Clear the list",
                      "Sum the list",
                      "Quit"};
 char *Heading =
 "Use arrow keys to highlight choice. "
 "Use Enter key to select choice.";

 void showmenu(int);
 int getmesg(int);
 main()
 {
     int messno = 0; /* message to be highlighted */
     ED();
     showmenu(messno);
     while (messno != ITEMS - 1)
         {
         messno = getmesg(messno);
         ED();
         switch (messno)
            {
            case 0 :
            case 1 :
            case 2 :
            case 3 : printf("...pretending to work ...");
                     printf("Hit any key to continue\n");
                     getch();
                     ED();
                     showmenu(messno);
                     break;
            case 4 : printf("Quitting!\n");
                     break;
            default: printf("Programming error!\n");
                     break;
            }
         }
 }

 /* showmenu() displays the menu  */
 void showmenu(highlite)
 int highlite;   /* message number to be highlighted */
 {
     int n;
     char *start;

     HOME();
     printf("%s", Heading);
     for (n = 0; n < ITEMS; n++)
     {
         if (n == highlite)
             start = VIDREV; /* turn on reverse video */
         else
             start = ATTOFF;
         printf("\n\n%s%s%s", start, Menu[n], ATTOFF);
     }
     HOME();
     CUD(2 + 2 * highlite);
 }

 /*  getmesg() selects a menu item */
 int getmesg(mnum)
 int mnum; /* current message number */
 {
     char ch;

     while ((ch = getch()) != '\r')
         if (ch == 0)
             {
             ch = getch();
             switch (ch)
                 {
                 case UP   : if (mnum > 0)
                                 {
                                 CUU(2);
                                 showmenu (--mnum);
                                 }
                             else
                                 {
                                 CUD(2 * ITEMS - 2);
                                 showmenu(mnum=ITEMS-1);
                                 }
                             break;
                 case DOWN : if (mnum < ITEMS - 1)
                                 {
                                 CUD(2);
                                 showmenu(++mnum);
                                 }
                             else
                                 {
                                 CUU(2 * ITEMS - 2);
                                 showmenu(mnum = 0);
                                 }
                             break;
                 }
             }
         return mnum;
 }


 MIDSTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\MIDSTR.C

 /* midstr.c -- a C version of BASIC's MID$  */

 #include <stdio.h>

 char *Midstr(char *str, int where, int cnt)
 {
     static char *cp = NULL;
     char *malloc();

     if (cnt > strlen(str + where))
         cnt = strlen(str + where);
     if (cp != NULL)
         free(cp);
     if ((cp = malloc(cnt + 1)) == NULL)
         return (NULL);
     strncpy(cp, str+where, cnt);
     return (cp);
 }



 MISIDENT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\MISIDENT.C

 /* misident.c -- careless typing              */

 #defne BIG 3
 main()
 {
     char ltr;
     integer num;

     num = 2 + BIG;
     lrt = 'a';
     printf("%c %d\n", ltr, num);
 }



 MIXED.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\MIXED.C

 /* mixed.c -- shows the effects of mixing */
 /*            data types in an expression */

 main()
 {
     int     i = 50, iresult;
     long    l = 1000000, lresult;
     float   f = 10.5, fresult;
     double  d = 1000.005, dresult;

     fresult = i + f;         /* int + float to float */
     printf("%f\n", fresult);

     fresult = i * f;         /* int * float to float */
     printf("%f\n", fresult);

     lresult = l + f;         /* long + int to long */
     printf("%f\n", lresult);

     printf("%f\n", d * f);   /* double * float */
                                  /* to double */
     fresult = d * f;         /* assigned to a float */
     printf("%f\n", fresult); /* loses some precision */

     /* debugging a division problem */

     iresult = i / l;          /* int / long to int */
     printf("%d\n", iresult);  /* whoops! loses result */
     printf("%ld\n", iresult); /* this won't fix it */
     fresult = i / l;          /* store in float result */
     printf("%f\n", fresult);  /* doesn't work */
     dresult = i / l;          /* try a double */
     printf("%f\n", dresult);  /* doesn't work */
     fresult = (float) i / l;  /* try type cast */
     printf("%f\n", fresult);  /* correct result */
 }


 MIXLOOPS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\MIXLOOPS.C


 /* MIXLOOPS.C -- reads characters,       */
 /*               beeps for ASCII count   */
 /*               uses a while and a for  */

 #include <conio.h>

 main()
 {
     char ch;
     int  i;

     while ((ch = getche()) != ' ')  /* get a char. */
         {
         for (i = 'a'; i <= ch; ++i) /* count up to */
             {                       /* alphabet pos.*/
             printf("In FOR loop!\n");
             printf("\a");  /* sound beep each time */
             }
         }
 }



 MIXTYPES.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\MIXTYPES.C

 /* mixtypes.c -- shows problem with calling           */
 /*               a function with wrong type parameter */

 main()
 {
     /* didn't bother to declare int function */
     float n = 5.0;
     int i;

     printf("n in main() is %f\n", n);
     i = examine(n);    /* pass float to function */
     printf("examine() returned n as %d\n", i);
 }

 examine(num)  /* function didn't declare return type */
 {
     printf("examine() says n is %d\n", num);
     return(num);
 }



 MODEINFO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\MODEINFO.C

 /* modeinfo.c -- set modes and obtain information      */
 /* Demonstrates _setvideomode() and _getvideoconfig()  */
 /* If you load graphics.qlb, no program list is needed.*/

 #include <conio.h>
 #include <graph.h>
 struct videoconfig vc;
 int modes[15] ={_TEXTBW40, _TEXTC40, _TEXTBW80, _TEXTC80,
         _MRES4COLOR, _MRESNOCOLOR, _HRESBW, _TEXTMONO,
         _MRES16COLOR, _HRES16COLOR, _ERESNOCOLOR, _ERESCOLOR,
         _VRES2COLOR, _VRES16COLOR, _MRES256COLOR};
 char *Adapt(short), *Display(short);
 main()
 {
     int i;

     for (i = 0; i < 15; i++)
     {
         if (_setvideomode(modes[i]))
         {
             _getvideoconfig(&vc);
             printf("video mode is %d\n", vc.mode);
             printf("number of columns is %d\n", vc.numtextcols);
             printf("number of colors is %d\n", vc.numcolors);
             printf("number of pages is %d\n", vc.numvideopages);
             printf("adapter is %s\n", Adapt(vc.adapter));
             printf("display is %s\n", Display(vc.monitor));
             printf("the adapter has %dK of memory\n",
                     vc.memory);
         }
         else
             printf("mode %d not supported\n", modes[i]);
         printf("strike a key for next mode\n");
         getch();
     }
     _setvideomode (_DEFAULTMODE);
 }

 /* Adapt() returns a pointer to a string describing   */
 /* the adapter characterized by adapt_num.            */
 char *Adapt(adapt_num)
 short adapt_num; /* videoconfig.adapter value         */
 {
     static char *anames[6] = {"Monochrome", "CGA", "EGA",
                               "MCGA", "VGA", "Not known"};
     char *point;

     switch (adapt_num)
     {
         case _MDPA : point = anames[0];
                      break;
         case _CGA  : point = anames[1];
                      break;
         case _EGA  : point = anames[2];
                      break;
         case _MCGA : point = anames[3];
                      break;
         case _VGA  : point = anames[4];
                      break;
         default    : point = anames[5];
     }
     return point;
 }

 /* Display() returns a pointer to a string describing  */
 /* the monitor characterized by disp.                  */
 char *Display(disp)
 short disp;  /* videoconfig.monitor value              */
 {
     static char *types[5] = {"monochrome", "color",
                              "enhanced color", "analog",
                              "unknown"};
     char *point;

     if (disp & _MONO)
         point = types[0];
     else if (disp & _COLOR)
         point = types[1];
     else if (disp & _ENHCOLOR)
         point = types[2];
     else if (disp & _ANALOG)
         point = types[3];
     else
         point = types[4];
     return point;
 }


 MOIRE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\MOIRE.C

 /*   moire.c -- variation on dots.c                   */
 /* If you load graphics.qlb, no program list is needed*/
 #include <conio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #define ESC '\033'
 BKCOLS 8      /* number of background colors */
 PALNUM 4      /* number of palettes */
 long Bkcolors[BKCOLS] = {_BLACK, _BLUE, _GREEN, _CYAN, _RED,
                          _MAGENTA, _BROWN, _WHITE};
 main (argc, argv)
 int argc;
 char *argv[];
 {
      struct videoconfig vc;
      unsigned int col, row;
      short color = 0;
      int bkc_index = 1;  /* blue background */
      short palette = 0;  /* red, green, brown */
      int firstcol, firstrow, lastrow, lastcol;
      int mode = _MRES4COLOR;
      int ch;

      if (argc > 1)
           mode = atoi(argv[1]);

      if (_setvideomode(mode) == 0)
           {
           printf("Can't do that mode.\n");
           exit(1);
           }
      _getvideoconfig(&vc);
      firstcol = vc.numxpixels / 5;
      firstrow = vc.numypixels / 5;
      lastcol = 4 * vc.numxpixels / 5;
      lastrow = 4 * vc.numypixels / 5;
      _selectpalette(palette);
      _setbkcolor (Bkcolors[bkc_index]);
      for (col = firstcol; col <= lastcol; ++col)
           {

           for (row = firstrow; row <= lastrow; ++row)
                {
                _setcolor(((row*row + col*col)/10)%vc.numcolors);
                _setpixel(col, row);
                }
           }
      while ((ch = getch()) != ESC)
           {
           if (ch == 'p')
                 _selectpalette(++palette % PALNUM);
           else if (ch == 'b')
                 _setbkcolor(Bkcolors[++bkc_index % BKCOLS]);
           }
      _setvideomode(_DEFAULTMODE);  /* reset orig. mode */
 }


 NARROW.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\NARROW.C

 /* narrow.c -- a choppy C program */

 main( )
 {
 printf
 ("Hello, and welcome to QuickC!\n");
 }


 ONELINE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\ONELINE.C

 /* oneline.c -- shows how printf() continues  */
 /*              on the same line              */

 main()
 {
     printf("All displayed on");
     printf("the same line, with no space");
     printf(" unless specified.");
             /* note added space in line above */
 }


 OPEQUAL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\OPEQUAL.C

 /* opequal.c -- shows combination math/assignment */
 /*              operators and increment operators */

 main()
 {
     int m = 10, n = 5;
     printf("Starting values: m = %d n = %d\n",
             m, n);

     /* combination of arithmetic and assignment */
     printf("m += 2 makes m %d\n", m += 2);
     printf("m -= n makes m %d\n", m -= n);
     printf("m *= 2 makes m %d\n", m *= 2);

     /* two ways to increment m */
     printf("m = m + 1 makes m %d\n",
             m = m + 1);
     printf("m += 1 makes m %d\n",
             m += 1);
 }


 PACK.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\PACK.C

 /* pack.c  --  demonstrates structure packing with */
 /*             the #pragma pack() directive        */

 pack(4)        /* 1, 2 or 4 */

 main()
 {
     struct {
         char ch1;
         int  int1;
         char ch2;
         long int2;
     } s;

     printf("ch1  -> %lu\n", (unsigned long)(&s.ch1));
     printf("int1 -> %lu\n", (unsigned long)(&s.int1));
     printf("ch2  -> %lu\n", (unsigned long)(&s.ch2));
     printf("int2 -> %lu\n", (unsigned long)(&s.int2));
 }


 PASSWORD.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\PASSWORD.C

 /*  password.c -- requires a password to complete the   */
 /*                program; illustrates a use of getch() */

 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #define GUESS_LIMIT 4
 WORD_LIMIT 10  /* maximum length of password */
 #define TRUE 1
 #define FALSE 0
 char *Password = "I'mOk";
 main()
 {
      int g_count = 0;           /* guesses taken */
      int w_count;               /* letters accepted */
      int in_count;              /* letters entered  */
      char entry[WORD_LIMIT + 1];
      char ch;
      int correct, go_on;

      do
           {
           puts("Enter the secret password.");
           in_count = w_count = 0;
           /* the following loop accepts no more chars */
           /* than entry[] will hold, but keeps track  */
           /* of total number typed                    */
           while ((ch = getch()) != '\r')
                {
                if (w_count < WORD_LIMIT)
                     entry[w_count++] = ch;
                in_count++;
                }
           entry[w_count] = '\0';
           if (in_count != w_count)
                correct = FALSE;    /* too many chars */
           else
                correct = (strcmp(entry, Password) == 0);
           g_count++;
           go_on = !correct && g_count < GUESS_LIMIT;
           if (go_on)
                puts("\nNo good; try again.");
           } while (go_on);
      if (!correct)
           {
           puts("Sorry, no more guesses.  Bye.");
           return(1);
           }
      puts("Welcome to Swiss bank account 2929100.");
      puts("Your current balance is $10,232,862.61.");
      return(0);
 }


 PEEK.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\PEEK.C

 /* peek.c    -- demonstrates how to cast an int to a  */
 /*              pointer                               */

 main()
 {
     char *mem_ptr;
     unsigned int address;

     while (1)
         {
         printf("Examine what memory location?\n");
         printf("Enter location in decimal: ");
         if (scanf("%u", &address) != 1)
             break;

         mem_ptr = (char *)address;   /* cast  */

         printf("The value in %u is 0x%02X\n",
                 address, (unsigned char)*mem_ptr);
         }
 }


 PHONE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\PHONE.C

 /* phone.c  -- a telephone number mini-database that  */
 /*             demonstrates fseek()                   */

 <stdio.h>          /* for FILE, BUFSIZ, NULL */

 #define MAXL (128)
 char Name[MAXL];
 char Number[MAXL];
 char File[] = "C:\\TMP\\PHONE.DB";
 int  Count;
 FILE *Fp;
 int  Distance = (MAXL * MAXL);

 main(argc, argv)
 int argc;
 char *argv[];
 {
     if (argc == 1)
         Ask();
     else
         Find(argv[1]);

     return (0);
     }

 Find(char *str)
     {
     int i;

     if ((Fp = fopen(File, "r")) == NULL)
         {
         fprintf(stderr, "\"%s\": Can't Read\n", File);
         exit (1);
         }
     if (fread(&Count, 1, sizeof(int), Fp) != sizeof(int))
         {
         fprintf(stderr,"\"%s\": Error Reading\n", File);
         exit (1);
         }
     for (i = 0; i < Count; i++)
         {
         fread(Name, 1, MAXL, Fp);
         fread(Number, 1, MAXL, Fp);
         if (ferror(Fp))
             {
             fprintf(stderr, "\"%s\": Error Reading.\n", File);
             exit (1);
             }
         if (strcmp(*str, *Name) == 0)
             {
             printf("Name: %s\n", Name);
             printf("Number: %s\n", Number);
             return;
             }
         }
     fprintf(stderr, "\"%s\": Not in database.\n", str);
     return;
 }

 Ask()
 {
     if ((Fp = fopen(File, "r+")) == NULL)
         Make();
     else if (fread(&Count, 1, sizeof(int),Fp) != sizeof(int))
         {
         fprintf(stderr, "\"%s\": Error Reading\n", File);
         exit (1);
         }
     printf("Name: ");
     if (gets(Name) == NULL || *Name == '\0')
         return;
     printf("Number: ");
     if (gets(Number) == NULL || *Number == '\0')
         return;
     if (fseek(Fp, (long)(Distance * Count), SEEK_CUR) != 0)
         {
         fprintf(stderr, "\"%s\": Error Seeking.\n", File);
         exit (1);
         }
     fwrite(Name, 1, MAXL, Fp);
     fwrite(Number, 1, MAXL, Fp);
     if (ferror(Fp))
         {
         fprintf(stderr, "\"%s\": Error Writing.\n", File);
         exit (1);
         }
     if (fseek(Fp, 0L, SEEK_SET) != 0)
         {
         fprintf(stderr, "\"%s\": Error Seeking.\n", File);
         exit (1);
         }
     ++Count;
     if (fwrite(&Count, 1, sizeof(int),Fp) != sizeof(int))
         {
         fprintf(stderr, "\"%s\": Error Writing\n", File);
         exit (1);
         }
     return;
 }

 Make()
 {
     if ((Fp = fopen(File, "w+")) == NULL)
         {
         fprintf(stderr, "\"%s\": Can't Create\n", File);
         exit (1);
         }
     Count = 0;
     if (fwrite(&Count, 1, sizeof(int), Fp) != sizeof(int))
         {
         fprintf(stderr," \"%s\": Error Creating\n", File);
         exit (1);
         }
 }


 PHWORD.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\PHWORD.C

 /* phword.c   --  generate all the possible words     */
 /*                in a phone number; demonstrates     */
 /*                functions that return addresses     */

 MAXD (7)    /* 7 digits max */

 main()
 {
     int digits[MAXD], ndigits = 0, line = 0;
     char *letters;
     signed char digit;
     int a, b, c, d, e, f, g;
     extern char *Range();

     printf("Enter Phone Number (7 digits): ");
     do
         {
         digit = getch() - '0';
         if (digit == ('-' - '0'))
             continue;
         if (digit < 0 || digit > 9)
             {
             printf("\nAborted: Non Digit\n");
             return(1);
             }
         digits[ndigits++] = digit;
         printf("%d", digit);
         } while (ndigits < 7);
     printf("\n");

     for( a = 0; a < 3; ++a)
      for( b = 0; b < 3; ++b)
       for( c = 0; c < 3; ++c)
        for( d = 0; d < 3; ++d)
         for( e = 0; e < 3; ++e)
          for( f = 0; f < 3; ++f)
           for( g = 0; g < 3; ++g)
               {
               printf("%c", Range(digits[0])[a]);
               printf("%c", Range(digits[1])[b]);
               printf("%c", Range(digits[2])[c]);
               printf("%c", Range(digits[3])[d]);
               printf("%c", Range(digits[4])[e]);
               printf("%c", Range(digits[5])[f]);
               printf("%c", Range(digits[6])[g]);
               printf("\n");
               if (++line == 20)
                   {
                   printf("Press Any key for More");
                   printf(" (or q to quit): ");
                   if (getch() == 'q')
                       return (0);
                   printf("\n");
                   line = 0;
                   }
               }
 }

 char *Range(int key)
     {
     static char keys[10][3] = {
         {'0', '0', '0' },
         {'1', '1', '1' },
         {'a', 'b', 'c' },
         {'d', 'e', 'f' },
         {'g', 'h', 'i' },
         {'j', 'k', 'l' },
         {'m', 'n', 'o' },
         {'p', 'r', 's' },
         {'t', 'u', 'v' },
         {'w', 'x', 'y' }
     };

     return (keys[key]);
 }


 PIXELS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\PIXELS.C

 /* pixels.c -- create shapes       */
 /*             from random pixels  */

 <graph.h> /* for graphics */

 main()
 {
     int pixels, xpos, ypos;
     /* window coordinates */
     int xmin = 100, xmax = 540;
     int ymin = 50,  ymax = 150;

     srand(0);               /* init random nums */
     _setvideomode(_HRESBW); /* CGA 640 x 200    */
     _setcolor(1);           /* white foreground */

     /* generate random pixel locations      */
     for (pixels = 1; pixels < 10000; pixels++)
         {
         xpos = rand() % 639;
         ypos = rand() % 199;

         /* set pixel if within window */
         if ((xpos > xmin && xpos < xmax) &&
              (ypos > ymin && ypos < ymax))
            _setpixel(xpos, ypos);
         }
     getch(); /* freeze screen until key pressed */
              /* restore original video mode */
     _setvideomode(_DEFAULTMODE);
 }


 POINTER.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\POINTER.C

 /* pointer.c  --  demonstrates pointer declaration,   */
 /*                assignment, and use                 */

 #define WAIT printf("(press any key)"); getch(); \
              printf("\n\n")

 main()
 {
     int num, *address_var;

     num = 0;
     address_var = &num;

     printf("The address of the variable ");
     printf("\"num\" is:  0x%04X\n", &num );
     printf("The value in the pointer ");
     printf("\"address_var\" is:  0x%04X\n", address_var);
     printf("The value in the variable ");
     printf("\"num\" is: %d\n", num );
     WAIT;
     printf("Since \"address_var\" points to \"num\"\n");
     printf("the value in ");
     printf("\"*address_var\" is: %d\n", *address_var);
     WAIT;
     printf("To verify this, let's store 3 in\n");
     printf("\"*address_var\", then print out ");
     printf("\"num\" and \"*address_var\"\n");
     printf("again.\n");
     WAIT;

     printf("Doing: *address_var = 3;\n\n");
     *address_var = 3;

     printf("The address of the variable ");
     printf("\"num\" is:  0x%04X\n", &num);
     printf("The value in the pointer ");
     printf("\"address_var\" is:  0x%04X\n", address_var);
     printf("The value in the variable ");
     printf("\"num\" is: %d\n", num);
     WAIT;
     printf("Since \"address_var\" points to \"num\"\n");
     printf("the value in ");
     printf("\"*address_var\" is: %d\n", *address_var);
     WAIT;

     printf("Now we will add 15 to \"num\" and print\n");
     printf("\"num\" and \"*address_var\" again.\n");
     WAIT;

     printf("Doing: num += 15;\n\n");
     num += 15;

     printf("The address of the variable ");
     printf("\"num\" is:  0x%04X\n", &num);
     printf("The value in the pointer ");
     printf("\"address_var\" is:  0x%04X\n", address_var);
     printf("The value in the variable ");
     printf("\"num\" is: %d\n", num);
     WAIT;
     printf("Since \"address_var\" points to \"num\"\n");
     printf("the value in ");
     printf("\"*address_var\" is: %d\n", *address_var);
     WAIT;

     printf("Doing: return (*address_var);\n\n");
     return (*address_var);
 }


 PORTINFO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\PORTINFO.C

 /* portinfo.c -- reads port values                    */
 /* program list -- portinfo.c (inp() not in core lib) */

 #include <conio.h>
 #include <stdio.h>
 main()
 {
     unsigned int portnum;
     int regvalue;

     printf("Enter number (in hex) of the port ");
     printf("you wish to read: ");
     while (scanf("%x", &portnum) == 1)
         {
     regvalue = inp(portnum);
     printf("\nValue returned for port %x is %d (decimal)"
            "  %x (hex)\n", portnum, regvalue, regvalue);
     printf("Next port? (q to quit): ");
         }
 }


 POWER.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\POWER.C

 /* power.c -- attempting to raise to a power   */

 main()
 {
     int number;

     number = 10**3; /* raise 10 to 3rd power? */
     printf("%d\n", number);
 }


 PREPOST.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\PREPOST.C

 /* prepost.c -- shows effect of pre- */
 /*              and post-increments  */
 /*              and decrements       */

 main()
 {
     int b = 100;

     printf("b is %d\n", b);
     printf("b++ is still %d\n", b++);
     printf("but after it's used, ");
     printf("b is incremented to %d\n\n, b);

     printf("++b, on the other hand, ");
     printf("is immediately %d\n", ++b);
 }


 PROTO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\PROTO.C

 /* proto.c -- demonstrate function prototyping */
 /*            and parameter checking           */

 main()
 {
     float n = 9995.997;
     int i;
     int examine(int num);  /* declare function */
                            /* with prototype   */

     printf("n in main() is %f\n", n);
     i = examine(n);    /* pass float to function */
     printf("examine() returned n as %d\n", i);
 }

 int examine(num)
 {
     printf("examine() says n is %d\n", num);
     return(num);
 }


 QCHELLO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP02\QCHELLO.C

 /* qchello.c -- a simple C program */

 main()
 {
     printf("Hello, and welcome to QuickC!\n");
 }


 RACE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\RACE.C

 /* race.c -- race of the patterned circles             */
 /*    Illustrates animation with _getimage() and       */
 /*    _putimage(), random number use with srand() and  */
 /*    rand(), and system clock use with time() and     */
 /*    ftime().
 /* Program list: race.c (for srand(), rand(), and      */
 /*                       ftime())                      */

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <graph.h>
 #include <time.h>
 #include <sys\types.h>
 #include <sys\timeb.h>

 #define END 25
 #define FIGNUM 3
 typedef char far *PTFRCHAR;
 PTFRCHAR Bufs[FIGNUM];
 unsigned char Masks[FIGNUM][8] = {
             {0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00},
             {0xF0,0xF0,0xF0,0xF0,0x0F,0x0F,0x0F,0x0F},
             {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}};
 short Xul[FIGNUM], Yul[FIGNUM];  /* figure locations */
 short Xsize, Ysize;              /* figure size      */
 struct videoconfig Vc;
 void Initialize(void);
 void Draw_n_store(void);
 void Move_figs(void);
 void Wait(double);

 main(argc, argv)
 int argc;
 char *argv[];
 {
     int mode = _MRES4COLOR;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
     {
         fprintf(stderr,"mode %d not supported\n",mode);
         exit(1);
     }
     Initialize();
     Draw_n_store();
     _settextcolor(2);
     _settextposition(1, 1);
     _outtext("Place your bets and type a key");
     _settextposition(25, 1);
     _outtext("Type a key again when done");
     getch();
     Move_figs();
     getch();
     _setvideomode(_DEFAULTMODE);
 }

 void Initialize()
 {
     int i;
     float ar;  /* aspect ratio */

     _getvideoconfig(&Vc);
     ar = (float)(10 * Vc.numypixels) / (6.5 * Vc.numxpixels);
       /* set size, initial positions */
     Xsize = Vc.numxpixels / 30;
     Ysize = ar * Xsize;
     for(i = 0; i < FIGNUM; i++)
     {
         Xul[i] = 0;
         Yul[i] = (i + 1) * Vc.numypixels /
                       (FIGNUM + 1);
     }
     _selectpalette(0);
     _setcolor(1);
         /*  draw finish line */
     _moveto(END * Xsize, 0);
     _lineto(END * Xsize, Vc.numypixels - 1);
 }

 void Draw_n_store() /* draw images, save them */
 {
     int i;

     for (i = 0; i < FIGNUM; i++)
         {
         _setcolor(i + 1);
         _setfillmask(Masks[i]);
         _ellipse(_GFILLINTERIOR ,Xul[i], Yul[i],
                  Xul[i] + Xsize, Yul[i] + Ysize);
         _ellipse(_GBORDER ,Xul[i], Yul[i],
                  Xul[i] + Xsize, Yul[i] + Ysize);
         Bufs[i] = (PTFRCHAR) malloc((unsigned int)
                    _imagesize(0,Yul[i], Xul[i] +
                    Xsize, Yul[i] + Ysize));
         _getimage(Xul[i],Yul[i], Xul[i] + Xsize, Yul[i] +
                   Ysize, Bufs[i]);

         }
 }
 void Move_figs()
 {
     int i, j;
     static int dx[FIGNUM] = {0, 0, 0}; /* displacements */
     time_t tval;

     time(&tval);    /*   use the current time value   */
     srand(tval);    /*   to initialize rand()         */
     while (dx[0] < END && dx[1] < END && dx[2] < END)
         {
         for (i = 0; i < FIGNUM; i++)
             {
             /* advance the figure one position if  */
             /* rand() returns an even number       */
             if (rand() % 2 == 0)
                 {
                 /* erase old image */
                 _putimage(dx[i] * Xsize, Yul[i],
                           Bufs[i], _GXOR);
                 /* redraw in new position */
                 _putimage((1 + dx[i]) * Xsize, Yul[i],
                           Bufs[i], _GPSET);
                 dx[i]++;
                 }
             }
         Wait(0.15);
         }
     for (j = 0; j < 5; j++)
         {
         for(i = 0; i < FIGNUM; i++)
             {
             /* flash winning figure */
             if (dx[i] >= END)
                 {
                 Wait(0.2);
                 _putimage(dx[i] * Xsize,Yul[i],
                           Bufs[i], _GPRESET);
                 Wait(0.2);
                 _putimage(dx[i] * Xsize,Yul[i],
                           Bufs[i], _GPSET);
                 }
             }
         }
 }

 void Wait(pause) /* wait for pause seconds */
 double pause;
 {
     struct timeb start, end;
     long delay;

     delay = 1000 * pause;  /* convert to milliseconds */
     ftime(&start);
     ftime(&end);
     while ((1000 * (end.time - start.time) +
             + end.millitm - start.millitm) < delay)
         ftime(&end);
 }



 READKEY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\READKEY.C

 /* readkey.c -- contains the Readkey() function     */
 #include <dos.h>
 KEYINTR 0x16  /* keyboard read interrupt */
 GETCHAR 0     /* read scancode function  */
 struct SCANCODE {
                 unsigned char ascii;  /* ascii code */
                 unsigned char scan;   /* scan code  */
                 };

 struct SCANCODE Readkey()
 {
     union REGS reg;
     struct SCANCODE scancode;

     reg.h.ah = GETCHAR;         /* specify function */
     int86(KEYINTR, &reg, &reg); /* note use of & oper.*/
     scancode.ascii = reg.h.al;
     scancode.scan = reg.h.ah;
     return (scancode);
 }


 RECALL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\RECALL.C

 /* recall.c -- displays previously stored screen,     */
 /*             including attributes.  Uses DMA.       */
 /* Program list: recall.c, scrfun.c                   */
 /* User include files: scrn.h, grafchar.h             */
 /* Note: activate Screen Swapping On in Debug menu    */

 #include <stdio.h>
 #include <conio.h>
 #include "scrn.h"
 #include "grafchar.h"

 main(ac, ar)
 int ac;
 char *ar[];
 {
      unsigned char mode;
      unsigned short char_attr;
      FILE *save;
      unsigned int offset;
      char filename[81];
      VIDMEM screen;

      if (ac < 2)
           {
           fprintf(stderr, "Usage: %s filename\n", ar[0]);
           exit(1);
           }

      if ((save = fopen(ar[1],"rb")) == NULL)
           {
           fprintf(stderr, "Can't open %s\n", ar[1]);
           exit(1);
           }

      if ((mode = Getvmode()) == TEXTMONO)
           screen = MONMEM;
      else if (mode == TEXTC80 || mode == TEXTBW80)
           screen = CGAMEM;
      else
         exit(1);

      Clearscr();
      for (offset = 0; offset < CHARS; offset++)
           {
           fread(&char_attr, 2, 1, save);
           screen[offset] = char_attr;
           }
      fclose(save);
      Setcurs(23, 0, PAGE);
      getch();   /* anti scrolling for QC environment */
 }


 RECEIPTS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\RECEIPTS.C

 /* receipts.c -- calculates gross and net */
 /*               receipts on sales        */

 main()
 {
     int units = 38;       /* number sold */
     float price = 149.99, /* price per item */
     rate = 0.06;          /* sales tax rate */

     /* variables to hold calculated totals */
     float gross, tax, net;

     /* perform calculations */
     net = units * price;
     tax = net * rate;
     gross = net + tax;

     /* print results */
     printf("\tSales Report\n");
     printf("Net sales: \t%6.2f\n", net);
     printf("Tax:\t\t %5.2f\n", tax);
     printf("Gross sales:\t%6.2f\n", gross);
 }


 RECT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\RECT.C

 /*  rect.c -- illustrates logical coordinates,         */
 /*            the _rectangle() and _setlinestyle()     */
 /*            functions                                */
 /* If you load graphics.qlb, no program list is needed */

 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>
 #define STYLES 5
 short Linestyles[STYLES] = {0xFFFF, 0x8888, 0x7777,
                             0x00FF, 0x8787};

 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _MRES4COLOR;
     int xcent, ycent;
     int xsize, ysize;
     int i;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
     {
         printf("Can't open that mode.\n");
         exit(1);
     }
     _getvideoconfig(&vc);
     xcent = vc.numxpixels / 2 - 1;
     ycent = vc.numypixels / 2 - 1;
     _setlogorg(xcent, ycent);
     xsize = 0.9 * xcent;
     ysize = 0.9 * ycent;
     _selectpalette(1);
     _setcolor(3);
     _rectangle(_GBORDER, -xsize, -ysize, xsize, ysize);
     xsize *= 0.9;
     ysize *= 0.9;
     _setcolor(1);
     _rectangle(_GFILLINTERIOR, -xsize, -ysize, xsize, ysize);
     for (i = 0; i < 16; i++)
     {
         _setcolor(((i % 2) == 0) ? 2 : 3);
         _setlinestyle(Linestyles[ i % 5 ]);
         xsize *= 0.9;
         ysize *= 0.9;
         _rectangle(_GBORDER, -xsize, -ysize, xsize, ysize);
     }
     getch();      /* Type a key to terminate. */
     _setvideomode(_DEFAULTMODE);
 }


 RECURSE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\RECURSE.C

 /* recurse.c -- demonstrates recursion */

 int level = 1; /* recursion level */
 main()
 {
     int num, result;

     printf("Factorial of what number? ");
     scanf("%d", &num);
     result = factorial(num);
     printf("Result is: %d\n", result);
 }

 factorial(number)
 {
     int result;
     printf("entering: ");
     printf("level %d. number = %d. &number = %d\n",
             level++, number, &number);

     if (number == 0)
         result = 1;
     else
         result = number * factorial(number - 1);

     printf("exiting : ");
     printf("level %d. number = %d. &number = %d. ",
             --level, number, &number);
     printf("result = %d\n", result);

     return(result);
 }


 REKEY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\REKEY.C

 /* rekey.c -- transliterates typed input             */
 /*    This program illustrates getch() and putch().  */

 #include <stdio.h>
 #include <conio.h>
 #include <ctype.h>
 ESC '\033'   /* the escape key */
 char Newchars[] = "qwertyuiopasdfghjklzxcvbnm";
  /* values to be assigned to the a,b,c keys, etc. */
 main()
 {
     char ch;

     printf("Type characters and see them transformed;\n");
     printf("Press the Esc key to terminate.\n");
     while ((ch = getch()) != ESC)
         if (islower(ch))
             putch(Newchars[ch - 'a']);
         else if (isupper(ch))
             {
             ch = tolower(ch);
             putch(toupper(Newchars[ch - 'a']));
             }
         else if (ch == '\r')
             {
             putch('\n');
             putch('\r');
             }
         else
             putch(ch);
 }


 RELATION.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\RELATION.C

 /* relation.c -- shows effect of      */
 /*               relational operators */

 main()
 {
     int a = 5, b = 3, c = 4;
     printf("a = %d\t b = %d\t c = %d\n", a, b, c);

     printf("Expression a > b has a value of %d\n",
             a > b);
     printf("Expression a == c has a value of %d\n",
             a == c);
     printf("Expression a > (b + c) has a value of %d\n",
             a > (b + c));
     printf("Expression a = b has a value of %d\n",
             a = b); /* what happened here? */
 }


 REMOIRE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\REMOIRE.C

 /* remoire.c -- adds palette remapping to moire.c      */
 #include <conio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #define ESC '\033'
 #define MAXCOLORS 64
 #define PALCOLORS 16
 long Ega_to_vga(int);

 main (argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     unsigned int col, row;
     long colors[MAXCOLORS];
     long palette[PALCOLORS];
     int index;
     int shift = 1;
     int firstcol, firstrow, lastrow, lastcol;
     int mode = _ERESCOLOR;


     if (argc > 1)
         mode = atoi(argv[1]);

     if (_setvideomode(mode) == 0)
         {
         printf("Can't do that mode.\n");
         exit(1);
         }
     /* Create array of all 64 color values. */
     for (index = 0; index < MAXCOLORS; index++)
         colors[index] = Ega_to_vga(index);
     /* Create array of 16 palette choices. */
     for (index = 0; index < PALCOLORS; index++)
         palette[index] = colors[index];
     _remapallpalette(palette);
     _getvideoconfig(&vc);
     firstcol = vc.numxpixels / 5;
     firstrow = vc.numypixels / 5;
     lastcol = 4 * vc.numxpixels / 5;
     lastrow = 4 * vc.numypixels / 5;

     for (col = firstcol; col <= lastcol; ++col)
         {
         for (row = firstrow; row <= lastrow; ++row)
             {
             _setcolor(((row * row + col * col) / 10)
                        % vc.numcolors);
             _setpixel(col, row);
             }
         }
     _settextposition(1, 1);
     _outtext("Type a key to stop or start.");
     _settextposition(2, 1);
     _outtext("Type [Esc] while paused to quit.");
     do
         {
         while (!kbhit())
             {
             /*  Set palette array to new color values. */
             for (index = 1; index < PALCOLORS; index++)
                 palette[index] = (colors[(index + shift)
                                   % MAXCOLORS]);
             _remapallpalette(palette);
             shift++;
              }
          getch();  /* pause until key is typed */
         }  while (getch() != ESC);

     _setvideomode(_DEFAULTMODE);  /* reset orig. mode */
 }

 long Ega_to_vga(egacolor)
 int egacolor;       /* ega color value */
 {
     static long vgavals[6] = {0x2A0000L, 0x002A00L, 0x00002AL,
                               0x150000L, 0x001500L, 0x000015L};
     long vgacolor = 0L; /* vga color value */
     int bit;

     for (bit = 0; bit < 6; bit++)
         vgacolor += ((egacolor >> bit) &1) * vgavals[bit];
     return (vgacolor);
 }


 REVERSE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\REVERSE.C

 /* reverse.c -- demonstrates an array of pointers     */
 /*              by reversing lines of text            */

 <stdio.h>         /* for NULL   */
 <malloc.h>        /* for size_t */

 #define MAXL 20

 main()
 {
     char *cptrs[MAXL];     /* array of pointers */
     char *cp;
     int count, i, j, ch;
     extern char *Getbyte();


     printf("Type in several lines of text, and I will\n");
     printf("print them back out in reverse order.\n");
     printf("(Any blank line ends input):\n");

     for (i = 0; i < MAXL; ++i)
         {
         cp = Getbyte();
         cptrs[i] = cp;     /* assign address to pointer */
         count = 0;
         while ((ch = getchar()) != '\n') /* gather line */
             {
             *cp = ch;
             cp = Getbyte();
             ++count;
             }
         *cp = '\0';
         if (count == 0)    /* all done if blank line */
             break;
         }
     printf("---------<reversed>---------\n");
     for (j = i-1; j >= 0; --j)
         {
         printf("%s\n", cptrs[j]);
         }
 }

 char *Getbyte(void)
 {
     char *cp;

     if ((cp = sbrk(1)) == (char *)-1)
         {
         printf("Panic: sbrk failed\n");
         exit(1);
         }
     return (cp);
 }


 REVERSE2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\REVERSE2.C

 /* reverse2.c -- demonstrates a pointer to a pointer  */

 <stdio.h>         /* for NULL   */
 <malloc.h>        /* for size_t */

 #define MAXL 20

 main()
 {
     char *cptrs[MAXL];
     char **pp;             /* pointer to pointer */
     char *cp;
     int count, i, ch;
     extern char *Getbyte();

     printf("Type in several lines of text, and I will\n");
     printf("print them back out in reverse order.\n");
     printf("(Any blank line ends input):\n");

     for (i = 0; i < MAXL; ++i)
         {
         cp = Getbyte();
         cptrs[i] = cp;     /* assign address to pointer */
         count = 0;
         while ((ch = getchar()) != '\n') /* gather line */
             {
             *cp = ch;
             cp = Getbyte();
             ++count;
             }
         *cp = '\0';
         if (count == 0)    /* all done if blank line */
             break;
         }
     printf("---------<reversed>---------\n");
     pp = &cptrs[i];
     while (pp >= cptrs)
         {
         printf("%s\n", *(pp--));
         }
 }

 char *Getbyte(void)
 {
     char *cp;

     if ((cp = sbrk(1)) == (char *)-1)
         {
         printf("Panic: sbrk failed\n");
         exit(1);
         }
     return (cp);
 }


 RIGHTSTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\RIGHTSTR.C

 /* rightstr.c -- a C version of BASIC's RIGHT$ */

 #include <stdio.h>

 char *Rightstr(char *str, int cnt)
 {
     static char *cp = NULL;
     char *malloc();

     if (cnt > strlen(str))
         cnt = strlen(str);
     if (cp != NULL)
         free(cp);
     if ((cp = malloc(cnt + 1)) == NULL)
         return (NULL);
     strcpy(cp, str + strlen(str) - cnt);
     return (cp);
 }


 RINGS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\RINGS.C

 /*  rings.c -- shoots colored rings                   */
 /*  This program illustrates _remapallpalette() and   */
 /*  how it can be used to produce the appearance of   */
 /*  motion. The program is intended for EGA modes 13, */
 /*  14, and 16.                                       */
 /* Program list: rings.c                              */
 /* If you load graphics.qlb, no program list is needed*/

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <graph.h>
 #define ESC '\033'

 long Colors[16] = {_BLACK, _BLUE, _GREEN, _CYAN,
                  _RED, _MAGENTA, _BROWN, _WHITE,
                  _GRAY, _LIGHTBLUE, _LIGHTGREEN,
                  _LIGHTCYAN, _LIGHTRED, _LIGHTMAGENTA,
                  _LIGHTYELLOW,_BRIGHTWHITE };

 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     float aspect;
     short xmax, ymax;
     long int newpalette[16];
     long int temp;
     int index;
     int hot1 = 1;  /* first colored ring  */
     int hot2 = 8;  /* second colored ring */
     int mode = _ERESCOLOR;
     int ch;

     if (argc > 1)
         mode = atoi(argv[1]);
     if (mode < 13)
     {
         fprintf(stderr,"Requires EGA or VGA mode\n");
         exit(1);
     }
     if (_setvideomode(mode) == 0)
     {
         fprintf(stderr,"% d mode unavailable\n", mode);
         exit(2);
     }
     _getvideoconfig(&vc);
     _setlogorg(vc.numxpixels / 2 - 1, vc.numypixels / 2 - 1);
     aspect = (10.0 * vc.numypixels) / (6.5 * vc.numxpixels);
     ymax = vc.numypixels / 2 - 2;
     xmax = ymax / aspect;
     for (index = 2; index < 16; index++)
         newpalette[index] = _LIGHTBLUE;
     newpalette[0] = _GRAY;
     newpalette[hot1] = _RED;
     newpalette[hot2] = _LIGHTRED;
     _remapallpalette(newpalette);  /* set initial palette */
     _setcolor(1);
     _ellipse(_GFILLINTERIOR, -xmax, -ymax, xmax, ymax);
     /* draw concentric circles */
     for (index = 2; index < 16; index++)
         {
         xmax /= 1.4;
         ymax /= 1.4;
         _setcolor(index);
         _ellipse(_GFILLINTERIOR, -xmax, -ymax, xmax, ymax);
         }
     do
         {
         while (!kbhit())
             {
             temp = newpalette[15];
             for(index = 15; index > 1; index--)
                 newpalette[index] = newpalette[index - 1];
             newpalette[1] = temp;
             _remapallpalette(newpalette);
             hot1 = hot1 % 15 + 1;  /* index of colored ring */
             hot2 = hot2 % 15 + 1;
             }
         ch = getch();
         if (ch > '1' && ch < '8')  /* reassign colors */
             {
             newpalette[hot1] = Colors[ ch - '0'];
             newpalette[hot2] = Colors[ ch - '0' + 8];
             }
          } while (ch != ESC);
     _clearscreen(_GCLEARSCREEN);
     _setvideomode(_DEFAULTMODE);
 }


 ROAMSCRN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\ROAMSCRN.C

 /*   roamscrn.c  -- puts text on screen, positions    */
 /*                  cursor with arrow keys, uses F1   */
 /*                  and F2 to control video inverse.  */
 /*   program list -- roamscreen.c, scrfun.lib         */
 /*   user include files -- keys.h, scrn.h             */
 /*  Note: Activate Screen Swapping On in Debug menu   */
 #include <conio.h>
 #include "keys.h"
 #include "scrn.h"
 #define BELL '\a'
 #define ESC '\033'
 #define PAGE 0

 char *Heading =
 "Use standard keys to enter text. Use arrow keys to "
 "reposition cursor.\nUse F2 to turn on video inverse "
 "and F1 to turn it off.\nHit the ESC key to quit.\n";

 main()
 {
     int ch;
     unsigned char atr = NORMAL;

     Clearscr();
     Home();
     printf("%s", Heading);
     while ((ch = getch()) != ESC)
         {
         if (ch == '\r')
             {
             putch('\n');
             putch('\r');
             }
         else if (ch != 0)
             {
                Write_ch_atr(ch, atr, PAGE, 1);
             if (!Cursrt())
                 putch(BELL);
             }
         else
             {
             ch = getch();
             switch (ch)
                 {
                 case F1 : atr = NORMAL; break;
                 case F2 : atr = VIDREV; break;
                     case UP : Rewrite(atr, PAGE);
                           if (!Cursup())
                             putch(BELL);
                           break;
                     case DN : Rewrite(atr, PAGE);
                           if (!Cursdn())
                             putch(BELL);
                           break;
                     case LT : Rewrite(atr, PAGE);
                           if (!Curslt())
                             putch(BELL);
                           break;
                     case RT : Rewrite(atr, PAGE);
                           if (!Cursrt())
                             putch(BELL);
                           break;
                 default : break;
                 }
             }
         }
 }


 ROLO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\ROLO.C

 /* rolo.c  --  demonstrates pointers to structures     */

 <stdio.h>      /* for NULL  and stdin */
 <string.h>     /* for strdup()        */

 #define MAXN 79
 #define MAXCARDS 3

 struct cardstruct {                 /* global pattern */
     char first[MAXN],
          last[MAXN],
          middle[MAXN];
     unsigned long street_no;
     char street[MAXN],
          city[MAXN],
          state[MAXN];
     unsigned long zip;
     unsigned int area;
     unsigned long phone;
 };

 struct cardstruct cards[MAXCARDS];

 main()
 {
     int i;

     for (i = 0; i < MAXCARDS; ++i)
         {
         printf("\n<card %d of %d>\n", i + 1, MAXCARDS);
         Input(&cards[i]);
         }
     for (i = 0; i < MAXCARDS; ++i)
         {
         printf("\n<%d> ", i + 1);
         Showcard(&cards[i]);
         }
 }

 Input(struct cardstruct *cardp)
 {
     char *Str_Input();
     long Lint_Input();

     strcpy(cardp->first,Str_Input("First Name"));
     strcpy(cardp->last,Str_Input("Last Name"));
     strcpy(cardp->middle,Str_Input("Middle Name"));
     cardp->street_no = Lint_Input("Street Number");
     strcpy(cardp->street,Str_Input("Street"));
     strcpy(cardp->city,Str_Input("City"));
     strcpy(cardp->state,Str_Input("State"));
     cardp->zip = Lint_Input("Zip Code");
     cardp->area = (int)Lint_Input("Area Code");
     cardp->phone = Lint_Input("Phone Number");
 }

 char *Str_Input(char *prompt)
 {
     char buf[MAXN + 1], *ptr;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     buf[strlen(buf) - 1] = '\0'; /* strip '\n' */
     if (strlen(buf) == 0)
         exit(0);
     if ((ptr = strdup(buf)) == NULL)
         exit(0);
     return (ptr);
 }

 long Lint_Input(char *prompt)
 {
     char buf[MAXN + 1];
     long  num;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     if (sscanf(buf, "%ld", &num) != 1)
         exit(0);
     return (num);
 }

 Showcard(struct cardstruct *cardptr)
 {
     printf("\n\n");
     printf("%s %s %s\n", cardptr->first, cardptr->middle,
             cardptr->last);
     printf("%ld %s, %s, %s %ld\n", cardptr->street_no,
             cardptr->street, cardptr->city, cardptr->state,
             cardptr->zip);
     printf("(%d) %ld\n", cardptr->area, cardptr->phone);
 }


 ROLO2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\ROLO2.C

 /* rolo2.c --  demonstrates a linked list */

 <stdio.h>      /* for NULL  and stdin */
 <string.h>     /* for strdup()        */
 <malloc.h>     /* for malloc()        */

 #define MAXN 79

 struct cardstruct {          /* global pattern */
     char first[MAXN],
          last[MAXN],
          middle[MAXN];
     unsigned long street_no;
     char street[MAXN],
          city[MAXN],
          state[MAXN];
     unsigned long zip;
     unsigned int area;
     unsigned long phone;
     struct   cardstruct *nextcard;
 };

 main()
 {
     int i;
     struct cardstruct card, *first, *current;

     first = (struct cardstruct *)malloc(sizeof(struct cardstruct));
     if(first == NULL)
         exit(1);
     if (Input(&card) != 0)
         exit(1);
     *first = card;
     current = first;

     while (Input(&card) == 0)
         {
         current->nextcard =
             (struct cardstruct *)malloc(sizeof(struct cardstruct));
         if(current->nextcard == NULL)
             exit(1);
         current = current->nextcard;
         *current = card;
         }
     current->nextcard = NULL;

     Dumplist(first);
 }

 Dumplist(struct cardstruct *head)
 {
     do
         {
         Showcard(head);
         } while ((head = head->nextcard) != NULL);
 }

 Showcard(struct cardstruct *cardptr)
 {
     printf("\n\n");

     printf("%s %s %s\n", cardptr->first, cardptr->middle,
             cardptr->last);
     printf("%ld %s, %s, %s %ld\n", cardptr->street_no,
             cardptr->street, cardptr->city, cardptr->state,
             cardptr->zip);
     printf("(%d) %ld\n", cardptr->area, cardptr->phone);
 }

 Input(struct cardstruct *cardp)
 {
     char *Str_Input();
     long Lint_Input();

     printf("\n<new card> (Empty first name Quits)\n");
     strcpy(cardp->first,Str_Input("First Name"));
     if (*(cardp->first) == '\0')
         return (1);
     strcpy(cardp->last,Str_Input("Last Name"));
     strcpy(cardp->middle,Str_Input("Middle Name"));
     cardp->street_no = Lint_Input("Street Number");
     strcpy(cardp->street,Str_Input("Street"));
     strcpy(cardp->city,Str_Input("City"));
     strcpy(cardp->state,Str_Input("State"));
     cardp->zip = Lint_Input("Zip Code");
     cardp->area = (int)Lint_Input("Area Code");
     cardp->phone = Lint_Input("Phone Number");
     return (0);
 }

 char *Str_Input(char *prompt)
 {
     char buf[MAXN + 1], *ptr;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     buf[strlen(buf) - 1] = '\0'; /* strip '\n' */
     if ((ptr = strdup(buf)) == NULL)
         exit(0);
     return (ptr);
 }

 long Lint_Input(char *prompt)
 {
     char buf[MAXN + 1];
     long  num;

     printf("%s: ", prompt);
     if (fgets(buf, MAXN, stdin) == NULL)
         exit(0);
     if (sscanf(buf, "%ld", &num) != 1)
         num = 0;
     return (num);
 }


 SADD.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\SADD.C

 /* sadd.c -- a small adding machine that illustrates  */
 /*           the need for array bounds checking.      */

 main()
 {
     int offset = 0, i, result = 0;
     int stack[3];

     while (scanf("%d", &stack[offset]) == 1)
         {
         ++offset;
         }
     for (i = 0; i < offset; ++i)
         {
         result += stack[i];
         }
     printf("-------------\n");
     printf("%d\n", result);

 }


 SADD2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\SADD2.C

 /* sadd2.c -- a small adding machine that includes */
 /*            array bounds checking.               */

 #define MAXSTAK 3

 main()
 {
     int offset = 0, i, result = 0;
     int stack[MAXSTAK];

     while (scanf("%d", &stack[offset]) == 1)
         {
         if (++offset >= MAXSTAK)
             {
             printf("Stack Full\n");
             break;
             }
         }
     for (i = 0; i < offset; ++i)
         {
         result += stack[i];
         }
     printf("-------------\n");
     printf("%d\n", result);

 }


 SAVEGRAF.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\SAVEGRAF.C

 /* savegraf.c -- uses DMA to save screen of graphics  */
 /*               characters and attributes            */
 /* Program list - savegraf.c, initstuf.c, drawchar.c, */
 /*                savescrn.c, scrfun.c                */
 /* User include files - scrn.h, keys.h, grafchar.h    */
 /* Note: activate Screen Swapping On in Debug menu    */


 #include "grafchar.h"
 unsigned char Grchr[NUMCHARS];  /* to store graphics set */
 void Init_stuff(void);
 void Draw_chars(void);
 void Save_screen(void);  /* in savescrn.c */

 main()
 {
     int ch;

     Init_stuff();  /* initialize vital elements */
     Draw_chars();  /* map keys to graphics characters */
     Setcurs(BOTLINE + 1, 0, PAGE);
     printf("%-80s", "Save screen? <y/n> ");
     Setcurs(BOTLINE + 1, 20, PAGE);
     ch = getche();
     if (ch == 'y' || ch == 'Y')
         Save_screen();
     Setcurs(BOTLINE + 2, 0, PAGE);
     printf("%-80s\n", "BYE!");
 }


 SAVESCRN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\SAVESCRN.C

 /* savescrn.c -- saves screen, including attribute    */
 /*               values, in a file                    */
 /*               Uses direct memory access.           */

 <stdio.h>  /* for file-handling */
 #include "scrn.h"
 #include "grafchar.h"
 void Save_screen()
 {
     FILE *save;
     char filename[80];
     unsigned char mode;
     unsigned short char_attr;  /* character,attribute */
     int offset;
     VIDMEM screen;

      if ((mode = Getvmode()) == TEXTMONO)
           screen = MONMEM;
      else if (mode == TEXTC80 || mode == TEXTBW80)
           screen = CGAMEM;
      else
         exit(1);
     Setcurs(BOTLINE + 1, 0, PAGE);
     printf("Please enter name for save file: ");
     scanf("%s", filename);
     if ((save = fopen(filename,"wb")) == NULL)
         {
         fprintf(stderr,"Can't open %s\n", filename);
         exit(1);
         }
    for (offset = 0; offset < CHARS; offset++)
         {
         char_attr = screen[offset];
         fwrite(&char_attr, 2, 1, save);
         }
    fclose(save);
 }


 SCANCODE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\SCANCODE.C

 /*   scancode.c -- displays ASCII or scan code         */
 /*   This program illustrates using getch() to detect  */
 /*   special keys such as function keys.               */

 #include <conio.h>
 ESC '\033'     /* ESC key */
 main()
 {
      int ch;

      printf("Strike keys and see the codes!\n");
      printf("Press the Esc key to quit.\n");

      while ((ch = getch()) != ESC)
           {
           if (ch != 0)
                {
                if (ch <= 32)    /* control characters */
                     printf("^%c has ASCII code %d\n",
                             ch + 64, ch);
                else
                     printf("%c has ASCII code %d\n", ch, ch);
                }
           else              /* ch IS 0 */
                {
                ch = getch();  /* get scan code */
                printf("Scan code is %d\n", ch);
                }
           }
 }


 SCANLINE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\SCANLINE.C

 /* scanline.c  -- demonstrates how scanf() reads  */
 /*                the individual words of a line  */

 #define INTRO \
 "Type in lines of text. They will be printed out\n\
 one word per line, thus demonstrating scanf().\n\
 (Type Ctrl-Z to Quit)\n"

 main()
 {
     char buf[512];    /* should be big enough */

     printf(INTRO);

     /*
      * scanf() returns the number of items
      * its control string matched.
      */
     while (scanf("%s", buf) == 1)
         {
         printf("%s\n", buf);
         }

 }


 SCAPE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\SCAPE.C

 /* scape.c -- uses nondefault EGA colors              */
 /* If you load graphics.qlb, no program list is needed.*/

 #include <stdio.h>
 #include <graph.h>
 #include "egacolor.h"
 #include <stdlib.h>
 #include <conio.h>
 #define SKY (b | B | g)
 #define OCEAN b
 #define SAND (R | g | b)
 #define SUN (R | G | r | g)

 main(argc, argv)
 int argc;
 char *argv[];
 {
     struct videoconfig vc;
     int mode = _ERESCOLOR;
     short xmax, ymax, sunx, suny, sunsizex, sunsizey;
     float ar;


     if (argc > 1)
         mode = atoi(argv[1]);
     if (_setvideomode(mode) == 0)
         {
         fprintf(stderr,"mode %d not supported\n", mode);
         exit(1);
         }
     _getvideoconfig(&vc);
     xmax = vc.numxpixels - 1;
     ymax = vc.numypixels - 1;
     sunx = 0.7 * xmax;
     suny = 0.2 * ymax;
     ar = (float)(10 * vc.numypixels) / (6.5 * vc.numxpixels);
     sunsizex = xmax / 30;
     sunsizey = ar * sunsizex;
     _remappalette(1, SKY);
     _remappalette(2, OCEAN);
     _remappalette(3, SAND);
     _remappalette(4, SUN);
     _setcolor(1);
     _rectangle(_GFILLINTERIOR, 0, 0, xmax, 2 * ymax / 5);
     _setcolor(4);
     _ellipse(_GFILLINTERIOR, sunx - sunsizex, suny -
              sunsizey, sunx + sunsizex, suny + sunsizey);
     _setcolor(2);
     _rectangle(_GFILLINTERIOR, 0, 2 * ymax / 5, xmax,
                2 * ymax / 3);
     _setcolor(3);
     _rectangle(_GFILLINTERIOR, 0, 2 * ymax / 3, xmax, ymax);
     getch();
     _setvideomode(_DEFAULTMODE);
 }


 SCORE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\SCORE.C

 /* score.c -- defines and prints   */
 /*            int and long vars    */

 main()
 {
     /* declare some int variables and assign values */
     /* to them in the same statement                */

     int home = 5, visitors = 2, inning =7, attendance = 31300;
     long total_attendance = 1135477;  /* long int */

     /* print out the values */

     printf("The score after %d innings is \n", inning);
     printf("Home team %d, Visitors %d.\n\n", home, visitors);
     printf("The attendance today is %d.\n", attendance);
     printf("Attendance this year to date is %ld.",
             total_attendance);
 }


 SCRANGE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\SCRANGE.C

 /* scrange.c  --  illustrates scanf()'s control */
 /*                directives                    */

 main()
 {
     char buf[512],    /* should be big enough */
          dummy[2];    /* for \n and \0        */
     int  num;

     do
         {
         printf("Running:\n");
         printf("\tscanf(\"%%d\", &num);\n");
         printf("\tscanf(\"%%[^\\n]\", buf);\n");
         printf("\tscanf(\"%%[\\n]\", dummy);\n");

         printf("\nType enough to satisfy this:\n");
         printf("(Set num equal to zero to quit)\n");

         scanf("%d", &num);
         scanf("%[^\n]", buf);
         scanf("%[\n]", dummy);

         printf("\n\tnum = %d\n", num);
         printf("\tbuf[] = \"%s\"\n", buf);
         printf("\n\n");

         } while (num != 0) ;

 }


 SCRFUN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\SCRFUN.C

 /*  scrfun.c -- contains several video BIOS calls     */
 /*  Setcurs() sets the cursor position                */
 /*  Getcurs() gets the cursor postion                 */
 /*  Setpage() sets the current video page             */
 /*  Setvmode() sets the video mode                    */
 /*  Clearscr() clears the screen                      */
 /*  Read_ch_atr() reads the character and             */
 /*                attribute at the cursor             */
 /*  Write_ch_atr() writes a character and             */
 /*                 attribute at the cursor            */
 /*  Rewrite() rewrites a screen character             */
 /*            with a new attribute                    */
 /*  Getvmode() gets the current video mode            */
 /*  Getpage() gets the current video page             */
 /*                                                    */
 /*  The following functions use Setcurs() to move the */
 /*  one position at a time up to a limit.             */
 /*  Curslt_lim() moves cursor one column left         */
 /*  Cursrt_lim() moves cursor one column right        */
 /*  Cursup_lim() moves cursor one line up             */
 /*  Cursdn_lim() moves cursor one line down           */
 /*                                                    */
 /*  Programs using these functions should include the */
 /*  scrn.h file                                       */

 #include <dos.h>
 #include "scrn.h"

 /* sets cursor to row, column, and page */
 void Setcurs(row, col, page)
 unsigned char row, col, page;
 {
     union REGS reg;

     reg.h.ah = SETCURSOR;
     reg.h.dh = row;
     reg.h.dl = col;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
 }

 /* gets current cursor row, column for given page */
 void Getcurs(pr, pc, page)
 unsigned char *pr, *pc, page;
 {
     union REGS reg;

     reg.h.ah = GETCURSOR;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
     *pr = reg.h.dh;  /* row number */
     *pc = reg.h.dl;   /* column number */
 }


 /* sets page to given value */
 void Setpage(page)
 unsigned char page;
 {
     union REGS reg;

     reg.h.ah = SETPAGE;
     reg.h.al = page;
     int86(VIDEO, &reg, &reg);
 }

 /* sets video mode to given mode */
 void Setvmode(mode)
 unsigned char mode;
 {
     union REGS reg;

     reg.h.ah = SETMODE;
     reg.h.al = mode;
     int86(VIDEO, &reg, &reg);
 }

 /* clear the screen */
 void Clearscr()
 {
     union REGS reg;

     reg.h.ah = SCROLL;
     reg.h.al = 0;
     reg.h.ch = 0;
     reg.h.cl = 0;
     reg.h.dh = ROWS - 1;
     reg.h.dl = COLS - 1;
     reg.h.bh = NORMAL;
     int86(VIDEO, &reg, &reg);
 }

 /* reads the character and attribute at the cursor */
 /* position on a given page                        */
 void Read_ch_atr(pc, pa, page)
 unsigned char *pc, *pa;
 unsigned char page;
 {
     union REGS reg;

     reg.h.ah = READCHATR;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
     *pc = reg.h.al;  /* character at cursor */
     *pa = reg.h.ah;  /* attribute at cursor */
 }

 /* writes a given character and attribute at the */
 /* cursor on a given page for num times          */
 void Write_ch_atr(ch, atr, page, num)
 unsigned char ch, atr, page;
 unsigned int num;
 {
     union REGS reg;

     reg.h.ah = WRITECHATR;
     reg.h.al = ch;
     reg.h.bl = atr;
     reg.h.bh = page;
     reg.x.cx = num;
     int86(VIDEO, &reg, &reg);
 }

 /* rewrites the character at the cursor using    */
 /* attribute at                                  */
 void Rewrite(at, page)
 unsigned char at, page;
 {
      unsigned char ch, atr;

      Read_ch_atr(&ch, &atr, page);
      Write_ch_atr(ch, at, page, 1);
 }

 /* obtains the current video mode */
 unsigned char Getvmode()
 {
     union REGS reg;

     reg.h.ah = GETMODE;
     int86(VIDEO, &reg, &reg);
     return reg.h.al;
 }

 /* obtains the current video page */
 unsigned char Getpage()
 {
     union REGS reg;

     reg.h.ah = GETMODE;
     int86(VIDEO, &reg, &reg);
     return reg.h.bh;
 }

 /* moves cursor one column left, but not past */
 /* the given limit                            */
 unsigned char Curslt_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (col > limit)
         Setcurs(row, col - 1, page);
     else
         status = 0;
     return status;
 }

 /* moves cursor one column right, but not past */
 /* the given limit                             */
 unsigned char Cursrt_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (col < limit)
         Setcurs(row, col + 1, page);
     else
         status = 0;
     return status;
 }

 /* move cursor one row down, but not past */
 /* the given limit                        */
 unsigned char Cursup_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (row > limit)
         Setcurs(row - 1, col, page);
     else
         status = 0;
     return status;
 }

 /* move cursor one row down, but not past */
 /* the given limit                        */
 unsigned char Cursdn_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (row < limit)
         Setcurs(row + 1, col, page);
     else
         status = 0;
     return status;
 }


 SCRFUN.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\SCRFUN.C

 /*  scrfun.c -- contains several video BIOS calls     */
 /*  Setcurs() sets the cursor position                */
 /*  Getcurs() gets the cursor postion                 */
 /*  Setpage() sets the current video page             */
 /*  Setvmode() sets the video mode                    */
 /*  Clearscr() clears the screen                      */
 /*  Read_ch_atr() reads the character and             */
 /*                attribute at the cursor             */
 /*  Write_ch_atr() writes a character and             */
 /*                 attribute at the cursor            */
 /*  Rewrite() rewrites a screen character             */
 /*            with a new attribute                    */
 /*  Getvmode() gets the current video mode            */
 /*  Getpage() gets the current video page             */
 /*                                                    */
 /*  The following functions use Setcurs() to move the */
 /*  one position at a time up to a limit.             */
 /*  Curslt_lim() moves cursor one column left         */
 /*  Cursrt_lim() moves cursor one column right        */
 /*  Cursup_lim() moves cursor one line up             */
 /*  Cursdn_lim() moves cursor one line down           */
 /*                                                    */
 /*  Programs using these functions should include the */
 /*  scrn.h file                                       */

 #include <dos.h>
 #include "scrn.h"

 /* sets cursor to row, column, and page */
 void Setcurs(row, col, page)
 unsigned char row, col, page;
 {
     union REGS reg;

     reg.h.ah = SETCURSOR;
     reg.h.dh = row;
     reg.h.dl = col;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
 }

 /* gets current cursor row, column for given page */
 void Getcurs(pr, pc, page)
 unsigned char *pr, *pc, page;
 {
     union REGS reg;

     reg.h.ah = GETCURSOR;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
     *pr = reg.h.dh;  /* row number */
     *pc = reg.h.dl;   /* column number */
 }


 /* sets page to given value */
 void Setpage(page)
 unsigned char page;
 {
     union REGS reg;

     reg.h.ah = SETPAGE;
     reg.h.al = page;
     int86(VIDEO, &reg, &reg);
 }

 /* sets video mode to given mode */
 void Setvmode(mode)
 unsigned char mode;
 {
     union REGS reg;

     reg.h.ah = SETMODE;
     reg.h.al = mode;
     int86(VIDEO, &reg, &reg);
 }

 /* clear the screen */
 void Clearscr()
 {
     union REGS reg;

     reg.h.ah = SCROLL;
     reg.h.al = 0;
     reg.h.ch = 0;
     reg.h.cl = 0;
     reg.h.dh = ROWS - 1;
     reg.h.dl = COLS - 1;
     reg.h.bh = NORMAL;
     int86(VIDEO, &reg, &reg);
 }

 /* reads the character and attribute at the cursor */
 /* position on a given page                        */
 void Read_ch_atr(pc, pa, page)
 unsigned char *pc, *pa;
 unsigned char page;
 {
     union REGS reg;

     reg.h.ah = READCHATR;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
     *pc = reg.h.al;  /* character at cursor */
     *pa = reg.h.ah;  /* attribute at cursor */
 }

 /* writes a given character and attribute at the */
 /* cursor on a given page for num times          */
 void Write_ch_atr(ch, atr, page, num)
 unsigned char ch, atr, page;
 unsigned int num;
 {
     union REGS reg;

     reg.h.ah = WRITECHATR;
     reg.h.al = ch;
     reg.h.bl = atr;
     reg.h.bh = page;
     reg.x.cx = num;
     int86(VIDEO, &reg, &reg);
 }

 /* rewrites the character at the cursor using    */
 /* attribute at                                  */
 void Rewrite(at, page)
 unsigned char at, page;
 {
      unsigned char ch, atr;

      Read_ch_atr(&ch, &atr, page);
      Write_ch_atr(ch, at, page, 1);
 }

 /* obtains the current video mode */
 unsigned char Getvmode()
 {
     union REGS reg;

     reg.h.ah = GETMODE;
     int86(VIDEO, &reg, &reg);
     return reg.h.al;
 }

 /* obtains the current video page */
 unsigned char Getpage()
 {
     union REGS reg;

     reg.h.ah = GETMODE;
     int86(VIDEO, &reg, &reg);
     return reg.h.bh;
 }

 /* moves cursor one column left, but not past */
 /* the given limit                            */
 unsigned char Curslt_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (col > limit)
         Setcurs(row, col - 1, page);
     else
         status = 0;
     return status;
 }

 /* moves cursor one column right, but not past */
 /* the given limit                             */
 unsigned char Cursrt_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (col < limit)
         Setcurs(row, col + 1, page);
     else
         status = 0;
     return status;
 }

 /* move cursor one row down, but not past */
 /* the given limit                        */
 unsigned char Cursup_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (row > limit)
         Setcurs(row - 1, col, page);
     else
         status = 0;
     return status;
 }

 /* move cursor one row down, but not past */
 /* the given limit                        */
 unsigned char Cursdn_lim(limit)
 unsigned char limit;
 {
     unsigned char row, col, page;
     unsigned char status = 1;

     Getcurs(&row, &col, page = Getpage());
     if (row < limit)
         Setcurs(row + 1, col, page);
     else
         status = 0;
     return status;
 }


 SCRINV.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\SCRINV.C

 /* scrinv.c  --  using a far pointer to access text   */
 /*               screen memory                        */

 #define ROWS 25
 #define COLS 80

 main()
 {
     int far *screenp;
     int temp, i;

     do
         {
         /* use 0xB800000 for EGA or VGA */
         screenp = (int far *)0xB0000000;

         for (i = 0; i < ((ROWS*COLS)/2); ++i)
             {
             temp = screenp[i];
             screenp[i] = screenp[(ROWS*COLS)-i-1];
             screenp[(ROWS*COLS)-i-1] = temp;
             }
         } while (getch() != 'Q');

 }


 SCRMENU.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\SCRMENU.C

 /* scrmenu.c  -- uses bit fields to modify your text   */
 /*               screen's attributes                   */

 char *Choice_Words[] = {
     "Quit",
     "Foreground",
     "Intensity",
     "Background",
     "Blinking"
 };
 enum Choices {
     Quit,
     Foreground,
     Intensity,
     Background,
     Blinking
 };

 /* use 0xB800000 for EGA or VGA */
 #define SCR_START (0xB0000000)
 #define SCR_SIZE (25 * 80)

 main()
 {
     enum Choices choice;

     printf("Select from the following by number:\n");

     for (choice = Quit; choice <= Blinking; ++choice)
         {
         printf("%d. %s\n", choice, Choice_Words[choice]);
         }

     printf("\nWhich: ");
     do
         {
         choice = getch();
         choice -= '0';
         if (choice < Foreground || choice > Blinking)
             continue;
         Redraw(choice);
         } while (choice != Quit);

 }

 Redraw(enum Choices field)
 {
     struct screen_char {
         unsigned int character  :8,
                      foreground :3,
                      intensity  :1,
                      background :3,
                      blink      :1;
     } scrchar, far *sp, far *ep;

     sp = (struct screen_char far *)SCR_START;
     ep = sp + SCR_SIZE;

     while (sp < ep)
         {
         scrchar = *sp;
         switch (field)
             {
             case Foreground:
                 scrchar.foreground = (scrchar.foreground)? 0 : 7;
                 break;
             case Intensity:
                 scrchar.intensity = (scrchar.intensity)? 0 : 1;
                 break;
             case Background:
                 scrchar.background = (scrchar.background)? 0 : 7;
                 break;
             case Blinking:
                 scrchar.blink = (scrchar.blink)? 0 : 1;
                 break;
             }
         *(sp++) = scrchar;
         }
 }


 SCRREST.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\SCRREST.C

 /* scrrest.c  --  demonstrates read() by restoring */
 /*                text screen from any file.       */

 <stdio.h>        /* for stderr              */
 <fcntl.h>        /* for O_RDONLY | O_BINARY */

 #define SCRCHARS  (25 * 80)
 int Buf[SCRCHARS];

 main(argc, argv)
 int argc;
 char *argv[];
 {
     int *cp, *ep;
     int far *sp;
     int fd_in, bytes;

     if (argc != 2)
         {
         fprintf(stderr, "usage: scrrest file.scr\n");
         exit(0);
         }
     if ((fd_in = open(argv[1], O_RDONLY | O_BINARY)) < 0)
         {
         fprintf(stderr, "\"%s\": Can't open to read.\n", argv[1]);
         exit(1);
         }
     /* Read it. */
     bytes = read(fd_in, Buf, SCRCHARS * 2);
     if (bytes < 0)
         {
         fprintf(stderr, "\"%s\": Error Reading.\n", argv[1]);
         exit(1);
         }
     if (bytes == 0)
         {
         fprintf(stderr, "\"%s\": Empty File.\n", argv[1]);
         exit(1);
         }
     /* Copy the buffer to screen memory. */
     ep = &Buf[bytes / 2];
     cp = Buf;

     /* use 0xB800000 for EGA or VGA */
     sp = (int far *)(0xB0000000);
     for (; cp < ep; ++cp, ++sp)
         *sp = *cp;
 }


 SCRSAVE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\SCRSAVE.C

 /* scrsave.c  --  demonstrates write() by saving the */
 /*                text screen to a file.             */

 <stdio.h>        /* for stderr              */
 <fcntl.h>        /* for O_CREAT | O_BINARY  */
 <sys\types.h>    /* for stat.h              */
 <sys\stat.h>     /* for S_IREAD | S_IWRITE  */

 #define SCRCHARS  (25 * 80)
 int Buf[SCRCHARS];

 main(argc, argv)
 int argc;
 char *argv[];
 {
     int *cp, *ep, fname[16];
     int far *sp;
     int fd_out, bytes;

     if (argc != 2)
         {
         fprintf(stderr, "usage: scrsave file\n");
         exit(0);
         }
     if (strlen(argv[1]) > 8)
         {
         fprintf(stderr, "\"%s\": File name too long.\n", argv[1]);
         exit(1);
         }
     strcpy(fname, argv[1]);
     strcat(fname, ".SCR");
     if (access(fname, 0) == 0)
         {
         fprintf(stderr, "\"%s\": Won't overwrite.\n", fname);
         exit(1);
         }
     if ((fd_out = open(fname, O_WRONLY|O_CREAT|O_BINARY,
                        S_IREAD|S_IWRITE)) < 0)
         {
         fprintf(stderr, "\"%s\": Can't create.\n", fname);
         exit(1);
         }
     /* Copy the screen into a near buffer. */
     ep = &Buf[SCRCHARS - 1];
     cp = Buf;
     /* use 0xB800000 for EGA or VGA */
     sp = (int far *)(0xB0000000);
     for (; cp < ep; ++cp, ++sp)
         *cp = *sp;
     /* Write it. */
     bytes = write(fd_out, Buf, SCRCHARS * 2);
     if (bytes != SCRCHARS * 2)
         {
         fprintf(stderr, "\"%s\": Error writing.\n", fname);
         exit(1);
         }
 }


 SETCURS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\SETCURS.C

 /* setcurs.c -- moves cursor, checks out Setcurs() */
 #include <dos.h>
 #include <stdio.h>
 #define VIDEO 0x10
 #define SETCURSOR 2
 void Setcurs(unsigned char, unsigned char,
              unsigned char);
 main()
 {
     int row, col;

     printf("Enter row and column: (q to quit)\n");
     while (scanf("%d %d", &row, &col) == 2)
     {
         Setcurs(row, col, 0);
         printf("Enter row and column: (q to quit)");
     }
 }

 /* Setcurs() -- sets cursor to row, column, and page */
 void Setcurs(row, col, page)
 unsigned char row, col, page;
 {
     union REGS reg;

     reg.h.ah = SETCURSOR;
     reg.h.dh = row;
     reg.h.dl = col;
     reg.h.bh = page;
     int86(VIDEO, &reg, &reg);
 }


 SHIFTADD.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\SHIFTADD.C

 /* shiftadd.c -- shift and add numbers               */

 main()
 {
     int x = 0x12;
     int y;

     y = x << 8 + 2;
     printf("y is 0x%x\n", y);
 }



 SHORTIF.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\SHORTIF.C

 /* shortif.c -- shows 'shorthand' IF / ELSE   */
 /*           -- gets absolute value of number */

 main()
 {
     int num, pos, abs;
     printf("Enter a whole number: ");
     scanf("%d", &num);

     pos = (num >= 0); /* is number positive? */

     abs = (pos) ? num : -num;  /* assigns negative of */
                       /* number if number is negative */
     if (pos)
         printf ("The number is positive.\n");
     else
         printf("The number is negative.\n");
     printf("Absolute value of number is: %d\n", abs);
 }


 SHOW2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\SHOW2.C

 /* show2.c  --     shows how to use main()'s envp */

 <stdio.h>        /* for NULL */

 main(argc, argv, envp)
 int argc;
 char *argv[], *envp[];
 {
     int i;

     printf("argc = %d\n", argc);
     printf("\n");

     for (i = 0; i < argc; ++i)
         {
         printf("argv[%d] -> \"%s\"\n", i, argv[i]);
         }
     printf("argv[%d] -> NULL\n", i);
     printf("\n");

     for (i= 0; envp[i] != NULL; ++i)
         {
         printf("envp[%d] -> \"%s\"\n", i, envp[i]);
         }
     printf("envp[%d] -> NULL\n", i);

 }


 SHOWARGS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\SHOWARGS.C

 /* showargs.c  --  shows how to access the arguments   */
 /*                 passed to main()                    */

 <stdio.h>        /* for NULL */

 main(argc, argv)
 int argc;
 char *argv[];
 {
     int i;

     printf("argc = %d\n", argc);
     printf("\n");

     for (i = 0; i < argc; ++i)
         {
         printf("argv[%d] -> \"%s\"\n", i, argv[i]);
         }
     printf("argv[%d] -> NULL\n", i);
     printf("\n");

 }


 SHOWCODE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\SHOWCODE.C

 /*  showcode.c -- shows ASCII and scan codes for    */
 /*                keystrokes                        */
 /* Note: Set Screen Swapping On in the Debug menu.  */
 #include <stdio.h>
 #include <dos.h>
 KEYINTR 0x16  /* keyboard read interrupt */
 GETCHAR 0     /* read scancode function  */
 ESC '\033'    /* escape key              */
 struct SCANCODE {
                 unsigned char ascii;  /* ascii code */
                 unsigned char scan;   /* scan code  */
                 };
 struct SCANCODE Readkey();

 main()
 {
     struct SCANCODE keys;

     printf("Press keys to see their scancodes. ");
     printf("Press the Esc key to quit.\n");
     do  {
         keys = Readkey();
         if (keys.ascii > 0 && keys.ascii < 040)
             printf("^%c: ascii = %3d, scan = %3d\n",
                     keys.ascii + 0100, keys.ascii,
                     keys.scan);
         else if (keys.ascii >= 40)
             printf(" %c: ascii = %3d, scan = %3d\n",
                     keys.ascii, keys.ascii, keys.scan);
         else
             printf("  : ascii = %3d, scan = %3d\n",
                     keys.ascii, keys.scan);
         } while (keys.ascii != ESC);
 }

 struct SCANCODE Readkey()
 {
     union REGS reg;
     struct SCANCODE scancode;

     reg.h.ah = GETCHAR;
     int86(KEYINTR, &reg, &reg);
     scancode.ascii = reg.h.al;
     scancode.scan = reg.h.ah;
     return (scancode);
 }


 SPECS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\SPECS.C

 /* specs.c -- shows printf() format  */
 /*            specifiers for numbers */

 main()
 {
     int    i = 122;       /* ASCII code for 'z' */
     long   l = 93000000;  /* distance to Sun (miles) */
     float  f = 192450.88; /* someone's bottom line */
     double d = 2.0e+030;  /* mass of Sun (kg.) */

     printf("%d\n", i);  /* integer as decimal */
     printf("%x\n", i);  /* integer as hex */
     printf("%ld\n", l); /* long */
     printf("%f\n", f);  /* float as decimal */
     printf("%e\n", f);  /* float as exponential */
     printf("%f\n", d);  /* double as decimal */
     printf("%d\n", d);  /* double as exponential */
 }


 SQUARE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\SQUARE.C

 /* square.c  --  a quiz to demonstrate passing        */
 /*               pointers and addresses in functions  */

 main()
 {
     int val, count, guess;

     for (count = 1; count < 255; ++count)
         {
         val = count;
         printf("\nWhat is the square of %d?\n", val);
         if (scanf("%d", &guess) != 1)
             return(0);           /* non-number exits   */

         if(Square(&val) != 0)    /* pass val's address */
             {
             printf("Range Error\n");
             exit(1);
             }
         if (val != guess)
             printf("Wrong. It is %d.\n", val);
         else
             printf("Right!\n");
         printf("Continue? ");
         if (getche() != 'y')
             break;
         }
 }

 int Square(int *where)
 {
     if (*where > 181 || *where < -181)
         return (-1);
     *where = (*where) * (*where);
     return (0);
 }


 SQUARE2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\SQUARE2.C

             /* LISTING 8-2 */

 /* square.c  --  A quiz to demonstrate passing        */
 /*               pointers and addresses in functions. */

 #include <stdio.h>

 main()
     {
     int val, count, guess;

     for (count = 1; count < 255; ++count)
         {
         val = count;
         printf("\nWhat is the square of %d?\n", val);
         if (scanf(" %d", &guess) != 1)
             return(0);           /* non-number exits   */

         if(Square(&val) != 0)    /* pass val's address */
             {
             printf("Range Error\n");
             exit(1);
             }

         if (val != guess)
             printf("Wrong. It is %d.\n", val);
         else
             printf("Right!\n");


         printf("Continue? ");
         if (getche() != 'y')
             break;
         }
     return (0);
     }

 int Square(int *where)
     {
     if (*where > 181 || *where < -181)
         return (-1);
     *where = (*where) * (*where);
     return (0);
     }


 STATIC.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\STATIC.C

 /* static.c -- demonstrates a static variable */
 /*             that holds count of lines,     */
 /*             words, and characters          */

 main()
     {
     void countline();
     printf("Type some lines of text.\n");
     printf("Start a line with a . to quit.\n\n");

     while (getche() != '.')
         countline();  /* accumulate word and */
                       /* line counts         */
     }

 void countline()
     {
     static int words = 0; /* static variables */
     static int chars = 0;
     char ch;
     ++chars; /* count char typed when */
              /* function was called   */

     while ((ch = getche()) != '\r')
         {
         ++chars;
         if (ch == ' ')
             ++words;
         }
         ++words; /* count last word */

     printf("\nWords so far %d. Chars. so far %d\n", words, chars);
     }


 STRINGS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\STRINGS.C

 /* strings.c -- shows two ways to print */
 /*              a string with printf()  */

 main()
 {
     printf("This uses a string literal by itself\n");
     printf("%s", "This plugs the literal into %s\n");
 }


 STRINGS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\STRINGS.C

 /* strings.c  --  opens a file and searches it for */
 /*                possible strings                 */

 <stdio.h>       /* for FILE, BUFSIZ & EOF */
 <ctype.h>       /* for isprint()          */

 main(argc, argv)
 int argc;
 char *argv[];
 {
     FILE *fp;
     char buf[BUFSIZ];
     int ch, count;

     if (argc != 2)
         {
         fprintf(stderr, "usage: strings file\n");
         exit(1);
         }
     if ((fp = fopen(argv[1], "rb")) == NULL)
         {
         fprintf(stderr, "Can't open %s\n", argv[1]);
         exit(1);
         }

     count = 0;
     while ((ch = fgetc(fp)) != EOF)
         {
         if (! isprint(ch) || count >= (BUFSIZ - 1))
             {
             if (count > 5)
                 {
                 buf[count] = 0;
                 puts(buf);
                 }
             count = 0;
             continue;
             }
         buf[count++] = ch;
         }
 }


 STRIO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP13\STRIO.C

 /* strio.c -- uses cgets() and cputs()                   */
 /* program list -- strio.c (cgets() not in core library) */
 #include <conio.h>
 #define MAXSIZE 6
 main()
 {
      char store[MAXSIZE + 2];

      store[0] = MAXSIZE; /* put limit in first element */
      cputs("What's your name?\n\r");
      cgets(store);
      cputs("\n\rI'll remember you, ");
      cputs(store + 2);
      cputs("!\n\r");
 }


 STRPOOL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\STRPOOL.C

 /* strpool.c  -- dumps the string pool to show how     */
 /*               quoted strings are stored             */

 #define PHRASE \
 "This is one long sentence that the compiler \
 combines into a single string."

 char Start[]        = "start";
 char Long_phrase[]  = PHRASE;
 char Short_phrase[] = "This is a short phrase";
 char Cent_string[]  = "\x9b";

 main()
 {
     static char local_phrase[] = "This is local";
     char *cp;

     printf("Dump of the string pool:\n");
     printf("-----------------------\n");

     printf("\"");                /* print leading quote */

     /*
      * Note that the address of a string can be
      * assigned to a pointer: cp = Start
      */
     for (cp = Start; *cp != '^'; ++cp)
         {
         if (*cp == '\0')        /* print '\0' as a quote */
             printf("\"\n\"");
         else if (*cp == '\n' )  /* print '\n' as '\' 'n' */
             printf("\\n");
         else
             printf("%c", *cp);
         }
     printf("^");                /* marks end */
 }


 SUMNUMS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\SUMNUMS.C

 /* sumnums.c -- type mismatch in function arguments  */
 /*              No function prototyping              */

 int sums();

 main()
 {
     float a = 10.0;
     float b = 20.0;
     int c;

     c = sums(a, b);
     printf("sum of %.1f and %.1f is %d\n", a, b, c); ;
 }

 int sums(x, y)
 int x, y;
 {
     return (x + y);
 }



 SUMNUMS2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\SUMNUMS2.C

 /* sumnums2.c -- type mismatch in function arguments  */
 /*               Function prototyping              */

 int sums(int, int);
 main()
 {
     float a = 10.0;
     float b = 20.0;
     int c;

     c = sums(a, b);
     printf("sum of %.1f and %.1f is %d\n", a, b, c);
 }
 int sums(x, y)
 int x, y;
 {
     return ( x + y);
 }



 SWITCH.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP05\SWITCH.C

 /* switch.c -- demonstrates switch statement */
 /*             prints values according       */
 /*             to user's choice              */

 <math.h> /* for sqrt() */
 #define TRUE 1
 main()
 {
     char choice;   /* routine wanted by user   */
     int number;    /* number entered by user   */

     while (TRUE)   /* endless loop */
     {
         printf("\nSelect value wanted:\n");
         printf("o = octal  h = hex   s = square\n");
         printf("r = square root  q = quit: ");
         choice = getche(); printf("\n");

         if (choice == 'q')
             break; /* exits WHILE loop; ends program */

         /* rest of program executed if base <> 'q' */
             printf("Enter a whole number: ");
             scanf("%d", &number);

         switch (choice) /* print according to */
                         /* choice requested   */
             {
             case 'o':   /* print octal */
                 printf("Result: %o\n", number);
                 break;  /* break here in each case    */
                         /* exits the switch statement */

             case 'h':   /* print hex */
                 printf("Result: %x\n", number);
                 break;

             case 's':   /* square */
                 printf("Result: %d\n", number * number);
                 break;

             case 'r':   /* square root */
                 printf("Result: %f\n", sqrt(number) );
                 break;

             default:
                 printf("Choice must be o, h, s, r, or q\n");
             }
      }
 }


 TABLE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\TABLE.C


 /* TABLE.C -- prints square root, square, and cube */
 /*            for the numbers 1 thru 9             */

 <math.h> /* include math functions so we  */
                   /*  can do square root           */

 main()
 {
     int i;
     printf("i\t sqrt(i)\tsquare(i)\tcube(i)\n\n");
     for (i = 1; i < 10; i++)
         /* beginning of body of loop */
         {
         printf("%d\t", i);
         printf("%f\t", sqrt(i));
         printf("%d\t\t", i * i);
         printf("%d\n", i * i * i);
         }
         /* end of body of loop */
 }



 TABS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\TABS.C

 /* tabs.c -- shows formatting with the \t */
 /*           tab escape sequence          */

 main()
 {
     int    q1 = 338, q2 = 57, q3 = 1048, q4 = 778,
            /* quantity in bin */
            t1 = 6, t2 = 8, t3 = 12, t4 = 16;
            /* threads per inch */

     float  s1 = 0.250, s2 = 0.500, s3 = 0.750, s4 = 1.0;
            /* size in inches */

     /* print table header */
     printf("number\t\t size\t\t threads\n");
     printf("in bin\t\t (inches)\t per inch\n\n");

     /* print lines of table */
     printf("%d\t\t %f\t %d\n", q1, s1, t1);
     printf("%d\t\t %f\t %d\n", q2, s2, t2);
     printf("%d\t\t %f\t %d\n", q3, s3, t3);
     printf("%d\t\t %f\t %d\n", q4, s4, t4);
 }


 TEST.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\TEST.C

 /* test.c -- test the routines in basic.lib */
 /* Program list: test.c and basic.lib       */

 #include <stdio.h>

 main()
 {
     static char string[] = "This is a test.";
     char *cp, *Leftstr(), *Midstr(), *Rightstr();

     printf("Testing: \"%s\"\n", string);

     if ((cp = Leftstr(string, 4)) == NULL)
         {
         printf("Error in Leftstr()\n");
         exit(1);
         }
     printf("Leftstr() returned: \"%s\"\n", cp);

     if ((cp = Midstr(string, 4, 5)) == NULL)
         {
         printf("Error in Midstr()\n");
         exit(1);
         }
     printf("Midstr() returned: \"%s\"\n", cp);

     if ((cp = Rightstr(string, 5)) == NULL)
         {
         printf("Error in Rightstr()\n");
         exit(1);
         }
     printf("Rightstr() returned: \"%s\"\n", cp);
 }


 TESTER.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP16\TESTER.C

 /* tester.c -- demonstrates the assert() macro        */
 /* Program list: tester.c (to link math functions)    */

 #include <assert.h>
 #include <stdio.h>
 #include <math.h>
 main()
 {
     float s1 = 3.0;
     float s2 = 4.0;
     float sumsq;
     float hypot;

     sumsq = s1*s1 - s2*s2;
     assert(sumsq >= 0);
     hypot = sqrt(sumsq);
     printf("hypotenuse is %.2f\n", hypot);
 }


 TEXED.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP12\TEXED.C

 /* texed.c  --  main entry point to the editor; the   */
 /*              menu and signal handlers are here     */

 main(argc, argv)
 int argc;
 char *argv[];
 {
     char ch;

     while (1)
         {
         printf("\nTexEd Main Menu\n");
         printf("Select from:\n");
         printf("0) Quit\n\n");
         printf("1) Load File\n");
         printf("2) Save File\n");
         printf("3) Edit File\n");
         printf("Which: ");
         do
             {
             ch = getch();
             ch -= '0';
             } while (ch < 0 || ch > 3);
         printf("%d\n\n", (int)ch);
         switch(ch)
             {
             case 0: exit(0);
             case 1: Load_file(); break;
             case 2: Save_file(); break;
             case 3: Edit_file(); break;
             }
         }
 }


 TIMER.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\TIMER.C


 /* TIMER.C -- uses do loop to    */
 /*            check elapsed time */

 #include <time.h>

 main()
 {
     long start, end, /* starting and ending times */
                      /* measured in seconds since */
                      /* Jan. 1, 1970 */
          ltime;      /* used to get val from time function */
     int seconds;     /* elapsed time to be set */

     printf("QuickC Egg Timer\n");
     printf("Enter time to set in seconds: ");
     scanf("%d", &seconds);
     start = time(&ltime);  /* get system elapsed seconds */
                            /* since 1-1-70 */
     end = start + seconds; /* calculate alarm time */

     do
        ;                       /* null statement for loop body */
     while (time(&ltime) < end);   /* wait for alarm time  */

     printf("Time's Up!\a\a\a\n");
 }



 TIMER2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP06\TIMER2.C

 /* timer2.c -- interval timer             */
 /*             calls delay(), uses beep() */

 main()
 {
     /* function declarations */
     void beep (times);
     void delay (seconds);

     /* variable declarations */
     int seconds, interval, tick;

     printf("Set for how many seconds? ");
     scanf("%d", &seconds);
     printf("Interval to show in seconds? ");
     scanf("%d", &interval);
     printf("Press a key to start timing\n");
     getch();

     tick = 0;                /* run "clock" for */
     while (tick < seconds)   /* time specified  */
         {
         delay(interval); /* wait interval seconds */
         tick += interval;
         printf("%d\n", tick);
         beep(1);
         }
     beep(3);
 }

 void delay(seconds)
                /* wait for number of seconds specified */
                /* see TIMER.C in chapter 4 for details */
                /* on the library function time().      */

 int seconds;   /* parameter declaration */
 {
     /* variable declarations */
     long start, end, /* starting and ending times */
                      /* measured in seconds since */
                      /* Jan. 1, 1970 */
          ltime;      /* used to get val from time function */

     start = time(&ltime);  /* get system elapsed seconds */
                            /* since 1-1-70 */
     end = start + seconds; /* calculate alarm time */

     do
        ;                          /* null statement for loop body */
     while (time(&ltime) < end);   /* wait for end of time  */
 }

 void beep(times)
     /* parameter declaration */
 int times;
 {
     /* variable declaration  */
     int count;


     /* check that parameter is between 1 and 4 */
     if ((times < 1) || (times > 4))
         {
         printf("Error in beep(): %d beeps specified.\n",
             times);
         printf("Specify one to four beeps");
         }
     else /* sound the beeps */
         for (count = 1; count <= times; count++)
             printf("\a");  /* "alert" escape sequence */
 }


 TINY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\TINY.C

 /* tiny.c -- the smallest possible C */
 /*           program with comments   */

 main() /* function name and argument list */
 {
        /* function definition in braces */
 }


 TODAY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\TODAY.C

 /* today.c  -- demonstrates using enum  */

 main()
 {
     enum week_days {
         monday = 1,    /* start with 1 */
         tuesday,
         wednesday,
         thursday,
         friday,
         saturday,
         sunday
     } pay_day;

     static char *day_names[] = {
         "",
         "monday",
         "tuesday",
         "wednesday",
         "thursday",
         "friday",
         "saturday",
         "sunday"
     };

     printf("What day do you want to be paid on?\n");

     for (pay_day = monday; pay_day <= sunday; ++pay_day)
         {
         printf("%d. %s\n", pay_day, day_names[pay_day]);
         }

     printf("Which (%d-%d): ", monday, sunday);

     do
         {
         pay_day = getch();
         pay_day -= '0';
         } while (pay_day < monday || pay_day > sunday);

     printf("%d\n\n", pay_day);

     printf("You selected %s\n", day_names[pay_day]);

 }


 TOTAL.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\TOTAL.C

 /* total.c  -- how to build an array on the fly    */

 <stdio.h>         /* for NULL   */
 <malloc.h>        /* for size_t */

 main()
 {
     int *iptr, count = 0, i, total;
     size_t bytes = sizeof(int);

     /* Start the array with room for one value. */
     if ((iptr = malloc(bytes)) == NULL)
         {
         printf("Oops, malloc failed\n");
         exit(1);
         }

     printf("Enter as many integer values as you want.\n");
     printf("I will build an array on the fly with them.\n");
     printf("(Any non-number means you are done.)\n");

     while (scanf("%d", &iptr[count]) == 1)
         {
         ++count;
         /* Enlarge the array. */
         if ((iptr = realloc(iptr,bytes*(count+1))) == NULL)
             {
             printf("Oops, realloc failed\n");
             exit(1);
             }
         }
     total = 0;
     printf("You entered:\n");
     for (i = 0; i < count; i++)
         {
         printf("iptr[%d] = %d\n", i, iptr[i]);
         total += iptr[i];
         }
     printf("\nTotal: %d\n", total);
     return (0);
 }


 TOTAL2.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP08\TOTAL2.C

 /* total2.c -- how to build an array on the fly       */
 /*             using sbrk()                           */

 <stdio.h>        /* for NULL   */
 <malloc.h>       /* for size_t */

 main()
     {
     int *iptr, count = 0, i, total;
     size_t bytes = sizeof(int);

     /* Start the array with room for one value. */
     iptr = sbrk(0);
     if (sbrk(bytes) == (int *)-1)
         {
         printf("Oops, sbrk failed\n");
         exit(1);
         }

     printf("Enter as many integer values as you want.\n");
     printf("I will build an array on the fly with them.\n");
     printf("(Any non-number means you are done.)\n");

     while (scanf("%d", &iptr[count]) == 1)
         {
         ++count;
         /* Enlarge the array. */
         if (sbrk(bytes) == (int *)-1)
             {
             printf("Oops, sbrk failed\n");
             exit(1);
             }
         }
     total = 0;
     for (i = 0; i < count; i++)
         total += iptr[i];
     /* just print the total this time */
     printf( "%d\n", total);
 }


 TRUTH.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\TRUTH.C

 /* truth.c -- shows logical operators */

 main()
 {
     printf("1 AND 1 is %d\n", 1 && 1);
     printf("1 AND 0 is %d\n", 1 && 0);
     printf("0 AND 0 is %d\n", 0 && 0);
     printf("1 OR 1 is %d\n",  1 || 1);
     printf("1 OR 0 is %d\n",  1 || 0);
     printf("0 OR 0 is %d\n",  0 || 0);
 }


 TTT.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\TTT.C

 /* ttt.c    --  a tic-tac-toe game demonstrates  */
 /*              passing two-dimensional arrays   */
 /*              to functions                     */

 main()
 {
     static char board[3][3] = {
         { '-', '-', '-' },
         { '-', '-', '-' },
         { '-', '-', '-' },
     };
     int row, col, ch;
     extern char Check_winner();
     extern void Make_move(), Draw_field();

     printf("You are X and make the first move.\n");
     while (1)
         {
         printf("Specify coordinate for your X.\n");
         printf("(eg, as a2, or Q to quit)\n");

         /* Print the square. */
         Draw_field(board);

         /* Input the user's coordinates. */
         if ((row = getch()) == 'Q')
             exit(0);
         row -= 'a';
         col = getch() - '1';

         /* Check for a legal move. */
         if (row < 0 || row > 2 || col < 0 || col > 2)
             {
             printf("Bad Square Specification\n\n");
             continue;
             }
         if (board[row][col] != '-')
             {
             printf("Sorry, Square Occupied\n\n");
             continue;
             }

         /* Make the move. */
         board[row][col] = 'X';
         if ((ch = Check_winner(board)) != '-' || ch == 't')
             break;
         Make_move(board);
         if ((ch = Check_winner(board)) != '-' || ch == 't')
             break;
         }
     Draw_field(board);
     if (ch == 't')
         printf("It's a tie!\n");
     else if (ch == 'X')
         printf("You win!\n");
     else
         printf("I win!\n");
 }

 char Check_winner(char field[][3])
 {
     int row, col;

     for (row = col = 0; row < 3; ++row, ++col)
         {
         if (field[row][0] != '-'             /* horizontal */
                 && field[row][0] == field[row][1]
                 && field[row][1] == field[row][2] )
             {
             return(field[row][0]);
             }
         if (field[0][col] != '-'             /* vertical */
                 && field[0][col] == field[1][col]
                 && field[1][col] == field[2][col] )
             {
             return(field[0][col]);
             }
         }
     if (field[0][0] != '-'         /* right diagonal */
             && field[0][0] == field[1][1]
             && field[1][1] == field[2][2] )
         {
         return(field[0][0]);
         }
     if (field[0][2] != '-'         /* left diagonal */
             && field[0][2] == field[1][1]
             && field[1][1] == field[2][0] )
         {
         return(field[0][2]);
         }

     for (row = 0; row < 3; ++row)        /* any moves left */
         {
         for (col = 0; col < 3; ++col)
             {
             if (field[row][col] == '-')
                 {
                 return('-');
                 }
             }
         }
     return ('t');
 }

 void Make_move(char field[3][3])
 {
     int row, col;

     for (row = 2; row >= 0; --row)
         {
         for (col = 2; col >= 0; --col)
             {
             if (field[row][col] == '-')
                 {
                 field[row][col] = 'O';
                 return;
                 }
             }
         }
 }

 void Draw_field(char field[][3])
 {
     int row, col;

     printf("\n   1  2  3\n\n");
     for (row = 0; row < 3; ++row)
         {
         printf("%c ", 'a'+row);
         for (col = 0; col < 3; ++col)
             {
             printf(" %c ", field[row][col] );
             }
         printf("\n");
         }
     printf("\n");
 }


 UDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP11\UDEMO.C

 /* udemo.c  --  demonstrates a union at work */

 #include <stdio.h>

 char *Strings[6] = {
         "Quit",
         "line of text",
         "floating point double value",
         "long integer value",
         "floating point value",
         "integer value"
 };

 struct Unitstruct {
     union {
         char   wtype[BUFSIZ];
         double dtype;
         long   ltype;
         float  ftype;
         int    itype;
     } manyu;
     int type_in_union;
 };

 main()
 {
     struct Unitstruct one_of_many;

     while ((one_of_many.type_in_union = Menu()) != 0)
         {
         Inputval(&one_of_many);
         Printval(&one_of_many);
         }
 }

 Inputval(struct Unitstruct *one_of_many)
     {
     printf("\nEnter a %s: ", Strings[one_of_many->type_in_union]);
     switch(one_of_many->type_in_union)
         {
         case 1:
             fgets(one_of_many->manyu.wtype, BUFSIZ, stdin);
             break;
         case 2:
             scanf("%lf", &(one_of_many->manyu.dtype));
             while (getchar() != '\n');
             break;
         case 3:
             scanf("%ld", &(one_of_many->manyu.ltype));
             while (getchar() != '\n');
             break;
         case 4:
             scanf("%f", &(one_of_many->manyu.ftype));
             while (getchar() != '\n');
             break;
         case 5:
             scanf("%i", &(one_of_many->manyu.itype));
             while (getchar() != '\n');
             break;
         }
 }

 Printval(struct Unitstruct *one_of_many)
 {
     printf("The %s you entered\nwas: ", Strings[one_of_many->type_in_union]);
     switch (one_of_many->type_in_union)
         {
         case 1:
             fputs(one_of_many->manyu.wtype, stdout);
             break;
         case 2:
             printf("%lf", one_of_many->manyu.dtype);
             break;
         case 3:
             printf("%ld", one_of_many->manyu.ltype);
             break;
         case 4:
             printf("%f", one_of_many->manyu.ftype);
             break;
         case 5:
             printf("%i", one_of_many->manyu.itype);
             break;
         }
     printf("\n\n");
 }

 Menu()
 {
     int i;
     char ch;

     for (i = 0; i < 6; ++i)
         {
         printf("%d) %s\n", i, Strings[i]);
         }
     printf("Which: ");
     do
         {
         ch = getch();
         } while (ch < '0' || ch > '5');
     printf("%c\n", ch);
     return (ch - '0');
 }


 UNDOVER.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\UNDOVER.C

 /* undover.c -- illustrates the effect of underinitializing and */
 /*              overinitializing arrays.                        */

 int Primes[6] = { 1, 2, 3, 5, 7, 11 };
 #define NUMP (sizeof(Primes)/sizeof(int))

 main()
 {
     int i;

     printf("The first %d primes are: ", NUMP);
     for (i = 0; i < NUMP; ++i)
         {
         printf("%d ", Primes[i]);
         }
     printf("\n");
 }


 UPITY.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\UPITY.C

 /* upity.c --  makes an uppercase copy of a file using */
 /*             fread() and fwrite()                    */

 <string.h>        /* for strrchr() */
 <stdio.h>         /* for NULL      */
 <malloc.h>        /* for malloc()  */
 <ctype.h>         /* for isupper() */

 #define HUNK 512

 main(argc, argv)
 int argc;
 char *argv[];
 {
     char *cp, newname[128], *np;
     FILE *fp;
     int  hunks = 0, bytes = 0, totbytes = 0;
     int  i;
     if (argc != 2)
         {
         printf("usage: upity file\n");
         exit(1);
         }

     if ((fp = fopen(argv[1], "rb")) == NULL)
         {
         printf("\"%s\": Can't open.\n", argv[1]);
         exit(1);
         }
     if ((cp = malloc(HUNK)) == NULL)
         {
         printf("Malloc Failed.\n");
         exit(1);
         }

     while ((bytes = fread(cp + (HUNK * hunks), 1, HUNK, fp)) == HUNK)
         {
         totbytes += bytes;
         ++hunks;
         if ((cp = realloc(cp, HUNK + (HUNK * hunks))) == NULL)
             {
             printf("Realloc Failed.\n");
             exit(1);
             }
         }
     if (bytes < 0)
         {
         printf("\"%s\": Error Reading.\n", argv[1]);
         exit(1);
         }
     totbytes += bytes;

     for (i = 0; i < totbytes; ++i)
         if (islower(cp[i]))
             cp[i] = toupper(cp[i]);

     (void)fclose(fp);

     if ((np = strrchr(argv[1], '.')) != NULL)
         *np = '\0';
     strcpy(newname, argv[1]);
     strcat(newname, ".up");
     if ((fp = fopen(newname, "wb")) == NULL)
         {
         printf("\"%s\": Can't open.\n", argv[1]);
         exit(1);
         }

     if (fwrite(cp, 1, totbytes, fp) != totbytes)
         {
         printf("\"%s\": Error writing.\n", argv[1]);
         exit(1);
         }

 }


 VARADDRS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\VARADDRS.C

 /* varaddrs.c -- use & operator to get     */
 /*               addresses of variables    */

 main()
 {
     char c1, c2;
     int i;
     long l;
     float f;
     double d;

     printf("Address of c1 %d\n", &c1);
     printf("Address of c2 %d\n", &c2);
     printf("Address of i  %d\n", &i);
     printf("Address of l  %d\n", &l);
     printf("Address of f  %d\n", &f);
     printf("Address of d  %d\n", &d);
 }


 VARSIZE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP03\VARSIZE.C

 /* varsize.c -- shows amount of memory */
 /*              by various types       */

 main()
 {
     printf("Size of a char is %d\n", sizeof(char));
     printf("Size of an int is %d\n", sizeof(int));
     printf("Size of a long is %d\n", sizeof(long));
     printf("Size of a float is %d\n", sizeof(float));
     printf("Size of a double is %d\n", sizeof(double));
 }


 VGAMAP.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP15\VGAMAP.C

 /*  vgamap.c  -- remaps the vga mode 19 palette        */
 /* Program list: vgamap.c (for rand())                 */
 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>
 #define ESC '\033'
 #define PALSIZE 256
 #define ROWS 16
 #define COLS 16
 #define MIDBLUE 0x190000L
 long newpal[PALSIZE]; /* array of color values */

 main()
 {
     struct videoconfig vc;
     int mode = _MRES256COLOR;
     short xmax, ymax;
     short xcs[ROWS][COLS];
     short ycs[ROWS][COLS];
     short row, col;
     long colorval;       /* VGA color value */
     long index;          /* looping index   */
     short palval;        /* palette value */
     int c_base;  /* color base -- blue, green, or red */
     int ch;

     if (_setvideomode(mode) == 0)
         {
         fprintf(stderr, "%d mode not supported\n", mode);
         exit(1);
         }
     _getvideoconfig(&vc);
     xmax = vc.numxpixels - 1;
     ymax = vc.numypixels - 1;
     for (col = 0; col < COLS; col++)
         for (row = 0; row < ROWS; row++)
             {
             xcs[row][col] =  col * xmax / COLS + 5;
             ycs[row][col] =  row * ymax / ROWS + 5;
             }
     _setcolor(1);
     _rectangle(_GBORDER, 0, 0, xmax, ymax);
     for (col = 1; col < COLS ; col++)
         {
         _moveto(col * (xmax + 1) / COLS, 0);
         _lineto(col * (xmax + 1) / COLS, ymax);
         }
     for (row = 1; row < ROWS;  row++)
         {
         _moveto(0, row * (ymax + 1) / ROWS);
         _lineto(xmax, row * (ymax + 1) / ROWS);
         }

     for (col = 0; col < COLS; col++)
         for (row = 0; row < ROWS; row++)
             {
             _setcolor(row * ROWS + col);
             _floodfill(xcs[row][col], ycs[row][col],1);
              }
     getch();

     /*  initialize newpal[] to 64 shades of blue, 64
         shades of green, 64 shades of red, and 64 shades
         of magenta */
     for (index = 0; index < 64; index++)
         {
         newpal[index] = index << 16;
         newpal[index + 64] = index << 8;
         newpal[index + 128] = index;
         newpal[index + 192] = index | MIDBLUE;
         }
     _remapallpalette(newpal);
     getch();

     /* set squares and colors randomly -- ESC
        terminates loop, and other keystrokes toggle
        it on and off */
     do
         {
         while (!kbhit())
             {
             palval = rand() % PALSIZE;
             colorval = 0L;
             for (c_base = 0; c_base < 3; c_base++)
                 colorval += ((long) rand() % 64) <<
                              (c_base * 8);
             _remappalette (palval, colorval);
             }
         ch = getch();
         if (ch != ESC)
             ch = getch();
         } while (ch != ESC);
     _setvideomode(_DEFAULTMODE);
 }


 VIEW.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP10\VIEW.C

 /* view.c  --  demonstrates lseek() by displaying  */
 /*             a file and moving around in it      */

 <fcntl.h>           /* for open()         */
 <stdio.h>           /* for SEEK_CUR, etc. */

 #define HUNK 512
 #define MOVE 512L

 main(argc, argv)
 int argc;
 char *argv[];
 {
     char ch, buf[HUNK];
     long position = 0L;
     int  bytes, eofflag = 0, fd_in;

     if (argc != 2)
         {
         fprintf(stderr, "Usage: view file\n");
         exit(0);
         }

     if ((fd_in = open(argv[1], O_RDONLY)) < 0)
         {
         fprintf(stderr, "\"%s\": Can't open.\n", argv[1]);
         exit(1);
         }

     for (;;)
         {
         bytes = read(fd_in, buf, HUNK);
         if (bytes == 0)
             {
             if (! eofflag)
                 {
                 fprintf(stderr, "\n<<at end of file>>\n");
                 ++eofflag;
                 }
             else
                 exit(0);
             }
         else if (bytes < 0)
             {
             fprintf(stderr, "\"%s\": Error Reading.\n", argv[1]);
             exit(1);
             }
         else
             {
             eofflag = 0;
             position = lseek(fd_in, 0L, SEEK_CUR);
             if (position == -1L)
                 {
                 fprintf(stderr, "\"%s\": Error Seeking.\n", argv[1]);
                 exit(1);
                 }
             Print(buf, bytes);
             do
                 {
                 ch = getch();
                 if (ch == 'q' || ch == 'Q')
                     exit(0);
                 } while (ch != '+' && ch != '-');

             if (ch == '-')
                 {
                 position = lseek(fd_in, -2 * MOVE, SEEK_CUR);
                 if (position == -1L)
                     {
                     fprintf(stderr, "\"%s\": Error Seeking.\n", argv[1]);
                     exit(1);
                     }
                 }
             }
         }
 }

 Print(char *buf, int cnt)
 {
     int i;

     for (i = 0; i < cnt; ++i, ++buf)
         {
         if (*buf < ' ' && *buf != '\n' && *buf != '\t')
             printf("^%c", *buf + '@');
         else
             putchar(*buf);
         }
 }


 WHATCHAR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP09\WHATCHAR.C

 /* whatchar.c  --  demonstrates the character         */
 /*                 classification routines in ctype.h */

 <stdio.h>        /* for NULL and BUFSIZ */
 <ctype.h>        /* for iscntl(), et al */
 #define MAXL 20

 main()
 {
     char buf[BUFSIZ];
     int i;

     printf("Enter a line of text (20 chars max):\n");
     if (gets(buf) == NULL)
         exit(1);

     for (i = 0; i < MAXL; ++i)
         {
         if (buf[i] == '\0')
             break;
         printf("'%c' ->", buf[i]);
         if (isalpha(buf[i]))   printf(" isalpha");
         if (isascii(buf[i]))   printf(" isascii");
         if (iscntrl(buf[i]))   printf(" iscntrl");
         if (isgraph(buf[i]))   printf(" isgraph");
         if (isprint(buf[i]))   printf(" isprint");
         if (isdigit(buf[i]))   printf(" isdigit");
         if (isupper(buf[i]))   printf(" isupper");
         if (islower(buf[i]))   printf(" islower");
         if (ispunct(buf[i]))   printf(" ispunct");
         if (isspace(buf[i]))   printf(" isspace");
         if (isalnum(buf[i]))   printf(" isalnum");
         if (isxdigit(buf[i]))  printf(" isxdigit");
         printf("\n");
         }
 }


 WHILE.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP04\WHILE.C


 /* WHILE.C -- a simple while loop */

 main()
 {
     int count = 1;

     while (count < 11)  /* loop condition */
         /* body of loop */
         {
         printf("%d\n", count);
         count++ ;
         }
     printf("Done!\n");
 }



 WRITECHR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\WRITECHR.C

 /* writechr.c -- writes char and attribute repeatedly */
 /*               using DMA                            */
 /* write character ch with attribute attr num times   */
 /* starting at location pstart -- uses array notation */

 typedef unsigned int (far * VIDMEM);

 void Write_chars(pstart, ch, attr, num)
 VIDMEM pstart;
 unsigned short ch, attr, num;
 {
     register count;
     unsigned short pair;

     pair = (attr << 8) | (ch & 0x00FF) ;
     for (count = 0; count < num; count++)
         pstart[count] = pair;
 }


 WRITESTR.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP14\WRITESTR.C

 /*  writestr.c -- writes string and attribute using DMA */
 /*  write the string str with attribute attr at         */
 /*  location pstart -- uses pointer notation.           */

 typedef unsigned int (far * VIDMEM);

 void Write_str(pstart, attr, str)
 VIDMEM pstart;
 unsigned short attr;
 char *str;
 {
     while (*str != '\0')
         *pstart++ = (attr << 8) | (*str++ & 0x00FF);
 }


 XMAS.C
 CD-ROM Disc Path:   \SAMPCODE\QC_PROG\CHAP07\XMAS.C

 /* xmas.c -- fills an array with values, then passes */
 /*           each of those values to a function.     */

 main()
 {
     int i, j, widths[20];
     void Center_out();

     for (i = 0, j = 1; i < 18; ++i, j += 2)
         {
         widths[i] = j;
         }
     widths[i++] = 3;
     widths[i] = 3;

     for (i = 0; i < 20; i++)
         {
         Center_out('X', widths[i]);
         }

 }

 void Center_out(char character, int width)
 {
     int i;

     for (i = 0; i < ((80 - width) / 2); ++i)
         {
         putch(' ');
         }
     for (i = 0; i < width; ++i)
         {
         putch(character);
         }
     putch('\r');
     putch('\n');
 }
 Misc. `C' Sample Code from Microsoft


 ABS.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ABS.C

 /* ABS.C: Demonstrate macros. */

 #include <stdio.h>
 #define ABS(value)  ( (value) >= 0 ? (value) : -(value) )

 main()
 {
    int val = -20;
    printf( "result = %d\n", ABS(val) );
 }


 ALARM.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ALARM.C

 /* ALARM.C illustrates inline assembly and functions or keywords
  * related to Terminate-and-Stay-Resident programs. Functions include:
  *      _dos_setvect    _dos_getvect    _dos_keep
  *      _chain_intr     _enable         _disable
  *
  * Keywords:
  *      interrupt       _asm
  * Directive:
  *      #pragma
  * Pragma:
  *      check_stack     check_pointer
  * Global variables:
  *      _psp            _amblksiz
  *
  * WARNING: You must run ALARM from the DOS command line. The QC
  * environment does not permit TSRs to be installed from inside it, since
  * this would cause subsequent memory problems.
  *
  * See HARDERR.C for another example of inline assembler. See MOVEMEM.C
  * for another pragma example.
  */

 #include <dos.h>
 #include <malloc.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>

 /* Stack and pointer checking off */
 #pragma check_stack( off )
 #pragma check_pointer( off )

 /* Inline assembler macro to sound a bell. Note that comments in macros must
  * be in the C format, not the assembler format.
  */
 #define BEEP() _asm { \
                         _asm     push bx        /* Save register   */ \
                         _asm     sub  bx, bx    /* Page 0          */ \
                         _asm     mov  ax, 0E07h /* TTY bell        */ \
                         _asm     int  10h       /* BIOS 10         */ \
                         _asm     pop  bx        /* Restore         */ \
                     }

 #define TICKPERMIN  1092L
 #define MINPERHOUR  60L
 enum BOOLEAN { FALSE, TRUE };

 /* Prototypes for interrupt functions */
 void (interrupt far *oldtimer)( void );
 void (interrupt far *oldvideo)( void );
 void interrupt far newtimer( void );
 void interrupt far newvideo( unsigned _es, unsigned _ds, unsigned _di,
                              unsigned _si, unsigned _bp, unsigned _sp,
                              unsigned _bx, unsigned _dx, unsigned _cx,
                              unsigned _ax, unsigned _ip, unsigned _cs,
                              unsigned _flags );

 /* Variables that will be accessed inside TSR must be global. */
 int  ftimesup = FALSE, fintimer = FALSE, finvideo = FALSE;
 long goaltick;
 long far *pcurtick = (long far *)0x0000046cL;

 /* Huge pointers force compiler to do segment arithmetic for us. */
 char huge *tsrstack;
 char huge *appstack;
 char huge *tsrbottom;

 main( int argc, char **argv )
 {
     long minute, hour;
     unsigned tsrsize;

     /* Initialize stack and bottom of program. */
     _asm mov  WORD PTR tsrstack[0], sp
     _asm mov  WORD PTR tsrstack[2], ss
     FP_SEG( tsrbottom ) = _psp;
     FP_OFF( tsrbottom ) = 0;

     /* Use 16 paragraph heap (controlled through global in malloc.h). */
     _amblksiz = 256;

     /* Program size is:
      *     top of stack
      *   - bottom of program (converted to paragraphs)
      *   + paragraphs in the heap plus
      *   + one extra paragraph just to be safe
      */
     tsrsize = ((tsrstack - tsrbottom) >> 4) + (_amblksiz >> 4) + 1;

     /* If command-line, convert time to ticks past midnight. Time must
      * include 0 in first place (0930, not 930). Time must be later than
      * current time.
      */
     if( argc < 2 )
     {
         puts( "  Syntax: ALARM <hhmm> " );
         puts( "     where <hhmm> is time (in military format) to ring alarm"
         exit( 1 );
     }

     minute = atol( argv[1] + 2 );
     argv[1][2] = 0;
     hour = atol( argv[1] );
     goaltick = (hour * MINPERHOUR * TICKPERMIN) + (minute * TICKPERMIN);
     if( *pcurtick > goaltick )
     {
         puts( "It's past that time now" );
         exit( 1 );
     }

     /* Replace existing timer and video routines with ours. */
     oldtimer = _dos_getvect( 0x1c );
     _dos_setvect( 0x1c, newtimer );
     oldvideo = _dos_getvect( 0x10 );
     _dos_setvect( 0x10, newvideo );

     /* Free the PSP segment and terminate with program resident. */
     _dos_freemem( _psp );
     _dos_keep( 0, tsrsize );
 }

 /* newtimer - Our timer interrupt compares current time to goal. If earlier
  * it just continues. If later, it beeps and sets a flag to quit checking.
  */
 void interrupt far newtimer()
 {
     if( ftimesup )
         _chain_intr( oldtimer );
     else
     {
         /* First execute the original timer interrupt. */
         (*oldtimer)();
         if( *pcurtick > goaltick )
         {
             /* If time is up, set flag so we'll never return. */
             ftimesup = TRUE;

             /* Save current stack of application, and set old stack of TSR.
              * This is for safety since we don't know the state of the
              * application stack, but we do know the state of our own stack.
              * Turn off interrupts during the stack switch.
              */
             _disable();
             _asm \
             {
                 mov  WORD PTR appstack[0], sp   ; Save current stack
                 mov  WORD PTR appstack[2], ss
                 mov  sp, WORD PTR tsrstack[0]   ; Load new stack
                 mov  ss, WORD PTR tsrstack[2]
             }
             _enable();

             /* Make sure we're not in video interrupt, then BEEP. This check
              * prevents the rare but potentially dangerous case of
              * calling INT 10 to beep while INT 10 is already running.
              */
             while( finvideo )
                 ;
             BEEP();
             BEEP();
             BEEP();

             /* Restore application stack. */
             _disable();
             _asm \
             {
                 mov  sp, WORD PTR appstack[0]
                 mov  ss, WORD PTR appstack[2]
             }
             _enable();
         }
     }
 }

 /* newvideo - This routine protects against reentering INT 10 while it is
  * already executing. This could be disastrous if the interrupt routine was
  * interrupted while it was accessing a hardware register.
  */
 void interrupt far newvideo( unsigned _es, unsigned _ds, unsigned _di,
                              unsigned _si, unsigned _bp, unsigned _sp,
                              unsigned _bx, unsigned _dx, unsigned _cx,
                              unsigned _ax, unsigned _ip, unsigned _cs,
                              unsigned _flags )
 {
     static unsigned save_bp;

     /* If not already in (most of the time), chain to original. */
     if( !finvideo )
         _chain_intr( oldvideo );
     else
     {

         /* Set the inside flag, then make sure all the real registers
          * that might be passed to an interrupt 10h match the parameter
          * registers. Some of the real registers may be modified by the
          * preceding code. Note that BP must be saved in a static (nonstack)
          * variable so that it can be retrieved without modifying the stack.
          */
         finvideo = TRUE;
         _asm \
         {
             mov ax, _ax
             mov bx, _bx
             mov cx, _cx
             mov dx, _dx
             mov es, _es
             mov di, _di
             mov save_bp, bp
             mov bp, _bp
         }

         /* Call the original interrupt. */
         (*oldvideo)();

         /* Make sure that any values returned in real registers by the
          * interrupt are updated in the parameter registers. Reset the flag.
          */
         _asm \
         {
             mov bp, save_bp
             mov _bp, bp
             mov _di, di
             mov _es, es
             mov _dx, dx
             mov _cx, cx
             mov _bx, bx
             mov _ax, ax
         }
         finvideo = FALSE;
     }
 }


 ANIMATE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\ANIMATE.C

 /* ANIMATE.C illustrates animation functions including:
  *          _imagesize     _getimage     _putimage
  */

 #include <conio.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <malloc.h>
 #include <graph.h>

 short action[5]  = { _GPSET,   _GPRESET, _GXOR,    _GOR,     _GAND    };
 char *descrip[5] = { "PSET  ", "PRESET", "XOR   ", "OR    ", "AND   " };

 main()
 {
     char far *buffer;
     short i, x, y = 30;
     size_t imsize;
     short mode = _VRES16COLOR;

     while( !_setvideomode( mode ) )         /* Find best graphics mode    */
         mode--;
     if (mode == _TEXTMONO )
         exit( 1 );                          /* No graphics available      */
     _setcolor( 3 );
     for ( i = 0; i < 5; i++ )
     {
         x = 50; y += 40;
         _settextposition( 1, 1 );           /* Display action type        */
         _outtext( descrip[i] );
                                             /* Draw and measure ellipse   */
         _ellipse( _GFILLINTERIOR, x - 15, y - 15, x + 15, y + 15 );
         imsize = (size_t)_imagesize( x - 16, y - 16, x + 16, y + 16 );
         buffer = (char far *)_fmalloc( imsize );
         if ( buffer == (char far *)NULL )
             exit( 1 );
                                             /* Get master copy of ellipse */
         _getimage( x - 16, y - 16, x + 16, y + 16, buffer );
         while( x < 260 )                    /* Copy row of ellipses       */
         {                                   /*   with specified action    */
             x += 5;
             _putimage( x - 16, y - 16, buffer, action[i] );
         }
         _ffree( (char far *)buffer );       /* Free memory                */
         getch();
     }
     exit( !_setvideomode( _DEFAULTMODE ) );
 }


 ARGS.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ARGS.C

 /* ARGS.C illustrates the following variables used for accessing
  * command-line arguments and environment variables:
  *      argc            argv            envp
  *
  * Also illustrates getting a process ID with:
  *      getpid
  */

 #include <stdio.h>
 #include <process.h>

 main( int argc,             /* Number of strings in array argv          */
       char *argv[],         /* Array of command-line argument strings   */
       char **envp )         /* Array of environment variable strings    */
 {
     int count;

     /* Display each command-line argument. */
     printf( "\nCommand-line arguments:\n" );
     for( count = 0; count < argc; count++ )
         printf( "  argv[%d]   %s\n", count, argv[count] );

     /* Display each environment variable. */
     printf( "\nEnvironment variables:\n" );
     while( *envp != NULL )
         printf( "  %s\n", *(envp++) );

     /* If run from DOS, shows different ID for DOS than for DOS shell.
      * If execed or spawned, shows ID of parent.
      */
     printf( "\nProcess id of parent: %d", getpid() );
     exit( 0 );
 }


 ARGV.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ARGV.C

 /* ARGV.C: Demonstrate accessing command-line arguments.
 */

 #include <stdio.h>

 void show_args( char *argument );

 int main( int argc, char *argv[] )
 {
    int count;
    for( count=0; count < argc; count++ )
       show_args( argv[count] );
    return 0;
 }

 void show_args( char *argument )
 {
    printf( "%s\n", argument );
 }


 ARGV1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ARGV1.C

 /* ARGV1.C: Demonstrate null pointers. */

 #include <stdio.h>

 void show_args( char *argument );

 int main( int argc, char **argv )
 {
    while( *argv )
       show_args( *(argv++) );
    return 0;
 }

 void show_args( char *argument )
 {
    printf( "%s\n", argument );
 }


 ARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ARRAY.C

 /* ARRAY.C: Demonstrate arrays. */

 #include <stdio.h>

 main()
 {
    int j, k;
    static int i_array[2][3] = { { 12, 2, 444 }, { 6, 55, 777 } };
    static char c_array[] = "Hello";

    printf( "--- Values --------     --- Addresses -------\n\n" );

    for( j = 0; j < 2; j = j + 1 )
    {
       for( k = 0; k < 3; k = k + 1 )
       {
          printf( "i_array[%d][%d] = %d", j, k, i_array[j][k] );
          printf( "\t&i_array[%d][%d] = %u\n", j, k, &i_array[j][k] );
       }
       printf( "\n" );
    }

    for( j = 0; j < 6; j = j + 1 )
    {
       printf( "c_array[%d]   = %x %c", j, c_array[j], c_array[j] );
       printf( "\t&c_array[%d]    = %u\n", j, &c_array[j] );
    }
 }


 ASSERT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ASSERT.C

 /* ASSERT.C illustrates function:
  *      assert
  */

 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #include <assert.h>

 #define MAXSTR 120

 void chkstr( char *string );    /* Prototype */

 main()
 {
     char string1[MAXSTR], string2[MAXSTR];

     /* Do various processes on strings and check the results. If
      * none cause errors, force on error with empty string.
      */
     printf( "Enter a string: " );
     gets( string1 );
     chkstr( string1 );

     printf( "Enter another string: " );
     gets( string2 );
     chkstr( string2 );

     strcat( string1, string2 );
     chkstr( string1 );
     printf( "string1 + string2 = %s\n", string1 );

     chkstr( "" );
     printf( "You'll never get here\n" );
 }

 void chkstr( char *string )
 {
     assert( string != NULL );               /* Cannot be NULL */
     assert( *string != '\0' );              /* Cannot be empty */
     assert( strlen( string ) < MAXSTR );    /* Length must be positive */
 }


 ATEXIT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ATEXIT.C

 /* ATEXIT.C illustrates:
  *      atexit          onexit
  */

 #include <stdlib.h>
 #include <stdio.h>
 ANSI                /* Comment out to try onexit     */

 /* Prototypes */
 void fn1( void ), fn2( void ), fn3( void ), fn4( void );

 main()
 {

     /* atexit is ANSI standard. It returns 0 for success, nonzero
      * for fail.
      */
 #ifdef ANSI
     atexit( fn1 );
     atexit( fn2 );
     atexit( fn3 );
     atexit( fn4 );

     /* onexit is Microsoft extension. It returns pointer to function
      * for success, NULL for fail.
      */
 #else
     onexit( fn1 );
     onexit( fn2 );
     onexit( fn3 );
     onexit( fn4 );
 #endif

     printf( "This is executed first.\n" );
 }

 void fn1()
 {
     printf( "next.\n" );
 }

 void fn2()
 {
     printf( "executed " );
 }

 void fn3()
 {
     printf( "is " );
 }

 void fn4()
 {
     printf( "This " );
 }


 ATONUM.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ATONUM.C

 /* ATONUM.C illustrates string to number conversion functions including:
  *      atof            atoi            atol            gcvt
  *
  * It also illustrates:
  *      cgets           cputs
  */

 #include <stdlib.h>
 #include <string.h>
 #include <conio.h>

 #define MAXSTR 100

 char cnumbuf[MAXSTR] = { MAXSTR + 2, 0 };
 numbuf cnumbuf + 2          /* Actual buffer starts at byte 3 */
 char tmpbuf[MAXSTR];

 /* Numeric input and output without printf. */
 main()
 {
     int     integer;
     long    longint;
     float   real;

     /* Using cgets (rather than gets) allows use of DOS editing keys
      * (or of editing keys from DOS command line editors).
      */
     cputs( "Enter an integer: " );
     cgets( cnumbuf );
     cputs( "\n\r" );                /* cputs doesn't translate \n     */
     integer = atoi( numbuf );
     strcpy( tmpbuf, numbuf );
     strcat( tmpbuf, " + " );

     cputs( "Enter a long integer: " );
     cgets( cnumbuf );
     cputs( "\n\r" );
     longint = atol( numbuf );
     strcat( tmpbuf, numbuf );
     strcat( tmpbuf, " + " );

     cputs( "Enter a floating point number: " );
     cgets( cnumbuf );
     cputs( "\n\r" );
     real = atof( numbuf );
     strcat( tmpbuf, numbuf );
     strcat( tmpbuf, " = " );

     gcvt( integer + longint + real, 4, numbuf );
     strcat( tmpbuf, numbuf );
     strcat( tmpbuf, "\n\r" );

     cputs( tmpbuf );
 }


 BADSEMI.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\BADSEMI.C

 /* BADSEMI.C: Misplaced semicolon. */

 #include <stdio.h>

 main()
 {
    int count;
    for( count = 0; count < 500; count++ ); /* Error! */
    {
       printf( "count = %d\n", count );
       printf( "And the beat goes on...\n" );
    }
 }


 BADSEMI1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\BADSEMI1.C

 /* BADSEMI1.C: Misplaced semicolon. */

 #include <stdio.h>

 main()
 {
    int count;
    for( count = 0; count < 500; count++ )
       ; /* Null statement */
    {
       printf( "count = %d\n", count );
       printf( "And the beat goes on...\n" );
    }
 }


 BEEP.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\UTILITY\BEEP.C

 /* BEEP.C illustrates timing and port input and output functions
  * including:
  *      inp             outp            clock
  * Also keyword:
  *      enum
  *
  * In addition to the delay use shown here, clock can be used as a
  * timer as shown in SIEVE.C.
  */

 #include <time.h>
 #include <conio.h>

 void beep( unsigned duration, unsigned frequency );
 void delay( clock_t wait );


 enum notes
 {   /* Enumeration of notes and frequencies     */
     C0 = 262, D0 = 296, E0 = 330, F0 = 349, G0 = 392, A0 = 440, B0 = 494,
     C1 = 523, D1 = 587, E1 = 659, F1 = 698, G1 = 784, A1 = 880, B1 = 988,
     EIGHTH = 125, QUARTER = 250, HALF = 500, WHOLE = 1000, END = 0
 } song[] =
 {   /* Array initialized to notes of song       */
     C1, HALF, G0, HALF, A0, HALF, E0, HALF, F0, HALF, E0, QUARTER,
     D0, QUARTER, C0, WHOLE, END
 };

 int main ()
 {
     int note = 0;

     while( song[note] )
         beep( song[note++], song[note++] );
 }

 /* beep - sounds the speaker for a time specified in microseconds by
  * duration at a pitch specified in hertz by frequency.
  */
 void beep( unsigned duration, unsigned frequency )
 {
     int control;

     /* If frequency is 0, beep doesn't try to make a sound. It
      * just sleeps for the duration.
      */
     if (frequency)
     {
         /* 75 is the shortest reliable duration of a sound. */
         if( duration < 75 )
             duration = 75;

         /* Prepare timer by sending 10111100 to port 43. */
         outp( 0x43, 0xb6 );

         /* Divide input frequency by timer ticks per second and
          * write (byte by byte) to timer.
          */
         frequency = (unsigned)(1193180L / frequency);
         outp( 0x42, (char)frequency );
         outp( 0x42, (char)(frequency >> 8) );

         /* Save speaker control byte. */
         control = inp( 0x61 );

         /* Turn on the speaker (with bits 0 and 1). */
         outp( 0x61, control | 0x3 );
     }

     delay( (clock_t)duration );

     /* Turn speaker back on if necessary. */
     if( frequency )
         outp( 0x61, control );
 }

 /* delay - Pauses for a specified number of microseconds. */
 void delay( clock_t wait )
 {
     clock_t goal;

     goal = wait + clock();
     while( goal > clock() )
         ;
 }


 BESSEL.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\BESSEL.C

 /* BESSEL.C illustrates Bessel functions including:
  *      j0          j1          jn          y0          y1          yn
  */

 #include <math.h>
 #include <stdio.h>

 main()
 {
     double x = 2.387;
     int n = 3, c;

     printf( "Bessel functions for x = %f:\n", x );
     printf( "  Kind\t\tOrder\t\Function\tResult\n\n" );
     printf( "  First\t\t0\tj0( x )\t\t%f\n", j0( x ) );
     printf( "  First\t\t1\tj1( x )\t\t%f\n", j1( x ) );
     for( c = 2; c < 10; c++ )
         printf( "  First\t\t%d\tjn( n, x )\t%f\n", c, jn( c, x ) );

     printf( "  Second\t0\ty0( x )\t\t%f\n", y0( x ) );
     printf( "  Second\t1\ty1( x )\t\t%f\n", y1( x ) );
     for( c = 2; c < 10; c++ )
         printf( "  Second\t%d\tyn( n, x )\t%f\n", c, yn( c, x ) );
 }


 BINTEXT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\BINTEXT.C

 /* BINTEXT.C illustrates changing between binary and text modes for
  * stream I/O using function:
  *      setmode
  * and global variable:
  *      _fmode
  */

 #include <stdio.h>
 #include <fcntl.h>
 #include <io.h>
 #include <string.h>
 <stdlib.h>         /* For _fmode and exit */

 main()
 {
     FILE *htmp;
     char name[13];

     /* Set default mode to binary and open file. */
     _fmode = O_BINARY;
     if( (htmp = fopen( tmpnam( name ), "w+" )) == NULL )
         exit( 1 );
     fprintf( htmp, "\nThis\nis\nsome\nbinary\ntext.\n\n" );

     /* Flush buffer and change mode to text. */
     fflush( htmp );
     setmode( fileno( htmp ), O_TEXT );
     fprintf( htmp, "\nThis\nis\nsome\ntext\ntext.\n\n" );
     fclose( htmp );

     system( strcat( "TYPE ", name ) );
     remove( name );
     exit( 0 );
 }


 BREAKER.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\BREAKER.C

 /* BREAKER.C: Demonstrate break statement. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press any key. Press TAB to quit.\n" );
    while( 1 )
    {
       ch = getche();
       if( ch == '\t' )
       {
          printf( "\a\nYou pressed TAB.\n" );
          break;
       }
    }
 }


 BREAKER1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\BREAKER1.C

 /* BREAKER1.C: Break only exits one loop. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    char ch;
    printf( "Press any key. Press RETURN to quit.\n" );
    do
    {
       while( ( ch = getche() ) != '\r' )
       {
          if( ch == '\t' )
          {
             printf( "\a\nYou pressed TAB.\n" );
             break;
          }
       }
    } while( ch != '\r' );
    printf( "\nBye bye." );
 }


 BUFTEST.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\BUFTEST.C

 /* BUFTEST.C illustrates buffer control for stream I/O using functions:
  *      setbuf              setvbuf
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #define BUF2SIZ 2048

 long countln( FILE *stream );           /* Prototype        */
 char buf1[BUFSIZ], buf2[BUF2SIZ];       /* File buffers     */

 main( int argc, char *argv[] )
 {
     time_t start;
     FILE *stream;
     int  c;

     /* Use our buffer with the default size. This gives us the option
      * of examining and/or modifying the buffer during I/0 (though the
      * example doesn't illustrate this).
      */
     if( (stream = fopen( argv[1], "rt" )) == NULL )
         exit( 1 );
     setbuf( stream, buf1 );
     start = clock();
     c = countln( stream );
     printf( "Time: %5.2f\tBuffering: Normal\tBuffer size: %d\n",
              ((float)clock() - start) / CLK_TCK, BUFSIZ );

     /* Use a larger buffer. */
     if( (stream = fopen( argv[1], "rt" )) == NULL )
         exit( 1 );
     setvbuf( stream, buf2, _IOFBF, sizeof( buf2 ) );
     start = clock();
     c = countln( stream );
     printf( "Time: %5.2f\tBuffering: Normal\tBuffer size: %d\n",
              ((float)clock() - start) / CLK_TCK, BUF2SIZ );

     /* Try it with no buffering. */
     if( (stream = fopen( argv[1], "rt" )) == NULL )
         exit( 1 );
     setvbuf( stream, NULL, _IONBF, 0 );
     start = clock();
     c = countln( stream );
     printf( "Time: %5.2f\tBuffering: Normal\tBuffer size: %d\n",
              ((float)clock() - start) / CLK_TCK, 0 );

     printf( "File %s has %d lines", argv[1], c );
     exit( 0 );
 }

 /* Count lines in text files and close file. */
 long countln( FILE *stream )
 {
     char linebuf[120];
     long c = 0;

     while( !feof( stream ) )
     {
         fgets( linebuf, 121, stream );
         ++c;
     }
     fclose( stream );
     return c;
 }


 CABS.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MATH\CABS.C

 /* CABS.C illustrates functions:
  *      cabs            hypot
  */

 #include <math.h>
 #include <stdio.h>

 main()
 {
     static struct complex ne = {  3.0,  4.0 }, se = { -3.0, -4.0 },
                           sw = { -3.0, -4.0 }, nw = { -3.0,  4.0 };

     printf( "Absolute %4.1lf + %4.1lfi:\t\t%4.1f\n",
             ne.x, ne.y, cabs( ne ) );
     printf( "Absolute %4.1lf + %4.1lfi:\t\t%4.1f\n",
             sw.x, sw.y, cabs( sw ) );

     printf( "Hypotenuse of %4.1lf and %4.1lf:\t%4.1f\n",
             se.x, se.y, hypot( se.x, se.y ) );
     printf( "Hypotenuse of %4.1lf and %4.1lf:\t%4.1f\n",
             nw.x, nw.y, hypot( nw.x, nw.y ) );
 }
 


 CASE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\CASE.C

 /* CASE.C illustrates case conversion and other conversions.
  * Functions illustrated include:
  *      strupr          toupper         _toupper
  *      strlwr          tolower         _tolower
  *      strrev          toascii
  */

 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>

 char mstring[] = "Dog Saw Dad Live On";
 char *ustring, *tstring, *estring;
 char *p;

 main()
 {
     printf( "Original:\t%s\n", mstring );

     /* Upper and lower case. */
     ustring = strupr( strdup( mstring ) );
     printf( "Upper case:\t%s\n", ustring );

     printf( "Lower case:\t%s\n", strlwr( ustring ) );

     /* Reverse case of each character. */
     tstring = strdup( mstring );
     for( p = tstring; *p; p++ )
     {
         if( isupper( *p ) )
             *p = tolower( *p );
         else
             *p = toupper( *p );

         /* This alternate code (commented out) shows how to use _tolower
          * and _toupper for the same purpose.
         if( isupper( *p ) )
             *p = _tolower( *p );
         else if( islower( *p ) )
             *p = _toupper( *p );
          */
     }
     printf( "Toggle case:\t%s\n", tstring );

     /* Encode and decode string. The decoding technique will convert
      * WordStar-style strings, which have some high bits set.
      */
     estring = strdup( mstring );
     for( p = estring; *p; p++ )
         *p = *p | 0x80;
     printf( "Encoded:\t%s\n", estring );

     for( p = estring; *p; p++ )
         *p = toascii( *p );
     printf( "Decoded:\t%s\n", estring );

     printf( "Reversed:\t%s\n", strrev( ustring ) );
 }


 CGA.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\CGA.C

 /* CGA.C: Demonstrates CGA colors */
 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>

 long bkcolor[8] =
    {_BLACK, _BLUE, _GREEN, _CYAN,
     _RED, _MAGENTA, _BROWN, _WHITE};

 char *bkcolor_name [] =
    {"_BLACK", "_BLUE", "_GREEN", "_CYAN",
    "_RED", "_MAGENTA", "_BROWN", "_WHITE"};

 main()
 {
    int i, j, k;
    _setvideomode( _MRES4COLOR );
    for( i=0; i<= 3; i++ )
    {
       _selectpalette( i );
       for( k=0; k <= 7; k++ )
       {
          _setbkcolor( bkcolor[k] );
          for( j=0; j<=3; j++ )
          {
             _settextposition( 1, 1 );
             printf( "background color: %8s\n", bkcolor_name[k] );
             printf( "palette: %d\ncolor: %d\n", i, j );
             _setcolor( j );
             _rectangle( _GFILLINTERIOR, 160, 100, 320, 200 );
                getch();
          }
       }
    }
    _setvideomode( _DEFAULTMODE );
 }


 CGAPAL.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\CGAPAL.C

 /* CGAPAL.C illustrates CGA palettes using:
  *      _selectpalette
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <graph.h>

 long bkcolor[8] = { _BLACK,  _BLUE,     _GREEN,  _CYAN,
                     _RED,    _MAGENTA,  _BROWN,  _WHITE };
 char *bkname [] = { "BLACK", "BLUE",    "GREEN", "CYAN",
                     "RED",   "MAGENTA", "BROWN", "WHITE" };
 main()
 {
     int i, j, k;

     if ( !_setvideomode( _MRES4COLOR ) )
         exit( 1 );
     for( i = 0; i < 4; i++ )
     {
         _selectpalette( i );
         for( k = 0; k < 8; k++ )
         {
             _setbkcolor( bkcolor[k] );
             for( j = 0; j < 4; j++ )
             {
                 _settextposition( 1, 1 );
                 printf( "Background color: %8s\n", bkname[k] );
                 printf( "Palette: %d\nColor: %d\n", i, j );
                 _setcolor( j );
                 _rectangle( _GFILLINTERIOR, 160, 100, 320, 200 );
                 getch();
             }
         }
     }
     exit( !_setvideomode( _DEFAULTMODE ) );
 }


 CHMOD1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\CHMOD1.C

 /* CHMOD1.C illustrates reading and changing file attribute and time using:
  *      access          chmod           utime
  *
  * See CHMOD2.C for a more powerful variation of this program using
  * _dos functions.
  */

 #include <io.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <sys\utime.h>
 #include <stdio.h>
 #include <conio.h>
 #include <stdlib.h>

 enum FILEATTRIB { EXIST, WRITE = 2, READ = 4, READWRITE = 6 };

 /* Exist macro uses access */
 #define EXIST( name ) !access( name, EXIST )

 main( int argc, char *argv[] )
 {
     if( !EXIST( argv[1] ) )
     {
         printf( "Syntax:  CHMOD1 <filename>" );
         exit( 1 );
     }

     if( !access( argv[1], WRITE ) )
     {
         printf( "File %s is read/write. Change to read only? ", argv[1] );

         /* Note: Use stdlib.h for function definition of toupper rather
          * than macro version in ctype.h. Macro side effects would cause
          * macro version to read two keys.
          */
         if( toupper( getch() ) == 'Y' )
             chmod( argv[1], S_IREAD );
     }
     else
     {
         printf( "File %s is read only. Change to read/write? ", argv[1] );
         if( toupper( getch() ) == 'Y' )
             chmod( argv[1], S_IREAD | S_IWRITE );
     }

     printf( "\nUpdate file time to current time? " );
     if( toupper( getch() ) == 'Y' )
         utime( argv[1], NULL );
     exit( 0 );
 }


 CHMOD2.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\CHMOD2.C

 /* CHMOD2.C illustrates reading and changing file attributes and file
  * time using:
  *      _dos_getftime       _dos_setftime
  *      _dos_getfileattr    _dos_setfileattr
  *
  * See CHMOD1.C for a simpler variation of this program using the utime,
  * access, and chmod functions.
  */

 #include <dos.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <conio.h>
 #include <stdlib.h>
 #include <sys\types.h>
 #include <sys\stat.h>

 char *datestr( unsigned d, char *buf );     /* Prototypes */
 char *timestr( unsigned t, char *buf );

 main( int argc, char *argv[] )
 {
     unsigned fdate, ftime, fattr;
     struct dosdate_t ddate;
     struct dostime_t dtime;
     int hsource;
     char timebuf[10], datebuf[10], *pkind;

     /* Open to get file handle and test for errors (such as nonexistence). */
     if( _dos_open( argv[1], O_RDONLY, &hsource ) )
     {
         printf( "Can't open file\n" );
         exit( 1 );
     }

     /* Get time, date, and attribute of file. */
     _dos_getftime( hsource, &fdate, &ftime );
     _dos_getfileattr( argv[1], &fattr );

     /* Convert information into formatted strings. */
     datestr( fdate, datebuf );
     timestr( ftime, timebuf );

     if( fattr & _A_SUBDIR )
         pkind = "Directory";
     else if( fattr & _A_VOLID )
         pkind = "Label";
     else
         pkind = "File";

     printf( "%-12s   %-8s   %-9s   %-9s    %s %s %s\n",
             "FILE", "TIME", "DATE", "KIND", "RDO", "HID", "SYS" );
     printf( "%-12s   %8s   %8s    %-9s     %c   %c   %c\n",
             argv[1], timebuf, datebuf, pkind,
             (fattr & _A_RDONLY) ? 'Y' : 'N',
             (fattr & _A_HIDDEN) ? 'Y' : 'N',
             (fattr & _A_SYSTEM) ? 'Y' : 'N' );

     /* Update file time or attribute. */
     printf( "Change: (T)ime  (R)ead only  (H)idden  (S)ystem\n" );
     switch( toupper( getch() ) )    /* Use stdlib.h, not ctype.h */
     {
         case 'T':               /* Set to current time */
             _dos_gettime( &dtime );
             _dos_getdate( &ddate );
             ftime = (dtime.hour << 11) | (dtime.minute << 5);
             fdate = ((ddate.year - 1980) << 9) | (ddate.month << 5) |
                       ddate.day;
             _dos_setftime( hsource, fdate, ftime );
             break;
         case 'R':               /* Toggle read only */
             _dos_setfileattr( argv[1], fattr ^ _A_RDONLY );
             break;
         case 'H':               /* Toggle hidden    */
             _dos_setfileattr( argv[1], fattr ^ _A_HIDDEN );
             break;
         case 'S':               /* Toggle system    */
             _dos_setfileattr( argv[1], fattr ^ _A_SYSTEM );
             break;
     }
     _dos_close( hsource );
     exit( 1 );
 }

 /* Take unsigned time in the format:                fedcba9876543210
  * s=2 sec incr, m=0-59, h=23                       hhhhhmmmmmmsssss
  * Change to a 9-byte string (ignore seconds):      hh:mm ?m
  */
 char *timestr( unsigned t, char *buf )
 {
     int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;

     sprintf( buf, "%2.2d:%02.2d %cm", h % 12, m,  h > 11 ? 'p' : 'a' );
     return buf;
 }

 /* Take unsigned date in the format:    fedcba9876543210
  * d=1-31, m=1-12, y=0-119 (1980-2099)  yyyyyyymmmmddddd
  * Change to a 9-byte string:           mm/dd/yy
  */
 char *datestr( unsigned d, char *buf )
 {
     sprintf( buf, "%2.2d/%02.2d/%02.2d",
              (d >> 5) & 0x0f, d & 0x1f, (d >> 9) + 80 );
     return buf;
 }


 CMPSTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\CMPSTR.C

 /* CMPSTR.C illustrates string and memory comparison functions including:
  *       memcmp        memicmp
  *       strncmp       strnicmp
  *       strcmp        stricmp          strcmpi
  */

 #include <memory.h>
 #include <string.h>
 #include <stdio.h>

 char string1[] = "The quick brown dog jumps over the lazy fox";
 char string2[] = "The QUICK brown fox jumps over the lazy dog";

 main()
 {
     char tmp[20];
     int result;

     printf( "Compare strings:\n\t\t%s\n\t\t%s\n\n", string1, string2 );

     printf( "Function:\tmemcmp\n" );
     result = memcmp( string1, string2 , 42 );
     if( result > 0 )
         strcpy( tmp, "greater than" );
     else if( result < 0 )
         strcpy( tmp, "less than" );
     else
         strcpy( tmp, "equal to" );
     printf( "Result:\t\tString 1 is %s than string 2\n\n", tmp );

     printf( "Function:\tmemicmp\n" );
     result = memicmp( string1, string2, 42 );
     if( result > 0 )
         strcpy( tmp, "greater than" );
     else if( result < 0 )
         strcpy( tmp, "less than" );
     else
         strcpy( tmp, "equal to" );
     printf( "Result:\t\tString 1 is %s than string 2\n\n", tmp );

     printf( "Function:\tstrncmp\n" );
     result = strncmp( string1, string2 , 42 );
     if( result > 0 )
         strcpy( tmp, "greater than" );
     else if( result < 0 )
         strcpy( tmp, "less than" );
     else
         strcpy( tmp, "equal to" );
     printf( "Result:\t\tString 1 is %s than string 2\n\n", tmp );

     printf( "Function:\tstrnicmp\n" );
     result = strnicmp( string1, string2, 42 );
     if( result > 0 )
         strcpy( tmp, "greater than" );
     else if( result < 0 )
         strcpy( tmp, "less than" );
     else
         strcpy( tmp, "equal to" );
     printf( "Result:\t\tString 1 is %s than string 2\n\n", tmp );

     printf( "Function:\tstrcmp\n" );
     result = strcmp( string1, string2 );
     if( result > 0 )
         strcpy( tmp, "greater than" );
     else if( result < 0 )
         strcpy( tmp, "less than" );
     else
         strcpy( tmp, "equal to" );
     printf( "Result:\t\tString 1 is %s than string 2\n\n", tmp );

     printf( "Function:\tstricmp or strcmpi\n" );
     result = stricmp( string1, string2 );
     /* strcmpi (commented out) is the same as stricmp.
     result = strcmpi( string1, string2 );
      */
     if( result > 0 )
         strcpy( tmp, "greater than" );
     else if( result < 0 )
         strcpy( tmp, "less than" );
     else
         strcpy( tmp, "equal to" );
     printf( "Result:\t\tString 1 is %s than string 2\n", tmp );
 }


 COLOR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\COLOR.C

  /* COLOR.C: Sets a medium resolution mode with maximum color choices */

 #include <stdio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <conio.h>
 struct videoconfig vc;

 main()
 {
    if( _setvideomode( _MRES256COLOR ) )
       ;
    else if( _setvideomode( _MRES16COLOR ) )
       ;
    else if( _setvideomode( _MRES4COLOR ) )
       ;
    else   {
       printf( "Error: No color graphics capability\n" );
       exit( 0 );
    }

    _getvideoconfig( &vc );

    printf( "%d available colors\n", vc.numcolors );
    printf( "%d horizontal pixels\n", vc.numxpixels );
    printf( "%d vertical pixels\n", vc.numypixels );

    getch();
    _clearscreen( _GCLEARSCREEN );
    _setvideomode( _DEFAULTMODE );
 }


 COLTEXT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\COLTEXT.C

 /* COLTEXT.C: Displays text in color */
 #include <stdio.h>
 #include <conio.h>
 #include <graph.h>

 char buffer [80];

 main()
 {
    int blink,fgd;
    long bgd;

    _clearscreen( _GCLEARSCREEN );
    printf( "Text color attributes:\n" );

    for( blink=0; blink<=16; blink+=16 )
    {
       for( bgd=0; bgd<8; bgd++ )
       {
          _setbkcolor( bgd );
          _settextposition( bgd + ((blink / 16) * 9) + 3, 1 );
          _settextcolor( 7 );
          sprintf( buffer, "Bgd: %d Fgd:", bgd );
          _outtext( buffer );

          for( fgd=0; fgd<16; fgd++ )
          {
             _settextcolor( fgd+blink );
             sprintf( buffer, " %2d ", fgd+blink );
             _outtext( buffer );
          }
       }
    }
    getch();
    _setvideomode( _DEFAULTMODE );
 }


 COM.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\COM.C

 /* COM.C illustrates serial port access using function:
  *      _bios_serialcom
  */

 #include <bios.h>
 #include <stdio.h>

 main()
 {
     unsigned status, port;

     for( port = 0; port < 3; port++ )
     {
         status = _bios_serialcom( _COM_STATUS, port, 0 );

         /* Report status of each serial port and test whether there is a
          * modem for each. If data-set-ready and clear-to-send, modem exists.
          */
         printf( "COM%c status: %.4X\tModem: %s\n",
                 (char)port + '1', status,
                 (status & 0x0030) ? "YES" : "NO" );
     }
 }


 COMMA.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\COMMA.C

 /* COMMA.C: Demonstrate comma operator. */

 #include <stdio.h>

 main()
 {
    int val = 5, val1 = 666, temp;
    temp = val, val = val1, val1 = temp;
    printf( "val = %d  val1 = %d\n", val, val1 );
 }


 CONT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\CONT.C

 /* CONT.C: Demonstrate continue statement. */

 #include <stdio.h>

 main()
 {
    int count;
    for( count = 0; count < 10; count++ )
    {
       if( count > 3 )
          continue;
       printf( "count = %d\n", count );
    }
    printf( "Done!\n" );
 }


 CONT1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\CONT1.C

 /* CONT1.C: Demonstrate alternative to continue. */

 #include <stdio.h>

 main()
 {
    int count;
    for( count = 0; count < 10; count++ )
    {
       if( count < 4 )
          printf( "count = %d\n", count );
    }
    printf( "Done!\n" );
 }


 CONVERT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\CONVERT.C

 /* CONVERT.C: Demonstrate type conversions. */

 #include <stdio.h>

 main()
 {
    char c_val = 10;
    int i_val = 20;
    long l_val = 64000;
    float f_val = 3.1;
    int result;

    result = c_val + i_val + l_val + f_val;  /* Error! */

    printf( "%d\n", result );
 }


 COPROC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MATH\COPROC.C

 /* COPROC.C illustrates use of the status and control words of a floating
  * point coprocessor (or emulator). Functions illustrated include:
  *      _clear87            _status87           _control87
  */

 #include <stdio.h>
 #include <conio.h>
 #include <float.h>
 #include <stdlib.h>
 #include <string.h>

 double dx = 1e-40, dy;
 float fx, fy;
 unsigned status, control;
 char tmpstr[20];
 char *binstr( int num, char *buffer );

 main()
 {
     printf( "Status Word Key:\n" );
     printf( "B\tBusy flag\n0-3\tCondition codes\nS\tStack top pointer\n" );
     printf( "E\tError summary\nF\tStack flag\nP\tPrecision exception\n" );
     printf( "U\tUnderflow exception\nO\tOverflow exception\n" );
     printf( "Z\tZero divide exception\nD\tDenormalized exception\n" );
     printf( "I\tInvalid operation exception\n\n" );

     binstr(  _clear87(), tmpstr );
     printf( "B3SSS210EFPUOZDI  Function\tCondition\n\n" );
     printf( "%16s  _clear87\tAfter clearing\n", tmpstr );

     /* Storing double to float that hasn't enough precision for it
      * causes underflow and precision exceptions.
      */
     fx = dx;
     binstr(  _status87(), tmpstr );
     printf( "%16s  _status87\tAfter moving double to float\n", tmpstr );

     /* Storing float with lost precision back to double adds denormalized
      * exception (previous exceptions remain).
      */
     dy = fx;
     binstr(  _clear87(), tmpstr );
     printf( "%16s  _clear87\tAfter moving float to double\n", tmpstr );

     /* Using clear87() erases previous exceptions. */
     fy = dy;
     binstr(  _status87(), tmpstr );
     printf( "%16s  _status87\tAfter moving double to float\n\n", tmpstr );

     getch();
     printf( "Control Word Key:\n" );
     printf( "i\tInfinity control\nr\tRounding control\n" );
     printf( "p\tPrecision control\ne\tInterrupt enable mask\n" );
     printf( "U\tUnderflow mask\nO\tOverflow mask\n" );
     printf( "Z\tZero divide mask\nD\tDenormalized mask\n" );
     printf( "I\tInvalid operation mask\n\n" );
     printf( "???irrppe?PUOZDI  Result\n" );
     fy = .1;

     /* Show current control word. */
     binstr( _control87( 0, 0 ), tmpstr );
     printf( "%16s  %.1f * %.1f = %.15e with initial precision\n",
             tmpstr, fy, fy, fy * fy );

     /* Set precision to 24 bits. */
     binstr( _control87( PC_24, MCW_PC ), tmpstr );
     printf( "%16s  %.1f * %.1f = %.15e with 24 bit precision\n",
             tmpstr, fy, fy, fy * fy );

     /* Restore default. */
     binstr( _control87( CW_DEFAULT, 0xffff ), tmpstr );
     printf( "%16s  %.1f * %.1f = %.15e with default precision\n",
             tmpstr, fy, fy, fy * fy );
 }

 /* Convert integer to string of 16 binary characters. */
 char *binstr( int num, char *buffer )
 {
     char tmp[17];
     int  len;

     memset( buffer, '0', 16 );
     len = strlen( itoa( num, tmp, 2 ) );
     strcpy( buffer + 16 - len, tmp );
     return buffer;
 }


 COPY2.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\COPY2.C

 /* COPY2.C illustrates DOS file I/O and DOS memory allocation functions
  * including:
  *      _dos_open       _dos_close      _dos_creatnew   _dos_creat
  *      _dos_read       _dos_write      _dos_allocmem   _dos_free
  *
  * See COPY1.C for another version of the copyfile function.
  */

 #include <dos.h>
 #include <fcntl.h>
 #include <conio.h>
 #include <stdio.h>

 int copyfile( char *source, char *destin );     /* Prototype */

 main( int argc, char *argv[] )
 {
     if( argc == 3 )
         if( copyfile( argv[1], argv[2] ) )
             printf( "Copy failed\n" );
         else
             printf( "Copy successful\n" );
     else
         printf( "  SYNTAX: COPY2 <source> <target>\n" );
 }

 /* Function to copy one file to another (both specified by path).
  * Dynamically allocates memory for the file buffer. Prompts before
  * overwriting existing file. Returns 0 if successful, or an error
  * number if unsuccessful. This function uses dos functions only; no
  * standard C library functions are used.
  */
 #define EXIST 80
 enum ATTRIB { NORMAL, RDONLY, HIDDEN, SYSTEM = 4 };
 int copyfile( char *source, char *target )
 {
     char far *buf = NULL;
     static char prompt[] = "Target exists. Overwrite? ", newline[] = "\n\r";
     int hsource, htarget, ch;
     unsigned ret, segbuf, count;

     /* Attempt to dynamically allocate all of memory (0xffff paragraphs).
      * This will fail, but will return the amount actually available
      * in segbuf. Then allocate this amount.
      */
     _dos_allocmem( 0xffff, &segbuf );
     count = segbuf;
     if( ret = _dos_allocmem( count, &segbuf ) )
         return ret;
     FP_SEG( buf ) = segbuf;

     /* Open source file and create target, overwriting if necessary. */
     if( ret = _dos_open( source, O_RDONLY, &hsource ) )
         return ret;
     ret = _dos_creatnew( target, NORMAL, &htarget );
     if( ret == EXIST )
     {
         /* Use _dos_write to display prompts. Use bdos to call
          * function 1 to get and echo keystroke.
          */
         _dos_write( 1, prompt, sizeof( prompt ) - 1, &ch );
         ch = bdos( 1, 0, 0 ) & 0x00ff;
         if( (ch == 'y') || (ch == 'Y') )
             ret = _dos_creat( target, NORMAL, &htarget );
         _dos_write( 1, newline, sizeof( newline ) - 1, &ch );
     }
     if( ret )
         return ret;

     /* Read and write until there is nothing left. */
     while( count )
     {
         /* Read and write input. */
         if( (ret = _dos_read( hsource, buf, count, &count )) )
             return ret;
         if( (ret = _dos_write( htarget, buf, count, &count )) )
             return ret;
     }

     /* Close files and free memory. */
     _dos_close( hsource );
     _dos_close( htarget );
     _dos_freemem( segbuf );
     return 0;
 }
 


 CPYSTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\CPYSTR.C

 /* CPYSTR.C illustrate memory and string copy and move functions including:
  *      memccpy         memcpy          memmove
  *      strncpy         strcpy          strdup          strlen
  */

 #include <memory.h>
 #include <string.h>
 #include <stdio.h>
 #include <conio.h>
 #include <dos.h>

 char string1[60] = "The quick brown dog jumps over the lazy fox";
 char string2[60] = "The quick brown fox jumps over the lazy dog";
 /*                           1         2         3         4         5 *
  *                  12345678901234567890123456789012345678901234567890 */
 main()
 {
     char buffer[61];
     char *pdest, *newstring;
     int  pos;

     printf( "Function:\tmemccpy 60 characters or to character 's'\n" );
     printf( "Source:\t\t%s\n", string1 );
     pdest = memccpy( buffer, string1, 's', 60 );
     *pdest = '\0';
     printf( "Result:\t\t%s\n", buffer );
     printf( "Length:\t\t%d characters\n\n", strlen( buffer ) );

     pos = pdest - buffer;
     printf( "Function:\tstrcpy\n" );
     printf( "Source:\t\t%s\n", string2 + pos );
     pdest = strcpy( buffer + pos, string2 + pos );
     printf( "Result:\t\t%s\n", buffer );
     printf( "Length:\t\t%d characters\n\n", strlen( buffer ) );

     printf( "Function:\tmemcpy 20 characters\n" );
     printf( "Source:\t\t%s\n", string2 );
     memcpy( buffer, string2, 20 );
     printf( "Result:\t\t%s\n", buffer );
     printf( "Length:\t\t%d characters\n\n", strlen( buffer ) );

     printf( "Function:\tstrncpy 30 characters\n" );
     printf( "Source:\t\t%s\n", string1 + 20 );
     pdest = strncpy( buffer + 20, string1 + 20, 30 );
     printf( "Result:\t\t%s\n", buffer );
     printf( "Length:\t\t%d characters\n\n", strlen( buffer ) );

     getch();

     printf( "Function:\tstrdup\n" );
     printf( "Source:\t\t%s\n", buffer );
     newstring = strdup( buffer );
     printf( "Result:\t\t%s\n", newstring );
     printf( "Length:\t\t%d characters\n\n", strlen( newstring ) );

     /* Illustrate overlapping copy: memmove handles it correctly;
      * memcpy does not.
      */
     printf( "Function:\tmemcpy with overlap\n" );
     printf( "Source:\t\t%s\n", string1 + 4 );
     printf( "Destination:\t%s\n", string1 + 10 );
     memcpy( string1 + 10, string1 + 4, 40 );
     printf( "Result:\t\t%s\n", string1 );
     printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );

     printf( "Function:\tmemmove with overlap\n" );
     printf( "Source:\t\t%s\n", string2 + 4 );
     printf( "Destination:\t%s\n", string2 + 10 );
     memmove( string2 + 10, string2 + 4, 40 );
     printf( "Result:\t\t%s\n", string2 );
     printf( "Length:\t\t%d characters\n\n", strlen( string2 ) );
 }


 DECRMENT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\DECRMENT.C

 /* DECRMENT.C: Demonstrate prefix and postfix operators.
 */

 #include <stdio.h>
 main()
 {
    int val, sample = 3, proton = 3;
    val = sample--;
    printf( "val = %d  sample = %d\n", val, sample );
    val = --proton;
    printf( "val = %d  proton = %d\n", val, proton );
 }


 DIRECT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\DIRECT.C

 /* DIRECT.C illustrates directory functions and miscellaneous file
  * and other functions including:
  *      getcwd          mkdir           chdir           rmdir
  *      system          mktemp          remove          unlink
  *      stat
  *
  * See NULLFILE.C for an example of fstat, which is similar to stat.
  */

 #include <direct.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <conio.h>
 #include <io.h>
 #include <time.h>
 #include <sys/types.h>
 #include <sys/stat.h>

 main()
 {
     char cwd[_MAX_DIR];
     static char tmpdir[] = "DRXXXXXX";
     struct stat filestat;

     /* Get the current working directory. */
     getcwd( cwd, _MAX_DIR );

     /* Try to make temporary name for directory. */
     if( mktemp( tmpdir ) == NULL )
     {
         perror( "Can't make temporary directory" );
         exit( 1 );
     }

     /* Try to create a new directory, and if successful, change to it. */
     if( !mkdir( tmpdir ) )
     {
         chdir( tmpdir );

         /* Create and display a file to prove it. */
         system( "echo This is a test. > TEST.TXT" );
         system( "type test.txt" );

         /* Display some file statistics. */
         if( !stat( "TEST.TXT", &filestat ) )
         {
             printf( "File: TEST.TXT\n" );
             printf( "Drive %c:\n", filestat.st_dev + 'A' );
             printf( "Directory: %s\\%s\n", cwd + 2, tmpdir );
             printf( "Size: %ld\n", filestat.st_size );
             printf( "Created: %s", ctime( &filestat.st_atime ) );
         }
         getch();

         /* Delete file, go back to original directory, and remove
          * directory. Note that under DOS, remove is equivalent to unlink,
          * so this line could be used instead.
         unlink( "TEST.TXT" );
          */
         remove( "TEST.TXT" );
         chdir( cwd );
         rmdir( tmpdir );
     }
 }


 DISK.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\DISK.C

 /* DISK.C illustrates low-level disk access using functions:
  *      _bios_disk          _dos_getdiskfree
  */

 #include <stdio.h>
 #include <conio.h>
 #include <bios.h>
 #include <dos.h>
 #include <stdlib.h>

 char far diskbuf[512];

 main( int argc, char *argv[] )
 {
     unsigned status = 0, i;
     struct diskinfo_t di;
     struct diskfree_t df;
     unsigned char far *p, linebuf[17];

     if( argc != 5 )
     {
         printf( "  SYNTAX: DISK <driveletter> <head> <track> <sector>" );
         exit( 1 );
     }

     if( (di.drive = toupper( argv[1][0] ) - 'A' ) > 1 )
     {
         printf( "Must be floppy drive" );
         exit( 1 );
     }
     di.head     = atoi( argv[2] );
     di.track    = atoi( argv[3] );
     di.sector   = atoi( argv[4] );
     di.nsectors = 1;
     di.buffer   = diskbuf;

     /* Get information about disk size. */
     if( _dos_getdiskfree( di.drive + 1, &df ) )
         exit( 1 );

     /* Try reading disk three times before giving up. */
     for( i = 0; i < 3; i++ )
     {
         status = _bios_disk( _DISK_READ, &di ) >> 8;
         if( !status )
             break;
     }

     /* Display one sector. */
     if( status )
         printf( "Error: 0x%.2x\n", status );
     else
     {
         for( p = diskbuf, i = 0; p < (diskbuf + df.bytes_per_sector); p++ )
         {
             linebuf[i++] = (*p > 32) ? *p : '.';
             printf( "%.2x ", *p );
             if( i == 16 )
             {
                 linebuf[i] = '\0';
                 printf( " %16s\n", linebuf );
                 i = 0;
             }
         }
     }
     exit( 1 );
 }


 DO.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\DO.C

 /* DO.C: Demonstrate do loop. */

 #include <stdio.h>

 main()
 {
    int test = 10;
    do
    {
       printf( "test = %d\n", test );
       test -= 2;
    }  while( test > 0 );
 }


 DOSMEM.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\DOSMEM.C

 /* DOSMEM.C illustrates functions:
  *      _dos_allocmem       _dos_setblock       _dos_freemem
  *
  * See COPY2.C for another example of _dos_allocmem and _dos_freemem.
  */

 #include <dos.h>
 #include <stdio.h>
 #include <stdlib.h>

 main()
 {
     char far *buf = NULL, far *p;
     unsigned segbuf, maxbuf, size = 512;

     /* Allocate 512-byte buffer. Convert the size to paragraphs).
      * Assign the segment to the buffer. Fill with A's.
      */
     if( _dos_allocmem( size >> 4, &segbuf ) )
         exit( 1 );
     FP_SEG( buf ) = segbuf;
     for( p = buf; p < (buf + size); p++ )
         *p = 'A';

     /* Double the allocation. Fill the second half with B's. */
     size *= 2;
     if( _dos_setblock( size >> 4, segbuf, &maxbuf ) )
         exit( 1 );
     FP_SEG( buf ) = segbuf;
     for( p = buf + (size / 2); p < (buf + size); p++ )
         *p = 'B';
     *(--p) = '\0';

     printf( "Memory available: %u paragraphs\n", maxbuf );
     printf( "Buffer at %Fp contains:\n%Fs", (int far *)buf, buf );

     /* Free memory */
     exit( !_dos_freemem( segbuf ) );
 }


 EGA.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\EGA.C

 /* EGA.C: Demonstrates EGA palettes */
 #include <stdio.h>
 #include <conio.h>
 #include <graph.h>

 main()
 {
    _setvideomode( _ERESCOLOR );
    _setcolor( 4 );
    _rectangle( _GFILLINTERIOR, 50, 50, 200, 200 );

    _settextposition( 1, 1 );
    printf( "Normal palette\n" );
    printf( "Press a key" );
    getch();

    _remappalette( 4, _BLUE );

    _settextposition( 1, 1 );
    printf( "Remapped palette\n" );
    printf( "Press a key" );
    getch();

    _remappalette( 4, _RED );

    _settextposition( 1, 1 );
    printf( "Restored palette\n" );
    printf( "Press a key to clear the screen" );
    getch();

    _clearscreen( _GCLEARSCREEN );
    _setvideomode( _DEFAULTMODE );
 }


 ELSE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ELSE.C

 /* ELSE.C: Demonstrate else clause. */

 #include <stdio.h>
 #include <conio.h>
 #define  B_KEY  'b'

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getch();
    if( ch == B_KEY )
       printf( "Beep!\a\n" );
    else
       printf( "Bye bye.\n" );
 }


 ELSE1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ELSE1.C

 /* ELSE1.C: Demonstrate else-if construct. */

 #include <stdio.h>
 #include <conio.h>
 #define  B_KEY  'b'
 #define  ENTER_KEY '\r'

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getch();
    if( ch == B_KEY )
       printf( "Beep!\a\n" );
    else
       if( ch == ENTER_KEY )
          printf( "What a boring selection...\n" );
    else
       printf( "Bye bye.\n" );
 }


 EMPLOY1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\EMPLOY1.C

 /* EMPLOY1.C: Demonstrate structure pointers. */

 #include <stdio.h>


 struct employee
 {
    char name[10];
    int months;
    float wage;
 };

 void display( struct employee *e_ptr  );

 main()
 {
    static struct employee jones =
       {
       "Jones, J",
       77,
       13.68
       };

    display( &jones );
 }

 void display( struct employee *e_ptr )
 {
    printf( "Name: %s\n", e_ptr->name );
    printf( "Months of service: %d\n", e_ptr->months );
    printf( "Hourly wage: %6.2f\n", e_ptr->wage );
 }


 EMPLOYEE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\EMPLOYEE.C

 /* EMPLOYEE.C: Demonstrate structures. */

 #include <stdio.h>
 #include <string.h>

 struct employee
 {
    char name[10];
    int months;
    float wage;
 };

 void display( struct employee show );

 main()
 {
    struct employee jones;

    strcpy( jones.name, "Jones, J" );
    jones.months = 77;
    jones.wage = 13.68;

    display( jones );
 }

 void display( struct employee show )
 {
    printf( "Name: %s\n", show.name );
    printf( "Months of service: %d\n", show.months );
    printf( "Hourly wage: %6.2f\n", show.wage );
 }


 ENVIRON1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ENVIRON1.C

 /* ENVIRON.C illustrates environment variable functions including:
  *      getenv          putenv          _searchenv
  */

 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>

 main()
 {
     char *pathvar, pathbuf[128], filebuf[128];

     /* Get the PATH environment variable and save a copy of it. */
     pathvar = getenv( "PATH" );
     strcpy( pathbuf, pathvar );
     printf( "Old PATH: %s\n", pathvar ? pathvar : "variable not set");

     /* Add a new directory to the path. */
     strcat( pathbuf, ";\\QC;" );
     if( putenv( pathbuf ) == -1 )
     {
         printf( "Failed\n");
         return 1;
     }
     else
         printf( "New PATH: %s\n", pathbuf );

     /* Search for file in the new path. */
     _searchenv( "QC.INI", "PATH", filebuf );
     if( *filebuf )
         printf( "QC.INI found at %s\n", filebuf );
     else
         printf( "QC.INI not found\n" );

     /* Restore original path. */
     if( putenv( pathvar ) == -1 )
         printf( "Failed\n");
     else
         printf( "Old PATH: %s\n", pathvar );
     return 0;
 }


 ERROR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\ERROR.C

 /* ERROR.C illustrates stream file error handling. Functions illustrated
  * include:
  *      ferror          clearerr        exit            _exit
  *      perror          strerror        _strerror
  *
  * The _exit routine is not specifically illustrated, but it is the same
  * as exit except that file buffers are not flushed and atexit and onexit
  * are not called.
  */

 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
 enum BOOL { FALSE, TRUE };

 FILE *stream;
 char string[] = "This should never be written";
 void errortest( FILE *stream, char *msg, int fterm );

 main( int argc, char *argv[] )
 {
     /* Open file and test to see if open caused error. If so, terminate. */
     stream = fopen( argv[1], "r" );
     errortest( stream, "Can't open file", TRUE );

     /* Try to write to a read-only file, then test to see if write
      * caused error. If so, clear error, but don't terminate.
      */
     fprintf( stream, "%s\n", string );
     errortest( stream, "Can't write file", FALSE );
     exit( 0 );
 }

 /* Error test routine takes a stream, a message, and a flag telling whether
  * to terminate if there is an error.
  */
 void errortest( FILE *stream, char *msg, int fterm )
 {
     /* If stream doesn't exist (failed fopen) or if there is an error
      * on the stream, handle error.
      */
     if( (stream == NULL) || (ferror( stream )) )
     {
         perror( msg );
         /* _strerror and strerror can be used to get the same result
          * as perror, as illustrated by these lines (commented out).
         printf( "%s: %s\n", msg, strerror( errno ) );
         printf( _strerror( msg ) );
          */

         /* Terminate or clear error, depending on terminate flag. */
         if( fterm )
             exit( errno );
         else
             clearerr( stream );
     }
 }


 EXEC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\EXEC.C

 /* EXEC.C illustrates the different versions of exec including:
  *      execl           execle          execlp          execlpe
  *      execv           execve          execvp          execvpe
  *
  * Although EXEC.C can exec any program, you can verify how different
  * versions handle arguments and environment by compiling and
  * specifying the sample program ARGS.C. See SPAWN.C for examples
  * of the similar spawn functions.
  */

 #include <stdio.h>
 #include <conio.h>
 #include <process.h>

 char *my_env[] =                /* Environment for exec?e */
 {
     "THIS=environment will be",
     "PASSED=to child by the",
     "SPAWN=functions",
     NULL
 };

 main()
 {
     char *args[4], prog[80];
     int ch;

     printf( "Enter name of program to exec: " );
     gets( prog );
     printf( " 1. execl   2. execle   3. execlp   4. execlpe\n" );
     printf( " 5. execv   6. execve   7. execvp   8. execvpe\n" );
     printf( "Type a number from 1 to 8 (or 0 to quit): " );
     ch = getche();
     if( (ch < '1') || (ch > '8') )
         exit( 1 );
     printf( "\n\n" );

     /* Arguments for execv? */
     args[0] = prog;             /* First argument ignored under most */
     args[1] = "exec??";         /*   recent versions of DOS          */
     args[2] = "two";
     args[3] = NULL;

     switch( ch )
     {
         case '1':
             execl( prog, prog, "execl", "two", NULL );
             break;
         case '2':
             execle( prog, prog, "execle", "two", NULL, my_env );
             break;
         case '3':
             execlp( prog, prog, "execlp", "two", NULL );
             break;
         case '4':
             execlpe( prog, prog, "execlpe", "two", NULL, my_env );
             break;
         case '5':
             execv( prog, args );
             break;
         case '6':
             execve( prog, args, my_env );
             break;
         case '7':
             execvp( prog, args );
             break;
         case '8':
             execvpe( prog, args, my_env );
             break;
         default:
             break;
     }

     /* This point is only reached if exec fails. */
     printf( "\nProcess was not execed." );
     exit( 0 );
 }


 EXTDIR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\EXTDIR.C

 /* EXTDIR.C illustrates wild card handling using functions:
  *      _dos_findfirst      _dos_findnext       sprintf
  */

 #include <stdlib.h>
 #include <stdio.h>
 #include <conio.h>
 #include <ctype.h>
 #include <dos.h>
 #include <io.h>
 #include <sys\types.h>
 #include <sys\utime.h>
 #include <sys\stat.h>

 long fileinfo( struct find_t *find );       /* Prototypes */
 char *timestr( unsigned d, char *buf );
 char *datestr( unsigned d, char *buf );

 main( int argc, char *argv[] )
 {
     struct find_t find;
     long size;

     /* Find first matching file, then find additional matches. */
     if( !_dos_findfirst( argv[1], 0xffff, &find ) )
     {
         printf( "%-12s   %-8s    %-8s   %-8s   %-9s   %s %s %s %s\n",
                 "FILE", "SIZE", "TIME", "DATE", "KIND",
                 "RDO", "HID", "SYS", "ARC" );
         size = fileinfo( &find );
     }
     else
     {
         printf( "  SYNTAX: TOUCH <wildfilespec>" );
         exit( 1 );
     }
     while( !_dos_findnext( &find ) )
         size += fileinfo( &find );
     printf( "%-12s   %8ld\n\n", "Total", size );
     exit( 0 );
 }

 long fileinfo( struct find_t *pfind )
 {
     char timebuf[10], datebuf[10], *pkind;

     datestr( pfind->wr_date, datebuf );
     timestr( pfind->wr_time, timebuf );

     if( pfind->attrib & _A_SUBDIR )
         pkind = "Directory";
     else if( pfind->attrib & _A_VOLID )
         pkind = "Label";
     else
         pkind = "File";

     printf( "%-12s   %8ld    %8s   %8s   %-9s    %c   %c   %c   %c\n",
             pfind->name, pfind->size, timebuf, datebuf, pkind,
             (pfind->attrib & _A_RDONLY) ? 'Y' : 'N',
             (pfind->attrib & _A_HIDDEN) ? 'Y' : 'N',
             (pfind->attrib & _A_SYSTEM) ? 'Y' : 'N',
             (pfind->attrib & _A_ARCH)   ? 'Y' : 'N' );
     return pfind->size;
 }

 /* Take unsigned time in the format:                fedcba9876543210
  * s=2 sec incr, m=0-59, h=23                       hhhhhmmmmmmsssss
  * Change to a 9-byte string (ignore seconds):      hh:mm ?m
  */
 char *timestr( unsigned t, char *buf )
 {
     int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;

     sprintf( buf, "%2.2d:%02.2d %cm", h % 12, m,  h > 11 ? 'p' : 'a' );
     return buf;
 }

 /* Take unsigned date in the format:    fedcba9876543210
  * d=1-31, m=1-12, y=0-119 (1980-2099)  yyyyyyymmmmddddd
  * Change to a 9-byte string:           mm/dd/yy
  */
 char *datestr( unsigned d, char *buf )
 {
     sprintf( buf, "%2.2d/%02.2d/%02.2d",
              (d >> 5) & 0x0f, d & 0x1f, (d >> 9) + 80 );
     return buf;
 }


 EXTERR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\EXTERR.C

 /* EXTERR.C illustrates function:
  *      dosexterr
  */

 #include <dos.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>

 void errorinfo( void );     /* Prototype */

 main( int argc, char *argv[] )
 {
     int hsource;

     /* Open to get file handle and test for errors. Try specifying
      * invalid files to show different errors.
      */
     if( _dos_open( argv[1], O_RDWR, &hsource ) )
         errorinfo();
     printf( "No error\n" );
     _dos_close( hsource );
     exit( 0 );
 }

 void errorinfo()
 {
     struct DOSERROR err;
     static char *eclass[] =
     {
         "", "Out of Resource", "Temporary Situation", "Authorization",
         "Internal", "Hardware Failure", "System Failure", "Application Error"
         "Not Found", "Bad Format", "Locked", "Media", "Already Exists",
         "Unknown"
     };
     static char *eaction[] =
     {
         "", "Retry", "Delay Retry", "User", "Abort", "Immediate Exit",
         "Ignore", "Retry After User Intervention"
     };
     static char *elocus[] =
     {
         "", "Unknown", "Block Device", "Net", "Serial Device", "Memory"
     };


     /* Get error information and display class, action, and locus. */
     dosexterr( &err );
     printf( "Class:\t%s\nAction:\t%s\nLocus:\t%s\nAction\t",
             eclass[err.class], eaction[err.action], elocus[err.locus] );

     /* Errors that could be caused by sample _dos_open. You can expand
      * this list to handle others.
      */
     switch( err.exterror )
     {
         case 2:
             printf( "File not found\n" );
             break;
         case 3:
             printf( "Path not found\n" );
             break;
         case 5:
             printf( "Access denied\n" );
             break;
     }
     exit( err.exterror );
 }


 FACTOR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FACTOR.C

 /* FACTOR.C: Demonstrate functions.
  *  NOTE:  a value > 16 will overflow a long integer.
  */

 #include <stdio.h>

 long factor( int param );

 main()
 {
    int num;
    long result;
    /* Display a prompt */
    printf( "Type a number: " );
    /* Input a numeric value, assign to num */
    scanf( "%d", &num );
    result = factor( num );
    printf( "Factorial of %d is %ld\n", num, result );
 }

 long factor( int param )
 {
    long value = 1;
    while( param > 1 )
    {
       value = value * param;
       param = param - 1;
    }
    return value;
 }


 FCVT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FCVT.C

 /* FCVT.C illustrates floating point to string conversion functions:
  *      gcvt            ecvt            fcvt
  *
  * See MKFPSTR.C for an example of using the data returned by fcvt
  * to build a formatted string. See ATONUM.C for an example of using
  * the string returned by gcvt.
  */

 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>

 main()
 {
     int decimal, sign;
     char *pnumstr;
     int precision = 7;
     char numbuf[50];
     double number1, number2;

     printf( "Enter two floating point numbers: " );
     scanf( "%lf %lf", &number1, &number2 );

     /* With gcvt, precision specifies total number of digits.
      * The decimal place and sign are inserted in the string.
      */
     gcvt( number1 + number2, precision, numbuf );
     printf( "\nString produced by gcvt: %s\n", numbuf );
     printf( "Total digits: %d\n", precision );

     /* With ecvt, precision specifies total number of digits.
      * The decimal place and sign are provided for use in formatting.
      */
     pnumstr = ecvt( number1 + number2, precision, &decimal, &sign );
     printf( "\nString produced by ecvt: %s\nSign: %s\n",
              pnumstr, sign ? "-" : "+" );
     printf( "Digits left of decimal: %d\nTotal digits: %d\n",
              decimal, precision );

     /* With fcvt, precision specifies digits after decimal place.
      * The decimal place and sign are provided for use in formatting.
      */
     pnumstr = fcvt( number1 + number2, precision, &decimal, &sign );
     printf( "\nString produced by fcvt: %s\nSign: %s\n",
              pnumstr, sign ? "-" : "+"  );
     printf( "Digits left of decimal: %d\nDigits after decimal: %d\n",
              decimal, precision );
 }


 FIGURE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\FIGURE.C

 /* FIGURE.C illustrates graphics drawing functions including:
  *      _setpixel   _lineto     _moveto     _rectangle      _ellipse
  *      _arc        _pie
  *
  * Window versions of graphics drawing functions (such as _rectangle_w,
  * _ellipse_wxy, and _lineto_w) are illustrated in WINDOW.C and GEDIT.C.
  */

 #include <conio.h>
 #include <stdlib.h>
 #include <graph.h>

 main()
 {
     short x, y;
     short mode = _VRES16COLOR;

     while( !_setvideomode( mode ) )     /* Find best graphics mode   */
         mode--;
     if( mode == _TEXTMONO )
         exit( 1 );                      /* No graphics available     */

     for( x = 10, y = 50; y < 90; x += 2, y += 3 )/* Draw pixels      */
         _setpixel( x, y );
     getch();

     for( x = 60, y = 50; y < 90; y += 3 )        /* Draw lines       */
     {
         _moveto( x, y );
         _lineto( x + 20, y );
     }
     getch();

     x = 110; y = 70;                             /* Draw rectangles  */
     _rectangle( _GBORDER,       x - 20, y - 20, x, y );
     _rectangle( _GFILLINTERIOR, x + 20, y + 20, x, y );
     getch();

     x = 160;                                     /* Draw ellipses    */
     _ellipse( _GBORDER,       x - 20, y - 20, x, y );
     _ellipse( _GFILLINTERIOR, x + 20, y + 20, x, y );
     getch();

     x = 210;                                     /* Draw arcs        */
     _arc( x - 20, y - 20, x, y, x, y - 10, x - 10, y );
     _arc( x + 20, y + 20, x, y, x + 10, y + 20, x + 20, y + 10 );
     getch();

     x = 260;                                    /* Draw pies        */
     _pie( _GBORDER,       x - 20, y - 20, x, y, x, y - 10, x - 10, y );
     _pie( _GFILLINTERIOR, x + 20, y + 20, x, y,
                           x + 10, y + 20, x + 20, y + 10 );
     getch();

     exit( !_setvideomode( _DEFAULTMODE ) );
 }


 FILEONE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FILEONE.C

 /* FILEONE.C: Visibility in multiple source files.
 */

 int chico = 20, harpo = 30;
 extern void yonder( void );

 main()
 {
    yonder();
 }


 FILETWO.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FILETWO.C

 /* FILETWO.C: Visibility in multiple source files.
 */

 #include <stdio.h>

 void yonder( void )
 {
    extern int chico, harpo;
    printf( "chico = %d, harpo = %d\n", chico, harpo );
 }


 FILL.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\FILL.C

 /* FILL.C illustrates color, filling, and linestyle functions including:
  *    _setlinestyle      _setfillmask       _setcolor
  *    _getlinestyle      _floodfill
  *
  * The _getfillmask function is not shown, but its use is similar to
  * _getlinestyle.
  */

 #include <conio.h>
 #include <graph.h>
 #include <time.h>
 #include <stdlib.h>

 main()
 {
     short x, y, xinc, yinc, xwid, ywid;
     unsigned char fill[8];
     struct videoconfig vc;
     unsigned seed = (unsigned)time( 0L );   /* Different seed each time */
     short i, color, mode = _VRES16COLOR;

     while( !_setvideomode( mode ) )         /* Find best graphics mode  */
         mode--;
     if (mode == _TEXTMONO )
         exit( 1 );                          /* No graphics available    */
     _getvideoconfig( &vc );

     xinc = vc.numxpixels / 8;               /* Size variables to mode   */
     yinc = vc.numxpixels / 8;
     xwid = (xinc / 2) - 4;
     ywid = (yinc / 2) - 4;

     /* Draw circles and lines with different patterns. */
     for( x = xinc; x <= (vc.numxpixels - xinc); x += xinc )
     {
         for( y = yinc; y <= (vc.numypixels - yinc); y += yinc )
         {
             /* Vary random seed, randomize fill and color. */
             srand( seed = (seed + 431) * 5 );
             for( i = 0; i < 8; i++ )
                 fill[i] = rand();
             _setfillmask( fill );
             color = (rand() % vc.numcolors) + 1;
             _setcolor( color );

             /* Draw ellipse and fill with random color. */
             _ellipse( _GBORDER, x - xwid, y - ywid, x + xwid, y + ywid );
             _setcolor( (rand() % vc.numcolors) + 1 );
             _floodfill( x, y, color );

             /* Draw vertical and horizontal lines. Vertical line style
              * is opposite of (not) horizontal style. Since lines are
              * overdrawn with several linestyles, this has the effect of
              * combining colors and styles.
              */
             _setlinestyle( rand() );
             _moveto( 0, y + ywid + 4 );
             _lineto( vc.numxpixels - 1, y + ywid + 4 );
             _setlinestyle( ~_getlinestyle() );
             _moveto( x + xwid + 4, 0 );
             _lineto( x + xwid + 4, vc.numypixels - 1 );
         }
     }
     getch();
     exit( !_setvideomode( _DEFAULTMODE ) );
 }


 FINDSTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FINDSTR.C

 /* FINDSTR.C illustrates memory and string search functions including:
  *       memchr        strchr        strrchr            strstr
  */

 #include <memory.h>
 #include <string.h>
 #include <stdio.h>

 int  ch = 'r';
 char str[] =    "lazy";
 char string[] = "The quick brown dog jumps over the lazy fox";
 char fmt1[] =   "         1         2         3         4         5";
 char fmt2[] =   "12345678901234567890123456789012345678901234567890";

 main()
 {
     char *pdest;
     int result;

     printf( "String to be searched:\n\t\t%s\n", string );
     printf( "\t\t%s\n\t\t%s\n\n", fmt1, fmt2 );

     printf( "Function:\tmemchr\n" );
     printf( "Search char:\t%c\n", ch );
     pdest = memchr( string, ch, sizeof( string ) );
     result = pdest - string + 1;
     if( pdest != NULL )
         printf( "Result:\t\t%c found at position %d\n\n", ch, result );
     else
         printf( "Result:\t\t%c not found\n" );

     printf( "Function:\tstrchr\n" );
     printf( "Search char:\t%c\n", ch );
     pdest = strchr( string, ch );
     result = pdest - string + 1;
     if( pdest != NULL )
         printf( "Result:\t\t%c found at position %d\n\n", ch, result );
     else
         printf( "Result:\t\t%c not found\n" );

     printf( "Function:\tstrrchr\n" );
     printf( "Search char:\t%c\n", ch );
     pdest = strrchr( string, ch );
     result = pdest - string + 1;
     if( pdest != NULL )
         printf( "Result:\t\t%c found at position %d\n\n", ch, result );
     else
         printf( "Result:\t\t%c not found\n" );

     printf( "Function:\tstrstr\n" );
     printf( "Search string:\t%s\n", str );
     pdest = strstr( string, str );
     result = pdest - string + 1;
     if( pdest != NULL )
         printf( "Result:\t\t%s found at position %d\n\n", str, result );
     else
         printf( "Result:\t\t%c not found\n" );
 }


 FOR1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FOR1.C

 /* FOR1.C: Demonstrate multiple expressions. */

 #include <stdio.h>

 main()
 {
    int a, b;
    for( a = 256, b = 1; b < 512; a /= 2, b *= 2 )
       printf( "a = %d  b = %d\n", a, b );
 }


 FOR2.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FOR2.C

 /* FOR2.C: Demonstrate variations on for loop. */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
    for( printf( "Type something\n" ); getche() != '\r'; )
       ; /* Null statement */
 }


 FOR3.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FOR3.C

 /* FOR3.C: Demonstrate similarity of for and while.
 */

 #include <stdio.h>

 main()
 {
    int count;

    for( count = 0; count < 10; count++ )
       printf( "count = %d\n", count );

    count = 0;
    while( count < 10 )
    {
       printf( "count = %d\n", count );
       count++;
    }

 }


 FOR4.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FOR4.C

 /* FOR.C: Demonstrate for loop. */

 #include <stdio.h>

 main()
 {
    int test;
    for( test = 10; test > 0; test -= 2 )
       printf( "test = %d\n", test );
 }


 FREECT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FREECT.C

 /* FREECT.C illustrates the following heap functions:
  *      _freect         _memavl
  */

 #include <malloc.h>
 #include <stdio.h>

 main()
 {
     char near *bufs[64];
     unsigned request, avail, i;

     printf( "Near heap bytes free: %u\n\n", _memavl() );
     printf( "How many 1K buffers do you want from the near heap? " );
     scanf( "%d", &request );
     if( request > 64 )
     {
         printf( "There are only 64K in a segment.\n" );
         request = 64;
     }

     avail = _freect( 1024 );
     request = (avail > request) ? request : avail;
     printf( "You can have %d buffers\n", request );

     printf( "They are available at:\n");
     for( i = 0; i < request; i++ )
     {
         bufs[i] = (char near *)_nmalloc( 1024 );
         printf( "%2d %Fp   ", i + 1, (char far *)bufs[i] );
         if( (i % 5) == 4 )
             printf( "\n" );
     }
     printf( "\n\nNear heap bytes free: %u\n\n", _memavl() );
     printf( "Freeing buffers . . ." );
     for( i = request; i; i-- )
         _nfree( bufs[i] );
     printf( "\n\nNear heap bytes free: %u", _memavl() );
 }


 FSAMPLER.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\FSAMPLER.C

 /* SAMPLER.C: Display sample text in various fonts.
 */

 #include <stdio.h>
 #include <conio.h>
 #include <stdlib.h>
 #include <graph.h>
 #include <string.h>

 #define NFONTS 6

 main()

 {
   static unsigned char *text[2*NFONTS] =
   {
       "COURIER",        "courier",
       "HELV",           "helv",
       "TMS RMN",        "tms rmn",
       "MODERN",         "modern",
       "SCRIPT",         "script",
       "ROMAN",          "roman"
   };
   static unsigned char *face[NFONTS] =
   {
       "t'courier'",
       "t'helv'",
       "t'tms rmn'"
       "t'modern'"
       "t'script'"
       "t'roman'"
   };
   static unsigned char list[20];
   struct videoconfig vc;
   int mode = _VRES16COLOR;
   register i;

   /*  Read header info from all .FON files in
    *  current directory   */

   if(_registerfonts( "*.FON" )<0 )
   {
      _outtext("Error:  can't register fonts");
      exit( 0 );
   }

   /*   Set highest available video mode */

   while( !_setvideomode( mode ) )
      mode--;
   if( mode == _TEXTMONO )
      exit ( 0 );

   /*   Copy video configuration into structure vc */

   _getvideoconfig( &vc );

   /*   Display six lines of sample text */

   for( i = 0; i<NFONTS; i++ )
   {
      strcpy( list, face[i] );
      strcat( list, "h30w24b" );

      if( !_setfont( list ) )
      {
          _setcolor( i + 1 );
          _moveto( 0, (i * vc.numypixels) / NFONTS );
          _outgtext( text[i * 2] );
          _moveto( vc.numxpixels / 2,
                      (i * vc.numypixels) / NFONTS );
          _outgtext( text[(i * 2) + 1] );
      }
      else
      {
          _setvideomode( _DEFAULTMODE );
          _outtext( "Error:  can't set font" );
          exit( 0 );
      }
   }
   getch();
   _setvideomode( _DEFAULTMODE );

   /* Return memory when finished with fonts */

   _unregisterfonts();
   exit( 0 );
 }


 FUNCPTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FUNCPTR.C

 /* FUNCPTR.C: Demonstrate function pointers. */

 #include <stdio.h>

 main()
 {
    int (*func_ptr) ();
    func_ptr = printf;
    (*func_ptr) ( "Curiouser and curiouser...\n" );
 }


 FUNCPTR1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\FUNCPTR1.C

 /* FUNCPTR1.C: Passing function pointers as arguments.
 */

 #include <stdio.h>

 void gimme_func( void (*func_ptr) () );

 main()
 {
    gimme_func( puts );
    gimme_func( printf );
 }

 void gimme_func( void (*func_ptr) () )
 {
    (*func_ptr) ( "Ausgezeichnet!" );
 }


 FUNGET.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\FUNGET.C

 /* FUNGET.C illustrates getting and ungetting characters from a file.
  * Functions illustrated include:
  *      getc            getchar         ungetc
  *      fgetc           fgetchar
  *
  * Although getchar and fgetchar are not specifically used in the example,
  * they are equivalent to using getc or fgetc with stdin. See HEXDUMP.C
  * for another example of getc and fgetc.
  */

 #include <conio.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>

 void getword( FILE *stream, char *buf );
 void skiptoword( FILE *stream );

 main()
 {
     char buffer[128];
     FILE *infile;

     printf( "Enter file name: " );
     gets( buffer );
     if( (infile = fopen( buffer, "rb" )) == NULL )
     {
         perror( "Can't open file" );
         exit( 1 );
     }

     /* Read each word and print reversed version. */
     while( 1 )
     {
         skiptoword( infile );
         getword( infile, buffer );
         puts( strrev( buffer ) );
     }
 }

 /* Read one word (defined as a string of alphanumeric characters). */
 void getword( FILE *stream, char *p )
 {
     int  ch;

     do
     {
         /* Macro version used here, but function version could be used:
         ch = fgetc( stream );
          */
         ch = getc( stream );        /* Get characters until EOF  */
         if( ch == EOF )             /*   or non-alphanumeric     */
             exit( 0 );
         *(p++) = (char)ch;
     } while( isalnum( ch ) );
     ungetc( ch, stream );           /* Put non-alphanumeric back */
     *(--p) = '\0';                  /* Null-terminate            */
 }

 /* Throw away non-digit characters. */
 void skiptoword( FILE *stream )
 {
     int  ch;

     do
     {
         ch = getc( stream );
         if( ch == EOF )
             exit( 0 );
     } while( !isalnum( ch ) );
     ungetc( ch, stream );
 }


 GETCH.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\GETCH.C

 /* GETCH.C illustrates how to process ASCII or extended keys.
  * Functions illustrated include:
  *      getch           getche
  */

 #include <conio.h>
 #include <ctype.h>
 #include <stdio.h>

 main()
 {
     int key;

     /* Read and display keys until ESC is pressed. */
     while( 1 )
     {
         /* If first key is 0, then get second extended. */
         if( !(key = getch()) )
         {
             key = getch();
             printf( "ASCII: no\tChar: NA\t" );
         }

         /* Otherwise there's only one key. */
         else
             printf( "ASCII: yes\tChar: %c \t", isgraph( key ) ? key : ' ' );

         printf( "Decimal: %d\tHex: %X\n", key, key );

         /* Echo character response to prompt. */
         if( key == 27)
         {
             printf( "Do you really want to quit? (Y/n) " );
             key = getche();
             printf( "\n" );
             if( (toupper( key ) == 'Y') || (key == 13) )
                 break;
         }
     }
 }


 GOODMAC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\GOODMAC.C

 /* GOODMAC.C: Parentheses in macro arguments. */
 #include <stdio.h>

 #define FOURX(arg)  ( (arg) * 4 )

 main()
 {
    int val;
    val = FOURX( 2 + 3 );
    printf( "val = %d\n", val );
 }


 GOODSEMI.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\GOODSEMI.C

 /* GOODSEMI.C */

 #include <stdio.h>

 main()
 {
    int count;
    for( count = 0; count < 500; count++ )
    {
       printf( "count = %d\n", count );
       printf( "And the beat goes on...\n" );
    }
 }


 GRAPHIC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\GRAPHIC.C

 /* GRAPHIC.C: Displays every graphics mode */

 #include <stdio.h>
 #include <graph.h>
 #include <conio.h>

 struct videoconfig screen;
 int modes[12] =
 {
    _MRES4COLOR, _MRESNOCOLOR, _HRESBW,
    _HERCMONO,
    _MRES16COLOR, _HRES16COLOR, _ERESNOCOLOR, _ERESCOLOR,
    _VRES2COLOR, _VRES16COLOR, _MRES256COLOR
 };

 void print_menu( void );
 void show_mode( char );

 main()
 {
    char key;
    print_menu();
    while( (key = getch()) != 'x' )
       show_mode( key );
 }

 void print_menu( void )
 {
    _setvideomode( _DEFAULTMODE );
    _clearscreen( _GCLEARSCREEN );
    printf( "Please choose a graphics mode\nType 'x' to exit.\n\n" );
    printf( "0 _MRES4COLOR\n1 _MRESNOCOLOR\n2 _HRESBW\n" );
    printf( "3 _HERCMONO\n4 _MRES16COLOR\n5 _HRES16COLOR\n" );
    printf( "6 _ERESNOCOLOR\n7 _ERESCOLOR\n" );
    printf( "8 _VRES2COLOR\n9 _VRES16COLOR\na _MRES256COLOR\n" );
 }

 void show_mode( char which )
 {
    int nc, i;
    int height, width;
    int mode = which;

    if( mode < '0' || mode > '9' )
       if( mode == 'a' )
          mode = '9' + 1;
       else if( mode == 'b' )
          mode = '9' + 2;
       else
          return;

    if( _setvideomode( modes[mode - '0'] ) )
    {
       _getvideoconfig( &screen );
       nc = screen.numcolors;
       width = screen.numxpixels/nc;
       height = screen.numypixels/2;
       for( i = 0; i < nc; i++ )
       {
          _setcolor( i );
          _rectangle( _GFILLINTERIOR, i * width, 0, (i + 1) * width, height );
       }
    }
    else
    {
       printf( " \nVideo mode %c is not available.\n", which);
       printf( "Please press a key.\n" );
    }
    getch();
    _setvideomode( _DEFAULTMODE );
    print_menu();
 }


 HALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\HALLOC.C

 /* HALLOC.C illustrates dynamic allocation of huge memory using functions:
  *      halloc          hfree
  */

 #include <stdio.h>
 #include <malloc.h>
 #include <stdlib.h>

 main()
 {
     char huge *bigbuf, huge *p;
     long count = 100000L;

     /* Allocate huge buffer. */
     bigbuf = (char huge *)halloc( count, sizeof( char ) );
     if( bigbuf == NULL )
     {
         printf( "Insufficient memory" );
         exit( 1 );
     }

     /* Fill the buffer with characters. */
     for( p = bigbuf; count; count--, p++ )
         *p = (char)(count % 10) + '0';

     /* Free huge buffer. */
     hfree( bigbuf );
     exit( 0 );
 }


 HARDERR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\HARDERR.C

 /* HARDERR.C illustrates handling of hardware errors using functions:
  *      _harderr            _hardresume         _hardretn
  */

 #include <stdio.h>
 #include <conio.h>
 #include <stdlib.h>
 #include <direct.h>
 #include <string.h>
 #include <dos.h>
 #include <bios.h>

 void far hardhandler( unsigned deverr, unsigned doserr, unsigned far *hdr );
 int _bios_str( char *p );

 main()
 {
     /* Install our hard error handler. */
     _harderr( hardhandler );

     /* Test it. */
     printf( "Make sure there is no disk in drive A:\n" );
     printf( "Press a key when ready...\n" );
     getch();
     if( mkdir( "a:\test" ) )
     {
         printf( "Failed" );
         exit( 1 );
     }
     else
     {
         printf( "Succeeded" );
         rmdir( "a:test" );
         exit( 0 );
     }
 }

 /* Handler to deal with hard error codes. Since DOS is not reentrant,
  * it is not safe use DOS calls to do I/O within the DOS Critical Error
  * Handler (int 24h) used by _harderr. Therefore, screen output and
  * keyboard input must be done through the BIOS.
  */
 void far hardhandler( unsigned deverr, unsigned doserr, unsigned far *hdr )
 {
     int ch;
     static char buf[200], tmpbuf[10];

     /* Copy message to buffer, then use BIOS to print it. */
     strcpy( buf, "\n\rDevice error code: " );
     strcat( buf, itoa( deverr, tmpbuf, 10 ) );
     strcat( buf, "\n\rDOS error code:    " );
     strcat( buf, itoa( doserr, tmpbuf, 10 ) );
     strcat( buf, "\n\r(R)etry, (F)ail, or (Q)uit? " );

     /* Use BIOS to write strings and get a key. */
     _bios_str( buf );
     ch = _bios_keybrd( _KEYBRD_READ ) & 0x00ff;
     _bios_str( "\n\r" );

     switch( ch )
     {
         case 'R':
         case 'r':       /* Try again */
         default:
             _hardresume( _HARDERR_RETRY );
         case 'F':
         case 'f':       /* Return to DOS with error code */
             _hardretn( doserr );
         case 'Q':
         case 'q':       /* Quit program */
             _hardresume( _HARDERR_ABORT );

     }
 }

 /* Display a string using BIOS interrupt 0x0e (Write TTY). Return length
  * of string displayed.
  */
 int _bios_str( char *p )
 {
     union REGS inregs, outregs;
     char *start = p;

     inregs.h.ah = 0x0e;
     for( ; *p; p++ )
     {
         inregs.h.al = *p;
         int86( 0x10, &inregs, &outregs );
     }
     return p - start;
 }


 HEAPWALK.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\HEAPWALK.C

 /* HEAPWALK.C illustrates heap testing functions including:
  *      _heapchk        _fheapchk       _nheapchk
  *      _heapset        _fheapset       _nheapset
  *      _heapwalk       _fheapwalk      _nheapwalk
  *      _msize          _fmsize         _nmsize
  *
  * Only the model independent versions are shown. They map to the model
  * dependent versions, depending on the memory model.
  */

 #include <stdio.h>
 #include <conio.h>
 #include <malloc.h>
 #include <stdlib.h>
 #include <time.h>

 /* Macro to get a random integer within a specified range */
 #define getrandom( min, max ) ((rand() % (int)((max) - (min))) + (min) + 1)

 void heapdump( char fill );
 void heapstat( int status );

 main()
 {
     int *p[10], i;

     srand( (unsigned)time( 0L ) );  /* Seed with current time. */

     /* Check heap status. Should be OK at start of heap. */
     heapstat( _heapchk() );

     /* Now do some operations that affect the heap. In this example,
      * allocate random-size blocks.
      */
     for( i = 0; i < 10; i++ )
     {
         if( (p[i] = (int *)calloc( getrandom( 1, 10000 ),
                                    sizeof( int ) )) == NULL )
         {
             --i;
             break;
         }
         printf( "Allocated %u at %p\n", _msize( p[i] ), (void far *)p[i] );
     }

     /* Fill all free blocks with the test character. */
     heapstat( _heapset( 254 ) );

     /* In a real program, you might do operations here on the allocated
      * buffers. Then do heapdump to make sure none of the operations wrote
      * to free blocks.
      */
     heapdump( 254 );

     /* Do some more heap operations. */
     for( ; i >= 0; i-- )
     {
         free( p[i] );
         printf( "Deallocating %u at %p\n", _msize( p[i] ), (void far *)p[i] )
     }

     /* Check heap again. */
     heapdump( 254 );
 }

 /* Test routine to check each block in the heap. */
 void heapdump( char fill )
 {
     struct _heapinfo hi;
     int heapstatus, i;
     char far *p;

     /* Walk through entries, displaying results and checking free blocks. */
     printf( "\nHeap dump:\n" );
     hi._pentry = NULL;
     while( (heapstatus = _heapwalk( &hi )) == _HEAPOK )
     {
         printf( "\n\t%s block at %p of size %u\t",
                 hi._useflag == _USEDENTRY ? "USED" : "FREE",
                 hi._pentry, hi._size );

         /* For free entries, check each byte to see that it still has
          * only the fill character.
          */
         if( hi._useflag != _USEDENTRY )
         {
             for( p = (char far *)hi._pentry, i = 0; i < hi._size; p++, i++ )
                 if( (char)*p != fill )
                     break;
             if( i == hi._size )
                 printf( "Not changed" );
             else
                 printf( "Changed" );
         }
     }
     heapstat( heapstatus );
 }

 /* Report on the status returned by _heapwalk, _heapset, or _heapchk. */
 void heapstat( int status )
 {
     printf( "\nHeap status: " );
     switch( status )
     {
         case _HEAPOK:
             printf( "OK - heap is fine" );
             break;
         case _HEAPEMPTY:
             printf( "OK - empty heap" );
             break;
         case _HEAPEND:
             printf( "OK - end of heap" );
             break;
         case _HEAPBADPTR:
             printf( "ERROR - bad pointer to heap" );
             break;
         case _HEAPBADBEGIN:
             printf( "ERROR - bad start of heap" );
             break;
         case _HEAPBADNODE:
             printf( "ERROR - bad node in heap" );
             break;
     }
     printf( "\n\n" );
 }


 HEXDUMP1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\HEXDUMP1.C

 /* HEXDUMP.C illustrates directory splitting and character stream I/O.
  * Functions illustrated include:
  *      _splitpath      _makepath
  *      fgetc           fputc           fgetchar        fputchar
  *      getc            putc            getchar         putchar
  *
  * While fgetchar, getchar, fputchar, and putchar are not specifically
  * used in the example, they are equivalent to using fgetc or getc with
  * stdin, or to using fputc or putc with stdout. See FUNGET.C for another
  * example of fgetc and getc.
  */

 #include <stdio.h>
 #include <conio.h>
 #include <io.h>
 #include <dos.h>
 #include <stdlib.h>
 #include <string.h>

 main()
 {
     FILE *infile, *outfile;
     char inpath[_MAX_PATH], outpath[_MAX_PATH];
     char drive[_MAX_DRIVE], dir[_MAX_DIR];
     char fname[_MAX_FNAME], ext[_MAX_EXT];
     int  in, size;
     long i = 0L;

     /* Query for and open input file. */
     printf( "Enter input file name: " );
     gets( inpath );
     strcpy( outpath, inpath );
     if( (infile = fopen( inpath, "rb" )) == NULL )
     {
         printf( "Can't open input file" );
         exit( 1 );
     }

     /* Build output file by splitting path and rebuilding with
      * new extension.
      */
     _splitpath( outpath, drive, dir, fname, ext );
     strcpy( ext, "hx" );
     _makepath( outpath, drive, dir, fname, ext );

     /* If file does not exist, open it */
     if( access( outpath, 0 ) )
     {
         outfile = fopen( outpath, "wb" );
         printf( "Creating %s from %s . . .\n", outpath, inpath );
     }
     else
     {
         printf( "Output file already exists" );
         exit( 1 );
     }

     printf( "(B)yte or (W)ord: " );
     size = getche();

     /* Get each character from input and write to output. */
     while( !feof( infile ) )
     {
         if( (size == 'W') || (size == 'w') )
         {
             in = getw( infile );
             fprintf( outfile, " %.4X", in );
             if( !(++i % 8) )
                 putw( 0x0D0A, outfile );        /* New line      */
         }
         else
         {
             /* This example uses the fgetc and fputc functions. You
              * could also use the macro versions:
             in = getc( infile );
              */
             in = fgetc( infile );
             fprintf( outfile, " %.2X", in );
             if( !(++i % 16) )
             {
                 /* Macro version:
                 putc( 13, outfile );
                  */
                 fputc( 13, outfile );           /* New line      */
                 fputc( 10, outfile );
             }
         }
     }
     fclose( infile );
     fclose( outfile );
     exit( 0 );
 }


 HORIZON.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\HORIZON.C

 /* HORIZON.C: VGA graphics with cycling of 256 colors */

 #include <stdio.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <graph.h>

 #define RED 0x0000003FL
 #define GRN 0x00003F00L
 #define BLU 0x003F0000L
 #define WHT 0x003F3F3FL
 #define STEP 21

 struct videoconfig screen;
 long int rainbow[512];

 main()
 {
    int i;
    long int col, gray;

    if( _setvideomode( _MRES256COLOR ) == 0 )
    {
       printf("This program requires a VGA card.\n" );
       exit( 0 );
    }
    for( col = 0; col < 64; col++ )
    {
       gray = col | (col << 8) | (col << 16);
       rainbow[col] = rainbow[col + 256] = BLU & gray;
       rainbow[col + 64] = rainbow[col + 64 + 256] = BLU | gray;
       rainbow[col + 128] = rainbow[col + 128 + 256] = RED | (WHT & ~gray);
       rainbow[col + 192] = rainbow[col + 192 + 256] = RED & ~gray;
    }
    _setvieworg( 160, 85 );

    for( i = 0; i < 255; i++ )
    {
       _setcolor( 255 - i );
       _moveto( i, i - 255 );
       _lineto( -i, 255 - i );
       _moveto( -i, i - 255 );
       _lineto( i, 255 - i );
       _ellipse( _GBORDER, -i, -i / 2, i, i / 2 );
    }
    for( i = 0; !kbhit(); i += STEP, i %= 256 )
       _remapallpalette( &(rainbow[i]) );

    _setvideomode( _DEFAULTMODE );
 }


 IF1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\IF1.C

 /* IF.C: Demonstrate if statement. */

 #include <stdio.h>
 #include <conio.h>
 #define  B_KEY  'b'

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getche();
    if( ch == B_KEY )
       printf( "Beep!\a\n" );
 }


 INCMAC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\INCMAC.C

 /* INCMAC.C: Increment operator in macro argument.
 */

 #include <stdio.h>
 #define ABS(value)  ( (value) >= 0 ? (value) : -(value) )

 main()
 {
    static int array[4] = {3, -20, -555, 6};
    int *ptr = array;
    int val, count;
    for( count = 0; count < 4; count++ )
    {
       val = ABS(*ptr++); /* Error! */
       printf( "abs of array[%d] = %d\n", count, val );
    }
 }


 INCMAC1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\INCMAC1.C

 /* INCMAC1.C: Increment operator in the for statement.
 */

 #include <stdio.h>
 #define ABS(value)  ( (value) >= 0 ? (value) : -(value) )

 main()
 {
    static int array[4] = {3, -20, -555, 6};
    int *ptr = array;
    int val, count;
    for( count = 0; count < 4; count++, ptr++ )
    {
       val = ABS(*ptr);
       printf( "abs of array[%d] = %d\n", count, val );
    }
 }


 INTMATH.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MATH\INTMATH.C

 /* INTMATH.C illustrates integer math functions including:
  *      abs         labs        min         max         div         ldiv
  *
  * See MATH.C for an example of the similar fabs function.
  */

 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>

 main()
 {
     int x, y;
     long lx, ly;
     div_t divres;
     ldiv_t ldivres;

     printf( "Enter two integers: " );
     scanf( "%d %d", &x, &y );

     printf("Function\tResult\n\n" );
     printf( "abs\t\tThe absolute value of %d is %d\n", x, abs( x ) );
     printf( "min\t\tThe lesser of %d and %d is %d\n", x, y, min( x, y ) );
     printf( "max\t\tThe greater of %d and %d is %d\n", x, y, max( x, y ) );
     divres = div( x, y );
     printf( "div\t\tFor %d / %d, quotient is %d and remainder is %d\n\n",
             x, y, divres.quot, divres.rem );

     printf( "Enter two long integers: " );
     scanf( "%ld %ld", &lx, &ly );

     printf("Function\tResult\n\n" );
     ldivres = ldiv( lx, ly );
     printf( "labs\t\tThe absolute value of %ld is %ld\n", lx, labs( lx ) );
     printf( "ldiv\t\tFor %ld / %ld, quotient is %ld and remainder is %ld\n",
             lx, ly, ldivres.quot, ldivres.rem );
 }


 IS.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\IS.C

 /* IS.C illustrates character classification functions including:
  *      isprint         isascii         isalpha         isalnum
  *      isupper         islower         isdigit         isxdigit
  *      ispunct         isspace         iscntrl         isgraph
  *
  * Console output is also shown using:
  *      cprintf
  *
  * See PRINTF.C for additional examples of formatting for cprintf.
  */

 #include <ctype.h>
 #include <conio.h>

 main()
 {
     int ch;

     /* Display each ASCII character with character type table. */
     for( ch = 0; ch < 256; ch++ )
     {
         if( ch % 22 == 0 )
         {
             if( ch )
                 getch();

             /* Note that cprintf does not convert "\n" to a CR/LF sequence.
              * You can specify this sequence with "\n\r".
              */
             cprintf( "\n\rNum Char ASCII Alpha AlNum Cap Low Digit " );
             cprintf( "XDigit Punct White CTRL Graph Print \n\r" );
         }
         cprintf( "%3d  ", ch );

         /* Console output functions (cprint, cputs, and putch) display
          * graphic characters for all values except 7 (bell), 8 (backspace),
          * 10 (line feed), 13 (carriage return), and 255.
          */
         if( ch == 7 || ch == 8 || ch == 10 || ch == 13 || ch == 255 )
             cprintf("NV" );
         else
             cprintf("%c ", ch );
         cprintf( "%5s", isascii( ch )  ? "Y" : "N" );
         cprintf( "%6s", isalpha( ch )  ? "Y" : "N" );
         cprintf( "%6s", isalnum( ch )  ? "Y" : "N" );
         cprintf( "%5s", isupper( ch )  ? "Y" : "N" );
         cprintf( "%4s", islower( ch )  ? "Y" : "N" );
         cprintf( "%5s", isdigit( ch )  ? "Y" : "N" );
         cprintf( "%7s", isxdigit( ch ) ? "Y" : "N" );
         cprintf( "%6s", ispunct( ch )  ? "Y" : "N" );
         cprintf( "%6s", isspace( ch )  ? "Y" : "N" );
         cprintf( "%5s", iscntrl( ch )  ? "Y" : "N" );
         cprintf( "%6s", isprint( ch )  ? "Y" : "N" );
         cprintf( "%6s\n\r", isgraph( ch )  ? "Y" : "N" );
     }
 }


 KBHIT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\KBHIT.C

 /* KBHIT.C illustrates:
  *      kbhit
  */

 #include <conio.h>

 main()
 {
     /* Display message until key is pressed. Use getch to throw key away. */
     while( !kbhit() )
         cputs( "Hit me!! " );
     getch();
 }


 KEYBRD.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\UTILITY\KEYBRD.C

 /* KEYBRD.C illustrates:
  *      _bios_keybrd
  */

 #include <bios.h>
 #include <stdio.h>
 #include <ctype.h>

 main()
 {
     unsigned key, shift;
     unsigned char scan, ascii = 0;

     /* Read and display keys until ESC is pressed. */
     while( ascii != 27 )
     {
         /* Drain any keys in the keyboard type-ahead buffer, then get
          * the current key. If you want the last key typed rather than
          * the key currently being typed, omit the initial loop.
          */
         while( _bios_keybrd( _KEYBRD_READY ) )
             _bios_keybrd( _KEYBRD_READ );
         key = _bios_keybrd( _KEYBRD_READ );

         /* Get shift state. */
         shift = _bios_keybrd( _KEYBRD_SHIFTSTATUS );

         /* Split key into scan and ascii parts. */
         scan = key >> 8;
         ascii = key & 0x00ff;

         /* Categorize key. */
         if( ascii )
             printf( "ASCII: yes\tChar: %c \t",
                     isgraph( ascii ) ? ascii : ' ' );
         else
             printf( "ASCII: no\tChar: NA\t" );
         printf( "Code: %.2X\tScan: %.2X\t Shift: %.2X\n",
                 ascii, scan, shift );
     }
 }


 LOCK.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\LOCK.C

 /* LOCK.C illustrates network file sharing functions:
  *      sopen       locking
  *
  * Also the global variable:
  *      _osmajor
  *
  * The program requires DOS 3.0 or higher. The DOS SHARE command must
  * be loaded. The locking mechanism will only work if the program is
  * run from a network drive.
  */

 #include <stdio.h>
 #include <conio.h>
 #include <io.h>
 #include <fcntl.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <sys\locking.h>
 #include <share.h>
 <stdlib.h>         /* For _osmajor and exit */

 void error( char *msg );

 main( int argc, char *argv[] )
 {
     int handle, i;
     static char msg[] = "Are any of these bytes locked?";
     char buf[1];

     /* Check for DOS version >= 3.0 */
     if( _osmajor < 3 )
         error( "Must be DOS 3.0 or higher" );

     /* If no argument, write file and lock some bytes in it. */
     if( argc == 1 )
     {
         /* Open file with deny none sharing. */
         handle = sopen( "tmpfil", O_BINARY | O_RDWR | O_CREAT,
                                   SH_DENYNO, S_IREAD | S_IWRITE );
         if( handle == -1 )
             error( "Can't open file\n" );

         write( handle, msg, sizeof( msg ) - 1 );

         /* Lock 10 bytes starting at byte 10. */
         lseek( handle, 10L, SEEK_SET );
         if( locking( handle, LK_LOCK, 10L ) )
             error( "Locking failed\n" );
         printf( "Locked 10 bytes starting at byte 10\n" );

         system( "LOCK read" );
         getch();

         /* Unlock. */
         lseek( handle, 10L, SEEK_SET );
         locking( handle, LK_UNLCK, 10L );
         printf( "\nUnlocked 10 bytes starting at byte 10\n" );

         system( "LOCK read" );
         getch();
     }

     /* If argument, Try to read some locked bytes. */
     else
     {
         /* Open file with deny none sharing. */
         handle = sopen( "tmpfil", O_BINARY | O_RDWR,
                                   SH_DENYNO, S_IREAD | S_IWRITE );
         if( handle == -1 )
             error( "Can't open file\n" );

         for( i = 0; i < sizeof( msg ) - 1; i++ )
         {
             /* Print characters until locked bytes are reached. */
             if( read( handle, buf, 1 ) == -1 )
                 break;
             else
                 putchar( *buf );
         }
     }
     close( handle );
     exit( 0 );
 }

 void error( char *errmsg )
 {
     printf( errmsg );
     exit( 1 );
 }


 MATH.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MATH\MATH.C

 /* MATH.C illustrates floating point math functions including:
  *      exp             pow             sqrt            frexp
  *      log             log10           ldexp           modf
  *      ceil            floor           fabs            fmod
  */

 #include <math.h>
 #include <float.h>
 #include <stdio.h>
 #include <stdlib.h>

 main()
 {
     double x, rx, y;
     int n;

     printf( "\nEnter a real number: " );
     scanf( "%lf", &x );

     printf( "Mantissa: %2.2lf\tExponent: %d\n", frexp( x, &n ), n );
     printf( "Fraction: %2.2lf\tInteger: %lf\n", modf( x, &y ), y );

     printf("\nFunction\tResult for %2.2f\n\n", x );
     if( (rx = exp( x )) && (errno != ERANGE) )
         printf( "exp\t\t%2.2f\n", rx );
     else
         errno = 0;
     if( x > 0.0 )
         printf( "log\t\t%2.2f\n", log( x ) );
     if( x > 0.0 )
         printf( "log10\t\t%2.2f\n", log10( x ) );
     if( x >= 0.0 )
         printf( "sqrt\t\t%2.2f\n", sqrt( x ) );
     printf( "ceil\t\t%2.2f\n", ceil( x ) );
     printf( "floor\t\t%2.2f\n", floor( x ) );
     printf( "fabs\t\t%2.2f\n", fabs( x ) );

     printf( "\nEnter another real number: " );
     scanf( "%lf", &y );
     printf("\nFunction\tResult for %2.2f and %2.2f\n\n", x, y );
     printf( "fmod\t\t%2.2f\n", fmod( x, y ) );
     rx = pow( x, y );
     if( (errno != ERANGE) && (errno != EDOM) )
         printf( "pow\t\t%2.2f\n", rx );
     else
         errno = 0;
     rx = hypot( x, y );
     if( errno != ERANGE )
         printf( "hypot\t\t%2.2f\n", hypot( x, y ) );
     else
         errno = 0;

     printf( "\nEnter an integer exponent: " );
     scanf( "%d", &n );
     rx = ldexp( x, n );
     if( errno != ERANGE )
     {
         printf("\nFunction\tResult for %2.2f to power %d\n\n", x, n );
         printf( "ldexp\t\t%2.2f\n", ldexp( x, n ) );
     }
 }


 MATHERR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MATH\MATHERR.C

 /* MATHERR.C illustrates writing an error routine for math functions.
  * The error function must be:
  *      matherr
  *
  * To use matherr, you must turn off the Extended Dictionary flag within
  * the QC environment (Options-Make-Linker Flags) or use the /NOE linker
  * option outside the environment. For example:
  *      QCL matherr.c /link /NOE
  */

 #include <math.h>
 #include <string.h>
 #include <stdio.h>

 main()
 {
     /* Do several math operations that cause errors. The matherr
      * routine handles DOMAIN errors, but lets the system handle
      * other errors normally.
      */
     printf( "log( -2.0 ) = %e\n", log( -2.0 ) );
     printf( "log10( -5.0 ) = %e\n", log10( -5.0 ) );
     printf( "log( 0.0 ) = %e\n", log( 0.0 ) );
 }

 /* Routine to handle several math errors caused by passing a negative
  * argument to log or log10 (DOMAIN errors). If this happens, matherr
  * returns the natural or base-10 logarithm of the absolute value of
  * the argument and suppresses the usual error message.
  */
 int matherr( struct exception *except )
 {
     /* Handle DOMAIN errors for log or log10. */
     if( except->type == DOMAIN )
     {
         if( strcmp( except->name, "log" ) == 0 )
         {
             except->retval = log( -(except->arg1) );
             printf( "Special: using absolute value: %s: DOMAIN error\n",
                     except->name );
             return 1;
         }
         else if( strcmp( except->name, "log10" ) == 0 )
         {
             except->retval = log10( -(except->arg1) );
             printf( "Special: using absolute value: %s: DOMAIN error\n",
                     except->name );
             return 1;
         }
     }
     else
     {
         printf( "Normal: " );
         return 0;    /* Else use the default actions */
     }
 }


 MENU.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\UTILITY\MENU.C

 /* MENU - Module of functions to put menus on the screen and handle keyboard
  * input. To use it, include the MENU.H file in your program. The following
  * functions are public:
  *
  *   Menu       -   Puts a menu on screen and reads input for it
  *   Box        -   Puts a box on screen (fill it yourself)
  *   GetKey     -   Gets ASCII or function key
  *   _outchar   -   Displays character using current text position and color
  *
  * The following structures are defined:
  *
  *   MENU       -   Defines menu colors, box type, and centering
  *   ITEM       -   Defines text of menu item and index of highlight characte
  *
  * The global variable "mnuAtrib" has type MENU. Change this variable to
  * change menu appearance.
  */

 #include <string.h>
 #include <stddef.h>
 #include <ctype.h>
 #include <graph.h>
 #include <bios.h>
 #include "menu.h"

 /* Default menu attribute. The default works for color or B&W. You can
  * override the default value by defining your own MENU variable and
  * assigning it to mnuAtrib. Or you can modify specific fields at
  * run time. For example, you could use a different attribute for color
  * than for black and white.
  */
 struct MENU mnuAtrib =
 {
     _TBLACK, _TBLACK, _TWHITE, _TBRIGHTWHITE, _TBRIGHTWHITE,
     _TWHITE, _TWHITE, _TBLACK, _TWHITE, _TBLACK,
     TRUE,
     'Ú', '¿', 'Ù', 'À', '³', 'Ä'
 };

 /* Menu - Puts menu on screen and reads menu input from keyboard. When a
  * highlighted hot key or ENTER is pressed, returns the index of the
  * selected menu item.
  *
  * Params: row and col - If "fCentered" attribute of "mnuAtrib" is true,
  *           center row and column of menu; otherwise top left of menu
  *         aItem - array of structure containing the text of each item
  *           and the index of the highlighted hot key
  *         iCur - index of the current selection--pass 0 for first item,
  *           or maintain a static value
  *
  * Return: The index of the selected item
  *
  * Uses:   mnuAtrib
  */
 int Menu( int row, int col, struct ITEM aItem[], int iCur )
 {
     int cItem, cchItem = 2; /* Counts of items and chars per item       */
     int i, iPrev;           /* Indexes - temporary and previous         */
     int acchItem[MAXITEM];  /* Array of counts of character in items    */
     char *pchT;             /* Temporary character pointer              */
     char achHilite[36];     /* Array for highlight characters           */
     unsigned uKey;          /* Unsigned key code                        */
     long bgColor;           /* Screen color, position, and cursor       */
     short fgColor;
     struct rccoord rc;
     unsigned fCursor;

     /* Save screen information. */
     fCursor = _displaycursor( _GCURSOROFF );
     bgColor = _getbkcolor();
     fgColor = _gettextcolor();
     rc = _gettextposition();

     /* Count items, find longest, and put count of each in array. Also,
      * put the highlighted character from each in a string.
      */
     for( cItem = 0; aItem[cItem].achItem[0]; cItem++ )
     {
         acchItem[cItem] = strlen( aItem[cItem].achItem );
         cchItem = (acchItem[cItem] > cchItem) ? acchItem[cItem] : cchItem;
         i = aItem[cItem].iHilite;
         achHilite[cItem] = aItem[cItem].achItem[i];
     }
     cchItem += 2;
     achHilite[cItem] = 0;          /* Null-terminate and lowercase string  */
     strlwr( achHilite );

     /* Adjust if centered, and draw menu box. */
     if( mnuAtrib.fCentered )
     {
         row -= cItem / 2;
         col -= cchItem / 2;
     }
     Box( row++, col++, cItem, cchItem );

     /* Put items on menu. */
     for( i = 0; i < cItem; i++ )
     {
         if( i == iCur )
             Itemize( row + i, col, TRUE, aItem[i], cchItem - acchItem[i] );
         else
             Itemize( row + i, col, FALSE, aItem[i], cchItem - acchItem[i] );
     }

     while( TRUE )
     {
         /* Wait until a uKey is pressed, then evaluate it. */
         uKey = GetKey( WAIT );
         switch( uKey )
         {
             case U_UP:                      /* Up key       */
                 iPrev = iCur;
                 iCur = (iCur > 0) ? (--iCur % cItem) : cItem - 1;
                 break;
             case U_DN:                      /* Down key     */
                 iPrev = iCur;
                 iCur = (iCur < cItem) ? (++iCur % cItem) : 0;
                 break;
             default:
                 if( uKey > 256 )             /* Ignore unknown function key
                     continue;
                 pchT = strchr( achHilite, (char)tolower( uKey ) );
                 if( pchT != NULL )          /* If in highlight string,      *
                     iCur = pchT - achHilite;/*   evaluate and fall through  *
                 else
                     continue;               /* Ignore unkown ASCII key      *
             case ENTER:
                 _setbkcolor( bgColor );
                 _settextcolor( fgColor );
                 _settextposition( rc.row, rc.col );
                 _displaycursor( fCursor );
                 return iCur;
         }
         /* Redisplay current and previous. */
         Itemize( row + iCur, col, TRUE, aItem[iCur], cchItem - acchItem[iCur]
         Itemize( row + iPrev, col, FALSE, aItem[iPrev], cchItem - acchItem[iP
     }
 }

 /* Box - Draw menu box, filling interior with blanks of the border color.
  *
  * Params: row and col - upper left of box
  *         rowLast and colLast - height and width
  *
  * Return: None
  *
  * Uses:   mnuAtrib
  */
 void Box( int row, int col, int rowLast, int colLast )
 {
     int i;
     char achT[MAXITEM + 2];         /* Temporary array of characters */

     /* Set color and position. */
     _settextposition( row, col );
     _settextcolor( mnuAtrib.fgBorder );
     _setbkcolor( mnuAtrib.bgBorder );

     /* Draw box top. */
     achT[0] = mnuAtrib.chNW;
     memset( achT + 1, mnuAtrib.chEW, colLast );
     achT[colLast + 1] = mnuAtrib.chNE;
     achT[colLast + 2] = 0;
     _outtext( achT );

     /* Draw box sides and center. */
     achT[0] = mnuAtrib.chNS;
     memset( achT + 1, ' ', colLast );
     achT[colLast + 1] = mnuAtrib.chNS;
     achT[colLast + 2] = 0;
     for( i = 1; i <= rowLast; ++i )
     {
         _settextposition( row + i, col );
         _outtext( achT );
     }

     /* Draw box bottom. */
     _settextposition( row + rowLast + 1, col );
     achT[0] = mnuAtrib.chSW;
     memset( achT + 1, mnuAtrib.chEW, colLast );
     achT[colLast + 1] = mnuAtrib.chSE;
     achT[colLast + 2] = 0;
     _outtext( achT );
 }

 /* Itemize - Display one (item) selection of a menu. This function
  * is normally only used internally by Menu.
  *
  * Params: row and col - top left of menu
  *         fCur - flag set if item is current selection
  *         itm - structure containing item text and index of highlight
  *         cBlank - count of blanks to fill
  *
  * Return: none
  *
  * Uses:   mnuAtrib
  */
 void Itemize( int row, int col, int fCur, struct ITEM itm, int cBlank )
 {
     int i;
     char achT[MAXITEM];             /* Temporary array of characters */

     /* Set text position and color. */
     _settextposition( row, col );
     if( fCur )
     {
         _settextcolor( mnuAtrib.fgSelect );
         _setbkcolor( mnuAtrib.bgSelect );
     }
     else
     {
         _settextcolor( mnuAtrib.fgNormal );
         _setbkcolor( mnuAtrib.bgNormal );
     }

     /* Display item and fill blanks. */
     strcat( strcpy( achT, " " ), itm.achItem );
     _outtext( achT );
     memset( achT, ' ', cBlank-- );
     achT[cBlank] = 0;
     _outtext( achT );

     /* Set position and color of highlight character, then display it. */
     i = itm.iHilite;
     _settextposition( row, col + i + 1 );
     if( fCur )
     {
         _settextcolor( mnuAtrib.fgSelHilite );
         _setbkcolor( mnuAtrib.bgSelHilite );
     }
     else
     {
         _settextcolor( mnuAtrib.fgNormHilite );
         _setbkcolor( mnuAtrib.bgNormHilite );
     }
     _outchar( itm.achItem[i] );
 }

 /* GetKey - Gets a key from the keyboard. This routine distinguishes
  * between ASCII keys and function or control keys with different shift
  * states. It also accepts a flag to return immediately if no key is
  * available.
  *
  * Params: fWait - Code to indicate how to handle keyboard buffer:
  *   NO_WAIT     Return 0 if no key in buffer, else return key
  *   WAIT        Return first key if available, else wait for key
  *   CLEAR_WAIT  Throw away any key in buffer and wait for new key
  *
  * Return: One of the following:
  *
  *   Keytype                                High Byte    Low Byte
  *   -------                                ---------    --------
  *   No key available (only with NO_WAIT)       0           0
  *   ASCII value                                0        ASCII code
  *   Unshifted function or keypad               1        scan code
  *   Shifted function or keypad                 2        scan code
  *   CTRL function or keypad                    3        scan code
  *   ALT function or keypad                     4        scan code
  *
  * Note:   getkey cannot return codes for keys not recognized by BIOS
  *         int 16, such as the CTRL-UP or the 5 key on the numeric keypad.
  */
 unsigned GetKey( int fWait )
 {
     unsigned uKey, uShift;

     /* If CLEAR_WAIT, drain the keyboard buffer. */
     if( fWait == CLEAR_WAIT )
         while( _bios_keybrd( _KEYBRD_READY ) )
             _bios_keybrd( _KEYBRD_READ );

     /* If NO_WAIT, return 0 if there is no key ready. */
     if( !fWait && !_bios_keybrd( _KEYBRD_READY ) )
         return FALSE;

     /* Get key code. */
     uKey = _bios_keybrd( _KEYBRD_READ );

     /* If low byte is not zero, its an ASCII key. Check scan code to see
      * if it's on the numeric keypad. If not, clear high byte and return.
      */
     if( uKey & 0x00ff )
         if( (uKey >> 8) < 69 )
             return( uKey & 0x00ff );

     /* For function keys and numeric keypad, put scan code in low byte
      * and shift state codes in high byte.
      */
     uKey >>= 8;
     uShift = _bios_keybrd( _KEYBRD_SHIFTSTATUS ) & 0x000f;
     switch( uShift )
     {
         case 0:
             return( 0x0100 | uKey );  /* None (1)    */
         case 1:
         case 2:
         case 3:
             return( 0x0200 | uKey );  /* Shift (2)   */
         case 4:
             return( 0x0300 | uKey );  /* Control (3) */
         case 8:
             return( 0x0400 | uKey );  /* Alt (4)     */
     }
 }

 /* _outchar - Display a character. This is the character equivalent of
  * _outtext. It is affected by _settextposition, _settextcolor, and
  * _setbkcolor. It should not be used in loops. Build strings and then
  * _outtext to show multiple characters.
  *
  * Params: out - character to be displayed
  *
  * Return: none
  */
 void _outchar( char out )
 {
     static char achT[2] = " ";      /* Temporary array of characters */

     achT[0] = out;
     _outtext( achT );
 }


 MKFPSTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\MKFPSTR.C

 /* MKFPSTR.C illustrates building and displaying floating point strings
  * without printf. Functions illustrated include:
  *      strcat          strncat         cscanf          fcvt
  */

 #include <stdlib.h>
 #include <conio.h>
 #include <string.h>

 main()
 {
     int decimal, sign;
     int precision = 7;
     static char numbuf[50] = "";
     char *pnumstr, tmpbuf[50];
     double number1, number2;

     cputs( "Enter two floating point numbers: " );
     cscanf( "%lf %lf", &number1, &number2 );
     putch( '\n' );

     /* Use information from fcvt to format number string. */
     pnumstr = fcvt( number1 + number2, precision, &decimal, &sign );

     /* Start with sign if negative. */
     if( sign )
         strcat( numbuf, "-" );

     if( decimal <= 0 )
     {
         /* If decimal is left of first digit (decimal negative), put
          * in leading zeros, then add digits.
          */
         strcat( numbuf, "0." );
         memset( tmpbuf, '0', (size_t)abs( decimal ) );
         tmpbuf[abs( decimal )] = 0;
         strcat( numbuf, tmpbuf );
         strcat( numbuf, pnumstr );
     }
     else
     {
         /* If decimal is right of first digit, put in leading digits.
          * then add decimal and trailing digits.
          */
         strncat( numbuf, pnumstr, (size_t)decimal );
         strcat( numbuf, "." );
         strcat( numbuf, pnumstr + decimal );
     }
     cputs( strcat( "Total is: ", numbuf ) );
 }


 MORE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\MORE.C

 /* MORE.C illustrates line input and output using:
  *      gets            puts            isatty          fileno
  *
  * Like the DOS MORE command, it is a filter whose input and output can
  * be redirected.
  */

 #include <stdio.h>
 #include <bios.h>
 #include <io.h>

 main()
 {
     long line = 0, page = 0;
     char tmp[128];

     /* Get each line from standard input and write to standard output. */
     while( 1 )
     {
         /* If standard out is the screen, wait for key after each screen. */
         if( isatty( fileno( stdout ) ) )
         {
             /* Wait for key every 23 lines. You must get the key directly
              * from the BIOS, since input is usually redirected.
              */
             if( !(++line % 23 ) )
                 _bios_keybrd( _KEYBRD_READ );
         }
         /* Must be redirected to file, so send a header every 58 lines. */
         else
         {
             if( !(line++ % 58) )
                 printf( "\f\nPage: %d\n\n", ++page );
         }

         /* Get and put a line of text. */
         if( gets( tmp ) == NULL )
             break;
         puts( tmp );

     }
 }


 MOVEMEM.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\MOVEMEM.C

 /* MOVEMEM.C illustrate direct memory access using functions:
  *      movedata        FP_SEG          FP_OFF
  *
  * Also illustrated:
  *      pack pragma
  *
  * See COPY2.C for another example of FP_SEG.
  */

 #include <memory.h>
 #include <stdio.h>
 #include <dos.h>

 pack(1)     /* Use pragma to force packing on byte boundaries. */

 struct LOWMEMVID
 {
     char     vidmode;       /* 0x449 */
     unsigned scrwid;        /* 0x44A */
     unsigned scrlen;        /* 0x44C */
     unsigned scroff;        /* 0x44E */
     struct   LOCATE
     {
         unsigned char col;
         unsigned char row;
     } csrpos[8];            /* 0x450 */
     struct   CURSIZE
     {
         unsigned char end;
         unsigned char start;
     } csrsize;              /* 0x460 */
     char     page;          /* 0x462 */
 } vid;
 struct LOWMEMVID far *pvid = &vid;

 main()
 {
     int page;

     /* Move system information into uninitialized structure variable. */
     movedata( 0, 0x449, FP_SEG( pvid ), FP_OFF( pvid ), sizeof( vid ) );

     printf( "Move data from low memory 0000:0449 to structure at %Fp\n\n",
              (void far *)&vid );

     printf( "Mode:\t\t\t%u\n", vid.vidmode );
     printf( "Page:\t\t\t%u\n", vid.page );
     printf( "Screen width:\t\t%u\n", vid.scrwid );
     printf( "Screen length:\t\t%u\n", vid.scrlen );
     printf( "Cursor size:\t\tstart: %u\tend: %u\n",
              vid.csrsize.start, vid.csrsize.end );
     printf( "Cursor location:\t" );
     for( page = 0; page < 8; page++ )
         printf( "page:\t%u\tcolumn: %u\trow: %u\n\t\t\t",
                 page, vid.csrpos[page].col, vid.csrpos[page].row );
 }


 NFORMAT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\NFORMAT.C

 /* NFORMAT.C: Prints numbers and a string. */

 #include <stdio.h>
 #include <string.h>

 main()
 {
    int    a = -765,
           b = 1,
           c = 44000,
           d = 33;
    float  e = 1.33E8,
           f = -0.1234567,
           g = 12345.6789,
           h = 1.0;
    char   i[80];

    strcpy( i, "word 1, word 2, word 3, word 4, word 5" );

    printf( "Unformatted:\n%d %d %d %d\n", a, b, c, d );
    printf( "%f %f %f %f\n", e, f, g, h );
    printf( "%s\n", i );
 }


 NOT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\NOT.C

 /* NOT.C: Demonstrate logical NOT operator. */

 #include <stdio.h>

 main()
 {
   int val = 0;
   if( !val )
      printf( "val is zero" );
 }


 NULLFILE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\NULLFILE.C

 /* NULLFILE.C illustrates these functions:
  *      chsize          umask           setmode
  *      creat           fstat
  */

 #include <stdio.h>
 #include <conio.h>
 #include <io.h>
 #include <fcntl.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <stdlib.h>
 #include <time.h>

 main()
 {
     int fhandle;
     long fsize;
     struct stat fstatus;
     char fname[80];

     /* Create a file of a specified length. */
     printf( "What dummy file do you want to create: " );
     gets( fname );
     if( !access( fname, 0 ) )
     {
         printf( "File exists" );
         exit( 1 );
     }

     /* Mask out write permission. This means that a later call to open
      * will not be able to set write permission. This is not particularly
      * useful in DOS, but umask is provided primarily for compatibility
      * with systems (such as Unix) that allow multiple permission levels.
      */
     umask( S_IWRITE );

     /* Despite write request, file is read only because of mask. */
     if( (fhandle = creat( fname, S_IREAD | S_IWRITE )) == -1 )
     {
         printf( "File can't be created" );
         exit( 1 );
     }

     /* Since creat uses the default mode (usually text), you must
      * use setmode to make sure the mode is binary.
      */
     setmode( fhandle, O_BINARY );

     printf( "How long do you want the file to be? " );
     scanf( "%ld", &fsize );
     chsize( fhandle, fsize );

     /* Display statistics. */
     fstat( fhandle, &fstatus );
     printf( "File: %s\n", fname );
     printf( "Size: %ld\n", fstatus.st_size );
     printf( "Drive %c:\n", fstatus.st_dev + 'A' );
     printf( "Permission: %s\n",
             (fstatus.st_mode & S_IWRITE) ? "Read/Write" : "Read Only" );
     printf( "Created: %s", ctime( &fstatus.st_atime ) );

     close( fhandle );
     exit( 0 );
 }


 NUMTOA.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\NUMTOA.C

 /* NUMTOA.C illustrates number to string conversion functions including:
  *      itoa            ltoa            ultoa
  */

 #include <stdlib.h>
 #include <stdio.h>

 main()
 {
     int  base, i;
     long l;
     unsigned long ul;
     char buffer[60];

     printf( "Enter an integer: " );
     scanf( "%d", &i );
     for( base =  2; base <= 16; base += 2 )
     {
         itoa( i, buffer, base );
         if( base != 10 )
             printf( "%d in base %d is: %s\n", i, base, buffer );
     }

     printf( "Enter a long integer: " );
     scanf( "%ld", &l );
     for( base =  2; base <= 16; base += 2 )
     {
         ltoa( l, buffer, base );
         if( base != 10 )
             printf( "%ld in base %d is: %s\n", l, base, buffer );
     }

     printf( "Enter an unsigned long integer: " );
     scanf( "%lu", &ul );
     for( base =  2; base <= 16; base += 2 )
     {
         ultoa( ul, buffer, base );
         if( base != 10 )
             printf( "%lu in base %d is: %s\n", ul, base, buffer );
     }
 }


 PAGE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\PAGE.C

 /* PAGE.C illustrates video page functions including:
  *      _getactivepage  _getvisualpage  _setactivepage  _setvisualpage
  */

 #include <conio.h>
 #include <graph.h>
 #include <time.h>

 void delay( clock_t wait );         /* Prototype */
 char *jumper[] = { { "\\o/\n O \n/ \\" },
                    { "_o_\n O \n( )"   },
                    { " o \n/O\\\n/ \\" },
                    { " o \n O \n( )"   }
                  };
 main()
 {
     int i, oldvpage, oldapage, oldcursor;

     _clearscreen( _GCLEARSCREEN );
     oldcursor = _displaycursor( _GCURSOROFF );
     oldapage  = _getactivepage();
     oldvpage  = _getvisualpage();

     /* Draw image on each page */
     for( i = 0; i < 4; i++ )
     {
         _setactivepage( i );
         _settextposition( 1, 1 );
         _outtext( jumper[i] );
     }

     while( !kbhit() )
         /* Cycle through pages 0 to 3 */
         for( i = 0; i < 4; i++ )
         {
             _setvisualpage( i );
             delay( 100L );
         }
     getch();

     /* Restore original page and cursor. */
     _displaycursor( oldcursor );
     _setactivepage( oldapage );
     _setvisualpage( oldvpage );
 }

 /* delay - Pauses for a specified number of microseconds. */
 void delay( clock_t wait )
 {
     clock_t goal;

     goal = wait + clock();
     while( goal > clock() )
         ;
 }


 PAGER.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\PAGER.C

 /* PAGER.C illustrates line input and output on stream text files.
  * Functions illustrated include:
  *      fopen           fclose          fcloseall       feof
  *      fgets           fputs           rename
  */

 #include <stdio.h>
 #include <io.h>
 #include <dos.h>
 #include <stdlib.h>
 #include <string.h>

 #define MAXSTRING 128
 #define PAGESIZE 55
 enum BOOL { FALSE, TRUE };

 void quit( int error );
 FILE *infile, *outfile;
 char outpath[] = "tmXXXXXX";

 main( int argc, char *argv[] )
 {
     char tmp[MAXSTRING];
     long line = 0, page = 1;
     int  endflag = FALSE;

     /* Open file (from command line) and output (temporary) files. */
     if( (infile = fopen( argv[1], "rt" )) == NULL )
         quit( 1 );
     mktemp( outpath );
     if( (outfile = fopen( outpath, "wt" )) == NULL )
         quit( 2 );

     /* Get each line from input and write to output. */
     while( 1 )
     {
         /* Insert form feed and page header at the top of each page. */
         if( !(line++ % PAGESIZE) )
             fprintf( outfile, "\f\nPage %d\n\n", page++ );

         if( fgets( tmp, MAXSTRING - 1, infile ) == NULL )
             if( feof( infile ) )
                 break;
             else
                 quit( 3 );
         if( fputs( tmp, outfile ) == EOF )
             quit( 3 );
     }

     /* Close files and move temporary file to original by deleting
      * original and renaming temporary.
      */
     fcloseall();
     remove( argv[1] );
     rename( outpath, argv[1] );
     exit( 0 );
 }

 /* Handle errors. */
 void quit( int error )
 {
     switch( error )
     {
         case 1:
             perror( "Can't open input file" );
             break;
         case 2:
             perror( "Can't open output file" );
             fclose( infile );
             break;
         case 3:
             perror( "Error processing file" );
             fclose( infile );
             fclose( outfile );
             remove( outpath );
             break;
     }
     exit( error );
 }


 PALETTE1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\PALETTE1.C

 /* PALETTE.C illustrates functions for assigning color values to
  * color indexes. Functions illustrated include:
  *      _remappalette       _remapallpalette
  */

 #include <graph.h>
 #include <conio.h>
 #include <stdio.h>
 #include <stdlib.h>

 /* Macro for mixing Red, Green, and Blue elements of color */
 #define RGB(r,g,b) (((long) ((b) << 8 | (g)) << 8) | (r))

 main()
 {
     short red, blue, green;
     short inc, i, mode, cells, x, y, xinc, yinc;
     long tmp, pal[256];
     char buf[40];
     struct videoconfig vc;

     /* Make sure all palette numbers are valid */
     for( i = 0; i < 256; i++ )
         pal[i] = _BLACK;

     /* Loop through each graphics mode that supports palettes. */
     for( mode = _MRES4COLOR; mode <= _MRES256COLOR; mode++ )
     {
         if( mode == _ERESNOCOLOR )
             mode++;
         if( !_setvideomode( mode ) )
             continue;

         /* Set variables for each mode. */
         _getvideoconfig( &vc );
         switch( vc.numcolors )
         {
             case 256:           /* Active bits in this order:           */
                 cells = 13;
                 inc = 12;       /* ???????? ??bbbbbb ??gggggg ??rrrrrr  */
                 break;
             case  16:
                 cells = 4;
                 if( (vc.mode == _ERESCOLOR) || (vc.mode == _VRES16COLOR) )
                     inc = 16;   /* ???????? ??????bb ??????gg ??????rr  */
                 else
                     inc = 32;   /* ???????? ??????Bb ??????Gg ??????Rr  */
                 break;
             case   4:
                 cells = 2;
                 inc = 32;       /* ???????? ??????Bb ??????Gg ??????Rr  */
                 break;
             default:
                 continue;
         }
         xinc = vc.numxpixels / cells;
         yinc = vc.numypixels / cells;

         /* Fill palette arrays in BGR order */
         for( i = 0, blue = 0; blue < 64; blue += inc )
             for( green = 0; green < 64; green += inc )
                 for( red = 0; red < 64; red += inc )
                 {
                     pal[i] = RGB( red, green, blue );
                     /* Special case of using 6 bits to represent 16 colors.
                      * If both bits are on for any color, intensity is set.
                      * If one bit is set for a color, the color is on.
                      */
                     if( inc == 32 )
                         pal[i + 8] = pal[i] | (pal[i] >> 1);
                     i++;
                 }

         /* If palettes available, remap all palettes at once. */
         if( !_remapallpalette( pal ) )
         {
             _setvideomode( _DEFAULTMODE );
             _outtext( "Palettes not available with this adapter" );
             exit( 1 );
         }

         /* Draw colored squares */
         for( i = 0, x = 0; x < vc.numxpixels; x += xinc )
             for( y = 0; y < vc.numypixels; y += yinc )
             {
                 _setcolor( i++ );
                 _rectangle( _GFILLINTERIOR, x, y, x + xinc, y + yinc );
             }
         sprintf( buf, "Mode %d has %d colors", vc.mode, vc.numcolors );
         _setcolor( vc.numcolors / 2 );
         _outtext( buf );
         getch();

         /* Change each palette entry separately in GRB order. */
         for( i = 0, green = 0; green < 64; green += inc )
             for( red = 0; red < 64; red += inc )
                 for(blue = 0; blue < 64; blue += inc )
                 {
                     tmp = RGB( red, green, blue );
                     _remappalette( i, tmp );
                     if( inc == 32 )
                         _remappalette( i + 8, tmp | (tmp >> 1) );
                     i++;
                 }
         getch();
     }
     exit( !_setvideomode( _DEFAULTMODE ) );
 }


 PARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PARRAY.C

 /* PARRAY.C: Demonstrate pointer to array. */

 #include <stdio.h>

 int i_array[] = { 25, 300, 2, 12 };

 main()
 {
    int *ptr;
    int count;
    ptr = &i_array[0];
    for( count = 0; count < 4 ; count++ )
    {
       printf( "array[%d] = %d\n", count, *ptr );
       ptr++;
    }
 }


 PARRAY1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PARRAY1.C

 /* PARRAY1.C: Compact version of PARRAY.C. */

 #include <stdio.h>

 int i_array[] = { 25, 300, 2, 12 };


 main()
 {
    int count;
    int *ptr = i_array;
    for( count = 0; count < 4 ; count++ )
       printf( "array[%d] = %d\n", count, *ptr++ );
 }


 PFUNC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PFUNC.C

 /* PFUNC.C: Passing pointers to a function. */

 #include <stdio.h>

 void swap( int *ptr1, int *ptr2 );

 main()
 {
    int first = 1, second = 3;
    int *ptr = &second;
    printf( "first: %d  second: %d\n", first, *ptr );
    swap( &first, ptr );
    printf( "first: %d  second: %d\n", first, *ptr );
 }

 void swap( int *ptr1, int *ptr2 )
 {
    int temp;
    temp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = temp;
 }


 POINTER.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\POINTER.C

 /* POINTER.C: Demonstrate pointer basics. */

 #include <stdio.h>

 main()
 {
    int val = 25;
    int *ptr;
    ptr = &val;
    printf( " val = %d\n", val );
    printf( "*ptr = %d\n\n", *ptr );
    printf( "&val = %u\n", &val );
    printf( " ptr = %d\n", ptr );
 }


 PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PRINTF.C

 /* PRINTF.C illustrates output formatting with:
  *      printf
  *
  * The rules for formatting also apply to cprintf, sprintf, vfprintf,
  * vprintf, and vsprintf. For other examples of printf formatting,
  * see EXTDIR.C (sprintf), VPRINTF (vprintf), TABLE.C (fprintf),
  * ROTATE.C (printf), and IS.C (cprintf).
  */

 #include <stdio.h>

 main()
 {
     char ch = 'h', *string = "computer";
     int count = 234, *ptr, hex = 0x10, oct = 010, dec = 10;
     double fp = 251.7366;

     /* Display integers. */
     printf("%d    %+d    %06d    %X    %x    %o\n\n",
             count, count, count, count, count, count );

     /* Count characters printed. */
     printf( "            V\n" );
     printf( "1234567890123%n45678901234567890\n", &count );
     printf( "Number of characters printed: %d\n\n", count );

     /* Display characters. */
     printf( "%10c%5c\n\n", ch, ch );

     /* Display strings. */
     printf( "%25s\n%25.4s\n\n", string, string );

     /* Display real numbers. */
     printf( "%f    %.2f    %e    %E\n\n", fp, fp, fp, fp );

     /* Display in different radixes. */
     printf( "%i    %i    %i\n\n", hex, oct, dec );

     /* Display pointers. */
     ptr = &count;
     printf( "%Np    %p    %Fp\n", ptr, (int far *)ptr, (int far *)ptr );
 }


 PRTESC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PRTESC.C

 /* PRTESC.C: Prints escape characters \",\n, and \t.
 */

 #include <stdio.h>
 #include <string.h>

 main()
 {
    char b[80];
    int i,j;

    strcpy( b, "and seven years ago\n" );
    printf( "\"Four score\n" );
    printf( b );
    printf( "\tone tab\n\t\ttwo tabs\n\t\t\tthree tabs\n" );
    i = sizeof( b );
    j = strlen( b );
    printf( "Size is %d\nLength is %d.\n", i, j );
 }


 PSTRING.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PSTRING.C

 /* PSTRING.C: Demonstrate pointer to a string. */

 #include <stdio.h>

 main()
 {
    int count;
    static char name[] = "john";
    char *ptr = name;
    for( count = 0; count < 4; count++ )
    {
       printf( "name[%d]: %c\n", count, *ptr++ );
    }
 }


 PSTRING1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PSTRING1.C

 /* PSTRING1.C: Look for null at string's end.  */

 #include <stdio.h>

 main()
 {
    static char name[] = "john";
    char *ptr = name;
    while( *ptr )
       printf( "*ptr = %c\n", *ptr++ );
 }


 PSTRING2.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PSTRING2.C

 /* PSTRING2.C: Demonstrate strings and array notation.
 */

 #include <stdio.h>
 #include <string.h>

 main()
 {
    int count;
    static char name[] = "john";
    for( count = 0; count < strlen( name ); count++ )
       printf( "name[%d]: %c\n", count, name[count] );
 }


 PSTRING3.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PSTRING3.C

 /* PSTRING3.C: Strings and pointer notation.  */

 #include <stdio.h>
 #include <string.h>

 main()
 {
    int count;
    static char name[] = "john";
    for( count = 0; count < strlen( name ); count++ )
       printf( "*(name+count) = %c\n", *(name+count) );
 }


 PTRPTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\PTRPTR.C

 /* PTRPTR.C: Demonstrate a pointer to a pointer. */

 #include <stdio.h>

 main()
 {
    int val = 501;
    int *ptr = &val;
    int **ptr_ptr = &ptr;
    printf( "val = %d\n", **ptr_ptr );
 }


 QSORT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\QSORT.C

 /* QSORT.C illustates randomizing, sorting, and searching. Functions
  * illustrated include:
  *      srand           rand            qsort
  *      lfind           lsearch         bsearch
  *
  * The lsearch function is not specifically shown in the program, but
  * its use is the same as lfind except that if it does not find the
  * element, it inserts it at the end of the array rather than failing.
  */

 #include <search.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <time.h>

 #define  ASIZE 1000
 unsigned array[ASIZE];

 /* Macro to get a random integer within a specified range */
 #define getrandom( min, max ) ((rand() % (int)((max) - (min))) + (min) + 1)

 /* Must be declared before call */
 unsigned cmpgle( unsigned *arg1, unsigned *arg2 );
 unsigned cmpe( unsigned *arg1, unsigned *arg2 );

 main()
 {
     unsigned i, *result, elements = ASIZE, key = ASIZE / 2;

     /* Seed the random number generator with current time. */
     srand( (unsigned)time( 0L ) );

     /* Build a random array of integers. */
     printf( "Randomizing . . .\n" );
     for( i = 0; i < ASIZE; i++ )
         array[i] = getrandom( 1, ASIZE );

     /* Show every tenth element. */
     printf( "Printing every tenth element . . .\n" );
     for( i = 9; i < ASIZE; i += 10 )
     {
         printf( "%5u", array[i] );
         if( !(i % 15) )
             printf( "\n" );
     }

     /* Find element using linear search. */
     printf( "\nDoing linear search . . .\n" );
     result = (unsigned *)lfind( (char *)&key, (char *)array, &elements,
                                 sizeof( unsigned ), cmpe);
     if( result == NULL )
         printf( "  Value %u not found\n", key );
     else
         printf( "  Value %u found in element %u\n", key, result - array + 1);

     /* Sort array using Quicksort algorithm. */
     printf( "Sorting . . .\n" );
     qsort( (void *)array, (size_t)ASIZE, sizeof( int ), cmpgle );

     /* Show every tenth element. */
     printf( "Printing every tenth element . . .\n" );
     for( i = 9; i < ASIZE; i += 10 )
     {
         printf( "%5u", array[i] );
         if( !(i % 15) )
             printf( "\n" );
     }

     /* Find element using binary search. Note that the array must
      * be previously sorted before using binary search.
      */
     printf( "\nDoing binary search . . .\n" );
     result = (unsigned *)bsearch( (char *)&key, (char *)array, elements,
                                   sizeof( unsigned ), cmpgle);
     if( result == NULL )
         printf( "  Value %u not found\n", key );
     else
         printf( "  Value %u found in element %u\n", key, result - array + 1 )
 }

 /* Compare and return greater than (1), less than (-1), or equal to (0).
  * This function is called by qsort and bsearch.
  */
 unsigned cmpgle( unsigned *arg1, unsigned *arg2 )
 {
     if( *arg1 > *arg2 )
         return 1;
     else if( *arg1 < *arg2 )
         return -1;
     else
         return 0;
 }

 /* Compare and return equal (1) or not equal (0). This function is
  * called by lfind and lsearch.
  */
 unsigned cmpe( unsigned *arg1, unsigned *arg2 )
 {
     return !( *arg1 == *arg2 );
 }


 RDFILE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\RDFILE.C

 /* RDFILE.C: Reads a file and prints characters to
  * the screen.  If you get "Error in opening file" try
  * running wrfile.c before you run this again.
  */

 #include <stdio.h>

 main()
 {
    int c;
    FILE *fp;

    if( fp = fopen( "c:\\testfile.asc", "rb" ) )
    {
       while( (c = fgetc( fp )) != EOF )
          printf( " %c\t%d\n", c, c );
       printf( "\nEnd of file marker: %d", c );
       fclose( fp );
    }
    else
       printf( "Error in opening file\n" );
 }


 RDKEYBRD.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\RDKEYBRD.C

 /* INPUT.C: Reads keyboard. */

 #include <stdio.h>
 #include <conio.h>
 #include <ctype.h>

 main()
 {
    int num;
    char c;
    char name[80];
    float rb;

    puts( "** Type \"Name:\" and your name" );
    scanf( "Name: %40s", name );
    printf( "** You typed this:\n%s", name );
    puts( "\n\n** Try again, with the gets function." );
    fflush( stdin );
    gets( name );
    printf( "** You typed this:\n%s\n", name );

    printf( "\n** Now type an integer.\n" );
    scanf( "%i", &num );
    sprintf( name, "** You typed this number: %i\n", num );
    puts( name );

    fflush( stdin );
    printf( "** Enter a floating-point value.\n" );
    scanf( "%f", &rb );
    printf( "** The answer is %f or %e\n", rb, rb );

    printf( "** Continue? Y or N\n" );

    do
       c = tolower( getch() );
    while( c != 'y' && c != 'n' );

 }


 REALG.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\REALG.C

  /* REALG.C: Example of real-coordinate graphics */

 #include <stdio.h>
 #include <conio.h>
 #include <graph.h>

 #define TRUE 1
 #define FALSE 0

 int four_colors( void );
 void three_graphs( void );
 void grid_shape( void );

 int halfx, halfy;
 struct videoconfig screen;
 double bananas[] =
 {   -0.3, -0.2, -0.224, -0.1, -0.5, +0.21, +2.9,
    +0.3, +0.2, 0.0, -0.885, -1.1, -0.3, -0.2,
    +.001, +.005, +0.14, 0.0, -0.9, -0.13, +0.3
 };


 main()
 {
    if( four_colors() )
       three_graphs();
    else
       printf( "This program requires a CGA, EGA, or VGA graphics card.\n"
 );
 }
 /*
 . Additional functions defined below
 .
 .
 */
  /* four_colors function from REALG.C */

 int four_colors( void )
 {
    _getvideoconfig( &screen );
    switch( screen.adapter )
    {
       case _CGA:
       case _OCGA:
          _setvideomode( _MRES4COLOR );
          break;
       case _EGA:
       case _OEGA:
          _setvideomode( _ERESCOLOR );
          break;
       case _VGA:
       case _OVGA:
          _setvideomode( _VRES16COLOR );
          break;
       default:
          return( FALSE );
    }
    _getvideoconfig( &screen );
    return( TRUE );
 }
 /* three_graphs function from REALG.C */

 void three_graphs( void )
 {
    int xwidth, yheight, cols, rows;
    struct _wxycoord upleft, botright;

    _clearscreen( _GCLEARSCREEN );
    xwidth = screen.numxpixels;
    yheight = screen.numypixels;
    halfx = xwidth/2;
    halfy = yheight/2;
    cols = screen.numtextcols;
    rows = screen.numtextrows;

    /* first window */
    _setviewport( 0, 0, halfx-1, halfy-1 );
    _settextwindow( 1, 1, rows/2, cols/2 );
    _setwindow( FALSE, -2.0, -2.0, 2.0, 2.0 );
    grid_shape();
    _rectangle( _GBORDER, 0, 0, halfx-1, halfy-1 );

    /* second window */
    _setviewport( halfx, 0, xwidth-1, halfy-1 );
    _settextwindow( 1, cols/2+1, rows/2, cols );
    _setwindow( FALSE, -3.0, -3.0, 3.0, 3.0 );
    grid_shape();
    _rectangle_w( _GBORDER, -3.0, -3.0, 3.0, 3.0 );

    /* third window */
    _setviewport( 0, halfy, xwidth-1, yheight-1 );
    _settextwindow( rows/2+1, 1, rows, cols );
    _setwindow( TRUE, -3.0, -1.5, 1.5, 1.5 );
    grid_shape();
    upleft.wx = -3.0;
    upleft.wy = -1.5;
    botright.wx = 1.5;
    botright.wy = 1.5;
    _rectangle_wxy( _GBORDER, &upleft, &botright );

    getch();
    _setvideomode( _DEFAULTMODE );
 }
 /* grid_shape from the REALG.C program */

 void grid_shape( void )
 {
    int i, numc, x1, y1, x2, y2;
    double x, y;
    char txt[80];

    numc = screen.numcolors;
    for( i = 1; i < numc; i++ )
    {
       _settextposition( i, 2 );
       _settextcolor( i );
       sprintf( txt, "Color %d", i );
       _outtext( txt );
    }

    _setcolor( 1 );
    _rectangle_w( _GBORDER, -1.0, -1.0, 1.0, 1.0 );
    _rectangle_w( _GBORDER, -1.02, -1.02, 1.02, 1.02 );

    for( x = -0.9, i = 0; x < 0.9; x += 0.1 )
    {
       _setcolor( 2 );
       _moveto_w( x, -1.0 );
       _lineto_w( x, 1.0 );
       _moveto_w( -1.0, x );
       _lineto_w( 1.0, x );

       _setcolor( 3 );
       _moveto_w( x - 0.1, bananas[i++] );
       _lineto_w( x, bananas[i] );
    }
    _moveto_w( 0.9, bananas[i++] );
    _lineto_w( 1.0, bananas[i] );
 }


 REALLOC1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\REALLOC1.C

 /* REALLOC.C illustrates heap functions:
  *      calloc      realloc         _expand
  */

 #include <stdio.h>
 #include <malloc.h>

 main()
 {
     int  *bufint;
     char *bufchar;

     printf( "Allocate two 512 element buffers\n" );
     if( (bufint = (int *)calloc( 512, sizeof( int ) )) == NULL )
         exit( 1 );
     printf( "Allocated %d bytes at %Fp\n",
             _msize( bufint ), (void far *)bufint );

     if( (bufchar = (char *)calloc( 512, sizeof( char ) )) == NULL )
         exit( 1 );
     printf( "Allocated %d bytes at %Fp\n",
             _msize( bufchar ), (void far *)bufchar );

     /* Expand the second buffer, reallocate the first. Note that trying
      * to expand the first buffer would fail because the second buffer
      * would be in the way.
      */
     if( (bufchar = (char *)_expand( bufchar, 1024 )) == NULL )
         printf( "Can't expand" );
     else
         printf( "Expanded block to %d bytes at %Fp\n",
                 _msize( bufchar ), (void far *)bufchar );

     if( (bufint = (int *)realloc( bufint, 1024 * sizeof( int ) )) == NULL )
         printf( "Can't reallocate" );
     else
         printf( "Reallocated block to %d bytes at %Fp\n",
                 _msize( bufint ), (void far *)bufint );

     /* Free memory */
     free( bufint );
     free( bufchar );
     exit( 0 );
 }


 RECORDS1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\RECORDS1.C

 /* RECORDS1.C illustrates reading and writing of file records using seek
  * functions including:
  *      fseek       rewind      ftell
  *
  * Other general functions illustrated include:
  *      tmpfile     rmtmp       fread       fwrite
  *
  * Also illustrated:
  *      struct
  *
  * See RECORDS2.C for a version program using fgetpos and fsetpos.
  */

 #include <stdio.h>
 #include <io.h>
 #include <string.h>

 /* File record */
 struct RECORD
 {
     int     integer;
     long    doubleword;
     double  realnum;
     char    string[15];
 } filerec = { 0, 1, 10000000.0, "eel sees tar" };

 main()
 {
     int c, newrec;
     size_t recsize = sizeof( filerec );
     FILE *recstream;
     long recseek;

     /* Create and open temporary file. */
     recstream = tmpfile();

     /* Write 10 unique records to file. */
     for( c = 0; c < 10; c++ )
     {
         ++filerec.integer;
         filerec.doubleword *= 3;
         filerec.realnum /= (c + 1);
         strrev( filerec.string );

         fwrite( &filerec, recsize, 1, recstream );
     }

     /* Find a specified record. */
     do
     {
         printf( "Enter record betweeen 1 and 10 (or 0 to quit): " );
         scanf( "%d", &newrec );

         /* Find and display valid records. */
         if( (newrec >= 1) && (newrec <= 10) )
         {
             recseek = (long)((newrec - 1) * recsize);
             fseek( recstream, recseek, SEEK_SET );

             fread( &filerec, recsize, 1, recstream );

             printf( "Integer:\t%d\n", filerec.integer );
             printf( "Doubleword:\t%ld\n", filerec.doubleword );
             printf( "Real number:\t%.2f\n", filerec.realnum );
             printf( "String:\t\t%s\n\n", filerec.string );
         }
     } while( newrec );

     /* Starting at first record, scan each for specific value. The following
      * line is equivalent to:
      *      fseek( recstream, 0L, SEEK_SET );
      */
     rewind( recstream );

     do
     {
         fread( &filerec, recsize, 1, recstream );
     } while( filerec.doubleword < 1000L );

     recseek = ftell( recstream );
     /* Equivalent to: recseek = fseek( recstream, 0L, SEEK_CUR ); */
     printf( "\nFirst doubleword above 1000 is %ld in record %d\n",
             filerec.doubleword, recseek / recsize );

     /* Close and delete temporary file. */
     rmtmp();
 }


 RECORDS2.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\RECORDS2.C

 /* RECORDS2.C illustrates reading and writing of file records with the
  * following functions:
  *      fgetpos     fsetpos
  *
  * See RECORDS1.C for a version using fseek, rewind, and ftell.
  */

 #include <stdio.h>
 #include <io.h>

 /* File record */
 struct RECORD
 {
     int     integer;
     long    doubleword;
     double  realnum;
 } filerec = { 0, 1, 10000000.0 };

 main()
 {
     int c, newrec;
     size_t recsize = sizeof( filerec );
     FILE *recstream;
     fpos_t *recpos;

     /* Create and open temporary file. */
     recstream = tmpfile();

     /* Write 10 unique records to file. */
     for( c = 0; c < 10; c++ )
     {
         ++filerec.integer;
         filerec.doubleword *= 3;
         filerec.realnum /= (c + 1);

         fwrite( &filerec, recsize, 1, recstream );
     }

     /* Find a specified record. */
     do
     {
         printf( "Enter record betweeen 1 and 10 (or 0 to quit): " );
         scanf( "%d", &newrec );

         /* Find and display valid records. */
         if( (newrec >= 1) && (newrec <= 10) )
         {
             *recpos = (fpos_t)((newrec - 1) * recsize);
             fsetpos( recstream, recpos );
             fread( &filerec, recsize, 1, recstream );

             printf( "Integer:\t%d\n", filerec.integer );
             printf( "Doubleword:\t%ld\n", filerec.doubleword );
             printf( "Real number:\t%.2f\n", filerec.realnum );
         }
     } while( newrec );

     /* Starting at first record, scan each for specific value. */
     *recpos = (fpos_t)0;
     fsetpos( recstream, recpos );
     do
     {
         fread( &filerec, recsize, 1, recstream );
     } while( filerec.doubleword < 1000L );

     fgetpos( recstream, recpos );
     printf( "\nFirst doubleword above 1000 is %ld in record %d\n",
             filerec.doubleword, *recpos / recsize );

     /* Close and delete temporary file. */
     rmtmp();
 }


 ROTATE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\ROTATE.C

 /* ROTATE.C illustrates bit rotation functions including:
  *      _rotl           _rotr           _lrotl          _lrotr
  *
  * _lrotl and _lrotr are not shown in the program, but they are the
  * same as _rotl and _rotr except that they work on long integers.
  */

 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>

 char *binstr( int num, char *buffer );      /* Prototype */

 main()
 {
     int  shift, i, ir, il;
     char tmpbuf[20];

     printf( "Enter integer: " );
     scanf( "%d", &i );
     printf( "\n\n" );

     /* Display table header for rotates. */
     printf( "%6s    %-7s    %16s    %-7s    %16s\n",
             " ", "Left", " ", "Right", " " );
     printf( "%6s    %7s    %16s    %7s    %16s\n\n",
             "Shift", "Decimal", "Binary", "Decimal", "Binary" );

     /* Display table of rotated values. */
     for( shift = 0; shift <= 16; shift++ )
     {
         il = _rotl( i, shift ); ;
         printf( "%5d    %7d    %16s    ", shift, il, binstr( il,  tmpbuf ) );
         ir = _rotr( i, shift );
         printf( "%7d    %16s\n", ir, binstr( ir, tmpbuf ) );
     }
 }

 /* Convert integer to string of 16 binary characters. */
 char *binstr( int num, char *buffer )
 {
     char tmp[17];
     int  len;

     memset( buffer, '0', 16 );
     len = strlen( itoa( num, tmp, 2 ) );
     strcpy( buffer + 16 - len, tmp );
     return buffer;
 }


 RWFILE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\RWFILE.C

 /* RWFILE.C: Reads and writes a file. */

 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <io.h>

 #define BUFF 512

 main()
 {
    char inbuffer[BUFF];
    char outbuffer[BUFF];
    int infile, outfile, length, num;

    strcpy( outbuffer, "Happy Birthday." );
    length = strlen( outbuffer );
    length++;

    if( (outfile = open( "testfile.bin",
       O_CREAT | O_WRONLY | O_BINARY,  S_IWRITE )) != -1 )
    {
       if( (num = write( outfile, outbuffer, length )) == -1 )
          perror( "Error in writing" );
       printf( "\nBytes written to file: %d\n", num );
       close( outfile );
    }
    else
       perror( "Error opening outfile" );

    if( (infile = open( "testfile.bin", O_RDONLY | O_BINARY )) != -1  )
    {
       while( length = read( infile, inbuffer, BUFF ) )
          printf( "%d bytes received so far.\n", length );
       close( infile );
       printf( "%s\n", inbuffer );
    }
    else
       perror( "Error opening infile" );
 }


 SBRK.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\SBRK.C

 /* SBRK.C illustrates memory allocation with function:
  *      sbrk
  */

 #include <malloc.h>
 #include <stdio.h>
 #include <stdlib.h>

 main()
 {
     char *bufA, *bufB, *bufC;

     /* Allocate 512 bytes. */
     if( (bufA = sbrk( 512 )) == (char *)-1 )
         exit( 1 );
     printf( "Allocate:\t256\tLocation:\t%p\n", (int far *)bufA );

     /* Allocate 50 bytes. */
     if( (bufB = sbrk( 50 )) == (char *)-1 )
         exit( 1 );
     printf( "Allocate:\t50\tLocation:\t%p\n", (int far *)bufB );

     /* Deallocate 256 bytes. */
     sbrk( -256 );
     printf( "Deallocate:\t256\n" );

     /* Allocate 20 bytes. */
     if( (bufC = sbrk( 20 )) == (char *)-1 )
         exit( 1 );
     printf( "Allocate:\t20\tLocation:\t%p\n", (int far *)bufC );
     exit( 0 );
 }


 SCANF.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\SCANF.C

 /* SCANF.C illustrates formatted input. Functions illustrated include:
  *          scanf           fflush          flushall
  *
  * For other examples of formatted input, see TABLE.C (fscanf) and
  * SETTIME.C (sscanf).
  */

 #include <stdio.h>
 #include <conio.h>

 main()
 {
     int result, integer;
     float fp;
     char string[81];

     /* Get numbers. */
     printf( "Enter an integer and a floating point number: " );
     scanf( "%d %f", &integer, &fp );
     printf( "%d + %f = %f\n\n", integer, fp, integer + fp );

     /* Read each word as a string. */
     printf( "Enter a sentence of four words with scanf: " );
     for( integer = 0; integer < 4; integer++ )
     {
         scanf( "%s", string );
         printf( "%s\n", string );
     }

     /* Clear the input buffer and get with gets. */
     fflush( stdin );
     printf( "Enter the same sentence with gets: " );
     gets( string );
     printf( "%s\n", string );

     /* Specify delimiters. The ^ inside the brackets says accept any
      * character except the following other characters in brackets (tab
      * and newline in the example).
      */
     printf( "Enter the same sentence with scanf and delimiters: " );
     scanf( "%[^\n\t]s", string );
     printf( "%s\n", string );

     /* Loop until input value is 0. */
     printf( "\n\nEnter numbers in C decimal (num), hex (0xnum), " );
     printf( "or octal (0num) format.\nEnter 0 to quit\n\n" );
     do
     {
         printf( "Enter number: " );
         result = scanf( "%i", &integer );
         if( result )
             /* Display valid integers. */
             printf( "Decimal: %i  Octal: 0%o  Hexadecimal: 0x%X\n\n",
                     integer, integer, integer );
         else
         {   /* Read invalid characters. Then flush and continue. */
             scanf( "%s", string );
             printf( "Invalid number: %s\n\n", string );
             flushall();
             integer = 1;
         }
     } while( integer );
 }


 SEEK.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\SEEK.C

 /* SEEK.C illustrates low-level file I/O functions including:
  *      filelength      lseek           tell
  */

 #include <io.h>
 #include <conio.h>
 #include <stdio.h>
 <fcntl.h>          /* O_ constant definitions */
 #include <process.h>

 void error( char *errmsg );

 main()
 {
     int handle, ch;
     unsigned count;
     long position, length;
     char buffer[2], fname[80];

     /* Get file name and open file. */
     do
     {
         printf( "Enter file name: " );
         gets( fname );
         handle = open( fname, O_BINARY | O_RDONLY );
     } while( handle == -1 );

     /* Get and print length. */
     length = filelength( handle );
     printf( "\nFile length of %s is: %ld\n\n", fname, length );

     /* Report the character at a specified position. */
     do
     {
         printf( "Enter integer position less than file length: " );
         scanf( "%ld", &position );
     } while( position > length );

     lseek( handle, position, SEEK_SET );
     if( read( handle, buffer, 1 ) == -1 )
         error( "Read error" );
     printf( "Character at byte %ld is ASCII %u ('%c')\n\n",
             position, *buffer, *buffer );

     /* Search for a specified character and report its position. */
     lseek( handle, 0L, SEEK_SET);           /* Set to position 0 */
     printf( "Type character to search for: " );
     ch = getche();

     /* Read until character is found */
     do
     {
         if( (count = read( handle, buffer, 1 )) == -1 )
             error( "Read error" );
     } while( (*buffer != (char)ch) && count );

     /* Report the current position. */
     position = tell( handle );
     if( count )
         printf( "\nFirst ASCII %u ('%c') is at byte %ld\n",
                 ch, ch, position );
     else
         printf( "\nASCII %u ('%c') not found\n", ch, ch );
     close( handle );
     exit( 0 );
 }

 void error( char *errmsg )
 {
     perror( errmsg );
     exit( 1 );
 }


 SETROWS.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\SETROWS.C

 /* SETROWS.C illustrates
  *      _settextrows
  */

 #include <graph.h>
 #include <stdlib.h>

 main( int argc, char ** argv )
 {
     struct videoconfig vc;
     short rows = atoi( argv[1] );

     _getvideoconfig( &vc );

     /* Make sure new rows is valid and the same as requested rows. */
     if( !rows || (_settextrows( rows ) != rows) )
         _outtext( "\nSyntax: SETROWS [ 25 | 43 | 50 ]\n" );

     /* Always return old rows for batch file testing. */
     exit( vc.numtextrows );
 }


 SETSTR.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SETSTR.C

 /* SETSTR.C illustrate string and memory set functions including:
  *     memset           strnset         strset
  */

 #include <memory.h>
 #include <string.h>
 #include <stdio.h>

 char string[60] = "The quick brown dog jumps over the lazy fox ";
 /*                          1         2         3         4         5 *
  *                 12345678901234567890123456789012345678901234567890 */
 main()
 {
     printf( "Function:\tmemset with fill character 'Û'\n" );
     printf( "Destination:\t%s\n", string );
     memset( string + 10, 'Û', 5 );
     printf( "Result:\t\t%s\n\n", string );

     printf( "Function:\tstrnset with fill character 'Û'\n" );
     printf( "Destination:\t%s\n", string );
     strnset( string + 15, 'Û', 5 );
     printf( "Result:\t\t%s\n\n", string );

     printf( "Function:\tstrset with fill character 'Û'\n" );
     printf( "Destination:\t%s\n", string );
     strset( string + 20, 'Û' );
     printf( "Result:\t\t%s\n\n", string );
 }


 SETTIME.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SETTIME.C

 /* SETTIME.C illustates getting and setting the DOS time and date using:
  *      _dos_gettime    _dos_settime    _dos_getdate    _dos_setdate
  *
  * Formatted input to a string is illustrated using:
  *      sscanf
  */

 #include <dos.h>
 #include <stdio.h>
 #include <conio.h>
 #include <string.h>

 struct dosdate_t ddate;
 struct dostime_t dtime;

 main()
 {
     unsigned tmpday, tmpmonth, tmpyear;
     unsigned tmphour, tmpminute, tmpsecond;
     static char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }
     char tmpbuf[20];

     /* Get current date. */
     _dos_getdate( &ddate );
     printf( "Date: %u/%02u/%02u %s\n",
             ddate.month, ddate.day, ddate.year - 1900,
             days[ddate.dayofweek] );
     printf( "Enter new date: " );

     /* Get a date string and if it's not 0 (for CR), assign it to date. */
     gets( tmpbuf );
     if( strlen( tmpbuf ) )
     {
         /* NOTE: You must read the month and day into a temporary unsigned
          * variable. If you try to read directly into the unsigned char
          * values ddate.day or ddate.month, sscanf (or scanf) will read a
          * word, thus overriding adjacent bytes.
          */
         sscanf( tmpbuf, "%u/%u/%u", &tmpmonth, &tmpday, &tmpyear );
         if( (tmpyear - 80) <= 20 )
             ddate.year = tmpyear + 1900;
         else if( (tmpyear >= 1980) && (tmpyear <= 2099 ) )
             ddate.year = tmpyear;
         if( (tmpmonth + 1) <= 13 )
             ddate.month = (unsigned char)tmpmonth;
         if( (tmpday + 1) <= 32 )
             ddate.day = (unsigned char)tmpday;
         _dos_setdate( &ddate );
         _dos_getdate( &ddate );
         printf( "New date: %u/%02u/%02u %s\n",
                 ddate.month, ddate.day, ddate.year - 1900,
                 days[ddate.dayofweek] );
     }

     /* Get current time. */
     _dos_gettime( &dtime );
     printf( "Time: %u:%02u:%02u\n", dtime.hour, dtime.minute, dtime.second );
     printf( "Enter new time: " );

     /* Get a time string and if it's not 0 (for CR), assign it to time. */
     gets( tmpbuf );
     if( strlen( tmpbuf ) )
     {
         sscanf( tmpbuf, "%u:%u:%u", &tmphour, &tmpminute, &tmpsecond );
         if( tmphour < 24 )
             dtime.hour = (unsigned char)tmphour;
         if( tmpminute < 60 )
             dtime.minute = (unsigned char)tmpminute;
         if( tmpsecond < 60 )
             dtime.second = (unsigned char)tmpsecond;
         _dos_settime( &dtime );
         _dos_gettime( &dtime );
         printf( "New time: %u:%02u:%02u\n",
                 dtime.hour, dtime.minute, dtime.second );
     }
 }
 


 SHOWME1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SHOWME1.C

 /* SHOWME1.C: Demonstrate passing by value. */

 #include <stdio.h>

 void showme( int any, int old, int name );

 main()
 {
    int x = 10, y = 20, z = 30;
    showme( z, y, x );

    printf( "z=%d y=%d x=%d\n", z, y, x );
 }

 void showme( int any, int old, int name )
 {
    printf( "any=%d old=%d name=%d\n", any, old, name );
    any = 55;
    old = 66;
    name = 77;
    printf( "any=%d old=%d name=%d\n", any, old, name );
 }


 SIGNAL1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SIGNAL1.C

 /* SIGNAL.C illustrates setting up signal interrupt routines. Functions
  * illustrated include:
  *      signal          abort           raise           _fpreset
  *
  * The program also illustrates saving an environment and then doing a
  * long jump to return to it using functions:
  *      setjmp          longjmp
  */

 #include <stdio.h>
 #include <conio.h>
 #include <signal.h>
 #include <process.h>
 #include <setjmp.h>
 #include <stdlib.h>
 #include <float.h>

 void ctrlchandler( void );          /* Prototypes */
 void aborthandler( void );
 void fphandler( int sig, int num );

 jmp_buf mark;                       /* Address for long jump to jump to */

 main()
 {
     double n1, n2, r;
     int jmpret;

     /* Modify abort behavior. */
     if( signal( SIGABRT, aborthandler ) == SIG_ERR )
     {
         printf( "Couldn't set SIGABRT\n" );
         exit( 1 );
     }

     /* Modify CTRL+C behavior. */
     if( signal( SIGINT, ctrlchandler ) == SIG_ERR )
     {
         fprintf( stderr, "Couldn't set SIGINT\n" );
         abort();
     }

     /* Set up pointer to error handler. */
     if( signal( SIGFPE, fphandler ) == SIG_ERR )
     {
         fprintf( stderr, "Couldn't set SIGFPE\n" );
         abort();
     }

     /* Save stack environment for return in case of error. First time
      * through, jmpret is 0, so true conditional is executed. If an
      * error occurs, jmpret will be set to -1 and false conditional
      * will be executed.
      */
     jmpret = setjmp( mark );
     if( jmpret == 0 )
     {
         /* Try forcing error by dividing by 0 or using very large numbers. */
         printf( "Enter number to divide or CTRL-C: " );
         scanf( "%lf", &n1 );
         printf( "Enter number to divide by or CTRL-C: " );
         scanf( "%lf", &n2 );
         r = n1 / n2;

         /* This won't be reached if error occurs. */
         printf( "\n%4.3g / %4.3g = %4.3g\n", n1, n2, r );
     }
     else
         printf( "Recovered from floating-point error\n" );

     /* Fake CTRL+C. Program will abort or exit, depending on user
      * response in handler.
      */
     raise( SIGINT );
     exit( 0 );
 }

 /* Function called whenever SIGINT (CTRL+C) interrupt is called. */
 void ctrlchandler()
 {
     int ch;

     /* Disallow CTRL+C during handler. */
     signal( SIGINT, SIG_IGN );

     printf( "Abort processing? " );
     ch = getche();
     printf( "\n" );
     if( (ch == 'y') || (ch == 'Y') )
         abort();
     else

         /* The CTRL+C interrupt must be reset to our handler since by
          * default DOS resets it to the system handler.
          */
         signal( SIGINT, ctrlchandler );
 }

 /* Function called whenever SIGABRT interrupt is called. */
 void aborthandler()
 {
     printf( "The abort() function was called\n" );
     exit( 1 );
 }

 /* Function called whenever SIGFPE interrupt is called. */
 void fphandler( int sig, int num )
 {
     printf( "Signal: %d   Subcode: 0x%x\n", sig, num );

     /* Initialize floating-point package. */
     _fpreset();

     /* Restore calling environment and jump back to setjmp. Return -1
      * so that setjmp will return false for conditional test.
      */
     longjmp( mark, -1 );
 }


 SIZEOF.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SIZEOF.C

 /* SIZEOF.C: Demonstrate sizeof operator. */

 #include <stdio.h>

 char string[] = "Hello, world";

 main()
 {
    int val;
    printf( "An int is %d bytes long\n", sizeof( int ) );
    printf( "The string is %d bytes long\n", sizeof string );
 }


 SORT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SORT.C

 /* SORT.C illustates randomizing, sorting, and searching. Functions
  * illustrated include:
  *      srand           rand            qsort
  *      lfind           lsearch         bsearch
  *
  * The lsearch function is not specifically shown in the program, but
  * its use is the same as lfind except that if it does not find the
  * element, it inserts it at the end of the array rather than failing.
  */

 #include <search.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <time.h>

 #define  ASIZE 1000
 unsigned array[ASIZE];

 /* Macro to get a random integer within a specified range */
 #define getrandom( min, max ) ((rand() % (int)((max) - (min))) + (min) + 1)

 /* Must be declared before call */
 unsigned cmpgle( unsigned *arg1, unsigned *arg2 );
 unsigned cmpe( unsigned *arg1, unsigned *arg2 );

 main()
 {
     unsigned i, *result, elements = ASIZE, key = ASIZE / 2;

     /* Seed the random number generator with current time. */
     srand( (unsigned)time( 0L ) );

     /* Build a random array of integers. */
     printf( "Randomizing . . .\n" );
     for( i = 0; i < ASIZE; i++ )
         array[i] = getrandom( 1, ASIZE );

     /* Show every tenth element. */
     printf( "Printing every tenth element . . .\n" );
     for( i = 9; i < ASIZE; i += 10 )
     {
         printf( "%5u", array[i] );
         if( !(i % 15) )
             printf( "\n" );
     }

     /* Find element using linear search. */
     printf( "\nDoing linear search . . .\n" );
     result = (unsigned *)lfind( (char *)&key, (char *)array, &elements,
                                 sizeof( unsigned ), cmpe);
     if( result == NULL )
         printf( "  Value %u not found\n", key );
     else
         printf( "  Value %u found in element %u\n", key, result - array + 1);

     /* Sort array using Quicksort algorithm. */
     printf( "Sorting . . .\n" );
     qsort( (void *)array, (size_t)ASIZE, sizeof( int ), cmpgle );

     /* Show every tenth element. */
     printf( "Printing every tenth element . . .\n" );
     for( i = 9; i < ASIZE; i += 10 )
     {
         printf( "%5u", array[i] );
         if( !(i % 15) )
             printf( "\n" );
     }

     /* Find element using binary search. Note that the array must
      * be previously sorted before using binary search.
      */
     printf( "\nDoing binary search . . .\n" );
     result = (unsigned *)bsearch( (char *)&key, (char *)array, elements,
                                   sizeof( unsigned ), cmpgle);
     if( result == NULL )
         printf( "  Value %u not found\n", key );
     else
         printf( "  Value %u found in element %u\n", key, result - array + 1 )

 }

 /* Compare and return greater than (1), less than (-1), or equal to (0).
  * This function is called by qsort and bsearch.
  */
 unsigned cmpgle( unsigned *arg1, unsigned *arg2 )
 {
     if( *arg1 > *arg2 )
         return 1;
     else if( *arg1 < *arg2 )
         return -1;
     else
         return 0;
 }

 /* Compare and return equal (1) or not equal (0). This function is
  * called by lfind and lsearch.
  */
 unsigned cmpe( unsigned *arg1, unsigned *arg2 )
 {
     return !( *arg1 == *arg2 );
 }


 SORT1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SORT1.C

 /* SORT1.C: Demonstrate sort with pointer notation.
 */

 #include <stdio.h>
 #define SIZE 4

 void sort( int size, double **p );
 void show( int size, double **p, double dd[] );

 main()
 {
    int x;
    static double d[] = { 3.333, 1.111, 2.222, 4.444 };
    static double *d_ptr[SIZE];
    for( x = 0; x < SIZE; x++ )
       d_ptr[x] = &d[x];
    show( SIZE, d_ptr, d );
    sort( SIZE, d_ptr );
    show( SIZE, d_ptr, d );
 }

 void sort( int size, double **p )
 {
    int x, x1;
    double *temp;
    for( x = 0; x < size - 1; x++ )
       for( x1 = x + 1; x1 < size; x1++ )
       {
          if( **(p+x) > **(p+x1) )
          {
             temp = *(p+x1);
             *(p+x1) = *(p+x);
             *(p+x) = temp;
          }
       }
 }

 void show( int size, double **p, double dd[] )
 {
    int x;
    printf( "------------------------" );
    printf( "------------------------\n" );
    for( x = 0; x < size; x++ )
    {
       printf( "*d_ptr[%d] = %1.3f   ", x, **(p+x) );
       printf( "d_ptr[%d] = %u ", x, *(p+x) );
       printf( "  d[%d] = %1.3f\n", x, dd[x] );
    }
 }


 SPAWN.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SPAWN.C

 /* SPAWN.C illustrates the different versions of spawn including:
  *      spawnl          spawnle         spawnlp         spawnlpe
  *      spawnv          spawnve         spawnvp         spawnvpe
  *
  * Although SPAWN.C can spawn any program, you can verify how different
  * versions handle arguments and environment by compiling and
  * specifying the sample program ARGS.C. See EXEC.C for examples
  * of the similar exec functions.
  */

 #include <stdio.h>
 #include <conio.h>
 #include <process.h>

 char *my_env[] =                        /* Environment for spawn?e */
 {
     "THIS=environment will be",
     "PASSED=to child by the",
     "SPAWN=functions",
     NULL
 };

 main()
 {
     char *args[4], prog[80];
     int ch, r;

     printf( "Enter name of program to spawn: " );
     gets( prog );
     printf( " 1. spawnl   2. spawnle   3. spawnlp   4. spawnlpe\n" );
     printf( " 5. spawnv   6. spawnve   7. spawnvp   8. spawnvpe\n" );
     printf( "Type a number from 1 to 8 (or 0 to quit): " );
     ch = getche();
     if( (ch < '1') || (ch > '8') )
         exit( -1 );
     printf( "\n\n" );

     /* Arguments for spawnv? */
     args[0] = prog;             /* First argument ignored under most */
     args[1] = "spawn??";        /*   recent versions of DOS          */
     args[2] = "two";
     args[2] = "two";
     args[3] = NULL;

     switch( ch )
     {
         case '1':
             r = spawnl( P_WAIT, prog, prog, "spawnl", "two", NULL );
             break;
         case '2':
             r = spawnle( P_WAIT, prog, prog, "spawnle", "two", NULL, my_env )
             break;
         case '3':
             r = spawnlp( P_WAIT, prog, prog, "spawnlp", "two", NULL );
             break;
         case '4':
             r = spawnlpe( P_WAIT, prog, prog, "spawnlpe", "two", NULL, my_env
             break;
         case '5':
             r = spawnv( P_WAIT, prog, args );
             break;
         case '6':
             r = spawnve( P_WAIT, prog, args, my_env );
             break;
         case '7':
             r = spawnvp( P_WAIT, prog, args );
             break;
         case '8':
             r = spawnvpe( P_WAIT, prog, args, my_env );
             break;
         default:
             break;
     }
     if( r == -1 )
         printf( "Couldn't spawn process" );
     else
         printf( "\nReturned from SPAWN!" );
     exit( r );
 }


 STACK.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MEMORY\STACK.C

 /* STACK.C illustrates stack functions including:
  *      alloca          stackavail
  */

 #include <malloc.h>
 #include <stdio.h>

 main()
 {
     char *buffer;

     printf( "Bytes available on stack: %u\n", stackavail() );

     /* Allocate memory for string. */
     buffer = alloca( 120 * sizeof( char ) );
     printf( "Enter a string: " );
     gets( buffer );
     printf( "You entered: %s\n", buffer );

     printf( "Bytest available on stack: %u\n", stackavail() );
 }


 STATIC.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\STATIC.C

 /* STATIC.C: Demonstrate static variables. */

 #include <stdio.h>

 void add_ten( int val );

 main()
 {
    int val = 10;
    add_ten( val++ );
    add_ten( val );
 }

 void add_ten( int value )
 {
    static int methuselah;
    if( value == 10 )
       methuselah = 0;
    methuselah = methuselah + value;
    printf( "methuselah = %d\n", methuselah );
 }


 STRTONUM.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\STRTONUM.C

 /* STRTONUM.C illustrates string to number conversion functions including:
  *      strtod              strtol              strtoul
  */

 #include <stdlib.h>
 #include <stdio.h>

 main()
 {
     char *string, *stopstring;
     double x;
     long l;
     unsigned long ul;
     int base;

     /* Convert string to double. */
     string = "3.1415926INVALID";
     x = strtod( string, &stopstring );
     printf( "\nString: %s\n", string );
     printf( "\tDouble:\t\t\t%f\n", x );
     printf( "\tScan stopped at:\t%s\n", stopstring );

     /* Convert string to long using bases 2, 4, and 8. */
     string = "-10110134932";
     printf( "\nString: %s\n", string );
     for( base = 2; base <= 8; base *= 2 )
     {
         l = strtol( string, &stopstring, base );
         printf( "\tBase %d signed long:\t%ld\n", base, l );
         printf( "\tScan stopped at:\t%s\n", stopstring );
     }

     /* Convert string to unsigned long using bases 2, 4, and 8. */
     string = "10110134932";
     printf( "\nString: %s\n", string );
     for( base = 2; base <= 8; base *= 2 )
     {
         ul = strtoul( string, &stopstring, base);
         printf("\tBase %d unsigned long:\t%ld\n", base, ul );
         printf("\tScan stopped at:\t%s\n", stopstring );
     }
 }


 SVBIN.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\SVBIN.C

 /* SVBIN.C: Saves integer variables in binary format.
 */

 #include <stdio.h>
 #define ASIZE 10

 main()
 {
    FILE *ap;
    int zebra[ASIZE], acopy[ASIZE], bcopy[ASIZE];
    int i;

    for( i = 0; i < ASIZE; i++ )
       zebra[i] = 7700 + i;

    if( (ap = fopen( "binfile", "wb" )) != NULL )
    {
       fwrite( zebra, sizeof(zebra), 1, ap );
       fclose( ap );
    }
    else
       perror( "Write error" );

    if( (ap = fopen( "morebin", "wb" )) != NULL )
    {
       fwrite( &zebra[0], sizeof(zebra[0]), ASIZE, ap );
       fclose( ap );
    }
    else
       perror( "Write error" );

    if( (ap = fopen( "binfile", "rb" )) != NULL )
    {
       printf( "Hexadecimal values in binfile:\n" );
       while( (i = fgetc( ap )) != EOF )
          printf( "%02X ", i );
       rewind( ap );
       fread( acopy, sizeof(acopy), 1, ap );



       rewind( ap );
       fread( &bcopy[0], sizeof( bcopy[0] ), ASIZE, ap);
       for( i=0; i<ASIZE; i++ )
          printf( "\nItem %d = %d\t%d", i, acopy[i], bcopy[i] );
       fclose( ap );

    }
    else
       perror( "Read error" );

 }


 SVTEXT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\SVTEXT.C

 /* SVTEXT.C: Save integer variables as text. */

 #include <stdio.h>

 int list[] = { 53, -23456, 50, 500, 5000, -99 };
 extern int errno;
 char fname[] = "numtext";
 char temp[81];

 main()
 {
    FILE *fptr;
    int i;

    if( (fptr = fopen( "numtext","wt" )) != NULL )
    {
       for( i=0; i<6; i++ )
          fprintf( fptr, "Item %d: %6d \n", i, list[i] );
       fclose( fptr );
    }
    else
       printf( "Error: Couldn't create file.\n" );

    if( (fptr = fopen( "badname", "rt" )) != NULL )
    {
       /* do nothing */
    }
    else
    {
       printf( "Error number: %d\n\t", errno );
       perror( "Couldn't open file BADNAME\n\t" );
    }

    if( (fptr = fopen( fname, "rt" )) != NULL )
    {
       list[0] = 0;
       fscanf( fptr, "Item %d: %d \n", &i, &list[0] );
       printf( "Values read from file:\t %d %d\n", i, list[0] );
       fgets( temp, 80, fptr );
       printf( "String from file: \t%s\n", temp );
       while( (i = fgetc( fptr )) != '\n' )
          printf( "char: %c \t ASCII: %d \n", i, i );
       rewind( fptr );
       printf( "Rewind to start -->\t%s", fgets( temp, 80, fptr ) );
       fclose( fptr );
    }
    else      printf( "Trouble opening %s \n", fname );
 }


 SWAB.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SWAB.C

 /* SWAB.C illustrates:
  *      swab
  */

 #include <stdlib.h>
 #include <stdio.h>

 char from[] = "BADCFEHGJILKNMPORQTSVUXWZY";
 char to[] =   "..........................";

 main()
 {
     printf( "Before:\t%s\n\t%s\n\n", from, to );
     swab( from, to, sizeof( from ) );
     printf( "After:\t%s\n\t%s\n\n", from, to );
 }


 SWITCH.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SWITCH.C

 /* SWITCH.C: Demonstrate switch statement. */

 #include <stdio.h>
 #include <conio.h>
 #define  B_KEY  'b'
 #define  ENTER_KEY  '\r'

 main()
 {
    char ch;
    printf( "Press the b key to hear a bell.\n" );
    ch = getch();
    switch( ch )
    {
       case B_KEY:
          printf( "Beep!\a\n" );
          break;
       case ENTER_KEY:
          printf( "What a boring selection...\n" );
          break;
       default:
          printf( "Bye bye." );
          break;
    }
 }


 SYSCALL.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SYSCALL.C

 /* SYSCALL.C illustrates system calls to DOS and BIOS interrupts using
  * functions:
  *      intdos          intdosx         bdos
  *      int86           int86x          segread
  *
  * The int86x call is not specifically shown in the example, but it is
  * the same as intdosx except that an interrupt number must be supplied.
  */

 #include <dos.h>
 #include <stdio.h>
 #define LPT1 0

 union REGS inregs, outregs;
 struct SREGS segregs;

 main()
 {
     const char far *buffer = "Dollar-sign terminated string\n\r$";
     char far *p;

     /* Print a $-terminated string on the screen using DOS function 0x9. */
     inregs.h.ah = 0x9;
     inregs.x.dx = FP_OFF( buffer );
     segregs.ds = FP_SEG( buffer );
     intdosx( &inregs, &outregs, &segregs );

     /* Get DOS version using DOS function 0x30. */
     inregs.h.ah = 0x30;
     intdos( &inregs, &outregs );
     printf( "\nMajor: %d\tMinor: %d\tOEM number: %d\n\n",
             outregs.h.al, outregs.h.ah, outregs.h.bh );

     segread( &segregs );
     printf( "Segments:\n\tCS\t%.4x\n\tDS\t%.4x\n\tES\t%.4x\n\tSS\t%.4x\n\n",
             segregs.cs, segregs.ds, segregs.es, segregs.ss );

     /* Make sure printer is available. Fail if any error bit is on,
      * or if either operation bit is off.
      */
     inregs.h.ah = 0x2;
     inregs.x.dx = LPT1;
     int86( 0x17, &inregs, &outregs );
     if(  (outregs.h.ah & 0x29) || !(outregs.h.ah & 0x80) ||
                                   !(outregs.h.ah & 0x10) )
         printf( "Printer not available." );
     else
     {
         /* Output a string to the printer using DOS function 0x5. */
         for( p = buffer; *p != '$'; p++ )
             bdos( 0x05, *p, 0 );

         /* Do print screen. */
         inregs.h.ah = 0x05;
         int86( 0x05, &inregs, &outregs );
     }
 }


 SYSINFO.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\SYSINFO.C

 /* SYSINFO.C illustrates miscellaneous DOS and BIOS status functions
  * including:
  *      _dos_getdrive       _dos_setdrive       _dos_getdiskfree
  *      _bios_memsize       _bios_equiplist     _bios_printer
  *
  * See DISK.C for another example of _dos_getdiskfree.
  *
  * Also illustrated:
  *      union               bitfield struct
  */

 #include <dos.h>
 #include <bios.h>
 #include <conio.h>
 #include <stdio.h>
 #define LPT1 0

 main()
 {
     struct diskfree_t drvinfo;
     unsigned drive, drivecount, memory, pstatus;
     union
     {                                   /* Access equiment either as:    */
         unsigned u;                     /*   unsigned or                 */
         struct                          /*   bit fields                  */
         {
             unsigned diskflag : 1;      /* Diskette drive installed?     */
             unsigned coprocessor : 1;   /* Coprocessor? (except on PC)   */
             unsigned sysram : 2;        /* Ram on system board           */
             unsigned video : 2;         /* Startup video mode            */
             unsigned disks : 2;         /* Drives 00=1, 01=2, 10=3, 11=4 */
             unsigned dma : 1;           /* 0=Yes, 1=No (1 for PC Jr.)    */
             unsigned comports : 3;      /* Serial ports                  */
             unsigned game : 1;          /* Game adapter installed?       */
             unsigned modem : 1;         /* Internal modem?               */
             unsigned printers : 2;      /* Number of printers            */
         } bits;
     } equip;
     static char y[] = "YES", n[] = "NO";

     /* Get current drive. */
     _dos_getdrive( &drive );
     printf( "Current drive:\t\t\t%c:\n", 'A' + drive - 1 );

     /* Set drive to current drive in order to get number of drives. */
     _dos_setdrive( drive, &drivecount );

     _dos_getdiskfree( drive, &drvinfo );
     printf( "Disk space free:\t\t%ld\n",
             (long)drvinfo.avail_clusters *
             drvinfo.sectors_per_cluster *
             drvinfo.bytes_per_sector );

     /* Get new drive and number of logical drives in system. */
     _dos_getdrive( &drive );
     printf( "Number of logical drives:\t%d\n", drivecount );

     memory = _bios_memsize();
     printf( "Memory:\t\t\t\t%dK\n", memory );

     equip.u = _bios_equiplist();

     printf( "Disk drive installed:\t\t%s\n", equip.bits.diskflag ? y : n );
     printf( "Coprocessor installed:\t\t%s\n", equip.bits.coprocessor ? y : n
     printf( "Game adapter installed:\t\t%s\n", equip.bits.game ? y : n );
     printf( "Serial ports:\t\t\t%d\n", equip.bits.comports );
     printf( "Number of printers:\t\t%d\n", equip.bits.printers );

     /* Fail if any error bit is on, or if either operation bit is off. */
     pstatus = _bios_printer( _PRINTER_STATUS, LPT1, 0 );
     if( (pstatus & 0x29) || !(pstatus & 0x80) || !(pstatus & 0x10) )
         pstatus = 0;
     else
         pstatus = 1;
     printf( "Printer available:\t\t%s\n", pstatus ? y : n );
 }
 


 TABLE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\TABLE.C

 /* TABLE.C illustrates reading and writing formatted file data using
  * functions:
  *      fprintf         fscanf
  */

 #include <stdio.h>
 #include <io.h>
 #include <fcntl.h>
 #include <sys\types.h>
 #include <sys\stat.h>
 #include <stdlib.h>

 main()
 {
     char buf[128];
     FILE *ftable;
     long l, tl;
     float fp, tfp;
     int  i, c = 'A';

     /* Open an existing file for reading. Fail if file doesn't exist. */
     if( (ftable = fopen( "table.smp", "r")) != NULL )
     {
         /* Read data from file and total it. */
         for( i = 0, tl = 0, tfp = 0.0; i < 10; i++ )
         {
             fscanf( ftable, "\t%s %c: %ld %f\n", buf, &c, &l, &fp );
             tl += l;
             tfp += fp;
             printf( "\t%s %c: %7ld %9.2f\n", buf, c, l, fp );
         }
         printf( "\n\tTotal:  %7ld %9.2f\n", tl, tfp );
     }
     else
     {
         /* File did not exist. Create it for writing. */
         if( (ftable = fopen( "table.smp", "w" )) == NULL )
             exit( 1 );

         /* Write table to file. */
         for( i = 0, l = 99999, fp = 3.14; i < 10; i++ )
             fprintf( ftable, "\tLine %c: %7ld %9.2f\n",
                      c++, l /= 2, fp *= 2 );

         printf( "Created table file. Run again to read it.\n" );
     }
     fclose( ftable );
     exit( 0 );
 }


 TEMPNAME.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\TEMPNAME.C

 /* TEMPNAME.C illustrates:
  *      tmpnam          tempnam
  */

 #include <stdio.h>

 main()
 {
     char *name1, *name2;
     int c;

     /* Create several temporary file names in the current directory. */
     for( c = 0; c < 5; c++ )
         if( (name1 = tmpnam( NULL )) != NULL )
             printf( "%s is a safe temporary file name.\n", name1 );

     /* Create a temporary file name with prefix TEMP and place it in
      * the first of these directories that exists:
      *   1. TMP environment directory
      *   2. C:\TEMPFILE
      *   3. P_tmpdir directory (defined in stdio.h)
      */
     if( (name2 = tempnam( "C:\\TEMPFILE", "TEMP" )) != NULL )
         printf( "%s is a safe temporary file name.\n", name2 );

 }


 TEXT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\TEXT.C

 /* TEXT.C illustrates text output functions including:
  *    _gettextcolor   _getbkcolor   _gettextposition   _outtext
  *    _settextcolor   _setbkcolor   _settextposition   _clearscreen
  *
  * See MODES.C for another use of _outtext and WINDOW.C for another
  * use of _clearscreen.
  */

 #include <conio.h>
 #include <stdio.h>
 #include <graph.h>

 char buffer [80];

 main()
 {
     short blink, fgd, oldfgd;
     long bgd, oldbgd;
     struct rccoord oldpos;

     /* Save original foreground, background, and text position. */
     oldfgd = _gettextcolor();
     oldbgd = _getbkcolor();
     oldpos = _gettextposition();
     _clearscreen( _GCLEARSCREEN );

     /* First time no blink, second time blinking. */
     for( blink = 0; blink <= 16; blink += 16 )
     {

         /* Loop through 8 background colors. */
         for( bgd = 0; bgd < 8; bgd++ )
         {
             _setbkcolor( bgd );
             _settextposition( (short)bgd + ((blink / 16) * 9) + 3, 1 );
             _settextcolor( 7 );
             sprintf(buffer, "Back: %d Fore:", bgd );
             _outtext( buffer );

             /* Loop through 16 foreground colors. */
             for( fgd = 0; fgd < 16; fgd++ )
             {
                 _settextcolor( fgd + blink );
                 sprintf( buffer, " %2d ", fgd + blink );
                 _outtext( buffer );
             }
         }
     }
     getch();

     /* Restore original foreground and background. */
     _settextcolor( oldfgd );
     _setbkcolor( oldbgd );
     _clearscreen( _GCLEARSCREEN );
     _settextposition( oldpos.row, oldpos.col );
 }


 TIMES.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\TIMES.C

 /* TIMES.C illustrates various time and date functions including:
  *      time            ftime           ctime
  *      localtime       asctime         gmtime          mktime
  *      _strtime        _strdate        tzset
  *
  * Also the global variable:
  *      tzname
  */

 #include <time.h>
 #include <stdio.h>
 #include <sys\types.h>
 #include <sys\timeb.h>
 #include <string.h>

 main()
 {
     char timebuf[9], datebuf[9];
     static char ampm[] = "AM";
     time_t ltime;
     struct timeb tstruct;
     struct tm *today, *tomorrow, *gmt;

     /* Set time zone from TZ environment variable. If TZ is not set,
      * PST8PDT is used (Pacific standard time, daylight savings).
      */
     tzset();

     /* Get Xenix-style time and display as number and string. */
     time( &ltime );
     printf( "Time in seconds since GMT 1/1/70:\t%ld\n", ltime );
     printf( "Xenix time and date:\t\t\t%s", ctime( &ltime ) );

     /* Display GMT. */
     gmt = gmtime( &ltime );
     printf( "Greenwich Mean Time:\t\t\t%s", asctime( gmt ) );

     /* Convert to local time structure and adjust for PM if necessary. */
     today = localtime( &ltime );
     if( today->tm_hour > 12 )
     {
         strcpy( ampm, "PM" );
         today->tm_hour -= 12;
     }
     /* Note how pointer addition is used to skip the first 11 characters
      * and printf is used to trim off terminating characters.
      */
     printf( "12-hour time:\t\t\t\t%.8s %s\n",
             asctime( today ) + 11, ampm );

     /* Make tomorrow's time. */
     *tomorrow = *today;
     tomorrow->tm_mday++;
     if( mktime( tomorrow ) != (time_t)-1 )
         printf( "Tomorrow's date:\t\t\t%d/%d/%.2d\n",
                 tomorrow->tm_mon + 1, tomorrow->tm_mday, tomorrow->tm_year );

     /* Display DOS date and time. */
     _strtime( timebuf );
     printf( "DOS time:\t\t\t\t%s\n", timebuf );
     _strdate( datebuf );
     printf( "DOS date:\t\t\t\t%s\n", datebuf );

     /* Print additional time information. */
     ftime( &tstruct );
     printf( "Plus miliseconds:\t\t\t%u\n", tstruct.millitm );
     printf( "Zone difference in seconds from GMT:\t%u\n", tstruct.timezone );
     printf( "Time zone name:\t\t\t\t%s\n", tzname[0] );
     printf( "Daylight savings:\t\t\t%s\n", tstruct.dstflag ? "YES" : "NO" );
 }


 TOKEN.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\TOKEN.C

 /* TOKEN.C illustrates tokenizing and searching for any of several
  * characters. Functions illustrated include:
  *      strcspn         strspn          strpbrk         strtok
  */

 #include <string.h>
 #include <stdio.h>

 main()
 {
     char string[100];
     static char vowels[] = "aeiouAEIOU", seps[] = " \t\n,";
     char *p;
     int  count;

     printf( "Enter a string: " );
     gets( string );

     /* Delete one word at a time. */
     p = string;
     while( *p )
     {
         printf( "String remaining: %s\n", p );
         p += strcspn( p, seps );    /* Find next separator     */
         p += strspn( p, seps );     /* Find next non-separator */
     }

     /* Count vowels. */
     p = string;
     count = 0;
     while( *(p - 1) )
     {
         p = strpbrk( p, vowels );   /* Find next vowel         */
         p++;
         count++;
     }
     printf( "\nVowels in string: %d\n\n", count - 1 );

     /* Break into tokens. */
     count = 0;
     p = strtok( string, seps );     /* Find first token        */
     while( p != NULL )
     {
         printf( "Token %d: %s\n", ++count, p );
         p = strtok( NULL, seps );   /* Find next token         */
     }
 }


 TOOLS.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\UTILITY\TOOLS.C

 /* TOOLS - Module containing several general functions that can be used
  * from any program. Include TOOLS.H to use.
  */

 #include <conio.h>
 #include <string.h>
 #include <time.h>
 #include <graph.h>
 #include <bios.h>
 #include "tools.h"

 /* delay - Pauses for a specified number of microseconds. Used to slow
  * life by delaying between generations.
  *
  * Params: wait - time in microseconds
  *
  * Return: None
  */
 void delay( clock_t wait )
 {

     clock_t t1, t2;

     if( !wait )
         return;

     t1 = wait + clock();
     do
     {
         t2 = clock();
     } while( t2 < t1 );
 }

 /* getkey - Gets a key from the keyboard. This routine distinguishes
  * between ASCII keys and function or control keys with different shift
  * states. It also accepts a flag to return immediately if no key is
  * available.
  *
  * Params: waitflag - Code to indicate how to handle keyboard buffer:
  *   NO_WAIT     Return 0 if no key in buffer, else return key
  *   WAIT        Return first key if available, else wait for key
  *   CLEAR_WAIT  Throw away any key in buffer and wait for new key
  *
  * Return: One of the following:
  *
  *   Keytype                                High Byte    Low Byte
  *   -------                                ---------    --------
  *   No key available (only with NO_WAIT)       0           0
  *   ASCII value                                0        ASCII code
  *   Unshifted function or keypad               1        scan code
  *   Shifted function or keypad                 2        scan code
  *   CTRL function or keypad                    3        scan code
  *   ALT function or keypad                     4        scan code
  *
  * Note:   getkey cannot return codes for keys not recognized by BIOS
  *         int 16, such as the CTRL-UP or the 5 key on the numeric keypad.
  */
 unsigned getkey( int waitflag )
 {
     unsigned inkey, shiftstate;

     /* If CLEAR_WAIT, drain the keyboard buffer. */
     if( waitflag == CLEAR_WAIT )
         while( _bios_keybrd( _KEYBRD_READY ) )
             _bios_keybrd( _KEYBRD_READ );

     /* If NO_WAIT, return 0 if there is no key ready. */
     if( !waitflag && !_bios_keybrd( _KEYBRD_READY ) )
         return FALSE;

     /* Get key code. */
     inkey = _bios_keybrd( _KEYBRD_READ );

     /* If low byte is not zero, its an ASCII key. Check scan code to see
      * if it's on the numeric keypad. If not, clear high byte and return.
      */
     if( inkey & 0x00ff )
         if( (inkey >> 8) < 69 )
             return( inkey & 0x00ff );

     /* For function keys and numeric keypad, put scan code in low byte
      * and shift state codes in high byte.
      */
     inkey >>= 8;
     shiftstate = _bios_keybrd( _KEYBRD_SHIFTSTATUS ) & 0x000f;
     switch( shiftstate )
     {
         case 0:
             return( 0x0100 | inkey );  /* None (1)    */
         case 1:
         case 2:
         case 3:
             return( 0x0200 | inkey );  /* Shift (2)   */
         case 4:
             return( 0x0300 | inkey );  /* Control (3) */
         case 8:
             return( 0x0400 | inkey );  /* Alt (4)     */
     }
 }


 TOUCH1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\TOUCH1.C

 /* TOUCH.C illustrates wild card handling and changing file time and
  * attribute. Functions used include:
  *      _dos_findfirst      _dos_findnext
  *      utime               chmod
  */

 #include <stdlib.h>
 #include <stdio.h>
 #include <conio.h>
 #include <ctype.h>
 #include <dos.h>
 #include <io.h>
 #include <sys\types.h>
 #include <sys\utime.h>
 #include <sys\stat.h>

 void fileinfo( struct find_t *find );
 char *timestr( unsigned d, char *buf );
 char *datestr( unsigned d, char *buf );

 main( int argc, char *argv[] )
 {
     struct find_t find;

     /* Find first matching file, then find additional matches. */
     if( !_dos_findfirst( argv[1], 0xffff, &find ) )
         fileinfo( &find );
     else
     {
         printf( "  SYNTAX: TOUCH <wildfilespec>" );
         return 1;
     }
     while( !_dos_findnext( &find ) )
         fileinfo( &find );
 }

 void fileinfo( struct find_t *pfind )
 {
     char timebuf[10], datebuf[10], *pkind;
     int ch;

     datestr( pfind->wr_date, datebuf );
     timestr( pfind->wr_time, timebuf );

     if( pfind->attrib & _A_SUBDIR )
         pkind = "Directory";
     else if( pfind->attrib & _A_VOLID )
         pkind = "Label";
     else
         pkind = "File";

     printf( "%-12s   %6ld   %8s   %9s   %-9s    %c %c %c %c\n",
             pfind->name, pfind->size, timebuf, datebuf, pkind,
             (pfind->attrib & _A_RDONLY) ? 'R' : ' ',
             (pfind->attrib & _A_HIDDEN) ? 'H' : ' ',
             (pfind->attrib & _A_SYSTEM) ? 'S' : ' ',
             (pfind->attrib & _A_ARCH) ? 'A' : ' ' );

     printf( "(T)ime update   (R)ead only   (Q)uit   Any other next\n" );
     ch = getch();
     switch( toupper( ch ) )
     {
         case 'T':               /* Set to current time */
             utime( pfind->name, NULL );
             break;
         case 'R':               /* Toggle read only */
             if( pfind->attrib & _A_RDONLY )
                 chmod( pfind->name, S_IWRITE );
             else
                 chmod( pfind->name, S_IREAD );
             break;
         case 'Q':               /* Quit */
             exit( 1 );
     }
 }

 /* Take unsigned date in the format:    fedcba9876543210
  * (year is 1980 - year)                yyyyyyymmmmddddd
  * Change to a 9-byte string:           mm/dd/yy
  */
 char *datestr( unsigned d, char *buf )
 {
     sprintf( buf, "%2.2d/%02.2d/%02.2d",
              (d >> 5) & 0x0f, d & 0x1f, (d >> 9) + 80 );
     return buf;
 }

 /* Take unsigned time in the format:                fedcba9876543210
  * (hours and minutes 0-based)                      hhhhhmmmmmmsssss
  * Change to a 9-byte string (ignore seconds):      hh:mm ?m
  */
 char *timestr( unsigned t, char *buf )
 {
     int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;

     sprintf( buf, "%2.2d:%02.2d %cm", h % 12, m,  h > 11 ? 'p' : 'a' );
     return buf;
 }


 TRIG.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\MATH\TRIG.C

 /* TRIG.C illustrates trignometric functions including:
  *    cos          cosh           acos
  *    sin          sinh           asin
  *    tan          tanh           atan          atan2
  */

 #include <math.h>
 #include <float.h>
 #include <stdio.h>
 #include <stdlib.h>

 main()
 {
     double x, rx, y;

     do
     {
         printf( "\nEnter a real number between 1 and -1: " );
         scanf( "%lf", &x );
     } while( (x > 1.0) || (x < -1.0) );

     printf("\nFunction\tResult for %2.2f\n\n", x );
     if( (x <= 1.0) && (x >= -1.0) )
     {
         printf( "acos\t\t%2.2f\n", acos( x ) );
         printf( "asin\t\t%2.2f\n", asin( x ) );
     }
     if( (rx = cos( x )) && (errno != ERANGE) )
         printf( "cos\t\t%2.2f\n", rx );
     else
         errno = 0;
     if( (rx = sin( x )) && (errno != ERANGE) )
         printf( "sin\t\t%2.2f\n", rx );
     else
         errno = 0;
     if( (rx = cosh( x )) && (errno != ERANGE) )
         printf( "cosh\t\t%2.2f\n", rx );
     else
         errno = 0;
     if( (rx = sinh( x )) && (errno != ERANGE) )
         printf( "sinh\t\t%2.2f\n", rx );
     else
         errno = 0;

     printf( "\nEnter a real number of any size: " );
     scanf( "%lf", &x );
     printf("\nFunction\tResult for %2.2f\n\n", x );
     printf( "atan\t\t%2.2f\n", atan( x ) );
     if( (rx = tan( x )) && (errno != ERANGE) )
         printf( "tan\t\t%2.2f\n", rx );
     else
         errno = 0;
     printf( "tanh\t\t%2.2f\n", tanh( x ) );

     printf( "\nEnter another real number of any size: " );
     scanf( "%lf", &y );
     printf("\nFunction\tResult for %2.2f and %2.2f\n\n", x, y );
     if( rx = atan2( x, y ) )
         printf( "atan2\t\t%2.2f\n", rx );
     else
         errno = 0;
 }


 TRUTH.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\TRUTH.C

 /* TRUTH.C: Demonstrate true and false values. */

 #include <stdio.h>

 main()
 {
    printf( "C generates %d for true\n", 2 == 2 );
    printf( "C generates %d for false\n", 2 == 4 );
    if( -33 )
       printf( "C recognizes any nonzero value as true\n" );
 }


 TYPEIT.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\FILE\TYPEIT.C

 /* TYPEIT.C illustrates reassigning handles and streams using functions:
  *      freopen         dup             dup2
  *
  * The example also illustrates:
  *      setargv
  *
  * To make the program handle wild cards, link it with the SETARGV.OBJ
  * file. You can do this in the QC environment by creating a program list
  * containg TYPEIT.C and SETARGV.OBJ (include the path or put in current
  * directory). You must also turn off the Extended Dictionary flag
  * within the QC environment (Options-Make-Linker Flags) or use the /NOE
  * linker option outside the environment. For example:
  *    QCL typeit.c setargv /link /NOE
  */

 #include <stdio.h>
 #include <conio.h>
 #include <io.h>
 #include <process.h>

 main( int argc, char **argv )
 {
     FILE *ftmp;
     int htmp;

     /* Duplicate handle of stdin. Save the original to restore later. */
     htmp = dup( fileno( stdin ) );

     /* Process each command line argument. */
     while( *(++argv) != NULL )
     {
         /* Original stdin used for getch. */
         printf( "Press any key to display file: %s\n", *argv );
         getch();

         /* Reassign stdin to input file. */
         ftmp = freopen( *argv, "rb", stdin );

         if( (ftmp == NULL) || (htmp == -1 ) )
         {
             perror( "Can't reassign standard input" );
             exit( 1 );
         }

         /* Spawn MORE, which will receive the open input file as its standard
          * input. MORE can be the DOS MORE or the sample program MORE.C.
          */
         spawnvp( P_WAIT, "MORE", NULL );

         /* Reassign stdin back to original so that we can use the
          * original stdin to get a key.
          */
         dup2( htmp, fileno( stdin ) );
     }
     exit( 0 );
 }


 TYPES.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\TYPES.C

 /* TYPES.C: Illustrate basic data types. */

 #include <stdio.h>

 main()
 {
    char char_val        = 'a';
    int int_val               = 543;
    float float_val     = 11.1;
    double double_val   = 66.123456789;
    printf( "char_val   = %c\n", char_val );
    printf( "int_val    = %d\n", int_val );
    printf( "float_val  = %f\n", float_val );
    printf( "double_val = %2.9f\n", double_val );
 }


 UNGET.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\UNGET.C

 /* UNGET.C illustrates getting and ungetting characters from the console.
  * Functions illustrated include:
  *      getch           ungetch         putch
  */

 #include <conio.h>
 #include <stdio.h>
 #include <ctype.h>

 void skiptodigit( void );
 int getnum( void );

 main()
 {
     int c, array[10];

     /* Get five numbers from console. Then display them. */
     for( c = 0; c < 5; c++ )
     {
         skiptodigit();
         array[c] = getnum();
         printf( "\t" );
     }
     for( c  = 0; c < 5; c++ )
         printf( "\n\r%d", array[c] );
     printf( "\n" );
 }

 /* Convert digit characters into a number until a non-digit is received. */
 int getnum()
 {
     int ch, num =  0;

     while( isdigit( ch = getch() ) )
     {
         putch( ch );                        /* Display digit      */
         num = (num * 10) + ch  - '0';       /* Convert to number  */
     }
     ungetch( ch );                          /* Put non-digit back */
     return num;                             /* Return result      */
 }

 /* Throw away non-digit characters. */
 void skiptodigit()
 {
     int ch;

     while( !isdigit( ch = getch() ) )
         ;
     ungetch( ch );
 }


 VARARG.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\VARARG.C

 /* VARARG.C illustrates passing a variable number of arguments using the
  * following macros:
  *      va_start            va_arg              va_end
  *      va_list             va_decl (Unix only)
  */

 #include <stdio.h>
 ANSI            /* Comment out for UNIX version     */
 ANSI             /* ANSI compatible version          */
 #include <stdarg.h>
 int average( int first, ... );
                   /* UNIX compatible version          */
 #include <varargs.h>
 int average( va_list );
 #endif

 main()
 {
     /* Call with 3 integers. Minus -1 is used as terminator.  */
     printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );

     /* Call with 4 integers. */
     printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );

     /* Call with just -1 terminator. */
     printf( "Average is: %d\n", average( -1 ) );
 }

 /* Return the average of a variable list of integers. */
 ANSI             /* ANSI compatible version    */
 int average( int first, ... )
 {
     int count = 0, sum = 0, i = first;
     va_list marker;

     va_start( marker, first );      /* Initialize variable arguments */
     while( i != -1 )
     {
         sum += i;
         count++;
         i = va_arg( marker, int);
     }
     va_end( marker );               /* Reset variable arguments      */
     return( sum ? (sum / count) : 0 );
 }
       /* UNIX compatible version must use old-style definition */
 int average( va_alist )
 va_dcl
 {
     int i, count, sum;
     va_list marker;

     va_start( marker );             /* Initialize variable arguments */
     for( sum = count = 0; (i = va_arg( marker, int)) != -1;  count++ )
         sum += i;
     va_end( marker );               /* Reset variable arguments      */
     return( sum ? (sum / count) : 0 );
 }
 #endif


 VISIBLE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\VISIBLE.C

 /* VISIBLE.C: Demonstrate visibility of variables.
 */

 #include <stdio.h>
 void be_bop( void );

 main()
 {
    int var1 = 10;
    be_bop();
 }

 void be_bop( void )
 {
    printf( "var1 = %d", var1 ); /* Error! */
 }


 VISIBLE1.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\VISIBLE1.C

 /* VISIBLE1.C: Demonstrate visibility of variables.
 */

 #include <stdio.h>

 void be_bop( int param );

 main()
 {
    int var1 = 10;
    be_bop( var1 );
 }

 void be_bop( int param )
 {
    printf( "%d\n", param );
 }


 VISIBLE2.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\VISIBLE2.C

 /* VISIBLE2.C: Demonstrate visibility of variables.
 */

 #include <stdio.h>

 void be_bop( int param );

 main()
 {
    be_bop( var1 ); /* Error! */
 }

 int var1 = 10;

 void be_bop( int param )
 {
    printf( "var1 = %d\n", param );
 }


 VOLUME.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\VOLUME.C

 /* VOLUME.C: Calculate sphere's volume. */

 #include <stdio.h>
 #define PI 3.14

 float sphere( int rad );

 main()
 {
    float volume;
    int radius = 3;
    volume = sphere( radius );
    printf( "Volume: %f\n", volume );
 }

 float sphere( int rad )
 {
    float result;
    result = rad * rad * rad;
    result = 4 * PI * result;
    result = result / 3;
    return result;
 }


 WHILE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\WHILE.C

 /* WHILE.C: Demonstrate while loop. */

 #include <stdio.h>

 main()
 {
    int test = 10;

 while( test > 0 )
    {
       printf( "test = %d\n", test );
       test -= 2;
    }
 }


 WINDOW.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\WINDOW.C

 /* WINDOW.C illustrates windows and coordinate systems, using the
  * following functions:
  *    _setviewport   _setvieworg    _setcliprgn     _setwindow
  *    _rectangle     _rectangle_w   _rectangle_wxy  _clearscreen
  *    _ellipse       _ellipse_w     _ellipse_wxy
  *
  * Although not all illustrated here, functions ending in _w
  * are similar to _rectangle_w and _ellipse_w; functions ending
  * in _wxy are similar to _rectangle_wxy and _ellipse_wxy.
  */

 #include <conio.h>
 #include <graph.h>
 #include <stdlib.h>

 main()
 {
     short xhalf, yhalf, xquar, yquar;
     struct _wxycoord upleft, botright;
     struct videoconfig vc;
     short mode = _VRES16COLOR;

     while( !_setvideomode( mode ) )     /* Find best graphics mode   */
         mode--;
     if( mode == _TEXTMONO )
         exit( 1 );                      /* No graphics available     */
     _getvideoconfig( &vc );

     xhalf = vc.numxpixels / 2;
     yhalf = vc.numypixels / 2;
     xquar = xhalf / 2;
     yquar = yhalf / 2;

     /* First window - integer physical coordinates */
     _setviewport( 0, 0, xhalf - 1, yhalf - 1 );
     _rectangle( _GBORDER, 0,  0, xhalf - 1, yhalf - 1 );
     _ellipse( _GFILLINTERIOR, xquar / 4, yquar / 4,
                               xhalf - (xquar / 4), yhalf - (yquar / 4) );
     getch();
     _clearscreen( _GVIEWPORT );
     _rectangle( _GBORDER, 0,  0, xhalf - 1, yhalf - 1 );

     /* Second window - integer world coordinates with clip region */
     _setcliprgn( xhalf, 0, vc.numxpixels, yhalf );
     _setvieworg( xhalf + xquar - 1, yquar - 1 );
     _rectangle( _GBORDER, -xquar + 1, -yquar + 1, xquar, yquar );
     _ellipse( _GFILLINTERIOR, (-xquar * 3) / 4, (-yquar * 3) / 4,
                               (xquar * 3) / 4, (yquar * 3) / 4 );
     getch();
     _clearscreen( _GVIEWPORT );
     _rectangle( _GBORDER, -xquar + 1, -yquar + 1, xquar, yquar );

     /* Third window */
     _setviewport( xhalf, yhalf, vc.numxpixels - 1, vc.numypixels - 1 );
     _setwindow( 0, -4.0, -5.0, 4.0, 5.0 );
     _rectangle_w( _GBORDER, -4.0, -5.0, 4.0, 5.0 );
     _ellipse_w( _GFILLINTERIOR, -3.0, -3.5, 3.0, 3.5 );
     getch();
     _clearscreen( _GVIEWPORT );
     _rectangle_w( _GBORDER, -4.0, -5.0, 4.0, 5.0 );

     /* Fourth window */
     _setviewport( 0, yhalf, xhalf - 1, vc.numypixels - 1 );
     _setwindow( 0, -4.0, -5.0, 4.0, 5.0 );
     upleft.wx = -4.0;
     upleft.wy = -5.0;
     botright.wx = 4.0;
     botright.wy = 5.0;
     _rectangle_wxy( _GBORDER, &upleft, &botright );
     upleft.wx = -3.0;
     upleft.wy = -3.5;
     botright.wx = 3.0;
     botright.wy = 3.5;
     _ellipse_wxy( _GFILLINTERIOR, &upleft, &botright );

     getch();
     exit( !_setvideomode( _DEFAULTMODE ) );
 }


 WPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\GRAPHICS\WPRINTF.C

 /* WPRINTF.C shows how to use vprintf functions to write new versions
  * of printf. Functions illustrated include:
  *      vsprintf        vprintf         vfprintf
  *
  * The vsprintf function is used in the example. The other variations
  * can be used similarly.
  */

 #include <stdio.h>
 #include <graph.h>
 #include <string.h>
 #include <stdarg.h>
 #include <malloc.h>

 int wprintf( short row, short col, short clr, long bclr, char *fmt, ... );

 main()
 {
     short fgd = 0;
     long  bgd = 0L;

     _clearscreen( _GCLEARSCREEN );
     _outtext( "Color text example:\n\n" );

     /* Loop through 8 background colors. */
     for( bgd = 0L; bgd < 8; bgd++ )
     {
         wprintf( (int)bgd + 3, 1, 7, bgd, "Back: %d Fore:", bgd );

         /* Loop through 16 foreground colors. */
         for( fgd = 0; fgd < 16; fgd++ )
             wprintf( -1, -1, fgd, -1L, " %2d ", fgd );
     }
 }

 /* Full-screen window version of printf that takes row, column, textcolor,
  * and background color as its first arguments, followed by normal printf
  * format strings (except that \t is not handled). You can specify -1 for
  * any of the first arguments to use the current value. The function returns
  * the number of characters printed, or a negative number for errors.
  */
 int wprintf( short row, short col, short clr, long bclr, char *fmt, ... )
 {
     struct  rccoord tmppos;
     short   ret, size;
     va_list marker;
     char    *buffer;

     /* It's probably safe to use a buffer 512 bytes long or five times
      * longer than the format string.
      */
     size = strlen( fmt );
     size = (size > 512) ? 512 : size * 5;
     if( (buffer = (char *)malloc( size )) == NULL )
         return -1;

     /* Set text position. */
     tmppos = _gettextposition();
     if( row < 1 )
         row = tmppos.row;
     if( col < 1 )
         col = tmppos.col;
     _settextposition( row, col );

     /* Set foreground and background colors. */
     if( clr >= 0 )
         _settextcolor( clr );
     if( bclr >= 0 )
         _setbkcolor( bclr );

     /* Write text to a string and output the string. */
     va_start( marker, fmt );
     ret = vsprintf( buffer, fmt, marker );
     va_end( marker );
     _outtext( buffer );
     free( buffer );
     return ret;
 }


 WRAP.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\WRAP.C

 /* WRAP.C illustrates:
  *      _wrapon
  */

 #include <conio.h>
 #include <graph.h>

 main()
 {
     _wrapon( _GWRAPON );
     while( !kbhit() )
         _outtext( "Wrap on! " );

     getch();
     _clearscreen( _GCLEARSCREEN );
     _wrapon( _GWRAPOFF );
     while( !kbhit() )
         _outtext( "Wrap off!" );
     getch();
 }


 WRFILE.C
 CD-ROM Disc Path:   \SAMPCODE\C\OTHER\LEARN\WRFILE.C

 /* WRFILE.C: Creates and writes to a disk file. */

 #include <stdio.h>

 main()
 {
    FILE *fp;

    if( (fp = fopen( "c:\\testfile.asc","w" )) != NULL )
    {
       fputs( "Example string", fp );
       fputc( '\n', fp );
       fclose( fp );
    }
    else
       printf( "error message\n" );
 }
 ALDE Public Domain Sample Code


 2UP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\2UP.C

 /*
         HEADER:                CUG236;
         TITLE:                Multi-Column Output Stacker;
         DATE:                05/23/87;
         DESCRIPTION:        "Formats text into one or more columns.  Has seve
                         command line parameters that can be set.";
         KEYWORDS:        Software tools, Text filters, Text formatters;
         FILENAME:        2UP.C;
         WARNINGS:        "The author claims copyrights and authorizes
                         non-commercial use only.";
         AUTHORS:        Eugene H. Mallory, William C. Colley III;
         COMPILERS:        vanilla;
 */

 /*********************************************************************
 *                                2UP                                     *
 **********************************************************************
 *                   COPYRIGHT 1983 EUGENE H. MALLORY                     *
 *                                                                     *
 * Hacked from BDS C to portable C 23 MAY 1987 by W. C. Colley, III.  *
 * This involved removing the -w option as it relies upon a non-             *
 * portable direct console I/O call.  In the process, I also reworked *
 * the thing into standard C puncutation and optimized various             *
 * sections of code so that even a stupid compiler can make a good    *
 * executable from it.                                                     *
 *                                                                     *
 *********************************************************************/

 #include <stdio.h>

 #define MAXW                132

 /*  Portability Note:  8-bit systems often don't have header file
     ctype.h.  If your system doesn't have it, uncomment the #define
     NO_CTYPE_H.

 /*
 #define         NO_CTYPE_H
 */

 /*  Portability Note:  Some older compilers don't know the new data
     type void.        If yours is one of these compilers, uncomment the
     following #define:

 /*
 #define void                int
 */

 #ifdef         NO_CTYPE_H
 int isdigit();
 #else
 #include <ctype.h>
 #endif

 #ifndef TRUE
 #define TRUE  1
 #endif

 #ifndef FALSE
 #define FALSE 0
 #endif

 char string[MAXW + 2];
 char array[90][MAXW + 2];
 int ncol = 0, col = 0, len = 0, margin = 0, space = 0, width;
 int bm = 0, doneflag = FALSE, tm = 0;
 void exit();

 int main(argc,argv)
 int argc;
 char **argv;
 {
     int i, j, k, atoi();
     void error(), strmov();

 /*********************************************************************
 ***                  ARGUMENT PROCESSING                                   **
 *********************************************************************/

     char c, *ss;
     int ii, jj, optionerr;

     optionerr = 0;
     for (ii = argc - 1; ii > 0; --ii)
         if (argv[ii][0] == '-') {
             for (ss = &argv[ii][1]; *ss != '\0';) {
                 c = *ss++;
                 switch (toupper(c)) {
                     case 'L':        len = atoi(ss);         break;

                     case 'C':        col= atoi(ss);        break;

                     case 'M':        margin = atoi(ss);  break;

                     case 'T':        tm = atoi(ss);        break;

                     case 'B':        bm = atoi(ss);        break;

                     case 'S':        space = atoi(ss);  break;

                     case 'N':        ncol= atoi(ss);         break;

                     case 'H':        optionerr = TRUE;  break;

                     default:        fprintf(stderr,"2UP: Illegal option %c.\n
                                 optionerr = TRUE;  break;
                 }
                 while (isdigit(*ss)) ss++;
             }
             for (jj = ii; jj < (argc-1); ++jj) argv[jj] = argv[jj + 1];
             argc--;
         }
     if (optionerr) {
         fprintf(stderr,"2UP:   Legal options are:\n");
         fprintf(stderr,"-Ln    Page length.\n");
         fprintf(stderr,"-Cn    Column width .\n");
         fprintf(stderr,"-Mn    Margin.\n");
         fprintf(stderr,"-Tn    Top margin.\n");
         fprintf(stderr,"-Bn    Bottom margin.\n");
         fprintf(stderr,"-Sn    Space between columns.\n");
         fprintf(stderr,"-Nn    Number of columns.\n");
         return !0;
     }
     if (ncol == 0) ncol = 2;
     if (len == 0) len = 66;
     if (col == 0) col = (80 - margin - space * (ncol - 1)) / ncol;
     if (len > 88) error("2UP: Too long a page, 88 lines is maximum.");
     if ((margin + ncol * col + (ncol - 1) * space) > MAXW)
         error("2UP: Total width exceeds 132.");
     len = len - tm - bm;
     if (len < 1) error("2UP: Insufficient length.");

 /*********************************************************************
 ***                     END OF ARGUMENT PROCESSING
 *********************************************************************/
 /*********************************/
 /*        MAIN LOOP                 */
 /*********************************/
     width = margin + ncol * col + (ncol - 1) * space;
     do {
         for (i = 1; i <= len; ++i)
             for (j = 1;j <= MAXW + 1; ++j) array[i][j] = ' ';
         for (k = 0; k < ncol; ++k) {
             for (i = 1; i <= len; ++i) {
                 if (gets(string))
                     strmov(&array[i][margin+k*col+k*space+1],string,col);
                 else {
                     if (!k && i == 1) return 0;
                     doneflag = TRUE;  goto end_of_file;
                 }
             }
         }
 end_of_file:
         for (i = 1; i <= tm; ++i) puts("\n");
         for (i = 1; i <= len; ++i) {
             for (j = MAXW + 1; j; --j)
                 if (array[i][j] != ' ' || j == 1) {
                     array[i][j+1] = 0;        break;
                 }
             puts(&array[i][1]);
         }
         for (i = bm; i; --i) puts("\n");
     } while (!doneflag);
     return 0;
 }

 void strmov(s1,s2,n)
 char *s1,*s2;
 int n;
 {
     char c;

     while (n--) {
         if (!(c = *s2++) || c == '\n') break;
         *s1++ = c;
     }
 }

 void error(msg)
 char *msg;
 {
     fprintf(stderr,"%s\n",msg);
     exit(!0);
 }


 ABORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\ABORT.C

 #include <stdio.h>

 void abort()
 /*
  *        Prints the message "Abnormal program termination" to stderr and
  *        calls _exit() with a status code of 3.
  */
 {
         fputs("Abnormal program termination\n", stderr);
         fflush(stderr);
         _exit(3);
 }


 ABOUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\ABOUT\ABOUT.C

 /*  about.c
 *
 *   Usage:           about  <name>  [<catfile>]
 *
 *   Examples:        about calloc
 *                    about *
 *                    about * b:c.cat
 *                    about fourier b:math.dat
 *
 *    Description:    For each line in <catfile> beginning as ":<name>",
 *                    successive lines are displayed until the next line
 *                    begins with ":";  if <name> is *, all entries are
 *                    displayed;  <catfile> defaults to "about.dat".
 *
 *    Purpose:        The file about.dat contains synopses of C functions,
 *                    thus making "about" an elementary "help facility".
 *
 *                    However, <catfile> may be any list of :<name>'s of
 *                    interest, with each name on a separate line, and
 *                    each followed by its respective text to be displayed.
 *
 *    Limitations:    A simple linear search is used, so probably no more
 *                    than a few hundred names can be handled usefully.
 *
 *    Language:       C (DeSmet 2.4)
 *
 *    Author:         R. E. Sawyer
 *                    3620 Spencer St. 30, Torrance, CA 90503
 *                    1 Jan 85
 */

 #define CATFILE "about.dat"
 #define DEFCHAR ':'
 #define BUFLEN 82

 int fin;

 main(ac, av)
     int ac;
     char *av[];
     {
     char *catfile;
     char buf[BUFLEN];
     int showall;
     int done;
     int more;

     showall = 0;
     done = 0;

     if ((ac < 2) || (ac > 3))
         {
         printf("\nUsage:    about  <name>  [<catfile>]\n");
         printf("\nFor each line in <catfile> beginning as \":<name>\",");
         printf("\nsuccessive lines are displayed until the next line");
         printf("\nbegins with \":\";  if <name> is *, all entries are");
         printf("\ndisplayed;  <catfile> defaults to \"about.dat\".\n");
         exit();
         }
     else if (ac == 2)
         {
         if ((fin = fopen(catfile = CATFILE, "r")) == 0)
             {
             printf("\n---File %s not found", catfile);
             exit();
             }
         }
     else if (ac ==3)
         {
         if ((fin = fopen(catfile = av[2], "r")) == 0)
             {
             printf("\n---File %s not found", catfile);
             exit();
             }
         }
     if (*av[1] == '*')
         showall = 1;
     printf("\n(Catalogue file:  %s)\n\n", catfile);
     more = fgets(buf, BUFLEN - 1, fin);
     while (more)
         {
         if ((buf[0] == DEFCHAR)
             && ((comp(av[1], buf + 1) == 0) || showall))
             {
             more = print_text(buf);
             if (!showall)
                 {
                 done = 1;
                 break;
                 }
             }
         else
             more = fgets(buf, BUFLEN - 1, fin);
         }
     if ((done != 1) && !showall)
         printf("\"%s\" is not catalogued\n\n", av[1]);
     fclose(fin);
     }

 int comp(s, t)
     char *s, *t;
     {
     int i;

     for (i = 0; (t[i] > ' ') && (t[i] <= '~'); ++i)
         ;
     t[i] = '\0';
     return strcmp(s, t);
     }

 int print_text(buf)
     char buf[];
     {
     int more;
     printf("%s:\n", &buf[1]);
     while (((more = fgets(buf, BUFLEN - 1, fin)) != 0)
         && (buf[0] != DEFCHAR))
         {
         puts(buf);
         }
     return more;
     }


 ABS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ABS.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         int
 abs(n)                        /* return the integer absolute value of int n

 /*----------------------------------------------------------------------*/
 int n;
 {
         return ABS(n);
 }


 ABSREAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\ABSREAD.C

 #include <dos.h>
 /****************************************************************************
 *
 *  absolute disk read (calls disk bios) 0x80 = 1st hard disk
 *
 *****************************************************************************
 absread(drive,cyl,head,record,count,buffer)
 int drive, cyl, head, record, count;
 char *buffer;
 {
   union  REGS  reg;
   struct SREGS seg;
   int err = 0;
   segread(&seg);
   reg.h.ch = (cyl & 0x00ff);             /* lo order cylinder */
   reg.h.cl = (((cyl & 0xff00) << 6) | record);
   reg.h.dh = head;
   reg.h.dl = drive;
   reg.h.al = count;
   reg.h.ah = 2;
   reg.x.bx = (unsigned int) buffer;                    /* point to buffer */
   err = int86x(0x13,&reg,&reg,&seg); /* read the disk */
   err = (err >> 8);
   return(err);
 }


 ADD1TO2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\ADD1TO2.C

 /*              Example: Add 1 to 2 and Print It
  */

 /*      main()

         Function: Add 1 and 2 and print the result.

         Algorithm: Call add to add the two numbers, and printf to print them.
 */

 main()

 {
         printf("1 + 2 = %d.\n",add(1,2));
 }



 ADDLF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\ADDLF.C

 /* addlf -- copy input to output; add line-feeds only if necessary.
  *            WHRauser   10-4-83                   a better mouse trap.
  */
 <stdio.h>           /* Microsoft C  Ver 1.04 */

  CR  0x000D           /* carriage return */
  LF  0x000A           /* line feed */
 #define  TRUE          1
 #define  FALSE          0

 main()            /* copy input to output and add line-feeds only if needed.
 {
     int  c;
     int  addlf = FALSE;

     while ((c = getchar()) != EOF) {
          if (addlf  &  c != LF) {
               putchar(LF);
               addlf = FALSE;
          }
          putchar(c);
          if (c == CR)  addlf = TRUE;
     }
 }


 ADDLF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TABS\ADDLF.C


 /* addlf -- copy input to output; add line-feeds only if necessary.
  *          WHRauser   10-4-83             a better mouse trap.
  */
 <stdio.h>         /* Microsoft C  Ver 1.04 */

  CR  0x000D        /* carriage return */
  LF  0x000A        /* line feed */
 #define  TRUE     1
 #define  FALSE    0

 main()      /* copy input to output and add line-feeds only if needed. */
 {
     int  c;
     int  addlf = FALSE;

     while ((c = getchar()) != EOF) {
          if (addlf  &  c != LF) {
               putchar(LF);
               addlf = FALSE;
          }
          putchar(c);
          if (c == CR)  addlf = TRUE;
     }
 }



 AGENT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\AGENT.C

 /* AGENTS.C - From "Microsoft C Programming for the IBM, page   */
 /* 300, by Robert Lafore. The program uses an array of struct-  */
 /* ures to maintain a list of agents in memory. It is also a    */
 /* continuation of the development of a simple database started */
 /* on page 292.                                                 */
 /****************************************************************/

 #include <stdio.h>
 #define TRUE 1

 struct personnel {
    char name [30];
    int agnumb;
    float height;
 };
 struct personnel agent[50];      /*array of 50 structures*/
 int n = 0;

 main()
 {
 char ch;

    while(TRUE) {
       printf("\nType 'e' to enter new agent");
       printf("\n  'L' to list all agents: ");
       ch = getche();
       switch (ch) {
          case 'e':
             newname();
             break;
          case 'L':
             listall();
             break;
          default:
             puts("\nEnter only selections listed");
       }
    }
 }

 /* newname */
 /* puts a new agent in the database */
 newname()
 {
    printf("\nRecord %d: \nEnter name: ", n + 1);
    gets(agent[n].name);
    printf("Enter agent number (3 digits): ");
    scanf("%d", &agent[n].agnumb);
    printf("Enter height in inches: ");
    scanf("%f", &agent[n++].height);
    fflush(stdin);
 }

 /* listall() */
 /* lists all agents and data */
 listall()
 {
 int j;

    if (n < 1)
       printf("\nEmpty list.\n");
    for(j = 0; j < n; j++) {
       printf("\nRecord number %d\n", j + 1);
       printf("   Name: %s\n", agent[j].name);
       printf("   Agent number: %03d\n", agent[j].agnumb);
       printf("   Height: %4.2f\n", agent[j].height);
    }
 }



 AGENT2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\AGENT2.C

 /* AGENT2.C - From page 309 of "Microsoft C Programming for the */
 /* IBM by Robert Lafore. This is the final program of the data- */
 /* base started on page 292. it uses linked lists.              */
 /****************************************************************/

 <stdio.h>           /*defines 'stdin'*/
 #define TRUE 1
 struct prs {
    char name[30];
    int agnumb;
    float height;
    struct prs *ptrnext;       /*ptr to next structure*/
 };
 struct prs *ptrfirst, *ptrthis, *ptrnew;

 main()
 {
 char ch;

    ptrfirst = (struct prs *)NULL;         /*no input yet*/
    while (TRUE) {
       printf("\nType 'e' to enter new agent");
       printf("\n  'L' to list all agents: ");
       ch = getche();
       switch (ch) {
          case 'e':
             newname();
             break;
          case 'L':
             listall();
             break;
          default:
             puts("\nEnter only selections listed");
       }
    }
 }

 /* newname() */      /*puts a new agent in the database*/
 newname()
 {
    ptrnew = (struct prs *) malloc(sizeof(struct prs));
    if (ptrfirst == (struct prs *)NULL)  /*if none already, save addr*/
       ptrfirst = ptrthis = ptrnew;
    else {                     /*not first item, go to end of list*/
       ptrthis = ptrfirst;     /* (start at begin ) */
       while (ptrthis->ptrnext != (struct prs *)NULL)
          ptrthis = ptrthis->ptrnext;      /*find next item*/
       ptrthis->ptrnext = ptrnew;          /*pt to new item*/
       ptrthis = ptrnew;                   /*go to new item*/
    }
    printf("\nEnter name: ");
    gets(ptrthis->name);
    printf("Enter number: ");
    scanf("%d", &ptrthis->agnumb);
    printf("Enter height: ");
    scanf("%f", &ptrthis->height);
    fflush(stdin);
    ptrthis->ptrnext = (struct prs *)NULL;    /*this is end*/
 }

 /* listall() */      /*lists all agents and data */
 listall()
 {
    if (ptrfirst == (struct prs *)NULL) {  /*if empty list*/
       printf("\nEmpty list.\n");
       return;
    }
    ptrthis = ptrfirst;           /*start at first item*/
    do {
       printf("\nName: %s\n", ptrthis->name);
       printf("Number: %03d\n", ptrthis->agnumb);
       printf("Height: %4.2f\n", ptrthis->height);
       ptrthis = ptrthis->ptrnext;      /*move to next item*/
    } while(ptrthis != (struct prs *)NULL);   /*quit on null ptr*/
 }



 AGENTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\AGENTR.C

 /* AGENTR.C - From page 453 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. This is a simple database program.*/
 /* I added 2 if statements to file in book. One is after else   */
 /* statement in rfile() function. This prevents adding exist-   */
 /* ing records to array (a duplication making the array twice   */
 /* as large) when selecting 'r' while an array already exists.  */
 /* It will then only read a file to array at program startup.   */
 /* The second if statement added is in the first case statement.*/
 /* This will prevent erasing an existing database by automat-   */
 /* ically writing it to disk before selecting enter a name,     */
 /* otherwise selecting enter before writing will start the new  */
 /* database at n == 0 after opening the disk file.              */
 /****************************************************************/

 #include "stdio.h"
 #define TRUE 1

 struct personnel {                  /*define data structure*/
    char name [40];
    int agnumb;
    float height;
 };
 struct personnel agent[50];         /*array of 50 structures*/
 int n = 0;

 main()
 {
 char ch;

    while(TRUE) {
       printf("\n'e' Enter new agent\n'l' List all agents");
       printf("\n'w' Write file\n'r' Read file: ");
       ch = getche();
       switch(ch) {
          case 'e':
             if (n == 0)
                rfile();
             newname();
             break;
          case 'l':
             listall();
             break;
          case 'w':
             wfile();
             break;
          case 'r':
             rfile();
             break;
          default:
             puts("\nEnter only selections listed.");
       }
    }
 }

 /* newname */    /* puts a new agent in the database */
 newname()
 {

    printf("\nRecord %d.\nEnter name: ", n + 1);
    gets(agent[n].name);
    printf("\nEnter agent number (3 digits): ");
    scanf("%d", &agent[n].agnumb);
    printf("Enter height in inches: ");
    scanf("%f", &agent[n++].height);
    fflush(stdin);
 }

 /* listall() */   /*lists all agents and data */
 listall()
 {
 int j;

    if(n < 1)
       printf("\nEmpty list.\n");
    for(j = 0; j < n; j++) {
       printf("\nRecord number %d\n", j + 1);
       printf("   Name: %s\n", agent[j].name);
       printf("   Agent number: %03d\n", agent[j].agnumb);
       printf("   Height: %4.2f\n", agent[j].height);
    }
 }

 /* wfile */    /* writes array of structures to file */
 wfile()
 {
 FILE *fptr;

    if(n < 1) {
       printf("\nCan't write empty list.\n");
       return;
    }
    if((fptr = fopen("c:agents.rec", "wb")) == NULL)
       printf("\nCan't open file agents.rec\n");
    else {
       fwrite(agent, sizeof(agent[0]), n, fptr);
       fclose(fptr);
       printf("\nFile of %d records written.\n", n);
    }
 }

 /* rfile() */  /* reads records from file into array */
 rfile()
 {
 FILE *fptr;

    if((fptr = fopen("c:agents.rec", "rb")) == NULL)
       printf("\nCan't open file agents.rec\n");
    else {
       if(n == 0)  /*Fill array only at start, otherwise will dup entire file*
          while(fread(&agent[n], sizeof(agent[n]), 1, fptr) == 1)
             n++;
    fclose(fptr);
    printf("\nFile read. Total agents is %d.\n", n);
    }
 }



 ALLDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\ALLDIR.C

 /* ALLDIR.C  a program to traverse DOS's tree-structured directory, looking
    for the file(s) specified. They are then displayed on the screen.
    Basically, I got damned tired of DOS not being able to tell me what's
    where.
     The basic traverse from directory to directory portion is a
    very versatile toy around which many useful utilities can (and will,
    I'm sure!) be written. Here's another one of them. I'll do more as time
    and inclination permits, but I'll turn this one loose because I think
    it's useful.
     This is written for MSDOS 2.0 or better, using the LATTICE C Compiler,
    on a Compaq. 7-20-84 jjw
    ps I know this could be shortened drastically and speeded up by
    combining some of the modules into larger functions, but this way was
    much easier to write & de-bug modularly and so I left it that way. Also,
    some of the modules might be useful in themselves to build into a
    library. This program differs from most C code I've seen before because
    1.) it does something useful.
    2.) it does not have pointers to pointers to arrays of pointers to functio
        returning pointers. It is easy and straight-forward, at the expense of
        some speed and length.
    3.) it is commented. Not extensively, but fairly well. The hard parts have
        to do with the dirstak, which is not a stack but a queue (dirqueue
        looked too silly to me and d_queue made me think of peanut buster
        parfaits). If puzzled, follow it through but keep the msdos manual
        handy to see what byte is what.
    If you have any questions about this, drop me a note. I frequent almost
    every tech-oriented CPM bulletin board around Chicago, Il.
    Name is John Welch, or just jjw.
            2397 John Smith Dr. Apt B
            Schaumburg, Il 60194 */

 #include "dos.h"
 #include "stdio.h"

 main(argc,argv)
 int argc;
 char *argv[];
 {
 char look[15],start[100],init_dir[100],drive[2],flag1,stuff[100];
 int first,last,temp,temp1,ret;

 printf("ALLDIR.C Ver 1.00 1-25-85 John J. Welch\n");
 printf("(for help, type ALLDIR HELP)\n\n");

 if (argc == 1)
  {
   /* get the filename to erase */
   printf("Filename to find -->");
   scanf("%s",look);

   /* get the drive we're going to do the erasing on */
   printf("Enter the drive letter -->");
   scanf("%s",stuff);
   drive[1] = stuff[0];

   /* get starting directory */
   printf("Directory to start in (absolute path from root) -->");
   scanf("%s",start);

   /* do we want to do all sub-directories, too, or just this one? */
   printf("Traverse all sub-directories under this one -->");
   scanf("%s",stuff);
   if ((stuff[0] == 'y') || (stuff[0] == 'Y'))
    flag1 = 1; /* if they specified Y, set the flag */
   else
    flag1 = 0; /* anything but Y or y means NO */

   }
 else
  {
   if (argc != 2)
    {
 HERE:
     printf("For prompts, just type ALLDIR.\n");
     printf("Command line syntax is ALLDIR [drive:][starting path]file.ext[/y]
     printf("where [drive:] is optional drive,\n");
     printf("  [starting path] is optional path to start at,\n");
     printf("  file.ext is the file name (wildcards ok) to look for,\n");
     printf("  [/y] is optionally if you want to do all sub-directories under
     printf("  starting directory (default value is no).\n");
     return;
    }
   else
    {
     if ((strcmp(argv[1],"HELP") == 0) || (strcmp(argv[1],"help") == 0))
      goto HERE;

     first = 0; /* first character of the command line */
     drive[1] = 255; /* set up to default to current drive */
     flag1 = 0; /* default it to not do sub-dirs */
     if (argv[1][1] == ':') /* if there was a drive specified, pick the letter
     { /*off and store it someplace */
      drive[1] = argv[1][0];
      first = 2; /* now, the first character in the command line is #2 */
     }
     last = strlen(argv[1]); /* get the length of the command line */
     if (argv[1][last-2] == '/') /* if they used the toggle, set it up */
     {
      if ((argv[1][last-1] == 'y') || (argv[1][last-1] == 'Y'))
       flag1 = 1; /* if they specified Y, set the flag */
      else
       flag1 = 0; /* anything but Y or y means NO */
      last -= 2; /* bump the last character down */
      argv[1][last] = 0; /* and now, null terminate the command line */
     }

     for (temp = last; ((argv[1][temp] != ':') && (temp >= first) && (argv[1][

     for (temp1 = first; temp1 < temp+1; temp1++) /* get pathname (if any) */
     {start[temp1-first] = argv[1][temp1];}
     start[temp1-first] = 0; /* null terminate it */

     for (temp1 = temp+1; temp1 <= last; temp1++) /* get the filename to look
     {look[temp1-(temp+1)] = argv[1][temp1];}
     look[temp1-(temp+1)] = 0; /* null terminate this */

    }
   }

 /* get the drive we started in */
 get_drive(drive);

 if (drive[1] == 255) /* if the default was for current drive, use it */
  drive[1] = drive[0];
 else /* otherwise, normalize whatever they typed in to start with a=0 */
  if ((drive[1] > 'A') && (drive[1] < 'Z'))
    drive[1] = drive[1] - 'A';
  else
    drive[1] = drive[1] - 'a';

 /* change to the starting drive */
 ret=chg_drive(drive[1]);

 if (ret < drive[1])
   printf("invalid drive selected...\n");
 else
  {
   /* get the directory we started in */
   init_dir[0] = '\\';
   get_dir(init_dir+1);

   if (start[0] == 0) /* if there was no starting path, use the current one */
    strcpy(start,init_dir);

   /* do the actual work */
   doit(look,start,flag1);

   /* change back to the initial drive */
   chg_drive(drive[0]);

   /* now, change back to the initial directory */
   chg_dir(init_dir);
  } /* end else */

 } /* end function */

 doit(look,start,flag1)
 char *look,*start,flag1;

 {
  char file[3],name[128],*dirstak,curdir[140],*getmem();
  int ret,tmp,top_ndx,bottom_ndx;

  dirstak = getmem(10000); /* get a hunk of memory for the directory queue */
  if (dirstak == 0) /* if the getmem returned a null, error */
  {printf("not enough memory...\n");
   return;}

 /* set the DTA to someplace we can use */
  put_dta(name);

  top_ndx = 0;    /* set pointer to top of directory queue */
  bottom_ndx = 0; /* set pointer to bottom of queue */

  /* put the starting directory in the queue */
  for (tmp = 0; start[tmp] != 0; tmp++)
   {dirstak[bottom_ndx++] = start[tmp];}
  dirstak[bottom_ndx++] = 0;

  while (top_ndx != bottom_ndx)
   {
    /* check for any sub-directories */
    ret = dirscan(file,name,curdir,dirstak,&top_ndx,&bottom_ndx);

    if (ret != 3)
     {
      /* run through the directory, querying for each file */
      filscan(look,name);
     }

    /* if only do this one directory, end here */
    if (flag1 == 0)
    {
     rlsmem(dirstak,10000);
     return(1);
    }

   } /* end while loop */
   rlsmem(dirstak,10000);

 } /* end function */

 dirscan(file,name,curdir,dirstak,top_ptr,bot_ptr)
 char *file,*name,*curdir,*dirstak;
 int *top_ptr,*bot_ptr;
 {
  int ret,tmp,top_ndx,bottom_ndx,*p_file;

  bottom_ndx = *bot_ptr;
  top_ndx = *top_ptr;

  /* initialize the file name for the directory search */
  file[0] = '*';
  file[1] = '.';
  file[2] = 0;

  tmp = 0;
  for (top_ndx; dirstak[top_ndx] != 0; top_ndx++)
   { curdir[tmp++] = dirstak[top_ndx];}
  curdir[tmp] = 0;
  ++top_ndx;
  ret = chg_dir(curdir);
  if (ret != 3)
   {
    printf("\n\n     %s\n",curdir);
    find_dir(name,file,curdir,dirstak,&bottom_ndx);
   }
  *bot_ptr = bottom_ndx;
  *top_ptr = top_ndx;

  return(ret);
 }

 find_dir(name,file,curdir,dirstak,bot_ndx)
 char *name,*file,*curdir,*dirstak;
 int *bot_ndx;
 {
  int ret,tmp,bottom_ndx;
  unsigned temp;

  bottom_ndx = *bot_ndx; /* set the local variable = the real thing. */

 /* search for first directory entry */
  temp = 0x0010;
  ret = srch1st(file,temp);

 /* while the return from search is successful, check for dir attribute
    and make sure it isn't a . or .. entry, put the whole pathname (null
    terminated) at the bottom of the queue */

  while (ret != 18)
  { if ((name[21] == 0x10) && (name[30] != '.'))
    {
     for (tmp = 0; curdir[tmp] != 0; tmp++)
     {dirstak[bottom_ndx] = curdir[tmp];
      ++bottom_ndx;}
     if (curdir[1] != 0)
      {dirstak[bottom_ndx++] = '\\';}
    for (tmp = 30; name[tmp] != 0; tmp++)
     {dirstak[bottom_ndx] = name[tmp];
      ++bottom_ndx;}
    dirstak[bottom_ndx++] = 0;

    } /* end if */
     ret = srchnext(file); /* get another directory entry */
  } /* end while */

  *bot_ndx = bottom_ndx; /*now restore the real value to its proper place */

 } /* end function */

 filscan(look,name)
 char *look,*name;
 {
  int ret,numb;
  char tmp,line[35],flag;
  unsigned temp;
  long make_line(),total;

  total = 0;
  numb = 0;
  flag = 0;
  temp = 0x0000;
  ret = srch1st(look,temp); /* start looking for files */

  while (ret != 18)
  {
   total += make_line(line,name);
   numb++;
   printf(line);
   if (flag == 0)
   {printf("         ");
    flag = 1;}
   else
   {printf("\n");
    flag = 0;}

   ret = srchnext(look); /* get another directory entry */
  } /* end while */
  if (flag == 1)
   printf("\n");
  printf("  --> %d files, total space = %8lu<--\n",numb,total);

 } /* end function */

 put_dta(p_dta)
 char *p_dta;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x1a;
  inreg.x.dx = p_dta;

  intdos(&inreg,&outreg);

  return(0);
 }

 srch1st(p_file,attr)
 int *p_file;
 unsigned attr;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x4e;
  inreg.x.cx = attr;
  inreg.x.dx = p_file;

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 srchnext(p_file)
 int *p_file;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x4f;

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 chg_dir(curdir)
 char *curdir;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x3b;
  inreg.x.dx = curdir;

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 get_dir(temp)
 char *temp;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x47;
  inreg.h.dl = 0; /* relative drive */
  inreg.x.si = temp; /* where to put the pathname */

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 get_drive(where)
 char *where;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x19;

  intdos(&inreg,&outreg);

  *where = outreg.h.al;
 }

 era_file(which)
 char *which;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x41;
  inreg.x.dx = which; /* pointer to filename */

  intdos(&inreg,&outreg);

  /* there's no easy way to check for errors, so don't even do it.
     dos returns error flag in carry flag, LATTICE C can't access it without
     your own assembler routine. I have one, but it's a bit hairy. For those
     who insist on doing things right, drop me a note. jjw */
 }

 chg_drive(drive)
 char drive;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x0e;
  inreg.h.dl = drive;

  intdos(&inreg,&outreg);

  return(outreg.h.al);
 }


 /************************************************************************/
 /*                         make_line()                                  */
 /*           make the line of directory info to be printed              */
 /*                                                                      */
 /************************************************************************/

 long make_line(dst,nam)
 char *dst,*nam;
 {
  unsigned g1,g2,g3; /* garbage variables */
  char flag,temp; /* flagged or not, temporary counter */
  char name[9],ext[5],*where; /* hold the file name & extension, which place t
  int ret; /* true if we are did not go off the bottom of the dir */
  long size,g7,t1,t2,t3; /* size of file in bytes, temp variables */
  char direct[23];

  t1 = 256; /* offset for high size low */
  t2 = 65536; /* offset for low size high */
  t3 = 16777216; /* offset for high size high */

   for (temp = 24; temp != 43; temp++) /* load the date, size and name */
   { direct[temp-21] = nam[temp]; /* put the char into the dir area */ }

   for (temp = 0; temp != 6; temp++) /* blank out the extension */
   { ext[temp] = 0; }

   for (temp = 0; temp != 10; temp++) /* blank out the file name */
   { name[temp] = 0; }

   where = name; /* start by putting the name in the name */

   for (temp = 0; temp <= 12; temp++) /* copy over the file name */
   { if (direct[9+temp] == '.') /* if we hit the seperator between name & ext,
     {
      where = ext; /*switch over to the extension */
      temp++; /* skip to next character */
     }
     if (direct[9+temp] == 0) /* if we're at the end of the string, stop */
      temp = 13; /* exit condition */
     else
     {
      *where = direct[9+temp]; /* copy the char over to the array */
      where++; /* increment pointer */
     }
   }

     g1 = direct[4]; /* will be the year */
     g2 = direct[4]*256+direct[3]; /* will be the month */
     g3 = direct[3]; /* will be the day */

     g7 = direct[5]; /* compute size in bytes */
     size = g7;
     g7 = direct[6];
     size = size + (g7*t1);
     g7 = direct[7];
     size = size + (g7*t2);
     g7 = direct[8];
     size = size + (g7*t3); /* will be the file size in bytes */

     /* shift things around to get rid of un-necessary bits */
     g1 >>= 1; /* right-shift month by 1 */
     g2 <<= 7; /* left-shift day by 7 */
     g2 >>= 12; /* then right-shift by 12 to drop off garbage bits */
     g3 &= 0x1f; /* mask off garbage bits to get the year */

     sprintf(dst,"%-8s.%-3s  %02d-%02d-%02d %8lu",name,ext,g2,g3,g1+80,size);
     /* make a useful string out of the flag, name, date and size */

 return(size);
 }


 ALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\ALLOC.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 /*
  * This file contains various routines dealing with allocation and
  * deallocation of data structures.
  */

 char *
 alloc(size)
 unsigned size;
 {
         char *p;                /* pointer to new storage space */

         p = malloc(size);
         if ( p == (char *)NULL ) {        /* if there is no more room... */
                 emsg("alloc() is unable to find memory!");
         }
         return(p);
 }

 char *
 strsave(string)
 char *string;
 {
         return(strcpy(alloc((unsigned)(strlen(string)+1)),string));
 }

 void
 screenalloc()
 {
         /*
          * If we're changing the size of the screen, free the old arrays
          */
         if (Realscreen != NULL)
                 free(Realscreen);
         if (Nextscreen != NULL)
                 free(Nextscreen);

         Realscreen = malloc((unsigned)(Rows*Columns));
         Nextscreen = malloc((unsigned)(Rows*Columns));
 }

 /*
  * Allocate and initialize a new line structure with room for
  * 'nchars' characters.
  */
 LINE *
 newline(nchars)
 int        nchars;
 {
         register LINE        *l;

         if ((l = (LINE *) alloc(sizeof(LINE))) == NULL)
                 return (LINE *) NULL;

         l->s = alloc(nchars);                /* the line is empty */
         l->s[0] = NUL;
         l->size = nchars;

         l->prev = (LINE *) NULL;        /* should be initialized by caller */
         l->next = (LINE *) NULL;

         return l;
 }

 /*
  * filealloc() - construct an initial empty file buffer
  */
 void
 filealloc()
 {
         if ((Filemem->linep = newline(1)) == NULL) {
                 fprintf(stderr,"Unable to allocate file memory!\n");
                 exit(1);
         }
         if ((Fileend->linep = newline(1)) == NULL) {
                 fprintf(stderr,"Unable to allocate file memory!\n");
                 exit(1);
         }
         Filemem->index = 0;
         Fileend->index = 0;

         Filemem->linep->next = Fileend->linep;
         Fileend->linep->prev = Filemem->linep;

         *Curschar = *Filemem;
         *Topchar  = *Filemem;

         Filemem->linep->num = 0;
         Fileend->linep->num = 0xffff;

         clrall();                /* clear all marks */
 }

 /*
  * freeall() - free the current buffer
  *
  * Free all lines in the current buffer.
  */
 void
 freeall()
 {
         LINE        *lp, *xlp;

         for (lp = Filemem->linep; lp != NULL ;lp = xlp) {
                 if (lp->s != NULL)
                         free(lp->s);
                 xlp = lp->next;
                 free(lp);
         }

         Curschar->linep = NULL;                /* clear pointers */
         Filemem->linep = NULL;
         Fileend->linep = NULL;
 }

 /*
  * bufempty() - return TRUE if the buffer is empty
  */
 bool_t
 bufempty()
 {
         return (buf1line() && Filemem->linep->s[0] == NUL);
 }

 /*
  * buf1line() - return TRUE if there is only one line
  */
 bool_t
 buf1line()
 {
         return (Filemem->linep->next == Fileend->linep);
 }

 /*
  * lineempty() - return TRUE if the current line is empty
  */
 bool_t
 lineempty()
 {
         return (Curschar->linep->s[0] == NUL);
 }

 /*
  * endofline() - return TRUE if the given position is at end of line
  *
  * This routine will probably never be called with a position resting
  * on the NUL byte, but handle it correctly in case it happens.
  */
 bool_t
 endofline(p)
 register LPTR        *p;
 {
         return (p->linep->s[p->index] == NUL || p->linep->s[p->index+1] == NU
 }
 /*
  * canincrease(n) - returns TRUE if the current line can be increased 'n' byt
  *
  * This routine returns immediately if the requested space is available.
  * If not, it attempts to allocate the space and adjust the data structures
  * accordingly. If everything fails it returns FALSE.
  */
 bool_t
 canincrease(n)
 register int        n;
 {
         register int        nsize;
         register char        *s;                /* pointer to new space */

         nsize = strlen(Curschar->linep->s) + 1 + n;        /* size required *

         if (nsize <= Curschar->linep->size)
                 return TRUE;

         /*
          * Need to allocate more space for the string. Allow some extra
          * space on the assumption that we may need it soon. This avoids
          * excessive numbers of calls to malloc while entering new text.
          */
         if ((s = alloc(nsize + SLOP)) == NULL) {
                 emsg("Can't add anything, file is too big!");
                 State = NORMAL;
                 return FALSE;
         }

         Curschar->linep->size = nsize + SLOP;
         strcpy(s, Curschar->linep->s);
         free(Curschar->linep->s);
         Curschar->linep->s = s;

         return TRUE;
 }


 ALLOT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ALLOT.C

 /* 1.3  02-11-86                                                 (allot.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985, 86        *
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /*----------------------------------------------------------------------*/

 LOCAL HEADER base;                 /* empty list to get started.
 LOCAL HEADER *allocp = NULL;        /* last allocated block.                *

 /************************************************************************/
         char *
 allot(nbytes)                /* Return pointer to block of memory nbytes in
                            size, or NULL if none available.                */
 /*----------------------------------------------------------------------*/
 unsigned nbytes;
 {
         HEADER *morecore();        /* Almost straight out of K & R.        */
         FAST HEADER *p, *q;
         FAST unsigned ru, au;        /* requested units, allotted units.
         unsigned n_units();

         if ((q = allocp) IS NULL)
         {        base.s.ptr = allocp = q = &base;
                 base.s.size = 0;
         }
         ru = n_units(nbytes);                /* convert to units        */
         for (p = q->s.ptr; ; q = p, p = p->s.ptr)
         {        if (p->s.size >= nbytes)
                 {        if ((au = n_units(p->s.size)) > ru)
                         {        p->s.size = (au -= ru) * sizeof(HEADER);
                                  p += au;
                         }
                         else                /* allot the whole block.
                                 q->s.ptr = p->s.ptr;
                         allocp = q;
                         return (char *) p;
                 }
                 if ((p IS allocp) AND NOT(p = morecore(ru)))
                         return NULL; /* wrapped around free list and
                                         no memory left.
         }
 }
 /*\p*********************************************************************/
         VOID
 liberate(ap, nbytes)        /* Put block of nbytes pointed to by ap into the
                            available list.                                */
 /*----------------------------------------------------------------------*/
 char *ap;
 unsigned nbytes;
 {
         FAST HEADER *p, *q;
         unsigned n_units();

         if (NOT p)
                 return;

         p = (HEADER *) ap;                        /* point to header        *
         for (q = allocp; NOT(q < p AND p < q->s.ptr); q = q->s.ptr)
                 if (q >= q->s.ptr AND (q < p OR p < q->s.ptr))
                         break;               /* stop if at one end or another

         p->s.size = nbytes;                        /* record the size
         if ((p + n_units(p->s.size)) IS q->s.ptr /* join to upper nghbor?*/
            AND (nbytes % sizeof(HEADER)) IS 0)        /* only if no holes.
         {        p->s.size += q->s.ptr->s.size;
                 p->s.ptr = q->s.ptr->s.ptr;
         }
         else
                 p->s.ptr = q->s.ptr;
         if (q + n_units(q->s.size) IS p)        /* join to lower nbr? */
         {        q->s.size += p->s.size;
                 q->s.ptr = p->s.ptr;
         }
         else
                 q->s.ptr = p;
         allocp = q;
 }
 /*\p*********************************************************************/
         LOCAL HEADER *
 morecore(nu)                /* ask system for nu blocks of memory and put on
                            the available list. Return ptr to the block. */
 /*----------------------------------------------------------------------*/
 unsigned nu;
 {
         char *sbrk();
         FAST char *cp;
         FAST HEADER *up;
         FAST unsigned rnu;

         rnu = NALLOC * ((nu + NALLOC - 1) / NALLOC);
         cp = sbrk(nu = rnu * sizeof(HEADER));        /* nu now no. of bytes
         if ((int) cp IS EOF)                        /* no space at all
                 return NULL;

         up = (HEADER *) cp;
         liberate((char *) up, nu);
         return allocp;
 }

 /************************************************************************/
         unsigned
 n_units(n)                /* return the number of HEADER-sized units
                            required to cover n bytes.
 /*----------------------------------------------------------------------*/
 unsigned n;
 {
         return (n + sizeof(HEADER) - 1) / sizeof(HEADER);
 }


 ANAGRAM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\ANAGRAM.C

 /* ANAGRAM.C - From page 584 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. Creates all possible letter ar-   */
 /* rangements in a given word. The version in the book doesn't  */
 /* work correctly. The line I changed is marked in the comments */
 /* in the source code. The printf() was added because in the    */
 /* recursive function rotate is called before the original      */
 /* word is printed.                                             */
 /****************************************************************/

 char word[40];
 int length;
 main()
 {

    printf("\n\nType word: ");
    gets(word);
    length = strlen(word);
    printf("%s\n", word);               /*** ADDED TO SOURCE ***/
    permute(0);
 }

 /* permute */  /* prints all permutations of word */
                /* word begins at position startperm */
 permute(startperm)
 int startperm;
 {
 int j;

    if(length - startperm < 2)       /* exit if one char */
       return;
    for(j = startperm; j < length - 1; j++)  {   /*# chars in word-1*/
       permute(startperm + 1);       /*permutes all but first*/
       rotate(startperm);            /*rotate all chars*/
       printf("%s\n", word);
    }
    permute(startperm + 1); /*restore word to*/
    rotate(startperm);               /*form at entry*/
 }

 /* rotate() */    /*rotates word one char left*/
                   /*word begins at char pos startrot*/
 rotate(startrot)
 int startrot;
 {
 int j;
 char ch;

    ch = word[startrot];             /*save first char*/
    for(j = startrot; j < length - 1; j++) /*move other chars left*/
       word[j] = word[j + 1];              /* one position */
    word[length - 1] = ch;
 }



 ANALYZE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\ANALYZE.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 extern struct amode     push[], pop[];

 /*
  *      this module will step through the parse tree and find all
  *      optimizable expressions. at present these expressions are
  *      limited to expressions that are valid throughout the scope
  *      of the function. the list of optimizable expressions is:
  *
  *              constants
  *              global and static addresses
  *              auto addresses
  *              contents of auto addresses.
  *
  *      contents of auto addresses are valid only if the address is
  *      never referred to without dereferencing.
  *
  *      scan will build a list of optimizable expressions which
  *      opt1 will replace during the second optimization pass.
  */

 static struct cse       *olist;         /* list of optimizable expressions */

 equalnode(node1, node2)
 /*
  *      equalnode will return 1 if the expressions pointed to by
  *      node1 and node2 are equivalent.
  */
 struct enode    *node1, *node2;
 {       if( node1 == 0 || node2 == 0 )
                 return 0;
         if( node1->nodetype != node2->nodetype )
                 return 0;
         if( (node1->nodetype == en_icon || node1->nodetype == en_labcon ||
             node1->nodetype == en_nacon || node1->nodetype == en_autocon) &&
             node1->v.i == node2->v.i )
                 return 1;
         if( lvalue(node1) && equalnode(node1->v.p[0], node2->v.p[0]) )
                 return 1;
         return 0;
 }

 struct cse      *searchnode(node)
 /*
  *      searchnode will search the common expression table for an entry
  *      that matches the node passed and return a pointer to it.
  */
 struct enode    *node;
 {       struct cse      *csp;
         csp = olist;
         while( csp != 0 ) {
                 if( equalnode(node,csp->exp) )
                         return csp;
                 csp = csp->next;
                 }
         return 0;
 }

 struct enode    *copynode(node)
 /*
  *      copy the node passed into a new enode so it wont get
  *      corrupted during substitution.
  */
 struct enode    *node;
 {       struct enode    *temp;
         if( node == 0 )
                 return 0;
         temp = xalloc(sizeof(struct enode));
         temp->nodetype = node->nodetype;
         temp->v.p[0] = node->v.p[0];
         temp->v.p[1] = node->v.p[1];
         return temp;
 }

 enternode(node,duse)
 /*
  *      enternode will enter a reference to an expression node into the
  *      common expression table. duse is a flag indicating whether or not
  *      this reference will be dereferenced.
  */
 struct enode    *node;
 int             duse;
 {       struct cse      *csp;
         if( (csp = searchnode(node)) == 0 ) {   /* add to tree */
                 csp = xalloc(sizeof(struct cse));
                 csp->next = olist;
                 csp->uses = 1;
                 csp->duses = (duse != 0);
                 csp->exp = copynode(node);
                 csp->voidf = 0;
                 olist = csp;
                 return csp;
                 }
         ++(csp->uses);
         if( duse )
                 ++(csp->duses);
         return csp;
 }

 struct cse      *voidauto(node)
 /*
  *      voidauto will void an auto dereference node which points to
  *      the same auto constant as node.
  */
 struct enode    *node;
 {       struct cse      *csp;
         csp = olist;
         while( csp != 0 ) {
                 if( lvalue(csp->exp) && equalnode(node,csp->exp->v.p[0]) ) {
                         if( csp->voidf )
                                 return 0;
                         csp->voidf = 1;
                         return csp;
                         }
                 csp = csp->next;
                 }
         return 0;
 }

 scanexpr(node,duse)
 /*
  *      scanexpr will scan the expression pointed to by node for optimizable
  *      subexpressions. when an optimizable expression is found it is entered
  *      into the tree. if a reference to an autocon node is scanned the
  *      corresponding auto dereferenced node will be voided. duse should be
  *      set if the expression will be dereferenced.
  */
 struct enode    *node;
 {       struct cse      *csp, *csp1;
         int             n;
         if( node == 0 )
                 return;
         switch( node->nodetype ) {
                 case en_icon:
                 case en_labcon:
                 case en_nacon:
                         enternode(node,duse);
                         break;
                 case en_autocon:
                         if( (csp = voidauto(node)) != 0 ) {
                                 csp1 = enternode(node,duse);
                                 csp1->uses = (csp1->duses += csp->uses);
                                 }
                         else
                                 enternode(node,duse);
                         break;
                 case en_b_ref:
                 case en_w_ref:
                 case en_l_ref:
                         if( node->v.p[0]->nodetype == en_autocon ) {
                                 csp = enternode(node,duse);
                                 if( csp->voidf )
                                         scanexpr(node->v.p[0],1);
                                 }
                         else
                                 scanexpr(node->v.p[0],1);
                         break;
                 case en_cbl:    case en_cwl:
                 case en_cbw:    case en_uminus:
                 case en_compl:  case en_ainc:
                 case en_adec:   case en_not:
                         scanexpr(node->v.p[0],duse);
                         break;
                 case en_asadd:  case en_assub:
                 case en_add:    case en_sub:
                         scanexpr(node->v.p[0],duse);
                         scanexpr(node->v.p[1],duse);
                         break;
                 case en_mul:    case en_div:
                 case en_lsh:    case en_rsh:
                 case en_mod:    case en_and:
                 case en_or:     case en_xor:
                 case en_lor:    case en_land:
                 case en_eq:     case en_ne:
                 case en_gt:     case en_ge:
                 case en_lt:     case en_le:
                 case en_asmul:  case en_asdiv:
                 case en_asmod:  case en_aslsh:
                 case en_asrsh:  case en_asand:
                 case en_asor:   case en_cond:
                 case en_void:   case en_assign:
                         scanexpr(node->v.p[0],0);
                         scanexpr(node->v.p[1],0);
                         break;
                 case en_fcall:
                         scanexpr(node->v.p[0],1);
                         scanexpr(node->v.p[1],0);
                         break;
                 }
 }

 scan(block)
 /*
  *      scan will gather all optimizable expressions into the expression
  *      list for a block of statements.
  */
 struct snode    *block;
 {       while( block != 0 ) {
                 switch( block->stype ) {
                         case st_return:
                         case st_expr:
                                 opt4(&block->exp);
                                 scanexpr(block->exp,0);
                                 break;
                         case st_while:
                         case st_do:
                                 opt4(&block->exp);
                                 scanexpr(block->exp,0);
                                 scan(block->s1);
                                 break;
                         case st_for:
                                 opt4(&block->label);
                                 scanexpr(block->label,0);
                                 opt4(&block->exp);
                                 scanexpr(block->exp,0);
                                 scan(block->s1);
                                 opt4(&block->s2);
                                 scanexpr(block->s2,0);
                                 break;
                         case st_if:
                                 opt4(&block->exp);
                                 scanexpr(block->exp,0);
                                 scan(block->s1);
                                 scan(block->s2);
                                 break;
                         case st_switch:
                                 opt4(&block->exp);
                                 scanexpr(block->exp,0);
                                 scan(block->s1);
                                 break;
                         case st_case:
                                 scan(block->s1);
                                 break;
                         }
                 block = block->next;
                 }
 }

 exchange(c1)
 /*
  *      exchange will exchange the order of two expression entries
  *      following c1 in the linked list.
  */
 struct cse      **c1;
 {       struct cse      *csp1, *csp2;
         csp1 = *c1;
         csp2 = csp1->next;
         csp1->next = csp2->next;
         csp2->next = csp1;
         *c1 = csp2;
 }

 int     desire(csp)
 /*
  *      returns the desirability of optimization for a subexpression.
  */
 struct cse      *csp;
 {       if( csp->voidf || (csp->exp->nodetype == en_icon &&
                         csp->exp->v.i < 16 && csp->exp->v.i >= 0))
                 return 0;
         if( lvalue(csp->exp) )
                 return 2 * csp->uses;
         return csp->uses;
 }

 int     bsort(list)
 /*
  *      bsort implements a bubble sort on the expression list.
  */
 struct cse      **list;
 {       struct cse      *csp1, *csp2;
         int             i;
         csp1 = *list;
         if( csp1 == 0 || csp1->next == 0 )
                 return 0;
         i = bsort( &(csp1->next));
         csp2 = csp1->next;
         if( desire(csp1) < desire(csp2) ) {
                 exchange(list);
                 return 1;
                 }
         return 0;
 }

 allocate()
 /*
  *      allocate will allocate registers for the expressions that have
  *      a high enough desirability.
  */
 {       struct cse      *csp;
         struct enode    *exptr;
         int             datareg, addreg, mask, rmask, i;
         struct amode    *ap, *ap2;
         datareg = 3;
         addreg = 10;
         mask = 0;
                 rmask = 0;
         while( bsort(&olist) );         /* sort the expression list */
         csp = olist;
         while( csp != 0 ) {
                 if( desire(csp) < 3 )
                         csp->reg = -1;
                 else if( csp->duses > csp->uses / 4 && addreg < 14 )
                         csp->reg = addreg++;
                 else if( datareg < 8 )
                         csp->reg = datareg++;
                 else
                         csp->reg = -1;
                 if( csp->reg != -1 )
                                 {
                                                 rmask = rmask | (1 << (15 - c
                         mask = mask | (1 << csp->reg);
                                 }
                 csp = csp->next;
                 }
         if( mask != 0 )
                 gen_code(op_movem,4,make_mask(rmask),push);
         save_mask = mask;
         csp = olist;
         while( csp != 0 ) {
                 if( csp->reg != -1 )
                         {               /* see if preload needed */
                         exptr = csp->exp;
                         if( !lvalue(exptr) || (exptr->v.p[0]->v.i > 0) )
                                 {
                                 initstack();
                                 ap = gen_expr(exptr,F_ALL,4);
                                 if( csp->reg < 8 )
                                         ap2 = makedreg(csp->reg);
                                 else
                                         ap2 = makeareg(csp->reg - 8);
                                 gen_code(op_move,4,ap,ap2);
                                 freeop(ap);
                                 }
                         }
                 csp = csp->next;
                 }
 }

 repexpr(node)
 /*
  *      repexpr will replace all allocated references within an expression
  *      with tempref nodes.
  */
 struct enode    *node;
 {       struct cse      *csp;
         if( node == 0 )
                 return;
         switch( node->nodetype ) {
                 case en_icon:
                 case en_nacon:
                 case en_labcon:
                 case en_autocon:
                         if( (csp = searchnode(node)) != 0 )
                                 if( csp->reg > 0 ) {
                                         node->nodetype = en_tempref;
                                         node->v.i = csp->reg;
                                         }
                         break;
                 case en_b_ref:
                 case en_w_ref:
                 case en_l_ref:
                         if( (csp = searchnode(node)) != 0 ) {
                                 if( csp->reg > 0 ) {
                                         node->nodetype = en_tempref;
                                         node->v.i = csp->reg;
                                         }
                                 else
                                         repexpr(node->v.p[0]);
                                 }
                         else
                                 repexpr(node->v.p[0]);
                         break;
                 case en_cbl:    case en_cbw:
                 case en_cwl:    case en_uminus:
                 case en_not:    case en_compl:
                 case en_ainc:   case en_adec:
                         repexpr(node->v.p[0]);
                         break;
                 case en_add:    case en_sub:
                 case en_mul:    case en_div:
                 case en_mod:    case en_lsh:
                 case en_rsh:    case en_and:
                 case en_or:     case en_xor:
                 case en_land:   case en_lor:
                 case en_eq:     case en_ne:
                 case en_lt:     case en_le:
                 case en_gt:     case en_ge:
                 case en_cond:   case en_void:
                 case en_asadd:  case en_assub:
                 case en_asmul:  case en_asdiv:
                 case en_asor:   case en_asand:
                 case en_asmod:  case en_aslsh:
                 case en_asrsh:  case en_fcall:
                 case en_assign:
                         repexpr(node->v.p[0]);
                         repexpr(node->v.p[1]);
                         break;
                 }
 }

 repcse(block)
 /*
  *      repcse will scan through a block of statements replacing the
  *      optimized expressions with their temporary references.
  */
 struct snode    *block;
 {       while( block != 0 ) {
                 switch( block->stype ) {
                         case st_return:
                         case st_expr:
                                 repexpr(block->exp);
                                 break;
                         case st_while:
                         case st_do:
                                 repexpr(block->exp);
                                 repcse(block->s1);
                                 break;
                         case st_for:
                                 repexpr(block->label);
                                 repexpr(block->exp);
                                 repcse(block->s1);
                                 repexpr(block->s2);
                                 break;
                         case st_if:
                                 repexpr(block->exp);
                                 repcse(block->s1);
                                 repcse(block->s2);
                                 break;
                         case st_switch:
                                 repexpr(block->exp);
                                 repcse(block->s1);
                                 break;
                         case st_case:
                                 repcse(block->s1);
                                 break;
                         }
                 block = block->next;
                 }
 }

 opt1(block)
 /*
  *      opt1 is the externally callable optimization routine. it will
  *      collect and allocate common subexpressions and substitute the
  *      tempref for all occurrances of the expression within the block.
  *
  *                optimizer is currently turned off...
  */
 struct snode    *block;
 {
                 olist = 0;
         scan(block);            /* collect expressions */
         allocate();             /* allocate registers */
         repcse(block);          /* replace allocated expressions */
 }



 ANSI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\ANSI.C

 /*************************************************************************
 main function to test some of the ansi device driving functions
 which follow below.  NOTE:  you need your device set to ansi.sys in the
 config.sys for this to work.

 written by Rex Jaeschke of Rockville, MD. 1983 (301) 251-8987
 compiler used DeSmet v2.2

 ci () is a DeSmet compiler specific function which does direct console
 input of 1 character without echoing it. It is used in sgr_dsr and the
 testing program only. All else should run on any compiler.
 *************************************************************************/

 #define CTRL_C 3
 #define BELL 7
 #define NULL '\0'
 LINEMIN 1  /* Minimum screen line # */
 LINEMAX 25 /* Maximum screen line # */
 COLMMIN 1  /* Minimum screen column # */
 COLMMAX 80 /* Maximum screen column # */
 #define L_ARROW 75
 #define R_ARROW 77
 #define U_ARROW 72
 #define D_ARROW 80
 #define HOME 71
 #define END 79
 #define C_HOME 119

 main ()
 {
     int c;

     scr_ed ();               /* clear screen */
     scr_cup (12,40);         /* move to screen center */
     while ((c = ci()) != CTRL_C) {
          if (c == NULL) {    /* do we have extended code? */
               c = ci();
               switch (c) {
               case L_ARROW:
                    scr_cub (1);
                    break;
               case R_ARROW:
                    scr_cuf (1);
                    break;
               case U_ARROW:
                    scr_cuu (1);
                    break;
               case D_ARROW:
                    scr_cud (1);
                    break;
               case C_HOME:
                    scr_ed ();
                    break;
               case HOME:
                    scr_cup (LINEMIN,COLMMIN);
                    break;
               case END:
                    scr_cup (LINEMAX,COLMMAX);
                    break;
               default:
                    putchar (BELL);
                    break;
               }
          }
          else
               putchar (BELL);
     }
 }


 ESCAPE 27  /* ASCII ESC character definition */

 /*************************************************************************
 SCR_CUB - Cursor Backward.

 Moves the cursor backward n columns. Current line remains unchanged. If # of
 columns exceeds left-of-screen, cursor is left at the left-most column.
 *************************************************************************/

 scr_cub (ncolms)
 int ncolms;
 {
     printf ("%c[%dD",ESCAPE,ncolms);
 }

 /*************************************************************************
 SCR_CUD - Cursor Down.

 Moves the cursor down n lines. Current column remains unchanged. If # of line
 to move down exceeds bottom-of-screen, cursor is left at the bottom.
 *************************************************************************/

 scr_cud (nlines)
 int nlines;
 {
     printf ("%c[%dB",ESCAPE,nlines);
 }

 /*************************************************************************
 SCR_CUF - Cursor Forward.

 Moves the cursor forward n columns. Current line remains unchanged. If # of
 columns exceeds right-of-screen, cursor is left at the right-most column.
 *************************************************************************/

 scr_cuf (ncolms)
 int ncolms;
 {
     printf ("%c[%dC",ESCAPE,ncolms);
 }

 /*************************************************************************
 SCR_CUP - Cursor Position. (same as HVP)

 Moves the cursor to the specified position line,colm.
 *************************************************************************/

 scr_cup (line,colm)
 int line,colm;
 {
     printf ("%c[%d;%dH",ESCAPE,line,colm);
 }

 /*************************************************************************
 SCR_CUU - Cursor Up.

 Moves the cursor up n lines. Current column remains unchanged. If # of lines
 to move up exceeds top-of-screen, cursor is left at the top.
 *************************************************************************/

 scr_cuu (nlines)
 int nlines;
 {
     printf ("%c[%dA",ESCAPE,nlines);
 }

 /*************************************************************************
 SCR_DSR - Device Status Report.

 Returns the Cursor Position Report (CPR) sequence in the form ESC[line;colmR

 ci () is a DeSmet compiler specific function which does direct console
 input of 1 character without echoing it.
 *************************************************************************/

 scr_dsr (line,colm)
 int *line,*colm;
 {
     int i = 0;
     char cpr[10];

     printf ("%c[6n",ESCAPE);
     while ((cpr[i++] = ci ()) != 'R')
          ;
     cpr[i] = '\0';

 /* format of cpr[] is ESC[rr;ccR row and colm are always two digits */

     *line = ((cpr[2]-'0')*10)+cpr[3]-'0';
     *colm = ((cpr[5]-'0')*10)+cpr[6]-'0';
 }

 /*************************************************************************
 SCR_ED - Erase in Display.

 Erases all of the screen leaving the cursor at home
 *************************************************************************/

 scr_ed ()
 {
     printf ("%c[2J",ESCAPE);
 }

 /*************************************************************************
 SCR_EL - Erase in Line.

 Erases from the cursor to the end of the line including the cursor position.
 *************************************************************************/

 scr_el ()
 {
     printf ("%c[2K",ESCAPE);
 }

 /*************************************************************************
 SCR_HVP - Horizontal and Vertical Position. (same as CUP)

 Moves the cursor to the specified position line,colm.
 *************************************************************************/

 scr_hvp (line,colm)
 int line,colm;
 {
     printf ("%c[%d;%dH",ESCAPE,line,colm);
 }

 /*************************************************************************
 SCR_RCP - Restore Cursor Position.

 Restores the cursor to the value it had when previously saved by scr_scp.
 *************************************************************************/

 scr_rcp ()
 {
     printf ("%c[u",ESCAPE);
 }

 /*************************************************************************
 SCR_SCP - Save Cursor Position.

 Saves the current cursor position for later restoration by scr_rcp.
 *************************************************************************/

 scr_scp ()
 {
     printf ("%c[s",ESCAPE);
 }

 /*************************************************************************
 SCR_SGR - Set Graphics Rendition.

 Sets the character attribute specified by the parameter.
 Attributes remain in force until reset or changed.
 *************************************************************************/

 scr_sgr (attrib)
 int attrib;
 {
     printf ("%c[%dm",ESCAPE,attrib);
 }

 /*************************************************************************
 SCR_SM - Set Mode.

 Sets the screen width or type specified by the parameter.
 *************************************************************************/

 scr_sm (param)
 int param;
 {
     printf ("%c[=%dh",ESCAPE,param);
 }

 /*************************************************************************
 SCR_RM - Reset Mode.

 Sets the screen width or type specified by the parameter.
 *************************************************************************/

 scr_rm (param)
 int param;
 {
     printf ("%c[=%dl",ESCAPE,param);
 }


 ANSI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\ANSI.C

 /*
  * The routines in this file provide support for ANSI style terminals
  * over a serial line. The serial I/O services are provided by routines in
  * "termio.c". It compiles into nothing if not an ANSI device.
  */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     ANSI

 #if        AMIGA
 NROW    23                      /* Screen size.                 */
 NCOL    77                      /* Edit if you want to.         */
 #else
 NROW    25                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
 #endif
        NPAUSE        100                        /* # times thru update to pau
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
 BEL     0x07                    /* BEL character.               */
 ESC     0x1B                    /* ESC character.               */

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     ansimove();
 extern  int     ansieeol();
 extern  int     ansieeop();
 extern  int     ansibeep();
 extern  int     ansiopen();
 extern        int        ansirev();
 extern        int        ansiclose();
 extern        int        ansikopen();
 extern        int        ansikclose();
 extern        int        ansicres();

 #if        COLOR
 extern        int        ansifcol();
 extern        int        ansibcol();

 int        cfcolor = -1;                /* current forground color */
 int        cbcolor = -1;                /* current background color */

 #if        AMIGA
 /* apperently the AMIGA does not follow the ANSI standards as
    regards to colors....maybe because of the default pallette
    settings?
 */

 int coltran[8] = {2, 3, 5, 7, 0, 4, 6, 1};        /* color translation table
 #endif
 #endif

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         ansiopen,
         ansiclose,
         ansikopen,
         ansikclose,
         ttgetc,
         ttputc,
         ttflush,
         ansimove,
         ansieeol,
         ansieeop,
         ansibeep,
         ansirev,
         ansicres
 #if        COLOR
         , ansifcol,
         ansibcol
 #endif
 };

 #if        COLOR
 ansifcol(color)                /* set the current output color */

 int color;        /* color to set */

 {
         if (color == cfcolor)
                 return;
         ttputc(ESC);
         ttputc('[');
 #if        AMIGA
         ansiparm(coltran[color]+30);
 #else
         ansiparm(color+30);
 #endif
         ttputc('m');
         cfcolor = color;
 }

 ansibcol(color)                /* set the current background color */

 int color;        /* color to set */

 {
         if (color == cbcolor)
                 return;
         ttputc(ESC);
         ttputc('[');
 #if        AMIGA
         ansiparm(coltran[color]+40);
 #else
         ansiparm(color+40);
 #endif
         ttputc('m');
         cbcolor = color;
 }
 #endif

 ansimove(row, col)
 {
         ttputc(ESC);
         ttputc('[');
         ansiparm(row+1);
         ttputc(';');
         ansiparm(col+1);
         ttputc('H');
 }

 ansieeol()
 {
         ttputc(ESC);
         ttputc('[');
         ttputc('K');
 }

 ansieeop()
 {
 #if        COLOR
         ansifcol(gfcolor);
         ansibcol(gbcolor);
 #endif
         ttputc(ESC);
         ttputc('[');
         ttputc('J');
 }

 ansirev(state)                /* change reverse video state */

 int state;        /* TRUE = reverse, FALSE = normal */

 {
 #if        COLOR
         int ftmp, btmp;                /* temporaries for colors */
 #endif

         ttputc(ESC);
         ttputc('[');
         ttputc(state ? '7': '0');
         ttputc('m');
 #if        COLOR
         if (state == FALSE) {
                 ftmp = cfcolor;
                 btmp = cbcolor;
                 cfcolor = -1;
                 cbcolor = -1;
                 ansifcol(ftmp);
                 ansibcol(btmp);
         }
 #endif
 }

 ansicres()        /* change screen resolution */

 {
         return(TRUE);
 }

 spal(dummy)                /* change pallette settings */

 {
         /* none for now */
 }

 ansibeep()
 {
         ttputc(BEL);
         ttflush();
 }

 ansiparm(n)
 register int    n;
 {
         register int q,r;

         q = n/10;
         if (q != 0) {
                 r = q/10;
                 if (r != 0) {
                         ttputc((r%10)+'0');
                 }
                 ttputc((q%10) + '0');
         }
         ttputc((n%10) + '0');
 }

 ansiopen()
 {
 #if     V7 | USG | BSD
         register char *cp;
         char *getenv();

         if ((cp = getenv("TERM")) == NULL) {
                 puts("Shell variable TERM not defined!");
                 exit(1);
         }
         if (strcmp(cp, "vt100") != 0) {
                 puts("Terminal type not 'vt100'!");
                 exit(1);
         }
 #endif
         strcpy(sres, "NORMAL");
         revexist = TRUE;
         ttopen();
 }

 ansiclose()

 {
 #if        COLOR
         ansifcol(7);
         ansibcol(0);
 #endif
         ttclose();
 }

 ansikopen()        /* open the keyboard (a noop here) */

 {
 }

 ansikclose()        /* close the keyboard (a noop here) */

 {
 }

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else
 ansihello()
 {
 }
 #endif


 ANYFILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\ANYFILE.C

                                          /* Chapter 10 - Program 7 */
 #include "stdio.h"

 main()
 {
 FILE *fp1;
 char oneword[100],filename[25];
 char *c;

    printf("Enter filename -> ");
    scanf("%s",filename);         /* read the desired filename */
    fp1 = fopen(filename,"r");

    do {
       c = fgets(oneword,100,fp1); /* get one line from the file */
       if (c != NULL)
          printf("%s",oneword);    /* display it on the monitor  */
    } while (c != NULL);          /* repeat until NULL          */

    fclose(fp1);
 }



 ANYWHERE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\ANYWHERE\ANYWHERE.C

 /***************************************************************
 *                                                               *
 *           WHERE                                               *
 *                                                               *
 * Where is a program to locate files on the PC hard disk.      *
 * It requires DOS 2.x or 3.x.                                       *
 *                                                               *
 * The command line syntax is:                                       *
 * where [starting directory]filename.ext                       *
 *                                                               *
 * Written by Mark S. Ackerman                                       *
 * PROGRAM IS WRITTEN IN MARK WILLIAMS  M W C 8 6  LANGUAGE     *
 * Copyright 1984, 1985 by Mark S. Ackerman.  Permission is     *
 * granted for unlimited copies if not sold or otherwise        *
 * exchanged for gain.                                               *
 *  PUBLISHED IN PC TECH JOURNAL - OCT '85 - VOL 3, NO. 10      *
 *                                                               *
 *  MODIFIED FOR LATTICE C VER 2.15 BY JOHN TEICHERT NOV 85     *
 *     Names shortened to 8 significant characters.               *
 *     Elimination of PTOREG() function                               *
 *     flag86 defined to return flags from intdosx()               *
 *     Use segread to set up regs for intdosx() function.       *
 *     Program modified to look for drive designator with colon.*
 *     DATE structure defined with bits high order to low order.*
 *     intrpt.h replaced with dos.h header file                       *
 *     rindex() function replaced with strrchr() function.      *
 *                                                               *
 *  MODIFIED FOR MICROSOFT V3 BY JOHN TEICHERT JAN 86.               *
 *     flag86 REDEFINED to dos_result for  intdosx() ax reg     *
 *     modified to use flag in REGS structure.                       *
 *     DATE structure defined with bits low order to high order.*
 *     _stack will not produce large stack in ver 3.0 must use  *
 *             link option or exemod program.                       *
 *                                                               *
 *   Added Code And Became ANYWHERE  JOHN TEICHERT FEB 86       *
 *                                                               *
 *        Taking advantange of V3 access to the environment      *
 *        string we set up the following.                        *
 *                                                               *
 *        1. An Environment String indicating what disk drives   *
 *           you want ANYWHERE to search as follows:               *
 *                                                               *
 *           AWDISK=d:[;d:[;d:;...d:]]                               *
 *                                                               *
 *              where d: is the drive specifier for one or more  *
 *              fixed disk(s).                                       *
 *                                                               *
 *              drive specifiers are searched in the order they  *
 *              are entered.                                       *
 *                                                               *
 *        2. The user can specify the environment string with    *
 *           the use of the set command in the autoexec.bat file.*
 *           As an example:                                       *
 *                                                               *
 *                set awdisks=c:;e:;d:                               *
 *                                                               *
 *           would be placed into the autoexec.bat file.               *
 *                                                               *
 *        With this modification the user has extended directory *
 *        capabilities by automatically searching all disk drives*
 *        listed in the environment string or isolated to a      *
 *        single drive by placing a drive specifier in the       *
 *        command line argument string.                               *
 *                                                               *
 *        Be sure to use the /stack option on the link with      *
 *        Microsoft V3 C compiler or stack problems will result  *
 *        if many subdirectories.  8K seems to work well.        *
 *                                                               *
 *                                                               *
 *        Added a few little perks May 1987 - Michael L Kaufman  *
 *                                                               *
 ***************************************************************/


 /***************************************************************
 * The C header files                                               *
 * These identify library routines like printf() and int86x()  *
 ***************************************************************/

 <stdio.h>   /* standard i/o                              */
 <dos.h>     /* functions for DOS interrupt calls     */

 /***************************************************************
 * Structure for MS-DOS date and time fields                       *
 * See pages 4-6 and 4-7 of the DOS 2.1 technical               *
 * reference manual for more information                        *
 * This structure is used in the next structure definition      *
 ***************************************************************/

 struct msdos_date
         {
         unsigned ms_sec    : 5; /* time in 2 sec. int (5 bits)*/
         unsigned ms_min    : 6; /* minutes (6 bits)              */
         unsigned ms_hour   : 5; /* hours (5 bits)              */
         unsigned ms_day    : 5; /* day of month (5 bits)      */
         unsigned ms_month  : 4; /* month (4 bits)              */
         unsigned ms_year   : 7; /* year since 1980 (7 bits)   */
         };

 /***************************************************************
 * Definition of DOS Disk Transfer Area (DTA)                       *
 ***************************************************************/

 /***************************************************************
 * Structure filled in by MS-DOS for interrupt 21 calls               *
 * See page 5-46 of the DOS 2.1 technical reference               *
 * manual for more information                                       *
 ***************************************************************/

 struct DTA
         {
         char        DTA_dosinfo[21];       /* used by DOS                */
         char        DTA_attr;               /* file attribute byte        */
         struct msdos_date DTA_date;    /* date struct. as above */
         long        DTA_size;               /* file size                */
         char        DTA_filename[13];      /* file name (w/o path)        */
         };


 /***************************************************************
 *                Definitions of constants                       *
 ***************************************************************/

 carry_set 0x0001 /* mask for flag register               */
                          /* for carry bit                       */
 no_type   0x00         /* no bits set on file attribute byte */
 directory_type         0x10 /* directory file bit on file    */
                               /* info word                       */

 no_more_files         18        /* DOS return code for                */
                                 /* no more files                */

 end_of_string         '\0'   /* C uses a binary zero to      */
                                 /* signal end of string         */

 backslash '\\'   /* the backslash character           */
 colon          ':'    /* Drive separator  JT 11/85           */
 semicolon ';'   /* Environment string drive separator   */

 char *month[] = {
                 "Jan","Feb","Mar","Apr","May","Jun",
                 "Jul","Aug","Sep","Oct","Nov","Dec"
                 };

 char *time_of_day[2] = {"AM","PM"};


 /***************************************************************
 *                Define the type "filename"                     *
 *                        to be a string of 65 characters  -JT   *
 ***************************************************************/

 typedef char filename[65];                   /* Change to 65 -JT

 /***************************************************************
 *                                                               *
 * The following filename strings are used in the program:      *
 *                                                               *
 *        chk_str                 filename to be searched for    *
 *                                filename in the command line)  *
 *        dir_string                directory name to be searched  *
 *        new_dstr                directory name to be searched  *
 *                                  on next recursive call       *
 *        cur_str                 temporary string for searching *
 *                                  in a specific directory      *
 ***************************************************************/


 /***************************************************************
 * Definition of any forward-referenced functions               *
 ***************************************************************/

 char *DATE();
 char *space();

 /***************************************************************
 *                Global variables                               *
 ***************************************************************/

 filename chk_str;                        /* this string "remembers" user inpu
 union        REGS        r8086;                        /* structure to allow
                                         /*   registers for interrupts
 struct        SREGS        s8086;                        /*   structure for s
 char                date_str[40];                /* print output string for d
 int                count=0;                /* Number of matches dislplayed
 char                spce[] = "                                           ";
 int                lastzero = 41;
 unsigned        dos_result;                /* Return code from DOS

 /**
 *        FOLLOWING CODE COMMENTED OUT FOR V3.0 SINCE CAN'T FIND A WAY TO DO I
 *        WITH A VARIABLE.
 **/

 /*int                  _stack = 8192;           Insure large stack to support
 /*                                           recursion in look routine

 /***************************************************************
 *                MAIN() -- the beginning of the code               *
 ***************************************************************/

 main( argc, argv, envp )
 int        argc;
 char        *argv[];
 char        *envp[];                        /* Version 3 pointer to environ *
 {
 /**
 *        External        function
 **/
 char                        *strrchr();        /* Lattice function which sear
                                         /* for the last occurrance of the  */
                                         /* desired character

 char                        *strchr();        /* Lattice function which searc
                                         /* for the first occurrance of the */
                                         /* desired character

 filename               dir_string;        /* directory to be searched

 char                       *usr_file;        /* address of filename in
                                         /* command line argument           */
                                         /* (ie, the filename)

 char *last_loc;                         /* address of last backslash in    */
                                         /* command line argument           */

 char *dos_parm;                         /* address of
                                         /* command line argument           */

 int  lst_dchr;                                /* last character
                                         /* in directory string

 /** added for ANYWHERE JT **/
 int                        strcmpi();        /* Microsoft V3 function to do a
                                         /*   string compare without regard
                                         /*   to case.
 void                        strcat();        /* String concatenate function
     MAXEDRV        16                /* Set max number of drives
 char                        *strdup();        /* MSC string dup function
 char                        *getcwd();        /* MSC ver3 function to return
                                         /* current working directory
 char                        *envdup;        /* pointer to duplicate of env st
 char                        *envdrv[MAXEDRV];   /* pointer to each drive
                                         /* in envdup
 filename                env_dir_string; /* Environment directory string
 char                        **cur_envp;        /* current environmnet array p
 char                        *env_stp;        /* Current environment string po
 char                        *env_chp;        /* environment character pointer
 static        char                envid[]="AWDISK=";  /* Our environment stri
 char                        *envid_p;        /* current id string ptr
 filename                dos_cwd;        /* buffer to hold cur working dir
 int                        env_cnt;        /* count of number of drives
 int                        envd_len;        /* length of the environment stri
 int                        wi;                /* A working integer
 struct        {
         unsigned        drive        : 1;        /* drive specifier found in
         unsigned        found        : 1;        /* environment contains AWDI
         unsigned        srchcwd : 1;        /* Search for current work dir
         unsigned        addcwd        : 1;        /* Add current working dire
         } flag;

 /********************************************************
 *        check number of incoming arguments                *
 *        if incorrect, write an error message                *
 ********************************************************/

 if (argc != 2)
     {
     printf( "ERR  usage is:   AW    [starting directory]filename.ext\n\n");
     printf( "Environment string is: AWDISK=d: [;d: [;....d:] ]\n");
     return;
     }

 /**        Added for Lattice C Version 2.15 JT
 *        Initialize the segment structure for later dos interrupt calls.
 **/

 segread( &s8086 );                /* initialize segments for interrupt calls
 dos_result = 0;                 /* init interrupt return variable MSCV3.   */

 /**
 *        dos_parm is set to the first argument in the
 *        command line
 **/

 dos_parm = *(++argv);

 /**
 *        If a drive specifier is found we do not want to go through overhead
 *        of environment string search.                AW - JT
 *        If no drive specifier is found we will extract the drive of the
 *            current working directory to be added to the array of environmen
 *            drives.
 **/
 flag.srchcwd = 1;                        /* Init true until command line
                                         /*     option added.
 if ( strchr( dos_parm, colon ) )
     {
     flag.drive = 1;                        /* Set drive specifier true
     flag.found = 0;                        /* Set environment found false
     }
 else
     {
     /**
     *        Drive flag is set to zero
     *        If the search current working directory flag is true then:
     *            Current working directory is obtained and the drive isolated
     *                from the directory string.
     **/
     flag.drive = 0;
     if ( flag.srchcwd )
         {
         getcwd(dos_cwd,sizeof(dos_cwd)-1);
         env_chp = strchr( dos_cwd, colon );
         *++env_chp = end_of_string;
         }
     }
 /**
 *   We check to see if there was a drive specifier found.  If so we
 +        want to continue rather than check the environment string for the
 *        AWDISK= parameter
 **/
 if (flag.drive)
     {
     /**
     *        There was a drive specifier so we zero the env_cnt variable
     **/
     env_cnt = 0;
     }
 else
     {
     /**
     *        The drive specifier was  found in the DOS command argument there
     *            the environment strings will be searched for the AWDISK= par
     **/
     cur_envp = envp;                    /* init current environ pointer */
     flag.found = 0;                    /* init flag found false            */
     /**
     *            Check each environment string to see if it is the AW
     *            environment string.  The envp array is terminated with
     *            a NULL pointer.  The search is terminated when found is
     *            true or the environment pointer is NULL.
     **/
     while( *cur_envp && !flag.found )
         {
         envid_p = envid;        /* init pointer to our environ id */
         env_chp = *cur_envp;        /* init pointer to environ string */
         flag.found = 1;         /* Set flag found = true to enter loop */
         /**
         *   Compare each character in the string to AWDISK=
         **/
         for ( env_cnt=0; (env_cnt<(sizeof(envid)-1)) && flag.found; env_cnt++
             {
             if ( *envid_p++ != *env_chp++ )
                 flag.found = 0;
             else
                 flag.found = 1;
             }

         /**
         *   If found true then copy string to our buffer
         *   Replace ';' with 0x00
         *   Count the number of drives found
         *   Set addcwd true to add the current working directory
         **/
         if ( flag.found )
             {
             flag.addcwd = 1;
             /**
             *        Create a duplicate of the environment string
             *        If it cannot be created we will probably fail but allow
             *        continuation just in case
             **/
             if (!(envdup = strdup(env_chp)))
                 {
                 fprintf( stderr, "Memory alloc problems\n" );
                 env_cnt = 0;                /* zero count cause we're goin ou
                 break;                        /* allow current drive to conti
                 }
             /**
             *        Examine the environment string for a ";"
             *        Replace each semicolon with a "\0" to terminate the stri
             *        Increment the env_cnt variable for each drive in the sys
             *            that the user wished to examine
             *        Place the pointer to the beginning of drive in the envdr
             *            variable.
             **/
             envd_len = strlen(envdup);        /* get length of environment st
             env_cnt  = 0;                /* Set count of drives to zero
             env_stp  = envdup;                /* Set the string pointer to cu
             while ( (envd_len > 0) && (env_cnt < MAXEDRV) )
                 {
                 /**
                 *   Look for the semicolon
                 **/
                 if (env_chp = strchr(env_stp,semicolon))
                     {
                     /**
                     *        We have a semicolon : See if its false
                     **/
                     if (env_chp-env_stp)
                         {
                         /**
                         *   There is a string so put in array
                         *   Decrement the length field
                         *   Change the value of the semi colon to a end of st
                         *   Set up a new pointer beyond env_stp
                         **/
                         envdrv[env_cnt++] = env_stp;
                         envd_len = envd_len-((env_chp-env_stp)+1);
                         *env_chp = end_of_string;
                         /**
                         *   Check the environment entry against the current
                         *        working directory.  If equal set addcwd to
                         *        false
                         **/
                         if ( strcmpi( dos_cwd, env_stp ) == 0 )
                             flag.addcwd = 0;
                         env_stp = ++env_chp;
                         }
                     else
                         {
                         /**
                         *   There was no string just a semicolon
                         *   Decrement the length field
                         *   setup a new pointer beyond the semi-colon
                         **/
                         --envd_len;
                         env_stp = ++env_chp;
                         }
                     }
                 else
                     {
                     /**
                     *        There was no semi-colon so we are on the last dr
                     *            entry.
                     *        Place address in array and increment count
                     *        Set the remaining string length to zero to exit.
                     *        See if last entry matches current working direct
                     *            if so don't add it.
                     **/
                     envdrv[env_cnt++] = env_stp;
                     envd_len = 0;
                     if ( strcmpi( dos_cwd, env_stp ) == 0 )
                         flag.addcwd = 0;
                     if ( flag.addcwd )
                         {
                         if ( (env_cnt < MAXEDRV) && (flag.srchcwd) )
                             envdrv[env_cnt++] = dos_cwd;
                         }
                     }
                 }
             }
         else
             {
             /**
             *        This environment string is not the one we want therefore
             *        Increment current environment pointer and continue
             **/
             cur_envp++;
             }
         }   /* End While */
     }        /* End Else */

 /**
 * The dos_parm is then searched for the last
 * occurrence of a backslash to find the end of
 * the directory name.
 **/

 last_loc = strrchr(dos_parm,backslash);


 /********************************************************
 * If there was not a backslash (and therefore the        *
 *     beginning directory is the root directory)        *
 * begin                                                 *
 *   copy command line argument into chk_str                *
 *   copy root directory into dir_string                 *
 * end                                                        *
 * else                                                        *
 * (if there was a backslash and therefore a beginning        *
 *     directory specified in the command line)                *
 * begin                                                 *
 *   set the usr_file to the next character                *
 *        past the backslash                                *
 *   copy the usr_file into chk_str                        *
 *   copy the command line argument into                 *
 *        dir_string                                        *
 *   terminate dir_string just after the                 *
 *        last backslash (therefore leaving only the        *
 *        the directory name in the string)                *
 * end                                                        *
 ********************************************************/

 if (last_loc == NULL)
     {
     /**
     * Since no backslash we'll still check for a drive designator LC 2.14 -JT
     **/
     last_loc = strchr(dos_parm, colon);
     if (last_loc == NULL)
         {
         strcpy(chk_str,dos_parm);
         strcpy(dir_string,"\\");
         }
     else
         {
         usr_file = last_loc + 1;
         strcpy(chk_str,usr_file);
         strcpy(dir_string,dos_parm);
         lst_dchr = usr_file - dos_parm;
         dir_string[lst_dchr++] = backslash;        /* Fake path */
         dir_string[lst_dchr]   = end_of_string; /* terminate directory str */
         }
     }
 else
     {
     usr_file = last_loc + 1;
     strcpy(chk_str,usr_file);
     strcpy(dir_string,dos_parm);
     lst_dchr = usr_file - dos_parm;
     dir_string[lst_dchr] = end_of_string;
     }


 /**
 *   if the environment string was found concatenate environment drives
 *        with the directory string that was extracted.
 *   else look for just the directory string
 **/

 if ( flag.found)
     {
     for ( wi = 0; wi < env_cnt; wi++ )
         {
         /**
         *   Search each directory in the environment array
         **/
         strcpy( env_dir_string, envdrv[ wi ] );
         strcat( env_dir_string, dir_string );
         LOOK( env_dir_string );
         }
     }
 else
     {
     /**
     *        There is no environment loop so look only for directory string
     **/
     LOOK(dir_string);
     }

 return;

 }

 /**/
 /*********************************************************
 *        LOOK is the recursive procedure in WHERE         *
 *        It is called once for each subdirectory          *
 *********************************************************/

 LOOK(dir_string)
 char *dir_string;
 {

 struct DTA cur_DTA;                /* used to return data from DOS  */

 filename new_dstr;                /* the directory to be                 */
                                 /* searched on the next          */
                                 /* call to LOOK()                 */

 filename cur_str;                /* temporary filename                 */
                                 /* string for searching for         */
                                 /* directories                         */


 /**
 * Form cur_str by copying dir_string and                *
 *    and then concatenating "*.*" to look through all   *
 *    files                                                *
 **/

 strcpy(cur_str,dir_string);
 strcat(cur_str,"*.*");

 /**
 * Set the Disk Transfer Area in DOS to the cur_DTA        *
 *    structure                                                *
 * Get the first subdirectory in this directory                *
 **/

 SET_DTA(&cur_DTA);
 GET_FIRST(cur_str,directory_type);

 /**
 * while there are more subdirectories in this directory *
 * begin                                                 *
 *   double check for proper directories (see text)        *
 *   if a directory                                        *
 *   begin                                                *
 *     set up the new_dstr for the                        *
 *     next call to LOOK (see text)                        *
 *     call LOOK                                         *
 *     reset Disk Transfer Address (see text)                *
 *   end                                                 *
 *   look for next directory                                *
 * end                                                        *
 **/

 while (!(r8086.x.cflag & carry_set))
     {
     if (cur_DTA.DTA_attr == directory_type &&
        cur_DTA.DTA_filename[0] != '.')
         {
         strcpy(new_dstr,dir_string);
         strcat(new_dstr,cur_DTA.DTA_filename);
         strcat(new_dstr,"\\");
         LOOK(new_dstr);
         SET_DTA(&cur_DTA);
         }
     GET_NEXT();
     }

 /********************************************************
 * if there are no more subdirectories in this directory *
 *   look for files                                        *
 * else                                                        *
 *   print an error message                                *
 ********************************************************/

 if (r8086.x.ax == no_more_files)
     GET_FILES(dir_string,&cur_DTA);
 else
     printf("problem with looking thru %s\n",dir_string);
 return;

 }


 /********************************************************
 * GET_FILES                                                *
 * is called once per directory to look for the                *
 *   actual files matching the search string                *
 ********************************************************/

 GET_FILES(dir_string,cur_DTA)
 char *dir_string;
 struct DTA *cur_DTA;
 {

 filename cur_str;

 /********************************************************
 * Form cur_str by copying dir_string into  *
 *   it and then concatenating the chk_str onto           *
 *   the end                                                *
 ********************************************************/

 strcpy(cur_str,dir_string);
 strcat(cur_str,chk_str);

 /*********************************************************
 * Get the first file that matches cur_str         *
 ********************************************************/

 GET_FIRST(cur_str,no_type);

 /********************************************************
 * while there are more files that match the search        *
 *   string:                                                *
 * begin                                                 *
 *   print the file information                                *
 *   get the next file                                        *
 * end                                                        *
 ********************************************************/

 while (!(r8086.x.cflag & carry_set))
     {

     /*  If we have gotten a screenful pause for a keystroke */
     if (++count==24) {
         printf("\t\t<<Hit any key to continue or Q to abort>>");
         count =        getch();
         printf("\r\t\t\t\t\t\t\t\t\r");
         if ((count == 'Q') || (count == 'q'))
                 exit(1);
         count = 0;
         }

     printf(" %10ld %s   %s%s\n", (*cur_DTA).DTA_size,
                         DATE(&((*cur_DTA).DTA_date)),
                         dir_string, (*cur_DTA).DTA_filename);
     GET_NEXT();
     }

 /*********************************************************
 * if error in looking for a file                        *
 *    print error message and return                        *
 ********************************************************/

 if (r8086.x.ax != no_more_files)
     printf("problem with looking for %s\n",cur_str);

 return;

 }

 /********************************************************
 * GET_NEXT does an interrupt 21h, function 4Fh                *
 * Function 4fh is Get next directory entry                *
 ********************************************************/

 GET_NEXT()

 {
 r8086.x.ax = 0x4f00;

 dos_result = int86x( 0x21, &r8086, &r8086, &s8086 );

 return;
 }


 /********************************************************
 * SET_DTA does an interrupt 21h, function 1Ah                *
 *   The DS:DX pair is set to the address of the         *
 *   cur_DTA data structure                            *
 ********************************************************/

 SET_DTA(cur_DTA)
 struct DTA        *cur_DTA;
 {

 r8086.x.ax = 0x1a00;
 r8086.x.dx = (int)cur_DTA;                /* set offset to disk transfer area

 dos_result = int86x(0x21, &r8086, &r8086, &s8086 );

 return;

 }

 /********************************************************
 * GET_FIRST does an interrupt 21h, function 4Eh         *
 *   The CX register is set to either normal or                *
 *   directory type (see text)                                *
 *   The DS:DX pair is set to the address of the         *
 *   search string                                        *
 ********************************************************/

 GET_FIRST(sea_str,filetype)
 char *sea_str;
 int filetype;
 {

 r8086.x.ax = 0x4e00;                                /* Set DOS function
 r8086.x.cx = filetype;                                /* Set search attribute
 r8086.x.dx = (int)    sea_str;                  /* Set address of string */

 dos_result = int86x( 0x21, &r8086, &r8086, &s8086 );

 return;

 }

 /********************************************************
 * DATE takes the date field from the current DTA        *
 *   structure and returns a string containing the        *
 *   information in formatted ASCII                        *
 ********************************************************/

 char *DATE(dateptr)
 struct msdos_date *dateptr;
 {

 sprintf(date_str, "%02d-%02d-%02d %02d:%02d %s",
         dateptr->ms_month, dateptr->ms_day,
         dateptr->ms_year+80, (dateptr->ms_hour)%12,
         dateptr->ms_min, time_of_day[((dateptr->ms_hour)/12)]);
 return(date_str);

 }

 char *space(where)
 int where;
 {
         spce[lastzero] = ' ';
         spce[where] = '\0';
         return spce;
 }


 AREACODE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\AREACODE.C

 /* area.c   11/26/83
    Modified 3-18-86 by Charles Ransom
    [update area codes -CR]

         Telephone area code search program
                 (C) 1983 Martin Smith
         Compuserve 72155,1214   Source ST2259
         310 Cinnamon Oak Lane   (713) 661-1241 [Office]
         Houston, Texas  77079   (713) 464-6737 [Home]

         Find area codes by entering an area code or state name on the
         command line.  Multiple codes, names are permitted up to 20,
         the limit set forth for C86 Computer Innovations(tm) compiler.
         Program written for IBM-PC with PC-DOS 2.0, but no machine-specific
         code is involved.

         The table is near the top of this file to make it easier to maintain.
         Area codes don't change much, but just this year in Houston our
         area code was broken off from the surrounding area.
         The format of the table is simple, so adding cities to the city list
         or even new states or regions won't upset the program if a few easy
         rules are followed:

         1) The table format is one array of string pointers.
         2) A state name consists of a two character postal abbreviation,
            like CA for California, and then the actual name,
            a)  All data on this line is lowercase. A multiple word name,
                like New Jersey, would be entered as "njnew*jersey" , .
                This prevents argv from making two arguments out of the name.
         3) An area code is the three digit code, followed by whatever text.
            a)  As many area codes, cities as you want are ok.
         4) All entries need to be enclosed in quotes (") and followed by a
            comma.
 */

 #include "stdio.h"
 areacode(s,x)
 char *s;
 int x;
 {
 unsigned strlen();

 static char *area[] =
 {  "alalabama"    , "205 All locations",
    "akalaska"     , "907 All locations",
    "azarizona"    , "602 All locations",
    "ararkansas"   , "501 All locations",
    "cacalifornia" ,
         "805 Bakersfield" , "209 Fresno" , "213 Los Angeles" ,
         "213 Burbank" , "714 Camp Pendelton" , "415 Palo Alto",
         "916 Folsom" , "714 Fullerton" , "805 Oxnard"
         "916 Sacramento" , "619 San Diego" , "415 San Francisco" ,
         "707 Santa Rosa" , "408 San Jose" , "213 Santa Monica" ,
    "cncanada" ,
         "519 London, Ont." , "514 Montreal, Quebec" , "403 Alberta" ,
         "613 Ottawa, Ont." , "418 Quebec, Quebec" , "306 Saskatchewan" ,
         "416 Toronto, Ont." , "604 British Columbia" , "204 Manitoba" ,
         "807 East Ontario" , "705 West Ontario" , "819 NW Quebec" ,
         "709 Newfoundland" , "506 New Brunswick" ,
         "902 Nova Scotia, Prince Edward Island" ,
    "cocolorado"   , "303 All locations" ,
    "ctconnecticut" , "203 All locations" ,
    "dedelaware"   , "302 All locations" ,
    "dcdistrict of*columbia" , "202 Washington" ,
    "flflorida" ,
         "813 Ft. Myers, Winter Haven" , "904 Jacksonville" ,
         "305 Miami, Key West, Ft. Lauderdale" ,
    "gageorgia" ,
         "404 Atlanta, Rome" , "912 Waycross" ,
    "hihawaii"  , "808 All locations" ,
    "ididaho"   , "208 All locations" ,
    "ilillinois" ,
         "618 Alton, Mt. Vernon" , "312 Chicago, Aurora, Waukegan" ,
         "815 Rockford" , "217 Springfield" , "309 Peoria" ,
    "inindiana" ,
         "812 Evansville" , "219 Gary, South Bend, Warsaw" ,
         "317 Indianapolis, Kokomo" ,
    "iaiowa" ,
         "712 Council Bluffs" , "515 Des Moines" , "319 Dubuque" ,
    "kskansas" ,
         "316 Wichita, Dodge City" ,
         "913 Topeka, Lawrence, Manhattan, Salina" ,
    "kykentucky" ,
         "502 Louisville, Frankfort, Paducah, Shelbyville" , "606 Winchester"
    "lalouisiana" ,
         "504 Baton Rouge, New Orleans" , "318 Lake Charles" ,
    "memaine"      , "207 All locations" ,
    "mdmaryland"   , "301 All locations" ,
    "mamassachusetts" ,
         "617 Boston, New Bedford, Plymouth, Worchester" ,
         "413 Springfield" ,
    "mxmexico" ,
         "905 Mexico City" , "706 NW Mexico" ,
    "mimichigan" ,
         "313 Detroit, Ann Arbor, Flint" ,
         "616 Battle Creek, Grand Rapids, Kalamazoo" ,
         "517 Lansing" , "906 Escanaba" ,
    "mnminnesota" ,
         "218 Duluth" , "612 Minneapolis, St. Paul" , "507 Rochester" ,
    "msmississippi" , "601 All locations" ,
    "momissouri" ,
         "816 Belton, Independence, Kansas City, Marshall, St. Joseph, Sedalia
         "314 St. Louis, Cape Girardeau, Columbia, Fulton, Hannibal, \n\tJeffe
         "417 Joplin, Springfield" ,
    "mtmontana"    , "406 All locations" ,
    "nenebraska" ,
         "402 Omaha, Lincoln" , "308 North Platte" ,
    "nvnevada"     , "702 All locations" ,
    "nhnew*hampshire" , "603 All locations" ,
    "njnew*jersey" ,
         "609 Atlantic City, Camden, Trenton" ,
         "201 Newark, Hackensack, New Brunswick, Patterson" ,
    "nmnew*mexico" , "505 All locations" ,
    "nynew*york" ,
         "518 Albany, Schenectady" , "607 Binghamton" ,
         "716 Buffalo, Niagara Falls, Rochester" , "914 White Plains" ,
         "212 New York City" , "315 Syracuse" ,
    "ncnorth*carolina" ,
         "704 Charlotte, Salisbury" ,
         "919 Greenville, Raleigh, Winston-Salem" ,
    "ndnorth*dakota" , "701 All locations" ,
    "ohohio" ,
         "216 Akron, Cleveland, Youngstown" ,
         "513 Cincinnati, Dayton" , "614 Columbus" ,
         "419 Toledo" ,
    "okoklahoma" ,
         "918 Tulsa, Bartlesville, McAlester, Muskogee" ,
         "405 Oklahoma City, Enid, Norman, Ponca City, Stillwater" ,
    "ororegon"      , "503 All locations" ,
    "papennsylvania" ,
         "215 Philadelphia, Allentown" , "814 Erie" ,
         "412 Pittsburgh" , "717 Harrisburg, Scranton" ,
    "prpuerto*rico"  ,
 "809 Anguilla, Antigua, Bahamas, Barbados, Bermuda, Cayman Islands, \n\tDomin
    "rirhode*island" , "401 All locations" ,
    "scsouth*carolina" , "803 All locations" ,
    "sdsouth*dakota" , "605 All locations" ,
    "tntennessee" ,
         "615 Nashville, Chattanooga" , "901 Memphis" ,
    "txtexas" ,
         "915 Abilene, Alpine, Big Spring, El Paso, Midland, Odessa" ,
         "512 Austin, Brownsville, Corpus Christi, Del Rio, Eagle Pass, \n\tLa
         "806 Amarillo, Dalhart, Lubbock" ,
         "713 Houston, Baytown, Pasadena" ,
         "409 Bay City, Beaumont, Bryan, College Station, Galveston, Huntsvill
         "214 Dallas, Ennis, Greenville, Jefferson, Longview, Sherman, Tyler"
         "817 Fort Worth, Denton, Temple, Waco, Wichita Falls" ,
    "ututah"        , "801 All locations" ,
    "vtvermont"     , "802 All locations" ,
    "vivirgin*islands" , "809 All locations" ,
    "vavirginia" ,
         "804 Charlottesville, Newport News, Norfolk, Richmond" ,
         "703 Roanoke, Winchester" ,
    "wawashington" ,
         "206 Seattle, Olympia, Vancouver" , "509 Walla Walla" ,
    "  wide area"   , "800 All locations" ,
    "wvwest*virginia" , "304 All locations" ,
    "wiwisconsin" ,
         "414 Milwaukee, Green Bay, Racine" ,
         "608 Madison" , "715 Wausau" ,
    "wywyoming"     , "307 All locations" ,
    NULL  } ;

     int i,j,found;
     unsigned k;
     char temp[64];
     char *t;

     if (x==2)   /* a number area code */
     {
         found=0;
         for (i=0; area[i] != NULL; i++)
            {
            if (strncmp(area[i],s,3)==0)  /* test for match */
                 {
                 for (j=i-1; satoi(area[j]) != 0; --j)  /* then go back for st
                         ;
                 stprint(area[j]);       /* special print out for state name *
                 putchar('\n');
                 printf("    %s.\n\n",area[i]);
                 found=-1;
                 break;                  /* stop when found */
                 }
            }
         if (found==0)
                 printf("Not found, %s.\n\n",s);

      }
     else
     if (x==1)   /* state name or two letter code is input */
     {
         for (i=0; s[i] != '\0'; i++)    /* make everything lowercase */
                 s[i]=tolower(s[i]);
         if (strlen(s)==2)               /* two letter code assumed */
                 {
                 found=0;
                 for (i=0; area[i] != NULL; i++)
                         {
                         if (strncmp(s,area[i],2)==0)
                                 {
                                 stprint(area[i]);
                                 putchar('\n');
                                 for (j=i+1; satoi(area[j]) != 0;j++)
                                         printf("    %s.\n",area[j]);
                                 found=-1;
                                 putchar('\n');
                                 break;
                                 }
                         }
                 if (found==0)
                         printf("Not found, %s.\n",s);
                 }
         else                            /* otherwise try for state name */
         {
         k=strlen(s);                    /* ok if partial name */
         found=0;
                 for (i=0; area[i] != NULL; i++)
                         {
                         if (satoi(area[i])==0)
                                 {
                                 t=area[i];
                                 t=t+2;
                                 strcpy(temp,t);
                                 if (strncmp(temp,s,k) == 0)
                                         {
                                         stprint(area[i]);
                                         putchar('\n');
                                         for (j=i+1; satoi(area[j]) != 0;j++)
                                                 printf("    %s.\n",area[j]);
                                         found=-1;
                                         putchar('\n');
                                         break;
                                         }
                                 }
                         }
                         if (found==0)
                                 printf("Not found, %s.\n",s);
         }
    }
    else         /* print entire list */
    {
      for (i=0; area[i] != NULL; i++)
      {
         if (satoi(area[i])==0)
                 {
                 putchar('\n');
                 stprint(area[i]);
                 putchar('\n');
                 }
         else
                 printf("    %s.\n",area[i]);
      }
    }
 }

 /* special printout for state name */
 stprint(s)
 char s[];
 {
         int i;
         putchar(toupper(s[0]));
         putchar(toupper(s[1]));
         printf("  ");
         putchar(toupper(s[2]));
         for (i=3; s[i] != '\0'; i++)
                 {
                 if (s[i]=='*')
                         {
                         putchar(' ');
                         putchar(toupper(s[++i]));
                         }
                 else
                         putchar(s[i]);
                 }
         printf(" area code(s): ");
 }

 main(argc,argv)
 int  argc;
 char *argv[];
 {
         int i,satoi();
         printf("   ** Area Code Finder **\n");
         printf("    (C) Marty Smith 1983 \n\n");
         printf("    Modified by Charles Ransom -1986\n\n");
         if (argc==1)
         {
         printf("Program searches for telephone area codes,\n");
         printf("   as area xxx xxx xxx etc.\n");
         printf("   xxx is an Area Code or State name.\n");
         printf("   Two letter state postal codes like TX for Texas, CA for Ca
         printf("      can be used, otherwise type in the state name.\n");
         printf("   Enter two word state names like this: New*Jersey.\n");
         printf("   Enter area * for a list of all Area Codes.\n");
         }
         else
         if (*argv[1]=='*')
                 areacode(argv[1],0);
         else
         {
         for (i=1; i < argc; ++i)
                 {
                 if (satoi(argv[i])==0)
                       areacode(argv[i],1);
                 else
                       areacode(argv[i],2);
                 }
         }
 }

 /* integer convert to number */
 int satoi(s)
 char s[];
 {
         int i, n, sign;

         for (i=0; s[i]==' ' || s[i]=='\n' || s[i]=='\t'; i++)
                 ;  /* skip white space */

         sign = 1;
         if (s[i] == '+' || s[i] == '-')
                 sign = (s[i++]=='+') ? 1 : -1;
         for (n=0; s[i] >= '0' && s[i] <= '9'; i++)
                 n = 10 * n + s[i] - '0';
         return(sign * n);

 }



 ASCIDUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\DUMPS\ASCIDUMP.C

 /****************************************************************************
 /*                                                                          *
 /* ASCIDUMP.C                                                               *
 /*                                                                          *
 /* This program prints the ASCII decimal codes and actual text for a file   *
 /* specified as the first command line argument. It reads the file a block  *
 /* at a time and prints the decimal value of each character, then prints    *
 /* the translated characters at the end of the line. It translates certain  *
 /* special characters like BELL, LF, FF to spaces for printing              *
 /*                                                                          *
 /* Written by: Jim Niederriter   12/26/83                                   *
 /*                                                                          *
 /****************************************************************************
 /*                                                                          *
 /* This program was written for the Lattice `C' Compiler, and works under   *
 /* version 1.04 or 2.00.                                                    *
 /*                                                                          *
 /****************************************************************************

 #include <stdio.h>
 #define  BELL   7
 #define  MAXCHR 30
 #define  NULL   0

 main(argc, argv)
 int argc;
 char *argv[];
 {
      int loopx, linecnt;
      int x, f1, stats, flag, fmode;
      long countr;
      char buffer[MAXCHR + 1];
      FILE *f2, *fopen();

 /****** Looks for filename as first command line argument *******************

      if (argc < 2)
      {
           puts("Requires file name in command line\n");
           putch(BELL);
           exit(1);
      }

 /****** Opens printer as LPT1 ***********************************************

      if ((f2 = fopen("LPT1:", "w")) == NULL)
      {
           puts("Can't open printer file\n");
           putch(BELL);
           exit(1);
      }
 /****** Open file as read-only, and in `untranslated' mode...(does not   */
 /****** convert CR/LF). *************************************************/

      fmode = 0;          /* mode for `read-only' */
      fmode = 0x8000;     /* set to read in `untranslated' or binary mode */

      if ((f1 = open(argv[1], fmode)) == NULL)
      {
           printf("Can't open file %s.\n", argv[1]);
           putch(BELL);
           exit(1);
      }
 /***** Printer codes are set up for EPSON FX (change to match your printer */

      fprintf(f2, "\x1BP\x0F");     /* set printer to PICA, CONDENSED  */

 /**** This one sets the `skip over perforation' to 3 lines *****************/

      fprintf(f2, "\x1BN\x03\nCount                              File ");
      fprintf(f2, "dump for file name: %s \n", argv[1]);

      countr = loopx = linecnt = 0;
      flag = 1;
      while (flag)
      {
           flag = 0;
           setmem(buffer, MAXCHR, NULL);               /* clear buffer  */
           if ((stats = read(f1, buffer, MAXCHR)) > 0) /* read blk from file *
           {
                fprintf(f2, "%05ld   ", countr);        /* print char count */
                countr += MAXCHR;
                flag = 1;

                for (x=0; x <= (MAXCHR-1); x++)
                {
                     fprintf(f2, "%03d", buffer[x]);  /* print decimal value *

 /****** change any special characters to SPACE for printing *****************

                     if (buffer[x] < 32 || buffer[x] > 128)
                          buffer[x] = ' ';    /* get rid of unprintables */

                     if ((loopx +=1) == 5)
                     {
                          fprintf(f2, " ");            /* 5 at a time */
                          loopx = 0;
                     }
                }
                fprintf(f2, "*");             /* print translated characters *
                for (x=0; x <= (MAXCHR-1); x++)
                     fprintf(f2, "%c", buffer[x]);
                fprintf(f2, "*\n");
                if ((linecnt += 1) == 5)
                {
                     fprintf(f2, "\n");       /* skip 1 after every 5 lines */
                     linecnt = 0;
                }
           }
      }
      fprintf(f2, "\x1BP\x0C");     /* set back to normal & do forms feed */
      fflush(f2);
      fclose(f2);
 }


 ASIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ASIN.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 174-193.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define P0         +1.0
 #define P1         -0.27368494524164255994e+2
 #define P2         +0.57208227877891731407e+2
 #define P3         -0.39688862997504877339e+2
 #define P4         +0.10152522233806463645e+2
 #define P5         -0.69674573447350646411
 #define P(g)         ((((P5*g P4)*g P3)*g P2)*g P1)

 #define Q0         -0.16421096714498560795e+3
 #define Q1         +0.41714430248260412556e+3
 #define Q2         -0.38186303361750149284e+3
 #define Q3         +0.15095270841030604719e+3
 #define Q4         -0.23823859153670238830e+2
 #define Q(g)         (((((g Q4)*g Q3)*g Q2)*g Q1)*g Q0)

 LOCAL double asincos();

 /************************************************************************/
         double
 asin(x)                        /* return the trigonometric arc-sine of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         return asincos(x, 0);
 }

 /*\p*********************************************************************/

 double acos(x)                /* return the trigonometric arc-cosine of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         return asincos(x, 1);
 }

 /************************************************************************/
         LOCAL double
 asincos(x, flg)                /* return arc sin or cos, depending on flg

 /*----------------------------------------------------------------------*/
 double x;
 {
         double y, g, r;
         FAST int i;
         LOCAL double a[2] = { 0.0, PIover4};
         LOCAL double b[2] = { PIover2, PIover4};

         y = ABS(x);
         i = flg;
         if (y < FADEOUT)
                 r = y;
         else
         {        if (y > 0.5)
                 {        i = 1 - i;
                         if (y > 1.0)
                         {        errno = EDOM;
                                 return 0.0;
                         }
                         g = ldexp((0.5 - y) + 0.5, -1);
                         y = -ldexp(sqrt(g), 1);
                 } else
                         g = y * y;
                 r = y + y *
                         ((P(g) * g)
                         / Q(g));
         }
         if (flg)
         {        if (x < 0.0)
                         r = (b[i] + r) + b[i];
                 else
                         r = (a[i] - r) + a[i];
         }
         else
                 r = (a[i] + r) + a[i];
         return (x < 0.0 ? -r : r);
 }



 ASINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\ASINE.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/

 #include "math.h"
 #include "errno.h"

 double arcsine();

 double asin(x)
 double x;
 {
         return arcsine(x,0);
 }

 double acos(x)
 double x;
 {
         return arcsine(x,1);
 }

 #define P1 -0.27368494524164255994e+2
 #define P2 +0.57208227877891731407e+2
 #define P3 -0.39688862997504877339e+2
 #define P4 +0.10152522233806463645e+2
 #define P5 -0.69674573447350646411
 #define Q0 -0.16421096714498560795e+3
 #define Q1 +0.41714430248260412556e+3
 #define Q2 -0.38186303361750149284e+3
 #define Q3 +0.15095270841030604719e+3
 #define Q4 -0.23823859153670238830e+2

 #define P(g) ((((P5*g P4)*g P3)*g P2)*g P1)
 #define Q(g) (((((g Q4)*g Q3)*g Q2)*g Q1)*g Q0)

 double arcsine(x,flg)
 double x;
 {
         double y, g, r;
         register int i;
         extern int errno;
         static double a[2] = { 0.0, 0.78539816339744830962 };
         static double b[2] = { 1.57079632679489661923, 0.78539816339744830962

         y = fabs(x);
         i = flg;
         if (y < 2.3e-10)
                 r = y;
         else {
                 if (y > 0.5) {
                         i = 1-i;
                         if (y > 1.0) {
                                 errno = EDOM;
                                 return 0.0;
                         }
                         g = (0.5-y)+0.5;
                         g = ldexp(g,-1);
                         y = sqrt(g);
                         y = -(y+y);
                 } else
                         g = y*y;
                 r = y + y*
                                 ((P(g)*g)
                                 /Q(g));
         }
         if (flg) {
                 if (x < 0.0)
                         r = (b[i] + r) + b[i];
                 else
                         r = (a[i] - r) + a[i];
         } else {
                 r = (a[i] + r) + a[i];
                 if (x < 0.0)
                         r = -r;
         }
         return r;
 }



 ASSIGN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\ASSIGN.C

 /* ASSIGN.C - From Microsoft C Programming for the IBM by Rob-  */
 /* ert Lafore, page 270. This program will assign a string(com- */
 /* mand) typed in by user to a chosen function key.             */
 /****************************************************************/

 main()
 {
 char string[81];
 int key;

    printf("Enter number of function key: ");
    gets(string);
    key = atoi(string);
    puts("Enter string to assign to that key: ");
    gets(string);
    printf("\x1B[0;%d;\"%s\";13p", key + 58, string);
 }



 ATAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ATAN.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 194-216.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define P0         -0.13688768894191926929e+2
 #define P1         -0.20505855195861651981e+2
 #define P2         -0.84946240351320683534e+1
 #define P3         -0.83758299368150059274e+0
 #define gP(g)         ((((P3*g P2)*g P1)*g P0)*g)

 #define Q0         +0.41066306682575781263e+2
 #define Q1         +0.86157349597130242515e+2
 #define Q2         +0.59578436142597344465e+2
 #define Q3         +0.15024001160028576121e+2
 #define Q4        +1.0
 #define Q(g)         ((((g Q3)*g Q2)*g Q1)*g Q0)

 /*\p*********************************************************************/
         double
 atan2(v, u)                /* computes atan(v, u) = atan(v / u)

 /*----------------------------------------------------------------------*/
 double u,v;
 {
         double f;
         FAST int c;

         if (u IS 0.0)
         {        if (v IS 0.0)
                 {        errno = EDOM;
                         return 0.0;
                 }
                 return PIover2;
         }
         c = chrstc(v) - chrstc(u);        /* characteristic of v/u        */
         if (c > MAXEXPG)
                 f = PIover2;                /* overflow
         else if (c < MINEXPG)
                 f = 0.0;                /* underflow                        *
         else
         {        f = v / u;
                 f = atan(ABS(f));
                 if (u < 0.0)
                         f = PI - f;
         }
         return (v < 0.0 ? -f : f);
 }

 /*\p*********************************************************************/
         double
 atan(x)                        /* return trigonometric arctangent of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double f, r, g;
         FAST int n;
         LOCAL double A[4] =
         {        0.0,
                 PIover6,
                 PIover2,
                 PIover3,
         };

         f = ABS(x);
         if (f > 1.0)
         {        f = 1.0 / f;
                 n = 2;
         }
         else
                 n = 0;
         if (f > TWOmSQRT3)
         {        f = (((SQRT3m1 * f - 0.5) - 0.5) + f) / (SQRT3 + f);
                 ++n;
         }
         if (ABS(f) < FADEOUT)
                 r = f;
         else
         {        g = f * f;
                 r = f + f *
                         gP(g)
                         /Q(g);
         }
         if (n > 1)
                 r = -r;
         r += A[n];
         return (x < 0.0 ? -r : r);
 }


 ATAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\ATAN.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/


 #include "libc.h"
 #include "math.h"
 #include "errno.h"

 static int nopper() {;}

 #define PI              3.14159265358979323846
 #define PIov2   1.57079632679489661923

 double atan2(v,u)
 double u,v;
 {
         double f;
         int (*save)();
         extern int flterr;
         extern int errno;

         if (u == 0.0) {
                 if (v == 0.0) {
                         errno = EDOM;
                         return 0.0;
                 }
                 return PIov2;
         }

         save = Sysvec[FLT_FAULT];
         Sysvec[FLT_FAULT] = nopper;
         flterr = 0;
         f = v/u;
         Sysvec[FLT_FAULT] = save;
         if (flterr == 2)        /* overflow */
                 f = PIov2;
         else {
                 if (flterr == 1)        /* underflow */
                         f = 0.0;
                 else
                         f = atan(fabs(f));
                 if (u < 0.0)
                         f = PI - f;
         }
         if (v < 0.0)
                 f = -f;
         return f;
 }

 #define P0 -0.13688768894191926929e+2
 #define P1 -0.20505855195861651981e+2
 #define P2 -0.84946240351320683534e+1
 #define P3 -0.83758299368150059274e+0
 #define Q0 +0.41066306682575781263e+2
 #define Q1 +0.86157349597130242515e+2
 #define Q2 +0.59578436142597344465e+2
 #define Q3 +0.15024001160028576121e+2

 #define P(g) (((P3*g P2)*g P1)*g P0)
 #define Q(g) ((((g Q3)*g Q2)*g Q1)*g Q0)

 double atan(x)
 double x;
 {
         double f, r, g;
         int n;
         static double Avals[4] = {
                 0.0,
                 0.52359877559829887308,
                 1.57079632679489661923,
                 1.04719755119659774615
         };

         n = 0;
         f = fabs(x);
         if (f > 1.0) {
                 f = 1.0/f;
                 n = 2;
         }
         if (f > 0.26794919243112270647) {
                 f = (((0.73205080756887729353*f - 0.5) - 0.5) + f) /
                                 (1.73205080756887729353 + f);
                 ++n;
         }
         if (fabs(f) < 2.3e-10)
                 r = f;
         else {
                 g = f*f;
                 r = f + f *
                         ((P(g)*g)
                         /Q(g));
         }
         if (n > 1)
                 r = -r;
         r += Avals[n];
         if (x < 0.0)
                 r = -r;
         return r;
 }



 ATOF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ATOF.C

 /* 1.2  10-08-85                                                (atof.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "mathcons.h"
 #include "mathtyp.h"
 #include "ctype.h"

 /************************************************************************/
         STRING
 astof(s, val)        /* convert value of string s in double/float format and
                    store in val.  return pointer to next unused char.
 /*----------------------------------------------------------------------*/
 STRING s;
 double *val;
 {
         STRING astoi();
         double v, fr, tenpow();
         int i;
         BOOL sign;
         char c;

         while (isspace(c = *s))
                 s++;
         if (sign = (c IS '-'))
                 s++;
         else if (c IS '+')
                 s++;
         for (v = 0.0; isdigit(*s); v = 10. * v + (*s++ - '0'));
         if (*s IS '.')
                 for (fr = 10.0, s++; isdigit(*s); fr *= 10.)
                         v += (*s++ - '0') / fr;
         while (isspace(*s))
                 s++;
         if (TOLOWER(*s) IS 'e')
         {        if ((i = ((c = *(++s)) IS '-')) OR c IS '+')
                         s++;
                 while (*s IS '0')
                         s++;
                 if (i)
                         *(--s) = '-';
                 s = astoi(s, &i);
                 v *= tenpow(i);
         }
         *val = (sign ? -v : v);
         return (s);
 }
 /*\p*********************************************************************/
         double
 atof(s)                /* return value of the string s in double/float format

 /*----------------------------------------------------------------------*/
 STRING s;
 {
         double x;
         STRING astof();

         astof(s, &x);
         return x;
 }

 /************************************************************************/
         LOCAL double
 tenpow(n)                /* Return 10.0^n, or -1 on error.                */

 /*----------------------------------------------------------------------*/
 {
         /********************************************************
          * This array contains 10^(2^n) up to n = BIG10X-1        *
          ********************************************************/
         LOCAL double tentothe2tothe[BIG10X] =
         {        10., 100., 10000., 100000000., 10000000000000000.,
                 100000000000000000000000000000000.
 #ifdef AZTEC
                 , 1.0e64, 1.0e128
 #endif

 #ifdef SUN
                 , 1.0e64, 1.0e128, 1.0e256
 #endif
         };

         /********************************************************
          * Also, make this array be 2^n up to 2^(BIG10X-1)        *
          ********************************************************/
         LOCAL int twoto[BIG10X] =
         {        1, 2, 4, 8, 16, 32
 #ifdef AZTEC
                 , 64, 128
 #endif

 #ifdef SUN
                 , 64, 128, 256
 #endif
         };

         int i, minus;
         double d;

         if (minus = (n < 0) ? TRUE : FALSE)
                 n = -n;
         for (d = 1.0, i = BIG10X; --i >= 0; )
                 if (n >= twoto[i])
                 {        d *= tentothe2tothe[i];
                         n -= twoto[i];
                 }
         return (minus) ? 1.0 / d : d;
 }


 ATOI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ATOI.C

 /* 1.1  01-08-86                                                  (atoi.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/

 atoi(s)                /* return integer value of string s up to first
                    non-digit                                                *
 /*----------------------------------------------------------------------*/
 STRING s;
 {
         int i;
         STRING astoi();

         astoi(s, &i);
         return i;
 }

 /************************************************************************/
         STRING
 astoi(s, val)        /* store into val the value of the string s up to the
                    first non-digit.  return pointer to that char.        */
 /*----------------------------------------------------------------------*/
 STRING s;
 int *val;
 {
         int c, v, base;
         BOOL minus;
         METACHAR tobase();

         while (isspace(*s))
                 s++;
         if ((minus = (*s IS '-')) OR (*s IS '+'))
                 s++;
         if (*s IS '0')
                 if (tolower(*(++s)) IS 'x')
                 {        base = 16;
                         s++;
                 }
                 else
                         base = 8;
         else
                 base = 10;
         for (v = 0; (c = tobase(*s, base)) >= 0; s++)
                 v = v * base + c;
         *val = (minus ? -v : v);
         return s;
 }


 ATOL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\ATOL.C

 #include <stdio.h>

 long atol(number)
 register char *number;
 {
         register long n = 0, neg = 0;

         while((*number == ' ') || (*number == '\t'))
                 ++number;
         if(*number == '-') {
                 neg = 1;
                 ++number;
         }
         else if(*number == '+')
                 ++number;
         while(isdigit(*number))
                 n = (n * 10) + ((*number++) - '0');
         return(neg ? -n : n);
 }

 int atoi(number)
 char *number;
 {
         return(atol(number));
 }


 ATOL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ATOL.C

 /* 1.2  01-08-86                                                (atol.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         long
 atol(s)                /* return long value of converted ascii string s.

 /*----------------------------------------------------------------------*/
 STRING s;
 {
         long i;
         STRING astol();

         astol(s, &i);
         return i;
 }

 /************************************************************************/
         STRING
 astol(s, val)                /* convert string s to long value and return
                            pointer to next character not converted        */
 /*----------------------------------------------------------------------*/
 STRING s;
 long *val;
 {
         long v;
         BOOL minus;
         int c, base;
         METACHAR tobase();

         while (isspace(*s))
                 s++;
         if ((minus = (*s IS '-')) OR (*s IS '+'))
                 s++;
         if (*s IS '0')
                 if (tolower(*(++s)) IS 'x')
                 {        base = 16;
                         s++;
                 }
                 else
                         base = 8;
         else
                 base = 10;
         for (v = 0; (c = tobase(*s, base)) >= 0; s++)
                 v = v * base + c;
         *val = (minus ? -v : v);
         return s;
 }


 ATTRF2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\ATTRF2.C

 /* ATTRF2.C - From page 361 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. The program uses bit fields to    */
 /* change attributes. Type 'x' to exit.                         */
 /****************************************************************/

 #define ROMAX 25
 #define COMAX 80
 #define TRUE 1

 main()
 {
 struct {
    unsigned int foregnd : 3;        /*bits 0,1,2 */
    unsigned int intense : 1;        /*bit 3*/
    unsigned int backgnd : 3;        /*bits 4, 5, 6*/
    unsigned int blinker : 1;        /*bit 7*/
 } attr;
 char ch;

    printf("\nType 'n' for normal,\n");
    printf("     'u' for underlined,\n");
    printf("     'i' for intensified,\n");
    printf("     'b' for blinking,\n");
    printf("     'r' for reverse video,\n");
    while((ch = getch()) != 'x') {
       switch(ch) {
          case 'n':                     /*set to normal*/
             attr.foregnd = 7;
             attr.backgnd = 0;
             break;
          case 'u':                     /*set to underline*/
             attr.foregnd = 1;
             break;
          case 'i':                     /*toggle intensity*/
             attr.intense = (attr.intense == 1) ? 0 : 1;
             break;
          case 'b':                     /*toggle blinking*/
             attr.blinker = (attr.blinker == 1) ? 0 : 1;
             break;
          case 'r':                     /*set to reverse video*/
             attr.foregnd = 0;
             attr.backgnd = 7;
             break;
       }
       fill(ch, attr);
    }
 }

 /* fill() */      /*fills screen with char 'ch', attribute 'attr' */
 fill(ch, attr)
 char ch, attr;
 {
 int far *farptr;
 int col, row;

    farptr = (int far *) 0xB0000000;
    for(row = 0; row < ROMAX; row++)
       for(col = 0; col < COMAX; col++)
          *(farptr + row*COMAX + col) = ch | attr << 8;
 }



 ATTRFILL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\ATTRFILL.C

 /* ATTRFILL.C - From page 358 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. This progam uses direct memory    */
 /* access to change the screen attributes. Enter 'x' to quit.   */
 /****************************************************************/

 #define ROMAX 25
 #define COMAX 80
 #define TRUE 1

 main()
 {
 char ch, attr;

    printf("\nType 'n' for normal,\n");
    printf("     'u' for underlined,\n");
    printf("     'i' for intensified,\n");
    printf("     'b' for blinking,\n");
    printf("     'r' for reverse video,\n\n");
    while((ch = getch()) != 'x') {
       switch(ch) {
          case 'n':
             attr = 0x07;            /*set to normal*/
             break;                  /*0000 0111*/
          case 'u':
             attr = attr & 0x88;     /*set to underline*/
             attr = attr | 0x01;     /* x000 x001 */
             break;
          case 'i':
             attr = attr ^ 0x08;     /*toggle intensified*/
             break;                  /* xxxx Txxx */
          case 'b':
             attr = attr ^ 0x80;     /*toggle blinking*/
             break;                  /* 1xxx xxx */
          case 'r':
             attr = attr & 0x88;     /*set to reverse video*/
             attr = attr | 0x70;     /* x111 x000 */
             break;
       }
       fill(ch, attr);
    }
 }

 /* fill() */      /*fills screen with char 'ch', attribute 'attr' */
 fill(ch, attr)
 char ch, attr;
 {
 int far *farptr;
 int col, row;

    farptr = (int far *) 0xB0000000;
    for(row = 0; row < ROMAX; row++)
       for(col = 0; col < COMAX; col++)
          *(farptr + row*COMAX + col) = ch | attr << 8;
 }



 AUTODIAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\AUTODIAL.C

 /* AUTODIAL.C - From page 500 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. This program dials a number that  */
 /* can be inserted by editing the program. Dial with program,   */
 /* pick up the phone and wait for answer. At this point, pres-  */
 /* sing any key will hang up modem and let the call continue    */
 /* by voice.                                                    */
 /****************************************************************/

 "dos.h"           /*initialize port*/
 COM 1              /*serial port no. (0 = COM1, 1 = COM2)*/
 CONF 0x43          /*300 bpi, no par, 1 stop, 8 bits*/
 RS232 0x14         /*RS232 serial port int number*/
 DATAR 0x100        /*data ready bit in status word*/
 union REGS inregs, outregs;   /*for ROM BIOS calls*/

 main()
 {
    init();
    command("AT D T 883-7045;\r");      /*dial phone*/
    /*** (Semicolon after phone # returns modem to command mode) ***/
    printf("\nPress any key to hang up: \n");
    getche();               /*await char*/
    command("AT H0\r");     /*hang up*/
 }

 /* command() */   /* sends commands to modem */
 command(comstr)
 char *comstr;
 {
 int j, k;
 char ch, receive();

    for(j = 0; (ch = *(comstr + j)) != '\0'; j++)  { /*send command*/
       send(ch);            /*send char to modem*/
       for(k = 0; k < 500 && !ready(); k++)   /*wait for echo*/
          ;
       ch = receive();            /*get echo*/
       putch(ch);
    }
 }

 /* init() */      /* initialize serial port */
 init(conf)
 char conf;        /*addr of configuration code*/
 {
    inregs.h.ah = 0;        /* 'initialize port' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = CONF;     /*configuration*/
    int86(RS232, &inregs, &outregs);
 }

 /* send() */      /* send char to serial port */
 send(c)
 char c;
 {
    inregs.h.ah = 1;        /* 'send char' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = c;        /*character*/
    int86(RS232, &inregs, &outregs);
 }

 /* ready */    /* get serial port ready status */
 ready()
 {
    inregs.h.ah = 3;        /* 'get status' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.x.ax & DATAR);    /*return 'data ready' status*/
 }

 /* receive */     /* get character from serial port */
 char receive()
 {
    inregs.h.ah = 2;        /* 'receive char' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.h.al & 0x7F);     /*return character*/
                                     /* (AND off 8th bit*/
 }


 BACKWARD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BACKWARD.C

                                          /* Chapter 5 - Program 6 */
 "stdio.h"      /* Prototypes for standard Input/Output   */
 "string.h"     /* Prototypes for string operations       */

 void forward_and_backwards(char line_of_char[],int index);

 main()
 {
 char line_of_char[80];
 int index = 0;

    strcpy(line_of_char,"This is a string.\n");

    forward_and_backwards(line_of_char,index);

 }

 void forward_and_backwards(char line_of_char[],int index)
 {
    if (line_of_char[index]) {
       printf("%c",line_of_char[index]);
       index++;
       forward_and_backwards(line_of_char,index);
    }
    printf("%c",line_of_char[index]);
 }


 BASE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\BASE.C

 /*
  * Copyright (c) 1978 Charles H. Forsyth
  *
  * Modified 02-Dec-80 Bob Denny -- Conditionalize debug code to reduce size
  * More     29-May-81 Bob Denny -- RSX overlaying
  * More     19-Mar-82 Bob Denny -- New C library & compiler
  * More     28-Aug-82 Bob Denny -- Reference "a" to shut up compiler
  * More                20-Nov-83 Scott Guthery -- Adapted for IBM PC & DeSmet
  */

 /*
  * lex -- find and set base values for `move' vector
  */
 #include <stdio.h>
 #include "lexlex.h"

 extern struct set *chase();

 /*
  * Choose the best default state for `st'.
  * Only states previous to the current state are considered,
  * as these are guaranteed to exist.
  */
 struct dfa *
 defalt(st, xsep)
 struct dfa *st;
 struct xset **xsep;
 {
         register struct dfa *dp;
         register unsigned minv, u;
         struct dfa *def;
         struct xset *xse;
         int i;

         xse = *xsep;
         if ((i = xse-sets)==0)
                 return(NULL);
 #ifdef DEBUG
         if (lldebug>1)
                 fprintf(stderr, "State %d, default:\n", st-dfa);
 #endif
         minv = -1;
         def = NULL;
         for (dp = dfa; dp < st; dp++) {
                 u = compat(st, dp, xse);
 #ifdef DEBUG
                 if (lldebug > 1)
                         fprintf(stderr, "\t%d rates %d\n", dp-dfa, u);
 #endif
                 if (u < minv) {
                         def = dp;
                         minv = u;
                 }
         }
         if (minv == -1 || 10*(i-(int)minv) < i)
                 def = NULL;
 #ifdef DEBUG
         if (lldebug>1 && def)
                 fprintf(stderr, "\t%d chosen\n", def-dfa);
 #endif

         if (def)
                 resolve(st, def, xsep);
         return(def);
 }

 /*
  * State `b' is compatible with, and hence a suitable default state
  * for state `a', if its transitions agree with
  * those of `a', except those for which `a' has transitions to the
  * (alleged) default. Circularity of the default
  * relation is also not allowed. If the state `b' has at least
  * twice as many transitions as `a', it is not even worth considering.
  */
 compat(a, b, xse)
 struct dfa *a, *b;
 struct xset *xse;
 {
         register struct dfa *dp;
         struct xset *xs;
         register nt;

         if (a==b || b->df_ntrans >= a->df_ntrans*2)
                 return(-1);
         for (dp = b; dp; dp = dp->df_default)
                 if (dp == a)
                         return(-1);
         nt = b->df_ntrans + a->df_ntrans;
         for (xs = sets; xs < xse; xs++)
                 if (chase(b, xs->x_char) == xs->x_set)
                         nt -= 2;
         return(nt);
 }

 struct set *
 chase(st, c)
 register struct dfa *st;
 register c;
 {
         register struct move *dp;

         c &= 0377;
         while ((dp = st->df_base) != NULL &&
                ((dp += c) >= st->df_max || dp->m_check != st))
                 if ((st = st->df_default) == NULL)
                         return(NULL);
         if (dp)
                 dp = dp->m_next;
         return(dp);
 }

 /*
  * set `sets' to indicate those characters on which the state `a'
  * and its default agree and those characters on which `a'
  * should go to `error' (as the default accepts it, but `a' does not).
  */
 resolve(a, def, xsep)
 struct dfa *a, *def;
 struct xset **xsep;
 {
         register struct move *dp;
         register c, i;
         struct xset *xs, *xse;

         a = a;                          /* Quiet compiler the easy way */

         xse = *xsep;
         i = xse-sets;
         for (xs = sets; xs < xse; xs++)
                 xs->x_defsame = 0;
         for (; def; def = def->df_default)
         for (dp = def->df_base; dp < def->df_max; dp++)
                 if (dp->m_check == def) {
                         c = dp - def->df_base;
                         for (xs = sets; xs < xse; xs++)
                                 if (c==(xs->x_char&0377)) {
                                         if (xs->x_set==dp->m_next) {
                                                 xs->x_defsame++;
                                                 i--;
                                         }
                                         break;
                                 }
                         if (xs >= xse) {
                                 xs->x_defsame = 0;
                                 xs->x_char = c;
                                 xs->x_set = NULL;
                                 i++;
                                 xse++;
                         }
                 }
         *xsep = xse;
         return(i);
 }

 /*
  * Choose a base in `move' for the current state.
  * The transitions of that state are in the vector `sets'.
  */
 struct move *
 stbase(xse)
 struct xset *xse;
 {
         register a;
         register struct move *base;
         register conflicts;
         struct xset *xs;

         if (xse==sets)
                 return(NULL);
         base = move;
         do {
                 if (base-move >= NNEXT) {
                         error("No space in `move' (stbase)");

 #ifdef DEBUG
                         if (lldebug>1)
                                 dfaprint();
 #endif
                         exit(1);
                 }
                 conflicts = 0;
                 for (xs = sets; xs < xse; xs++) {
                         a = xs->x_char&0377;
                         if (xs->x_defsame==0 &&
                             (base+a>=move+NNEXT || base[a].m_check!=NULL)) {
                                 conflicts++;
                                 base++;
                                 break;
                         }
                 }
         } while (conflicts);
         return(base);
 }

 /*
  * Given a state, its `base' value in `move',
  * and the set of transitions in `sets' (ending near `xse'),
  * set the `move' values.
  */
 setbase(st, base, xse)
 struct dfa *st;
 register struct move *base;
 struct xset *xse;
 {
         register struct move *dp;
         register struct xset *xs;
         struct move *maxdp;

         st->df_base = base;
         st->df_max = base;
 #ifdef DEBUG
         if (lldebug>1)
                 fprintf(stderr, "Setbase: state %d\n", st-dfa);
         if (lldebug>1 && base==0)
                 fprintf(stderr, "\tno base\n");
 #endif
         if (base==NULL)
                 return;
         maxdp = base;
         for (xs = sets; xs < xse; xs++)
                 if (xs->x_defsame==0) {
                         dp = base + (int)xs->x_char;
                         if (dp > maxdp)
                                 maxdp = dp;
                         dp->m_next = xs->x_set;
                         dp->m_check = st;
                         if (dp-move > llnxtmax)
                                 llnxtmax = dp-move;
 #ifdef DEBUG
                         if (lldebug>1)
                         fprintf(stderr, "\t%c nets %d\n",
                                 xs->x_char&0377, dp-move);
 #endif
                 }

         st->df_max = maxdp+1;
 }


 BASIC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\BASIC.C

 /*
  * The routines in this file move the cursor around on the screen. They
  * compute a new value for the cursor, then adjust ".". The display code
  * always updates the cursor location, so only moves between lines, or
  * functions that adjust the top line in the window and invalidate the
  * framing, are hard.
  */
 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 /*
  * Move the cursor to the
  * beginning of the current line.
  * Trivial.
  */
 gotobol(f, n)
 {
         curwp->w_doto  = 0;
         return (TRUE);
 }

 /*
  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  * "forwchar" to actually do the move. Otherwise compute the new cursor
  * location. Error if you try and move out of the buffer. Set the flag if the
  * line pointer for dot changes.
  */
 backchar(f, n)
 register int    n;
 {
         register LINE   *lp;

         if (n < 0)
                 return (forwchar(f, -n));
         while (n--) {
                 if (curwp->w_doto == 0) {
                         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
                                 return (FALSE);
                         curwp->w_dotp  = lp;
                         curwp->w_doto  = llength(lp);
                         curwp->w_flag |= WFMOVE;
                 } else
                         curwp->w_doto--;
         }
         return (TRUE);
 }

 /*
  * Move the cursor to the end of the current line. Trivial. No errors.
  */
 gotoeol(f, n)
 {
         curwp->w_doto  = llength(curwp->w_dotp);
         return (TRUE);
 }

 /*
  * Move the cursor forwards by "n" characters. If "n" is less than zero call
  * "backchar" to actually do the move. Otherwise compute the new cursor
  * location, and move ".". Error if you try and move off the end of the
  * buffer. Set the flag if the line pointer for dot changes.
  */
 forwchar(f, n)
 register int    n;
 {
         if (n < 0)
                 return (backchar(f, -n));
         while (n--) {
                 if (curwp->w_doto == llength(curwp->w_dotp)) {
                         if (curwp->w_dotp == curbp->b_linep)
                                 return (FALSE);
                         curwp->w_dotp  = lforw(curwp->w_dotp);
                         curwp->w_doto  = 0;
                         curwp->w_flag |= WFMOVE;
                 } else
                         curwp->w_doto++;
         }
         return (TRUE);
 }

 gotoline(f, n)                /* move to a particular line.
                            argument (n) must be a positive integer for
                            this to actually do anything                */

 {
         register int status;        /* status return */
         char arg[NSTRING];        /* buffer to hold argument */

         /* get an argument if one doesnt exist */
         if (f == FALSE) {
                 if ((status = mlreply("Line to GOTO: ", arg, "")) != TRUE) {
                         mlwrite("[Aborted]");
                         return(status);
                 }
                 n = atoi(arg);
         }

         if (n < 1)                /* if a bogus argument...then leave */
                 return(FALSE);

         /* first, we go to the start of the buffer */
         curwp->w_dotp  = lforw(curbp->b_linep);
         curwp->w_doto  = 0;
         return(forwline(f, n-1));
 }

 /*
  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  * considered to be hard motion; it really isn't if the original value of dot
  * is the same as the new value of dot. Normally bound to "M-<".
  */
 gotobob(f, n)
 {
         curwp->w_dotp  = lforw(curbp->b_linep);
         curwp->w_doto  = 0;
         curwp->w_flag |= WFHARD;
         return (TRUE);
 }

 /*
  * Move to the end of the buffer. Dot is always put at the end of the file
  * (ZJ). The standard screen code does most of the hard parts of update.
  * Bound to "M->".
  */
 gotoeob(f, n)
 {
         curwp->w_dotp  = curbp->b_linep;
         curwp->w_doto  = 0;
         curwp->w_flag |= WFHARD;
         return (TRUE);
 }

 /*
  * Move forward by full lines. If the number of lines to move is less than
  * zero, call the backward line function to actually do it. The last command
  * controls how the goal column is set. Bound to "C-N". No errors are
  * possible.
  */
 forwline(f, n)
 {
         register LINE   *dlp;

         if (n < 0)
                 return (backline(f, -n));

         /* if we are on the last line as we start....fail the command */
         if (curwp->w_dotp == curbp->b_linep)
                 return(FALSE);

         /* if the last command was not note a line move,
            reset the goal column */
         if ((lastflag&CFCPCN) == 0)
                 curgoal = getccol(FALSE);

         /* flag this command as a line move */
         thisflag |= CFCPCN;

         /* and move the point down */
         dlp = curwp->w_dotp;
         while (n-- && dlp!=curbp->b_linep)
                 dlp = lforw(dlp);

         /* reseting the current position */
         curwp->w_dotp  = dlp;
         curwp->w_doto  = getgoal(dlp);
         curwp->w_flag |= WFMOVE;
         return (TRUE);
 }

 /*
  * This function is like "forwline", but goes backwards. The scheme is exactl
  * the same. Check for arguments that are less than zero and call your
  * alternate. Figure out the new line and call "movedot" to perform the
  * motion. No errors are possible. Bound to "C-P".
  */
 backline(f, n)
 {
         register LINE   *dlp;

         if (n < 0)
                 return (forwline(f, -n));


         /* if we are on the last line as we start....fail the command */
         if (lback(curwp->w_dotp) == curbp->b_linep)
                 return(FALSE);

         /* if the last command was not note a line move,
            reset the goal column */
         if ((lastflag&CFCPCN) == 0)
                 curgoal = getccol(FALSE);

         /* flag this command as a line move */
         thisflag |= CFCPCN;

         /* and move the point up */
         dlp = curwp->w_dotp;
         while (n-- && lback(dlp)!=curbp->b_linep)
                 dlp = lback(dlp);

         /* reseting the current position */
         curwp->w_dotp  = dlp;
         curwp->w_doto  = getgoal(dlp);
         curwp->w_flag |= WFMOVE;
         return (TRUE);
 }

 #if        WORDPRO
 gotobop(f, n)        /* go back to the beginning of the current paragraph
                    here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
                    combination to delimit the beginning of a paragraph

 int f, n;        /* default Flag & Numeric argument */

 {
         register int suc;        /* success of last backchar */

         if (n < 0)        /* the other way...*/
                 return(gotoeop(f, -n));

         while (n-- > 0) {        /* for each one asked for */

                 /* first scan back until we are in a word */
                 suc = backchar(FALSE, 1);
                 while (!inword() && suc)
                         suc = backchar(FALSE, 1);
                 curwp->w_doto = 0;        /* and go to the B-O-Line */

                 /* and scan back until we hit a <NL><NL> or <NL><TAB>
                    or a <NL><SPACE>                                        */
                 while (lback(curwp->w_dotp) != curbp->b_linep)
                         if (llength(curwp->w_dotp) != 0 &&
                             lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
                             lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
                                 curwp->w_dotp = lback(curwp->w_dotp);
                         else
                                 break;

                 /* and then forward until we are in a word */
                 suc = forwchar(FALSE, 1);
                 while (suc && !inword())
                         suc = forwchar(FALSE, 1);
         }
         curwp->w_flag |= WFMOVE;        /* force screen update */
         return(TRUE);
 }

 gotoeop(f, n)        /* go forword to the end of the current paragraph
                    here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
                    combination to delimit the beginning of a paragraph

 int f, n;        /* default Flag & Numeric argument */

 {
         register int suc;        /* success of last backchar */

         if (n < 0)        /* the other way...*/
                 return(gotobop(f, -n));

         while (n-- > 0) {        /* for each one asked for */

                 /* first scan forward until we are in a word */
                 suc = forwchar(FALSE, 1);
                 while (!inword() && suc)
                         suc = forwchar(FALSE, 1);
                 curwp->w_doto = 0;        /* and go to the B-O-Line */
                 if (suc)        /* of next line if not at EOF */
                         curwp->w_dotp = lforw(curwp->w_dotp);

                 /* and scan forword until we hit a <NL><NL> or <NL><TAB>
                    or a <NL><SPACE>                                        */
                 while (curwp->w_dotp != curbp->b_linep) {
                         if (llength(curwp->w_dotp) != 0 &&
                             lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
                             lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
                                 curwp->w_dotp = lforw(curwp->w_dotp);
                         else
                                 break;
                 }

                 /* and then backward until we are in a word */
                 suc = backchar(FALSE, 1);
                 while (suc && !inword()) {
                         suc = backchar(FALSE, 1);
                 }
                 curwp->w_doto = llength(curwp->w_dotp);        /* and to the
         }
         curwp->w_flag |= WFMOVE;        /* force screen update */
         return(TRUE);
 }
 #endif

 /*
  * This routine, given a pointer to a LINE, and the current cursor goal
  * column, return the best choice for the offset. The offset is returned.
  * Used by "C-N" and "C-P".
  */
 getgoal(dlp)
 register LINE   *dlp;
 {
         register int    c;
         register int    col;
         register int    newcol;
         register int    dbo;

         col = 0;
         dbo = 0;
         while (dbo != llength(dlp)) {
                 c = lgetc(dlp, dbo);
                 newcol = col;
                 if (c == '\t')
                         newcol |= 0x07;
                 else if (c<0x20 || c==0x7F)
                         ++newcol;
                 ++newcol;
                 if (newcol > curgoal)
                         break;
                 col = newcol;
                 ++dbo;
         }
         return (dbo);
 }

 /*
  * Scroll forward by a specified number of lines, or by a full page if no
  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  * the overlap; this value is the default overlap value in ITS EMACS. Because
  * this zaps the top line in the display window, we have to do a hard update.
  */
 forwpage(f, n)
 register int    n;
 {
         register LINE   *lp;

         if (f == FALSE) {
                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
                 if (n <= 0)                     /* Forget the overlap   */
                         n = 1;                  /* if tiny window.      */
         } else if (n < 0)
                 return (backpage(f, -n));
 #if     CVMVAS
         else                                    /* Convert from pages   */
                 n *= curwp->w_ntrows;           /* to lines.            */
 #endif
         lp = curwp->w_linep;
         while (n-- && lp!=curbp->b_linep)
                 lp = lforw(lp);
         curwp->w_linep = lp;
         curwp->w_dotp  = lp;
         curwp->w_doto  = 0;
         curwp->w_flag |= WFHARD;
         return (TRUE);
 }

 /*
  * This command is like "forwpage", but it goes backwards. The "2", like
  * above, is the overlap between the two windows. The value is from the ITS
  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  * reason.
  */
 backpage(f, n)
 register int    n;
 {
         register LINE   *lp;

         if (f == FALSE) {
                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
                 if (n <= 0)                     /* Don't blow up if the */
                         n = 1;                  /* window is tiny.      */
         } else if (n < 0)
                 return (forwpage(f, -n));
 #if     CVMVAS
         else                                    /* Convert from pages   */
                 n *= curwp->w_ntrows;           /* to lines.            */
 #endif
         lp = curwp->w_linep;
         while (n-- && lback(lp)!=curbp->b_linep)
                 lp = lback(lp);
         curwp->w_linep = lp;
         curwp->w_dotp  = lp;
         curwp->w_doto  = 0;
         curwp->w_flag |= WFHARD;
         return (TRUE);
 }

 /*
  * Set the mark in the current window to the value of "." in the window. No
  * errors are possible. Bound to "M-.".
  */
 setmark(f, n)
 {
         curwp->w_markp = curwp->w_dotp;
         curwp->w_marko = curwp->w_doto;
         mlwrite("[Mark set]");
         return (TRUE);
 }

 /*
  * Swap the values of "." and "mark" in the current window. This is pretty
  * easy, bacause all of the hard work gets done by the standard routine
  * that moves the mark about. The only possible error is "no mark". Bound to
  * "C-X C-X".
  */
 swapmark(f, n)
 {
         register LINE   *odotp;
         register int    odoto;

         if (curwp->w_markp == NULL) {
                 mlwrite("No mark in this window");
                 return (FALSE);
         }
         odotp = curwp->w_dotp;
         odoto = curwp->w_doto;
         curwp->w_dotp  = curwp->w_markp;
         curwp->w_doto  = curwp->w_marko;
         curwp->w_markp = odotp;
         curwp->w_marko = odoto;
         curwp->w_flag |= WFMOVE;
         return (TRUE);
 }


 BAWK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\BAWK.C

 /*
         HEADER:                CUG236;
         TITLE:                BAWK Text Pattern/Action Tool (Brod86);
         DATE:                05/17/1987;
         DESCRIPTION:        "BAWK scans text files for regular expression pat
                         and executes a user-defined action (C code fragment)
                         for each specified pattern found.  Descended from the
                         DECUS version of the same program.";
         VERSION:        1.1;
         KEYWORDS:        Text Filter;
         FILENAME:        BAWK.C;
         SEE-ALSO:        BAWK.H, BAWK.DOC, BAWKACT.C, BAWKDO.C, BAWKPAT.C,
                         BAWKSYM.C;
         COMPILERS:        vanilla;
         AUTHORS:        W. C. Colley III, B. Brodt;
         WARNINGS:        "Program runs out of memory under CP/M Eco-C and die
                         without a trace.  Aztec C II is OK.  Won't compile
                         yet under ECO-C88 -- module bawkdo.c gives a strange
                         code generator error.  REQUIRES that sizeof(int) ==
                         sizeof(char *)!!!!!  Therefore, the MSDOS small model
                         is OK, but the MSDOS large model is no good.";
 */

 /*
  * Bawk main program
  */
 #define MAIN 1
 #include <stdio.h>
 #include "bawk.h"

 /* Functions local to this module.        */

 void compile(), newfile(), process(), usage();

 /*
  * Main program
  */
 int main( argc, argv )
 int argc;
 char **argv;
 {
         char gotrules, didfile, getstdin;

         getstdin =
         didfile =
         gotrules = 0;

         /*
          * Initialize global variables:
          */
         Stackptr = Stackbtm - 1;
         Stacktop = Stackbtm + MAXSTACKSZ;
         Nextvar = Vartab;

         strcpy( Fldsep, " \t" );
         strcpy( Rcrdsep, "\n" );

         /*
          * Parse command line
          */
         while ( --argc )
         {
                 if ( **(++argv) == '-' )
                 {
                         /*
                          * Process dash options.
                          */
                         switch (*++*argv)
                         {
 #ifdef DEBUG
                         case 'D':
                         case 'd':
                                 ++Debug;
                                 break;
 #endif
                         case 0:
                                 ++getstdin;
                                 --argv;
                                 goto dosomething;
                                 break;
                         default: usage();
                         }
                 }
                 else
                 {
 dosomething:
                         if ( gotrules )
                         {
                                 /*
                                  * Already read rules file - assume this is
                                  * is a text file for processing.
                                  */
                                 if ( ++didfile == 1 && Beginact )
                                         doaction( Beginact );
                                 if ( getstdin )
                                 {
                                         --getstdin;
                                         newfile( 0 );
                                 }
                                 else
                                         newfile( *argv );
                                 process();
                         }
                         else
                         {
                                 /*
                                  * First file name argument on command line
                                  * is assumed to be a rules file - attempt to
                                  * compile it.
                                  */
                                 if ( getstdin )
                                 {
                                         --getstdin;
                                         newfile( 0 );
                                 }
                                 else
                                         newfile( *argv );
                                 compile();
                                 gotrules = 1;
                         }
                 }
         }
         if ( !gotrules )
                 usage();

         if ( ! didfile )
         {
                 /*
                  * Didn't process any files yet - process stdin.
                  */
                 newfile( 0 );
                 if ( Beginact )
                         doaction( Beginact );
                 process();
         }
         if ( Endact )
                 doaction( Endact );
         return 0;
 }

 /*
  * Regular expression/action file compilation routines.
  */
 void compile()
 {
         /*
          * Compile regular expressions and C actions into Rules struct,
          * reading from current input file "Fileptr".
          */
         int c, len;

 #ifdef DEBUG
         if ( Debug )
                 error( "compiling...", 0 );
 #endif

         while ( (c = getcharacter()) != -1 )
         {
                 if ( c==' ' || c=='\t' || c=='\n' )
                         /* swallow whitespace */
                         ;
                 else if ( c=='#' )
                 {
                         /*
                          * Swallow comments
                          */
                         while ( (c=getcharacter()) != -1 && c!='\n' )
                                 ;
                 }
                 else if ( c=='{' )
                 {
 #ifdef DEBUG
                         if ( Debug )
                                 error( "action", 0 );
 #endif
                         /*
                          * Compile (tokenize) the action string into our
                          * global work buffer, then allocate some memory
                          * for it and copy it over.
                          */
                         ungetcharacter( '{' );
                         len = act_compile( Workbuf );

                         if ( Rulep && Rulep->action )
                         {
                                 Rulep->nextrule =
                                         (RULE *)getmem(sizeof(RULE));
                                 Rulep = Rulep->nextrule;
                                 fillmem( Rulep, sizeof(RULE), 0 );
                         }
                         if ( !Rulep )
                         {
                                 /*
                                  * This is the first action encountered.
                                  * Allocate the first Rules structure and
                                  * initialize it
                                  */
                                 Rules = Rulep =
                                         (RULE *)getmem(sizeof(RULE));
                                 fillmem( Rulep, sizeof(RULE), 0 );
                         }
                         Rulep->action = getmem( len );
                         movemem( Workbuf, Rulep->action, len );
                 }
                 else if ( c==',' )
                 {
 #ifdef DEBUG
                         if ( Debug )
                                 error( "stop pattern", 0 );
 #endif
                         /*
                          * It's (hopefully) the second part of a two-part
                          * pattern string.  Swallow the comma and start
                          * compiling an action string.
                          */
                         if ( !Rulep || !Rulep->pattern.start )
                                 error( "stop pattern without a start",
                                         RE_ERROR );
                         if ( Rulep->pattern.stop )
                                 error( "already have a stop pattern",
                                         RE_ERROR );
                         len = pat_compile( Workbuf );
                         Rulep->pattern.stop = getmem( len );
                         movemem( Workbuf, Rulep->pattern.stop, len );
                 }
                 else
                 {
                         /*
                          * Assume it's a regular expression pattern
                          */
 #ifdef DEBUG
                         if ( Debug )
                                 error( "start pattern", 0 );
 #endif

                         ungetcharacter( c );
                         len = pat_compile( Workbuf );

                         if ( *Workbuf == T_BEGIN )
                         {
                                 /*
                                  * Saw a "BEGIN" keyword - compile following
                                  * action into special "Beginact" buffer.
                                  */
                                 len = act_compile( Workbuf );
                                 Beginact = getmem( len );
                                 movemem( Workbuf, Beginact, len );
                                 continue;
                         }
                         if ( *Workbuf == T_END )
                         {
                                 /*
                                  * Saw an "END" keyword - compile following
                                  * action into special "Endact" buffer.
                                  */
                                 len = act_compile( Workbuf );
                                 Endact = getmem( len );
                                 movemem( Workbuf, Endact, len );
                                 continue;
                         }
                         if ( Rulep )
                         {
                                 /*
                                  * Already saw a pattern/action - link in
                                  * another Rules structure.
                                  */
                                 Rulep->nextrule =
                                         (RULE *)getmem(sizeof(RULE));
                                 Rulep = Rulep->nextrule;
                                 fillmem( Rulep, sizeof(RULE), 0 );
                         }
                         if ( !Rulep )
                         {
                                 /*
                                  * This is the first pattern encountered.
                                  * Allocate the first Rules structure and
                                  * initialize it
                                  */
                                 Rules = Rulep =
                                         (RULE *)getmem(sizeof(RULE));
                                 fillmem( Rulep, sizeof(RULE), 0 );
                         }
                         if ( Rulep->pattern.start )
                                 error( "already have a start pattern",
                                         RE_ERROR );

                         Rulep->pattern.start = getmem( len );
                         movemem( Workbuf, Rulep->pattern.start, len );
                 }
         }
         endfile();
 }

 /*
  * Text file main processing loop.
  */
 void process()
 {
         /*
          * Read a line at a time from current input file at "Fileptr",
          * then apply each rule in the Rules chain to the input line.
          */
         int i;

 #ifdef DEBUG
         if ( Debug )
                 error( "processing...", 0 );
 #endif

         Recordcount = 0;

         while ( getline() )
         {
                 /*
                  * Parse the input line.
                  */
                 Fieldcount = parse( Linebuf, Fields, Fldsep );
 #ifdef DEBUG
                 if ( Debug>1 )
                 {
                         printf( "parsed %d words:\n", Fieldcount );
                         for(i=0; i<Fieldcount; ++i )
                                 printf( "<%s>\n", Fields[i] );
                 }
 #endif

                 Rulep = Rules;
                 do
                 {
                         if ( ! Rulep->pattern.start )
                         {
                                 /*
                                  * No pattern given - perform action on
                                  * every input line.
                                  */
                                 doaction( Rulep->action );
                         }
                         else if ( Rulep->pattern.startseen )
                         {
                                 /*
                                  * Start pattern already found - perform
                                  * action then check if line matches
                                  * stop pattern.
                                  */
                                 doaction( Rulep->action );
                                 if ( dopattern( Rulep->pattern.stop ) )
                                         Rulep->pattern.startseen = 0;
                         }
                         else if ( dopattern( Rulep->pattern.start ) )
                         {
                                 /*
                                  * Matched start pattern - perform action.
                                  * If a stop pattern was given, set "start
                                  * pattern seen" flag and process every input
                                  * line until stop pattern found.
                                  */
                                 doaction( Rulep->action );
                                 if ( Rulep->pattern.stop )
                                         Rulep->pattern.startseen = 1;
                         }
                 }
                 while ( Rulep = Rulep->nextrule );

                 /*
                  * Release memory allocated by parse().
                  */
                 while ( Fieldcount )
                         free( Fields[ --Fieldcount ] );
         }
 }

 /*
  * Miscellaneous functions
  */
 int parse( str, wrdlst, delim )
 char *str;
 char *wrdlst[];
 char *delim;
 {
         /*
          * Parse the string of words in "str" into the word list at "wrdlst".
          * A "word" is a sequence of characters delimited by one or more
          * of the characters found in the string "delim".
          * Returns the number of words parsed.
          * CAUTION: the memory for the words in "wrdlst" is allocated
          * by malloc() and should eventually be returned by free()...
          */
         int wrdcnt, wrdlen;
         char wrdbuf[ MAXLINELEN ], c;

         wrdcnt = 0;
         while ( *str )
         {
                 while ( instr( *str, delim ) )
                         ++str;
                 if ( !*str )
                         break;
                 wrdlen = 0;
                 while ( (c = *str) && !instr( c, delim ) )
                 {
                         wrdbuf[ wrdlen++ ] = c;
                         ++str;
                 }
                 wrdbuf[ wrdlen++ ] = 0;
                 /*
                  * NOTE: allocate a MAXLINELEN sized buffer for every
                  * word, just in case user wants to copy a larger string
                  * into a field.
                  */
                 wrdlst[ wrdcnt ] = getmem( MAXLINELEN );
                 strcpy( wrdlst[ wrdcnt++ ], wrdbuf );
         }

         return wrdcnt;
 }

 void unparse( wrdlst, wrdcnt, str, delim )
 char *wrdlst[];
 int wrdcnt;
 char *str;
 char *delim;
 {
         /*
          * Replace all the words in "str" with the words in "wrdlst",
          * maintaining the same word seperation distance as found in
          * the string.
          * A "word" is a sequence of characters delimited by one or more
          * of the characters found in the string "delim".
          */
         int wc;
         char strbuf[ MAXLINELEN ], *sp, *wp, *start;

         wc = 0;                /* next word in "wrdlst" */
         sp = strbuf;        /* points to our local string */
         start = str;        /* save start address of "str" for later... */
         while ( *str )
         {
                 /*
                  * Copy the field delimiters from the original string to
                  * our local version.
                  */
                 while ( instr( *str, delim ) )
                         *sp++ = *str++;
                 if ( !*str )
                         break;
                 /*
                  * Skip over the field in the original string and...
                  */
                 while ( *str && !instr( *str, delim ) )
                         ++str;

                 if ( wc < wrdcnt )
                 {
                         /*
                          * ...copy in the field in the wordlist instead.
                          */
                         wp = wrdlst[ wc++ ];
                         while ( *wp )
                                 *sp++ = *wp++;
                 }
         }
         /*
          * Tie off the local string, then copy it back to caller's string.
          */
         *sp = 0;
         strcpy( start, strbuf );
 }

 int instr( c, s )
 char c, *s;
 {
         while ( *s )
                 if ( c==*s++ )
                         return 1;
         return 0;
 }

 char *getmem( len )
 unsigned len;
 {
         char *cp;

         if (cp = malloc(len)) return cp;
         error( "out of memory", MEM_ERROR );
 }

 void newfile(s)
 char *s;
 {
         Linecount = 0;
         if ( Filename = s )
         {
                 if ( !(Fileptr = fopen( s, "r" )) )
                         error( "file not found", FILE_ERROR );
         }
         else
         {
                 /*
                  * No file name given - process standard input.
                  */
                 Fileptr = stdin;
                 Filename = "standard input";
         }
 }

 int getline()
 {
         /*
          * Read a line of text from current input file.         Strip off
          * trailing record seperator (newline).
          */
         int rtn, len;

         for ( len=0; len<MAXLINELEN; ++len )
         {
                 if ( (rtn = getcharacter()) == *Rcrdsep || rtn == -1 )
                         break;
                 Linebuf[ len ] = rtn;
         }
         Linebuf[ len ] = 0;

         if ( rtn == -1 )
         {
                 endfile();
                 return 0;
         }
         return 1;
 }

 int getcharacter()
 {
         /*
          * Read a character from curren input file.
          * WARNING: your getc() must convert lines that end with CR+LF
          * to LF and EOF marks (like CP/M's ^Z) to a -1.
          * Also, getc() must return a -1 when attempting to read from
          * an unopened file.
          */
         int c;

         if ((c = getc(Fileptr)) == *Rcrdsep )
                 ++Recordcount;
         if ( c=='\n' )
                 ++Linecount;

         return c;
 }

 int ungetcharacter( c )
 {
         /*
          * Push a character back into the input stream.
          * If the character is a record seperator, or a newline character,
          * the record and line counters are adjusted appropriately.
          */
         if ( c == *Rcrdsep )
                 --Recordcount;
         if ( c=='\n' )
                 --Linecount;
         return ungetc( c, Fileptr );
 }

 void endfile()
 {
         fclose( Fileptr );
         Filename = NULL;  Linecount = 0;
 }

 void error( s, severe )
 char *s;
 int severe;
 {
         if ( Filename )
                 fprintf( stderr, "%s:", Filename );

         if ( Linecount )
                 fprintf( stderr, " line %d:", Linecount );

         fprintf( stderr, " %s\n", s );
         if ( severe )
                 exit( severe );
 }

 void usage()
 {
         error( "Usage: bawk <actfile> [<file> ...]\n", USAGE_ERROR );
 }

 void movemem( from, to, count )
 char *from, *to;
 int count;
 {
         while ( count-- > 0 )
                 *to++ = *from++;
 }

 void fillmem( array, count, value )
 char *array, value;
 int count;
 {
         while ( count-- > 0 )
                 *array++ = value;
 }

 int alpha( c )
 char c;
 {
         return isalpha(c) || c == '_';
 }

 int alphanum( c )
 char c;
 {
         return isalnum(c) || c == '_';
 }


 BAWK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\BAWK\BAWK.C

 /*
  * Bawk main program
  */
 #define MAIN 1
 #include <stdio.h>
 #include "bawk.h"

 /*
  * Main program
  */
 main( argc, argv )
 int argc;
 char **argv;
 {
         char gotrules, didfile, getstdin;

         getstdin =
         didfile =
         gotrules = 0;

         /*
          * Initialize global variables:
          */
         Beginact =
         Endact =
         Rules =
         Rulep =
 #ifdef DEBUG
         Debug =
 #endif
         Filename =
         Linecount =
         Saw_break = 0;
         Stackptr = Stackbtm - 1;
         Stacktop = Stackbtm + MAXSTACKSZ;
         Nextvar = Vartab;

         strcpy( Fieldsep, " \t" );
         strcpy( Recordsep, "\n" );

         /*
          * Parse command line
          */
         while ( --argc )
         {
                 if ( **(++argv) == '-' )
                 {
                         /*
                          * Process dash options.
                          */
                         switch ( tolower( *(++(*argv)) ) )
                         {
 #ifdef DEBUG
                         case 'd':
                                 ++Debug;
                                 break;
 #endif
                         case 0:
                                 ++getstdin;
                                 --argv;
                                 goto dosomething;
                                 break;
                         default: usage();
                         }
                 }
                 else
                 {
 dosomething:
                         if ( gotrules )
                         {
                                 /*
                                  * Already read rules file - assume this is
                                  * is a text file for processing.
                                  */
                                 if ( ++didfile == 1 && Beginact )
                                         doaction( Beginact );
                                 if ( getstdin )
                                 {
                                         --getstdin;
                                         newfile( 0 );
                                 }
                                 else
                                         newfile( *argv );
                                 process();
                         }
                         else
                         {
                                 /*
                                  * First file name argument on command line
                                  * is assumed to be a rules file - attempt to
                                  * compile it.
                                  */
                                 if ( getstdin )
                                 {
                                         --getstdin;
                                         newfile( 0 );
                                 }
                                 else
                                         newfile( *argv );
                                 compile();
                                 gotrules = 1;
                         }
                 }
         }
         if ( !gotrules )
                 usage();

         if ( ! didfile )
         {
                 /*
                  * Didn't process any files yet - process stdin.
                  */
                 newfile( 0 );
                 if ( Beginact )
                         doaction( Beginact );
                 process();
         }
         if ( Endact )
                 doaction( Endact );
 }

 /*
  * Regular expression/action file compilation routines.
  */
 compile()
 {
         /*
          * Compile regular expressions and C actions into Rules struct,
          * reading from current input file "Fileptr".
          */
         int c, len;

 #ifdef DEBUG
         if ( Debug )
                 error( "compiling...", 0 );
 #endif

         while ( (c = getcharacter()) != -1 )
         {
                 if ( c==' ' || c=='\t' || c=='\n' )
                         /* swallow whitespace */
                         ;
                 else if ( c=='#' )
                 {
                         /*
                          * Swallow comments
                          */
                         while ( (c=getcharacter()) != -1 && c!='\n' )
                                 ;
                 }
                 else if ( c=='{' )
                 {
 #ifdef DEBUG
                         if ( Debug )
                                 error( "action", 0 );
 #endif
                         /*
                          * Compile (tokenize) the action string into our
                          * global work buffer, then allocate some memory
                          * for it and copy it over.
                          */
                         ungetcharacter( '{' );
                         len = act_compile( Workbuf );

                         if ( Rulep && Rulep->action )
                         {
                                 Rulep->nextrule = getmem( sizeof( *Rulep ) );
                                 Rulep = Rulep->nextrule;
                                 fillmem( Rulep, sizeof( *Rulep ), 0 );
                         }
                         if ( !Rulep )
                         {
                                 /*
                                  * This is the first action encountered.
                                  * Allocate the first Rules structure and
                                  * initialize it
                                  */
                                 Rules = Rulep = getmem( sizeof( *Rulep ) );
                                 fillmem( Rulep, sizeof( *Rulep ), 0 );
                         }
                         Rulep->action = getmem( len );
                         movemem( Workbuf, Rulep->action, len );
                 }
                 else if ( c==',' )
                 {
 #ifdef DEBUG
                         if ( Debug )
                                 error( "stop pattern", 0 );
 #endif
                         /*
                          * It's (hopefully) the second part of a two-part
                          * pattern string.  Swallow the comma and start
                          * compiling an action string.
                          */
                         if ( !Rulep || !Rulep->pattern.start )
                                 error( "stop pattern without a start",
                                         RE_ERROR );
                         if ( Rulep->pattern.stop )
                                 error( "already have a stop pattern",
                                         RE_ERROR );
                         len = pat_compile( Workbuf );
                         Rulep->pattern.stop = getmem( len );
                         movemem( Workbuf, Rulep->pattern.stop, len );
                 }
                 else
                 {
                         /*
                          * Assume it's a regular expression pattern
                          */
 #ifdef DEBUG
                         if ( Debug )
                                 error( "start pattern", 0 );
 #endif

                         ungetcharacter( c );
                         len = pat_compile( Workbuf );

                         if ( *Workbuf == T_BEGIN )
                         {
                                 /*
                                  * Saw a "BEGIN" keyword - compile following
                                  * action into special "Beginact" buffer.
                                  */
                                 len = act_compile( Workbuf );
                                 Beginact = getmem( len );
                                 movemem( Workbuf, Beginact, len );
                                 continue;
                         }
                         if ( *Workbuf == T_END )
                         {
                                 /*
                                  * Saw an "END" keyword - compile following
                                  * action into special "Endact" buffer.
                                  */
                                 len = act_compile( Workbuf );
                                 Endact = getmem( len );
                                 movemem( Workbuf, Endact, len );
                                 continue;
                         }
                         if ( Rulep )
                         {
                                 /*
                                  * Already saw a pattern/action - link in
                                  * another Rules structure.
                                  */
                                 Rulep->nextrule = getmem( sizeof( *Rulep ) );
                                 Rulep = Rulep->nextrule;
                                 fillmem( Rulep, sizeof( *Rulep ), 0 );
                         }
                         if ( !Rulep )
                         {
                                 /*
                                  * This is the first pattern encountered.
                                  * Allocate the first Rules structure and
                                  * initialize it
                                  */
                                 Rules = Rulep = getmem( sizeof( *Rulep ) );
                                 fillmem( Rulep, sizeof( *Rulep ), 0 );
                         }
                         if ( Rulep->pattern.start )
                                 error( "already have a start pattern",
                                         RE_ERROR );

                         Rulep->pattern.start = getmem( len );
                         movemem( Workbuf, Rulep->pattern.start, len );
                 }
         }
         endfile();
 }

 /*
  * Text file main processing loop.
  */
 process()
 {
         /*
          * Read a line at a time from current input file at "Fileptr",
          * then apply each rule in the Rules chain to the input line.
          */
         int i;

 #ifdef DEBUG
         if ( Debug )
                 error( "processing...", 0 );
 #endif

         Recordcount = 0;

         while ( getline() )
         {
                 /*
                  * Parse the input line.
                  */
                 Fieldcount = parse( Linebuf, Fields, Fieldsep );
 #ifdef DEBUG
                 if ( Debug>1 )
                 {
                         printf( "parsed %d words:\n", Fieldcount );
                         for(i=0; i<Fieldcount; ++i )
                                 printf( "<%s>\n", Fields[i] );
                 }
 #endif

                 Rulep = Rules;
                 do
                 {
                         if ( ! Rulep->pattern.start )
                         {
                                 /*
                                  * No pattern given - perform action on
                                  * every input line.
                                  */
                                 doaction( Rulep->action );
                         }
                         else if ( Rulep->pattern.startseen )
                         {
                                 /*
                                  * Start pattern already found - perform
                                  * action then check if line matches
                                  * stop pattern.
                                  */
                                 doaction( Rulep->action );
                                 if ( dopattern( Rulep->pattern.stop ) )
                                         Rulep->pattern.startseen = 0;
                         }
                         else if ( dopattern( Rulep->pattern.start ) )
                         {
                                 /*
                                  * Matched start pattern - perform action.
                                  * If a stop pattern was given, set "start
                                  * pattern seen" flag and process every input
                                  * line until stop pattern found.
                                  */
                                 doaction( Rulep->action );
                                 if ( Rulep->pattern.stop )
                                         Rulep->pattern.startseen = 1;
                         }
                 }
                 while ( Rulep = Rulep->nextrule );

                 /*
                  * Release memory allocated by parse().
                  */
                 while ( Fieldcount )
                         free( Fields[ --Fieldcount ] );
         }
 }

 /*
  * Miscellaneous functions
  */
 parse( str, wrdlst, delim )
 char *str;
 char *wrdlst[];
 char *delim;
 {
         /*
          * Parse the string of words in "str" into the word list at "wrdlst".
          * A "word" is a sequence of characters delimited by one or more
          * of the characters found in the string "delim".
          * Returns the number of words parsed.
          * CAUTION: the memory for the words in "wrdlst" is allocated
          * by malloc() and should eventually be returned by free()...
          */
         int wrdcnt, wrdlen;
         char wrdbuf[ MAXLINELEN ], c;

         wrdcnt = 0;
         while ( *str )
         {
                 while ( instr( *str, delim ) )
                         ++str;
                 if ( !*str )
                         break;
                 wrdlen = 0;
                 while ( (c = *str) && !instr( c, delim ) )
                 {
                         wrdbuf[ wrdlen++ ] = c;
                         ++str;
                 }
                 wrdbuf[ wrdlen++ ] = 0;
                 /*
                  * NOTE: allocate a MAXLINELEN sized buffer for every
                  * word, just in case user wants to copy a larger string
                  * into a field.
                  */
                 wrdlst[ wrdcnt ] = getmem( MAXLINELEN );
                 strcpy( wrdlst[ wrdcnt++ ], wrdbuf );
         }

         return wrdcnt;
 }

 unparse( wrdlst, wrdcnt, str, delim )
 char *wrdlst[];
 int wrdcnt;
 char *str;
 char *delim;
 {
         /*
          * Replace all the words in "str" with the words in "wrdlst",
          * maintaining the same word seperation distance as found in
          * the string.
          * A "word" is a sequence of characters delimited by one or more
          * of the characters found in the string "delim".
          */
         int wc;
         char strbuf[ MAXLINELEN ], *sp, *wp, *start;

         wc = 0;                /* next word in "wrdlst" */
         sp = strbuf;        /* points to our local string */
         start = str;        /* save start address of "str" for later... */
         while ( *str )
         {
                 /*
                  * Copy the field delimiters from the original string to
                  * our local version.
                  */
                 while ( instr( *str, delim ) )
                         *sp++ = *str++;
                 if ( !*str )
                         break;
                 /*
                  * Skip over the field in the original string and...
                  */
                 while ( *str && !instr( *str, delim ) )
                         ++str;

                 if ( wc < wrdcnt )
                 {
                         /*
                          * ...copy in the field in the wordlist instead.
                          */
                         wp = wrdlst[ wc++ ];
                         while ( *wp )
                                 *sp++ = *wp++;
                 }
         }
         /*
          * Tie off the local string, then copy it back to caller's string.
          */
         *sp = 0;
         strcpy( start, strbuf );
 }

 instr( c, s )
 char c, *s;
 {
         while ( *s )
                 if ( c==*s++ )
                         return 1;
         return 0;
 }

 char *
 getmem( len )
 unsigned len;
 {
         char *cp;

         if ( cp=malloc( len ) )
                 return cp;
         error( "out of memory", MEM_ERROR );
 }

 char *
 newfile( s )
 char *s;
 {
         Linecount = 0;
         if ( Filename = s )
         {
 #ifdef BDS_C
                 if ( fopen( s, Fileptr = Curfbuf ) == -1 )
 #else
                 if ( !(Fileptr = fopen( s, "r" )) )
 #endif
                         error( "file not found", FILE_ERROR );
         }
         else
         {
                 /*
                  * No file name given - process standard input.
                  */
                 Fileptr = stdin;
                 Filename = "standard input";
         }
 }

 getline()
 {
         /*
          * Read a line of text from current input file.  Strip off
          * trailing record seperator (newline).
          */
         int rtn, len;

         for ( len=0; len<MAXLINELEN; ++len )
         {
                 if ( (rtn = getcharacter()) == *Recordsep || rtn == -1 )
                         break;
                 Linebuf[ len ] = rtn;
         }
         Linebuf[ len ] = 0;

         if ( rtn == -1 )
         {
                 endfile();
                 return 0;
         }
         return 1;
 }

 getcharacter()
 {
         /*
          * Read a character from curren input file.
          * WARNING: your getc() must convert lines that end with CR+LF
          * to LF and CP/M's EOF character (^Z) to a -1.
          * Also, getc() must return a -1 when attempting to read from
          * an unopened file.
          */
         int c;

 #ifdef BDS_C
         /*
          * BDS C doesn't do CR+LF to LF and ^Z to -1 conversions <gag>
          */
         if ( (c = getc( Fileptr )) == '\r' )
         {
                 if ( (c = getc( Fileptr )) != '\n' )
                 {
                         ungetc( c );
                         c = '\r';
                 }
         }
         else if ( c == 26 )        /* ^Z */
                 c = -1;
 #else
         c = getc( Fileptr );
 #endif

         if ( c == *Recordsep )
                 ++Recordcount;
         if ( c=='\n' )
                 ++Linecount;

         return c;
 }

 ungetcharacter( c )
 {
         /*
          * Push a character back into the input stream.
          * If the character is a record seperator, or a newline character,
          * the record and line counters are adjusted appropriately.
          */
         if ( c == *Recordsep )
                 --Recordcount;
         if ( c=='\n' )
                 --Linecount;
         return ungetc( c, Fileptr );
 }

 endfile()
 {
         fclose( Fileptr );
         Filename = Linecount = 0;
 }

 error( s, severe )
 char *s;
 int severe;
 {
         char *cp, *errat;

         if ( Filename )
                 fprintf( stderr, "%s:", Filename );

         if ( Linecount )
                 fprintf( stderr, " line %d:", Linecount );

         fprintf( stderr, " %s\n", s );
         if ( severe )
                 exit( severe );
 }

 usage()
 {
         error( "Usage: bawk <actfile> [<file> ...]\n", USAGE_ERROR );
 }

 movemem( from, to, count )
 char *from, *to;
 int count;
 {
         while ( count-- > 0 )
                 *to++ = *from++;
 }

 fillmem( array, count, value )
 char *array, value;
 int count;
 {
         while ( count-- > 0 )
                 *array++ = value;
 }

 strncmp( s, t, n )
 char *s, *t;
 int n;
 {
         while ( --n>0 && *s && *t && *s==*t )
         {
                 ++s;
                 ++t;
         }
         if ( *s || *t )
                 return *s - *t;
         return 0;
 }

 num( c )
 char c;
 {
         return '0'<=c && c<='9';
 }

 alpha( c )
 char c;
 {
         return ('a'<=c && c<='z') || ('A'<=c && c<='Z') || c=='_';
 }

 alphanum( c )
 char c;
 {
         return alpha( c ) || num( c );
 }


 BAWKACT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\BAWKACT.C

 /*
         HEADER:                CUG236;
         TITLE:                BAWK Actions Compiler;
         DATE:                05/17/1987;
         VERSION:        1.1;
         FILENAME:        BAWKACT.C;
         SEE-ALSO:        BAWK.C;
         AUTHORS:        W. C. Colley III, B. Brodt;
 */

 /*
  * Bawk C actions compiler
  */
 #include <stdio.h>
 #include "bawk.h"

 /* Functions local to this module.        */

 char *str_compile();
 int stmt_compile();

 int act_compile( actbuf )
 char        *actbuf;        /* where tokenized actions are compiled into */
 {
         Where = ACTION;
         return stmt_compile( actbuf );
 }

 int pat_compile( actbuf )
 char        *actbuf;        /* where tokenized actions are compiled into */
 {
         Where = PATTERN;
         return stmt_compile( actbuf );
 }

 int stmt_compile( actbuf )
 char        *actbuf;        /* where tokenized actions are compiled into */
 {
         /*
          * Read and tokenize C actions from current input file into the
          * action buffer.  Strip out comments and whitespace in the
          * process.
          */
         char        *actptr,        /* actbuf pointer */
                 *cp,                /* work pointer */
                 buf[MAXLINELEN];/* string buffer */
         int        braces,                /* counts '{}' pairs - return when
                 parens,                /* counts '()' pairs */
                 i,                /* temp */
                 c;                /* current input character */

         braces = parens = 0;
         actptr = actbuf;
         while ( (c = getcharacter()) != -1 )
         {
                 /*
                  * Skip over spaces, tabs and newlines
                  */
                 if ( c==' ' || c=='\t' || c=='\n' )
                         continue;
                 if ( c=='#' )
                 {
                         /*
                          * Skip comments.  Comments start with a '#' and
                          * end at the next newline.
                          */
                         while ( (c = getcharacter()) != -1 && c!='\n' )
                                 ;
                         continue;
                 }

                 if ( c=='{' )
                 {
                         if ( Where==PATTERN )
                         {
                                 /*
                                  * We're compiling a pattern. The '{' marks
                                  * the beginning of an action statement.
                                  * Push the character back and return.
                                  */
                                 ungetcharacter( '{' );
                                 break;
                         }
                         else
                         {
                                 /*
                                  * We must be compiling an action statement.
                                  * '{'s mark beginning of action or compound
                                  * statements.
                                  */
                                 ++braces;
                                 *actptr++ = T_LBRACE;
                         }
                 }
                 else if ( c=='}' )
                 {
                         *actptr++ = T_RBRACE;
                         if ( ! --braces )
                                 /*
                                  * Found the end of the action string
                                  */
                                 break;
                 }
                 else if ( c=='(' )
                 {
                         ++parens;
                         *actptr++ = T_LPAREN;
                 }
                 else if ( c==')' )
                 {
                         if ( --parens < 0 )
                                 error( "mismatched '()'", ACT_ERROR );
                         *actptr++ = T_RPAREN;
                 }
                 else if ( c==',' && !braces && !parens && Where==PATTERN )
                 {
                         /*
                          * found a comma outside of any braces or parens-
                          * this must be a regular expression seperator.
                          */
                         ungetcharacter( ',' );
                         break;
                 }

                 /*
                  * Check if it's a regular expression:
                  */
                 else if ( c=='/' )
                 {
                         /*
                          * A '/' inside a pattern string starts a regular
                          * expression.        Inside action strings, a '/' is
                          * the division operator.
                          */
                         if ( Where == PATTERN )
                                 goto dopattern;
                         else
                                 *actptr++ = T_DIV;
                 }
                 else if ( c=='@' )
                 {
 dopattern:
                         /*
                          * Within action strings, only the '@' may be used to
                          * delimit regular expressions
                          */
                         *actptr++ = T_REGEXP;
                         ungetcharacter( c );
                         actptr += re_compile( actptr );
                 }

                 /*
                  * symbol, string or constant:
                  */
                 else if ( alpha( c ) )
                 {
                         /*
                          * It's a symbol reference. Copy the symbol into
                          * string buffer.
                          */
                         cp = buf;
                         do
                                 *cp++ = c;
                         while ( (c=getcharacter()) != -1 && alphanum( c ) );
                         ungetcharacter( c );
                         *cp = 0;
                         /*
                          * Check if a keyword, builtin function or variable.
                          */
                         if ( c = iskeyword( buf ) )
                                 *actptr++ = c;
                         else if ( i = isfunction( buf ) )
                         {
                                 *actptr++ = T_FUNCTION;
                                 *((int *)actptr)++ = i;
                         }
                         else
                         {
                                 /*
                                  * It's a symbol name.
                                  */
                                 *actptr++ = T_VARIABLE;
                                 if (!(cp = (char *)findvar(buf)))
                                         cp = (char *)addvar(buf);
                                 *((char **)actptr)++ = cp;
                         }
                 }

                 else if ( c == '"' )
                 {
                         /*
                          * It's a string constant
                          */
                         *actptr++ = T_STRING;
                         actptr = str_compile( actptr, '"' );
                 }
                 else if ( c == '\'' )
                 {
                         /*
                          * It's a character constant
                          */
                         *actptr++ = T_CONSTANT;
                         str_compile( buf, '\'' );
                         *((int *)actptr)++ = *buf;
                 }

                 else if (isdigit(c))
                 {
                         /*
                          * It's a numeric constant
                          */
                         *actptr++ = T_CONSTANT;
                         cp = buf;
                         do
                                 *cp++ = c;
                         while ((c=getcharacter()) != -1 && isdigit(c));
                         ungetcharacter( c );
                         *cp = 0;
                         *((int *)actptr)++ = atoi(buf);
                 }

                 /*
                  * unary operator:
                  */
                 else if ( c == '$' )
                         *actptr++ = T_DOLLAR;

                 /*
                  * or binary operator:
                  */
                 else if ( c == '=' )
                 {
                         if ( (c=getcharacter()) == '=' )
                                 *actptr++ = T_EQ;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_ASSIGN;
                         }
                 }

                 else if ( c == '!' )
                 {
                         if ( (c=getcharacter()) == '=' )
                                 *actptr++ = T_NE;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_LNOT;
                         }
                 }

                 else if ( c == '<' )
                 {
                         if ( (c=getcharacter()) == '<' )
                                 *actptr++ = T_SHL;
                         else if ( c == '=' )
                                 *actptr++ = T_LE;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_LT;
                         }
                 }

                 else if ( c == '>' )
                 {
                         if ( (c=getcharacter()) == '>' )
                                 *actptr++ = T_SHR;
                         else if ( c == '=' )
                                 *actptr++ = T_GE;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_GT;
                         }
                 }

                 else if ( c == '&' )
                 {
                         if ( (c=getcharacter()) == '&' )
                                 *actptr++ = T_LAND;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_AND;
                         }
                 }

                 else if ( c == '|' )
                 {
                         if ( (c=getcharacter()) == '|' )
                                 *actptr++ = T_LIOR;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_IOR;
                         }
                 }
                 else if ( c == '+' )
                 {
                         if ( (c=getcharacter()) == '+' )
                                 *actptr++ = T_INCR;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_ADD;
                         }
                 }

                 else if ( c == '-' )
                 {
                         if ( (c=getcharacter()) == '-' )
                                 *actptr++ = T_DECR;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_SUB;
                         }
                 }

                 /*
                  * punctuation
                  */
                 else if ( instr( c, "[](),;*/%+-^~" ) )
                         *actptr++ = c;

                 else
                 {
                         /*
                          * Bad character in input line
                          */
                         error( "lexical error", ACT_ERROR );
                 }

                 if ( actptr >= Workbuf + MAXWORKBUFLEN )
                         error( "action too long", MEM_ERROR );
         }
         if ( braces || parens )
                 error( "mismatched '{}' or '()'", ACT_ERROR );

         *actptr++ = T_EOF;

         return actptr - actbuf;
 }

 char *str_compile( str, delim )
 char *str, delim;
 {
         /*
          * Compile a string from current input file into the given string
          * buffer.  Stop when input character is the delimiter in "delim".
          * Returns a pointer to the first character after the string.
          */
         int c;
         char buf[ MAXLINELEN ];

         while ( (c = getcharacter()) != -1 && c != delim)
         {
                 if ( c        == '\\' )
                 {
                         switch ( c = getcharacter() )
                         {
                         case -1: goto err;
                         case 'b': c = '\b'; break;
                         case 'n': c = '\n'; break;
                         case 't': c = '\t'; break;
                         case 'f': c = '\f'; break;
                         case 'r': c = '\r'; break;
                         case '0':
                         case '1':
                         case '2':
                         case '3':
                                 *buf = c;
                                 for ( c=1; c<3; ++c )
                                 {
                                         if ( (buf[c]=getcharacter()) == -1 )
                                                 goto err;
                                 }
                                 buf[c] = 0;
                                 sscanf( buf, "%o", &c );
                                 break;
                         case '\n':
                                 if ( getcharacter() == -1 )
                                         goto err;
                         default:
                                 if ( (c = getcharacter()) == -1 )
                                         goto err;
                         }
                 }
                 *str++ = c;
         }
         *str++ = 0;

         return str;
 err:
         sprintf( buf, "missing %c delimiter", delim );
         error( buf, 4 );
 }

 int getoken()
 {
         switch ( Token = *Actptr++ )
         {
         case T_STRING:
         case T_REGEXP:
                 Value.dptr = Actptr;
                 Actptr += strlen( Actptr ) + 1;
                 break;
         case T_VARIABLE:
                 Value.dptr = *((char **)Actptr)++;
                 break;
         case T_FUNCTION:
         case T_CONSTANT:
                 Value.ival = *((int *)Actptr)++;
                 break;
         case T_EOF:
                 --Actptr;
         default:
                 Value.dptr = 0;
         }

 #ifdef DEBUG
         if ( Debug > 1 )
                 printf( "Token='%c' (0x%x), Value=%d\n",
                         Token,Token,Value.ival );
 #endif

         return Token;
 }


 BAWKACT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\BAWK\BAWKACT.C

 /*
  * Bawk C actions compiler
  */
 #include <stdio.h>
 #include "bawk.h"

 act_compile( actbuf )
 char        *actbuf;        /* where tokenized actions are compiled into */
 {
         Where = ACTION;
         return stmt_compile( actbuf );
 }

 pat_compile( actbuf )
 char        *actbuf;        /* where tokenized actions are compiled into */
 {
         Where = PATTERN;
         return stmt_compile( actbuf );
 }

 stmt_compile( actbuf )
 char        *actbuf;        /* where tokenized actions are compiled into */
 {
         /*
          * Read and tokenize C actions from current input file into the
          * action buffer.  Strip out comments and whitespace in the
          * process.
          */
         char        *actptr,        /* actbuf pointer */
                 *cp,                /* work pointer */
                 buf[MAXLINELEN];/* string buffer */
         int        braces,                /* counts '{}' pairs - return when
                 parens,                /* counts '()' pairs */
                 i,                /* temp */
                 c;                /* current input character */

         braces = parens = 0;
         actptr = actbuf;
         while ( (c = getcharacter()) != -1 )
         {
                 /*
                  * Skip over spaces, tabs and newlines
                  */
                 if ( c==' ' || c=='\t' || c=='\n' )
                         continue;
                 if ( c=='#' )
                 {
                         /*
                          * Skip comments.  Comments start with a '#' and
                          * end at the next newline.
                          */
                         while ( (c = getcharacter()) != -1 && c!='\n' )
                                 ;
                         continue;
                 }

                 if ( c=='{' )
                 {
                         if ( Where==PATTERN )
                         {
                                 /*
                                  * We're compiling a pattern. The '{' marks
                                  * the beginning of an action statement.
                                  * Push the character back and return.
                                  */
                                 ungetcharacter( '{' );
                                 break;
                         }
                         else
                         {
                                 /*
                                  * We must be compiling an action statement.
                                  * '{'s mark beginning of action or compound
                                  * statements.
                                  */
                                 ++braces;
                                 *actptr++ = T_LBRACE;
                         }
                 }
                 else if ( c=='}' )
                 {
                         *actptr++ = T_RBRACE;
                         if ( ! --braces )
                                 /*
                                  * Found the end of the action string
                                  */
                                 break;
                 }
                 else if ( c=='(' )
                 {
                         ++parens;
                         *actptr++ = T_LPAREN;
                 }
                 else if ( c==')' )
                 {
                         if ( --parens < 0 )
                                 error( "mismatched '()'", ACT_ERROR );
                         *actptr++ = T_RPAREN;
                 }
                 else if ( c==',' && !braces && !parens && Where==PATTERN )
                 {
                         /*
                          * found a comma outside of any braces or parens-
                          * this must be a regular expression seperator.
                          */
                         ungetcharacter( ',' );
                         break;
                 }

                 /*
                  * Check if it's a regular expression:
                  */
                 else if ( c=='/' )
                 {
                         /*
                          * A '/' inside a pattern string starts a regular
                          * expression.  Inside action strings, a '/' is
                          * the division operator.
                          */
                         if ( Where == PATTERN )
                                 goto dopattern;
                         else
                                 *actptr++ = T_DIV;
                 }
                 else if ( c=='@' )
                 {
 dopattern:
                         /*
                          * Within action strings, only the '@' may be used to
                          * delimit regular expressions
                          */
                         *actptr++ = T_REGEXP;
                         ungetcharacter( c );
                         actptr += re_compile( actptr );
                 }

                 /*
                  * symbol, string or constant:
                  */
                 else if ( alpha( c ) )
                 {
                         /*
                          * It's a symbol reference. Copy the symbol into
                          * string buffer.
                          */
                         cp = buf;
                         do
                                 *cp++ = c;
                         while ( (c=getcharacter()) != -1 && alphanum( c ) );
                         ungetcharacter( c );
                         *cp = 0;
                         /*
                          * Check if a keyword, builtin function or variable.
                          */
                         if ( c = iskeyword( buf ) )
                                 *actptr++ = c;
                         else if ( i = isfunction( buf ) )
                         {
                                 *actptr++ = T_FUNCTION;
                                 storeint( actptr, i );
                                 actptr += sizeof( i );
                         }
                         else
                         {
                                 /*
                                  * It's a symbol name.
                                  */
                                 *actptr++ = T_VARIABLE;
                                 if ( !(cp = findvar( buf )) )
                                         cp = addvar( buf );
                                 storeptr( actptr, cp );
                                 actptr += sizeof( cp );
                         }
                 }

                 else if ( c == '"' )
                 {
                         /*
                          * It's a string constant
                          */
                         *actptr++ = T_STRING;
                         actptr = str_compile( actptr, '"' );
                 }
                 else if ( c == '\'' )
                 {
                         /*
                          * It's a character constant
                          */
                         *actptr++ = T_CONSTANT;
                         str_compile( buf, '\'' );
                         storeint( actptr, *buf );
                         actptr += sizeof( i );
                 }

                 else if ( num( c ) )
                 {
                         /*
                          * It's a numeric constant
                          */
                         *actptr++ = T_CONSTANT;
                         cp = buf;
                         do
                                 *cp++ = c;
                         while ( (c=getcharacter()) != -1 && num(c) );
                         ungetcharacter( c );
                         *cp = 0;
                         storeint( actptr, atoi( buf ) );
                         actptr += sizeof( i );
                 }

                 /*
                  * unary operator:
                  */
                 else if ( c == '$' )
                         *actptr++ = T_DOLLAR;

                 /*
                  * or binary operator:
                  */
                 else if ( c == '=' )
                 {
                         if ( (c=getcharacter()) == '=' )
                                 *actptr++ = T_EQ;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_ASSIGN;
                         }
                 }

                 else if ( c == '!' )
                 {
                         if ( (c=getcharacter()) == '=' )
                                 *actptr++ = T_NE;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_LNOT;
                         }
                 }

                 else if ( c == '<' )
                 {
                         if ( (c=getcharacter()) == '<' )
                                 *actptr++ = T_SHL;
                         else if ( c == '=' )
                                 *actptr++ = T_LE;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_LT;
                         }
                 }

                 else if ( c == '>' )
                 {
                         if ( (c=getcharacter()) == '>' )
                                 *actptr++ = T_SHR;
                         else if ( c == '=' )
                                 *actptr++ = T_GE;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_GT;
                         }
                 }

                 else if ( c == '&' )
                 {
                         if ( (c=getcharacter()) == '&' )
                                 *actptr++ = T_LAND;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_AND;
                         }
                 }

                 else if ( c == '|' )
                 {
                         if ( (c=getcharacter()) == '|' )
                                 *actptr++ = T_LIOR;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_IOR;
                         }
                 }
                 else if ( c == '+' )
                 {
                         if ( (c=getcharacter()) == '+' )
                                 *actptr++ = T_INCR;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_ADD;
                         }
                 }

                 else if ( c == '-' )
                 {
                         if ( (c=getcharacter()) == '-' )
                                 *actptr++ = T_DECR;
                         else
                         {
                                 ungetcharacter( c );
                                 *actptr++ = T_SUB;
                         }
                 }

                 /*
                  * punctuation
                  */
                 else if ( instr( c, "[](),;*/%+-^~" ) )
                         *actptr++ = c;

                 else
                 {
                         /*
                          * Bad character in input line
                          */
                         error( "lexical error", ACT_ERROR );
                 }

                 if ( actptr >= Workbuf + MAXWORKBUFLEN )
                         error( "action too long", MEM_ERROR );
         }
         if ( braces || parens )
                 error( "mismatched '{}' or '()'", ACT_ERROR );

         *actptr++ = T_EOF;

         return actptr - actbuf;
 }

 str_compile( str, delim )
 char *str, delim;
 {
         /*
          * Compile a string from current input file into the given string
          * buffer.  Stop when input character is the delimiter in "delim".
          * Returns a pointer to the first character after the string.
          */
         int c;
         char buf[ MAXLINELEN ];

         while ( (c = getcharacter()) != -1 && c != delim)
         {
                 if ( c  == '\\' )
                 {
                         switch ( c = getcharacter() )
                         {
                         case -1: goto err;
                         case 'b': c = '\b'; break;
                         case 'n': c = '\n'; break;
                         case 't': c = '\t'; break;
                         case 'f': c = '\f'; break;
                         case 'r': c = '\r'; break;
                         case '0':
                         case '1':
                         case '2':
                         case '3':
                                 *buf = c;
                                 for ( c=1; c<3; ++c )
                                 {
                                         if ( (buf[c]=getcharacter()) == -1 )
                                                 goto err;
                                 }
                                 buf[c] = 0;
                                 sscanf( buf, "%o", &c );
                                 break;
                         case '\n':
                                 if ( getcharacter() == -1 )
                                         goto err;
                         default:
                                 if ( (c = getcharacter()) == -1 )
                                         goto err;
                         }
                 }
                 *str++ = c;
         }
         *str++ = 0;

         return str;
 err:
         sprintf( buf, "missing %c delimiter", delim );
         error( buf, 4 );
 }

 storeint( ip, i )
 int *ip, i;
 {
         return *ip = i;
 }

 storeptr( pp, p )
 char **pp, *p;
 {
         return *pp = p;
 }

 fetchint( ip )
 int *ip;
 {
         return *ip;
 }

 char *
 fetchptr( pp )
 char **pp;
 {
         return *pp;
 }

 getoken()
 {
         char *cp;
         int i;

         switch ( Token = *Actptr++ )
         {
         case T_STRING:
         case T_REGEXP:
                 Value.dptr = Actptr;
                 Actptr += strlen( Actptr ) + 1;
                 break;
         case T_VARIABLE:
                 Value.dptr = fetchptr( Actptr );
                 Actptr += sizeof( cp );
                 break;
         case T_FUNCTION:
         case T_CONSTANT:
                 Value.ival = fetchint( Actptr );
                 Actptr += sizeof( i );
                 break;
         case T_EOF:
                 --Actptr;
         default:
                 Value.dptr = 0;
         }

 #ifdef DEBUG
         if ( Debug > 1 )
                 printf( "Token='%c' (0x%x), Value=%d\n",
                         Token,Token,Value.ival );
 #endif

         return Token;
 }


 BAWKDO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\BAWK\BAWKDO.C

 /*
  * Bawk C actions interpreter
  */
 #include <stdio.h>
 #include "bawk.h"

 dopattern( pat )
 char *pat;
 {
         Where = PATTERN;
         Actptr = pat;
         getoken();
         expression();
         return popint();
 }

 doaction( act )
 char *act;
 {
         Where = ACTION;
         Actptr = act;
         getoken();
         while ( Token!=T_EOF )
                 statement();
 }

 expression()
 {
         expr1();

         if ( Token==T_ASSIGN )
         {
                 getoken();
                 assignment( expression() );
         }
 }

 expr1()
 {
         int ival;

         expr2();
         for ( ;; )
         {
                 if ( Token==T_LIOR )
                 {
                         getoken();
                         ival = popint();
                         expr2();
                         pushint( popint() || ival );
                 }
                 else
                         return;
         }
 }

 expr2()
 {
         int ival;

         expr3();
         for ( ;; )
         {
                 if ( Token==T_LAND )
                 {
                         getoken();
                         ival = popint();
                         expr3();
                         pushint( popint() && ival );
                 }
                 else
                         return;
         }
 }

 expr3()
 {
         int ival;

         expr4();
         for ( ;; )
         {
                 if ( Token==T_IOR )
                 {
                         getoken();
                         ival = popint();
                         expr4();
                         pushint( popint() | ival );
                 }
                 else
                         return;
         }
 }


 expr4()
 {
         int ival;

         expr5();
         for ( ;; )
         {
                 if ( Token==T_AND )
                 {
                         getoken();
                         ival = popint();
                         expr5();
                         pushint( popint() & ival );
                 }
                 else
                         return;
         }
 }

 expr5()
 {
         int ival;

         expr6();
         for ( ;; )
         {
                 if ( Token==T_XOR )
                 {
                         getoken();
                         ival = popint();
                         expr6();
                         pushint( popint() ^ ival );
                 }
                 else
                         return;
         }
 }

 expr6()
 {
         int ival;

         expr7();
         for ( ;; )
         {
                 if ( Token==T_EQ )
                 {
                         getoken();
                         ival = popint();
                         expr7();
                         pushint( ival == popint() );
                 }
                 else if ( Token==T_NE )
                 {
                         getoken();
                         ival = popint();
                         expr7();
                         pushint( ival != popint() );
                 }
                 else
                         return;
         }
 }

 expr7()
 {
         int ival;

         expr8();
         for ( ;; )
         {
                 if ( Token==T_LE )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival <= popint() );
                 }
                 else if ( Token==T_GE )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival >= popint() );
                 }
                 else if ( Token==T_LT )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival < popint() );
                 }
                 else if ( Token==T_GT )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival > popint() );
                 }
                 else
                         return;
         }
 }

 expr8()
 {
         int ival;

         expr9();
         for ( ;; )
         {
                 if ( Token==T_SHL )
                 {
                         getoken();
                         ival = popint();
                         expr9();
                         pushint( ival << popint() );
                 }
                 else if ( Token==T_SHR )
                 {
                         getoken();
                         ival = popint();
                         expr9();
                         pushint( ival >> popint() );
                 }
                 else
                         return;
         }
 }

 expr9()
 {
         int ival;

         expr10();
         for ( ;; )
         {
                 if ( Token==T_ADD )
                 {
                         getoken();
                         ival = popint();
                         expr10();
                         pushint( ival + popint() );
                 }
                 else if ( Token==T_SUB )
                 {
                         getoken();
                         ival = popint();
                         expr10();
                         pushint( ival - popint() );
                 }
                 else
                         return;
         }
 }

 expr10()
 {
         int ival;

         primary();
         for ( ;; )
         {
                 if ( Token==T_MUL )
                 {
                         getoken();
                         ival = popint();
                         primary();
                         pushint( ival * popint() );
                 }
                 else if ( Token==T_DIV )
                 {
                         getoken();
                         ival = popint();
                         primary();
                         pushint( ival / popint() );
                 }
                 else if ( Token==T_MOD )
                 {
                         getoken();
                         ival = popint();
                         primary();
                         pushint( ival % popint() );
                 }
                 else
                         return;
         }
 }

 primary()
 {
         int index;
         DATUM data;
         VARIABLE *pvar;

         switch ( Token )
         {
         case T_LPAREN:
                 /*
                  * it's a parenthesized expression
                  */
                 getoken();
                 expression();
                 if ( Token!=T_RPAREN )
                         error( "missing ')'", ACT_ERROR );
                 getoken();
                 break;
         case T_LNOT:
                 getoken();
                 primary();
                 pushint( ! popint() );
                 break;
         case T_NOT:
                 getoken();
                 primary();
                 pushint( ~ popint() );
                 break;
         case T_ADD:
                 getoken();
                 primary();
                 break;
         case T_SUB:
                 getoken();
                 primary();
                 pushint( - popint() );
                 break;
         case T_INCR:
         case T_DECR:
                 preincdec();
                 break;
         case T_MUL:
                 getoken();
                 primary();
                 /*
                  * If item on stack is an LVALUE, do an extra level of
                  * indirection before changing it to an LVALUE.
                  */
                 if ( Stackptr->lvalue )
                         Stackptr->value.ptrptr = *Stackptr->value.ptrptr;
                 Stackptr->lvalue = 1;
                 --Stackptr->class;
                 break;
         case T_AND:
                 getoken();
                 primary();
                 if ( Stackptr->lvalue )
                         Stackptr->lvalue = 0;
                 else
                         error( "'&' operator needs an lvalue", ACT_ERROR );
                 break;
         case T_CONSTANT:
                 pushint( Value.ival );
                 getoken();
                 break;
         case T_REGEXP:
                 /*
                  * It's a regular expression - parse it and compile it.
                  */
                 if ( Where == PATTERN )
                 {
                         /*
                          * We're processing a pattern right now - perform a
                          * match of the regular expression agains input line.
                          */
                         unparse( Fields, Fieldcount, Linebuf, Fieldsep );
                         pushint( match( Linebuf, Value.dptr ) );
                 }
                 else
                         push( 1, ACTUAL, BYTE, &Value );
                 getoken();
                 break;
         case T_NF:
                 pushint( Fieldcount );
                 getoken();
                 break;
         case T_NR:
                 pushint( Recordcount );
                 getoken();
                 break;
         case T_FS:
                 Fieldsep[1] = 0;
                 data.dptr = Fieldsep;
                 push( 0, LVALUE, BYTE, &data );
                 getoken();
                 break;
         case T_RS:
                 Recordsep[1] = 0;
                 data.dptr = Recordsep;
                 push( 0, LVALUE, BYTE, &data );
                 getoken();
                 break;
         case T_FILENAME:
                 data.dptr = Filename;
                 push( 1, ACTUAL, BYTE, &data );
                 getoken();
                 break;
         case T_DOLLAR:
                 /*
                  * It's a reference to one (or all) of the words in Linebuf.
                  */
                 getoken();
                 primary();
                 if ( index = popint() )
                 {
                         if ( index > Fieldcount )
                                 index = Fieldcount;
                         else if ( index < 1 )
                                 index = 1;
                         data.dptr = Fields[ index-1 ];
                 }
                 else
                 {
                         /*
                          * Reconstitute the line buffer in case any of the
                          * fields have been changed.
                          */
                         unparse( Fields, Fieldcount, Linebuf, Fieldsep );
                         data.dptr = Linebuf;
                 }
                 /*
                  * $<expr>'s are treated the same as string constants:
                  */
                 push( 1, ACTUAL, BYTE, &data );
                 break;
         case T_STRING:
                 push( 1, ACTUAL, BYTE, &Value );
                 getoken();
                 break;
         case T_FUNCTION:
                 /*
                  * Do a built-in function call
                  */
                 index = Value.ival;
                 getoken();
                 function( index );
                 break;
         case T_VARIABLE:
                 pvar = Value.dptr;
                 getoken();
                 /*
                  * it's a plain variable. The way a variable is
                  * represented on the stack depends on its type:
                  *      lvalue class value.dptr
                  * vars:  1      0   address of var
                  * ptrs:  1      1   ptr to address of ptr
                  * array: 0      1   address of var
                  */
                 if ( pvar->vclass && !pvar->vlen )
                         /* it's a pointer */
                         data.dptr = &pvar->vptr;
                 else
                         /* an array or simple variable */
                         data.dptr = pvar->vptr;
                 /*
                  * If it's an array it can't be used as an LVALUE.
                  */
                 push( pvar->vclass, !pvar->vlen, pvar->vsize, &data );
                 break;
         case T_EOF:
                 break;
         default:
                 syntaxerror();
         }
         /*
          * a "[" means it's an array reference
          */
         if ( Token==T_LBRACKET )
         {
                 getoken();
                 if ( ! Stackptr->class )
                         error( "'[]' needs an array or pointer", ACT_ERROR );
                 /*
                  * compute the subscript
                  */
                 expression();
                 if ( Token!=T_RBRACKET )
                         error( "missing ']'", ACT_ERROR );
                 getoken();
                 index = popint();
                 /*
                  * compute the offset (subscript times two for int arrays)
                  * and then the effective address.
                  */
                 index *= Stackptr->size;
                 if ( Stackptr->lvalue )
                         /*
                          * It's a pointer - don't forget that the stack top
                          * item's value is the address of the pointer so we
                          * must do another level of indirection.
                          */
                         Stackptr->value.dptr = *Stackptr->value.ptrptr+index;
                 else
                         /*
                          * It's a plain array - the stack top item's value is
                          * the address of the first element in the array.
                          */
                         Stackptr->value.dptr += index;

                 /*
                  * The stack top item now becomes an LVALUE, but we've
                  * reduced the indirection level.
                  */
                 Stackptr->lvalue = 1;
                 --Stackptr->class;
         }

         if ( Token==T_INCR || Token==T_DECR )
                 postincdec();
 }

 preincdec()
 {
         /*
          * Pre increment/decrement
          */
         int incr;

         incr = Token==T_INCR ? 1 : -1;
         getoken();
         primary();
         if ( Stackptr->lvalue )
         {
                 if ( Stackptr->class )
                         incr *= Stackptr->size;
                 *Stackptr->value.ptrptr += incr;
         }
         else
                 error( "pre '++' or '--' needs an lvalue", ACT_ERROR );
 }

 postincdec()
 {
         /*
          * Post increment/decrement
          */
         char **pp;
         int incr;

         incr = Token==T_INCR ? 1 : -1;
         getoken();
         if ( Stackptr->lvalue )
         {
                 if ( Stackptr->class )
                 {
                         /*
                          * It's a pointer - save its old value then
                          * increment/decrement the pointer.  This makes the
                          * item on top of the stack look like an array, which
                          * means it can no longer be used as an LVALUE. This
                          * doesn't really hurt, since it doesn't make much
                          * sense to say:
                          *   char *cp;
                          *   cp++ = value;
                          */
                         pp = *Stackptr->value.ptrptr;
                         *Stackptr->value.ptrptr += incr * Stackptr->size;
                         Stackptr->value.ptrptr = pp;
                 }
                 else
                 {
                         /*
                          * It's a simple variable - save its old value then
                          * increment/decrement the variable.  This makes the
                          * item on top of the stack look like a constant,
                          * which means it can no longer be used as an LVALUE.
                          * Same reasoning as above.
                          */
                         if ( Stackptr->size == BYTE )
                                 pp = *Stackptr->value.dptr;
                         else
                                 pp = *Stackptr->value.ptrptr;
                         *Stackptr->value.ptrptr += incr;
                         Stackptr->value.ival = pp;
                 }
                 Stackptr->lvalue = 0;
         }
         else
                 error( "post '++' or '--' needs an lvalue", ACT_ERROR );
 }

 statement()
 {
         /*
          * Evaluate a statement
          */
         char *repeat, *body;

         switch ( Token )
         {
         case T_EOF:
                 break;
         case T_CHAR:
         case T_INT:
                 declist();
                 break;
         case T_LBRACE:
                 /*
                  * parse a compound statement
                  */
                 getoken();
                 while ( !Saw_break && Token!=T_RBRACE )
                         statement();

                 if ( Token==T_RBRACE )
                         getoken();
                 break;
         case T_IF:
                 /*
                  * parse an "if-else" statement
                  */
                 if ( getoken() != T_LPAREN )
                         syntaxerror();
                 getoken();
                 expression();
                 if ( Token!=T_RPAREN )
                         syntaxerror();
                 getoken();
                 if ( popint() )
                 {
                         statement();
                         if ( Token==T_ELSE )
                         {
                                 getoken();
                                 skipstatement();
                         }
                 }
                 else
                 {
                         skipstatement();
                         if ( Token==T_ELSE )
                         {
                                 getoken();
                                 statement();
                         }
                 }
                 break;
         case T_WHILE:
                 /*
                  * parse a "while" statement
                  */
                 repeat = Actptr;
                 for ( ;; )
                 {
                         if ( getoken() != T_LPAREN )
                                 syntaxerror();

                         getoken();
                         expression();
                         if ( Token!=T_RPAREN )
                                 syntaxerror();

                         if ( popint() )
                         {
                                 body = Actptr;
                                 getoken();
                                 statement();
                                 if ( Saw_break )
                                 {
                                         Actptr = body;
                                         Saw_break = 0;
                                         break;
                                 }
                                 Actptr = repeat;
                         }
                         else
                                 break;
                 }
                 getoken();
                 skipstatement();
                 break;
         case T_BREAK:
                 /*
                  * parse a "break" statement
                  */
                 getoken();
                 Saw_break = 1;
                 break;
         case T_SEMICOLON:
                 break;
         default:
                 expression();
                 popint();
         }

         if ( Token==T_SEMICOLON )
                 getoken();
 }

 skipstatement()
 {
         /*
          * Skip a statement
          */

         switch ( Token )
         {
         case T_LBRACE:
                 /*
                  * skip a compound statement
                  */
                 skip( T_LBRACE, T_RBRACE );
                 break;
         case T_IF:
                 /*
                  * skip an "if-else" statement
                  */
                 getoken();        /* skip 'if' */
                 skip( T_LPAREN, T_RPAREN );
                 skipstatement();
                 if ( Token==T_ELSE )
                 {
                         getoken();        /* skip 'else' */
                         skipstatement();
                 }
                 break;
         case T_WHILE:
                 /*
                  * skip a "while" statement
                  */
                 getoken();        /* skip 'while' */
                 skip( T_LPAREN, T_RPAREN );
                 skipstatement();
                 break;
         default:
                 /*
                  * skip a one-liner
                  */
                 while (Token!=T_SEMICOLON && Token!=T_RBRACE && Token!=T_EOF)
                         getoken();
                 if ( Token==T_EOF )
                         error( "unexpected end", ACT_ERROR );
                 if ( Token==T_SEMICOLON )
                         getoken();
         }
 }

 skip( left, right )
 char left, right;
 {
         /*
          * Skip matched left and right delimiters and everything in between
          */
         int parity;
         char *save, errmsg[ 80 ];

         parity = 1;
         save = Actptr;
         while ( getoken() != T_EOF )
         {
                 if ( Token == left )
                 {
                         save = Actptr;
                         ++parity;
                 }
                 else if ( Token == right )
                         --parity;
                 if ( !parity )
                 {
                         getoken();
                         return;
                 }
         }
         Actptr = save;

         sprintf( errmsg, "mismatched '%c' and '%c'", left, right );
         error( errmsg, ACT_ERROR );
 }

 syntaxerror()
 {
         error( "syntax error", ACT_ERROR );
 }


 BAWKDO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\BAWKDO.C

 /*
         HEADER:                CUG236;
         TITLE:                BAWK Actions Interpreter;
         DATE:                05/17/1987;
         VERSION:        1.1;
         FILENAME:        BAWKDO.C;
         SEE-ALSO:        BAWK.C;
         AUTHORS:        W. C. Colley III, B. Brodt;
 */

 /*
  * Bawk C actions interpreter
  */
 #include <stdio.h>
 #include "bawk.h"

 /* Functions local to this module.        */

 void expr1(), expr2(), expr3(), expr4(), expr5(), expr6(), expr7(), expr8();
 void expr9(), expr10(), postincdec(), preincdec(), primary(), skip();
 void skipstatement(), statement();

 int dopattern( pat )
 char *pat;
 {
         Where = PATTERN;
         Actptr = pat;
         getoken();
         expression();
         return popint();
 }

 void doaction( act )
 char *act;
 {
         Where = ACTION;
         Actptr = act;
         getoken();
         while ( Token!=T_EOF )
                 statement();
 }

 void expression()
 {
         expr1();
         if ( Token==T_ASSIGN ) {
                 getoken();  expression();  assignment();
         }
 }

 void expr1()
 {
         int ival;

         expr2();
         for ( ;; )
         {
                 if ( Token==T_LIOR )
                 {
                         getoken();
                         ival = popint();
                         expr2();
                         pushint( popint() || ival );
                 }
                 else
                         return;
         }
 }

 void expr2()
 {
         int ival;

         expr3();
         for ( ;; )
         {
                 if ( Token==T_LAND )
                 {
                         getoken();
                         ival = popint();
                         expr3();
                         pushint( popint() && ival );
                 }
                 else
                         return;
         }
 }

 void expr3()
 {
         int ival;

         expr4();
         for ( ;; )
         {
                 if ( Token==T_IOR )
                 {
                         getoken();
                         ival = popint();
                         expr4();
                         pushint( popint() | ival );
                 }
                 else
                         return;
         }
 }


 void expr4()
 {
         int ival;

         expr5();
         for ( ;; )
         {
                 if ( Token==T_AND )
                 {
                         getoken();
                         ival = popint();
                         expr5();
                         pushint( popint() & ival );
                 }
                 else
                         return;
         }
 }

 void expr5()
 {
         int ival;

         expr6();
         for ( ;; )
         {
                 if ( Token==T_XOR )
                 {
                         getoken();
                         ival = popint();
                         expr6();
                         pushint( popint() ^ ival );
                 }
                 else
                         return;
         }
 }

 void expr6()
 {
         int ival;

         expr7();
         for ( ;; )
         {
                 if ( Token==T_EQ )
                 {
                         getoken();
                         ival = popint();
                         expr7();
                         pushint( ival == popint() );
                 }
                 else if ( Token==T_NE )
                 {
                         getoken();
                         ival = popint();
                         expr7();
                         pushint( ival != popint() );
                 }
                 else
                         return;
         }
 }

 void expr7()
 {
         int ival;

         expr8();
         for ( ;; )
         {
                 if ( Token==T_LE )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival <= popint() );
                 }
                 else if ( Token==T_GE )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival >= popint() );
                 }
                 else if ( Token==T_LT )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival < popint() );
                 }
                 else if ( Token==T_GT )
                 {
                         getoken();
                         ival = popint();
                         expr8();
                         pushint( ival > popint() );
                 }
                 else
                         return;
         }
 }

 void expr8()
 {
         int ival;

         expr9();
         for ( ;; )
         {
                 if ( Token==T_SHL )
                 {
                         getoken();
                         ival = popint();
                         expr9();
                         pushint( ival << popint() );
                 }
                 else if ( Token==T_SHR )
                 {
                         getoken();
                         ival = popint();
                         expr9();
                         pushint( ival >> popint() );
                 }
                 else
                         return;
         }
 }

 void expr9()
 {
         int ival;

         expr10();
         for ( ;; )
         {
                 if ( Token==T_ADD )
                 {
                         getoken();
                         ival = popint();
                         expr10();
                         pushint( ival + popint() );
                 }
                 else if ( Token==T_SUB )
                 {
                         getoken();
                         ival = popint();
                         expr10();
                         pushint( ival - popint() );
                 }
                 else
                         return;
         }
 }

 void expr10()
 {
         int ival;

         primary();
         for ( ;; )
         {
                 if ( Token==T_MUL )
                 {
                         getoken();
                         ival = popint();
                         primary();
                         pushint( ival * popint() );
                 }
                 else if ( Token==T_DIV )
                 {
                         getoken();
                         ival = popint();
                         primary();
                         pushint( ival / popint() );
                 }
                 else if ( Token==T_MOD )
                 {
                         getoken();
                         ival = popint();
                         primary();
                         pushint( ival % popint() );
                 }
                 else
                         return;
         }
 }

 void primary()
 {
         int index;
         DATUM data;
         VARIABLE *pvar;

         switch ( Token )
         {
         case T_LPAREN:
                 /*
                  * it's a parenthesized expression
                  */
                 getoken();
                 expression();
                 if ( Token!=T_RPAREN )
                         error( "missing ')'", ACT_ERROR );
                 getoken();
                 break;
         case T_LNOT:
                 getoken();
                 primary();
                 pushint( ! popint() );
                 break;
         case T_NOT:
                 getoken();
                 primary();
                 pushint( ~ popint() );
                 break;
         case T_ADD:
                 getoken();
                 primary();
                 break;
         case T_SUB:
                 getoken();
                 primary();
                 pushint( - popint() );
                 break;
         case T_INCR:
         case T_DECR:
                 preincdec();
                 break;
         case T_MUL:
                 getoken();
                 primary();
                 /*
                  * If item on stack is an LVALUE, do an extra level of
                  * indirection before changing it to an LVALUE.
                  */
                 if ( Stackptr->lvalue )
                         Stackptr->value.dptr = *Stackptr->value.ptrptr;
                 Stackptr->lvalue = 1;
                 --Stackptr->class;
                 break;
         case T_AND:
                 getoken();
                 primary();
                 if ( Stackptr->lvalue )
                         Stackptr->lvalue = 0;
                 else
                         error( "'&' operator needs an lvalue", ACT_ERROR );
                 break;
         case T_CONSTANT:
                 pushint( Value.ival );
                 getoken();
                 break;
         case T_REGEXP:
                 /*
                  * It's a regular expression - parse it and compile it.
                  */
                 if ( Where == PATTERN )
                 {
                         /*
                          * We're processing a pattern right now - perform a
                          * match of the regular expression agains input line.
                          */
                         unparse( Fields, Fieldcount, Linebuf, Fldsep );
                         pushint( match( Linebuf, Value.dptr ) );
                 }
                 else
                         push( 1, ACTUAL, BYTE, &Value );
                 getoken();
                 break;
         case T_NF:
                 pushint( Fieldcount );
                 getoken();
                 break;
         case T_NR:
                 pushint( Recordcount );
                 getoken();
                 break;
         case T_FS:
                 Fldsep[1] = 0;
                 data.dptr = Fldsep;
                 push( 0, LVALUE, BYTE, &data );
                 getoken();
                 break;
         case T_RS:
                 Rcrdsep[1] = 0;
                 data.dptr = Rcrdsep;
                 push( 0, LVALUE, BYTE, &data );
                 getoken();
                 break;
         case T_FILENAME:
                 data.dptr = Filename;
                 push( 1, ACTUAL, BYTE, &data );
                 getoken();
                 break;
         case T_DOLLAR:
                 /*
                  * It's a reference to one (or all) of the words in Linebuf.
                  */
                 getoken();
                 primary();
                 if ( index = popint() )
                 {
                         if ( index > Fieldcount )
                                 index = Fieldcount;
                         else if ( index < 1 )
                                 index = 1;
                         data.dptr = Fields[ index-1 ];
                 }
                 else
                 {
                         /*
                          * Reconstitute the line buffer in case any of the
                          * fields have been changed.
                          */
                         unparse( Fields, Fieldcount, Linebuf, Fldsep );
                         data.dptr = Linebuf;
                 }
                 /*
                  * $<expr>'s are treated the same as string constants:
                  */
                 push( 1, ACTUAL, BYTE, &data );
                 break;
         case T_STRING:
                 push( 1, ACTUAL, BYTE, &Value );
                 getoken();
                 break;
         case T_FUNCTION:
                 /*
                  * Do a built-in function call
                  */
                 index = Value.ival;
                 getoken();
                 function( index );
                 break;
         case T_VARIABLE:
                 pvar = (VARIABLE *)Value.dptr;
                 getoken();
                 /*
                  * it's a plain variable. The way a variable is
                  * represented on the stack depends on its type:
                  *        lvalue class value.dptr
                  * vars:  1         0   address of var
                  * ptrs:  1         1   address of ptr to var
                  * array: 0         1   address of var
                  */
                 if ( pvar->vclass && !pvar->vlen )
                         /* it's a pointer */
                         data.ptrptr = &pvar->vptr;
                 else
                         /* an array or simple variable */
                         data.dptr = pvar->vptr;
                 /*
                  * If it's an array it can't be used as an LVALUE.
                  */
                 push( pvar->vclass, !pvar->vlen, pvar->vsize, &data );
                 break;
         case T_EOF:
                 break;
         default:
                 syntaxerror();
         }
         /*
          * a "[" means it's an array reference
          */
         if ( Token==T_LBRACKET )
         {
                 getoken();
                 if ( ! Stackptr->class )
                         error( "'[]' needs an array or pointer", ACT_ERROR );
                 /*
                  * compute the subscript
                  */
                 expression();
                 if ( Token!=T_RBRACKET )
                         error( "missing ']'", ACT_ERROR );
                 getoken();
                 index = popint();
                 /*
                  * compute the offset (subscript times two for int arrays)
                  * and then the effective address.
                  */
                 index *= Stackptr->size;
                 if ( Stackptr->lvalue )
                         /*
                          * It's a pointer - don't forget that the stack top
                          * item's value is the address of the pointer so we
                          * must do another level of indirection.
                          */
                         Stackptr->value.dptr =
                                 *(Stackptr->value.ptrptr) + index;
                 else
                         /*
                          * It's a plain array - the stack top item's value is
                          * the address of the first element in the array.
                          */
                         Stackptr->value.dptr += index;

                 /*
                  * The stack top item now becomes an LVALUE, but we've
                  * reduced the indirection level.
                  */
                 Stackptr->lvalue = 1;
                 --Stackptr->class;
         }

         if ( Token==T_INCR || Token==T_DECR )
                 postincdec();
 }

 void preincdec()
 {
         /*
          * Pre increment/decrement
          */
         int incr;

         incr = Token==T_INCR ? 1 : -1;
         getoken();
         primary();
         if ( Stackptr->lvalue )
         {
                 if ( Stackptr->class )
                         incr *= Stackptr->size;
                 *(Stackptr->value.ptrptr) += incr;
         }
         else
                 error( "pre '++' or '--' needs an lvalue", ACT_ERROR );
 }

 void postincdec()
 {
         /*
          * Post increment/decrement
          */
         char *p;
         int i, incr;

         incr = Token==T_INCR ? 1 : -1;
         getoken();
         if ( Stackptr->lvalue )
         {
                 if ( Stackptr->class )
                 {
                         /*
                          * It's a pointer - save its old value then
                          * increment/decrement the pointer.  This makes the
                          * item on top of the stack look like an array, which
                          * means it can no longer be used as an LVALUE. This
                          * doesn't really hurt, since it doesn't make much
                          * sense to say:
                          *   char *cp;
                          *   cp++ = value;
                          */
                         p = *(Stackptr->value.ptrptr);
                         *(Stackptr->value.ptrptr) += incr * Stackptr->size;
                         Stackptr->value.dptr = p;
                 }
                 else
                 {
                         /*
                          * It's a simple variable - save its old value then
                          * increment/decrement the variable.  This makes the
                          * item on top of the stack look like a constant,
                          * which means it can no longer be used as an LVALUE.
                          * Same reasoning as above.
                          */
                         if ( Stackptr->size == BYTE )
                                 i = *(Stackptr->value.dptr);
                         else
                                 i = *((int *)Stackptr->value.dptr);
                         *(Stackptr->value.ptrptr) += incr;
                         Stackptr->value.ival = i;
                 }
                 Stackptr->lvalue = 0;
         }
         else
                 error( "post '++' or '--' needs an lvalue", ACT_ERROR );
 }

 void statement()
 {
         /*
          * Evaluate a statement
          */
         char *repeat, *body;

         switch ( Token )
         {
         case T_EOF:
                 break;
         case T_CHAR:
         case T_INT:
                 declist();
                 break;
         case T_LBRACE:
                 /*
                  * parse a compound statement
                  */
                 getoken();
                 while ( !Saw_break && Token!=T_RBRACE )
                         statement();

                 if ( Token==T_RBRACE )
                         getoken();
                 break;
         case T_IF:
                 /*
                  * parse an "if-else" statement
                  */
                 if ( getoken() != T_LPAREN )
                         syntaxerror();
                 getoken();
                 expression();
                 if ( Token!=T_RPAREN )
                         syntaxerror();
                 getoken();
                 if ( popint() )
                 {
                         statement();
                         if ( Token==T_ELSE )
                         {
                                 getoken();
                                 skipstatement();
                         }
                 }
                 else
                 {
                         skipstatement();
                         if ( Token==T_ELSE )
                         {
                                 getoken();
                                 statement();
                         }
                 }
                 break;
         case T_WHILE:
                 /*
                  * parse a "while" statement
                  */
                 repeat = Actptr;
                 for ( ;; )
                 {
                         if ( getoken() != T_LPAREN )
                                 syntaxerror();

                         getoken();
                         expression();
                         if ( Token!=T_RPAREN )
                                 syntaxerror();

                         if ( popint() )
                         {
                                 body = Actptr;
                                 getoken();
                                 statement();
                                 if ( Saw_break )
                                 {
                                         Actptr = body;
                                         Saw_break = 0;
                                         break;
                                 }
                                 Actptr = repeat;
                         }
                         else
                                 break;
                 }
                 getoken();
                 skipstatement();
                 break;
         case T_BREAK:
                 /*
                  * parse a "break" statement
                  */
                 getoken();
                 Saw_break = 1;
                 break;
         case T_SEMICOLON:
                 break;
         default:
                 expression();
                 popint();
         }

         if ( Token==T_SEMICOLON )
                 getoken();
 }

 void skipstatement()
 {
         /*
          * Skip a statement
          */

         switch ( Token )
         {
         case T_LBRACE:
                 /*
                  * skip a compound statement
                  */
                 skip( T_LBRACE, T_RBRACE );
                 break;
         case T_IF:
                 /*
                  * skip an "if-else" statement
                  */
                 getoken();        /* skip 'if' */
                 skip( T_LPAREN, T_RPAREN );
                 skipstatement();
                 if ( Token==T_ELSE )
                 {
                         getoken();        /* skip 'else' */
                         skipstatement();
                 }
                 break;
         case T_WHILE:
                 /*
                  * skip a "while" statement
                  */
                 getoken();        /* skip 'while' */
                 skip( T_LPAREN, T_RPAREN );
                 skipstatement();
                 break;
         default:
                 /*
                  * skip a one-liner
                  */
                 while (Token!=T_SEMICOLON && Token!=T_RBRACE && Token!=T_EOF)
                         getoken();
                 if ( Token==T_EOF )
                         error( "unexpected end", ACT_ERROR );
                 if ( Token==T_SEMICOLON )
                         getoken();
         }
 }

 void skip( left, right )
 char left, right;
 {
         /*
          * Skip matched left and right delimiters and everything in between
          */
         int parity;
         char *save, errmsg[ 80 ];

         parity = 1;
         save = Actptr;
         while ( getoken() != T_EOF )
         {
                 if ( Token == left )
                 {
                         save = Actptr;
                         ++parity;
                 }
                 else if ( Token == right )
                         --parity;
                 if ( !parity )
                 {
                         getoken();
                         return;
                 }
         }
         Actptr = save;

         (void)sprintf(errmsg,"mismatched '%c' and '%c'",left,right);
         error( errmsg, ACT_ERROR );
 }

 void syntaxerror()
 {
         error( "syntax error", ACT_ERROR );
 }


 BAWKPAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\BAWK\BAWKPAT.C

 /*
  * Bawk regular expression compiler/interpreter
  */
 #include <stdio.h>
 #include "bawk.h"

 re_compile( patbuf )
 char        *patbuf;                /* where to put compiled pattern */
 {
         /*
          * Compile a regular expression from current input file
          * into the given pattern buffer.
          */
         int        c,                /* Current character         */
                 o;                /* Temp                      */
         char        *patptr,        /* destination string pntr   */
                 *lp,                /* Last pattern pointer      */
                 *spp,                /* Save beginning of pattern */
                 delim,                /* pattern delimiter         */
                 *cclass();        /* Compile class routine     */

         patptr = patbuf;
         delim = getcharacter();

         while ( (c = getcharacter()) != -1 && c != delim )
         {
                 /*
                  * STAR, PLUS and MINUS are special.
                  */
                 if (c == '*' || c == '+' || c == '-') {
                         if (patptr == patbuf ||
                                   (o=patptr[-1]) == BOL ||
                                   o == EOL ||
                                   o == STAR ||
                                   o == PLUS ||
                                   o == MINUS)
                                 error( "illegal occurrance op", RE_ERROR );
                         *patptr++ = ENDPAT;
                         *patptr++ = ENDPAT;
                         spp = patptr;                /* Save pattern end
                         while (--patptr > lp)        /* Move pattern down...
                                 *patptr = patptr[-1];        /* one byte
                         *patptr =   (c == '*') ? STAR :
                                 (c == '-') ? MINUS : PLUS;
                         patptr = spp;                /* Restore pattern end
                         continue;
                 }
                 /*
                  * All the rest.
                  */
                 lp = patptr;                        /* Remember start       *
                 switch(c) {

                 case '^':
                         *patptr++ = BOL;
                         break;

                 case '$':
                         *patptr++ = EOL;
                         break;

                 case '.':
                         *patptr++ = ANY;
                         break;

                 case '[':
                         patptr = cclass( patptr );
                         break;

                 case ':':
                         if ( (c=getcharacter()) != -1 )
                         {
                                 switch( tolower( c ) )
                                 {

                                 case 'a':
                                         *patptr++ = ALPHA;
                                         break;

                                 case 'd':
                                         *patptr++ = DIGIT;
                                         break;

                                 case 'n':
                                         *patptr++ = NALPHA;
                                         break;

                                 case ' ':
                                         *patptr++ = PUNCT;
                                         break;

                                 default:
                                         error( "unknown ':' type", RE_ERROR )

                                 }
                         }
                         else
                                 error( "no ':' type", RE_ERROR );
                          break;

                 case '\\':
                         c = getcharacter();

                 default:
                         *patptr++ = CHAR;
                         *patptr++ = c;
                 }
         }
         *patptr++ = ENDPAT;
         *patptr++ = 0;                        /* Terminate string     */

 #ifdef DEBUG
         if ( Debug>1 )
         {
                 for ( lp=patbuf; lp<patptr; ++lp )
                 {
                         switch ( c = *lp )
                         {
                         case CHAR:        printf("char "); break;
                         case BOL:        printf("bol "); break;
                         case EOL:        printf("eol "); break;
                         case ANY:        printf("any "); break;
                         case CLASS:        printf("class(%d) ", *++lp); break
                         case NCLASS:        printf("notclass(%d) ",*++lp); br
                         case STAR:        printf("star "); break;
                         case PLUS:        printf("plus "); break;
                         case MINUS:        printf("minus "); break;
                         case ALPHA:        printf("alpha "); break;
                         case DIGIT:        printf("digit "); break;
                         case NALPHA:        printf("notalpha "); break;
                         case PUNCT:        printf("punct "); break;
                         case RANGE:        printf("range "); break;
                         case ENDPAT:        printf("endpat "); break;
                         default:        printf("<%c> ", c); break;
                         }
                 }
                 printf( "\n" );
         }
 #endif

         return patptr - patbuf;
 }

 char *
 cclass( patbuf )
 char        *patbuf;        /* destination pattern buffer */
 {
         /*
          * Compile a class (within [])
          */
         char        *patptr,        /* destination pattern pointer */
                 *cp;                /* Pattern start     */
         int        c,                /* Current character */
                 o;                /* Temp              */

         patptr = patbuf;

         if ( (c = getcharacter()) == -1 )
                 error( "class terminates badly", RE_ERROR );
         else if ( c == '^')
         {
                 /*
                  * Class exclusion, for example: [^abc]
                  * Swallow the "^" and set token type to class exclusion.
                  */
                 o = NCLASS;
         }
         else
         {
                 /*
                  * Normal class, for example: [abc]
                  * push back the character and set token type to class
                  */
                 ungetcharacter( c );
                 o = CLASS;
         }
         *patptr++ = o;

         cp = patptr;        /* remember where byte count is */
         *patptr++ = 0;        /* and initialize byte count */
         while ( (c = getcharacter()) != -1 && c!=']' )
         {
                 o = getcharacter();                /* peek at next char */
                 if (c == '\\')                        /* Store quoted chars *
                 {
                         if ( o == -1) /* Gotta get something */
                                 error( "class terminates badly", RE_ERROR );
                         *patptr++ = o;
                 }
                 else if ( c=='-' && (patptr-cp)>1 && o!=']' && o != -1 )
                 {
                         c = patptr[-1];                /* Range start     */
                         patptr[-1] = RANGE;        /* Range signal    */
                         *patptr++ = c;                /* Re-store start  */
                         *patptr++ = o;                /* Store end char  */
                 }
                 else
                 {
                         *patptr++ = c;                /* Store normal char */
                         ungetcharacter( o );
                 }
         }
         if (c != ']')
                 error( "unterminated class", RE_ERROR );
         if ( (c = (patptr - cp)) >= 256 )
                 error( "class too large", RE_ERROR );
         if ( c == 0 )
                 error( "empty class", RE_ERROR );
         *cp = c;                /* fill in byte count */

         return patptr;
 }

 match( line, pattern )
 char        *line;                /* line to match */
 char        *pattern;        /* pattern to match */
 {
         /*
          * Match the current line (in Linebuf[]), return 1 if it does.
          */
         char        *l;                /* Line pointer       */
         char        *pmatch();
         char        *next;
         int        matches;

         matches = 0;
         for (l = line; *l; l++)
         {
                 if ( next = pmatch(line, l, pattern) )
                 {
                         l = next - 1;
                         ++matches;
 #ifdef DEBUG
                         if ( Debug )
                                 printf( "match!\n" );
 #endif
                 }
         }

         return matches;
 }

 char *
 pmatch(linestart, line, pattern)
 char        *linestart;        /* start of line to match */
 char        *line;                /* (partial) line to match      */
 char        *pattern;        /* (partial) pattern to match   */
 {
         char        *l;        /* Current line pointer         */
         char        *p;        /* Current pattern pointer      */
         char        c;        /* Current character            */
         char        *e;        /* End for STAR and PLUS match  */
         int        op;        /* Pattern operation            */
         int        n;        /* Class counter                */
         char        *are;        /* Start of STAR match          */

         l = line;

 #ifdef DEBUG
         if (Debug > 1)
                 printf("pmatch(\"%s\")\n", line);
 #endif

         p = pattern;
         while ((op = *p++) != ENDPAT) {

 #ifdef DEBUG
                 if (Debug > 1)
                         printf("byte[%d] = 0%o, '%c', op = 0%o\n",
                                         l-line, *l, *l, op);
 #endif

                 switch(op) {

                 case CHAR:
                         if ( *l++ != *p++)
                                 return 0;
                         break;

                 case BOL:
                         if (l != linestart)
                                 return 0;
                         break;

                 case EOL:
                         if (*l != '\0')
                                 return 0;
                         break;

                 case ANY:
                         if (*l++ == '\0')
                                 return 0;
                         break;

                 case DIGIT:
                         if ((c = *l++) < '0' || (c > '9'))
                                 return 0;
                         break;

                 case ALPHA:
                         c = tolower( *l++ );
                         if (c < 'a' || c > 'z')
                                 return 0;
                         break;

                 case NALPHA:
                         c = tolower(*l++);
                         if (c >= 'a' && c <= 'z')
                                 break;
                         else if (c < '0' || c > '9')
                                 return 0;
                         break;

                 case PUNCT:
                         c = *l++;
                         if (c == 0 || c > ' ')
                                 return 0;
                         break;

                 case CLASS:
                 case NCLASS:
                         c = *l++;
                         n = *p++ & 0377;
                         do {
                                 if (*p == RANGE) {
                                         p += 3;
                                         n -= 2;
                                         if (c >= p[-2] && c <= p[-1])
                                                 break;
                                 }
                                 else if (c == *p++)
                                         break;
                         } while (--n > 1);
                         if ((op == CLASS) == (n <= 1))
                                 return 0;
                         if (op == CLASS)
                                 p += n - 2;
                         break;

                 case MINUS:
                         e = pmatch(linestart,l,p);/* Look for a match    */
                         while (*p++ != ENDPAT);        /* Skip over pattern
                         if (e)                        /* Got a match?
                                 l = e;                /* Yes, update string
                         break;                        /* Always succeeds

                 case PLUS:                        /* One or more ...     */
                         if ((l = pmatch(linestart,l,p)) == 0)
                                 return 0;        /* Gotta have a match  */
                 case STAR:                        /* Zero or more ...    */
                         are = l;                /* Remember line start */
                         while (*l && (e = pmatch(linestart,l,p)))
                                 l = e;                /* Get longest match
                         while (*p++ != ENDPAT);        /* Skip over pattern
                         while (l >= are) {        /* Try to match rest   */
                                 if (e = pmatch(linestart,l,p))
                                         return e;
                                 --l;                /* Nope, try earlier   */
                         }
                         return 0;                /* Nothing else worked */

                 default:
                         fprintf( stderr, "bad op code %d\n", op );
                         error( "can't happen -- match", RE_ERROR );
                 }
         }
         return l;
 }


 BAWKPAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\BAWKPAT.C

 /*
         HEADER:                CUG236;
         TITLE:                BAWK Regular Expression Interpreter;
         DATE:                05/17/1987;
         VERSION:        1.1;
         FILENAME:        BAWKPAT.C;
         SEE-ALSO:        BAWK.C;
         AUTHORS:        W. C. Colley III, B. Brodt;
 */

 /*
  * Bawk regular expression compiler/interpreter
  */
 #include <stdio.h>
 #include "bawk.h"

 /* Functions local to this module.        */

 char *cclass(), *pmatch();

 int re_compile( patbuf )
 char        *patbuf;                /* where to put compiled pattern */
 {
         /*
          * Compile a regular expression from current input file
          * into the given pattern buffer.
          */
         int        c,                /* Current character             */
                 o;                /* Temp                             */
         char        *patptr,        /* destination string pntr   */
                 *lp,                /* Last pattern pointer             */
                 *spp,                /* Save beginning of pattern */
                 delim;                /* pattern delimiter             */

         patptr = patbuf;
         delim = getcharacter();

         while ( (c = getcharacter()) != -1 && c != delim )
         {
                 /*
                  * STAR, PLUS and MINUS are special.
                  */
                 if (c == '*' || c == '+' || c == '-') {
                         if (patptr == patbuf ||
                                   (o=patptr[-1]) == BOL ||
                                   o == EOL ||
                                   o == STAR ||
                                   o == PLUS ||
                                   o == MINUS)
                                 error( "illegal occurrance op", RE_ERROR );
                         *patptr++ = ENDPAT;
                         *patptr++ = ENDPAT;
                         spp = patptr;                /* Save pattern end
                         while (--patptr > lp)        /* Move pattern down...
                                 *patptr = patptr[-1];        /* one byte
                         *patptr =   (c == '*') ? STAR :
                                 (c == '-') ? MINUS : PLUS;
                         patptr = spp;                /* Restore pattern end
                         continue;
                 }
                 /*
                  * All the rest.
                  */
                 lp = patptr;                        /* Remember start
                 switch(c) {

                 case '^':
                         *patptr++ = BOL;
                         break;

                 case '$':
                         *patptr++ = EOL;
                         break;

                 case '.':
                         *patptr++ = ANY;
                         break;

                 case '[':
                         patptr = cclass( patptr );
                         break;

                 case ':':
                         if ( (c=getcharacter()) != -1 )
                         {
                                 switch( tolower( c ) )
                                 {

                                 case 'a':
                                         *patptr++ = ALPHA;
                                         break;

                                 case 'd':
                                         *patptr++ = DIGIT;
                                         break;

                                 case 'n':
                                         *patptr++ = NALPHA;
                                         break;

                                 case ' ':
                                         *patptr++ = PUNCT;
                                         break;

                                 default:
                                         error( "unknown ':' type", RE_ERROR )

                                 }
                         }
                         else
                                 error( "no ':' type", RE_ERROR );
                         break;

                 case '\\':
                         c = getcharacter();

                 default:
                         *patptr++ = CHAR;
                         *patptr++ = c;
                 }
         }
         *patptr++ = ENDPAT;
         *patptr++ = 0;                        /* Terminate string        */

 #ifdef DEBUG
         if ( Debug>1 )
         {
                 for ( lp=patbuf; lp<patptr; ++lp )
                 {
                         switch ( c = *lp )
                         {
                         case CHAR:        printf("char "); break;
                         case BOL:        printf("bol "); break;
                         case EOL:        printf("eol "); break;
                         case ANY:        printf("any "); break;
                         case CLASS:        printf("class(%d) ", *++lp); break
                         case NCLASS:        printf("notclass(%d) ",*++lp); br
                         case STAR:        printf("star "); break;
                         case PLUS:        printf("plus "); break;
                         case MINUS:        printf("minus "); break;
                         case ALPHA:        printf("alpha "); break;
                         case DIGIT:        printf("digit "); break;
                         case NALPHA:        printf("notalpha "); break;
                         case PUNCT:        printf("punct "); break;
                         case RANGE:        printf("range "); break;
                         case ENDPAT:        printf("endpat "); break;
                         default:        printf("<%c> ", c); break;
                         }
                 }
                 printf( "\n" );
         }
 #endif

         return patptr - patbuf;
 }

 char *cclass( patbuf )
 char        *patbuf;        /* destination pattern buffer */
 {
         /*
          * Compile a class (within [])
          */
         char        *patptr,        /* destination pattern pointer */
                 *cp;                /* Pattern start     */
         int        c,                /* Current character */
                 o;                /* Temp                     */

         patptr = patbuf;

         if ( (c = getcharacter()) == -1 )
                 error( "class terminates badly", RE_ERROR );
         else if ( c == '^')
         {
                 /*
                  * Class exclusion, for example: [^abc]
                  * Swallow the "^" and set token type to class exclusion.
                  */
                 o = NCLASS;
         }
         else
         {
                 /*
                  * Normal class, for example: [abc]
                  * push back the character and set token type to class
                  */
                 ungetcharacter( c );
                 o = CLASS;
         }
         *patptr++ = o;

         cp = patptr;        /* remember where byte count is */
         *patptr++ = 0;        /* and initialize byte count */
         while ( (c = getcharacter()) != -1 && c!=']' )
         {
                 o = getcharacter();                /* peek at next char */
                 if (c == '\\')                        /* Store quoted chars *
                 {
                         if ( o == -1) /* Gotta get something */
                                 error( "class terminates badly", RE_ERROR );
                         *patptr++ = o;
                 }
                 else if ( c=='-' && (patptr-cp)>1 && o!=']' && o != -1 )
                 {
                         c = patptr[-1];                /* Range start
                         patptr[-1] = RANGE;        /* Range signal
                         *patptr++ = c;                /* Re-store start  */
                         *patptr++ = o;                /* Store end char  */
                 }
                 else
                 {
                         *patptr++ = c;                /* Store normal char */
                         ungetcharacter( o );
                 }
         }
         if (c != ']')
                 error( "unterminated class", RE_ERROR );
         if ( (c = (patptr - cp)) >= 256 )
                 error( "class too large", RE_ERROR );
         if ( c == 0 )
                 error( "empty class", RE_ERROR );
         *cp = c;                /* fill in byte count */

         return patptr;
 }

 int match( line, pattern )
 char        *line;                /* line to match */
 char        *pattern;        /* pattern to match */
 {
         /*
          * Match the current line (in Linebuf[]), return 1 if it does.
          */
         char        *l;                /* Line pointer              */
         char        *next;
         int        matches;

         matches = 0;
         for (l = line; *l; l++)
         {
                 if ( next = pmatch(line, l, pattern) )
                 {
                         l = next - 1;
                         ++matches;
 #ifdef DEBUG
                         if ( Debug )
                                 printf( "match!\n" );
 #endif
                 }
         }

         return matches;
 }

 char *pmatch(linestart, line, pattern)
 char        *linestart;        /* start of line to match */
 char        *line;                /* (partial) line to match        */
 char        *pattern;        /* (partial) pattern to match        */
 {
         char        *l;        /* Current line pointer                */
         char        *p;        /* Current pattern pointer        */
         char        c;        /* Current character                */
         char        *e;        /* End for STAR and PLUS match        */
         int        op;        /* Pattern operation                */
         int        n;        /* Class counter                */
         char        *are;        /* Start of STAR match                */

         l = line;

 #ifdef DEBUG
         if (Debug > 1)
                 printf("pmatch(\"%s\")\n", line);
 #endif

         p = pattern;
         while ((op = *p++) != ENDPAT) {

 #ifdef DEBUG
                 if (Debug > 1)
                         printf("byte[%d] = 0%o, '%c', op = 0%o\n",
                                         l-line, *l, *l, op);
 #endif

                 switch(op) {

                 case CHAR:
                         if ( *l++ != *p++) return NULL;
                         break;

                 case BOL:
                         if (l != linestart) return NULL;
                         break;

                 case EOL:
                         if (*l) return NULL;
                         break;

                 case ANY:
                         if (!*l++) return NULL;
                         break;

                 case DIGIT:
                         c = *l++;
                         if (!isdigit(c)) return NULL;
                         break;

                 case ALPHA:
                         c = *l++;
                         if (!isalpha(c)) return NULL;
                         break;

                 case NALPHA:
                         c = *l++;
                         if (!isalnum(c)) return NULL;
                         break;

                 case PUNCT:
                         if (!(c = *l++) || c > ' ') return NULL;
                         break;

                 case CLASS:
                 case NCLASS:
                         c = *l++;
                         n = *p++ & 0377;
                         do {
                                 if (*p == RANGE) {
                                         p += 3;
                                         n -= 2;
                                         if (c >= p[-2] && c <= p[-1])
                                                 break;
                                 }
                                 else if (c == *p++)
                                         break;
                         } while (--n > 1);
                         if ((op == CLASS) == (n <= 1)) return NULL;
                         if (op == CLASS) p += n - 2;
                         break;

                 case MINUS:
                         e = pmatch(linestart,l,p);/* Look for a match
                         while (*p++ != ENDPAT); /* Skip over pattern   */
                         if (e)                        /* Got a match?
                                 l = e;                /* Yes, update string
                         break;                        /* Always succeeds

                 case PLUS:                        /* One or more ...     */
                         if (!(l = pmatch(linestart,l,p))) return NULL;
                                                 /* Gotta have a match  */
                 case STAR:                        /* Zero or more ...    */
                         for (are=l; *l && (e = pmatch(linestart,l,p)); l=e);
                                                 /* Get longest match   */
                         while (*p++ != ENDPAT); /* Skip over pattern   */
                         do {                        /* Try to match rest   */
                                 if (e = pmatch(linestart,l,p))
                                         return e;
                         } while (l-- > are);
                         return NULL;                /* Nothing else worked */

                 default:
                         fprintf( stderr, "bad op code %d\n", op );
                         error( "can't happen -- match", RE_ERROR );
                 }
         }
         return l;
 }


 BAWKSYM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\BAWKSYM.C

 /*
         HEADER:                CUG236;
         TITLE:                BAWK Support Module;
         DATE:                05/17/1987;
         VERSION:        1.1;
         FILENAME:        BAWKSYM.C;
         SEE-ALSO:        BAWK.C;
         AUTHORS:        W. C. Colley III, B. Brodt;
 */

 /*
  * Bawk C actions builtin functions, variable declaration, and
  * stack management routines.
  */
 #include <stdio.h>
 #include "bawk.h"

 MAXARGS                10        /* max # of arguments to a builtin func */
 #define F_PRINTF        1
 #define F_GETLINE        2
 #define F_STRLEN        3
 #define F_STRCPY        4
 #define F_STRCMP        5
 #define F_TOUPPER        6
 #define F_TOLOWER        7
 #define F_MATCH                8
 #define F_NEXTFILE        9

 /* Functions that are local to this module.        */

 VARIABLE *decl();

 int isfunction( s )
 char *s;
 {
         /*
          * Compare the string "s" to a list of builtin functions
          * and return its (non-zero) token number.
          * Return zero if "s" is not a function.
          */
         if ( !strcmp( s, "printf" ) )
                 return F_PRINTF;
         if ( !strcmp( s, "getline" ) )
                 return F_GETLINE;
         if ( !strcmp( s, "strlen" ) )
                 return F_STRLEN;
         if ( !strcmp( s, "strcpy" ) )
                 return F_STRCPY;
         if ( !strcmp( s, "strcmp" ) )
                 return F_STRCMP;
         if ( !strcmp( s, "toupper" ) )
                 return F_TOUPPER;
         if ( !strcmp( s, "tolower" ) )
                 return F_TOLOWER;
         if ( !strcmp( s, "match" ) )
                 return F_MATCH;
         if ( !strcmp( s, "nextfile" ) )
                 return F_NEXTFILE;
         return 0;
 }

 int iskeyword( s )
 char *s;
 {
         /*
          * Compare the string "s" to a list of keywords and return its
          * (non-zero) token number.  Return zero if "s" is not a keyword.
          */
         if ( !strcmp( s, "char" ) )
                 return T_CHAR;
         if ( !strcmp( s, "int" ) )
                 return T_INT;
         if ( !strcmp( s, "if" ) )
                 return T_IF;
         if ( !strcmp( s, "else" ) )
                 return T_ELSE;
         if ( !strcmp( s, "while" ) )
                 return T_WHILE;
         if ( !strcmp( s, "break" ) )
                 return T_BREAK;

         if ( !strcmp( s, "NF" ) )
                 return T_NF;
         if ( !strcmp( s, "NR" ) )
                 return T_NR;
         if ( !strcmp( s, "FS" ) )
                 return T_FS;
         if ( !strcmp( s, "RS" ) )
                 return T_RS;
         if ( !strcmp( s, "FILENAME" ) )
                 return T_FILENAME;
         if ( !strcmp( s, "BEGIN" ) )
                 return T_BEGIN;
         if ( !strcmp( s, "END" ) )
                 return T_END;
         return 0;
 }

 void function(funcnum)
 int funcnum;
 {
         int argc;
         char lpar;
         DATUM args[MAXARGS];

         argc = 0;
         if (Token == T_LPAREN) {
                 lpar = 1;  getoken();
         }
         else lpar = 0;
         /*
          * If there are any arguments, evaluate them and copy their values
          * to a local array.
          */
         if (Token != T_RPAREN && Token != T_EOF) {
                 for (;;) {
                         expression();
                         if (argc < MAXARGS) args[argc++].ival = popint();
                         else popint();
                         if (Token == T_COMMA) getoken();
                         else break;
                 }
         }
         if (lpar && Token != T_RPAREN) error( "missing ')'", ACT_ERROR );
         else if (Token == T_RPAREN) getoken();

         switch (funcnum) {
                case F_PRINTF:  /* just like the real printf() function */
                     pushint(printf(args[0].dptr,args[1].ival,args[2].ival,
                         args[3].ival,args[4].ival,args[5].ival, args[6].ival,
                         args[7].ival,args[8].ival,args[9].ival));
                     break;
                case F_GETLINE:
                 /*
                  * Get the next line of input from the current input file
                  * and parse according to the current field seperator.
                  * Don't forget to free up the previous line's words first...
                  */
                     while (Fieldcount) free(Fields[--Fieldcount]);
                     pushint(getline());
                     Fieldcount = parse(Linebuf,Fields,Fldsep);
                     break;
                case F_STRLEN:  /* calculate length of string argument */
                     pushint(strlen(args[0].dptr));
                     break;
                case F_STRCPY:  /* copy second string to first string */
                     pushint((int)strcpy(args[0].dptr,args[1].dptr));
                     break;
                case F_STRCMP:  /* compare two strings */
                     pushint(strcmp(args[0].dptr,args[1].dptr));
                     break;
                case F_TOUPPER: /* convert character argument to upper case */
                     pushint(toupper(args[0].ival));
                     break;
                case F_TOLOWER: /* convert character argument to lower case */
                     pushint(tolower(args[0].ival));
                     break;
                case F_MATCH:   /* match string argument to regular expr. */
                     pushint(match(args[0].dptr,args[1].dptr));
                     break;
                case F_NEXTFILE:/* close current input file, process next */
                     endfile();        pushint(0);
                     break;
                default:               /* oops! */
                     error("bad function call",ACT_ERROR);
         }
 }

 VARIABLE *findvar( s )
 char *s;
 {
         /*
          * Search the symbol table for a variable whose name is "s".
          */
         VARIABLE *pvar;
         int i;
         char name[ MAXVARLEN ];

         i = 0;
         while ( i < MAXVARLEN && alphanum( *s ) )
                 name[i++] = *s++;
         if ( i<MAXVARLEN )
                 name[i] = 0;

         for ( pvar = Vartab; pvar<Nextvar; ++pvar )
         {
                 if ( !strncmp( pvar->vname, name, MAXVARLEN ) )
                         return pvar;
         }
         return NULL;
 }

 VARIABLE *addvar( name )
 char *name;
 {
         /*
          * Add a new variable to symbol table and assign it default
          * attributes (int name;)
          */
         int i;

         if ( Nextvar <= Vartab + MAXVARTABSZ )
         {
                 i = 0;
                 while ( i<MAXVARLEN && alphanum( *name ) )
                         Nextvar->vname[i++] = *name++;
                 if ( i<MAXVARLEN )
                         Nextvar->vname[i] = 0;

                 Nextvar->vclass = 0;
                 Nextvar->vsize = WORD;
                 Nextvar->vlen = 0;
                 /*
                  * Allocate some new room
                  */
                 Nextvar->vptr = getmem( WORD );
                 fillmem( Nextvar->vptr, WORD, 0 );
         }
         else
                 error( "symbol table overflow", MEM_ERROR );

         return Nextvar++;
 }

 void declist()
 {
         /*
          * Parse a "char" or "int" statement.
          */
         char type;

         type = Token;
         getoken();
         decl( type );
         while ( Token==T_COMMA )
         {
                 getoken();
                 decl( type );
         }
         if ( Token==T_SEMICOLON )
                 getoken();
 }

 VARIABLE *decl( type )
 int type;
 {
         /*
          * Parse an element of a "char" or "int" declaration list.
          * The function stmt_compile() has already entered the variable
          * into the symbol table as an integer, this routine simply changes
          * the symbol's class, size or length according to the declaraction.
          * WARNING: The interpreter depends on the fact that pointers are
          * the same length as int's.  If your machine uses long's for
          * pointers either change the code or #define int long (or whatever).
          */
         char class, size;
         int len;
         unsigned oldsize, newsize;
         VARIABLE *pvar;

         if ( Token==T_MUL )
         {
                 /*
                  * it's a pointer
                  */
                 getoken();
                 pvar = decl( type );
                 ++pvar->vclass;
         }
         else if ( Token==T_VARIABLE )
         {
                 /*
                  * Simple variable so far.  The token value (in the global
                  * "Value" variable) is a pointer to the variable's symbol
                  * table entry.
                  */
                 pvar = (VARIABLE *)Value.dptr;
                 getoken();
                 class = 0;
                 /*
                  * Compute its length
                  */
                 if ( Token==T_LBRACKET )
                 {
                         /*
                          * It's an array.
                          */
                         getoken();
                         ++class;
                         /*
                          * Compute the dimension
                          */
                         expression();
                         if ( Token!=T_RBRACKET )
                                 error( "missing ']'", ACT_ERROR );
                         getoken();
                         len = popint();
                 }
                 else
                         /*
                          * It's a simple variable - array length is zero.
                          */
                         len = 0;

                 size = (type==T_CHAR) ? BYTE : WORD;

                 newsize = (len ? len : 1) * size;
                 oldsize = (pvar->vlen ? pvar->vlen : 1) * pvar->vsize;
                 if ( newsize != oldsize )
                 {
                         /*
                          * The amount of storage needed for the variable
                          * has changed - free up memory allocated initially
                          * and reallocate for new size.
                          */
                         free( pvar->vptr );
                         pvar->vptr = getmem( newsize );
                 }
                 /*
                  * Now change the variable's attributes.
                  */
                 pvar->vclass = class;
                 pvar->vsize = size;
                 pvar->vlen = len;
         }
         else
                 syntaxerror();

         return pvar;
 }

 void assignment()
 {
         /*
          * Perform an assignment
          */
         int ival;

         ival = popint();
         /*
          * make sure we've got an lvalue
          */
         if ( Stackptr->lvalue )
         {
                 if ( Stackptr->class )
                         movemem( &ival, Stackptr->value.dptr, WORD );
                 else
                         movemem(&ival, Stackptr->value.dptr, Stackptr->size);
                 pop();
                 pushint( ival );
         }
         else
                 error( "'=' needs an lvalue", ACT_ERROR );
 }

 int pop()
 {
         /*
          * Pop the stack and return the integer value
          */
         if ( Stackptr >= Stackbtm )
                 return (Stackptr--)->value.ival;
         error( "stack underflow", ACT_ERROR );
         return 0;
 }

 void push( pclass, plvalue, psize, pdatum )
 char pclass, plvalue, psize;
 DATUM *pdatum;
 {
         /*
          * Push item parts onto the stack
          */
         if ( ++Stackptr <= Stacktop )
         {
                 Stackptr->lvalue = plvalue;
                 Stackptr->size = psize;
                 if ( !(Stackptr->class = pclass)  &&  !plvalue )
                         Stackptr->value.ival = pdatum->ival;
                 else
                         Stackptr->value.dptr = pdatum->dptr;
         }
         else
                 error( "stack overflow", MEM_ERROR );
 }

 void pushint( intvalue )
 int intvalue;
 {
         /*
          * push an integer onto the stack
          */
         if ( ++Stackptr <= Stacktop )
         {
                 Stackptr->lvalue =
                 Stackptr->class = 0;
                 Stackptr->size = WORD;
                 Stackptr->value.ival = intvalue;
         }
         else
                 error( "stack overflow", MEM_ERROR );
 }

 int popint()
 {
         /*
          * Resolve the item on the top of the stack and return it
          */
         int intvalue;

         if ( Stackptr->lvalue )
         {
                 /*
                  * if it's a byte indirect, sign extend it
                  */
                 if ( Stackptr->size == BYTE && !Stackptr->class )
                         intvalue = *Stackptr->value.dptr;
                 else
                 {
                         /*
                          * otherwise, it's an unsigned int
                          */
                         intvalue = *(int *)Stackptr->value.dptr;
                 }
                 pop();
                 return intvalue;
         }
         else
         {
                 /*
                  * else it's an ACTUAL, just pop it
                  */
                 return pop();
         }
 }


 BAWKSYM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\BAWK\BAWKSYM.C

 /*
  * Bawk C actions builtin functions, variable declaration, and
  * stack management routines.
  */
 #include <stdio.h>
 #include "bawk.h"

 MAXARGS                10        /* max # of arguments to a builtin func */
 #define F_PRINTF        1
 #define F_GETLINE        2
 #define F_STRLEN        3
 #define F_STRCPY        4
 #define F_STRCMP        5
 #define F_TOUPPER        6
 #define F_TOLOWER        7
 #define F_MATCH                8
 #define F_NEXTFILE        9

 isfunction( s )
 char *s;
 {
         /*
          * Compare the string "s" to a list of builtin functions
          * and return its (non-zero) token number.
          * Return zero if "s" is not a function.
          */
         if ( !strcmp( s, "printf" ) )
                 return F_PRINTF;
         if ( !strcmp( s, "getline" ) )
                 return F_GETLINE;
         if ( !strcmp( s, "strlen" ) )
                 return F_STRLEN;
         if ( !strcmp( s, "strcpy" ) )
                 return F_STRCPY;
         if ( !strcmp( s, "strcmp" ) )
                 return F_STRCMP;
         if ( !strcmp( s, "toupper" ) )
                 return F_TOUPPER;
         if ( !strcmp( s, "tolower" ) )
                 return F_TOLOWER;
         if ( !strcmp( s, "match" ) )
                 return F_MATCH;
         if ( !strcmp( s, "nextfile" ) )
                 return F_NEXTFILE;
         return 0;
 }

 iskeyword( s )
 char *s;
 {
         /*
          * Compare the string "s" to a list of keywords and return its
          * (non-zero) token number.  Return zero if "s" is not a keyword.
          */
         if ( !strcmp( s, "char" ) )
                 return T_CHAR;
         if ( !strcmp( s, "int" ) )
                 return T_INT;
         if ( !strcmp( s, "if" ) )
                 return T_IF;
         if ( !strcmp( s, "else" ) )
                 return T_ELSE;
         if ( !strcmp( s, "while" ) )
                 return T_WHILE;
         if ( !strcmp( s, "break" ) )
                 return T_BREAK;

         if ( !strcmp( s, "NF" ) )
                 return T_NF;
         if ( !strcmp( s, "NR" ) )
                 return T_NR;
         if ( !strcmp( s, "FS" ) )
                 return T_FS;
         if ( !strcmp( s, "RS" ) )
                 return T_RS;
         if ( !strcmp( s, "FILENAME" ) )
                 return T_FILENAME;
         if ( !strcmp( s, "BEGIN" ) )
                 return T_BEGIN;
         if ( !strcmp( s, "END" ) )
                 return T_END;
         return 0;
 }

 function( funcnum )
 {
         int argc, args[ MAXARGS ];
         char lpar;

         argc = 0;
         if ( Token==T_LPAREN )
         {
                 lpar = 1;
                 getoken();
         }
         else
                 lpar = 0;
         /*
          * If there are any arguments, evaluate them and copy their values
          * to a local array.
          */
         if ( Token!=T_RPAREN && Token!=T_EOF )
         {
                 for ( ;; )
                 {
                         expression();
                         if ( argc<MAXARGS )
                                 args[ argc++ ] = popint();
                         else
                                 popint();
                         if ( Token==T_COMMA )
                                 getoken();
                         else
                                 break;
                 }
         }
         if ( lpar && Token!=T_RPAREN )
                 error( "missing ')'", ACT_ERROR );
         else if ( Token==T_RPAREN )
                 getoken();

         switch ( funcnum )
         {
         case F_PRINTF:        /* just like the real printf() function */
                 pushint( printf( args[0], args[1], args[2], args[3], args[4],
                          args[5], args[6], args[7], args[8], args[9] ) );
                 break;
         case F_GETLINE:
                 /*
                  * Get the next line of input from the current input file
                  * and parse according to the current field seperator.
                  * Don't forget to free up the previous line's words first...
                  */
                 while ( Fieldcount )
                         free( Fields[ --Fieldcount ] );
                 pushint( getline() );
                 Fieldcount = parse( Linebuf, Fields, Fieldsep );
                 break;
         case F_STRLEN:        /* calculate length of string argument */
                 pushint( strlen( args[0] ) );
                 break;
         case F_STRCPY:        /* copy second string argument to first string
                 pushint( strcpy( args[0], args[1] ) );
                 break;
         case F_STRCMP:        /* compare two strings */
                 pushint( strcmp( args[0], args[1] ) );
                 break;
         case F_TOUPPER:        /* convert the character argument to upper cas
                 pushint( toupper( args[0] ) );
                 break;
         case F_TOLOWER:        /* convert the character argument to lower cas
                 pushint( tolower( args[0] ) );
                 break;
         case F_MATCH:        /* match a string argument to a regular expressi
                 pushint( match( args[0], args[1] ) );
                 break;
         case F_NEXTFILE:/* close current input file and process next file */
                 pushint( endfile() );
                 break;
         default:        /* oops! */
                 error( "bad function call", ACT_ERROR );
         }
 }

 VARIABLE *
 findvar( s )
 char *s;
 {
         /*
          * Search the symbol table for a variable whose name is "s".
          */
         VARIABLE *pvar;
         int i;
         char name[ MAXVARLEN ];

         i = 0;
         while ( i < MAXVARLEN && alphanum( *s ) )
                 name[i++] = *s++;
         if ( i<MAXVARLEN )
                 name[i] = 0;

         for ( pvar = Vartab; pvar<Nextvar; ++pvar )
         {
                 if ( !strncmp( pvar->vname, name, MAXVARLEN ) )
                         return pvar;
         }
         return NULL;
 }

 VARIABLE *
 addvar( name )
 char *name;
 {
         /*
          * Add a new variable to symbol table and assign it default
          * attributes (int name;)
          */
         int i;

         if ( Nextvar <= Vartab + MAXVARTABSZ )
         {
                 i = 0;
                 while ( i<MAXVARLEN && alphanum( *name ) )
                         Nextvar->vname[i++] = *name++;
                 if ( i<MAXVARLEN )
                         Nextvar->vname[i] = 0;

                 Nextvar->vclass = 0;
                 Nextvar->vsize = WORD;
                 Nextvar->vlen = 0;
                 /*
                  * Allocate some new room
                  */
                 Nextvar->vptr = getmem( WORD );
                 fillmem( Nextvar->vptr, WORD, 0 );
         }
         else
                 error( "symbol table overflow", MEM_ERROR );

         return Nextvar++;
 }

 declist()
 {
         /*
          * Parse a "char" or "int" statement.
          */
         char type;

         type = Token;
         getoken();
         decl( type );
         while ( Token==T_COMMA )
         {
                 getoken();
                 decl( type );
         }
         if ( Token==T_SEMICOLON )
                 getoken();
 }

 VARIABLE *
 decl( type )
 {
         /*
          * Parse an element of a "char" or "int" declaration list.
          * The function stmt_compile() has already entered the variable
          * into the symbol table as an integer, this routine simply changes
          * the symbol's class, size or length according to the declaraction.
          * WARNING: The interpreter depends on the fact that pointers are
          * the same length as int's.  If your machine uses long's for
          * pointers either change the code or #define int long (or whatever).
          */
         char class, size;
         int len;
         unsigned oldsize, newsize;
         VARIABLE *pvar;

         if ( Token==T_MUL )
         {
                 /*
                  * it's a pointer
                  */
                 getoken();
                 pvar = decl( type );
                 ++pvar->vclass;
         }
         else if ( Token==T_VARIABLE )
         {
                 /*
                  * Simple variable so far.  The token value (in the global
                  * "Value" variable) is a pointer to the variable's symbol
                  * table entry.
                  */
                 pvar = Value.dptr;
                 getoken();
                 class = 0;
                 /*
                  * Compute its length
                  */
                 if ( Token==T_LBRACKET )
                 {
                         /*
                          * It's an array.
                          */
                         getoken();
                         ++class;
                         /*
                          * Compute the dimension
                          */
                         expression();
                         if ( Token!=T_RBRACKET )
                                 error( "missing ']'", ACT_ERROR );
                         getoken();
                         len = popint();
                 }
                 else
                         /*
                          * It's a simple variable - array length is zero.
                          */
                         len = 0;

                 size = (type==T_CHAR) ? BYTE : WORD;

                 newsize = (len ? len : 1) * size;
                 oldsize = (pvar->vlen ? pvar->vlen : 1) * pvar->vsize;
                 if ( newsize != oldsize )
                 {
                         /*
                          * The amount of storage needed for the variable
                          * has changed - free up memory allocated initially
                          * and reallocate for new size.
                          */
                         free( pvar->vptr );
                         pvar->vptr = getmem( newsize );
                 }
                 /*
                  * Now change the variable's attributes.
                  */
                 pvar->vclass = class;
                 pvar->vsize = size;
                 pvar->vlen = len;
         }
         else
                 syntaxerror();

         return pvar;
 }

 assignment()
 {
         /*
          * Perform an assignment
          */
         int ival;

         ival = popint();
         /*
          * make sure we've got an lvalue
          */
         if ( Stackptr->lvalue )
         {
                 if ( Stackptr->class )
                         movemem( &ival, Stackptr->value.dptr, WORD );
                 else
                         movemem(&ival, Stackptr->value.dptr, Stackptr->size);
                 pop();
                 pushint( ival );
         }
         else
                 error( "'=' needs an lvalue", ACT_ERROR );
 }

 pop()
 {
         /*
          * Pop the stack and return the integer value
          */
         if ( Stackptr >= Stackbtm )
                 return (Stackptr--)->value.ival;
         return error( "stack underflow", ACT_ERROR );
 }

 push( pclass, plvalue, psize, pdatum )
 char pclass, plvalue, psize;
 DATUM *pdatum;
 {
         /*
          * Push item parts onto the stack
          */
         if ( ++Stackptr <= Stacktop )
         {
                 Stackptr->lvalue = plvalue;
                 Stackptr->size = psize;
                 if ( !(Stackptr->class = pclass)  &&  !plvalue )
                         Stackptr->value.ival = pdatum->ival;
                 else
                         Stackptr->value.dptr = pdatum->dptr;
         }
         else
                 error( "stack overflow", MEM_ERROR );
 }

 pushint( intvalue )
 int intvalue;
 {
         /*
          * push an integer onto the stack
          */
         if ( ++Stackptr <= Stacktop )
         {
                 Stackptr->lvalue =
                 Stackptr->class = 0;
                 Stackptr->size = WORD;
                 Stackptr->value.ival = intvalue;
         }
         else
                 error( "stack overflow", MEM_ERROR );
 }

 popint()
 {
         /*
          * Resolve the item on the top of the stack and return it
          */
         int intvalue;

         if ( Stackptr->lvalue )
         {
                 /*
                  * if it's a byte indirect, sign extend it
                  */
                 if ( Stackptr->size == BYTE && !Stackptr->class )
                         intvalue = *Stackptr->value.dptr;
                 else
                 {
                         /*
                          * otherwise, it's an unsigned int
                          */
                         intvalue = *Stackptr->value.ptrptr;
                 }
                 pop();
                 return intvalue;
         }
         else
         {
                 /*
                  * else it's an ACTUAL, just pop it
                  */
                 return pop();
         }
 }


 BETTERIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BETTERIN.C

                                         /* Chapter 9 - Program 3 */
 #include "stdio.h"
 CR 13       /* this defines CR to be 13 */
 LF 10       /* this defines LF to be 10 */

 main()
 {
 char c;

    printf("Input any characters, hit X to stop.\n");

    do {
       c = getch();                    /* get a character */
       putchar(c);                     /* display the hit key */
       if (c == CR) putchar(LF);       /* if it is a carriage return
                                          put out a linefeed too */
    } while (c != 'X');

    printf("\nEnd of program.\n");
 }


 BIGARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BIGARRAY.C

                                          /* Chapter 7 - Program 4 */
 char name1[] = "First Program Title";

 main()
 {
 int index;
 int stuff[12];
 float weird[12];
 static char name2[] = "Second Program Title";

    for (index = 0;index < 12;index++) {
       stuff[index] = index + 10;
       weird[index] = 12.0 * (index + 7);
    }

    printf("%s\n",name1);
    printf("%s\n\n",name2);
    for (index = 0;index < 12;index++)
       printf("%5d %5d %10.3f\n",index,stuff[index],weird[index]);
 }


 BIGDYNL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BIGDYNL.C

                                       /* Chapter 12 - Program 2 */
 main()
 {
 struct animal {
    char name[25];
    char breed[25];
    int age;
 } *pet[12], *point;   /* this defines 13 pointers, no variables */
 int index;

             /* first, fill the dynamic structures with nonsense */
    for (index = 0;index < 12;index++) {
       pet[index] = (struct animal *)malloc(sizeof(struct animal));
       strcpy(pet[index]->name,"General");
       strcpy(pet[index]->breed,"Mixed Breed");
       pet[index]->age = 4;
    }

    pet[4]->age = 12;        /* these lines are simply to        */
    pet[5]->age = 15;        /*      put some nonsense data into */
    pet[6]->age = 10;        /*            a few of the fields.  */

        /* now print out the data described above */

    for (index = 0;index <12;index++) {
       point = pet[index];
       printf("%s is a %s, and is %d years old.\n", point->name,
               point->breed, point->age);
    }

        /* good programming practice dictates that we free up the */
        /* dynamically allocated space before we quit.            */

    for (index = 0;index < 12;index++)
       free(pet[index]);
 }


 BIGSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\BIGSORT\BIGSORT.C

 /* Reverse Engineered UNIX (tm) inspired sort                       */
 /* Copyright (c) Jim Gast, Naperville, IL    April, 1986            */
 /* NOT copyright, I hereby put this here thing in the PUBLIC DOMAIN */

 /* SYNTAX:   bigsort [ -tx ] [+dd.dd[n][r]] [-dd.dd] . . .          */
 /*                        [infile] . . . -o [outfile]                    */
 /* "-tx" specifies a new tab (delimeter) character (default is tab) */
 /* "+5.6 -6.0" means that a key starts at the 5th delimeter plus    */
 /*        six more characters, and ends at the sixth delimeter        */
 /* "n" appended to any key specifier makes it a numeric comparison  */
 /* "r" appended to any key specifier makes it a reverse comparison  */

 /* Assuming a file that contained:
  *        accountname;name;address;balance;phone number
  *
  * Example record:
  *        0023Flint;Flintstone, Fred;43 Quarry Lane;120.00;355-9881
  *
  * SAMPLE sorts:
  *        bigsort people -o namesort
  *                bigsorts by name and puts the output in file "namesort".
  *        bigsort -t; +3n -4 +0 people
  *                sorts by balance (numerically), and accountname if the
  *                balance is the same. outputs to stdout.
  *                The "-t;" changes the tab (field delimeter) to semicolon.
  *                Note that +3n skips to the field after the 3rd delimeter,
  *                you might think of it as the 4th field.
  *        bigsort +0.4 people
  *                sorts by characters starting with the 5th (skips 4).
  */

 /*  This program is SHAREWARE, an $8.00 donation puts you on my mailing
  *  list to receive the next version of this and my screen utilities.
  *
  *                Jim Gast
  *                16 N. Columbia
  *                Naperville, IL 60540
  */

 /* Compiled under CI-86, and depends on the CI-86 routine qsort()   */
 /* To sort any decent size file, compile with BIG model                    */

 /* up to MAXKEYS keys can be specified  */
 #define MAXKEYS                  20

 /* up to MAXRECS records can be sorted  */
 #define MAXRECS                5000

 /* each record can be up to LINELEN long */
 #define LINELEN                 512

 /* there can be up to MAXFILES input files */
 #define MAXFILES         50

 /* CI-86 is does not understand <stdio.h> */
 #include "\lib\stdio.h"

 #define STRING                1
 #define NUMERIC                2

 #define FORWARD                1
 #define REVERSE                2

 #define INFINITY        LINELEN

 #define TAB                '\011'

 struct key_struct {
         int k_lo_field;
         int k_lo_char;
         int k_hi_field;
         int k_hi_char;
         int k_comparison;
         int k_direction;
         } key_table[MAXKEYS], *lastkey;

 int keypointers;
 char tab;
 char *rec[MAXRECS];
 int numrecs;

 char *passdigits();
 char *keyptr();
 FILE *fopen();
 char *fgets();
 char *alloc();
 long atoi();

 main (argc, argv)
  int argc;
  char *argv[];
  {
   int a;
   int hi;
   register char *arg;
   register struct key_struct *k;
   char *pdata;
   int r;
   char *p;
   char *infile_name[MAXFILES];
   char outfile[80];
   int infiles;
   int fi;
   FILE *sort_out;
   int comp();

   infiles = 0;
   numrecs = 0;
   *outfile = 0;
   tab = TAB;
   k = &key_table[-1];
   for (a = 1;a < argc; a++)
         {
          arg = argv[a];
          if (*arg != '-' && *arg != '+')
                 {
                  /* This must be an input file name */
                  infile_name[infiles] = alloc(strlen(arg) + 1);
                  strcpy(infile_name[infiles], arg);
                  infiles++;
                  continue;
                 }
          if (*arg == '-' && arg[1] == 'o')
                 {
                  if (arg[2] == 0) arg = argv[++a];
                  strcpy(outfile,arg);
                  continue;
                 }
          if (*arg == '-' && arg[1] == 't')
                 {
                  tab = arg[2];
                  continue;
                 }
          if (*arg == '+' || k < &key_table[0])
                 {
                  k++;
                  k->k_lo_field = 0;
                  k->k_lo_char  = 0;
                  k->k_hi_field = INFINITY;
                  k->k_hi_char  = 0;
                  k->k_comparison = STRING;
                  k->k_direction  = FORWARD;
                 }

          hi = (*arg++ == '-');

          if (hi) k->k_hi_field = atoi(arg);
             else k->k_lo_field = atoi(arg);
          arg = passdigits(arg);

          if (*arg == '.')
                 {
                  arg++;
                  if (hi) k->k_hi_char = atoi(arg);
                     else k->k_lo_char = atoi(arg);
                  arg = passdigits(arg);
                 }

          /* handle letters appended after field specifiers */
          while (*arg)
                 {
                  switch (*arg)
                         {
                     case 'n':  k->k_comparison = NUMERIC;
                                break;

                     case 'r':  k->k_direction = REVERSE;
                                break;

                     default:   fprintf(stderr,"bad specifier: %s\n",argv[a]);
                                 fprintf(stderr,"bad letter:    %c\n",*arg);
                                break;
                         }
                  arg++;
                 }
         }

  /* if no keys were specified */
  if (k == &key_table[-1])
         {
          k++;
          k->k_lo_field = 0;
          k->k_lo_char  = 0;
          k->k_hi_field = INFINITY;
          k->k_hi_char  = 0;
          k->k_comparison = STRING;
          k->k_direction = FORWARD;
         }

  lastkey = k;

  keypointers = sizeof (char *) * 2 * (lastkey - &key_table[-1]);

  if (*outfile != 0)
         {
          sort_out = fopen(outfile,"w");
          if (sort_out == NULL)
                 {
                  fprintf(stderr, "bigsort: unable to open out file %s\n",outf
                  exit(1);
                 }
         }
      else
         {
          sort_out = stdout;
         }

  if (infiles == 0)
         {
          infiles = 1;
          infile_name[0] = "";
         }

  for (fi = 0; fi < infiles; fi++) get_data(infile_name[fi]);

  qsort(rec, numrecs, sizeof (char *), comp);

  for (r = 0; r < numrecs; r++)
         {
          pdata = rec[r] + keypointers;
          fprintf(sort_out,"%s",pdata);
         }
   fclose(sort_out);
  }

 char *passdigits(p)
  char *p;
   {
    while (*p >= '0' && *p <= '9') p++;
    return(p);
   }

 int show_args()
   {
    register struct key_struct *k;

    printf("Tab is octal %4o\n",tab);

    for (k = &key_table[0]; k <= lastkey; k++)
         {
          printf("\n");
          printf("lo = %4d . %4d\n",k->k_lo_field, k->k_lo_char);
          printf("hi = %4d . %4d\n",k->k_hi_field, k->k_hi_char);
          printf("compare   = %s\n",
                 (k->k_comparison == NUMERIC? "numeric" : "string"));
          printf("direction = %s\n",
                 (k->k_direction == FORWARD? "forward" : "reverse"));
         }
   }

 char *keyptr(data, fld, chr)
  char *data;
  int fld;
  int chr;
   {
    int f, c;

    for (f = 0; f < fld; )
         {
          if (*data == tab) f++;
          if (*data == 0) break;
          data++;
         }

    for (c = 0; c < chr; c++)
         {
          if (*data == tab) break;
          if (*data == 0) break;
          data++;
         }
    return(data);
   }

 int comp(a,b)
  char **a, **b;
   {
    register char *p, *q;
    register struct key_struct *k;
    char *p_end, *q_end;
    char **pp, **qq;
    int high, low;
    long pval, qval;

    pp = (char **) *a;
    qq = (char **) *b;

    for (k = &key_table[0]; k <= lastkey; k++)
         {
          p = *pp++;
          p_end = *pp++;
          q = *qq++;
          q_end = *qq++;

          if (k->k_direction == FORWARD)
                 {
                  high = 1;
                  low = -1;
                 }
          else
                 {
                  high = -1;
                  low = 1;
                 }

          if (k->k_comparison == NUMERIC)
                 {
                  pval = atoi(p);
                  qval = atoi(q);
                  if (pval > qval) return(high);
                  if (pval < qval) return(low);
                 }

          /* all other comparisons are string comparisons */
          else while (1)
                 {
                  if (p >= p_end)
                         {
                          if (q >= q_end) break;
                             else return(low);
                         }
                  if (q >= q_end) return(high);
                  if (*p < *q) return(low);
                  if (*p > *q) return(high);
                  p++; q++;
                 }
         }
    return(0);
   }

 /* get_data reads records in from a data file. If the file name is */
 /* NULL (""), it reads from standard in */

 int get_data(filename)
  char *filename;
  {
   register char *p;
   register int r;
   char buffer[LINELEN];
   char **pp;
   char *pdata;
   FILE *sort_in;
   struct key_struct *k;

   if (filename[0] != 0)
         {
          sort_in = fopen(filename, "r");
          if (sort_in == NULL)
                 {
                  fprintf(stderr, "bigsort: unable to open %s\n",filename);
                  exit(1);
                 }
         }
     else sort_in = stdin;

   for (r = numrecs; r < MAXRECS; r++)
         {
          p = fgets(buffer,LINELEN,sort_in);
          if (p == NULL) break;
          rec[r] = alloc(strlen(buffer) + keypointers + 1);
          pdata = rec[r] + keypointers;
          strcpy(pdata, buffer);
          pp = (char **) rec[r];
          for (k = &key_table[0]; k <= lastkey; k++)
                 {
                  *pp++ = keyptr(pdata,k->k_lo_field,k->k_lo_char);
                  *pp++ = keyptr(pdata,k->k_hi_field,k->k_hi_char);
                 }
         }
   numrecs = r;

   if (filename[0] != 0) fclose(sort_in);
  }


 BINCOMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\BINCOMP.C


 /***********************************************************************/
 /* BINCOMP:  The Telemacus file comparison utility                     */
 /* Copyright (c), 3/88, Telemacus Software Associates                  */
 /* Garry J. Vass  [72307,3311]                                         */
 /*                                                                     */
 /* Usage:  BINCOMP {file spec}  {file spec}                            */
 /*                                                                     */
 /* Source:  Turbo C (1.5), Large model                                 */
 /*                                                                     */
 /***********************************************************************/


 #include <stdio.h>
 #include <conio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <io.h>
 #include <fcntl.h>
 #include <ctype.h>

 /*#define MICROSOFT 1*/
 #define TURBOC 1
 #ifdef MICROSOFT
 #undef  TURBOC
 #define COMPILER_NAME    "(MSC-5.1)"
 #define _close(x)         close(x)
 #define _open(x, y)       open(x, y)
 #define _read(x, y, z)    read(x, y, z)
 #include <dos.h>
 #endif
 #ifdef TURBOC
 #define  COMPILER_NAME "(TC-1.5)"
 #endif

 #define PROGRAM_NAME  "BINCOMP:  "
 #define BUFFERSIZE    ((int)  (((unsigned) - 1) >> 1))
 #define IMIN(a,b)     ((a<b?a:b))
 #define CHARVAL(a)    ((isprint(a)?a:46))

 typedef struct bincomp_file_type
     {
         unsigned char    *bc_file_name;
         int               bc_file_handle;
         int               bc_read_result;
         long              bc_count_of_total_bytes;
         unsigned char    *bc_index_to_buffer;
         unsigned char    *bc_buffer;
         }
         bc_file_type;

 long             file_offset               = 0L;
 int          loop_control              = 0;
 int          count_of_lines            = 0;
 bc_file_type file1;
 bc_file_type file2;
 long         count_of_differences      = 0L;

 void pause
     (
         bc_file_type *f1,
         bc_file_type *f2
         )
 {
 ++count_of_lines;
 if (count_of_lines > 18)
     {
     printf("\n\n%sPausing.  Hit almost any key...", PROGRAM_NAME);
     (void) getch();
     printf("\n\n");
     printf("%sComparing %s to %s\n", PROGRAM_NAME, f1 -> bc_file_name, f2 ->
     count_of_lines = 0;
     }
 }

 void initialize_file_record
     (
         unsigned char      *fname,
         bc_file_type       *frec
         )
 {
 frec -> bc_file_name = (unsigned char *) malloc(strlen(fname));
 strcpy(frec -> bc_file_name, fname);
 frec -> bc_file_handle = open(frec -> bc_file_name, O_RDWR | O_BINARY);
 if (frec -> bc_file_handle < 0)
     {
         printf("%sCannot open %s\n", PROGRAM_NAME, frec -> bc_file_name);
         abort();
         }
 frec -> bc_buffer = (unsigned char *) malloc (BUFFERSIZE);
 if (!frec -> bc_buffer)
     {
         printf("%sUnable to get memory\n", PROGRAM_NAME);
         abort();
         }
 frec -> bc_count_of_total_bytes = 0L;
 }

 void read_into_buffer
     (
         bc_file_type *frec
         )
 {
 frec -> bc_read_result = read(frec -> bc_file_handle,
                               frec -> bc_buffer,
                               BUFFERSIZE);
 frec -> bc_index_to_buffer       = frec -> bc_buffer;
 frec -> bc_count_of_total_bytes += frec -> bc_read_result;
 }

 main
     (
     int argc,
     unsigned char *argv[]
     )
 {
 printf("%sThe Telemacus file comparison utility %s\n\n",
          PROGRAM_NAME,
                  COMPILER_NAME);
 if (argc < 3)
     {
         printf("Usage  BINCOMP  {file specification}  {file specification}\n\
     printf("\tTwo file names are required in the command tail\n");
     printf("\twhich specify the names of the files you want to\n");
     printf("\tcompare.\n\n");
     exit(0);
     }

 initialize_file_record(argv[1], &file1);
 initialize_file_record(argv[2], &file2);

 read_into_buffer(&file1);
 read_into_buffer(&file2);

 printf("%sComparing %s to %s\n",
         PROGRAM_NAME,
                 file1.bc_file_name,
                 file2.bc_file_name);

 while ((file1.bc_read_result) && (file2.bc_read_result))
     {
     for (loop_control=0;
                  loop_control<IMIN(file1.bc_read_result, file2.bc_read_result
                  ++loop_control)
                 {
                 if (*file1.bc_index_to_buffer != *file2.bc_index_to_buffer)
                         {
                     printf("Offset:  %5ld   %s:  %02X (%c)   %s:  %02X (%c)\n
                                  file_offset,
                                  file1.bc_file_name,
                                  *file1.bc_index_to_buffer,
                                  CHARVAL(*file1.bc_index_to_buffer),
                                  file2.bc_file_name,
                                  *file2.bc_index_to_buffer,
                                  CHARVAL(*file2.bc_index_to_buffer));
                         ++count_of_differences;
             pause(&file1, &file2);
                         }
                 ++file1.bc_index_to_buffer;
                 ++file2.bc_index_to_buffer;
                 ++file_offset;
                 }
         read_into_buffer(&file1);
     read_into_buffer(&file2);
         }

 (void) close(file1.bc_file_handle);
 (void) close(file2.bc_file_handle);

 printf("\n\n");
 printf("%s%ld bytes were read from %s\n", PROGRAM_NAME, file1.bc_count_of_tot
 printf("%s%ld bytes were read from %s\n", PROGRAM_NAME, file2.bc_count_of_tot
 printf("%s%ld bytes were different\n",PROGRAM_NAME, count_of_differences);
 printf("%sProcessing complete\n",PROGRAM_NAME);
 return(0);
 }
 /***********************************************************************/
 /* end of bincomp.c                                                    */
 /*                                                                     */
 /*                                                                     */
 /*                                                                     */
 /***********************************************************************/



 BIND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\BIND.C

 /*        This file is for functions having to do with key bindings,
         descriptions, help commands and startup file.

         written 11-feb-86 by Daniel Lawrence
                                                                 */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"
 #include        "epath.h"

 extern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions

 help(f, n)        /* give me some help!!!!
                    bring up a fake buffer and read the help file
                    into it with view mode                        */
 {
         register WINDOW *wp;        /* scaning pointer to windows */
         register BUFFER *bp;        /* buffer pointer to help */
         char *fname;                /* ptr to file returned by flook() */

         /* first check if we are already here */
         bp = bfind("emacs.hlp", FALSE, BFINVS);

         if (bp == NULL) {
                 fname = flook(pathname[1], FALSE);
                 if (fname == NULL) {
                         mlwrite("[Help file is not online]");
                         return(FALSE);
                 }
         }

         /* split the current window to make room for the help stuff */
         if (splitwind(FALSE, 1) == FALSE)
                         return(FALSE);

         if (bp == NULL) {
                 /* and read the stuff in */
                 if (getfile(fname, FALSE) == FALSE)
                         return(FALSE);
         } else
                 swbuffer(bp);

         /* make this window in VIEW mode, update all mode lines */
         curwp->w_bufp->b_mode |= MDVIEW;
         curwp->w_bufp->b_flag |= BFINVS;
         wp = wheadp;
         while (wp != NULL) {
                 wp->w_flag |= WFMODE;
                 wp = wp->w_wndp;
         }
         return(TRUE);
 }

 deskey(f, n)        /* describe the command for a certain key */

 {
         register int c;                /* key to describe */
         register char *ptr;        /* string pointer to scan output strings *
         char outseq[NSTRING];        /* output buffer for command sequence */
         int (*getbind())();

         /* prompt the user to type us a key to describe */
         mlwrite(": describe-key ");

         /* get the command sequence to describe
            change it to something we can print as well */
         cmdstr(c = getckey(FALSE), &outseq[0]);

         /* and dump it out */
         ostring(outseq);
         ostring(" ");

         /* find the right ->function */
         if ((ptr = getfname(getbind(c))) == NULL)
                 ptr = "Not Bound";

         /* output the command sequence */
         ostring(ptr);
 }

 /* bindtokey:        add a new key to the key binding table                */

 bindtokey(f, n)

 int f, n;        /* command arguments [IGNORED] */

 {
         register unsigned int c;/* command key to bind */
         register (*kfunc)();        /* ptr to the requested function to bind
         register KEYTAB *ktp;        /* pointer into the command table */
         register int found;        /* matched command flag */
         char outseq[80];        /* output buffer for keystroke sequence */
         int (*getname())();

         /* prompt the user to type in a key to bind */
         mlwrite(": bind-to-key ");

         /* get the function name to bind it to */
         kfunc = getname();
         if (kfunc == NULL) {
                 mlwrite("[No such function]");
                 return(FALSE);
         }
         ostring(" ");

         /* get the command sequence to bind */
         c = getckey((kfunc == meta) || (kfunc == cex) ||
                     (kfunc == unarg) || (kfunc == ctrlg));

         /* change it to something we can print as well */
         cmdstr(c, &outseq[0]);

         /* and dump it out */
         ostring(outseq);

         /* if the function is a prefix key */
         if (kfunc == meta || kfunc == cex ||
             kfunc == unarg || kfunc == ctrlg) {

                 /* search for an existing binding for the prefix key */
                 ktp = &keytab[0];
                 found = FALSE;
                 while (ktp->k_fp != NULL) {
                         if (ktp->k_fp == kfunc)
                                 unbindchar(ktp->k_code);
                         ++ktp;
                 }

                 /* reset the appropriate global prefix variable */
                 if (kfunc == meta)
                         metac = c;
                 if (kfunc == cex)
                         ctlxc = c;
                 if (kfunc == unarg)
                         reptc = c;
                 if (kfunc == ctrlg)
                         abortc = c;
         }

         /* search the table to see if it exists */
         ktp = &keytab[0];
         found = FALSE;
         while (ktp->k_fp != NULL) {
                 if (ktp->k_code == c) {
                         found = TRUE;
                         break;
                 }
                 ++ktp;
         }

         if (found) {        /* it exists, just change it then */
                 ktp->k_fp = kfunc;
         } else {        /* otherwise we need to add it to the end */
                 /* if we run out of binding room, bitch */
                 if (ktp >= &keytab[NBINDS]) {
                         mlwrite("Binding table FULL!");
                         return(FALSE);
                 }

                 ktp->k_code = c;        /* add keycode */
                 ktp->k_fp = kfunc;        /* and the function pointer */
                 ++ktp;                        /* and make sure the next is nu
                 ktp->k_code = 0;
                 ktp->k_fp = NULL;
         }
         return(TRUE);
 }

 /* unbindkey:        delete a key from the key binding table        */

 unbindkey(f, n)

 int f, n;        /* command arguments [IGNORED] */

 {
         register int c;                /* command key to unbind */
         char outseq[80];        /* output buffer for keystroke sequence */

         /* prompt the user to type in a key to unbind */
         mlwrite(": unbind-key ");

         /* get the command sequence to unbind */
         c = getckey(FALSE);                /* get a command sequence */

         /* change it to something we can print as well */
         cmdstr(c, &outseq[0]);

         /* and dump it out */
         ostring(outseq);

         /* if it isn't bound, bitch */
         if (unbindchar(c) == FALSE) {
                 mlwrite("[Key not bound]");
                 return(FALSE);
         }
         return(TRUE);
 }

 unbindchar(c)

 int c;                /* command key to unbind */

 {
         register KEYTAB *ktp;        /* pointer into the command table */
         register KEYTAB *sktp;        /* saved pointer into the command table
         register int found;        /* matched command flag */

         /* search the table to see if the key exists */
         ktp = &keytab[0];
         found = FALSE;
         while (ktp->k_fp != NULL) {
                 if (ktp->k_code == c) {
                         found = TRUE;
                         break;
                 }
                 ++ktp;
         }

         /* if it isn't bound, bitch */
         if (!found)
                 return(FALSE);

         /* save the pointer and scan to the end of the table */
         sktp = ktp;
         while (ktp->k_fp != NULL)
                 ++ktp;
         --ktp;                /* backup to the last legit entry */

         /* copy the last entry to the current one */
         sktp->k_code = ktp->k_code;
         sktp->k_fp   = ktp->k_fp;

         /* null out the last one */
         ktp->k_code = 0;
         ktp->k_fp = NULL;
         return(TRUE);
 }

 desbind(f, n)        /* describe bindings
                    bring up a fake buffer and list the key bindings
                    into it with view mode                        */

 #if        APROP
 {
         buildlist(TRUE, "");
 }

 apro(f, n)        /* Apropos (List functions that match a substring) */

 {
         char mstring[NSTRING];        /* string to match cmd names to */
         int status;                /* status return */

         status = mlreply("Apropos string: ", mstring, NSTRING - 1);
         if (status != TRUE)
                 return(status);

         return(buildlist(FALSE, mstring));
 }

 buildlist(type, mstring)  /* build a binding list (limited or full) */

 int type;        /* true = full list,   false = partial list */
 char *mstring;        /* match string if a partial list */

 #endif
 {
 #if        ST520 & LATTICE
 #define        register
 #endif
         register WINDOW *wp;        /* scanning pointer to windows */
         register KEYTAB *ktp;        /* pointer into the command table */
         register NBIND *nptr;        /* pointer into the name binding table *
         register BUFFER *bp;        /* buffer to put binding list into */
         char *strp;                /* pointer int string to send */
         int cpos;                /* current position to use in outseq */
         char outseq[80];        /* output buffer for keystroke sequence */

         /* split the current window to make room for the binding list */
         if (splitwind(FALSE, 1) == FALSE)
                         return(FALSE);

         /* and get a buffer for it */
         bp = bfind("Binding list", TRUE, 0);
         if (bp == NULL || bclear(bp) == FALSE) {
                 mlwrite("Can not display binding list");
                 return(FALSE);
         }

         /* let us know this is in progress */
         mlwrite("[Building binding list]");

         /* disconect the current buffer */
         if (--curbp->b_nwnd == 0) {             /* Last use.            */
                 curbp->b_dotp  = curwp->w_dotp;
                 curbp->b_doto  = curwp->w_doto;
                 curbp->b_markp = curwp->w_markp;
                 curbp->b_marko = curwp->w_marko;
         }

         /* connect the current window to this buffer */
         curbp = bp;        /* make this buffer current in current window */
         bp->b_mode = 0;                /* no modes active in binding list */
         bp->b_nwnd++;                /* mark us as more in use */
         wp = curwp;
         wp->w_bufp = bp;
         wp->w_linep = bp->b_linep;
         wp->w_flag = WFHARD|WFFORCE;
         wp->w_dotp = bp->b_dotp;
         wp->w_doto = bp->b_doto;
         wp->w_markp = NULL;
         wp->w_marko = 0;

         /* build the contents of this window, inserting it line by line */
         nptr = &names[0];
         while (nptr->n_func != NULL) {

                 /* add in the command name */
                 strcpy(outseq, nptr->n_name);
                 cpos = strlen(outseq);

 #if        APROP
                 /* if we are executing an apropos command..... */
                 if (type == FALSE &&
                     /* and current string doesn't include the search string *
                     strinc(outseq, mstring) == FALSE)
                         goto fail;
 #endif
                 /* search down any keys bound to this */
                 ktp = &keytab[0];
                 while (ktp->k_fp != NULL) {
                         if (ktp->k_fp == nptr->n_func) {
                                 /* padd out some spaces */
                                 while (cpos < 25)
                                         outseq[cpos++] = ' ';

                                 /* add in the command sequence */
                                 cmdstr(ktp->k_code, &outseq[cpos]);
                                 while (outseq[cpos] != 0)
                                         ++cpos;

                                 /* and add it as a line into the buffer */
                                 strp = &outseq[0];
                                 while (*strp != 0)
                                         linsert(1, *strp++);
                                 lnewline();

                                 cpos = 0;        /* and clear the line */
                         }
                         ++ktp;
                 }

                 /* if no key was bound, we need to dump it anyway */
                 if (cpos > 0) {
                         outseq[cpos] = 0;
                         strp = &outseq[0];
                         while (*strp != 0)
                                 linsert(1, *strp++);
                         lnewline();
                 }

 fail:                /* and on to the next name */
                 ++nptr;
         }

         curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
         curbp->b_flag &= ~BFCHG;        /* don't flag this as a change */
         wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
         wp->w_doto = 0;
         wp = wheadp;                        /* and update ALL mode lines */
         while (wp != NULL) {
                 wp->w_flag |= WFMODE;
                 wp = wp->w_wndp;
         }
         mlwrite("");        /* clear the mode line */
         return(TRUE);
 }

 #if        APROP
 strinc(source, sub)        /* does source include sub? */

 char *source;        /* string to search in */
 char *sub;        /* substring to look for */

 {
         char *sp;        /* ptr into source */
         char *nxtsp;        /* next ptr into source */
         char *tp;        /* ptr into substring */

         /* for each character in the source string */
         sp = source;
         while (*sp) {
                 tp = sub;
                 nxtsp = sp;

                 /* is the substring here? */
                 while (*tp) {
                         if (*nxtsp++ != *tp)
                                 break;
                         else
                                 tp++;
                 }

                 /* yes, return a success */
                 if (*tp == 0)
                         return(TRUE);

                 /* no, onward */
                 sp++;
         }
         return(FALSE);
 }
 #endif

 /* get a command key sequence from the keyboard        */

 unsigned int getckey(mflag)

 int mflag;        /* going for a meta sequence? */

 {
         register unsigned int c;        /* character fetched */
 #if        MSC | TURBO
         register unsigned char *tp;        /* pointer into the token */
 #else
         register char *tp;                /* pointer into the token */
 #endif
         char tok[NSTRING];                /* command incoming */

         /* check to see if we are executing a command line */
         if (clexec) {
                 macarg(tok);        /* get the next token */
                 return(stock(tok));
         }

         /* or the normal way */
         if (mflag)
                 c = get1key();
         else
                 c = getcmd();
         return(c);
 }

 /* execute the startup file */

 startup(sfname)

 char *sfname;        /* name of startup file (null if default) */

 {
         char *fname;        /* resulting file name to execute */

         /* look up the startup file */
         if (*sfname != 0)
                 fname = flook(sfname, TRUE);
         else
                 fname = flook(pathname[0], TRUE);

         /* if it isn't around, don't sweat it */
         if (fname == NULL)
                 return(TRUE);

         /* otherwise, execute the sucker */
         return(dofile(fname));
 }

 /*        Look up the existance of a file along the normal or PATH
         environment variable. Look first in the HOME directory if
         asked and possible
 */

 char *flook(fname, hflag)

 char *fname;        /* base file name to search for */
 int hflag;        /* Look in the HOME environment variable first? */

 {
         register char *home;        /* path to home directory */
         register char *path;        /* environmental PATH variable */
         register char *sp;        /* pointer into path spec */
         register int i;                /* index */
         register int status;        /* return status */
         static char fspec[NSTRING];        /* full path spec to search */
         char *getenv();

 #if        ENVFUNC

         if (hflag) {
                 home = getenv("HOME");
                 if (home != NULL) {
                         /* build home dir file spec */
                         strcpy(fspec, home);
                         strcat(fspec, "/");
                         strcat(fspec, fname);

                         /* and try it out */
                         if (ffropen(fspec) == FIOSUC) {
                                 ffclose();
                                 return(fspec);
                         }
                 }
         }
 #endif

         /* always try the current directory first */
         if (ffropen(fname) == FIOSUC) {
                 ffclose();
                 return(fname);
         }

 #if        ENVFUNC
         /* get the PATH variable */
         path = getenv("PATH");
         if (path != NULL)
                 while (*path) {

                         /* build next possible file spec */
                         sp = fspec;
                         while (*path && (*path != PATHCHR))
                                 *sp++ = *path++;
                         *sp++ = '/';
                         *sp = 0;
                         strcat(fspec, fname);

                         /* and try it out */
                         if (ffropen(fspec) == FIOSUC) {
                                 ffclose();
                                 return(fspec);
                         }

                         if (*path == PATHCHR)
                                 ++path;
                 }
 #endif

         /* look it up via the old table method */
         for (i=2; i < NPNAMES; i++) {
                 strcpy(fspec, pathname[i]);
                 strcat(fspec, fname);

                 /* and try it out */
                 if (ffropen(fspec) == FIOSUC) {
                         ffclose();
                         return(fspec);
                 }
         }

         return(NULL);        /* no such luck */
 }

 cmdstr(c, seq)        /* change a key command to a string we can print out */

 int c;                /* sequence to translate */
 char *seq;        /* destination string for sequence */

 {
         char *ptr;        /* pointer into current position in sequence */

         ptr = seq;

         /* apply meta sequence if needed */
         if (c & META) {
                 *ptr++ = 'M';
                 *ptr++ = '-';
         }

         /* apply ^X sequence if needed */
         if (c & CTLX) {
                 *ptr++ = '^';
                 *ptr++ = 'X';
         }

         /* apply SPEC sequence if needed */
         if (c & SPEC) {
                 *ptr++ = 'F';
                 *ptr++ = 'N';
         }

         /* apply control sequence if needed */
         if (c & CTRL) {
                 *ptr++ = '^';
         }

         c = c & 255;        /* strip the prefixes */

         /* and output the final sequence */

         *ptr++ = c;
         *ptr = 0;        /* terminate the string */
 }

 /*        This function looks a key binding up in the binding table        */

 int (*getbind(c))()

 int c;        /* key to find what is bound to it */

 {
         register KEYTAB *ktp;

         ktp = &keytab[0];                       /* Look in key table.   */
         while (ktp->k_fp != NULL) {
                 if (ktp->k_code == c)
                         return(ktp->k_fp);
                 ++ktp;
         }

         /* no such binding */
         return(NULL);
 }

 /* getfname:        This function takes a ptr to function and gets the name
                 associated with it
 */

 char *getfname(func)

 int (*func)();        /* ptr to the requested function to bind to */

 {
         register NBIND *nptr;        /* pointer into the name binding table *

         /* skim through the table, looking for a match */
         nptr = &names[0];
         while (nptr->n_func != NULL) {
                 if (nptr->n_func == func)
                         return(nptr->n_name);
                 ++nptr;
         }
         return(NULL);
 }

 int (*fncmatch(fname))() /* match fname to a function in the names table
                             and return any match or NULL if none

 char *fname;        /* name to attempt to match */

 {
         register NBIND *ffp;        /* pointer to entry in name binding table

         /* scan through the table, returning any match */
         ffp = &names[0];
         while (ffp->n_func != NULL) {
                 if (strcmp(fname, ffp->n_name) == 0)
                         return(ffp->n_func);
                 ++ffp;
         }
         return(NULL);
 }

 /* stock:        String key name TO Command Key                */

 unsigned int stock(keyname)

 char *keyname;                /* name of key to translate to Command key form

 {
         register unsigned int c;        /* key sequence to return */

         /* parse it up */
         c = 0;

         /* first, the META prefix */
         if (*keyname == 'M' && *(keyname+1) == '-') {
                 c = META;
                 keyname += 2;
         }

         /* next the function prefix */
         if (*keyname == 'F' && *(keyname+1) == 'N') {
                 c |= SPEC;
                 keyname += 2;
         }

         /* control-x as well... (but not with FN) */
         if (*keyname == '^' && *(keyname+1) == 'X'&& !(c & SPEC)) {
                 c |= CTLX;
                 keyname += 2;
         }

         /* a control char? */
         if (*keyname == '^' && *(keyname+1) != 0) {
                 c |= CTRL;
                 ++keyname;
         }
         if (*keyname < 32) {
                 c |= CTRL;
                 *keyname += 'A';
         }


         /* make sure we are not lower case (not with function keys)*/
         if (*keyname >= 'a' && *keyname <= 'z' && !(*keyname & SPEC))
                 *keyname -= 32;

         /* the final sequence... */
         c |= *keyname;
         return(c);
 }

 char *transbind(skey)        /* string key name to binding name.... */

 char *skey;        /* name of keey to get binding for */

 {
         char *bindname;
         unsigned int stock();
         int (*getbind())();

         bindname = getfname(getbind(stock(skey)));
         if (bindname == NULL)
                 bindname = "ERROR";

         return(bindname);
 }


 BINDUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\BINDUMP.C

 /* BINDUMP.C - From page 446 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. Performs a binary dump of a file. */
 /* In the book there is a semicolon that doesn't belong at the  */
 /* end of the second if statement. Also there is a space after  */
 /* the ">" character in the first printf statement that doesn't */
 /* belong.                                                      */
 /****************************************************************/

 #include <stdio.h>
 #define LENGTH 10
 #define TRUE 0
 #define FALSE -1

 main(argc, argv)
 int argc;
 char *argv[];
 {
 FILE *fileptr;
 unsigned int ch;
 int j, not_eof;
 unsigned char string[LENGTH + 1];

    if(argc != 2) {
       printf("\nFormat: C>bindump filename");
       exit();
    }
    if((fileptr = fopen(argv[1], "rb")) == NULL) {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    not_eof = TRUE;                  /*not EOF flag*/
    do {
       for(j = 0; j < LENGTH; j++) {
          if((ch = getc(fileptr)) == EOF)     /*read character*/
             not_eof = FALSE;              /*clear flag on EOF*/
          printf("%3x ", ch);              /*print ASCII code*/
          if(ch > 31)
             *(string + j) = ch;           /*save printable char*/
          else                             /*use period for*/
             *(string + j) = '.';          /*nonprintable char*/
       }
       *(string + j) = '\0';               /*end string*/
       printf("   %s\n", string);          /*print string*/
    } while(not_eof == TRUE);              /*quit on EOF*/
    fclose(fileptr);
 }



 BITCALC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\BITCALC.C

 /* BITCALC.C - From page 345 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. It demonstrates the use of the    */
 /* 6 bitwise operators.  x1 and x2 were made unsigned int       */
 /* (different from book) to make the >> operator not insert     */
 /* a 1 in the leftmost bit.                                     */
 /****************************************************************/

 #define TRUE 1

 main()
 {
 char op[10];
 unsigned int x1, x2;

    while(TRUE) {
       printf("\n\nEnter expression (example 'ff00 & 1111'): ");
       scanf("%x %s %x", &x1, op, &x2);
       printf("\n\n");
       switch(op[0]) {
          case '&':
             pbin(x1);
             printf("& (and)\n");
             pbin(x2);
             pline();
             pbin(x1 & x2);
             break;
          case '|':
             pbin(x1);
             printf("| (incl or)\n");
             pbin(x2);
             pline();
             pbin(x1 | x2);
             break;
          case '^':
             pbin(x1);
             printf("^ (excl or)\n");
             pbin(x2);
             pline();
             pbin(x1 ^ x2);
             break;
          case '>':
             pbin(x1);
             printf(">> ");
             printf("%d\n", x2);
             pline();
             pbin(x1 >> x2);
             break;
          case '<':
             pbin(x1);
             printf("<< ");
             printf("%d\n", x2);
             pline();
             pbin(x1 << x2);
             break;
          case '~':
             pbin(x1);
             printf("~ (compliment)\n");
             pline();
             pbin(~x1);
             break;
          default:
             printf("\nNot valid operator.\n");
       }
    }
 }

 /* pbin */  /*prints number in hex and binary*/
 pbin(num)
 int num;
 {
 unsigned int mask;
 int j, bit;

    mask = 0x8000;                /*one-bit mask*/
    printf("%04x  ", num);        /*print in hex*/
    for(j = 0; j < 16; j++) {     /*for each bit in num*/
       bit = (mask & num) ? 1 : 0;   /*bit is 1 or 0*/
       printf("%d ", bit);
       if (j == 7)
          printf("-- ");
       mask >>= 1;             /*shift mask right by 1 bit*/
    }
    printf("\n");
 }

 /* pline */
 pline()
 {
    printf("----------------------------------------\n");
 }



 BITCOUNT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\BITCOUNT.C

 /* 1.0  07-06-84
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *
  *        This is the bitcount(n) function in Kernighan and Ritchie, on
  *        page 47.
  */

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/

 bitcount(n)                /* count number of 1-bits in n

 /*----------------------------------------------------------------------*/
 BITS n;
 {
         int b;

         for (b = 0; n ISNT 0; n >>= 1)
                 if (n & 01)
                         b++;
         return (b);
 }


 BITFIELD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BITFIELD.C

                                          /* Chapter 11 - Program 7 */
 main()
 {
 union {
    int index;
    struct {
       unsigned int x : 1;
       unsigned int y : 2;
       unsigned int z : 2;
    } bits;
 } number;

    for (number.index = 0;number.index < 20;number.index++) {
       printf("index = %3d, bits = %3d%3d%3d\n",number.index,
               number.bits.z,number.bits.y,number.bits.x);
    }
 }


 BITOPS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BITOPS.C

                                         /* Chapter 13 - Program 3 */
 main()
 {
 char mask;
 char number[6];
 char and,or,xor,inv,index;

    number[0] = 0X00;
    number[1] = 0X11;
    number[2] = 0X22;
    number[3] = 0X44;
    number[4] = 0X88;
    number[5] = 0XFF;

    printf(" nmbr  mask   and    or   xor   inv\n");
    mask = 0X0F;
    for (index = 0;index <= 5;index++) {
       and = mask & number[index];
       or = mask | number[index];
       xor = mask ^ number[index];
       inv = ~number[index];
       printf("%5x %5x %5x %5x %5x %5x\n",number[index],
               mask,and,or,xor,inv);
    }

    printf("\n");
    mask = 0X22;
    for (index = 0;index <= 5;index++) {
       and = mask & number[index];
       or = mask | number[index];
       xor = mask ^ number[index];
       inv = ~number[index];
       printf("%5x %5x %5x %5x %5x %5x\n",number[index],
               mask,and,or,xor,inv);
    }
 }


 BLKCMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\BLKCMP.C

 int blkcmp(blk1, blk2, len)
 register char *blk1;
 register char *blk2;
 register int len;
 /*
  *        Lexicographically compare the two blocks.  Return a value
  *        indicating the relationship between the blocks.  Possible
  *        return values are:
  *                negative        blk1 < blk2
  *                0                blk1 == blk2
  *                positive        blk1 > blk2
  *        <len> bytes are always compared.
  */
 {
         while((--len) && (*blk1 == *blk2)) {
                 ++blk1;
                 ++blk2;
         }
         return(*blk1 - *blk2);
 }


 BLKICMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\BLKICMP.C

 int blkicmp(blk1, blk2, len)
 register char *blk1;
 register char *blk2;
 register int len;
 /*
  *        Same as blkcmp() except the case of alphabetic characters is
  *        ignored during comparison.
  */
 {
         register char c1, c2;

         while(((c1 = tolower(*blk1++)) == (c2 = tolower(*blk2++))) && (--len)
                 ;
         return(c1 - c2);
 }


 BLKSIZ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\BLKSIZ.C

 /*
  *        Default _BLKSIZ variable declaration
  *
  *        NOTE:  (16 * _BLKSIZ) is the maximum amount of memory that can
  *        by managed by the dynamic memory management routines.
  */

 unsigned long _BLKSIZ = 65536;                /* Malloc() in 64K chunks */


 BORD2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\BORD2.C

 /*              Change Border Color from Keyboard

         This program changes the background color/attributes.
 */

 /*      main(argc,argv)

         Function: Watch the keyboard and change the border color of the
         display based on the current state of the shift, control and
         alt keys. Exit when any other key is pressed.

         Algorithm: Repeatedly call keyChk to see if something other than
         shift keys are pressed. If not, call keyShf to get the current
         state of the shift keys, and pass that on to setPal to actually
         set the color o the border.
 */

 main(argc,argv)

 int argc;
 char *argv[];

 {
         int key;

         /* Repeatedly call keyChk to see if anything non-shift was pressed. *
         while (!keyChk(&key))
                 /* If not, set the border to the current shift state. */
                 setPal(0,keyShf());
 }



 BORD3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\BORD3.C

 /*              Change Border Color from Keyboard

         This program changes the background color/attributes.
 */

 #define TRUE 1
 #define FALSE 0

 /*      main(argc,argv)

         Function: Watch the keyboard and change the attributes of each
         character on the display based on the current state of the shift,
         control and alt keys. The low four bits of the attributes are to
         be set to the current shift state; the upper four bits are set from
         the shift state when the space bar is pressed. Exit when any key
         other than the space bar is pressed.

         Algorithm: Repeatedly call keyChk to see if something other than
         shift keys are pressed. If not, call keyShf to get the current
         state of the shift keys; if they've changed, call getACh/putACh
         for each character on the display.
 */

 main(argc,argv)

 int argc;
 char *argv[];

 {
         int key;                        /* Key pressed. */
         char curAttr, lastAttr;         /* Current and last attribute. */
         char ch, attr;                  /* Char and attribute from display. *
         int i,j;                        /* Row and column indices. */

         /* Set the attribute to white on black. */
         lastAttr = 7;

         /* Repeatedly call keyChk to see if anything non-shift was pressed. *
         while (TRUE) {
                 /* Assume the top bits stay the same as they were. */
                 curAttr = lastAttr & 0xF0;
                 /* Check for a key press. */
                 if (keyChk(&key)) {
                         /* If yes, check for the space bar. */
                         if ((key & 0xFF) == ' ') {
                                 /* If yes, clear the key from the queue. */
                                 keyRd();
                                 /* Set the new top of the attribute. */
                                 curAttr = (keyShf() << 4) & 0xF0;
                         /* Otherwise, exit the loop. */
                         } else break;
                 };
                 curAttr |= keyShf() & 0xF;
                 /* If we've got a new attribute, set all the characters
                    to it. */
                 if (curAttr != lastAttr)
                         for (i = 0; i < 24; i++)
                                 for (j = 0; j < 79; j++) {
                                         /* Position the cursor. */
                                         setPos(0,i,j);
                                         /* Get the old character/attribute. *
                                         getACh(0,&ch,&attr);
                                         /* Put the new character/attribute. *
                                         putACh(0,ch,curAttr,1);
                                         /* Remember the new attribute. */
                                         lastAttr = curAttr;
                                 };
          };
 }



 BORDER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\BORDER.C

 /*                      Change Border Color

         This program changes the background color/attributes.
 */

 /*      main(argc,argv)

         Function: Change the color of the border of the display to that
         given as a command line parameter.

         Algorithm: Check the number of parameters. If there is one, then
         convert it to a number using atoi, and pass that to the setPal
         function to actually set the border color.

         Comments: This program will do nothing with a non-color display
         adapter.
 */

 main(argc,argv)

 int argc;
 char *argv[];

 {
         /* Check for the right number of parameters. */
         if (argc != 2) {
                 /* If wrong, tell the user and exit. */
                 puts("Usage: border <border color>");
                 exit(1);
         };

         /* Convert the parameter to a number and pass it to setPal. */
         setPal(0,atoi(argv[1]));
 }



 BOSSDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\WNDWBOSS\BOSSDEMO.C

 /*
 ** Demo for The Window Boss
 **
 ** Copyright (c) 1985 - Philip A. Mongelluzzo
 ** All rights reserved.
 **
 */

 "windows.h"                    /* windows header file */

 #if DLC
 int _stack = 8192;                      /* Datalight C */
 #endif

 TRUE 1                          /* a few equates */
 #define FALSE 0

   struct mitem {                        /* menu item template */
     int r;                              /* row */
     int c;                              /* col */
     char *t;                            /* text */
     int rv;                             /* return value */
   };

   struct pmenu {                        /* popup menu structure */
     int fm;                             /* first menu item index */
     int lm;                             /* last menu item index */
     struct mitem scrn[25];              /* a bunch of menu items */
   };

 main(argc,argv)
 int argc;
 char *argv[];
 {
 WINDOWPTR w0, w2, w3;                   /* a few windows */
 WINDOWPTR tw1, tw2, tw3;                /* and a few more */

 WINDOWPTR qpopup();                     /* function returns WP */
 int i,j,k;                              /* scratch integers */
 int watrib,batrib;                      /* scratch atributes */
 int rv;                                 /* for popup */

   static struct pmenu m1 = {
     00, 00, {
     01, 02, "Presenting", 0,
     00, 00, "",99 }
   };

   static struct pmenu m2 = {
     00, 00, {
     01, 02, "The", 0,
     03, 02, "W i n d o w   B O S S", 0,
     05, 02, "Fast - Easy - Windows", 0,
     07, 02, "for the C Language", 0,
     00, 00, "",99 }
   };

   static struct pmenu intelc = {
     02, 06, {
     01, 02, "         Intellicom", 0,
     02, 02, "        Quick - Help", 0,
     04, 05, "_ General Information", 1,
     05, 05, "_ Terminal Mode Options", 2,
     06, 05, "_ XMODEM File Send", 3,
     07, 05, "_ XMODEM File Receive", 4,
 #if MSC | DLC
      8, 05, "_ CompuServe Exec Mode", 5,
 #else
     08, 05, "_ CompuServe Exec Mode", 5,
 #endif
     10, 02, "Press: ESC to quit or Cursor", 0,
     11, 02, " Keys to Position Cursor then", 0,
     12, 02, " press RETURN for MORE info.", 0,
     00, 00, "",99 }
   };

   if(argc > 1) wn_dmaflg=FALSE;         /* for testing bios access */
   w0 = wn_save(0,0,0,78,23);            /* save entry screen */
   if(!w0) exit();                       /* less than graceful exit */

   batrib = v_setatr(WHITE,BLACK,0,BOLD);/* set border atrib */
   watrib = v_setatr(WHITE,RED,0,0);     /* make it american */
   w2 = qpopup(0,0,0,16,3,watrib,batrib,&m1);
   for(i=1; i<11; i++)                   /* move it into place */
     w2 = wn_move(w2, i, i*2);

   hiber(1);                             /* wait 1 second (aprx) */

   batrib = v_setatr(RED,WHITE,0,0);     /* set border atrib */
   watrib = v_setatr(BLUE,WHITE,0,0);    /* make this american too */
   w3 = qpopup(0,0,0,30,9,watrib,batrib,&m2);
   for(i=1; i<8; i++)                    /* move into place */
     w3 = wn_move(w3,i,6*i);             /* move into place */

   hiber(7);                             /* reading time.. */

   wn_close(w3);                         /* close a couple */
   hiber(1);
   wn_close(w2);
   hiber(1);

   watrib = v_setatr(WHITE,BLACK,0,BOLD);
   for(i=0; i<25; i++) {                 /* build the back drop */
     v_locate(0,i,0);                    /* position cursor */
     v_wca(0, 0xb0, watrib, 80);         /* the fast way */
   }
   v_hidec();                            /* hide the cursor */

   watrib = v_setatr(WHITE,BLACK,0,0);   /* window attribute */
   batrib = v_setatr(BLUE,WHITE,0,0);    /* border attribute */
   w3 = wn_open(0,2,9,60,19,watrib,batrib);
   w3->bstyle |= BOLD;                   /* toggle bold on then off */
   wn_title(w3," The Window BOSS for C ");
   w3->bstyle ^= BOLD;
   wn_puts(w3,1,1,"The Window BOSS puts YOU in control of the most important")
   wn_puts(w3,2,1,"sophisticated state-of-the-art screen handing techniques ")
   wn_puts(w3,3,1,"available today.  Pop-up windows, pull-down menus, status "
   wn_puts(w3,4,1,"lines and context sensitive help functions are a breeze ");
   wn_puts(w3,5,1,"to implement!  Your program automatically senses the ");
   wn_puts(w3,6,1,"video card installed and ALL your video output takes ");
   wn_puts(w3,7,1,"place with no snow, no flicker, and no delay. But best of")
   wn_puts(w3,8,1,"all, The Window BOSS is SHAREWARE software!  ");
   wn_puts(w3,9,1," ");
   wn_puts(w3,10,1,"The Window BOSS is available for the Lattice, Microsoft,
   wn_puts(w3,11,1,"Datalight, and Computer Innovations CI86 Compilers.");
   wn_puts(w3,12,1,"Registered users receive complete documentation, all");
   wn_puts(w3,13,1,"source code, and complete libaries for all memory models."
   wn_puts(w3,14,1," ");
   wn_puts(w3,15,1,"I challenge you to compare: The Window BOSS is faster");
   wn_puts(w3,16,1,"and easier to use, than most commercial products on the");
   wn_puts(w3,17,1,"market today!");
   hiber(30);

   watrib = v_setatr(WHITE,BLUE,0,0);    /* window attribute */
   batrib = v_setatr(RED,WHITE,0,BOLD);  /* border attribute */
   w2 = wn_open(0,5,5,50,10,watrib,batrib);
   if(!w2) exit();                       /* yes.. it should be better */
   wn_puts(w2,0,0," Simple text output is very fast");
   wn_puts(w2,1,0," and snow free.");
   wn_puts(w2,3,0," Watch this....");
   hiber(3);
   wn_clr(w2);                           /* clear it then fill it */
   for(i=0; i<10; i++)
     wn_puts(w2,i,0," Very fast screen output - no snow!");
   hiber(5);
   wn_clr(w2);                           /* do it again */
   for(i=0; i<10; i++)
     wn_puts(w2,i,0," Another window full of fast text.");
   hiber(5);

   wn_clr(w2);
   wn_printf(w2," The BOSS also supports a printf function!\n");
   wn_printf(w2," Its as simple as:\n\n");
   wn_printf(w2," \twn_printf(wn,\"%%d\\n\",i);\n\n");
   wn_printf(w2," to print a value in a window.\n\n");
   wn_printf(w2," Scrolling works too\n");
   wn_printf(w2," Lets count (slowly) to 10...\n");
   wn_sync(w2, TRUE);
   hiber(10);
   for(i=1;i<11;i++) {
     wn_printf(w2," The count is: %d\n", i);
     nap(5);
   }
   wn_printf(w2," Ok, lets see what it looks like at\n");
   wn_printf(w2," full speed.. (counting to 25)\n");
   hiber(5);
   for(i=1;i<26;i++)
     wn_printf(w2," The count is: %d\n", i);
   hiber(5);                             /* reading time */
   wn_sync(w2, FALSE);
   v_hidec();

   wn_clr(w2);
   wn_putsa(w2,0,0," Full color support is provided.",WHITE<<4);
   for(i=1; i<6; i++)
     wn_putsa(w2,i,0, " Add a little color to your life.",WHITE<<4|i);
   wn_putsa(w2,6,0," As is window movement....watch...",WHITE<<4|BLACK);
   hiber(5);

   for(i=0; i<13; i++)                   /* move the window around */
     w2 = wn_move(w2, i, i*2);
   hiber(5);
   wn_printf(w2,"\n Lets put it back where we started...\n");
   hiber(3);
   w2 = wn_move(w2,5,5);
   wn_printf(w2," Now, lets add a title to our window!\n");
   hiber(3);
   w2->bstyle |= BOLD;
   wn_title(w2," Pretty Powerful Stuff ");
   w2->bstyle ^= BOLD;
   hiber(5);

 /* ============================= Tiled Window Stuff ===================== */

   wn_printf(w2," Tiled windows are supported\n");
   wn_printf(w2," Lets add three.\n");
   hiber(5);

   wn_sbit=FAST;
   wn_blank=FALSE;
   tw1 = wn_open(0,3,5,40,10, RED<<4|YELLOW|BOLD, RED<<4|WHITE|BOLD);
   wn_sync(tw1,TRUE);
   wn_printf(tw1,"ONE\n");
   tw2 = wn_open(0,6,8,40,10, BLUE<<4|WHITE|BOLD, BLUE<<4|GREEN|BOLD);
   wn_sync(tw2,TRUE);
   wn_printf(tw2,"TWO\n");
   tw3 = wn_open(0,9,11,40,10,GREEN<<4|WHITE|BOLD, GREEN<<4|WHITE|BOLD);
   wn_sync(tw3,TRUE);
   wn_printf(tw3,"THREE\n");
   wn_printf(tw3," Press a key and watch TWO move\n");
   wn_printf(tw3," To the top!!\n");
   v_getch();

   wn_activate(tw2);
   wn_printf(tw2," Press a key and watch THREE move\n");
   wn_printf(tw2," To the top!!\n");
   v_getch();
   wn_activate(tw3);
   wn_printf(tw3," Press a key and watch ONE move\n");
   wn_printf(tw3," To the top!!\n");
   v_getch();
   wn_activate(tw1);

   wn_printf(tw1, " Ok..Press a key\n");
   wn_printf(tw1, " and we will continue with the show!");
   v_getch();

   wn_close(tw1);
   wn_close(tw3);
   wn_close(tw2);
   wn_sbit=SLOW;
   wn_blank=TRUE;

 /* ========================= End Tiled Stuff ============================ */

   wn_clr(w2);
   wn_printf(w2," Popup Menus are a breeze.\n\n");
   wn_printf(w2," Watch....");
   hiber(2);

   help_init("intelc");                  /* init help function */
   do {
     rv = popup(0,0,0,33,14, WHITE<<4|BLACK, BLUE<<4|WHITE, &intelc,FALSE);

     switch (rv) {                       /* dispatch */
       case 1:
         help("%general information\r\n");
         break;
       case 2:
         help("%terminal\r\n");
         break;
       case 3:
         help("%checksum xmit1\r\n");
         break;
       case 4:
         help("%checksum recv1\r\n");
         break;
       case 5:
         help("%cistty1\r\n");
         break;
       case 99:
       default:
         break;
     }
   } while(rv !=99);

   wn_clr(w2);                           /* clear the window */
   w2->bstyle |= BOLD;                   /* toggle bold on then off */
   wn_title(w2," The Window BOSS for C ");
   w2->bstyle ^= BOLD;
   wn_printf(w2,"\n\n  The following is a quick summary\n");
   wn_printf(w2,"  of SOME of the functions available...");
   hiber(4);

   help("%bossinfo\r\n");                /* provide some details */

   wn_clr(w2);                           /* and now the credits */
   wn_printf(w2,"\n\n\n");
   wn_printf(w2,"                  The Window BOSS\n");
   wn_printf(w2,"                Copyright (c) 1985\n");
   wn_printf(w2,"              Philip  A. Mongelluzzo\n");
   wn_printf(w2,"                 273 Windy Drive\n");
   wn_printf(w2,"              Waterbury, Conn  06705\n");

   wn_printf(w2,"\n\t\t\t\tThats all folks...\n\n");

   hiber(10);                            /* all done ! */
   wn_close(w2);
   wn_close(w3);
   wn_restore(w0);
 }

 nap(ticks)                              /* sleep a few clock ticks */
 int ticks;
 {
 int tc;
 int ts, te;

 CI86 | MSC | MWC                    /* MS , CI86, or MWC */
   ts = peek(0x6c,0x40);
   for(tc=0; tc<ticks; ) {
     if(chkesc()) return;
     te = peek(0x6c,0x40);
     if(ts == te) continue;
     tc++;
     ts = te;
   }
                                   /* lattice */
   peek(0x40, 0x6c, &ts, 2);
   for(tc=0; tc<ticks; ) {
     if(chkesc()) return;
     peek(0x40, 0x6c, &te, 2);
     if(ts == te) continue;
     tc++;
     ts = te;
   }
 #endif
 }

 hiber(seconds)
 int seconds;
 {
   nap(seconds * 18);
 }

 chkesc()                                /* check for ESC while napping */
 {
 int c;

   if(v_kstat()) {
     c=v_getch() & 0x7f;
     switch(c) {
       case ESC:
         return(TRUE);
       case ETX:
         v_cls(7);
         v_locate(0,0,0);
         exit(0);
       default:
         break;
     }
   }
   return(FALSE);
 }

 /* End */



 BPLUS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\BPLUS11\BPLUS.C

 /********************************************************************/
 /*                                                                  */
 /*             BPLUS file indexing program - Version 1.1            */
 /*                                                                  */
 /*                      A "shareware program"                       */
 /*                                                                  */
 /*                                                                  */
 /*                      Copyright (C) 1987 by                       */
 /*                                                                  */
 /*                      Hunter and Associates                       */
 /*                      7050 NW Zinfandel Lane                      */
 /*                      Corvallis, Oregon  97330                    */
 /*                      (503) 745 - 7186                            */
 /*                                                                  */
 /********************************************************************/


 #include <stdio.h>
 #include <fcntl.h>
 #include <io.h>
 <sys\types.h>            /*  delete this line for Turbo C  */
 #include <sys\stat.h>
 #include <string.h>
 #include "bplus.h"


 /*  macros, constants, data types  */

 #define  NULLREC      (-1L)
 #define  FREE_BLOCK   (-2)

 #define  ENT_ADR(pb,off)  ((ENTRY*)((char*)((pb)->entries) + off))
 #define  ENT_SIZE(pe)     strlen((pe)->key) + 1 + 2 * sizeof(RECPOS)
 #define  BUFDIRTY(j)      (mci->cache[j].dirty)
 #define  BUFHANDLE(j)     (mci->cache[j].handle)
 #define  BUFBLOCK(j)      (mci->cache[j].mb)
 #define  BUFCOUNT(j)      (mci->cache[j].count)
 #define  CB(j)            (pci->pos[j].cblock)
 #define  CO(j)            (pci->pos[j].coffset)


                     /*    ATTENTION MICROSOFT USERS   */
                     /* Microsoft changed the memcpy   */
                     /* library routine in the C 5.0   */
                     /* compiler.  The following macro */
                     /* must be used for Microsoft 5.0 */
                     /* and the Quick C compiler.      */

 /* #define memcpy            memmove */

 /*  declare some global variables  */

 IX_DESC      *pci;
 IX_BUFFER    bt_buffer;
 IX_BUFFER    *mci = &bt_buffer;
 BLOCK        *block_ptr;
 BLOCK        *spare_block;
 int          cache_ptr = 0;
 int          cache_init = 0;
 int          split_size = IXB_SPACE;
 int          comb_size  = (IXB_SPACE/2);

 void pascal error(int, long);
 void pascal read_if(long, char *, int);
 void pascal write_if(int, long, char *, int);
 int  pascal creat_if(char *);
 int  pascal open_if(char *);
 void pascal close_if(int);
 void pascal update_block(void);
 void pascal init_cache(void);
 int  pascal find_cache(RECPOS);
 int  pascal new_cache(void);
 void pascal load_cache(RECPOS);
 void pascal get_cache(RECPOS);
 void pascal retrieve_block(int, RECPOS);
 int  pascal prev_entry(int);
 int  pascal next_entry(int);
 int  pascal copy_entry(ENTRY *, ENTRY *);
 int  pascal scan_blk(int);
 int  pascal last_entry(void);
 int  pascal write_free( RECPOS, BLOCK *);
 RECPOS pascal get_free(void);
 int  pascal find_block(ENTRY *, int *);
 void pascal movedown(BLOCK *, int, int);
 void pascal moveup(BLOCK *, int, int);
 void pascal ins_block(BLOCK *, ENTRY *, int);
 void pascal del_block(BLOCK *, int);
 int  pascal split(int, ENTRY *, ENTRY *);
 void pascal ins_level(int, ENTRY *);
 int  pascal insert_ix(ENTRY *, IX_DESC *);
 int  pascal find_ix(ENTRY *, IX_DESC *, int);
 int  pascal combineblk(RECPOS, int);
 void pascal replace_entry(ENTRY *);
 void print_blk(BLOCK *);


 /*  file I/O for B-PLUS module  */

 void pascal error(j, l)
   int j;
   long l;
   {
     static char *msg[3] = {"ERROR - CANNOT OPEN/CLOSE FILE",
                            "ERROR WHILE READING FILE",
                            "ERROR WHILE WRITING FILE"};
     printf("\n  %s - Record Number %ld\n", msg[j], l);
     exit(1);
   } /* error */


 void pascal read_if(start, buf, nwrt)
   long start;
   char *buf;
   int nwrt;
   {
     long err;
     err = start - lseek(pci->ixfile, start, SEEK_SET);
     if (err == 0) err = nwrt - read(pci->ixfile, buf, nwrt);
     if (err != 0) error(1, start);
   } /* read_if */


 void pascal write_if(handle, start, buf, nwrt)
   int handle;
   long start;
   char *buf;
   int nwrt;
   {
     long err;
     err = start - lseek(handle, start, SEEK_SET);
     if (err == 0) err = nwrt - write(handle, buf, nwrt);
     if (err != 0) error(2, start);
   } /* write_if */


 int pascal creat_if(fn)
   char *fn;
   {
     int   ret;
     ret = open(fn,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE);
     if (ret  < 0) error(0,0L);
     return (ret);
   } /* creat_if */


 int pascal open_if(fn)
   char *fn;
   {
     int  ret;
     ret = open(fn,O_RDWR|O_BINARY);
     if (ret < 1) error(0,0L);
     return (ret);
   } /* open_if */


 void pascal close_if(handle)
   int handle;
   {
     if(close(handle) < 0)  error(2,0L);
   } /*  close_if */


 int cdecl open_index(name, pix, dup)
   char *name;
   IX_DESC *pix;
   int dup;
   {
     pci = pix;
     pci->ixfile = open_if(name);
     pci->duplicate = dup;
     read_if(0L,(char *)&(pix->root), (sizeof(BLOCK) + sizeof(IX_DISK)));
     if (!cache_init)
       {
         init_cache();
         cache_init = 1;
       }
     first_key(pix);
     return ( IX_OK );
   } /* open_index */


 int cdecl close_index(pix)
   IX_DESC *pix;
   {
     int i;
     write_if(pix->ixfile, 0L,(char *)&(pix->root),
                (sizeof(BLOCK) + sizeof(IX_DISK)));
     for (i = 0; i < NUM_BUFS; i++)
       if (BUFHANDLE(i) == pix->ixfile)
         {
           if (BUFDIRTY(i))
             {
               write_if(BUFHANDLE(i),
                        BUFBLOCK(i).brec,
                        (char *) &BUFBLOCK(i),
                        sizeof(BLOCK));
               BUFDIRTY(i) = 0;
             }
           BUFBLOCK(i).brec = NULLREC;
       }
     close_if(pix->ixfile);
     return( IX_OK );
   } /* close_index */


 int cdecl make_index(name, pix, dup)
   char *name;
   IX_DESC *pix;
   int dup;
   {
     pci = pix;
     pci->ixfile = creat_if(name);
     pci->duplicate = dup;
     pci->dx.nl = 1;
     pci->dx.ff = NULLREC;
     pci->level = 0;
     CO(0) = -1;
     CB(0) = 0L;
     pci->root.brec = 0L;
     pci->root.bend = 0;
     pci->root.p0 = NULLREC;
     write_if(pci->ixfile, 0L,(char *)&(pix->root),
                (sizeof(BLOCK) + sizeof(IX_DISK)));
     if (!cache_init)
       {
         init_cache();
         cache_init = 1;
       }
     first_key(pix);
     return ( IX_OK );
   } /* make_index */


 /*  cache I/O for BPLUS  */

 void pascal update_block()
   {
     if (block_ptr != &(pci->root))
        BUFDIRTY(cache_ptr) = 1;
   } /* update_block */


 void pascal init_cache()
   {
     register int  j;
     for (j = 0; j < NUM_BUFS; j++)
       {  BUFDIRTY(j) = 0;
          BUFCOUNT(j) = 0;
          BUFBLOCK(j).brec = NULLREC;
       }
   } /* init_cache */


 int pascal find_cache(r)
   RECPOS r;
   {
     register int  j;
     for (j = 0; j < NUM_BUFS; j++)
       {
         if((BUFBLOCK(j).brec == r) && (BUFHANDLE(j) == pci->ixfile))
          {  cache_ptr = j;
             return (1);
       }  }
     return (-1);
   } /* find_cache */


 int pascal new_cache()
   {
     register int  i;
     i = (cache_ptr + 1) % NUM_BUFS;
     if (BUFDIRTY(i)) write_if(BUFHANDLE(i),
                               BUFBLOCK(i).brec,
                               (char *) &BUFBLOCK(i),
                               sizeof(BLOCK));
     BUFHANDLE(i) = pci->ixfile;
     BUFDIRTY(i) = 0;
     return (i);
   } /* new_cache */


 void pascal load_cache(r)
   RECPOS r;
   {
     cache_ptr = new_cache();
     read_if(r, (char *)&BUFBLOCK(cache_ptr), sizeof(BLOCK));
   } /* load_cache */


 void pascal get_cache(r)
   RECPOS r;
   {
     if (find_cache(r) < 0)
        load_cache(r);
     block_ptr = &BUFBLOCK(cache_ptr);
   } /* get_cache */


 void pascal retrieve_block(j, r)
   int j;
   RECPOS r;
   {
     if (j == 0)
        block_ptr = &(pci->root);
     else  get_cache(r);
     CB(j) = block_ptr->brec;
   } /* retrieve_block */


 /*  low level functions of BPLUS  */

 int pascal prev_entry(off)
   int off;
   {
      if (off <= 0)
        {
          off = -1;
          CO(pci->level) = off;
        }
      else
        off = scan_blk(off);
      return(off);
   } /* prev_entry */


 int pascal next_entry(off)
   int off;
   {
      if (off == -1)
        off = 0;
      else
        {
          if (off < block_ptr->bend)
             off += ENT_SIZE(ENT_ADR(block_ptr,off));
        }
      CO(pci->level) = off;
      return (off);
   } /* next_entry */


 int pascal copy_entry(to, from)
   ENTRY *to;
   ENTRY *from;
   {
     int me;
     me = ENT_SIZE(from);
     memcpy(to, from, me);
   } /* copy_entry */


 int pascal scan_blk(n)
   int n;
   {
      register int off, last;
      off = 0;
      last = -1;
      while (off < n )
        {  last = off;
           off += ENT_SIZE(ENT_ADR(block_ptr,off));
        }
      CO(pci->level) = last;
      return (last);
   } /* scan_blk */


 int pascal last_entry()
   {
      return( scan_blk(block_ptr->bend) );
   } /* last_entry */


 /*  maintain list of free index blocks  */

 int pascal write_free(r, pb)
   RECPOS r;
   BLOCK *pb;
   {
     pb->p0 = FREE_BLOCK;
     pb->brec = pci->dx.ff;
     write_if(pci->ixfile, r, (char *) pb, sizeof(BLOCK));
     pci->dx.ff = r;
   } /* write_free */


 RECPOS pascal get_free()
   {
     RECPOS  r, rt;

     r = pci->dx.ff;
     if ( r != NULLREC )
       {  read_if(r, (char *)&rt, sizeof( RECPOS ));
          pci->dx.ff = rt;
       }
     else
       r = filelength (pci->ixfile);
     return (r);
   } /* get_free */


 /*  general BPLUS block level functions  */

 int pascal find_block(pe, poff)
   ENTRY *pe;
   int *poff;
   {
     register int pos, nextpos, ret;
     pos = -1;
     nextpos = 0;
     ret = 1;
     while ( nextpos < block_ptr->bend)
       {
         ret = strcmp((char *)(pe->key),
                      (char *)(ENT_ADR(block_ptr, nextpos)->key));
         if (ret <= 0)
           {
              if (ret == 0) pos = nextpos;
              break;
           }
         pos = nextpos;
         nextpos = next_entry(pos);
       }
     CO(pci->level) = pos;
     *poff = pos;
     return (ret);
   } /* find_block */


 void pascal movedown(pb, off, n)
   BLOCK *pb;
   int off;
   int n;
   {
     memcpy(ENT_ADR(pb, off),
            ENT_ADR(pb, off + n),
            pb -> bend - (off + n));
   } /* movedown */


 void pascal moveup(pb, off, n)
   BLOCK *pb;
   int off;
   int n;
   {
     memcpy(ENT_ADR(pb, off + n),
             ENT_ADR(pb, off),
             pb->bend - off);
   } /* moveup */


 void pascal ins_block(pb, pe, off)
   BLOCK *pb;
   ENTRY *pe;
   int off;
   {
     int size;
     size = ENT_SIZE(pe);
     moveup(pb,off,size);
     copy_entry(ENT_ADR(pb,off),pe);
     pb->bend += size;
   } /* ins_block */


 void pascal del_block(pb, off)
   BLOCK *pb;
   int off;
   {
     int ne;
     ne = ENT_SIZE(ENT_ADR(pb, off));
     movedown(pb, off, ne);
     pb->bend -= ne;
   } /* del_block */


 /*  position at start/end of index  */

 int cdecl first_key(pix)
   IX_DESC *pix;
   {
     pci = pix;
     block_ptr = &(pci->root);
     CB(0) = 0L;
     CO(0) = -1;
     pci->level = 0;
     while(block_ptr->p0 != NULLREC)
       {
         retrieve_block(++(pci->level), block_ptr->p0);
         CO(pci->level) = -1;
       }
     return ( IX_OK );
   } /* first_key */


 int cdecl last_key(pix)
   IX_DESC *pix;
   {
     long  ads;
     pci = pix;
     block_ptr = &(pci->root);
     CB(0) = 0L;
     pci->level = 0;
     if(last_entry() >= 0)
       {
         while ((ads = ENT_ADR(block_ptr,last_entry())->idxptr) != NULLREC)
              retrieve_block(++(pci->level), ads);
       }
     CO(pci->level) = block_ptr->bend;
     return ( IX_OK );
   } /* last_key */


 /*  get next, previous entries  */

 int cdecl next_key(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
     RECPOS  address;
     pci = pix;
     retrieve_block(pci->level, CB(pci->level));
     if(CO(pci->level) == -1) address = block_ptr->p0;
     else
      {
        if (CO(pci->level) == block_ptr->bend) address = NULLREC;
        else  address = ENT_ADR(block_ptr, CO(pci->level))->idxptr;
      }
     while (address != NULLREC)
       {
          retrieve_block(++(pci->level), address);
          CO(pci->level) = -1;
          address = block_ptr->p0;
       }
     next_entry(CO(pci->level));
     if (CO(pci->level) == block_ptr->bend)
       {
         do
           { if(pci->level == 0)
               {
                 last_key(pci);
                 return (EOIX);
               }
             --(pci->level);
             retrieve_block(pci->level, CB(pci->level));
             next_entry(CO(pci->level));
           } while (CO(pci->level) == block_ptr->bend);
       }
     copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level)));
     return ( IX_OK );
   } /* next_key */


 int cdecl prev_key(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
     RECPOS  address;
     pci = pix;
     retrieve_block(pci->level, CB(pci->level));
     prev_entry(CO(pci->level));
     if (CO(pci->level) == -1)
       address = block_ptr->p0;
     else
       address = ENT_ADR(block_ptr, CO(pci->level))->idxptr;
     if (address != NULLREC)
       { do
           {
             retrieve_block(++(pci->level), address);
             address = ENT_ADR(block_ptr, last_entry())->idxptr;
           } while (address != NULLREC);
       }
     if (CO(pci->level) == -1)
       { do
           {
             if(pci->level == 0)
               {
                 first_key(pci);
                 return (EOIX);
               }
             --(pci->level);
           } while (CO(pci->level) == -1);
         retrieve_block(pci->level, CB(pci->level));
       }
     copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level)));
     return ( IX_OK );
   } /* prev_key */


 /*  insert new entries into tree  */

 int pascal split(l, pe, e)
   int l;
   ENTRY *pe;
   ENTRY *e;
   {
     int  half, ins_pos, size;
     ins_pos = CO(pci->level);
     half = scan_blk(block_ptr->bend / 2 + sizeof(RECPOS));
     if (half == ins_pos)
       *e = *pe;
     else
       {
          copy_entry(e, ENT_ADR(block_ptr, half));
          size = ENT_SIZE(e);
          movedown(block_ptr, half, size);
          block_ptr->bend -= size;
       }
     spare_block = &BUFBLOCK(new_cache());
     memcpy(spare_block->entries,
            ENT_ADR(block_ptr,half),
            block_ptr->bend - half);
     spare_block->brec = get_free();
     spare_block->bend = block_ptr->bend - half;
     spare_block->p0 = e->idxptr;
     block_ptr->bend = half;
     e->idxptr = spare_block->brec;
     if (ins_pos < half)
       ins_block(block_ptr,pe,ins_pos);
     else if (ins_pos > half)
       {
          ins_pos -= ENT_SIZE(e);
          ins_block(spare_block,pe,ins_pos - half);
          CB(l) = e->idxptr;
          CO(l) = CO(l) - half;
       }
     write_if(pci->ixfile, spare_block->brec,
              (char *) spare_block, sizeof(BLOCK));
   } /* split */


 void pascal ins_level(l, e)
   int l;
   ENTRY *e;
   {
     int  i;
     if ( l < 0)
       {  for (i = 1; i < MAX_LEVELS; i++)
            {  CO(MAX_LEVELS - i) = CO(MAX_LEVELS - i - 1);
               CB(MAX_LEVELS - i) = CB(MAX_LEVELS - i - 1);
            }
          memcpy(spare_block, &(pci->root), sizeof(BLOCK));
          spare_block->brec = get_free();
          write_if(pci->ixfile, spare_block->brec,
                   (char *) spare_block, sizeof(BLOCK));
          pci->root.p0 = spare_block->brec;
          copy_entry((ENTRY *) (pci->root.entries), e);
          pci->root.bend = ENT_SIZE(e);
          CO(0) = 0;
          pci->level = 0;
          (pci->dx.nl)++;
       }
     else ins_block(block_ptr,e,CO(l));
   } /* ins_level */


 int pascal insert_ix(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
     ENTRY    e, ee;
     int h;
     h = 0;
     pci = pix;
     ee = *pe;
     do
       {
          if(CO(pci->level) >= 0)
            CO(pci->level) +=
                   ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level)));
          else
            CO(pci->level) = 0;
          update_block();
          if( (block_ptr->bend + ENT_SIZE(&ee)) <= split_size)
            {
              ins_level(pci->level, &ee);
              break;
            }
          else
            {
              h = 1;
              split(pci->level,&ee, &e);
               ee = e;
               pci->level--;
               if (pci->level < 0)
                 {
                   ins_level(pci->level, &e);
                   break;
                 }
               retrieve_block(pci->level, CB(pci->level));
            }
       }
     while (1);
     if (h) find_ix(pe, pix, 0);
     return ( IX_OK );
   } /* insert_ix */


 /*  BPLUS find and add key functions  */

 int pascal find_ix(pe, pix, find)
   ENTRY *pe;
   IX_DESC *pix;
   int find;
   {
     int      level, off, ret;
     RECPOS   ads;
     ENTRY    found;
     pci = pix;
     ads = 0L;
     level = ret = 0;
     while (ads != NULLREC)
       {  pci->level = level;
          retrieve_block(level, ads);
          if (find_block(pe, &off) == 0) ret = 1;
          if (ret && find) break;
          if (off == -1)
            ads = block_ptr->p0;
          else
            ads = ENT_ADR(block_ptr, off)->idxptr;
          CO(level++) = off;
        }
      return ( ret );
    } /* find_ix */


 int cdecl find_key(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
     int ret;
     ret = find_ix(pe, pix, 1);
     if ( ret ) copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level)));
     return ( ret );
   } /* find_key */


 int cdecl add_key(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
     int ret;
     ret = find_ix(pe, pix, 0);
     if ( ret && (pci->duplicate == 0)) return ( IX_FAIL );
     pe->idxptr = NULLREC;
     return (insert_ix(pe, pix));
   } /* add_key */


 int cdecl locate_key(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
     int ret;
     ENTRY e;
     ret = find_ix(pe, pix, 1);
     if (ret) copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level)));
     else if (next_key(pe,pix) == EOIX) ret = EOIX;
     return ( ret );
   } /* locate_key */


 int cdecl find_exact(pe, pix)
   ENTRY *pe;
   IX_DESC * pix;
   {
     int  ret;
     ENTRY e;
     copy_entry(&e, pe);
     ret = find_key(&e, pix);
     if ( ret && pci->duplicate)
       {
         do
           {
             ret = (e.recptr == pe->recptr);
             if( !ret )  ret = next_key(&e, pci);
             if (ret) ret = (strcmp(e.key, pe->key) == 0);
             if ( !ret ) return ( 0 );
           } while ( !ret );
       }
     copy_entry(pe, &e);
     return ( ret );
   } /* find_exact */


 /* BPLUS delete key functions */

 int cdecl delete_key(pe, pix)
   ENTRY *pe;
   IX_DESC *pix;
   {
      ENTRY   e;
      RECPOS  ads;
      int     h, leveli, levelf;
      if (!find_exact(pe, pix))  return( IX_FAIL );
      h = 1;
      if ((ads = pe->idxptr) != NULLREC)
        {
           leveli = pci->level;
           do
             {
                retrieve_block(++(pci->level), ads);
                CO(pci->level) = -1;
             }
           while ((ads = block_ptr->p0) != NULLREC);
           CO(pci->level) = 0;
           copy_entry(&e, ENT_ADR(block_ptr, CO(pci->level)));
           levelf = pci->level;
           pci->level = leveli;
           replace_entry(&e);
           pci->level = levelf;
        }
      while ( h )
        {
           retrieve_block(pci->level, CB(pci->level));
           del_block(block_ptr, CO(pci->level));
           update_block();
           if ( (pci->level == 0) && (block_ptr->bend == 0))
           /* tree was reduced in height */
             {
               if (pci->root.p0 != NULLREC)
                 {
                   retrieve_block(++pci->level, pci->root.p0);
                   memcpy(&(pci->root), block_ptr, sizeof(BLOCK));
                   (pci->dx.nl)--;
                   write_free(block_ptr->brec, block_ptr);
                   BUFDIRTY(cache_ptr) = 0;
                   BUFHANDLE(cache_ptr) = 0;
                 }
               break;
             }
           h = (block_ptr->bend < comb_size) && (pci->level > 0);
           if ( h )
               h = combineblk(CB(pci->level), block_ptr->bend);
        }
     find_ix(pe,pix,0);
     return( IX_OK );
   } /* delete_key */


 int pascal combineblk(ads, size)
   RECPOS ads;
   int size;
   {
     ENTRY  e;
     RECPOS address;
     int    esize, off, ret, saveoff, ibuff;
     ret = 0;
     saveoff = CO(--(pci->level));
     retrieve_block(pci->level, CB(pci->level));
     if ((off = next_entry( saveoff )) < block_ptr->bend)
       /* combine with page on right */
       {
         if ( (ENT_SIZE(ENT_ADR(block_ptr, off)) + size) < split_size)
           {
             copy_entry(&e, ENT_ADR(block_ptr, off));
             address = ENT_ADR(block_ptr, CO(pci->level))->idxptr;
             retrieve_block(++pci->level, address);
             ibuff = cache_ptr;
             spare_block = block_ptr;
             retrieve_block(pci->level, ads);
             esize = ENT_SIZE(&e);
             if(((block_ptr->bend + spare_block->bend + esize) >= split_size)
                  && (spare_block->bend <= block_ptr->bend + esize))
                return( ret );
             e.idxptr = spare_block->p0;
             ins_block(block_ptr, &e, block_ptr->bend);
             update_block();
             if ((block_ptr->bend + spare_block->bend) < split_size)
             /* combine the blocks */
               {
                 memcpy(ENT_ADR(block_ptr, block_ptr->bend),
                        ENT_ADR(spare_block, 0),
                        spare_block->bend);
                 block_ptr->bend += spare_block->bend;
                 write_free(spare_block->brec, spare_block);
                 BUFDIRTY(ibuff) = 0;
                 BUFHANDLE(ibuff) = 0;
                 --pci->level;
                 ret = 1;
               }
             else
             /* move an entry up to replace the one moved */
               {
                 copy_entry(&e, ENT_ADR(spare_block, 0));
                 esize = ENT_SIZE(&e);
                 movedown(spare_block, 0, esize);
                 spare_block->bend -= esize;
                 spare_block->p0 = e.idxptr;
                 BUFDIRTY(ibuff) = 1;
                 --(pci->level);
                 replace_entry(&e);
               }
           }
       }
     else
       /* move from page on left */
       {
         if ( (ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level))) + size)
                  < split_size)
           {
             copy_entry(&e, ENT_ADR(block_ptr, saveoff));
             off = prev_entry(saveoff);
             if (CO(pci->level) == -1) address = block_ptr->p0;
             else address = ENT_ADR(block_ptr, CO(pci->level))->idxptr;
             retrieve_block(++pci->level, address);
             off = last_entry();
             ibuff = cache_ptr;
             spare_block = block_ptr;
             retrieve_block(pci->level, ads);
             esize = ENT_SIZE(&e);
             if(((block_ptr->bend + spare_block->bend + esize) >= split_size)
                  && (spare_block->bend <= block_ptr->bend + esize))
                return( ret );
             BUFDIRTY(ibuff) = 1;
             CO(pci->level) = 0;
             e.idxptr = block_ptr->p0;
             ins_block(block_ptr, &e, 0);
             if ((block_ptr->bend + spare_block->bend) < split_size)
             /* combine the blocks */
               {
                 memcpy(ENT_ADR(spare_block, spare_block->bend),
                        ENT_ADR(block_ptr, 0),
                        block_ptr->bend);
                 spare_block->bend += block_ptr->bend;
                 write_free(block_ptr->brec, block_ptr);
                 BUFDIRTY(cache_ptr) = 0;
                 BUFHANDLE(cache_ptr) = 0;
                 CO(--(pci->level)) = saveoff;
                 ret = 1;
               }
             else
             /* move an entry up to replace the one moved */
               {
                  block_ptr->p0 = ENT_ADR(spare_block,off)->idxptr;
                  copy_entry(&e, ENT_ADR(spare_block, off));
                  spare_block->bend = off;
                  update_block();
                  CO(--(pci->level)) = saveoff;
                  replace_entry(&e);
               }
           }
       }
     return ( ret );
   } /* combineblk */


 void pascal replace_entry(pe)
   ENTRY *pe;
   {
     retrieve_block(pci->level, CB(pci->level));
     pe->idxptr = ENT_ADR(block_ptr, CO(pci->level))->idxptr;
     del_block(block_ptr, CO(pci->level));
     prev_entry(CO(pci->level));
     insert_ix(pe, pci);
   } /* replace_entry */



 BREAKCON.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\BREAKCON.C

                                           /* Chapter 3 - Program 5 */
 main()
 {
 int xx;

    for(xx = 5;xx < 15;xx = xx + 1){
       if (xx == 8)
          break;
       printf("In the break loop, xx is now %d\n",xx);
    }

    for(xx = 5;xx < 15;xx = xx + 1){
       if (xx == 8)
          continue;
       printf("In the continue loop, xx is now %d\n",xx);
    }
 }


 BSEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\BSEARCH.C

 #include <stdio.h>

 int        _bsearch;        /* index of element found, or where to insert */

 char *bsearch(key, base, num, size, cmp)
 register char *key;                /* item to search for */
 register char *base;                /* base address */
 int num;                        /* number of elements */
 register int size;                /* element size in bytes */
 register int (*cmp)();                /* comparison function */
 /*
  *        Perform a binary search for <key> on the sorted data at <base>.
  *        <num>, <size> and <cmp> are like the corresponding parameters
  *        to qsort().  A pointer to the matching element is returned for
  *        success, or NULL for failure.  The global variable "_bsearch"
  *        will contain the index of either the matching element, or the
  *        place where <key> value should be inserted.  The use of "_bsearch"
  *        is not supported by many implementations of bsearch().
  */
 {
         register int a, b, c, dir;

         a = 0;
         b = num - 1;
         while(a <= b) {
                 c = (a + b) >> 1;        /* == ((a + b) / 2) */
                 if (dir = (*cmp)((base + (c * size)), key)) {
                         if (dir > 0)
                                 b = c - 1;
                         else /* (dir < 0) */
                                 a = c + 1;
                 }
                 else {
                         _bsearch = c;
                         return(base + (c * size));
                 }
         }
         _bsearch = b;
         return(NULL);
 }


 BUFFER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\BUFFER.C

 /*
  * Buffer management.
  * Some of the functions are internal,
  * and some are actually attached to user
  * keys. Like everyone else, they set hints
  * for the display system.
  */
 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 /*
  * Attach a buffer to a window. The
  * values of dot and mark come from the buffer
  * if the use count is 0. Otherwise, they come
  * from some other window.
  */
 usebuffer(f, n)
 {
         register BUFFER *bp;
         register int    s;
         char            bufn[NBUFN];

         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
                 return (s);
         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
                 return (FALSE);
         return(swbuffer(bp));
 }

 nextbuffer(f, n)        /* switch to the next buffer in the buffer list */

 int f, n;        /* default flag, numeric argument */
 {
         register BUFFER *bp;        /* eligable buffer to switch to*/
         register BUFFER *bbp;        /* eligable buffer to switch to*/

         /* make sure the arg is legit */
         if (f == FALSE)
                 n = 1;
         if (n < 1)
                 return(FALSE);

         bbp = curbp;
         while (n-- > 0) {
                 /* advance to the next buffer */
                 bp = bbp->b_bufp;

                 /* cycle through the buffers to find an eligable one */
                 while (bp == NULL || bp->b_flag & BFINVS) {
                         if (bp == NULL)
                                 bp = bheadp;
                         else
                                 bp = bp->b_bufp;

                         /* don't get caught in an infinite loop! */
                         if (bp == bbp)
                                 return(FALSE);

                 }

                 bbp = bp;
         }

         return(swbuffer(bp));
 }

 swbuffer(bp)        /* make buffer BP current */

 BUFFER *bp;

 {
         register WINDOW *wp;

         if (--curbp->b_nwnd == 0) {             /* Last use.            */
                 curbp->b_dotp  = curwp->w_dotp;
                 curbp->b_doto  = curwp->w_doto;
                 curbp->b_markp = curwp->w_markp;
                 curbp->b_marko = curwp->w_marko;
         }
         curbp = bp;                             /* Switch.              */
         if (curbp->b_active != TRUE) {                /* buffer not active ye
                 /* read it in and activate it */
                 readin(curbp->b_fname, TRUE);
                 curbp->b_dotp = lforw(curbp->b_linep);
                 curbp->b_doto = 0;
                 curbp->b_active = TRUE;
         }
         curwp->w_bufp  = bp;
         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
         if (bp->b_nwnd++ == 0) {                /* First use.           */
                 curwp->w_dotp  = bp->b_dotp;
                 curwp->w_doto  = bp->b_doto;
                 curwp->w_markp = bp->b_markp;
                 curwp->w_marko = bp->b_marko;
                 return (TRUE);
         }
         wp = wheadp;                            /* Look for old.        */
         while (wp != NULL) {
                 if (wp!=curwp && wp->w_bufp==bp) {
                         curwp->w_dotp  = wp->w_dotp;
                         curwp->w_doto  = wp->w_doto;
                         curwp->w_markp = wp->w_markp;
                         curwp->w_marko = wp->w_marko;
                         break;
                 }
                 wp = wp->w_wndp;
         }
         return (TRUE);
 }

 /*
  * Dispose of a buffer, by name.
  * Ask for the name. Look it up (don't get too
  * upset if it isn't there at all!). Get quite upset
  * if the buffer is being displayed. Clear the buffer (ask
  * if the buffer has been changed). Then free the header
  * line and the buffer header. Bound to "C-X K".
  */
 killbuffer(f, n)

 {
         register BUFFER *bp;
         register int    s;
         char bufn[NBUFN];

         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
                 return(s);
         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
                 return (TRUE);
         if(bp->b_flag & BFINVS)                /* Deal with special buffers
                         return (TRUE);                /* by doing nothing.
         return(zotbuf(bp));
 }

 zotbuf(bp)        /* kill the buffer pointed to by bp */

 register BUFFER *bp;

 {
         register BUFFER *bp1;
         register BUFFER *bp2;
         register int    s;

         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
                 mlwrite("Buffer is being displayed");
                 return (FALSE);
         }
         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
                 return (s);
         free((char *) bp->b_linep);             /* Release header line. */
         bp1 = NULL;                             /* Find the header.     */
         bp2 = bheadp;
         while (bp2 != bp) {
                 bp1 = bp2;
                 bp2 = bp2->b_bufp;
         }
         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
         if (bp1 == NULL)                        /* Unlink it.           */
                 bheadp = bp2;
         else
                 bp1->b_bufp = bp2;
         free((char *) bp);                      /* Release buffer block */
         return (TRUE);
 }

 namebuffer(f,n)                /*        Rename the current buffer        */

 int f, n;                /* default Flag & Numeric arg */

 {
         register BUFFER *bp;        /* pointer to scan through all buffers */
         char bufn[NBUFN];        /* buffer to hold buffer name */

         /* prompt for and get the new buffer name */
 ask:        if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
                 return(FALSE);

         /* and check for duplicates */
         bp = bheadp;
         while (bp != NULL) {
                 if (bp != curbp) {
                         /* if the names the same */
                         if (strcmp(bufn, bp->b_bname) == 0)
                                 goto ask;  /* try again */
                 }
                 bp = bp->b_bufp;        /* onward */
         }

         strcpy(curbp->b_bname, bufn);        /* copy buffer name to structure
         curwp->w_flag |= WFMODE;        /* make mode line replot */
         mlerase();
         return(TRUE);
 }

 /*
         List all of the active buffers.  First update the special
         buffer that holds the list.  Next make sure at least 1
         window is displaying the buffer list, splitting the screen
         if this is what it takes.  Lastly, repaint all of the
         windows that are displaying the list.  Bound to "C-X C-B".
         A numeric argument forces it to list invisable buffers as
         well.
 */

 listbuffers(f, n)
 {
         register WINDOW *wp;
         register BUFFER *bp;
         register int    s;

         if ((s=makelist(f)) != TRUE)
                 return (s);
         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
                 if ((wp=wpopup()) == NULL)
                         return (FALSE);
                 bp = wp->w_bufp;
                 if (--bp->b_nwnd == 0) {
                         bp->b_dotp  = wp->w_dotp;
                         bp->b_doto  = wp->w_doto;
                         bp->b_markp = wp->w_markp;
                         bp->b_marko = wp->w_marko;
                 }
                 wp->w_bufp  = blistp;
                 ++blistp->b_nwnd;
         }
         wp = wheadp;
         while (wp != NULL) {
                 if (wp->w_bufp == blistp) {
                         wp->w_linep = lforw(blistp->b_linep);
                         wp->w_dotp  = lforw(blistp->b_linep);
                         wp->w_doto  = 0;
                         wp->w_markp = NULL;
                         wp->w_marko = 0;
                         wp->w_flag |= WFMODE|WFHARD;
                 }
                 wp = wp->w_wndp;
         }
         return (TRUE);
 }

 /*
  * This routine rebuilds the
  * text in the special secret buffer
  * that holds the buffer list. It is called
  * by the list buffers command. Return TRUE
  * if everything works. Return FALSE if there
  * is an error (if there is no memory). Iflag
  * indecates weather to list hidden buffers.
  */
 makelist(iflag)

 int iflag;        /* list hidden buffer flag */

 {
         register char   *cp1;
         register char   *cp2;
         register int    c;
         register BUFFER *bp;
         register LINE   *lp;
         register int    s;
         register int        i;
         long nbytes;                /* # of bytes in current buffer */
         char b[7+1];
         char line[128];

         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
                 return (s);
         strcpy(blistp->b_fname, "");
         if (addline("AC MODES        Size Buffer        File") == FALSE
         ||  addline("-- -----        ---- ------        ----") == FALSE)
                 return (FALSE);
         bp = bheadp;                            /* For all buffers      */

         /* build line to report global mode settings */
         cp1 = &line[0];
         *cp1++ = ' ';
         *cp1++ = ' ';
         *cp1++ = ' ';

         /* output the mode codes */
         for (i = 0; i < NUMMODES; i++)
                 if (gmode & (1 << i))
                         *cp1++ = modecode[i];
                 else
                         *cp1++ = '.';
         strcpy(cp1, "         Global Modes");
         if (addline(line) == FALSE)
                 return(FALSE);

         /* output the list of buffers */
         while (bp != NULL) {
                 /* skip invisable buffers if iflag is false */
                 if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
                         bp = bp->b_bufp;
                         continue;
                 }
                 cp1 = &line[0];                 /* Start at left edge   */

                 /* output status of ACTIVE flag (has the file been read in? *
                 if (bp->b_active == TRUE)    /* "@" if activated       */
                         *cp1++ = '@';
                 else
                         *cp1++ = ' ';

                 /* output status of changed flag */
                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
                         *cp1++ = '*';
                 else
                         *cp1++ = ' ';
                 *cp1++ = ' ';                   /* Gap.                 */

                 /* output the mode codes */
                 for (i = 0; i < NUMMODES; i++) {
                         if (bp->b_mode & (1 << i))
                                 *cp1++ = modecode[i];
                         else
                                 *cp1++ = '.';
                 }
                 *cp1++ = ' ';                   /* Gap.                 */
                 nbytes = 0L;                    /* Count bytes in buf.  */
                 lp = lforw(bp->b_linep);
                 while (lp != bp->b_linep) {
                         nbytes += (long)llength(lp)+1L;
                         lp = lforw(lp);
                 }
                 ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
                 cp2 = &b[0];
                 while ((c = *cp2++) != 0)
                         *cp1++ = c;
                 *cp1++ = ' ';                   /* Gap.                 */
                 cp2 = &bp->b_bname[0];          /* Buffer name          */
                 while ((c = *cp2++) != 0)
                         *cp1++ = c;
                 cp2 = &bp->b_fname[0];          /* File name            */
                 if (*cp2 != 0) {
                         while (cp1 < &line[2+1+5+1+6+1+NBUFN])
                                 *cp1++ = ' ';
                         while ((c = *cp2++) != 0) {
                                 if (cp1 < &line[128-1])
                                         *cp1++ = c;
                         }
                 }
                 *cp1 = 0;                       /* Add to the buffer.   */
                 if (addline(line) == FALSE)
                         return (FALSE);
                 bp = bp->b_bufp;
         }
         return (TRUE);                          /* All done             */
 }

 ltoa(buf, width, num)

 char   buf[];
 int    width;
 long   num;

 {
         buf[width] = 0;                         /* End of string.       */
         while (num >= 10) {                     /* Conditional digits.  */
                 buf[--width] = (int)(num%10L) + '0';
                 num /= 10L;
         }
         buf[--width] = (int)num + '0';          /* Always 1 digit.      */
         while (width != 0)                      /* Pad with blanks.     */
                 buf[--width] = ' ';
 }

 /*
  * The argument "text" points to
  * a string. Append this line to the
  * buffer list buffer. Handcraft the EOL
  * on the end. Return TRUE if it worked and
  * FALSE if you ran out of room.
  */
 addline(text)
 char    *text;
 {
         register LINE   *lp;
         register int    i;
         register int    ntext;

         ntext = strlen(text);
         if ((lp=lalloc(ntext)) == NULL)
                 return (FALSE);
         for (i=0; i<ntext; ++i)
                 lputc(lp, i, text[i]);
         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
         lp->l_bp = blistp->b_linep->l_bp;
         blistp->b_linep->l_bp = lp;
         lp->l_fp = blistp->b_linep;
         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
                 blistp->b_dotp = lp;            /* move it to new line  */
         return (TRUE);
 }

 /*
  * Look through the list of
  * buffers. Return TRUE if there
  * are any changed buffers. Buffers
  * that hold magic internal stuff are
  * not considered; who cares if the
  * list of buffer names is hacked.
  * Return FALSE if no buffers
  * have been changed.
  */
 anycb()
 {
         register BUFFER *bp;

         bp = bheadp;
         while (bp != NULL) {
                 if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
                         return (TRUE);
                 bp = bp->b_bufp;
         }
         return (FALSE);
 }

 /*
  * Find a buffer, by name. Return a pointer
  * to the BUFFER structure associated with it.
  * If the buffer is not found
  * and the "cflag" is TRUE, create it. The "bflag" is
  * the settings for the flags in in buffer.
  */
 BUFFER  *
 bfind(bname, cflag, bflag)
 register char   *bname;
 {
         register BUFFER *bp;
         register BUFFER *sb;        /* buffer to insert after */
         register LINE   *lp;
         char *malloc();

         bp = bheadp;
         while (bp != NULL) {
                 if (strcmp(bname, bp->b_bname) == 0)
                         return (bp);
                 bp = bp->b_bufp;
         }
         if (cflag != FALSE) {
                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
                         return (NULL);
                 if ((lp=lalloc(0)) == NULL) {
                         free((char *) bp);
                         return (NULL);
                 }
                 /* find the place in the list to insert this buffer */
                 if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
                         /* insert at the beginning */
                         bp->b_bufp = bheadp;
                         bheadp = bp;
                 } else {
                         sb = bheadp;
                         while (sb->b_bufp != NULL) {
                                 if (strcmp(sb->b_bufp->b_bname, bname) > 0)
                                         break;
                                 sb = sb->b_bufp;
                         }

                         /* and insert it */
                                bp->b_bufp = sb->b_bufp;
                         sb->b_bufp = bp;
                        }

                 /* and set up the other buffer fields */
                 bp->b_active = TRUE;
                 bp->b_dotp  = lp;
                 bp->b_doto  = 0;
                 bp->b_markp = NULL;
                 bp->b_marko = 0;
                 bp->b_flag  = bflag;
                 bp->b_mode  = gmode;
                 bp->b_nwnd  = 0;
                 bp->b_linep = lp;
                 strcpy(bp->b_fname, "");
                 strcpy(bp->b_bname, bname);
 #if        CRYPT
                 bp->b_key[0] = 0;
 #endif
                 lp->l_fp = lp;
                 lp->l_bp = lp;
         }
         return (bp);
 }

 /*
  * This routine blows away all of the text
  * in a buffer. If the buffer is marked as changed
  * then we ask if it is ok to blow it away; this is
  * to save the user the grief of losing text. The
  * window chain is nearly always wrong if this gets
  * called; the caller must arrange for the updates
  * that are required. Return TRUE if everything
  * looks good.
  */
 bclear(bp)
 register BUFFER *bp;
 {
         register LINE   *lp;
         register int    s;

         if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
         && (s=mlyesno("Discard changes")) != TRUE)
                 return (s);
         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
                 lfree(lp);
         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
         bp->b_doto  = 0;
         bp->b_markp = NULL;                     /* Invalidate "mark"    */
         bp->b_marko = 0;
         return (TRUE);
 }

 unmark(f, n)        /* unmark the current buffers change flag */

 int f, n;        /* unused command arguments */

 {
         curbp->b_flag &= ~BFCHG;
         curwp->w_flag |= WFMODE;
         return(TRUE);
 }


 BUG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\DEBUGC\BUG.C

 #include bug.h
 #include stdio.h

       /*  *****************************************************  */
       /*  Dr. Bob's Utilities    Copyright (c) 1985              */
       /*  DEBUG  preprocessor macro example                      */
       /*  compile with  cc -ddebug bug.c     to see debug stuff  */
       /*  *****************************************************  */


 main()
 {
     int n;

     DB_PRINT("Debug is active\n\n");
     NDB_PRINT("Debug is NOT active\n\n");

     HERE("main");

     readfile();

     DEBUG(
        printf("\n\nIf debug is defined only two calls to ");
        printf("sortfile() will be made here\n");
        sortfile();
        sortfile();
     )
     HERE("main2");

     N_DEBUG(
        printf("Statements in this section will execute only if debug is NOT d
        for(n = 1; n <= 8; n++)
        sortfile();
     )

     writefile();
     printf("\n");
     HERE("main3");

     printf("\nThis should be printed no matter what\n");

 }


 readfile()
 {
     HERE("readfile");
 }


 sortfile()
 {
     static int i = 1;
     DB_PRINT("      sortfile - pass #%d \n" COMMA i++);
     NDB_PRINT ("sf() - pass #%d \n" COMMA i++);
 }


 writefile()
 {
     static char st[] = "This message created by writefile";
     HERE("writefile");
     DB_PRINT("\nThe string is: %s\n" COMMA st);
 }


 CALC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\CALC.C

 #include <stdio.h>
 #include <ctype.h>

 /*
  * Calculator program - 9 May 1985
  * Please send corrections or remarks to:
  *        Bob Brodt
  *        34 Mehrhof Rd.
  *        Little Ferry, NJ 07643
  *        (201)-641-9582
  *
  * This is a simple integer arithmetic calculator program. It uses infix
  * notation, i.e. 1+2*3 as opposed to "reverse polish" notation: 1 2 3 * +.
  *
  * CONSTANTS:
  *        Numbers may be input as in C using 0x notation for hex, and a
  *        leading zero for octal, everything else is assumed to be decimal.
  * VARIABLES:
  *        Also available are 26 registers referenced by a single letter
  *        (a-z or A-Z, case is ignored).
  * OPERATORS:
  *        The following operators are supported (from highest precedence to
  *        lowest):
  *
  *        ( )                associativity
  *        ~                one's complement
  *        * / %                mutliply, divide and modulo
  *        + -                unary and binary add & subtract
  *        << >>                shift left and right
  *        &                bitwise AND
  *        ^                bitwise exclusive OR
  *        |                bitwise inclusive OR
  *        =                assignment
  *        ,                comma - seperates function arguments
  *
  *        All operators associate from left to right with the exception of
  *        the assignment (=) operator.
  * FUNCTIONS:
  *        The calculator also has built-in function capabilties which may be
  *        enhanced later:
  *        base n  - set the output conversion base to n (n = 8, 10 or 16)
  * ADDITIONAL FEATURES:
  *        help - displays a help screen containing the above information.
  *        ? - displays all of the variables and their current values.
  */

 /*
  * Tokens
  */
 #define T_EOL                ';'
 #define T_CONST                'C'
 #define T_SYMBOL        'S'
 #define T_LPAR                '('
 #define T_RPAR                ')'
 #define T_COMMA                ','
 #define T_ASSIGN        '='
 #define T_POINT                '$'
 #define T_MUL                '*'
 #define T_DIV                '/'
 #define T_MOD                '%'
 #define T_ADD                '+'
 #define T_SUB                '-'
 #define T_NEG                '_'
 #define T_NOT                '~'
 #define T_SHL                'L'
 #define T_SHR                'R'
 #define T_AND                '&'
 #define T_XOR                '^'
 #define T_IOR                '|'
 #define T_FUNC                'F'


 /*
  * Operator/Operand stack, base ptr and top of stack ptr
  */
 #define STAKSZ 128
 struct {
         char o_token;
         int o_value;
 } Opstk[ STAKSZ ];
 int Opbase, Opsp;

 /*
  * Value (working) stack, base ptr and top of stack ptr
  */
 int Valstk[ STAKSZ ];
 int Valbase, Valsp;

 /*
  * Built-in Functions and jump table
  */
 int f_sum(), f_base();
 int (*Functab[ 2 ])();

 /*
  * Symbol Table
  */
 int Symbols[ 26 ];

 /*
  * Miscellaneous
  */
 #define MAXLEVEL 32
 char Level;        /* current recursion level in calc() */
 char Token;        /* current input token */
 int Value;        /* and its value */
 char Eol;        /* set when end of line encountered */
 char *Lineptr;        /* points to next character in input line */
 char *Ofmt;        /* current output format (set by "base" command) */
 int Error;        /* set if parsing error occurred */
 char Nohelp;        /* set if help was given already */

 char *skipws();

 main()
 {
         char line[ 1024 ], *cp;

         initialize();

         for ( ;; )
         {
                 Error = 0;
                 /*
                  * read a line from stdin and try to parse it
                  */
                 printf( "? " );
                 if ( ! gets( line ) )
                         break;
                 cp = skipws( line );
                 if ( *cp )
                 {
                         if ( *cp == '?' )
                         {
                                 dumpvars();
                                 continue;
                         }
                         else if ( strcmp( cp, "quit" ) == 0 )
                                 break;
                         else if ( strcmp( cp, "help" ) == 0 )
                         {
                                 help();
                                 continue;
                         }
                         calc( cp );
                         /*
                          * If no parsing errors were found, print the
                          * results of the evaluation of the expression.
                          */
                         if ( Error && Nohelp )
                         {
                                 printf( "do you need help ? " );
                                 gets( line );
                                 cp = skipws( line );
                                 if ( toupper( *cp ) == 'Y' )
                                         help();
                         }
                         else if ( ! Error )
                         {
                                 printf( Ofmt, Value );
                                 putchar( '\n' );
                         }
                 }
         }
         printf( "bye bye\n" );
 }

 initialize()
 {
         /*
          * initialize
          */
         Functab[0] = f_sum;
         Functab[1] = f_base;

         push( 10 );
         f_base();
         Nohelp = 1;
 }

 help()
 {
         Nohelp = 0;

 printf("This calculator uses infix notation i.e. 1+2*3 as opposed to\n");
 printf("\"reverse polish\" notation: 1 2 3 * +.\n");
 printf("CONSTANTS:\n");
 printf(" Numbers may be entered using 0x notation for hex (like in C),\n");
 printf(" and a leading zero for octal, everything else is assumed to be\n");
 printf(" decimal.\n");
 printf("VARIABLES:\n");
 printf(" Also available are 26 registers referenced by a single letter\n");
 printf(" (a-z or A-Z, case is ignored).\n");
 printf("OPERATORS:\n");
 printf(" The following operators are supported (from highest precedence\n");
 printf(" to lowest):\n");
 printf("\n");
 printf(" ( )                associativity\n");
 printf(" ~                one's complement\n");
 printf(" * / %                mutliply, divide and modulo\n");
 printf(" + -                unary and binary add & subtract\n");
 printf(" << >>                shift left and right\n");
 printf(" &                bitwise AND\n");
 printf(" ^                bitwise exclusive OR\n");
 printf(" |                bitwise inclusive OR\n");
 printf("-MORE-" );
         getchar();
 printf(" =                assignment\n");
 printf(" ,                comma - seperates function arguments\n");
 printf("\n");
 printf(" All operators associate from left to right with the exception\n");
 printf(" of the assignment (=) operator.\n");
 printf("FUNCTIONS:\n");
 printf(" The calculator also has built-in function capabilties (which\n");
 printf(" may be enhanced in a later revision):\n");
 printf("\n");
 printf(" base n  - set the output conversion base to n (n = 8, 10 or 16)\n");
 printf("\n");
 printf("ADDITIONAL FEATURES:\n");
 printf(" help - displays a help screen containing the above information.\n");
 printf(" ? - displays all of the variables and their current values.\n");
 }

 dumpvars()
 {
         int i;

         for ( i=0; i<26; ++i )
         {
                 if ( !(i % 8) )
                         printf( "\n" );
                 printf( "%c=", i + 'A' );
                 printf( Ofmt, Symbols[ i ] );
                 printf( "\t" );
         }
         printf( "\n" );
 }

 /*************************************************************
 *                 EXPRESSION EVALUATOR                       *
 **************************************************************/
 /*
  * NOTE: The comments make reference to "lvalues" and "rvalues". These
  * are attributes of <primaries> (primaries, for the layman, are things
  * like constants and variables, and parenthesized expressions. If you
  * don't know what an expression is, you shouldn't be a reading this!).
  * If a <primary> is an "lvalue", it means that it can usually be found on
  * LEFT-HAND side of an assignment operator. "rvalues" can only be found
  * on the RIGHT-HAND side of an assignment. Simply stated, only things like
  * variables can be used as both "lvalues" and "rvalues", whereas things
  * like constants and parenthesized expressions can only be "rvalues" since
  * it wouldn't make sense to say: 12 = 5.
  */


 calc( line )
 char *line;
 {
         /*
          * Parse and calculate an arithmetic expression pointed to
          * by "line". This routine is fully re-entrant - a feature
          * that is not currently used, but may come in handy later
          * (for instance if a variable points to a character string
          * that contains an expression to be evaluated).
          */
         char *savLineptr;
         int savValbase, savValsp, savOpbase, savOpsp;

         if ( ++Level > MAXLEVEL )
         {
                 err( "recursion" );
         }
         else
         {
                 /*
                  * Save all global variables that may change if calc()
                  * is called recursively.
                  */
                 savLineptr = Lineptr;
                 savValbase = Valbase;
                 savValsp = Valsp;
                 savOpbase = Opbase;
                 savOpsp = Opsp;

                 /*
                  * Set up stack base ptrs and input line ptr
                  */
                 Valbase = Valsp;
                 Opbase = Opsp;
                 Lineptr = line;

                 /*
                  * Get the first token from input line and parse an
                  * expression and then evaluate it.
                  */
                 Eol = 0;

                 getoken();
                 if ( ! Eol )
                 {
                         expression();
                         if ( Error <= 0 )
                                 Value = evaluate();
                 }
                 /*
                  * Restore previous values of globals
                  */
                 Lineptr = savLineptr;
                 Valbase = savValbase;
                 Valsp = savValsp;
                 Opbase = savOpbase;
                 Opsp = savOpsp;
         }

         --Level;
 }

 evaluate()
 {
         /*
          * Evaluate an expression by popping operators and operands
          * from the Operator/Operand stack and performing each indicated
          * operation. Only the operators starting from current base ptr
          * (Opbase) to top of stack (Opsp) are evaluated, so that evaluate()
          * may be called by any generation of calc().
          */
         int opsp, val, *ip;
         char op;

 TOS (Valstk[Valsp-1])        /* top of stack macro */

         for ( opsp=Opbase; opsp<Opsp; ++opsp )
         {
                 op = Opstk[ opsp ].o_token;

                 if ( op == T_CONST )
                         push( Opstk[ opsp ].o_value );
                 else if ( op == T_SYMBOL )
                         /*
                          * Push the address of a variable
                          */
                         push( &Symbols[ Opstk[ opsp ].o_value ] );
                 else if ( op == T_POINT )
                 {
                         /*
                          * Get the value of the integer pointed to by the
                          * address on top of the stack. This usually follows
                          * a T_SYMBOL when the symbol is not being used
                          * as an "lvalue".
                          */
                         ip = pop();
                         push( *ip );
                 }
                 else if ( op == T_ASSIGN )
                 {
                         /*
                          * Assignment operator: The item on top of stack is
                          * the "rvalue", second on stack is the "lvalue"
                          * (an address where to store the "rvalue"). The
                          * "rvalue" gets pushed back on top of the stack.
                          */
                         val = pop();
                         ip = pop();
                         push( *ip = val );
                 }
                 else if ( op == T_ADD )
                 {
                         val = pop();
                         TOS += val;
                 }
                 else if ( op == T_SUB )
                 {
                         val = pop();
                         TOS -= val;
                 }
                 else if ( op == T_NOT )
                         TOS = ~TOS;
                 else if ( op == T_NEG )
                         TOS = -TOS;
                 else if ( op == T_MUL )
                 {
                         val = pop();
                         TOS *= val;
                 }
                 else if ( op == T_DIV )
                 {
                         val = pop();
                         TOS /= val;
                 }
                 else if ( op == T_MOD )
                 {
                         val = pop();
                         TOS %= val;
                 }
                 else if ( op == T_SHL )
                 {
                         val = pop();
                         TOS <<= val;
                 }
                 else if ( op == T_SHR )
                 {
                         val = pop();
                         TOS >>= val;
                 }
                 else if ( op == T_AND )
                 {
                         val = pop();
                         TOS &= val;
                 }
                 else if ( op == T_XOR )
                 {
                         val = pop();
                         TOS ^= val;
                 }
                 else if ( op == T_IOR )
                 {
                         val = pop();
                         TOS |= val;
                 }
                 else if ( op == T_COMMA )
                         ;
                 else if ( op == T_FUNC )
                         push( (*Functab[ Opstk[ opsp ].o_value ])() );
                 else
                         err( "bad operator in stack: 0x%x (%c)", op, op );
         }
         return Valstk[ Valbase ];
 }

 push( val )
 {
         if ( Valsp >= STAKSZ )
                 err( "stack overflow" );
         return Valstk[ Valsp++ ] = val;
 }

 pop()
 {
         if ( --Valsp < 0 )
                 Valsp = 0;
         return Valstk[ Valsp ];
 }

 /*************************************************************
 *                   EXPRESSION PARSER                        *
 **************************************************************/
 expression()
 {
         /*
          * Parse an expression. Expressions have the following syntax:
          *    <expression> := <primary> <operator> <primary>
          * so the first thing to look for is a primary.
          */
         int lvalue;

         if ( !(lvalue = primary()) )
                 err( "bad expression" );
         else if ( Eol )
         {
                 if ( lvalue < 0 )
                         generate( T_POINT, 0 );
         }
         else
                 op_prim( 0, lvalue );
 }

 op_prim( precedence, lvalue )
 int precedence;        /* precedence of current <operator> */
 int lvalue;        /* type of current <primary>: -1 => lvalue */
                 /*                             0 => no <primary> (error) */
                 /*                             1 => rvalue */
 {
         /*
          * Parse the <operator> <primary> part of an expression.
          * "precedence" is the PREVIOUS <operator>'s precedence level
          * (0=low, +n=high).
          */
         char tkn;
         int pr, lv;

         while ( ! Eol )
         {
                 /*
                  * Get the precedence level of current <operator> ("pr").
                  * If it is greater than previous operator ("precedence"),
                  * get the next <primary> and do another <operator> <primary>
                  * NOTE: For left-to-right associativity, the condition
                  *     pr > precedence
                  * must be true. for right-to-left associativity,
                  *     pr >= precedence
                  * must be true (assignment operator only).
                  */

                 pr = binop( Token );

                 if (
                         (pr>precedence && pr>0) ||
                         (Token==T_ASSIGN && pr>=precedence)
                 )
                 {
                         if ( Token == T_ASSIGN )
                         {
                                 if ( lvalue > 0 )
                                         err( "= needs and lvalue" );
                         }
                         else if ( lvalue < 0 )
                                 generate( T_POINT, 0 );

                         /*
                          * Save the operator token and do a primary.
                          */
                         tkn = Token;
                         getoken();
                         if ( ! (lv = primary()) )
                                 err( "missing an operand" );
                         /*
                          * Now look at the next operator. If its precedence
                          * is greater than this one ("tkn" above), generate
                          * code for it BEFORE this one.
                          */
                         lvalue = op_prim( pr, lv );

                         if ( Token != T_ASSIGN && lvalue < 0 )
                         {
                                 /*
                                  * Next operator is not the assignment op.
                                  * and the current <primary> is an lvalue,
                                  * therefore generate a "load from address
                                  * on top of stack" instruction.
                                  */
                                 generate( T_POINT, 0 );
                                 /*
                                  * This makes it an rvalue now.
                                  */
                                 lvalue = 1;
                         }
                         else if ( tkn!=T_ASSIGN && Token==T_ASSIGN )
                         {
                                 /*
                                  * YEECH! this is the only way I know of to
                                  * detect errors like: a+b=c
                                  */
                                 err( "= needs an lvalue" );
                         }

                         /*
                          * Generate the instruction for the current operator.
                          */
                         generate( tkn, 0 );
                 }
                 else
                         break;
         }

         return lvalue;
 }

 primary()
 {
         /*
          * Parse a primary. Primaries have the following syntax:
          *    <primary> := <constant> |
          *                 '(' <expression> ')' |
          *                 <unary op> <primary> |
          *                 <function> <primary>
          */
         int rtn;
         int val;

         if ( Eol )
                 return 0;

         /*
          * Return value:
          *   -1   => the <primary> is an lvalue
          *    0   => not a <primary> (usually end of line or a syntax error)
          *    1   => the <primary> is an rvalue
          */
         rtn = 1;

         switch ( Token )
         {
         case T_SYMBOL:        /* a symbol */
                 rtn = -1;
         case T_CONST:        /* a constant */
                 generate( Token, Value );
                 getoken();
                 break;
         case T_LPAR:        /* a parenthesized expression */
                 getoken();
                 expression();
                 if ( Token != T_RPAR )
                 {
                         err( "missing ')'" );
                         rtn = 0;
                 }
                 else
                         getoken();
                 break;
         case T_SUB:        /* unary - */
                 /*
                  * The lexical analyzer is not smart enough to recognize
                  * unary operators (+ and -), that's why we have to do
                  * it here
                  */
                 getoken();
                 expression();
                 generate( T_NEG, 0 );
                 break;
         case T_NOT:        /* unary ~ */
                 getoken();
                 expression();
                 generate( T_NOT, 0 );
                 break;
         case T_ADD:        /* unary + */
                 getoken();
                 expression();
                 break;
         case T_FUNC:        /* built-in function */
                 val = Value;
                 getoken();
                 expression();
                 generate( T_FUNC, val );
                 break;
         default:
                 /*
                  * Not a primary
                  */
                 rtn = 0;
         }
         return rtn;
 }

 binop( op )
 char op;
 {
         /*
          * Determine if "op" is a binary operator and return its
          * precedence level if so. If not, return 0.
          */
         switch ( op )
         {
         case T_COMMA:
                 return 1;
         case T_ASSIGN:
                 return 2;
         case T_IOR:
                 return 3;
         case T_XOR:
                 return 4;
         case T_AND:
                 return 5;
         case T_SHL:
         case T_SHR:
                 return 6;
         case T_ADD:
         case T_SUB:
                 return 7;
         case T_MUL:
         case T_DIV:
         case T_MOD:
                 return 8;
         case T_NOT:
                 return 9;
         }
         return 0;
 }

 generate( tkn, val )
 char tkn;
 {
         /*
          * Push the given token and value onto the Operator/Operand stack.
          */
         if ( Opsp < STAKSZ )
         {
                 Opstk[ Opsp ].o_token = tkn;
                 Opstk[ Opsp ].o_value = val;
                 ++Opsp;
         }
         else
                 err( "expression too complex" );
 }

 /*************************************************************
 *                     LEXICAL ANALYZER                       *
 *************************************************************/
 getoken()
 {
         /*
          * Lexical Analyzer. Gets next token from the input line
          * pointed to by "Lineptr" and advances "Lineptr" to next
          * character. If end of input line is encountered, the
          * "Eol" flag is set.
          */
         char *cp, buf[ 128 ];
         int i;

         /*
          * skip white space
          */
         Lineptr = skipws( Lineptr );

         if ( ! *Lineptr )
         {
                 Eol = 1;
                 Token = T_EOL;
         }
         else if ( *Lineptr == '0' )
         {
                 /*
                  * Check if it's a hex or octal constant
                  */
                 Token = T_CONST;
                 ++Lineptr;
                 if ( toupper( *Lineptr ) == 'X' )
                 {
                         ++Lineptr;
                         for ( cp = buf; ishexdigit( *Lineptr ); )
                                 *cp++ = *Lineptr++;
                         *cp = 0;
                         sscanf( buf, "%x", &Value );
                 }
                 else if ( isdigit( *Lineptr ) )
                 {
                         for ( cp = buf; isoctdigit( *Lineptr ); )
                                 *cp++ = *Lineptr++;
                         *cp = 0;
                         sscanf( buf, "%o", &Value );
                 }
                 else
                         Value = 0;
         }
         else if ( isdigit( *Lineptr ) )
         {
                 /*
                  * It's a numeric constant, "Value" will be its value.
                  */
                 Token = T_CONST;
                 for ( cp = buf; isdigit( *Lineptr ); )
                         *cp++ = *Lineptr++;
                 *cp = 0;
                 Value = atoi( buf );
         }
         else if ( Value = isfunc( &Lineptr ) )
         {
                 /*
                  * It's a built-in function, "Value" will be the index
                  * into the function jump table.
                  */
                 Token = T_FUNC;
                 --Value;
         }
         else if ( Token = isbinop( &Lineptr ) )
         {
                 /*
                  * It's a binary operator
                  */
                 ;
         }
         else if ( isalpha( *Lineptr ) )
         {
                 Token = T_SYMBOL;
                 Value = toupper( *Lineptr ) - 'A';
                 ++Lineptr;
         }
         else
         {
                 /*
                  * Bad character in input line
                  */
                 err( "bad syntax: %s", Lineptr );
                 ++Lineptr;
         }

         return Token;
 }

 char *
 skipws( cp )
 char *cp;
 {
         while ( *cp==' ' || *cp=='\t' )
                 ++cp;
         return cp;
 }

 isfunc( cpp )
 char **cpp;
 {
         /*
          * Check if *cpp is the name of a built-function, return the
          * function jump table index+1 if so and bump *cpp to next
          * character. Return 0 if not a function.
          */
         char *cp, *bp, buf[ 80 ];
         int funcno;

         /*
          * copy the name from input line buffer to a local buffer so
          * we can use it to make a proper comparison to function names.
          */
         for ( cp=*cpp, bp=buf; isalpha( *cp ); )
                 *bp++ = *cp++;
         *bp = 0;

         /*
          * compare it to all of the function names we know about.
          */
         if ( strcmp( buf, "sum" ) == 0 )
                 funcno = 1;
         else if ( strcmp( buf, "base" ) == 0 )
                 funcno = 2;
         else
                 /*
                  * not a built-in function
                  */
                 funcno = 0;

         if ( funcno )
                 *cpp = cp;

         return funcno;
 }

 isbinop( cpp )
 char **cpp;
 {
         /*
          * Check if *cpp is a binary operator, return its token value
          * and bump *cpp to next character.
          */
         int tkn;
         char c;

         c = **cpp;
         if ( c == ',' )
                 tkn = T_COMMA;
         else if ( c == '=' )
                 tkn = T_ASSIGN;
         else if ( c == '<' )
         {
                 if ( *(++(*cpp)) == '<' )
                         tkn = T_SHL;
         }
         else if ( c == '>' )
         {
                 if ( *(++(*cpp)) == '>' )
                         tkn = T_SHR;
         }
         else if ( c == '(' )
                 tkn = T_LPAR;
         else if ( c == ')' )
                 tkn = T_RPAR;
         else if ( c == '*' )
                 tkn = T_MUL;
         else if ( c == '/' )
                 tkn = T_DIV;
         else if ( c == '%' )
                 tkn = T_MOD;
         else if ( c == '+' )
                 tkn = T_ADD;
         else if ( c == '-' )
                 tkn = T_SUB;
         else if ( c == '^' )
                 tkn = T_XOR;
         else if ( c == '&' )
                 tkn = T_AND;
         else if ( c == '|' )
                 tkn = T_IOR;
         else if ( c == '~' )
                 tkn = T_NOT;
         else
                 tkn = 0;

         if ( tkn )
                 ++(*cpp);

         return tkn;
 }

 /*************************************************************
 *                   BUILT-IN FUNCTIONS                       *
 **************************************************************/
 f_sum()
 {
         /*
          * usage: sum( a, b )
          *    Sum all the numbers between a and b
          */
         int i, a, b;

         b = pop();
         a = pop();
         for ( i=a+1; i<=b; ++i )
                 a += i;

         push( a );
 }

 f_base()
 {
         /*
          * usage: base( n )
          *    Set output number base
          */
         switch ( pop() )
         {
         case 8:
                 Ofmt = "0%o";
                 break;
         case 16:
                 Ofmt = "0x%x";
                 break;
         case 10:
         default:
                 Ofmt = "%d";
                 break;
         }
 }


 /*************************************************************
 *                       MISCELLANEOUS                        *
 **************************************************************/
 err( a, b, c, d, e, f )
 {
         if ( ! Error )
         {
                 printf( a, b, c, d, e, f );
                 putchar( '\n' );
                 Error = 1;
         }
 }

 ishexdigit( c )
 char c;
 {
         return instr( c, "0123456789abcdefABCDEF" );
 }

 isoctdigit( c )
 char c;
 {
         return instr( c, "01234567" );
 }

 instr( c, s )
 char c, *s;
 {
         while ( *s )
                 if ( c == *s++ )
                         return 1;

         return 0;
 }


 CALIB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\CALIB.C

 /*                      Processor Speed Calibration Function
  */

 /*      calib()

         Function: Return the speed of this processor, as a percent of
         the speed of a standard IBM-PC.

         Algorithm: Iterate for one system timer tic (as found in low
         memory location 46C). Multiply the result by 100 (conver to %)
         add in 50 (so the next divide will round rather than truncate),
         and divide by the number of iterations on a normal PC. Do all
         the calculations in long format to avoid overflow.
 */

 calib()

 {
         /* Pointer to system timer in low memory: */
         unsigned far *timerLow = {(unsigned far *) 0x46C};
         unsigned lastTime;      /* Last value read from *timerLow. */
         unsigned iter;          /* Iteration count. */

         /* Wait until timer has just ticked. */
         for (lastTime = *timerLow; lastTime == *timerLow;);
         /* Count iterations until the next tick. */
         for (iter = 0, lastTime = *timerLow; lastTime == *timerLow; iter++);
         /* Calculate and return the percent of a standard IBM-PC. */
         return ((100L*((long) iter) + 50L)/1878L);
 }



 CALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\CALLOC.C

 /* 1.2  07-10-85                                                 (calloc.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         char *
 calloc(nelem, elsize)        /* Return pointer to storage for nelem elements
                            of size elsize. Initialize storage to zeros.
 /*----------------------------------------------------------------------*/
 unsigned nelem, elsize;
 {
         char *malloc(), *p, *q;
         unsigned i, n_units();

         p = q = malloc(i = nelem * n_units(elsize) * sizeof(HEADER));
         if (q /* ISNT NULL */)
                 while (i--)
                         *q++ = NULL;
         return p;
 }


 CALLS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\CALLS\CALLS.C

 /*
  * CALLS.C
  *     prints a paragraphed list of function calls
  *     that occur in a body of C source code.
  *
  * Author: M.M. Taylor, DCIEM, Toronto, Canada.
  * Modified for IBM-PC DOS 2.1, 02/Dec/85, Robert E. Sawyer, Torrance, CA.
  *     (DeSmet C v2.4)
  */

 #include <stdio.h>

 #ifdef  DESMET
 #else
 #include <ctype.h>
 #endif

 #define ATOMLENGTH 20
 #define MAXNAME 500
 #define MAXINST 4000
 #define MAXDEPTH 25
 #define MAXSEEN 100
 #define PAPERWIDTH 80
 #define TAB "    "
 #define TABSIZE 4


 int bracket, linect, terse, ntabs;
 char aseen [MAXSEEN][ATOMLENGTH];

 /* if lastchar==0, getch gets next character, else getch gets lastchar */
 int lastchar;
 char *sysword [ ] =
     {
     "if",
     "while",
     "for",
     "return",
     "switch",
     0
     };

 struct rname
     {
     char namer[ATOMLENGTH];
     int rnamecalled;
     int rnameout;
     struct rinst *dlistp;
     } namelist[MAXNAME];

 struct rinst
     {
     struct rname *namep;
     struct rinst *calls;
     struct rinst *calledby;
     } dlist[MAXINST];

 struct rname *activelist[MAXDEPTH];
 int activep = 0;
 struct rinst *frp;

 FILE *fin, *fopen();

 main(argc,argv)
     int argc;
     char *argv[];
     {
     int gf, i, ok;
     char atom[ATOMLENGTH];
     char *startfunc;
     struct rname *startp, *lookfor();
     struct rinst *curproc, *initfree(), *newproc(), *add2call();

     bracket=0;
     terse=1;
     lastchar = 0;
     aseen[0][0] = 0;
     startfunc = "main" ;
     frp = dlist;
     initfree();
     for (i = 0; i < MAXDEPTH ; i++ ) activelist[i] = 0 ;
     activep = 0;
     ntabs = (PAPERWIDTH - 20)/TABSIZE;

     if (argc < 2)
         usage();
     else if ((fin = fopen(argv[1],"r")) == NULL)
         {
         printf("\nCan't open %s\n",argv[1]);
         usage();
         }

     /*  get arguments and flags*/
     for (i = 2; i<argc && (argv[i][0]=='-' || argv[i][0]=='?'); i++)
         {
         if (match(argv[i],"-v"))
             terse=0;
         else if (match(argv[i],"-w"))
             ntabs = (atoi(argv[++i])-20)/TABSIZE;
         else
             usage();
         }
     ok = 1;
     while ((gf = getfunc(atom)) != -1 && ok ){
         if (gf) ok = (int)add2call(atom,curproc);
         else ok = (int)(curproc = newproc(atom));
         }
     if (i<argc)
         {
         do
             {
             startfunc = argv[i];
             if (startp = (lookfor(startfunc)))
                 {
                 output (startp,0);
                 printf ("\n\n");
                 }
             else printf ("*** error *** %s not found\n",startfunc);
             } while (++i<argc);
         }
     else
         {
         for (startp=namelist; startp->namer[0] ; startp++)
             {
             if (!startp->rnamecalled)
                 {
                 output (startp,0);
                 printf ("\n\n");
                 }
             }
         }
     fclose(fin);
     }

 /* return name of a function. value 0 == definition, 1 == called */
 getfunc(atom)
     char atom[];
     {
     int c;
     int ss;
     for(;;)
         {
         c = getch();
         if (isalpha(c))
             {
             lastchar=c;
             scan(atom);
             continue;
             }
         else
             {
             switch(c)
                 {
                 case '\t':
                 case ' ':
                     continue;
                 case '\n':
                    if ((c= getch())=='#')
                         while ((c= getch()) != '\n')
                             ;
                     lastchar = c;
                     continue;
                 case '\'':
                     atom[0]='\0';
                     while ((c= getch()) != '\'')
                         if (c == '\\')
                             getch();
                         continue;
                 case '\"':
                     while (( c = getch()) != '\"')
                         if (c=='\\')
                             getch();
                     continue;
                 case '\\':
                     atom[0] = '\0';
                     getch();
                     continue;
                 case '{':
                     bracket++;
                     atom[0]='\0';
                     continue;
                 case '}':
                     --bracket;
                     if (bracket < 0)
                         printf ("bracket underflow");
                     atom[0]='\0';
                     continue;
                 case '(':
                     if( ! atom[0] )
                         continue;
                     if (!checksys(atom))
                         {
                         if (!bracket)
                             return (0);
                         if ((ss=seen(atom))==-1)
                             printf("aseen overflow");
                         if (bracket && !ss)
                             return (1);
                         }
                     atom[0]='\0';
                     continue;
                 case ')':
                     atom[0]='\0';
                     continue;
                 case EOF:
                     return (-1);
                 case '/':
                     if (( c = getch())=='*')
                         {
                         for (;;)
                             {
                             while (getch() != '*')
                                 ;
                             if ((c = getch()) == '/')
                                 break;
                             lastchar = c;
                             }
                         continue;
                         }
                     else
                         {
                         lastchar = c;
                         continue;
                         }
                 case '*':
                     atom [0] = '\0';
                     continue;
                 default:
                     atom[0]='\0';
                     continue;
                 }
             }
         }
     }

 /* scan text until an atom that could be a function name is found */
 scan(atom)
     char atom[];
     {
     char c;
     int i;

     c = lastchar;
     i = 0;
     while( isalpha(c) || isdigit(c) || (c == '_') )
         {
         atom [i++] = (c=getch());
         if (i == ATOMLENGTH )
             break;
         }
     atom [i-1] = '\0';
     while( isalpha(c) || isdigit(c) || (c == '_') )
         c = getch();
     lastchar= c;
     return (1);
     }

 /* return value 1 if atom is a system keyword, else 0 */
 checksys(atom)
     char atom[];
     {
     int i;

     for (i=0; sysword[i] ; i++)
         if (match(atom,sysword[i]))
             return (1);
         return (0);
     }

 /*** see if we have seen this function within this process ***/

 seen(atom)
     char *atom;
     {
     int i,j;

     for (i=0; aseen[i][0] && i < MAXSEEN ; i++)
         {
         if (match (atom, aseen[i]))
             return (1);
         }
     if (i >= MAXSEEN)
         return (-1);
     for (j=0; (aseen[i][j] = atom[j]) != '\0' && j < ATOMLENGTH ; j++)
         ;
     aseen[i+1][0] = '\0';
     return (0);
     }

 /* return 1 if strings match, else 0 */
 match(atom,name)
     char name[];
     char atom[];
     {
     register char *ap,*np;

     ap = atom;
     np = name;
     while (*ap==*np)
         {
         if (*ap== 0)
             return (1);
         ap++; np++;
         }
     return (0);
     }

 /* get a character, but perhaps return previous one instead */
 getch()
     {
     int c;

     if( lastchar == 0 )
         return (fgetc(fin));
     c = lastchar;
     lastchar = 0;
     return (c);
     }

 /*
 when scanning the text each function instance is inserted into a
 linear list of names, using the rname structure, when it is first
 encountered. It is also inserted into the linked list using the rinst
 structure. The entry into the name list has a pointer to the defining
 instance in the linked list, and each entry in the linked list has
 a pointer back to the relevant name. Newproc makes an entry in the
 defining list, which is distinguished from the called list only because
 it has no calledby link (value=0). Add2proc enters into the called
 list, by inserting a link to the new instance in the calls pointer of
 the last entry (may be a defining instance, or a function called by
 that defining instance), and points back to the defining instance of
 the caller in its called-by pointer.
 */

 struct rinst *
 newproc(name)
     char name[];
     {
     struct rinst *install();
     struct rname *place();

     aseen[0][0] = '\0';
     return (install(place(name),(struct rinst *)0));
     }

 struct rinst *
 add2call(name,curp)
     char name[];
     struct rinst *curp;
     {
     struct rinst *install(),*ip;
     struct rname *place(),*p;

     ip = install(p = place(name),curp);
     if (p)
         ++(p->rnamecalled);
     return (ip);
     }

 /**
 place(name)  returns a pointer to the name on the namelist.
         If the name was not there, it puts it at the end of the list.
         If there was no room, it returns -1.
 **/

 struct rname *
 place(name)
     char name[];
     {
     int i,j;
     struct rname *npt;

     for (i = 0 ; (npt = &namelist[i])->namer[0] && i<MAXNAME ; i++)
         {
         if (match(name,npt->namer))
             return (npt);
         if (i >= MAXNAME)
             {
             printf ("namelist overflow");
             return ( (struct rname *) -1);
             }
         }
 /* name was not on list, so put it on */

     for (j=0 ; name[j]; j++)
         npt->namer[j] = name[j];
     npt->namer[j] = '\0';
     (npt+1)->namer[0] = '\0';
     npt->rnamecalled = 0;
     npt->rnameout=0;
     return (npt);
     }

 /**
 install(np,rp) puts a new instance of a function into the linked list.
 It puts a pointer (np) to its own name (returned by place) into its
 namepointer, a pointer to the calling routine (rp) into
 its called-by pointer, and zero into the calls pointer. It then
 puts a pointer to itself into the last function in the chain.
 **/

 struct rinst *
 install(np,rp)
     struct rname *np;
     struct rinst *rp;
     {
     struct rinst *newp;
     struct rinst *op;
     struct rinst *getfree();

     if (!np)
         return ( (struct rinst *) -1);
     if ( !(newp = getfree()))
         return ( (struct rinst *) 0);
     newp->namep = np;
     newp->calls = 0;
     if (rp)
         {
         op = rp;
         while (op->calls)
             op = op->calls;
         newp->calledby = op->calledby;
         op->calls = newp;
         }
     else
         {
         newp->calledby = (struct rinst *) np;
         np->dlistp = newp;
         }
     return (newp);
     }

 /*
 getfree returns a pointer to the next free instance block on the list
 */

 struct rinst *
 getfree()
     {
     struct rinst *ret;

     ret=frp;
     if (!ret)
         printf ("out of instance blocks\n");
     frp=frp->calls;
     return(ret);
     }

 /*
 initfree makes a linked list of instance blocks, and returns a pointer
 to the first one. it is called only once, at the beginning of the programme.
 */

 struct rinst *
 initfree()
     {
     int i;

     for (i = 0 ; i < MAXINST-2 ; i++)
         {
         frp->namep = 0;
         frp->calls = frp+1;
         (frp+1)->calledby = frp;
         frp++;
         }
     frp->namep=0;
     frp->calls = 0;
     frp= dlist;
     return(dlist);
     }

 /********
 output is a recursive routine which is supposed to print one tab for each
 level of recursion, then the name of the function called, followed by the
 next function called by the same higher level routine. In doing this, it
 calls itself to output the name of the first function called by the
 function whose name it is outputting. It maintains an active list of
 functions currently being output by the different levels of recursion,
 and if it finds itself asked to output one which is already active,
 it terminates, marking that call with a * .
 *********/

 output(func,tabc)
     struct rname *func;
     int tabc;
     {
     struct rinst *nextp;
     int i, tabd, tabstar, tflag;

     ++linect;
     printf ("\n%d  ",linect);
     if (!(makeactive(func)))
         printf ("*"); /* calls nested too deep */
     else
         {
         tabstar= 0;
         tabd = tabc;
         for (;tabd >ntabs; tabstar++)
             tabd = tabd-ntabs;
         for (i = 0 ; i < tabstar ; i++ )
             printf ("<");
         printf (" ");
         for (i = 0 ; i < tabd ; i++ )
             printf ("%s",TAB);
         if (active(func))
             printf ("^ %s ^",func->namer); /* recursive call */
         else
             {
             if (func->dlistp)
                 {
                 printf ("%s", func->namer);
                 nextp = func->dlistp->calls;
                 if (!terse || !func->rnameout)
                     {
                     ++tabc;
                     if (!func->rnameout)
                         func->rnameout = linect;
                     if (tabc > ntabs && tabc%ntabs==1 && nextp)
                         {
                         printf("\n- - - - - - - - - - - - - - - - - - - ");
                         printf("- - - - - - - - - - - - - - -");
                         tflag = 1;
                         }
                     else
                         tflag = 0;
                     for (;nextp; nextp = nextp->calls)
                         output (nextp->namep, tabc);
                     if (tflag)
                         {
                         printf("\n- - - - - - - - - - - - - - - - - - - ");
                         printf("- - - - - - - - - - - - - - -");
                         tflag = 0;
                         }
                     }
                 else if (nextp)
                     printf (" ... [see line %d]", func->rnameout);
                 }
             else
                 printf ("%s [ext]",func->namer); /* library or external call
             }
         backup();
         }
     return;
     }

 /*
 makeactive simply puts a pointer to the nameblock into a stack with
 maximum depth MAXDEPTH. the error return only happens for stack overflow.
 */

 makeactive(func)
     struct rname *func;
     {
     if (activep < MAXDEPTH)
         {
         activelist[activep] = func;
         activep++;
         return (1);
         }
     else
         return (0);
     }

 /*
 backup removes an item from the active stack
 */

 backup()
     {
     if (activep)
         {
         activelist [activep--] = 0;
         return (1);
         }
     else return (-1);
     }

 /*
 active checks whether the pointer which is its argument has already
 occurred on the active list, and returns 1 if so.
 */

 active(func)
     struct rname *func;
     {
     int i;

     for (i = 0; i < activep-1 ; i++)
         if (func == activelist[i])
             return (1);
     return (0);
     }

 /* lookup(name) accepts a pointer to a name and sees if the name is on the
 namelist. If so, it returns a pointer to the nameblock. Otherwise
 returns zero.
 */

 struct rname *
 lookfor(name)
     char *name;
     {
     struct rname *np;

     for (np = namelist; np->namer[0] ; np++)
         if (match(name, np->namer))
             return (np);
     return (0);
     }

 usage()
     {
     printf("\nCALLS reads a C source program,\n");
     printf("and writes the function-call structure to stdout.\n");
     printf("\nUsage:  CALLS fromfile [>tofile] [-v] [-w nn] [fun1 ...]\n");
     printf("\n-v          verbose form (default is terse)\n");
     printf("-w nn       paper width  (default is 80)\n");
     printf("fun1 ...    names of functions to start at (default is main)\n\n"
     exit();
     }


 CAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\CAT.C


   /* (This program is from p. 154 of the Kernighan and Ritchie text */
 #include <stdio.h>

 main(argc, argv)        /* cat: concatenate files */
 int argc;
 char *argv[];
 {
     FILE *fp, *fopen();

     if (argc == 1) /* no args; copy standard input */
          filecopy(stdin);
     else
          while (--argc > 0)
             if ((fp = fopen(*++argv, "r")) == NULL) {
                 fprintf(stderr,
                         "cat: can't open %s\n", *argv);
                 exit(1);
             } else {
                 filecopy(fp);
                 fclose(fp);
             }
     exit(0);
 }

 filecopy(fp)    /* copy file fp to standard output */
 FILE *fp;
 {
     int c;

     while ((c = getc(fp)) != EOF)
         putc(c, stdout);
 }



 CAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\CAT.C


   /* (This program is from p. 154 of the Kernighan and Ritchie text */
 #include <stdio.h>

 main(argc, argv)        /* cat: concatenate files */
 int argc;
 char *argv[];
 {
     FILE *fp, *fopen();

     if (argc == 1) /* no args; copy standard input */
          filecopy(stdin);
     else
          while (--argc > 0)
             if ((fp = fopen(*++argv, "r")) == NULL) {
                 fprintf(stderr,
                         "cat: can't open %s\n", *argv);
                 exit(1);
             } else {
                 filecopy(fp);
                 fclose(fp);
             }
     exit(0);
 }

 filecopy(fp)    /* copy file fp to standard output */
 FILE *fp;
 {
     int c;

     while ((c = getc(fp)) != EOF)
         putc(c, stdout);
 }



 CATCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CATCH.C

 #include <setjmp.h>

 static        int        _catchval;                /* catch/throw return valu

 int catch(id, fn)                        /* execute fn() within a catch frame
 register jmp_buf *id;
 register int (*fn)();
 {
         return(setjmp(id) ? _catchval : ((*fn)()));
 }

 throw(id, rv)                                /* return rv to the id catch */
 register jmp_buf *id;
 register int rv;
 {
         _catchval = rv;
         longjmp(id, 1);
 }


 CB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\CB.C

 /*
         HEADER:                CUG236;
         TITLE:                C Source Formatter;
         DATE:                04/04/1987;
         DESCRIPTION:        "Formats a C source program with proper indents f
                         each statement.";
         VERSION:        2.1;
         KEYWORDS:        Pretty Printer;
         FILENAME:        CB.C;
         SEE-ALSO:        CB.DOC;
         COMPILERS:        vanilla;
         AUTHORS:        W. C. Colley III, J. W. Kindschi Jr.;
 */

 /*
         Modified for Portable C
         by: William C. Colley, III (4 APR 1987)

         Modified for Lattice C Ver 1.01
         by: John W. Kindschi Jr. (10-30-83)

         Swiped from CPIG'S UNIX system and modified to
         run under BDS C by William C. Colley, III


 To use the program type the following command line:

         A>cb input.fil [output.fil]

         Where input.fil is the file to be pretty printed and [output.fil]
         is the destination file. If no output file is specified, then
         the output goes to standard output.
 */

 #include <stdio.h>

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * pair of #defines if you are running AZTEC C:
  */

 /*
 #define getc(f)                agetc(f)
 #define putc(c,f)        aputc(c,f)
 */

 char cc, lchar, pchar, string[200];
 char *wif[] =        {   "if",   NULL                };
 char *welse[] = {   "else", NULL                };
 char *wfor[] =        {   "for",  NULL                };
 char *wds[] =        {   "case", "default",        NULL        };

 int clevel, ct, iflev, ind[10], level, paren, sifflg[10], siflev[10];
 int sind[20][10], slevel[10], spflg[20][10], stabs[20][10];
 int aflg, bflg, eflg, ifflg = -1, pflg[10], qflg, sflg = 1;
 int c, j, lastchar, peek = -1, tabs;
 FILE *f1, *f2 = stdout;

 void comment(), gotelse(), ptabs(), put_str();

 int main(argc,argv)
 int argc;
 char *argv[];
 {
     int getchr(), get_nl(), get_str(), lookup();

     /* Initialize everything here */

     if (argc < 2 || argc > 3) {
         fprintf(stderr,"Usage:  CB input.fil { output.fil }\n");  return !0;
     }
     if (!(f1 = fopen(*++argv,"r"))) {
         fprintf(stderr,"ERROR:  Cannot find file %s\n",*argv);  return !0;
     }
     if (argc == 3 && !(f2 = fopen(*++argv,"w"))) {
         fprintf(stderr,"ERROR:  Cannot create file %s\n",*argv);  return !0;
     }

     /* End of Initialization */

     while ((c = getchr()) != EOF) {
         switch (c) {
             default:        string[j++] = c;
                         if (c != ',') lchar = c;
                         break;

             case ' ':
             case '\t':        if (lookup(welse) == 1) {
                             gotelse();
                             if (sflg == 0 || j > 0) string[j++] = c;
                             put_str();        sflg = 0;  break;
                         }
                         if (sflg == 0 || j > 0) string[j++] = c;
                         break;

             case '\n':        if (eflg = lookup(welse) == 1) gotelse();
                         put_str();  fprintf(f2,"\n");  sflg = 1;
                         if (eflg == 1) {  pflg[level]++;  tabs++; }
                         else if(pchar == lchar) aflg = 1;
                         break;

             case '{':        if (lookup(welse) == 1) gotelse();
                         siflev[clevel] = iflev;         sifflg[clevel] = iffl
                         iflev = ifflg = 0;  clevel++;
                         if (sflg == 1 && pflg[level] != 0) {
                             pflg[level]--;  tabs--;
                         }
                         string[j++] = c;  put_str();  get_nl();         put_s
                         fprintf(f2,"\n");  tabs++;  sflg = 1;
                         if (pflg[level] > 0) {
                             ind[level] = 1;  level++;  slevel[level] = clevel
                         }
                         break;

             case '}':        clevel--;
                         if ((iflev = siflev[clevel]-1) < 0) iflev = 0;
                         ifflg = sifflg[clevel];         put_str();  tabs--;
                         if ((peek = getchr()) == ';') {
                             fprintf(f2,"%c;",c);  peek = -1;
                         }
                         else fprintf(f2,"%c",c);
                         get_nl();  put_str();  fprintf(f2,"\n");  sflg = 1;
                         if (clevel < slevel[level] && level > 0) level--;
                         if (ind[level] != 0) {
                             tabs -= pflg[level];  pflg[level] = ind[level] =
                         }
                         break;

             case '"':
             case '\'':        string[j++] = c;
                         while ((cc = getchr()) != c) {
                             string[j++] = cc;
                             if (cc == '\\') string[j++] = getchr();
                             if (cc == '\n') { put_str();  sflg = 1; }
                         }
                         string[j++] = cc;
                         if (get_nl() == 1) { lchar = cc;  peek = '\n'; }
                         break;

             case ';':        string[j++] = c;  put_str();
                         if (pflg[level] > 0 && ind[level] == 0) {
                             tabs -= pflg[level];  pflg[level] = 0;
                         }
                         get_nl();  put_str();  fprintf(f2,"\n");  sflg = 1;
                         if(iflev > 0 && ifflg == 1){ iflev--;  ifflg = 0; }
                         else iflev = 0;
                         break;

             case '\\':        string[j++] = c;  string[j++] = getchr();  brea

             case '?':        qflg = 1;  string[j++] = c;  break;

             case ':':        string[j++] = c;
                         if (qflg == 1) { qflg = 0;  break; }
                         if (!lookup(wds)) { sflg = 0;  put_str(); }
                         else { tabs--;        put_str();  tabs++; }
                         if ((peek = getchr()) == ';') {
                             fprintf(f2,";");  peek = -1;
                         }
                         get_nl();  put_str();  fprintf(f2,"\n");  sflg = 1;
                         break;

             case '/':        string[j++] = c;
                         if ((peek = getchr()) != '*') break;
                         string[j++] = peek;  peek = -1;         comment();  b

             case ')':        paren--;  string[j++] = c;  put_str();
                         if (get_nl() == 1) {
                             peek = '\n';
                             if (paren != 0) aflg = 1;
                             else if (tabs > 0) {
                                 pflg[level]++;        tabs++;         ind[lev
                             }
                         }
                         break;

             case '#':        string[j++] = c;
                         while ((cc = getchr()) != '\n') string[j++] = cc;
                         string[j++] = cc;  sflg = 0;  put_str();  sflg = 1;
                         break;

             case '(':        string[j++] = c;  paren++;
                         if (lookup(wfor) == 1) {
                             while ((c = get_str()) != ';');
                             ct = 0;
 cont:                            while ((c = get_str()) != ')')
                                 if(c == '(') ct++;
                             if (ct != 0) { ct--;  goto cont; }
                             paren--;  put_str();
                             if (get_nl() == 1) {
                                 peek = '\n';  pflg[level]++;
                                 tabs++;         ind[level] = 0;
                             }
                             break;
                         }
                         if (lookup(wif) == 1) {
                             put_str();
                             stabs[clevel][iflev] = tabs;
                             spflg[clevel][iflev] = pflg[level];
                             sind[clevel][iflev] = ind[level];
                             iflev++;  ifflg = 1;
                         }
         }
     }
     if (f2 != stdout && (ferror(f2) || fclose(f2))) {
         fprintf(stderr,"ERROR:  Disk full\n");        return !0;
     }
     fclose(f1);         return 0;
 }

 void ptabs()
 {
     int i;

     for (i=0; i < tabs; i++) fprintf(f2,"\t");
 }

 int getchr()
 {
     if (peek < 0 && lastchar != ' ' && lastchar != '\t') pchar = lastchar;
     lastchar = (peek < 0) ? getc(f1) : peek;  peek = -1;
     return lastchar;
 }

 void put_str()
 {
     if (j > 0) {
         if (sflg != 0) {
             ptabs();  sflg = 0;
             if (aflg == 1) {
                 aflg = 0;
                 if (tabs > 0) fprintf(f2,"    ");
             }
         }
         string[j] = '\0';  fprintf(f2,"%s",string);  j = 0;
     }
     else if (sflg != 0) { sflg = 0;  aflg = 0; }
 }

 int lookup(tab)
 char *tab[];
 {
     char r;
     int i,kk,k,l;

     if (j < 1) return 0;
     for (kk = 0; string[kk] == ' '; ++kk);
     for (i = 0; tab[i] != 0; i++) {
         l = 0;
         for (k=kk; (r = tab[i][l++]) == string[k] && r != '\0'; ++k);
         if (r == '\0' && (string[k] < 'a' || string[k] > 'z')) return 1;
     }
     return 0;
 }

 int get_str()
 {
     char ch;

 beg:
     if ((ch = string[j++] = getchr()) == '\\') {
         string[j++] = getchr();         goto beg;
     }
     if (ch == '\'' || ch == '"') {
         while ((cc = string[j++] = getchr()) != ch)
             if (cc == '\\') string[j++] = getchr();
         goto beg;
     }
     if (ch == '\n') { put_str();  aflg = 1;  goto beg; }
     else return ch;
 }

 void gotelse()
 {
     tabs = stabs[clevel][iflev];  pflg[level] = spflg[clevel][iflev];
     ind[level] = sind[clevel][iflev];  ifflg = 1;
 }

 int get_nl()
 {
     while ((peek = getchr()) == '\t' || peek == ' ') {
         string[j++] = peek;  peek = -1;
     }
     if ((peek = getchr()) == '/') {
         peek = -1;
         if ((peek = getchr()) == '*') {
             string[j++] = '/';        string[j++] = '*';
             peek = -1;        comment();
         }
         else string[j++] = '/';
     }
     if ((peek = getchr()) == '\n') { peek = -1;         return 1; }
     return 0;
 }

 void comment()
 {
 rep:
     while ((c = string[j++] = getchr()) != '*')
         if (c == '\n') { put_str();  sflg = 1; }
 gotstar:
     if ((c = string[j++] = getchr()) != '/') {
         if (c == '*') goto gotstar;
         goto rep;
     }
 }


 CB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CB2\CB.C

 #define VERS "CB  08/25/83  Vers 1.2 for IBM-PC\n\n"
 /*
         Pretty-printer for C Programs

         Swiped from the CIPG's UNIX system and modified to run
                 under BDS C by William C. Colley, III

         Mods made July 1980

         *** REVISIONS ***

         Modified to run on the IBM-PC with C86 08/16/83  J.E.Will

         Put indent level option in  08/23/83   J.E.Will

         Change interface for single file name, old file is
         renamed .BAK after program terminates. 08/25/83  J.E.Will

         *** END ***

 */

 #include <stdio.h>

 int s_level[10];
 int c_level;
 int sp_flg[20][10];
 int s_ind[20][10];
 int s_if_lev[10];
 int s_if__flg[10];
 int if_lev;
 int if_flg;
 int level;
 int indent;                /* number of spaces to indent */
 static int ind[10] = {
         0,0,0,0,0,0,0,0,0,0};
 int e_flg;
 int paren;
 static int p_flg[10] = {
         0,0,0,0,0,0,0,0,0,0};
 char l_char;
 char p_char;
 int a_flg;
 int ct;
 int s_tabs[20][10];
 int q_flg;
 char *w_if_[2];
 char *w_else[2];
 char *w_for[2];
 char *w_ds[3];
 int j;
 char string[256];
 char cc;
 int s_flg;
 int b_flg;
 int peek;
 int tabs;
 char last_char;
 char c;
 char *w_kptr;

 FILE *inpfil,*outfil,*fopen();

 int comment(), putcoms(), getnl(), gotelse(), get_string(), lookup(),
         indent_puts(), getchr(), p_tabs();

 char *index();

 /* code starts here, Jack */

 main(argc,argv)
 int argc;
 char *argv[];
 {
         int k;
         printf(VERS);                /* tell the world about version */

         /*  Initialize everything here.  */

         if (argc < 2 || argc > 4)
         {
                 printf("Usage:  CB input.fil [indent]\n\n");
                 printf("input.fil  - 'C' input source file in current directo
                 printf("indent         - where 'indent' is a number from 1 to
                 printf("                         to number of spaces for each
                 printf("                         Default 4 if not supplied on
                 printf("NOTES:\n");
                 printf("        - Original source is in input.BAK\n\n");
                 exit(99);
         }

         /* get name and check that it"s not a back-up file */

         strcpy(string,argv[1]);
         if((w_kptr = index(string,'.')) != 0)
         {
                 if ((strcmp(w_kptr,".bak") == 0) || (strcmp(w_kptr,".BAK") ==
                 {
                         printf("Input file can not be a .BAK file!\n");
                         exit(99);
                 }
         }

         if ((inpfil = fopen(argv[1],"r")) == 0)
         {
                 printf("File not found: %s\n",argv[1]);
                 exit(99);
         }

         unlink("CB.$$$");        /* delete any existing temp file */

         if ((outfil = fopen("CB.$$$","wr")) == 0)
         {
                 printf("Could not create CB.$$$, the temp output file\n");
                 exit(99);
         }
         /* process indent option */

         indent = 4;                /* set default indent */

         if (argc == 3)
         {
                 indent = atoi(argv[2]);
                 if ((indent < 1) || (indent > 8))
                 {
                         printf("Indent option value out of range, valid from
                         exit(99);
                 }
         }
         c_level = iflev = level = e_flg = paren = 0;
         a_flg = q_flg = j = b_flg = tabs = 0;
         if_flg = peek = -1;
         s_flg = 1;
         w_if_[0] = "if";
         w_else[0] = "else";
         w_for[0] = "for";
         w_ds[0] = "case";
         w_ds[1] = "default";
         w_if_[1] = w_else[1] = w_for[1] = w_ds[2] = 0;

         /*  End of initialization.  */

         while((c = getchr()) != 032)
         {
         switch(c)
         {
         default:
                 string[j++] = c;
                 if(c != ',')l_char = c;
                 break;
         case ' ':
         case '\t':
                 if(lookup(w_else) == 1)
                 {
                 gotelse();
                 if(s_flg == 0 || j > 0)string[j++] = c;
                 indent_puts();
                 s_flg = 0;
                 break;
                 }
                 if(s_flg == 0 || j > 0)string[j++] = c;
                 break;
         case '\n':
                 if(e_flg = lookup(w_else) == 1)gotelse();
                 indent_puts();
                 fprintf(outfil,"\n");
                 s_flg = 1;
                 if(e_flg == 1)
                 {
                 p_flg[level]++;
                 tabs++;
                 }
                 else
                 if(p_char == l_char)
                         a_flg = 1;
                 break;
         case '{':
                 if(lookup(w_else) == 1)gotelse();
                 s_if_lev[c_level] = iflev;
                 s_if_flg[c_level] = if_flg;
                 if_lev = if_flg = 0;
                 c_level++;
                 if(s_flg == 1 && p_flg[level] != 0)
                 {
                 p_flg[level]--;
                 tabs--;
                 }
                 string[j++] = c;
                 indent_puts();
                 getnl();
                 indent_puts();
                 fprintf(outfil,"\n");
                 tabs++;
                 s_flg = 1;
                 if(p_flg[level] > 0)
                 {
                 ind[level] = 1;
                 level++;
                 s_level[level] = c_level;
                 }
                 break;
         case '}':
                 c_level--;
                 if((if_lev = s_if_lev[c_level]-1) < 0)if_lev = 0;
                 if_flg = s_if_flg[c_level];
                 indent_puts();
                 tabs--;
                 p_tabs();
                 if((peek = getchr()) == ';')
                 {
                 fprintf(outfil,"%c;",c);
                 peek = -1;
                 }
                 else fprintf(outfil,"%c",c);
                 getnl();
                 indent_puts();
                 fprintf(outfil,"\n");
                 s_flg = 1;
                 if(c_level < s_level[level])if(level > 0)level--;
                 if(ind[level] != 0)
                 {
                 tabs -= p_flg[level];
                 p_flg[level] = 0;
                 ind[level] = 0;
                 }
                 break;
         case '"':
         case '\'':
                 string[j++] = c;
                 while((cc = getchr()) != c)
                 {
                 string[j++] = cc;
                 if(cc == '\\')
                 {
                         string[j++] = getchr();
                 }
                 if(cc == '\n')
                 {
                         indent_puts();
                         s_flg = 1;
                 }
                 }
                 string[j++] = cc;
                 if(getnl() == 1)
                 {
                 l_char = cc;
                 peek = '\n';
                 }
                 break;
         case ';':
                 string[j++] = c;
                 indent_puts();
                 if(p_flg[level] > 0 && ind[level] == 0)
                 {
                 tabs -= p_flg[level];
                 p_flg[level] = 0;
                 }
                 getnl();
                 indent_puts();
                 fprintf(outfil,"\n");
                 s_flg = 1;
                 if(if_lev > 0)
                 if(if_flg == 1)
                 {
                         if_lev--;
                         if_flg = 0;
                 }
                 else if_lev = 00;
                 break;
         case '\\':
                 string[j++] = c;
                 string[j++] = getchr();
                 break;
         case '?':
                 q_flg = 1;
                 string[j++] = c;
                 break;
         case ':':
                 string[j++] = c;
                 if(q_flg == 1)
                 {
                 q_flg = 0;
                 break;
                 }
                 if(lookup(w_ds) == 0)
                 {
                 s_flg = 0;
                 indent_puts();
                 }
                 else
                 {
                 tabs--;
                 indent_puts();
                 tabs++;
                 }
                 if((peek = getchr()) == ';')
                 {
                 fprintf(outfil,";");
                 peek = -1;
                 }
                 getnl();
                 indent_puts();
                 fprintf(outfil,"\n");
                 s_flg = 1;
                 break;
         case '/':
                 string[j++] = c;
                 if((peek = getchr()) != '*')break;
                 string[j++] = peek;
                 peek = -1;
                 comment();
                 break;
         case ')':
                 paren--;
                 string[j++] = c;
                 indent_puts();
                 if(getnl() == 1)
                 {
                 peek = '\n';
                 if(paren != 0)a_flg = 1;
                 else if(tabs > 0)
                 {
                         p_flg[level]++;
                         tabs++;
                         ind[level] = 0;
                 }
                 }
                 break;
         case '#':
                 string[j++] = c;
                 while((cc = getchr()) != '\n')string[j++] = cc;
                 string[j++] = cc;
                 s_flg = 0;
                 indent_puts();
                 s_flg = 1;
                 break;
         case '(':
                 string[j++] = c;
                 paren++;
                 if(lookup(w_for) == 1)
                 {
                 while((c = get_string()) != ';');
                 ct=0;
 cont:
                 while((c = get_string()) != ')')
                 {
                         if(c == '(') ct++;
                 }
                 if(ct != 0)
                 {
                         ct--;
                         goto cont;
                 }
                 paren--;
                 indent_puts();
                 if(getnl() == 1)
                 {
                         peek = '\n';
                         p_flg[level]++;
                         tabs++;
                         ind[level] = 0;
                 }
                 break;
                 }
                 if(lookup(w_if) == 1)
                 {
                 indent_puts();
                 s_tabs[c_level][if_lev] = tabs;
                 sp_flg[c_level][if_lev] = p_flg[level];
                 s_ind[c_level][if_lev] = ind[level];
                 if_lev++;
                 if_flg = 1;
                 }
         }
         }

         /* eof processing */

         fprintf(outfil,"\032");        /* throw in an EOF mark */
         fclose(outfil);
         fclose(inpfil);

         /* get origional name with a .BAK on it */

         strcpy(string,argv[1]);
         if((w_kptr = index(string,'.')) == 0)
         strcat(string,".BAK");
         else
         strcpy(w_kptr,".BAK");
         unlink(string);                /* kill any .BAK file */
         rename(argv[1],string);        /* origional is now .BAK */
         rename("CB.$$$",argv[1]);        /* new now has origional name */
         exit(0);                        /* normal exit */
 }
 /* expand indent into tabs and spaces */
 p_tabs()
 {
         int i,j,k;

         i = tabs * indent;                /* calc number of spaces */
         j = i/8;                        /* calc number of tab chars */
         i -= j*8;                        /* calc remaining spaces */

         for (k=0;k < j;k++) fprintf(outfil,"\t");
         for (k=0;k < i;k++) fprintf(outfil," ");
 }
 /* get character from stream or return the saved one */
 getchr()
 {
         if(peek < 0 && last_char != ' ' && last_char != '\t')p_char = last_ch
         last_char = (peek<0) ? getc(inpfil):peek;
         if (last_char == -1) last_char = 0x1a;
         peek = -1;
         return(last_char == '\r' ? getchr():last_char);
 }
 /* put string with indent logic */
 indent_puts()
 {
         if(j > 0)
         {
         if(s_flg != 0)
         {
                 if((tabs > 0) && (string[0] != '{') && (a_flg == 1)) tabs++;
                 p_tabs();
                 s_flg = 0;
                 if((tabs > 0) && (string[0] != '{') && (a_flg == 1)) tabs--;
                 a_flg = 0;
         }
         string[j] = '\0';
         fprintf(outfil,"%s",string);
         j = 0;
         }
         else
         {
         if(s_flg != 0)
         {
                 s_flg = 0;
                 a_flg = 0;
         }
         }
 }
 /* search table for character string and return index number */
 lookup(tab)
 char *tab[];
 {
         char r;
         int l,kk,k,i;
         if(j < 1)return(0);
         kk=0;
         while(string[kk] == ' ')kk++;
         for(i=0; tab[i] != 0; i++)
         {
         l=0;
         for(k=kk;(r = tab[i][l++]) == string[k] && r != '\0';k++);
         if(r == '\0' && (string[k] < 'a' || string[k] > 'z'))return(1);
         }
         return(0);
 }
 /* read string between double quotes */
 get_string()
 {
         char ch;
 beg:
         if((ch = string[j++] = getchr()) == '\\')
         {
         string[j++] = getchr();
         goto beg;
         }
         if(ch == '\'' || ch == '"')
         {
         while((cc = string[j++] = getchr()) != ch)
       if(cc == '\\')
          string[j++] = getchr();
         goto beg;
         }
         if(ch == '\n')
         {
         indent_puts();
         a_flg = 1;
         goto beg;
         }
         else return(ch);
 }
 /* else processing */
 gotelse()
 {
         tabs = s_tabs[c_level][if_lev];
         p_flg[level] = sp_flg[c_level][if_lev];
         ind[level] = s_ind[c_level][if_lev];
         if_flg = 1;
 }
 /* read to new_line */
 getnl()
 {
         while((peek = getchr()) == '\t' || peek == ' ')
         {
         string[j++] = peek;
         peek = -1;
         }
         if((peek = getchr()) == '/')
         {
         peek = -1;
         if((peek = getchr()) == '*')
         {
                 string[j++] = '/';
                 string[j++] = '*';
                 peek = -1;
                 comment();
         }
         else string[j++] = '/';
         }
         if((peek = getchr()) == '\n')
         {
         peek = -1;
         return(1);
         }
         return(0);
 }
 /* special edition of put string for comment processing */
 putcoms()
 {
         if(j > 0)
         {
         if(s_flg != 0)
         {
                 p_tabs();
                 s_flg = 0;
         }
         string[j] = '\0';
         fprintf(outfil,"%s",string);
         j = 0;
         }
 }
 /* comment processing */
 comment()
 {
 rep:
         while((c = string[j++] = getchr()) != '*')
         if(c == '\n') putcoms();

 gotstar:
         if((c = string[j++] = getchr()) != '/')
         {
         if(c == '*') goto gotstar;
         if(c == '\n') putcoms();
         goto rep;
         }
 }


 char *index(s, c)
 char *s;
 char c;
 {
         while(*s != c) s++;
         return s;
 }


 CBRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\CBRT.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathcons.h"

 /*
 Reference: See J. F. Hart, E. W. Cheney, C. L. Lawson, H. J. Maehly,
 C. K. Mesztenyi, J. R. Rice, H. C. Thacher, Jr., and C. Witzgall,
 COMPUTER APPROXIMATIONS, John Wiley & Sons, Inc., New York, NY, 1968.
 */

 /************************************************************************/
         double
 cbrt(x)                        /* return cube root of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double fx, yn, frexp(), ldexp();
         int n, ex, sgn;

         if (x IS 0.0)
                 return x;

         sgn = (x < 0.0 ? 1 : 0);
         if (sgn)
                 x = -x;
         fx = frexp(x, &ex);                /* frac x and exp x
         yn = 0.59130052 + 0.41533799 * fx;
                 /* See Chapter 7, Table 640 of Reference. Has err=2.1 D */
         yn = ldexp((yn + 1.5 * fx / (yn * yn + ldexp(fx, -1) / yn)), -1);
                 /* See Newton iteration formula 6.1.13 of Reference,        *
         yn -= ldexp((yn - 1.5 * fx / (yn * yn + ldexp(fx, -1) / yn)), -1);
                 /* after two iterations, err = 19 D, without roundoff

         n = (ex % 3);
         ex -= n;                /* ex now divisible by 3                */
         if (n < 0)                /* must compensate if negative
         {        n += 3;
                 ex -= 3;
         }
         if (n IS 1)
                 yn *= CBRTTWO;
         else if (n IS 2)
                 yn *= CBRTFOUR;
         yn = ldexp(yn, ex/3);
         return (sgn ? -yn : yn);
 }


 CC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\BISICC\CC.C

 /*                cc.c                program to simulate (sortof) the cc com

                 usage:        cc [flags] file ...
                         flags:        all C86 flags are passed thru directly

                                 -c                        compile only, don't
                                 -lpath        path/name of new lib to add to
                                 -C                        nested comments (-c
                                 -o file        name of output.exe, assumed fi
                                 -M file        name of map file (linker)
                                 -H                 /h option (linker)
                                 -D                        /d option (linker)
                                 -L                        /l option (linker)
                                 -P                        /p option (linker)
                                 -S size        /s option (linker)
                                 -A                        /a option (assemble
                                 -B                        /d option (assemble
                                 -E                        /e option (assemble
                                 -N                        /n option (assemble
                                 -O                        /o option (assemble
                                 -R                        /r option (assemble
                                 -F                        /X        option (a
                                 -X name        name for CREF file (assembler)

                                 may have multiple files in list and they can
                                 wildcards.
 */

 #include <stdio.h>
 #include <ctype.h>

 #define TRUE -1
 #define FALSE 0
 /* flags */
 /* internal */
 int link=TRUE;
 char libs[255] = "\0";
 /* compiler */
 int cf1=FALSE;
 int cf2=FALSE;
 int cfa=FALSE;
 int cfb=FALSE;
 int cfc=FALSE;
 char cfd[255];
 int cfe=FALSE;
 int cfh=FALSE;
 int cfi=FALSE;
 int cfj=FALSE;
 int cfn=FALSE;
 int cfp=FALSE;
 int cfs=FALSE;
 int cft=FALSE;
 int cfu=FALSE;
 /* linker */
 int lfh=FALSE;
 int lfd=FALSE;
 int lfl=FALSE;
 int lfp=FALSE;
 int lfs=FALSE;
 /* assembler */
 int afa=FALSE;
 int afb=FALSE;
 int afe=FALSE;
 int afn=FALSE;
 int afo=FALSE;
 int afr=FALSE;
 int aff=FALSE;

 char outfile[255] = "\0";
 char mapfile[255] = "\0";
 char creffile[255] = "\0";

 char biglib[255] = "/lib/c86b2s.lib";
 char smllib[255] = "/lib/c86s2s.lib";
 char include[255] = "/lib/";

 char copts[255] = "\0";
 char aopts[255] = "\0";
 char lopts[255] = "\0";

 main(ac,av)
 int ac;
 char *av[];
 {
         char *s;
         char *ts;
         int i,nd,j,nf;
         char *filelist[30];
         char tstr[255];
         char *first,*next;
         char *switchar();

         nd=0;
         while(--ac > 0 && (*++av)[0] == '-') {
                 for (s = av[0]+1; *s != '\0'; s++) {
                         switch (*s) {
                         case '1':                /* 80186 code */
                                 cf1=TRUE;
                                 strcat(copts,"-1");
                                 break;
                         case '2':                /* 80286 code */
                                 cf2=TRUE;
                                 strcat(copts,"-2");
                                 break;
                         case 'a':                /* gen asm */
                                 cfa=TRUE;
                                 strcat(copts,"-a ");
                                 break;
                         case 'A':                /* */
                                 afa=TRUE;
                                 strcat(aopts,switchar());
                                 strcat(aopts,"A");
                                 break;
                         case 'b':                /* big model */
                                 cfb=TRUE;
                                 strcat(copts,"-b ");
                                 break;
                         case 'B':                /* both passes */
                                 afb=TRUE;        /* gens a -D */
                                 strcat(aopts,switchar());
                                 strcat(aopts,"D");
                                 break;
                         case 'c':                /* compile only */
                                 link = FALSE;
                                 break;
                         case 'C':                /* nested comments */
                                 cfc=TRUE;
                                 strcpy(copts,"-c ");
                                 break;
                         case 'd':                /* compiler define */
                                 ts = ++s;
                                 while(*++s != ' ');
                                 *s++ = '\0';
                                 strcpy(cfd,ts);
                                 strcat(copts,"-d ");
                                 strcat(copts,cfd);
                                 strcat(copts," ");
                                 break;
                         case 'D':                /* */
                                 lfd=TRUE;
                                 strcat(lopts,switchar());
                                 strcat(lopts,"D");
                                 break;
                         case 'e':                /* */
                                 cfe = TRUE;
                                 strcat(copts,"-e ");
                                 break;
                         case 'E':
                                 afe=TRUE;
                                 strcat(aopts,switchar());
                                 strcat(aopts,"E");
                                 break;
                         case 'F':
                                 aff=TRUE;        /* to /x */
                                 strcat(aopts,switchar());
                                 strcat(aopts,"X");
                                 break;
                         case 'h':
                                 ts=++s;
                                 cfh = TRUE;
                                 while(*++s != ' ');
                                 *s++ = '\0';
                                 strcat(copts,"-h");
                                 strcat(copts,ts);
                                 break;
                         case 'H':
                                 lfh=TRUE;
                                 strcat(lopts,switchar());
                                 strcat(lopts,"H");
                                 break;
                         case 'i':
                                 cfi=TRUE;
                                 strcat(copts,"-i ");
                                 break;
                         case 'j':
                                 ts=++s;
                                 *++s = '\0';
                                 strcat(copts,"-j");
                                 strcat(copts,ts);
                                 strcat(copts," ");
                                 break;
                         case 'l':
                                 ts=++s;
                                 while(*++s != ' ');
                                 *s++ = '\0';
                                 strcat(libs,ts);
                                 strcat(libs,"+");
                                 break;
                         case 'L':
                                 lfl=TRUE;
                                 strcat(lopts,switchar());
                                 strcat("L");
                                 break;
                         case 'M':
                                 ts=++s;
                                 while (*++s != ' ');
                                 *s++ = '\0';
                                 strcpy(mapfile,ts);
                                 break;
                         case 'n':
                                 cfn=TRUE;
                                 strcat(copts,"-n ");
                                 break;
                         case 'o':
                                 ts=++s;
                                 while (*++s != ' ');
                                 *s++ = '\0';
                                 strcpy(outfile,ts);
                                 break;
                         case 'O':
                                 afo=TRUE;
                                 strcat(aopts,switchar());
                                 strcat(aopts,"O");
                                 break;
                         case 'p':
                                 cfp=TRUE;
                                 strcat(copts,"-p ");
                                 break;
                         case 'P':
                                 lfp=TRUE;
                                 strcat(lopts,switchar());
                                 strcat(lopts,"P");
                                 break;
                         case 'R':
                                 afr=TRUE;
                                 strcat(aopts,switchar());
                                 strcat(aopts,"R");
                                 break;
                         case 's':
                                 cfs=TRUE;
                                 strcat(copts,"-s ");
                                 break;
                         case 't':
                                 cft=TRUE;
                                 strcat(copts,"-t ");
                                 break;
                         case 'u':
                                 cfu=TRUE;
                                 strcat(copts,"-u ");
                                 break;
                         case 'X':
                                 ts=++s;
                                 while (*++s != ' ');
                                 *s++ = '\0';
                                 strcpy(creffile,ts);
                         }
                 }
         }
         if (ac < 1) usage();                                        /* not en

         readenv();

         if (!cfh) {
                 strcat(copts,"-h");                                /* if they
                 strcat(copts,include);
         }
         for (i=0;i<30;i++)
                 filelist[i] = alloc(128);                /* grab space for th

         /* parse off filenames */

         for (i=nf=0;i<ac;i++) {
                 if (strchr(av[i],'*') || strchr(av[i],'?')) {         /* any
                         strcpy(tstr,av[i]);
                         first = filedir(tstr,0);
                         for(next=first;*next != '\0';) {
                                 strcpy(filelist[nf++],lower(next));
                                 next += strlen(next)+1;
                         }
                         free(first);
                 }
                 else {
                         strcpy(filelist[nf++],lower(av[i]));
                 }
         }

         /* now have a list of files to compile, assemble and/or link */
         /* test them for validity and compile them */

         for (i=0;i<nf;i++) {
                 if (!(ts=strrchr(filelist[i],'.'))) {        /* no ext? */
                         strcat(filelist[i],".c");
                 }
                 if (strcmp(strrchr(filelist[i],'.'),".c")==0) {
                         _cc(filelist[i]);
                 }
                 else if (strcmp(strrchr(filelist[i],'.'),".asm")==0)        {
                         _as(filelist[i]);
                 }
                 else if (strcmp(strrchr(filelist[i],'.'),".obj")!=0) {
                         fputs(filelist[i],stderr);
                         fubar("invalid file type ",filelist[i]);
                 }
         }

         /* done compiling/assembling, time to link */

         if (link) {
                 if (*outfile == '\0') {
                         strcpy(outfile,filelist[0]);                /* assume
                         ts = strrchr(outfile,'.');
                         *ts = '\0';
                 }
                 _link(outfile,filelist,nf);
         }
         puts("\ndone.");
         exit(0);
 }

 char *switchar()
 {
         struct regs {int ax,bx,cx,dx,si,di,ds,es; } r;
         char t[3];

         r.ax = 0x3700;
         r.dx = 0;
         sysint21(&r,&r);
         t[0] = r.dx&0xff;
         t[1] = '\0';
         return(t);
 }

 _cc(file)                        /* compile file with current options */
 char *file;
 {
         static char *passes[] = {"cc1 ","cc2 ","cc3 ","cc4 ","\0"};
         int i,fr;
         char comlin[255];
         char ts[255];

         for (i=0;*passes[i] != '\0';i++) {
                 strcpy(comlin,passes[i]);                /* get pass */
                 if (i==0) {
                         strcat(comlin,copts);                        /* add o
                         strcat(comlin," ");
                 }
                 strcat(comlin,file);
                 puts(comlin);
                 fr=fork(comlin);
                 if (fr) {
                         fubar("error compiling: ",file);
                 }
         }
 }

 _as(file)                        /* assemble file with current options */
 char *file;
 {
         char comlin[255];
         char ts[255];
         int fr;

         strcpy(comlin,"masm ");
         strcat(comlin,file);
         strcat(comlin,",,");
         if (*creffile != '\0') strcat(comlin,creffile);
         else strcat(comlin,",");
         strcat(comlin,aopts);
         strcat(comlin,";");
         puts(comlin);
         if ((fr=fork(comlin)))        {
                 fubar("error assembling ",file);
         }
 }

 _link(out,filelist,nf)                /* link the files in filelist into out
 char *out;
 char *filelist[];
 int nf;
 {
         char comlin[255];
         int i,fr;
         char *ts;

         strcpy(comlin,"link ");
         for (i=0;i<nf;i++) {
                 ts = strchr(filelist[i],'.');
                 *ts = '\0';
                 strcat(comlin,filelist[i]);
                 if (i < nf-1)                                        /* don't
                         strcat(comlin,"+");                /* plus on last fi
         }
         strcat(comlin,",");
         strcat(comlin,out);
         strcat(comlin,",");
         if (*mapfile != '\0')
                 strcat(comlin,mapfile);
         strcat(comlin,",");
         if (libs[0] != '\0')                        /* any user libs? */
                 strcat(comlin,libs);                /* add them */
         if (cfb)                                                 /* big model
                 strcat(comlin,biglib);        /* add system library */
         else
                 strcat(comlin,smllib);
         strcat(comlin,lopts);                /* add linker options */
         strcat(comlin,";");
         puts(comlin);
         fr=fork(comlin);
         if (fr) {
                 fubar("error linking");
         }
 }

 readenv()                        /* reads the environment variables */
 {
         struct {int ax,bx,cx,dx,si,di,ds,es;} r;
         char *ep,*envfind();

         if (ep = envfind("CCBLIB")) {
                 strcpy(biglib,ep);
                 free(ep);
         }
         if (ep = envfind("CCSLIB")) {
                 strcpy(smllib,ep);
                 free(ep);
         }
         if (ep = envfind("CCINCLUDES")) {
                 strcpy(include,ep);
                 free(ep);
         }
 }

 fubar(s,s2)
 char *s;
 char *s2;
 {
         fputs("cc: ",stderr);
         fputs(s,stderr);
         puts(s2);
         exit(1);
 }

 usage()
 {
 puts("        usage: cc [flags] file ...");
 puts("        flags: all C86 flags are passed thru directly except -c.");
 puts("        ");
 puts("        -c      compile only, don't link
 puts("   -lpath  path/name of library to add to lib list");
 puts("        -C      nested comments (-c for compiler)");
 puts("        -ofile  name of output.exe, assumed first name in list");
 puts("        -Mfile  name of map file (linker)");
 puts("        -H      /h option (linker)");
 puts("        -D      /d option (linker)");
 puts("        -L      /l option (linker)");
 puts("        -P      /p option (linker)");
 puts("        -Ssize  /s option (linker)");
 puts("        -A      /a option (assembler)");
 puts("        -B      /d option (assembler)");
 puts("        -E      /e option (assembler)");
 puts("        -N      /n option (assembler)");
 puts("        -O      /o option (assembler)");
 puts("        -R      /r option (assembler)");
 puts("        -F      /X option (assembler)");
 puts("        -Xname  name for CREF file (assembler)");
 puts("");
 puts("        may have multiple files in list and they can contain");
 puts("        wildcards.");
 puts("");
 exit(1);
 }


 CCHECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CCHECK\CCHECK.C

 /*
  * CCHECK.C -- Aztec C Version of CCHK, 06/23/85
  *
  *
  * Copyright: The Regents of the University of California
  *   [Note - since Steve Draper distributed cchk.c over
  *    Usenet, I assume it's effectively in the public
  *    domain. JCM]
  *
  * Title:  ccheck
  *
  * Purpose: To find and report all badly matched openers and
  *   closers plus assignment/equality confusions
  *   in a c source file.
  *
  * Author:  Steve Draper, expanding cnest by Tom Anderson
  *
  * Usage:  ccheck [-q] [-v] <filename1> <filename2> ...
  *
  * History (in reverse order to minimize reading time for updates):
  *
  *   June 18, 1985  Converted to Aztec C - removed BDS C code  -  Rick Moore
  *
  *   January 9, 1983  Single BDS/UNIX source created
  *      as CCHECK.C  -- Jeff Martin
  *
  *   December 29, 1982 Adapted for BDS C --
  *       Jeff Martin at home.
  *
  *   December 20, 1982 Converted to cchk --
  *       Steve Draper at UCSD
  *
  *   December 9, 1982 Jeffrey Mogul at Stanford
  *    - checks for unclosed comment at end of file.
  *
  *   December 3, 1982 creation date --
  *      Tom Anderson at microsof!fluke
  */

 #include <stdio.h>
 #include <ctype.h>

 #define TRUE 1
 #define FALSE 0
 #define SPACE 32

 #define BRACE 1
 #define SQBRAK  2
 #define PAREN 3
 #define IF 4
 #define IFCOND 5
 #define WHLCOND 6
 #define THEN 7
 #define ELSE 8

 #define STACKSIZ 64

 struct brak {
     int type, b_indent, b_ln;
 } stack[STACKSIZ];

 #define rmbrak(N) (top -= N, stackc -= N)
 #define myungetc(C)  ungetc(((C) == '\n' ? SPACE : (C)), infile)

 #define VFLAG "-v"
 #define QFLAG "-q"
 #define SFLAG "-s"

 int firsttime; /* This was a static in mygetchar() */

 int mygetchar(), pr();
 void checkelse(), newbrak(), checkcloser(), prtype();

 FILE *infile;
 int ln, indent, commindent, stackc, commln;
 int singlequoterr, oddsinglequote, bracecnt, parencnt, sqbrakcnt;
 int errstatus, wstatus;
 int errnmb, wnmb;
 int verbose;
 char *filename;
 struct brak *top;

 main(argc, argv)
 unsigned argc ;
 char *argv[] ;
 {
     register int c ;
     int i;
     int doubleqflag;
     unsigned file_index;

     wnmb = 0;
     verbose = 0;
     file_index = 1;

     while (argc > 1  &&  argv[file_index][0] == '-') {
         if (strcmp(argv[file_index], VFLAG) == 0)
             verbose++;
         if (strcmp(argv[file_index], QFLAG) == 0)
             wnmb = -2;
         if (strcmp(argv[file_index], SFLAG) == 0)
             wnmb = -2;
         file_index++;
         argc--;
     }

     do {
         /* INIT for each file */
         firsttime = 1;
         doubleqflag = 0;
         errstatus = wstatus = 0;
         ln = 1;
         indent = 0;
         commindent = 0;
         singlequoterr = oddsinglequote = parencnt = sqbrakcnt = bracecnt =
           0;
         errnmb = 0;
         if (wnmb > -2)
             wnmb = 0;
         newbrak(0);

         if (argc == 1) {
             infile = stdin;
             filename = NULL;
         } else {
             if ((infile = fopen(argv[file_index], "r")) == (FILE * ) NULL) {
                 fprintf (stdout, "%s: Can't access %s\n", argv[0], argv[file_
                 continue;
             }
             filename = argv[file_index];
         }

         while ( ( c = mygetchar()) !=  EOF ) {
             if (verbose == 2) {
                 for (i = stackc; i > 0; i--) {
                     printf("%c %d: type ", c, i);
                     prtype(stack[i].type);
                     printf(", indent %d, line %d.\n", stack[i].b_indent, stac
                 }
             }

             switch (c) {
             case ';':
                 ungetc(SPACE, infile);
                 while (top->type == ELSE)
                     rmbrak(1);
                 if (top->type == THEN) {
                     rmbrak(1);
                     checkelse();
                 }
                 break;

             case '!':
             case '>':
             case '<':
                 /* swallow legit. '=' chars */
                 c = mygetchar();
                 if (c != '=')
                     myungetc(c);
                 break;

             case '=':
                 if ((top - 1)->type == IFCOND  ||  (top - 1)->type == WHLCOND
                     c = mygetchar();
                     if (c != '=') {
                         myungetc(c);
                         if (pr(1))
                             printf("Assignment instead of equals in condition
                                ln);
                     }
                 }
                 break;

             case '\n':
             case SPACE:
                 c = mygetchar();
                 switch (c) {
                 case 'i':
                     /* if */
                     c = mygetchar();
                     if (c == 'f'
                       && !isalpha(c = fgetc(infile)) && !isdigit(c)) {
                         ungetc(c, infile);
                         newbrak(IF);
                         while ((c = mygetchar()) == SPACE ||  c == '\n')
                             ;
                         if (c != '(') {
                             if (pr(1))
                                 printf("Bad if (no condition) line %d.\n",
                                    ln);
                             rmbrak(1);
                         } else
                             newbrak(IFCOND);
                         myungetc(c);
                     } else
                         myungetc(c);
                     break;
                 case 'w':
                     /* while */
                     if ((c = mygetchar()) == 'h'
                       &&  (c = mygetchar()) == 'i'
                       &&  (c = mygetchar()) == 'l'
                       &&  (c = mygetchar()) == 'e'
                       &&  !isalpha(c = fgetc(infile))  &&  !isdigit(c)) {
                         ungetc(c, infile);
                         while ((c = mygetchar()) == SPACE ||  c == '\n')
                             ;
                         if (c != '(') {
                             if (pr(1))
                                 printf("Bad while (no condition) line %d.\n",
                                    ln);
                         } else
                             newbrak(WHLCOND);
                         myungetc(c);
                     } else
                         myungetc(c);
                     break;
                 case 'e':
                     /* else */
                     myungetc(c);
                     checkelse();
                     break;

                 default:
                     myungetc(c);
                     break;
                 }
                 break;

             case '*':
                 /* close comment ? */
                 c = mygetchar();
                 if (c != '/') {
                     myungetc(c);
                     break;
                 }

                 if (pr(1))
                     printf
                       ("Line %d: Comment close without open, indent %d\n",
                       ln, indent);

                 break;

             case '\'':
                 if ((c = fgetc(infile)) != '\\') {
                     if (c == '\''  ||  (c = fgetc(infile)) != '\'') {
                         if (pr(1))
                             printf("Bad character constant line %d\n", ln);
                         singlequoterr = 1;
                     }
                 } else if (!isdigit(c = fgetc(infile))) {
                     if ((c = fgetc(infile)) != '\'') {
                         if (pr(1))
                             printf("Bad character constant with \\ line %d\n"
                                ln);
                     }
                 } else {
                     if (isdigit(c = fgetc(infile)))
                         if (isdigit(c = fgetc(infile)))
                             c = fgetc(infile);
                     if (c != '\'')
                         if (pr(1))
                             printf("Bad character constant with \\0 line %d\n
                                ln);
                 }

                 if (c != '\'') {
                     ungetc(c, infile);
                     oddsinglequote = !oddsinglequote;
                     singlequoterr = 1;
                 }
                 break;

             case '"':
                 do {
                     c = fgetc(infile);
                     if (c == EOF) {
                         if (pr(2))
                             printf("Error: '\"' quoted string not ended by en
                         break;
                     } else if (c == '\n') {
                         if (doubleqflag == 0)
                             if (pr(0))
                                 printf("Warning: '\"' quoted string not ended
                                    ln);
                         doubleqflag = 1;
                         ln++;
                     } else if (c == '\\') {
                         c = SPACE;
                         fgetc(infile);
                     }
                 } while (c != '"');
                 doubleqflag = 0;
                 break;

             case '{':
                 if (stackc  &&  indent < top->b_indent)
                     if (pr(0))
                         printf("Indent jumps backwards line %d.\n", ln);
                 newbrak(BRACE);
                 break;

             case '}':
                 checkcloser(BRACE);
                 while (top->type == ELSE)
                     rmbrak(1);
                 if (top->type == THEN) {
                     rmbrak(1);
                     checkelse();
                 }
                 break;

             case '(':
                 if (stackc  &&  indent < top->b_indent)
                     if (pr(0))
                         printf("Indent jumps backwards line %d.\n", ln);
                 newbrak(PAREN);
                 break;

             case ')':
                 checkcloser(PAREN);
                 if (top->type == IFCOND) {
                     rmbrak(1);
                     newbrak(THEN);
                 } else if (top->type == WHLCOND)
                     rmbrak(1);
                 break;

             case '[':
                 if (stackc  &&   indent < top->b_indent)
                     if (pr(0))
                         printf("Indent jumps backwards line %d.\n", ln);
                 newbrak(SQBRAK);
                 break;

             case ']':
                 checkcloser(SQBRAK);
                 break;

             default:
                 break;

             }
         }

         fclose(infile);

         while (stackc > 0) {
             pr(2);
             fputs("Unclosed brak at EOF: ", stdout);
             prtype(top->type);
             printf(" opened on line %d.\n", top->b_ln);
             switch (top->type) {
             case BRACE:
                 bracecnt++;
                 break;
             case SQBRAK:
                 sqbrakcnt++;
                 break;
             case PAREN:
                 parencnt++;
                 break;
             default:
                 break;
             }
             rmbrak(1);
         }

         if ((i = (oddsinglequote || bracecnt || sqbrakcnt || parencnt)) ||
           errstatus) {
             pr(2);
             printf("Summary:\n");
         } else {
             if (filename != NULL) {
                 fputs(filename, stdout);
                 fputs(": ", stdout);
             }
             printf(" OK\n");
         }
         if (oddsinglequote)
             printf("\tOdd number of single quotes.\n");
         if (bracecnt)
             printf("\t%d too few %s braces.\n", abs(bracecnt), (bracecnt >
               0 ? "closing" : "opening"));
         if (sqbrakcnt)
             printf("\t%d too few %s square brackets.\n", abs(sqbrakcnt), (sqb
               > 0 ? "closing" : "opening"));
         if (parencnt)
             printf("\t%d too few %s parentheses.\n", abs(parencnt), (parencnt
               > 0 ? "closing" : "opening"));
         if (errstatus && !i)
             printf("\tPossible error(s), but no net delimiter imbalance.\n");
         putchar('\n');
     } while (++file_index < argc);

     exit(errstatus ? 2 : wstatus);
 }

 int mygetchar()
 {
     register int c;

     c = fgetc(infile);

     /*
     if (c == ';') {
  ungetc(SPACE, infile);
  return(';');
     }
     */
     if (c == '/') {    /* open comment ? */
         c = fgetc(infile);
         if (c != '*') {
             ungetc(c, infile);
             return('/');
         }
         commln = ln;
         commindent = indent;

         while (1) {
             c = fgetc(infile);

             if (c == EOF) {   /* last comment never ended */
                 if (pr(2))
                     printf
                       ("Comment opened line %d unclosed by end of file.\n",
                       commln);
                 break; /* Get out of this loop! */
             } else if (c == '/') {  /* nested comment ? */
                 if ((c = fgetc(infile)) == '*') {
                     if (pr(0))
                         fprintf(stdout,
                           "Nested comment: line %d, indent %d.  First open: l
                              ln, indent, commln, commindent);
                 } else
                     ungetc(c, infile);
             } else if (c == '*') {  /* end comment ? */
                 if ((c = fgetc(infile)) == '/') {
                     if (indent != commindent  &&  indent - 1 != commindent)
                         if (pr(0))
                             printf(
                               "Indent of comment close doesn't match open: li
                                      commln, ln, commindent, indent);

                     break;    /* only exit from loop, except EOF */
                 } else
                     ungetc(c, infile);
             } else if (c == '\n') {
                 do {
                     if (c == SPACE)
                         indent++;
                     else if (c == '\t')
                         indent = ((indent + 8) / 8) * 8;
                     else if (c == '\n') {
                         ln++;
                         indent = 0;
                     }
                 } while (isspace(c = fgetc(infile)));
                 ungetc(c, infile);
             }
         }
         return(SPACE);

     }

     if (c == '\n'  ||  firsttime == 1) {
         firsttime = 0;
 lf:
         while (1) {
             if (c == SPACE)
                 indent++;
             else if (c == '\t')
                 indent = ((indent + 8) / 8) * 8;
             else if (c == '\n') {
                 ln++;
                 indent = 0;
                 singlequoterr = 0;
             } else {
                 ungetc(c, infile);
                 return('\n');
                 /*NOTREACHED*/
                 break;
             }
             c = fgetc(infile);
         }
     }

     if (c == SPACE  ||  c == '\t') {
         do
             c = fgetc(infile);
         while (c == SPACE  ||  c == '\t');
         if (c != '\n') {
             ungetc(c, infile);
             return(SPACE);
         } else
             goto lf;
     }
     return(c);
 }

 /*
  * administer count of error msgs. and suppress if too many
  * administer the status var.s
  * prepend file name to msg.
  * flag error msg.s (not warnings) with '*'
  */
 int pr(error)
 int error;
 {
     int i;

     if (singlequoterr)
         return(0);

     if (verbose) {
         for (i = stackc; i > 0; i--) {
             printf("%d: type ", i);
             prtype(stack[i].type);
             printf(", indent %d, line %d.\n", stack[i].b_indent, stack[i].b_l
         }
     }

     if (error == 2) {
         errnmb = 0;
         errstatus = 1;
     } else if (error) {
         errstatus = 1;
         if (errnmb < 0)
             return(0);
         else if (errnmb >= 9) {
             errnmb = -1;
             printf("Other error messages being suppressed.\n");
             return(0);
         }
     } else {
         wstatus = 1;
         if (wnmb < 0)
             return(0);
         else if (errnmb + wnmb >= 9) {
             wnmb = -1;
             puts("Further warning messages being suppressed.\n");
             return(0);
         }
     }

     if (filename != NULL) {
         fputs(filename, stdout);
         fputs(": ", stdout);
     }
     if (error)
         putchar('*');
     if (error)
         errnmb++;
     else
         wnmb++;
     return(1);
 }

 void newbrak(newtype)
 int newtype;
 {
     if (newtype == 0) {
         top = stack;
         stackc = 0;
     } else {
         top++;
         stackc++;
     }
     if (stackc >= STACKSIZ) {
         if (pr(2))
             printf("***stack overflow, line %d.\n", ln);
         exit(3);
     }

     top->type = newtype;
     top->b_indent = indent;
     top->b_ln = ln;

 }

 void prtype(typ)
 int typ;
 {
     switch (typ) {
     case BRACE:
         putchar('}');
         break;
     case PAREN:
         putchar(')');
         break;
     case SQBRAK:
         putchar(']');
         break;
     case IF:
         fputs("if", stdout);
         break;
     case IFCOND:
         fputs("if-condition", stdout);
         break;
     case THEN:
         fputs("then", stdout);
         break;
     case ELSE:
         fputs("else", stdout);
         break;
     case WHLCOND:
         fputs("while-condition", stdout);
         break;
     default:
         fputs("'NULL'", stdout);
         break;
     }
 }

 void checkcloser(typ)
 int (typ);
 {
     int i, found;

     i = found = 0;
     if (typ == top->type  &&  top->b_indent == indent) {
         rmbrak(1);
         return;
     }

     while (!found  &&  ++i < stackc  &&  indent <= (top - i)->b_indent)
         if (typ == (top - i)->type  &&  (top - i)->b_indent == indent)
             found = 1;

     if (found) {
         if (pr(1))
             printf("Missing closer%s detected line %d:\n", (i > 1 ? "s" :
               ""), ln);
         while (i--) {
             if (pr(1)) {
                 fputs("\tMissing closing ", stdout);
                 prtype(top->type);
                 printf(" opened line %d.\n", top->b_ln);
             }
             switch (top->type) {
             case BRACE:
                 bracecnt++;
                 break;
             case SQBRAK:
                 sqbrakcnt++;
                 break;
             case PAREN:
                 parencnt++;
                 break;
             default:
                 break;
             }
             rmbrak(1);
         }
         rmbrak(1); /* the matching brak */
     } else if (typ == top->type) {
         if (indent != top->b_indent) {
             if (pr(0)) {
                 fputs("Mismatched indent on closing ", stdout);
                 prtype(typ);
                 printf
                   (" lines %d, %d; indents %d, %d.\n",
                   top->b_ln, ln, top->b_indent, indent);
             }
         }
         rmbrak(1);
     }
       else {
         switch (typ) {
         case BRACE:
             bracecnt--;
             break;
         case SQBRAK:
             sqbrakcnt--;
             break;
         case PAREN:
             parencnt--;
             break;
         default:
             break;
         }

         if (pr(1)) {
             fputs("Muddle detected at unmatched closing ", stdout);
             prtype(typ);
             printf(" line %d.\n", ln);
         }
     }
 }

 /*
  * removes IF from stack
  * checks else's indent
  */
 void checkelse()
 {
     int c;

     while ((c = mygetchar()) == SPACE  || c == '\n')
         ;
     if (c == 'e'
       &&  (c = mygetchar()) == 'l'
       &&  (c = mygetchar()) == 's'
       &&  (c = mygetchar()) == 'e'
       &&  !isalpha(c = fgetc(infile))  &&  !isdigit(c)) {
         ungetc(c, infile);
         if (top->type == THEN)
             rmbrak(1);
         if (top->type != IF) {
             if (pr(1))
                 printf("Else with no if line %d.\n", ln);
         }
           else if (indent + 2 < top->b_indent) {
             if (pr(1))
                 printf("Dangling else -- bound to wrong if?  \"if\" line %d,
                    top->b_ln, ln);
         }
           else if (indent != top->b_indent) {
             if (pr(0)) {
                 fputs("Wrong indent for else", stdout);
                 if (indent - 2 >  top->b_indent)
                     fputs(" (missing if?)", stdout);
                 printf(".  \"if\" line %d, \"else\" line %d.\n", top->b_ln,
                    ln);
             }
         }

         if (top->type == IF)
             rmbrak(1);
         newbrak(ELSE);
     } else {
         myungetc(c);
         ungetc(SPACE, infile);  /* BUG?? */
         /* no else so terminate the IF */
         if (top->type == IF) {
             rmbrak(1);
             while (top->type == ELSE)
                 rmbrak(1);
             if (top->type == THEN) {
                 rmbrak(1);
                 checkelse();
             }
         }
     }
 }

 /*  This function is included because Aztec C does not include an "abs"
     function.  If your library contains this function, this code can be
     deleted.
 */
 int abs(i)
 {
     int c;

     return((i < 0) ? -i : i);
 }


 CCHECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\CCHECK.C

 /*
  * CCHECK.C -- Aztec C Version of CCHK, 06/23/85
  *
  *
  * Copyright: The Regents of the University of California
  *   [Note - since Steve Draper distributed cchk.c over
  *    Usenet, I assume it's effectively in the public
  *    domain. JCM]
  *
  * Title:  ccheck
  *
  * Purpose: To find and report all badly matched openers and
  *   closers plus assignment/equality confusions
  *   in a c source file.
  *
  * Author:  Steve Draper, expanding cnest by Tom Anderson
  *
  * Usage:  ccheck [-q] [-v] <filename1> <filename2> ...
  *
  * History (in reverse order to minimize reading time for updates):
  *
  *   June 18, 1985  Converted to Aztec C - removed BDS C code  -  Rick Moore
  *
  *   January 9, 1983  Single BDS/UNIX source created
  *      as CCHECK.C  -- Jeff Martin
  *
  *   December 29, 1982 Adapted for BDS C --
  *       Jeff Martin at home.
  *
  *   December 20, 1982 Converted to cchk --
  *       Steve Draper at UCSD
  *
  *   December 9, 1982 Jeffrey Mogul at Stanford
  *    - checks for unclosed comment at end of file.
  *
  *   December 3, 1982 creation date --
  *      Tom Anderson at microsof!fluke
  */

 #include <stdio.h>
 #include <ctype.h>

 #define TRUE 1
 #define FALSE 0
 #define SPACE 32

 #define BRACE 1
 #define SQBRAK  2
 #define PAREN 3
 #define IF 4
 #define IFCOND 5
 #define WHLCOND 6
 #define THEN 7
 #define ELSE 8

 #define STACKSIZ 64

 struct brak {
     int type, b_indent, b_ln;
 } stack[STACKSIZ];

 #define rmbrak(N) (top -= N, stackc -= N)
 #define myungetc(C)  ungetc(((C) == '\n' ? SPACE : (C)), infile)

 #define VFLAG "-v"
 #define QFLAG "-q"
 #define SFLAG "-s"

 int firsttime; /* This was a static in mygetchar() */

 int mygetchar(), pr();
 void checkelse(), newbrak(), checkcloser(), prtype();

 FILE *infile;
 int ln, indent, commindent, stackc, commln;
 int singlequoterr, oddsinglequote, bracecnt, parencnt, sqbrakcnt;
 int errstatus, wstatus;
 int errnmb, wnmb;
 int verbose;
 char *filename;
 struct brak *top;

 main(argc, argv)
 unsigned argc ;
 char *argv[] ;
 {
     register int c ;
     int i;
     int doubleqflag;
     unsigned file_index;

     wnmb = 0;
     verbose = 0;
     file_index = 1;

     while (argc > 1  &&  argv[file_index][0] == '-') {
         if (strcmp(argv[file_index], VFLAG) == 0)
             verbose++;
         if (strcmp(argv[file_index], QFLAG) == 0)
             wnmb = -2;
         if (strcmp(argv[file_index], SFLAG) == 0)
             wnmb = -2;
         file_index++;
         argc--;
     }

     do {
         /* INIT for each file */
         firsttime = 1;
         doubleqflag = 0;
         errstatus = wstatus = 0;
         ln = 1;
         indent = 0;
         commindent = 0;
         singlequoterr = oddsinglequote = parencnt = sqbrakcnt = bracecnt =
           0;
         errnmb = 0;
         if (wnmb > -2)
             wnmb = 0;
         newbrak(0);

         if (argc == 1) {
             infile = stdin;
             filename = NULL;
         } else {
             if ((infile = fopen(argv[file_index], "r")) == (FILE * ) NULL) {
                 fprintf (stdout, "%s: Can't access %s\n", argv[0], argv[file_
                 continue;
             }
             filename = argv[file_index];
         }

         while ( ( c = mygetchar()) !=  EOF ) {
             if (verbose == 2) {
                 for (i = stackc; i > 0; i--) {
                     printf("%c %d: type ", c, i);
                     prtype(stack[i].type);
                     printf(", indent %d, line %d.\n", stack[i].b_indent, stac
                 }
             }

             switch (c) {
             case ';':
                 ungetc(SPACE, infile);
                 while (top->type == ELSE)
                     rmbrak(1);
                 if (top->type == THEN) {
                     rmbrak(1);
                     checkelse();
                 }
                 break;

             case '!':
             case '>':
             case '<':
                 /* swallow legit. '=' chars */
                 c = mygetchar();
                 if (c != '=')
                     myungetc(c);
                 break;

             case '=':
                 if ((top - 1)->type == IFCOND  ||  (top - 1)->type == WHLCOND
                     c = mygetchar();
                     if (c != '=') {
                         myungetc(c);
                         if (pr(1))
                             printf("Assignment instead of equals in condition
                                ln);
                     }
                 }
                 break;

             case '\n':
             case SPACE:
                 c = mygetchar();
                 switch (c) {
                 case 'i':
                     /* if */
                     c = mygetchar();
                     if (c == 'f'
                       && !isalpha(c = fgetc(infile)) && !isdigit(c)) {
                         ungetc(c, infile);
                         newbrak(IF);
                         while ((c = mygetchar()) == SPACE ||  c == '\n')
                             ;
                         if (c != '(') {
                             if (pr(1))
                                 printf("Bad if (no condition) line %d.\n",
                                    ln);
                             rmbrak(1);
                         } else
                             newbrak(IFCOND);
                         myungetc(c);
                     } else
                         myungetc(c);
                     break;
                 case 'w':
                     /* while */
                     if ((c = mygetchar()) == 'h'
                       &&  (c = mygetchar()) == 'i'
                       &&  (c = mygetchar()) == 'l'
                       &&  (c = mygetchar()) == 'e'
                       &&  !isalpha(c = fgetc(infile))  &&  !isdigit(c)) {
                         ungetc(c, infile);
                         while ((c = mygetchar()) == SPACE ||  c == '\n')
                             ;
                         if (c != '(') {
                             if (pr(1))
                                 printf("Bad while (no condition) line %d.\n",
                                    ln);
                         } else
                             newbrak(WHLCOND);
                         myungetc(c);
                     } else
                         myungetc(c);
                     break;
                 case 'e':
                     /* else */
                     myungetc(c);
                     checkelse();
                     break;

                 default:
                     myungetc(c);
                     break;
                 }
                 break;

             case '*':
                 /* close comment ? */
                 c = mygetchar();
                 if (c != '/') {
                     myungetc(c);
                     break;
                 }

                 if (pr(1))
                     printf
                       ("Line %d: Comment close without open, indent %d\n",
                       ln, indent);

                 break;

             case '\'':
                 if ((c = fgetc(infile)) != '\\') {
                     if (c == '\''  ||  (c = fgetc(infile)) != '\'') {
                         if (pr(1))
                             printf("Bad character constant line %d\n", ln);
                         singlequoterr = 1;
                     }
                 } else if (!isdigit(c = fgetc(infile))) {
                     if ((c = fgetc(infile)) != '\'') {
                         if (pr(1))
                             printf("Bad character constant with \\ line %d\n"
                                ln);
                     }
                 } else {
                     if (isdigit(c = fgetc(infile)))
                         if (isdigit(c = fgetc(infile)))
                             c = fgetc(infile);
                     if (c != '\'')
                         if (pr(1))
                             printf("Bad character constant with \\0 line %d\n
                                ln);
                 }

                 if (c != '\'') {
                     ungetc(c, infile);
                     oddsinglequote = !oddsinglequote;
                     singlequoterr = 1;
                 }
                 break;

             case '"':
                 do {
                     c = fgetc(infile);
                     if (c == EOF) {
                         if (pr(2))
                             printf("Error: '\"' quoted string not ended by en
                         break;
                     } else if (c == '\n') {
                         if (doubleqflag == 0)
                             if (pr(0))
                                 printf("Warning: '\"' quoted string not ended
                                    ln);
                         doubleqflag = 1;
                         ln++;
                     } else if (c == '\\') {
                         c = SPACE;
                         fgetc(infile);
                     }
                 } while (c != '"');
                 doubleqflag = 0;
                 break;

             case '{':
                 if (stackc  &&  indent < top->b_indent)
                     if (pr(0))
                         printf("Indent jumps backwards line %d.\n", ln);
                 newbrak(BRACE);
                 break;

             case '}':
                 checkcloser(BRACE);
                 while (top->type == ELSE)
                     rmbrak(1);
                 if (top->type == THEN) {
                     rmbrak(1);
                     checkelse();
                 }
                 break;

             case '(':
                 if (stackc  &&  indent < top->b_indent)
                     if (pr(0))
                         printf("Indent jumps backwards line %d.\n", ln);
                 newbrak(PAREN);
                 break;

             case ')':
                 checkcloser(PAREN);
                 if (top->type == IFCOND) {
                     rmbrak(1);
                     newbrak(THEN);
                 } else if (top->type == WHLCOND)
                     rmbrak(1);
                 break;

             case '[':
                 if (stackc  &&   indent < top->b_indent)
                     if (pr(0))
                         printf("Indent jumps backwards line %d.\n", ln);
                 newbrak(SQBRAK);
                 break;

             case ']':
                 checkcloser(SQBRAK);
                 break;

             default:
                 break;

             }
         }

         fclose(infile);

         while (stackc > 0) {
             pr(2);
             fputs("Unclosed brak at EOF: ", stdout);
             prtype(top->type);
             printf(" opened on line %d.\n", top->b_ln);
             switch (top->type) {
             case BRACE:
                 bracecnt++;
                 break;
             case SQBRAK:
                 sqbrakcnt++;
                 break;
             case PAREN:
                 parencnt++;
                 break;
             default:
                 break;
             }
             rmbrak(1);
         }

         if ((i = (oddsinglequote || bracecnt || sqbrakcnt || parencnt)) ||
           errstatus) {
             pr(2);
             printf("Summary:\n");
         } else {
             if (filename != NULL) {
                 fputs(filename, stdout);
                 fputs(": ", stdout);
             }
             printf(" OK\n");
         }
         if (oddsinglequote)
             printf("\tOdd number of single quotes.\n");
         if (bracecnt)
             printf("\t%d too few %s braces.\n", abs(bracecnt), (bracecnt >
               0 ? "closing" : "opening"));
         if (sqbrakcnt)
             printf("\t%d too few %s square brackets.\n", abs(sqbrakcnt), (sqb
               > 0 ? "closing" : "opening"));
         if (parencnt)
             printf("\t%d too few %s parentheses.\n", abs(parencnt), (parencnt
               > 0 ? "closing" : "opening"));
         if (errstatus && !i)
             printf("\tPossible error(s), but no net delimiter imbalance.\n");
         putchar('\n');
     } while (++file_index < argc);

     exit(errstatus ? 2 : wstatus);
 }

 int mygetchar()
 {
     register int c;

     c = fgetc(infile);

     /*
     if (c == ';') {
  ungetc(SPACE, infile);
  return(';');
     }
     */
     if (c == '/') {    /* open comment ? */
         c = fgetc(infile);
         if (c != '*') {
             ungetc(c, infile);
             return('/');
         }
         commln = ln;
         commindent = indent;

         while (1) {
             c = fgetc(infile);

             if (c == EOF) {   /* last comment never ended */
                 if (pr(2))
                     printf
                       ("Comment opened line %d unclosed by end of file.\n",
                       commln);
                 break; /* Get out of this loop! */
             } else if (c == '/') {  /* nested comment ? */
                 if ((c = fgetc(infile)) == '*') {
                     if (pr(0))
                         fprintf(stdout,
                           "Nested comment: line %d, indent %d.  First open: l
                              ln, indent, commln, commindent);
                 } else
                     ungetc(c, infile);
             } else if (c == '*') {  /* end comment ? */
                 if ((c = fgetc(infile)) == '/') {
                     if (indent != commindent  &&  indent - 1 != commindent)
                         if (pr(0))
                             printf(
                               "Indent of comment close doesn't match open: li
                                      commln, ln, commindent, indent);

                     break;    /* only exit from loop, except EOF */
                 } else
                     ungetc(c, infile);
             } else if (c == '\n') {
                 do {
                     if (c == SPACE)
                         indent++;
                     else if (c == '\t')
                         indent = ((indent + 8) / 8) * 8;
                     else if (c == '\n') {
                         ln++;
                         indent = 0;
                     }
                 } while (isspace(c = fgetc(infile)));
                 ungetc(c, infile);
             }
         }
         return(SPACE);

     }

     if (c == '\n'  ||  firsttime == 1) {
         firsttime = 0;
 lf:
         while (1) {
             if (c == SPACE)
                 indent++;
             else if (c == '\t')
                 indent = ((indent + 8) / 8) * 8;
             else if (c == '\n') {
                 ln++;
                 indent = 0;
                 singlequoterr = 0;
             } else {
                 ungetc(c, infile);
                 return('\n');
                 /*NOTREACHED*/
                 break;
             }
             c = fgetc(infile);
         }
     }

     if (c == SPACE  ||  c == '\t') {
         do
             c = fgetc(infile);
         while (c == SPACE  ||  c == '\t');
         if (c != '\n') {
             ungetc(c, infile);
             return(SPACE);
         } else
             goto lf;
     }
     return(c);
 }

 /*
  * administer count of error msgs. and suppress if too many
  * administer the status var.s
  * prepend file name to msg.
  * flag error msg.s (not warnings) with '*'
  */
 int pr(error)
 int error;
 {
     int i;

     if (singlequoterr)
         return(0);

     if (verbose) {
         for (i = stackc; i > 0; i--) {
             printf("%d: type ", i);
             prtype(stack[i].type);
             printf(", indent %d, line %d.\n", stack[i].b_indent, stack[i].b_l
         }
     }

     if (error == 2) {
         errnmb = 0;
         errstatus = 1;
     } else if (error) {
         errstatus = 1;
         if (errnmb < 0)
             return(0);
         else if (errnmb >= 9) {
             errnmb = -1;
             printf("Other error messages being suppressed.\n");
             return(0);
         }
     } else {
         wstatus = 1;
         if (wnmb < 0)
             return(0);
         else if (errnmb + wnmb >= 9) {
             wnmb = -1;
             puts("Further warning messages being suppressed.\n");
             return(0);
         }
     }

     if (filename != NULL) {
         fputs(filename, stdout);
         fputs(": ", stdout);
     }
     if (error)
         putchar('*');
     if (error)
         errnmb++;
     else
         wnmb++;
     return(1);
 }

 void newbrak(newtype)
 int newtype;
 {
     if (newtype == 0) {
         top = stack;
         stackc = 0;
     } else {
         top++;
         stackc++;
     }
     if (stackc >= STACKSIZ) {
         if (pr(2))
             printf("***stack overflow, line %d.\n", ln);
         exit(3);
     }

     top->type = newtype;
     top->b_indent = indent;
     top->b_ln = ln;

 }

 void prtype(typ)
 int typ;
 {
     switch (typ) {
     case BRACE:
         putchar('}');
         break;
     case PAREN:
         putchar(')');
         break;
     case SQBRAK:
         putchar(']');
         break;
     case IF:
         fputs("if", stdout);
         break;
     case IFCOND:
         fputs("if-condition", stdout);
         break;
     case THEN:
         fputs("then", stdout);
         break;
     case ELSE:
         fputs("else", stdout);
         break;
     case WHLCOND:
         fputs("while-condition", stdout);
         break;
     default:
         fputs("'NULL'", stdout);
         break;
     }
 }

 void checkcloser(typ)
 int (typ);
 {
     int i, found;

     i = found = 0;
     if (typ == top->type  &&  top->b_indent == indent) {
         rmbrak(1);
         return;
     }

     while (!found  &&  ++i < stackc  &&  indent <= (top - i)->b_indent)
         if (typ == (top - i)->type  &&  (top - i)->b_indent == indent)
             found = 1;

     if (found) {
         if (pr(1))
             printf("Missing closer%s detected line %d:\n", (i > 1 ? "s" :
               ""), ln);
         while (i--) {
             if (pr(1)) {
                 fputs("\tMissing closing ", stdout);
                 prtype(top->type);
                 printf(" opened line %d.\n", top->b_ln);
             }
             switch (top->type) {
             case BRACE:
                 bracecnt++;
                 break;
             case SQBRAK:
                 sqbrakcnt++;
                 break;
             case PAREN:
                 parencnt++;
                 break;
             default:
                 break;
             }
             rmbrak(1);
         }
         rmbrak(1); /* the matching brak */
     } else if (typ == top->type) {
         if (indent != top->b_indent) {
             if (pr(0)) {
                 fputs("Mismatched indent on closing ", stdout);
                 prtype(typ);
                 printf
                   (" lines %d, %d; indents %d, %d.\n",
                   top->b_ln, ln, top->b_indent, indent);
             }
         }
         rmbrak(1);
     }
       else {
         switch (typ) {
         case BRACE:
             bracecnt--;
             break;
         case SQBRAK:
             sqbrakcnt--;
             break;
         case PAREN:
             parencnt--;
             break;
         default:
             break;
         }

         if (pr(1)) {
             fputs("Muddle detected at unmatched closing ", stdout);
             prtype(typ);
             printf(" line %d.\n", ln);
         }
     }
 }

 /*
  * removes IF from stack
  * checks else's indent
  */
 void checkelse()
 {
     int c;

     while ((c = mygetchar()) == SPACE  || c == '\n')
         ;
     if (c == 'e'
       &&  (c = mygetchar()) == 'l'
       &&  (c = mygetchar()) == 's'
       &&  (c = mygetchar()) == 'e'
       &&  !isalpha(c = fgetc(infile))  &&  !isdigit(c)) {
         ungetc(c, infile);
         if (top->type == THEN)
             rmbrak(1);
         if (top->type != IF) {
             if (pr(1))
                 printf("Else with no if line %d.\n", ln);
         }
           else if (indent + 2 < top->b_indent) {
             if (pr(1))
                 printf("Dangling else -- bound to wrong if?  \"if\" line %d,
                    top->b_ln, ln);
         }
           else if (indent != top->b_indent) {
             if (pr(0)) {
                 fputs("Wrong indent for else", stdout);
                 if (indent - 2 >  top->b_indent)
                     fputs(" (missing if?)", stdout);
                 printf(".  \"if\" line %d, \"else\" line %d.\n", top->b_ln,
                    ln);
             }
         }

         if (top->type == IF)
             rmbrak(1);
         newbrak(ELSE);
     } else {
         myungetc(c);
         ungetc(SPACE, infile);  /* BUG?? */
         /* no else so terminate the IF */
         if (top->type == IF) {
             rmbrak(1);
             while (top->type == ELSE)
                 rmbrak(1);
             if (top->type == THEN) {
                 rmbrak(1);
                 checkelse();
             }
         }
     }
 }

 /*  This function is included because Aztec C does not include an "abs"
     function.  If your library contains this function, this code can be
     deleted.
 */
 int abs(i)
 {
     int c;

     return((i < 0) ? -i : i);
 }


 CCOUNT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CCOUNT.C

 /*
         Title:                ccount

         Function:        Counts number of lines of code, lines with comments,
                         and total lines in C source programs.

         Usage:                ccount <file1> [<file2> ...]
                         ccount                (prints help info)

         History:        May 1983 - Created by Deb Brown, Mitre
                         (Based on Tom Anderson's cnest.)
 */

 #include <stdio.h>

 #define TRUE -1
 #define FALSE 0

 main (argc, argv)
 unsigned int        argc;
 char   *argv[];

 {
     char    c;
     char    prev_char;
     unsigned register int   in_comment;
     unsigned register int   line_number;
     unsigned register int   file_index;
     unsigned register int   count_code;
     unsigned register int   count_com;
     unsigned register int   some_comment;
     unsigned register int   some_code;
     unsigned register int   total_code = 0;
     unsigned register int   total_com = 0;
     unsigned register int   total_lines = 0;
     char    status;
     FILE   *chk_file;

     status = 0;

 if (argc == 1) {
         printf ("Usage: %s <file1> [<file2> ...]\n", argv [0]);
         printf ("Output: lines_of_code lines_of_comments total_lines\n");
         exit ();
 }

     for (file_index = 1; file_index < argc; ++file_index)
     {
         line_number = 1;
         in_comment = FALSE;
         count_code = 0;
         count_com = 0;
         prev_char = ' ';
         if (argc == 1)
             chk_file = stdin;
         else
         {
             if ((chk_file = fopen (argv[file_index], "r")) == (FILE *) NULL)
             {
                 fprintf (stderr, "%s: Can't access %s", argv[0], argv[file_in
                 status = 2;
                 continue;
             }
         }

         while ((c = fgetc (chk_file)) != EOF)
         {
             switch (c)
             {
                 case '\n':
                     line_number++;
                     if (some_comment)
                         ++count_com;
                     if (some_code)
                         ++count_code;
                     some_comment = FALSE;
                     some_code = FALSE;
                     break;
                 case '/':
                     if (prev_char == '*')
                     {
                         in_comment = FALSE;
                         some_comment = TRUE;
                     }
                     break;
                 case '*':
                     if (prev_char == '/')
                     {
                         in_comment = TRUE;
                         some_comment = TRUE;
                     }
                     break;
 case ' ':
 case '\t':
         break;
                 default:
                     if (in_comment)
                         some_comment = TRUE;
                     else
                         some_code = TRUE;
                     break;
             }
             prev_char = c;
         }
         fclose (chk_file);
         total_code += count_code;
         total_com += count_com;
         total_lines += (--line_number);
 if (argc > 1)
         printf ("%7d %7d %7d %s\n",
              count_code, count_com, line_number, argv [file_index]);
 else
         printf ("%7d %7d %7d\n", count_code, count_com, line_number);
     }
 if (argc > 2)
     printf ("\n%7d %7d %7d Total\n", total_code, total_com, total_lines);
     exit (status);
 }


 CFILL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\CFILL.C

 /* CFILL.C - From page 354 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. Uses C putch() function to        */
 /* fill the screen. To quit, enter X. The DOS file ANSI.SYS     */
 /* must be on disk and accessable in your path and must be in   */
 /* your CONFIG.SYS file as:  device = ANSI.SYS for this pro-    */
 /* gram to work.                                                */
 /****************************************************************/

 #define ROMAX 25
 #define COMAX 80
 #define CLEAR "\x1B[2J"

 main()
 {
 int col, row;
 char ch;

    printf("\nType character to start, another to change, X to exit.");
    while((ch = getche()) != 'X') {
       printf(CLEAR);
       for(row = 0; row < ROMAX; row++)
          for(col = 0; col < COMAX; col++)
             putch(ch);
    }
 }



 CFLOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\CFLOW\CFLOW.C


 /*
 **   CFLOW.C : find module call structure of c program
 **   refer to cflow.doc for how to use
 **                                       Mark Ellington
 **                                       05-27-84
 */

 /*
 **    Modified for Lattice C.
 **    Changed logic in skipline() to correct problem with '#'.
 **    Changed logic in comout() to correct problem with '/'.
 **                                       Lew Paper
 **                                       7/21/85
 */

 #include <stdio.h>

 #define LINS 256
 #define TRUE 1
 #define FALSE 0

 FILE *fptr;       /* input file pointer */
 int level;      /* keep track of level of open "{"s */
 char name[100]; /* module name buffer */

 char ins[LINS];  /* source input line buffer */
 int curchar;     /* current character in input line buffer
                    array subscript */

 main(argc,argv)
 int argc; char *argv[];
 {

         printf("\nCFLOW --> function declarations and calls in C source");
         printf("\n by Mark Ellington");

         if (argc != 2) {
                 printf("\nusage: cflow [infilename.ext] ");
                 exit();
         }

         if ((fptr = fopen(argv[1],"r")) == NULL) {
                 printf("\nCan't open %s\n",argv[1]);
                 exit();
         }

         printf("\nSource file: %s",argv[1]);

         modules();

         fclose(fptr);
         exit();
 }


 modules()    /* find function declarations and calls */
 {
         int j;
         char c;
         int incom;       /* comment flag */
         int decl;        /* module declaration line flag */
         char *lastlin;   /* Pointer to ins if not last line and no error */
                          /* NULL if error or last line */
         int quoted;      /* within " quotes */
         int header;      /* within function header (before 1st '{') */

         incom = quoted  = header = FALSE;

         lastlin = NULL;

         level = 0;

         do {

                 lastlin = fgets(ins, LINS, fptr);    /* read a line of source

                 decl = FALSE;  /* assume nothing */
                 curchar = 0;
                 while (curchar < LINS) {/* read for significant characters */

                         if (skipline()) break;

                         quotes();        /* skip single quoted character */

                         incom = comment(incom);  /* true if in comment */

                         c = ins[curchar];

                         /* read for significant characters */

                         if (!incom) {

                                 /* skip double quoted strings */

                                 if (c == '\042') quoted = !quoted;

                                 if (!quoted) {

                                     switch(c) {

                                         case '{' :
                                                 level++;
                                                 header = FALSE;
                                                 break;

                                         case '}' :
                                                 level--;
                                                 break;

                                         /* "(" always follows function call *
                                         /* or declaration */

                                         case '(' :

                                         if (!ischar(ins[curchar-1]))
                                                 break;
                                         lookbak(curchar);
                                         j = modname();
                                         if (!j) break;
                                         else decl = TRUE;
                                         if (j == 2)
                                                 header = TRUE;
                                         break;


                                         default :
                                                   break;
                                     }
                                 }
                         }

                         ++curchar;     /* next character */
                 }

                 /* display argument declarations */
                 comout(ins);
                 if (header && !decl) printf("%s",ins);

         } while (lastlin != NULL);    /* = NULL if last line */

 }

 /* skip this line ? */

 skipline()
 {
 char c;
 int sk; /* Return value for function */

         c = ins[curchar];

         if (c == '\0') return(TRUE);     /* end of line */

         sk = FALSE;  /* No except for macro defines */

         if (c == '#') {              /* skip macro defs */
                 if (curchar < 5) /* at beginning of line */
                         sk = (!strcmp("define",&ins[curchar+1]));
         }

         return(sk);

 }


 /* skip characters quoted (for instance '}' would throw off level count */

 quotes()
 {
         if (flowchar(ins[curchar]))          /* test critical chars only */
             if (ins[curchar+1] == '\047')   /* next char single quote? */
                 if (curchar+2 < LINS)         /* don't pass end of string */
                         curchar = curchar + 2; /* skip past quote */
 }


 /* return TRUE if entering comment, FALSE if exiting */

 comment(incom)
 int incom;
 {
         if (ins[curchar] == '/') {
                 if (ins[curchar+1] == '*') {
                          if (curchar + 1 < LINS)   /* stay within string */
                               return(TRUE);
                          else return(incom);  /* unchanged */
                 }
                 else if (ins[curchar-1] == '*') {
                         if(curchar - 1 >= 0)  /* stay within string */
                                 return(FALSE);
                         else return(incom);  /* unchanged */
                 }
                 else return(incom); /* An isolated slash, so unchanged */
         }
         else return(incom);  /* unchanged */
 }


 /* look back from position n in string.  called with n indicating '('.
    determine function name  */

 lookbak(n)
 int n;
 {
         int i;

         while (!ischar(ins[n])) {
                 if (n == 0) break;
                 --n;
         }

         /* find leading blank */
         while (ischar(ins[n-1])) {
                 if (n == 0) break;
                 --n;
         }

         /* save name */
         /* include variable declarations if module declaration */

         i = 0;
         if (level == 0) {
                 while (ins[n])               /* full line if declaration */
                         name[i++] = ins[n++];
         }
         else {
                 while (ischar(ins[n]))      /* function call within function
                         name[i++] = ins[n++];
         }

         name[i] = '\0';

         comout(name);    /* remove comment from name string */

 }


 /* terminate string at comment */

 comout(s)
 char *s;
 {
 char c;

         while(c = *s++)
                 if (c == '/')
                         if (*s == '*') {
                                 --s;
                                 *s++ = '\n';
                                 *s = '\0';
                                 break;
                         }

 }



 /* display module name with indentation according to { level */
 /* returns 0 if not module, 1 if call within module, 2 if    */
 /* module declaration  */

 modname()
 {
         int j;

         if (unreserved()) {              /* test if builtin like while */
                 if (level == 0) {
                         printf("\n\n\n");
                         printf("**\n");
                         comout(ins);
                         printf("%s",ins);
                         return(2);
                 }
                 else {
                         printf("\n");
                         for (j=0; j < level; ++j)
                                 putchar('\t');
                         printf("%s()",name);
                         return(1);
                 }
         }
         return(0);

 }

 /* test for names that are operators not functions */

 unreserved()
 {

         if (!strcmp(name,"return")) return(0);
         else if (!strcmp(name,"if")) return(0);
         else if (!strcmp(name,"while")) return(0);
         else if (!strcmp(name,"for")) return(0);
         else if (!strcmp(name,"switch")) return(0);

         else return(1);

 }


 /* test if character is one that program tracks */

 flowchar(c)
 char c;
 {
         if (c == '{' || c == '}' || c == '\"') return(TRUE);
         else return(FALSE);
 }



 /* test for character */

 ischar(c)
 char c;
 {
         if (isalpha(c) || isdigit(c)) return(TRUE);
         else return(FALSE);
 }



 CFLOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\CFLOW.C

 /*
         HEADER:                CUG236;
         TITLE:                Function Abstractor;
         DATE:                04/19/1987;
         DESCRIPTION:        "Abstracts C function calls and declarations from
                         source and produces a listing of the program's callin
                         hierarchy."
         VERSION:        3.0;
         KEYWORDS:        Flow Analysis, Flow Analyzer;
         FILENAME:        CFLOW.C;
         SEE-ALSO:        CFLOW.DOC;
         COMPILERS:        vanilla;
         AUTHORS:        W. C. Colley III, Mark Ellington;
 */

 /*
 **   CFLOW.C : find module call structure of c program
 **   refer to cflow.doc for how to use
 **                                        Mark Ellington
 **                                        05-27-84
 **
 **   Ported to portable C.  Required the following changes:
 **
 **        1)  Stripped BDS C hooks.
 **        2)  Stripped C/80 hooks.
 **        3)  Allowed for presence/absence of header files "ctype.h"
 **                and "string.h".
 **        4)  Allowed for possible pre-definition of constants TRUE,
 **                FALSE, and EOF.
 **        5)  Made variable fptr type FILE * instead of int.
 **        6)  Added a #define for the max line length.
 **        7)  Made preprocessor directive rejection logic smarter.
 **        8)  Removed name conflict between our fgets() and the std
 **            library fgets() by changing ours to get_source_line().
 **                                        William C. Colley, III
 **                                        04-19-87
 */

 #include <stdio.h>

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * pair of #defines if you are running AZTEC C:
  */

 /*
 #define getc(f)                agetc(f)
 #define putc(c,f)        aputc(c,f)
 */

 /*  Portability Note:  If you do not have a header file "ctype.h",
     uncomment the following #define so that the program will look for
     library support.                                                        *

 /* #define        NO_CTYPE_H                                                *

 #ifdef        NO_CTYPE_H
 extern int isalnum();
 #else
 #include <ctype.h>
 #endif

 /*  Portability Note:  If you do not have a header file "string.h",
     uncomment the following #define so that the program will look for
     library support.                                                        *

 /* #define        NO_STRING_H

 #ifdef        NO_STRING_H
 extern int strcmp();
 #else
 #include <string.h>
 #endif

 /*  Portability Note:  A few compilers don't know the additional type
     void.  If yours is one of these, uncomment the following #define.

 /* #define        void                int

 #ifndef TRUE
 #define TRUE        1
 #endif

 #ifndef FALSE
 #define FALSE        0
 #endif

 #ifndef EOF
 #define EOF        -1
 #endif

 LINE_LENGTH        256        /* Max line length program can handle.        *

 FILE *fptr;                        /* input file pointer
 int level;                        /* keep track of level of open "{"s
 char name[LINE_LENGTH];                /* module name buffer
 char ins[LINE_LENGTH];                /* source input line buffer
 int curchar;                        /* current character in input line
                                         buffer array subscript

 /*  Fixed bug that makes _ characters lop off the beginning of function
     names.  WCC3.                                                        */

 int isal_num(c)
 int c;
 {
     return isalnum(c) || c == '_';
 }

 int main(argc,argv)
 int argc;
 char *argv[];
 {
         void modules();

         printf("\nCFLOW --> function declarations and calls in C source");
         printf("\n by Mark Ellington");

         if (argc != 2) {
                 printf("\nUsage: cflow [infilename.ext] ");
                 return TRUE;
         }

         if (!(fptr = fopen(argv[1],"r"))) {
                 printf("\nCan't open %s\n",argv[1]);
                 return TRUE;
         }
         printf("\nSource file: %s",argv[1]);

         modules();

         fclose(fptr);  return FALSE;
 }


 void modules()                /* find function declarations and calls
 {
         int j;
         char c;
         int incom;        /* comment flag
         int decl;        /* module declaration line flag
         int lastlin;        /* last line of file flag
         int quoted;        /* within " quotes
         int header;        /* within function header (before 1st '{')
         int comment(), get_source_line(), modname(), skipline();
         void comout(), lookbak(), quotes();

         incom = lastlin = quoted  = header = FALSE;  level = 0;

         do {
                 lastlin = get_source_line();        /* read a line of source
                 decl = FALSE;                /* assume nothing
                 curchar = 0;
                                         /* read for significant characters */
                 while (curchar < LINE_LENGTH) {
                         if (skipline()) break;
                         quotes();        /* skip single quoted character */
                         incom = comment(incom); /* true if in comment
                         c = ins[curchar];
                         /* read for significant characters */
                         if (!incom) {
                             /* skip double quoted strings */
                             if (c == '"') quoted = !quoted;
                             if (!quoted)
                                 switch(c) {
                                     case '{' :        level++;  header = FALS
                                                 break;

                                     case '}' :        level--;
                                                 break;

                                 /* "(" always follows function call */
                                         /* or declaration */

                                     case '(' :        if (!isalnum(ins[curcha
                                                     break;
                                                 lookbak(curchar);
                                                 if (!(j = modname())) break;
                                                 else decl = TRUE;
                                                 if (j == 2) header = TRUE;
                                                 break;

                                     default :        break;
                                 }
                         }
                         ++curchar;     /* next character */
                 }
                 /* display argument declarations */
                 comout(ins);
                 if (header && !decl) printf("%s",ins);
         } while (lastlin);    /*  = 0 if last line */
 }

 /* skip this line ? */

 int skipline()
 {
         char c;
         int i;

         if (!(c = ins[curchar])) return TRUE;        /* end of line
         if (c == '#') {                        /* skip preprocessor directive
                 for (i = curchar; i--; )
                         if (ins[i] != ' ' && ins[i] != '\t') return FALSE;
                 return TRUE;
         }
         return FALSE;                                /* don't skip
 }


 /* skip characters quoted (for instance '}' would throw off level count) */

 void quotes()
 {
         int flowchar();

         if (flowchar(ins[curchar]) &&                /* test critical chars o
             ins[curchar+1] == '\'' &&                /* next char single quot
             curchar+2 < LINE_LENGTH)                /* don't pass end of stri
             curchar = curchar + 2;                /* skip past quote        *
 }


 /* return TRUE if entering comment, FALSE if exiting */

 int comment(incom)
 int incom;
 {
         if (ins[curchar] == '/') {
                 if (ins[curchar+1] == '*') return TRUE;
                 if (curchar > 0 && ins[curchar-1] == '*') return FALSE;
         }
         return incom;                                /* unchanged
 }


 /* look back from position n in string.         called with n indicating '('.
    determine function name                                                */

 void lookbak(n)
 int n;
 {
         int i;
         void comout();

         while (!isal_num(ins[n]) && n) --n;

         /* find leading blank */
         while (isal_num(ins[n-1]) && n) --n;

         /* save name */
         /* include variable declarations if module declaration */

         i = 0;
         if (level == 0)                        /* full line if declaration
                 while (ins[n]) name[i++] = ins[n++];
         else                                /* function call within function
                 while (isal_num(ins[n])) name[i++] = ins[n++];
         name[i] = '\0';
         comout(name);        /* remove comment from name string */
 }


 /* terminate string at comment */

 void comout(s)
 char *s;
 {
         char c;

         while (c = *s++)
                 if (c == '/')
                         if (*s == '*') {
                                 *(s - 1) = '\n';
                                 *s = '\0';
                                 break;
                         }
 }



 /* display module name with indentation according to { level */
 /* returns 0 if not module, 1 if call within module, 2 if    */
 /* module declaration  */

 int modname()
 {
         int j, unreserved();
         void comout();

         if (unreserved()) {                /* test if builtin like while */
                 if (level == 0) {
                         comout(ins);
                         printf("\n\n\n**\n%s",ins);
                         return 2;
                 }
                 else {
                         printf("\n");
                         for (j=0; j < level; ++j)
                                 putchar('\t');
                         printf("%s()",name);
                         return 1;
                 }
         }
         return 0;
 }

 /* test for names that are operators not functions */

 int unreserved()
 {
         return        strcmp(name,"return") &&
                 strcmp(name,"if") &&
                 strcmp(name,"while") &&
                 strcmp(name,"for") &&
                 strcmp(name,"switch");
 }


 /* test if character is one that program tracks */

 int flowchar(c)
 char c;
 {
         return c == '{' || c == '}' || c == '\"';
 }


 /* read a line of source */

 int get_source_line()
 {
         char *s;
         int ch;

         s = ins;
         while ((ch = getc(fptr)) != EOF) {
                 if ((*s++ = ch) == '\n') {
                         *s = '\0';
                         return TRUE;
                 }
         }
         *s = '\0';
         return FALSE;
 }


 CFLOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CFLOW.C


 /*
 **   CFLOW.C : find module call structure of c program
 **   refer to cflow.doc for how to use
 **                                       Mark Ellington
 **                                       05-27-84
 */

 /*
 **    Modified for Lattice C.
 **    Changed logic in skipline() to correct problem with '#'.
 **    Changed logic in comout() to correct problem with '/'.
 **                                       Lew Paper
 **                                       7/21/85
 */

 #include <stdio.h>

 #define LINS 256

 FILE *fptr;       /* input file pointer */
 int level;      /* keep track of level of open "{"s */
 char name[100]; /* module name buffer */

 char ins[LINS];  /* source input line buffer */
 int curchar;     /* current character in input line buffer
                    array subscript */

 main(argc,argv)
 int argc; char *argv[];
 {

         printf("\nCFLOW --> function declarations and calls in C source");
         printf("\n by Mark Ellington");

         if (argc != 2) {
                 printf("\nusage: cflow [infilename.ext] ");
                 exit();
         }

         if ((fptr = fopen(argv[1],"r")) == FALSE) {
                 printf("\nCan't open %s\n",argv[1]);
                 exit();
         }

         printf("\nSource file: %s",argv[1]);

         modules();

         fclose(fptr);
         exit();
 }


 modules()    /* find function declarations and calls */
 {
         int j;
         char c;
         int incom;       /* comment flag */
         int decl;        /* module declaration line flag */
         char *lastlin;   /* Pointer to ins if not last line and no error */
                          /* NULL if error or last line */
         int quoted;      /* within " quotes */
         int header;      /* within function header (before 1st '{') */

         incom = quoted  = header = FALSE;

         lastlin = NULL;

         level = 0;

         do {

                 lastlin = fgets(ins, LINS, fptr);    /* read a line of source

                 decl = FALSE;  /* assume nothing */
                 curchar = 0;
                 while (curchar < LINS) {/* read for significant characters */

                         if (skipline()) break;

                         quotes();        /* skip single quoted character */

                         incom = comment(incom);  /* true if in comment */

                         c = ins[curchar];

                         /* read for significant characters */

                         if (!incom) {

                                 /* skip double quoted strings */

                                 if (c == '\042') quoted = !quoted;

                                 if (!quoted) {

                                     switch(c) {

                                         case '{' :
                                                 level++;
                                                 header = FALSE;
                                                 break;

                                         case '}' :
                                                 level--;
                                                 break;

                                         /* "(" always follows function call *
                                         /* or declaration */

                                         case '(' :

                                         if (!ischar(ins[curchar-1]))
                                                 break;
                                         lookbak(curchar);
                                         j = modname();
                                         if (!j) break;
                                         else decl = TRUE;
                                         if (j == 2)
                                                 header = TRUE;
                                         break;


                                         default :
                                                   break;
                                     }
                                 }
                         }

                         ++curchar;     /* next character */
                 }

                 /* display argument declarations */
                 comout(ins);
                 if (header && !decl) printf("%s",ins);

         } while (lastlin != NULL);    /* = NULL if last line */

 }

 /* skip this line ? */

 skipline()
 {
 char c;
 int sk; /* Return value for function */

         c = ins[curchar];

         if (c == '\0') return(TRUE);     /* end of line */

         sk = FALSE;  /* No except for macro defines */

         if (c == '#') {              /* skip macro defs */
                 if (curchar < 5) /* at beginning of line */
                         sk = (!strcmp("define",&ins[curchar+1]));
         }

         return(sk);

 }


 /* skip characters quoted (for instance '}' would throw off level count */

 quotes()
 {
         if (flowchar(ins[curchar]))          /* test critical chars only */
             if (ins[curchar+1] == '\047')   /* next char single quote? */
                 if (curchar+2 < LINS)         /* don't pass end of string */
                         curchar = curchar + 2; /* skip past quote */
 }


 /* return TRUE if entering comment, FALSE if exiting */

 comment(incom)
 int incom;
 {
         if (ins[curchar] == '/') {
                 if (ins[curchar+1] == '*') {
                          if (curchar + 1 < LINS)   /* stay within string */
                               return(TRUE);
                          else return(incom);  /* unchanged */
                 }
                 else if (ins[curchar-1] == '*') {
                         if(curchar - 1 >= 0)  /* stay within string */
                                 return(FALSE);
                         else return(incom);  /* unchanged */
                 }
                 else return(incom); /* An isolated slash, so unchanged */
         }
         else return(incom);  /* unchanged */
 }


 /* look back from position n in string.  called with n indicating '('.
    determine function name  */

 lookbak(n)
 int n;
 {
         int i;

         while (!ischar(ins[n])) {
                 if (n == 0) break;
                 --n;
         }

         /* find leading blank */
         while (ischar(ins[n-1])) {
                 if (n == 0) break;
                 --n;
         }

         /* save name */
         /* include variable declarations if module declaration */

         i = 0;
         if (level == 0) {
                 while (ins[n])               /* full line if declaration */
                         name[i++] = ins[n++];
         }
         else {
                 while (ischar(ins[n]))      /* function call within function
                         name[i++] = ins[n++];
         }

         name[i] = '\0';

         comout(name);    /* remove comment from name string */

 }


 /* terminate string at comment */

 comout(s)
 char *s;
 {
 char c;

         while(c = *s++)
                 if (c == '/')
                         if (*s == '*') {
                                 --s;
                                 *s++ = '\n';
                                 *s = '\0';
                                 break;
                         }

 }



 /* display module name with indentation according to { level */
 /* returns 0 if not module, 1 if call within module, 2 if    */
 /* module declaration  */

 modname()
 {
         int j;

         if (unreserved()) {              /* test if builtin like while */
                 if (level == 0) {
                         printf("\n\n\n");
                         printf("**\n");
                         comout(ins);
                         printf("%s",ins);
                         return(2);
                 }
                 else {
                         printf("\n");
                         for (j=0; j < level; ++j)
                                 putchar('\t');
                         printf("%s()",name);
                         return(1);
                 }
         }
         return(0);

 }

 /* test for names that are operators not functions */

 unreserved()
 {

         if (!strcmp(name,"return")) return(0);
         else if (!strcmp(name,"if")) return(0);
         else if (!strcmp(name,"while")) return(0);
         else if (!strcmp(name,"for")) return(0);
         else if (!strcmp(name,"switch")) return(0);

         else return(1);

 }


 /* test if character is one that program tracks */

 flowchar(c)
 char c;
 {
         if (c == '{' || c == '}' || c == '\"') return(TRUE);
         else return(FALSE);
 }



 /* test for character */

 ischar(c)
 char c;
 {
         if (isalpha(c) || isdigit(c)) return(TRUE);
         else return(FALSE);
 }



 CFLOWX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\CFLOWX\CFLOWX.C

 /*        CFLOWX.C: cflow cross-reference utility for function/macro calls
 **
 **        Copyright (c) 1985 by:
 **
 **                Lawrence R. Steeger
 **                1009 North Jackson
 **                Milwaukee, Wisconsin 53202
 **                414-277-8149
 */

 <stdio.h>                        /* CI-C86 header                */

 #define        VOID int

 /*        external functions                */

 extern        VOID abort();
 extern        char *alloc();
 extern        VOID exit();
 extern        int fclose();
 extern        char *fgets();
 extern        FILE *fopen();
 extern        VOID fprintf();
 extern        VOID free();
 extern        char *lower();
 extern        VOID printf();
 extern        VOID qsort();
 extern        char *realloc();
 extern        VOID sprintf();
 extern        int sscanf();
 extern        char *strcat();
 extern        int strcmp();
 extern        char *strcpy();
 extern        int strlen();
 extern        int strncmp();
 extern        int tolower();

 "cflowx.h"                        /* CFLOW/CFLOWX header                */

 #define        VERSION        85
 #define        RELEASE        06
 #define        MODIFIC        20

 #define        outinfo(S) fputs(S, stdout)

 outlogo()
 {
         fprintf(stdout, "\n%s V%02d.%02d.%02d - %s",
                 "CFLOWX",
                 VERSION, RELEASE, MODIFIC,
                 "cflow cross-reference generator");
         outinfo("\nCopyright (c) 1985 by Lawrence R. Steeger\n");
 }

 outhelp()
 {
         outinfo("\nusage: cflowx [-[efimr]] infile [>outfile]");
         outinfo("\n note: infile is created by the");
         outinfo(" CFLOW utility using the -x flag\n");
         outinfo("\nreports: -e    function/macro external definition report")
         outinfo("\n         -f    path\\file name report");
         outinfo("\n         -i    function/macro internal definition report")
         outinfo("\n         -m    macro name cross-reference report");
         outinfo("\n         -r    function name cross-reference report");
         outinfo("\n   note: The order of the specified [efimr] flags will");
         outinfo("\n         be the order that the reports will generated in."
 }

        OUTHDR        0                        /* start output header
        OUTUPD        1                        /* update output array
        OUTFLSH        2                        /* flush output line
        OUTCLR        3                        /* clear output line

 typedef        struct _xref {                        /* cross-reference recor

         struct _xref *_related;                /* related XREF chain

         unsigned char _dup;                /* duplicate entry flag

         int _fnmbr,                        /* file name number
             _level,                        /* {...} nest level number
             _line;                        /* line number

         unsigned int _str;                /* record data string offset

         } XREF;

 static        XREF *xref = NULL,                /* XREF element pointers
              *xref1 = NULL,
              *xref2 = NULL,
              *xref3 = NULL,
              *xref4 = NULL,
              *xchain = NULL;

 /*        useability macros for XREF        */

 #define        related xref->_related
 #define        dup xref->_dup
 #define        fnmbr xref->_fnmbr
 #define        level xref->_level
 #define        line xref->_line
 #define        str xref->_str

 #define        related1 xref1->_related
 #define        dup1 xref1->_dup
 #define        fnmbr1 xref1->_fnmbr
 #define        level1 xref1->_level
 #define        line1 xref1->_line
 #define        str1 xref1->_str

 #define        related2 xref2->_related
 #define        dup2 xref2->_dup
 #define        fnmbr2 xref2->_fnmbr
 #define        level2 xref2->_level
 #define        line2 xref2->_line
 #define        str2 xref2->_str

 #define        related3 xref3->_related
 #define        dup3 xref3->_dup
 #define        fnmbr3 xref3->_fnmbr
 #define        level3 xref3->_level
 #define        line3 xref3->_line
 #define        str3 xref3->_str

 #define        related4 xref4->_related
 #define        dup4 xref4->_dup
 #define        fnmbr4 xref4->_fnmbr
 #define        level4 xref4->_level
 #define        line4 xref4->_line
 #define        str4 xref4->_str

 #define        relxc xchain->_related
 #define        dupxc xchain->_dup
 #define        fnmbrxc xchain->_fnmbr
 #define        levelxc xchain->_level
 #define        linexc xchain->_line
 #define        strxc xchain->_str

 typedef        struct _rqueue {                /* xref record queue header

         XREF **__xref;                        /* XREF record queue pointer
         unsigned char _sorted;                /* sorted queue flag
         unsigned int _total,                /* offset counter
                      _index;                /* offset index

         } RQUEUE;

 static        RQUEUE rqueue[HIGHKEY];                /* xref record queue hea

 static        int rkey = 0,                        /* xref record queue keys
             rkey1 = 0,
             rkey2 = 0;

 /*        useability macros for RQUEUE        */

 #define        pxref rqueue[rkey].__xref
 #define        sorted rqueue[rkey]._sorted
 #define        total rqueue[rkey]._total
 #define        index rqueue[rkey]._index

 #define        pxref1 rqueue[rkey1].__xref
 #define        sorted1 rqueue[rkey1]._sorted
 #define        total1 rqueue[rkey1]._total
 #define        index1 rqueue[rkey1]._index

 #define        pxref2 rqueue[rkey2].__xref
 #define        sorted2 rqueue[rkey2]._sorted
 #define        total2 rqueue[rkey2]._total
 #define        index2 rqueue[rkey2]._index

 static        unsigned char *strings = NULL;        /* character strings buff
 static        unsigned int stringl = 0;        /* character strings length

 static        char *invrec =                        /* standard input error f
              "invalid record %s- %d: \"%s";

 static        int reportc = 0;                /* report function counter
 static        PFI *(reports) = NULL;                /* report function pointe

 /*        mainline                        */

 main(argc, argv)
 int argc;
 unsigned char **argv;
 {
         int i, j;

         outlogo();                        /* display utility logo

         if (argc < 2) {                        /* too few arguments
                 outhelp();
                 exit(1);                /* exit abnormal                */
         }

         for (rkey = 0; rkey < HIGHKEY; rkey++) { /* reset queue headers
                 pxref  = NULL;
                 sorted = FALSE;
                 total  = 0;
                 index  = 0;
         }

         for (i = 1; i < argc; i++) {        /* process -flags
                 if (*argv[i] == '-') {
                         flags(argv[i]);
                         for (j = i--, --argc; j < argc; j++)
                                 argv[j] = argv[j+1];
                 }
         }

         if (argc < 2) {                        /* no filename specified !
                 outhelp();
                 exit(1);                /* exit abnormal                */
         }

         buildq(argv[1]);                /* build CFLOWX record queues

         dupfile();                        /* detect duplicate files        */

         for (i = 0; i < reportc; i++)        /* generate CFLOWX reports
                 (*(reports[i]))();

         exit(0);                        /* exit normal
 }

 /*        process command line flags                                        *

 flags(flag)
 unsigned char *flag;
 {
         int i;

         PFI function;

         int reporte(),                        /* function/macro external
             reportf(),                        /* path\file name
             reporti(),                        /* function/macro internal
             reportm(),                        /* macro cross_reference
             reportr();                        /* function cross_reference

         for (i = 0; flag[++i];) {                /* scan all characters

                 function = NULL;

                 switch (tolower(flag[i])) {        /* set any valid flag

                 case 'e':                /* function/macro external        */
                         function = reporte;
                         break;

                 case 'f':                /* path\file name                */
                         function = reportf;
                         break;

                 case 'i':                /* function/macro internal        */
                         function = reporti;
                         break;

                 case 'm':                /* macro cross_reference        */
                         function = reportm;
                         break;

                 case 'r':                /* function cross_reference        *
                         function = reportr;
                         break;

                 default:
                         abort("Unknown flag: '%c'\n", flag[i]);
                         break;
                 }

                 if (function != NULL) {
                         reports = realloc(reports, (sizeof(PFI)*(reportc+1)))
                         if (reports == NULL)
                                 abort("REALLOC - reports");
                         reports[reportc++] = function;
                 }
         }

         flag[0] = EOS;                                /* terminate flag
 }

 /*        build CFLOWX record queues                                        *

 buildq(filename)
 unsigned char *filename;
 {
         unsigned char *cp,
                       string[MAXBUF];

         unsigned int stradd();                /* add string to char buffer

         int currec,                        /* current input record
             crelxkey,                        /* current related base key
             i,
             j;

         FILE *fptr;                        /* input file pointer

         XREF *crelated;                        /* related XREF base pointer

         if ((fptr = fopen(filename, "r+")) == NULL) /* open input file
                 abort("FOPEN - %s\n", filename);

         currec = 0;                        /* start record counter
         crelated = NULL;                /* clear related chain base        */

         while (1) {                        /* scan XREF input

                 if (fgets(string,MAXBUF,fptr)==FALSE) /* get record        */
                         break;

                 xref = alloc(sizeof(XREF));        /* next XREF element

                 ++currec;                        /* update line count

                 /*        scan for standard fields                         */

                 if ((i=sscanf(string,
                                 cxref((MAXFLDS-1)),
                                 &rkey,
                                 &fnmbr,
                                 &level,
                                 &line)
                     ) != ((MAXFLDS-1)*2)) {
                         printf("sscanf(%d)\n", i);
                         abort(invrec, "sscanf ", currec, string);
                 }

                 if (rkey >= HIGHKEY)                /* validate record key
                         abort(invrec, "type ", currec, string);

                 /*        skip over standard fields                        */

                 for (i=j=0; j != (MAXFLDS-1) && string[i] != RS; i++)
                         if (string[i] == US) ++j;

                 cp = &string[i];                /* save data position

                 /*        find trailing RS                                */

                 for (; string[i] && string[i] != RS; i++);

                 string[i] = EOS;                /* truncate at RS        */

                 str = stradd(cp);                /* add string to buffer

                 pxref = realloc(pxref, (sizeof(XREF *) * (index+1)));

                 if (pxref == NULL) abort("REALLOC - XREC");

                 pxref[index++] = xref;
                 total++;

                 switch (rkey) {                /* build record relationships

                 /*        related record base keys                        */

                 case WILDPTH:                        /* wildcard path
                 case FILEPTH:                        /* C source path
                 case FUNCNME:                        /* function name
                 case MACNME:                        /* macro name
                         crelated = xref;        /* set new base record
                         crelxkey = rkey;        /* set new base key        */
                         break;

                 /*        related record keys

                 case WILDNME:                        /* wildcard name
                         checkrel(WILDPTH,crelxkey,currec,string);
                         goto relation;

                 case FILENME:                        /* C source name
                         checkrel(FILEPTH,crelxkey,currec,string);
                         goto relation;

                 case FUNCDCL:                        /* function declaration
                         checkrel(FUNCNME,crelxkey,currec,string);
                         goto relation;

                 case FUNCARG:                        /* function argument
                         if (crelxkey == FUNCARG)
                                 goto relation;
                         checkrel(FUNCDCL,crelxkey,currec,string);
                         goto relation;

                 case MACDCL:                        /* macro declaration
                         checkrel(MACNME,crelxkey,currec,string);
                         goto relation;

                 case MACEQU:                        /* macro equate
                         checkrel(MACDCL,crelxkey,currec,string);

                 relation:
                         if (crelated == NULL)
                                 abort(invrec,
                                 "has missing relationship ", currec, string);
                         crelated->_related=xref;/* chain related XREFs
                         crelated = xref;        /* update chain base        *
                         crelxkey = rkey;        /* update related key
                         break;

                 default:
                         crelated = NULL;        /* break related chain
                         crelxkey = NOFUNC;        /* reset related key
                         break;
                 }
         }

         fclose(fptr);
         return;
 }

 /*        detect duplicate file names

 dupfile()
 {
         char tfile[MAXPATH],
              tfile1[MAXPATH];

         int sindex;

         for (rkey = FILEPTH, index = 0; index < total; index++) {

                 xref = pxref[index];
                 strcpy(tfile, &strings[str]);

                 for (xchain = related;
                      xchain != NULL;
                      xchain = relxc
                     )
                         strcat(tfile, &strings[strxc]);

                 lower(tfile);

                 sindex = index;

                 for (rkey1 = FILEPTH, index1 = index + 1;
                      index1 < total1;
                      index1++
                     ) {

                         xref1 = pxref1[index1];
                         strcpy(tfile1, &strings[str1]);

                         for (xchain = related1;
                              xchain != NULL;
                              xchain = relxc
                             )
                                 strcat(tfile1, &strings[strxc]);

                         lower(tfile1);

                         if (strcmp(tfile, tfile1) == 0) {
                                 dup1 = TRUE;

                                 for (xchain = related1;
                                      xchain != NULL;
                                      xchain = relxc
                                     )
                                         dupxc = TRUE;
                         }
                 }

                 index = sindex;
         }
 }

 /*        generate funcation/macro external report                        */

 reporte()
 {
         int xrefcmp();                        /* compare XREF queue elements

         xsort(FUNCREF, xrefcmp);        /* sort function ref queue        */

         xsort(FUNCNME, xrefcmp);        /* sort function name queue        */

         xsort(MACNME, xrefcmp);                /* sort macro name queue

         /*        report external functions/macros                        */

         _reporte(FUNCREF,
                  FILENME,
                  FUNCNME,
                  MACNME,
                  "\nFUNCTION/MACRO EXTERNAL REFERENCES:\n",
                  "\n(no external functions/macros)\n"
                 );
 }

 /*        generate header/wildcard/file names listing

 reportf()
 {
         int _reportf();

         /*        report any -hsystem[,project] specifications

         rkey = HDRSYST;                        /* -hsystem specification

         for (index = 0; index < total; index++) {
                 xref = pxref[index];
                 fprintf(stdout, "\nSYSTEM HEADER: %s", &strings[str]);
         }

         if (total) fprintf(stdout, "\n");

         rkey = HDRPROJ;                        /* -h[,project] specification

         for (index = 0; index < total; index++) {
                 xref = pxref[index];
                 fprintf(stdout, "\nPROJECT HEADER: %s", &strings[str]);
         }

         if (total) fprintf(stdout, "\n");

         /*        report any wildcard path\file names

         if (_reportf(WILDPTH,
                 "\nWILDCARD PATH\\FILE NAMES:\n",
                 "\n(no wildcard names)\n")
            )
                 fprintf(stdout,
                 "\n\t\"# \" before a wildcard indicates no files found\n");

         /*        report all other path\file names                        */

         if (_reportf(FILEPTH,
                 "\nC SOURCE PATH\\FILE NAMES:\n",
                 "\n(no C source names)\n")
            )
                 fprintf(stdout,
                 "\n\t\"* \" before a file name indicates an open error\n");
 }

 /*        generate function/macro internal report

 reporti()
 {
         int xrefcmp();                        /* compare XREF queue elements

         xsort(FUNCNME, xrefcmp);        /* sort function name queue        */

         /*        report FUNCNME internal queue

         _reporti(FUNCNME,
                  FILENME,
                  -1,
                  "\nFUNCTION INTERNAL DECLARATIONS:\n",
                  "\n(no functions)\n"
                 );

         xsort(MACNME, xrefcmp);                /* sort macro name queue

         /*        report MACNME internal queue

         _reporti(MACNME,
                  FILENME,
                  -1,
                  "\nMACRO INTERNAL DECLARATIONS:\n",
                  "\n(no macros)\n"
                 );
 }

 /*        generate macro cross-reference report

 reportm()
 {
         int xrefcmp();                        /* compare XREF queue elements

         xsort(MACNME, xrefcmp);                /* sort macro name queue

         xsort(FUNCREF, xrefcmp);        /* sort function reference queue*/

         /*        report MACNME queue

         _reporti(MACNME,
                  FILENME,
                  FUNCREF,
                  "\nMACRO CROSS_REFERENCE:\n",
                  "\n(no macros)\n"
                 );
 }

 /*        generate function cross-reference report                        */

 reportr()
 {
         int xrefcmp();                        /* compare XREF queue elements

         xsort(FUNCNME, xrefcmp);        /* sort function name queue        */

         xsort(FUNCREF, xrefcmp);        /* sort function reference queue*/

         /*        report FUNCNME queue

         _reporti(FUNCNME,
                  FILENME,
                  FUNCREF,
                  "\nFUNCTION CROSS_REFERENCE:\n",
                  "\n(no functions)\n"
                 );
 }

 /*        function/macro external reporter                                */

 int _reporte(qkey, qkey1, qkey2, qkey3, title, noreport)
 unsigned char *title, *noreport;
 int qkey, qkey1, qkey2, qkey3;
 {
         char outfnme[MAXPATH];                /* output path\file name string

         int curfile,                        /* current FILENME queue number
             tcount,                        /* total reference count        */
             _reportr();                        /* reference reporter/counter

         fprintf(stdout, title);                /* display report title

         rkey = qkey;                        /* function/macro ref queue

         for (tcount = index = 0; index < total;) {

                 xref = pxref[index];        /* function/macro ref queue ptr

                 if (dup
                 || _reportr(qkey2, FALSE)        /* function dcl found
                 || _reportr(qkey3, FALSE)        /* macro dcl found        */
                    ) {
                         ++index;
                         continue;                /* not external name
                 }

                 tcount++;                /* increment external count        *

                 /*        report function/macro external name

                 fprintf(stdout, "\n%s:", &strings[str]);

                 for (rkey2 = qkey, index2 = index, curfile = -1;
                      index2 < total2;
                      index2++
                     ) {
                         xref2 = pxref2[index2];        /* reference queue ptr

                         if (strcmp(&strings[str], &strings[str2]) != 0) {
                                 index = index2;
                                 break;
                         }

                         if (curfile != fnmbr2) {        /* new filename
                                 fmtout(OUTFLSH);
                                 xref1 = pxref1[(curfile = fnmbr2)];
                                 strcpy(outfnme, &strings[str1]);

                                 for (xchain = related1;
                                         xchain != NULL;
                                         xchain = relxc
                                     )
                                         strcat(outfnme, &strings[strxc]);

                                 fmtout(OUTHDR, 0, outfnme);
                         }

                         if (dup1) {
                                 fmtout(OUTCLR);
                                 continue;        /* skip duplicate files
                         }

                         fmtout(OUTUPD, line2);        /* update output array
                 }

                 fmtout(OUTFLSH);                /* flush format output
         }

         if (tcount)
                 fprintf(stdout, "\n");
         else        fprintf(stdout, noreport);

         fmtout(OUTCLR);

         return (tcount);
 }

 /*        path\file name reporter

 int _reportf(qkey, title, noreport)
 unsigned char *title, *noreport;
 int qkey;
 {
         int filerr;

         filerr = 0;

         fprintf(stdout, title);                /* report title

         rkey = qkey;                        /* report queue = qkey

         for (index = 0; index < total; index++) {

                 xref = pxref[index];        /* queue XREF pointer

                 fprintf(stdout,                /* report number/pathname
                         "\n%d: %s",
                         (fnmbr+1),
                         &strings[str]
                        );

                 if (strncmp(&strings[str], "* ", 2) == 0
                 ||  strncmp(&strings[str], "# ", 2) == 0)
                         filerr++;

                 for (xchain = related; xchain != NULL; xchain = relxc) {
                         fprintf(stdout, "%s", &strings[strxc]);
                         if (strncmp(&strings[strxc], "* ", 2) == 0
                         ||  strncmp(&strings[strxc], "# ", 2) == 0)
                                 filerr++;
                 }
         }

         if (total)
                 fprintf(stdout, "\n");
         else        fprintf(stdout, noreport);

         return (filerr);
 }

 /*        function/macro internal reporter                                */

 int _reporti(qkey, qkey1, qkey2, title, noreport)
 unsigned char *title, *noreport;
 int qkey, qkey1, qkey2;
 {
         char *cid;

         int tcount;

         fprintf(stdout, title);                /* display report title

         rkey = qkey;                        /* function/macro queue
         rkey1 = qkey1;                        /* path\file name queue

         for (tcount = index = 0; index < total; index++, tcount++) {

                 xref = pxref[index];        /* function/macro queue ptr
                 xref1 = pxref1[fnmbr];        /* path\file name queue ptr

                 if (dup && qkey2 != -1)
                         continue;                /* ignore duplicates

                 /*        report function/macro & 1st path\file segment

                 fprintf(stdout, "\n%s:\t%s (%d)",
                         &strings[str],                /* function/macro name
                         &strings[str1],                /* 1st pathfile segmen
                         line                        /* line where declared
                        );

                 /*        report path\file name related chain

                 for (xchain = related1; xchain != NULL; xchain = relxc)
                         fprintf(stdout, "%s", &strings[strxc]);

                 fprintf(stdout, "\n");

                 /*        report function/macro related chain

                 for (xchain = related, cid = "**";
                      xchain != NULL;
                      xchain = relxc, cid = " *"
                     )
                         fprintf(stdout, "\n\t%s %s", cid, &strings[strxc]);

                 if (related != NULL) fprintf(stdout, "\n");

                 if (qkey2 != -1)
                         _reportr(qkey2, TRUE);        /* reference report
                 else        fprintf(stdout, "\n");
         }

         if (tcount)
                 fprintf(stdout, "\n");
         else        fprintf(stdout, noreport);

         return (tcount);
 }

 /*        cross_reference reporter                                        */

 int _reportr(qkey2, display)
 int qkey2, display;
 {
         char outfnme[MAXPATH];                /* output path\file name string

         int curfile,
             tcount;

         tcount = 0;
         rkey2 = qkey2;                        /* reference queue

         /*        search reference queue for a matching reference

         for (index2 = 0; index2 < total2; index2++) {

                 xref2 = pxref2[index2];        /* reference queue ptr

                 if (strcmp(&strings[str], &strings[str2]) == 0)
                         break;
         }

         if (!(index2 < total2))
                 if (display) fprintf(stdout, "\n\t(no references)");

         /*        count/report references

         for (curfile = -1; index2 < total2; tcount++, index2++) {

                 xref2 = pxref2[index2];        /* reference queue ptr

                 if (strcmp(&strings[str], &strings[str2]) != 0)
                         break;

                 if (display) {
                         if (curfile != fnmbr2) {        /* new filename
                                 fmtout(OUTFLSH);
                                 xref1 = pxref1[(curfile = fnmbr2)];
                                 strcpy(outfnme, &strings[str1]);

                                 for (xchain = related1;
                                         xchain != NULL;
                                         xchain = relxc
                                     )
                                         strcat(outfnme, &strings[strxc]);

                                 fmtout(OUTHDR, 0, outfnme);
                         }

                         fmtout(OUTUPD, line2);        /* add to detail line
                 }
         }

         if (display) {
                 fmtout(OUTFLSH);        /* flush final pending line        */
                 fmtout(OUTCLR);                /* clear all output
                 fprintf(stdout, "\n");
         }

         return (tcount);
 }

 /*        check key relationship, abort on a bad relationship

 checkrel(rkey, xkey, currec, string)
 int rkey, xkey, currec;
 unsigned char *string;
 {
         if (rkey != xkey)
                 abort(invrec, "relationship ", currec, string);
 }

 /*        formatted reference output                                        *

 fmtout(mode, outval, outfnme)
 int mode, outval;
 char *outfnme;
 {
         static        char *outfmt = NULL,        /* output format string
                      *outhdr = NULL,        /* output format header
                      *fmthdr = NULL,        /* format header string
                      *fmtdet = NULL;        /* format detail string

         static        int outcnt = 0,                /* output reference coun
                     outhdrl = 0,        /* output header length
                     outlim = 0,                /* output reference maximum
                     outint[8] =                /* output reference array
                     {0,0,0,0,0,0,0,0};

         int outlen;

         switch (mode) {                        /* select output mode

         case OUTHDR:                        /* start format heading

                 if (outfmt == NULL) {                /* 1st time thru only
                         outfmt = alloc((MAXPATH * 2));
                         outhdr = alloc(MAXPATH);
                         fmthdr = alloc(16);
                         fmtdet = alloc(8);
                 }

                 strcpy(fmthdr, "  %*s   ");        /* fprintf() formats
                 fmthdr[0] = '\n';
                 fmthdr[1] = '\t';
                 strcpy(fmtdet, "%8d");

                 strcpy(outhdr, outfnme);        /* build format heading
                 outhdrl = strlen(outhdr);
                 strcpy(outfmt, fmthdr);
                 outlen = (80 - (outhdrl + 11));
                 for (outlim = 0;
                      outlim < 8 && outlen > 8;
                      outlen -= 8, outlim++
                     )
                         strcat(outfmt, fmtdet);

                 outcnt = 0;                        /* restart array        */
                 break;

         case OUTUPD:                        /* update formatted array

                 if (outfmt == NULL) break;

                 outint[outcnt++] = outval;

                 if (outcnt < outlim);
                 else {                        /* format line full - flush
                         fprintf(stdout,
                                 outfmt, outhdrl, outhdr,
                                 outint[0], outint[1], outint[2],
                                 outint[3], outint[4], outint[5],
                                 outint[6], outint[7]
                                );
                         strcpy(outhdr, " ");
                         outcnt = 0;
                 }
                 break;

         case OUTFLSH:                        /* flush formatted output line

                 if (outfmt == NULL) break;

                 if (outcnt) {
                         outfmt[(strlen(fmthdr)+(strlen(fmtdet)*outcnt))] = EO
                         strcat(outfmt, "\n");
                         fprintf(stdout,
                                 outfmt, outhdrl, outhdr,
                                 outint[0], outint[1], outint[2], outint[3],
                                 outint[4], outint[5], outint[6], outint[7]
                                );
                 }
                 else        fprintf(stdout, "\n");

                 free(outfmt);
                 free(outhdr);
                 free(fmthdr);
                 free(fmtdet);
                 outfmt = outhdr = fmthdr = fmtdet = NULL;
                 outcnt = 0;
                 break;

         case OUTCLR:                        /* clear current format

                 if (outfmt == NULL) break;

                 free(outfmt);
                 free(outhdr);
                 free(fmthdr);
                 free(fmtdet);
                 outfmt = outhdr = fmthdr = fmtdet = NULL;
                 outcnt = 0;
                 break;

         default:
                 break;
         }
 }

 /*        add string to character string buffer

 unsigned int stradd(string)
 unsigned char *string;
 {
         unsigned int sp,                        /* string offset        */
                      strfind();                        /* search char buffer

         if ((sp = strfind(string)) != -1)
                 return (sp);                /* existing string found        *

         strings = realloc(strings, (stringl + strlen(string) + 1));
         if (strings == NULL) abort("REALLOC - STRINGS");

         sp = stringl;

         strcpy(&strings[stringl], string);
         stringl += (strlen(string) + 1);

         return (sp);
 }

 /*        search string buffer for matching string

         returns:        unsigned int        string buffer offset if found
                         -1                string not found
 */

 unsigned int strfind(string)
 unsigned char *string;
 {
         unsigned int sp;

         for (sp = 0;
              sp < stringl;
              sp += (strlen(&strings[sp]) + 1)
             )
                 if (strcmp(&strings[sp], string) == 0)
                          return (sp);                /* match found

         return (-1);                                /* no match found
 }

 /*        XREF qsort() routine

 xsort(key,compare)
 int key;
 PFI compare;
 {
         rkey = key;

         if (sorted == FALSE) {

                 qsort((char *)pxref,                /* 1st XREF pointer
                       (unsigned)total,                /* XREF pointer count
                       (unsigned)sizeof(XREF *),        /* size of XREF elemen
                       compare                        /* XREF comparison
                      );

                 rkey = key;
                 sorted = TRUE;                        /* set sort completed
         }
 }

 /*        qsort() XREF comparison routine

 int xrefcmp(rec1, rec2)
 XREF **rec1, **rec2;
 {
         unsigned char *rstring;

         int result;

         xref1 = *rec1;                        /* 1st element pointer
         xref2 = *rec2;                        /* 2nd element pointer

         rkey1 = FILENME;                /* file name queue header        */
         xref3 = pxref1[fnmbr1];                /* 1st element file name
         xref4 = pxref1[fnmbr2];                /* 2nd element file name

         if ((result = strcmp(&strings[str1], &strings[str2])) == 0) {

                 /*        element names match

                 if ((result = strcmp(&strings[str3], &strings[str4])) == 0) {

                         /*        file names match                        */

                         if (line1 == line2)

                                 /*        line numbers match                *

                                 result = 0;
                         else {
                                 if (line1 > line2)
                                         result = 1;
                                 else        result = -1;
                         }
                 }
         }

         if (result == 0 && !dup1 && !dup2 && (line1 != line2))
                 dup2 = TRUE;                /* flag duplicate entries

         if (result == 0 && !dup1 && dup2)
                 result = -1;                /* a non-duplicate is lower

         return (result);
 }

 /*        end of cflowx.c                        */



 CGLBDEF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\CGLBDEF.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 /*      global definitions      */

 FILE            *input = 0,
                 *list = 0,
                 *output = 0;

 int             lineno = 0;
 int             nextlabel = 0;
 int             lastch = 0;
 int             lastst = 0;
 char            lastid[20] = "";
 char            laststr[MAX_STRLEN + 1] = "";
 long            ival = 0;
 double          rval = 0.0;

 TABLE           gsyms = {0,0},
                 lsyms = {0,0};
 SYM             *lasthead = NULL;
 struct slit     *strtab = 0;
 int             lc_static = 0;
 int             lc_auto = 0;
 struct snode    *bodyptr = 0;
 int             global_flag = 1;
 TABLE           defsyms = {0,0};
 int             save_mask = 0;          /* register save mask */



 CGRAPH1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\CGRAPH\CGRAPH1.C

 /***************************** C _ G R A P H . C ************************/
 /*  ....Fast dot and line functions for IBM's EGA adapter in hires      */
 /*    (640x350) color mode                                              */
 /*    Also double buffering for 256k ega's!!!                           */
 /*  This version uses the DeSmet (ver 2.4) C compiler with its built    */
 /* in inline assembler.                                                 */
 /*                                                                      */
 /* (c)Copywrite 1985 E. Lear - use only for non commercial programming  */
 /************************************************************************/

 /* Define the interrupt for ega's bios calls */
 #define     VIDEO_INT        0x0010

 /* Defines for the various modes available from ega's bios              */
 /* For more information refer to the Options and Adapters reference     */
 /* manual.                                                              */
 #define     SET_MODE         0x0000
 #define     SET_CUR_TYPE     0x0100
 #define     SET_CUR_POS      0x0200
 #define     READ_CUR_POS     0x0300
 #define     READ_PEN_POS     0x0400
 #define     SELECT_PAGE      0x0500
 #define     SCROLL_UP        0x0600
 #define     SCROLL_DOWN      0x0700
 #define     READ_ATC         0x0800
 #define     WRITE_ATC        0x0900
 #define     WRITE_ATCO       0x0A00
 #define     SET_PAL          0x0B00
 #define     WRITE_DOT        0x0C00
 #define     READ_DOT         0x0D00
 #define     WRITE_TTY        0x0E00
 #define     READ_MODE        0x0F00
 #define     SET_PAL_REG      0x1000
 #define     CHAR_GEN         0x1100
 #define     SELECT_ALT       0x1200
 #define     WRITE_STR        0x1300


 unsigned x,y;

 /*  Use these values with _doint() for calling IBM's functions and
     interrupts */

 extern unsigned _rax, _rbx, _rcx, _rdx, _rsi, _rdi, _res, _rds;
 extern void _doint();

 /*********************** S E T _ V I D E O _ M O D E **********************/
 /*
          function set_video_mode(mode):

               Inputs:  int - (0..16) = ( mode )

               Returns:  none.

               Example:  set_video_mode(0x10) (Set up 640x350 hi-res mode)
 */


 void set_video_mode(mode)
    unsigned mode;
    {
     _rax = SET_MODE | mode;
     _doint(VIDEO_INT);
    }


 /*********************** S E T _ P A L _ R E G ************************/
 /*
         function set_pal_reg(pal_reg,pal_val)

               Inputs: int - (0..15) = ( pal_reg )
                       int - (0..63) = ( pal_val )

               Returns: none

               Example: set_pal_reg(0,1) - (set normally black background
                                            to blue.)

 */
 void set_pal_reg(pal_reg, pal_val)
    unsigned pal_reg, pal_val;
    {
     _rax = SET_PAL_REG;
     _rbx = (pal_val << 8) | (pal_reg && 0x00ff);
     _doint(VIDEO_INT);
    }

 /*********************** B _ W R I T E _ D O T ************************/
 /*
         function b_write_dot(page,row,col,color)

               Inputs: int - (0..1) = ( page )  (In hires mode. i.e 640x350)
                       int - (0..349) = ( row )    "        "        "
                       int - (0..639) = ( col )    "        "        "
                       int - (0..15)  = ( color ) ( In 16 color modes )

               Returns: none.

               Example: b_write_dot(0,20,20,1) - Write a blue dot on page
                                                 one at location 20,20.
 */

 void b_write_dot(page,row,col,color)
    unsigned page,row,col,color;
    {
     _rax = WRITE_DOT | color;
     _rbx = page << 8;
     _rdx = row;
     _rcx = col;
     _doint(VIDEO_INT);
    }

 /*  pixel table for the write dot routines ! */
 int pixel_table[8] = { 0x4080, 0x1020, 0x0408, 0x0102 };


 /**************************** W R I T E _ D O T **********************/
 /* this is the 'fastest' version of write_dot (no color but white)   */
 /* This is the ultra fast write one color write dot routine          */
 /* s/r must be off and all planes must be enabled (white)            */

 void write_dot(x,y)
     unsigned x,y;
 {
 #asm
 public write_dot
 write_dot:
       mov   ax,[bp+6]
       mov   cx,ax                         ; copy y to cx reg.
       shl   ax,1                          ;
       shl   ax,1                          ; y = y * 4
       add   cx,ax                         ; y = (y*4 + y) = 5*y
 dot_buffer_start:
       add   cx,0a000h                     ; a0 -> ch = base page for ega
       mov   ax,[bp+4]
       and   al,07h                        ; al >= 0 and <= 7
       mov   bx,offset pixel_table_        ; use al as lookup for bit position
       xlat  pixel_table_                  ; al now contains bit to write
       shr   si,1
       shr   si,1
       shr   si,1                          ; si = si / 8
       mov   es,cx                         ; es now = base adr. + y * 5 * 16
       or    es:[si],al
 #
    }


 /***************************** L I N E _ D R A W ***********************/
 /*  This is the ultra fast line drawing routine.  It writes only in    */
 /*  white and s/r mode must be turned off                              */

 void line_draw(x1,y1,x2,y2)
    unsigned x1,y1,x2,y2;
    {
 #asm
       push  ds                         ; save ds reg.
       mov   si,[bp+04h]                ; reg. si = x1
       mov   di,[bp+08h]                ; reg. di = x2
       mov   cx,[bp+06h]                ; reg. cx = y1
       mov   dx,[bp+0ah]                ; reg. dx = y2
       cmp   si,di                      ; cmp x1, x2
       jle   swapxy                     ; skip if (x1<=x2)
       xchg  cx,dx                      ; x1 > x2 so swap y1,y2
       xchg  si,di                      ; and swap x1,x2
 swapxy:
       sub   dx,cx                      ; dy = y2-y1
       mov   al,80                      ; deldy = 80
       jge   ydown                      ; skip if y1<=y2
       neg   dx                         ; |y2-y1|
       neg   al                         ; -80
 ydown:
       sub   di,si                      ; absdx = x2-x1
       cmp   di,dx                      ; di = absdx, dx = absdy
       lahf                             ; save flags
       jnl   minmax                     ; skip if absdx >= absdy
       xchg  di,dx
 minmax:
       xchg  ax,bp
 ;
 ; compute initial ds address (a000h + y * 80)
 ; al = initial pixel
       mov   ax,cx                      ; copy y to ax reg.
       shl   ax,1
       shl   ax,1                       ; y = y * 4
       add   cx,ax                      ; y = y * 4 + y = 5y
       shl   cx,1
       shl   cx,1
       shl   cx,1
       shl   cx,1                       ; y = 5y * 16
       mov   bx,offset pixel_table_     ; get location of pixel lookup table
       mov   al,07h
       and   ax,si                      ; mask out bits > 8
       xlat  pixel_table_               ; get starting pixel location
       sal   dx,1                       ; dx = delse = dmin * 2
       xchg  ax,dx                      ; ax = delse, dx = pixel location
       xchg  ax,bp                      ; ax = flags(absdx,absdy), bp=delse
       sahf                             ; cmp absdx,absdy
       pushf                            ; save flags on stack
       cbw                              ; ax = deldy
       mov   cs:delsy+2,ax              ; save deldy
       mov   cs:deldy+2,ax
       mov   cs:deldy2+2,ax

       xchg  ax,bp                      ; ax = dmin * 2 = delse
       mov   cs:delse+2,ax              ; save delse
       mov   cs:delse2+2,ax
       sub   ax,di                      ; ax = dmin * 2 - dmax = d
       mov   bp,ax                      ; bp = d = error for start
       sub   ax,di                      ; ax = dmin * 2 - dmax * 2
       mov   cs:delde+2,ax              ; save delde
       mov   cs:delde2+2,ax
       sar   si,1
       sar   si,1
       sar   si,1                       ; x = x / 8
       add   si,cx
 line_buffer_start:
       mov   cx,0a000h
       mov   ds,cx
       popf
       mov   cx,di
       jns   delsx2

       or    [si],dl
       or    cx,cx
       jz    lineexit
       or    bp,bp
       jge   diagonal

 straight:
 delsy:
       add   si,1000h                   ; increment y by -80 or 80
       or    [si],dl                    ; or in byte on screen
       dec   cx                         ; decrement loop count
       jz    lineexit                   ; jump to end if cx = 0
 delse:
       add   bp,1000h                   ; add error term
       js    straight

 diagonal:
       ror   dl,1                       ; rotate pixel right
       jnc   noincr                     ; skip if dl > 0
       inc   si                         ; increment x
 noincr:
 deldy:
       add   si,1000h
       or    [si],dl                    ; write the dot
       dec   cx                         ; decrement loop count
       jz    lineexit
 delde:
       add   bp,1000h                   ; add error term
       js    straight                   ; if bp<0 goto straight
       jmp   diagonal                   ; if bp>=0 goto diagonal
 ;
 ; absdeltax > absdeltay
 ;
 delsx2:
       or    [si],dl
       jcxz  lineexit
       or    bp,bp
       jge   diagonal2
 straight2:
       ror   dl,1                       ; rotate pixel right
       jnc   noincr2
       inc   si
 noincr2:
       or    [si],dl                    ; write the dot
       dec   cx
       jz    lineexit
 delse2:
       add   bp,1000h
       js    straight2
 diagonal2:
       ror   dl,1
       jnc   noincr3
       inc   si
 noincr3:
 deldy2:
       add   si,1000h
       or    [si],dl
       dec   cx
       jz    lineexit
 delde2:
       add   bp,1000h
       js    straight2
       jmp   diagonal2
 lineexit:
       pop   ds

 #

 }

 /************************** C _ W R I T E _ D O T *************************/
 /* This is the fast version of the color write dot routine.               */

 void c_write_dot(x,y)
    unsigned x,y;
    {
 #asm
       mov   si,[bp+6]                     ; get y value off stack
       mov   cx,si                         ; copy y to cx reg.
       shl   si,1                          ;
       shl   si,1                          ; y = y * 4
       add   cx,si                         ; y = (y*4 + y) = 5*y
 c_dot_buffer_start:
       add   cx,0a000h                     ; a0 -> ch = base page for ega
       mov   si,[bp+4]                     ; get x value off stack
       mov   dx,03ceh                      ; select bit mask reg. for out
       mov   al,08h                        ; to 03cfh.8
       out   dx,al
       mov   ax,si                         ; copy x to ax reg.
       and   al,07h                        ; al >= 0 and <= 7
       mov   bx,offset pixel_table_        ; use al as lookup for bit position
       xlat  pixel_table_                  ; al now contains bit to write
       shr   si,1
       shr   si,1
       shr   si,1                          ; si = si / 8
       mov   es,cx                         ; es now = base adr. + y * 5 * 16
       inc   dx                            ; mask all but desired pixel
       out   dx,al                         ; output mask to 03fh.8
 ;
       mov   al,es:[si]                    ; dummy read
       mov   al,0ffh
       mov   es:[si],al                    ; blank pixel
 ;
 #
    }

 /*************************** S H O W _ B U F F E R *************************/
 /*
          function show_buffer(x)

                Input: x - (0 or 1) Note: this function is provided for double
                                          buffering in 640x350 16 color mode.
                                          You must have 256k in the EGA's
                                          memory for this to work!!!!
                Returns: none
 */

 void show_buffer(x)
    unsigned x;
    {
 #asm
       mov   ax,[bp+4]
       mov   cx,03d4h
       mov   dx,cx                           ; reg cx = 03d4h
       or    ax,ax
       jz    buffer0                         ; Jump if buffer 0 selected
       mov   al,0ch                          ; Start Address High Register
       out   dx,al                           ; Out 3d4,0c
       inc   dx
       mov   al,80h
       out   dx,al                           ; Out 3d5,80
       mov   dx,cx                           ; Now fix Address Low Register
       mov   al,0dh
       out   dx,al                           ; Out 3d4,0d
       inc   dx
       mov   al,00h
       out   dx,al                           ; Out 3d5,00
       jmp   exo
 buffer0:
       mov   al,0ch                          ; Start Address High Register
       out   dx,al                           ; Out 3d4,0c
       inc   dx
       xor   al,al
       out   dx,al                           ; Out 3d5,00
       mov   dx,cx                           ; Now fix Address Low Register
       mov   al,0dh
       out   dx,al                           ; Out 3d4,0d
       inc   dx
       xor   al,al
       out   dx,al                           ; Out 3d5,00
 exo:
 #
 }


 /****************************** S E T _ C O L O R *************************/
 /*
          function set_color(color)

             Input: color (0..15) = color Note: this routine must be used
                                                before calling either
                                                color_write_line or
                                                color_write_dot.
             Returns: none
 */

 void set_color(color)
    unsigned color;
    {
 #asm
       mov   dx,03ceh                   ; Select s/r register
       xor   al,al
       out   dx,al
       inc   dx
       mov   al,[bp+04]                ; output color to s/r resister
       out   dx,al
       dec   dx                         ; dx = 03ce
       mov   al,01                      ; Select s/r register enable
       out   dx,al
       inc   dx
       mov   al,0ffh                    ; select s/r for all planes
       out   dx,al
 #
    }

 /**************************** C L E A R _ C O L O R ***********************/
 /*
          function clear_color()

             Input: none

             Returns: none       Note:  the function must be called
                                        after using set_color. Otherwise
                                        you will get garbage on the
                                        screen when attempting to write
                                        text with bios.
 */

 void clear_color()
    {
 #asm
       mov   dx,03ceh
       mov   al,01                      ; Out 03ce,01
       out   dx,al
       inc   dx
       dec   al                         ; Disable s/r on all planes
       out   dx,al                      ; Out 03cf,00
       dec   dx
       mov   al,08                      ; Select bit mask register
       out   dx,al                      ; Out 03ce,08
       inc   dx
       mov   al,0ffh                    ; Turn bit mask off
       out   dx,al                      ; Out 03cf,ff
 #
 }

 /************************ C _ L I N E _ D R A W ****************************/
 /* this is the color fast line draw */
 void c_line_draw(x1,y1,x2,y2)
    unsigned x1,y1,x2,y2;
    {
 #asm
       push  ds                         ; save ds reg.
       mov   si,[bp+04h]                ; reg. si = x1
       mov   di,[bp+08h]                ; reg. di = x2
       mov   cx,[bp+06h]                ; reg. cx = y1
       mov   dx,[bp+0ah]                ; reg. dx = y2
       cmp   si,di                      ; cmp x1, x2
       jle   swapxyc                    ; skip if (x1<=x2)
       xchg  cx,dx                      ; x1 > x2 so swap y1,y2
       xchg  si,di                      ; and swap x1,x2
 swapxyc:
       sub   dx,cx                      ; dy = y2-y1
       mov   al,80                      ; deldy = 80
       jge   ydownc                     ; skip if y1<=y2
       neg   dx                         ; |y2-y1|
       neg   al                         ; -80
 ydownc:
       sub   di,si                      ; absdx = x2-x1
       cmp   di,dx                      ; di = absdx, dx = absdy
       lahf                             ; save flags
       jnl   minmaxc                    ; skip if absdx >= absdy
       xchg  di,dx
 minmaxc:
       xchg  ax,bp
 ;
 ; compute initial ds address (a000h + y * 80)
 ; al = initial pixel
       mov   ax,cx                      ; copy y to ax reg.
       shl   ax,1
       shl   ax,1                       ; y = y * 4
       add   cx,ax                      ; y = y * 4 + y = 5y
       shl   cx,1
       shl   cx,1
       shl   cx,1
       shl   cx,1                       ; y = 5y * 16
       mov   bx,offset pixel_table_     ; get location of pixel lookup table
       mov   al,07h
       and   ax,si                      ; mask out bits > 8
       xlat  pixel_table_               ; get starting pixel location
       sal   dx,1                       ; dx = delse = dmin * 2
       xchg  ax,dx                      ; ax = delse, dx = pixel location
       xchg  ax,bp                      ; ax = flags(absdx,absdy), bp=delse
       sahf                             ; cmp absdx,absdy
       pushf                            ; save flags on stack
       cbw                              ; ax = deldy
       mov   cs:delsyc+2,ax             ; save deldy
       mov   cs:deldyc+2,ax
       mov   cs:deldy2c+2,ax

       xchg  ax,bp                      ; ax = dmin * 2 = delse
       mov   cs:delsec+2,ax              ; save delse
       mov   cs:delse2c+2,ax
       sub   ax,di                      ; ax = dmin * 2 - dmax = d
       mov   bp,ax                      ; bp = d = error for start
       sub   ax,di                      ; ax = dmin * 2 - dmax * 2
       mov   cs:deldec+2,ax              ; save delde
       mov   cs:delde2c+2,ax
       sar   si,1
       sar   si,1
       sar   si,1                       ; x = x / 8
       add   si,cx
 c_line_buffer_start:
       mov   cx,0a000h
       mov   ds,cx
       mov   cx,di
       mov   ah,dl
       mov   al,08                      ; select bit mask register
       mov   dx,03ceh
       out   dx,al
       inc   dx
       mov   al,ah
       out   dx,al                      ; output bit to mask register
       dec   dx
       mov   al,[si]                    ; dummy read
       mov   al,0ffh
       mov   [si],al                    ; write all ones to address
       or    cx,cx                      ; check for zero line length
       jz    lineexitc
       popf
       jns   delsx2c
       or    bp,bp
       jge   diagonalc
 straightc:
 delsyc:
       add   si,1000h                   ; increment y by -80 or 80
       mov   al,[si]                    ; dummy read for data latches on ega
       mov   al,0ffh
       mov   [si],al                    ; write all ones to address <- si
       dec   cx                         ; decrement loop count
       jz    lineexitc                  ; jump to end if cx = 0
 delsec:
       add   bp,1000h                   ; add error term
       js    straightc
 diagonalc:
       ror   ah,1                       ; rotate pixel right
       jnc   noincrc                    ; skip if ah > 0
       inc   si                         ; increment x
 noincrc:
       mov   al,08                      ; store bit in bit mask reg.
       out   dx,al
       mov   al,ah
       inc   dx
       out   dx,al
           dec        dx
 deldyc:
       add   si,1000h
       mov   al,[si]                    ; dummy read
       mov   al,0ffh
       mov   [si],al                    ; write all ones
       dec   cx                         ; decrement loop count
       jz    lineexitc
 deldec:
       add   bp,1000h                   ; add error term
       js    straightc                  ; if bp<0 goto straight
       jmp   diagonalc                  ; if bp>=0 goto diagonal
 ;
 ; absdeltax > absdeltay
 ;
 delsx2c:
       or    bp,bp
       jge   diagonal2c
 straight2c:
       ror   ah,1                       ; rotate pixel right
       jnc   noincr2c
       inc   si
 noincr2c:
       mov   al,08                      ; store bit in bit mask reg.
       out   dx,al
       mov   al,ah
       inc   dx
       out   dx,al
       dec   dx
       mov   al,[si]                    ; dummy read
       mov   al,0ffh
       mov   [si],al                    ; write all ones
       dec   cx
       jz    lineexitc
 delse2c:
       add   bp,1000h
       js    straight2c
 diagonal2c:
       ror   ah,1
       jnc   noincr3c
       inc   si
 noincr3c:
       mov   al,08                      ; store bit in bit mask reg.
       out   dx,al
       mov   al,ah
       inc   dx
       out   dx,al
       dec        dx
 deldy2c:
       add   si,1000h                   ; y increment or decrement by 80
       mov   al,[si]                    ; dummy read
       mov   al,0ffh
       mov   [si],ah
       dec   cx
       jz    lineexitc
 delde2c:
       add   bp,1000h
       js    straight2c
       jmp   diagonal2c
 lineexitc:
       pop   ds                         ; restore data segment
 #
 }

 /********************** S E T _ W R I T E _ B U F F E R ********************/
 /*
          function set_write_buffer(x)

                Input: x - (0 or 1) Note: this function is provided for double
                                          buffering in 640x350 16 color mode.
                                          You must have 256k in the EGA's
                                          memory for this to work!!!!
                Returns: none
 */

 void set_write_buffer(x)
    unsigned x;
    {
 #asm
       mov   ax,[bp+4]
       or    ax,ax
       mov   ax,0a000h
       jz    lower_write
       mov   ax,0a800h
 lower_write:
       mov   cs:dot_buffer_start+2,ax
       mov   cs:line_buffer_start+1,ax
       mov   cs:c_line_buffer_start+1,ax
       mov   cs:c_dot_buffer_start+2,ax
 #
 }

 void  write_lower_pattern()
   {
       unsigned int i,j,k=0;
       set_color(3);                  /* Set the color to cyan */
       for(i=150;i<340;i += 3)        /* Draw pattern with cyan lines */
          c_line_draw(1,150,600,i);

       set_color(4);                                         /* Set the color
       for(i=1;i<340;i += 3)          /* Draw pattern with red lines */
          c_line_draw(300,1,100,i);

       set_color(1);                  /* Set the color to blue  */

       for(i=0;i<=340;i += 10)        /* Draw a grid pattern    */
          c_line_draw(1,i,600,i);
       for(i=0;i<=600;i += 10)
          c_line_draw(i,1,i,340);

       for(i=300;i<600;i += 4,k++)    /* Show off the color dot writing */
       {
        set_color(k);
        for(j=1;j<150;++j)
         {
           c_write_dot(i,j);
         }
       }
   }


 void  write_upper_pattern()
   {
       unsigned int i,j,k=0;
       set_color(5);                  /* Set the color to magenta */
       for(i=150;i<340;i += 4)        /* Draw pattern with magenta lines */
          c_line_draw(4,150,600,i);

       set_color(2);                                            /* Set the col
       for(i=1;i<340;i += 2)          /* Draw pattern with red lines */
          c_line_draw(300,1,200,i);

       set_color(12);                  /* Set the color to bright red  */

       for(i=0;i<=340;i += 20)         /* Draw a grid pattern    */
          c_line_draw(1,i,600,i);
       for(i=0;i<=600;i += 20)
          c_line_draw(i,1,i,340);

       for(i=300;i<600;i += 5,k++)    /* Show off the color dot writing */
       {
        set_color(k);
        for(j=150;j<300;++j)
         {
           c_write_dot(i,j);
         }
       }
   }

 void draw_box(size)
    unsigned int size;
    {
       c_line_draw(0,0,size,0);
       c_line_draw(size,0,size,size);
       c_line_draw(size,size,0,size);
       c_line_draw(0,size,0,0);
    }

 /* Here is a little example to show you how to use the above functions ! */

 main()
    {
       unsigned int i,h,times, delay;
       set_video_mode(0x10);    /* SET THE HIRES (640X350 - 16 COLOR) */
       set_write_buffer(0);     /* Do all writing to lower buffer */
       show_buffer(0);          /* Display lower buffer */
       write_lower_pattern();   /* Write 'stuff' to lower buffer */

       set_write_buffer(1);     /* Do all writing to upper buffer */
       write_upper_pattern();   /* Write 'stuff' to upper buffer */
       show_buffer(1);          /* Display the upper buffer */
       for(times=0;times<50000;times++);
       show_buffer(0);
       for(times=0;times<2;times++)
        {
          show_buffer(0);
          for(delay=0;delay<40000;++delay);
          show_buffer(1);
          for(delay=0;delay<40000;++delay);
        }
       set_video_mode(0x10);
       show_buffer(0);
       set_write_buffer(0);

       for(h=0;h<20;++h)
        for(i=1;i<16;++i)
         {
          set_color((i+h) & 15);
          if(i % 2)
           {
             show_buffer(0);
             set_write_buffer(1);
           }
          else
           {
             show_buffer(1);
             set_write_buffer(0);
           }
          for(times=i*20-10;times<i*20;times++)
              draw_box(times);
          }

       show_buffer(0);

       clear_color();                 /* You need this command to     */
                                      /* clean up after your graphics */
                                      /* operations                   */
       printf("All done......\n\n");
    }


 CHARCLAS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\CHARCLAS.C

                                          /* Chapter 13 - Program 2 */
 #include "stdio.h"
 "ctype.h"       /* Note - your compiler may not need this */

 main()
 {
 FILE *fp;
 char line[80], filename[24];
 char *c;

    printf("Enter filename -> ");
    scanf("%s",filename);
    fp = fopen(filename,"r");

    do {
       c = fgets(line,80,fp);   /* get a line of text */
       if (c != NULL) {
          count_the_data(line);
       }
    } while (c != NULL);

    fclose(fp);
 }

 count_the_data(line)
 char line[];
 {
 int whites, chars, digits;
 int index;

    whites = chars = digits = 0;

    for (index = 0;line[index] != 0;index++) {
       if (isalpha(line[index]))   /* 1 if line[] is alphabetic  */
           chars++;
       if (isdigit(line[index]))   /* 1 if line[] is a digit     */
           digits++;
       if (isspace(line[index]))   /* 1 if line[] is blank, tab, */
           whites++;               /*           or newline       */
    }   /* end of counting loop */

    printf("%3d%3d%3d %s",whites,chars,digits,line);
 }


 CHARCNT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\CHARCNT.C

 /* CHARCNT.C - From page 434 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. This file counts characters in    */
 /* a file that is opened as a text file as opposed to a file    */
 /* opened as a binary mode file. These 2 modes differ in the    */
 /* way they handle the EOF and the CR/LF-newline. See CHARCNT2.C*/
 /****************************************************************/

 #include <stdio.h>

 main(argc, argv)
 int argc;
 char *argv[];
 {
 FILE *fptr;
 char string[81];
 int count = 0;

    if(argc != 2) {
       printf("\nFormat: C>charcnt2 filename");
       exit();
    }
    if((fptr = fopen(argv[1], "r")) == NULL) {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    while(getc(fptr) != EOF)
       count++;
    fclose(fptr);
    printf("\nFile %s contains %d characters.", argv[1], count);
 }





 CHARCNT2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\CHARCNT2.C

 /* CHARCNT2.C - From page 444 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. This file counts characters in    */
 /* a file that is opened as a binary file as opposed to a file  */
 /* opened as a text mode file. These 2 modes differ in the      */
 /* way they handle the EOF and the CR/LF-newline.               */
 /****************************************************************/

 #include <stdio.h>

 main(argc, argv)
 int argc;
 char *argv[];
 {
 FILE *fptr;
 char string[81];
 int count = 0;

    if(argc != 2) {
       printf("\nFormat: C>charcnt2 filename");
       exit();
    }
    if((fptr = fopen(argv[1], "rb")) == NULL) {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    while(getc(fptr) != EOF)
       count++;
    fclose(fptr);
    printf("\nFile %s contains %d characters.", argv[1], count);
 }





 CHAROUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\CHAROUT.C

                                          /* Chapter 10 - Program 2 */
 #include "stdio.h"
 main()
 {
 FILE *point;
 char others[35];
 int indexer,count;

    strcpy(others,"Additional lines.");
    point = fopen("tenlines.txt","a"); /* open for appending */

    for (count = 1;count <= 10;count++) {
       for (indexer = 0;others[indexer];indexer++)
          putc(others[indexer],point);  /* output a single character */
       putc('\n',point);                /* output a linefeed */
    }
    fclose(point);
 }


 CHATT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CHATT\CHATT.C


 /***********************************************************************/
 /* CHATT.C - This program was typed from the April 1988 issue of Micro */
 /* Systems Journal from an article by Mark Zeiger titled "Using MS-DOS */
 /* Functions in C". CHATT changes file mode to or from READ/ONLY,      */
 /* SYSTEM, or HIDDEN interactively by first displaying current mode    */
 /* and then asking if you wish a change to be made. Wildcards may be   */
 /* used. CHATT.C and its functions was written in Eco-88 by the author */
 /* and modified by the typist for Quick-C. This file will not work     */
 /* with Eco-88. I (the typist) couldn't get the program to work with   */
 /* some of Mr. Zeigler's code and made some changes, most notably in   */
 /* the format of the way the prompt to change is handled and in the    */
 /* method of calling INT 21h. If you have the article you can compare  */
 /* the code, if you don't it won't matter anyhow; the program works    */
 /* and will compile as is with Quick C in the small memory model. Note */
 /* that getzf.asm must be assembled and the two object modules must    */
 /* be linked with chatt.obj linked first. Any changes I made are re-   */
 /* flected in the remarks and code below.                              */
 /***********************************************************************/

 /*
 Command line parameters

 C>chatt [control] [path\]filename [[path\]filename ...]

 "Control" parameter specifies whether attribute should be turned on or off
 and whether you should be asked if change is to be done.

 R specifies READ/ONLY, H specifies hidden, and S specifies SYSTEM. If path is
 not specified, default directouy is used. Filename may include wildcard
 characters. A directory alone is expanded to all files in directory (i.e.
 test = test\*.* if test is a directory).

 A "+N" in control parameter will allow changes to be made without asking. If
 no control parameter is specified then attributes will be displayed only.
 A "-N" in control paremeter is equivilent to omitting this paremeter, you wil
 be asked to confirm each change.
 The control parameter takes the form of the string +/-R | +/-H | +/-S | +/-N
 any order, and the control string must start with a + or -)

    examples:

 1. chatt +r-h+s+n abc\*.com   Changes all .COM files in directory "abc" to
                               READ/ONLY and SYSTEM andtakes away HIDDEN
                               attribute. No prompt is issued for each file

 2. chatt -s+h abc\*.* d:*.asm Changes all files in directory "abc" to HIDDEN
                               and all .ASM files in current directory of driv
                               "D" to HIDDEN. Also takes away SYSTEM attribute
                               of those files. You will be prompted if change
                               is to be done.

 3. chatt -s+h abc d:*.asm     Same as above

 4. chatt \abc\*.com           Lists attributes of all .COM files in dir \abc.
 */

 <dos.h>           /* declares REGS */
 #include <string.h>
 <ctype.h>         /* for toupper(), etc. */

 #define TRUE 1
 #define FALSE 0
 #define NULL 0

 /* DOS call parameters */

  MSDOSS   0x0021   /* MS-DOS interrupt */
  SETMODE  0x4301   /* subfunction number in AL */
  GETMODE  0x4300   /* subfunction number in AL */
  SEARCHF  0x4e00   /* search for first occurance */
  SEARCHN  0x4f00   /* search for next occurance */
  SETDMA   0x1a00   /* set DMA address */
  CONNIO   0x06     /* raw console I/O */
  CARRYF   0x0001   /* position of carry flag */
  ZEROF    0x0040   /* position of zero flag */

 /* file attribute bits for function 43H */

 #define  RO       0x0001
 #define  HIDDEN   0x0002
 #define  SYSTEM   0x0004
 #define  VOLUME   0x0008
 #define  SUBDIR   0x0010

 /* errors from setmode and search commands */

  NOFILE   0x0002   /* file not found */
  NOPATH   0x0003   /* path not found */
  NOACCESS 0x0005   /* access denied */
  NOFILES  0x0012   /* no more files on SEARCHN */

 /* BIOS interrupt 10h constants */

  CURR_VIDEO  0x0f   /* */
  READ_CURSOR 0x03   /* */
  SET_CURSOR  0x02   /* */
  VIDEO_INT   0x0010   /* */

 /* structure filled in by SEARCHF command of MS-DOS */

 struct DMA {
    char reserved[21];   /* reserved by MS-DOS */
    char attribute;      /* attribute of file */
    unsigned time;
    unsigned date;
    unsigned size_L;     /* file size - low word */
    unsigned size_h;     /* file size - high word */
    char fname[13];      /* parsed name of file */
 };

 union REGS inregs, outregs;
 struct SREGS segregs;

 /*---------------------------- MAIN -----------------------------------*/

 main(argc, argv)
 int argc;
 char *argv[];
 {
    char atton_off;      /* is it a + or - */
    char path[64];       /* holds path name up to 64 bytes */
    char new_arg[64];    /* might hold subdir concat with \*.*    */
    int bslpos;          /* position of last backslash in path name */
    struct DMA dmabuf;   /* used for MS-DOS search function */
    int i;               /* used to count parameters */
    int carryf;          /* carry flag for MS-DOS calls */

    void fpe(), bad_syntax(), pfname();
    void set_att_masks(), change_att();
    void concat();
    void display_type();
    char lastchar();
    int getpath();

    unsigned att_on_mask, att_off_mask; /* masks to set/reset attributes */
    unsigned ask;                       /* prompt for each change ???    */
    int start_file;               /* which argv[] contains 1st. path\file */
    int display_att_only;         /* flag to display attributes only */

    if (argc < 2)
       bad_syntax();
    atton_off = argv[1][0];
    if (atton_off != '+' && atton_off != '-') {
       start_file = 1;                  /* argv[1] is a path */
       display_att_only = TRUE;
    }
    else {
       start_file = 2;               /* argv[1] is control parameter */
       display_att_only = FALSE;     /* and argv[2] starts files */
       if (argc < 3)                 /* must have at least one file */
          bad_syntax();
       set_att_masks(argv[1], &att_on_mask, &att_off_mask, &ask);
    }

 /* set the MS-DOS DMA x'fer address to dmabuf */

    segread(&segregs);      /* put seg regs in structure (need DS) */
    inregs.x.ax = SETDMA;              /* AH = funct 1Ah */
    inregs.x.dx = (unsigned) &dmabuf;
    int86x(MSDOSS, &inregs, &outregs, &segregs);

    for(i = start_file; i < argc; i++) {
       /* changes a subdirectory name to subdir\*.* or changes root to
          full search (\ -> \*.*) or changes to drivespec:\*.* (c: -> c:\*.*)
       */
       if (lastchar(argv[i]) == ':') {
          concat(new_arg, argv[i], "\\*.*");
          argv[i] = new_arg;
       }
       else if(lastchar(argv[i]) == '\\') {
          concat(new_arg, argv[i], "*.*");
          argv[i] = new_arg;
       }
       else {      /* Subdirectory ? or file ?   */
          segread(&segregs);      /* put seg regs in structure (need DS) */
          inregs.x.ax = GETMODE;  /* AX = 4300 (Int 43h, 00 = 'get' mode */
          inregs.x.dx = (unsigned) argv[i];
          int86x(MSDOSS, &inregs, &outregs, &segregs);
          carryf = outregs.x.cflag;
          if(outregs.x.cx == SUBDIR) {
             concat(new_arg, argv[i], "\\*.*");
             argv[i] = new_arg;
          }
       }

       bslpos = getpath(argv[i], path);

       fpe("\n====================> ");
       fpe(" >====================\n\n");

       segread(&segregs);      /* put seg regs in structure (need DS) */
       inregs.x.ax = SEARCHF;             /* AH = funct 4Eh */
       inregs.x.dx = (unsigned) argv[i];
       inregs.x.cx = 0x001f;              /* search for file with any attri- *
       int86x(MSDOSS, &inregs, &outregs, &segregs);  /* bute except archive */
       carryf = outregs.x.cflag;

       if ((carryf & CARRYF) == CARRYF) {
          if ((outregs.x.ax == NOFILES) || (outregs.x.ax == NOPATH )) {
             fpe("\n");
             fpe(argv[i]);
             fpe(" not found\n\n\r");
          }
          else {
             fpe("\nUndefined error\n\007");
             exit(1);
          }
       }

       while((carryf & CARRYF) != CARRYF) {
          pfname(path, &(dmabuf.fname[0]), bslpos);
          fpe(path);     /* echo path and/or file */
          display_type(dmabuf.attribute);        /* echo current attribs */
          if ((display_att_only != TRUE) && (dmabuf.attribute != SUBDIR))
             change_att(path, dmabuf.attribute, &att_on_mask,&att_off_mask,&as
          else
             fpe("\n");

          segread(&segregs);      /* put seg regs in structure (need DS) */
          inregs.x.ax = SEARCHN;  /* AX = 4F00 (4Fh= 'search for next match' *
          int86x(MSDOSS, &inregs, &outregs, &segregs);
          carryf = outregs.x.cflag;
       }
    }        /* end of for loop */
    exit(0);
 }           /* end of main */

 /*-----------Funct set_att_masks---------------------------------------*/
 /*
    When it comes time to set or reset attributes, directory attribute byte
    will be "or"ed with "att_on_mask" to set attribute bits we want on and the
    "and"ed with "att_off_mask" to reset attributes we want off. This is done
    in function "change_att()".
 */

 void set_att_masks(att_string, att_on_mask, att_off_mask, ask)
 char *att_string;
 unsigned *att_on_mask, *att_off_mask, *ask;
 {

 int sub_str();

    *att_on_mask = 0;
    *att_off_mask = 0xffff;

    if (sub_str(att_string, "+R"))  *att_on_mask |= RO;
    else if (sub_str(att_string, "-R"))  *att_off_mask ^= RO;

    if (sub_str(att_string, "+H"))  *att_on_mask |= HIDDEN;
    else if (sub_str(att_string, "-H"))  *att_off_mask ^= HIDDEN;

    if (sub_str(att_string, "+S"))  *att_on_mask |= SYSTEM;
    else if (sub_str(att_string, "-S"))  *att_off_mask ^= SYSTEM;

    if (sub_str(att_string, "+N"))  *ask = FALSE;
    else *ask = TRUE;
 }

 /*----------------------function sub_str()-----------------------------*/

 /*
    Returns TRUE if substring (+R,-H, etc.) is contained in first string or
    FALSE if not. Case insensitive.
 */

 int sub_str(main_string, sub_string)
 char *main_string, *sub_string;
 {

 static int *pos, temp;
 int len_main, len_sub;
 int xstrcomp();

    pos = &temp;         /* point to any int to initialize */
    len_main = strlen(main_string);
    len_sub = strlen(sub_string);
    if (len_main < len_sub)
       return FALSE;
    for (*pos = 0; *pos < len_main - len_sub + 1; (*pos)++)
       if (xstrcomp(main_string, sub_string, pos, len_sub))
          return TRUE;
    return FALSE;
 }

 /*------------------------function xstrcomp()--------------------------*/

 /*
    Compares "sub_string" substring with "main_string" starting at "pos"
    with a length of "length". Case insensitive.
 */

 int xstrcomp(main_string, sub_string, pos, length)
 char *main_string, *sub_string;
 int *pos, length;
 {

 int j;

    for( j = 0; j < length; (*pos)++, j++) {
       if(toupper(*(main_string + *pos)) != toupper(*(sub_string + j))) {
          if(!(isalpha(*(main_string + *pos))))     /* if not alphabetic */
             (*pos)++;
          return FALSE;
       }
       continue;
    }
    return TRUE;
 }

 /*------------------------function concat()----------------------------*/

 /*
    Concatenates "first" string followed by "second" and puts result in "new"
    string.
 */

 void concat(new, first, second)
 char *new, *first, *second;
 {

    while(*first != (char) NULL) {
       *new = *first;
       first++;
       new++;
    }
    while(*second != (char) NULL) {
       *new = *second;
       second++;
       new++;
    }
    *new = (char) NULL;
 }

 /*--------------------------function lastchar()------------------------*/

 /*
    returns the last (non-null) character of a string
 */

 char lastchar(string)
 char *string;
 {
    return string[(strlen(string) - 1)];
 }

 /*-------------------------function getpath()--------------------------*/

 /*
    Puts path name (without file name) in array "path" and returns position of
    last backslash. If no path name (default dir) then puts NULL string in
    path[] and sets bslpos to -1. A path is also considered to be a drive
    specification without a subdirectory, hence the test for(:).
 */

 int getpath(argvs, path)
 char *argvs, *path;
 {

 static char ch;
 register int i;
 int bslpos = -1;

    for(i = 0; (ch = argvs[i]) != (char) NULL; i++) {
       if (ch == '\\' || ch == ':')
          bslpos = i;
    }
    if (bslpos != -1)
       for(i = 0; i <= bslpos; i++)
          path[i] = argvs[i];
    path[i] = NULL;
    return bslpos;
 }

 /*--------------------------function pfname()--------------------------*/

 /*
    Puts file name (from dmabuf.fname) at end of path (which contains
    pathname).  bslpos is position of last backslash.
 */

 void pfname(path, fname, bslpos)
 char *path, *fname;
 int bslpos;
 {

 register i, j;
 static char ch;

    j = bslpos != -1 ? bslpos + 1 : 0;
    for (i = 0; (ch = fname[i]) != (char) NULL; i++, j++)
       path[j] = fname[i];
    path[j] = (char) NULL;
 }

 /*------------------function change_att()------------------------------*/

 /*
    Changes attribute of file after query (unless "ask" is FALSE). No change i
    subdirectory.
 */

 void change_att(fullname, att, att_on_mask, att_off_mask, ask)
 char *fullname;
 unsigned att, *att_on_mask, *att_off_mask, *ask;
 {

 static unsigned char answer;
 static int carryf;
 char input();
 void echo(), state_err(), fpe();

    if (*ask == TRUE) {
       fpe("     Change? ");
       do {
          answer = input();
          if (answer == 3)        /* abort if ^C */
             exit(2);
       }
       while ((toupper(answer) != 'Y') && (toupper(answer) != 'N'));
       echo(answer);
    }
    else answer = 'Y';         /* force answer without asking */
    if(toupper(answer) == 'Y') {
       segread(&segregs);      /* put seg regs in structure (need DS) */
       inregs.x.ax = SETMODE;  /* AX = 4301, (Int 43h, 01 = 'set' mode  */
       inregs.x.cx = att | *att_on_mask;
       inregs.x.cx = (inregs.x.cx & *att_off_mask) & 0x00ff;
       inregs.x.dx = (unsigned) fullname;
       int86x(MSDOSS, &inregs, &outregs, &segregs);
       carryf = outregs.x.cflag;
       if ((carryf & CARRYF) == CARRYF)
          state_err(outregs.x.ax);
    }
    fpe("\n");
 }

 /*----------------------function state_err-----------------------------*/
 /*
    States error returned in AX register after change attribute call. Will
    abort if no file or incorrect path since this indicates program can not
    start. Will not abort on "Access Denied" since this can happen with
    subdirectories.
 */

 void state_err(rax)
 unsigned rax;
 {

 void fpe();

    rax = rax & 0x00ff;        /* isolate AL register */
    if (rax == NOFILE)
       fpe("\nFile not found.\007");
    if (rax == NOPATH)
       fpe("\nPath not found.\007");
    if (rax == NOACCESS)
       fpe("    Access denied.\007");

    if ( !((rax == NOFILE) || (rax == NOPATH) || (rax == NOACCESS )))
       fpe("\n\007Undefined error.");
    if (rax == NOACCESS) {
       fpe("\n");
       exit(1);
    }
 }

 /*---------------------function bad_syntax()---------------------------*/
 /*
    Indicates command line error and shows correct syntax.
 */

 void bad_syntax()
 {

 void fpe();

    fpe("\nIncorrect syntax\007");      /* 361 is octal for +/-  */
    fpe("\n\nUsage: chatt [\361R | \361S | \361H | \361N] file file ...\007");
    fpe("\n\n\361R = R/O on/off.");
    fpe("\n\361S = SYSTEM on/off.");
    fpe("\n\361H = HIDDEN on/off.");
    fpe("\n+N = Change without asking.");
    fpe("\nControls may be strung together.");
    fpe("\n   i.e. +R-H+N+S or -S+R+N");
    fpe("\n\nIf no control, then file attributes are displayed only.\n");
    exit(1);
 }

 /*------------------function display_type()----------------------------*/
 /*
    Displays attribute of file. Called from pfname() which gets attribute from
    dmabuf.attribute.
 */

 void display_type(att)
 char att;
 {

 void fpe(), cursor_col();

    cursor_col(30);
    if ((att & 0x1f) == 0)
       fpe(" NORMAL");
    else {
       if ((att & RO) == RO)
          fpe(" READ/ONLY");
       if ((att & HIDDEN) == HIDDEN)
          fpe(" HIDDEN");
       if ((att & SYSTEM) == SYSTEM)
          fpe(" SYSTEM");
       if ((att & VOLUME) == VOLUME)
          fpe(" VOLUME");
       if ((att & SUBDIR) == SUBDIR)
          fpe(" SUB-DIRECTORY");
    }
 }

 /*------------------------function fpe()-------------------------------*/
 /*
    Prints string using MS-DOS console I/O function. This is because fputs()
    library function is incredibly slow. Also tests for console input and
    pauses if any key is pressed. Will resume when any key is pressed again.
 */

 void fpe(string)
 char *string;
 {

 static unsigned char ch, ch1;
 void echo();
 char input();

    while (( ch = *string++) != (unsigned char) NULL)
       if (ch != '\n')
          echo(ch);
       else {
          echo('\015');        /* ASCII CR */
          echo(ch);            /* now do linefeed */
       }
       if ((ch1 = input()) != (unsigned char) NULL)
          if (ch1 == 3)
             exit(1);
          else while ((ch1 = input()) == (unsigned char) NULL)
             if (ch1 == 3)
                exit(1);
 }


 /*---------------function cursor_col()---------------------------------*/
 /*
    Places cursor at column "col" of cursor line using BIOS int 10h
 */

 void cursor_col(col)
 int col;
 {

 static unsigned char current_page;

    inregs.h.ah = CURR_VIDEO;     /* Get current page funct */
    int86(VIDEO_INT, &inregs, &outregs);
    current_page = outregs.h.bh;

    inregs.h.ah = READ_CURSOR;    /* Read cur pos funct call */
    inregs.h.bh = current_page;   /* Page number */
    int86(VIDEO_INT, &inregs, &outregs);

    inregs.h.ah = SET_CURSOR;     /* Set cur pos funct call */
    inregs.h.bh = current_page;   /* Page number */
    inregs.h.dh = outregs.h.dh;   /* row (y) from fumct 3 above */
    inregs.h.dl = outregs.h.dl;   /* col (x) from funct 3 above */
    int86(VIDEO_INT, &inregs, &outregs);
 }

 /*-----------------------function input()------------------------------*/
 /*
    Will return NULL if not character ready, or character. Does not wait for
    input. Uses MS-DOS function AH = 6 for raw console I/O. Can not be used fo
    function key input.
 */

 char input()
 {

 static unsigned int zerof;    /* used for return of zero flag */
 extern int getzf();

    inregs.h.ah = CONNIO;              /* AH = funct 06h */
    inregs.h.dl = 0xff;           /* input subfunction */
    int86x(MSDOSS, &inregs, &outregs, &segregs);
    zerof = getzf();        /* ASM routine to get zero flag */

    if ((zerof & ZEROF) == ZEROF)
       return (char) NULL;
    else
       return outregs.h.al;
 }

 /*-----------------------function echo()-------------------------------*/
 /*
    Echos character to console using MS-DOS function AH = 6.
 */

 void echo(ch)
 unsigned char ch;
 {

    inregs.h.ah = CONNIO;
    inregs.h.dl = ch;
    int86(MSDOSS, &inregs, &outregs);
 }



 CHD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\GLOB\CHD.C


 /*
  *        chd.c                change directory
  *                        John Plocher
  *
  *        usage:        chd [new directory]
  *
  *                [new directory] may contain wildcards; it may not be ambigu
  *                If no arguments, use $HOME variable in environment
  *
  *                C:\BIN > set HOME=/usr/plocher
  *                C:\BIN > chd \u*\lo*
  *                C:\USR\LOCAL > chd
  *                C:\USR\PLOCHER >
  *
  *                uses glob() to expand wildcards in pathname
  *
  *        returns (ERRORLEVEL)
  *
  *                0        No error
  *                1        could not find directory
  *                2        ambiguous pathname
  *                3        directoryname expected, you gave a filename
  *                4        internal error
  *
  *        Change log
  *
  *        Version        Date                Who        Comments
  *        -------        ----                ---        --------
  *        1.00        16-Jan-86        jmp        Initially coded
  *        1.01        21-Jan-86        jmp        Expanded help menu (-?), fi
  */


 #include <stdio.h>
 #include "glob.h"

 #define VERSION        "1.01 21-Jan-86"
 /* #define DEBUG */

 char *sccsid        = "21-Jan-86 (Plocher) @(#)chd.c        1.01";

 extern char *strchr();
 extern char *getenv();
 extern char *strdup();
 extern void usage();

 extern char *filename();
 extern char *fixslash();
 extern void recover();

 main(argc, argv)
 int argc;
 char *argv[];
 {
     char **names;        /* array of pointers to names returned by glob() */
     char *progname;        /* name of program (either argv[0] or hardcoded) *
     char *p;                /* temp string pointer */
     char errstring[150];/* for usage() errors */
     char path[127];        /* workspace for getting starting (un-globbed) pat

     if (argv[0])        /* if there is something here, use it (DOS 3.xx+) */
             progname = filename(argv[0]);
     else                /* hardcode the program name */
             progname = "chd";

     if (argc > 2) {        /* must have less than 2 arguments */
             usage(progname,"Too many arguments");
             exit(1);
     }
     if (argc == 1) {                /* need to get HOME */
             p = getenv("HOME");        /* p == NULL if not found ... */
             if (p != NULL)
                     strcpy(path,p);
             else {
                     usage(progname,"Environment variable HOME not found\n");
                     exit(1);
             }
     } else {                /* we have a pathspec from command line */
             if (argv[1][0] == '-') {        /* if invoked chd -anything, just
                     usage(progname,NULL);        /* explain ourselves */
                     exit(0);
             }
             strcpy(path,argv[1]);
     }

     fixslash(path);        /* convert all '\'s into '/'s */

     names = glob(path);                        /* get files which match */

     if (names == NULL && globerror == GE_BADPATH) {
             sprintf(errstring,"Path not found: \"%s\"",path);
             usage(progname, errstring);
             recover(names);
             exit(1);
     }
     if ((names == NULL && globerror == GE_AMBIGUOUS) || names[1] != NULL) {
             sprintf(errstring,"Ambiguous pathname \"%s\"",path);
             usage(progname, errstring);
             recover(names);
             exit(2);
     }
     if (chdir(names[0])) {        /* do the actual chdir */
             usage(progname,"You must specify a DIRECTORY path");
             recover(names);
             exit(3);
     }
     if (names == NULL && (globerror == GE_MAXFILES || globerror == GE_NOMEM))
             sprintf(errstring,"Internal error: %s",
                 globerror == GE_MAXFILES ? "Too many files" : "Out of memory"
             usage(progname, errstring);
             recover(names);
             exit(4);
     }
     recover(names);        /* free memory used by *names[] */

     exit(0);                /* no errors */
 }

 /*
  *        usage                tell the workd about this program
  */
 void usage(progname, error)
 char *progname;
 {
 fprintf(stderr,"%s version %s by John Plocher on FidoNet 121/90\n",
                 progname,VERSION);
 if (error)
         fprintf(stderr,"\nERROR: %s\n",error);
 else {
  fprintf(stderr,"\n%s - a replacement for MS-DOS's chdir & cd commands\n",
                 progname);
  fprintf(stderr,"%s is Copyright 1986 by John Plocher\n\n",progname);
  fprintf(stderr,"%s is released to the NON PROFIT, NON COMMERCIAL public.\n",
                 progname);
  fprintf(stderr,"Commercial rights to %s reserved by John Plocher\n", prognam
  fprintf(stderr,"%s has some features which the DOS version lacks:\n",prognam
  fprintf(stderr,"\t1) ALL wildcards (* and ?) are expanded, no matter where\n
  fprintf(stderr,"\t   they are in the path.\n");
  fprintf(stderr,"\t\tC:\\ >%s \\u*\\p*\\w*\\?\n",progname);
  fprintf(stderr,"\t\tC:\\USR\\PLOCHER\\WORK\\C >\n");
  fprintf(stderr,"\t2) If %s is invoked without arguments, it will try to\n",p
  fprintf(stderr,"\t   change to the directory found in the environment\n");
  fprintf(stderr,"\t   variable HOME.\n");
  fprintf(stderr,"\t\tC:\\ >SET HOME=\\usr\\plocher    -or-\n");
  fprintf(stderr,"\t\tC:\\ >SET HOME=\\u*\\p*\n");
  fprintf(stderr,"\t3) If %s fails, it leaves an indication in ERRORLEVEL.\n",
  fprintf(stderr,"\t   This exit code can be tested in batch files:\n");
  fprintf(stderr,"\t    ERRORLEVEL  Meaning\n");
  fprintf(stderr,"\t    ----------  -------\n");
  fprintf(stderr,"\t\t0        No error\n");
  fprintf(stderr,"\t\t1        could not find directory\n");
  fprintf(stderr,"\t\t2        ambiguous pathname\n");
  fprintf(stderr,"\t\t3        directoryname expected, you gave a filename\n")
  fprintf(stderr,"\t\t4        internal error (let me know about this!)\n\n");
 }
 fprintf(stderr,"usage: %s <directory name>     change to directory\n",prognam
 fprintf(stderr,"       %s                      change to HOME\n",progname);
 fprintf(stderr,"       %s -?                   help screen\n",progname);
 }

 /*
  *        filename                extract the filename from a pathname
  *                                ie C:\usr\plocher\chd.exe results in chd
  */
 char *filename(path)
 char *path;

 {
         register char *p, *pd;

         p = strchr(path,'\0');        /* work from the back... */
         while (--p != path && *p != ':' && *p != '\\' && *p != '/');
         if (*p == '\\' || *p == '/' || *p == ':')
                 p++;
         pd = strchr(p,'.');                /* we don't want the .EXE */
         if (pd != NULL)
                 *pd = '\0';
         strlwr(p);
         return (p);
 }

 /*
  *        fixslash        convert all '\'s to '/'s
  */
 char *fixslash(s)
 char *s;
 {
         register int x;

         if (s == NULL) return;
         for (x=0; x < strlen(s); x++)
                 if (s[x] == '\\')
                         s[x] = '/';
 }


 /*
  *        recover                free up the space malloc()'d in *names[] by
  */
 void recover(names)
 char **names;
 {
         register int i;

         i = 0;
         while (names[i] != (char *)0) {
                 free(names[i]);
                 i++;
         }
         free(names);
 }



 CHECKC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\CSR20A\CHECKC.C

 /* Christmas, 1985 - Bob Pritchett */
 /*   Modify and distribute as you will, just leave the credits. */
 /*   ...My small gift to the PD world... */

 /* NOTE: This source code is NO LONGER in the Public Domain.  I have */
 /* left the above message and the other comments to give a history of */
 /* the program.  It is currently a part of the C Spot Run C Add-On Library. *

 /* Tiny bug and multiple files added the day after... */

 /* 01/09/1986 RDP Fixed a bug, (yes, another...) and added error tally. */
 /* 02/07/1986 RDP Going for effiecient analysis... */
 /* 02/08/1986 RDP More analysis... */
 /* 06/15/1986 RDP More work on 2.0.... */
 /* 07/16/1986 RDP Continuing on 2.0, hopefully near completion. */
 /*                Version 2.1 now.  CheckC.ANL eliminated. */
 /* 07/17/1986 RDP More accurate location of some errors. */
 /* 07/19/1986 RDP Can trace a new error with the ; check. */
 /* 08/05/1986 RDP Attempting to fix ; error.... */
 /* 09/16/1986 RDP Oh, what the heck.  Let's add comment beginning variable. *
 /*                (This tells what line starts 'EOF with comment open.') */

 /*


         Simply put, this program will check your C code's syntax in just
         about every concievable way that does not involve CheckC to track
         variable names or any other identifiers.  If you really care, read
         CHECKC.DOC.  Informal testing has shown that it can narrow down
         almost any syntactical error to within 3 lines, and it supports full
         error recovery.  (When I say syntax errors, I mean {} () [] "" ''
         comments, etc.)  The program follows K&R for syntax, so those of you
         with compilers that allow nested comments, watch out.  (They are
         illegal in K&R, and thus here.)

         This program has grown from a simple 'curly brace checker' into
         what I feel is a powerful and useful tool for C programmers.  I
         hope you agree, and that it proves to be a useful tool for you.

           Bob Pritchett
           New Dimension Software
             23 Pawtucket Dr.
             Cherry Hill, NJ 08003
             Voice: (609) 424-2595
              Data: (609) 354-9259  (300B/1200B)  (24hrs.)

 */

 #include <stdio.h>
 <ctype.h>        /* For the isalpha() macro */

 FILE *data;                /* Input File */

 int in_comment;                /* Flag - Positive if in Comments */
 int in_single;                /* Flag - Positive if in Single Quotes */
 int in_double;                /* Flag - Positive if in Double Quotes */

 int paren;                /* Temporary Paren Count */
 int tparen;                /* Total (Per File) Paren Count */

 int brack;                /* Bracket Count */

 int square;                /* Temporary Square Bracket Count */
 int tsquare;                /* Total (Per File) Square Bracket Count */

 int errors;                /* Error Count (Per File) */

 int line;                /* Current Line Number */

 int anal;                /* Analysis Flag - Positive if Analysis On */

 int tbrack;                /* Extra Bracket Count */

 int semi;                /* Semicolon Counter for for Statements */

 int cbl;                /* Line on Which Last Comment Began */

 main(argc,argv)
  int argc;
  char *argv[];
  {
   int x = 1;                /* First Argument that is a File - 1 is Default *
   int c;                /* Current Character */
   int lastc;                /* Last Character */
   int llast;                /* Character Before lastc */
   int vlast;                /* Character Before llast */
   int forflag;                /* Flag to mark for statement */
   int err_flg = 0;        /* Total errors in all files. */
   printf("\n  CheckC Version 2.1   Copyright 1985, 86 Bob Pritchett\n");
   printf("                 A small C code checker.\n");
   if ( argc < 2 )        /* if no arguments */
    {
     printf("\nCHECKC: Usage is CHECKC [/A] <filename> [<filename>...]\n");
     exit(1);                /* Exit with failure flag */
    }
   if ( argv[1][0] == '/' && ( argv[1][1] == 'A' || argv[1][1] == 'a' ) )
    {
     x = 2;                /* First Argument is an option */
     anal = 1;                /* Analysis on */
    }
   for ( ; x < argc; ++x )        /* For Each File... */
    {
     in_comment = 0;        /* Initialize Data */
     in_single = 0;
     in_double = 0;
     paren = 0;
     tparen = 0;
     brack = 0;
     square = 0;
     tsquare = 0;
     errors = 0;
     line = 1;
     tbrack = 0;
     semi = 0;
     forflag = 0;
     cbl = 0;
     c = 0;
     lastc = 0;
     llast = 0;
     vlast = 0;

     strcpy(argv[x],strupr(argv[x]));        /* Put file name in upper case */
     if ( ( data = fopen(argv[x],"r") ) == 00 )        /* If unable to open so
      {
       printf("\nCHECKC: Error Opening %s\n",argv[x]);        /* Print message
       continue;                                /* and continue with next file
      }
     if ( anal )
        printf("\n        Checking and Analyzing %s\n\n",argv[x]);
     else
        printf("\n        Checking %s\n\n",argv[x]);
     while ( c != EOF )
      {
       vlast = llast;
       llast = lastc;
       lastc = c;
       c = getc(data);        /* Get character from data file */

       if ( c == '\n' )        /* Increment here so comment lines are counted.
        {
         if ( in_single )
          {
           printf("Line %04d:  Missing single quote.  Diagnostics now inaccura
           in_single = 0;                        /* Fix flag for diags. */
           ++errors;
          }
         else if ( in_double )
          {
           printf("Line %04d:  Missing double quote.  Diagnostics now inaccura
           in_double = 0;                        /* Fix flag for diags. */
           ++errors;
          }
         ++line;
         continue;
        }

       if ( in_double )                /* If in double quotes, check for end q
        {                                           /* It is an ending " if  *
         if ( ( c == '"' && lastc == '\\' && llast == '\\' ) ||  /*  \\"  or *
              ( c == '"' && lastc != '\\' ) )                    /*  !  \"   *
            in_double = 0;        /* If so, turn off quote flag */
         continue;                /* and continue with next character */
        }

       if ( in_comment )                /* If in a Comment */
        {
         if ( c == '/' && lastc == '*' )        /* Check for end comment sign
            in_comment = 0;                /* If comment ends, change flag */
         continue;                        /* and get next character */
        }

       if ( in_single )                /* If in single quotes */
        {                        /* check for closing single quote */
         if ( ( c == 39 && lastc == '\\' && llast == '\\' ) ||   /* 39 is ' */
              ( c == 39 && lastc != '\\' ) )
            in_single = 0;
         continue;
        }

       switch ( c )        /* If not in a comment or quote */
        {                /* check and count all relevant characters */
         case '(':
           ++paren;
           ++tparen;
           break;
         case ')':
           --paren;
           --tparen;
           break;
         case '{':
           ++brack;
           ++tbrack;
           break;
         case '}':
           --brack;
           --tbrack;
           break;
         case '[':
           ++square;
           ++tsquare;
           break;
         case ']':
           --square;
           --tsquare;
           break;
         case '"':
           in_double = 1;
           break;
         case 39:
           in_single = 1;
           break;
         case '*':        /* Must be last so break w/o correct if is ok. */
           if ( lastc == '/' )
            {
             in_comment = 1;
             cbl = line;        /* Latest comment started here. */
            }
           break;
         default:
           break;
        }

       if ( anal )        /* If in analysis mode, attempt to diagnose */
        {                /* problem by the level of brackets etc. and */
         if ( c == '{' )        /* call appropriate error. */
          {
           if ( brack == 1 )
            {
             if ( paren > 0 )
                error(1);
             if ( square > 0 )
                error(7);
            }
           else if ( brack > 1 )
            {
             if ( paren > 0 )
                error(3);
             if ( square > 0 )
                error(9);
            }
          }
         else if ( c == '}' )
          {
           if ( brack == 0 )
            {
             if ( paren > 0 )
                error(2);
             if ( square > 0 )
                error(8);
            }
           else if ( brack > 0 )
            {
             if ( paren > 0 )
                error(4);
             if ( square > 0 )
                error(10);
            }
           else
              error(13);
          }

         if ( c == '(' && forflag == 1 )
          {
           semi = 1;                /* Must wait till for statement is begun *
           forflag = 0;                /* before allowing ; counting in statem
          }

         if ( square < 0 )        /* Never allowed to go under */
            error(11);
         else if ( square > 0 && c == ';' )  /* Not even in for statement */
            error(12);

         if ( c == 'r' && lastc == 'o' && llast == 'f' )
          {
           if ( isalpha(vlast) || vlast == '_' )        /* If it's an identifi
              break;                /* ..stop here */
           c = getc(data);        /* Peek at next character */
           if ( ! isalpha(c) && c != '_' )          /* If it's not an identifi
              forflag = 1;        /* ...it's a for statment */
           ungetc(c,data);        /* Put it back to be processed */
           c = 'r';                /* Put the correct letter in c again */
          }
         else if ( c == ';' && semi > 0 )        /* If counting has started */
            ++semi;                /* and there is a ;, record it */

         if ( paren < 0 )        /* Never allowed to go under */
            error(5);
         else if ( paren > 0 && semi == 0 && c == ';' )
            error(6);
         else if ( paren == 0 )
          {
           if ( semi > 3 )
              error(14);
           else if ( semi == 1 || semi == 2 )
              error(15);
           semi = 0;
          }

        }                /* Close of Analysis Stage */

      }                        /* Close of While Loop */

     putchar('\n');

     fclose(data);        /* Close source file */

     if ( tparen > 0 )
        printf("CHECKC: %d too many ('s.\n",tparen);
     else if ( tparen < 0 )
        printf("CHECKC: %d too many )'s.\n",abs(tparen));

     if ( tbrack > 0 )
        printf("CHECKC: %d extra }'s or missing {'s.\n",tbrack);
     else if ( tbrack < 0 )
        printf("CHECKC: %d too many {'s.\n",abs(tbrack));

     if ( tsquare > 0 )
        printf("CHECKC: %d too many ['s.\n",tsquare);
     else if ( tsquare < 0 )
        printf("CHECKC: %d too many ]'s.\n",abs(tsquare));

     if ( in_double == 1 )
        printf("CHECKC: EOF with double quote open.\n");

     if ( in_comment == 1 )
        printf("CHECKC: EOF with comment open.  Comment opened on line %04d.\n
               ,cbl);

     if ( in_single == 1 )
        printf("CHECKC: EOF with single quote open.\n");

     errors += in_single + in_comment + in_double +         /* Total all error
               abs( tsquare ) +
               abs( brack ) +
               abs( tparen );

     err_flg += errors;                /* Flag positive if any files have erro

     printf("\n        %d Errors found in %s\n",errors,argv[x]);

     if ( anal )
        printf("        Check and Analysis of %s Completed\n",argv[x]);
     else
        printf("        Check of %s Completed\n",argv[x]);

    }
   if ( err_flg != 0 )        /* If errors found in any file */
      exit(1);                /* Exit with 1 in ERRORLEVEL. */
   exit(0);                /* Otherwise exit cleanly. */
  }

 /* ----------------------------------------------------------- */

 error(x)
  int x;
  {
   printf("Line %04d:  ",line);        /* Line on which error first noticed */
   if ( x == 1 )
      printf("New function started with %d ('s open.",paren);
   else if ( x == 7 )
      printf("New function started with %d ['s open.",square);
   else if ( x == 2 )
      printf("Function ended with %d ('s open.",paren);
   else if ( x == 8 )
      printf("Function ended with %d ['s open.",square);
   else if ( x == 3 )
      printf("Block started with %d ('s open.",paren);
   else if ( x == 9 )
      printf("Block started with %d ['s open.",square);
   else if ( x == 4 )
      printf("Block ended with %d ('s open.",paren);
   else if ( x == 10 )
      printf("Block ended with %d ['s open.",square);
   else if ( x == 5 )
      printf("%d extra )'s or missing ('s.",abs(paren));
   else if ( x == 6 )
      printf("Semicolon with %d extra ('s or missing )'s.",paren);
   else if ( x == 11 )
      printf("%d extra ]'s or missing ['s.",abs(square));
   else if ( x == 12 )
      printf("Semicolon with %d extra ['s or missing ]'s.",square);
   else if ( x == 13 )        /* A bad { } count can ruin the analysis accurac
    {
     printf("An extra } or missing {.");
     brack = 0;
    }
   else if ( x == 14 )
      printf("A for statement with %d extra ;'s.",semi-2);
   else if ( x == 15 )
      printf("A for statement without two ;'s.");
   if ( x > 0 && x < 7 )
      paren = 0;
   else if ( x > 6 && x < 13 )
      square = 0;
   putchar('\n');
  }


 CHMOD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CHMOD.C

 1
  /***********************************************************************/
  /* CHMOD - EXERCISE CHMOD DOS FUNCTION CALL (#43)                      */
  /***********************************************************************/
  /* (C) COPYRIGHT JERRY M. CARLIN 8/14/1983                             */
  /* PERMISSION GIVEN TO USE OR DISTRIBUTE SO LONG AS NO MONEY CHARGED.  */
  /* IF QUESTIONS, CALL 415-680-7590.                                    */
  /***********************************************************************/
 /*
 #DEFINE DEBUG 1
 */
 #INCLUDE "STDIO.H"
 CARRY  1        /* 8086 FLAGS CARRY BIT */
 NO_MORE 18      /* DOS 'NO MORE FILES' ERROR CODE */
 FCALL  0X21     /* FUNCTION CALL INT PER DOS 2.0 MANUAL PG D-2 */
 CHMOD  0X43     /* DOS 2.0 CHANGE FILE MODE PG D-39 */
 SETDTA 0X1A     /* SET DISK TRANSFER ADDRESS */
 FFIRST 0X4E     /* DOS 2.0 FIND FIRST FILE */
 FNEXT  0X4F     /* DOS 2.0 FIND NEXT FILE */
  /* FILE ATTRIBUTES FROM DOS 2.0 MANUAL PAGE C-4 */
 RO     01       /* READ ONLY */
 HIDE   02       /* HIDDEN FILE */
 SYS    04       /* SYSTEM FILE */
 VOLLBL 08       /* SPECIAL VOLUME LABEL - IN FIRST 11 BYTES */
 SUBDIR 0X10     /* DEFINES A SUBDIRECTORY */
 ARCHV  0X20     /* ARCHIVE BIT */
 CHAR *INDEX();
 STRUCT REGVAL {
         UNSIGNED AX,BX,CX,DX,SI,DI,DS,ES;
 } IREGS, OREGS, FILEREGS;
 STRUCT SEGREG {
         UNSIGNED CS,SS,SDS,SES;
 } SR;
 MAIN(AC,AV)
 INT AC;
 CHAR *AV[];
 {
         CHAR ATTR[9];           /* FILE ATTRIBUTES */
         INT FLAGS;              /* 8086 FLAG REGISTER */
         CHAR BUFF[128];         /* DISK I/O BUFFER */
         CHAR FULLNAME[128];     /* FULL FILE NAME INCLUDING DRIVE AND DIR */
         CHAR DDPREFIX[120];     /* DRIVE AND DIRECTORY INFO */
         INT I;
         BDOS(SETDTA,BUFF);      /* SET DATA TRANSFER ADDRESS */
         IREGS.AX = 17152;       /* SET AH = 43 */
         SEGREAD(&SR);           /* GET STACK & DATA SEG REGS */
         IREGS.DS = SR.SDS;
         IREGS.ES = SR.SES;
         FILEREGS.DS = IREGS.DS;
         FILEREGS.ES = IREGS.ES;
         FILEREGS.AX = 0X4E00;                   /* FIND FIRST */
         FILEREGS.CX = HIDE | SYS | SUBDIR;      /* ALLOW ANY FILE */
         IF (STRCMP(AV[1],"HELP") == 0 || STRCMP(AV[1],"?") == 0 || AC == 1)
         {
                 PRINTF("\NCHMOD [-[R][H][S][A]] FILENAME.EXT ");
                 PRINTF("[FILENAME.EXT...]\N");
                 PRINTF("\NUSE THE '-' OPTION TO SET FILE MODES. OMIT");
                 PRINTF(" THE '-' OPTION FOR MODE DISPLAY.\NA DASH BY ");
                 PRINTF(" ITSELF (CHMOD - FILENAME) SETS NORMAL MODE.\N\N");
                 PRINTF("SETTABLE FLAGS:\N  R = READ ONLY\N");
                 PRINTF("  H = HIDDEN\N  S = SYSTEM");
                 PRINTF("\N  A = ARCHIVE\N\NANY FLAG NOT SET WILL BE RESET.");
                 PRINTF(" THIS MEANS THAT IF YOU DO NOT, \NFOR EXAMPLE, SET");
                 PRINTF(" READ-ONLY THE FILE WILL BE WRITE ENABLED.\N\N");
                 PRINTF("DOS GLOBAL FILENAME CHARS '*' AND '?' MAY BE USED.\N"
                 PRINTF("\NMODE DISPLAY INCLUDES 'W' FOR WRITE OK AND ");
                 PRINTF("'D' FOR A SUBDIRECTORY.\N\N");
                 EXIT(0);
         }
         IF (AV[1][0] == '-')    /* SET MODE */
         {
                 IREGS.AX |= 1;  /* SET UPDATE BIT */
                 IREGS.CX = 0;
                 IF (INDEX(AV[1],'R') != 0)
                         IREGS.CX |= RO;
                 IF (INDEX(AV[1],'H') != 0)
                         IREGS.CX |= HIDE;
                 IF (INDEX(AV[1],'S') != 0)
                         IREGS.CX |= SYS;
                 IF (INDEX(AV[1],'A') != 0)
                         IREGS.CX |= ARCHV;
 #IFDEF DEBUG
                 PRINTF("FUN CODE =%X\N",IREGS.AX);
                 PRINTF("SET MODE =%X\N",IREGS.CX);
 #ENDIF
                 ++AV;   /* SKIP OVER SET MODE WORD */
                 --AC;
                 WHILE (--AC > 0)
                 {
                         FILEREGS.DX = *++AV;
                         FLAGS = SYSINT(FCALL,&FILEREGS,&OREGS);
                         IF (FLAGS & CARRY)
                         {
                                 PERROR(FILEREGS.DX,OREGS.AX);
                                 CONTINUE;
                         }
                         BUILDP(*AV,DDPREFIX);
                         WHILE (OREGS.AX != NO_MORE)
                         {
                                 STRCPY(FULLNAME,DDPREFIX);
                                 STRCAT(FULLNAME,BUFF+30);
                                 IREGS.DX = FULLNAME;
                                 FLAGS = SYSINT(FCALL,&IREGS,&OREGS);
                                 IF (FLAGS & CARRY)
                                         PERROR(IREGS.DX,OREGS.AX);
                                 OREGS.AX = BDOS(FNEXT,0) & 0XFF;
                         }
                 }
                 EXIT(0);
         }
  /**********************************/
  /* ELSE REPORT ON CURRENT SETTING */
  /**********************************/
         WHILE (--AC > 0)
         {
                 FILEREGS.DX = *++AV;
                 FLAGS = SYSINT(FCALL,&FILEREGS,&OREGS);   /* FIND FIRST */
                 IF (FLAGS & CARRY)
                 {
                         PERROR(FILEREGS.DX,OREGS.AX);
                         CONTINUE;
                 }
                 I = 0;
                 BUILDP(*AV,DDPREFIX);
                 WHILE (I != NO_MORE)
                 {
                         STRCPY(FULLNAME,DDPREFIX);
                         STRCAT(FULLNAME,BUFF+30);       /* SEE PG D-49 */
                         IREGS.DX = FULLNAME;            /* NEXT FILE */
                         FLAGS = SYSINT(FCALL,&IREGS,&OREGS);
 #IFDEF DEBUG
                         PRINTF("FILE     = %S\N",IREGS.DX);
                         PRINTF("ERR CODE = %X\N",OREGS.AX);
                         PRINTF("8086FLAGS= %X\N",FLAGS);
                         PRINTF("MODE BYTE= %D\N",OREGS.CX);
 #ENDIF
                         IF (FLAGS & CARRY)
                         {
                                 PERROR(IREGS.DX,OREGS.AX);
                                 BREAK;
                         }
                         IF (OREGS.CX & RO)
                                 ATTR[0] = 'R';
                         ELSE
                                 ATTR[0] = 'W';
                         IF (OREGS.CX & HIDE)
                                 ATTR[1] = 'H';
                         ELSE
                                 ATTR[1] = '-';
                         IF (OREGS.CX & SYS)
                                 ATTR[2] = 'S';
                         ELSE
                                 ATTR[2] = '-';
                         IF (OREGS.CX & SUBDIR)
                                 ATTR[3] = 'D';
                         ELSE
                                 ATTR[3] = '-';
                         IF (OREGS.CX & ARCHV)
                                 ATTR[4] = 'A';
                         ELSE
                                 ATTR[4] = '-';
                         ATTR[5] = '\0';
                         PRINTF("%S %S\N",ATTR,IREGS.DX);
                         I = BDOS(FNEXT,0) & 0XFF;  /* FIND NEXT */
                 }
         }
         EXIT(0);
 }
  /*****************************************************************/
  /* PRINT ERROR - SEE ERROR RETURN TABLE DOS 2.0 MANUAL PAGE D-14 */
  /*****************************************************************/
 PERROR(S,CODE)
 CHAR *S;
 UNSIGNED CODE;
 {
         PRINTF("CHMOD: FILE %S",S);
         SWITCH(CODE) {
         CASE 2:
         CASE 18: /* PERROR CALLED WITH 18 IF BAD FILENAME ENTERED */
                 PRINTF(" NOT FOUND.\N");
                 BREAK;
         CASE 3:
                 PRINTF(". PATH NOT FOUND.\N");
                 BREAK;
         CASE 5:
                 PRINTF(". ACCESS DENIED.\N");
                 BREAK;
         DEFAULT:
                 PRINTF(". DOS ERROR CODE %U RETURNED.\N",CODE);
         }
         RETURN;
 }
  /********************************************************/
  /* BUILD PREFIX STR CONTAINING DRIVE AND DIRECTORY INFO */
  /* NEEDED SINCE FFIRST DTA DOES NOT STORE THIS INFO     */
  /********************************************************/
 BUILDP(FULLNAME,DDPREFIX)
 CHAR *FULLNAME; /* FULL PATH NAME (INPUT) */
 CHAR *DDPREFIX; /* DRIVE AND DIRECTORY INFO */
 {
 #IFDEF DEBUG
         CHAR *SAVEP;
         SAVEP = DDPREFIX;
 #ENDIF
         WHILE ((INDEX(FULLNAME,':') != 0) || (INDEX(FULLNAME,'\\') != 0))
                 *DDPREFIX++ = *FULLNAME++;
         *DDPREFIX = '\0';
 #IFDEF DEBUG
         PRINTF("PREFIX=%S\N",SAVEP);
 #ENDIF
 }
 PRESS ENTER TO CONTINUE:


 CHMOD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CHMOD.C

 #include <osbind.h>
 #include <stdio.h>

 int chmod(filename, pmode)
 char *filename;
 int pmode;
 /*
  *        Change the mode attribute of <filename> to <pmode>.  Values for
  *        <pmode> are the same as for the creat() function.  Returns 0 for
  *        success, or a negative error code.
  */
 {
         register int rv;

         if((rv = Fattrib(filename, 1, pmode)) < 0)
                 return(rv);
         return(0);
 }


 CHOSIT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\MENCON\CHOSIT.C

 /*                              *** chosit.c ***                     */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to display a menu, prompt for a response, and validate.  */
 /* Calls function mencon to display the menu.  Returns the integer   */
 /* response, or -1 if invalid response or error occured.              */
 /*                                                                   */
 /* Written by L. Cuthbertson, April 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 int chosit(menu,ans,lenans)
 char menu[],ans[];
 int lenans;
 {
         extern int rc[][2];
         extern int vrange[2];
         int i,j,ians,nfield;

         /* display menu */
         if (strcmp(menu,"skip") != 0) {
                 nfield = mencon(menu);
                 if (nfield == (-1))
                         return(-1);        /* error in mencon */
         }

         /* move cursor to entry position */
         i=0;                        /* position within rc array */
         if (i > (nfield-1)) {
                 return(-1);        /* no entry position on menu */
         }

         loop:
         cursor(rc[i][0],rc[i][1]);

         /* accept answer */
         reads(ans,lenans);

         /* convert answer to integer */
         sscanf(ans,"%d",&ians);

         /* always exit if 99 entered */
         if (ians == 99)
                 exit();

         /* validate answer */
         if ((ians < vrange[0]) || (ians > vrange[1])) {
                 cursor(25,19);
                 writes("\007*** invalid response - please try again ***");
                 pause(5.);
                 cursor(25,19);
                 eline(0);
                 cursor(rc[i][0],rc[i][1]);
                 for (j=1;j<lenans;j++)
                         writec(' ');
                 goto loop;
         }

         /* done */
         return(ians);
 }


 CHRPUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MIKES30C\CHRPUT.C

 chr_put(c)    /* Put character with attribute in first 8 bits of int */
 int        c;       /* and character in last 8 bits */
 {
     union REGS REG;

     REG.h.ah = 0x9;
     REG.h.al = c;
     REG.h.bl = c >> 8;
     REG.h.bh = 00;
     REG.x.cx = 1;
     int86(0x10, &REG, &REG);

     return(REG.x.ax);

 }

 chr_get()   /* Get character with attribute returns 2byte int used above */
 {
     union REGS REG;

     REG.h.ah = 0x8;
     REG.h.bh = 00;
     int86(0x10, &REG, &REG);

     return(REG.x.ax);

 }



 CHRSTC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\CHRSTC.C

 /* 1.1  06-27-85                                                (chrstc.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathcons.h"

 /************************************************************************/
         int
 chrstc(x)                /* return the characteristic (2's exponent) of
                            double x. Mantissa is in (.5, 1).                *
 /*----------------------------------------------------------------------*/
 double x;
 {
         char *xp;
         int n, norm;

         if (x IS 0.0)
         {        errno = EDOM;
                 return -INFINITY;
         }
         xp = (char *) &x;

 #ifdef ECOSOFT
         return (((int) *xp) - 0x80);
 #endif

 #ifdef AZTEC
         n = (((int) (*xp++ & 0x7f)) - 0x40) * 8;
         norm = *xp;
         while (NOT(norm & 0x80))
         {        n--;
                 norm = (norm << 1) | 1;
         }
         return n;
 #endif

 #ifdef CPM86
         return (((int) (((xp[7] << 4) + (xp[6] >> 4)) & 0x7ff)) - 0x3fe);
 #endif

 #ifdef UNIVERSE
         return (((int)(((*xp << 1) + (xp[1] & 0x80 ? 1 : 0)) & 0xff)) - 0x80)
 #endif

 #ifdef SUN
         return (int)(((*xp & 0x7f) << 4) + ((xp[1] >> 4) & 0xf) - 0x3fe);
 #endif
 }


 CHRSTRG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\CHRSTRG.C

                                          /* Chapter 7 - Program 1 */
 main()
 {
 char name[5];       /* define a string of characters */

    name[0] = 'D';
    name[1] = 'a';
    name[2] = 'v';
    name[3] = 'e';
    name[4] = 0;     /* Null character - end of text */

    printf("The name is %s\n",name);
    printf("One letter is %c\n",name[2]);
    printf("Part of the name is %s\n",&name[1]);
 }


 CIRCLE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\CIRCLE.C

 /**********************************************************************
 CIRCLE
 Description -circle(x coordinate, y coordinate, radius)
 **********************************************************************
 Function - draws a circle on the screen
 Input - integers for x,y center coordinates, integer for radius
 Output - to the screen
 #includes -
 #defines  - none
 Routines Called - plot8.c, plotxy.c
 Notes - listing 3 page 30 dec83 dobbs
 **********************************************************************/
 circle(xcenter,ycenter,radius)
 int xcenter,ycenter,radius;
 {
   int xcrd,ycrd,a,b,f;
   xcrd=radius;
   ycrd=0;
   a=-2*(xcrd+1);
   b=1;
   f=0;
   do{
      plot8(xcenter,ycenter,xcrd,ycrd);
      ycrd=ycrd+1;
      f=f+b;
      if(f>radius){f=f+a;
                   a=a+2;
                   xcrd=xcrd-1;}
      b=b+2;
     }
      while(b<=-a);
   return;
 }
 /******************** end of function ********************************/
 /**********************************************************************
 PLOT8
 Description - plots 8 points for circle routine
 **********************************************************************
 Function -  plot8(xcenter,ycenter,xcrd,ycrd);
 Input - x,y coordinates of center pt, x,y coord of base octant
 Output - 8 characters to screen
 #includes - plotxy.c
 #defines  - none
 Routines Called - plotxy to print character
 Notes - no error checking, char is defined in plotxy
 **********************************************************************/
 plot8(xcenter,ycenter,xcrd,ycrd)

 int xcenter,ycenter,xcrd,ycrd;
 {
   plotxy(ycrd+xcenter,((2*xcrd)/5)+ycenter);    /* b quart c-clockwise   */
   plotxy(-ycrd+xcenter,((2*xcrd)/5)+ycenter);   /* b quart clockwise */
   plotxy(-ycrd+xcenter,((2*-xcrd)/5)+ycenter);  /* d quart c-clockwise   */
   plotxy(ycrd+xcenter,((2*-xcrd)/5)+ycenter);   /* d quart clockwise */
   plotxy(xcrd+xcenter,((2*-ycrd)/5)+ycenter);   /* a quart c-clockwise   */
   plotxy(xcrd+xcenter,((2*ycrd)/5)+ycenter);    /* a quart clockwise */
   plotxy(-xcrd+xcenter,((2*ycrd)/5)+ycenter);   /* c quart c-clockwise   */
   plotxy(-xcrd+xcenter,((2*-ycrd)/5)+ycenter);  /* c quart clockwise */
   return;
 }

 /******************** end of function ********************************/


 CLRCRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\CLRCRT.C

 #include "dos.h"
 /****************************************************************************
 *
 *  clear crt & reset cursor
 *
 *****************************************************************************
 clrcrt(a)                           /* attribute */
 int a;
 {
   union REGS reg;
   reg.x.cx = 2000;                   /* chars on crt */
   reg.h.bh = 0;                    /* page number */
   reg.h.bl = a;                    /* set attribute */
   reg.h.al = ' ';                  /* blank out screen */
   reg.h.ah = 9;                    /* write char/attr */
   int86(0x10,&reg,&reg);           /* clr the screen */
 }


 CLS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MIKES30C\CLS.C

 cls()         /* Clear the screen  */
 {

     union REGS REG;

     REG.x.ax = 0x0600;
     REG.h.bh = 0x07;
     REG.x.cx = 0X0000;
     REG.x.dx = 0x184f;
     int86(0x10, &REG, &REG);

 }




 CLS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CLS.C

 #include <dos.h>
 cls()
 {

         union REGS REG;

         REG.x.ax=0x0600;
         REG.h.bh=0x07;
         REG.x.cx=0X0000;
         REG.x.dx=0x184f;
         int86(0x10,&REG,&REG);

 }



 CLS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\CLS\CLS.C

 /**************************************************************/
 /*                                                              */
 /*  NAME                                                      */
 /*                                                              */
 /*         cls  - clear video screen                              */
 /*                                                              */
 /*  SYNOPSIS                                                      */
 /*                                                              */
 /*         cls();                                               */
 /*                                                              */
 /*  DESCRIPTION                                               */
 /*                                                              */
 /*         This function clears the terminal.  It requires      */
 /*         no parameters.  "cls" uses the "csysint" C-to-       */
 /*         assembler interface.                                      */
 /*                                                              */
 /*  RETURNS                                                      */
 /*                                                              */
 /*         No return codes are provided.                              */
 /*                                                              */
 /**************************************************************/
 cls()
 {
      struct regset {
           char al;
           char ah;
           char bl;
           char bh;
           char cl;
           char ch;
           char dl;
           char dh;
      };
      unsigned csysint();
      struct regset sreg;     /* regs to send to csysint */
      struct regset rreg;     /* regs returned from csysint */
      unsigned flags;             /* machine status register */
      int interrupt;             /* interrupt code requested */

      interrupt = 0x10;
      sreg.ah = 0;
      sreg.al = 0x03;

      sreg.bh = 0;
      sreg.bl = 0;
      sreg.ch = 0;
      sreg.cl = 0;
      sreg.dh = 0;
      sreg.dl = 0;

      flags = csysint(interrupt,&sreg,&rreg);
 }
 /*   ---- test program for above routine commented out..
 main()
 {
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");
      cprintf("Test pattern to fill screen.\n");

      cls();
 }  end of commented out code  for test routine */


 CMAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\CMAIN.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 char            infile[20],
                 listfile[20],
                 outfile[20];
 extern TABLE    tagtable;
 int                mainflag;
 extern int      total_errors;

 main(argc,argv)
 int     argc;
 char    **argv;
 {       while(--argc) {
                 if( **++argv == '-')
                         options(*argv);
                 else if( openfiles(*argv)) {
                         lineno = 0;
                         initsym();
                         getch();
                         getsym();
                         compile();
                         summary();
                         release_global();
                         closefiles();
                         }
                 }
 }

 int        options(s)
 char        *s;
 {        return 0;
 }

 int     openfiles(s)
 char    *s;
 {       char    *p;
         int     ofl, lfl;
         strcpy(infile,s);
         strcpy(listfile,s);
         strcpy(outfile,s);
         makename(listfile,".lis");
         makename(outfile,".s");
         if( (input = fopen(infile,"r")) == 0) {
                 printf(" cant open %s\n",infile);
                 return 0;
                 }
         ofl = creat(outfile,-1);
         if( ofl < 0 )
                 {
                 printf(" cant create %s\n",outfile);
                 fclose(input);
                 return 0;
                 }
         if( (output = fdopen(ofl,"w")) == 0) {
                 printf(" cant open %s\n",outfile);
                 fclose(input);
                 return 0;
                 }
         if( (list = fopen(listfile,"w")) == 0) {
                 printf(" cant open %s\n",listfile);
                 fclose(input);
                 fclose(output);
                 return 0;
                 }
         return 1;
 }

 makename(s,e)
 char    *s, *e;
 {       while(*s != 0 && *s != '.')
                 ++s;
         while(*s++ = *e++);
 }

 summary()
 {       printf("\n -- %d errors found.",total_errors);
         fprintf(list,"\f\n *** global scope symbol table ***\n\n");
         list_table(&gsyms,0);
         fprintf(list,"\n *** structures and unions ***\n\n");
         list_table(&tagtable,0);
 }

 closefiles()
 {       fclose(input);
         fclose(output);
         fclose(list);
 }



 CMD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\CMD.C

 /* SDB - command parser */

 #include "stdio.h"
 #include "sdbio.h"
 #include "ctype.h"

 extern int dbv_token;
 extern char dbv_tstring[];
 extern int dbv_tvalue;
 extern struct ifile *dbv_ifp;
 extern struct macro *dbv_macros;
 extern int dbv_fold;

 #ifdef Lattice
 int _fmode = 0;  /*dns*/
 #endif

 /* db_parse - parse a command */
 int db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     int sts;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* determine the statement type */
     switch (db_ntoken()) {
     case ';':   sts = TRUE;
                 break;
     case COMPRESS:
                 sts = db_squeeze(NULL);
                 break;
     case CREATE:
                 sts = create();
                 break;
     case DEFINE:
                 sts = mc_define();
                 break;
     case DELETE:
                 sts = delete();
                 break;
     case EXIT:
                 exit();
     case EXPORT:
                 sts = db_export(NULL);
                 break;
     case EXTRACT:
                 sts = db_extract(NULL);
                 break;
     case HELP:
                 sts = help();
                 break;
     case IMPORT:
                 sts = db_import(NULL);
                 break;
     case INSERT:
                 sts = insert();
                 break;
     case PRINT:
                 sts = print();
                 break;
     case SELECT:
                 sts = select();
                 break;
     case SET:
                 sts = set();
                 break;
     case SHOW:
                 sts = mc_show();
                 break;
     case SORT:
                 sts = db_sort(NULL);
                 break;
     case UPDATE:
                 sts = update();
                 break ;
     default:
                 return (db_ferror(SYNTAX));
     }

     return (sts);
 }

 /* help - print a short help message */
 static int help()
 {
     FILE *fp;
     int ch;

     if ((fp = fopen("sdb.hlp","r")) != NULL) {
      /* while ((ch = agetc(fp)) != EOF)    dns */
         while ((ch =  getc(fp)) != EOF)
             putchar(ch);
         fclose(fp);
     }
     else
         printf("No online help available.  Read the manual\n");

     /* return successfully */
     return (TRUE);
 }

 /* create - create a new relation */
 static int create()
 {
     struct relation *rptr;
     char aname[STRINGMAX+1];
     int atype;

     /* get relation name */
     if (db_ntoken() != ID)
         return (db_ferror(SYNTAX));

     /* start relation creation */
     if ((rptr = db_rcreate(dbv_tstring)) == NULL)
         return (FALSE);

     /* check for attribute list */
     if (db_ntoken() != '(') {
         free(rptr);
         return (db_ferror(SYNTAX));
     }

     /* parse the attributes */
     while (TRUE) {

         /* get the attribute name */
         if (db_ntoken() != ID) {
             free(rptr);
             return (db_ferror(SYNTAX));
         }
         strcpy(aname,dbv_tstring);

         /* get the attribute type */
         db_ntoken();
         if (dbv_token == CHAR)
             atype = TCHAR;
         else if (dbv_token == NUM)
             atype = TNUM;
         else {
             free(rptr);
             return (db_ferror(SYNTAX));
         }

         /* get the attribute size */
         if (db_ntoken() != NUMBER) {
             free(rptr);
             return (db_ferror(SYNTAX));
         }

         /* add the attribute */
         if (!db_rcattr(rptr,aname,atype,dbv_tvalue)) {
             free(rptr);
             return (FALSE);
         }

         /* check for end of attributes */
         if (db_token() != ID)
             break;
     }

     /* check for attribute list end */
     if (db_ntoken() != ')') {
         free(rptr);
         return (db_ferror(SYNTAX));
     }

     /* check for relation size */
     if (db_ntoken() != NUMBER) {
         free(rptr);
         return (db_ferror(SYNTAX));
     }

     /* finish relation creation */
     if (!db_rcheader(rptr))
         return (FALSE);
     if (!db_rctuples(rptr,dbv_tvalue))
         return (FALSE);
     if (!db_rcdone(rptr))
         return (FALSE);

     /* return successfully */
     return (TRUE);
 }

 /* insert - insert a tuple into a relation */
 static int insert()
 {
     struct scan *sptr;
     struct attribute *aptr;
     char aname[ANSIZE+1],avalue[STRINGMAX+1];
     int tcnt,astart,i;

     /* get relation name */
     if (db_token() == ID)
         db_ntoken();
     else
         strcpy(dbv_tstring,"sdbcur");

     /* make sure that the rest of the line is blank */
     if (!db_flush())
         return (FALSE);

     /* open the relation */
     if ((sptr = db_ropen(dbv_tstring)) == NULL)
         return (FALSE);

     /* insert tuples */
     for (tcnt = 0; ; tcnt++) {

         /* print separator if not the first tuple */
         if (tcnt != 0)
             printf("----\n");

         /* get attribute values */
         astart = 1;
         for (i = 0; i < NATTRS; i++) {

             /* get a pointer to the current attribute */
             aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

             /* check for the last attribute */
             if (aptr->at_name[0] == 0)
                 break;

             /* get the attribute name */
             stccpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;

             /* setup null prompt strings */
             db_prompt(NULL,NULL);

             /* prompt and input attribute value */
             while (TRUE) {
                 if (dbv_ifp == NULL)
                     if (strlen(aname) < 8)
                         printf("%s\t\t: ",aname);
                     else
                         printf("%s\t: ",aname);
                 if (db_gline(avalue) != NULL)
                     break;
             }

             /* check for last insert */
             if (i == 0 && avalue[0] == EOS)
                 break;

             /* store the attribute value */
             db_aput(aptr,&sptr->sc_tuple[astart],avalue);

             /* update the attribute start */
             astart += aptr->at_size;
         }

         /* check for last insert */
         if (avalue[0] == EOS)
             break;

         /* store the new tuple */
         if (!db_rstore(sptr)) {
             db_rclose(sptr);
             return (FALSE);
         }
     }

     /* close the relation */
     db_rclose(sptr);

     /* check number of tuples inserted */
     if (tcnt != 0) {

         /* print tuple count */
         printf("[ %d inserted ]\n",tcnt);
     }
     else
         printf("[ none inserted ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* delete - delete tuples from a relation */
 static int delete()
 {
     struct sel *slptr;
     struct srel *srptr;
     int tcnt;

     /* parse the retrieval clause */
     if ((slptr = db_retrieve(NULL)) == NULL)
         return (FALSE);

     /* loop through the retrieved tuples */
     for (tcnt = 0; db_fetch(slptr); tcnt++)

         /* delete the retrieved tuples */
         for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
             if (!db_rdelete(srptr->sr_scan)) {
                 db_done(slptr);
                 return (FALSE);
             }

     /* finish the retrieval */
     db_done(slptr);

     /* check number of tuples deleted */
     if (tcnt != 0) {

         /* print tuple count */
         printf("[ %d deleted ]\n",tcnt);
     }
     else
         printf("[ none deleted ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* update - update tuples from a relation */
 static int update()
 {
     struct sel *slptr;
     struct sattr *saptr;
     struct attribute *aptr;
     char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap;
     int tcnt;

     /* parse the selection clause */
     if ((slptr = db_select(NULL)) == NULL)
         return (FALSE);

     /* make sure that the rest of the line is blank */
     if (!db_flush()) {
         db_done(slptr);
         return (FALSE);
     }

     /* loop through the selected tuples */
     for (tcnt = 0; db_fetch(slptr); tcnt++) {

         /* print separator if not the first tuple */
         if (tcnt != 0)
             printf("----\n");

         /* loop through the selected attributes */
         for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)

             /* get the attribute pointer */
             aptr = saptr->sa_attr;

             /* get the attribute name */
             stccpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;

             /* get the attribute value */
             db_aget(aptr,saptr->sa_aptr,avalue);
             for (ap = avalue; isspace(*ap); ap++)
                 ;

             /* print it */
             if (strlen(aname) < 8)
                 printf("%s\t\t: %s\n",aname,ap);
             else
                 printf("%s\t: %s\n",aname,ap);

             /* setup null prompt strings */
             db_prompt(NULL,NULL);

             /* prompt and input attribute value */
             while (TRUE) {
                 if (strlen(aname) < 8)
                     printf("%s\t\t: ",aname);
                 else
                     printf("%s\t: ",aname);
                 if (db_gline(avalue) != NULL)
                     break;
             }

             /* store the attribute value */
             if (avalue[0] != EOS) {
                 db_aput(aptr,saptr->sa_aptr,avalue);
                 saptr->sa_srel->sr_update = TRUE;
             }
         }

         /* update the tuples */
         db_update(slptr);
     }

     /* finish the selection */
     db_done(slptr);

     /* check number of tuples updated */
     if (tcnt != 0) {

         /* print tuple count */
         printf("[ %d updated ]\n",tcnt);
     }
     else
         printf("[ none updated ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* print - print tuples from a set of relations */
 static int print()
 {
     struct sel *slptr;
     FILE *ffp,*ofp;
     int tcnt;

     /* parse the using clause */
     if (!using(&ffp,".frm"))
         return (FALSE);

     /* parse the select clause */
     if ((slptr = db_select(NULL)) == NULL)
         return (FALSE);

     /* parse the into clause */
     if (!db_to(&ofp,".txt")) {
         db_done(slptr);
         return (FALSE);
     }

     /* check for normal or formated output */
     if (ffp == NULL)
         tcnt = table(ofp,slptr);
     else
         tcnt = form(ofp,slptr,ffp);

     /* finish the selection */
     db_done(slptr);

     /* close the form definition file */
     if (ffp != NULL)
         fclose(ffp);

     /* close the output file */
     if (ofp != stdout)
         fclose(ofp);

     /* check number of tuples selected */
     if (tcnt != 0)
         printf("[ %d found ]\n",tcnt);
     else
         printf("[ none found ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* select - select tuples from a set of relations */
 static int select()
 {
     struct sel *slptr;
     struct relation *rptr;
     struct sattr *saptr;
     char *aname,*tbuf;
     int tcnt,abase,i;

     /* parse the select clause */
     if ((slptr = db_select(NULL)) == NULL)
         return (FALSE);

     /* create a new relation */
     if ((rptr = db_rcreate("sdbcur")) == NULL) {
         db_done(slptr);
         return (FALSE);
     }

     /* create the selected attributes */
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {

         /* decide which attribute name to use */
         if ((aname = saptr->sa_name) == NULL)
             aname = saptr->sa_aname;

         /* add the attribute */
         if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type,
                                   saptr->sa_attr->at_size)) {
             free(rptr);
             db_done(slptr);
             return (FALSE);
         }
     }

     /* create the relation header */
     if (!db_rcheader(rptr)) {
         db_done(slptr);
         return (FALSE);
     }

     /* allocate and initialize a tuple buffer */
     if ((tbuf = calloc(1,rptr->rl_size)) == NULL) {
         db_rcdone(rptr);
         return (db_ferror(INSMEM));
     }
     tbuf[0] = ACTIVE;

     /* loop through the selected tuples */
     for (tcnt = 0; db_fetch(slptr); tcnt++) {

         /* create the tuple from the selected attributes */
         abase = 1;
         for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
             for (i = 0; i < saptr->sa_attr->at_size; i++)
                 tbuf[abase + i] = saptr->sa_aptr[i];
             abase += i;
         }

         /* write the tuple */
         if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
             db_rcdone(rptr);
             free(tbuf);
             return (db_ferror(INSBLK));
         }
         rptr->rl_tcnt++;
         rptr->rl_tmax++;
     }

     /* finish the selection */
     db_done(slptr);

     /* finish relation creation */
     if (!db_rcdone(rptr))
         return (FALSE);

     /* check number of tuples selected */
     if (tcnt != 0)
         printf("[ %d found ]\n",tcnt);
     else
         printf("[ none found ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* mc_define - define a macro */
 static int mc_define()
 {
     struct macro *mptr,*mlast;
     struct mtext *tptr,*tlast;
     char textline[LINEMAX+1];

     /* get macro name */
     if (db_xntoken() != ID)
         return (db_ferror(SYNTAX));

     /* make sure that the rest of the line is blank */
     if (!db_flush())
         return (FALSE);

     /* find the macro in the macro table and free it */
     for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast = mptr, mptr =
         if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
             if (mlast == NULL)
                 dbv_macros = mptr->mc_next;
             else
                 mlast->mc_next = mptr->mc_next;
             mc_free(mptr);
         }

     /* allocate and initialize a macro structure */
     if ((mptr = malloc(sizeof(struct macro))) == NULL)
         return (db_ferror(INSMEM));
     if ((mptr->mc_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
         free(mptr);
         return (db_ferror(INSMEM));
     }
     strcpy(mptr->mc_name,dbv_tstring);
     mptr->mc_mtext = NULL;

     /* setup null prompt strings */
     db_prompt(NULL,"SDB-DEF> ");

     /* get definition text */
     for (tlast = NULL; ; tlast = tptr) {

         /* get a line */
         db_gline(textline);
         if (textline[0] == EOS || textline[0] == '\n')
             break;

         /* allocate a macro text structure */
         if ((tptr = malloc(sizeof(struct mtext))) == NULL) {
             mc_free(mptr);
             return (db_ferror(INSMEM));
         }
         if ((tptr->mt_text = malloc(strlen(textline)+1)) == NULL) {
             mc_free(mptr);
             return (db_ferror(INSMEM));
         }
         strcpy(tptr->mt_text,textline);
         tptr->mt_next = NULL;

         /* link it into the macro list */
         if (tlast == NULL)
             mptr->mc_mtext = tptr;
         else
             tlast->mt_next = tptr;
     }

     /* link the new macro into the macro list */
     if (tlast == NULL)
         mc_free(mptr);
     else {
         mptr->mc_next = dbv_macros;
         dbv_macros = mptr;
     }

     /* return successfully */
     return (TRUE);
 }

 /* mc_show - show a macro */
 static int mc_show()
 {
     struct macro *mptr;
     struct mtext *tptr;

     /* get macro name */
     if (db_xntoken() != ID)
         return (db_ferror(SYNTAX));

     /* find the macro in the macro table */
     for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
         if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
             for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next)
                 printf("\t%s\n",tptr->mt_text);
             break;
         }

     /* check for successful search */
     if (mptr == NULL)
         printf("*** no macro named: %s ***\n",dbv_tstring);

     /* return successfully */
     return (TRUE);
 }

 /* mc_free - free a macro definition */
 static mc_free(mptr)
   struct macro *mptr;
 {
     struct mtext *tptr;

     while ((tptr = mptr->mc_mtext) != NULL) {
         mptr->mc_mtext = tptr->mt_next;
         free(tptr->mt_text);
         free(tptr);
     }
     free(mptr->mc_name);
     free(mptr);
 }

 /* db_to - redirect output into a file */
 int db_to(pfp,ext)
   FILE **pfp; char *ext;
 {
 #ifdef vms
     int fd;
 #endif

     /* assume no into clause */
     *pfp = stdout;

     /* check for "into <fname>" */
     if (db_token() != INTO)
         return (TRUE);
     db_ntoken();
     if (db_ntoken() == ID)
         strcat(dbv_tstring,ext);
     else if (dbv_token != STRING)
         return (db_ferror(SYNTAX));

     /* open the output file */
 #ifdef vms
     if ((fd = creat(dbv_tstring,0,"rfm=var","rat=cr")) == -1)
         return (db_ferror(OUTCRE));
     *pfp = fdopen(fd,"w");
 #else
 #ifdef Lattice
     _fmode = 0x8000;  /*dns*/
 #endif
     *pfp = fopen(dbv_tstring,"w");  /*dns*/
 #ifdef Lattice
     _fmode = 0;       /*dns*/
 #endif
     if (*pfp == NULL)               /*dns*/
         return (db_ferror(OUTCRE)); /*dns*/
 #endif

     /* return successfully */
     return (TRUE);
 }

 /* using - get form definition file spec */
 static int using(pfp,ext)
   FILE **pfp; char *ext;
 {
     /* assume no using clause */
     *pfp = NULL;

     /* check for "using <fname>" */
     if (db_token() != USING)
         return (TRUE);
     db_ntoken();
     if (db_ntoken() == ID)
         strcat(dbv_tstring,ext);
     else if (dbv_token != STRING)
         return (db_ferror(SYNTAX));

     /* open the input file */
     if ((*pfp = fopen(dbv_tstring,"r")) == NULL)
         return (db_ferror(INPFNF));

     /* return successfully */
     return (TRUE);
 }

 /* table - output a relation table */
 static int table(fp,slptr)
   FILE *fp; struct sel *slptr;
 {
     int tcnt;

     /* loop through the selected tuples */
     for (tcnt = 0; db_fetch(slptr); tcnt++) {

         /* print table head on first tuple selected */
         if (tcnt == 0)
             db_thead(fp,slptr);

         /* print the tuple */
         db_tentry(fp,slptr);
     }

     /* print table foot */
     if (tcnt != 0)
         db_tfoot(fp,slptr);

     /* return the tuple count */
     return (tcnt);
 }

 /* form - process a form */
 static int form(ofp,slptr,ffp)
   FILE *ofp; struct sel *slptr; FILE *ffp;
 {
     char aname[ANSIZE+1];
     int ch,tcnt;

     /* loop through the selected tuples */
     for (tcnt = 0; db_fetch(slptr); tcnt++) {

         /* reposition the form definition file */
         fseek(ffp,0L,0);

         /* process the form */
         while ((ch = getc(ffp)) != -1)
             if (ch == '<') {
                 get_aname(ffp,aname);
                 put_avalue(ofp,slptr,aname);
             }
             else
                 putc(ch,ofp);
     }

     /* return the tuple count */
     return (tcnt);
 }

 /* get_aname - get an attribute name */
 static get_aname(fp,aname)
   FILE *fp; char *aname;
 {
     int ch;

     while ((ch = getc(fp)) != '>')
         if (!isspace(ch))
             *aname++ = ch;
     *aname = 0;
 }

 /* put_avalue - output attribute value */
 static put_avalue(fp,slptr,aname)
   FILE *fp; struct sel *slptr; char *aname;
 {
     struct sattr *saptr;
     char *saname;
     int i;

     /* loop through the selected attributes */
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {

         /* check the selected attribute name */
         if ((saname = saptr->sa_name) == NULL)
             saname = saptr->sa_aname;
         if (db_scmp(saname,aname) == 0)
             break;
     }

     if (saptr == NULL) {
         fprintf(fp,"<error>");
         return;
     }

     /* get the attribute value */
     for (i = 0; i < saptr->sa_attr->at_size; i++)
         if (saptr->sa_aptr[i] != 0)
             putc(saptr->sa_aptr[i],fp);
         else
             putc(' ',fp);
 }

 /* set - set internal parameters */
 static int set()
 {
     int value;

     /* process each set request */
     while (db_token() == ID) {

         /* skip the identifier */
         db_ntoken();

         /* check for "no" */
         if (db_scmp(dbv_tstring,"no") == 0) {
             value = FALSE;
             if (db_token() != ID)
                 return (db_ferror(BADSET));
             db_ntoken();
         }
         else
             value = TRUE;

         /* check for parameter to set */
         if (db_scmp(dbv_tstring,"fold") == 0)
             dbv_fold = value;
         else
             return (db_ferror(BADSET));
     }

     /* return successfully */
     return (TRUE);
 }



 CMDLINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\CMDLINE.C

 /*
  * STevie - ST editor for VI enthusiasts.   ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 static        char        *altfile = NULL;        /* alternate file */
 static        int        altline;                /* line # in alternate file

 static        char        *nowrtmsg = "No write since last change (use ! to o

 extern        char        **files;                /* used for "n" and "rew" *
 extern        int        numfiles, curfile;

 /*
  * The next two variables contain the bounds of any range given in a
  * command. If no range was given, both contain null line pointers.
  * If only a single line was given, u_pos will contain a null line
  * pointer.
  */
 static        LPTR        l_pos, u_pos;

 static        bool_t        interactive;        /* TRUE if we're reading a re

        CMDSZ        100                /* size of the command buffer */

 static        bool_t        doecmd();
 static        void        badcmd(), doshell(), get_range();
 static        LPTR        *get_line();

 #ifdef        MEGAMAX
 overlay "cmdline"
 #endif

 /*
  * readcmdline() - accept a command line starting with ':', '/', or '?'
  *
  * readcmdline() accepts and processes colon commands and searches. If
  * 'cmdline' is null, the command line is read here. Otherwise, cmdline
  * points to a complete command line that should be used. This is used
  * in main() to handle initialization commands in the environment variable
  * "EXINIT".
  */
 void
 readcmdline(firstc, cmdline)
 int        firstc;                /* either ':', '/', or '?' */
 char        *cmdline;        /* optional command string */
 {
         int c;
         char buff[CMDSZ];
         char *p, *q, *cmd, *arg;

         /*
          * Clear the range variables.
          */
         l_pos.linep = (struct line *) NULL;
         u_pos.linep = (struct line *) NULL;

         interactive = (cmdline == NULL);

         if (interactive)
                 gotocmd(1,1,firstc);
         p = buff;
         if ( firstc != ':' )
                 *p++ = firstc;

         if (interactive) {
                 /* collect the command string, handling '\b' and @ */
                 for ( ; ; ) {
                         c = vgetc();
                         if ( c=='\n'||c=='\r'||c==EOF )
                                 break;
                         if ( c=='\b' ) {
                                 if ( p > buff ) {
                                         p--;
                                         /* this is gross, but it relies
                                          * only on 'gotocmd'
                                          */
                                         gotocmd(1,0,firstc==':'?':':0);
                                         for ( q=buff; q<p; q++ )
                                                 outchar(*q);
                                 } else {
                                         msg("");
                                         return;                /* back to cmd
                                 }
                                 continue;
                         }
                         if ( c=='@' ) {
                                 p = buff;
                                 gotocmd(1,1,firstc);
                                 continue;
                         }
                         outchar(c);
                         *p++ = c;
                 }
                 *p = '\0';
         } else {
                 if (strlen(cmdline) > CMDSZ-2)        /* should really do som
                         return;                        /* better here... */
                 strcpy(p, cmdline);
         }

         /* skip any initial white space */
         for ( cmd = buff; *cmd != NUL && isspace(*cmd); cmd++ )
                 ;

         /* search commands */
         c = *cmd;
         if ( c == '/' || c == '?' ) {
                 cmd++;
                 if ( *cmd == c ) {
                         /* the command was '//' or '??' */
                         repsearch();
                         return;
                 }
                 /* If there is a matching '/' or '?' at the end, toss it */
                 p = strchr(cmd, NUL);
                 if ( *(p-1) == c && *(p-2) != '\\' )
                         *(p-1) = NUL;
                 dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
                 return;
         }

         /*
          * Parse a range, if present (and update the cmd pointer).
          */
         get_range(&cmd);

         /* isolate the command and find any argument */
         for ( p=cmd; *p != NUL && ! isspace(*p); p++ )
                 ;
         if ( *p == NUL )
                 arg = NULL;
         else {
                 *p = NUL;
                 for (p++; *p != NUL && isspace(*p) ;p++)
                         ;
                 arg = p;
                 if ( *arg == '\0' )
                         arg = NULL;
         }
         if ( strcmp(cmd,"q!")==0 )
                 getout();
         if ( strcmp(cmd,"q")==0 ) {
                 if ( Changed )
                         emsg(nowrtmsg);
                 else
                         getout();
                 return;
         }
         if ( strcmp(cmd,"w")==0 ) {
                 if ( arg == NULL ) {
                         if (Filename != NULL) {
                                 writeit(Filename, &l_pos, &u_pos);
                                 UNCHANGED;
                         } else
                                 emsg("No output file");
                 }
                 else
                         writeit(arg, &l_pos, &u_pos);
                 return;
         }
         if ( strcmp(cmd,"wq")==0 ) {
                 if (Filename != NULL) {
                         if ( writeit(Filename, NULL, NULL) )
                                 getout();
                 } else
                         emsg("No output file");
                 return;
         }
         if ( strcmp(cmd, "x") == 0 ) {
                 if (Changed) {
                         if (Filename != NULL) {
                                 if (!writeit(Filename, NULL, NULL))
                                         return;
                         } else {
                                 emsg("No output file");
                                 return;
                         }
                 }
                 getout();
         }
         if ( strcmp(cmd,"f")==0 && arg==NULL ) {
                 fileinfo();
                 return;
         }
         if ( *cmd == 'n' ) {
                 if ( (curfile + 1) < numfiles ) {
                         /*
                          * stuff ":e[!] FILE\n"
                          */
                         stuffin(":e");
                         if (cmd[1] == '!')
                                 stuffin("!");
                         stuffin(" ");
                         stuffin(files[++curfile]);
                         stuffin("\n");
                 } else
                         emsg("No more files!");
                 return;
         }
         if ( *cmd == 'p' ) {
                 if ( curfile > 0 ) {
                         /*
                          * stuff ":e[!] FILE\n"
                          */
                         stuffin(":e");
                         if (cmd[1] == '!')
                                 stuffin("!");
                         stuffin(" ");
                         stuffin(files[--curfile]);
                         stuffin("\n");
                 } else
                         emsg("No more files!");
                 return;
         }
         if ( strncmp(cmd, "rew", 3) == 0) {
                 if (numfiles <= 1)                /* nothing to rewind */
                         return;
                 curfile = 0;
                 /*
                  * stuff ":e[!] FILE\n"
                  */
                 stuffin(":e");
                 if (cmd[3] == '!')
                         stuffin("!");
                 stuffin(" ");
                 stuffin(files[0]);
                 stuffin("\n");
                 return;
         }
         if ( strcmp(cmd,"e") == 0 || strcmp(cmd,"e!") == 0 ) {
                 doecmd(arg, cmd[1] == '!');
                 return;
         }
         if ( strcmp(cmd,"f") == 0 ) {
                 Filename = strsave(arg);
                 filemess("");
                 return;
         }
         if ( strcmp(cmd,"r") == 0 || strcmp(cmd,".r") == 0 ) {
                 if ( arg == NULL ) {
                         badcmd();
                         return;
                 }
                 if (readfile(arg, Curschar, 1)) {
                         emsg("Can't open file");
                         return;
                 }
                 updatescreen();
                 CHANGED;
                 return;
         }
         if ( strcmp(cmd,".=")==0 ) {
                 char messbuff[80];
                 sprintf(messbuff,"line %d", cntllines(Filemem,Curschar));
                 msg(messbuff);
                 return;
         }
         if ( strcmp(cmd,"$=")==0 ) {
                 char messbuff[8];
                 sprintf(messbuff, "%d", cntllines(Filemem, Fileend)-1);
                 msg(messbuff);
                 return;
         }
         if ( strncmp(cmd,"ta", 2) == 0 ) {
                 dotag(arg, cmd[2] == '!');
                 return;
         }
         if ( strcmp(cmd,"set")==0 ) {
                 doset(arg, interactive);
                 return;
         }
         if ( strcmp(cmd,"help")==0 ) {
                 if (help()) {
                         screenclear();
                         updatescreen();
                 }
                 return;
         }
         if ( strcmp(cmd, "version") == 0) {
                 extern        char        *Version;

                 msg(Version);
                 return;
         }
         if ( strcmp(cmd, "sh") == 0) {
                 doshell();
                 return;
         }
         /*
          * If we got a line, but no command, then go to the line.
          */
         if (*cmd == NUL && l_pos.linep != NULL) {
                 *Curschar = l_pos;
                 cursupdate();
                 return;
         }

         badcmd();
 }

 /*
  * get_range - parse a range specifier
  *
  * Ranges are of the form:
  *
  * addr[,addr]
  *
  * where 'addr' is:
  *
  * $  [+- NUM]
  * 'x [+- NUM]        (where x denotes a currently defined mark)
  * .  [+- NUM]
  * NUM
  *
  * The pointer *cp is updated to point to the first character following
  * the range spec. If an initial address is found, but no second, the
  * upper bound is equal to the lower.
  */
 static void
 get_range(cp)
 char        **cp;
 {
         LPTR        *l;
         char        *p;

         if ((l = get_line(cp)) == NULL)
                 return;

         l_pos = *l;

         for (p = *cp; *p != NUL && isspace(*p) ;p++)
                 ;

         *cp = p;

         if (*p != ',') {                /* is there another line spec ? */
                 u_pos = l_pos;
                 return;
         }

         *cp = ++p;

         if ((l = get_line(cp)) == NULL) {
                 u_pos = l_pos;
                 return;
         }

         u_pos = *l;
 }

 static LPTR *
 get_line(cp)
 char        **cp;
 {
         static        LPTR        pos;
         LPTR        *lp;
         char        *p, c;
         int        lnum;

         pos.index = 0;                /* shouldn't matter... check back later

         p = *cp;
         /*
          * Determine the basic form, if present.
          */
         switch (c = *p++) {

         case '$':
                 pos.linep = Fileend->linep->prev;
                 break;

         case '.':
                 pos.linep = Curschar->linep;
                 break;

         case '\'':
                 if ((lp = getmark(*p++)) == NULL) {
                         emsg("Unknown mark");
                         return (LPTR *) NULL;
                 }
                 pos = *lp;
                 break;

         case '0': case '1': case '2': case '3': case '4':
         case '5': case '6': case '7': case '8': case '9':
                 for (lnum = c - '0'; isdigit(*p) ;p++)
                         lnum = (lnum * 10) + (*p - '0');

                 pos = *gotoline(lnum);
                 break;

         default:
                 return (LPTR *) NULL;
         }

         while (*p != NUL && isspace(*p))
                 p++;

         if (*p == '-' || *p == '+') {
                 bool_t        neg = (*p++ == '-');

                 for (lnum = 0; isdigit(*p) ;p++)
                         lnum = (lnum * 10) + (*p - '0');

                 if (neg)
                         lnum = -lnum;

                 pos = *gotoline( cntllines(Filemem, &pos) + lnum );
         }

         *cp = p;
         return &pos;
 }

 static void
 badcmd()
 {
         if (interactive)
                 emsg("Unrecognized command");
 }

        LSIZE        512        /* max. size of a line in the tags file */

 /*
  * dotag(tag, force) - goto tag
  */
 void
 dotag(tag, force)
 char        *tag;
 bool_t        force;
 {
         FILE        *tp, *fopen();
         char        lbuf[LSIZE];
         char        *fname, *str;

         if ((tp = fopen("tags", "r")) == NULL) {
                 emsg("Can't open tags file");
                 return;
         }

         while (fgets(lbuf, LSIZE, tp) != NULL) {

                 if ((fname = strchr(lbuf, TAB)) == NULL) {
                         emsg("Format error in tags file");
                         return;
                 }
                 *fname++ = '\0';
                 if ((str = strchr(fname, TAB)) == NULL) {
                         emsg("Format error in tags file");
                         return;
                 }
                 *str++ = '\0';

                 if (strcmp(lbuf, tag) == 0) {
                         if (doecmd(fname, force)) {
                                 stuffin(str);                /* str has \n at
                                 stuffin("\007");        /* CTRL('G') */
                                 fclose(tp);
                                 return;
                         }
                 }
         }
         emsg("tag not found");
         fclose(tp);
 }

 static        bool_t
 doecmd(arg, force)
 char        *arg;
 bool_t        force;
 {
         int        line = 1;                /* line # to go to in new file */

         if (!force && Changed) {
                 emsg(nowrtmsg);
                 return FALSE;
         }
         if ( arg != NULL ) {
                 /*
                  * First detect a ":e" on the current file. This is mainly
                  * for ":ta" commands where the destination is within the
                  * current file.
                  */
                 if (Filename != NULL && strcmp(arg, Filename) == 0) {
                         if (!Changed || (Changed && !force))
                                 return TRUE;
                 }
                 if (strcmp(arg, "#") == 0) {        /* alternate */
                         char        *s = Filename;

                         if (altfile == NULL) {
                                 emsg("No alternate file");
                                 return FALSE;
                         }
                         Filename = altfile;
                         altfile  = s;
                         line = altline;
                         altline = cntllines(Filemem, Curschar);
                 } else {
                         altfile = Filename;
                         altline = cntllines(Filemem, Curschar);
                         Filename = strsave(arg);
                 }
         }
         if (Filename == NULL) {
                 emsg("No filename");
                 return FALSE;
         }

         /* clear mem and read file */
         freeall();
         filealloc();
         UNCHANGED;

         readfile(Filename, Filemem, 0);
         *Topchar = *Curschar;
         if (line != 1) {
                 stuffnum(line);
                 stuffin("G");
         }
         setpcmark();
         updatescreen();
         return TRUE;
 }

 static void
 doshell()
 {
         char        *sh, *getenv();

         if ((sh = getenv("SHELL")) == NULL) {
                 emsg("Shell variable not set");
                 return;
         }
         gotocmd(TRUE, FALSE, 0);

         if (system(sh) < 0) {
                 emsg("Exec failed");
                 return;
         }

         wait_return();
 }

 void
 gotocmd(clr, fresh, firstc)
 bool_t  clr, fresh;
 char        firstc;
 {
         int n;

         windgoto(Rows-1,0);
         if ( clr )
                 outstr(T_EL);                /* clear the bottom line */
         if ( firstc )
                 outchar(firstc);
 }

 /*
  * msg(s) - displays the string 's' on the status line
  */
 void
 msg(s)
 char *s;
 {
         gotocmd(TRUE, TRUE, 0);
         outstr(s);
 }

 void
 smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 char        *s;
 int        a1, a2, a3, a4, a5, a6, a7, a8, a9;
 {
         char        sbuf[80];

         sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
         msg(sbuf);
 }

 /*
  * emsg() - display an error message
  *
  * Rings the bell, if appropriate, and calls message() to do the real work
  */
 void
 emsg(s)
 char        *s;
 {
         if (P(P_EB))
                 beep();
         msg(s);
 }

 void
 wait_return()
 {
         char        c;

         outstr("Press RETURN to continue");
         do {
                 c = vgetc();
         } while (c != '\r' && c != '\n');

         screenclear();
         updatescreen();
 }


 CMENU.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\CMENU.C

 /************************************************
 *                                                *
 *        CMENU -- MENU DRIVEN PROGRAM LOADER        *
 *        BY WELCOM H. WATSON, JR.                *
 *                                                *
 *        DOCUMENTED IN CMENU.DOC                        *
 *                                                *
 ************************************************/
 #include "stdio.h"
 MAXPROGS 51        /* number of selectable programs = 51 (0 - 50) */
 B_SIZE 3        /* buffer size for selection = 2 */
 C_SIZE 81        /* command line size = 80 */

 int _stack = 5120;

 main(argc, argv)
 int argc;
 char *argv[];
 {
         FILE *fp, *fopen();
         int c, fgetc();
         char progs[MAXPROGS][C_SIZE];
         char *p, *stpbrk(), *stpblk();

         extern int _oserr;
         int error;
         static char breaks[] = {' ', '\t', '\n', '\0'};
         int i, n;

         char menu[31];

         static char *dos_err[] = {
                 " ",
                 "INVALID FUNCTION NUMBER",
                 "FILE NOT FOUND",
                 "PATH NOT FOUND",
                 "TOO MANY OPEN FILES (NO HANDLES LEFT)",
                 "ACCESS DENIED",
                 "INVALID HANDLE",
                 "MEMORY CONTROL BLOCKS DESTROYED",
                 "INSUFFICIENT MEMORY",
                 "INVALID MEMORY BLOCK ADDRESS",
                 "INVALID ENVIRONMENT",
                 "INVALID FORMAT",
                 "INVALID ACCESS CODE",
                 "INVALID DATA",
                 " ",
                 "INVALID DRIVE WAS SPECIFIED",
                 "ATTEMPTED TO REMOVE THE CURRENT DIRECTORY",
                 "NOT SAME DEVICE",
                 "NO MORE FILES"
         };

 /*
 If no arguments exit.
 */

         if (argc == 1) {
                 exit();
         }

 /*
 Open and read menu control file
 all characters before '~' are output to
 console.  Character string beginning after
 first occurrence of '~' and ending with
 '\n' is the program if '0' or CR only is entered
 from the console.  If nothing is between
 '~` and '\n' '0' or CR will cause the program
 to terminate with exit.

 Strings following are the program options for
 the fork, with each program name terminated
 with '\n'.  The first program name will be loaded
 and executed if '1' is entered from the console.
 */
         strcpy(menu, argv[1]);



 loop:
         fp = fopen(menu, "ra");
         if (fp == NULL) {
                 cprintf("\nCANNOT OPEN [%s]", menu);
                 putch(7);
                 waitsec(2);
                 exit();
         }

         while ( (c = fgetc(fp)) != '~' ) {
                 putch(c);
         }


         /* get the program options */
         i = n = 0;
         while ((c = fgetc(fp)) != EOF && i < MAXPROGS) {
                 switch (c) {
                         case '\n':
                                 progs[i][n] = '\0';
                                 ++i;
                                 n = 0;
                                 break;
                         default:
                                 if (n < C_SIZE) {
                                         progs[i][n] = c;
                                         ++n;
                                 }
                                 break;
                 }
         }

         fclose(fp);

         --i;

         n = enterir(i);


         if (*progs[n] == '\0') {
                 exit();
         }


         p = progs[n];

         for (i=0; *p != '\0'; ++i) {

                 argv[i] = p;
                 p = stpbrk(p, breaks);
                 if (*p != '\0') {
                         *p = '\0';
                         ++p;
                 }

                 p = stpblk(p);

         }

         argv[i] = NULL;


         error = forkvp(argv[0], argv);
         if (error != 0) {
                 if (_oserr > 0) {
                         cprintf("\nMS-DOS ERROR [%d] IN LOADING '%s'\n%s", _o
                 }
                 else {
                         error = wait();
                         cprintf("\nMS-DOS ERROR [%d] IN EXECUTING '%s'\n%s",
                 }
                 putch(7);
                 waitsec(2);
         }
         goto loop;
 }

 /*function for entry of non negative integer characters*/

 enteri(charcnt)
 int *charcnt;        /*pointer to integer which keeps track of # of chars ent
 {
         char c, buffer[B_SIZE];
         int i, x;
         for (i = 0; (c = getch()) != '\r'; ) {
                 if ((c >= '0' && c <= '9') && i < B_SIZE - 1) {
                         buffer[i] = c;
                         putch(c);
                         ++i;
                 }
                 else if (c == '\b' && i > 0) {
                         putch('\b');
                         putch(' ');
                         putch('\b');
                         --i;
                 }
                 else {
                         putch(7);
                 }
         }
         buffer[i] = '\0';
         *charcnt = i;
         x = atoi(buffer);
         return(x);
 }

 /*entry of int >= 0 but not > maximum selection*/
 enterir(maxsel)
 int maxsel;
 {
         int x, charcnt;
         while ((x = enteri(&charcnt)) > maxsel) {
                 putch(7);
                 while (charcnt > 0) {
                         putch('\b');
                         putch(' ');
                         putch('\b');
                         --charcnt;
                 }
         }
         return(x);
 }


 CMODEM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\CMODEM.C

 /*THIS FILE MAY REQUIRE THE INFORMATION CONTAINED IN ANOTHER FILE
   CALLED "DCH.H" TO BE PROPERLY IMPLEMENTED.

                              Calamity Cliffs Computer Center
 */

 /*This program implements the Ward Christenson assembly language
   program in C.  All of the original modes are available, and a
   capture buffer was added to the terminal and computer modes.
   The UNIX and PDP10 modes were added to facilitate sending files
   to those systems.,  Note that this program as written is for the
   original version of the D. C. Hayes modem board. However, it will
   execute correctly on the newer Modem-100 board.

                                       Jack M. Wierda
 */
      DCHDP  128        /*D. C. HAYES DATA PORT*/
      DCHMASK  255      /*D. C. HAYES DATA MASK*/

      DCHSP  129        /*D. C. HAYES STATUS PORT*/
 /*STATUS PORT BIT ASSIGNMENTS*/
      RRF         1   /*RECEIVE REGISTER FULL*/
      TRE         2   /*TRANSMIT REGISTER EMPTY*/
      PERR        4   /*PARITY ERROR*/
      FERR        8   /*FRAMING ERROR*/
      OERR        16  /*OVERFLOW ERROR*/
      CD          64  /*CARRIER DETECT*/
      NRI         128 /*NO RINGING INDICATOR*/

      DCHCP1      129 /*D. C. HAYES CONTROL PORT 1*/
 /*CONTROL PORT 1 BIT ASSIGNMENTS*/
      EPE         1   /*EVEN PARITY ENABLE*/
      LS1         2   /*LENGTH SELECT 1*/
      LS2         4   /*LENGTH SELECT 2*/
      SBS         8   /*STOP BIT SELECT*/
      PI          16  /*PARITY INHIBIT*/

      DCHCP2  130       /*D. C. HAYES CONTROL PORT 2*/
 /*CONTROL PORT 2 BIT ASSIGNMENTS*/
      BRS         1   /*BIT RATE SELECT*/
      TXE         2   /*TRANSMIT ENABLE*/
      MS          4   /*MODE SELECT*/
      ES          8   /*ECHO SUPPRESS*/
      ST          16  /*SELF TEST*/
      RID         32  /*RING INDICATOR DISABLE*/
      OH          128 /*OFF HOOK*/

 #define      FALSE  0
 #define      TRUE  1
 #define      NUL  0
 #define      SOH  1
 #define      CTRLB 2
 #define      CTRLC  3
 #define      EOT  4
 #define      ERRORMAX  5
 #define      RETRYMAX  5
 #define      CTRLE  5
 #define      ACK  6
 #define      TAB  9
 #define      LF  10
 #define      CR  13
 #define      CTRLQ  17
      SPS 2750           /*loops per second*/
 #define      CTRLS  19
 #define      NAK  21
 #define      CTRLZ  26
 #define      SPACE  32
 #define      DELETE  127
 #define      TIMEOUT  -1
 #define      SECSIZ  0x80
      BUFSIZ  0x7f80        /*maximum size, 0x8000 will not work with
                                   with BDS C, reduce buffer size as necessary
                                   for smaller systems*/

 char dchcw1, dchcw2;
 char hangup, option, option2, mode, baudrate, display, system;
 char asciiflg, showtrans, showrecv, view;
 char buffer[BUFSIZ];

 sendline(data)
 char data;
 {
   while(!statp(DCHSP,TRE,TRE));
   outp(DCHDP,data);
   if(showtrans)
     { if(asciiflg)
         if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR
             || data == TAB)
           putchar(data);
         else
           printf("[%0x]",data);
       if(option2 == 'H')
         printf("[%0x]",data);
     }
 }

 readline(seconds)
 int seconds;
 {
   char data;
   seconds = seconds * SPS;
   while (!statp(DCHSP,RRF,RRF) && seconds--);
   if(seconds < 0)
     return(TIMEOUT);
   data = input(DCHDP,DCHMASK);
   if(showrecv)
     { if(asciiflg)
         if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR
             || data == TAB)
           putchar(data);
         else
           printf("[%0x]",data);
       if(option2 == 'H')
         printf("<%0x>",data);
     }
   return(data);
 }

 purgeline()
 {
   while(statp(DCHSP,RRF,RRF))
     input(DCHDP,DCHMASK);   /*PURGE THE RECEIVE REGISTER*/
 }

 dchinitialize()
 {
   char cdflg;
   cdflg = TRUE;
   if((option == 'R') || (option == 'S'))
     { dchcw1 = PI+LS2+LS1;
       dchcw2 = OH+RID+TXE+dchcw2;
     }
   else
     { dchcw1 = LS2+EPE;
       dchcw2 = OH+RID+TXE+dchcw2;
     }
   if(!statp(DCHSP,CD,CD))
     { printf("Waiting for carrier\n");
       cdflg = FALSE;
     }
   while(!statp(DCHSP,CD,CD) && !bios(2))
     { outp(DCHCP2,dchcw2);
       outp(DCHCP1,dchcw1);
     }
   if(statp(DCHSP,CD,CD) && !cdflg)
     printf("Carrier detected\n");
   purgeline();
 }

 sendstr(str)
 char *str;
 {
   while(*str)
     if(option == 'U')
       sendline(tolower(*str++));
     else
       sendline(*str++);
 }

 termcomp()
 {
   char bflag, kbdata, dchdata;
   int fd;
   int bufctr;
   bflag = FALSE;
   bufctr = 0;
   dchinitialize();
   while((statp(DCHSP,CD,CD)) && (kbdata != CTRLE))
     { if(bios(2))
         switch(kbdata = bios(3))
           { case CTRLB:
               bflag = ~bflag;
               if(bflag)
                 printf("Capture initiated");
               else
                 printf("Capture terminated");
               printf(", %u bytes free\n",BUFSIZ - bufctr);
               break;
             case CTRLE:
               break;
             default:
               if(option == 'C')
                 { putchar(kbdata);
                   if(bflag && (bufctr < BUFSIZ))
                     buffer[bufctr++] = kbdata;
                 }
               outp(DCHDP,kbdata);
               break;
           }
       if(statp(DCHSP,RRF,RRF))
         { dchdata = input(DCHDP,DCHMASK);
           if(option == 'C')
             outp(DCHDP,dchdata);
           if(bflag && (bufctr < BUFSIZ))
             buffer[bufctr++] = dchdata;
           else if(bflag)
             printf("Buffer overflow\n");
           putchar(dchdata);
         }
     }
   if(bufctr)
     { buffer[bufctr] = CTRLZ;
       fd = creat("cmodem.tmp");
       if(fd == -1)
         { printf("Cannot create cmodem.tmp\n");
           exit();
         }
       write(fd,buffer,1 + (bufctr/SECSIZ));
       close(fd);
     }
 }

 putbuffer(buffer,sectors)
 char *buffer;
 int sectors;
 {
   char ch, dchdata;
   unsigned  k;
   ch = 0;
   k = 0;
   while((ch != CTRLZ) && (k < sectors * SECSIZ) && (statp(DCHSP,CD,CD)))
         { k = k+1;
           if((ch = *buffer++) == LF)        /*don't send LF's*/
             putchar(LF);
           else
             if(ch != CTRLZ || option != 'U') /*don't send CTRLZ to UNIX*/
               sendline(ch);
           if(!(k & 0xff))                   /*let other end catch-up*/
              while(readline(1) != TIMEOUT);
         }
 }

 pdp10(file)
 char *file;
 {
   char sectors;
   int fd;
   showrecv = FALSE;
   asciiflg = showtrans = TRUE;
   fd = open(file,0);
   if(fd == -1)
     { printf("Cannot open %s\n",file);
       exit();
     }
   dchinitialize();
   if(option == 'P')
     { sendstr("\nR PIP\n");
       while((readline(1) != '*') && !bios(2));
       if(*(++file) != ':')
         sendstr(--file);
       else
         sendstr(++file);
       sendstr("=TTY:\n");
     }
   else
     { sendstr("\ncat > ");
       if(*(++file) != ':')
         sendstr(--file);
       else
         sendstr(++file);
       sendstr("\n");
     }
   while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) == BUFSIZ/SECSIZ)
     putbuffer(buffer,sectors);
   if(sectors)
     putbuffer(buffer,sectors);
   close(fd);
   while(readline(1) != TIMEOUT);
   if(option == 'P')
     sendline(CTRLC);
   else
     { sendline(CR);
       sendline(LF);
       sendline(EOT);
     }
   while(readline(10) != TIMEOUT);
   sendline(CR);
   sendline(LF);
 }

 readfile(file)
 char *file;
 { int j, firstchar, sectnum, sectcurr, sectcomp, errors;
   int checksum;
   int errorflag, fd;
   int bufctr;

   if(view)
     { showrecv = TRUE;
       showtrans = FALSE;
     }
   option2 = 'A';
   fd = creat(file);
   if(fd == -1)
     { printf("Cannot create %s\n",file);
       exit();
     }
   sectnum = 0;
   errors = 0;
   bufctr = 0;
   dchinitialize();
   sendline(NAK);
   do
     { errorflag = FALSE;
       do
         firstchar = readline(6);
       while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);
       if(firstchar == TIMEOUT)
         { errorflag = TRUE;
           printf("SOH timeout\n");
         }
       if(firstchar == SOH)
         { sectcurr = readline(1);
           sectcomp = readline(1);
           if((sectcurr + sectcomp) == 255)
             { if(sectcurr == sectnum + 1)
                 { checksum = 0;
                   if(option2 == 'A')
                     asciiflg = TRUE;
                   for(j = bufctr;j < (bufctr + SECSIZ);j++)
                     { buffer[j] = readline(1);
                       checksum = (checksum + buffer[j]) & 0xff;
                     }
                   asciiflg = FALSE;
                   if(checksum == readline(1))
                     { errors = 0;
                       sectnum = sectcurr;
                       bufctr = bufctr + SECSIZ;
                       if(bufctr == BUFSIZ)
                         { bufctr = 0;
                           write(fd,buffer,BUFSIZ/SECSIZ);
                         }
                       if(!showrecv)
                         printf("Received sector %d\n",sectcurr);
                       sendline(ACK);
                     }
                   else
                     { printf("Checksum error, expected <%0x>\n",checksum);
                       errorflag = TRUE;
                     }
                 }
               else
                 if(sectcurr == sectnum)
                   { do;
                     while(readline(1) != TIMEOUT);
                     printf("Received duplicate sector %d\n", sectcurr);
                     sendline(ACK);
                   }
                 else
                   { printf("Synchronization error\n");
                     errorflag = TRUE;
                   }
               }
             else
               { printf("Sector number error\n");
                 errorflag = TRUE;
               }
           }
        if(errorflag == TRUE)
          { errors++;
            printf("Error %d\n",errors);
            while(readline(1) != TIMEOUT);
            sendline(NAK);
          }
      }
   while(firstchar != EOT && errors != ERRORMAX);
   if((firstchar == EOT) && (errors < ERRORMAX))
     { sendline(ACK);
       write(fd,buffer,1 + (bufctr/SECSIZ));
       close(fd);
       printf("Transfer complete\n");
     }
   else
     printf("Aborting\n");
 }

 sendfile(file)
 char *file;
 {
   int j, sectnum, sectors, attempts;
   int checksum;
   int bufctr, fd;

   if(view)
     { showrecv = FALSE;
       showtrans = TRUE;
     }
   option2 = 'A';
   fd = open(file,0);
   if(fd == -1)
     { printf("Cannot open %s\n",file);
       exit();
     }
   dchinitialize();
   attempts = 0;
   sectnum = 1;
   while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) && (attempts != RETRYMAX))
     { if(sectors == -1)
         printf("\nFile read error\n");
       else
         { bufctr = 0;
           do
             { attempts = 0;
               do
                 { if(!showtrans)
                     printf("\nSending sector %d\n",sectnum);
                   sendline(SOH);
                   sendline(sectnum);
                   sendline(-sectnum-1);
                   checksum = 0;
                   if(option2 == 'A')
                     asciiflg = TRUE;
                   for(j = bufctr;j < (bufctr + SECSIZ);j++)
                     { sendline(buffer[j]);
                       checksum = (checksum + buffer[j]) & 0xff;
                     }
                   asciiflg = FALSE;
                   sendline(checksum);
                   purgeline();
                   attempts++;
                 }
               while((readline(10) != ACK) && (attempts != RETRYMAX));
               bufctr = bufctr + SECSIZ;
               sectnum++;
               sectors--;
             }
           while((sectors != 0) && (attempts != RETRYMAX));
         }
     }
       if(attempts == RETRYMAX)
         printf("\nNo ACK on sector, aborting\n");
       else
         { attempts = 0;
           do
             { sendline(EOT);
               purgeline();
               attempts++;
             }
           while((readline(10) != ACK) && (attempts != RETRYMAX));
           if(attempts == RETRYMAX)
             printf("\nNo ACK on EOT, aborting\n");
           else
             printf("\nTransfer complete\n");
         }
   close(fd);
 }

 ckfile(argc) int argc;
 { if(!argc)
     { printf("File required\n");
       exit();
     }
 }

 main(argc,argv)
 int argc;
 char **argv;
 { char *s;
   printf("Cmodem, 9-July-80\n");
   dchcw2 = 0;
   asciiflg = hangup = showrecv = showtrans = view = FALSE;
   if(**++argv != '-')
     { printf("Command line format: cmodem -options file1 file2 ... file14\n")
       printf("Available options are:\n");
       printf("\ta: answer\n");
       printf("\tc: computer\n");
       printf("\th: auto-hangup\n");
       printf("\to: originate\n");
       printf("\tp: PDP10\n");
       printf("\tr: receive file\n");
       printf("\ts: send file\n");
       printf("\tt: terminal\n");
       printf("\tu: UNIX\n");
       printf("\tv: view data\n");
       printf("\t1: 110 baud\n");
       printf("\t3: 300 baud\n");
       printf("The p, r, s, and u options require one or more files.\n");
       printf("Ctrl-B initiates and terminates data capture in file\n");
       printf("cmodem.tmp in the terminal and computer modes.\n");
       printf("Ctrl-E is used to initiate file transfers in the UNIX and\n");
       printf("PDP10 modes. In the terminal mode Ctrl-E escapes to the\n");
       printf("hangup question or CP/M.\n");
       printf("Any character escapes the no carrier condition.\n");
       exit();
     }
   --argv;
   while(--argc && **++argv == '-')
     for(s = *argv+1;*s;s++)
       switch(*s)
         { case 'C':
           case 'P':
           case 'R':
           case 'S':
           case 'T':
           case 'U':
             option = *s;
             break;
           case 'A':
           case '1':
             break;
           case 'H':
             hangup = TRUE;
             break;
           case 'V':
             view = TRUE;
             break;
           case 'O':
             dchcw2 = dchcw2 + MS;
             break;
           case '3':
             dchcw2 = dchcw2 + BRS;
             break;
           default:
             printf("Unimplemented option %c\n\n",*s);
             exit();
             break;
         }
       switch(option)
         { case 'C':
           case 'T':
             termcomp();
             break;
           case 'P':
           case 'U':
             ckfile(argc);
             termcomp();
             while(argc--)
               { printf("\nSending %s\n",*argv);
                 pdp10(*argv++);
               }
             termcomp();
             break;
           case 'R':
             ckfile(argc);
             while(argc--)
               { printf("\nReceiving %s\n",*argv);
                 readfile(*argv++);
               }
             break;
           case 'S':
             ckfile(argc);
             while(argc--)
               { printf("\nSending %s\n",*argv);
                 sendfile(*argv++);
               }
             break;
         }
       if(hangup)
         outp(DCHCP2,0);
       else
         { do
             { printf("\nHangup : Y(es), N(o) ? ");
               hangup = tolower(getchar());
               printf("\n");
             }
           while((hangup != 'y') && (hangup != 'n'));
           if(hangup == 'y')
             outp(DCHCP2,0);
         }
 }













 CMODEM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\CMODEM.C

 /*THIS FILE MAY REQUIRE THE INFORMATION CONTAINED IN ANOTHER FILE
   CALLED "DCH.H" TO BE PROPERLY IMPLEMENTED.

                              Calamity Cliffs Computer Center
 */

 /*This program implements the Ward Christenson assembly language
   program in C.  All of the original modes are available, and a
   capture buffer was added to the terminal and computer modes.
   The UNIX and PDP10 modes were added to facilitate sending files
   to those systems.,  Note that this program as written is for the
   original version of the D. C. Hayes modem board. However, it will
   execute correctly on the newer Modem-100 board.

                                       Jack M. Wierda
 */
      DCHDP  128        /*D. C. HAYES DATA PORT*/
      DCHMASK  255      /*D. C. HAYES DATA MASK*/

      DCHSP  129        /*D. C. HAYES STATUS PORT*/
 /*STATUS PORT BIT ASSIGNMENTS*/
      RRF         1   /*RECEIVE REGISTER FULL*/
      TRE         2   /*TRANSMIT REGISTER EMPTY*/
      PERR        4   /*PARITY ERROR*/
      FERR        8   /*FRAMING ERROR*/
      OERR        16  /*OVERFLOW ERROR*/
      CD          64  /*CARRIER DETECT*/
      NRI         128 /*NO RINGING INDICATOR*/

      DCHCP1      129 /*D. C. HAYES CONTROL PORT 1*/
 /*CONTROL PORT 1 BIT ASSIGNMENTS*/
      EPE         1   /*EVEN PARITY ENABLE*/
      LS1         2   /*LENGTH SELECT 1*/
      LS2         4   /*LENGTH SELECT 2*/
      SBS         8   /*STOP BIT SELECT*/
      PI          16  /*PARITY INHIBIT*/

      DCHCP2  130       /*D. C. HAYES CONTROL PORT 2*/
 /*CONTROL PORT 2 BIT ASSIGNMENTS*/
      BRS         1   /*BIT RATE SELECT*/
      TXE         2   /*TRANSMIT ENABLE*/
      MS          4   /*MODE SELECT*/
      ES          8   /*ECHO SUPPRESS*/
      ST          16  /*SELF TEST*/
      RID         32  /*RING INDICATOR DISABLE*/
      OH          128 /*OFF HOOK*/

 #define      FALSE  0
 #define      TRUE  1
 #define      NUL  0
 #define      SOH  1
 #define      CTRLB 2
 #define      CTRLC  3
 #define      EOT  4
 #define      ERRORMAX  5
 #define      RETRYMAX  5
 #define      CTRLE  5
 #define      ACK  6
 #define      TAB  9
 #define      LF  10
 #define      CR  13
 #define      CTRLQ  17
      SPS 2750           /*loops per second*/
 #define      CTRLS  19
 #define      NAK  21
 #define      CTRLZ  26
 #define      SPACE  32
 #define      DELETE  127
 #define      TIMEOUT  -1
 #define      SECSIZ  0x80
      BUFSIZ  0x7f80        /*maximum size, 0x8000 will not work with
                                   with BDS C, reduce buffer size as necessary
                                   for smaller systems*/

 char dchcw1, dchcw2;
 char hangup, option, option2, mode, baudrate, display, system;
 char asciiflg, showtrans, showrecv, view;
 char buffer[BUFSIZ];

 sendline(data)
 char data;
 {
   while(!statp(DCHSP,TRE,TRE));
   outp(DCHDP,data);
   if(showtrans)
     { if(asciiflg)
         if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR
             || data == TAB)
           putchar(data);
         else
           printf("[%0x]",data);
       if(option2 == 'H')
         printf("[%0x]",data);
     }
 }

 readline(seconds)
 int seconds;
 {
   char data;
   seconds = seconds * SPS;
   while (!statp(DCHSP,RRF,RRF) && seconds--);
   if(seconds < 0)
     return(TIMEOUT);
   data = input(DCHDP,DCHMASK);
   if(showrecv)
     { if(asciiflg)
         if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR
             || data == TAB)
           putchar(data);
         else
           printf("[%0x]",data);
       if(option2 == 'H')
         printf("<%0x>",data);
     }
   return(data);
 }

 purgeline()
 {
   while(statp(DCHSP,RRF,RRF))
     input(DCHDP,DCHMASK);   /*PURGE THE RECEIVE REGISTER*/
 }

 dchinitialize()
 {
   char cdflg;
   cdflg = TRUE;
   if((option == 'R') || (option == 'S'))
     { dchcw1 = PI+LS2+LS1;
       dchcw2 = OH+RID+TXE+dchcw2;
     }
   else
     { dchcw1 = LS2+EPE;
       dchcw2 = OH+RID+TXE+dchcw2;
     }
   if(!statp(DCHSP,CD,CD))
     { printf("Waiting for carrier\n");
       cdflg = FALSE;
     }
   while(!statp(DCHSP,CD,CD) && !bios(2))
     { outp(DCHCP2,dchcw2);
       outp(DCHCP1,dchcw1);
     }
   if(statp(DCHSP,CD,CD) && !cdflg)
     printf("Carrier detected\n");
   purgeline();
 }

 sendstr(str)
 char *str;
 {
   while(*str)
     if(option == 'U')
       sendline(tolower(*str++));
     else
       sendline(*str++);
 }

 termcomp()
 {
   char bflag, kbdata, dchdata;
   int fd;
   int bufctr;
   bflag = FALSE;
   bufctr = 0;
   dchinitialize();
   while((statp(DCHSP,CD,CD)) && (kbdata != CTRLE))
     { if(bios(2))
         switch(kbdata = bios(3))
           { case CTRLB:
               bflag = ~bflag;
               if(bflag)
                 printf("Capture initiated");
               else
                 printf("Capture terminated");
               printf(", %u bytes free\n",BUFSIZ - bufctr);
               break;
             case CTRLE:
               break;
             default:
               if(option == 'C')
                 { putchar(kbdata);
                   if(bflag && (bufctr < BUFSIZ))
                     buffer[bufctr++] = kbdata;
                 }
               outp(DCHDP,kbdata);
               break;
           }
       if(statp(DCHSP,RRF,RRF))
         { dchdata = input(DCHDP,DCHMASK);
           if(option == 'C')
             outp(DCHDP,dchdata);
           if(bflag && (bufctr < BUFSIZ))
             buffer[bufctr++] = dchdata;
           else if(bflag)
             printf("Buffer overflow\n");
           putchar(dchdata);
         }
     }
   if(bufctr)
     { buffer[bufctr] = CTRLZ;
       fd = creat("cmodem.tmp");
       if(fd == -1)
         { printf("Cannot create cmodem.tmp\n");
           exit();
         }
       write(fd,buffer,1 + (bufctr/SECSIZ));
       close(fd);
     }
 }

 putbuffer(buffer,sectors)
 char *buffer;
 int sectors;
 {
   char ch, dchdata;
   unsigned  k;
   ch = 0;
   k = 0;
   while((ch != CTRLZ) && (k < sectors * SECSIZ) && (statp(DCHSP,CD,CD)))
         { k = k+1;
           if((ch = *buffer++) == LF)        /*don't send LF's*/
             putchar(LF);
           else
             if(ch != CTRLZ || option != 'U') /*don't send CTRLZ to UNIX*/
               sendline(ch);
           if(!(k & 0xff))                   /*let other end catch-up*/
              while(readline(1) != TIMEOUT);
         }
 }

 pdp10(file)
 char *file;
 {
   char sectors;
   int fd;
   showrecv = FALSE;
   asciiflg = showtrans = TRUE;
   fd = open(file,0);
   if(fd == -1)
     { printf("Cannot open %s\n",file);
       exit();
     }
   dchinitialize();
   if(option == 'P')
     { sendstr("\nR PIP\n");
       while((readline(1) != '*') && !bios(2));
       if(*(++file) != ':')
         sendstr(--file);
       else
         sendstr(++file);
       sendstr("=TTY:\n");
     }
   else
     { sendstr("\ncat > ");
       if(*(++file) != ':')
         sendstr(--file);
       else
         sendstr(++file);
       sendstr("\n");
     }
   while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) == BUFSIZ/SECSIZ)
     putbuffer(buffer,sectors);
   if(sectors)
     putbuffer(buffer,sectors);
   close(fd);
   while(readline(1) != TIMEOUT);
   if(option == 'P')
     sendline(CTRLC);
   else
     { sendline(CR);
       sendline(LF);
       sendline(EOT);
     }
   while(readline(10) != TIMEOUT);
   sendline(CR);
   sendline(LF);
 }

 readfile(file)
 char *file;
 { int j, firstchar, sectnum, sectcurr, sectcomp, errors;
   int checksum;
   int errorflag, fd;
   int bufctr;

   if(view)
     { showrecv = TRUE;
       showtrans = FALSE;
     }
   option2 = 'A';
   fd = creat(file);
   if(fd == -1)
     { printf("Cannot create %s\n",file);
       exit();
     }
   sectnum = 0;
   errors = 0;
   bufctr = 0;
   dchinitialize();
   sendline(NAK);
   do
     { errorflag = FALSE;
       do
         firstchar = readline(6);
       while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);
       if(firstchar == TIMEOUT)
         { errorflag = TRUE;
           printf("SOH timeout\n");
         }
       if(firstchar == SOH)
         { sectcurr = readline(1);
           sectcomp = readline(1);
           if((sectcurr + sectcomp) == 255)
             { if(sectcurr == sectnum + 1)
                 { checksum = 0;
                   if(option2 == 'A')
                     asciiflg = TRUE;
                   for(j = bufctr;j < (bufctr + SECSIZ);j++)
                     { buffer[j] = readline(1);
                       checksum = (checksum + buffer[j]) & 0xff;
                     }
                   asciiflg = FALSE;
                   if(checksum == readline(1))
                     { errors = 0;
                       sectnum = sectcurr;
                       bufctr = bufctr + SECSIZ;
                       if(bufctr == BUFSIZ)
                         { bufctr = 0;
                           write(fd,buffer,BUFSIZ/SECSIZ);
                         }
                       if(!showrecv)
                         printf("Received sector %d\n",sectcurr);
                       sendline(ACK);
                     }
                   else
                     { printf("Checksum error, expected <%0x>\n",checksum);
                       errorflag = TRUE;
                     }
                 }
               else
                 if(sectcurr == sectnum)
                   { do;
                     while(readline(1) != TIMEOUT);
                     printf("Received duplicate sector %d\n", sectcurr);
                     sendline(ACK);
                   }
                 else
                   { printf("Synchronization error\n");
                     errorflag = TRUE;
                   }
               }
             else
               { printf("Sector number error\n");
                 errorflag = TRUE;
               }
           }
        if(errorflag == TRUE)
          { errors++;
            printf("Error %d\n",errors);
            while(readline(1) != TIMEOUT);
            sendline(NAK);
          }
      }
   while(firstchar != EOT && errors != ERRORMAX);
   if((firstchar == EOT) && (errors < ERRORMAX))
     { sendline(ACK);
       write(fd,buffer,1 + (bufctr/SECSIZ));
       close(fd);
       printf("Transfer complete\n");
     }
   else
     printf("Aborting\n");
 }

 sendfile(file)
 char *file;
 {
   int j, sectnum, sectors, attempts;
   int checksum;
   int bufctr, fd;

   if(view)
     { showrecv = FALSE;
       showtrans = TRUE;
     }
   option2 = 'A';
   fd = open(file,0);
   if(fd == -1)
     { printf("Cannot open %s\n",file);
       exit();
     }
   dchinitialize();
   attempts = 0;
   sectnum = 1;
   while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) && (attempts != RETRYMAX))
     { if(sectors == -1)
         printf("\nFile read error\n");
       else
         { bufctr = 0;
           do
             { attempts = 0;
               do
                 { if(!showtrans)
                     printf("\nSending sector %d\n",sectnum);
                   sendline(SOH);
                   sendline(sectnum);
                   sendline(-sectnum-1);
                   checksum = 0;
                   if(option2 == 'A')
                     asciiflg = TRUE;
                   for(j = bufctr;j < (bufctr + SECSIZ);j++)
                     { sendline(buffer[j]);
                       checksum = (checksum + buffer[j]) & 0xff;
                     }
                   asciiflg = FALSE;
                   sendline(checksum);
                   purgeline();
                   attempts++;
                 }
               while((readline(10) != ACK) && (attempts != RETRYMAX));
               bufctr = bufctr + SECSIZ;
               sectnum++;
               sectors--;
             }
           while((sectors != 0) && (attempts != RETRYMAX));
         }
     }
       if(attempts == RETRYMAX)
         printf("\nNo ACK on sector, aborting\n");
       else
         { attempts = 0;
           do
             { sendline(EOT);
               purgeline();
               attempts++;
             }
           while((readline(10) != ACK) && (attempts != RETRYMAX));
           if(attempts == RETRYMAX)
             printf("\nNo ACK on EOT, aborting\n");
           else
             printf("\nTransfer complete\n");
         }
   close(fd);
 }

 ckfile(argc) int argc;
 { if(!argc)
     { printf("File required\n");
       exit();
     }
 }

 main(argc,argv)
 int argc;
 char **argv;
 { char *s;
   printf("Cmodem, 9-July-80\n");
   dchcw2 = 0;
   asciiflg = hangup = showrecv = showtrans = view = FALSE;
   if(**++argv != '-')
     { printf("Command line format: cmodem -options file1 file2 ... file14\n")
       printf("Available options are:\n");
       printf("\ta: answer\n");
       printf("\tc: computer\n");
       printf("\th: auto-hangup\n");
       printf("\to: originate\n");
       printf("\tp: PDP10\n");
       printf("\tr: receive file\n");
       printf("\ts: send file\n");
       printf("\tt: terminal\n");
       printf("\tu: UNIX\n");
       printf("\tv: view data\n");
       printf("\t1: 110 baud\n");
       printf("\t3: 300 baud\n");
       printf("The p, r, s, and u options require one or more files.\n");
       printf("Ctrl-B initiates and terminates data capture in file\n");
       printf("cmodem.tmp in the terminal and computer modes.\n");
       printf("Ctrl-E is used to initiate file transfers in the UNIX and\n");
       printf("PDP10 modes. In the terminal mode Ctrl-E escapes to the\n");
       printf("hangup question or CP/M.\n");
       printf("Any character escapes the no carrier condition.\n");
       exit();
     }
   --argv;
   while(--argc && **++argv == '-')
     for(s = *argv+1;*s;s++)
       switch(*s)
         { case 'C':
           case 'P':
           case 'R':
           case 'S':
           case 'T':
           case 'U':
             option = *s;
             break;
           case 'A':
           case '1':
             break;
           case 'H':
             hangup = TRUE;
             break;
           case 'V':
             view = TRUE;
             break;
           case 'O':
             dchcw2 = dchcw2 + MS;
             break;
           case '3':
             dchcw2 = dchcw2 + BRS;
             break;
           default:
             printf("Unimplemented option %c\n\n",*s);
             exit();
             break;
         }
       switch(option)
         { case 'C':
           case 'T':
             termcomp();
             break;
           case 'P':
           case 'U':
             ckfile(argc);
             termcomp();
             while(argc--)
               { printf("\nSending %s\n",*argv);
                 pdp10(*argv++);
               }
             termcomp();
             break;
           case 'R':
             ckfile(argc);
             while(argc--)
               { printf("\nReceiving %s\n",*argv);
                 readfile(*argv++);
               }
             break;
           case 'S':
             ckfile(argc);
             while(argc--)
               { printf("\nSending %s\n",*argv);
                 sendfile(*argv++);
               }
             break;
         }
       if(hangup)
         outp(DCHCP2,0);
       else
         { do
             { printf("\nHangup : Y(es), N(o) ? ");
               hangup = tolower(getchar());
               printf("\n");
             }
           while((hangup != 'y') && (hangup != 'n'));
           if(hangup == 'y')
             outp(DCHCP2,0);
         }
 }













 CMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CMP.C

 /* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
         Program to compare (byte for byte)
         two files and print differences

         H.Moran                10/27/79
         slight mod        2/13/80
    : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
 /*
         Whatever compiler Mr. Morgan uses it is very non-K & R
         or maybe it's Unix V6 rather than V7 or system III or some
         thing like that...So I've taken the liberty of making it
         ci-c86-able and at least as of 3/20/84 this works for
         ascii files
                         Matthew Weinstein

         Finis.... added binary file option...BEWARE USER
         this will open files as binary .... otherwise use
         the -a flag. --3/21/84

                         Matthew Weinstein

 */

 /* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
         Macros for constant definitions
    : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
 #define TRUE 1
 #define FALSE 0
 EOFF -1                /* end of file marker returned by getc() */
 NOFILE 0        /* no such file indication given by fopen() */
 #include "stdio.h"

 /*        -------------------------------------------------------

         Name:                main(argc,argv)
         Result:                ---
         Errors:                invocation syntax error or no such file
         Globals:        ---
         Macros:                TRUE,FALSE,NOFILE
         Procedures:        fopen(),tolower(),bummer(),htoi(),fcompare()

         Action:                Byte by byte compare of 2 files and
                         print their differences on console

         ------------------------------------------------------- */


 main(argc,argv)
         int argc;
         char *argv[];
 {
         FILE *fopen(),*fd1,*fd2;
         int ascii;
         unsigned start_adrs,htoi();
         char mode[3], *ptr, *strcpy();

         strcpy(mode,"rb");
         ascii = FALSE;        /* assign the defaults */
         start_adrs = 0;
           while( argc > 3 )
          {
             ptr = argv[--argc];
             if( *ptr++ != '-' )
               bummer();
             switch ( tolower(*ptr++) )
               {
               case 'a':        ascii = TRUE;
                         strcpy(mode,"r");
                         break;

               case 'b':        start_adrs = htoi(ptr);
                         break;

               default:        puts("Unrecognized option. Aborted\n\n");
                         bummer();
               }        /* end switch */
             }        /* end while */
         if( argc < 3 || argc > 5 )
           bummer();
         else if( (fd1 = fopen(argv[1],mode)) == NOFILE )
           printf("No such file %s\n",argv[1]);
         else if( (fd2  = fopen(argv[2],mode)) == NOFILE)
           printf("No such file %s\n",argv[2]);
         else  fcompare(fd1,fd2,start_adrs,ascii);
         exit();
         }


 /*        -------------------------------------------------------

         Name:                fcompare(mfile,cfile,adrs,ascii)
         Result:                ---
         Errors:                ---
         Globals:        ---
         Macros:                EOFF,EOF
         Procedures:        getc(),puts(),strcpy(),printf()

         Action:                compare 2 files and print their differences
                         on the console

         ------------------------------------------------------- */



 fcompare(mfile,cfile,adrs,ascii)
         FILE *mfile;                /* the input file buffer */
         FILE *cfile;                /* the output file buffer */
         unsigned adrs;                /* the address of begin of file */
         int ascii;                /* flag of whether these are ascii files */
         {
         int mc,cc;                /* 1 char buffers */
         char erflg;                /* flag that an error has occurred */
         char *xl();                /* function to translate control chars */
         char str1[6],str2[6];        /* temporaries for strings */
         char xlate[10];        /* string used in ascii control char translati


         erflg = 0;
         while( ! ( (mc = getc(mfile)) == EOFF || (ascii && mc == EOF)) ) {
           if( (cc =getc(cfile)) == EOFF || ( ascii && cc == EOF )) {
             puts("Checkfile shorter than Master file\n");
             return;
             }
           else if( mc != cc ) {
             if( ! erflg ) {
               erflg = 1;
               puts("\nRelative Master Check");
               puts("\nAddress  File   File   Mismatch");
               puts("\n-------  ----   ----   --------\n");
               }        /* end if */
             if( ascii )        {
               strcpy(str1,xl(mc,xlate)); /* fudge because parameters are */
               strcpy(str2,xl(cc,xlate)); /* evaluated before being passed */
               printf("%4x     %-4s   %-4s   %8b\n",adrs,str1,str2,mc^cc);
               }
             else
               printf("%4x     %2x     %2x     %8b\n",adrs,mc,cc,mc ^ cc);
             }                /* end else if */
           else
             ;
           adrs++;
           }                /* end while */
         if(! ( (cc = getc(cfile)) == EOFF || (ascii && cc == EOF) ) )
           puts("Masterfile shorter than checkfile\n");
         return;
         }                /* end fcompare() */

 /*        -------------------------------------------------------

         Name:                err_exit(msg)
         Result:                ---
         Errors:                ---
         Globals:        ---
         Macros:                ---
         Procedures:        printf(),exit()

         Action:                Print a message then exit to CP/M

         ------------------------------------------------------- */


 err_exit(msg)
         char *msg;
         {
         exit(puts(msg));
         }

 /*        -------------------------------------------------------

         Name:                htoi(string)
         Result:                unsigned integer value of ascii hex string
         Errors:                ---
         Globals:        ---
         Macros:                ---
         Procedures:        tolower(),isalpha(),isdigit()

         Action:                ---

         ------------------------------------------------------- */


 unsigned htoi(string)
         char *string;
         {
         unsigned number;
         char c;

         number = 0;
         c = tolower(*string++);
         while( isalpha(c) || isdigit(c) ) {
           if( c > 'f' )
             return number;
           number *= 16;
           if( isdigit(c) )
             number += c -'0';
           else
             number += c - 'a' + 10;
           c = tolower(*string++);
           }
         return number;
         }
 /*        -------------------------------------------------------

         Name:                bummer()
         Result:                ---
         Errors:                ---
         Globals:        ---
         Macros:                ---
         Procedures:        puts(),exit()

         Action:                Print the invocation syntax error message
                         and exit to CP/M

         ------------------------------------------------------- */


 bummer()
         {
         puts("Correct invocation form is:\n");
         puts(" FILECOMP <master file> <check file> {-a -b<hex-num>}\n\n");
         puts("Where optional arguments are:\n\n");
         puts("-a          => these are ascii files (terminate on 1AH )\n");
         puts("-b<hex-num> => begin of file is address <hex-num> ");
         puts("default is 0\n");
         exit();
         }


 /*        -------------------------------------------------------

         Name:                xl(c)
         Result:                pointer to  xlate[]
         Errors:                ---
         Globals:
         Macros:                ---
         Procedures:        strcpy()

         Action:                Translate the char argument c into a
                         4 char string in  xlate[]
                         If c is a printable ascii char its
                           translation is itself right blank padded
                         Else if c is a standard control char its
                           translation is a string identifying that
                           control char
                         Else its translation is "????"

         ------------------------------------------------------- */


 char *xl(c,xlate)
         int c;
         char *xlate;
         {
         if( c > 0x7f || c < 0 )
           strcpy(xlate,"????");
         else if( c == 0x7f )
           strcpy(xlate,"del ");
         else if( c > 0x1f ) {        /* then it is printable */
           xlate[0] = c;
           strcpy(xlate+1,"   ");
           }
         else
           switch (c) {
             case 0x7:        strcpy(xlate,"bel");
                         break;

             case 0x8:        strcpy(xlate,"bs");
                         break;

             case 0x9:        strcpy(xlate,"tab");
                         break;

             case 0xa:        strcpy(xlate,"lf");
                         break;

             case 0xc:        strcpy(xlate,"ff");
                         break;

             case 0xd:        strcpy(xlate,"cr");
                         break;

             case 0x1b:        strcpy(xlate,"esc");
                         break;

             default:        xlate[0] = '^';                /* show control ch
                         xlate[1] = c + 0x40;        /* ^ <char> e.g. ^A is */
                         xlate[2] = '\0';        /* control A */
                         break;
             }
         return xlate;
         }


 COLOR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\COLOR.C

 /****************************************************************************
  *                                              *
  *  COLOR.C   Max R. D�rsteler    12-7-83            *
  *                                              *
  *  Set screen colors in text mode.                  *
  *                                              *
  ****************************************************************************
  */
 #include <stdio.h>
 #include <ctype.h>
 #include "graph.h"

 main(argc, argv)
     int argc;
     char **argv;
 {
     int charcol = 11;
     int scrncol = 4;
     int bordcol = 4;
     int i;

     if (argc < 4) {
           printf("Usage: color [forground ] [background] [border]\n");
           printf(" e.g.:\ncolor 11 4 12\n");
           printf(" or:\ncolor yellow blue lblue\n");
           printf(" or:\ncolor y blu lblu\n\n");
           printf(" DOS 2.0 color indices: [0..15], background [0..7]\n\n");
           printf(" Available color names: \n");
           printf("  bla<ck> <l>r<ed> <l>g<reen> y<ellow> br<own>\n");
           printf("  <l>blu<e> <l>m<agenta> <l>c<yan> <l>w<hite>\n\n");
           printf(" <x> : x=optional character
           printf("  l  : light (for foreground & border color only!)\n");
           exit(0);
     }
     argv++;
     charcol = colnum(*argv++);
     scrncol = colnum(*argv++);
     bordcol = colnum(*argv);
     i = bordcol & 7;
     switch (i) {        /* Translation from DOS 2.0 color table */
          case 1:   /* to IBM color card color table */
               i = 4;
               break;
          case 3:
               i = 6;
               break;
          case 4:
               i = 1;
               break;
          case 6:
               i = 3;
               break;
          default:
               i = bordcol;
               break;
     };
     bordcol = i | (bordcol & 8);
     screen(TEXTMOD);
     outp(COLREG, bordcol | 0x10);
     if (charcol & 8) printf("\033[1m\n");
     else printf("\033[0m\n");
     charcol = (charcol & 7) + 30;
     scrncol = (scrncol & 7) + 40;
     printf("\033[%d;%dm\n", charcol, scrncol);
     cls();
 }
 /*----------------------------------------------------------------------*/

 colnum(colname)
     char *colname;
 {
     int ncol;
     int intens;
     char *pc;

     pc = colname;
     intens = 0;
     if (isdigit(*pc)) {
          if(sscanf(pc,"%d", &ncol) == 1)
               return(ncol);
          else {
               fprintf(stderr,"what color number ? \n");
               exit(0);
          }
     }
     else if (isalpha(*pc)) {
          if (*pc == 'l' || *pc == 'L') {       /* light ? */
               intens = 8;
               pc++;
          }
          switch(*pc) {
               case 'b':
               case 'B':
                    if (*(pc + 1) == 'r' || *(pc + 1) == 'R')
                         return(3);     /* brown */
                    else switch(*(pc + 2)) {
                         case 'a':       /* black */
                         case 'A':
                              return(0 | intens);
                         case 'u':       /* blue */
                         case 'U':
                              return(4 | intens);
                    };
               case 'r':                       /* red */
               case 'R':
                    return(1 | intens);
               case 'g':                       /* green */
               case 'G':
                    return(2 | intens);
               case 'y':                       /* yellow */
               case 'Y':
                    return(11);
               case 'm':        /* magenta */
               case 'M':
               case 'v':
               case 'V':
                    return(5 | intens);
               case 'c':                       /* cyan */
               case 'C':
                    return(6 | intens);
               case 'w':                       /* white */
               case 'W':
                    return(7 | intens);
               default:
                    fprintf(stderr,"what colour? \n");
                    exit(0);
          } /* end switch (*pc) */
     } /* end else if (alpha) */
 } /* end subroutine colnum */
 /* end color.c */


 COLOR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\COLOR\COLOR.C

 /****************************************************************************
  *
  *        COLOR.C         Max R. D�rsteler    12-7-83
  *
  *        Set screen colors in text mode.
  *
  ****************************************************************************
  */
 #include <stdio.h>
 #include <ctype.h>
 #include <graph.h>

 #include "graph.h"

 main(argc, argv)
         int argc;
         char **argv;
 {
         int charcol = 11;
         int scrncol = 4;
         int bordcol = 4;
         int i;

         if (argc < 4) {
               printf("Usage: color [forground ] [background] [border]\n");
               printf(" e.g.:\ncolor 11 4 12\n");
               printf(" or:\ncolor yellow blue lblue\n");
               printf(" or:\ncolor y blu lblu\n\n");
               printf(" DOS 2.0 color indices: [0..15], background [0..7]\n\n"
               printf(" Available color names: \n");
               printf("  bla<ck> <l>r<ed> <l>g<reen> y<ellow> br<own>\n");
               printf("  <l>blu<e> <l>m<agenta> <l>c<yan> <l>w<hite>\n\n");
               printf(" <x> : x=optional character");
               printf("  l  : light (for foreground & border color only!)\n");
               exit(0);
         }
         argv++;
         charcol = colnum(*argv++);
         scrncol = colnum(*argv++);
         bordcol = colnum(*argv);
         i = bordcol & 7;
         switch (i) {                /* Translation from DOS 2.0 color table *
                 case 1:         /* to IBM color card color table */
                         i = 4;
                         break;
                 case 3:
                         i = 6;
                         break;
                 case 4:
                         i = 1;
                         break;
                 case 6:
                         i = 3;
                         break;
                 default:
                         i = bordcol;
                         break;
         };
         bordcol = i | (bordcol & 8);
         _setvideomode(TEXTMOD);
         outp(COLREG, bordcol | 0x10);
         if (charcol & 8) printf("\033[1m\n");
         else printf("\033[0m\n");
         charcol = (charcol & 7) + 30;
         scrncol = (scrncol & 7) + 40;
         printf("\033[%d;%dm\n", charcol, scrncol);
         cls();
 }
 /*----------------------------------------------------------------------*/

 colnum(colname)
         char *colname;
 {
         int ncol;
         int intens;
         char *pc;

         pc = colname;
         intens = 0;
         if (isdigit(*pc)) {
                 if(sscanf(pc,"%d", &ncol) == 1)
                         return(ncol);
                 else {
                         fprintf(stderr,"what color number ? \n");
                         exit(0);
                 }
         }
         else if (isalpha(*pc)) {
                 if (*pc == 'l' || *pc == 'L') {       /* light ? */
                         intens = 8;
                         pc++;
                 }
                 switch(*pc) {
                         case 'b':
                         case 'B':
                                 if (*(pc + 1) == 'r' || *(pc + 1) == 'R')
                                         return(3);        /* brown */
                                 else switch(*(pc + 2)) {
                                         case 'a':       /* black */
                                         case 'A':
                                                 return(0 | intens);
                                         case 'u':       /* blue */
                                         case 'U':
                                                 return(4 | intens);
                                 };
                         case 'r':                       /* red */
                         case 'R':
                                 return(1 | intens);
                         case 'g':                       /* green */
                         case 'G':
                                 return(2 | intens);
                         case 'y':                       /* yellow */
                         case 'Y':
                                 return(11);
                         case 'm':        /* magenta */
                         case 'M':
                         case 'v':
                         case 'V':
                                 return(5 | intens);
                         case 'c':                       /* cyan */
                         case 'C':
                                 return(6 | intens);
                         case 'w':                       /* white */
                         case 'W':
                                 return(7 | intens);
                         default:
                                 fprintf(stderr,"what colour? \n");
                                 exit(0);
                 } /* end switch (*pc) */
         } /* end else if (alpha) */
 } /* end subroutine colnum */
 /* end color.c */


 COM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\COM.C

 /* SDB - expression compiler
     syntax:
         <expr>          ::= <lor> <EOS>
         <lor>           ::= <land> { '|' <land> }
         <land>          ::= <relat> { '&' <relat> }
         <relat>         ::= <primary> { <relop> <primary> }
         <primary>       ::= <factor> | <unop> <unary>
         <factor>        ::= <number> | <string> | '(' <query> ')'
         <number>        ::= <digit> | <number> <digit>
         <string>        ::= '"' <chars> '"'
         <chars>         ::= nil | <chars> <character>
         <relop>         ::= '=' | '<>' | '<' | '>' | '<=' | '>='
         <unop>          ::= '+' | '-' | '~'
 */

 #include "sdbio.h"

 extern int dbv_token;
 extern char dbv_tstring[];
 extern int dbv_tvalue;

 extern int db_xand();
 extern int db_xor();
 extern int db_xnot();
 extern int db_xlss();
 extern int db_xleq();
 extern int db_xeql();
 extern int db_xgeq();
 extern int db_xgtr();
 extern int db_xneq();
 extern int db_xpush();
 extern int db_xstop();

 static union codecell code[CODEMAX+1];
 static int cndx;
 static struct sel *selptr;

 /* compile - compile a boolean expression */
 int db_compile(slptr)
   struct sel *slptr;
 {
     int result,i;
     union codecell *cptr;
 #ifdef Lattice
     int (*dns)();  /*dns*/
 #endif

     /* save the selection structure pointer */
     selptr = slptr;

     /* initialize the code array index */
     cndx = 0;

     /* parse the boolean expression */
     if (!expr(&result)) {
         code[cndx++].c_operator = db_xstop;
         freelit(code);
         return (FALSE);
     }

     /* terminate the code */
     code[cndx++].c_operator = db_xstop;

     /* allocate space for the code array */
     if ((cptr = malloc(sizeof(union codecell) * cndx)) == NULL) {
         freelit(code);
         return (FALSE);
     }

     /* store the code into the code array */
     slptr->sl_where = cptr;
     for (i = 0; i < cndx; i++) {
         (*cptr++).c_operator = code[i].c_operator;
 #ifndef Lattice
         if (code[i].c_operator == db_xpush)
 #else
         if ( code[i].c_operator == (dns=db_xpush) )  /*dns*/
 #endif
             (*cptr++).c_operand = code[++i].c_operand;
     }

     /* return successfully */
     return (TRUE);
 }

 /* db_fcode - free a code array */
 db_fcode(slptr)
   struct sel *slptr;
 {
     /* make sure there is a where clause */
     if (slptr->sl_where == NULL)
         return;

     /* free the literals */
     freelit(slptr->sl_where);

     /* free the code array */
     free(slptr->sl_where);
 }

 /* operator - insert an operator into the code array */
 static int operator(opr)
   int (*opr)();
 {
     /* insert the operator */
     if (cndx < CODEMAX)
         code[cndx++].c_operator = opr;
     else
         return (db_ferror(CDSIZE));

     /* return successfully */
     return (TRUE);
 }

 /* operand - insert an operand into the code array */
 static int operand(opr)
   struct operand *opr;
 {
     /* insert the push operator */
     if (!operator(db_xpush))
         return (FALSE);

     /* insert the operand */
     if (cndx < CODEMAX)
         code[cndx++].c_operand = opr;
     else
         return (db_ferror(CDSIZE));

     /* return successfully */
     return (TRUE);
 }

 /* expr - compile an expression */
 static int expr(result)
   int *result;
 {
     int lval,rval;

     if (!land(&lval))
         return (FALSE);
     while (db_token() == '|') {
         db_ntoken();
         if (!land(&rval))
             return (FALSE);
         if (!operator(db_xor))
             return (FALSE);
     }
     *result = lval;
     return (TRUE);
 }

 static int land(result)
   int *result;
 {
     int lval,rval;

     if (!relat(&lval))
         return (FALSE);
     while (db_token() == '&') {
         db_ntoken();
         if (!relat(&rval))
             return (FALSE);
         if (!operator(db_xand))
             return (FALSE);
     }
     *result = lval;
     return (TRUE);
 }

 static int relat(result)
   int *result;
 {
     int lval,rval;
     int tkn;

     if (!primary(&lval))
         return (FALSE);
     while (db_token() <= LSS && dbv_token >= GTR) {
         tkn = db_ntoken();
         if (!primary(&rval))
             return (FALSE);
         switch (tkn) {
         case LSS:
                 if (!operator(db_xlss))
                     return (FALSE);
                 break;
         case LEQ:
                 if (!operator(db_xleq))
                     return (FALSE);
                 break;
         case EQL:
                 if (!operator(db_xeql))
                     return (FALSE);
                 break;
         case NEQ:
                 if (!operator(db_xneq))
                     return (FALSE);
                 break;
         case GEQ:
                 if (!operator(db_xgeq))
                    return (FALSE);
                 break;
         case GTR:
                 if (!operator(db_xgtr))
                     return (FALSE);
                 break;
         }
     }
     *result = lval;
     return (TRUE);
 }

 static int primary(result)
   int *result;
 {
     int val;
     int tkn;

     if (db_token() == '~') {
         tkn = db_ntoken();
         if (!primary(&val))
             return (FALSE);
         switch (tkn) {
         case '~':
                 if (!operator(db_xnot))
                     return (FALSE);
                 break;
         }
     }
     else
         if (!factor(&val))
             return (FALSE);
     *result = val;
     return (TRUE);
 }

 static int factor(result)
   int *result;
 {
     int val;

     if (db_token() == '(') {
         db_ntoken();
         if (!expr(&val))
             return (FALSE);
         if (db_token() != ')')
             return (db_ferror(SYNTAX));
         db_ntoken();
     }
     else
         if (!get_operand(&val))
             return (FALSE);
     *result = val;
     return (TRUE);
 }

 /* get_operand - get an operand (number, string, or attribute) */
 static int get_operand(result)
   int *result;
 {
     /* determine operand type */
     if (db_ntoken() == NUMBER)
         return (get_number(result));
     else if (dbv_token == ID)
         return (get_attr(result));
     else if (dbv_token == STRING)
         return (get_string(result));
     else
         return (db_ferror(SYNTAX));
 }

 /* get_attr - get an attribute argument */
 static int get_attr(result)
   int *result;
 {
     struct operand *opr;
     char rname[RNSIZE+1],aname[ANSIZE+1];
     char *aptr; int atype,alen;

     /* save the attribute name */
     stccpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;

     /* check for a "." indicating a qualified attribute name */
     if (db_token() == '.') {
         db_ntoken();

         /* the previous ID was really a relation name */
         strcpy(rname,aname);

         /* check for the real attribute name */
         if (db_ntoken() != ID)
             return (db_ferror(SYNTAX));

         /* save the attribute name */
         stccpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;

         /* lookup the attribute name */
         if (!db_sattr(selptr,rname,aname,&atype,&aptr,&alen))
             return (FALSE);
     }
     else
         if (!db_sattr(selptr,NULL,aname,&atype,&aptr,&alen))
             return (FALSE);

     /* get a new operand structure */
     if ((opr = malloc(sizeof(struct operand))) == NULL)
         return (db_ferror(INSMEM));

     /* initialize the new operand structure */
     opr->o_type = ATTR;
     opr->o_value.ov_char.ovc_type = atype;
     opr->o_value.ov_char.ovc_string = aptr;
     opr->o_value.ov_char.ovc_length = alen;

     /* insert the operand into the code array */
     if (!operand(opr)) {
         free(opr);
         return (FALSE);
     }

     /* store operand type */
     *result = atype;

     /* return successfully */
     return (TRUE);
 }

 /* get_number - get a numeric operand */
 static int get_number(result)
   int *result;
 {
     struct operand *opr;

     /* get a new operand structure */
     if ((opr = malloc(sizeof(struct operand))) == NULL)
         return (db_ferror(INSMEM));

     /* initialize the new operand structure */
     opr->o_type = LITERAL;
     if ((opr->o_value.ov_char.ovc_string =
                 malloc(strlen(dbv_tstring)+1)) == NULL) {
         free(opr);
         return (db_ferror(INSMEM));
     }
     opr->o_value.ov_char.ovc_type = TNUM;
     strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
     opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);

     /* insert the operand into the code array */
     if (!operand(opr)) {
         free(opr->o_value.ov_char.ovc_string); free(opr);
         return (FALSE);
     }

     /* operand type is number */
     *result = TNUM;

     /* return successfully */
     return (TRUE);
 }

 /* get_string - get a string operand */
 static int get_string(result)
   int *result;
 {
     struct operand *opr;

     /* get a new operand structure */
     if ((opr = malloc(sizeof(struct operand))) == NULL)
         return (db_ferror(INSMEM));

     /* initialize the new operand structure */
     opr->o_type = LITERAL;
     if ((opr->o_value.ov_char.ovc_string =
                 malloc(strlen(dbv_tstring)+1)) == NULL) {
         free(opr);
         return (db_ferror(INSMEM));
     }
     opr->o_value.ov_char.ovc_type = TCHAR;
     strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
     opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);

     /* insert the operand into the code array */
     if (!operand(opr)) {
         free(opr->o_value.ov_char.ovc_string); free(opr);
         return (FALSE);
     }

     /* operand type is character */
     *result = TCHAR;

     /* return successfully */
     return (TRUE);
 }

 /* freelit - free the literals in a code array */
 static freelit(cptr)
   union codecell *cptr;
 {
 #ifdef Lattice
     int (*dns)();  /*dns*/
     for (; (*cptr).c_operator != (dns=db_xstop); cptr++)  /*dns*/
         if ((*cptr).c_operator == (dns=db_xpush) )        /*dns*/
 #else
     for (; (*cptr).c_operator != db_xstop; cptr++)
         if ((*cptr).c_operator == db_xpush )
 #endif
             if ((*++cptr).c_operand->o_type == LITERAL)
                 free((*cptr).c_operand->o_value.ov_char.ovc_string);
 }



 COMCHECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\COMCHECK.C

 /* COMCHECK.C - From page 581 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. Checks for matching comment       */
 /* symbols, reports first occurrence of mispairing.             */
 /****************************************************************/

 #include "stdio.h"
 #define TRUE 1
 #define FALSE 0

 main(argc, argv)
 int argc;
 char *argv[];
 {
 FILE *fptr;
 char ch;
 int slash = FALSE;
 int star = FALSE;
 int comments = 0;
 int line = 1;
 void chcount(), finalcnt();

    if(argc != 2)  {
       printf("\nType \"comcheck filename\".");
       exit();
    }
    if((fptr = fopen(argv[1], "r")) == NULL)  {
       printf("\nCan't open file %s", argv[1]);
       exit();
    }
    while((ch = getc(fptr)) != EOF)  {
       switch(ch)  {
          case '*':
             star = TRUE;
             if(slash == TRUE)  {          /*found start comment?*/
                comments++;
                if(comments > 1)  {        /*unmatched start comm*/
                   printf("\nUnexpected start comment, line %d", line);
                   exit();
                }
                slash = star = FALSE;      /*reset flags*/
             }
             break;
          case '/':
             slash = TRUE;
             if(star == TRUE)  {           /*found end comment ?*/
                comments--;
                if(comments < 0)  {        /*unmatched end comment*/
                   printf("\nUnexpected end comment, line %d", line);
                   exit();
                }
                slash = star = FALSE;
             }
             break;
          case '\n':
             line++;
          default:
             slash = star = FALSE;
       }  /*end switch*/
    }  /*end while*/
    fclose(fptr);
    if(comments > 0)           /*open comment at EOF*/
       printf("\nUnmatched open comment.");
 }



 COMM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\COMM.C



 COMM.C.1




 /* NOTE: this code is indented using tabs set every 4 columns, not 8. */


 /*

  * Rudimentary communication program; written in C with I/O

  * routines in assembler, using "#asm" construct in DeSmet C.

  */


 #define TRUE 1

 #define FALSE 0

 #define NULL 0


 #define comm_stat head!=tail


 int head=0,

         tail=0;


 char comm_buffer[8192];


 main()

 {

         char commget();


         int c,

                 echo=FALSE,

                 verbose=FALSE;


         initcomm();


         goto inside;

         while((c=my_ci())<256) /* alt's and function keys are >=256 */

         {

                 commput(c);

                 if(echo)

                         my_co(c);

 inside:        while(my_stat()==0)

                         if(comm_stat)

                                 if(is_nice(c=commget()))

                                         my_co(c);

                                 else

                                         if(verbose)

                                         {

                                                 my_co('^');

                                                 my_co(127&(c+'@'));

                                         }

         }

         switch(c>>8) /* process function key */

         {

                 case '\060': /* b        send break        */

                         make_break();

                         my_puts("** break **\n");

                         break;

                 case '\022': /* e        echo toggle        */

                         echo = !echo;

                         if(echo)

                                 my_puts("** echo on **\n");

                         else

                                 my_puts("** echo off **\n");

                         break;

                 case '\020': /* q        quit                */

                         my_puts("** returning to DOS **\n");

                         goto byebye;

                 case '\057': /* v        verbose                */

                         verbose = !verbose;

                         if(verbose)

                                 my_puts("** verbose on **\n");

                         else

                                 my_puts("** verbose off **\n");

                         break;

         }

         goto inside;


 byebye:

         killcomm();

 }


 initcomm()

 {

 #asm


 ; initialize communication port,

 ; and install interrupt handler


 ; save dseg for interrupt handler

         mov                ax,ds

         mov                cs:dssave,ax


 ; set int vector to my handler

         push        ds

         xor                ax,ax

         mov                ds,ax

         mov                [30h],offset handler

         mov                ax,cs

         mov                [32h],ax

         pop                ds


 ; assert DTR, RTS, and OUT2

         mov                dx,3fch

         mov                al,11

         out                dx,al


 ; enable interrupts for data ready

         mov                dx,3f9h

         mov                al,1

         out                dx,al


 ; clear any outstanding int

         mov                dx,3f8h

         in                al,dx


 ; enable interrupts

         sti


 ; enable IRQ4 on 8259A

         in                al,21h

         and                al,0efh

         out                21h,al


 ; and return

         jmp                init_finis


 dssave:        dw 0


 handler:

         push        ds

         push        ax

         push        dx

         push        bx


 ; restore appropriate dseg

         mov                ax,cs:dssave

         mov                ds,ax


 ; grab the byte from comm port

         mov                dx,3f8h

         in                al,dx


 ; put it in the buffer

         mov                bx,tail_

         mov                comm_buffer_[bx],al


 ; tail=tail+1 (mod 8192)

         inc                bx

         cmp                bx,8192

         jl                handler_around

         xor                bx,bx


 handler_around:

         mov                tail_,bx


 ; tell the 8259A EOI

         mov                dx,20h

         mov                al,32

         out                dx,al


         pop                bx

         pop                dx

         pop                ax

         pop                ds


 ; reenable interrupts

         sti


         iret


 init_finis:

 #

 }


 commput(c)

 int c;

 {

 #asm

 ; put the character out the port

         mov                dx,3f8h

         mov                ax,[bp+4]

         out                dx,al

 #

 }


 char commget()

 {

         char temp;


                 temp=comm_buffer[head++];

                 head%=8192;

                 return(temp);

 }


 killcomm()

 {

 #asm

 ; disconnect the interrupt handler

         in                al,21h

         or                al,10h

         out                21h,al

 #

 }


 make_break()

 {

 #asm

 ; set bit on LCR

         mov                dx,3fbh

         in                al,dx

         push        ax

         or                al,40h

         out                dx,al


 ; wait a wee bit (~200 ms)

         mov                bx,8

 outer:

         mov                cx,7000

 tight:

         loop        tight

         dec                bx

         jnz                outer


 ; and turn break back off

         pop                ax

         out                dx,al

 #

 }


 is_nice(c) /* true for those characters that "should" be received */

 char c;

 {

         c&=127;

         if(c>=' ' && c<='~')        /* printable */

                 return(TRUE);

         if(c>6 && c<11)                        /* BEL, BS, HT, LF */

                 return(TRUE);

         if(c==13 || c==27)                /* CR, ESC */

                 return(TRUE);

         return(FALSE);

 }


 my_puts(s) /* puts, using my_co() */

 char *s;

 {

         while(*s)

         {

                 if(*s=='\n')

                         my_co('\r');

                 my_co(*(s++));

         }

 }


 my_co(c) /* character output, smaller and faster than DeSmet's,

                         using DOS function call 2.00 */

 char c;

 {

 #asm

         mov                ah,2

         mov                dx,[bp+4]

         int                21h

 #

 }


 my_stat() /* true if character is ready from keyboard */

 {

 #asm

         mov                ah,1

         int                16h

         jz                stat_no_char

         mov                ax,1

         jmp                stat_finis


 stat_no_char:

         xor                ax,ax


 stat_finis:

 #

 }


 my_ci() /* get character from keyboard, using BIOS function call */

 {

 #asm

         xor                ah,ah

         int                16h

         or                al,al

         jz                my_ci_finis

         xor                ah,ah


 my_ci_finis:

 #

 }

 -----------------------------------------------------------------------------

 The termcap for DOS 2.00 with ansi device driver follows:

 -----------------------------------------------------------------------------

 pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\

         :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\

         :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\

         :pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt:

 pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\

         :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\

         :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\

         :pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt:

 -----------------------------------------------------------------------------

 and that's it! Enjoy. I place this in the public domain, and would appreciate

 feedback. Improvements and bug reports especially desired. If the code is too

 cryptic or uncommented, feel free to send questions to:

                                         Bennett Todd

                                         ...{decvax,ihnp4,akgua}!mcnc!ecsvax!b



 COMMEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\COMMEN.C

 /*
  * Bob Denny          28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */
 #include <lex.h>

 extern int yyline;

 comment(mat)
 char *mat;
 {
         register c;
         register char *cp;
         int lno;

         lno = yyline;
         c = 1;
         for (cp = mat; *cp && c>=0;) {
                 if ((c = lexchar())=='\n')
                         yyline++;
                 if (c!=*cp++)
                         cp = mat;
         }
         if (c < 0) {
                 yyline = lno;
                 lexerror("End of file in comment");
         }
 }


 COMMENTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\COMMENTS.C

        /* This is a comment ignored by the compiler */

 main() /* This is another comment ignored by the compiler */
 {
    printf("We are looking at how comments are "); /* A comment is
                                                      allowed to be
                                                      continued on
                                                      another line */
    printf("used in C.\n");
 }
      /* One more comment for effect */


 COMMSUPP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\COMMSUPP\COMMSUPP.C

 /*

  commsupp.c    - communications support for DeSmet C

  Tom Poindexter- March, 1984

  routines:

   init_com     - initialize comm port, interrupts, baud, data, parity, stop
   uninit_com   - disable interrupts, flushes buffer
   send_brk     - send break signal
   set_xoff     - enable XON, XOFF protocol
   recd_xoff    - return true if XOFF received
   sent_xoff    - return true if XOFF sent
   inp_cnt      - returns the number of unread bytes in receive buffer
   inp_char     - return one byte from buffer
   inp_strn     - transfer n bytes from buffer to string
   outp_char    - send one byte
   outp_strn    - send n bytes of a string, up to end of string
   com_stat     - return line status (high byte) and modem status (low byte)
   on_com       - specify a routine to execute when a byte is received

  internal routines:
   -in commsupp.c-
   port_chk     - validate the port number (C88)

   -in commasm.a-
   int_c_handlr - interrupt driven port read, com1:, store in buffer (ASM88)
   int_b_handlr - interrupt driven port read, com2:, store in buffer (ASM88)
   sysint       - call a system routine (ASM88)
   inb          - input byte from hardware port (ASM88)
   outb         - output byte to hardware port (ASM88)
   cli          - clear interrupts (ASM88)
   sti          - set interrupts   (ASM88)

  standard DeSmet C library functions called:

   _lmove     - block move outside C data
   _move      - block move within C data
   _showcs    - get code segment
   _showds    - get data segment
   malloc     - allocate memory


 */

 /* global parm data for two com ports */

 struct
  {
   int  port_base;
   char *buff_addr;
   int  buff_len;
   char *buff_head;
   char *buff_tail;
   int  buff_cnt;
   int  x_state;
   int  x_recd;
   int  x_sent;
   int  org_int_off;
   int  org_int_seg;
   int  (*on_com_rtn)();
  }
  _com_parms[2];


 /* global defines */
 #define FALSE     0
 #define TRUE      1
 #define ERROR     -1

 /* defines for 8250 serial controller */
 #define DATAPORT  0
 #define INT_REG   1
 #define INT_ID    2
 #define LCTL_REG  3
 #define MDM_REG   4
 #define LCTL_STAT 5
 #define MDM_STAT  6
 #define LSB_BAUD  0
 #define MSB_BAUD  1
 #define DLAB      0x80
 #define DLAB_OFF  0x7f
 #define MDM_BRK   0x40
 #define PAR_NONE  0x00
 #define PAR_EVEN  0x18
 #define PAR_ODD   0x08
 #define PAR_STICK 0x20
 #define DATA_RDY  0x01
 #define OUT2_DR   0x0b
 #define BREAK_ON  0x40
 #define THRE      0x20
 /* count to wait for THRE */
 #define TIME      0xffff

 /* defines for break request */
 #define TIME_OF_DAY 0x1a
 #define HALF_SEC  9

 /* baud rate divisor constants */
 #define B110      1047
 #define B150      768
 #define B300      384
 #define B450      256
 #define B600      192
 #define B1200     96
 #define B2400     48
 #define B4800     24
 #define B9600     12
 /* defines to mask baud divisors MSB and LSB */
 #define MASK_LSB  0xff00
 #define MASK_MSB  0x00ff

 /* defines for 8259 interrupt controller */
 #define C8259_1   0x21
 #define C8259_3   0x20
 #define ENBL_IRQ4 0xef
 #define DIS_IRQ4  0x10
 #define ENBL_IRQ3 0xf7
 #define DIS_IRQ3  0x08
 #define EOI_IRQ4  0x64
 #define EOI_IRQ3  0x63
 #define IRQ4_VEC  0x0c
 #define IRQ3_VEC  0x0b

 /* defines for data areas */
 #define SYS_VEC   0x0
 #define ROM_DATA  0x40
 #define INT_DSEG  2


 /****************************************************************************

 /* init_com

       parms:
             port: 1 = com1:, 2 = com2:
             baud: 110, 150, 300, 450, 600, 1200, 2400, 4800, 9600
           parity: 0 = none, 1 = odd, 2 = even, 3 = mark, 4 = space
             data: 5, 6, 7, 8
             stop: 1, 2
         buff_len: length desired for receive buffer ( 0 < buff_len < 32767 )

    returns:
       ERROR = com port not available or invalid parm value
        TRUE = ok

 */

 init_com (port, baud, parity, data, stop, buff_len)

 int port;
 int baud;
 int parity;
 int data;
 int stop;
 int buff_len;

 {

   int divisor;
   int buff_addr;
   int line_reg;
   int data_seg;
   int code_seg;
   int int_c_handlr();
   int int_b_handlr();
   int int_handlr_addr;

   /*  get C program segment registers */

   data_seg = _showds ();
   code_seg = _showcs ();

   /* validate port; store port address */

   if (port < 1 || port > 2)
     return (ERROR);
   else
    {
     port--;
     _lmove (2,port*2,ROM_DATA,&_com_parms[port].port_base,data_seg);
     if (_com_parms[port].port_base == 0)
       return (ERROR);
    }


   /* validate baud; set baud divisors */

   switch (baud)
    {
     case  110:
       divisor =  B110;
       break;
     case  150:
       divisor =  B150;
       break;
     case  300:
       divisor =  B300;
       break;
     case  450:
       divisor =  B450;
       break;
     case  600:
       divisor =  B600;
       break;
     case 1200:
       divisor = B1200;
       break;
     case 2400:
       divisor = B2400;
       break;
     case 4800:
       divisor = B4800;
       break;
     case 9600:
       divisor = B9600;
       break;
     default:
       return (ERROR);
    }


   /* validate parity; set line control register parity */

   switch (parity)
    {
      case 0:  /* none  */
        line_reg = PAR_NONE;
        break;
      case 1:  /* odd   */
        line_reg = PAR_ODD;
        break;
      case 2:  /* even  */
        line_reg = PAR_EVEN;
        break;
      case 3:  /* mark  */
        line_reg = PAR_ODD | PAR_STICK;
        break;
      case 4:  /* space */
        line_reg = PAR_EVEN | PAR_STICK;
        break;
      default:
        return (ERROR);
     }


   /* validate data len; set line control register data length */

   if (data < 5 || data > 8)
     return (ERROR);
   else
     line_reg |= data - 5;


   /* validate stop bits; set line control register stop bits */

   if (stop < 1 || stop > 2)
     return (ERROR);
   else
     line_reg |=  (stop - 1) << 2;


   /* validate buffer len; allocate memory, set initial settings */

   if (buff_len < 1 || buff_len > 32767)
     return (ERROR);
   else
    {
     _com_parms[port].buff_addr  = malloc (buff_len);
     if (_com_parms[port].buff_addr == 0)
       return (ERROR);
     _com_parms[port].buff_len   = buff_len;
     _com_parms[port].buff_head  = _com_parms[port].buff_addr;
     _com_parms[port].buff_tail  = _com_parms[port].buff_addr;
     _com_parms[port].buff_cnt   = 0;
     _com_parms[port].x_state    = FALSE;
     _com_parms[port].x_recd     = FALSE;
     _com_parms[port].x_sent     = FALSE;
     _com_parms[port].on_com_rtn = FALSE;
    }

   /* set 8250 baud divisor */

   outb (_com_parms[port].port_base + LCTL_REG, DLAB);
   outb (_com_parms[port].port_base + LSB_BAUD, divisor & MASK_MSB);
   outb (_com_parms[port].port_base + MSB_BAUD, (divisor & MASK_LSB) >> 8);


   /* set 8250 line control register */

   outb (_com_parms[port].port_base + LCTL_REG, line_reg);


   /* set IRQx interrupt to point to interrupt handler ;
          enable 8259 IRQx interrupts;
          enable 8250 data ready interrupts;
          enable 8250 OUT2 ,DTR, RTS */

   cli ();

   if (port == 0)
    {
     /* IRQ4, com1: */
     _lmove (2,IRQ4_VEC*4,  SYS_VEC,&_com_parms[port].org_int_off,data_seg);
     _lmove (2,IRQ4_VEC*4+2,SYS_VEC,&_com_parms[port].org_int_seg,data_seg);

     int_handlr_addr = (unsigned) &int_c_handlr;
     _lmove (2,&int_handlr_addr,data_seg,IRQ4_VEC*4,  SYS_VEC);
     _lmove (2,&code_seg,       data_seg,IRQ4_VEC*4+2,SYS_VEC);

     outb (C8259_1, (inb (C8259_1) & ENBL_IRQ4));

    }

   else
    {
     /* IRQ3, com2: */
     _lmove (2,IRQ3_VEC*4,  SYS_VEC,&_com_parms[port].org_int_off,data_seg);
     _lmove (2,IRQ3_VEC*4+2,SYS_VEC,&_com_parms[port].org_int_seg,data_seg);

     int_handlr_addr = (unsigned) &int_b_handlr;
     _lmove (2,&int_handlr_addr,data_seg,IRQ3_VEC*4,  SYS_VEC);
     _lmove (2,&code_seg,       data_seg,IRQ3_VEC*4+2,SYS_VEC);

     outb (C8259_1, (inb (C8259_1) & ENBL_IRQ3));

    }

   /* save C data segment in interrupt handlr routine */
   int_handlr_addr = (unsigned) &int_c_handlr + INT_DSEG;
   _lmove (2,&data_seg,data_seg,int_handlr_addr,code_seg);


   outb (_com_parms[port].port_base + INT_REG, DATA_RDY);

   outb (_com_parms[port].port_base + MDM_REG, OUT2_DR);

   sti ();

   return (TRUE);
   /* end of init_com */

 }


 /****************************************************************************

 /* port_chk

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       ERROR = com port never initialized, invalid port number
       TRUE = ok

 */

 port_chk(port)

 int port;

 {
   if (port < 1 || port > 2)
     return (ERROR);

   if (_com_parms[--port].port_base == FALSE)
     return (ERROR);

   return (TRUE);

 }


 /****************************************************************************

 /* uninit_com

       parms:
             port: 1 = com1:, 2 = com2:
          lv_open: TRUE = leave comm open (DTR true), FALSE = turn off

    returns:
       ERROR = com port never initialized
       TRUE = ok

 */


 uninit_com (port,lv_open)

 int port;
 int lv_open;

 {
   int data_seg;
   int code_seg;

   /*  get C program segment registers */

   data_seg = _showds ();
   code_seg = _showcs ();


   /* validate port; reset interrupts ; disable data ready, out2 */

   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   cli ();

   /* restore original interrupt vectors, mask 8259 interrupt handling */
   if (port == 0)
    {
     /* IRQ4, com1: */
     _lmove (2,&_com_parms[port].org_int_off,data_seg,IRQ4_VEC*4,  SYS_VEC);
     _lmove (2,&_com_parms[port].org_int_seg,data_seg,IRQ4_VEC*4+2,SYS_VEC);

     outb (C8259_1, inb (C8259_1) | DIS_IRQ4);
    }
   else
    {
     /* IRQ3, com2: */
     _lmove (2,&_com_parms[port].org_int_off,data_seg,IRQ3_VEC*4,  SYS_VEC);
     _lmove (2,&_com_parms[port].org_int_seg,data_seg,IRQ3_VEC*4+2,SYS_VEC);

     outb (C8259_1, inb (C8259_1) | DIS_IRQ3);
    }

   /* disable 8250 interrupt generation */
   outb (_com_parms[port].port_base + LCTL_REG,
          inb (_com_parms[port].port_base + LCTL_REG) & DLAB_OFF);
   outb (_com_parms[port].port_base + INT_REG, FALSE);

   /* leave serial port enabled if requested, else drop DTR */
   if (!lv_open)
     outb (_com_parms[port].port_base + MDM_REG, FALSE);

   sti ();

   /* free buffer storage */
   free (_com_parms[port].buff_addr);
   _com_parms[port].port_base = FALSE;

   return (TRUE);
   /* end of uninit_com */

 }


 /****************************************************************************


 /* send_brk

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       ERROR = com port never initialized or bad parm
       TRUE = ok

 */


 send_brk (port)

 int port;

 {

   int line_reg;
   int ticks;
   int count;

   struct
    {int ax,bx,cx,dx,si,di,ds,es;} r;

   r.ax = r.bx = r.cx = r.dx = r.si = r.di = r.ds = r.es = 0;

   /* validate port; send break (1/2 second) */

   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   /* get current line reg */
   line_reg = inb (_com_parms[port].port_base + LCTL_REG);

   /* set break */
   outb (_com_parms[port].port_base + LCTL_REG, line_reg | BREAK_ON);

   /* delay for 1/2 second using time-of-day counter */
   /* dx returned is the lower 16 bits of the counter */
   for (count = 0; count < HALF_SEC; count++)
    {
     sysint (TIME_OF_DAY,&r,&r);
     ticks = r.dx;
     while (ticks == r.dx)
       sysint (TIME_OF_DAY,&r,&r);
    }

   /* reset line reg */
   outb (_com_parms[port].port_base + LCTL_REG, line_reg);


   return (TRUE);
   /* end of send_brk */

 }


 /****************************************************************************

 /* set_xoff

       parms:
             port: 1 = com1:, 2 = com2:
            state: TRUE = XON/XOFF enabled, FALSE = XON/XOFF disabled

    returns:
       ERROR = com port never initialized
       TRUE = ok

 */


 set_xoff (port,state)

 int port;
 int state;

 {

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   /* set XON/XOFF state */
   _com_parms[port].x_state = state;

   /* reset flags */
   _com_parms[port].x_recd = FALSE;
   _com_parms[port].x_sent = FALSE;

   return (TRUE);
   /* end of set_xoff */

 }


 /****************************************************************************

 /* recd_xoff

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       ERROR = com port never initialized
       FALSE = XOFF never received
       TRUE = XOFF received

 */


 recd_xoff (port)

 int port;

 {
   int state;

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;


   state = _com_parms[port].x_recd;

   _com_parms[port].x_recd = FALSE;

   return (state);
   /* end of recd_xoff */

 }


 /****************************************************************************

 /* sent_xoff

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       ERROR = com port never initialized
       FALSE = XOFF never sent
       TRUE = XOFF sent

 */


 sent_xoff (port)

 int port;

 {
   int state;

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;


   state = _com_parms[port].x_sent;

   _com_parms[port].x_sent = FALSE;

   return (state);
   /* end of sent_xoff */

 }


 /****************************************************************************

 /* inp_cnt

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       ERROR = com port never initialized, bad parm
       other = number of bytes in buffer

 */


 inp_cnt (port)

 int port;

 {

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;


   return (_com_parms[port].buff_cnt);
   /* end of inp_cnt */

 }



 /****************************************************************************

 /* inp_char

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       ERROR = com port never initialized, bad parm, nothing to get
       other = next (FIFO) char in buffer

 */


 inp_char (port)

 int port;

 {
   char c;

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;


   if (_com_parms[port].buff_cnt)
    {
     _com_parms[port].buff_cnt--;
     c = *_com_parms[port].buff_tail;

     if ( (unsigned int) ++_com_parms[port].buff_tail >=
          (unsigned int)   _com_parms[port].buff_addr +
          (unsigned int)   _com_parms[port].buff_len   )
       _com_parms[port].buff_tail = _com_parms[port].buff_addr;

     return (c);
    }
   else
    return (ERROR);

   /* end of inp_char */

 }



 /****************************************************************************

 /* inp_strn

       parms:
             port: 1 = com1:, 2 = com2:
             addr: address of string to put incoming chars
              cnt: number of bytes to transfer (up to actual number in buffer)

    returns:
       ERROR = com port never initialized, bad parm, nothing to get
       other = the actual number of chars transferred

 */


 inp_strn (port,addr,cnt)

 int port;
 char *addr;
 int cnt;

 {
   int rest_buff;

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   /* max transfer = buff count */
   if (cnt > _com_parms[port].buff_cnt)
     cnt = _com_parms[port].buff_cnt;

   if (cnt)
    {
     rest_buff = ( (unsigned int) _com_parms[port].buff_addr +
                   (unsigned int) _com_parms[port].buff_len ) -
                 (unsigned int) _com_parms[port].buff_tail;

     if (cnt > rest_buff)
      {
        /* circle around buffer */
        _move(rest_buff,_com_parms[port].buff_tail,addr);
        _move(cnt - rest_buff,_com_parms[port].buff_addr,addr + rest_buff);
        _com_parms[port].buff_tail =
              (unsigned int) _com_parms[port].buff_addr + (cnt - rest_buff);
       }
     else
       {
        _move(cnt,_com_parms[port].buff_tail,addr);
        _com_parms[port].buff_tail += cnt;
        if (cnt == rest_buff)
          _com_parms[port].buff_tail = _com_parms[port].buff_addr;
       }

     _com_parms[port].buff_cnt -= cnt;
     return (cnt);

    }

   else
    return (ERROR);

   /* end of inp_strn */

 }



 /****************************************************************************

 /* outp_char

       parms:
             port: 1 = com1:, 2 = com2:
                c: the character to send

    returns:
       TRUE = OK
       ERROR = timeout condition


 */


 outp_char (port,c)

 int  port;
 char c;

 {

   unsigned int time_out;

   /* validate port; return state */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   /* wait for THRE (transmitter holding register empty) */

   for (time_out = TIME;
        (inb (_com_parms[port].port_base + LCTL_STAT) & THRE) == FALSE
           && time_out > 0;
        time_out--)
     ;

   if (time_out == 0)
     /* THRE timeout error */
     return (ERROR);


   /* everything ok, send it */

   outb (_com_parms[port].port_base + DATAPORT, c);

   return (TRUE);
   /* end of outp_char */

 }


 /****************************************************************************

 /* outp_strn

       parms:
             port: 1 = com1:, 2 = com2:
             addr: the string to send
              cnt: the maximum number of characters to send

    returns:
       TRUE = OK
       ERROR = timeout condition


 */


 outp_strn (port,addr,cnt)

 int  port;
 char addr[];
 int cnt;

 {
   int n;

   for (n = 0; n <= cnt && addr[n] != '\0'; n++)
     if (outp_char(port,addr[n]) == ERROR)
       return (ERROR);


   return (TRUE);
   /* end of outp_strn */

 }


 /****************************************************************************

 /* com_stat

       parms:
             port: 1 = com1:, 2 = com2:

    returns:
       line status (MSB) and modem status (LSB)
       ERROR = invalid com port, never initialized


 */


 com_stat (port)

 int  port;

 {
   int status;

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   status = inb (_com_parms[port].port_base + LCTL_STAT) << 8;

   status |= inb (_com_parms[port].port_base + MDM_STAT);

   return (status);
   /* end of com_stat */

 }


 /****************************************************************************

 /* on_com

       parms:
             port: 1 = com1:, 2 = com2:
              rtn: pointer to a C routine

    returns:
       TRUE = ok
       ERROR = invalid com port, never initialized


 */


 on_com (port,rtn)

 int  port;
 int  (*rtn)();

 {

   /* validate port */
   if (port_chk(port) == ERROR)
     return (ERROR);
   else
     port--;

   _com_parms[port].on_com_rtn = rtn;

   return (TRUE);
   /* end of on_com */

 }


 /****************************************************************************


 /* end of commsupp.c */



 COMMTERM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\COMMSUPP\COMMTERM.C

 /*
   commterm.c - a stupid communications program demonstrating the use of
                commsupp.c and commasm.a

   Tom Poindexter, March 1984

 */

 #include "commsupp.h"
 /* commsupp.h    - commsupp declares and defines */

 /*
   init_com   - initialize comm port, interrupts, baud, data, parity, stop, bu
   uninit_com - disable interrupts, flushes buffer
   send_brk   - send break signal
   set_xoff   - enable XON, XOFF protocol
   recd_xoff  - return true if XOFF received, reset recd_xoff flag
   sent_xoff  - return true if XOFF sent, reset sent_xoff flag
   inp_cnt    - returns the number of unread bytes in receive buffer
   inp_char   - return one byte from buffer
   inp_strn   - transfer n bytes from buffer to string
   outp_char  - send one byte
   outp_strn  - send n bytes of a string, up to end of string
   com_stat   - return line status (high byte) and modem status (low byte)
   on_com     - specify a routine to execute when a character is received
 */

 /* declare entry points to commsupp routines */

 int  init_com();   /* init_com(port,baud,parity,data,stop,buff_len); */
 int  uninit_com(); /* uninit_com(port,lv_open);  */
 int  send_brk();   /* send_brk(port);            */
 int  set_xoff();   /* set_xoff(port,xoff_state); */
 int  recd_xoff();  /* recd_xoff(port);           */
 int  sent_xoff();  /* sent_xoff(port);           */
 int  inp_cnt();    /* inp_cnt(port);             */
 int  inp_char();   /* inp_char(port);            */
 int  inp_strn();   /* inp_strn(port,&str,cnt);   */
 int  outp_char();  /* outp_char(port,c);         */
 int  outp_strn();  /* outp_strn(port,&str,cnt);  */
 int  com_stat();   /* com_stat(port);            */
 int  on_com();     /* on_com(port,routine);      */

 /* define for values returned by routines */
 #define ERROR     -1
 #define TRUE      1
 #define FALSE     0

 /* defines for parity (init_com) */
 #define PARITY_NONE  0
 #define PARITY_ODD   1
 #define PARITY_EVEN  2
 #define PARITY_MARK  3
 #define PARITY_SPACE 4

 /* defines for comm errors - mask using com_stat value */
 #define OVER_RUN    0x0200
 #define PARITY_ERR  0x0400
 #define FRAME_ERR   0x0800
 #define BREAK_IND   0x1000

 /* defines for modem conditions - mask using com_stat value */
 #define CLEAR_SEND  0x0010
 #define DATASET_RDY 0x0020
 #define RING_IND    0x0040
 #define CARRIER     0x0080

 /* end of commsupp.h */


 ALT_H  0x2300  /* help  */
 ALT_B  0x3000  /* break */
 ALT_X  0x2d00  /* exit  */
 ALT_E  0x1200  /* echo  */
 ALT_S  0x1f00  /* pause */
 ALT_Q  0x1000  /* resume*/
 PGUP   0x4900  /* upload */
 PGDN   0x5100  /* download */
 #define NUL    0
 #define BS     8
 #define LF     10
 #define CR     13
 #define XON    17
 #define XOFF   19
 #define DELAY  5000

 int max;
 unsigned total,min_sp;

 #include <stdio.h>

 main ()

 {
   int port,baud,parity,data,stop,buff_len;
   int c,e,x,i,n,x_state,counter;
   int bytecount();
   FILE f;
   char strn[128];


   puts("\n\n\ncommterm\n");

   puts("\nComm port (1 or 2)? ");
   gets(strn);
   port = atoi(strn);

   puts("\nBaud rate? ");
   gets(strn);
   baud = atoi(strn);

   puts("\nParity (0=none, 1=odd, 2=even, 3=mark, 4=space)? ");
   gets(strn);
   parity = atoi(strn);

   puts("\nData length (5 - 8)? ");
   gets(strn);
   data = atoi(strn);

   puts("\nStop bits (1 or 2)? ");
   gets(strn);
   stop = atoi(strn);

   puts("\nBuffer length? ");
   gets(strn);
   buff_len = atoi(strn);

   puts("\nXON/XOFF enabled (y or n)? ");
   gets(strn);
   x_state = (tolower(strn[0]) == 'y') ? TRUE : FALSE;

   if (init_com(port,baud,parity,data,stop,buff_len) == ERROR)
    {
     putchar(7);
     puts("\n\nSorry, you screwed up somewhere along the line.\n\n");
     exit();
    }
   else
    {
     set_xoff(port,x_state);
     on_com(port,bytecount);
    }

   puts("\nEnter modem initialization string: ");
   gets(strn);
   outp_strn(port,strn,128);
   outp_char(port,CR);

   puts("\n\nPress ALT-H for help on special keys.\n\n");
   total = max = c = e = n = 0;
   min_sp = 0xffff;

   while (c != ALT_X)
    {

     termin(port,1);

     if (com_stat(port) & BREAK_IND)
       puts("\n\n**B R E A K**\n\n");

     c = key_in();
     if (c > 0)
      {
       switch (c)
        {
         case ALT_H:
          puts("\n\ncommterm help\n\n");
          puts("press.........to\n");
          puts("Alt-E.........echo key strokes\n");
          puts("Alt-B.........send break signal\n");
          puts("Alt-H.........help on keys\n");
          puts("Alt-X.........exit program\n");
          puts("Alt-S.........pause (XOFF)\n");
          puts("Alt-Q.........resume (XON)\n");
          puts("PgUp..........upload a file\n");
          puts("PgDn..........download to a file\n");
          puts("\n\ncontinue...\n\n");
          break;

         case ALT_B:
          send_brk(port);
          break;

         case ALT_E:
          e = !e;
          break;

         case PGUP:
          puts("\n\nUpload what file? ");
          gets(strn);
          f=fopen(strn,"r");
          if (f == FALSE)
           {
            puts("\nERROR - file ");
            puts(strn);
            puts(" not found.....\n");
           }
          else
           {
            puts("\nUploading ");
            puts(strn);
            puts(", press PgUp key to abort.....\n\n");
            while (fgets(strn,128,f) != FALSE && key_in() != PGUP)
             {
              termin(port,0);
              for (i = 0; i < 128 && strn[i] != '\0'; i++)
                {
                 if (x_state && recd_xoff(port) == TRUE)
                  {
                   puts("\nXOFF received.  Waiting for XON or press any key to
                   while (inp_char(port) != XON && csts() == FALSE)
                     ;
                  }
                 outp_char(port,strn[i]);
                 termin(port,0);
                }
               outp_char(port,CR);
             }
            fclose(f);
            puts("\nUpload complete.\n\n");
           }
          break;

         case PGDN:
          puts("\n\nDownload to what file? ");
          gets(strn);
          if ((f=fopen(strn,"r")) == FALSE)
           {
            if (strlen(strn) > 0)
             {
              puts("\nCreating ");
              puts(strn);
              puts("\n\n");
              f = creat(strn);
             }
            else
              f = 0;
           }
          else
           {
            fclose(f);
            puts("\nFile ");
            puts(strn);
            puts(" exists, press 'e' to erase file or 'a' to add to it: ");
            i = getchar();
            if (tolower(i) == 'e')
              f = creat(strn);
            else
              f = fopen(strn,"a");
           }
          puts("\n\nDownloading, press PgDn again to close file.\n\n");
          counter = DELAY;
          while (((c=key_in()) != PGDN) && (f != 0))
           {
            if (c != 0)
              conout(c,e,port);
            if (inp_cnt(port) > max) max = inp_cnt(port);
            i = inp_cnt(port);
            i = (i <= 127) ? i : 127;
            inp_strn(port,strn,i);
            strn[i] = '\0';
            fputs(strn,f);
            for (n = 0; strn[n] != '\0'; n++)
              switch (strn[n])
               {
                case BS:
                 putchar('\b');
                 break;
                case CR:
                 putchar(CR);
                 putchar(LF);
                 break;
                case LF:
                 break;
                case NUL:
                 break;
                default:
                 putchar(strn[n]);
               }
            if (x_state && sent_xoff(port) == TRUE)
             {
              puts("\nXOFF sent. No test delay till buffer empties to 25%.\n")
              outp_char(port,XOFF);
              counter = 0;
             }
            if (x_state && counter == 0)
             {
              if (inp_cnt(port) < (buff_len * 1/4))
                {
                 puts("\nXON sent\n");
                 outp_char(port,XON);
                 counter = DELAY;
                }
             }
            else
              if (x_state)
                /* dummy loop to test the XON/XOFF flow control */
                for(i=0; i<counter; i++)
                  ;
           }
          fclose(f);
          puts("\nDownload complete.\n\n");

          break;

         default:
          conout(c,e,port);
          break;
         }
       }
    }

   puts("\n\nExiting..\n");
   puts("\nLeave port initialized (y or n)? ");
   gets(strn);
   x = (tolower(strn[0]) == 'y') ? TRUE : FALSE;

   uninit_com(port,x);

   printf("\nThe buffer high water mark reached %d of a buffer length of %d",
          max,buff_len);

   printf("\nThe total number of characters received was %u",
          total);

   printf("\nThe smallest stack space available was %u",
          min_sp);

 }  /* end of commterm.c */

 bytecount () /* on comm routine */
 {
  int m;

  m = _showsp();
  if (m < min_sp)
    min_sp = m;
  total++;
 }

 conout(c,e,port) /* send a character over the serial port, optionally echo */
 int c,e,port;
 {
   switch (c)
    {
     case ALT_S:
      /* DOS sometimes eats ^S as a pause (ala Ctrl-NumLock) */
      outp_char(port,XOFF);
      break;

     case ALT_Q:
      outp_char(port,XON);
      break;

     case CR:
      if (e)
       {
        putchar(CR);
        putchar(LF);
       }
      outp_char(port,CR);
      break;

     case BS:
      if (e)
        putchar ('\b');
      outp_char(port,BS);
      break;

     default:
      if (c < 128)
       {
        if (e)
         putchar(c);
        outp_char(port,c);
       }
      break;
     }
 }



 termin(port,x)  /* get characters from the serial port and print it */
 int port,x;
 {
   int c;

     if (x)
       if (recd_xoff(port))
         puts("<<XOFF>>");

     if (inp_cnt(port) > max) max = inp_cnt(port);
     while (inp_cnt(port))
      {
       c = inp_char(port);
       switch (c)
        {
         case NUL:
          break;

         case CR:
          putchar(CR);
          putchar(LF);
          break;

         case LF:
          break;

         case BS:
          putchar('\b');
          break;

         default:
          putchar(c);
          break;
        }
      }

 }  /* end of termin */

 /* ********************************************************************** */

 /* key_in.c

       direct read of keyboard, including special keys.

       written to replace scr_in() in pcio.a because scr_in()
       filters most special keys, and returns char.
       key_in, returns an int value.  see tech reference manual
       or basic manual for values of different key combinations.

       key_in() returns: 0 = no key pressed
                         other = key and/or special key code

                         when value < 128 : normal ASCII
                         when value >=128 : special key


     calls: sysint

 */

 #define KEYBOARD 0x16
 #define GET_KEY  0x0000
 #define KEY_STAT 0x0100
 #define ZERO     0x0040
 /* ZERO is a mask for the 8088 flag register zero bit */

 key_in ()

 {
  struct {int ax,bx,cx,dx,si,di,ds,es;} r;

  r.ax = r.bx = r.cx = r.dx = r.si = r.di = r.ds = r.es = 0;

  r.ax = KEY_STAT;

  if ( !(sysint (KEYBOARD, &r, &r) & ZERO))
   {
    r.ax = GET_KEY;
    sysint (KEYBOARD, &r, &r);
    return ( (r.ax & 0x00ff) ? (r.ax & 0x00ff) : (r.ax) );
   }
  else
   return (0);

 } /* end of key_in.c */



 COMPARE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\BEYONDC\COMPARE.C

 /*
 ** Copyright (c) 1987,  Tom Steppe.  All rights reserved.
 **
 ** This module compares two arrays of lines (representing
 ** files) and reports the sequences of consecutive matching
 ** lines between them using the "recursive longest matching
 ** sequence" algorithm.  This is useful for implementing a
 ** file comparison utility.
 **
 ** Compiler:  Microsoft (R) C Compiler  Version 4.00
 */

 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
 #include <malloc.h>

 /* Boolean type and values. */
 typedef int     BOOLEAN;
 #define TRUE    1
 #define FALSE   0

 /* Minimum macro. */
 #define min(x, y)   (((x) <= (y)) ? (x) : (y))

 /* Value to indicate identical strings with strcmp. */
 #define ALIKE   0

 /* Result of hashing function for a line of text. */
 typedef unsigned int   HASH;

 /* Mask for number of bits in hash code.  (12 bits). */
 #define MASK   (unsigned int) 0x0FFF

 /* Number of possible hash codes. */
 #define HASHSIZ   (MASK + 1)

 /* Information about an entry in a hash table. */
 typedef struct tblentry
 {
     int   frst;   /* First line # with this hash code. */
     int   last;   /* Last line # with this hash code. */
 } TBLENTRY;

 /* Information about a line of text. */
 typedef struct lineinf
 {
     HASH   hash;    /* Hash code value. */
     int    nxtln;   /* Next line with same hash (or 0). */
 } LINEINF;

 /* Information about a file. */
 typedef struct fileinf
 {
     char       **txt;      /* Array of lines of text. */
     LINEINF    *line;      /* Array of line info structs. */
     TBLENTRY   *hashtbl;   /* Hash table. */
 } FILEINF;

 /* Function declarations. */
 BOOLEAN filcmp      (char **, int, char **, int, int);
 BOOLEAN get_inf     (char **, int, FILEINF *);
 HASH    calc_hash   (char *);
 void    fnd_seq     (FILEINF *, int, int,
                           FILEINF *, int, int, int);
 BOOLEAN chk_hashes  (LINEINF *, LINEINF *, int);
 int     cnt_matches (char **, char **, int);
 void    rpt_seq     (int, int, int);

 /***********************************************************
 ** compare compares two arrays of lines and reports the
 ** sequences of consecutive matching lines.  The zeroth
 ** element of each array is unused so that the index into
 ** the array is identical to the associated line number.
 **
 ** RETURNS:  TRUE if comparison succeeded.
 **           FALSE if not enough memory.
 ***********************************************************/

 BOOLEAN compare (a1, n1, a2, n2, lngval)

 char   **a1;     /* (I) Array of lines of text in #1. */
 int    n1;       /* (I) Number of lines in a1.
                         (Does not count 0th element.) */
 char   **a2;     /* (I) Array of lines of text in #2. */
 int    n2;       /* (I) Number of lines in a2.
                         (Does not count 0th element.) */
 int    lngval;   /* (I) "Long enough" value. */
 {
     FILEINF   f1;    /* File information for #1. */
     FILEINF   f2;    /* File information for #2. */
     BOOLEAN   rtn;   /* Return value. */

     /* Gather information for each file, then compare. */
     if (rtn =
         (get_inf (a1, n1, &f1) && get_inf (a2, n2, &f2)))
     {
         fnd_seq (&f1, 1, n1, &f2, 1, n2, lngval);
     }

     return (rtn);
 }

 /***********************************************************
 ** get_inf calculates hash codes and builds a hash table.
 **
 ** RETURNS:  TRUE if get_inf succeeded.
 **           FALSE if not enough memory.
 ***********************************************************/

 static BOOLEAN get_inf (a, n, f)

 char      **a;   /* (I) Array of lines of text. */
 int       n;     /* (I) Number of lines in a. */
 FILEINF   *f;    /* (O) File information. */
 {
     unsigned int   size;     /* Size of hash table. */
     register int   i;        /* Counter. */
     TBLENTRY       *entry;   /* Entry in hash table. */

     /* Assign the array of text. */
     f->txt = a;

     /* Allocate and initialize a hash table. */
     size = HASHSIZ * sizeof (TBLENTRY);
     if (f->hashtbl = (TBLENTRY *) malloc (size))
     {
         memset ((char *) f->hashtbl, '\0', size);
     }
     else
     {
         return (FALSE);
     }

     /* If there are any lines: */
     if (n > 0)
     {
         /* Allocate an array of line structures. */
         if (f->line = (LINEINF *)
                 malloc ((n + 1) * sizeof (LINEINF *)))
         {
             /* Loop through the lines. */
             for (i = 1; i <= n; i++)
             {
                 /* Calculate the hash code value. */
                 f->line[i].hash = calc_hash (f->txt[i]);

                 /* Locate the entry in the hash table. */
                 entry = f->hashtbl + f->line[i].hash;

                 /* Update the linked list of lines with */
                 /* the same hash code.                  */
                 f->line[entry->last].nxtln = i;
                 f->line[i].nxtln = 0;

                 /* Update the first and last line */
                 /* information in the hash table. */
                 if (entry->frst == 0)
                 {
                     entry->frst = i;
                 }
                 entry->last = i;
             }
         }
         else
         {
             return (FALSE);
         }
     }
     else
     {
        f->line = NULL;
     }

     return (TRUE);
 }

 /***********************************************************
 ** calc_hash calculates a hash code for a line of text.
 **
 ** RETURNS:  a hash code value.
 ***********************************************************/

 static HASH calc_hash (buf)

 char   *buf;   /* (I) Line of text. */
 {
     register unsigned int   chksum;   /* Checksum. */
     char                    *s;       /* Pointer. */
     HASH                    hash;     /* Hash code value. */

     /* Build up a checksum of the characters in the text. */
     for (chksum = 0, s = buf; *s; chksum ^= *s++)
     {
         ;
     }

     /* Combine the 7-bit checksum and as much of the */
     /* length as is possible.                        */
     hash = ((chksum & 0x7F) | ((s - buf) << 7)) & MASK;

     return (hash);
 }

 /***********************************************************
 ** Given starting and ending line numbers, fnd_seq finds a
 ** "good sequence" of lines within those ranges.  fnd_seq
 ** then recursively finds "good sequences" in the sections
 ** of lines above the "good sequence" and below it.
 ***********************************************************/

 static void fnd_seq (f1, beg1, end1, f2, beg2, end2, lngval)

 FILEINF   *f1;      /* (I) File information for #1. */
 int       beg1;     /* (I) First line # to compare in #1. */
 int       end1;     /* (I) Last line # to compare in #1. */
 FILEINF   *f2;      /* (I) File information for #2. */
 int       beg2;     /* (I) First line # to compare in #2. */
 int       end2;     /* (I) Last line # to compare in #2. */
 int       lngval;   /* (I) "Long enough" value. */
 {
     LINEINF      *line1;   /* Line information ptr in #1. */
     LINEINF      *line2;   /* Line information ptr in #2. */
     register int limit;    /* Looping limit. */
     int          ln1;      /* Line number in #1. */
     int          ln2;      /* Line number in #2. */
     register int ln;       /* Working line number. */
     BOOLEAN      go;       /* Continue to loop? */
     int          most;     /* Longest possible seq. */
     int          most1;    /* Longest possible due to #1. */
     int          most2;    /* Longest possible due to #2. */
     int          cnt;      /* Length of longest seq. */
     int          oldcnt;   /* Length of prev longest seq. */
     int          n;        /* Length of cur longest seq. */
     int          m1;       /* Line of longest seq. in #1. */
     int          m2;       /* Line of longest seq. in #2. */

     /* Initialize. */
     go    = TRUE;
     line1 = f1->line;
     line2 = f2->line;

     /* Initialize longest sequence information. */
     cnt    = 0;          /* Length of longest seq. */
     m1     = beg1 - 1;   /* Line # of longest seq. in #1. */
     m2     = beg2 - 1;   /* Line # of longest seq. in #2. */
     oldcnt = 0;          /* Length of prev longest seq. */

     /* Calculate maximum possible number of consecutive */
     /* lines that can match (based on line # ranges).   */
     most1 = end1 - beg1 + 1;
     most2 = end2 - beg2 + 1;

     /* Scan lines looking for a "good sequence".
     ** Compare lines in the following order of line numbers:
     **
     **                 (1, 1)
     **         (1, 2), (2, 1), (2, 2)
     ** (1, 3), (2, 3), (3, 1), (3, 2), (3, 3)
     ** etc.
     */
     for (ln1 = beg1, ln2 = beg2; TRUE; ln1++, ln2++)
     {
         if (ln2 <= end2 - cnt)
         /* There are enough lines left in #2 such that it */
         /* is possible to find a longer sequence.         */
         {
             /* Determine the limit in #1 that both       */
             /* enforces the order scheme and still makes */
             /* it possible to find a longer sequence.    */
             limit = min (ln1 - 1, end1 - cnt);

             /* Calculate first potential match in #1. */
             for (ln = f1->hashtbl[line2[ln2].hash].frst;
                     ln && ln < beg1; ln = line1[ln].nxtln)
             {
                ;
             }

             /* Loop through the lines in #1. */
             for (; ln && ln <= limit; ln = line1[ln].nxtln)
             {
                 if (line1[ln].hash == line2[ln2].hash &&
                         line1[ln + cnt].hash ==
                             line2[ln2 + cnt].hash &&
                         !(ln - m1 == ln2 - m2 &&
                         ln < m1 + cnt && m1 != beg1 - 1))
                 /* A candidate for a longer sequence has */
                 /* been located.  The current lines      */
                 /* match, the current lines + cnt match, */
                 /* and this sequence is not a subset of  */
                 /* the longest sequence so far.          */
                 {
                     /* Calculate most possible matches. */
                     most = min (end1 - ln + 1, most2);

                     /* First compare hash codes.  If the  */
                     /* number of matches exceeds the      */
                     /* longest sequence so far, then      */
                     /* compare the actual text.           */
                     if (chk_hashes (line1 + ln,
                                 line2 + ln2, cnt) &&
                             (n = cnt_matches (f1->txt + ln,
                                 f2->txt + ln2, most)) > cnt)
                     /* This is the longest seq. so far. */
                     {
                         /* Update longest sequence info. */
                         oldcnt = cnt;
                         cnt    = n;
                         m1     = ln;
                         m2     = ln2;

                         /* If it's long enough, end the */
                         /* search.                      */
                         if (cnt >= lngval)
                         {
                             break;
                         }

                         /* Update limit, using new count. */
                         limit = min (ln1 - 1, end1 - cnt);
                     }
                 }
             }

             /* If it's long enough, end the search. */
             if (cnt >= lngval)
             {
                 break;
             }
             most2--;
         }
         else
         {
             go = FALSE;   /* This file is exhausted. */
         }

         /* Repeat the process for the other file. */
         if (ln1 <= end1 - cnt)
         {
             limit = min (ln2, end2 - cnt);

             for (ln = f2->hashtbl[line1[ln1].hash].frst;
                     ln && ln < beg2; ln = line2[ln].nxtln)
             {
                ;
             }

             for (; ln && ln <= limit; ln = line2[ln].nxtln)
             {
                 if (line1[ln1].hash == line2[ln].hash &&
                         line1[ln1 + cnt].hash ==
                             line2[ln+ cnt].hash &&
                         !(ln1 - m1 == ln - m2 &&
                         ln1 < m1 + cnt && m2 != beg2 - 1))
                 {
                     most = min (end2 - ln + 1, most1);

                     if (chk_hashes (line1 + ln1,
                                 line2 + ln, cnt) &&
                             (n = cnt_matches (f1->txt + ln1,
                                 f2->txt + ln, most)) > cnt)
                     {
                         oldcnt = cnt;
                         cnt    = n;
                         m1     = ln1;
                         m2     = ln;

                         if (cnt >= lngval)
                         {
                             break;
                         }

                         limit = min (ln2, end2 - cnt);
                     }
                 }
             }

             if (cnt >= lngval)
             {
                 break;
             }
             most1--;
         }
         else if (!go)
         {
             break;   /* This file is exhausted, also. */
         }
     }

     /* If the longest sequence is shorter than the "long */
     /* enough" value, the "long enough" value can be     */
     /* adjusted for the rest of the comparison process.  */
     if (cnt < lngval)
     {
         lngval = cnt;
     }

     if (cnt >= 1)
     /* Longest sequence exceeds minimum necessary size. */
     {
         if (m1 != beg1 && m2 != beg2 && oldcnt > 0)
         /* There is still something worth comparing */
         /* previous to the sequence.                */
         {
             /* Use knowledge of the previous longest seq. */
             fnd_seq (f1, beg1, m1 - 1,
                     f2, beg2, m2 - 1, oldcnt);
         }

         /* Report the sequence. */
         rpt_seq (m1, m2, cnt);

         if (m1 + cnt - 1 != end1 && m2 + cnt - 1 != end2)
         /* There is still something worth comparing */
         /* subsequent to the sequence.              */
         {
             fnd_seq (f1, m1 + cnt, end1,
                     f2, m2 + cnt, end2, lngval);
         }
     }
 }

 /***********************************************************
 ** chk_hashes determines whether this sequence of matching
 ** hash codes is longer than cnt.  It knows that the first
 ** pair of hash codes is guaranteed to match.
 **
 ** RETURNS:  TRUE if this sequence is longer than cnt.
 **           FALSE if this sequence is not longer than cnt.
 ***********************************************************/

 static BOOLEAN chk_hashes (line1, line2, cnt)

 LINEINF        *line1;   /* (I) Line information for #1. */
 LINEINF        *line2;   /* (I) Line information for #2. */
 register int   cnt;      /* (I) Count to try to exceed. */
 {
     register int   n;   /* Count of consecutive matches. */

     for (n = 1; n <= cnt &&
         ((++line1)->hash == (++line2)->hash); n++)
     {
         ;
     }

     return (n > cnt);
 }

 /***********************************************************
 ** cnt_matches counts the number of consecutive matching
 ** lines of text.
 **
 ** RETURNS:  number of consecutive matching lines.
 ***********************************************************/

 static int cnt_matches (s1, s2, most)

 char         **s1;   /* (I) Starting line in file #1. */
 char         **s2;   /* (I) Starting line in file #2. */
 register int most;   /* (I) Most matching lines possible. */
 {
     register int   n;   /* Count of consecutive matches. */

     /* Count the consecutive matches. */
     for (n = 0; n < most && strcmp (*s1++, *s2++) == ALIKE;
             n++)
     {
         ;
     }

     return (n);
 }

 /***********************************************************
 ** rpt_seq reports a matching sequence of lines.
 ***********************************************************/

 static void rpt_seq (m1, m2, cnt)

 int   m1;    /* (I) Location of matching sequence in #1. */
 int   m2;    /* (I) Location of matching sequence in #2. */
 int   cnt;   /* (I) Number of lines in matching sequence. */
 {
     fprintf (stdout,
         "Matched %5d lines:  (%5d - %5d) and (%5d - %5d)\n",
          cnt, m1, m1 + cnt - 1, m2, m2 + cnt - 1);
 }


 COMPARES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\COMPARES.C

                                           /* Chapter 4 - Program 4 */
 main()  /* This file will illustrate logical compares */
 {
 int x = 11,y = 11,z = 11;
 char a = 40,b = 40,c = 40;
 float r = 12.987,s = 12.987,t = 12.987;

                          /* First group of compare statements */

    if (x == y) z = -13;   /* This will set z = -13 */
    if (x > z)  a = 'A';   /* This will set a = 65  */
    if (!(x > z)) a = 'B'; /* This will change nothing */
    if (b <= c) r = 0.0;   /* This will set r = 0.0 */
    if (r != s) t = c/2;   /* This will set t = 20  */

                          /* Second group of compare statements */

    if (x = (r != s)) z = 1000; /* This will set x = some positive
                                   number and z = 1000 */
    if (x = y) z = 222;   /* This sets x = y, and z = 222 */
    if (x != 0) z = 333;  /* This sets z = 333 */
    if (x) z = 444;       /* This sets z = 444 */

                          /* Third group of compare statements */

    x = y = z = 77;
    if ((x == y) && (x == 77)) z = 33; /* This sets z = 33 */
    if ((x > y) || (z > 12))   z = 22; /* This sets z = 22 */
    if (x && y && z) z = 11;           /* This sets z = 11 */
    if ((x = 1) && (y = 2) && (z = 3)) r = 12.00; /* This sets
                              x = 1, y = 2, z = 3, r = 12.00 */
    if ((x == 2) && (y = 3) && (z = 4)) r = 14.56; /* This doesn't
                              change anything */

                          /* Fourth group of compares */

    if (x == x); z = 27.345;  /* z always gets changed */
    if (x != x)  z = 27.345;  /* Nothing gets changed */
    if (x = 0)   z = 27.345;  /* This sets x = 0, z is unchanged */

 }


 COMTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\COMTEST.C

 /* COMTEST.C - From page 499 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. Program tests automatic command   */
 /* transmission to modem. Program works at 300 bpi. To work     */
 /* at 1200 with PC or XT, add the clscr() and putscr() func-    */
 /* tions from the SER1200.C program and change CONF to 0x83.    */
 /****************************************************************/

 "dos.h"              /*for union REGS */
 COM 1                 /*serial port no. (0 = COM1, 1 = COM2)*/
 CONF 0x43             /*300 bpi, no par, 1 stop, 8 bits*/
 RS232 0x14            /*RS232 serial port interrupt number*/
 DATAR 0x100           /*data ready bit in status word*/
 char *comstr = "AT Z\r";      /*modem reset command*/
 union REGS inregs, outregs;   /*for ROM BIOS calls*/

 main()
 {
 char ch, receive();
 int j, k;
 init();

    for(j = 0; (ch = *(comstr + j)) != '\0'; j++)  {     /*send command*/
       send(ch);               /*send char to modem*/
       while(!ready())         /*wait for echo*/
          ;
       ch = receive();         /*get echo*/
       putch(ch);
    }
    do  {
       while(!ready())         /*wait for response char*/
          ;
       ch = receive();         /*get response*/
       putch(ch);
    } while(ch != 'K');        /*quit on 'K' in "OK"*/
 }

 /* init() */      /* initialize serial port */
 init(conf)
 char conf;        /*addr of configuration code*/
 {
    inregs.h.ah = 0;        /* 'initialize port' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = CONF;     /*configuration*/
    int86(RS232, &inregs, &outregs);
 }

 /* send() */      /* send char to serial port */
 send(c)
 char c;
 {
    inregs.h.ah = 1;        /* 'send char' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = c;        /*character*/
    int86(RS232, &inregs, &outregs);
 }

 /* ready */    /* get serial port ready status */
 ready()
 {
    inregs.h.ah = 3;        /* 'get status' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.x.ax & DATAR);    /*return 'data ready' status*/
 }

 /* receive */     /* get character from serial port */
 char receive()
 {
    inregs.h.ah = 2;        /* 'receive char' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.h.al & 0x7F);     /*return character*/
                                     /* (AND off 8th bit*/
 }


 CONIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\WINDKW\CONIO.C


 /**
 *
 * This module defines the various console I/O functions.  They may
 * be called directly, using the names included here, or the header
 * file CONIO.H may be included so that more standard names may be
 * used.  This source module is provided so that users may customize
 * the console I/O functions, if desired.  Note that "cprintf" and
 * "cscanf" (included in MC.LIB) call the functions "putch", "getch",
 * and "ungetch".
 *
 **/
 BDOS_IN   7     /* input function for "getch" */
 BDOS_OUT  6     /* output function for "putch" */
 BDOS_CKS  11    /* check keyboard status for "kbhit" */
 BDOS_BKI  10    /* buffered keyboardd input for "cgets" */
 BDOS_PRT  9     /* print string for "cputs" */

 static char pushback;   /* character save for "ungetch" */

 /**
 *
 * name          getch -- get character from console
 *
 * synopsis      c = getch();
 *               char c;         input character
 *
 * description   This function obtains the next character typed at
 *               the console or, if one was pushed back via "ungetch",
 *               returns the previously pushed back character.
 *
 **/
 getch()
 {
 int c;

 if (pushback != '\0')
    {                    /* character was pushed back */
    c = pushback;
    pushback = '\0';
    return(c);
    }
 return(bdos(BDOS_IN, 0xFF) & 127);
 }
 /**
 *
 * name          putch -- send character directly to console
 *
 * synopsis      putch(c);
 *               char c;         character to be sent
 *
 * description   This function sends the specified character directly
 *               to the user's console.
 *
 **/
 putch(c)
 char c;
 {
 bdos(BDOS_OUT, c&127);
 return(c);
 }
 /**
 *
 * name          ungetch -- push character back to console
 *
 * synopsis      r = ungetch(c);
 *               int r;          return code
 *               char c;         character to be pushed back
 *
 * description   This function pushes the indicated character back
 *               on the console.  Only a single level of pushback is
 *               allowed.  The effect is to cause "getch" to return
 *               the pushed-back character the next time it is called.
 *
 * returns       r = -1 if character already pushed back
 *               = c otherwise
 *
 **/
 ungetch(c)
 char c;
 {

 if (pushback != '\0') return(-1);
 pushback = c;
 return(c);
 }
 /**
 *
 * name          cgets -- get string directly from console
 *
 * synopsis      p = cgets(s);
 *               char *p;        pointer to result string
 *               char *s;        string buffer (first byte = count)
 *
 * description   This function obtains a string directly from the
 *               user's console.  This version uses the buffered
 *               keyboard input function supported by the BDOS, so
 *               that all of the line editing capabilities are available.
 *               The first byte of "s" must be initialized to contain
 *               the number of bytes, minus two, in "s".  The string
 *               pointer returned is "s+2", which contains the first
 *               byte of input data.  Note that "s[1]" will contain
 *               the number of characters in the string.  The carriage
 *               return (which the user at the console must type to
 *               terminate the operation) is replaced by a null byte.
 *
 * returns       p = pointer to string received
 *
 **/
 char *cgets(s)
 char *s;
 {
 char *p;

 if (*s == 0) *s = 250;          /* do not allow zero byte count */
 bdos(BDOS_BKI, s);
 p = s+2;
 p[s[1]] = '\0';                 /* set terminating byte */
 return(p);
 }
 /**
 *
 * name          cputs -- send character string directly to console
 *
 * synopsis      cputs(s);
 *               char *s;        character string to be sent
 *
 * description   This function sends the specified string directly to
 *               the user's console.  The BDOS function for "print
 *               string" is used.  The function locates the terminating
 *               null byte, changes it to a '$' (the terminator
 *               required by the BDOS function), and then changes it
 *               back to the null byte before returning.  Thus, the
 *               string to be printed cannot itself contain a '$' and
 *               it cannot reside in read-only memory (ROM).
 *
 *               Note that a carriage return or linefeed is NOT appended
 *               by this function; they must be included in the string,
 *               if desired.
 *
 **/
 cputs(s)
 char *s;
 {
 char *p;

 for (p = s; *p != '\0'; p++) ;          /* find string terminator */
 *p = '$';
 bdos(BDOS_PRT, s);
 *p = '\0';
 return;
 }



 CONIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CONIO.C


 /**
 *
 * This module defines the various console I/O functions.  They may
 * be called directly, using the names included here, or the header
 * file CONIO.H may be included so that more standard names may be
 * used.  This source module is provided so that users may customize
 * the console I/O functions, if desired.  Note that "cprintf" and
 * "cscanf" (included in MC.LIB) call the functions "putch", "getch",
 * and "ungetch".
 *
 **/
 BDOS_IN   7        /* input function for "getch" */
 BDOS_OUT  6        /* output function for "putch" */
 BDOS_CKS  11        /* check keyboard status for "kbhit" */
 BDOS_BKI  10        /* buffered keyboardd input for "cgets" */
 BDOS_PRT  9        /* print string for "cputs" */

 static char pushback;        /* character save for "ungetch" */

 /**
 *
 * name                getch -- get character from console
 *
 * synopsis        c = getch();
 *                char c;                input character
 *
 * description        This function obtains the next character typed at
 *                the console or, if one was pushed back via "ungetch",
 *                returns the previously pushed back character.
 *
 **/
 getch()
 {
 int c;

 if (pushback != '\0')
    {                        /* character was pushed back */
    c = pushback;
    pushback = '\0';
    return(c);
    }
 return(bdos(BDOS_IN, 0xFF) & 127);
 }
 /**
 *
 * name                putch -- send character directly to console
 *
 * synopsis        putch(c);
 *                char c;                character to be sent
 *
 * description        This function sends the specified character directly
 *                to the user's console.
 *
 **/
 putch(c)
 char c;
 {
 bdos(BDOS_OUT, c&127);
 return(c);
 }
 /**
 *
 * name                ungetch -- push character back to console
 *
 * synopsis        r = ungetch(c);
 *                int r;                return code
 *                char c;                character to be pushed back
 *
 * description        This function pushes the indicated character back
 *                on the console.  Only a single level of pushback is
 *                allowed.  The effect is to cause "getch" to return
 *                the pushed-back character the next time it is called.
 *
 * returns        r = -1 if character already pushed back
 *                = c otherwise
 *
 **/
 ungetch(c)
 char c;
 {

 if (pushback != '\0') return(-1);
 pushback = c;
 return(c);
 }
 /**
 *
 * name                cgets -- get string directly from console
 *
 * synopsis        p = cgets(s);
 *                char *p;        pointer to result string
 *                char *s;        string buffer (first byte = count)
 *
 * description        This function obtains a string directly from the
 *                user's console.  This version uses the buffered
 *                keyboard input function supported by the BDOS, so
 *                that all of the line editing capabilities are available.
 *                The first byte of "s" must be initialized to contain
 *                the number of bytes, minus two, in "s".  The string
 *                pointer returned is "s+2", which contains the first
 *                byte of input data.  Note that "s[1]" will contain
 *                the number of characters in the string.  The carriage
 *                return (which the user at the console must type to
 *                terminate the operation) is replaced by a null byte.
 *
 * returns        p = pointer to string received
 *
 **/
 char *cgets(s)
 char *s;
 {
 char *p;

 if (*s == 0) *s = 250;                /* do not allow zero byte count */
 bdos(BDOS_BKI, s);
 p = s+2;
 p[s[1]] = '\0';                        /* set terminating byte */
 return(p);
 }
 /**
 *
 * name                cputs -- send character string directly to console
 *
 * synopsis        cputs(s);
 *                char *s;        character string to be sent
 *
 * description        This function sends the specified string directly to
 *                the user's console.  The BDOS function for "print
 *                string" is used.  The function locates the terminating
 *                null byte, changes it to a '$' (the terminator
 *                required by the BDOS function), and then changes it
 *                back to the null byte before returning.  Thus, the
 *                string to be printed cannot itself contain a '$' and
 *                it cannot reside in read-only memory (ROM).
 *
 *                Note that a carriage return or linefeed is NOT appended
 *                by this function; they must be included in the string,
 *                if desired.
 *
 **/
 cputs(s)
 char *s;
 {
 char *p;

 for (p = s; *p != '\0'; p++) ;                /* find string terminator */
 *p = '$';
 bdos(BDOS_PRT, s);
 *p = '\0';
 return;
 }


 CONTCUR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MIKES30C\CONTCUR.C

 /**************************************************************************
    These routines are very useful in doing the job of cursor control for
    Microsoft C 3.0.  You must #include <dos.h>  for these to work.

           Mike's "C" Board   619-722-8724
 **************************************************************************/


 gotoxy(row, col)  /* Position cursor at x,y on screen */
 int        row, col;
 {
     union REGS REG;

     REG.h.ah = 02;
     REG.h.bh = 00;
     REG.h.dh = row;
     REG.h.dl = col;
     int86(0x10, &REG, &REG);
 }


 getxy(hold) /* Get cursor coordinate and attribute */
 int        *hold;
 {
     union REGS REG;

     REG.h.ah = 03;
     REG.h.bh = 00;
     int86(0x10, &REG, &REG);
     hold[0] = REG.h.dh;
     hold[1] = REG.h.dl;
     hold[2] = REG.h.ch;
     hold[3] = REG.h.cl;
 }


 restorxy(hold)  /* Restore cursor gotten above */
 int        *hold;
 {
     union REGS REG;

     gotoxy(hold[0], hold[1]);
     REG.h.ah = 01;
     REG.h.bh = 00;
     REG.h.ch = hold[2];
     REG.h.cl = hold[3];
     int86(0x10, &REG, &REG);

 }


 get_mode()   /* Check for Monocrome or graphics  */
 {
     union REGS REG;

     REG.h.ah = 15;
     REG.h.bh = 00;
     REG.h.ch = 0;
     REG.h.cl = 0;
     int86(0x10, &REG, &REG);

     return(REG.h.al);
 }


 del_cur()  /* Make cursor disappear */
 {
     union REGS REG;

     REG.h.ah = 01;
     REG.h.bh = 00;
     REG.h.ch = 0x26;
     REG.h.cl = 7;
     int86(0x10, &REG, &REG);
 }


 restor_cur()  /* Put cursor back on screen checking for adapter */
 {
     union REGS REG;
     unsigned        st, en;

     if (get_mode() == 7)       /* Monocrone adapter */
         st = 0x0d, en = 14;
     else
         st = 0x06, en = 7;     /* Color graphics adapter */

     REG.h.ah = 01;
     REG.h.bh = 00;
     REG.h.ch = st;
     REG.h.cl = en;
     int86(0x10, &REG, &REG);


 }




 CONVERT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUTILS\CONVERT.C

 /*
                 AUTHOR          Jon Wesener
                 DATE            7 / 19 / 85
                 PURPOSE           These routines are used for conversions
                                 between integers and strings.
 */

 /*
         ATOI converts a string of specified base to an integer
          err= atoi(string, &number, base);
         RETURNS:        0= Error        1= Success
 */

 atoi(str,num,base)
 char    *str;
 unsigned     *num,base;
 {
         int     digit;          /* holds value of ASCII converted character *

         *num= 0;
         while (*str)
         {
                 if ( (*str >= '0') && (*str <= '9') )
                         digit= *(str++) - '0';

                 else if ( (*str >= 'A') && (*str <= 'Z') )
                         digit= *(str++) - 'A' + 10;

                 else if ( (*str >= 'a') && (*str <= 'z') )
                         digit= *(str++) - 'a' + 10;

                 else return(0);         /* digit was unrecognized */

                 if (digit < base)
                         *num= *num * base + digit;
                 else return(0);         /* digit was invalid in base */
         }
         return(1);
 }

 /*
         ITOA converts an integer to a string of specified base
          itoa(string, number, base);
         RETURNS:        nothing
 */

 itoa(str,num,base)
 char    *str;
 unsigned     num, base;
 {
         int     digit;
         char    temp[30], *ptr;

         ptr=temp + 29;
         *ptr= '\0';
         while (num)
         {
                 digit= num % base;      /* get last character */
                 *(--ptr)=  (digit < 10)? digit+'0' :digit+'A'- 10;
                 num= num / base;
         }
         strcpy(str,(*ptr)?ptr:"0");
 }


 COPY2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\COPY2.C

 /* COPY2.C - From page 467 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. This does the same as DOS,s       */
 /* COPY command.                                                */
 /****************************************************************/

 "fcntl.h"            /*needed for oflags*/
 "types.h"            /*needed for stat.h*/
 "stat.h"             /*needed for pmode*/
 #define BUFSIZ 4096
 char buff[BUFSIZ];

 main(argc, argv)
 int argc;
 char *argv[];
 {
 int inhandle, outhandle, bytes;

    if(argc != 3) {
       printf("\nFormat: A>copy2 source.xxx dest.xxx");
       exit();
    }
    if ((inhandle = open(argv[1], O_RDONLY | O_BINARY)) < 0) {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    if ((outhandle = open(argv[2],
          O_CREAT | O_WRONLY | O_BINARY, S_IWRITE)) < 0) {
       printf("\nCan't open file %s.", argv[2]);
       exit();
    }
    while((bytes = read(inhandle, buff, BUFSIZ)) > 0)
       write(outhandle, buff, bytes);
    close(inhandle);
    close(outhandle);
 }




 COSH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\COSH.C

 /* 1.0  05-16-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 217-238.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define LNv        0.69316101074218750000
 #define Vm2        0.24999308500451499336
 #define Vov2m1        0.13830277879601902638e-4

 /************************************************************************/
         double
 cosh(x)                                /* return hyperbolic cosine of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double y, w, z;

         if ((y = ABS(x)) > 1.0)
         {        w = y - LNv;
                 if (w > LOGINFINITY)
                 {        errno = ERANGE;
                         return INFINITY;
                 }
                 z = exp(w);
                 if (w < PRECISION)
                         z += Vm2 / z;
                 z += Vov2m1 * z;
         }
         else
         {        z = exp(y);
                 z = ldexp(z,-1) + 0.5 / z;
         }
         return z;
 }


 CPCN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CCOMP\CPCN.C

 /* ### cpcn-1 */
 /************************************************/
 /*                                                */
 /*                small-c:PC compiler                */
 /*                                                */
 /*                  by Ron Cain                        */
 /*        modified by CAPROCK SYSTEMS for IBM PC        */
 /*                                                */
 /************************************************/


 #define BANNER  "* * *  Small-C:PC  V1.1  * * *"


 #define VERSION "PC-DOS Version N: June, 1982"


 #define AUTHOR "By Ron Cain, Modified by CAPROCK SYSTEMS for IBM PC"


 /*        Define system dependent parameters        */


 /*        Stand-alone definitions                        */


 #define NULL 0
 #define eol 13


 /*        UNIX definitions (if not stand-alone)        */


 /* #include <stdio.h>        */
 /* #define eol 10        */


 /*        Define the symbol table parameters        */


 #define        symsiz        14
 #define        symtbsz        5040
 #define numglbs 300
 #define        startglb symtab
 #define        endglb        startglb+numglbs*symsiz
 #define        startloc endglb+symsiz
 #define        endloc        symtab+symtbsz-symsiz


 /*        Define symbol table entry format        */


 #define        name        0
 #define        ident        9
 #define        type        10
 #define        storage        11
 #define        offset        12


 /*        System wide name size (for symbols)        */


 #define        namesize 9
 #define namemax  8


 /*        Define data for external symbols        */

 #define extblsz 2000
 #define startextrn exttab
 #define endextrn exttab+extblsz-namesize-1

 /* Possible types of exttab entries */
 /* Stored in the byte following zero terminating the name */

 #define rtsfunc 1
 #define userfunc 2
 #define statref 3


 /*        Define possible entries for "ident"        */


 #define        variable 1
 #define        array        2
 #define        pointer        3
 #define        function 4


 /*        Define possible entries for "type"        */


 #define        cchar        1
 #define        cint        2


 /*        Define possible entries for "storage"        */


 #define        statik        1
 #define        stkloc        2


 /*        Define the "while" statement queue        */


 #define        wqtabsz        100
 #define        wqsiz        4
 #define        wqmax        wq+wqtabsz-wqsiz


 /*        Define entry offsets in while queue        */


 #define        wqsym        0
 #define        wqsp        1
 #define        wqloop        2
 #define        wqlab        3


 /*        Define the literal pool                        */


 #define        litabsz        3000
 #define        litmax        litabsz-1


 /*        Define the input line                        */


 #define        linesize 80
 #define        linemax        linesize-1
 #define        mpmax        linemax


 /*        Define the macro (define) pool                */


 #define        macqsize 1000
 #define        macmax        macqsize-1


 /*        Define statement types (tokens)                */


 #define        stif        1
 #define        stwhile        2
 #define        streturn 3
 #define        stbreak        4
 #define        stcont        5
 #define        stasm        6
 #define        stexp        7


 /* Define how to carve up a name too long for the assembler */


 #define asmpref        7
 #define asmsuff        7


 /*        Now reserve some storage words                */


 char        exttab[extblsz];        /* external symbols */
 char        *extptr;                /* pointer to next available entry */


 char        symtab[symtbsz];        /* symbol table */
 char        *glbptr,*locptr;                /* ptrs to next entries */


 int        wq[wqtabsz];                /* while queue */
 int        *wqptr;                        /* ptr to next entry */


 char        litq[litabsz];                /* literal pool */
 int        litptr;                        /* ptr to next entry */


 char        macq[macqsize];                /* macro string buffer */
 int        macptr;                        /* and its index */


 char        line[linesize];                /* parsing buffer */
 char        mline[linesize];        /* temp macro buffer */
 int        lptr,mptr;                /* ptrs into each */


 /*        Misc storage        */


 int        nxtlab,                /* next avail label # */
         litlab,                /* label # assigned to literal pool */
         cextern,        /* collecting external names flag */
         Zsp,                /* compiler relative stk ptr */
         argstk,                /* function arg sp */
         ncmp,                /* # open compound statements */
         errcnt,                /* # errors in compilation */
         errstop,        /* stop on error                        gtf 7/17/80 *
         eof,                /* set non-zero on final input eof */
         input,                /* iob # for input file */
         output,                /* iob # for output file (if any) */
         input2,                /* iob # for "include" file */
         ctext,                /* non-zero to intermix c-source */
         cmode,                /* non-zero while parsing c-code */
                         /* zero when passing assembly code */
         lastst,                /* last executed statement type */
         saveout,        /* holds output ptr when diverted to console
                         /*                                        gtf 7/16/80
         fnstart,        /* line# of start of current fn.        gtf 7/2/80 */
         lineno,                /* line# in current file                gtf 7/
         infunc,                /* "inside function" flag                gtf 7
         savestart,        /* copy of fnstart "        "                gtf 7/
         saveline,        /* copy of lineno  "        "                gtf 7/1
         saveinfn;        /* copy of infunc  "        "                gtf 7/1


 char   *currfn,                /* ptr to symtab entry for current fn.
        *savecurr;        /* copy of currfn for #include                gtf 7/
 char        quote[2];        /* literal string for '"' */
 char        *cptr;                /* work ptr to any char buffer */
 int        *iptr;                /* work ptr to any int buffer */
 /*        >>>>> start cc1 <<<<<<                */


 /*                                        */
 /*        Compiler begins execution here        */
 /*                                        */
 main()
 {
         hello();        /* greet user */
         see();                /* determine options */
         litlab=1;
         openin();        /* first file to process */
         while (input!=0)        /* process user files till he quits */
                 {
                 extptr=startextrn;        /* clear external symbols */
                 glbptr=startglb;        /* clear global symbols */
                 locptr=startloc;        /* clear local symbols */
                 wqptr=wq;                /* clear while queue */
                 macptr=                /* clear the macro pool */
                 litptr=                /* clear literal pool */
                   Zsp =                /* stack ptr (relative) */
                 errcnt=                /* no errors */
                 eof=                /* not end-of-file yet */
                 input2=                /* no include file */
                 saveout=        /* no diverted output */
                 ncmp=                /* no open compound states */
                 lastst=                /* no last statement yet */
                 cextern=        /* no externs yet */
                 fnstart=        /* current "function" started at line 0 gtf 7
                 lineno=                /* no lines read from file
                 infunc=                /* not in function now
                 quote[1]=
                 0;                /*  ...all set to zero.... */
                 quote[0]='"';                /* fake a quote literal */
                 currfn=NULL;        /* no function yet
                 cmode=nxtlab=1;        /* enable preprocessing and reset labe
                 openout();
                 header();
                 parse();
                 if (ncmp) error("missing closing bracket");
                 extdump();
                 dumpublics();
                 trailer();
                 closeout();
                 errorsummary();
                 openin();
                 }
 }
 /* ### cpcn-2 */
 /*                                        */
 /*        Abort compilation                */
 /*                gtf 7/17/80                */
 abort()
 {
         if(input2)
                 endinclude();
         if(input)
                 fclose(input);
         closeout();
         toconsole();
         pl("Compilation aborted.");  nl();
         exit();
 /* end abort */}


 /*                                        */
 /*        Process all input text                */
 /*                                        */
 /* At this level, only static declarations, */
 /*        defines, includes, and function */
 /*        definitions are legal...        */
 parse()
         {
         while (eof==0)                /* do until no more input */
                 {
                 if(amatch("extern",6)) {
                         cextern=1;
                         if(amatch("char",4)) {declglb(cchar);ns();}
                         else if(amatch("int",3)) {declglb(cint);ns();}
                         else {declglb(cint);ns();}
                         cextern=0;
                         }
                 else if(amatch("char",4)){declglb(cchar);ns();}
                 else if(amatch("int",3)){declglb(cint);ns();}
                 else if(match("#asm"))doasm();
                 else if(match("#include"))doinclude();
                 else if(match("#define"))addmac();
                 else newfunc();
                 blanks();        /* force eof if pending */
                 }
         }
 /* ### cpcn-3 */
 dumpublics()
         {
         outstr("DUMMY SEGMENT BYTE STACK 'dummy'");nl();
         outstr("DUMMY ENDS");nl();
         outstr("STACK SEGMENT BYTE PUBLIC 'stack'");nl();
         dumplits();
         dumpglbs();
         outstr("STACK ENDS");nl();
         }

 extdump()
         {
         char *ptrext;
         ptrext=startextrn;
         while(ptrext<extptr)
                 {
                 if((cptr=findglb(ptrext))!=0)
                         {if(cptr[ident]==function)
                                 if(cptr[offset]!=function) outextrn(ptrext);
                         }
                 else outextrn(ptrext);
                 ptrext=ptrext+strlen(ptrext)+2;
                 }
         outstr("CSEG ENDS");nl();
         }
 /* ### cpcn-4 */
 outextrn(ptr)
         char *ptr;
         {
         char *functype;
         functype=ptr+strlen(ptr)+1;
         if(*functype==statref) return;
         ot("EXTRN ");
         if(*functype==rtsfunc) outasm(ptr);
         else outname(ptr);
         col();outstr("NEAR");nl();
         }


 /*                                        */
 /*        Dump the literal pool                */
 /*                                        */
 dumplits()
         {int j,k;
         if (litptr==0) return;        /* if nothing there, exit...*/
         printlabel(litlab); /* print literal label */
         k=0;                        /* init an index... */
         while (k<litptr)        /*         to loop with */
                 {defbyte();        /* pseudo-op to define byte */
                 j=10;                /* max bytes per line */
                 while(j--)
                         {outdec((litq[k++]&127));
                         if ((j==0) | (k>=litptr))
                                 {nl();                /* need <cr> */
                                 break;
                                 }
                         outbyte(',');        /* separate bytes */
                         }
                 }
         }
 /*                                        */
 /*        Dump all static variables        */
 /*                                        */
 dumpglbs()
 {
         int j;
         cptr=startglb;
         while(cptr<glbptr)
                 {if(cptr[ident]!=function)
                         /* do if anything but function */
                         {
                         if(findext(cptr+name))
                                 {
                                 ot("EXTRN ");
                                 outname(cptr);col();
                                 if((cptr[type]==cint) |
                                         (cptr[ident]==pointer)) outstr("WORD"
                                 else outstr("BYTE");
                                 nl();
                                 }
                         else {
                                 ot("PUBLIC ");outname(cptr);nl();
                                 outname(cptr);
                                 /* output name as label... */
                                 j=((cptr[offset]&255)+
                                         ((cptr[offset+1]&255)<<8));
                                         /* calc # bytes */
                                 if((cptr[type]==cint)|
                                         (cptr[ident]==pointer)) defword();
                                 else defbyte();
                                 outdec(j);
                                 outstr(" DUP(?)");
                                 nl();
                                 }
                         }
                 cptr=cptr+symsiz;
                 }
 }
 /*                                        */
 /*        Report errors for user                */
 /*                                        */
 errorsummary()
         {
         nl();
         outstr("There were ");
         outdec(errcnt);        /* total # errors */
         outstr(" errors in compilation.");
         nl();
         }
 /* ### cpcn-5 */
 /*        Greet User        */


 hello()
         {
         clrscreen();         /* clear screen function */
         nl();nl();                /* print banner */
         pl(BANNER);
         nl();
         pl(AUTHOR);
         nl();nl();
         pl("Distributed by: CAPROCK SYSTEMS, INC.");
         pl("                P.O. Box 13814");
         pl("                Arlington, Texas 76013");
         nl();
         pl(VERSION);
         nl();
         nl();
 } /* end of hello */


 see()
         {
         kill();
         /* see if user wants to be sure to see all errors */
         pl("Should I pause after an error (y,N)?");
         gets(line);
         errstop=0;
         if((ch()=='Y')|(ch()=='y'))
                 errstop=1;

         kill();
         pl("Do you want the small-c:PC-text to appear (y,N)?");
         gets(line);
         ctext=0;
         if((ch()=='Y')|(ch()=='y')) ctext=1;
         }
 /*                                        */
 /*        Get output filename                */
 /*                                        */
 openout()
         {
         output=0;                /* start with none */
         while(output==0)
                 {
                 kill();
                 pl("Output filename? "); /* ask...*/
                 gets(line);        /* get a filename */
                 if(ch()==0)break;        /* none given... */
                 if((output=fopen(line,"w"))==NULL) /* if given, open */
                         {output=0;        /* can't open */
                         error("Open failure!");
                         }
                 }
         kill();                        /* erase line */
 }
 /*                                        */
 /*        Get (next) input file                */
 /*                                        */
 openin()
 {
         input=0;                /* none to start with */
         while(input==0){        /* any above 1 allowed */
                 kill();                /* clear line */
                 pl("Input filename? ");
                 gets(line);        /* get a name */
                 if(ch()==0) break;
                 if((input=fopen(line,"r"))!=NULL)
                         newfile();                        /* gtf 7/16/80 */
                 else {        input=0;        /* can't open it */
                         pl("Open failure");
                         }
                 }
         kill();                /* erase line */
         }


 /*                                        */
 /*        Reset line count, etc.                */
 /*                        gtf 7/16/80        */
 newfile()
 {
         lineno  = 0;        /* no lines read */
         fnstart = 0;        /* no fn. start yet. */
         currfn  = NULL;        /* because no fn. yet */
         infunc  = 0;        /* therefore not in fn. */
 /* end newfile */}
 /* ### cpcn-6 */


 /*                                        */
 /*        Open an include file                */
 /*                                        */
 doinclude()
 {
         blanks();        /* skip over to name */


         toconsole();                                        /* gtf 7/16/80 */
         outstr("#include "); outstr(line+lptr); nl();
         tofile();


         if(input2)                                        /* gtf 7/16/80 */
                 error("Cannot nest include files");
         else if((input2=fopen(line+lptr,"r"))==NULL)
                 {input2=0;
                 error("Open failure on include file");
                 }
         else {        saveline = lineno;
                 savecurr = currfn;
                 saveinfn = infunc;
                 savestart= fnstart;
                 newfile();
                 }
         kill();                /* clear rest of line */
                         /* so next read will come from */
                         /* new file (if open */
 }


 /*                                        */
 /*        Close an include file                */
 /*                        gtf 7/16/80        */
 endinclude()
 {
         toconsole();
         outstr("#end include"); nl();
         tofile();


         input2  = 0;
         lineno  = saveline;
         currfn  = savecurr;
         infunc  = saveinfn;
         fnstart = savestart;
 /* end endinclude */}


 /*                                        */
 /*        Close the output file                */
 /*                                        */
 closeout()
 {
         tofile();        /* if diverted, return to file */
         if(output)fclose(output); /* if open, close it */
         output=0;                /* mark as closed */
 }
 /* ### cpcn-7 */
 /*                                        */
 /*        Declare a static variable        */
 /*          (i.e. define for use)                */
 /*                                        */
 /* makes an entry in the symbol table so subsequent */
 /*  references can call symbol by name        */
 declglb(typ)                /* typ is cchar or cint */
         int typ;
 {        int k,j;char sname[namesize];
         while(1)
                 {while(1)
                         {if(endst())return;        /* do line */
                         k=1;                /* assume 1 element */
                         if(match("*"))        /* pointer ? */
                                 j=pointer;        /* yes */
                                 else j=variable; /* no */
                          if (symname(sname)==0) /* name ok? */
                                 illname(); /* no... */
                         if(findglb(sname)) /* already there? */
                                 multidef(sname);
                         if (match("["))                /* array? */
                                 {k=needsub();        /* get size */
                                 if(k)j=array;        /* !0=array */
                                 else j=pointer; /* 0=ptr */
                                 }
                         addglb(sname,j,typ,k); /* add symbol */
                         if(cextern) addext(sname,statref);
                         break;
                         }
                 if (match(",")==0) return; /* more? */
                 }
         }
 /*                                        */
 /*        Declare local variables                */
 /*        (i.e. define for use)                */
 /*                                        */
 /* works just like "declglb" but modifies machine stack */
 /*        and adds symbol table entry with appropriate */
 /*        stack offset to find it again                        */
 declloc(typ)                /* typ is cchar or cint */
         int typ;
         {
         int k,j;char sname[namesize];
         while(1)
                 {while(1)
                         {if(endst())return;
                         if(match("*"))
                                 j=pointer;
                                 else j=variable;
                         if (symname(sname)==0)
                                 illname();
                         if(findloc(sname))
                                 multidef(sname);
                         if (match("["))
                                 {k=needsub();
                                 if(k)
                                         {j=array;
                                         if(typ==cint)k=k+k;
                                         }
                                 else
                                         {j=pointer;
                                         k=2;
                                         }
                                 }
                         else
                                 if((typ==cchar)
                                         &(j!=pointer))
                                         k=1;else k=2;
                         /* change machine stack */
                         Zsp=modstk(Zsp-k);
                         addloc(sname,j,typ,Zsp);
                         break;
                         }
                 if (match(",")==0) return;
                 }
         }
 /* ### cpcn-8 */
 /*        >>>>>> start of cc2 <<<<<<<<        */


 /*                                        */
 /*        Get required array size                */
 /*                                        */
 /* invoked when declared variable is followed by "[" */
 /*        this routine makes subscript the absolute */
 /*        size of the array. */
 needsub()
         {
         int num[1];
         if(match("]"))return 0;        /* null size */
         if (number(num)==0)        /* go after a number */
                 {error("must be constant");        /* it isn't */
                 num[0]=1;                /* so force one */
                 }
         if (num[0]<0)
                 {error("negative size illegal");
                 num[0]=(-num[0]);
                 }
         needbrack("]");                /* force single dimension */
         return num[0];                /* and return size */
         }
 /*                                        */
 /* ### cpcn-9 */
 /*        Begin a function                */
 /*                                        */
 /* Called from "parse" this routine tries to make a function */
 /*        out of what follows.        */
 newfunc()
         {
         char n[namesize]; /* ptr => currfn,  gtf 7/16/80 */
         if (symname(n)==0)
                 {
                 if(eof==0) error("illegal function or declaration");
                 kill();        /* invalidate line */
                 return;
                 }
         fnstart=lineno;                /* remember where fn began        gtf
         infunc=1;                /* note, in function now.        gtf 7/16/80
         if(currfn=findglb(n))        /* already in symbol table ? */
                 {if(currfn[ident]!=function)multidef(n);
                         /* already variable by that name */
                 else if(currfn[offset]==function)multidef(n);
                         /* already function by that name */
                 else currfn[offset]=function;
                         /* otherwise we have what was earlier*/
                         /*  assumed to be a function */
                 }
         /* if not in table, define as a function now */
         else currfn=addglb(n,function,cint,function);


         toconsole();                                        /* gtf 7/16/80 */
         outstr("====== "); outstr(currfn+name); outstr("()"); nl();
         tofile();


         /* we had better see open paren for args... */
         if(match("(")==0)error("missing open paren");
         ot("PUBLIC ");outname(n);nl();
         outname(n);col();nl();        /* print function name */
         argstk=0;                /* init arg count */
         while(match(")")==0)        /* then count args */
                 /* any legal name bumps arg count */
                 {if(symname(n))argstk=argstk+2;
                 else{error("illegal argument name");junk();}
                 blanks();
                 /* if not closing paren, should be comma */
                 if(streq(line+lptr,")")==0)
                         {if(match(",")==0)
                         error("expected comma");
                         }
                 if(endst())break;
                 }
         locptr=startloc;        /* "clear" local symbol table*/
         Zsp=0;                        /* preset stack ptr */
         while(argstk)
                 /* now let user declare what types of things */
                 /*        those arguments were */
                 {if(amatch("char",4)){getarg(cchar);ns();}
                 else if(amatch("int",3)){getarg(cint);ns();}
                 else{error("wrong number args");break;}
                 }
         if(statement()!=streturn) /* do a statement, but if */
                                 /* it's a return, skip */
                                 /* cleaning up the stack */
                 {modstk(0);
                 zret();
                 }
         Zsp=0;                        /* reset stack ptr again */
         locptr=startloc;        /* deallocate all locals */
         infunc=0;                /* not in fn. any more                gtf 7/
         }
 /* ### cpcn-10 */
 /*                                        */
 /*        Declare argument types                */
 /*                                        */
 /* called from "newfunc" this routine adds an entry in the */
 /*        local symbol table for each named argument */
 getarg(t)                /* t = cchar or cint */
         int t;
         {
         char n[namesize],c;int j;
         while(1)
                 {if(argstk==0)return;        /* no more args */
                 if(match("*"))j=pointer;
                         else j=variable;
                 if(symname(n)==0) illname();
                 if(findloc(n))multidef(n);
                 if(match("["))        /* pointer ? */
                 /* it is a pointer, so skip all */
                 /* stuff between "[]" */
                         {while(inbyte()!=']')
                                 if(endst())break;
                         j=pointer;
                         /* add entry as pointer */
                         }
                 addloc(n,j,t,argstk);
                 argstk=argstk-2;        /* cnt down */
                 if(endst())return;
                 if(match(",")==0)error("expected comma");
                 }
         }
 /* ### cpcn-11 */
 /*        Statement parser                */
 /*                                        */
 /* called whenever syntax requires        */
 /*        a statement.                          */
 /*  this routine performs that statement */
 /*  and returns a number telling which one */
 statement()
 {
 /* comment out ctrl-C check since ctrl-break will work on PC */
 /*        if(cpm(11,0) & 1) */        /* check for ctrl-C                gtf
         /*        if(getchar()==3) */
                 /*        abort(); */


         if ((ch()==0) & (eof)) return;
         else if(amatch("char",4))
                 {declloc(cchar);ns();}
         else if(amatch("int",3))
                 {declloc(cint);ns();}
         else if(match("{"))compound();
         else if(amatch("if",2))
                 {doif();lastst=stif;}
         else if(amatch("while",5))
                 {dowhile();lastst=stwhile;}
         else if(amatch("return",6))
                 {doreturn();ns();lastst=streturn;}
         else if(amatch("break",5))
                 {dobreak();ns();lastst=stbreak;}
         else if(amatch("continue",8))
                 {docont();ns();lastst=stcont;}
         else if(match(";"));
         else if(match("#asm"))
                 {doasm();lastst=stasm;}
         /* if nothing else, assume it's an expression */
         else{expression();ns();lastst=stexp;}
         return lastst;
 }
 /*                                        */
 /* ### cpcn-12 */
 /*        Semicolon enforcer                */
 /*                                        */
 /* called whenever syntax requires a semicolon */
 ns()        {if(match(";")==0)error("missing semicolon");}
 /*                                        */
 /*        Compound statement                */
 /*                                        */
 /* allow any number of statements to fall between "{}" */
 compound()
         {
         ++ncmp;                /* new level open */
         while (match("}")==0) statement(); /* do one */
         --ncmp;                /* close current level */
         }
 /*                                        */
 /*                "if" statement                */
 /*                                        */
 doif()
         {
         int flev,fsp,flab1,flab2;
         flev=locptr;        /* record current local level */
         fsp=Zsp;                /* record current stk ptr */
         flab1=getlabel(); /* get label for false branch */
         test(flab1);        /* get expression, and branch false */
         statement();        /* if true, do a statement */
         Zsp=modstk(fsp);        /* then clean up the stack */
         locptr=flev;        /* and deallocate any locals */
         if (amatch("else",4)==0)        /* if...else ? */
                 /* simple "if"...print false label */
                 {printlabel(flab1);col();nl();
                 return;                /* and exit */
                 }
         /* an "if...else" statement. */
         jump(flab2=getlabel());        /* jump around false code */
         printlabel(flab1);col();nl();        /* print false label */
         statement();                /* and do "else" clause */
         Zsp=modstk(fsp);                /* then clean up stk ptr */
         locptr=flev;                /* and deallocate locals */
         printlabel(flab2);col();nl();        /* print true label */
         }
 /*                                        */
 /*        "while" statement                */
 /*                                        */
 dowhile()
         {
         int wq[4];                /* allocate local queue */
         wq[wqsym]=locptr;        /* record local level */
         wq[wqsp]=Zsp;                /* and stk ptr */
         wq[wqloop]=getlabel();        /* and looping label */
         wq[wqlab]=getlabel();        /* and exit label */
         addwhile(wq);                /* add entry to queue */
                                 /* (for "break" statement) */
         printlabel(wq[wqloop]);col();nl(); /* loop label */
         test(wq[wqlab]);        /* see if true */
         statement();                /* if so, do a statement */
         Zsp = modstk(wq[wqsp]);        /* zap local vars: 9/25/80 gtf */
         jump(wq[wqloop]);        /* loop to label */
         printlabel(wq[wqlab]);col();nl(); /* exit label */
         locptr=wq[wqsym];        /* deallocate locals */
         delwhile();                /* delete queue entry */
         }
 /*                                        */
 /* ### cpcn-13 */
 /*                                        */
 /*        "return" statement                */
 /*                                        */
 doreturn()
         {
         /* if not end of statement, get an expression */
         if(endst()==0)expression();
         modstk(0);        /* clean up stk */
         zret();                /* and exit function */
         }
 /*                                        */
 /*        "break" statement                */
 /*                                        */
 dobreak()
         {
         int *ptr;
         /* see if any "whiles" are open */
         if ((ptr=readwhile())==0) return;        /* no */
         modstk((ptr[wqsp]));        /* else clean up stk ptr */
         jump(ptr[wqlab]);        /* jump to exit label */
         }
 /*                                        */
 /*        "continue" statement                */
 /*                                        */
 docont()
         {
         int *ptr;
         /* see if any "whiles" are open */
         if ((ptr=readwhile())==0) return;        /* no */
         modstk((ptr[wqsp]));        /* else clean up stk ptr */
         jump(ptr[wqloop]);        /* jump to loop label */
         }
 /*                                        */
 /*        "asm" pseudo-statement                */
 /*                                        */
 /* enters mode where assembly language statement are */
 /*        passed intact through parser        */
 doasm()
         {
         cmode=0;                /* mark mode as "asm" */
         while (1)
                 {inline();        /* get and print lines */
                 if (match("#endasm")) break;        /* until... */
                 if(eof)break;
                 outstr(line);
                 nl();
                 }
         kill();                /* invalidate line */
         cmode=1;                /* then back to parse level */
         }
 /* ### cpcn-14 */
 /*        >>>>> start of cc3 <<<<<<<<<        */


 /*                                        */
 /*        Perform a function call                */
 /*                                        */
 /* called from heir11, this routine will either call */
 /*        the named function, or if the supplied ptr is */
 /*        zero, will call the contents of BX                */
 callfunction(ptr)
         char *ptr;        /* symbol table entry (or 0) */
 {        int nargs;
         nargs=0;
         blanks();        /* already saw open paren */
         if(ptr==0)zpush();        /* calling BX */
         while(streq(line+lptr,")")==0)
                 {if(endst())break;
                 expression();        /* get an argument */
                 if(ptr==0)swapstk(); /* don't push addr */
                 zpush();        /* push argument */
                 nargs=nargs+2;        /* count args*2 */
                 if (match(",")==0) break;
                 }
         needbrack(")");
         if(ptr)zcall(ptr);
         else callstk();
         Zsp=modstk(Zsp+nargs);        /* clean up arguments */
 }
 junk()
 {        if(an(inbyte()))
                 while(an(ch()))gch();
         else while(an(ch())==0)
                 {if(ch()==0)break;
                 gch();
                 }
         blanks();
 }
 endst()
 {        blanks();
         return ((streq(line+lptr,";")|(ch()==0)));
 }
 illname()
 {        error("illegal symbol name");junk();}
 multidef(sname)
         char *sname;
 {        error("already defined");
         comment();
         outstr(sname);nl();
 }
 needbrack(str)
         char *str;
 {        if (match(str)==0)
                 {error("missing bracket");
                 comment();outstr(str);nl();
                 }
 }
 needlval()
 {        error("must be lvalue");
 }
 /* ### cpcn-15 */
 findglb(sname)
         char *sname;
 {        char *ptr;
         ptr=startglb;
         while(ptr!=glbptr)
                 {if(astreq(sname,ptr,namemax))return ptr;
                 ptr=ptr+symsiz;
                 }
         return 0;
 }
 findloc(sname)
         char *sname;
 {        char *ptr;
         ptr=startloc;
         while(ptr!=locptr)
                 {if(astreq(sname,ptr,namemax))return ptr;
                 ptr=ptr+symsiz;
                 }
         return 0;
 }
 addglb(sname,id,typ,value)
         char *sname,id,typ;
         int value;
 {        char *ptr;
         if(cptr=findglb(sname))return cptr;
         if(glbptr>=endglb)
                 {error("global symbol table overflow");
                 return 0;
                 }
         cptr=ptr=glbptr;
         while(an(*ptr++ = *sname++));        /* copy name */
         cptr[ident]=id;
         cptr[type]=typ;
         cptr[storage]=statik;
         cptr[offset]=value;
         cptr[offset+1]=value>>8;
         glbptr=glbptr+symsiz;
         return cptr;
 }
 addloc(sname,id,typ,value)
         char *sname,id,typ;
         int value;
 {        char *ptr;
         if(cptr=findloc(sname))return cptr;
         if(locptr>=endloc)
                 {error("local symbol table overflow");
                 return 0;
                 }
         cptr=ptr=locptr;
         while(an(*ptr++ = *sname++));        /* copy name */
         cptr[ident]=id;
         cptr[type]=typ;
         cptr[storage]=stkloc;
         cptr[offset]=value;
         cptr[offset+1]=value>>8;
         locptr=locptr+symsiz;
         return cptr;
 }
 /* ### cpcn-16 */
 addext(sname,id)
         char *sname,id;
         {
         char *ptr;
         if(cptr=findext(sname)) return cptr;
         if(extptr>=endextrn)
                 {error("external symbol table overflow"); return 0;}
         cptr=ptr=extptr;
         while(an(*ptr++=*sname++)); /* copy name */
         /* type stored in byte following zero terminating name */
         *ptr++=id;
         extptr=ptr;
         return cptr;
         }
 findext(sname)
         char *sname;
         {char *ptr;
         ptr=startextrn;
         while(ptr<extptr)
                 {if(astreq(sname,ptr,namemax)) return ptr;
                  ptr=ptr+strlen(ptr)+2;
                 }
         return 0;
         }


 /* Test if next input string is legal symbol name */
 symname(sname)
         char *sname;
 {        int k;char c;
         blanks();
         if(alpha(ch())==0)return 0;
         k=0;
         while(an(ch()))sname[k++]=gch();
         sname[k]=0;
         return 1;
         }
 /* ### cpcn-17 */
 /* Return next avail internal label number */
 getlabel()
 {        return(++nxtlab);
 }
 /* Print specified number as label */
 printlabel(label)
         int label;
 {        outasm("cc");
         outdec(label);
 }
 /* Test if given character is alpha */
 alpha(c)
         char c;
 {        c=c&127;
         return(((c>='a')&(c<='z'))|
                 ((c>='A')&(c<='Z'))|
                 (c=='_'));
 }
 /* Test if given character is numeric */
 numeric(c)
         char c;
 {        c=c&127;
         return((c>='0')&(c<='9'));
 }
 /* Test if given character is alphanumeric */
 an(c)
         char c;
 {        return((alpha(c))|(numeric(c)));
 }
 /* Print a carriage return and a string only to console */
 pl(str)
         char *str;
 {        int k;
         k=0;
         putchar(eol);
         while(str[k])putchar(str[k++]);
 }
 addwhile(ptr)
         int ptr[];
  {
         int k;
         if (wqptr==wqmax)
                 {error("too many active whiles");return;}
         k=0;
         while (k<wqsiz)
                 {*wqptr++ = ptr[k++];}
 }
 delwhile()
         {if(readwhile()) wqptr=wqptr-wqsiz;
         }
 readwhile()
  {
         if (wqptr==wq){error("no active whiles");return 0;}
         else return (wqptr-wqsiz);
  }
 ch()
 {        return(line[lptr]&127);
 }
 nch()
 {        if(ch()==0)return 0;
                 else return(line[lptr+1]&127);
 }
 gch()
 {        if(ch()==0)return 0;
                 else return(line[lptr++]&127);
 }
 kill()
 {        lptr=0;
         line[lptr]=0;
 }
 /* ### cpcn-18 */
 inbyte()
 {
         while(ch()==0)
                 {if (eof) return 0;
                 inline();
                 preprocess();
                 }
         return gch();
 }
 inchar()
 {
         if(ch()==0)inline();
         if(eof)return 0;
         return(gch());
 }
 inline()
 {
         int k,unit;
         while(1)
                 {if (input==0)  {eof=1;return;}
                 if((unit=input2)==0)unit=input;
                 kill();
                 while((k=getc(unit))>0)
                         {if((k==eol)|(lptr>=linemax))break;
                         line[lptr++]=k;
                         }
                 line[lptr]=0;        /* append null */
                 lineno++;        /* read one more line                gtf 7/2
                 if(k<=0)
                         {fclose(unit);
                         if(input2)endinclude();                /* gtf 7/16/80
                                 else input=0;
                         }
                 if(lptr)
                         {if((ctext)&(cmode))
                                 {comment();
                                 outstr(line);
                                 nl();
                                 }
                         lptr=0;
                         return;
                         }
                 }
 }
 /* ### cpcn-19 */
 /*        >>>>>> start of cc4 <<<<<<<        */


 preprocess()
 {        int k;
         char c,sname[namesize];
         if(cmode==0)return;
         mptr=lptr=0;
         while(ch())
                 {if((ch()==' ')|(ch()==9))
                         predel();
                 else if(ch()=='"')
                         prequote();
                 else if(ch()==39)
                         preapos();
                 else if((ch()=='/')&(nch()=='*'))
                         precomm();
                 else if(alpha(ch()))        /* from an(): 9/22/80 gtf */
                         {k=0;
                         while(an(ch()))
                                 {if(k<namemax)sname[k++]=ch();
                                 gch();
                                 }
                         sname[k]=0;
                         if(k=findmac(sname))
                                 while(c=macq[k++])
                                         keepch(c);
                         else
                                 {k=0;
                                 while(c=sname[k++])
                                         keepch(c);
                                 }
                         }
                 else keepch(gch());
                 }
         keepch(0);
         if(mptr>=mpmax)error("line too long");
         lptr=mptr=0;
         while(line[lptr++]=mline[mptr++]);
         lptr=0;
         }
 /* ### cpcn-20 */
 keepch(c)
         char c;
 {        mline[mptr]=c;
         if(mptr<mpmax)mptr++;
         return c;
 }
 predel()
                         {keepch(' ');
                         while((ch()==' ')|
                                 (ch()==9))
                                 gch();
                         }
 prequote()
                         {keepch(ch());
                         gch();
                         while(ch()!='"')
                                 {if(ch()==0)
                                   {error("missing quote");
                                   break;
                                   }
                                 keepch(gch());
                                 }
                         gch();
                         keepch('"');
                         }
 preapos()
                         {keepch(39);
                         gch();
                         while(ch()!=39)
                                 {if(ch()==0)
                                   {error("missing apostrophe");
                                   break;
                                   }
                                 keepch(gch());
                                 }
                         gch();
                         keepch(39);
                         }
 precomm()
                         {inchar();inchar();
                         while(((ch()=='*')&
                                 (nch()=='/'))==0)
                                 {if(ch()==0)inline();
                                         else inchar();
                                 if(eof)break;
                                 }
                         inchar();inchar();
                         }
 /* ### cpcn-21 */
 addmac()
 {        char sname[namesize];
         int k;
         if(symname(sname)==0)
                 {illname();
                 kill();
                 return;
                 }
         k=0;
         while(putmac(sname[k++]));
         while(ch()==' ' | ch()==9) gch();
         while(putmac(gch()));
         if(macptr>=macmax)error("macro table full");
         }
 putmac(c)
         char c;
 {        macq[macptr]=c;
         if(macptr<macmax)macptr++;
         return c;
 }
 findmac(sname)
         char *sname;
 {        int k;
         k=0;
         while(k<macptr)
                 {if(astreq(sname,macq+k,namemax))
                         {while(macq[k++]);
                         return k;
                         }
                 while(macq[k++]);
                 while(macq[k++]);
                 }
         return 0;
 }
 /* ### cpcn-22 */
 /* direct output to console                gtf 7/16/80 */
 toconsole()
 {
         saveout = output;
         output = 0;
 /* end toconsole */}


 /* direct output back to file                gtf 7/16/80 */
 tofile()
 {
         if(saveout)
                 output = saveout;
         saveout = 0;
 /* end tofile */}


 outbyte(c)
         char c;
 {
         if(c==0)return 0;
         if(output)
                 {if((putc(c,output))<=0)
                         {closeout();
                         error("Output file error");
                         abort();                        /* gtf 7/17/80 */
                         }
                 }
         else putchar(c);
         return c;
 }
 outstr(ptr)
         char ptr[];
  {
         int k;
         k=0;
         while(outbyte(ptr[k++]));
  }


 /* write text destined for the assembler to read */
 /* (i.e. stuff not in comments)                        */
 /*  gtf  6/26/80 */
 outasm(ptr)
 char *ptr;
 {
         while(outbyte(raise(*ptr++)));
 /* end outasm */}


 nl()
         {outbyte(eol);}
 tab()
         {outbyte(9);}
 col()
         {outbyte(58);}
 /* ### cpcn-23 */
 error(ptr)
 char ptr[];
 {        int k;
         char junk[81];


         toconsole();
         bell();
         outstr("Line "); outdec(lineno); outstr(", ");
         if(infunc==0)
                 outbyte('(');
         if(currfn==NULL)
                 outstr("start of file");
         else        outstr(currfn+name);
         if(infunc==0)
                 outbyte(')');
         outstr(" + ");
         outdec(lineno-fnstart);
         outstr(": ");  outstr(ptr);  nl();


         outstr(line); nl();


         k=0;        /* skip to error position */
         while(k<lptr){
                 if(line[k++]==9)
                         tab();
                 else        outbyte(' ');
                 }
         outbyte('^');  nl();
         ++errcnt;


         if(errstop){
                 pl("Continue (Y,n,g) ? ");
                 gets(junk);
                 k=junk[0];
                 if((k=='N') | (k=='n'))
                         abort();
                 if((k=='G') | (k=='g'))
                         errstop=0;
                 }
         tofile();
 /* end error */}


 ol(ptr)
         char ptr[];
 {
         ot(ptr);
         nl();
 }
 ot(ptr)
         char ptr[];
 {
         tab();
         outasm(ptr);
 }
 /* ### cpcn-24 */
 streq(str1,str2)
         char str1[],str2[];
  {
         int k;
         k=0;
         while (str2[k])
                 {if ((str1[k])!=(str2[k])) return 0;
                 k++;
                 }
         return k;
  }
 astreq(str1,str2,len)
         char str1[],str2[];int len;
  {
         int k;
         k=0;
         while (k<len)
                 {if ((str1[k])!=(str2[k]))break;
                 if(str1[k]==0)break;
                 if(str2[k]==0)break;
                 k++;
                 }
         if (an(str1[k]))return 0;
         if (an(str2[k]))return 0;
         return k;
  }
 match(lit)
         char *lit;
 {
         int k;
         blanks();
         if (k=streq(line+lptr,lit))
                 {lptr=lptr+k;
                 return 1;
                 }
          return 0;
 }
 amatch(lit,len)
         char *lit;int len;
  {
         int k;
         blanks();
         if (k=astreq(line+lptr,lit,len))
                 {lptr=lptr+k;
                 while(an(ch())) inbyte();
                 return 1;
                 }
         return 0;
  }
 /* ### cpcn-25 */
 blanks()
         {while(1)
                 {while(ch()==0)
                         {inline();
                         preprocess();
                         if(eof)break;
                         }
                 if(ch()==' ')gch();
                 else if(ch()==9)gch();
                 else return;
                 }
         }
 outdec(number)
         int number;
  {
         int k,zs;
         char c;
         zs = 0;
         k=10000;
         if (number<0)
                 {number=(-number);
                 outbyte('-');
                 }
         while (k>=1)
                 {
                 c=number/k + '0';
                 if ((c!='0')|(k==1)|(zs))
                         {zs=1;outbyte(c);}
                 number=number%k;
                 k=k/10;
                 }
  }
 /* return the length of a string */
 /* gtf 4/8/80 */
 strlen(s)
 char *s;
 {        char *t;


         t = s;
         while(*s) s++;
         return(s-t);
 /* end strlen */}


 /* convert lower case to upper */
 /* gtf 6/26/80 */
 raise(c)
 char c;
 {
         if((c>='a') & (c<='z'))
                 c = c - 'a' + 'A';
         return(c);
 /* end raise */}
 /* ### cpcn-26 */
 /*        >>>>>>> start of cc5 <<<<<<<        */


 /* modified 9/25/80: putstk() */


 expression()
 {
         int lval[2];
         if(heir1(lval))rvalue(lval);
 }
 heir1(lval)
         int lval[];
 {
         int k,lval2[2];
         k=heir2(lval);
         if (match("="))
                 {if(k==0){needlval();return 0;}
                 if (lval[1])zpush();
                 if(heir1(lval2))rvalue(lval2);
                 store(lval);
                 return 0;
                 }
         else return k;
 }
 heir2(lval)
         int lval[];
 {        int k,lval2[2];
         k=heir3(lval);
         blanks();
         if(ch()!='|')return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("|"))
                         {zpush();
                         if(heir3(lval2)) rvalue(lval2);
                         zpop();
                         zor();
                         }
                 else return 0;
                 }
 }
 /* ### cpcn-27 */
 heir3(lval)
         int lval[];
 {        int k,lval2[2];
         k=heir4(lval);
         blanks();
         if(ch()!='^')return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("^"))
                         {zpush();
                         if(heir4(lval2))rvalue(lval2);
                         zpop();
                         zxor();
                         }
                 else return 0;
                 }
 }
 heir4(lval)
         int lval[];
 {        int k,lval2[2];
         k=heir5(lval);
         blanks();
         if(ch()!='&')return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("&"))
                         {zpush();
                         if(heir5(lval2))rvalue(lval2);
                         zpop();
                         zand();
                         }
                 else return 0;
                 }
 }
 heir5(lval)
         int lval[];
 {
         int k,lval2[2];
         k=heir6(lval);
         blanks();
         if((streq(line+lptr,"==")==0)&
                 (streq(line+lptr,"!=")==0))return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("=="))
                         {zpush();
                         if(heir6(lval2))rvalue(lval2);
                         zpop();
                         zeq();
                         }
                 else if (match("!="))
                         {zpush();
                         if(heir6(lval2))rvalue(lval2);
                         zpop();
                         zne();
                         }
                 else return 0;
                 }
 }
 /* ### cpcn-28 */
 heir6(lval)
         int lval[];
 {
         int k;
         k=heir7(lval);
         blanks();
         if((streq(line+lptr,"<")==0)&
                 (streq(line+lptr,">")==0)&
                 (streq(line+lptr,"<=")==0)&
                 (streq(line+lptr,">=")==0))return k;
                 if(streq(line+lptr,">>"))return k;
                 if(streq(line+lptr,"<<"))return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("<="))
                         {if(heir6wrk(1,lval)) continue;
                         zle();
                         }
                 else if (match(">="))
                         {if(heir6wrk(2,lval)) continue;
                         zge();
                         }
                 else if((streq(line+lptr,"<"))&
                         (streq(line+lptr,"<<")==0))
                         {inbyte();
                         if(heir6wrk(3,lval)) continue;
                         zlt();
                         }
                 else if((streq(line+lptr,">"))&
                         (streq(line+lptr,">>")==0))
                         {inbyte();
                         if(heir6wrk(4,lval)) continue;
                         zgt();
                         }
                 else return 0;
                 }
 }
 /* ### cpcn-29 */
 heir6wrk(k,lval)
         int k,lval[];
 {
         int lval2[2];
         zpush();
         if(heir7(lval2))rvalue(lval2);
         zpop();
         if(cptr=lval[0])
                 if(cptr[ident]==pointer)
                         {heir6op(k);
                         return 1;
                         }
         if(cptr=lval2[0])
                 if(cptr[ident]==pointer)
                         {heir6op(k);
                         return 1;
                         }
         return 0;
 }
 heir6op(k)
         int k;
 {
         if(k==1) ule();
         else if(k==2) uge();
              else if(k==3) ult();
                   else ugt();
 }
 /* ### cpcn-30 */
 /*        >>>>>> start of cc6 <<<<<<        */


 heir7(lval)
         int lval[];
 {
         int k,lval2[2];
         k=heir8(lval);
         blanks();
         if((streq(line+lptr,">>")==0)&
                 (streq(line+lptr,"<<")==0))return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match(">>"))
                         {zpush();
                         if(heir8(lval2))rvalue(lval2);
                         zpop();
                         asr();
                         }
                 else if (match("<<"))
                         {zpush();
                         if(heir8(lval2))rvalue(lval2);
                         zpop();
                         asl();
                         }
                 else return 0;
                 }
 }
 /* ### cpcn-31 */
 heir8(lval)
         int lval[];
 {
         int k,lval2[2];
         k=heir9(lval);
         blanks();
         if((ch()!='+')&(ch()!='-'))return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("+"))
                         {zpush();
                         if(heir9(lval2))rvalue(lval2);
                         if(cptr=lval[0])
                                 if((cptr[ident]==pointer)&
                                 (cptr[type]==cint))
                                 doublereg();
                         zpop();
                         zadd();
                         }
                 else if (match("-"))
                         {zpush();
                         if(heir9(lval2))rvalue(lval2);
                         if(cptr=lval[0])
                                 if((cptr[ident]==pointer)&
                                 (cptr[type]==cint))
                                 doublereg();
                         zpop();
                         zsub();
                         }
                 else return 0;
                 }
 }
 /* ### cpcn-32 */
 heir9(lval)
         int lval[];
 {
         int k,lval2[2];
         k=heir10(lval);
         blanks();
         if((ch()!='*')&(ch()!='/')&
                 (ch()!='%'))return k;
         if(k)rvalue(lval);
         while(1)
                 {if (match("*"))
                         {zpush();
                         if(heir9(lval2))rvalue(lval2);
                         zpop();
                         mult();
                         }
                 else if (match("/"))
                         {zpush();
                         if(heir10(lval2))rvalue(lval2);
                         zpop();
                         div();
                         }
                 else if (match("%"))
                         {zpush();
                         if(heir10(lval2))rvalue(lval2);
                         zpop();
                         zmod();
                         }
                 else return 0;
                 }
 }
 /* ### cpcn-33 */
 heir10(lval)
         int lval[];
 {
         int k;
         if(match("++"))
                 {if((k=heir10(lval))==0)
                         {needlval();
                         return 0;
                         }
                 heir10inc(lval);
                 return 0;
                 }
         else if(match("--"))
                 {if((k=heir10(lval))==0)
                         {needlval();
                         return 0;
                         }
                 heir10dec(lval);
                 return 0;
                 }
         else if (match("-"))
                 {k=heir10(lval);
                 if (k) rvalue(lval);
                 neg();
                 return 0;
                 }
         else if(match("*"))
                 {heir10as(lval);
                 return 1;
                 }
         else if(match("&"))
                 {k=heir10(lval);
                 if(k==0)
                         {error("illegal address");
                         return 0;
                         }
                 else if(lval[1])return 0;
                 else
                         {heir10at(lval);
                         return 0;
                         }
                 }
         else
                 {k=heir11(lval);
                 if(match("++"))
                         {if(k==0)
                                 {needlval();
                                 return 0;
                                 }
                         heir10id(lval);
                         return 0;
                         }
                 else if(match("--"))
                         {if(k==0)
                                 {needlval();
                                 return 0;
                                 }
                         heir10di(lval);
                         return 0;
                         }
                 else return k;
                 }
         }
 /* ### cpcn-34 */
 heir10inc(lval)
         int lval[];
 {
         char *ptr;
         if(lval[1])zpush();
         rvalue(lval);
         inc();
         ptr=lval[0];
         if((ptr[ident]==pointer)&
                 (ptr[type]==cint))
                         inc();
         store(lval);
 }
 heir10dec(lval)
         int lval[];
 {
         char *ptr;


         if(lval[1])zpush();
         rvalue(lval);
         dec();
         ptr=lval[0];
         if((ptr[ident]==pointer)&
                 (ptr[type]==cint))
                         dec();
         store(lval);
 }
 heir10as(lval)
         int lval[];
 {
         int k;
         char *ptr;


         k=heir10(lval);
         if(k)rvalue(lval);
         lval[1]=cint;
         if(ptr=lval[0])lval[1]=ptr[type];
         lval[0]=0;
 }
 /* ### cpcn-35 */
 heir10at(lval)
         int lval[];
 {
         char *ptr;


         immed();
         outstr("OFFSET ");
         outname(ptr=lval[0]);
         nl();
         lval[1]=ptr[type];
 }
 heir10id(lval)
         int lval[];
 {
         char *ptr;


         if(lval[1])zpush();
         rvalue(lval);
         inc();
         ptr=lval[0];
         if((ptr[ident]==pointer)&
                 (ptr[type]==cint))
                         inc();
         store(lval);
         dec();
         if((ptr[ident]==pointer)&
                 (ptr[type]==cint))
                 dec();
 }
 heir10di(lval)
         int lval[];
 {
         char *ptr;


         if(lval[1])zpush();
         rvalue(lval);
         dec();
         ptr=lval[0];
         if((ptr[ident]==pointer)&
                 (ptr[type]==cint))
                         dec();
         store(lval);
         inc();
         if((ptr[ident]==pointer)&
                 (ptr[type]==cint))
                 inc();
 }
 /* ### cpcn-36 */
 /*        >>>>>> start of cc7 <<<<<<        */


 heir11(lval)
         int *lval;
 {        int k;char *ptr;
         k=primary(lval);
         ptr=lval[0];
         blanks();
         if((ch()=='[')|(ch()=='('))
         while(1)
                 {if(match("["))
                         {if(ptr==0)
                                 {error("can't subscript");
                                 junk();
                                 needbrack("]");
                                 return 0;
                                 }
                         else if(ptr[ident]==pointer)rvalue(lval);
                         else if(ptr[ident]!=array)
                                 {error("can't subscript");
                                 k=0;
                                 }
                         zpush();
                         expression();
                         needbrack("]");
                         if(ptr[type]==cint)doublereg();
                         zpop();
                         zadd();
                         lval[1]=ptr[type];
                         k=1;
                         }
                 else if(match("("))
                         {if(ptr==0)
                                 {callfunction(0);
                                 }
                         else if(ptr[ident]!=function)
                                 {rvalue(lval);
                                 callfunction(0);
                                 }
                         else callfunction(ptr);
                         k=lval[0]=0;
                         }
                 else return k;
                 }
         if(ptr==0)return k;
         if(ptr[ident]==function)
                 {immed();
                 outstr("OFFSET ");
                 outname(ptr);
                 nl();
                 return 0;
                 }
         return k;
 }
 /* ### cpcn-37 */
 primary(lval)
         int *lval;
 {        char *ptr,sname[namesize];int num[1];
         int k;
         if(match("("))
                 {k=heir1(lval);
                 needbrack(")");
                 return k;
                 }
         if(symname(sname))
                 {if(ptr=findloc(sname))
                         {getloc(ptr);
                         lval[0]=ptr;
                         lval[1]=ptr[type];
                         if(ptr[ident]==pointer)lval[1]=cint;
                         if(ptr[ident]==array)return 0;
                                 else return 1;
                         }
                 if(ptr=findglb(sname))
                         if(ptr[ident]!=function)
                         {lval[0]=ptr;
                         lval[1]=0;
                         if(ptr[ident]!=array)return 1;
                         immed();
                         outstr("OFFSET ");
                         outname(ptr);nl();
                         lval[1]=ptr[type];
                         return 0;
                         }
                 ptr=addglb(sname,function,cint,0);
                 lval[0]=ptr;
                 lval[1]=0;
                 return 0;
                 }
         if(constant(num))
                 return(lval[0]=lval[1]=0);
         else
                 {error("invalid expression");
                 immed();outdec(0);nl();
                 junk();
                 return 0;
                 }
         }
 /* ### cpcn-38 */
 store(lval)
         int *lval;
 {        if (lval[1]==0)putmem(lval[0]);
         else putstk(lval[1]);
 }
 rvalue(lval)
         int *lval;
 {        if((lval[0] != 0) & (lval[1] == 0))
                 getmem(lval[0]);
                 else indirect(lval[1]);
 }
 test(label)
         int label;
 {
         needbrack("(");
         expression();
         needbrack(")");
         testjump(label);
 }
 constant(val)
         int val[];
 {        if (number(val))
                 immed();
         else if (pstr(val))
                 immed();
         else if (qstr(val))
                 {immed();outstr("OFFSET ");printlabel(litlab);outbyte('+');}
         else return 0;
         outdec(val[0]);
         nl();
         return 1;
 }
 /* ### cpcn-39 */
 number(val)
         int val[];
 {        int k,minus;char c;
         k=minus=1;
         while(k)
                 {k=0;
                 if (match("+")) k=1;
                 if (match("-")) {minus=(-minus);k=1;}
                 }
         if(numeric(ch())==0)return 0;
         while (numeric(ch()))
                 {c=inbyte();
                 k=k*10+(c-'0');
                 }
         if (minus<0) k=(-k);
         val[0]=k;
         return 1;
 }
 pstr(val)
         int val[];
 {        int k;char c;
         k=0;
         if (match("'")==0) return 0;
         while((c=gch())!=39)
                 k=(k&255)*256 + (c&127);
         val[0]=k;
         return 1;
 }
 qstr(val)
         int val[];
 {        char c;
         if (match(quote)==0) return 0;
         val[0]=litptr;
         while (ch()!='"')
                 {if(ch()==0)break;
                 if(litptr>=litmax)
                         {error("string space exhausted");
                         while(match(quote)==0)
                                 if(gch()==0)break;
                         return 1;
                         }
                 litq[litptr++]=gch();
                 }
         gch();
         litq[litptr++]=0;
         return 1;
 }
 /* ### cpcn-40 */
 /*        >>>>>> start of cc8 <<<<<<<        */


 /* Begin a comment line for the assembler */
 comment()
 {        outbyte(';');
 }


 /* Put out assembler info before any code is generated */
 header()
 {        comment();
         outstr(BANNER);
         nl();
         comment();
         outstr(VERSION);
         nl();
         comment();
         outstr(AUTHOR);
         nl();
         comment();
         nl();
         outstr("CSEG SEGMENT BYTE PUBLIC 'code'");nl();
         ol("ASSUME CS:CSEG,SS:STACK");
 }
 /* Print any assembler stuff needed after all code */
 trailer()
 {
         nl();                        /* 6 May 80 rj errorsummary() now goes t
         comment();
         outstr(" --- End of Compilation ---");
         nl();
         ol("END");
 }
 /* ### cpcn-41 */
 /* Print out a name such that it won't annoy the assembler */
 /*        (by matching anything reserved, like opcodes.) */
 /*        gtf 4/7/80 */
 outname(sname)
 char *sname;
 {        int len, i,j;


         outasm("qz");
         len = strlen(sname);
         if(len>(asmpref+asmsuff)){
                 i = asmpref;
                 len = len-asmpref-asmsuff;
                 while(i-- > 0)
                         outbyte(raise(*sname++));
                 while(len-- > 0)
                         sname++;
                 while(*sname)
                         outbyte(raise(*sname++));
                 }
         else        outasm(sname);
 /* end outname */}
 /* Fetch a static memory cell into the primary register */
 getmem(sym)
         char *sym;
 {        if((sym[ident]!=pointer)&(sym[type]==cchar))
                 { ot("MOV AL,SS:");
                 outname(sym+name);
                 nl();
                 ol("CBW");
                 ol("MOV BX,AX");
                 }
         else
                 {ot("MOV BX,SS:");
                 outname(sym+name);
                 nl();
                 }
         }
 /* Fetch the address of the specified symbol */
 /*        into the primary register */
 getloc(sym)
         char *sym;
 {        immed();
         outdec(((sym[offset]&255)+
                 ((sym[offset+1]&255)<<8))-
                 Zsp);
         nl();
         ol("ADD BX,SP");
         }
 /* Store the primary register into the specified */
 /*        static memory cell */
 putmem(sym)
         char *sym;
 {
         ot("MOV SS:");outname(sym+name);
         outstr(",");
         if((sym[ident]!=pointer)&(sym[type]==cchar)) outstr("BL");
         else outstr("BX");
         nl();
         }
 /* Store the specified object type in the primary register */
 /*        at the address on the top of the stack */
 putstk(typeobj)
         char typeobj;
 {        zpop();
         if(typeobj==cint)
                 callrts("ccpint");
         else {
                 ol("MOV BP,DX");
                 ol("MOV [BP],BL");
                 }
         }
 /* ### cpcn-42 */
 /* Fetch the specified object type indirect through the */
 /*        primary register into the primary register */
 indirect(typeobj)
         char typeobj;
 {        if(typeobj==cchar)callrts("ccgchar");
                 else callrts("ccgint");
 }
 /* Swap the primary and secondary registers */
 swap()
 {
         ol("XCHG DX,BX");
 }
 /* Print partial instruction to get an immediate value */
 /*        into the primary register */
 immed()
 {
         ot("MOV BX,");
 }
 /* Push the primary register onto the stack */
 zpush()
 {
         ol("PUSH BX");
         Zsp=Zsp-2;
 }
 /* Pop the top of the stack into the secondary register */
 zpop()
 {
         ol("POP DX");
         Zsp=Zsp+2;
 }
 /* Swap the primary register and the top of the stack */
 swapstk()
 {
         ol("MOV BP,SP");
         ol("XCHG BX,[BP]");
 }
 /* Call the specified subroutine name */
 zcall(sname)
         char *sname;
 {        ot("CALL ");
         outname(sname);
         nl();
         addext(sname,userfunc);
 }
 /* Call a run-time library routine */
 callrts(sname)
 char *sname;
 {
         ot("CALL ");
         outasm(sname);
         nl();
         addext(sname,rtsfunc);
 /*end callrts*/}


 /* Return from subroutine */
 zret()
 {        ol("RET");
 }
 /* ### cpcn-43 */
 /* Perform subroutine call to value on top of stack */
 callstk()
 {        immed();
         outasm("$+11");
         nl();
         swapstk();
         ol("JMP BX");
         Zsp=Zsp-2;
         }
 /* Jump to specified internal label number */
 jump(label)
         int label;
 {        ot("JMP ");
         printlabel(label);
         nl();
         }
 /* Test the primary register and jump if false to label */
 testjump(label)
         int label;
 {
         ol("OR BX,BX");
         ol("JNZ $+5");
         jump(label);
 }
 /* Print pseudo-op to define a byte */
 defbyte()
 {        ot("DB ");
 }
 /*Print pseudo-op to define storage */
 defstorage()
 {        ot("DS ");
 }
 /* Print pseudo-op to define a word */
 defword()
 {        ot("DW ");
 }
 /* Modify the stack pointer to the new value indicated */
 modstk(newsp)
         int newsp;
  {        int k;
         k=newsp-Zsp;
         if(k==0)return newsp;
         if(k>=0)
                 {if(k<7)
                         {if(k&1)
                                 {
                                 ol("INC SP");
                                 k--;
                                 }
                         while(k)
                                 {ol("POP CX");
                                 k=k-2;
                                 }
                         return newsp;
                         }
                 }
         if(k<0)
                 {if(k>-7)
                         {if(k&1)
                                 { ol("DEC SP");
                                 k++;
                                 }
                         while(k)
                                 {ol("PUSH CX");
                                 k=k+2;
                                 }
                         return newsp;
                         }
                 }
         swap();
         immed();outdec(k);nl();
         ol("ADD SP,BX");
         swap();
         return newsp;
 }
 /* ### cpcn-44 */
 /* Double the primary register */
 doublereg()
 {        ol("ADD BX,BX");
 }
 /* Add the primary and secondary registers */
 /*        (results in primary) */
 zadd()
 {        ol("ADD BX,DX");
 }
 /* Subtract the primary register from the secondary */
 /*        (results in primary) */
 zsub()
 {
         ol("SUB BX,DX");
         ol("NEG BX");
 }
 /* Multiply the primary and secondary registers */
 /*        (results in primary */
 mult()
 {        callrts("ccmult");
 }
 /* Divide the secondary register by the primary */
 /*        (quotient in primary, remainder in secondary) */
 div()
 {        callrts("ccdiv");
 }
 /* Compute remainder (mod) of secondary register divided */
 /*        by the primary */
 /*        (remainder in primary, quotient in secondary) */
 zmod()
 {        div();
         swap();
         }
 /* Inclusive 'or' the primary and the secondary registers */
 /*        (results in primary) */
 zor()
         {ol("OR BX,DX");}
 /* Exclusive 'or' the primary and seconday registers */
 /*        (results in primary) */
 zxor()
         {ol("XOR BX,DX");}
 /* 'And' the primary and secondary registers */
 /*        (results in primary) */
 zand()
         {ol("AND BX,DX");}
 /* Arithmetic shift right the secondary register number of */
 /*         times in primary (results in primary) */
 asr()
         {ol("MOV CL,BL");ol("MOV BX,DX");ol("SAR BX,CL");}
 /* Arithmetic left shift the secondary register number of */
 /*        times in primary (results in primary) */
 asl()
         {ol("MOV CL,BL");ol("MOV BX,DX");ol("SAL BX,CL");}
 /* Form two's complement of primary register */
 neg()
         {ol("NEG BX");}
 /* Form one's complement of primary register */
 com()
         {ol("NOT BX");}
 /* Increment the primary register by one */
 inc()
         {ol("INC BX");}
 /* Decrement the primary register by one */
 dec()
         {ol("DEC BX");}


 /* Following are the conditional operators */
 /* They compare the secondary register against the primary */
 /* and put a literal 1 in the primary if the condition is */
 /* true, otherwise they clear the primary register */


 /* Test for equal */
 zeq()
         {callrts("cceq");}
 /* Test for not equal */
 zne()
         {callrts("ccne");}
 /* Test for less than (signed) */
 zlt()
         {callrts("cclt");}
 /* Test for less than or equal to (signed) */
 zle()
         {callrts("ccle");}
 /* Test for greater than (signed) */
 zgt()
         {callrts("ccgt");}
 /* Test for greater than or equal to (signed) */
 zge()
         {callrts("ccge");}
 /* Test for less than (unsigned) */
 ult()
         {callrts("ccult");}
 /* Test for less than or equal to (unsigned) */
 ule()
         {callrts("ccule");}
 /* Test for greater than (unsigned) */
 ugt()
         {callrts("ccugt");}
 /* Test for greater than or equal to (unsigned) */
 uge()
         {callrts("ccuge");}


 /*        <<<<<  End of small-c:PC compiler  >>>>>        */


 CPG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\CPG\CPG.C

 /*Tcpg - c program source listing formatter */
 /*F cpg.c **********************************************************
  *
  *                           cpg.c
  *
  *    DESCRIPTION OF FILE CONTENTS:
  *      C source program listing formatter source.
  *
  *  Cpg provides the facility to print out a C language source file
  *  with headers, nesting level indicators, and table of contents.
  *  It makes use of "triggers" for page headings, titles and
  *  subtitles, and pagination.  It also recognizes function
  *  declarations and form feeds and treats them appropriately.
  *
  *******************************************************************/
 /*E*/
 /*S includes, defines, and globals */
 /*P*/
 #include <stdio.h>
 #include    <ctype.h>
 #include    <time.h>

 #define EQ ==
 #define NE !=
 #define GT >
 #define GE >=
 #define LT <
 #define LE <=
 #define OR ||
 #define AND &&

 #define TRUE 1
 #define FALSE 0
 #define YES 1
 #define NO 0

 #define SPACE ' '
 #define NUL '\0'

 typedef short   BOOL;

 #define INULL -32768
 #define LNULL -2147483648

 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #define ABS(a) ((a) >= 0 ? (a) : -(a))

 #define LINESINHEAD 6
 #define LPP 60
 #define MAXWIDTH    132

 #define notend(ll) ((ll[0] EQ SLASH AND ll[1] EQ STAR AND ll[2] EQ 'E') ? FAL
 #define SLASH   '/'
 #define STAR    '*'
 #define DQUOTE '"'
 #define SQUOTE '\''
 #define BSLASH '\\'

 #ifdef BSD
 #define strrchr rindex
 #define strchr index
 #endif

 extern char *strrchr ();
 extern char *strchr ();

 char    *basename ();

 char    tim_lin[40];
 char    *file_name;
 char    fh_name[50] = "";
 char    fnc_name[40] = "";
 char    subttl[70] = "";
 char    title[70] = "";
 char    tocname[] = "/tmp/toc_XXXXXX";

 int     nlvl = 0;

 int     page_line = LPP+1;
 int     pageno = 1;

 int     tabstop = 8;

 int     infunc = FALSE;
 int     logging = 0;
 int     BASENAMES = FALSE;

 int     incomment = FALSE;
 int     insquote = FALSE;
 int     indquote = FALSE;

 char    specline = FALSE;

 FILE    *tocfile;
 FILE    *fd;

 char    *pgm;

 char    *ReservedWord[]  = {
      "auto", "bool", "break", "case", "char", "continue",
      "default", "do", "double", "else", "entry", "enum",
      "extern", "float", "for", "goto", "if",
      "int", "long", "register", "return", "short",
      "sizeof", "static", "struct", "switch",
      "typedef", "union", "unsigned", "void", "while",
      NULL };

 /*S main function */
 /*Hmain */
 /*E*/

 main (ac, av)
 int     ac;
 char    **av;
 {
     char    *std_input = "standard input";  /* input file name      */

     long    cur_time;               /* place for current raw time   */

     register int i;                 /* temporary for indexes, etc.  */

     struct tm *tim;                 /* return from localtime        */
     struct tm *localtime ();

     char    cmdbuf[40];             /* place to format sort command */

     extern char *optarg;            /* option argument pointer      */
     extern int   optind;            /* option index                 */

     pgm = basename (av[0]);

     while ((i = getopt (ac, av, "bl:t:")) NE EOF)
     {
         switch (i)
         {
             case    'b':
                 BASENAMES = TRUE;
                 break;
             case    'l':
                 logging = atoi (optarg);
                 break;
             case    't':
                 tabstop = atoi (optarg);
                 break;
             default:
                 fprintf (stderr,
         "usage: %s [ -b<asename> ] [ -t <tabstop> ] [ files... ]\n",
                         pgm);
         }
     }

     /* ------------------------------------------------------------ */
     /* set up the date/time portion of page headings                */
     /* ------------------------------------------------------------ */

     time(&cur_time);

     tim = localtime (&cur_time);
     sprintf (tim_lin, "Printed: %02d/%02d/%02d at %2d:%02d %s",
         tim->tm_mon + 1, tim->tm_mday, tim->tm_year,
         tim->tm_hour GT 12 ? tim->tm_hour - 12 : tim->tm_hour,
         tim->tm_min,
         tim->tm_hour GE 12 ? "PM" : "AM" );

     /* ------------------------------------------------------------ */
     /* create the temporary file for the table of contents          */
     /*   don't bother if output is to a terminal                    */
     /* ------------------------------------------------------------ */

     mktemp (tocname);
     if (!isatty (1))
     {
         tocfile = fopen (tocname, "w");
         if (!tocfile)
         {
             fprintf (stderr, "%s: unable to create tocfile %s\n",
                 pgm, tocname);
             exit (2);
         }
     }

     /* ------------------------------------------------------------ */
     /* if no file names, read standard input                        */
     /* ------------------------------------------------------------ */

     if (optind EQ ac)
     {
         fd = stdin;
         file_name = std_input;
         dofile (fd);
     }
     else
     {
     /* ------------------------------------------------------------ */
     /* process each file named on the command line                  */
     /* ------------------------------------------------------------ */

         for (i = optind; i LT ac; i++)
         {
     /* ------------------------------------------------------------ */
     /* special file name `-' is standard input                      */
     /* ------------------------------------------------------------ */

             if (strcmp (av[i], "-") EQ 0)
             {
                 fd = stdin;
                 file_name = std_input;
             }
             else
             {
                 fd = fopen (av[i], "r");
                 if (fd EQ NULL)
                 {
                     fprintf (stderr,
                         "cpg: unable to open %s\n", av[i]);
                 }
             }
             if (fd NE NULL)
             {
                 if (BASENAMES) strcpy (fh_name, basename (av[i]));
                 else strcpy (fh_name, av[i]);
                 file_name = av[i];
                 dofile (fd);
                 fclose (fd);
             }
         }
     }

     fflush (stdout);

     /* ------------------------------------------------------------ */
     /* sort and print the table of contents - straight alpha order  */
     /* on function and file name                                    */
     /* ------------------------------------------------------------ */

     if (!isatty (1))
     {
         fclose (tocfile);
         sprintf (cmdbuf, "sort +1 -2 +0 -1 -u -o %s %s", tocname, tocname);
         system (cmdbuf);
         tocfile = fopen (tocname, "r");
         if (!tocfile)
         {
             fprintf (stderr, "%s: unable to read tocfile\n", pgm);
             exit (2);
         }
         else
         {
             tocout (tocfile);
             fclose (tocfile);
             if (!logging) unlink (tocname);
         }
     }

     fprintf (stdout, "\f");

     exit (0);
 }
 /*Sdofile - process an input file */
 /*Hdofile*/
 /*E*/
 dofile (fd)
 FILE    *fd;
 {
     register int i;                 /* temporary                    */

     int     lineno = 1;             /* line number in current file  */

     register char *line;            /* current line pointer         */

     char    ibuf[MAXWIDTH];         /* original input line          */
     char    ebuf[MAXWIDTH];         /* line with tabs expanded      */

     register char *p;               /* temporary char pointer       */

     /* ------------------------------------------------------------ */
     /* initialize the function name to `.' - unknown                */
     /* retrieve the basename portion of the file name               */
     /* ------------------------------------------------------------ */

     strcpy (fnc_name, ".");

     /* ------------------------------------------------------------ */
     /* if building TOC, add this entry                              */
     /* ------------------------------------------------------------ */

     if (!isatty (1))
         fprintf (tocfile,
             "%s %s %d %d\n", fh_name, fnc_name, pageno, lineno);

     /* ------------------------------------------------------------ */
     /* if tabs are to be expanded, use the expansion buffer         */
     /* ------------------------------------------------------------ */

     if (tabstop) line = ebuf;
     else         line = ibuf;

     /* ------------------------------------------------------------ */
     /* process each line in the file, looking for triggers          */
     /* ------------------------------------------------------------ */

     while (fgets (ibuf, MAXWIDTH, fd) NE NULL)
     {
         if (logging GE 9) fprintf (stderr, "%s: LOG: %s", pgm, line);
     /* ------------------------------------------------------------ */
     /* expand the input line                                        */
     /* ------------------------------------------------------------ */

         expand (ebuf, ibuf);

         if (line[0] EQ SLASH AND line[1] EQ STAR)
         {
     /* ------------------------------------------------------------ */
     /* comment found - could be a trigger                           */
     /* ------------------------------------------------------------ */

             switch (line[2])
             {
                 case 'F':
                 case 'H':
                 {
                     if (logging GE 9) fprintf (stderr, "F/H header\n");
                     header (&lineno, line, fd);
                     break;
                 }
                 case 'P':
                 {
                     if (logging GE 9) fprintf (stderr, "page break\n");
                     print_head ();
                     lineno++;
                     break;
                 }
                 case 'S':
                 {
                     if (logging GE 9) fprintf (stderr, "subtitle\n");
                     getname (line, subttl);
                     lineno++;
                     break;
                 }
                 case 'T':
                 {
                     if (logging GE 9) fprintf (stderr, "title\n");
                     getname (line, title);
                     /* print_head (); */
                     lineno++;
                     break;
                 }
                 default:
                 {
                     if (logging GE 9) fprintf (stderr, "other comment\n");
                     print (&lineno, line);
                     break;
                 }
             }
         }
         else
         {
     /* ------------------------------------------------------------ */
     /* not a comment - check for function declaration               */
     /* if a form feed is found, start a new page with header        */
     /* ------------------------------------------------------------ */

             if (logging GE 9) fprintf (stderr, "not a comment\n");
             if (!nlvl AND !isatty (1)) infunc = ckfunc (lineno, line);
             if (*line EQ '\f') print_head ();
             else print (&lineno, line);
         }
     }

     page_line = LPP+1;      /* force new page after file            */
     title[0] = NUL;         /* clear title and subtitle             */
     subttl[0] = NUL;

     return;
 }
 /*Sheader - construct and print header box */
 /*Hheader*/
 /*E*/
 header  (lineno, line, fd)
 register int     *lineno;
 register char    *line;
 register FILE    *fd;
 {
     register char *p;

     if (line[2] EQ 'F')
     {
         getname (line, fh_name);
         if (BASENAMES) strcpy (fh_name, basename (fh_name));
         strcpy (fnc_name, ".");
     }
     else if (line[2] EQ 'H')
     {
         getname (line, fnc_name);
     }

     if (!isatty (1))
         fprintf (tocfile,
             "%s %s %d %d\n", fh_name, fnc_name, pageno, *lineno);

     print_head ();

     print (lineno, line);

     while (fgets (line, MAXWIDTH, fd) NE NULL AND
             notend (line))
     {
         if (line[0] EQ SLASH AND line[1] EQ STAR AND line[2] EQ 'P')
         {
             print_head ();
             (*lineno)++;
         }
         else
         {
             print (lineno, line);
         }
     }

     print (lineno, line);

     return;
 }
 /*Sgetname - get a string from a signal line */
 /*Hgetname */
 /*E*/
 getname (line, name)
 register char    *line;
 register char    *name;
 {
     register int     i;
     register int     j;

     /* ------------------------------------------------------------ */
     /* skip leading spaces in the trigger line                      */
     /* copy up to trailing asterisk or end-of-line                  */
     /* strip trailing spaces                                        */
     /* ------------------------------------------------------------ */

     for (i = 3; isspace(line[i]) AND i LT MAXWIDTH; i++);

     for (j = 0; line[i] AND line[i] NE '*'; i++, j++)
     {
         name[j] = line[i];
     }

     while (j-- GT 0 AND isspace (name[j]));

     name[++j] = NUL;

     return;
 }
 /*Sprint - print a line with line number */
 /*Hprint */
 /*E*/
 print (lineno, line)
 register int     *lineno;
 register char    *line;
 {
     register int llen = strlen (line);
     register int i;

     register char sc = specline ? '*' : ' ';

     int     j = 0;

     register char    dc = NUL;

     /* ------------------------------------------------------------ */
     /* new page with header if page length is exceeded              */
     /* ------------------------------------------------------------ */

     if (page_line GT LPP)
     {
         print_head ();
     }

     /* ------------------------------------------------------------ */
     /* if brace(s) found,                                           */
     /*   modify the nesting level by the net nesting delta          */
     /*   select the indicator according to the net delta            */
     /*   if nexting is back to zero (none), clear function name     */
     /* ------------------------------------------------------------ */

     if (fnd (line, &j))
     {
         nlvl += j;

         if (j LT 0) dc = '<';
         else if (j EQ 0) dc = '*';
         else dc = '>';

         i = nlvl;
         if (j LT 0) i++;
         fprintf (stdout, "%4d%c%2d%c ",
             (*lineno)++, sc, i, dc);
         if (nlvl EQ 0) strcpy (fnc_name, ".");
     }
     else
     {
         fprintf (stdout, "%4d%c    ", (*lineno)++, sc);
     }

     /* ------------------------------------------------------------ */
     /* break up long lines by finding the first space form the end  */
     /* ------------------------------------------------------------ */

     if (llen GT 132)
     {
         for (i = 132; i GE 0; i--)
         {
             if (line[i] EQ SPACE)
             {
                 fprintf (stdout, "%*.*s \\\n", i, i, line);
                 page_line++;
                 break;
             }
         }

         j = 79 - (llen - i);

         for (j; j GE 0; j--) putc (SPACE, stdout);

         fprintf (stdout, "%s", &line[i+1]);
     }
     else
     {
         fprintf (stdout, "%s", line);
     }

     page_line++;

     specline = FALSE;       /* true if function declaration     */

     return;
 }
 /*Sprint_head - print the page heading with page number */
 /*Hprint_head */
 /*E*/
 print_head ()
 {
     char    headbuf[80];
     register int len;

     sprintf (headbuf, "[ %s | %s <- %s",
         tim_lin, fh_name, fnc_name);

     for (len = strlen (headbuf); len LT 68; len++) headbuf[len] = SPACE;

     sprintf (&headbuf[68], "Page %-4d ]", pageno++);
     fprintf (stdout, "\f\n");
     if (!isatty (1))
         fprintf (stdout, "_______________________________________\
 ________________________________________");
     fprintf (stdout, "\n%s\n", headbuf);
     fprintf (stdout, "[-------------------------------+------\
 ---------------------------------------]\n");

     if (*title)
     {
         sprintf (headbuf, "[    %s", title);
     }
     else
     {
         sprintf (headbuf, "[    %s", fh_name);
     }
     for (len = strlen (headbuf); len LT 78; len++) headbuf[len] = SPACE;
     headbuf[78] = ']';
     fprintf (stdout, "%s\n", headbuf);

     if (*subttl)
     {
         sprintf (headbuf, "[    %s", subttl);
     }
     else
     {
         sprintf (headbuf, "[    %s", fnc_name);
     }
     for (len = strlen (headbuf); len LT 78; len++) headbuf[len] = SPACE;
     headbuf[78] = ']';
     fprintf (stdout, "%s", headbuf);

     if (!isatty (1))
         fprintf (stdout, "\r_______________________________________\
 ________________________________________");
     fprintf (stdout, "\n\n");

     page_line = LINESINHEAD;

     return;
 }
 /*S fnd - return true if a brace is found */
 /*H fnd */
 /*E*/
 fnd (in, nchg)
 register char *in;
 register int    *nchg;
 {
 #   define LBRACE   '{'
 #   define RBRACE   '}'
 #   define SHARP    '#'
 #   define COLON    ':'

     register found = FALSE;         /* true if keyword found        */

     register char blank = TRUE;     /* used to check for shell/make */
                                     /* comments beginning with #/:  */
     register int inshcomment = FALSE;   /* true if in shell comment */

     *nchg = 0;              /* initialize net change to zero        */

     /* ------------------------------------------------------------ */
     /* check each character of the line                             */
     /* ------------------------------------------------------------ */

     for (in; *in; in++)
     {
         if (!incomment AND !inshcomment AND !indquote AND !insquote)
         {
             if (logging GE 9) fprintf (stderr, "not in comment or quote\n");
             if (*in EQ SLASH AND *(in+1) EQ STAR)
             {
                 incomment = TRUE;
                 blank = FALSE;
                 if (logging GE 9) fprintf (stderr, "new comment\n");
             }
             else if (blank AND
                      ((*in EQ SHARP OR *in EQ COLON) AND
                      (*(in+1) NE LBRACE AND *(in+1) NE RBRACE))
                     )
             {
                 inshcomment = TRUE;
                 blank = FALSE;
                 if (logging GE 9) fprintf (stderr, "new shell comment\n");
             }
             else if (*in EQ DQUOTE AND
                     (*(in-1) NE BSLASH OR *(in-2) EQ BSLASH))
             {
                 indquote = TRUE;
                 blank = FALSE;
                 if (logging GE 9) fprintf (stderr, "new dquote\n");
             }
             else if (*in EQ SQUOTE AND
                     (*(in-1) NE BSLASH OR *(in-2) EQ BSLASH))
             {
                 insquote = TRUE;
                 blank = FALSE;
                 if (logging GE 9) fprintf (stderr, "new squote\n");
             }
             else if (*in EQ LBRACE)
             {
                 (*nchg)++;
                 found = TRUE;
                 blank = FALSE;
                 if (logging GE 9) fprintf (stderr, "nest in\n");
             }
             else if (*in EQ RBRACE)
             {
                 (*nchg)--;
                 found = TRUE;
                 blank = FALSE;
                 if (logging GE 9) fprintf (stderr, "nest out\n");
             }
             else if (!isspace (*in))
             {
                 blank = FALSE;
             }
         }
         else if (incomment AND *in EQ STAR AND *(in+1) EQ SLASH)
         {
             incomment = FALSE;
             if (logging GE 9) fprintf (stderr, "end comment\n");
         }
         else if (indquote AND *in EQ DQUOTE AND
                 (*(in-1) NE BSLASH OR *(in-2) EQ BSLASH))
         {
             indquote = FALSE;
             if (logging GE 9) fprintf (stderr, "end dquote\n");
         }
         else if (insquote AND *in EQ SQUOTE AND
                 (*(in-1) NE BSLASH OR *(in-2) EQ BSLASH))
         {
             insquote = FALSE;
             if (logging GE 9) fprintf (stderr, "end squote\n");
         }
     }

     return found;
 }
 /*Stocout - print out the table of contents */
 /*Htocout */
 /*E*/
 tocout (toc)
 FILE    *toc;
 {
     char    buf[80];
     char    filenam[80];
     char    fncnam[80];
     int     page;
     int     line;

     char    outline[80];

     register int toclines = 99;

     while (fscanf (toc, "%s%s%d%d", filenam, fncnam, &page, &line) EQ 4)
     {
         if (toclines GT 54)
         {
             printf ("\f\n\
                              _____________________\n\
                              [ TABLE OF CONTENTS ]\r\
                              _____________________\n\n\
                 File -> Function                     Page    Line\r\
 ________________________________________\
 ________________________________________\n\n");
             toclines = 0;
         }

         toclines++;

         printf ("\
     %16s -> %-16.16s ............ %3d   %5d\n",
             filenam, *fncnam EQ '.' ? "START" : fncnam, page, line);
     }
     return;
 }
 /*S expand - expand tabs to tabstop */
 /*H expand */
 /*E*/
 expand (to, from)
 register char *to;
 register char *from;
 {
     register int i;
     register int tofill;

 #   define BACKSPACE '\b'
 #   define FORMFEED '\f'
 #   define NEWLINE '\n'
 #   define RETURN '\r'
 #   define TAB '\t'

     i = 0;

     while (*from)
     {
         switch (*from)
         {
             case    TAB:
                 tofill = tabstop - (i % tabstop);
                 i += tofill;
                 while (tofill--) *(to++) = SPACE;
                 break;
             case    NEWLINE:
             case    RETURN:
                 i = 0;
             case    FORMFEED:
                 *(to++) = *from;
                 break;
             case    BACKSPACE:
                 i--;
                 *(to++) = *from;
                 break;
             default:
                 i++;
                 *(to++) = *from;
                 break;
         }

         from++;
     }

     *to = NUL;

     return;
 }
 /*S ckfunc - check line for function declaration */
 /*H ckfunc */
 /*E*/

 #define isidchr(c) (isalnum(c) || (c == '_'))

 ckfunc (lineno, s)
 register int lineno;
 register char   *s;
 {
     register char *p;
     register int  Cnt;
     register int  i;
     register int  result;
     register char found = FALSE;

     static char *_fnm = "ckfunc";

     char FunctionName[40];

     if (logging GE 3)
     {
         fprintf (stderr,
             "%s<%s>: LOG: ckfunc called - line = %s",
             pgm, _fnm, s);
     }

     if(!strcmp (fnc_name, ".") AND !incomment && !indquote && !insquote)
     {
         found = TRUE;

         while (found)
         {
             found = FALSE;
             p = FunctionName;
             for (s; isascii (*s) && isspace (*s) && *s; s++);
             if( *s == '*' )
             {
                 for (++s; isascii (*s) && isspace (*s) && *s; s++);
             }

             if ((*s == '_') || isalpha(*s))
             {
                 while (isidchr (*s)) *p++ = *s++;

                 *p = '\0';

                 for (found = FALSE, i = 0;
                      !found AND ReservedWord[i]; i++)
                 {
                     if (!(result = strcmp (FunctionName, ReservedWord[i])))
                         found = TRUE;

                     if  (result < 0) break;
                 }

                 if (logging GE 3 AND found)
                 {
                     fprintf (stderr,
                         "%s<%s>: LOG: reserved word = %s\n",
                         pgm, _fnm, FunctionName);
                 }
             }
         }

         if (logging GE 3)
         {
             fprintf (stderr,
                 "%s<%s>: LOG: last word = %s\n",
                 pgm, _fnm, FunctionName);
         }

         for (s; isascii (*s) && isspace (*s) && *s; s++);

         if (*s EQ '(')
         {
             for (found = FALSE; *s AND !found; s++)
                 found = *s EQ ')';

             if (found)
             {
                 for (; *s AND isspace (*s); s++);

                 found = *s NE ';';

                 if (found)
                 {
                     strcpy (fnc_name, FunctionName);
                     fprintf (tocfile,
                         "%s %s %d %d\n",
                         fh_name, fnc_name, pageno-1, lineno);
                     specline = TRUE;
                 }
             }
         }
     }

     if (logging GE 3)
     {
         fprintf (stderr,
     "%s<%s>: LOG: this line does%s contain a function declaration\n",
             pgm, _fnm, found ? "" : " not");
     }

     return found;
 }
 /*S basename - return the basename part of a pathname */
 /*H basename *********************************************************
 *
 *                                   basename
 *
 *  given a (presumed) pathname, return the part after the last slash
 *
 *********************************************************************/
 /*E*/
 char *
 basename (str)
 register char *str;
 {
     register char *ret;

     if (ret = strrchr (str, '/')) ret++;
     else ret = str;

     return ret;
 }


 CPM2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\CPM2.C

 /*-------------------------------------------------------------------*/
 /*                                                                   */
 /*  Critical Path Method Project Scheduler - 18 Sept 83 - E. Dong    */
 /*  Based on BASIC version, "Hard Hat Management: Two On-Site        */
 /*  Tools", by Richard Parry, INTERFACE AGE, February, 1981.         */
 /*                                                                   */
 /*  Translated into CIC86 "C" by Edward V. Dong                      */
 /*                                                                   */
 /*  Modifications: (1) No PERT option.                               */
 /*                 (2) Added GANTT chart output.                     */
 /*                 (3) Allow naming of activities.                   */
 /*                                                                   */
 /*  Updated 30 Sept 83  - Fix Gantt chart output.                    */
 /*                                                                   */
 /*-------------------------------------------------------------------*/

 #include "stdio.h"
 #define  BEGIN  {
 #define  END    }
 #define  SIZE   100

 int i, j, k, m, num;                    /* Internal Integer Parms    */

 int c1, c2, du, l1, m1, m2, pl;

 int ml[SIZE], mo[SIZE], mp[SIZE], cp[SIZE], me[SIZE], sd[SIZE], ic[20];
 int s[SIZE], f[SIZE], d[SIZE], e[SIZE], l[SIZE], f1[SIZE];

 char jobname[SIZE][9];                                /* Job names */

 main()

 BEGIN
 printf("CPM: Project Scheduler\n\n");                /* identify program */

 /* initialize variables */
 c1 = 0; c2 = 0; du = 0; m1 = 0; m2 = 0; pl = 0;

 printf("Enter number of activities: ");                /* get # of activities
 scanf("%d",&num);

 for (i=1; i<num+1; i++)                                /* input routine */
         BEGIN
         printf("Activity %d\n",i);
         getdata();
         printf("\n");
         END

 printf("\n--> SORTING IN PROGRESS <--\n");        /* call sort routine */
 sort();

 printf("Activity #\tName\t");                      /* display sort */
 printf("From\tTo\tDuration\n");                        /* display sort */
 for (i=1; i<num+1; i++)
         BEGIN
         printf("%d\t\t%s\t%d\t%d\t%d\n",i,jobname[i],s[i],f[i],d[i]);
         END

 cpm();                                 /* do critical path analysis */
 c2 = 0;
 printf("\nCP Analysis is:\n");
 printf("[EST   = Earliest Starting Time]\n");
 printf("[LFT   = Latest  Finishing Time]\n");
 printf("[FLOAT = Float  or  Slack  Time]\n");
 printf("Name\tFrom\tTo\tEST\tLFT\tFLOAT\n");
 for (i=1; i<num+1; i++)
         BEGIN
         printf("%s\t",jobname[i]);
         printf("%d\t%d\t%d\t%d\t%d\n",s[i],f[i],e[s[i]],l[f[i]],f1[i]);
         END
 printf("\nThe Critical Path Length is %d\n",pl);
 printf("\nThe Critical Path is:\nName\tFrom\tTo\n");
 i=1; while (f1[i] != 0) i++;        /* locate start of critical path */
 cplout();                        /* critical path printout */
 gantt();                        /* display GANTT chart */
 END

 /* Sort Data Subroutine, Using Start Node as Key */
 sort()
 BEGIN
 int sw, temp;
 sw = 0;
 for (i=1; i<num; i++)
         BEGIN
         j = i + 1;
         if (s[i] > s[j])
                 BEGIN
                 temp = s[i]; s[i] = s[j]; s[j] = temp;
                 temp = f[i]; f[i] = f[j]; f[j] = temp;
                 temp = d[i]; d[i] = d[j]; d[j] = temp;
                 sw = 1;
                 END
         END
 if (sw==1) sort();        /* sort again if needed */
 END

 cpm()
 BEGIN
 printf("--> CPM ANALYSIS IN PROGRESS <--\n");

 /* compute earliest starting time */
 c1 = 0; c2 = 0; pl = 0;
 for (i=1; i<num+1; i++)
         BEGIN
         m1 = e[s[i]] + d[i];
         if (e[f[i]] <= m1) e[f[i]] = m1;
         END

 /* compute latest finishing time */
 l[f[num]] = e[f[num]];
 for (i=num; i>0; i--)
         BEGIN
         l1 = s[i]; m2 = l[f[i]] - d[i];
         if ((l[l1] >= m2) || (l[l1] == 0))
                 l[l1] = m2;
         END

 /* compute float time */
 for (i=1; i<num+1; i++)
         BEGIN
         f1[i] = l[f[i]] - e[s[i]] - d[i];
         if (f1[i] == 0) c1 = c1 + 1;
         END

 /* compute critical path length */
 for (i=1; i<num+1; i++)
         BEGIN
         if (l[f[i]] > pl) pl = l[f[i]];
         END

 /* compute critical path */
 i = 0;
 while (f[i] != 0) i++;
 cpm_test:
         c2 = c2 + 1; cp[i] = cp[i] + 1;
         if (i > num) goto cpm_exit;
 for (m=1; m<num+1; m++)
         BEGIN
         if (s[m] != f[i]) continue;
         else if (f1[m] != 0) continue;
                 else
                         BEGIN
                         i=m;
                         goto cpm_test;
                         END
         END
 cpm_exit:
         if (c1 != c2) du = du + 1;
 END

 /* Input Data Subroutine */
 getdata()
 BEGIN
         int temp;
         printf("Jobname:\t\t");        scanf("%s",jobname[i]);
         printf("From:\t\t");         scanf("%d",&temp); s[i] = temp;
         printf("To:\t\t");         scanf("%d",&temp); f[i] = temp;
         printf("Duration:\t");         scanf("%d",&temp); d[i] = temp;
         while (f[i] > num)
                 BEGIN
                 printf("*** End Node # %d ",f[i]);
                 printf("Not =< # (%d) of Activities ***\n",num);
                 printf("To: ");
                 scanf("%d",f[i]);
                 END
         if (s[i] >= f[i])
                 BEGIN
                 printf("*** Start Node (%d)",s[i]);
                 printf("Must Be < End Node (%d) ***\n",f[i]);
                 printf("\n*** Redo Entry ***\n");
                 getdata();
                 END
 END

 /* critical path printout */
 cplout()
 BEGIN
 int iname, jname;

 iname = s[i];
 jname = f[i];
 printf("%s\t%d\t%d\n",jobname[i],iname,jname);
 c2 = c2 + 1;
 if (i<=num)
         BEGIN
         for (m=1; m<num+1; m++)
                 BEGIN
                 if ((s[m]==f[i]) && (f1[m]==0))
                         BEGIN
                         i = m;
                         cplout();
                         END
                 END
         END
 if (c1 != c2) printf("There is more than one critical path.\n");
 END

 /* generate GANTT chart */
 gantt()
 BEGIN

 float linelen, scale, xtemp;
 int limit, incrm, step;
 char newpg, symbol;

 printf("%cGANTT Chart for Project:\n\n",newpg);
 printf("Non-critical path is denoted as ==\n");
 printf("    Critical path is denoted as **\n\n");

 /* calculate chart scaling */
 linelen = 60.0;
 scale = linelen/pl;
 incrm = scale;
 step=1;
 while (incrm < 1)
         BEGIN
         limit = 10.0 * scale;
         step = 60 / limit;
         incrm = limit;
         END

 /* generate ruler line for chart */
 printf("               0");
 for (j=0; j<pl+step; j=j+step)
         BEGIN
         for (k=0; k<incrm; k++)
                 BEGIN
                 printf("-");
                 END
         printf("+");
         END
 printf("\n");

 /* generate GANTT waterfall */
 for (j=1; j<num+1; j++)
         BEGIN
         printf("%8s\t",jobname[j]);
         xtemp = e[s[j]] * scale;
         limit = (xtemp + 0.5);
         for (k=0; k<limit; k++)
                 BEGIN
                 printf(" ");
                 END
         if (f1[j]==0) symbol = '*';
                 else  symbol = '=';
         xtemp = l[f[j]] * scale - xtemp;
         limit = (xtemp + 0.5);
         for (k=0; k<limit; k++)
                 BEGIN
                 printf("%c",symbol);
                 END
         printf("\n");
         END
 END


 CPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CPRINTF.C

 #include <stdio.h>

 extern        int        putch();

 cprintf(fmt, arg)
 char *fmt;
 int arg;
 /*
  *        Formatted output directly to the console.  This functions uses the
  *        system dependent putch() for output.  See the _printf() function
  *        for a description of the <fmt> formatting string.
  */
 {
         return(_printf(NULL, putch, fmt, &arg));
 }


 CPUTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CPUTS.C

 #include <stdio.h>

 extern        int        putch();

 void cputs(data)
 register char *data;
 /*
  *        Write the characters in <data> directly to the console using the
  *        system dependent putch() function.  A newline WILL NOT be written
  *        after the data.
  */
 {
         while(*data)
                 putch(*data++);
 }


 CRC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\CRC.C

 /****************************************************************************
 *
 *               Cyclic Redundancy Check (CRC) functions
 *
 *****************************************************************************

 /*
 *   crc_clear:
 *        This function clears the CRC to zero. It should be called prior to
 *        the start of the processing of a block for both received messages,
 *        and messages to be transmitted.
 *
 *        Calling sequence:
 *
 *        short crc;
 *        crc = crc_clear();
 */
 short crc_clear()
 {
         return(0);
 }
 /*
 *   crc_update:
 *        this function must be called once for each character which is
 *        to be included in the CRC for messages to be transmitted.
 *        This function is called once for each character which is included
 *        in the CRC of a received message, AND once for each of the two CRC
 *        characters at the end of the received message. If the resulting
 *        CRC is zero, then the message has been correctly received.
 *
 *   Calling sequence:
 *
 *        crc = crc_update(crc,next_char);
 */
 short crc_update(crc,crc_char)
 short crc;
 char crc_char;
 {
         long x;
         short i;

 /* "x" will contain the character to be processed in bits 0-7 and the CRC
 /* in bits 8-23. Bit 24 will be used to test for overflow, and then cleared
 /* to prevent the sign bit of "x" from being set to 1. Bits 25-31 are not
 /* used. ("x" is treated as though it is a 32 bit register).
         x = ((long)crc << 8) + crc_char;    /* Get the CRC and the character

 /* Repeat the following loop 8 times (for the 8 bits of the character).
         for(i = 0;i < 8;i++)
         {

 /* Shift the high-order bit of the character into the low-order bit of the
 /* CRC, and shift the high-order bit of the CRC into bit 24.
                 x = x << 1;                        /* Shift "x" left one bit

 /* Test to see if the old high-order bit of the CRC was a 1.
                 if(x & 0x01000000)                     /* Test bit 24 of "x"

 /* If the old high-order bit of the CRC was a 1, exclusive-or it with a one
 /* to set it to 0, and exclusive-or the CRC with hex 1021 to produce the
 /* CCITT-recommended CRC generator of: X**16 + X**12 + X**5 + 1. To produce
 /* the CRC generator of: X**16 + X**15 + X**2 + 1, change the constant from
 /* 0x01102100 to 0x01800500. This will exclusive-or the CRC with hex 8005
 /* and produce the same CRC that IBM uses for their synchronous transmission
 /* protocols.
                         x = x ^ 0x01102100;     /* Exclusive-or "x" with a...
                                               /* ...constant of hex 01102100
 /* And repeat 8 times.
         }                                               /* End of "for" loop

 /* Return the CRC as the 16 low-order bits of this function's value.
         return(((x & 0x00ffff00) >> 8)); /* AND off the unneeded bits and...
                                   /* ...shift the result 8 bits to the right

 }
 /*
 *   crc_finish:
 *        This function must be called once after all the characters in a bloc
 *        have been processed for a message which is to be TRANSMITTED. It
 *        returns the calculated CRC bytes, which should be transmitted as the
 *        two characters following the block. The first of these 2 bytes
 *        must be taken from the high-order byte of the CRC, and the second
 *        must be taken from the low-order byte of the CRC. This routine is NO
 *        called for a message which has been RECEIVED.
 *
 *   Calling sequence:
 *
 *        crc = crc_finish(crc);
 */
 short crc_finish(crc)
 short crc;
 {
 /* Call crc_update twice, passing it a character of hex 00 each time, to
 /* flush out the last 16 bits from the CRC calculation, and return the
 /* result as the value of this function.
         return(crc_update(crc_update(crc,'\0'),'\0'));

 }

 /*
 * This is a sample of the use of the CRC functions, which calculates the
 * CRC for a 1-character message block, and then passes the resulting CRC back
 * into the CRC functions to see if the "received" 1-character message and CRC
 * are correct.
 */
 main()
 {

         short crc;                                     /* The calculated CRC
         char crc_char;                            /* The 1-character message
         char x, y;            /* 2 places to hold the 2 "received" CRC bytes

         crc_char = 'A';                    /* Define the 1-character message
         crc = crc_clear();      /* Reset the CRC to "transmit" a new message
         crc = crc_update(crc,crc_char);   /* Update the CRC for the first...
                                    /* ...(and only) character of the message
         crc = crc_finish(crc);        /* Finish the transmission calculation
         x = (char)((crc & 0xff00) >> 8);  /* Extract the high-order CRC byte
         y = (char)(crc & 0x00ff);          /* And extract the low-order byte
         printf("%04x\n",crc);                           /* Print the results

         crc = crc_clear();                 /* Prepare to "receive" a message
         crc = crc_update(crc,crc_char);   /* Update the CRC for the first...
                                    /* ...(and only) character of the message
         crc = crc_update(crc,x);     /* Pass both bytes of the "received"...
         crc = crc_update(crc,y);           /* ...CRC through crc_update, too
         printf("%04x\n",crc);    /* If the result was 0, then the message...
                                             /* ...was received without error

 }


 CRE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\CRE.C

 /* SDB - relation creation routines */

 #include "sdbio.h"

 /* db_rcreate(rname) - begin the creation of a new relation */
 struct relation *db_rcreate(rname)
   char *rname;
 {
     struct relation *rptr;

     /* allocate the relation structure */
     if ((rptr = calloc(1,sizeof(struct relation))) == NULL)
         return (db_nerror(INSMEM));

     /* initialize the relation structure */
     stccpy(rptr->rl_name,rname,RNSIZE);
     rptr->rl_tcnt = 0;
     rptr->rl_tmax = 0;
     rptr->rl_data = 512;
     rptr->rl_size = 1;
     rptr->rl_header.hd_attrs[0].at_name[0] = 0;

     /* return the new relation structure pointer */
     return (rptr);
 }

 /* db_rcheader - create the relation header */
 int db_rcheader(rptr)
   struct relation *rptr;
 {
     char rname[RNSIZE+1],filename[RNSIZE+13];

     /* initialize the relation file header */
     db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
     db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
     db_cvbytes(rptr->rl_data,rptr->rl_header.hd_data);
     db_cvbytes(rptr->rl_size,rptr->rl_header.hd_size);

     /* create the relation file name */
     stccpy(rname,rptr->rl_name,RNSIZE); rname[RNSIZE] = 0;
     sprintf(filename,"%s.sdb",rname);

     /* create the relation file */
     if ((rptr->rl_fd = creat(filename,0)) == -1) {
         free(rptr);
         return (db_ferror(RELCRE));
     }

     /* write the header to the relation file */
     if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
         close(rptr->rl_fd);
         free(rptr);
         return (db_ferror(BADHDR));
     }

     /* return successfully */
     return (TRUE);
 }

 /* db_rctuples - create the relation tuples */
 int db_rctuples(rptr,tcnt)
   struct relation *rptr; unsigned int tcnt;
 {
     unsigned int i;
     char *tbuf;

     /* store the number of tuples */
     rptr->rl_tmax = tcnt;

     /* allocate a tuple buffer */
     if ((tbuf = calloc(1,rptr->rl_size)) == NULL)
         return (db_ferror(INSMEM));

     /* write null tuples into the file */
     for (i = 0; i < tcnt; i++)
         if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
             free(tbuf);
             return (db_ferror(INSBLK));
         }

     /* free the tuple buffer */
     free(tbuf);

     /* return successfully */
     return (TRUE);
 }

 /* db_rcdone(rptr) - finish the creation of a new relation */
 int db_rcdone(rptr)
   struct relation *rptr;
 {
     /* initialize the relation file header */
     db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
     db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);

     /* write the header to the relation file */
     lseek(rptr->rl_fd,0L,0);
     if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
         close(rptr->rl_fd);
         free(rptr);
         return (db_ferror(BADHDR));
     }

    /* close the relation file */
     close(rptr->rl_fd);

     /* free the relation structure */
     free(rptr);

     /* return successfully */
     return (TRUE);
 }

 /* db_rcattr(rptr,aname,type,size) - add an attribute to relation being creat
 */
 int db_rcattr(rptr,aname,type,size)
   struct relation *rptr; char *aname; int type,size;
 {
     int i;

     /* look for attribute name */
     for (i = 0; i < NATTRS; i++)
         if (rptr->rl_header.hd_attrs[i].at_name[0] == 0)
             break;
         else if (db_sncmp(aname,rptr->rl_header.hd_attrs[i].at_name,ANSIZE) =
 )
             return (db_ferror(DUPATT));

     /* check for too many attributes */
     if (i == NATTRS)
         return (db_ferror(MAXATT));

     /* store the new attribute */
     stccpy(rptr->rl_header.hd_attrs[i].at_name,aname,ANSIZE);
     rptr->rl_header.hd_attrs[i].at_type = type;
     rptr->rl_header.hd_attrs[i].at_size = size;

     /* terminate the attribute table */
     if (++i != NATTRS)
         rptr->rl_header.hd_attrs[i].at_name[0] = 0;

     /* update the tuple size */
     rptr->rl_size += size;

     /* return successfully */
     return (TRUE);
 }



 CREAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CREAT.C

 #include <osbind.h>
 #include <stdio.h>

 int creat(filename, pmode)
 register char *filename;
 register int pmode;
 /*
  *        Create a new file with the given <filename>.  If a file with
  *        the name already exists, it will be truncated to zero bytes.
  *        Since the OS doesn't do this properly, the file is actually
  *        deleted and then re-created.  <pmode> specifies the attributes
  *        initially given to the file.  Valid <pmode> values are:
  *                _CRErw                read/write
  *                _CREro                read only
  *                _CREh                hidden file
  *                _CREs                system file
  *                _CREv                volume label
  *        If _CRErw or _CREv modes are specified, they must be the only
  *        mode given.  Other modes may be combined with the | operator.
  *
  *        Implementation Note:  File is deleted first to avoid a TOS bug
  *        that allows creation of duplicate file names.
  */
 {
         register int rv;

         rv = Fdelete(filename);
         if((rv == 0) || (rv == -33))        /* SUCCESS or FILE-NOT-FOUND */
                 rv = Fcreate(filename, pmode);
         return(rv);
 }


 CROOT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\KWMV\CROOT.C

 /* Copyright (C) 1981,1982, 1983 by Manx Software Systems */
 #include <errno.h>
 #include <fcntl.h>
 #ifndef NULL
 #define NULL ((void *)0)
 #endif

 char *get_first(), *get_next(), *sbrk();

 #define ARGMAX 256
 static char *Argv[ARGMAX];
 static int argvsize;
 static int Argc;
 static char curr_path[128];

 noper()
 {
         return 0;
 }

 int (*cls_)() = noper;
 extern char _ioflg[];

 Croot(cp, first)
 register char *cp;
 {
         register char *cp2;
         char *save;
         char *wild_match;
         char *index(),*rindex(), *save_str();
         char *path,*copy; int j;

         _ioflg[0] = isatty(0);        /* set flag for i/o routines */
         _ioflg[1] = isatty(1);        /* set flag for i/o routines */
         _ioflg[2] = isatty(2);        /* set flag for i/o routines */


         /* Null out first argument */
         Argv[0] = "";
         Argc = first;

         /* loop through arguments */
         for (;;)
         {
                 /* skip blanks */
                 while (*cp == ' ' || *cp == '\t')
                         ++cp;

                 /* if you're at the end of command line, you're done */
                 if (*cp == 0)
                         break;

                 /* find beginning of next argument */
                 cp2 = cp;        /* save original pointer to the string */
                 *cp2 = (*cp2 == '/' ? '\\' : *cp2);
                 while (*++cp2)
                 {
                         /* if you hit a space char - stick a null in to termi
                            argument
                          */
                         if (*cp2 == ' ' || *cp2 == '\t')
                         {
                                 *cp2++ = 0;
                                 break;
                         }
                         *cp2 = (*cp2 == '/' ? '\\' : *cp2);
                 }

                 /* if no wild card characters, do it the old fashioned way */
                 if (index(cp,'*') == NULL && index(cp,'?') == NULL)
                 {
                         /* update the next argv pointer */
                         Argv[Argc] = cp;
                         /* bump the argument count */
                         if (++Argc == ARGMAX)
                                 abort();
                 }
                 else
                 {
                         /* if there is a path included, save it off */
                         if ((path = rindex(cp,'\\')) || (path = rindex(cp,'/'
                         {
                                 copy = cp;
                                 /* copy to curr_path, mapping / to \ */
                                 for (j = 0; j < sizeof(curr_path) && copy !=
                                         curr_path[j] = (*copy == '/' ? '\\' :
                                 /* terminate string */
                                 curr_path[j] = '\0';
                         }
                         else
                         /* null path */
                                 curr_path[0] = 0;
                         if (wild_match = get_first(cp))
                         {
                                 /* update the next argv pointer */
                                 Argv[Argc]= save_str(wild_match);
                                 /* bump the argument count */
                                 if (++Argc == ARGMAX)
                                         abort();
                                 /* get the rest of the matching file names */
                                 while (wild_match = get_next())
                                 {

                                         /* update the next argv pointer */
                                         Argv[Argc] = save_str(wild_match);
                                         /* bump the argument count */
                                         if (++Argc == ARGMAX)
                                                 abort();
                                 }
                         }
                 }
                 cp = cp2;        /* point to beginning of next argument */
         }
         Argv[Argc] = NULL;
         main(Argc,Argv);
         exit(0);
 }

 char *save_str(s)
         register char *s;
 {
         register char *r;
         int pathlen;
         /* squirrel away matched file name */
         if (NULL == (r = sbrk(strlen(s)+(pathlen = strlen(curr_path))+1)))
                 abort();
         strcat(curr_path,s);
         strcpy(r,curr_path);
         curr_path[pathlen] = '\0';
         return r;
 }

 abort()
 {
         write(2, "Too many args.", 14);
         _exit(200);
 }

 exit(code)
 {
         (*cls_)();
         _exit(code);
 }

 typedef struct
 {
         char dos_reserved[21];
         char attribute;
         unsigned file_time;
         unsigned file_date;
         long file_size;
         char file_name[13];
 } fcb;
 fcb wildcard;

 char *get_first(fname)
         char *fname;
 {
         register int result;
         /* set the disk transfer address */
         bdos(0x1A,&wildcard);
         result = bdos(0x4E,fname,0);
         /* make the find first call */
         if(2 == result || 18 == result)
                 return NULL;
         return &(wildcard.file_name[0]);
 }

 char *get_next(fname)
         char *fname;
 {
         register int result;
         /* set the disk transfer address */
         bdos(0x1A,&wildcard);
         result = bdos(0x4f,0,0);
         /* make the find next call */
         if (18 == result)
                 return NULL;
         return &(wildcard.file_name[0]);
 }


 CRT_LINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\LBLCS\CRT_LINE.C





 /******************************************************************
  *
  * name                crt_line - plot lines w/ BIOS point set routine
  *
  * synopsis        crt_line(row1,col1,row2,col2,color);
  *                int row1,col2,row2,color;
  *
  * description        This routine uses a simple octantal DDA to plot
  *                lines on your graphics screen.  The screen
  *                needs to be set to graphics mode, of course...
  *
  * notes        This routine is still written in 'C'.  It is faster
  *                than many of the other line draw routines I have seen
  *                around, but still relatively slow compared to assembler.
  *
  *                Since this routine uses the BIOS point set routine,
  *                it will run on color or mono display adaptors, in
  *                any supported graphics mode.  The disadvantage of
  *                using the BIOS point set routine is that it is
  *                extremely slow.....  The speed of this routine is
  *                entirely limited by the speed of the BIOS pset call.
  *
  * bugs                Better be sure that your x and y values are in range
  *                no range checking is done.
  ********************************************************************/

 crt_line(startx, starty, endx, endy, color)
 int  startx, starty, endx, endy, color;
     {
     int count, deltax, deltay, error, t;


     if (endx < startx)
         {
         t = startx;             /* fold quadrants 2, 3 to 1, 4  */
         startx = endx;
         endx = t;
         t = starty;
         starty = endy;
         endy = t;
         }
     deltax = endx - startx;
     deltay = endy - starty;
     if (deltay < 0)
         {
         if (-deltay > deltax)   /* octant 7             */
             {
             count = -deltay;
             error = deltay / 2;
             do
                 {
                 crt_pset(startx, starty, color);

                 starty--;
                 if ((error += deltax) >= 0)
                     {
                     startx++;
                     error += deltay;
                     }
                 }
             while (--count >= 0);
             }
         else                    /* octant 8             */
             {
             count = deltax;
             error = -deltax / 2;
             do
                 {

                 crt_pset(startx, starty, color);

                 startx++;
                 if ((error -= deltay) >= 0)
                     {
                     starty--;
                     error -= deltax;
                     }
                 }
             while (--count >= 0);
             }
         }
     else if (deltay > deltax)       /* octant 2         */
         {
         count = deltay;
         error = -deltay / 2;
         do
             {
                 crt_pset(startx , starty, color);

             starty++;
             if ((error += deltax) >= 0)
                 {
                 startx++;
                 error -= deltay;
                 }
             }
         while (--count >= 0);
         }
     else                        /* octant 1             */
         {
         count = deltax;
         error = -deltax/2;
         do
             {

                 crt_pset(startx , starty, color);

             startx++;
             if ((error += deltay) >= 0)
                 {
                 starty++;
                 error -= deltax;
                 }
             }
         while (--count >= 0);
         }
     }







 CRT_LN32.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\LBLCS\CRT_LN32.C






 /******************************************************************
  *
  * name                crt_line320 - plot lines w/ fast 320x200 point routine
  *
  * synopsis        crt_line320(row1, col2, row2, col2, color)
  *                int row1,col2,row2,col2,color;
  *
  * description        This routine uses a simple octantal DDA to plot
  *                lines on your 320 x 200 COLOR graphics screen.  The
  *                screen needs to be set to graphics mode, of course...
  *
  * notes        This routine is still written in 'C'.  It is faster
  *                than many of the other line draw routines I have seen
  *                around, but still relatively slow compared to assembler.
  *                Next released version of the libraries will have this
  *                one written in assembler...
  *
  *                Works only in 320x200 color graphics mode!!
  *
  * bugs                Better be sure that your x and y values are in range
  *                no range checking is done.
  ********************************************************************/

 crt_line320(startx, starty, endx, endy, color)
 int  startx, starty, endx, endy, color;
     {
     int count, deltax, deltay, error, t;


     if (endx < startx)
         {
         t = startx;             /* fold quadrants 2, 3 to 1, 4  */
         startx = endx;
         endx = t;
         t = starty;
         starty = endy;
         endy = t;
         }
     deltax = endx - startx;
     deltay = endy - starty;
     if (deltay < 0)
         {
         if (-deltay > deltax)   /* octant 7             */
             {
             count = -deltay;
             error = deltay / 2;
             do
                 {
 /*              if (flag)
                     pixerase(startx + XOFF, YOFF - starty);
                 else
                     pixplot(startx + XOFF, YOFF - starty);

 */
                 crt_ps32(startx, starty, color);

                 starty--;
 Š                if ((error += deltax) >= 0)
                     {
                     startx++;
                     error += deltay;
                     }
                 }
             while (--count >= 0);
             }
         else                    /* octant 8             */
             {
             count = deltax;
             error = -deltax / 2;
             do
                 {
 /*
                 if (flag)
                     pixerase(startx + XOFF, YOFF - starty);
                 else
                     pixplot(startx + XOFF, YOFF - starty);

 */

                 crt_ps32(startx, starty, color);


                 startx++;
                 if ((error -= deltay) >= 0)
                     {
                     starty--;
                     error -= deltax;
                     }
                 }
             while (--count >= 0);
             }
         }
     else if (deltay > deltax)       /* octant 2         */
         {
         count = deltay;
         error = -deltay / 2;
         do
             {
 /*
             if (flag)
                 pixerase(startx + XOFF, YOFF - starty);
             else
                 pixplot(startx + XOFF, YOFF - starty);

 */
                 crt_ps32(startx , starty, color);


             starty++;
             if ((error += deltax) >= 0)
                 {
                 startx++;
                 error -= deltay;
                 }
             }
         while (--count >= 0);
         }
 Š    else                        /* octant 1             */
         {
         count = deltax;
         error = -deltax/2;
         do
             {

 /*
           if (flag)
                 pixerase(startx + XOFF, YOFF - starty);
             else
                 pixplot(startx + XOFF, YOFF - starty);
 */
                 crt_ps32(startx , starty, color);


             startx++;
             if ((error += deltay) >= 0)
                 {
                 starty++;
                 error -= deltax;
                 }
             }
         while (--count >= 0);
         }
     }




 CRYPT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\CRYPT.C

 /*        Crypt:        Encryption routines for MicroEMACS
                 written by Dana Hoggatt and Daniel Lawrence
 */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if        CRYPT
 setkey(f, n)        /* reset encryption key of current buffer */

 int f;                /* default flag */
 int n;                /* numeric argument */

 {
         register int status;        /* return status */
         int odisinp;                /* original vlaue of disinp */
         char key[NPAT];                /* new encryption string */

         /* turn command input echo off */
         odisinp = disinp;
         disinp = FALSE;

         /* get the string to use as an encrytion string */
         status = mlreply("Encryption String: ", key, NPAT - 1);
         disinp = odisinp;
         if (status != TRUE)
                 return(status);

         /* and encrypt it */
         crypt((char *)NULL, 0);
         crypt(key, strlen(key));

         /* and save it off */
         strcpy(curbp->b_key, key);
         mlwrite(" ");                /* clear it off the bottom line */
         return(TRUE);
 }

 /**********
  *
  *        crypt - in place encryption/decryption of a buffer
  *
  *        (C) Copyright 1986, Dana L. Hoggatt
  *        1216, Beck Lane, Lafayette, IN
  *
  *        When consulting directly with the author of this routine,
  *        please refer to this routine as the "DLH-POLY-86-B CIPHER".
  *
  *        This routine was written for Dan Lawrence, for use in V3.8 of
  *        MicroEMACS, a public domain text/program editor.
  *
  *        I kept the following goals in mind when preparing this function:
  *
  *            1.        All printable characters were to be encrypted back
  *                into the printable range, control characters and
  *                high-bit characters were to remain unaffected.  this
  *                way, encrypted would still be just as cheap to
  *                transmit down a 7-bit data path as they were before.
  *
  *            2.        The encryption had to be portable.  The encrypted
  *                file from one computer should be able to be decrypted
  *                on another computer.
  *
  *            3.        The encryption had to be inexpensive, both in terms
  *                of speed and space.
  *
  *            4.        The system needed to be secure against all but the
  *                most determined of attackers.
  *
  *        For encryption of a block of data, one calls crypt passing
  *        a pointer to the data block and its length. The data block is
  *        encrypted in place, that is, the encrypted output overwrites
  *        the input.  Decryption is totally isomorphic, and is performed
  *        in the same manner by the same routine.
  *
  *        Before using this routine for encrypting data, you are expected
  *        to specify an encryption key.  This key is an arbitrary string,
  *        to be supplied by the user.  To set the key takes two calls to
  *        crypt().  First, you call
  *
  *                crypt(NULL, vector)
  *
  *        This resets all internal control information.  Typically (and
  *        specifically in the case on MICRO-emacs) you would use a "vector"
  *        of 0.  Other values can be used to customize your editor to be
  *        "incompatable" with the normally distributed version.  For
  *        this purpose, the best results will be obtained by avoiding
  *        multiples of 95.
  *
  *        Then, you "encrypt" your password by calling
  *
  *                crypt(pass, strlen(pass))
  *
  *        where "pass" is your password string.  Crypt() will destroy
  *        the original copy of the password (it becomes encrypted),
  *        which is good.  You do not want someone on a multiuser system
  *        to peruse your memory space and bump into your password.
  *        Still, it is a better idea to erase the password buffer to
  *        defeat memory perusal by a more technical snooper.
  *
  *        For the interest of cryptologists, at the heart of this
  *        function is a Beaufort Cipher.  The cipher alphabet is the
  *        range of printable characters (' ' to '~'), all "control"
  *        and "high-bit" characters are left unaltered.
  *
  *        The key is a variant autokey, derived from a wieghted sum
  *        of all the previous clear text and cipher text.  A counter
  *        is used as salt to obiterate any simple cyclic behavior
  *        from the clear text, and key feedback is used to assure
  *        that the entire message is based on the original key,
  *        preventing attacks on the last part of the message as if
  *        it were a pure autokey system.
  *
  *        Overall security of encrypted data depends upon three
  *        factors:  the fundamental cryptographic system must be
  *        difficult to compromise; exhaustive searching of the key
  *        space must be computationally expensive; keys and plaintext
  *        must remain out of sight.  This system satisfies this set
  *        of conditions to within the degree desired for MicroEMACS.
  *
  *        Though direct methods of attack (against systems such as
  *        this) do exist, they are not well known and will consume
  *        considerable amounts of computing time.  An exhaustive
  *        search requires over a billion investigations, on average.
  *
  *        The choice, entry, storage, manipulation, alteration,
  *        protection and security of the keys themselves are the
  *        responsiblity of the user.
  *
  **********/

 crypt(bptr, len)
 register char *bptr;        /* buffer of characters to be encrypted */
 register unsigned len;        /* number of characters in the buffer */
 {
         register int cc;        /* current character being considered */

         static long key = 0;        /* 29 bit encipherment key */
         static int salt = 0;        /* salt to spice up key with */

         if (!bptr) {                /* is there anything here to encrypt? */
                 key = len;        /* set the new key */
                 salt = len;        /* set the new salt */
                 return;
         }
         while (len--) {                /* for every character in the buffer *

                 cc = *bptr;        /* get a character out of the buffer */

                 /* only encipher printable characters */
                 if ((cc >= ' ') && (cc <= '~')) {

 /**  If the upper bit (bit 29) is set, feed it back into the key.  This
         assures us that the starting key affects the entire message.  **/

                         key &= 0x1FFFFFFFL;        /* strip off overflow */
                         if (key & 0x10000000L) {
                                 key ^= 0x0040A001L;        /* feedback */
                         }

 /**  Down-bias the character, perform a Beaufort encipherment, and
         up-bias the character again.  We want key to be positive
         so that the left shift here will be more portable and the
         mod95() faster   **/

                         cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';

 /**  the salt will spice up the key a little bit, helping to obscure
         any patterns in the clear text, particularly when all the
         characters (or long sequences of them) are the same.  We do
         not want the salt to go negative, or it will affect the key
         too radically.  It is always a good idea to chop off cyclics
         to prime values.  **/

                         if (++salt >= 20857) {        /* prime modulus */
                                 salt = 0;
                         }

 /**  our autokey (a special case of the running key) is being
         generated by a wieghted checksum of clear text, cipher
         text, and salt.   **/

                         key = key + key + cc + *bptr + salt;
                 }
                 *bptr++ = cc;        /* put character back into buffer */
         }
         return;
 }

 static int mod95(val)

 register int val;

 {
         /*  The mathematical MOD does not match the computer MOD  */

         /*  Yes, what I do here may look strange, but it gets the
                 job done, and portably at that.  */

         while (val >= 9500)
                 val -= 9500;
         while (val >= 950)
                 val -= 950;
         while (val >= 95)
                 val -= 95;
         while (val < 0)
                 val += 95;
         return (val);
 }
 #else
 nocrypt()
 {
 }
 #endif


 CRYPTIC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\CRYPTIC.C

                                          /* Chapter 4 - Program 5 */
 main()
 {
 int x = 0,y = 2,z = 1025;
 float a = 0.0,b = 3.14159,c = -37.234;

                                               /* incrementing */
    x = x + 1;       /* This increments x */
    x++;             /* This increments x */
    ++x;             /* This increments x */
    z = y++;         /* z = 2, y = 3 */
    z = ++y;         /* z = 4, y = 4 */

                                               /* decrementing */
    y = y - 1;       /* This decrements y */
    y--;             /* This decrements y */
    --y;             /* This decrements y */
    y = 3;
    z = y--;         /* z = 3, y = 2 */
    z = --y;         /* z = 1, y = 1 */

                                               /* arithmetic op */
    a = a + 12;      /* This adds 12 to a */
    a += 12;         /* This adds 12 more to a */
    a *= 3.2;        /* This multiplies a by 3.2 */
    a -= b;          /* This subtracts b from a */
    a /= 10.0;       /* This divides a by 10.0 */

                                      /* conditional expression */
    a = (b >= 3.0 ? 2.0 : 10.5 );     /* This expression     */

    if (b >= 3.0)                     /* And this expression */
       a = 2.0;                       /* are identical, both */
    else                              /* will cause the same */
       a = 10.5;                      /* result.             */

    c = (a > b?a:b);        /* c will have the max of a or b */
    c = (a > b?b:a);        /* c will have the min of a or b */
 }


 CSRPOS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\CSRPOS.C

 #include "dos.h"
 /****************************************************************************
 *
 *  locate the cursor
 *
 *****************************************************************************
 csrpos(row,col)                    /* cursor  row, col, attribute */
 int *row,*col;
 {
   union REGS reg;
   reg.h.bh = 0;                    /* page number */
   reg.h.ah = 3;                    /* set csr command */
   int86(0x10,&reg,&reg);           /* clr the screen */
   *row = reg.h.dh;                   /* set row number */
   *col = reg.h.dl;                   /* set col number */
 }


 CSRPROMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\CSR20A\CSRPROMO.C

 /*
 **  C S R P R O M O . C
 **
 **  Promotional program to demonstrate what the C Spot Run
 **  library does and how to use it.
 **
 **  Uses the C Spot Run C Add-On Library and was compiled with
 **  Microsoft C V3.0.
 **
 **  The C Spot Run C Add-On Library is always available at
 **  the listed BBS, and the author may be contacted as below.
 **
 **    C Spot Run
 **    New Dimension Software
 **    23 Pawtucket Dr.
 **    Cherry Hill, NJ 08003
 **    Voice: (609) 424-2595
 **     Data: (609) 354-9259  300-2400B  24hrs  (FidoNet 107/414)
 **
 **  Copyright 1986, 1987 Bob Pritchett
 **
 **  History in reverse order:
 **
 **  01/10/87  Final modifications for version 2.0.
 **
 **  09/17/86  Changing some colors, testing multi color in a window.
 **
 **  08/18/86  Some more small modifications.
 **
 **  08/06/86  Small modifications to work with new version.
 **
 **  05/24/86  Created using version 1.0 and a few routines
 **            from the not yet released version 1.1.  (V1.1a)
 **
 */

 #include <stdio.h>
 #include <color.h>
 #include <csrsound.h>

 static char *menu[] =
  {
   "  General Information  ",
   "      Window Demo      ",
   "       Directory       ",
   "    Other Functions    ",
   "   Programming Tools   ",
   "      Exit to DOS      "
  };

 static char *tools[] =
  {
   "    CheckC    ",
   "     FLine    ",
   " Header Files "
  };

 static char *logo[] =
  {
   "   CCCC",
   "  CC  CC",
   " CC",
   " CC   S P O T   R U N",
   " CC",
   "  CC  CC",
   "   CCCC"
  };

 main()
  {
   int w;
   int x;
   int i;
   dma(0);
   save_cursor();
   save_screen();
   cls();
   wcolor(LGRY_F+BLU_B,BLU_B);
   w = wopen(4,26,19,53,1);
   wcenter(w,1,"Introducing");
   for ( x = 0; x < 7; ++x )
       wputat(w,3+x,2,logo[x]);
   wcenter(w,11,"A User-Supported");
   wcenter(w,12,"C Add-On Library");
   wmessage(w,"[ Any Key ]",0);
   sound(C,30);
   sound(D,30);
   sound(E,30);
   sound(F,30);
   sound(G,30);
   sound(A,30);
   sound(B,30);
   getch();
   wclose(w);
   while ( 1 )
    {
     mcolor(BLK_F+RED_B,WHT_F+BLU_B);
     color(RED_F+WHT_B);
     x = pop_menu(9,27,6,menu," C Spot Run ",3);
     if ( x == -1 )
        break;
     else if ( x == 5 )
        break;
     else if ( x == 4 )
        utilities();
     else if ( x == 3 )
        other();
     else if ( x == 2 )
        directory();
     else if ( x == 1 )
        wndwdemo();
     else if ( x == 0 )
        info();
    }
   wcloseall();
   restore_screen();
   restore_cursor();
   exit(0);
  }

 other()
  {
   int w;
   int w1;
   int h;
   int m;
   int s;
   int hn;
   int dy;
   int mn;
   int yr;
   int n;
   color(BLK_F+GRN_B);
   w = wopen(10,10,20,70,1);
   wtitle(w,"< Other Functions >",0);
   wk(w);
   wcenter(w,1,"Why not add some sound to life?");
   for ( s = 25; s < 1000; s += 5 )
       sound(s,40);
   dosver(&m,&n);
   wcenterf(w,2,"You are running V%d.%d of DOS.\n",m,n);
   wcenter(w,4,"And there are many more functions handling");
   wcenter(w,5,"time, data, DOS and BIOS calls.");
   w1 = wopen(2,61,5,78,3);
   while ( ! kbhit() )
    {
     get_date(&dy,&mn,&yr);
     get_time(&h,&m,&s,&hn);
     whome(w1);
     wprintf(w1," Date: %02d/%02d/%d\n",mn,dy,(yr-1900));
     wprintf(w1," Time: %02d:%02d:%02d",h,m,s);
     gotoxy(30,0);                        /* Cursor Goes Away */
     for ( s = 0; s < 20000; ++s )
         ;
    }
   getch();
   wcloseall();
  }

 info()
  {
   int w;
   color(BOLD+RED_F+BLK_B);
   w = wopen(4,9,19,71,3);
   wcenter(w,1,"C Spot Run");
   wcenter(w,3,"Version 1.1a  Copyright 1986 Bob Pritchett");
   whline(w,5);
   wcenter(w,7,"C Spot Run is a collection of routines and programming");
   wcenter(w,8,"utilities for C programmers.  The purpose of this");
   wcenter(w,9,"library is to provide low cost tools for programmers");
   wcenter(w,10,"under the user-supported distribution concept.");
   wcenter(w,11,"For more information, contact the author at the following");
   wcenter(w,12,"address, or consult the C Spot Run manual.");
   wk(w);
   getch();
   wclose(w);
   w = wopen(7,28,17,52,3);
   wtitle(w,"< Address >",0);
   wcenter(w,1,"C Spot Run");
   wcenter(w,3,"Bob Pritchett");
   wcenter(w,4,"23 Pawtucket Dr.");
   wcenter(w,5,"Cherry Hill, NJ 08003");
   wcenter(w,7,"FidoNet 107/414");
   wk(w);
   getch();
   wclose(w);
  }

 wk(num)
  int num;
  {
   wmessage(num,"[ Press a Key ]",0);
  }

 wndwdemo()
  {
   int w;
   int w2;
   int w3;
   wcolor(WHT_F+BLK_B,BOLD+GRN_F);
   w = wopen(1,5,22,75,177);
   wtitle(w," Do you do windows?... ",1);
   wk(w);
   wcenter(w,1,"With the C Spot Run window functions library, you have");
   wcenter(w,2,"access to one of the most powerful windowing packages");
   wcenter(w,3,"available, and by far one of the best priced.");
   wcenter(w,4,"-- It's Free!! --");
   wcenter(w,5,"That's right.  The object code, libraries, and utilities");
   wcenter(w,6,"included in this package are absolutely free, and you may");
   wcenter(w,7,"use them for any non-commercial purpose as long as credit");
   wcenter(w,8,"is given.  For use in commercial applications, or to");
   wcenter(w,9,"obtain the surce code, check in the included manual");
   wcenter(w,10,"and contact the author.");
   wcenter(w,12,"Speaking of credit, I'd like to thank Phillip A. Mongelluzzo"
   wcenter(w,13,"whose source code taught me many of the techniques in this");
   wcenter(w,14,"library, and who answered many questions for me.");
   wcenter(w,16,"What follows is a small demonstration of some of the routines
   wcenter(w,17,"in the library, and a short explanation of each.  For a");
   wcenter(w,18,"complete description, please consult your manual.");
   getch();
   wclose(w);
   wcolor(BOLD+CYN_F+WHT_B,MAG_F);
   w = wopen(5,7,22,70,4);
   wprint(w,"Title anywhere with wtitle()...\n");
   getch();
   wtitle(w,"[ Left ]",1);
   wtitle(w,"< Right ]",2);
   wtitle(w,"< Center a Message >",0);
   getch();
   wprint(w,"Send a message with wmessage()...\n");
   getch();
   wmessage(w," Here... ",1);
   wmessage(w," ...or here. ",2);
   wk(w);
   getch();
   wprint(w,"We can skip around...");
   wscolor(w,RED_F+WHT_B,MAG_F);
   wgotoxy(w,6,6);
   wprint(w,"+ To here at 6,6 with wgotoxy()...");
   getch();
   wputat(w,7,4,"+ Or to 7,4 with wpuat()...");
   getch();
   wcenter(w,8,"Or center a line with wcenter().");
   wgotoxy(w,10,0);
   wprint(w,"Of course all output is done through an assembly routine,\n");
   wprint(w,"just as cursor movement is...  We do stick with C for this:\n");
   wprint(w,"(Go on, hit a key...)\n");
   getch();
   wjump(w,1,1);
   getch();
   wprint(w,"(Hit a key...)");
   getch();
   wprint(w,"\f The windows are all in a linked format, and can be moved\n");
   wprint(w,"from fore to background easily.  Any call that involves a non\n")
   wprint(w,"active window will activate that window before performing\n");
   wprint(w,"it's action.  You may also close the windows in any order\n");
   wprint(w,"you wish.\n");
   wprint(w," The wactivate(window) function will activate the window\n");
   wprint(w,"specified by window, and place it on 'top' of any overlapping\n")
   wprint(w,"windows.\n");
   getch();
   color(YEL_F+RED_B);
   w2 = wopen(5,5,20,35,2);
   getch();
   w3 = wopen(5,40,20,75,1);
   getch();
   whline(w2,2);
   whline(w2,8);
   wvline(w3,4);
   wvline(w3,10);
   wvline(w3,16);
   wk(w2);
   wk(w3);
   getch();
   wactivate(w);
   getch();
   wactivate(w2);
   getch();
   wactivate(w);
   wactivate(w3);
   getch();
   wcloseall();
   wcolor(WHT_F+BLU_B,CYN_F+WHT_B);
   w = wopen(5,10,20,70,4);
   wprint(w,"\tOf course there is a wprintf() function...\n");
   getch();
   for ( w2 = 0; w2 < 50; ++w2 )
       wprintf(w,"Counting up...%03d.\n",w2);
   wprintf(w,"Counting up...%03d.",w2);
   getch();
   wk();
   wprint(w,"\nWe can even set the scrolling boundaries...\n");
   getch();
   wcls(w);
   wcenter(w,0,"Freeze this line.");
   wcenter(w,wrow(w),"Freeze this also.");
   wfreeze(w,1,wrow(w)-1);
   whome(w);
   for ( w2 = 0; w2 < 50; ++w2 )
       wprintf(w,"Counting up...%03d.\n",w2);
   wprintf(w,"Counting up...%03d.",w2);
   getch();
   wclose(w);
  }

 utilities()
  {
   int x;
   while ( 1 )
    {
     color(MAG_F+BLK_B);
     mcolor(CYN_F,RED_F+WHT_B);
     x = pop_menu(10,10,3,tools," Tools ",1);
     if ( x == -1 )
        return(-1);
     else if ( x == 0 )
        checkc();
     else if ( x == 1 )
        fline();
     else if ( x == 2 )
        headers();
    }
  }

 checkc()
  {
   int w;
   color(BOLD+MAG_F+BLK_B);
   w = wopen(7,4,19,66,2);
   wcenter(w,1,"CheckC");
   whline(w,3);
   wcenter(w,5,"CheckC is a small C code checker that checks for unmatched");
   wcenter(w,6,"( ) { } [ ] \" \' in C source code.  Working with multiple");
   wcenter(w,7,"files at once and correctly counting special cases, such");
   wcenter(w,8,"as escape characters, makes this utility a valuable");
   wcenter(w,9,"addition to your C debugging tools.");
   wk(w);
   getch();
   wclose(w);
  }

 fline()
  {
   int w;
   color(BOLD+GRN_F+BLK_B);
   w = wopen(7,6,19,74,2);
   wcenter(w,1,"FLine");
   whline(w,3);
   wcenter(w,5,"FLine is a small utility that scans source code and places");
   wcenter(w,6,"and lines begining with a non-whitespace character into the");
   wcenter(w,7,"output file specified on the command line.  This provides");
   wcenter(w,8,"a useful reference file containing all function declerations,"
   wcenter(w,9,"preproccessor statements, global variables, and comments.");
   wk(w);
   getch();
   wclose(w);
  }

 headers()
  {
   int w;
   color(BOLD+RED_F+BLK_B);
   w = wopen(5,7,16,76,2);
   wcenter(w,1,"Header Files");
   whline(w,3);
   wcenter(w,5,"The C Spot Run library contains a number of header files");
   wcenter(w,6,"designed to make programming easier.  Color, special keys,");
   wcenter(w,7,"sound, and character codes are all covered in the different");
   wcenter(w,8,"header files included here.");
   wk(w);
   getch();
   wclose(w);
  }

 directory()
  {
   color(WHT_F+RED_B);
   if ( num_drives() < 3 )
      dirwin("A:","*.*");
   else
      dirwin("C:","*.*");
  }



 CTDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CTOOLBX1\CTDEMO.C


 /*                             CTDEMO.C
  *
  *
  *   This is a simple demo program to test some of the C Tool Box
  *   functions.  Current plans call for further expansion of the library.
  *   The final library developed will hopefully include data entry
  *   forms and menus built around windows.  It is hoped to provide
  *   full data editing and verification with the window forms.
  *
  *   This version requires the use of a color graphics adapter if you
  *   beyond the window portion of the program.
  *
  *
  *   This program and its supporting code (with the exception of the
  *   Unicorn Library) are placed in the public domain by the author.
  *   You have full rights to use this code in any manner you may see
  *   fit with the exception of using any or all for profit.  A club
  *   or users group may however charge a small handling fee not to
  *   exceed $7.00.  The author retains all rights to the Library
  *   subject to the shareware notice contained with the documentation for
  *   that library.
  *
  *   This will be released under the shareware concept as was the previous
  *   Unicorn library.
  *
  *
  *                            David A. Miller
  *                            Unicorn Software
  *                            8018 NE 123rd St
  *                            Kirkland, WA 98034
  *                            (206) 823-4656 after 6PM PST
  *                            Please, no collect calls
  *
  *    Release date 22 August 1987
  */

 #include <alloc.h>
 #include <stdio.h>
 #include <windows.h>
 #include <ctb.h>
 #include <border.h>
 #include <bdrdef.h>
 #include <colors.h>


 extern ct_mode_;    /* These are global variables where the current video  */
 extern ct_col_;     /* mode and number of screen columns are stored        */
 extern v_start;

 BOX *title, *first, *second, *third, *fourth, *fifth, *sixth, *small;
 BOX *mine;



 /*  The user is allowed up to 249 notes for background music.  The last
  *  note (the 250th if all are used) MUST be 0xff or the function will
  *  not terminate properly.
  */
                                 /* Short segment for test purposes */
 /*
 int melody[250] = {26, 29, 31, 33, 0xff};
 int beat[250]   = { 6, 12,  6,  7, 1};
 */

                         /* The below defines notes for Greensleeves */

 int melody[250] = {26, 29, 31, 33, 35, 33, 31, 28, 24, 26, 28, 29, 26,100,
                    26, 25, 26, 28, 25, 21, 26, 29, 31, 33, 35, 33, 31,
                    28, 24, 26, 28, 29, 28, 26, 25, 23, 25, 26,100, 26, 36,
                   100, 36, 35, 33, 31, 28, 24, 26, 28, 29, 26,100, 26, 25, 26
                    28, 25, 21, 36,100, 36, 35, 33, 31, 28, 24, 26, 28, 29,
                    28, 26, 25, 23, 25, 26,100, 26, 0xff};

 int beat[250] =   { 6, 12,  6,  7,  4,  6, 12,  6,  7,  4,  6, 12,  6,  1,
                     7,  4,  6, 12,  6, 12,  6, 12,  6,  7,  4,  6, 12,
                     6,  7,  4,  6,  7,  4,  7,  4,  6,  6, 18,  1, 18, 12,
                     1,  6,  6,  6, 12,  6,  7,  4,  6, 12,  6,  1,  7,  4,  6
                    12,  6, 20, 20,  1,  7,  4,  6, 12,  6,  7,  4,  6,  7,
                     4,  6,  6,  6,  6, 20,  1, 16,  1};



 int start = 9;


 main()
 {
    char a[80], *wgets(), ch, name[60];
    int  i, j, w, h, row, col;
    unsigned *p, *mem;

    sm(3);
    ctinit();

 /*  makebox sets up the definition of a box by allocating memory for a box
  *  structure and placing data into it.  The form is
  *  makebox(row, col, height, width, bfore, bback, ffore, fback);
  *
  *  savebox copies the screen area under the box and stores a pointer to
  *  that memory in the box structure.
  *
  *  draw box actually draws the box on the screen using direct video memory
  *  writes for speed.
  *
  *  boxtitle places a title in the border area of the box.  The form is
  *  boxtitle(BoxPointer, 0/1, " Title ", fore, back);
  *
  */


    first = makebox(0,0,23,79,14, 4, 14, 1);
    savebox(first);
    drawbox(first);
    boxtitle(first, 0, 72, " Box 1 " , YELLOW, 99);


    ct_wvstr(6, 68, LTWHITE, 99, "Vertical Strings", first);
    ct_wvstr(6, 72, LTWHITE, 99, "are possible    ", first);



    ct_str( 8, 10,  4, 1, "        ÜÜÜÜÜÜ
    ct_str( 9, 10,  4, 1, "        ÛÛÛÛÛÜ
    ct_str(10, 10, 11, 1, "        ³
    ct_str(11, 10, 11, 1, "        ³
    ct_str(12, 10,  7, 1, "ÛÛ  ÛÛ  ÛÛ                              ÛÛ  ÛÛ  ÛÛ
    ct_str(13, 10,  7, 1, " ÛÛÛÛÛÛÛÛ                                ÛÛÛÛÛÛÛÛ
    ct_str(14, 10,  7, 1, " ÛÛÛÛ  ÛÛ   ÛÛ  ÛÛ  ÛÛ  ÛÛ  ÛÛ  ÛÛ  ÛÛ   ÛÛÛ  ÛÛÛ
    ct_str(15, 10,  7, 1, " ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
    ct_str(16, 10,  7, 1, " ÛÛÛÛÛÛÛÛÛ  ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ  ÛÛÛÛÛÛÛÛÛÛ  ÛÛÛÛÛÛÛÛ
    ct_str(17, 10,  7, 1, " ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ°°°°°°ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
    ct_str(18, 10,  7, 1, " ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ°°°°°°ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
    ct_str(19, 10,  7, 1, " ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ°°°°°°ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
    ct_str(20, 10,  7, 1, " ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ°°°°°°ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
    ct_str(21, 5, GREEN, 1, "ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
    ct_str(22, 5, GREEN, 1, "ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

    if (ct_mode_ != 7)
    {
       ct_str(14, 15, 14, 1, "ÛÛ");
       ct_str(16, 37, 14, 1, "ÛÛ");

       ct_str(8,  18,  4, 1, "ÜÜÜÜÜ");
       ct_str(9,  18, 11, 4, " CTB ");
       ct_str(8,  18,  7, 4, "ß");

       ct_str(17, 29,  8, 6, "°°°°°°");
       ct_str(18, 29,  8, 6, "°°°°°°");
       ct_str(19, 29,  8, 6, "°°°°°°");
       ct_str(20, 29,  8, 6, "°°°°°°");
    }

    title = makebox(1, 25, 2, 27, 14, 1, 14, 1);
    makebdr(title, space);
    savebox(title);
    drawbox(title);
    ct_wstr(1,5,99,99, "Unicorn Software ", title);


    second = makebox(3, 25, 4, 26, 9, 1, 9, 1);
    makebdr(second, space);
    savebox(second);
    drawbox(second);
    ct_wstr(1,9,99,99, "Presents", second);
    ct_wstr(2,6,15 + BLINK, 99, "The C Tool Box", second);

    for(i = 0; i <= 10000; i++)
      for(j = 0; j <= 30; j++)
           ;

    third = makebox(12, 10, 4, 59, 9,6,9,6);
    makebdr(third, bdr1);
    savebox(third);
    drawbox(third);
    boxtitle(third, 1, 2, " Box 3 ", 98, 98);

    ct_wstr(1,15,99,99, "What is your name?", third);
    setcurps(0, 13, 45);
    gets(name);
    ct_wstr(2,15,99,99,"Hello ", third);
    ct_wstr(2,22,99,99, name, third);
    ct_wstr(3,5,99,99, "Would you be so kind as to press my enter key?", third
    setcurps(0, 15, 67);
    gets(a);


    fourth = makebox(18, 10, 3, 59, 7,4,7, 4);
    makebdr(fourth, bdr21);
    savebox(fourth);
    drawbox(fourth);
    boxtitle(fourth, 0, 10, " Fourth Box ", 99, 99);

    ct_wstr(1,5,99,99, "Thank you ", fourth);
    ct_wstr(1,16,99,99, name, fourth);
    ct_wstr(2, 5, 99,99, "Now if you would press it again please", fourth);

    setcurps(0, 20, 57);
    gets(a);


    fifth = makebox(6,10, 13, 59, LTMAGENTA, 5, 9, 5);
    makebdr(fifth, bdr12);
    savebox(fifth);
    drawbox(fifth);
    boxtitle(fifth, 0, 10, "® Fifth Box ¯", 99, 99);

    ct_wstr(1,3,99,99," Unicorn Software is happy to provide this tool box of"
    ct_wstr(2,3,99,99,"functions in the form of shareware.  The library may  "
    ct_wstr(3,3,99,99,"be registered with the author.  Upon registration you "
    ct_wstr(4,3,99,99,"will be sent the complete manual on disk and full     "
    ct_wstr(5,3,99,99,"source code to the library.  The manual runs well over"
    ct_wstr(6,3,99,99,"200 pages.  If you wish, a preprinted manual is also  "
    ct_wstr(7,3,99,99,"available.                                            "

    ct_wstr(9, 3,YELLOW,99,   "                David A.  Miller
    ct_wstr(10,3,WHITE,99,    "                Unicorn Software
    ct_wstr(11,3,LTMAGENTA,99,"     8018 NE 123rd St.  Kirkland, WA  98034


    gets(a);


    sixth = makebox(5,5, 10, 59, 4, 3, 15, 3);
    makebdr(sixth, bdr12);
    savebox(sixth);
    drawbox(sixth);
    boxtitle(sixth, 0, 10, "® Sixth Box ¯", 99, 99);

    ct_wstr(1,3,99,99,"The tool box contains most of the previous Unicorn    "
    ct_wstr(2,3,99,99,"Library functions ( over 200) plus a fast window      "
    ct_wstr(3,3,99,99,"library, background sound and much more.  The entire  "
    ct_wstr(4,3,99,99,"library encompasses graphics, text handling, mouse and"
    ct_wstr(5,3,99,99,"joystick control graphics and daisy wheel control     "
    ct_wstr(6,3,99,99,"functions, background sound functions and more.  An   "
    ct_wstr(7,3,99,99,"EGA version of the library should be released         "
    ct_wstr(8,3,99,99,"before the end of 1987.  <Press ENTER at each pause>  "

    setcurps(0,0,0);
    gets(a);
    resbox(sixth);
    gets(a);
    resbox(fifth);
    gets(a);
    resbox(fourth);
    gets(a);
    resbox(third);
    gets(a);
    resbox(second);
    gets(a);
    resbox(first);


    back16_8(12, 14);   /* Switch to using highlighted background colors */

    printf("\tMode is %d and columns are %d and start is %X Hex\n", ct_mode_,
    if (gcomtype() == 0xff)
       printf("\tThis computer is a PC or very close compatible\n\n");
    if (gcomtype() == 0xfc)
       printf("\tThis computer is an AT or very close compatible\n\n");
    if (gcomtype() == 0xfe)
       printf("\tThis computer is an XT or very close compatible\n\n");
    if (gcomtype() == 0xfd)
       printf("\tThis computer is an PCjr or very close compatible\n\n");
    if (gcomtype() == 0xf9)
       printf("\tThis computer is an PC convertible or very close compatible\n

    printf("\tNote that it is possible to use the highlighted colors in the\n"
    printf("\ttext mode for background color if you give up the blinking \n");
    printf("\ttext attribute.  Functions are available to switch between\n");
    printf("\tblink and high-intensity background modes.  If you wish to\n");
    printf("\tgo further in this demo you MUST have a graphics adapter\n");
    printf("\tinstalled.  Please be aware also that music will be played\n");
    printf("\tin the background mode while other things occur on screen.\n");
    printf("\tWhile this is similar to BASIC in some respects you have \n");
    printf("\ta limit of 249 notes with this library, not the limit of \n");
    printf("\t32 notes BASIC allows you.  Even this limit is user changable.\n



    printf("\n\t\t\tPress any key to continue\n");
    waitkey();






    /* Draw bar graphs next */

    sm(4);
    palette(2, 5, 14);

    hollow('B', 5,  70, 3);
    hollow('A', 5,  90, 3);
    hollow('R', 5, 110, 3);
    hollow('G', 5, 140, 3);
    hollow('R', 5, 160, 3);
    hollow('A', 5, 180, 3);
    hollow('P', 5, 200, 3);
    hollow('H', 5, 220, 3);

    vbar3d(150, 80, 100, 12, 16, 2, 3);
    vbar3d(150, 100, 140, 8, 26, 2, 3);
    vbar3d(150, 40, 180, 25, 8, 2, 3);

    usrfont('I', 153,  90, 1, 1, 2, 1);
    usrfont('T', 153,  95, 1, 1, 2, 1);
    usrfont('E', 153, 100, 1, 1, 2, 1);
    usrfont('M', 153, 105, 1, 1, 2, 1);
    usrfont('1', 153, 115, 1, 1, 2, 1);

    usrfont('I', 153, 135, 1, 1, 2, 1);
    usrfont('T', 153, 140, 1, 1, 2, 1);
    usrfont('E', 153, 145, 1, 1, 2, 1);
    usrfont('M', 153, 150, 1, 1, 2, 1);
    usrfont('2', 153, 160, 1, 1, 2, 1);

    usrfont('I', 153, 180, 1, 1, 2, 1);
    usrfont('T', 153, 185, 1, 1, 2, 1);
    usrfont('E', 153, 190, 1, 1, 2, 1);
    usrfont('M', 153, 195, 1, 1, 2, 1);
    usrfont('3', 153, 205, 1, 1, 2, 1);

    script('O', 158,  66, 1);
    script('t', 158,  82, 1);
    script('h', 158,  98, 1);
    script('e', 158, 114, 1);
    script('r', 158, 130, 1);
    script('g', 158, 156, 1);
    script('r', 158, 172, 1);
    script('a', 158, 188, 1);
    script('p', 158, 204, 1);
    script('h', 158, 220, 1);

    usrfont('S', 189, 30,  1, 1, 1, 0);
    usrfont('T', 189, 40,  1, 1, 1, 0);
    usrfont('Y', 189, 50,  1, 1, 1, 0);
    usrfont('L', 189, 60,  1, 1, 1, 0);
    usrfont('E', 189, 70,  1, 1, 1, 0);
    usrfont('S', 189,  80, 1, 1, 1, 0);
    usrfont('W', 189, 100, 1, 1, 2, 0);
    usrfont('I', 189, 110, 1, 1, 2, 0);
    usrfont('L', 189, 120, 1, 1, 2, 0);
    usrfont('L', 189, 130, 1, 1, 2, 0);
    usrfont('B', 189, 150, 1, 1, 1, 0);
    usrfont('E', 189, 160, 1, 1, 1, 0);
    usrfont('A', 189, 180, 1, 1, 1, 0);
    usrfont('V', 189, 190, 1, 1, 1, 0);
    usrfont('A', 189, 200, 1, 1, 1, 0);
    usrfont('I', 189, 210, 1, 1, 1, 0);
    usrfont('L', 189, 220, 1, 1, 1, 0);
    usrfont('A', 189, 230, 1, 1, 1, 0);
    usrfont('B', 189, 240, 1, 1, 1, 0);
    usrfont('L', 189, 250, 1, 1, 1, 0);
    usrfont('E', 189, 260, 1, 1, 1, 0);
    waitkey();



    sm(4);
    backclr(1);

    gothic('U',10,start+0,3);
    gothic('n',10,start+25,3);
    gothic('i',10,start+45,3);
    gothic('c',10,start+60,3);
    gothic('o',10,start+80,3);
    gothic('r',10,start+100,3);
    gothic('n',10,start+120,3);

    gothic('S',10,start+150,3);
    gothic('o',10,start+170,3);
    gothic('f',10,start+190,3);
    gothic('t',10,start+205,3);
    gothic('w',10,start+220,3);
    gothic('a',10,start+240,3);
    gothic('r',10,start+260,3);
    gothic('e',10,start+280,3);

    raschar('P', 50, start + 70, 2, 2, 3);
    raschar('r', 50, start + 90, 2, 2, 3);
    raschar('e', 50, start + 110, 2, 2, 3);
    raschar('s', 50, start + 130, 2, 2, 3);
    raschar('e', 50, start + 150, 2, 2, 3);
    raschar('n', 50, start + 170, 2, 2, 3);
    raschar('t', 50, start + 190, 2, 2, 3);
    raschar('s', 50, start + 210, 2, 2, 3);

    setsound();   /* Play the greensleeves melody in the background */

    unicorn();
    atsay(24, 3, 2, 0,"Copyright (c) 1986 David A. Miller");
    cntue();
    waitkey();
    sm(4);       /* this resets the mode which in effect is a
                    clear screen command.                      */
    backclr(9);

    printf("\n\n A demonstration of IBM PC graphics\n");
    printf(" using the 4 color med. resolution mode\n");
    printf(" and the C Tool Box library of\n");
    printf(" functions.\n");
    printf(" This library is designed to work with \n");
    printf(" the Turbo C small model. It has\n");
    printf(" been written using Turbo C  1.0 \n");
    printf(" and the Microsoft Assembler 4.0.\n");
    printf("    Not all library functions are\n");
    printf(" illustrated in this demo.  The\n");
    printf(" library is capable of many graphics\n");
    printf(" concepts including points, lines,\n");
    printf(" circles, ellipses (these may be \n");
    printf(" rotated from the vertical or\n");
    printf(" horizontal) and colorful print\n");
    printf(" including different fonts.  We\n");
    printf(" hope you enjoy the C TOOL BOX\n");
    printf(" Version 1.00 for Turbo C  ver 1.0\n");
    printf(" small model.\n");
    printf("  Copyright (C) 1986 David A. Miller\n");
    atsay(23,8,2,0,"Press any key to continue");
    waitkey();
    sm(4);       /* this resets the mode which in effect is a
                    clear screen command.                      */
    backclr(14);



    pg1();
    waitkey();
    sm(4);
    backclr(1);



    pg2();
    cntue();
    waitkey();
    sm(4);
    backclr(1);

    pg3();
    cntue();
    waitkey();
    sm(4);
    backclr(9);

    atom();
    cntue();
    waitkey();
    sm(4);
    backclr(1);

    printf("   The next screen will demonstrate\n\n");
    printf("    T U R T L E  F U N C T I O N S");

    printf("\n\n\n\n\n   The delay function is used to");
    printf("\n   slow down the display of lines\n");
    cntue();
    waitkey();
    palette(0,5,8);

    pg5();
    cntue();
    waitkey();
    sm(4);
    backclr(1);

    script('P', 5, 100, 3);
    script('a', 5, 116, 3);
    script('l', 5, 132, 3);
    script('e', 5, 148, 3);
    script('t', 5, 164, 3);
    script('t', 5, 180, 3);
    script('e', 5, 196, 3);

    redalert();

    printf("\n\n\n\nThe following page illustrates\n");
    printf("the palette command.  This command\n");
    printf("allows the programmer to control the\n");
    printf("color set and background color with\n");
    printf("one command.  There are a total of 6\n");
    printf("sets of three colors that may be \n");
    printf("displayed.  Three of these are normal;\n");
    printf("while the other three are bright\n");
    printf("versions of the basic three.\n");
    printf("\n\n     Press any key to continue\n");
    waitkey();

    pg6();
    cntue();
    waitkey();
    sm(4);
    backclr(9);


    pg7();
    cntue();
    waitkey();
    sm(4);
    backclr(9);


    pg8();
    atsay(24,7,3,0, "Press any key to continue");
    waitkey();
    sm(4);
    backclr(9);

    pgf();
    waitkey();
    sm(3);
    backclr(1);



    sm(3);
    printf("\n\n\n\n");
    printf("\tPlease address any comments, sugestions or criticisms to the\n")
    printf("\tauthor - we do listen, many of the functions in the library\n");
    printf("\tcurrently are a result of listening to users.  \n");
    printf("\tThis Lirary is designed as a library for Turbo C from \n");
    printf("\tBorland International.  A Microsoft C version 4.0 and 5.0\n");
    printf("\tversion of the library are also available.  Other versions\n");
    printf("\tare possible if there is enough interest in them.\n\n");
    printf("\tAll currently registered owners of the Unicorn Library will be\n
    printf("\table to update for an update fee.  A preprinted manual will also
    printf("\tbe made available for those who so wish. Registered owners, as w
    printf("\tthe Unicorn Library will, of course, receive ALL source code for
    printf("\tlibrary.\n\n");
    printf("                             David A.  Miller\n");
    printf("                             Unicorn Software\n");
    printf("                             8018 NE 123rd St\n");
    printf("                             Kirkland, WA 98034\n");
    printf("                             (206) 823 4656 after 6:30PM \n");
    printf("                             (no collect calls PLEASE)  \n");



 }


 pg1()
 {
    atsay(10,5,2,0, "The next page will demonstrate");
    atsay(11,5,2,0, "some of the simple graphics");
    atsay(12,5,2,0, "primitives including dots,");
    atsay(13,5,2,0, "lines, filled boxes and");
    atsay(14,5,2,0, "rectangles. ");
    atsay(20,5,3,0, "Press any key to continue");
 }

 pg2()
 {
    int i;

    for(i=0; i <= 20; i++)
       point(20, 10+i*2, i % 4);
    rect(50,20,80,50,1);
    boxfill(54,24,76,46,2);
    rect1(50,80,80,110,2,1);
    rect2(50,140,80,170,3,1);
    circle(65,240,50,1,1,3);
    paint(65,240,2,3);
    line(120,20,190,300,1);
    line(190,20,120,300,2);
    line(155,20,155,300,3);
 }

 pg3()
 {
    atsay(7,5,3,0, "The following screen will further");
    atsay(8,5,3,0, "demonstrate the circle function");
    atsay(9,5,3,0, "and introduce the rotated ellipse");
    atsay(10,5,3,0, "function.  The latter allows the");
    atsay(11,5,3,0, "user to draw an ellipse with a");
    atsay(12,5,3,0, "specified aspect and angle of");
    atsay(13,5,3,0, "rotation.");
 }


 pg5()
 {

    turnright(150);     /*  Double Triangle  */

    pencolor(1);

    forward(50);

    delay(500);
    turnright(120);
    forward(50);
    delay(500);
    turnright(120);
    forward(100);
    delay(500);
    turnleft(120);
    forward(50);
    delay(500);
    turnleft(120);
    forward(50);

    turnright(180);
    forward(50);

    pencolor(0);

    forward(50);
    turnright(120);
    pencolor(2);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(97);

    turnright(72);
    forward(5);
    pencolor(0);
    forward(48);
    turnright(96);

    turnleft(72);
    pencolor(3);
    forward(90);
    turnright(72);
    forward(90);
    turnright(72);
    forward(90);
    turnright(72);
    forward(90);
    turnright(73);
    forward(90);
    pencolor(0);

    paint(90,160,3,1);
    paint(110,160,3,1);

    paint(40,160,2,3);
    paint(182,160,1,2);

  }


 pg6()
 {
    palette(2,4,0);
    house();
    palette(0,5,0);
    house();
    palette(0,4,0);
    house();
 }


 house()
 {
    int i;

    for(i=0;i<=120;i++)                 /* Make some stars in the sky */
       point(rand() / 165,rand() / 103, rand() / 8192);

    line(180,0,180,319,1);        /* grass line */
    paint(183,10,1,1);            /*   grass */
    line(150,50,120,110,1);
    line(120,110,152,160,1);

    line(140,70,180,70,1);
    line(140,140,180,140,1);
    line(180,70,180,140,1);

    line(160,80,180,80,1);
    line(160,95,180,95,1);
    line(160,80,160,95,1);


    line(150,110,170,110,1);       /* Window */
    line(150,120,170,120,1);
    line(150,130,170,130,1);
    line(150,110,150,130,1);
    line(160,110,160,130,1);
    line(170,110,170,130,1);
    paint(155,115,2,1);             /* color the widow panes */
    paint(155,125,2,1);
    paint(165,115,2,1);
    paint(165,125,2,1);
    paint(130,110,3,1);            /* color the house  */

    line(130,100,130,120,2);       /* lines in the house */
    line(161,75,161,79,2);
    line(155,86,155,97,2);
    line(165,100,165,107,2);
    line(161,72,161,78,2);
    line(142,70,142,93,2);
    line(147,100,147,116,2);

    paint(170,90,2,1);             /*  color the door   */
    circle(170,90,2,1,1,1);        /*    knob           */
    paint(170,90,2,1);             /*   fill it         */
    line(114,124,128,124,2);       /*   chimney         */
    line(114,136,136,136,2);
    line(114,124,114,136,2);
    line(128,124,136,136,2);
    paint(120,130,2,2);            /*  fill chimney       */
    line(116,125,116,135,3);       /*  horizontal bricks  */
    line(118,125,118,135,3);
    line(120,125,120,135,3);
    line(122,125,122,135,3);
    line(124,125,124,135,3);
    line(126,125,126,135,3);
    line(128,125,128,135,3);
    line(130,128,130,135,3);
    line(132,132,132,135,3);
    line(134,134,134,135,3);

    line(116,130,118,130,3);       /*  vertical bricks */
    line(118,133,120,133,3);
    line(118,127,120,127,3);
    line(120,130,122,130,3);
    line(122,127,124,127,3);
    line(122,133,124,133,3);
    line(124,130,126,130,3);
    line(126,127,128,127,3);
    line(126,133,128,133,3);

    line(128,130,130,130,3);
    line(130,133,132,133,3);

    line(132,130,134,130,3);

    boxfill(140,190,180,210,3);      /*  Tree Trunk   */
    line(168,190,172,188,3);
    line(172,188,180,177,3);
    line(168,210,172,212,3);
    line(172,212,180,223,3);
    line(180,177,180,223,3);         /*  base line of tree  */
    paint(178,185,3,3);              /*  paint the tree     */
    paint(178,215,3,3);

    line(174,190,178,183,2);        /*   root lines in tree */
    line(172,210,178,213,2);
    line(174,198,178,190,2);
    line(176,203,178,207,2);
    circle(150,190,3,3,1,3);
    paint(150,189,3,3);
    circle(160,210,3,1,3,3);
    paint(160,211,3,3);
    point(168,205,2);
    point(171,203,2);
    point(168,193,2);
    point(172,195,2);

    circle(135,216,10,1,2,1);
    paint(135,216,1,1);
    circle(105,180,9,1,1,1);
    paint(105,180,1,1);
    circle(128,180,9,1,3,1);
    paint(128,180,1,1);
    circle(125,228,5,1,2,1);
    paint(125,228,1,1);
    circle(94,200,10,1,3,1);
    paint(94,200,1,1);

    circle(117,200,30,3,5,1);
    paint(116,200,1,1);
    line(110,190,117,200,3);
    line(120,180,128,197,3);
    line(115,200,125,180,3);

    circle(74,100,10,1,1,2);       /*   cloud  */
    paint(74,100,2,2);
    circle(62,130,12,1,2,2);
    paint(62,130,2,2);
    circle(72,70,9,1,2,2);
    paint(72,70,2,2);
    circle(32,58,8,1,2,2);
    paint(32,58,2,2);
    circle(20,68,22,1,2,2);
    paint(20,68,2,2);
    circle(35,130,12,1,2,2);
    paint(35,130,2,2);
    circle(21,95,10,1,2,2);
    paint(21,95,2,2);
    circle(33,125,7,1,2,2);
    paint(33,125,2,2);

    circle(50,100,41,3,7,2);            /*   cloud  */
    paint(50,100,2,2);               /*  fill it */


    line(150,194,167,194,1);
    line(142,197,153,197,1);
    line(165,195,174,195,1);
    line(147,200,153,200,1);
    line(150,205,164,205,1);
    line(153,201,164,201,1);
    line(163,202,172,202,1);


    circle(50,270,15,1,1,3);      /*  moon */
    paint(50,270,03,03);            /*  fill it  */
    point(52,273,1);
    point(43,260,1);
    point(52,262,1);
    point(53,262,1);
    point(52,261,1);
    point(53,273,1);
    point(40,270,1);
    point(60,268,1);
    point(45,281,1);
    point(45,282,1);
    point(44,281,1);
    point(44,272,0);
    point(43,272,0);
    point(43,271,0);
    point(47,265,0);
    point(46,265,0);
    point(46,264,0);
    point(53,275,0);
    point(54,276,0);

    delay(3000);
 }


 pg7()
 {

    rhollow(20, 100, 'F',0,  0,3, .15);
    rhollow(20, 100, 'O',0, 22,3, .15);
    rhollow(20, 100, 'N',0, 44,3, .15);
    rhollow(20, 100, 'T',0, 66,3, .15);
    rhollow(20, 100, 'S',0, 88,3, .15);

    gliss(100,1000,300);

    atsay(6,2,2,0,"  Many different Fonts are Possible");
    atsay(7,2,3,0, "      Including rotated fonts");

    usrfont('T',80,60,2,2,3,0);
    usrfont('H',80,80,2,2,3,0);
    usrfont('I',80,100,2,2,3,0);
    usrfont('N',80,120,2,2,3,0);
    usrfont('L',88,140,1,1,3,0);
    usrfont('E',88,150,1,1,3,0);
    usrfont('T',88,160,1,1,3,0);
    usrfont('T',88,170,1,1,3,0);
    usrfont('E',88,180,1,1,3,0);
    usrfont('R',88,190,1,1,3,0);
    usrfont('S',88,200,1,1,3,0);

    usrfont('S',135,146,1,1,3,1);
    usrfont('U',135,152,1,1,3,1);
    usrfont('B',135,158,1,1,3,1);
    usrfont('/',130,164,1,1,3,0);
    usrfont('S',127,174,1,1,3,1);
    usrfont('U',127,180,1,1,3,1);
    usrfont('P',127,186,1,1,3,1);
    usrfont('E',127,192,1,1,3,1);
    usrfont('R',127,198,1,1,3,1);
    usrfont('S',130,209,1,1,2,0);
    usrfont('C',130,219,1,1,2,0);
    usrfont('R',130,229,1,1,2,0);
    usrfont('I',130,239,1,1,2,0);
    usrfont('P',130,249,1,1,2,0);
    usrfont('T',130,259,1,1,2,0);
    usrfont('S',130,269,1,1,2,0);



    usrfont('X',175,65,3,3,1,0);
    usrfont('2',175,97,2,2,1,1);
    usrfont('+',175,105,3,3,1,0);
    usrfont('X',175,134,3,3,1,0);
    usrfont('-',175,160,3,3,1,0);
    usrfont('4',175,185,3,3,1,0);
    usrfont('=',175,210,3,3,1,0);
    usrfont('0',175,230,3,3,1,0);

 }



 pg8()
 {
    printf("   Below are a few Unit Conversions\n\n\n\n\n");
    printf("%8.6f inches    = %f cm\n",4.0, INCH_CM(4.0));
    printf("%8.6f cm       = %f inches\n",10.0, CM_INCH(10.0));
    printf("%8.6f degrees  = %f radians\n",90.0, DEG_RAD(90.0));
    printf("%8.6f radians   = %f degrees\n",1.0, RAD_DEG(1.0));
    printf("%8.6f ounces    = %f grams\n",4.0, OZ_GM(4.0));
    printf("%8.6f grams    = %f ounces\n",50.0, GM_OZ(50.0));
    printf("%8.6f gallons  = %f liters\n",10.0, GAL_LT(10.0));
    printf("%8.6f liters   = %f gallons\n",50.0, LT_GAL(50.0));
    printf("%8.6f pounds    = %f kilograms\n",4.0, LB_KG(4.0));
    printf("%8.6f kilogram = %f pounds\n",50.0, KG_LB(50.0));

 }



 pgf()
 {


    rgothic(25, 15, 'U', 0,   0,  3, .2);
    rgothic(25, 15, 'n', 0,  16,  3, .2);
    rgothic(25, 15, 'i', 0,  32,  3, .2);
    rgothic(25, 15, 'c', 0,  48,  3, .2);
    rgothic(25, 15, 'o', 0,  64,  3, .2);
    rgothic(25, 15, 'r', 0,  80,  3, .2);
    rgothic(25, 15, 'n', 0,  96,  3, .2);

    rgothic(5, 155, 'S', 0,   0,  3, -.17);
    rgothic(5, 155, 'o', 0,  18,  3, -.17);
    rgothic(5, 155, 'f', 0,  32,  3, -.17);
    rgothic(5, 155, 't', 0,  48,  3, -.17);
    rgothic(5, 155, 'w', 0,  64,  3, -.17);
    rgothic(5, 155, 'a', 0,  80,  3, -.17);
    rgothic(5, 155, 'r', 0,  96,  3, -.17);
    rgothic(5, 155, 'e', 0, 112,  3, -.17);


    atsay(7,5,3,0, "We Hope you have enjoyed seeing");
    atsay(8,5,3,0, "some of the features contained");
    atsay(9,5,3,0, "in the C TOOL BOX for the");
    atsay(10,5,3,0, "IBM PC medium resolution mode");
    atsay(11,5,3,0, "graphics.  The next release");
    atsay(12,5,3,0, "(Dec 87) will contain even");
    atsay(13,5,3,0, "more features.  Currently");
    atsay(14,5,3,0, "registered users will receive.");
    atsay(15,5,3,0, "a FREE UPDATE when released.");

    atsay(17,5,2,0, "       Developed by");
    atsay(18,5,2,0, "      David A. Miller");

    gliss(3000, 200, 100);

    atsay(24,4,2,0, " Press any key to return to Dos");
 }




 atom()
 {
   ellipser(100,160,0,50,25,2);
   ellipser(100,160,0,25,50,2);
   ellipser(100,160,48,50,25,1);
   ellipser(100,160,48,25,50,1);

   circle(100,160,70,1,1,1);
   circle(100,160,66,1,1,1);
   paint(100,228,2,1);
   circle(100,160,4,1,1,3);
   paint(100,160,3,3);
 }


 cntue()
 {
    atsay(15,1,2,0, "Press any");
    atsay(16,2,2,0, "Key to");
    atsay(17,1,2,0, "continue");
 }

 unicorn()
 {
    line(66,100,107,156, 3);      /*   horn  */
    line(66,100,113,148, 3);


    line(157,170,158,154, 3);
    line(158,154,172,138, 3);
    line(172,138,173,125, 3);
    line(173,125,166,115, 3);
    line(166,115,151,117, 3);
    line(151,117,130,138, 3);
    line(130,138,120,140, 3);
    line(120,140,98,168, 3);     /* this line ends at the ear  */
    line(98,168,85,165,  3);
    line(85,165,89,172, 3);
    line(89,172,97,180, 3);
    line(97,180,121,224, 3);     /* outline after ear      */
    line(121,224,156,255, 3);
    line(156,255,198,266, 3);    /*  very bottom line  */

    line(157,170,170,180, 3);     /* part to left going down  */
    line(170,180,198,180, 3);     /* very bottom line */

    line(198,180,198,266,3);      /*   line across base of head  */
    paint(188,182,3,3);           /*   fill in the head!!  */
    paint(111,148, 3,3);        /*   fill in the horn    */
    line(148,185,157,170, 2);      /* head starting at bottom  */

    line(152,130,140,142, 2);     /* in head near mouth    */
    line(140,142,133,156, 2);

    line(103,167,123,173,2);     /* between ear and eye   */

    line(173,125,160,138,2);       /*  mouth   */

    line(167,145,181,151,3);       /*  goatee   */
    line(181,151,175,141,3);
    line(175,141,183,139,3);
    line(183,139,173,133,3);
    paint(172,141,3,3);             /*  color the goatee  */

    line(102,149,107,142, 2);       /* lines across the horn   */
    line(97,140, 100,135, 2);
    line(91,134,94,130, 2);
    line(86,127,88,122, 2);
    line(81,121,83,119, 2);
    line(76,113,77,111, 2);

    line(98,180,140,182,2);        /*  mane     */
    line(106,160,118,168,2);
    line(140,182,149,198,2);
    line(130,205,170,208,2);
    line(170,208,180,220,2);
    line(154,232,190,235,2);
    line(190,235,194,245,2);

    ellipser(122,158,42,7,3,2);
    paint(122,158,2,2);
    ellipser(156,123,72,4,2,2);
    paint(156,123,2,2);

    circle(123,157,2,1,1,1);
    paint(123,157,1,1);
    point(123,157,3);

 }



 CTLCNV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CTLCNV.C

 #include <stdio.h>

 extern        char        _numstr[];                /* string of hexadecimal

 char *ctlcnv(string)
 char *string;
 /*
  *        Convert \<char> notation in <string> to actual characters.  This
  *        is useful for reading strings from a stream when you want to allow
  *        insertion of control character or other characters that may have
  *        special meaning otherwise, or may not otherwise be allowed.  The
  *        following formats are supported:
  *                \n                newline or linefeed
  *                \r                carriage return
  *                \0                null character (value 0)
  *                \b                backspace
  *                \t                horizontal tab
  *                \v                vertical tab
  *                \f                form feed
  *                \a                alarm (bell)
  *                \\                backslash
  *                \'                single quote
  *                \"                double quote
  *                \NNN                octal constant
  *                \xNN                hexadecimal constant
  *                \<nl>                "folded" line (both characters removed
  */
 {
         register char *p, *q, c;
         register int i, n;

         p = q = string;
         while(*q) {
                 if(*q == '\\') {
                         switch(*++q) {
                                 case 'n':        /* newline or linefeed */
                                         *p++ = '\n';
                                         break;
                                 case 'r':        /* carriage return */
                                         *p++ = '\r';
                                         break;
                                 case 'b':        /* backspace */
                                         *p++ = '\b';
                                         break;
                                 case 't':        /* horizontal tab */
                                         *p++ = '\t';
                                         break;
                                 case 'v':        /* vertical tab */
                                         *p++ = '\v';
                                         break;
                                 case 'f':        /* form feed */
                                         *p++ = '\f';
                                         break;
                                 case 'a':        /* alarm (bell) */
                                         *p++ = '\a';
                                         break;
                                 case '0':
                                 case '1':
                                 case '2':
                                 case '3':        /* octal constant */
                                         c = (*q - '0');
                                         i = 0;
                                         n = 3;
                                         do {
                                                 i = (i<<3) + c;
                                                 c = (*++q - '0');
                                         } while(--n & (c >= 0) && (c < 8));
                                         *p++ = i;
                                         --q;
                                         break;
                                 case 'x':        /* hexadecimal constant */
                                         i = 0;
                                         n = 2;
                                         while(n-- & ((c = strpos(_numstr,
                                             toupper(*++q))) >= 0))
                                                 i = (i << 4) + c;
                                         --q;
                                         break;
                                 case '\n':        /* "folded" line */
                                         break;
                                 default:
                                         *p++ = *q;
                         }
                 }
                 else
                         *p++ = *q;
                 ++q;
         }
         *p = '\0';
         return(string);
 }


 CTYPE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\CTYPE.C

 /*
  *  CTYPE.C        Character classification and conversion
  */

 #include <d:\usr\stdlib\stdio.h>
 #include <d:\usr\stdlib\ctype.h>

 #undef        toupper
 #undef        tolower

 unsigned char _ctype[128] = {
         /* 0x00 */        _CTc,
         /* 0x01 */        _CTc,
         /* 0x02 */        _CTc,
         /* 0x03 */        _CTc,
         /* 0x04 */        _CTc,
         /* 0x05 */        _CTc,
         /* 0x06 */        _CTc,
         /* 0x07 */        _CTc,
         /* 0x08 */        _CTc,
         /* 0x09 */        _CTc|_CTs,
         /* 0x0A */        _CTc|_CTs,
         /* 0x0B */        _CTc|_CTs,
         /* 0x0C */        _CTc|_CTs,
         /* 0x0D */        _CTc|_CTs,
         /* 0x0E */        _CTc,
         /* 0x0F */        _CTc,

         /* 0x10 */        _CTc,
         /* 0x11 */        _CTc,
         /* 0x12 */        _CTc,
         /* 0x13 */        _CTc,
         /* 0x14 */        _CTc,
         /* 0x15 */        _CTc,
         /* 0x16 */        _CTc,
         /* 0x17 */        _CTc,
         /* 0x18 */        _CTc,
         /* 0x19 */        _CTc,
         /* 0x1A */        _CTc,
         /* 0x1B */        _CTc,
         /* 0x1C */        _CTc,
         /* 0x1D */        _CTc,
         /* 0x1E */        _CTc,
         /* 0x1F */        _CTc,

         /* 0x20 */        _CTs,
         /* 0x21 */        _CTp,
         /* 0x22 */        _CTp,
         /* 0x23 */        _CTp,
         /* 0x24 */        _CTp,
         /* 0x25 */        _CTp,
         /* 0x26 */        _CTp,
         /* 0x27 */        _CTp,
         /* 0x28 */        _CTp,
         /* 0x29 */        _CTp,
         /* 0x2A */        _CTp,
         /* 0x2B */        _CTp,
         /* 0x2C */        _CTp,
         /* 0x2D */        _CTp,
         /* 0x2E */        _CTp,
         /* 0x2F */        _CTp,

         /* 0x30 */        _CTd|_CTx,
         /* 0x31 */        _CTd|_CTx,
         /* 0x32 */        _CTd|_CTx,
         /* 0x33 */        _CTd|_CTx,
         /* 0x34 */        _CTd|_CTx,
         /* 0x35 */        _CTd|_CTx,
         /* 0x36 */        _CTd|_CTx,
         /* 0x37 */        _CTd|_CTx,
         /* 0x38 */        _CTd|_CTx,
         /* 0x39 */        _CTd|_CTx,
         /* 0x3A */        _CTp,
         /* 0x3B */        _CTp,
         /* 0x3C */        _CTp,
         /* 0x3D */        _CTp,
         /* 0x3E */        _CTp,
         /* 0x3F */        _CTp,

         /* 0x40 */        _CTp,
         /* 0x41 */        _CTu|_CTx,
         /* 0x42 */        _CTu|_CTx,
         /* 0x43 */        _CTu|_CTx,
         /* 0x44 */        _CTu|_CTx,
         /* 0x45 */        _CTu|_CTx,
         /* 0x46 */        _CTu|_CTx,
         /* 0x47 */        _CTu,
         /* 0x48 */        _CTu,
         /* 0x49 */        _CTu,
         /* 0x4A */        _CTu,
         /* 0x4B */        _CTu,
         /* 0x4C */        _CTu,
         /* 0x4D */        _CTu,
         /* 0x4E */        _CTu,
         /* 0x4F */        _CTu,

         /* 0x50 */        _CTu,
         /* 0x51 */        _CTu,
         /* 0x52 */        _CTu,
         /* 0x53 */        _CTu,
         /* 0x54 */        _CTu,
         /* 0x55 */        _CTu,
         /* 0x56 */        _CTu,
         /* 0x57 */        _CTu,
         /* 0x58 */        _CTu,
         /* 0x59 */        _CTu,
         /* 0x5A */        _CTu,
         /* 0x5B */        _CTp,
         /* 0x5C */        _CTp,
         /* 0x5D */        _CTp,
         /* 0x5E */        _CTp,
         /* 0x5F */        _CTp,

         /* 0x60 */        _CTp,
         /* 0x61 */        _CTl|_CTx,
         /* 0x62 */        _CTl|_CTx,
         /* 0x63 */        _CTl|_CTx,
         /* 0x64 */        _CTl|_CTx,
         /* 0x65 */        _CTl|_CTx,
         /* 0x66 */        _CTl|_CTx,
         /* 0x67 */        _CTl,
         /* 0x68 */        _CTl,
         /* 0x69 */        _CTl,
         /* 0x6A */        _CTl,
         /* 0x6B */        _CTl,
         /* 0x6C */        _CTl,
         /* 0x6D */        _CTl,
         /* 0x6E */        _CTl,
         /* 0x6F */        _CTl,

         /* 0x70 */        _CTl,
         /* 0x71 */        _CTl,
         /* 0x72 */        _CTl,
         /* 0x73 */        _CTl,
         /* 0x74 */        _CTl,
         /* 0x75 */        _CTl,
         /* 0x76 */        _CTl,
         /* 0x77 */        _CTl,
         /* 0x78 */        _CTl,
         /* 0x79 */        _CTl,
         /* 0x7A */        _CTl,
         /* 0x7B */        _CTp,
         /* 0x7C */        _CTp,
         /* 0x7D */        _CTp,
         /* 0x7E */        _CTp,
         /* 0x7F */        _CTc
 };

 int toupper(c)
 int c;
 {
         return(islower(c) ? (c)^0x20 : (c));
 }

 int tolower(c)
 int c;
 {
         return(isupper(c) ? (c)^0x20 : (c));
 }


 CURBACK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CURBACK.C

 /*                       *** curback.c ***                           */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to move the cursor backward x relative columns.          */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define POUND        '#'

 curback(x)
 int x;
 {
         extern char CUB[];
         char xrel[3],command[20];
         int i,inpos,outpos;

         /* initialize screen controls */
         scrinit();

         /* convert integer relative motion into string */
         sprintf(xrel,"%d",x);

         /* build command line */
         inpos = 0;        /* position within control string */
         outpos = 0;        /* position within command string */

         while (CUB[inpos] != POUND)
                 command[outpos++] = CUB[inpos++];

         for (i=0;xrel[i] != NULL;i++)
                 command[outpos++] = xrel[i];

         inpos++;
         while (CUB[inpos] != NULL)
                 command[outpos++] = CUB[inpos++];

         command[outpos] = NULL;

         /* write command to screen */
         writes(command);
 }


 CURDOWN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CURDOWN.C

 /*                        *** curdown.c ***                          */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to move the cursor down y relative lines.                */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define POUND        '#'

 curdown(y)
 int y;
 {
         extern char CUD[];
         char yrel[3],command[20];
         int i,inpos,outpos;

         /* initialize screen controls */
         scrinit();

         /* convert integer relative motion into string */
         sprintf(yrel,"%d",y);

         /* build command line */
         inpos = 0;        /* position within control string */
         outpos = 0;        /* position within command string */

         while (CUD[inpos] != POUND)
                 command[outpos++] = CUD[inpos++];

         for (i=0;yrel[i] != NULL;i++)
                 command[outpos++] = yrel[i];

         inpos++;
         while (CUD[inpos] != NULL)
                 command[outpos++] = CUD[inpos++];

         command[outpos] = NULL;

         /* write command to screen */
         writes(command);
 }


 CURFOR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CURFOR.C

 /*                        *** curfor.c ***                           */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to move the cursor forward x relative columns.           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define POUND        '#'

 curfor(x)
 int x;
 {
         extern char CUF[];
         char xrel[3],command[20];
         int i,inpos,outpos;

         /* initialize screen controls */
         scrinit();

         /* convert integer relative motion into string */
         sprintf(xrel,"%d",x);

         /* build command line */
         inpos = 0;        /* position within control string */
         outpos = 0;        /* position within command string */

         while (CUF[inpos] != POUND)
                 command[outpos++] = CUF[inpos++];

         for (i=0;xrel[i] != NULL;i++)
                 command[outpos++] = xrel[i];

         inpos++;
         while (CUF[inpos] != NULL)
                 command[outpos++] = CUF[inpos++];

         command[outpos] = NULL;

         /* write command to screen */
         writes(command);
 }


 CURSOR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CURSOR.C

 /*                         *** cursor.c ***                          */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to move the cursor to a specific r,c co-ordinate.        */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define POUND        '#'

 cursor(r,c)
 int r,c;
 {
         extern char CUP[];
         char row[3],col[4],command[20];
         int i,inpos,outpos;

         /* initialize screen controls */
         scrinit();

         /* decode integer co-ordinates */
         sprintf(row,"%d",r);
         sprintf(col,"%d",c);

         /* build control sequence */
         inpos = 0;        /* position in control line */
         outpos = 0;        /* position in command line */

         while (CUP[inpos] != POUND)
                 command[outpos++] = CUP[inpos++];

         for (i=0;row[i] != NULL;i++)
                 command[outpos++] = row[i];

         inpos++;
         while(CUP[inpos] != POUND)
                 command[outpos++] = CUP[inpos++];

         for (i=0;col[i] != NULL;i++)
                 command[outpos++] = col[i];

         inpos++;
         while(CUP[inpos] != NULL)
                 command[outpos++] = CUP[inpos++];

         command[outpos] = NULL;

         /* write command to screen */
         writes(command);
 }


 CURUP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CURUP.C

 /*                        *** curup.c ***                            */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to move the cursor up y relative lines.                  */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define POUND        '#'

 curup(y)
 int y;
 {
         extern char CUU[];
         char yrel[3],command[20];
         int i,inpos,outpos;

         /* initialize screen controls */
         scrinit();

         /* convert integer relative motion into string */
         sprintf(yrel,"%d",y);

         /* build command line */
         inpos = 0;        /* position within control string */
         outpos = 0;        /* position within command string */

         while (CUU[inpos] != POUND)
                 command[outpos++] = CUU[inpos++];

         for (i=0;yrel[i] != NULL;i++)
                 command[outpos++] = yrel[i];

         inpos++;
         while (CUU[inpos] != NULL)
                 command[outpos++] = CUU[inpos++];

         command[outpos] = NULL;

         /* write command to screen */
         writes(command);
 }


 CVTDATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\CVTDATE.C

 /*                     *** cvtdate.c ***                             */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to check and convert a "packed" gregorian date (1/1/83)  */
 /* into its "expanded" form (01/01/83).  Will return a 0 if success- */
 /* ful or a -1 if unable to convert gregorian date received.         */
 /*                                                                   */
 /* WARNING - if indate has not been declared at least 9 characters a */
 /*           memory overwrite will occure.                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #include <ctype.h>

 int cvtdate(indate)
 char indate[];
 {
         char hold[9];
         int i;

         i = 0;                /* position within indate */

         /* get month */
         if (isdigit(indate[i]))
                 if (isdigit(indate[i+1])) {
                         hold[0] = indate[i++];
                         hold[1] = indate[i++];
                 } else {
                         hold[0] = '0';
                         hold[1] = indate[i++];
                 }
         else
                 return(-1);

         /* insert slash */
         if (isdigit(indate[i++]))
                 return(-1);
         else
                 hold[2] = '/';

         /* get day */
         if (isdigit(indate[i]))
                 if (isdigit(indate[i+1])) {
                         hold[3] = indate[i++];
                         hold[4] = indate[i++];
                 } else {
                         hold[3] = '0';
                         hold[4] = indate[i++];
                 }
         else
                 return(-1);

         /* insert slash */
         if (isdigit(indate[i++]))
                 return(-1);
         else
                 hold[5] = '/';

         /* get year */
         if (isdigit(indate[i]))
                 if (isdigit(indate[i+1])) {
                         hold[6] = indate[i++];
                         hold[7] = indate[i++];
                 } else {
                         hold[6] = '0';
                         hold[7] = indate[i++];
                 }
         else
                 return(-1);

         /* insert null terminator */
         if (indate[i] != '\0')
                 return(-1);
         else
                 hold[8] = '\0';

         /* copy hold into indate */
         strcpy(indate,hold);

         /* done */
         return(0);
 }


 CVTDATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\CVTDATE.C

 /*                     *** cvtdate.c ***                             */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to check and convert a "packed" gregorian date (1/1/83)  */
 /* into its "expanded" form (01/01/83).  Will return a 0 if success- */
 /* ful or a -1 if unable to convert gregorian date received.         */
 /*                                                                   */
 /* WARNING - if indate has not been declared at least 9 characters a */
 /*           memory overwrite will occure.                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #include <ctype.h>

 int cvtdate(indate)
 char indate[];
 {
         char hold[9];
         int i;

         i = 0;                /* position within indate */

         /* get month */
         if (isdigit(indate[i]))
                 if (isdigit(indate[i+1])) {
                         hold[0] = indate[i++];
                         hold[1] = indate[i++];
                 } else {
                         hold[0] = '0';
                         hold[1] = indate[i++];
                 }
         else
                 return(-1);

         /* insert slash */
         if (isdigit(indate[i++]))
                 return(-1);
         else
                 hold[2] = '/';

         /* get day */
         if (isdigit(indate[i]))
                 if (isdigit(indate[i+1])) {
                         hold[3] = indate[i++];
                         hold[4] = indate[i++];
                 } else {
                         hold[3] = '0';
                         hold[4] = indate[i++];
                 }
         else
                 return(-1);

         /* insert slash */
         if (isdigit(indate[i++]))
                 return(-1);
         else
                 hold[5] = '/';

         /* get year */
         if (isdigit(indate[i]))
                 if (isdigit(indate[i+1])) {
                         hold[6] = indate[i++];
                         hold[7] = indate[i++];
                 } else {
                         hold[6] = '0';
                         hold[7] = indate[i++];
                 }
         else
                 return(-1);

         /* insert null terminator */
         if (indate[i] != '\0')
                 return(-1);
         else
                 hold[8] = '\0';

         /* copy hold into indate */
         strcpy(indate,hold);

         /* done */
         return(0);
 }


 CXREF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CXREF\CXREF.C

 #include <stdio.h>
 #include <ctype.h>

 #define NestMax 10

 char CR = 0x0D;
 char IDChar[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwx
 char TINCLUDE[] = "#include";
 char *Reserved[] = {
    "auto",
    "break",
    "case",
    "char",
    "continue",
    "default",
    "do",
    "double",
    "else",
    "entry",
    "extern",
    "float",
    "for",
    "goto",
    "if",
    "int",
    "long",
    "register",
    "return",
    "short",
    "sizeof",
    "static",
    "struct",
    "switch",
    "typedef",
    "union",
    "unsigned",
    "void",
    "while"
 };

 typedef struct
 {
    int AX, BX, CX, DX, SI, DI;
 } RegPack;

 typedef struct
 {
    FILE *ID;
    char Name[64];
    int Lnno;
    char InsertChar;
    int EndFile, First, Print;
 } FileDef;

 typedef struct LR
 {
    struct LR *Next;
    int Key;
    char Code;
 } LineRec;

 typedef struct
 {
    LineRec *First, *Current;
 } LineQueueRec;

 typedef struct
 {
    char *Key;
    LineQueueRec *LineList;
 } WordRec;

 typedef struct TR
 {
    struct TR *Left, *Right;
    WordRec *Ref;
 } TreeRec;

 int PageNum, PageLn;
 TreeRec *Root;
 FileDef MainFile, IncludeFile, InFile;
 FILE *Output;
 int TotalLn, ChIndex;
 int Listing, StdFlag, IncludeFlag;
 int NestUp, NestDn, NestLvl;
 int Tabs;
 char Token[30], Path[64], IncludePath[64];
 int i;
 char *FDate, *FTime;
 char Today[30];
 char *OutFileName[64];
 char Ch;
 int UnGetCount = 0;
 char UnGot = ' ';
 char Line[255];

 main(argc, argv)
 int argc;
 char *argv[];
 {
    void Init(), GetFileDate(), Header(), GetLiteral(), GetIncludeFile();
    void GetCharLiteral(), GetComment(), GetToken(), PrintLine(), AddQueue();
    void Concordance(), Usage();
    FILE *fopen();
    char GetChar(), *index();

    Init();
    if (argc < 2)
       Usage();
    else
    {
       for (i = 1; i < argc; i++)
       {
          strcpy(Token, argv[i]);
          if (Token[0] == '-')
          {
             UpperCase(Token);
             if (strcmp(Token, "-NL") == 0)
                Listing = FALSE;
             else if (strcmp(Token, "-NS") == 0)
                StdFlag = FALSE;
             else if (strcmp(Token, "-NI") == 0)
                IncludeFlag = FALSE;
             else if (Token[1] == 'T')
             {
                if (i + 1 < argc)
                   Tabs = atoi(argv[++i]);
                else
                   fprintf(stderr, "Invalid Tab option\n");
             }
             else if (Token[1] == 'I')
             {
                if (i + 1 < argc)
                {
                   strcpy(IncludePath, argv[++i]);
                   if (IncludePath[strlen(IncludePath) - 1] != "\\")
                      strcat(IncludePath, "\\");
                }
                else
                   fprintf(stderr, "Invalid Include Path option\n");
             }
             else
             {
                fprintf(stderr, "Invalid option: %s\n", argv[i]);
             }
          }
          else if (strlen(InFile.Name) == 0)
             strcpy(InFile.Name, argv[i]);
          else
          if (strlen(OutFileName) == 0)
             strcpy(OutFileName, argv[i]);
          else
          {
             fprintf(stderr, "Invalid parameter or too many file names: %s\n",
             Abort();
          }
       }
    }
    if (strlen(InFile.Name) == 0)
    {
       fprintf(stderr, "I have nothing to do!  No input file specified.\n");
       Abort();
    }
    if (index(InFile.Name, '.') == NULL)
       strcat(InFile.Name, ".C");
    for (i = strlen(InFile.Name); i >= 0; i--)
    {
       if ((InFile.Name[i] == '\\') || (InFile.Name[i] == '/') || (InFile.Name
          break;
    }
    if (i < 0)
       strcpy(Path, "");
    else
    {
       strncpy(Path, InFile.Name, i + 1);
       Path[i + 1] = '\0';
    }
    if (strlen(OutFileName) == 0)
    {
       strcpy(OutFileName, InFile.Name);
       *index(OutFileName, '.') = 0x00;
    }
    if (index('.', OutFileName) == NULL)
       strcat(OutFileName, ".LST");
    if ((InFile.ID = fopen(InFile.Name, "r")) == NULL)
    {
       fprintf(stderr, "I can't find input file: %s\n", InFile.Name);
       Abort();
    }
    InFile.Lnno = 0;
    InFile.EndFile = FALSE;
    InFile.Print = TRUE;
    InFile.First = TRUE;
    if ((Output = fopen(OutFileName, "w")) == NULL)
    {
       fprintf(stderr, "I can't create output file: %s\n", OutFileName);
       Abort();
    }
    MainFile = InFile;
    ChIndex = 0;
    GetFileDate(InFile.ID->_file, &FDate, &FTime);
    strcpy(Today, " Date: ");
    strcat(Today, FDate);
    strcat(Today, " @ ");
    strcat(Today, FTime);

    if (Listing)
       Header();
    while (!MainFile.EndFile)
    {
       while (!InFile.EndFile)
       {
          Ch = GetChar();
          if (Ch == '"')
             GetLiteral();
          else if ((Ch == '#') && IncludeFlag)
             GetIncludeFile();
          else if (Ch == '\'')
             GetCharLiteral();
          else if (Ch == '/')
             GetComment();
          else if (index(IDChar, Ch) != NULL)
             GetToken();
          else if (Ch == '{')
          {
             if (NestLvl == NestMax)
                fprintf(stderr, "---- Too many levels\n");
             else
             {
                NestLvl++;
                NestUp = TRUE;
             }
          }
          else if (Ch == '}')
          {
             if (NestLvl == 0)
                fprintf(stderr, "---- Nesting Error");
             else
             {
                NestLvl--;
                NestDn = TRUE;
             }
          }
       }
       PrintLine();
       if (InFile.InsertChar != ' ')
       {
          fclose(InFile.ID);
          InFile = MainFile;
          ChIndex = 0;
       }
       else
          MainFile = InFile;
    }
    Header();
    fprintf(stderr, "\n");
    fprintf(stderr, "Writing Cross Reference\n");
    Concordance(Root);
    fclose(Output);
    fprintf(stderr, "    Total Pages= %d\n", PageNum);
 }

 void BackCh(Ch)
 char Ch;
 {
    UnGot = Ch;
    UnGetCount = 1;
 }

 char GetChar()
 {
    char Ch, InLine[255];
    int i, j;

    if (UnGetCount)
    {
       UnGetCount = 0;
       return (UnGot);
    }
    if (InFile.First)
    {
       InFile.ID = fopen(InFile.Name, "r");
       InFile.First = FALSE;
    }
    if (ChIndex == 0)
    {
       if (!InFile.EndFile)
       {
          if (InFile.Print)
          {
             InFile.Print = FALSE;
             fprintf(stderr, "\n");
             fprintf(stderr, "Line= %4d%c Total Lines= %4d  ", InFile.Lnno, In
             if (InFile.InsertChar != ' ')
                fprintf(stderr, "%13s", "");
             fprintf(stderr, "%s", InFile.Name);
             fputc(CR, stderr);
          }
          else
             PrintLine();
          fgets(InLine, 255, InFile.ID);
          i = j = 0;
          while (InLine[i])
          {
             if (InLine[i] == '\t')
             {
                do
                   Line[j++] = ' ';
                while (j % Tabs);
             }
             else
                Line[j++] = InLine[i];
             ++i;
          }
          Line[j] = 0x00;
          if (feof(InFile.ID))
             InFile.EndFile = TRUE;
          else
          {
             Line[strlen(Line) - 1] = 0x00;
             InFile.Lnno++;
             TotalLn++;
             GotoXY(6, WhereY());
             fprintf(stderr, "%4d%c", InFile.Lnno, InFile.InsertChar);
             GotoXY(25, WhereY());
             fprintf(stderr, "%4d", TotalLn);
             NestUp = FALSE;
             NestDn = FALSE;
             ChIndex = 1;
          }
       }
    }
    if (!InFile.EndFile)
    {
       if (ChIndex <= strlen(Line))
          Ch = Line[ChIndex++ - 1];
       else
       {
          Ch = ' ';
          ChIndex = 0;
       }
    }
    return (Ch);
 }

 void Init()
 {
    printf("C Cross Reference: Version 2.00  June 25, 1986\n\n");
    PageNum = 0;
    Root = NULL;
    InFile.InsertChar = ' ';
    TotalLn = 0;
    IncludeFile.InsertChar = '@';
    Listing = TRUE;
    StdFlag = TRUE;
    IncludeFlag = TRUE;
    NestUp = FALSE;
    NestDn = FALSE;
    NestLvl = 0;
    Tabs = 4;
    IncludePath[0] = 0x00;
 }

 int UpperCase(Str)
 char *Str;
 {
    int i;

    for (i = 0; i < strlen(Str); i++)
       if (islower(Str[i]))
          Str[i] = (char) toupper(Str[i]);
 }

 void GetFileDate(Handle, Date, Time)
 int Handle;
 char **Date, **Time;
 {
    char *malloc();

    struct
    {
       int AX, BX, CX, DX, SI, DI;
    } Regs;

    Regs.AX = 0x5700;
    Regs.BX = Handle;
    intdos(&Regs, &Regs);
    *Date = malloc(9);
    sprintf(*Date, "%02d-%02d-%02d", ((Regs.DX >> 5) & 0x0F), (Regs.DX & 0x1F)
            (Regs.DX >> 9));
    *Time = malloc(9);
    sprintf(*Time, "%02d:%02d:%02d", (Regs.CX >> 11), ((Regs.CX >> 5) & 0x3F),
            (Regs.CX & 0x1F));
 }

 void Header()
 {
    PageNum++;
    fputc(0x0C, Output);                /* Form Feed */
    fprintf(Output, "%-48s", MainFile.Name);
    fprintf(Output, "Block Structure and Cross Reference");
    fprintf(Output, "%29s   Page %3d", Today, PageNum);
    fprintf(Output, "\n\n\n");
    PageLn = 60;
 }

 void GetLiteral()
 {
    char Ch;

    do
    {
       Ch = GetChar();
       if (Ch == '\\')
       {
          Ch = GetChar();
          Ch = GetChar();
       }
    }
    while ((!InFile.EndFile) && (Ch != '"'));
 }

 void GetIncludeFile()
 {
    extern int stricmp();
    void PrintLine(), GetToken();

    int i, OK;
    char DeLim;
    char Temp[64];

    GetToken();
    if (stricmp(Token, TINCLUDE) == 0)
    {
       OK = TRUE;
       while ((!InFile.EndFile) && (Ch == ' '))
          Ch = GetChar();
       switch (Ch)
       {
       case '"':
          DeLim = Ch;
          break;
       case '<':
          DeLim = '>';
          break;
       default:
          DeLim = ' ';
       }
       for (i = 0; ((!InFile.EndFile) && ((Ch = GetChar()) != DeLim)); i++)
       {
          Temp[i] = Ch;
       }
       Temp[i] = 0x00;
       if (InFile.InsertChar == 'Z')
       {
          fprintf(stderr, "Too many include files\n");
          OK = FALSE;
       }
       else
       {
          if (DeLim == '"')
          {
             strcpy(IncludeFile.Name, Path);
             strcat(IncludeFile.Name, Temp);
          }
          else
          {
             strcpy(IncludeFile.Name, IncludePath);
             strcat(IncludeFile.Name, Temp);
          }
          IncludeFile.InsertChar++;
          IncludeFile.Lnno = 0;
          IncludeFile.EndFile = FALSE;
          IncludeFile.Print = TRUE;
          IncludeFile.First = TRUE;
          if ((IncludeFile.ID = fopen(IncludeFile.Name, "r")) == NULL)
          {
             fprintf(stderr, "\nCan't find include file: %s\n", IncludeFile.Na
             OK = FALSE;
          }
       }
       PrintLine();
       if (OK)
       {
          MainFile = InFile;
          MainFile.Print = TRUE;
          InFile = IncludeFile;
          ChIndex = 0;
       }
    }
 }

 void PrintLine()
 {
    void FillLine();

    int Column;

    if (Listing)
    {
       fprintf(Output, "%4d%c    ", InFile.Lnno, InFile.InsertChar);
       for (Column = 0; Column < NestLvl - 1; Column++)
          fprintf(Output, "|  ");
       if (NestLvl > 0)
       {
          if (NestUp || NestDn)
          {
             if (NestDn)
             {
                fprintf(Output, "|  ");
                fprintf(Output, "E--");
                for (Column = NestLvl + 1; Column < NestMax; Column++)
                   fprintf(Output, "---");
             }
             else
             {
                fprintf(Output, "B--");
                for (Column = NestLvl; Column < NestMax; Column++)
                   fprintf(Output, "---");
             }
             FillLine(Line);
          }
          else
          {
             fprintf(Output, "|  ");
             for (Column = NestLvl; Column < NestMax; Column++)
                fprintf(Output, "   ");
          }
       }
       else if (NestDn)
       {
          fprintf(Output, "E--");
          for (Column = 1; Column < NestMax; Column++)
             fprintf(Output, "---");
          FillLine(Line);
       }
       else
          for (Column = 0; Column < NestMax; Column++)
             fprintf(Output, "   ");
       fprintf(Output, "%s\n", Line);
       PageLn--;
       if (PageLn <= 0)
          Header();
    }
 }

 void FillLine(Line)
 char *Line;
 {
    int i;

    for (i = 0; i < strlen(Line) && Line[i] == ' '; i++)
       Line[i] = '-';
 }


 void GetToken()
 {
    TreeRec *BinaryTree();

    int j;

    j = 0;
    do
    {
       Token[j] = Ch;
       j++;
       Ch = GetChar();
    }
    while ((index(IDChar, Ch) != NULL) && (!InFile.EndFile));
    Token[j] = 0x00;
    if (StdFlag)
       Root = BinaryTree(Root);
    else if (!BinarySearch(Token, Reserved, 29))
       Root = BinaryTree(Root);
 }

 void GetComment()
 {
    char Ch;

    if (!InFile.EndFile)
       Ch = GetChar();
    if ((!InFile.EndFile) && (Ch == '*'))
    {
       while ((!InFile.EndFile) && (Ch != '/'))
       {
          while ((!InFile.EndFile) && (Ch != '*'))
             Ch = GetChar();
          Ch = GetChar();
       }
    }
    else
       BackCh(Ch);
 }

 void GetCharLiteral()
 {
    char Ch;

    do
    {
       Ch = GetChar();
       if (Ch == '\\')
       {
          Ch = GetChar();
          Ch = GetChar();
       }
    }
    while ((!InFile.EndFile) && (Ch != '\''));
 }

 int BinarySearch(T, A, Num)
 char *T, *A[];
 int Num;
 {
    extern int stricmp();
    int i, j, k, Result;

    i = 0;
    j = Num;
    do
    {
       k = (i + j) / 2;
       Result = stricmp(A[k], T);
       switch (Result)
       {
       case -1:
          i = ++k;
          break;
       case 1:
          j = --k;
          break;
       default:
          break;
       }
    }
    while ((Result != 0) && (i <= j));
    if (Result == 0)
       return (TRUE);
    else
       return (FALSE);
 }

 TreeRec *BinaryTree(wl)
 TreeRec *wl;
 {
    extern int stricmp();

    TreeRec *w;

    w = wl;
    if (w == NULL)
    {
       w = (TreeRec *) malloc(sizeof(*w));
       w->Ref = (WordRec *) malloc(sizeof(*(w->Ref)));
       w->Left = w->Right = NULL;
       wl = w;
       w->Ref->Key = malloc(strlen(Token) + 1);
       strcpy(w->Ref->Key, Token);
       w->Ref->LineList = (LineQueueRec *) malloc(sizeof(*(w->Ref->LineList)))
       w->Ref->LineList->First = NULL;
       AddQueue(w->Ref->LineList);
    }
    else
    {
       switch (stricmp(Token, w->Ref->Key))
       {
       case -1:
          w->Left = BinaryTree(w->Left);
          break;
       case 1:
          w->Right = BinaryTree(w->Right);
          break;
       case 0:
          AddQueue(w->Ref->LineList);
          break;
       }
    }
    return (w);
 }


 void AddQueue(Queue)
 LineQueueRec *Queue;
 {
    LineRec *w;

    w = (LineRec *) malloc(sizeof(LineRec));
    if (Queue->First == NULL)
       Queue->First = w;
    else
       Queue->Current->Next = w;
    Queue->Current = w;
    w->Next = NULL;
    w->Key = InFile.Lnno;
    w->Code = InFile.InsertChar;
 }

 char *FillString(Str, Size, Char)
 char *Str, Char;
 int Size;
 {
    char Temp[255];
    int l;

    strcpy(Temp, Str);
    if (strlen(Temp) < Size)
    {
       strcat(Temp, " ");
       l = strlen(Temp);
       while (l < Size)
          Temp[l++] = Char;
       Temp[l] = 0x00;
    }
    return (Temp);
 }

 void Concordance(T)
 TreeRec *T;
 {
    char *FillString();

    static char OldCh = 'A';
    LineRec *P;
    int i;

    if (T != NULL)
    {
       Concordance(T->Left);
       if (toupper(T->Ref->Key[0]) != OldCh)
       {
          fprintf(Output, "\n");
          PageLn--;
          if (PageLn <= 0)
             Header();
          OldCh = toupper(T->Ref->Key[0]);
       }
       fprintf(Output, "%s ", FillString(T->Ref->Key, 26, '.'));
       if (!BinarySearch(T->Ref->Key, Reserved, 29))
          fprintf(Output, "%c", ' ');
       else
          fprintf(Output, "%c", 'R');
       P = T->Ref->LineList->First;
       i = 0;
       while (P != NULL)
       {
          if (i >= 17)
          {
             fprintf(Output, "\n");
             i = 0;
             PageLn--;
             if (PageLn <= 0)
                Header();
             fprintf(Output, "%28s", " ");
          }
          fprintf(Output, "%4d%c", P->Key, P->Code);
          i++;
          if (i < 17)
             fprintf(Output, "%s", " ");
          P = P->Next;
       }
       if (i > 0)
       {
          fprintf(Output, "\n");
          PageLn--;
          if (PageLn <= 0)
             Header();
       }
       Concordance(T->Right);
    }
 }

 void Usage()
 {
    fprintf(stderr, "USAGE: cxref input_file_spec [output_file_spec] [options]
    fprintf(stderr, "\t-NL\tSuppress production of listing\n");
    fprintf(stderr, "\t-NS\tSuppress cross reference of C key words\n");
    fprintf(stderr, "\t-NI\tSuppress analysis of #include files\n\n");
    fprintf(stderr, "\t-I <path> Provide path for #include <file> files\n");
    fprintf(stderr, "\t-T <n>    Provide the tab stop value for tab expansion\
    exit();
 }


 C_FUNCT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\C_FUNCT.C

 pr *.f


 Jul 27 17:12 1984  fact.f Page 1


 double fact(num)        /* recursive function to compute and
                            return factorial (num!) for num > 0 */
 int num;
 {       if      (num > 1)
                 return (num * fact(num - 1));
         else    return 1;
 }
























































 Jul 27 17:12 1984  getdbl.f Page 1


 double  getdbl()        /* convert ASCII from terminal to dbl */
 {       int     c, sign = 1;    /* c = char input, sign = + */
         float   d = 1.0;        /* d = decimal place */
         double  num = 0.0;      /* num = converted number */
         printf("input number: ");
         if      ((c = getchar()) == '-')
                 sign = -1;                      /* sign = - */
         else if (c == '\n' || c == EOF)
                 return (0);
         else if (c == '.')
                 goto dot;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         while ((c = getchar()) != '\n' && c != '.' && c != EOF)
                 if (c >= '0' && c <= '9')
                         num = num * 10 + (c - '0');
         if (c == '.')
 dot:            while ((c = getchar()) != EOF && c != '\n')
                         if (c >= '0' && c <= '9')
                         { d /= 10.0; num += d * (c - '0');
                         }
         return (num * sign);
 }








































 Jul 27 17:12 1984  getdbl_a.f Page 1


 double getdbl_a()       /* use (3S) & (3C) functions */
 {       char stor[MAX];
         double atof();

         printf("input number: ");
         return (atof(fgets(stor, MAX, stdin)));
 }
























































 Jul 27 17:12 1984  getdbl_n.f Page 1


 double  getdbl_n()      /* convert ASCII to dbl - 2nd version */
 {       int     c, sign = 1;    /* c = char input, sign = + */
         float   d = 1.0;        /* d = decimal place */
         double  num = 0.0;      /* num = converted number */
         printf("input number: ");
         if      ((c = getc(stdin)) == '-')
                 sign = -1;              /* sign = - */
         else if (c == '\n' || c == EOF)
                 return (0);
         else if (c == '.' || (c >= '0' && c <= '9'))
                 ungetc(c, stdin);       /* return c to buffer */
         while ((c = getc(stdin)) != '\n' && c != '.' && c != EOF)
                 if (c >= '0' && c <= '9')
                         num = num * 10 + (c - '0');
         if (c == '.')
                 while ((c = getc(stdin)) != EOF && c != '\n')
                         if (c >= '0' && c <= '9')
                         { d /= 10.0; num += d * (c - '0');
                         }
         return (num * sign);
 }










































 Jul 27 17:12 1984  getint.f Page 1


 getint()        /* function to convert ASCII
                 /* input from terminal to an int */
 {       int     c, sign = 1, num = 0;

         printf("input integer: ");
         if      ((c = getchar()) == '-')
                 sign = -1;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         else
                 return (0);
         while ((c = getchar()) >= '0' && c <= '9')
                 num = num * 10 + (c - '0');
         return (num * sign);
 }
















































 Jul 27 17:12 1984  getintp.f Page 1


 int *getintp()  /* function to convert ASCII
                 /* input from terminal to an int;
                 /* return pointer to int */
 { int   c, sign = 1, num = 0;

   printf("input integer: ");
   if    ((c = getchar()) == '-')
         sign = -1;
   else if (c >= '0' && c <= '9')
         num = (c - '0');
   else
         return (&num);
   while ((c = getchar()) >= '0' && c <= '9')
         num = num * 10 + (c - '0');
   num *= sign;
   return (&num);
 }














































 Jul 27 17:12 1984  getline.f Page 1


 getline(line, lim)      /* function to read a line from std input;
                         /* insert NULL at end and return char count */
 char    line[];         /* array where line will be stored */
 int     lim;            /* max line size */
 {
   int   c, i;

   for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
         line[i] = c;
   if (c == '\n')                /* retain  */
         line[i++] = c;          /* newline */
   line[i] = '\0'; return (i);
 }


















































 Aug  3 14:21 1984  getlinep.f Page 1


 getlinep(line, lim)     /* function to read a line from std input;
                         /* insert NULL at end and return char count */
 char    *line;          /* array where line will be stored */
 int     lim;            /* max line size */
 {
   int   c, i;

   for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
         *line++ = c;
   if (c == '\n')                /* retain  */
         *line++ = c;            /* newline */
   *line = '\0'; return (i);
 }


















































 Jul 27 17:12 1984  getlinepn.f Page 1


 getlinepn(pline, lim)   /* function to get a line from std input
                         /* (do not save newline); insert null at end
                         /* and return char count per PA ex. 04a */
 char    *pline;         /* pointer to array where line will be stored */
 int     lim;            /* max line size */
 {
   register c, i;

   for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
         *pline++ = c;           /* newline is                   */
   *pline = '\0'; return (i);    /*      not retained or counted */
 }



















































 Jul 27 17:12 1984  inter.f Page 1


 inter(pfi)      /* call function via pointer arg */
 int (*pfi)();   /* pfi is pointer to function
                 /* returning type int */
 {
   return ((*pfi)());    /* (*pfi)() is a function call */
 }

























































 Jul 27 17:12 1984  itob.f Page 1


 itob(num, ar)   /* convert int to ASCII 0's and 1's */
 int num;        /* received int */
 char ar[];      /* array to store 0's and 1's */
 {       int cnt, mask = 1;
         for (cnt = (8 * sizeof(cnt)) - 1; cnt >= 0; cnt--)
         {       ar[cnt] = ((num & mask)? '1': '0'); mask <<= 1;
         }
         ar[(8 * sizeof(cnt))] = '\0';
 }






















































 Jul 27 17:12 1984  power.f Page 1


 power(x, n)     /* raise x to the n-th power; n > 0 */
 int x, n;       /* declaration of arguments */
 {
         int i, p = 1;
         for (i = 1; i <= n; ++i)
                 p = p * x;
         return (p);
 }























































 Jul 27 17:12 1984  square.f Page 1


 square(ar, sz)  /* fills array ar of size sz with the
                 /* square of the element number */
 int ar[], sz;
 {
         for (--sz; sz >= 0; --sz)
                 ar[sz] = sz * sz;
 }
























































 Jul 27 17:12 1984  strcmp.f Page 1


 strcmp(s1, s2)  /* compare 2 strings;
                 /* if match return 0 (else char count) */
 char    *s1, *s2;
 {       register i;
         for (i = 1; *s1 == *s2; ++i)
                 if (*s1++ == '\0')
                         return (0);
                 else s2++;
         return (i);
 }





















































 Jul 27 17:12 1984  strcpy.f Page 1


 strcpy(d, s)    /* copy string in s[] into d[] */
 char d[], s[];
 {       register i;
         for (i = 0; d[i] = s[i]; ++i)
                 ;
 }

























































 Jul 27 17:12 1984  strcpy_p.f Page 1


 strcpy_p(d, s)  /* copy string *s to *d */
 char *d, *s;
 {
         while (*d++ = *s++)
                 ;
 }

























































 Jul 27 17:12 1984  strln.f Page 1


 strln(str)      /* return length of char string stored in array str;
                 /* include null at end in count */
 char str[];
 {       int i = 0, length = 0;
         do
         {       ++length;
         } while (str[i++] != '\0');
         return (length);
 }






















































 Jul 27 17:12 1984  strln_p.f Page 1


 strln_p(ptr)    /* return length of char string pointed to by ptr;
                 /* include null at end in count */
 char *ptr;
 {       register length = 0;
         do
         {       ++length;
         } while (*ptr++ != '\0');       /* ++ increments ptr by 1 */
         return (length);
 }






















































 Jul 27 17:12 1984  swap.f Page 1


 swap(px, py)            /* call by reference */
 int *px, *py;           /* px, py are pointers to type int */
 {       int tmp;
         tmp = *px;
         *px = *py;
         *py = tmp;
 }
























































 Jul 27 17:12 1984  vol.f Page 1


 double vol(a, b, c)     /* given 3 dimensions compute volume */
 double a, b, c;         /* arg declarations */
 {
         return (a * b * c);
 }
























































 $


 C_TO_PAS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\C_TO_PAS.C

 /* C to Pascal program -- filter to replace C punctuation and certain
    key words with their Pascal equivalents.

   C form          Pascal form
  -======-        -===========-
     "                 '
     {               BEGIN
     }                END
   <tab>        < 2 blank spaces >
     ()            < nothing >
     &&               AND
     ||                OR
 comment start        {
 comment end          }
     ==               =
     !=               <>
     =                :=
  printf            writeln
  scanf             readln
  while             WHILE

 Usage:  ctopas <infile >outfile

 Copyright 1984 Ted Carnevale.
 Permission granted for personal nonprofit use.
 All other rights reserved.
 */

 #include "stdio.h"
 #include "ctype.h"
 #define EOF -1
 #define EOS '\0'

 main()
 {
    char c, *letter, word[100];
    int wordlnth;

    letter=word;
    wordlnth=0;
    while((c=getchar()) != EOF) {
       if(isalpha(c)) letter[wordlnth++]=c;
       else {
          if(wordlnth>0) {            /* word ready to check */
             letter[wordlnth]='\0';
             wtest(word);             /* pass or replace it */
             wordlnth=0;              /* reset index */
          }
          ctest(c);                   /* process following character */
       }
    }
 }       /* Note:  the last word in the file will be missed if it is
 immediately followed by EOF with no intervening nonalpha characters.
 This is not a problem for Pascal or C source files.  However,
 a general purpose workd filter would have to check for a nonzero
 wordlength after EOF is reached.   */

 wtest(word)
 char *word;
 {
    char *swapword;

    swapword=word;
    switch(word[0]) {       /* test first letter, then rest of word */
       case 'p':  if(strcmp(word,"printf\0")==0) swapword="writeln\0";
         break;
       case 's':  if(strcmp(word,"scanf\0")==0) swapword="readln\0";
         break;
       case 'w':  if(strcmp(word,"while\0")==0) swapword="WHILE\0";
         break;
       default:  break;       /* pass unchanged */
    }
    swap(swapword);
 }

 ctest(c)
 char c;
 {
    switch(c) {
    case '"':  putchar('\'');
      break;
    case '{':  swap("BEGIN\0");
      break;
    case '}':  swap("END;\0");
      break;
    case '\t':  swap("  \0");
      break;
    case '&':  swapif('&','&',"AND  \0");
      break;
    case '|':  swapif('|','|',"OR  \0");
      break;
    case '(':  swapif('(',')',"\0");
      break;
    case '/':  swapif('/','*',"{\0");
      break;
    case '*':  swapif('*','/',"}\0");
      break;
    case '!':  swapif('!','=',"<>\0");
      break;
    case '<':
    case '>':  putchar(c);      /* <x and >x are passed unchanged */
               c=getchar();
               putchar(c);
      break;
    case '=':  identassign();   /* == -> =, = -> := */
      break;
    default :  putchar(c);
      break;

    }
 }

 swap(s)
 char *s;
 {
    while(*s != EOS) putchar(*s++);
 }

 swapif(first, second, replacement)
 char first, second, *replacement;
 {
    char c;

    if((c=getchar()) == second) swap(replacement);
    else {
       putchar(first);
       putchar(c);
    }

 }

 identassign()
 {
    char c;

    if((c=getchar()) != '=') {          /* assignment */
       putchar(':');
       putchar('=');
    }
    putchar(c);
 }

 /* end of ctp.c */


 DATA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DATA.C

 /*    DATA.C   DATA.C    DATA.C    DATA.C    DATA.C    DATA.C

 DATA INITIALIZE AND CALCULATE      XXXX     X    XXXXX    X
                                    X   X   X X     X     X X
 July 1, 1987                       X   X  X   X    X    X   X
                                    X   X  X   X    X    X   X
                                    X   X  XXXXX    X    XXXXX
                                    X   X  X   X    X    X   X
                                    XXXX   X   X    X    X   X
 */
 #include "ctype.h"
 #include "string.h"
 #include "math.h"
 #include "struct.def"
 #include "defin.h"

 extern struct vars allvars[];
 extern char inline[];
 extern int col;
 extern int errcode,colerr;
 extern char strngout[];
 extern int valattr;

 /* ****************************************************** initdata */
 /* This function is used to initialize all of the variables to the */
 /* starting values including their variable names.                 */
 void initdata(struct vars *pnt)
 {
 int index;
     for (index = 0;index < 6;++index){
        (pnt+index)->varname[0] = 'A' + index;
        (pnt+index)->varname[1] = 0;
        (pnt+index)->outtype = 'F';
        (pnt+index)->value = 0.0;
     }
     for (index = 6;index < 12;++index){
        (pnt+index)->varname[0] = 'I' + index - 6;
        (pnt+index)->varname[1] = 0;
        (pnt+index)->outtype = 'D';
        (pnt+index)->value = 0;
     }
     (pnt+4)->value = 2.718281828459045;
     (pnt+5)->value = 3.141592653589793;
     (pnt+11)->value = 16777215;
 }

 /* ******************************************************* getnames */
 /* This function reads in a new list of variable names to be used   */
 /* in place of the names A to F. This is only as a convenience for  */
 /* the user, so he can use more meaningful names.                   */
 void getnames(void)
 {
 char var,index;
 char dummy[80];

    col = 1;                      /* skip over and ignore the # sign */
    do {
       if (inline[col] == ' ') col++;   /* ignore all leading blanks */
       else {
          var = inline[col] - 'A';
          if ((var >= 0) && (var <= 5)) {             /* A through F */
             col++;
             if (inline[col] != '-') {           /* should be a dash */
                errchk(14);
                errout();
                return;
             }
             col++;
             for (index = 0;index < 6;index++)
                if (isalpha(inline[col]) || isdigit(inline[col])) {
                   dummy[index] = inline[col];
                   dummy[index + 1] = 0;
                   col++;
                }
             if (index > 0) {
                strcpy(allvars[var].varname,dummy);
                strcpy(strngout,"      ");         /* this is for    */
                strngout[6-strlen(dummy)] = 0;     /* leading blanks */
                strcat(strngout,dummy);
                strngdis(var + 1,1,valattr);
             }
          }
          else if ((var >= 8) && (var <= 13)) {       /* I through N */
             col++;
             if (inline[col] != '-') {           /* should be a dash */
                errchk(14);
                errout();
                return;
             }
             col++;
             if ((inline[col] == 'O') || (inline[col] == 'D') ||
                 (inline[col] == 'H') || (inline[col] == 'X')) {
                var -= 2;
                allvars[var].outtype = inline[col];
                col++;
             }
             else {
                errchk(15);
                errout();
                return;
             }
          }
          else {                            /* unknown variable name */
             errchk(3);
             errout();
             return;
          }
       }
    } while (inline[col] && (errcode == 0));
 }

 /* ******************************************************* calcdata */
 /* This is the function that actually does the work of deciding     */
 /* what calculations need to be done. The method used is described  */
 /* in detail below.                                                 */
 /*    Three variables and two operators are         number1         */
 /*    stored as per the list. "op1" is always         op1           */
 /*    a plus or minus, and op2 is always a          number2         */
 /*    multiplication or divide. If a plus or          op2           */
 /*    minus is found for op2, number1 and           number3         */
 /*    number2 are combined according to op1                         */
 /*    and the result becomes number1, the new op2 becomes op1, and  */
 /*    number3 becomes number2. If op2 is either a multiplication or */
 /*    divide, number2 and number3 are combined according to op2 and */
 /*    the result is placed in number2. When a parentheses is found, */
 /*    a recursive call is made and the expression in the parenthe-  */
 /*    ses is evaluated. A bit of study will be very fruitful in     */
 /*    understanding this operation.                                 */
 void calcdata(double *newval)
 {
 double number1,number2,number3,getnum();
 char op1,op2,getop();
    number1 = 0.0;
    op1 = '+';
    number2 = 0.0;
    while (inline[col] == ' ') col++;               /* ignore blanks */
                                         /* check for unary operator */
    if ((inline[col] == '+') || (inline[col] == '-')) {
       op1 = inline[col];
       col++;
    }

    number2 = getnum();          /* (inline[col]== 0 ) = End of line */
                                 /* (inline[col]=='$') = End of line */
    if ((inline[col] == 0) || (inline[col] =='$')) {
       calcdat(&number1,&op1,&number2);
       *newval = number1;
       return;
    }
    for (;;){
       op2 = getop();
       col++;
                                /* check for end of line  0, ), or $ */
       if (op2 == '$') op2 = 0;        /* force a $ to lool like eol */
       if ((op2 == 0) || (op2 == ')')) {
          col++;
          calcdat(&number1,&op1,&number2);
          *newval = number1;
          return;
       }
       number3 = getnum();
       if ((op2 == '*') || (op2 == '/')){
          calcdat(&number2,&op2,&number3);
       }
       else{
          calcdat(&number1,&op1,&number2);
          op1 = op2;
          number2 = number3;
       }
    } /* end of infinite for loop */
 }

 /* ******************************************************** calcdat */
 /* This function actually does the calculations described in the    */
 /* function above.                                                  */
 void calcdat(double *number1,char *op1,double *number2)
 {
    switch (*op1) {
       case '*' : *number1 = (*number1)*(*number2);
                  break;
       case '/' : if (*number2 == 0.0) {
                      errchk(10);
                      break;
                  }
                  *number1 = (*number1)/(*number2);
                  break;
       case '+' : *number1 = *number1 + *number2;
                  break;
       case '-' : *number1 = *number1 - *number2;
                  break;
       default  : break;
    }
    return;
 }

 /* ********************************************************* getnum */
 /* This is the workhorse of the program. It actually scans the data */
 /* input field and converts the data into numbers which are in the  */
 /* internal format of the computer so the calculations can be done. */
 double getnum(void)
 {
 int index,i,decpt;
 double newval;
 char name[7];
 double sqrt(), exp(), log(), sin(), cos(), atan();

    while (inline[col] == ' ') col++;               /* ignore blanks */

    index = inline[col];
    if (index == '('){
        col++;
        calcdata(&newval);                         /* recursive call */
        col--;
        return(newval);
    }

    decpt = 0;                         /* search for a decimal point */
    i = col;
    index = inline[i];
    while ((index >= '0') && (index <= '9')) {
       i++;
       index = inline[i];
       if (index == '.') decpt = 1;
    }

    index = inline[col];
    if (((index > '0') && (index <= '9')) ||
        ((index == '0') && (decpt == 1))  ||
         (index == '.')) {                        /* floating number */
       newval = 0.0;
       while ((index >= '0') && (index <= '9')) {
          newval = 10.0*newval + (index - '0');
          col++;
          index = inline[col];
       }
       if (index == '.') {
          double constant = 0.1;
          col++;
          index = inline[col];
          while ((index >= '0') && (index <= '9')) {
             newval = newval + (index - '0') * constant;
             constant *= 0.1;
             col++;
             index = inline[col];
          }
       }
       return(newval);
    }                                /* end of floating point number */

    if (index == '0') {                      /* octal or hexadecimal */
       col++;
       index = inline[col];
       if ((index == 'x') || (index == 'X')){         /* hexadecimal */
          col++;
          index = inline[col];
          newval = 0.0;
          while (((index >= '0') && (index <= '9')) ||
                 ((index >= 'A') && (index <= 'F')) ||
                 ((index >= 'a') && (index <= 'f'))) {
             switch (index) {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':i = index - '0';
                         break;
                case 'A':
                case 'B':
                case 'C':
                case 'D':
                case 'E':
                case 'F':i = index - 'A' + 10;
                         break;
                case 'a':
                case 'b':
                case 'c':
                case 'd':
                case 'e':
                case 'f':i = index - 'a' + 10;
                         break;
                default :break;
             }
             newval = 16.0*newval + i;
             col++;
             index = inline[col];
          }
       return(newval);
       }                                  /* end of hexadecimal 'if' */

       else {                                               /* octal */
          newval = 0.0;
          while ((index >= '0') && (index <= '7')) {
             newval = 8.0*newval + (index - '0');
             col++;
             index = inline[col];
          }
       return(newval);
       }                                      /* end of octal 'else' */

    }                         /* end of octal or hexadecimal numbers */

                                   /* find variable or function name */
    if ((inline[col] >= 'A') && (inline[col] <= 'Z')) {
       name[0] = inline[col++];
       i = 1;
       while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
              ((inline[col] >= '0') && (inline[col] <= '9'))) &&
              (i <= 5)) {           /* continue var or function name */
          name[i++] = inline[col++];
       }
       name[i] = 0;                                    /* name found */

       if (inline[col] == '('){                     /* function call */
          col++;
          if (strcmp(name,"ABS") == 0) {
             calcdata(&newval);
             if (newval < 0.0) newval = -newval;
          }
          else if (strcmp(name,"SQRT") == 0) {
             calcdata(&newval);
             if (newval < 0.0) {
                errchk(5);                     /* Neg value for SQRT */
                newval = 0.0;
             }
             else newval = sqrt(newval);
          }
          else if (strcmp(name,"FACT") == 0) {
             calcdata(&newval);
             if (newval < 0.0) {
                errchk(16);                    /* Neg value for FACT */
                newval = 0.0;
             }
             else {
             double count;
             int howmany;
                count = newval;
                newval = 1.0;
                for (howmany = count;howmany > 1;howmany--) {
                   count = howmany;
                   newval = newval * count;
                }
             }
          }
          else if (strcmp(name,"EXP") == 0) {
             calcdata(&newval);
             newval = exp(newval);
          }
          else if (strcmp(name,"LOG") == 0) {
             calcdata(&newval);
             if (newval < 0.0) {
                errchk(7);                      /* Neg value for LOG */
                newval = 0.0;
             }
             else newval = log(newval);
          }
          else if (strcmp(name,"SIN") == 0){
             calcdata(&newval);
             newval = sin(newval);
          }
          else if (strcmp(name,"COS") == 0){
             calcdata(&newval);
             newval = cos(newval);
          }
          else if (strcmp(name,"ATAN") == 0){
             calcdata(&newval);
             newval = atan(newval);
          }
          else {
             errchk(6);                        /* function not found */
             newval = 0.0;
          }
          col--;
          return(newval);
       }                                     /* end of function call */

       else {                                       /* variable name */
          for (i = 0;i < 12;i++) {
             if ((strcmp(name,allvars[i].varname)) == 0) {
                newval = allvars[i].value;
                return(newval);
             }
          }
          errchk(3);                           /* variable not found */
          newval = 0.0;
          return(newval);
       }                                     /* end of variable call */

    }                            /* end of variable or function call */
    errchk(9);
    return(0.0);                               /* invalid data found */
 }

 /* ********************************************************** getop */
 /* A call to this function expects to find an operator, end of line */
 /* or a close parenthesis.                                          */
 char getop(void)
 {
    while (inline[col] == ' ') col++;               /* ignore blanks */
    switch (inline[col]){
       case '$':
       case ')':
       case  0 :
       case '+':
       case '-':
       case '*':
       case '/': break;
       default : errchk(4);                      /* invalid operator */
    }
    return(inline[col]);
 }

 /* ********************************************************* errchk */
 /* The error code is stored by this function and the cursor column  */
 /* is adjusted in an attempt to put the cursor near the error that  */
 /* caused the problem.                                              */
 void errchk(int err)
 {
    if(errcode) return;                       /* error already found */
    else {                         /* only the first error is stored */
       errcode = err;                      /* store the error number */
       switch (err){
          case 2  :
          case 4  :
          case 8  :
          case 9  :
          case 10 :
          case 11 :
          case 12 : colerr = col;
                    break;
          case 1  :
          case 3  : colerr = col - 1;
                    break;
          case 6  : colerr = col - 2;
                    break;
          case 5  :
          case 7  : colerr = col - 3;
                    break;
          default : colerr = col;
       }
    }
 }


 DAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\DAY.C



 /* ---------------------------------------------------------------------- */
 /*        Program to calculate # of days between two dates                */
 /*        This program was tested & compiled on a DeSmet 'C' compiler     */
 /*        ver 2.2 -- but should run on any good 'C' compiler              */
 /* ---------------------------------------------------------------------- */

 /* Please note that this program only works from 01-12-1600 A.D. onward   */



 struct date                                 /*   structure to hold date   */
   {
    int     month;
    int    day;
    int    year;
   } date_1;


 long int funct1 (y,m)                       /*   part of # of days calc.  */
     int y, m;
     {
      long int result;
      if ( m <= 2 )
        y -= 1;
      result = y;
      return (result);
     }

 long int funct2 (m)
     int m;
     {
      long int result;
      if ( m <= 2 )
        result = m + 13;
      else
        result = m + 1;
        return(result);
     }

 /* Function to calculate the number of days in dates */

 long int day_count (m, d, y)
     int m, d, y;
     {
      long int number;
      number = 1461 *  funct1(y,m) / 4 + 153 * funct2(m) / 5 + d;

      return (number);
     }

 main ()
 {
     long int number_of_days1;
     int day_of_week, screw_up = 0;

     printf("\n\n*************************************************************
     printf("THIS PROGRAM WILL COMPUTE THE DAY OF THE WEEK (SUNDAY - SATURDAY)
     printf("\t\tTHAT A GIVEN DATE WILL FALL ON\n");
     printf("*****************************************************************

     printf ("Enter a date (mm dd yyyy) i.e. 03 12 1985  \n");
     scanf ("%d %d %d", &date_1.month, &date_1.day, &date_1.year);

     number_of_days1 = day_count (date_1.month, date_1.day, date_1.year);

     printf ("\nThe date is:  " );

     day_of_week = (number_of_days1 - 621049) % 7;

     switch (day_of_week)
       {
         case 0 :
             printf ("Sunday,");
             break;
         case 1 :
             printf ("Monday,");
             break;
         case 2 :
             printf ("Tuesday,");
             break;
         case 3 :
             printf ("Wednesay,");
             break;
         case 4 :
             printf ("Thursday,");
             break;
         case 5 :
             printf ("Friday,");
             break;
         case 6 :
             printf ("Saturday,");
             break;
         default:
             printf ("Something is screwed up -- Maybee you entered\n");
             printf ("a date earlier than 01 12 1600\n\n");
             screw_up = 1;
       }
       if ( !screw_up )
         printf (" %02d/%02d/%02d\n", date_1.month, date_1.day, date_1.year);
 }


 DBCLEAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBCLEAN.C

 /****************************************************************
 * db_clean is a utility program for DBASE II files.  It performs*
 * the following functions.                                      *
 *                                                               *
 *    (i)   It strips all non-printing ASCII characters from the *
 *          data fields by changing them to blanks.              *
 *                                                               *
 *    (ii)  It strips all non-printing characters from the status*
 *          field except for the CP/M end of file marker (^Z)    *
 *          which it replace with a blank unless it is a valid   *
 *          end of file mark.                                    *
 *                                                               *
 *    (iii) It reset the record count in the DBASE file header.  *
 *                                                               *
 *    (C) Richard Hoffbeck                                 1983  *
 ****************************************************************/

 #include   "libc.h"
 #include   "dbase.h"
     DB_SECT_SZ   512        /* DBASE uses a 512 byte file buffer */

 int         maxrec ;
 long        char_size ;
 DBASE_FILE  *db_ptr ;

 main(argc,argv)
      char *argv[] ;
      int  argc ;

      {char          DONE = FALSE, db_buffer[1000] ;
       int           i = 0, chng = FALSE, bad_eof = 0, bad_char = 0 ;
       long          lseek() ;

       if( argc != 2 ){
          help() ;
          exit() ;
       }

       else if( (db_ptr = db_open(argv[1])) == ERROR ){
          printf("\n %s NOT FOUND",argv[1]) ;
          exit() ;
       }

       char_size = lseek(db_ptr->file_ptr,0L,2) ;
       maxrec = (char_size-DATA_START) / db_ptr->rec_len  ;
       db_seek(db_ptr,1,0) ;
       printf("\nThere are a maximum of %d records",maxrec) ;
       printf("\nProcessing ");
       /*---------- Start of main loop ----------*/
       while( ! DONE  &&  (db_read(db_ptr,db_buffer,1) != ERROR) ) {
          chng = FALSE ;
          if( ++i == maxrec )
            DONE = TRUE ;
          if( (i % 25) == 0 )
             putchar('.') ;
          if( db_buffer[0] == CPM_EOF ) {
             if(  valid_eof(i,db_buffer) != FALSE )
                DONE = TRUE ;
             else  {                            /*invalid end of file */
                chng = TRUE ;
                db_buffer[0] = ' ' ;
                bad_eof++ ;
             }
          }
          if( strip(db_buffer,db_ptr->rec_len) > 0 ) {       /*invalid charact
             chng = TRUE ;
             bad_char++ ;
          }
          if( chng == TRUE ) {                                     /*if there
             db_seek(db_ptr,i,0) ;                                 /* rewrite
             db_write(db_ptr,db_buffer,1) ;
          }
       }

      /*----- finish up the book keeping -----*/
      if( i != db_recnum(db_ptr) ) {
          db_ptr->rec_num = i ;
          db_ptr->chng_ind = TRUE ;
          db_close(db_ptr) ;
       }
       printf("\n\n\n\tThere were %d bad end of file markers removed",bad_eof)
       printf("\n\tand %d records with illegal characters were rewritten",bad_
 }



 /*********************************************************
 * strip(str,len) strips the non-printing ascii characters*
 * from the string "str".  First the 8th bit is stripped  *
 * from  each  character and then the  following  rule is *
 * applied                                                *
 *                                                        *
 * (i)   If the character is <= 32 (space), except for ^Z *
 *       CP/M end of file, it is converted to a space     *
 *                                                        *
 * (ii)  Any character in the first position other than a *
 *       '*' (DBASE deleted record marker), a space or a  *
 *       ^Z is reset to a space (NORMAL status)           *
 *********************************************************/
 strip(buff,len)
      char buff[] ;
      int  len ;

      {int      bad_char ;
      bad_char = 0 ;

      /*----- process the last n-1 charaters in the string -----*/
      while ( --len > 0 ) {
         if( buff[len] & 128 ) {
            buff[len] = buff[len] & 127 ;
            bad_char++;
         }
         if( buff[len] < 32 ){
            buff[len] = 32 ;
            bad_char++ ;
          }
      }

      if( buff[0] != '*' && buff[0] != ' ' && buff[0] != CPM_EOF ) {
         buff[0] = ' ' ;
         bad_char++ ;
      }

      return( bad_char ) ;
 }


 /**********************************************
 * valid_eof(i) determines whether or not the  *
 * CP/M end of file mark encountered in the    *
 * status field of the ith record is valid.  It*
 * uses the following set of rules :           *
 *                                             *
 * (i)   If the record is the maximum record in*
 *       the file, return TRUE.                *
 *                                             *
 * (ii)  If the record is not within a DBASE   *
 *       buffer size of the end of the file, a *
 *       FALSE value is returned               *
 *                                             *
 * (iii) If no other end of file mark is en-   *
 *       countered in the file, return TRUE    *
 *                                             *
 * (iv)  If two potentially valid EOF marks are*
 *       found, the  user is prompted for a    *
 *       decision.                             *
 **********************************************/
 valid_eof(i,buffer)
      int  i ;
      char buffer[] ;

      {int   cur_rec ;
       char  db_buffer[1000], c ;

      if( i >= maxrec-1 )
         return( TRUE ) ;
      else if( (i*db_ptr->rec_len+DATA_START) < (char_size-DB_SECT_SZ) )
         return( FALSE ) ;
      else if( strip(buffer,db_ptr->rec_len) > 2)
         return( TRUE ) ;
       else {
          printf("\nUnable to determine whether the end of file mark");
          printf("\nat record #%d is reasonable",i) ;
          printf("\nIs this the end of the file[Y/N]:");
          c = keyin() ;
          if( (c == 'y') || (c == 'Y') )
             return( TRUE ) ;
          else
            return( FALSE ) ;
       }
 }

 help() {
      puts("DBCLEAN is a utility program for cleaning up DBASE II files.");
      puts("Because of some bugs, DBASE will occasionally place invalid ");
      puts("characters in the record status field or in the data field that");
      puts("efffectively lock up the database.  DBASE is also known to mis-");
      puts("count the records which causes problems with some of the com-");
      puts("mands.  DBCLEAN attempts to repair these damaged DBASE files and")
      puts("the interested user should see the source file DBCLEAN.C for ");
      puts("details."); puts(" ");
      puts("     To use DBCLEAN simply type"); puts(" ");
      puts("       DBCLEAN filename.dbf") ; puts(" ") ;
      puts(">>>>> Caution: DBCLEAN rewrites the database in place so it <<<<<"
      puts(">>>>> should only be used on a copy of your working dataset <<<<<"
      puts(">>>>> until you have a corrected version.                   <<<<<"
 }






 DBCLOSE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBCLOSE.C

 #include  "libc.h"
 #include  "dbase.h"


 /***************************************************************
 *  db_close(db_ptr) closes the dbase file pointed to by db_ptr *
 * if the file has been changed, dbclose updates the dbase head-*
 * er before closing the file.  Any  errors are  passed back to *
 * the calling routine.                                         *
 ***************************************************************/
 db_close(db_ptr)
    DBASE_FILE  *db_ptr ;
    {int        inptr ;

    inptr = db_ptr->file_ptr ;         /* save the file pointer */

    /*----- Update the file description block if required -----*/
    if( db_ptr->chng_ind == TRUE ) {
       lseek(db_ptr->file_ptr,0L,0) ;
       write(db_ptr->file_ptr,db_ptr,DB_HDR_SZ) ;
    }
    return( close(inptr) ) ;                        /* save the file and retur
 }


 DBCREATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBCREATE.C

 #include        "libc.h"
 #include        "dbase.h"

 /***************************************************************
 *  db_create(filename)  creates a new  DBASE file  header for  *
 * output.  A pointer to the DBASE file description block is    *
 * returned if there is sufficient memory.  If not, the ERROR   *
 * value is returned.                                           *
 *                                                              *
 * Richard Hoffbeck                                  (c) 1983   *
 ***************************************************************/
 db_create(filename)
    char                filename[];
    {int         *inptr ;
     DBASE_FILE  *db_ptr ;

    /*------- allocate memory for the file desc. block -----*/
    if( (db_ptr=alloc(DB_HDR_SZ)) == ERROR ){
       printf("\nInsufficient HEAP space to create file descriptor");
       printf("\nCalled from db_create");
       exit();
    }

    /*----- initialize the file description block -----*/
    if( (inptr=open(filename,O_TRUNC+O_RDWR)) == ERROR ){
       printf("\nUnable to open file %s",filename);
       printf("Called from db_create");
       return( ERROR );
    }

    clear(db_ptr,DB_HDR_SZ,0) ;
    db_ptr->file_ptr = inptr ;
    db_ptr->version  = 02 ;
    db_ptr->chng_ind = TRUE ;

    return( db_ptr ) ;
 }


 DBDUPL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBDUPL.C


 #include  "libc.h"
 #include  "dbase.h"


 /***************************************************************
 *  db_dupl(dp_ptr) duplicates a DBASE file  description  block *
 * and returns a pointer to the block.  It aborts the processing*
 * if there is insufficient memory to create the block.         *
 ***************************************************************/
 db_dupl(filename,db_ptr)
    DBASE_FILE  *db_ptr ;
    char        filename[] ;
    {DBASE_FILE *db_new ;

    /*----- open the new file and allocate file descriptor space -----*/
    if( (db_new=db_open(filename)) == ERROR ) {
       printf("\nInsufficient HEAP space to create the block");
       printf("\nCalled from db_dupl");
    }

    /*----- there was enough space, copy the old block and set */
    /*----- the change indicator                               */
    blockmv(db_ptr,db_new,DB_HDR_SZ);
    db_new->chng_ind = TRUE ;

    return(db_new) ;

 }


 DBHEAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBHEAD.C

 /*dbhead--contains dbase header definitions       */
 /*---------- Macro Function Definitions ----------*/
 #define          db_tell(db_ptr)        db_ptr->curr_rec;
 #define   db_recnum(db_ptr)        db_ptr->rec_num;
 #define   db_reclen(db_ptr)     db_ptr->rec_len;
 #define   db_varnum(db_ptr)     db_ptr->var_num;

 /*-- Definition of the File Description Block -----*/
 typedef   struct    {
                       char    name[11];
                       char    var_type;
                       char    var_len;
                       int     var_loc;
                       char    dec_pts;
                     } DB_DESC;


 /* Definition of the DBASE header record and internal working */
 /*   variables                                                */

 typedef   struct    {
                       char    version;
                         /* Version number.  Must be 02        */
              unsigned int     rec_num;
                         /* number of records                  */
                       char    day, month, year;
                         /* date of last modification dd/mm/yy */
              unsigned int     rec_len;
                         /* record length. sum(fields) + 1     */
                       DB_DESC field_desc[32];
                         /* field descriptors                  */
                       int     *file_ptr;
                         /* pointer to FCB from open command   */
                       char    var_num;
                         /* number of variables in the file    */
                       char    chng_ind;
                         /* boolean if file changed by db_write*/
                       int     curr_rec;
                         /* current record number              */
                     } DBASE_FILE;

 /*end of dbase.h*/


 DBOPEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBOPEN.C

 #include  "libc.h"
 #include  "dbase.h"



 /***************************************************************************
 *  db_open(filename) opens the DBASE .DBF file contained in "filename"     *
 * and returns a pointer to the block containing the DBASE file discription *
 * block.  A value of -1 is returned if the file doesn't exist and execution*
 * is terminated if there is insufficient memory availible to allocate the  *
 * file descriptor block                                                    *
 ***************************************************************************/
 db_open(filename){
    int         i, *inptr, variables ;
    DBASE_FILE  *db_pointer ;

    /*----- allocate the storage area -----*/
    if( (db_pointer = alloc(DB_HDR_SZ+5)) == 0 ){
      puts("Insufficient HEAP space to open DBASE file description block");
      puts("Called from db_open");
      exit();
      }

    if( (inptr=open(filename,O_RDWR)) == ERROR)  /* open the file */
       return(inptr);                            /* return the errror if not f
    read(inptr,db_pointer,DB_HDR_SZ);            /* read in the header informa
                                                 /* reset the number of variab
    variables = 0;
    while(db_pointer->field_desc[variables].var_len != 0 ) variables++;

    /*----- fill in the rest of the file descriptor and return -----*/
    db_pointer->file_ptr = inptr;
    db_pointer->var_num  = variables ;
    db_pointer->chng_ind = FALSE ;
    lseek(inptr,DATA_START,0);                   /* set to the beginning of da
    db_pointer->curr_rec = 0 ;

    return(db_pointer);
    }



 DBREAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBREAD.C

 #include        "libc.h"
 #include        "dbase.h"

 /**************************************************************************
 *  db_read reads the next n records from the database at db_ptr into the  *
 * buffer.  It returns a read error if it is unsucessful.                  *
 **************************************************************************/
 db_read(db_ptr,buffer,n)
   DBASE_FILE   *db_ptr ;
   char         buffer[] ;
   int          n ;
   {    int  char_transfered, length ;
        length = n * db_ptr->rec_len ;
        char_transfered = read(db_ptr->file_ptr,buffer,length) ;  /* read n re
        if( char_transfered == length){                           /* mark the
           buffer[char_transfered] = '\0' ;                       /* if the re
           db_ptr->curr_rec++ ;                                   /* update th
           return( char_transfered );
           }
        else {
           if( char_transfered == EOF) {
              buffer[0] = '\0' ;                           /* clear out the bu
              return(EOF);                                 /* read error numbe
              }
           else {
              buffer[char_transfered] = '\0' ;             /* set the end of t
              return( char_transfered/db_ptr->rec_len);    /* return the numbe
              }
           }
   }


 DBSEEK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBSEEK.C


 #include  "libc.h"
 #include  "dbase.h"


 /*************************************************************************
 * db_seek positions the read/write pointer to the ith record in the data *
 * base.  It also works with an offset so that the pointer can be moved   *
 * back or forward n records from the current position, the beginning  or *
 * end of the file.  If db_seek is sucessful it returns the current posi- *
 * tion in the file; otherwise, it returns a -1.  The offset codes are as *
 * follows:                                                               *
 *                                                                        *
 *          OFFSET                             MEANING                    *
 *          ------                   ------------------------------       *
 *                                                                        *
 *            0                       offset from the beginning of the    *
 *                                    data base. zero or + offset only    *
 *                                                                        *
 *            1                       offset from the current position    *
 *                                    in the database. zero, + or - offst *
 *                                    allowed                             *
 *                                                                        *
 *            2                       offset from the end of the database *
 *                                    zero or - offset only               *
 *                                                                        *
 *************************************************************************/
 db_seek(db_ptr,rcrds,origin)
    DBASE_FILE  *db_ptr ;
    int         rcrds, origin ;
    {long       offset, char_pos, lseek();

       /*----- calculate the character position offset for the "records" posit
       switch ( origin  )
         {
          case 0 :
            if( rcrds < 1 )
               return( ERROR );
            else {
               offset = (long) (DATA_START + (rcrds-1) * db_ptr->rec_len) ;
               break;
            }

          case 1 :
            offset =  (long) ( rcrds * db_ptr->rec_len ) ;
            if( (offset > 0) && (db_ptr->curr_rec + offset/db_ptr->rec_len) >
               return( ERROR );          /* tried to get past end of file
            else if( (offset < 0) && (db_ptr->curr_rec + offset/db_ptr->rec_le
                    return( ERROR );     /* tried to get past beginning of fil
            break;

          case 2 :
            if( rcrds > 0 )
              return( ERROR );               /* attempt to offset past end-of-
            else {
              offset = (long) DATA_START + (db_ptr->rec_num + rcrds ) * db_ptr
              origin = 0 ;                   /* reset origin since offset is f
              break;
              }

          default :
            return ( ERROR );                /* undefined origin value */
         }

       /*----- return the record number -----*/
       if( (char_pos = lseek(db_ptr->file_ptr,offset,origin )) == ERROR ){
          db_seek(db_ptr,db_ptr->curr_rec,0);          /* reset the file point
          return(char_pos);
          }
       else{
          /*----- reset the current record number pointer -----*/
          db_ptr->curr_rec = (char_pos-DATA_START)/(db_ptr->rec_len)  ;
          return( db_ptr->curr_rec );
          }
    }


 DBSTRIP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBSTRIP.C

 /*********************************************************
 * strip(str,len) strips the non-printing ascii characters*
 * from the string "str".  First the 8th bit is stripped  *
 * from  each  character and then the  following  rule is *
 * applied                                                *
 *                                                        *
 * (i)   If the character is <= 32 (space), except for ^Z *
 *       CP/M end of file, it is converted to a space     *
 *                                                        *
 * (ii)  Any character in the first position other than a *
 *       '*' (DBASE deleted record marker), a space or a  *
 *       ^Z is reset to a space (NORMAL status)           *
 *********************************************************/
 strip(buff,len)
      char buff[];
      int  len;
 {
      int      bad_char;
      bad_char = 0;

      /*----- process the last n-1 charaters in the string -----*/
      while ( --len > 0 )
        {
         if( buff[len] & 128 )
           {
            buff[len] = buff[len] & 127;
            bad_char++;
           }
         if( buff[len] < 32 )
           {
            buff[len] = 32;
            bad_char++;
           }
         }

      if( buff[0] != '*' && buff[0] != ' ' && buff[0] != CPM_EOF )
        {
         buff[0] = ' ';
         bad_char++;
        }

      return( bad_char );
 }

 /* end of dbstrip.c */


 DBUTIL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBUTIL.C

 /**********************************************************************
 *             DBASE II UTILITIES FOR AZTEC C                          *
 *_____________________________________________________________________*
 *    These routine are intended to provide the C language programmer  *
 * with a set of I/O utilities to manipulate DBase II DBF files.  This *
 * will eventually include sorting, editting and  the likes.           *
 *                                                                     *
 *    (C) Copyright 1983                 Richard Hoffbeck              *
 **********************************************************************/

 #include  "libc.h"
 #include  "dbase.h"

 main(){
    DBASE_FILE  *db_header, *db_open() ;
    char        infile[14], db_buffer[100], name[10] , var_buf[30] ;
    int         i, record ;

    /*----- get the input file name -----*/
    printf("Enter the input file name: "); scanf("%s",infile);
    if( (db_header=db_open(infile)) == -1 ){
       printf("\nUnable to open the input file\n\n\n\n");
       exit();
       }

    /*----- display the information -----*/
    printf("\n\t\tDBase II file: %s",infile);
    printf("\n\t\tModified on  : %u %u %u",db_header->month,db_header->day,db_
    printf("\n\t\tContains %u records of length %u\n\n",db_header->rec_num,db_
    for( i=0; i<db_header->var_num ; i++)
       printf("\n\t\t\t %10s :  %u",db_header->field_desc[i].name,db_header->f

    /*----- test the lookup function -----*/
    while( 1 ) {
       printf("\nEnter the variable name: ") ;  scanf("%s", name) ;
       printf("\nEnter the record number: ") ;  scanf("%d", &record );
       if( strncmp(name,"quit",4) == 0 )
          exit();
       db_seek(db_header,record,0) ;
       db_read(db_header,db_buffer,1) ;
       if( lookup(name,db_header,db_buffer,var_buf) == ERROR )
          printf("\nVariable not found in the table");
       else {
          printf("\n %s is ",name) ;
          printf("%s",var_buf) ;
       }
    }
  }


 DBVALID.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBVALID.C

 /**********************************************
 * valid_eof(i) determines whether or not the  *
 * CP/M end of file mark encountered in the    *
 * status field of the ith record is valid.  It*
 * uses the following set of rules :           *
 *                                             *
 * (i)   If the record is the maximum record in*
 *       the file, return TRUE.                *
 *                                             *
 * (ii)  If the record is not within a DBASE   *
 *       buffer size of the end of the file, a *
 *       FALSE value is returned               *
 *                                             *
 * (iii) If no other end of file mark is en-   *
 *       countered in the file, return TRUE    *
 *                                             *
 * (iv)  If two potentially valid EOF marks are*
 *       found, the  user is prompted for a    *
 *       decision.                             *
 **********************************************/
 valid_eof(i,buffer)
      int  i;
      char buffer[];

      {int   cur_rec;
       char  db_buffer[1000], c;

      if( i >= maxrec-1 )
         return( TRUE );
      else if( (i*db_ptr->rec_len+DATA_START) < (char_size-DB_SECT_SZ) )
         return( FALSE );
      else if( strip(buffer,db_ptr->rec_len) > 2)
         return( TRUE );
       else {
          printf("\nUnable to determine whether the end of file mark");
          printf("\nat record #%d is reasonable",i);
          printf("\nIs this the end of the file[Y/N]:");
          c = keyin();
          if( (c == 'y') || (c == 'Y') )
             return( TRUE );
          else
            return( FALSE );
       }
 }
 /* end of dbvalid.c */


 DBWRITE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\DBWRITE.C


 #include  "libc.h"
 #include  "dbase.h"


 /*************************************************************************
 * db_write writes out n records from buffer to the DBASE file mapped at  *
 * db_ptr.   It  returns  -1  for an  error and the  number of characters *
 * written if the write is sucessful                                      *
 *************************************************************************/
 db_write(db_ptr,buffer,records)
    DBASE_FILE  *db_ptr;
    int         records;
    char        buffer[];
    {  int      length, char_wrt;
       char     eofileb = 0x1A ;

       length = records * db_ptr->rec_len ;
       if( (char_wrt = write(db_ptr->file_ptr,buffer,length )) == length )   /
          db_ptr->curr_rec++ ;                                   /* update the
       if( db_ptr->curr_rec > db_ptr->rec_num ) {
          write(db_ptr->file_ptr,&eofileb,1);                    /* write a ne
          lseek(db_ptr->file_ptr,-1L,1);                         /* and return
          db_ptr->rec_num = db_ptr->curr_rec ;                   /* update the
          db_ptr->chng_ind = TRUE ;                              /* as necessa
       }
       return(char_wrt);
    }


 DECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CTOOLBX1\DECK.C

 /* Deck the Halls */

 int d[250] =      { 39, 37, 36, 34, 32, 34, 36, 32,
                     34, 36, 37, 34, 36, 34, 32, 31, 32,
                     39, 37, 36, 34, 32, 34, 36, 32,
                     34, 36, 37, 34, 36, 34, 32, 31, 32,
                     34, 36, 37, 34, 36, 37, 39, 34,
                     36, 38, 39, 41, 43, 44, 43, 41, 39,100,
                     39, 37, 36, 34, 32, 34, 36, 32,
                     41,100, 41,100, 41,100, 41, 39, 37, 36, 34, 32,
                            0xff };

 int db[250]   =   {  7,  3,  6,  6,  6,  6,  6,  6,
                      3,  3,  3,  3,  7,  3,  6,  6, 12,
                      7,  3,  6,  6,  6,  6,  6,  6,
                      3,  3,  3,  3,  7,  3,  6,  6, 12,
                      7,  3,  6,  6,  7,  3,  6,  6,
                      3,  3,  6,  3,  3,  6,  6,  6, 12,  1,
                      7,  3,  6,  6,  6,  6,  6,  6,
                      2,  1,  2,  1,  2,  1,  2,  7,  3,  6,  6, 12,
                            1 };

 deck()
 {
    setsound();
 }


 DECL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\DECL.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 TYP             *head = 0;
 TYP             *tail = 0;
 char            *declid = 0;
 TABLE           tagtable = {0,0};
 TYP             stdconst = { bt_long, 1, 4, {0, 0}, 0, "stdconst"};

 int     imax(i,j)
 int     i,j;
 {       return (i > j) ? i : j;
 }

 char    *litlate(s)
 char    *s;
 {       char    *p;
         p = xalloc(strlen(s) + 1);
         strcpy(p,s);
         return p;
 }

 TYP     *maketype(bt,siz)
 int     bt, siz;
 {       TYP     *tp;
         tp = xalloc(sizeof(TYP));
         tp->val_flag = 0;
         tp->size = siz;
         tp->type = bt;
         tp->sname = 0;
         tp->lst.head = 0;
         return tp;
 }

 int     decl(table)
 TABLE   *table;
 {       switch (lastst) {
                 case kw_char:
                         head = tail = maketype(bt_char,1);
                         getsym();
                         break;
                 case kw_short:
                         head = tail = maketype(bt_short,2);
                         getsym();
                         break;
                 case kw_int: case kw_long:
                         head = tail = maketype(bt_long,4);
                         getsym();
                         break;
                 case kw_unsigned:
                         head = tail = maketype(bt_unsigned,4);
                         getsym();
                         if( lastst == kw_int )
                                 getsym();
                         break;
                 case id:                /* no type declarator */
                         head = tail = maketype(bt_long,4);
                         break;
                 case kw_float:
                         head = tail = maketype(bt_float,4);
                         getsym();
                         break;
                 case kw_double:
                         head = tail = maketype(bt_double,8);
                         getsym();
                         break;
                 case kw_enum:
                         getsym();
                         declenum(table);
                         break;
                 case kw_struct:
                         getsym();
                         declstruct(bt_struct);
                         break;
                 case kw_union:
                         getsym();
                         declstruct(bt_union);
                         break;
                 }
 }

 decl1()
 {       TYP     *temp1, *temp2, *temp3, *temp4;
         switch (lastst) {
                 case id:
                         declid = litlate(lastid);
                         getsym();
                         decl2();
                         break;
                 case star:
                         temp1 = maketype(bt_pointer,4);
                         temp1->btp = head;
                         head = temp1;
                         if(tail == NULL)
                                 tail = head;
                         getsym();
                         decl1();
                         break;
                 case openpa:
                         getsym();
                         temp1 = head;
                         temp2 = tail;
                         head = tail = NULL;
                         decl1();
                         needpunc(closepa);
                         temp3 = head;
                         temp4 = tail;
                         head = temp1;
                         tail = temp2;
                         decl2();
                         temp4->btp = head;
                         if(temp4->type == bt_pointer &&
                                 temp4->val_flag != 0 && head != NULL)
                                 temp4->size *= head->size;
                         head = temp3;
                         break;
                 default:
                         decl2();
                         break;
                 }
 }

 decl2()
 {       TYP     *temp1;
         switch (lastst) {
                 case openbr:
                         getsym();
                         temp1 = maketype(bt_pointer,0);
                         temp1->val_flag = 1;
                         temp1->btp = head;
                         if(lastst == closebr) {
                                 temp1->size = 0;
                                 getsym();
                                 }
                         else if(head != NULL) {
                                 temp1->size = intexpr() * head->size;
                                 needpunc(closebr);
                                 }
                         else {
                                 temp1->size = intexpr();
                                 needpunc(closebr);
                                 }
                         head = temp1;
                         if( tail == NULL)
                                 tail = head;
                         decl2();
                         break;
                 case openpa:
                         getsym();
                         temp1 = maketype(bt_func,0);
                         temp1->val_flag = 1;
                         temp1->btp = head;
                         head = temp1;
                         if( lastst == closepa) {
                                 getsym();
                                 if(lastst == begin)
                                         temp1->type = bt_ifunc;
                                 }
                         else
                                 temp1->type = bt_ifunc;
                         break;
                 }
 }

 int     alignment(tp)
 TYP     *tp;
 {       switch(tp->type) {
                 case bt_char:           return AL_CHAR;
                 case bt_short:          return AL_SHORT;
                 case bt_long:           return AL_LONG;
                 case bt_enum:           return AL_SHORT;
                 case bt_pointer:
                         if(tp->val_flag)
                                 return alignment(tp->btp);
                         else
                                 return AL_POINTER;
                 case bt_float:          return AL_FLOAT;
                 case bt_double:         return AL_DOUBLE;
                 case bt_struct:
                 case bt_union:          return AL_STRUCT;
                 default:                return AL_CHAR;
                 }
 }

 int     declare(table,al,ilc,ztype)
 /*
  *      process declarations of the form:
  *
  *              <type>  <decl>, <decl>...;
  *
  *      leaves the declarations in the symbol table pointed to by
  *      table and returns the number of bytes declared. al is the
  *      allocation type to assign, ilc is the initial location
  *      counter. if al is sc_member then no initialization will
  *      be processed. ztype should be bt_struct for normal and in
  *      structure declarations and sc_union for in union declarations.
  */
 TABLE           *table;
 int                       al;
 int             ilc;
 int                       ztype;
 {       SYM     *sp, *sp1;
         TYP     *dhead;
         int     nbytes;
         nbytes = 0;
         decl(table);
         dhead = head;
         for(;;) {
                 declid = 0;
                 decl1();
                 if( declid != 0) {      /* otherwise just struct tag... */
                         sp = xalloc(sizeof(SYM));
                         sp->name = declid;
                         sp->storage_class = al;
                         while( (ilc + nbytes) % alignment(head)) {
                                 if( al != sc_member &&
                                         al != sc_external &&
                                         al != sc_auto) {
                                         dseg();
                                         genbyte(0);
                                         }
                                 ++nbytes;
                                 }
                         if( al == sc_static)
                                 sp->value.i = nextlabel++;
                         else if( ztype == bt_union)
                                 sp->value.i = ilc;
                         else if( al != sc_auto )
                                 sp->value.i = ilc + nbytes;
                         else
                                 sp->value.i = -(ilc + nbytes + head->size);
                         sp->tp = head;
                         if( sp->tp->type == bt_func &&
                                 sp->storage_class == sc_global )
                                 sp->storage_class = sc_external;
                         if(ztype == bt_union)
                                 nbytes = imax(nbytes,sp->tp->size);
                         else if(al != sc_external)
                                 nbytes += sp->tp->size;
                         if( sp->tp->type == bt_ifunc &&
                                 (sp1 = search(sp->name,table->head)) != 0 &&
                                 sp1->tp->type == bt_func )
                                 {
                                 sp1->tp = sp->tp;
                                 sp1->storage_class = sp->storage_class;
                                 sp1->value.i = sp->value.i;
                                 sp = sp1;
                                 }
                         else
                                 insert(sp,table);
                         if( sp->tp->type == bt_ifunc) { /* function body foll
                                 funcbody(sp);
                                 return nbytes;
                                 }
                         if( (al == sc_global || al == sc_static) &&
                                 sp->tp->type != bt_func)
                                 doinit(sp);
                         }
                 if(lastst == semicolon)
                         break;
                 needpunc(comma);
                 if(declbegin(lastst) == 0)
                         break;
                 head = dhead;
                 }
         getsym();
         return nbytes;
 }

 int     declbegin(st)
 int                       st;
 {       return st == star || st == id || st == openpa ||
                 st == openbr;
 }

 declenum(table)
 TABLE   *table;
 {       SYM     *sp;
         TYP     *tp;
         int     evalue;
         if( lastst == id) {
                 if((sp = search(lastid,tagtable.head)) == 0) {
                         sp = xalloc(sizeof(SYM));
                         sp->tp = xalloc(sizeof(TYP));
                         sp->tp->type = bt_enum;
                         sp->tp->size = 2;
                         sp->tp->lst.head = sp->tp->btp = 0;
                         sp->storage_class = sc_type;
                         sp->name = litlate(lastid);
                         sp->tp->sname = sp->name;
                         getsym();
                         if( lastst != begin)
                                 error(ERR_INCOMPLETE);
                         else    {
                                 insert(sp,&tagtable);
                                 getsym();
                                 enumbody(table);
                                 }
                         }
                 else
                         getsym();
                 head = sp->tp;
                 }
         else    {
                 tp = xalloc(sizeof(tp));
                 tp->type = bt_short;
                 if( lastst != begin)
                         error(ERR_INCOMPLETE);
                 else    {
                         getsym();
                         enumbody(table);
                         }
                 head = tp;
                 }
 }

 enumbody(table)
 TABLE   *table;
 {       int     evalue;
         SYM     *sp;
         evalue = 0;
         while(lastst == id) {
                 sp = xalloc(sizeof(SYM));
                 sp->value.i = evalue++;
                 sp->name = litlate(lastid);
                 sp->storage_class = sc_const;
                 sp->tp = &stdconst;
                 insert(sp,table);
                 getsym();
                 if( lastst == comma)
                         getsym();
                 else if(lastst != end)
                         break;
                 }
         needpunc(end);
 }

 declstruct(ztype)
 /*
  *      declare a structure or union type. ztype should be either
  *      bt_struct or bt_union.
  */
 int                       ztype;
 {       SYM     *sp;
         TYP     *tp;
         int     slc;
         if(lastst == id) {
                 if((sp = search(lastid,tagtable.head)) == 0) {
                         sp = xalloc(sizeof(SYM));
                         sp->name = litlate(lastid);
                         sp->tp = xalloc(sizeof(TYP));
                         sp->tp->type = ztype;
                         sp->tp->lst.head = 0;
                         sp->storage_class = sc_type;
                         sp->tp->sname = sp->name;
                         getsym();
                         if(lastst != begin)
                                 error(ERR_INCOMPLETE);
                         else    {
                                 insert(sp,&tagtable);
                                 getsym();
                                 structbody(sp->tp,ztype);
                                 }
                         }
                 else
                         getsym();
                 head = sp->tp;
                 }
         else    {
                 tp = xalloc(sizeof(TYP));
                 tp->type = ztype;
                 tp->sname = 0;
                 tp->lst.head = 0;
                 if( lastst != begin)
                         error(ERR_INCOMPLETE);
                 else    {
                         getsym();
                         structbody(tp,ztype);
                         }
                 head = tp;
                 }
 }

 structbody(tp,ztype)
 TYP             *tp;
 int                       ztype;
 {       int     slc;
         slc = 0;
         tp->val_flag = 1;
         while( lastst != end) {
                 if(ztype == bt_struct)
                         slc += declare(&(tp->lst),sc_member,slc,ztype);
                 else
                         slc = imax(slc,declare(&tp->lst,sc_member,0,ztype));
                 }
         tp->size = slc;
         getsym();
 }

 compile()
 /*
  *      main compiler routine. this routine parses all of the
  *      declarations using declare which will call funcbody as
  *      functions are encountered.
  */
 {       while(lastst != eof) {
                 dodecl(sc_global);
                 if( lastst != eof)
                         getsym();
                 }
         dumplits();
 }

 dodecl(defclass)
 int                       defclass;
 {       int     size;
         for(;;) {
             switch(lastst) {
                 case kw_register:
                         getsym();
                         if( defclass != sc_auto && defclass != sc_member )
                                 error(ERR_ILLCLASS);
                         goto do_decl;
                 case id:
                         if(defclass == sc_auto)
                                 return;
 /*                      else fall through to declare    */
                 case kw_char: case kw_int: case kw_short: case kw_unsigned:
                 case kw_long: case kw_struct: case kw_union:
                 case kw_enum: case kw_void:
                 case kw_float: case kw_double:
 do_decl:            if( defclass == sc_global)
                         lc_static +=
                             declare(&gsyms,sc_global,lc_static,bt_struct);
                     else if( defclass == sc_auto)
                         lc_auto +=
                             declare(&lsyms,sc_auto,lc_auto,bt_struct);
                     else
                         declare(&lsyms,sc_auto,0,bt_struct);
                     break;
                 case kw_static:
                         getsym();
                         if( defclass == sc_member)
                             error(ERR_ILLCLASS);
                                                 if( defclass == sc_auto )
                                                         lc_static +=
                                                                 declare(&lsym
                                                 else
                                                         lc_static +=
                                                                 declare(&gsym
                         break;
                 case kw_extern:
                         getsym();
                         if( defclass == sc_member)
                             error(ERR_ILLCLASS);
                         ++global_flag;
                         declare(&gsyms,sc_external,0,bt_struct);
                         --global_flag;
                         break;
                 default:
                         return;
                 }
             }
 }



 DEFDRV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\DEFDRV.C

 #include <dos.h>
 defdrv()
 {
   int i;
   union REGS reg;
   reg.h.ah = 0x19;
   int86(0x21,&reg,&reg);
   i = reg.h.al;
   return(i);
 }


 DEFINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DEFINE.C

                                         /* Chapter 6 - Program 1 */
 START  0  /* Starting point of loop */
 ENDING 9  /* Ending point of loop */
 MAX(A,B)  ((A)>(B)?(A):(B))  /* Max macro definition */
 MIN(A,B)  ((A)>(B)?(B):(A))  /* Min macro definition */

 main()
 {
 int index,mn,mx;
 int count = 5;

    for (index = START;index <= ENDING;index++) {
       mx = MAX(index,count);
       mn = MIN(index,count);
       printf("Max is %d and min is %d\n",mx,mn);
    }
 }


 DEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CASM\DEMO.C

 extern int cadd(int);
 extern int cons;
 main(argc, argv, envp)
         int argc;
         char **argv;
         char **envp;

         {
         register char **p;
         char ii;
         int ccadd, ccons, ctemp;

         /* print out the argument list for this program */

         for (p = argv; argc > 0; argc--,p++) {
                 printf("%s\n", *p);
                 }

         /* test the cadd.asm linkup */

         ctemp = 100;
         ccadd = cadd(ctemp);
         ccons = cons;
         printf("ccadd =%d\nccons =%d\n", ccadd, ccons);

         /* print out the current environment settings.  Note that
          * the environment table is terminated by a NULL entry
          */

         for (p = envp; *p; p++) {
                 printf("%s\n", *p);
                 }

         exit(0);
         }


 DEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\WINDOW4C\DEMO.C

 #define        foreground(A)        ((color_mon==1)?(A):(7))


         int        u_row[14]={2,2,2,2,2,8,14,20,20,20,20,20,14,8};
         int        u_col[14]={6,21,36,51,66,66,66,66,51,36,21,6,6,6};
         int        l_row[14]={6,6,6,6,6,12,18,24,24,24,24,24,18,12};
         int        l_col[14]={15,30,45,60,75,75,75,75,60,45,30,15,15,15};
         int        wind[14];

         int        color_mon=0;


 main()

 {

         int        temp,key,i,j,k,l;

         color(7,0);

         temp=open_window(9,15,13,61);

         locate(11,20);printf("Do you have a color monitor (Y/N) [ ]");
         locate(11,55);
         putch(key=getch());
         if(key=='Y' || key=='y')color_mon=1;

         close_window(temp);

         color(foreground(1),0);
         temp=open_window(3,5,23,75);
         color_window(temp,foreground(14),0);
         cls_window(temp);
         print_window(temp,"ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ±
         print_window(temp,"º                            °°°°°°              Û
         print_window(temp,"º    ÛÛ   Û   ÛÛ             °____               Û
         print_window(temp,"º     ÛÛ ÛÛÛ ÛÛ                   °              ß
         print_window(temp,"º      ÛÛ   ÛÛ   I N D O W   °°°°°°   O F T
         print_window(temp,"º
         print_window(temp,"ÈÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍ
         print_window(temp,"           ³   Fast - Small - Easy &  ³   ÉÍÍÍÍÍÍÍ
         print_window(temp,"           ³        C H E A P         ³   º  Glen
         print_window(temp,"     ÉÍÍÍÍÍ³                          ³ÍÍÍ¹  21606
         print_window(temp,"     º     ³  W I N D O W S  For  'C' ³   º  Missi
         print_window(temp,"     º     ³                          ³   º
         print_window(temp,"     º     ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¾   ÈÍÍËÍÍÍÍ
         print_window(temp,"     º                                       º\n")
         print_window(temp,"     º If you use these functions and find   º\n")
         print_window(temp,"     º them of value, a contribution of $30  º\n")
         print_window(temp,"     º would be greatly appreciated.         º\n")
         print_window(temp,"     º                                       º\n")
         print_window(temp,"     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¼");

         key=getch();

         close_window(temp);


         for(i=0;i<=13;i++){

                 color(foreground(i+1),0);
                 wind[i]=open_window(u_row[i],u_col[i],l_row[i],l_col[i]);

         }

         for(i=13;i>=0;i--){

                 close_window(wind[i]);

         }

         for(i=13;i>=0;i--){

                 color(foreground(i+1),0);
                 wind[i]=open_window(u_row[i],u_col[i],l_row[i],l_col[i]);

         }

         for(i=0;i<=13;i++){

                 close_window(wind[i]);

         }

         for(i=0;i<14;i++){

                 color(foreground(i+1),0);
                 wind[i]=open_window(u_row[i],u_col[i],l_row[i],l_col[i]);
                 color_window(wind[i],foreground(13),0);
                 print_window(wind[i],"C-WINDOWC-WINDOWC-WINDOW");
                 color_window(wind[i],foreground(i+1),0);

         }




         subject(-1);


 /*  Move box 14 into place */

         for(i=15;i<=35;i++){

                 move_window(wind[13],2);
                 slower();

         }
         close_window(wind[13]);


         subject(13);

 /* Move box 13 into place */

         for(i=14;i>=11;i--){

                 move_window(wind[12],1);
                 slower(13);

         }

         for(i=15;i<=40;i++){

                 move_window(wind[12],2);
                 slower();

         }
         close_window(wind[12]);

         subject(12);


 /* Move box 12 into place */

         for(i=11;i>=7;i--){

                 for(j=u_col[i];j>6;j--){

                         move_window(wind[i],4);
                         slower();
                 }

                 for(j=u_row[i];j>11;j--){

                         move_window(wind[i],1);
                         slower();
                 }

                 l_col[i]=11;

                 for(j=l_col[i];j<=35;j++){

                         move_window(wind[i],2);
                         slower();
                 }

                 close_window(wind[i]);

                 subject(i);

         }

         for(i=6;i>=4;i--){

                 for(j=l_row[i];j<24;j++){
                         move_window(wind[i],3);
                         slower();
                 }
                 l_row[i]=24;


                 for(j=u_col[i];j>6;j--){

                         move_window(wind[i],4);
                         slower();
                 }


                 for(j=l_row[i];j>15;j--){

                         move_window(wind[i],1);
                         slower();
                 }

                 l_col[i]=6;

                 for(j=l_col[i];j<=35;j++){

                         move_window(wind[i],2);
                         slower();
                 }

                 close_window(wind[i]);

                 subject(i);

         }


         for(i=3;i>=0;i--){

                 for(j=l_col[i];j<75;j++){

                         move_window(wind[i],2);
                         slower();
                 }

                 l_col[i]=75;


                 for(j=l_row[i];j<24;j++){
                         move_window(wind[i],3);
                         slower();
                 }
                 l_row[i]=24;


                 for(j=l_col[i];j>15;j--){

                         move_window(wind[i],4);
                         slower();
                 }

                 for(j=l_row[i];j>15;j--){

                         move_window(wind[i],1);
                         slower();
                 }

                 l_col[i]=11;

                 for(j=l_col[i];j<=35;j++){

                         move_window(wind[i],2);
                         slower();
                 }

                 close_window(wind[i]);

                 subject(i);

         }

         subject(-2);

 }

 subject(wind)

 int        wind;

 {

 static        int        temp,
                 temp2;
         int        key,
                 wind1,
                 wind2,
                 wind3,
                 wind4,i,j;

         char        string[100];

         switch(wind){


                 case (-1):

                         color(foreground(14),0);
                         temp2=open_window(8,17,18,64);
                         color_window(temp2,foreground(2),0);
                         print_window(temp2," C-WINDOWS is a comprehensive scr
                         print_window(temp2,"\n window handling package.  C-WI
                         print_window(temp2,"\n the programmer of handling ext
                         print_window(temp2,"\n and window manipulation.  C-WI
                         print_window(temp2,"\n library of pre-written 'C' and
                         print_window(temp2,"\n functions which do printing, c
                         print_window(temp2,"\n cursor positioning, and window
                         locate_window(temp2,9,9);
                         print_window(temp2,"Press any key to continue...");
                         color_window(temp2,foreground(14),0);
                         key=getch();

                         break;

                 case(13):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," C-WINDOWS is supplied in a MS-DOS
                         print_window(temp,"\n the source for C-WINDOWS send a

                         print_window(temp,"\n C-WINDOWS provides you with a e
                         print_window(temp,"\n functions   for   manipulation
                         print_window(temp,"\n provides functions for handling
                         print_window(temp,"\n printing, locating the cursor,
                         print_window(temp,"\n of the screen, printing boxes,
                         print_window(temp,"\n the  screen,  and  printing  ho
                         print_window(temp,"\n characters. \n");

                         print_window(temp,"\n C-WINDOWS also contains a exten
                         print_window(temp,"\n handling  windows.  C-WINDOWS t
                         print_window(temp,"\n a seperate virtual screen.  C-W
                         print_window(temp,"\n locate in,  color, blank, print
                         print_window(temp,"\n activate each window by only sp


                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;
                 case(12):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," this to take place in. \n");

                         print_window(temp,"\n C-WINDOWS  has  a  default maxi
                         print_window(temp,"\n one time.  This can be changed
                         print_window(temp,"\n amount by recompiling the sourc
                         print_window(temp,"\n in  the same manor as the Macin
                         print_window(temp,"\n can open windows in layers on t
                         print_window(temp,"\n re-activate  a  window  which
                         print_window(temp,"\n bottom.  C-WINDOWS will restore
                         print_window(temp,"\n when they are opened, closed or

                         print_window(temp,"\n To  use  the C-WINDOWS function
                         print_window(temp,"\n the code in your program which
                         print_window(temp,"\n and then at link time specify t
                         print_window(temp,"\n is a example of how this progra
                         print_window(temp,"\n linked. \n");



                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;
                 case(11):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp,"            A>lc1 b:demo");
                         print_window(temp,"\n            A>lc2 b:demo");
                         print_window(temp,"\n            A>link a:cs+b:demo,d

                         print_window(temp,"\n C-WINDOWS  was  written  using
                         print_window(temp,"\n and IBM macro assembler ver 1.0
                         print_window(temp,"\n with this compiler you can make
                         print_window(temp,"\n those  who  are  not:  lc1 and
                         print_window(temp,"\n compiler,  and when you link,
                         print_window(temp,"\n which   is   linked   to  your
                         print_window(temp,"\n 'windows.lib'  must  be  specif
                         print_window(temp,"\n LATTICE   library)   because
                         print_window(temp,"\n replacements for the LATTICE li


                          locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;
                 case(10):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," To give the support of color and
                         print_window(temp,"\n standard  'C'  some changes had
                         print_window(temp,"\n is handled.  C-WINDOWS handles
                         print_window(temp,"\n similiar  to  that  of  IBM BAS
                         print_window(temp,"\n cursor location support to the
                         print_window(temp,"\n Printf()  looks  at  the last c
                         print_window(temp,"\n function call and then prints u
                         print_window(temp,"\n has been specified it uses the
                         print_window(temp,"\n black.  Printf()  was rewritten
                         print_window(temp,"\n blazing speed increase and to s
                         print_window(temp,"\n of  printf() is not compatable
                         print_window(temp,"\n I/O supported by DOS,  but most
                         print_window(temp,"\n which are screen intensive,  ne
                         print_window(temp,"\n so there is on real loss. ");


                          locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;
                 case(9):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," The files provided with this pack

                         print_window(temp,"\n             WINDOWS.LIB
                         print_window(temp,"\n             WINDOWS.DOC
                         print_window(temp,"\n
                         print_window(temp,"\n             DEMO.EXE
                         print_window(temp,"\n             DEMO.C
                         print_window(temp,"\n
                         print_window(temp,"\n

                         print_window(temp,"\n As mentioned earlier.  To obtai
                         print_window(temp,"\n please send a contribution of $

                         print_window(temp,"\n                  Glen Boyd");
                         print_window(temp,"\n                  21606 Criptana
                         print_window(temp,"\n                  Mission Veijo,


                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;

                 case(8):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," When  you  send in a contribution
                         print_window(temp,"\n which contains the source and a
                         print_window(temp,"\n WINDOWS  library,  any new func
                         print_window(temp,"\n WINDOWS and documentation for
                         print_window(temp,"\n also  send  you any new program
                         print_window(temp,"\n name will go on a mailing list
                         print_window(temp,"\n about a new version or new prog
                         print_window(temp,"\n You  will also receive a teleph
                         print_window(temp,"\n or questions about C-WINDOWS or
                         print_window(temp,"\n you might have. \n");

                         print_window(temp,"\n This  demo  you  are watching i
                         print_window(temp,"\n uses the C-WINDOWS functions to
                         print_window(temp,"\n manipulation.  I  will take you
                         print_window(temp,"\n functions are and how they can
                         print_window(temp,"\n applications. ");

                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;
                 case(7):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," color()                   /* Allo
                         print_window(temp,"\n                              th
                         print_window(temp,"\n locate()                  /* Po
                         print_window(temp,"\n                              th
                         print_window(temp,"\n place()                   /* Pr
                         print_window(temp,"\n cls()                     /* Cl
                         print_window(temp,"\n v_bar()                   /* Pr
                         print_window(temp,"\n                              a
                         print_window(temp,"\n h_bar()                   /* Pr
                         print_window(temp,"\n                              of
                         print_window(temp,"\n scroll()                  /* Sc
                         print_window(temp,"\n                              sc
                         print_window(temp,"\n printf()                  /* ju
                         print_window(temp,"\n                              ex
                         print_window(temp,"\n                              fo


                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;
                 case(6):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);
                         print_window(temp," box()                     /* Draw
                         print_window(temp,"\n                              li
                         print_window(temp,"\n minor_box( )              /* Dr
                         print_window(temp,"\n                              li
                         print_window(temp,"\n window()                  /* Ma
                         print_window(temp,"\n save_restore()            /* Sa
                         print_window(temp,"\n                              of

                         print_window(temp,"\n Are  functions  which operate w
                         print_window(temp,"\n is on it.  These function can b
                         print_window(temp,"\n your  own  window  or  screen
                         print_window(temp,"\n functions  are  the  primitives
                         print_window(temp,"\n below to  handle  the  windows.
                         print_window(temp,"\n individual screens, for example
                         print_window(temp,"\n is  ten  rows  by  thirty colum
                         print_window(temp,"\n like a  seperate  screen.  You



                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);
                         key=getch();
                         close_window(temp);

                         break;

                 case(5):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);


                         print_window(temp," locate the cursor, and do a host
                         print_window(temp,"\n to this virtual screen by just
                         print_window(temp,"\n have  up to 255 virtual screens
                         print_window(temp,"\n is if I have that much memory.

                         print_window(temp,"\n activate()              /* Make
                         print_window(temp,"\n                            the
                         print_window(temp,"\n open_window()           /* Open
                         print_window(temp,"\n close_window()          /* Clos
                         print_window(temp,"\n                            wind
                         print_window(temp,"\n scroll_window()         /* Scro
                         print_window(temp,"\n                            a wi
                         print_window(temp,"\n locate_window()         /* Loca
                         print_window(temp,"\n                            of a
                         print_window(temp,"\n print_window()          /* Allo
                         print_window(temp,"\n                            spec


                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);

                         key=getch();
                         close_window(temp);
                         break;
                 case(4):

                         color_window(temp,foreground(2),0);

                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," cls_window()            /* Clears
                         print_window(temp,"\n                            wind
                         print_window(temp,"\n move_window()           /* Move
                         print_window(temp,"\n color_window()          /* Set
                         print_window(temp,"\n                            on t

                         print_window(temp,"\n When a window is opened all tex
                         print_window(temp,"\n saved,  then the window will op
                         print_window(temp,"\n specified with the last  color(
                         print_window(temp,"\n virtual  screen  (the  inside o
                         print_window(temp,"\n and the cursor will locate in t
                         print_window(temp,"\n 1).  Any printing,  locating,
                         print_window(temp,"\n inside  this  window  will  be
                         print_window(temp,"\n C-WINDOWS allows overlapping wi
                         print_window(temp,"\n top of each other.  When a  win



                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);

                         key=getch();
                         close_window(temp);

                         break;

                 case(3):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);


                         print_window(temp," current (active) window,  that is
                         print_window(temp,"\n on top.  When another window is
                         print_window(temp,"\n window  and  the  previous  win
                         print_window(temp,"\n mechanism  allows  for  windows
                         print_window(temp,"\n another.  You can do anything t
                         print_window(temp,"\n just  specifying  the window #,
                         print_window(temp,"\n what is to be done to  whom.  F
                         print_window(temp,"\n windows  opened up and I want t
                         print_window(temp,"\n I  would  call  the  print_wind
                         print_window(temp,"\n appropriate  window  #  and  da
                         print_window(temp,"\n WINDOWS will make it the activa
                         print_window(temp,"\n the top and then printing in it

                         print_window(temp,"\n I  am  going  to  take  you thr
                         print_window(temp,"\n opening windows and printing to
                         print_window(temp,"\n four windows which are opened,

                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);

                         key=getch();
                         close_window(temp);

                         break;
                 case(2):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," in,  move around,  cleared,  and
                         print_window(temp,"\n will  start  off  by  opening
                         print_window(temp,"\n thirty five columns wide.  We w
                         print_window(temp,"\n our  upper left corner of this
                         print_window(temp,"\n do this looks like this. \n");

                         print_window(temp,"\n            wind1=open_window(7,

                         print_window(temp,"\n Ok,  lets examine this statemen
                         print_window(temp,"\n First  of  all  the  function
                         print_window(temp,"\n integer which is a window ID #,
                         print_window(temp,"\n assigned  when  the  window  is
                         print_window(temp,"\n represent the coresponding plac
                         print_window(temp,"\n represents  a  ID  given  to  t
                         print_window(temp,"\n assigned an unique ID number wh


                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);

                         key=getch();
                         close_window(temp);

                         break;
                 case(1):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);
                         print_window(temp," with the rest of the windows.  Ok
                         print_window(temp,"\n function call is the row which
                         print_window(temp,"\n the window will be placed in,
                         print_window(temp,"\n upper left hand corner, the nex
                         print_window(temp,"\n left  hand  corners  row  and
                         print_window(temp,"\n understand that lets do the cal

                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);

                         key=getch();

                         color(foreground(1),0);

                 wind1=open_window(7,14,18,50);


 /*  do the open  */

                         print_window(wind1," Now you can see  we  are  inside
                         print_window(wind1,"\n this   window   and  it  is  t
                         print_window(wind1,"\n current active window.  Now le
                         print_window(wind1,"\n open up some more windows so
                         print_window(wind1,"\n can see some more. ");
                         print_window(wind1,"\n Press any key when ready..");
                         key=getch();

                         color(foreground(4),0);


                 wind2=open_window(1,23,12,60);

 /* open up another window */

                           print_window(wind2," This is our second window");
                         print_window(wind2,"\n\n Press any key when ready..")
                         key=getch();

                         color(foreground(15),0);


                 wind3=open_window(9,43,20,80);


                         print_window(wind3," This is our third window");
                         print_window(wind3,"\n\n Press any key when ready..")
                         key=getch();


                         color(foreground(10),0);

                 wind4=open_window(14,1,25,37);

 /* open up another window */

                         print_window(wind4," This  is  our   fourth   window.
                         print_window(wind4,"\n Notice   that  I  specified  t
                         print_window(wind4,"\n window    locations     in
                         print_window(wind4,"\n overlapping    fashion.     Ea
                         print_window(wind4,"\n window  is  placed  some   whe
                         print_window(wind4,"\n overlapping   the   one   unde
                         print_window(wind4,"\n neath.  Now that we  have  the
                         print_window(wind4,"\n windows  open we can call up a
                         print_window(wind4,"\n window at any  time.  Lets  ca
                         print_window(wind4,"\n window two. Press any key... "

                         key=getch();


 /* Now activate window two */

                         cls_window(wind2);
                         print_window(wind2," Notice how this  window  becomes
                         print_window(wind2,"\n active   restoring   all   stu
                         print_window(wind2,"\n underneath  it  and     anythi
                         print_window(wind2,"\n inside    the    window.    Le
                         print_window(wind2,"\n demonstrate  some  other  thin
                         print_window(wind2,"\n C-WINDOWS  can  do.   Lets  mo
                         print_window(wind2,"\n this window  to  the  right  t
                         print_window(wind2,"\n spaces.  Press any key ten tim


                         for(i=0;i<10;i++){

                                 key=getch();
                                 move_window(wind2,2);
                         }

                         key=getch();


 /* do the move */

                         cls_window(wind2);

                         print_window(wind2," I am going  to  demonstrate  the
                         print_window(wind2,"\n scrolling capabilities  of  ea
                         print_window(wind2,"\n window.\n\n   Press any key wh
                         print_window(wind2,"ready... ");

                         key=getch();


 /* Do scrolling on each window */

                         cls_window(wind1);

                         for(j=1;j<=25;j++){

                                 sprintf(string," This is scrolling up %d\n",j
                                 print_window(wind1,string);

                         }

                         cls_window(wind4);

                         for(j=1;j<=25;j++){

                                 sprintf(string," This is scrolling up %d\n",j
                                 print_window(wind4,string);

                         }
                         for(j=25;j>=10;j--){

                                 scroll_window(wind4,1,1);
                                 locate_window(wind4,1,1);
                                 sprintf(string,"  This is a scrolling down %d
                                 print_window(wind4,string);

                         }

                         locate_window(wind4,10,1);
                         print_window(wind4,"\n Press any key to continue...")
                         key=getch();


 /* open window 1 and */

 /* clear window one */
                         cls_window(wind1);

                         print_window(wind1," Now we are back  to  window  one
                         print_window(wind1,"\n and you can start to see some
                         print_window(wind1,"\n the power we have by just havi
                         print_window(wind1,"\n four windows, and you have up
                         print_window(wind1,"\n 255! \n");

                         print_window(wind1,"\n Press any key when ready...");
                         key=getch();
                         close_window(wind1);
 /* close window one */

                         cls_window(wind3);

 /* clear window 3 */
                         print_window(wind3,"\n Now lets close them all\n");

                         print_window(wind3,"\n Press any key when ready...");
                         key=getch();

                         close_window(wind3);
 /* close window 3 */
                         cls_window(wind4);

 /* clear window 4 */
                         print_window(wind4," Now lets close window 4");

                         print_window(wind4,"\n Press any key when ready...");
                         key=getch();

                         close_window(wind4);
 /* close window 4 */
                         cls_window(wind2);
 /* clear window 2 */

                         print_window(wind2," This  is  the  last  one so here
                         print_window(wind2,"\n goes.  Watch  how  the  previo
                         print_window(wind2,"\n window,  which  is the one bel
                         print_window(wind2,"\n becomes active as we  close  a
                         print_window(wind2,"\n the windows on top of it. ");

                         print_window(wind2,"\n Press any key when ready...");

                         key=getch();

                         close_window(wind2);

 /* close window 2 */

                         cls_window(temp);

                         color_window(temp,foreground(2),0);
                         print_window(temp,"\n We made it back here and thats
                         print_window(temp,"\n Thank you and have fun, writtin

                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");

                         key=getch();
                         close_window(temp);

                         break;
                 case(0):

                         color(foreground(14),0);
                         temp=open_window(4,9,23,73);
                         color_window(temp,foreground(2),0);

                         print_window(temp," To get the latest copy of this pr
                         print_window(temp,"\n message for me, you can call");
                         print_window(temp,"\n\n                   The Consult
                         print_window(temp,"\n                   714-842-6348"
                         print_window(temp,"\n                   Huntington Be
                         print_window(temp,"\n\n And leave a message on it for
                         print_window(temp,"\n This is a Electronic BBS.  You
                         print_window(temp,"\n modem to call this number.");

                         locate_window(temp,18,15);
                         print_window(temp,"Press any key to continue...");
                         color_window(temp,foreground(14),0);

                         key=getch();
                         close_window(temp);

                         break;

                 case(-2):

                         close_window(temp2);

                         break;

         }

 }

 slow()
 {

         int        i;
         for(i=0;i<=5000;i++);

 }

 slower()

 {

         int        i;

         for(i=0;i<=350;i++);

 }



 DEMO1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\SIMGRAFC\DEMO1.C

 #include        <stdio.h>

 main()
 {
 int i,j,k,x1,x2,y1,y2;

    g_init();
    g_pal(1);
    g_bakgnd(1);
 for (j=0; j<=3; ++j)
    {
    pause();
    for (i=0; i<= 15; ++i)
        {
        x1 = i*6 + 2*j;
        y1 = i*6 + 2*j;
        x2 = 319-x1;
        y2 = 199-y1;
        box(x1,y1,x2,y2,j);
        }
     }
 for (k=0; k<=15; ++k)
    {
    pause();
    g_bakgnd(k);
    }

    getch();
    g_clear();
    g_text();
 }
 box(x1,y1,x2,y2,clr)
 int x1,y1,x2,y2,clr;
 {
     g_line(x1,y1,x2,y1,clr);
     g_line(x2,y1,x2,y2,clr);
     g_line(x2,y2,x1,y2,clr);
     g_line(x1,y2,x1,y1,clr);
 }
 pause()
 {
     int l;
     for (l=0; l<=20000; ++l) {}
 }


 DEMO2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\SIMGRAFC\DEMO2.C

 #include        <stdio.h>

 #define XMAX      319
 #define YMAX      199
 #define COLORMAX    3
 #define WXMAX     220
 #define WXMIN     100
 #define WYMAX     150
 #define WYMIN      50

 main()
 {
 int i,x,y,clr;

    g_init();
    g_pal(0);
    g_bakgnd(0);
    g_window(WXMIN,WYMIN,WXMAX,WYMAX);


    randseed(1,1);

    for (i=0; i<=10000; ++i)
        {
        x = rand(XMAX);
        y = rand(YMAX);
        clr = 1 + rand(COLORMAX);
        g_dot(x,y,clr);
        }
    getch();
    g_text(80);
 }



 DEMO3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\SIMGRAFC\DEMO3.C

 #include <stdio.h>
 #include <math.h>
 #include <limits.h>

 int clr1, clr2, clr3;
 int xp[9], yp[9], zp[9];
 float x0, y0, z0, xa, ya, za;
 int xc[9], yc[9], zc[9];
 double the, phi, rho;
 float cc[4][4];
 float x,y;

 main()
 {

    float dtor;
    int i;
    int ret;

    x0 = 160;
    y0 = 100;
    z0 = 100;
    the = 0;
    phi = 0;
    rho = 0;
    dtor = 3.14159/180;

 g_init();
 g_pal(0);
 gbox(40,20,280,180,1);
 locate(1,24);
 printf("Hit <ENTER> to rotate cube");
 locate(1,1);
    for (i=0;i<=18;++i){
            getcoord();
            xmat();
            rotate();
            ymat();
             rotate();
            the += 10*dtor;
            phi += 10*dtor;
            clr1 = 1, clr2 = 2, clr3 = 3;
            draw_box();
            scanf("%c",&ret);
            clr1 = 0, clr2 = 0, clr3 = 0;
            draw_box();
          }

 scanf("%c",&ret);
 g_text(80);
 }
 getcoord()
 {
 float da,db,dc;

    da = 100;
    db =  80;
    dc =  80;
    xp[1] = xp[2] = xp[5] = xp[6] = x0 - da/2;
    xp[3] = xp[4] = xp[7] = xp[8] = x0 + da/2;
    yp[1] = yp[4] = yp[5] = yp[8] = y0 + db/2;
    yp[2] = yp[3] = yp[6] = yp[7] = y0 - db/2;
    zp[1] = zp[2] = zp[3] = zp[4] = z0 - dc/2;
    zp[5] = zp[6] = zp[7] = zp[8] = z0 + dc/2;

    /* coordinates for the number on the face */

    xc[1] = xp[1] + 20;
    yc[1] = yp[1] - 15;
    xc[2] = xc[1] + 40;
    yc[2] = yc[1];
    xc[3] = xc[2] + 20;
    yc[3] = yc[2] - 10;
    xc[4] = xc[3];
    yc[4] = yc[3] - 10;
    xc[5] = xc[2];
    yc[5] = yc[4] - 10;
    xc[6] = xc[1];
    yc[6] = yc[5];
    xc[7] = xc[1];
    yc[7] = yc[6] - 20;
    xc[8] = xc[1] + 60;
    yc[8] = yc[7];
    zc[1]=zc[2]=zc[3]=zc[4]=zc[5]=zc[6]=zc[7]=zc[8]=zp[1];
 }
 xmat()
 {
 float sinthe = sin(the);
 float costhe = cos(the);

    cc[1][1] = 1;
    cc[1][2] = cc[1][3] = cc[2][1] = cc[3][1] = 0;
    cc[2][2] = cc[3][3] = costhe;
    cc[2][3] = sinthe;
    cc[3][2] = -sinthe;
 }
 ymat()
 {
 float sinphi = sin(phi);
 float cosphi = cos(phi);

    cc[1][1] = cc[3][3] = cosphi;
    cc[1][2] = cc[2][1] = cc[2][3] = cc[3][2] = 0;
    cc[1][3] = -sinphi;
    cc[2][2] = 1;
    cc[3][1] = sinphi;
 }
 zmat()
 {
 float sinrho = sin(rho);
 float cosrho = cos(rho);

    cc[1][1] = cc[2][2] = cosrho;
    cc[1][2] = sinrho;
    cc[2][1] = -cc[1][2];
    cc[1][3] = cc[2][3] = cc[3][1] = cc[3][2] = 0;
    cc[3][3] = 1;
 }
 draw_box()
 {
 int i;

    /* individual lines*/

    for (i=1; i<=4; ++i){
        g_line(xp[i],yp[i],xp[i+4],yp[i+4],clr3);
        }

    /* back rectangle  */

    g_line(xp[5],yp[5],xp[6],yp[6],clr2);
    g_line(xp[6],yp[6],xp[7],yp[7],clr2);
    g_line(xp[7],yp[7],xp[8],yp[8],clr2);
    g_line(xp[8],yp[8],xp[5],yp[5],clr2);

    /* front rectangle */

    g_line(xp[1],yp[1],xp[2],yp[2],clr1);
    g_line(xp[2],yp[2],xp[3],yp[3],clr1);
    g_line(xp[3],yp[3],xp[4],yp[4],clr1);
    g_line(xp[4],yp[4],xp[1],yp[1],clr1);

    /* number */
    for (i=2; i<=8; ++i)
        {
        g_line(xc[i-1],yc[i-1],xc[i],yc[i],clr3);
        }


 }
 rotate()
 {
    int i;
         for (i=1;i<9;++i){
                 xa = xp[i] - x0;
                 ya = yp[i] - y0;
                 za = zp[i] - z0;
                 xp[i] = x0 + xa*cc[1][1] + ya*cc[2][1] + za*cc[3][1];
                 yp[i] = y0 + xa*cc[1][2] + ya*cc[2][2] + za*cc[3][2];
                 zp[i] = z0 + xa*cc[1][3] + ya*cc[2][3] + za*cc[3][3];
         }

         for (i=1;i<=8;++i){
                 xa = xc[i] - x0;
                 ya = yc[i] - y0;
                 za = zc[i] - z0;
                 xc[i] = x0 + xa*cc[1][1] + ya*cc[2][1] + za*cc[3][1];
                 yc[i] = y0 + xa*cc[1][2] + ya*cc[2][2] + za*cc[3][2];
                 zc[i] = z0 + xa*cc[1][3] + ya*cc[2][3] + za*cc[3][3];
         }
 }
 write_coords()
 {
    int i;
    int row = 1;
    int col = 1;

         locate(row,col);
         for (i=1;i<9;++i){
                 printf("%4d  %4d  %4d\n",xp[i],yp[i],zp[i]);
         }
 }
 gbox(x1,y1,x2,y2,clr)
 int x1,y1,x2,y2,clr;
 {
     g_line(x1,y1,x2,y1,clr);
     g_line(x2,y1,x2,y2,clr);
     g_line(x2,y2,x1,y2,clr);
     g_line(x1,y2,x1,y1,clr);
 }
 pause()
 {
     int l;
     for (l=0; l<=20000; ++l) {}
 }


 DEMO4.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\SIMGRAFC\DEMO4.C

 #include        <stdio.h>

 #define        CHAINS        4
 #define        LINES        12
 #define        XMIN        0
 #define        XMAX        319
 #define        YMIN        0
 #define        YMAX        199
 #define        DXMAX        10
 #define        DYMAX        6
 #define        HICOLOR        3

 int        ax[CHAINS*LINES],ay[CHAINS*LINES],adx[CHAINS],ady[CHAINS];
 int        bx[CHAINS*LINES],by[CHAINS*LINES],bdx[CHAINS],bdy[CHAINS];
 int        lax[CHAINS],lay[CHAINS],lbx[CHAINS],lby[CHAINS];
 int        color[CHAINS];
 int        chain,line,lptr,i;

 _main()
 {
    g_init();                /*        Put screen in Medium Res Graphics Mode
    g_pal(1);
    g_bakgnd(0);
    randseed(0,0);

                                  /****  INITIALIZE EACH LINE CHAIN  ****/
       for (chain=0; chain<CHAINS; ++chain)
    {
       lax[chain] = lbx[chain] = (XMIN+XMAX)/2;
       lay[chain] = (YMIN+YMAX)/2 - 20;
       lby[chain] = (YMIN+YMAX)/2 + 20;
       color[chain] = rand(HICOLOR)+1;
       adx[chain] = (rand(1)?1:-1) * (rand(DXMAX)+1);
       ady[chain] = (rand(1)?1:-1) * (rand(DYMAX)+1);
       bdx[chain] = (rand(1)?1:-1) * (rand(DXMAX)+1);
       bdy[chain] = (rand(1)?1:-1) * (rand(DYMAX)+1);
    }

    line = 0;
    while (!keyboard(1))  /** WHILE (no key) **/
       for (line=0; line<LINES; ++line)
          for (chain=0; chain<CHAINS; ++chain)
          {
             lptr = chain*LINES+line;
             g_line(ax[lptr],ay[lptr],bx[lptr],by[lptr],0);    /* ERASE LINE *
             newline();
             g_line(ax[lptr],ay[lptr],bx[lptr],by[lptr],color[chain]); /*DRAW*
          }
    g_text(80);
    _exit();
 }


 newline()
 {
    int change=0;

                                 /** CALC NEW AX **/
    i = lax[chain]+adx[chain];
    if (i>=XMIN && i<=XMAX)
       lax[chain]=ax[lptr]=i;
    else
    {
       lax[chain]+= (adx[chain]= (adx[chain]<0 ?1:-1)*(rand(DXMAX)+1));
       ax[lptr]=lax[chain];
       change=1;
    }

                                 /** CALC NEW AY **/
    i = lay[chain]+ady[chain];
    if (i>=YMIN && i<=YMAX)
       lay[chain]=ay[lptr]=i;
    else
    {
       lay[chain]+= (ady[chain]= (ady[chain]<0 ?1:-1)*(rand(DYMAX)+1));
       ay[lptr]=lay[chain];
       change=1;
    }

                                 /** CALC NEW BX **/
    i = lbx[chain]+bdx[chain];
    if (i>=XMIN && i<=XMAX)
       lbx[chain]=bx[lptr]=i;
    else
    {
       lbx[chain]+= (bdx[chain]= (bdx[chain]<0 ?1:-1)*(rand(DXMAX)+1));
       bx[lptr]=lbx[chain];
       change=1;
    }

                                 /** CALC NEW BY **/
    i = lby[chain]+bdy[chain];
    if (i>=YMIN && i<=YMAX)
       lby[chain]=by[lptr]=i;
    else
    {
       lby[chain]+= (bdy[chain]= (bdy[chain]<0 ?1:-1)*(rand(DYMAX)+1));
       by[lptr]=lby[chain];
       change=1;
    }

                 /** CHANGE COLOR IF DIRECTION CHANGE **/
    if (change)
       color[chain] = rand(HICOLOR)+1;

 }


 DEMO5.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\SIMGRAFC\DEMO5.C

 #include        <stdio.h>

 #define        CHAINS        4
 #define        LINES        12
 #define        XMIN        0
 #define        XMAX        319
 #define        YMIN        0
 #define        YMAX        199
 #define        DXMAX        8
 #define        DYMAX        4
 #define        HICOLOR        3
 #define COLORMAX    3
 #define W1XMIN      1
 #define W1YMIN      1
 #define W1XMAX     79
 #define W1YMAX     59
 #define W2XMIN    161
 #define W2YMIN      1
 #define W2XMAX    318
 #define W2YMAX    198
 #define W3XMIN     40
 #define W3YMIN    100
 #define W3XMAX    120
 #define W3YMAX    179

 int        ax[CHAINS*LINES],ay[CHAINS*LINES],adx[CHAINS],ady[CHAINS];
 int        bx[CHAINS*LINES],by[CHAINS*LINES],bdx[CHAINS],bdy[CHAINS];
 int        lax[CHAINS],lay[CHAINS],lbx[CHAINS],lby[CHAINS];
 int        color[CHAINS];
 int        chain,line,lptr,i;
 int     x3,y3,x4,y4,clrb;
 main()
 {
 int i,j,x,y,clr;

    g_init();
    g_pal(0);
    g_bakgnd(1);
    clrb = 1;
    resetbox();

    randseed(0,0);

    initlines();

    g_window(W1XMIN,W1YMIN,W1XMAX,W1YMAX);
    box(W1XMIN-1,W1YMIN-1,W1XMAX+1,W1YMAX+1,1);
    box(W2XMIN-1,W2YMIN-1,W2XMAX+1,W2YMAX+1,1);

 while (!keyboard(1))
    {
        display();
    }
    getch();
    g_text(80);
 }

 plotpoint()
 {
 int x,y,clr;
        x = rand(XMAX);
        y = rand(YMAX);
        clr = 1 + rand(COLORMAX);
        g_dot(x,y,clr);
 }

 initlines()
 {                         /****  INITIALIZE EACH LINE CHAIN  ****/
       for (chain=0; chain<CHAINS; ++chain)
    {
       lax[chain] = lbx[chain] = (W2XMIN+W2XMAX)/2;
       lay[chain] = (W2YMIN+W2YMAX)/2 - 20;
       lby[chain] = (W2YMIN+W2YMAX)/2 + 20;
       color[chain] = rand(HICOLOR)+1;
       adx[chain] = (rand(1)?1:-1) * (rand(DXMAX)+1);
       ady[chain] = (rand(1)?1:-1) * (rand(DYMAX)+1);
       bdx[chain] = (rand(1)?1:-1) * (rand(DXMAX)+1);
       bdy[chain] = (rand(1)?1:-1) * (rand(DYMAX)+1);
    }
 }

 display()
 {
 int k;
       for (line=0; line<LINES; ++line)
          for (chain=0; chain<CHAINS; ++chain)
          {
             lptr = chain*LINES+line;
             g_line(ax[lptr],ay[lptr],bx[lptr],by[lptr],0);    /* ERASE LINE *
             newline();
             g_line(ax[lptr],ay[lptr],bx[lptr],by[lptr],color[chain]); /*DRAW*
             for (k=0; k<=6; ++k)
                 {
                 plotpoint();
                 }
             if (x4>130)
                resetbox();
             else
                growbox();
          }
 }

 newline()
 {
    int change=0;

                                 /** CALC NEW AX **/
    i = lax[chain]+adx[chain];
    if (i>=W2XMIN && i<=W2XMAX)
       lax[chain]=ax[lptr]=i;
    else
    {
       lax[chain]+= (adx[chain]= (adx[chain]<0 ?1:-1)*(rand(DXMAX)+1));
       ax[lptr]=lax[chain];
       change=1;
    }

                                 /** CALC NEW AY **/
    i = lay[chain]+ady[chain];
    if (i>=W2YMIN && i<=W2YMAX)
       lay[chain]=ay[lptr]=i;
    else
    {
       lay[chain]+= (ady[chain]= (ady[chain]<0 ?1:-1)*(rand(DYMAX)+1));
       ay[lptr]=lay[chain];
       change=1;
    }

                                 /** CALC NEW BX **/
    i = lbx[chain]+bdx[chain];
    if (i>=W2XMIN && i<=W2XMAX)
       lbx[chain]=bx[lptr]=i;
    else
    {
       lbx[chain]+= (bdx[chain]= (bdx[chain]<0 ?1:-1)*(rand(DXMAX)+1));
       bx[lptr]=lbx[chain];
       change=1;
    }

                                 /** CALC NEW BY **/
    i = lby[chain]+bdy[chain];
    if (i>=W2YMIN && i<=W2YMAX)
       lby[chain]=by[lptr]=i;
    else
    {
       lby[chain]+= (bdy[chain]= (bdy[chain]<0 ?1:-1)*(rand(DYMAX)+1));
       by[lptr]=lby[chain];
       change=1;
    }

                 /** CHANGE COLOR IF DIRECTION CHANGE **/
    if (change)
       color[chain] = rand(HICOLOR)+1;

 }
 box(x1,y1,x2,y2,clr)
 int x1,y1,x2,y2,clr;
 {
     g_line(x1,y1,x2,y1,clr);
     g_line(x2,y1,x2,y2,clr);
     g_line(x2,y2,x1,y2,clr);
     g_line(x1,y2,x1,y1,clr);
 }
 pause()
 {
     int l;
     for (l=0; l<=20000; ++l) {}
 }
 growbox()
 {
    box(x3,y3,x4,y4,clrb);
    x3 -= 1;
    y3 -= 1;
    x4 += 1;
    y4 += 1;
 }
 resetbox()
 {
    x3 = x4 =  80;
    y3 = y4 = 130;
    clrb = 1 + (clrb+1)%3;
 }


 DEMOIBM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\DEMOIBM.C

 /*                      Demo4.c
 *
 *    This program is designed to illustate some of the features contained
 *  in the UC4 library.  It uses the 4 color medium resolution mode of the
 *  IBM PC and compatibles.  A second version of the library is available
 *  to be used with the 16 color medium resolution mode (mode 9) on the
 *  Tandy 1000 computer.
 */

 #include <uc.h>

 int i;

 main()
 {

    int start = 9;

    sm(4);
    backclr(1);

    gothic('U',10,start+0,3);
    gothic('n',10,start+25,3);
    gothic('i',10,start+45,3);
    gothic('c',10,start+60,3);
    gothic('o',10,start+80,3);
    gothic('r',10,start+100,3);
    gothic('n',10,start+120,3);

    gothic('S',10,start+150,3);
    gothic('o',10,start+170,3);
    gothic('f',10,start+190,3);
    gothic('t',10,start+205,3);
    gothic('w',10,start+220,3);
    gothic('a',10,start+240,3);
    gothic('r',10,start+260,3);
    gothic('e',10,start+280,3);

    raschar('P', 50, start + 70, 2, 2, 3);
    raschar('r', 50, start + 90, 2, 2, 3);
    raschar('e', 50, start + 110, 2, 2, 3);
    raschar('s', 50, start + 130, 2, 2, 3);
    raschar('e', 50, start + 150, 2, 2, 3);
    raschar('n', 50, start + 170, 2, 2, 3);
    raschar('t', 50, start + 190, 2, 2, 3);
    raschar('s', 50, start + 210, 2, 2, 3);
    victory();
    unicorn();
    greenslv();
    atsay(24, 3, 2, 0,"Copyright (c) 1986 David A. Miller");
    cntue();
    waitkey();
    sm(4);       /* this resets the mode which in effect is a
                    clear screen command.                      */
    backclr(9);

    printf("\n\n\n  A demonstration of IBM PC graphics\n");
    printf(" using the 4 color med. resolution mode\n");
    printf(" and the unicorn library of functions.\n");
    printf(" This library is designed to work with \n");
    printf(" the Microsoft C small model. It has\n");
    printf(" been written using Microsoft C 4.0 \n");
    printf(" and the Microsoft Assembler 4.0.\n");
    printf("    Not all library functions are\n");
    printf(" illustrated in this demo.  The\n");
    printf(" library is capable of many graphics\n");
    printf(" concepts including points, lines,\n");
    printf(" circles, ellipses (these may be \n");
    printf(" rotated from the vertical or\n");
    printf(" horizontal and colorful print\n");
    printf(" including different fonts.  We\n");
    printf(" hope you enjoy the Unicorn library!\n\n");
    printf(" Version 4.0 pre-release for Microsoft\n");
    printf(" C small model.\n");
    printf("  Copyright (C) 1986 David A. Miller\n");
    atsay(23,8,2,0,"Press any key to continue");
    waitkey();
    sm(4);       /* this resets the mode which in effect is a
                    clear screen command.                      */
    backclr(14);



    pg1();
    waitkey();
    sm(4);
    backclr(1);



    pg2();
    cntue();
    waitkey();
    sm(4);
    backclr(1);

    pg3();
    cntue();
    waitkey();
    sm(4);
    backclr(9);

    atom();
    cntue();
    waitkey();
    sm(4);
    backclr(1);

    printf("   The next screen will demonstrate\n\n");
    printf("    T U R T L E  F U N C T I O N S");

    burble(200, 300);

    printf("\n\n\n\n\n   The delay function is used to");
    printf("\n   slow down the display of lines\n");
    cntue();
    waitkey();
    palette(0,5,8);

    pg5();
    cntue();
    waitkey();
    sm(4);
    backclr(1);

    script('P', 5, 100, 3);
    script('a', 5, 116, 3);
    script('l', 5, 132, 3);
    script('e', 5, 148, 3);
    script('t', 5, 164, 3);
    script('t', 5, 180, 3);
    script('e', 5, 196, 3);

    redalert();

    printf("\n\n\n\nThe following page illustrates\n");
    printf("the palette command.  This command\n");
    printf("allows the programmer to control the\n");
    printf("color set and background color with\n");
    printf("one command.  There are a total of 6\n");
    printf("sets of three colors that may be \n");
    printf("displayed.  Three of these are normal;\n");
    printf("while the other three are bright\n");
    printf("versions of the basic three.\n");
    printf("\n\n     Press any key to continue\n");
    waitkey();

    pg6();
    cntue();
    waitkey();
    sm(4);
    backclr(9);


    pg7();
    cntue();
    waitkey();
    sm(4);
    backclr(9);


    pg8();
    atsay(24,7,3,0, "Press any key to continue");
    waitkey();
    sm(4);
    backclr(9);

    pgf();
    greenslv();
    waitkey();
    sm(3);
    backclr(1);

 }  /*  End of main program */



 pg1()
 {
    burble(200,300);

    atsay(10,5,2,0, "The next page will demonstrate");
    atsay(11,5,2,0, "some of the simple graphics");
    atsay(12,5,2,0, "primitives including dots,");
    atsay(13,5,2,0, "lines, filled boxes and");
    atsay(14,5,2,0, "rectangles. ");
    atsay(20,5,3,0, "Press any key to continue");
 }

 pg2()
 {
    int i;

    for(i=0; i <= 20; i++)
       point(20, 10+i*2, i % 4);
    box(50,20,80,50,1);
    boxfill(54,24,76,46,2);
    box1(50,80,80,110,2,1);
    box2(50,140,80,170,3,1);
    circle(65,240,50,1,1,3);
    paint(65,240,2,3);
    line(120,20,190,300,1);
    line(190,20,120,300,2);
    line(155,20,155,300,3);
 }

 pg3()
 {
    atsay(7,5,3,0, "The following screen will further");
    atsay(8,5,3,0, "demonstrate the circle function");
    atsay(9,5,3,0, "and introduce the rotated ellipse");
    atsay(10,5,3,0, "function.  The latter allows the");
    atsay(11,5,3,0, "user to draw an ellipse with a");
    atsay(12,5,3,0, "specified aspect and angle of");
    atsay(13,5,3,0, "rotation.");
 }

 pg5()
 {

    turnright(150);     /*  Double Triangle  */

    pencolor(1);

    forward(50);

    delay(500);
    turnright(120);
    forward(50);
    delay(500);
    turnright(120);
    forward(100);
    delay(500);
    turnleft(120);
    forward(50);
    delay(500);
    turnleft(120);
    forward(50);

    turnright(180);
    forward(50);

    pencolor(0);

    forward(50);
    turnright(120);
    pencolor(2);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(100);
    turnright(60);
    delay(500);
    forward(97);

    turnright(72);
    forward(5);
    pencolor(0);
    forward(48);
    turnright(96);

    turnleft(72);
    pencolor(3);
    forward(90);
    turnright(72);
    forward(90);
    turnright(72);
    forward(90);
    turnright(72);
    forward(90);
    turnright(73);
    forward(90);
    pencolor(0);

    paint(90,160,3,1);
    paint(110,160,3,1);

    burble(100,200);

    paint(40,160,2,3);
    paint(182,160,1,2);

  }




 pg6()
 {
    palette(2,4,0);
    house();

    palette(0,5,0);
    house();

    palette(0,4,0);
    palette(0,4,0);
    house();

 }

 house()
 {
    for(i=0;i<=120;i++)
       point(rand() / 165,rand() / 103, rand() / 8192);

    line(180,0,180,319,1);        /* grass line */
    paint(183,10,1,1);            /*   grass */
    line(150,50,120,110,1);
    line(120,110,152,160,1);

    line(140,70,180,70,1);
    line(140,140,180,140,1);
    line(180,70,180,140,1);

    line(160,80,180,80,1);
    line(160,95,180,95,1);
    line(160,80,160,95,1);


    line(150,110,170,110,1);       /* Window */
    line(150,120,170,120,1);
    line(150,130,170,130,1);
    line(150,110,150,130,1);
    line(160,110,160,130,1);
    line(170,110,170,130,1);
    paint(155,115,2,1);             /* color the widow panes */
    paint(155,125,2,1);
    paint(165,115,2,1);
    paint(165,125,2,1);
    paint(130,110,3,1);            /* color the house  */

    line(130,100,130,120,2);       /* lines in the house */
    line(161,75,161,79,2);
    line(155,86,155,97,2);
    line(165,100,165,107,2);
    line(161,72,161,78,2);
    line(142,70,142,93,2);
    line(147,100,147,116,2);

    paint(170,90,2,1);             /*  color the door   */
    circle(170,90,2,1,1,1);        /*    knob           */
    paint(170,90,2,1);             /*   fill it         */
    line(114,124,128,124,2);       /*   chimney         */
    line(114,136,136,136,2);
    line(114,124,114,136,2);
    line(128,124,136,136,2);
    paint(120,130,2,2);            /*  fill chimney       */
    line(116,125,116,135,3);       /*  horizontal bricks  */
    line(118,125,118,135,3);
    line(120,125,120,135,3);
    line(122,125,122,135,3);
    line(124,125,124,135,3);
    line(126,125,126,135,3);
    line(128,125,128,135,3);
    line(130,128,130,135,3);
    line(132,132,132,135,3);
    line(134,134,134,135,3);

    line(116,130,118,130,3);       /*  vertical bricks */
    line(118,133,120,133,3);
    line(118,127,120,127,3);
    line(120,130,122,130,3);
    line(122,127,124,127,3);
    line(122,133,124,133,3);
    line(124,130,126,130,3);
    line(126,127,128,127,3);
    line(126,133,128,133,3);

    line(128,130,130,130,3);
    line(130,133,132,133,3);

    line(132,130,134,130,3);

    boxfill(140,190,180,210,3);      /*  Tree Trunk   */
    line(168,190,172,188,3);
    line(172,188,180,177,3);
    line(168,210,172,212,3);
    line(172,212,180,223,3);
    line(180,177,180,223,3);         /*  base line of tree  */
    paint(178,185,3,3);              /*  paint the tree     */
    paint(178,215,3,3);

    line(174,190,178,183,2);        /*   root lines in tree */
    line(172,210,178,213,2);
    line(174,198,178,190,2);
    line(176,203,178,207,2);
    circle(150,190,3,3,1,3);
    paint(150,189,3,3);
    circle(160,210,3,1,3,3);
    paint(160,211,3,3);
    point(168,205,2);
    point(171,203,2);
    point(168,193,2);
    point(172,195,2);

    circle(135,216,10,1,2,1);
    paint(135,216,1,1);
    circle(105,180,9,1,1,1);
    paint(105,180,1,1);
    circle(128,180,9,1,3,1);
    paint(128,180,1,1);
    circle(125,228,5,1,2,1);
    paint(125,228,1,1);
    circle(94,200,10,1,3,1);
    paint(94,200,1,1);

    circle(117,200,30,3,5,1);
    paint(116,200,1,1);
    line(110,190,117,200,3);
    line(120,180,128,197,3);
    line(115,200,125,180,3);

    circle(74,100,10,1,1,2);       /*   cloud  */
    paint(74,100,2,2);
    circle(62,130,12,1,2,2);
    paint(62,130,2,2);
    circle(72,70,9,1,2,2);
    paint(72,70,2,2);
    circle(32,58,8,1,2,2);
    paint(32,58,2,2);
    circle(20,68,22,1,2,2);
    paint(20,68,2,2);
    circle(35,130,12,1,2,2);
    paint(35,130,2,2);
    circle(21,95,10,1,2,2);
    paint(21,95,2,2);
    circle(33,125,7,1,2,2);
    paint(33,125,2,2);

    circle(50,100,41,3,7,2);            /*   cloud  */
    paint(50,100,2,2);               /*  fill it */


    line(150,194,167,194,1);
    line(142,197,153,197,1);
    line(165,195,174,195,1);
    line(147,200,153,200,1);
    line(150,205,164,205,1);
    line(153,201,164,201,1);
    line(163,202,172,202,1);


    circle(50,270,15,1,1,3);      /*  moon */
    paint(50,270,03,03);            /*  fill it  */
    point(52,273,1);
    point(43,260,1);
    point(52,262,1);
    point(53,262,1);
    point(52,261,1);
    point(53,273,1);
    point(40,270,1);
    point(60,268,1);
    point(45,281,1);
    point(45,282,1);
    point(44,281,1);
    point(44,272,0);
    point(43,272,0);
    point(43,271,0);
    point(47,265,0);
    point(46,265,0);
    point(46,264,0);
    point(53,275,0);
    point(54,276,0);

    delay(3000);
 }


 pg7()
 {

    hollow('F',15,100,3);
    hollow('O',15,124,3);
    hollow('N',15,148,3);
    hollow('T',15,172,3);
    hollow('S',15,196,3);

    gliss(100,1000,300);

    atsay(6,2,2,0,"Many different Fonts are Possible");

    usrfont('T',80,60,2,2,3,0);
    usrfont('H',80,80,2,2,3,0);
    usrfont('I',80,100,2,2,3,0);
    usrfont('N',80,120,2,2,3,0);
    usrfont('L',88,140,1,1,3,0);
    usrfont('E',88,150,1,1,3,0);
    usrfont('T',88,160,1,1,3,0);
    usrfont('T',88,170,1,1,3,0);
    usrfont('E',88,180,1,1,3,0);
    usrfont('R',88,190,1,1,3,0);
    usrfont('S',88,200,1,1,3,0);

    usrfont('S',135,146,1,1,3,1);
    usrfont('U',135,152,1,1,3,1);
    usrfont('B',135,158,1,1,3,1);
    usrfont('/',130,164,1,1,3,0);
    usrfont('S',127,174,1,1,3,1);
    usrfont('U',127,180,1,1,3,1);
    usrfont('P',127,186,1,1,3,1);
    usrfont('E',127,192,1,1,3,1);
    usrfont('R',127,198,1,1,3,1);
    usrfont('S',130,209,1,1,2,0);
    usrfont('C',130,219,1,1,2,0);
    usrfont('R',130,229,1,1,2,0);
    usrfont('I',130,239,1,1,2,0);
    usrfont('P',130,249,1,1,2,0);
    usrfont('T',130,259,1,1,2,0);
    usrfont('S',130,269,1,1,2,0);



    usrfont('X',175,65,3,3,1,0);
    usrfont('2',175,97,2,2,1,1);
    usrfont('+',175,105,3,3,1,0);
    usrfont('X',175,134,3,3,1,0);
    usrfont('-',175,160,3,3,1,0);
    usrfont('4',175,185,3,3,1,0);
    usrfont('=',175,210,3,3,1,0);
    usrfont('0',175,230,3,3,1,0);

 }



 pg8()
 {
    printf("   Below are a few Unit Conversions\n\n\n\n\n");
    printf("%8.6f inches    = %f cm\n",4.0, INCH_CM(4.0));
    printf("%8.6f cm       = %f inches\n",10.0, CM_INCH(10.0));
    printf("%8.6f degrees  = %f radians\n",90.0, DEG_RAD(90.0));
    printf("%8.6f radians   = %f degrees\n",1.0, RAD_DEG(1.0));
    printf("%8.6f ounces    = %f grams\n",4.0, OZ_GM(4.0));
    printf("%8.6f grams    = %f ounces\n",50.0, GM_OZ(50.0));
    printf("%8.6f gallons  = %f liters\n",10.0, GAL_LT(10.0));
    printf("%8.6f liters   = %f gallons\n",50.0, LT_GAL(50.0));
    printf("%8.6f pounds    = %f kilograms\n",4.0, LB_KG(4.0));
    printf("%8.6f kilogram = %f pounds\n",50.0, KG_LB(50.0));

 }



 pgf()
 {
    int start = 9;


    gothic('U',10,start+0,3);
    gothic('n',10,start+25,3);
    gothic('i',10,start+45,3);
    gothic('c',10,start+65,3);
    gothic('o',10,start+85,3);
    gothic('r',10,start+105,3);
    gothic('n',10,start+125,3);

    gothic('S',10,start+155,3);
    gothic('o',10,start+175,3);
    gothic('f',10,start+195,3);
    gothic('t',10,start+215,3);
    gothic('w',10,start+235,3);
    gothic('a',10,start+255,3);
    gothic('r',10,start+275,3);
    gothic('e',10,start+295,3);

    atsay(7,5,3,0, "We Hope you have enjoyed seeing");
    atsay(8,5,3,0, "some of the features contained");
    atsay(9,5,3,0, "in the Unicorn library for the");
    atsay(10,5,3,0, "IBM PC medium resolution mode");
    atsay(11,5,3,0, "graphics.");
    atsay(14,5,2,0, "       Developed by");
    atsay(15,5,2,0, "      David A. Miller");

    gliss(3000, 200, 100);

    atsay(24,4,2,0, " Press any key to return to Dos");
 }




 atom()
 {
   ellipser(100,160,0,50,25,2);
   ellipser(100,160,0,25,50,2);
   ellipser(100,160,48,50,25,1);
   ellipser(100,160,48,25,50,1);

   circle(100,160,70,1,1,1);
   circle(100,160,66,1,1,1);
   paint(100,228,2,1);
   circle(100,160,4,1,1,3);
   paint(100,160,3,3);
 }


 cntue()
 {
    atsay(15,1,2,0, "Press any");
    atsay(16,2,2,0, "Key to");
    atsay(17,1,2,0, "continue");
 }

 unicorn()
 {
    line(66,100,107,156, 3);      /*   horn  */
    line(66,100,113,148, 3);


    line(157,170,158,154, 3);
    line(158,154,172,138, 3);
    line(172,138,173,125, 3);
    line(173,125,166,115, 3);
    line(166,115,151,117, 3);
    line(151,117,130,138, 3);
    line(130,138,120,140, 3);
    line(120,140,98,168, 3);     /* this line ends at the ear  */
    line(98,168,85,165,  3);
    line(85,165,89,172, 3);
    line(89,172,97,180, 3);
    line(97,180,121,224, 3);     /* outline after ear      */
    line(121,224,156,255, 3);
    line(156,255,198,266, 3);    /*  very bottom line  */

    line(157,170,170,180, 3);     /* part to left going down  */
    line(170,180,198,180, 3);     /* very bottom line */

    line(198,180,198,266,3);      /*   line across base of head  */
    paint(188,182,3,3);           /*   fill in the head!!  */
    paint(111,148, 3,3);        /*   fill in the horn    */
    line(148,185,157,170, 2);      /* head starting at bottom  */

    line(152,130,140,142, 2);     /* in head near mouth    */
    line(140,142,133,156, 2);

    line(103,167,123,173,2);     /* between ear and eye   */

    line(173,125,160,138,2);       /*  mouth   */

    line(167,145,181,151,3);       /*  goatee   */
    line(181,151,175,141,3);
    line(175,141,183,139,3);
    line(183,139,173,133,3);
    paint(172,141,3,3);             /*  color the goatee  */

    line(102,149,107,142, 2);       /* lines across the horn   */
    line(97,140, 100,135, 2);
    line(91,134,94,130, 2);
    line(86,127,88,122, 2);
    line(81,121,83,119, 2);
    line(76,113,77,111, 2);

    line(98,180,140,182,2);        /*  mane     */
    line(106,160,118,168,2);
    line(140,182,149,198,2);
    line(130,205,170,208,2);
    line(170,208,180,220,2);
    line(154,232,190,235,2);
    line(190,235,194,245,2);

    ellipser(122,158,42,7,3,2);
    paint(122,158,2,2);
    ellipser(156,123,72,4,2,2);
    paint(156,123,2,2);

    circle(123,157,2,1,1,1);
    paint(123,157,1,1);
    point(123,157,3);
 }

 greenslv()
 {
    playibm(6,3,400);

 /* 1 */
    playibm(9,3,800);
    playibm(11,3,400);

 /* 2 */
    playibm(1,4,500);
    playibm(3,4,300);
    playibm(1,4,400);

 /* 3 */
    playibm(11,3,800);
    playibm(8,3,400);

 /* 4 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 5 */
    playibm(9,3,800);
    playibm(6,3,400);

 /* 6 */
    playibm(6,3,500);
    playibm(5,3,300);
    playibm(6,3,400);

 /* 7 */
    playibm(8,3,800);
    playibm(5,3,400);

 /* 8 */
    playibm(1,3,800);
    playibm(6,3,400);

 /* 9 */
    playibm(9,3,800);
    playibm(11,3,400);

 /* 10 */
    playibm(1,4,500);
    playibm(3,4,300);
    playibm(1,4,400);

 /* 11 */
    playibm(11,3,800);
    playibm(8,3,400);

 /* 12 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 13 */
    playibm(9,3,500);
    playibm(8,3,300);
    playibm(6,3,400);

 /* 14 */
    playibm(5,3,400);
    playibm(3,3,400);
    playibm(5,3,400);

 /* 15 */
    playibm(6,3,1200);
    playibm(1,1,1);
 /* 16 */
    playibm(6,3,1200);

 /* 17 */
    playibm(4,4,800);
    playibm(1,1,1);

 /* 18 */
    playibm(4,4,400);
    playibm(3,4,400);
    playibm(1,4,400);

 /* 19 */
    playibm(11,3,800);
    playibm(8,3,400);

 /* 20 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 21 */
    playibm(9,3,800);
    playibm(6,3,400);

 /* 22 */
    playibm(6,3,400);
    playibm(5,3,400);
    playibm(6,3,400);

 /* 23 */
    playibm(8,3,800);
    playibm(5,3,400);

 /* 24 */
    playibm(1,3,1600);
    playibm(1,1,1);

 /* 25 */
    playibm(4,4,1600);
    playibm(1,1,1);

 /* 26 */
    playibm(4,4,400);
    playibm(3,4,400);
    playibm(1,4,400);

 /* 27 */
    playibm(11,3,800);
    playibm(8,3,400);
    playibm(1,1,1);

 /* 28 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 29 */
    playibm(9,3,500);
    playibm(8,3,300);
    playibm(6,3,400);

 /* 30 */
    playibm(5,3,400);
    playibm(3,3,400);
    playibm(5,3,400);

 /* 31 */
    playibm(6,3,1600);
    playibm(1,1,1);

 /* 32 */
    playibm(6,3,1200);
 }

 victory()
 {
   playibm(7,3,320);
   playibm(1,4,320);
   playibm(4,4,320);
   playibm(7,4,480);
   playibm(7,4,160);
   playibm(7,4,320);
   playibm(4,4,480);
   playibm(4,4,160);
   playibm(4,4,320);
   playibm(12,3,320);
   playibm(4,4,320);
   playibm(12,3,320);
   playibm(7,3,960);
 }


 DEMOTDY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\DEMOTDY.C

 /*                               Demo.c
 *
 *    This program is designed to illustate some of the features contained
 *  in the Unicorn Library.  It uses the 16 color medium resolution mode of
 *  Tandy 1000 computer.  A second version of the library is available
 *  to be used with the 4 color medium resolution mode (mode 4) on the
 *  IBM-PC computer.
 *
 *    This program was written to test the Unicorn Library and to illustrate
 *  the use of the library functions.  Although it includes some art work
 *  please keep in mind that the author claims little or no artistic
 *  talent.  In spite of this, the program does illustrate how to call
 *  various functions contained in the library.
 *
 *    The library was originally developed to be used in a public school
 *  district in the development of software.  In addition it was used as
 *  a learning tool by the author.  The author has had no formal training
 *  in C or Assembler and was responsible for software development for
 *  the district.  The learning experience was worthwhile and the author
 *  feels that many others may also benefit by examining the source code.
 *
 *    This library is an upgraded version of an earlier release but
 `*  further improvements will occur in future releases.  This library
 *  now includes a paint command and many functions formally written in
 *  the C language have now been written in assembler to improve speed.
 *
 *    This program and library are both
 *                 Copyright (c) 1986 by David A. Miller
 *
 *  The right to use and give away both are hereby granted as long as the
 *  copyright notice is not removed from either, and the restrictions
 *  listed in the user agreement list elsewhere are followed.
 *
 *                           David A. Miller
 *                           8018 NE 123rd St.
 *                           Kirkland, WA  98034
 *                           (206) 823-4656
 *                           no collect calls please!
 *
 */


 #include "uc.h"


 main()
 {
    int start = 9;   /*  define title start column  */


    /* The following must be declared to return proper values */

    sm(9);
    backclr(9);

    gothic('U',10,start+0,14);
    gothic('n',10,start+25,14);
    gothic('i',10,start+45, 14);
    gothic('c',10,start+60, 14);
    gothic('o',10,start+80,14);
    gothic('r',10,start+100,14);
    gothic('n',10,start+120,14);

    gothic('S',10,start+155,14);
    gothic('o',10,start+175,14);
    gothic('f',10,start+195,14);
    gothic('t',10,start+210,14);
    gothic('w',10,start+225,14);
    gothic('a',10,start+245,14);
    gothic('r',10,start+265,14);
    gothic('e',10,start+285,14);

    raschar('P',50, start + 70, 2, 2, 11);
    raschar('r',50, start + 90, 2, 2, 11);
    raschar('e',50, start + 110, 2, 2, 11);
    raschar('s',50, start + 130, 2, 2, 11);
    raschar('e',50, start + 150, 2, 2, 11);
    raschar('n',50, start + 170, 2, 2, 11);
    raschar('t',50, start + 190, 2, 2, 11);
    raschar('s',50, start + 210, 2, 2, 11);

    victory();

 /* opening to 5th symphony */
 /*
    soundon();

    note(1,3,11,10);
    delay(200);
    note(1,3,11,0);
    delay(50);

    note(1,3,11,10);
    delay(200);
    note(1,3,11,0);
    delay(50);

    note(1,3,11,10);
    delay(200);
    note(1,3,11,0);
    delay(50);

    note(1,3,7,10);
    delay(1200);

    note(1,3,9,10);
    delay(200);
    note(1,3,9,0);
    delay(50);

    note(1,3,9,10);
    delay(200);
    note(1,3,9,0);
    delay(50);

    note(1,3,9,10);
    delay(200);
    note(1,3,9,0);
    delay(50);

    note(1,3,6,10);
    delay(1200);


    setatten(1,15);
    setatten(2,15);
    setatten(3,15);
 */
    unicorn();
    atsay(24,3,8,0,"Copyright (c) 1986 David A. Miller");



    greenslv();

    cntue();
    waitkey();
    sm(9);       /* this resets the mode which in effect is a
                    clear screen command.                      */
    backclr(9);

    burble(200, 300);

    printf("\n\n\n\n\n A demonstration of Tandy-1000\n");
    printf(" graphics using the 16 color medium\n");
    printf(" resolution mode and the Unicorn\n");
    printf(" library of functions.  This library\n");
    printf(" uses the Lattice C large model.\n");
    printf("   Not all library functions are \n");
    printf(" illustrated in this demo.  The \n");
    printf(" library is capable of many graphics\n");
    printf(" concepts including points, lines, \n");
    printf(" circles, ellipses (also rotated),\n");
    printf(" and colorful print including \n");
    printf(" different fonts.\n\n");
    printf("    We hope you enjoy the demo\n");
    printf("       and using the library!\n\n");
    printf("   Copyright (C) 1986 David A. Miller\n");
    atsay(24,10,8,0,"Press any key to continue");

    waitkey();
    gliss(100, 1500, 3);

    sm(9);       /* this resets the mode which in effect is a
                    clear screen command.                      */
    backclr(14);



    pg1();
    waitkey();
    sm(9);
    backclr(1);



    pg2();
    cntue();
    waitkey();
    burble(300, 450);
    sm(9);
    backclr(1);

    pg3();
    cntue();
    waitkey();
    sm(9);
    backclr(9);

    atom();
    redalert();
    cntue();
    waitkey();
    sm(9);
    backclr(1);

    printf("   The next screen will demonstrate\n\n\n");
    printf("   T u r t l e    F u n c t i o n s");
    printf("\n\n\n\n\n   The delay function is used to");
    printf("\n   slow down the display of lines\n");
    cntue();
    burble(200, 350);
    waitkey();
    sm(9);
    backclr(7);

    pg5();
    cntue();
    waitkey();
    sm(9);
    backclr(1);

    script('C',5,110,15);
    script('o',5,126,14);
    script('l',5,142,13);
    script('o',5,158,12);
    script('r',5,174,11);
    script('s',5,190,10);


    printf("\n\n\n\n   The following page illustrates\n");
    printf("   the full 16 color color-set.\n");
    printf("\n\n        Press any key to continue\n");
    waitkey();

    pg6();
    cntue();
    waitkey();
    gliss(1200, 400, 4);
    sm(9);
    backclr(9);


    pg7();
    cntue();
    waitkey();
    sm(9);
    backclr(9);


    pg8();
    atsay(24,5,8,0,"Press any key to continue");
    waitkey();
    sm(9);
    backclr(1);


    pgf();
    waitkey();
    sm(3);
    backclr(1);

 }  /*  End of main program */



 pg1()
 {
    atsay(10,05,8,0, "The next page will demonstrate");
    atsay(11,05,8,0, "some of the simple graphics");
    atsay(12,05,8,0, "primitives including dots,");
    atsay(13,05,8,0, "lines, filled boxes and");
    atsay(14,05,8,0, "rectangles. ");
    atsay(20,05,7,0, "Press any key to continue");
 }

 pg2()
 {
    int i;

    for(i=0; i <= 20; i++)
       point(20, 10+i*2,i % 16);
    box(50,20,80,50,15);
    boxfill(54,24,76,46,4);
    box1(50,80,80,110,12,14);
    box2(50,140,80,170,13,9);
    circle(65,240,50,1,1,13);
    paint(65,240,4,13);
    line(120,20,190,300,14);
    line(190,20,120,300,12);
    line(155,20,155,300,4);
    line(120,20,120,300,5);
    line(190,20,190,300,15);
 }

 pg3()
 {
    atsay(7,05,12,0,  "The following screen will further");
    atsay(8,05,12,0,  "demonstrate the circle function");
    atsay(9,05,12,0,  "and introduce the rotated ellipse");
    atsay(10,05,12,0, "function.  The latter allows the");
    atsay(11,05,12,0, "user to draw an ellipse with a");
    atsay(12,05,12,0, "specified aspect and angle of");
    atsay(13,05,12,0, "rotation.");
 }

 pg5()
 {
    turnright(150);

    pencolor(14);

    forward(50);

    delay(300);
    turnright(120);
    forward(50);
    delay(300);
    turnright(120);
    forward(100);
    delay(300);
    turnleft(120);
    forward(50);
    delay(300);
    turnleft(120);
    forward(50);

    turnright(180);
    forward(50);

    pencolor(0);

    forward(50);
    turnright(120);
    pencolor(14);
    delay(300);
    forward(100);
    turnright(60);
    delay(300);
    forward(100);
    turnright(60);
    delay(300);
    forward(100);
    turnright(60);
    delay(300);
    forward(100);
    turnright(60);
    delay(300);
    forward(100);
    turnright(60);
    delay(300);
    forward(97);

    turnright(72);
    forward(5);

    pencolor(0);

    forward(48);
    turnright(96);

    turnleft(72);
    pencolor(4);
    forward(90);
    turnright(72);
    forward(90);
    turnright(72);
    forward(90);
    turnright(72);
    forward(90);
    turnright(73);
    forward(90);
    pencolor(0);

    paint(90,160,4,14);
    paint(110,160,4,14);


    paint(40,160,15,4);
    paint(182,160,14,15);

  }




 pg6()
 {
    int i;
    sm(9);
    backclr(0);
    for(i=0;i<=150;i++)
       point(rand()/165,rand()/103,rand()/2048);

    line(180,0,180,319,1);        /* grass line */
    paint(183,10,2,1);            /*   grass */
    line(150,50,120,110,1);
    line(120,110,152,160,1);

    line(140,70,180,70,1);
    line(140,140,180,140,1);
    line(180,70,180,140,1);

    line(160,80,180,80,1);
    line(160,95,180,95,1);
    line(160,80,160,95,1);


    line(150,110,170,110,1);       /* Window */
    line(150,120,170,120,1);
    line(150,130,170,130,1);
    line(150,110,150,130,1);
    line(160,110,160,130,1);
    line(170,110,170,130,1);
    paint(155,115,14,1);             /* color the widow panes */
    paint(155,125,14,1);
    paint(165,115,14,1);
    paint(165,125,14,1);
    paint(130,110,3,1);            /* color the house  */

    line(130,100,130,120,11);       /* lines in the house */
    line(161,75,161,79,11);
    line(155,86,155,97,11);
    line(165,100,165,107,11);
    line(161,72,161,78,11);
    line(142,70,142,93,11);
    line(147,100,147,116,11);

    paint(170,90,6,1);             /*  color the door   */
    circle(170,90,2,1,1,8);        /*    knob           */
    paint(170,90,8,8);             /*   fill it         */
    line(114,124,128,124,4);       /*   chimney         */
    line(114,136,136,136,4);
    line(114,124,114,136,4);
    line(128,124,136,136,4);
    paint(120,130,4,4);            /*  fill chimney       */
    line(116,125,116,135,8);       /*  horizontal bricks  */
    line(118,125,118,135,8);
    line(120,125,120,135,8);
    line(122,125,122,135,8);
    line(124,125,124,135,8);
    line(126,125,126,135,8);
    line(128,125,128,135,8);
    line(130,128,130,135,8);
    line(132,132,132,135,8);
    line(134,134,134,135,8);

    line(116,130,118,130,8);       /*  vertical bricks */
    line(118,133,120,133,8);
    line(118,127,120,127,8);
    line(120,130,122,130,8);
    line(122,127,124,127,8);
    line(122,133,124,133,8);
    line(124,130,126,130,8);
    line(126,127,128,127,8);
    line(126,133,128,133,8);

    line(128,130,130,130,8);
    line(130,133,132,133,8);

    line(132,130,134,130,8);

    boxfill(140,190,180,210,6);      /*  Tree Trunk   */
    line(168,190,172,188,6);
    line(172,188,180,177,6);
    line(168,210,172,212,6);
    line(172,212,180,223,6);
    line(180,177,180,223,6);         /*  base line of tree  */
    paint(178,185,6,6);              /*  paint the tree     */
    paint(178,215,6,6);

    line(174,190,178,183,8);        /*   root lines in tree */
    line(172,212,178,213,8);
    line(174,198,178,190,8);
    line(176,203,178,207,8);
    circle(150,190,3,3,1,6);
    paint(150,189,6,6);
    circle(160,210,3,1,3,6);
    paint(160,211,6,6);
    point(168,205,8);
    point(171,203,8);
    point(168,193,8);
    point(172,195,8);

    circle(135,216,10,1,2,2);
    paint(135,216,2,2);
    circle(105,180,9,1,1,2);
    paint(105,180,2,2);
    circle(128,180,9,1,3,2);
    paint(128,180,2,2);
    circle(125,228,5,1,2,2);
    paint(125,228,2,2);
    circle(104,200,10,1,3,2);
    paint(104,200,2,2);

    circle(117,200,30,3,5,2);
    paint(116,200,2,2);
    line(110,190,117,200,10);
    line(120,180,128,197,10);




    circle(74,100,10,1,1,8);       /*   cloud  */
    paint(74,100,8,8);
    circle(62,130,12,1,2,8);
    paint(62,130,8,8);
    circle(72,70,9,1,2,8);
    paint(72,70,8,8);
    circle(32,58,8,1,2,8);
    paint(32,58,8,8);
    circle(20,68,22,1,2,8);
    paint(20,68,8,8);
    circle(35,130,12,1,2,8);
    paint(35,130,8,8);
    circle(21,95,10,1,2,8);
    paint(21,95,8,8);
    circle(33,125,7,1,2,8);
    paint(33,125,8,8);

    circle(50,100,41,3,7,8);            /*   cloud  */
    paint(50,100,8,8);               /*  fill it */


    line(150,194,167,194,8);
    line(142,197,153,197,8);
    line(165,195,174,195,8);
    line(147,200,153,200,8);
    line(150,205,164,205,8);
    line(153,201,164,201,8);
    line(163,202,172,202,8);


    circle(50,270,15,1,1,7);      /*  moon */
    paint(50,270,7,7);            /*  fill it  */
    point(52,273,8);
    point(43,260,8);
    point(52,262,8);
    point(53,262,8);
    point(52,261,8);
    point(53,273,8);
    point(40,270,8);
    point(60,268,8);
    point(45,281,8);
    point(45,282,8);
    point(44,281,8);
    point(44,272,15);
    point(43,272,15);
    point(43,271,15);
    point(47,265,15);
    point(46,265,15);
    point(46,264,15);
    point(53,272,15);
    point(54,276,15);

    delay(2000);



 }

 pg7()
 {
    hollow('F',15,100,14);
    hollow('O',15,120,14);
    hollow('N',15,140,14);
    hollow('T',15,160,14);
    hollow('S',15,180,14);

    printf("Many different fonts possible");
    usrfont('T',80,60,2,2,4,0);
    usrfont('H',80,80,2,2,4,0);
    usrfont('I',80,100,2,2,4,0);
    usrfont('N',80,120,2,2,4,0);
    usrfont('L',88,140,1,1,4,0);
    usrfont('E',88,150,1,1,4,0);
    usrfont('T',88,160,1,1,4,0);
    usrfont('T',88,170,1,1,4,0);
    usrfont('E',88,180,1,1,4,0);
    usrfont('R',88,190,1,1,4,0);
    usrfont('S',88,200,1,1,4,0);

    usrfont('S',135,146,1,1,14,1);
    usrfont('U',135,152,1,1,14,1);
    usrfont('B',135,158,1,1,14,1);
    usrfont('/',130,164,1,1,14,0);
    usrfont('S',127,174,1,1,14,1);
    usrfont('U',127,180,1,1,14,1);
    usrfont('P',127,186,1,1,14,1);
    usrfont('E',127,192,1,1,14,1);
    usrfont('R',127,198,1,1,14,1);
    usrfont('S',130,209,1,1,14,0);
    usrfont('C',130,219,1,1,14,0);
    usrfont('R',130,229,1,1,14,0);
    usrfont('I',130,239,1,1,14,0);
    usrfont('P',130,249,1,1,14,0);
    usrfont('T',130,259,1,1,14,0);
    usrfont('S',130,269,1,1,14,0);



    usrfont('X',175,65,3,3,14,0);
    usrfont('2',175,97,2,2,14,1);
    usrfont('+',175,105,3,3,14,0);
    usrfont('X',175,134,3,3,14,0);
    usrfont('-',175,160,3,3,14,0);
    usrfont('4',175,185,3,3,14,0);
    usrfont('=',175,210,3,3,14,0);
    usrfont('0',175,230,3,3,14,0);

 }

 pg8()
 {
    printf("   Below are a few Unit Conversions\n\n\n\n\n");

    printf("%8.6f inches    = %f cm\n",4.0, INCH_CM(4.0));
    printf("%8.6f cm       = %f inches\n",10.0, CM_INCH(10.0));
    printf("%8.6f degrees  = %f radians\n",90.0, DEG_RAD(90.0));
    printf("%8.6f radians   = %f degrees\n",1.0, RAD_DEG(1.0));
    printf("%8.6f ounces    = %f grams\n",4.0, OZ_GM(4.0));
    printf("%8.6f grams    = %f ounces\n",50.0, GM_OZ(50.0));
    printf("%8.6f gallons  = %f liters\n",10.0, GAL_LT(10.0));
    printf("%8.6f liters   = %f gallons\n",50.0, LT_GAL(50.0));
    printf("%8.6f pounds    = %f kilograms\n",4.0, LB_KG(4.0));
    printf("%8.6f kilogram = %f pounds\n",50.0, KG_LB(50.0));


 }






 pgf()
 {
    int start = 9;
    gothic('U',10,start+0,14);
    gothic('n',10,start+25,14);
    gothic('i',10,start+45, 14);
    gothic('c',10,start+60, 14);
    gothic('o', 10,start+80,14);
    gothic('r',10,start+100,14);
    gothic('n',10,start+120,14);

    gothic('S',10,start+150,14);
    gothic('o',10,start+170,14);
    gothic('f',10,start+190,14);
    gothic('t',10,start+205,14);
    gothic('w',10,start+220,14);
    gothic('a',10,start+240,14);
    gothic('r',10,start+260,14);
    gothic('e',10,start+280,14);


    atsay(7,04,14,0, "hopes you have enjoyed seeing");
    atsay(8,04,14,0, "some of the features contained");
    atsay(9,04,14,0, "in the Unicorn library for the");
    atsay(10,04,14,0, "Tandy 1000 16 color medium");
    atsay(11,04,14,0, "resolution mode  (mode 9).");
    atsay(14,04,9,0, "      This Library was");
    atsay(16,04,11,0, "        Developed by");
    atsay(18,04,15,0, "      David A. Miller");

    greenslv();

    atsay(24,02,7,0, "    Press any key to return to Dos");
 }




 atom()
 {
   ellipser(100,160,0,50,25,14);
   ellipser(100,160,0,25,50,12);
   ellipser(100,160,48,50,25,13);
   ellipser(100,160,48,25,50,10);

   circle(100,160,70,1,1,1);
   circle(100,160,66,1,1,1);
   paint(100,228,4,1);
   circle(100,160,4,1,1,3);
   paint(100,160,4,3);
 }


 cntue()
 {
    atsay(15,1,8,0, "Press any");
    atsay(16,2,8,0, "Key to");
    atsay(17,1,8,0, "continue");
 }




 unicorn()
 {
    line(66,100,107,156, 15);      /*   horn  */
    line(66,100,113,148, 15);

    line(157,170,158,154, 15);
    line(158,154,172,138, 15);
    line(172,138,173,125, 15);
    line(173,125,166,115, 15);
    line(166,115,151,117, 15);
    line(151,117,130,138, 15);
    line(130,138,120,140, 15);
    line(120,140,98,168, 15);     /* this line ends at the ear  */
    line(98,168,85,165 , 15);
    line(85,165,89,172, 15);
    line(89,172,97,180, 15);
    line(97,180,121,224, 15);     /* outline after ear      */
    line(121,224,156,255, 15);
    line(156,255,198,266, 15);    /*  very bottom line  */

    line(157,170,170,180, 15);     /* part to left going down  */
    line(170,180,198,180, 15);     /* very bottom line */

    line(198,180,198,266,15);      /*   line across base of head  */
    paint(188,182,15,15);           /*   fill in the head!!  */
    paint(111, 148, 15,15);        /*   fill in the horn    */
    line(148,185,157,170, 8);      /* head starting at bottom  */

    line(152,130,140,142, 8);     /* in head near mouth    */
    line(140,142,133,156, 8);

    line(103,167,123,173,8);     /* between ear and eye   */

    line(173,125,160,138,8);       /*  mouth   */

    line(167,145, 181,151,15);       /*  goatee   */
    line(181,151,175,141,15);
    line(175,141,183,139,15);
    line(183,139,173,133,15);
    line(133,173,145,167,15);
    paint(172,141,15,15);             /*  color the goatee  */

    line(102,149,107,142, 8);       /* lines across the horn   */
    line(97,140, 100,135, 8);
    line(91,134,94,130, 8);
    line(86,127,88,122, 8);
    line(81,121,83,119, 8);
    line(76,113,77,111, 8);

    line(98,180,140,182,8);        /*  mane     */
    line(106,160,118,168,8);
    line(140,182,149,198,8);
    line(130,205,170,208,8);
    line(170,208,180,220,8);
    line(154,232,190,235,8);
    line(190,235,194,245,8);

    ellipser(122,158,42,7,3,8);
    paint(122,158,8,8);
    ellipser(156,123,72,4,2,8);
    paint(156,123,8,8);

    circle(123,157,2,1,1,9);
    paint(123,157,9,9);
    point(123,157,7);
 }




 victory()
 {
   playibm(7,3,320);
   playibm(1,4,320);
   playibm(4,4,320);
   playibm(7,4,480);
   playibm(7,4,160);
   playibm(7,4,320);
   playibm(4,4,480);
   playibm(4,4,160);
   playibm(4,4,320);
   playibm(12,3,320);
   playibm(4,4,320);
   playibm(12,3,320);
   playibm(7,3,960);
 }



 greenslv()
 {
    playibm(6,3,400);

 /* 1 */
    playibm(9,3,800);
    playibm(11,3,400);

 /* 2 */
    playibm(1,4,500);
    playibm(3,4,300);
    playibm(1,4,400);

 /* 3 */
    playibm(11,3,800);
    playibm(8,3,400);

 /* 4 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 5 */
    playibm(9,3,800);
    playibm(6,3,400);

 /* 6 */
    playibm(6,3,500);
    playibm(5,3,300);
    playibm(6,3,400);

 /* 7 */
    playibm(8,3,800);
    playibm(5,3,400);

 /* 8 */
    playibm(1,3,800);
    playibm(6,3,400);

 /* 9 */
    playibm(9,3,800);
    playibm(11,3,400);

 /* 10 */
    playibm(1,4,500);
    playibm(3,4,300);
    playibm(1,4,400);

 /* 11 */
    playibm(11,3,800);
    playibm(8,3,400);

 /* 12 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 13 */
    playibm(9,3,500);
    playibm(8,3,300);
    playibm(6,3,400);

 /* 14 */
    playibm(5,3,400);
    playibm(3,3,400);
    playibm(5,3,400);

 /* 15 */
    playibm(6,3,1200);
    playibm(1,1,1);
 /* 16 */
    playibm(6,3,1200);

 /* 17 */
    playibm(4,4,800);
    playibm(1,1,1);

 /* 18 */
    playibm(4,4,400);
    playibm(3,4,400);
    playibm(1,4,400);

 /* 19 */
    playibm(11,3,800);
    playibm(8,3,400);

 /* 20 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 21 */
    playibm(9,3,800);
    playibm(6,3,400);

 /* 22 */
    playibm(6,3,400);
    playibm(5,3,400);
    playibm(6,3,400);

 /* 23 */
    playibm(8,3,800);
    playibm(5,3,400);

 /* 24 */
    playibm(1,3,1600);
    playibm(1,1,1);

 /* 25 */
    playibm(4,4,1600);
    playibm(1,1,1);

 /* 26 */
    playibm(4,4,400);
    playibm(3,4,400);
    playibm(1,4,400);

 /* 27 */
    playibm(11,3,800);
    playibm(8,3,400);
    playibm(1,1,1);

 /* 28 */
    playibm(4,3,500);
    playibm(6,3,300);
    playibm(8,3,400);

 /* 29 */
    playibm(9,3,500);
    playibm(8,3,300);
    playibm(6,3,400);

 /* 30 */
    playibm(5,3,400);
    playibm(3,3,400);
    playibm(5,3,400);

 /* 31 */
    playibm(6,3,1600);
    playibm(1,1,1);

 /* 32 */
    playibm(6,3,1200);
 }








 DEQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\DEQ\DEQ.C

 /*--------------------------------------------------------------------------*
 /*   deq.c- selective delete; queries for each file to delete
  *          Uses C86 filedir() subroutine to return matching directory
  *          entries, queries to delete each file separately: Yes or No;
  *          Entry of G ends polling, begins automatic deletion (abort with
  *                    any keystroke).  Quit ends program.
  *   Copyright 1985 Walter Borys. No liability or guarantee for usage.
  *   Distributed as Freeware for utility or educational purposes
  *              only; not to be sold under any circumstances.
  *   Name and copyright notice may not be altered or removed.
  */
 /*--------------------------------------------------------------------------*
 #include "stdio.h"
 main(ac,av)
     int ac;
     char *av[];
     {
     extern char *filedir();         /* pointer to directory strings */
     char *filptr, *next;            /* pointer to current, next file*/
     char delfile[20];               /* filename with drive          */
     char *driveptr;                 /* pointer to drive with files  */
     int n,killall,reply,attrib;
     int bdos();
     static *hlptxt[]={
 "DEQ Selective Delete Program Usage:  dq [d:]filnam.ext\n\n",
 "  Program will poll to delete each matching file: /Y/N/G/Q\n",
 "    'Y'ES or 'N'O to delete, 'G'O to delete without polling, or 'Q'UIT\n",
 "    `G' process may be halted by hitting any key.\n",
 "    * and ? wildcards are supported, pathes are not.\n",
 "\nDEQ Version 1.1  Copyright Walt Borys 1985. Distributed as Freeware\n"};
 /*--------------------------------------------------------------------------*

     if (ac != 2)    /* print help message if no files specified */
         {
         for (n=0;n<6;n++)
             printf(hlptxt[n]);
         exit(0);
         }

     strncpy(delfile,av[1],20);              /* get file spec */
     attrib = 0;                             /* normal file attributes */
     for (n=0;n<strlen(delfile);n++)         /* check for pathes       */
         if (delfile[n] == 0134)
             abort("Sorry- don't do pathes \n");

     if (delfile[1]==':')                    /* another disk */
         driveptr=&delfile[2];
     else
         driveptr=&delfile[0];

     filptr = filedir(delfile,attrib);       /* directory string returned */

     if (filptr == NULL)
         {
         printf("No match for files %s found \n",delfile);
         exit(1);
         }

     killall = reply = 0;
     for (next = filptr; *next != NULL; next = next + strlen(next) + 1)
         {
         strcpy(driveptr,next);                   /* next file to delete */

         if (!killall)   /* query next delete, unless in delete all mode  */
             {
             while (bdos(11)&01)     /* flush typeahead */
                 bdos(7);
             do  {             /* main query iteration- loop thru files  */
                 printf(" Delete '%-15.15s'? (Y/N/G/Q) *",delfile);putchar(-1)
                 reply = toupper(bdos(7) &0177);     /* keystroke reply  */
                 if (reply=='\03')                   /* convert ^C to Q  */
                     reply = 'Q';
                 printf("%c\n",reply);               /* echo reply       */
                 } while (reply!='Y'&&reply!='N'&&reply!='G'&&reply!='Q');
             }

         if (reply == 'G') /* full delete, toggle reply to permanent Y  */
             killall = reply = 'Y';

         if (reply == 'Y')                        /* yes, delete file */
            unlink(delfile);

         if (reply == 'Q')                        /* quit */
             break;

         if (killall)         /* tell what is automatically being deleted */
             printf("   Deleting '%-15.15s'\n",next);

         if (killall && bdos(11)&01)         /* interrupt the full delete */
             killall = 0;                           /* go back to polling */
         }
     free(filptr);                           /* de allocate memory  */
     }


 DETAB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TABS\DETAB.C

 /* ------------------------------------------- */
 /*     DETAB - Convert tabs to blanks          */
 /*             Adapted from Software Tools     */
 /*             By Kernighan and Plauger        */
 /*                                             */
 /*             written by Michael Burton       */
 /*             Last Update: 14 Jan 1984       */
 /* ------------------------------------------- */
 /*     USAGE:                                  */
 /*             DETAB FROMFILE TOFILE N         */
 /*               N is the number of columns    */
 /*                 between tab stops           */
 /* ------------------------------------------- */
 #include "stdio.h"

 main(argc,argv)
        int argc;
        char *argv[];
 {
        static int col = 1, n, *fd, *td;
        static char c, *sp;

        if (argc != 4)
        {
                fputs("Usage: DETAB FROMFILE TOFILE N\007\n",stdout);
                return;
        }
        sp = argv[1];
        while ((*sp = toupper(*sp)) != EOS) sp++;
        sp = argv[2];
        while ((*sp = toupper(*sp)) != EOS) sp++;
        if ((fd = fopen(argv[1],"r")) == 0)
        {
                fputs(argv[1],stdout);
                fputs(" not found\007\n",stdout);
                return;
        }
        if ((td = fopen(argv[2],"w")) == 0)
        {
                fputs("Unable to open ",stdout);
                fputs(argv[2],stdout);
                fputs("\007\n",stdout);
                return;
        }
        n = atoi(argv[3]);
        if (n < 1 || n > 32) fputs("Tabs < 1 or > 32\007\n",stdout);
        while ((c = fgetc(fd)) != EOF)
        {
                switch (c)
                {
                        case '\t':
                                do
                                {
                                        fputc(' ',td);
                                        col++;
                                }
                                while ((col % n) != 0);
                                break;
                        case '\n':
                                fputc('\n',td);
                                col = 1;
                                break;
                        default:
                                fputc(c,td);
                                col++;
                }
        }
        fflush(fd);
        fflush(td);
        fclose(fd);
        fclose(td);
 }


 DETAR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\DETAR\DETAR.C

 /*
  *        detar.c
  *
  *        Version 1.1
  *
  *        Fixed bug in convert() wich produced errors on files without
  *        a slash '/' in them.
  *
  *        Unix Tape Archive (TAR) Extractor for MSDOS
  *
  *        Public Domain January 1988, Steve Sampson
  *        Based on the public domain TAR program by John Gilmore
  *
  *        Compiled with ECO-C88 V3.21
  */

 /* Includes */

 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <malloc.h>

 #include "detar.h"

 /* Defines */

 #define        isodigit(c)        ( ((c) >= '0') && ((c) <= '7') )

 /* Globals */

 FILE        *fdi,
         *fdo;

 union        record        *head;                /* the archive file header *
 struct        stat        hstat;                /* the decoded stat info   */
 struct        {
         int        year;
         int        month;
         int        day;
         int        hour;
         int        min;
         int        sec;
 } tm;

 long        s_p_min,
         s_p_hour,
         s_p_day,
         s_p_year;

 int        ugswidth = 11,
         dir_only = 0,
         days_per_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

 char        *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"},
         *days[] = {"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"},
         tempname[102],
         t_buf[26];

 /* Forward References, Prototypes */

 long        from_oct(int, char *);
 char        *ctime(long *);
 char        *convert(char *);
 void        cv_time(long);
 void        decode_header(union record *, struct stat *, int *);
 void        dir_tar(void);
 void        de_tar(void);
 void        demode(unsigned int, char *);
 void        read_header(void);
 void        exit(int);

 /* Main Program */

 main(argc, argv)
 int        argc;
 char        **argv;
 {
         char        *p;

         /*
          *        The operator can ask for directory only
          *        or de-tar only.
          */

         argv++;

         if (argc == 3 && **argv == 'd')  {
                 dir_only++;
                 argc--;
                 argv++;
         }

         if (argc != 2)  {
                 fprintf(stderr, "Usage: detar [d] filename[.tar]\n");
                 fprintf(stderr, "Where d means directory only\n");
                 exit(1);
         }

         for (p = *argv; *p; p++)
                 *p = (char)toupper(*p);

         /* parse the many possibilities, this stuff not needed with MSC */

         if ((p = strrchr(*argv, '.')) == (char *)NULL)
                 goto add;
         else if (strcmp(p, ".TAR") == NULL)
                 strcpy(tempname, *argv);
         else if (*(p+1) == '/' || *(p+1) == '\\')  {
 add:                strcpy(tempname, *argv);
                 strcat(tempname, ".TAR");
         } else  {
                 fprintf(stderr, "File '%s' not a TAR archive\n", *argv);
                 exit(1);
         }

         if ((fdi = fopen(tempname, "rb")) == (FILE *)NULL)  {
                 fprintf(stderr, "Tar File '%s' Not Found\n", tempname);
                 exit(1);
         }

         head = (union record *)malloc(512);

         if (dir_only)
                 dir_tar();
         else
                 de_tar();

         free(head);
         exit(0);
 }


 /*
  *        Produce a directory of the files contained on the TAR
  */

 void dir_tar()
 {
         char        modes[11], *timestamp;
         char        uform[11], gform[11];
         char        *user, *group, size[24];
         int        n, pad, header_std;
         long        longie;

         for (;;)  {
                 if ((n = fread((char *)head, 1, 512, fdi)) == EOF) {
                         fclose(fdi);
                         return;
                 }

                 decode_header(head, &hstat, &header_std);

                 /* File type and modes */

                 modes[0] = '?';

                 switch (head->header.linkflag) {
                 case LF_NORMAL:
                 case LF_OLDNORMAL:
                 case LF_LINK:
                         modes[0] = '-';
                         if ('/' == head->header.name[strlen(head->header.name
                                 modes[0] = 'd';
                         break;
                 case LF_DIR:
                         modes[0] = 'd';
                         break;
                 case LF_SYMLINK:
                         modes[0] = 'l';
                         break;
                 case LF_BLK:
                         modes[0] = 'b';
                         break;
                 case LF_CHR:
                         modes[0] = 'c';
                         break;
                 case LF_FIFO:
                         modes[0] = 'f';
                         break;
                 case LF_CONTIG:
                         modes[0] = '=';
                         break;
                 }

                 demode(hstat.st_mode, modes+1);

                 /* Timestamp */

                 longie = hstat.st_mtime;
                 timestamp = ctime(&longie);
                 timestamp[16] = '\0';
                 timestamp[24] = '\0';

                 /* User and group names */

                 if (*head->header.uname && header_std) {
                         user  = head->header.uname;
                 } else {
                         user = uform;
                         sprintf(uform, "%d", hstat.st_uid);
                 }

                 if (*head->header.gname && header_std) {
                         group = head->header.gname;
                 } else {
                         group = gform;
                         sprintf(gform, "%d", hstat.st_gid);
                 }

                 /* Format the file size or major/minor device numbers */

                 switch (head->header.linkflag) {
                 case LF_CHR:
                 case LF_BLK:
                         sprintf(size, "%d, %d",
                            (int)from_oct(8, head->header.devmajor),
                            (int)from_oct(8, head->header.devminor));
                         break;
                 default:
                         sprintf(size, "%ld", hstat.st_size);
                 }

                 /* Figure out padding and print the whole line. */

                 pad = strlen(user) + strlen(group) + strlen(size) + 1;

                 if (pad > ugswidth)
                         ugswidth = pad;

                 printf("%s %s/%s %*s%s %s %s %.*s",
                         modes,
                         user,
                         group,
                         ugswidth - pad,
                         "",
                         size,
                         timestamp+4, timestamp+20,
                         sizeof(head->header.name),
                         head->header.name);

                 switch (head->header.linkflag) {
                 case LF_SYMLINK:
                         printf(" -> %s\n", head->header.linkname);
                         break;

                 case LF_LINK:
                         printf(" link to %s\n", head->header.linkname);
                         break;

                 default:
                         printf(" unknown file type '%c'\n", head->header.link
                         break;

                 case LF_OLDNORMAL:
                 case LF_NORMAL:
                 case LF_CHR:
                 case LF_BLK:
                 case LF_DIR:
                 case LF_FIFO:
                 case LF_CONTIG:
                         putc('\n', stdout);
                         break;
                 }

                 /*
                  *        Seek to next file
                  */

                 fseek(fdi, hstat.st_size, 1);

                 /*
                  *        File starts on 512 byte boundary
                  */

                 fseek(fdi, 512L - (hstat.st_size % 512L), 1);
         }
 }


 /*
  *        Extract the files from the TAR archive
  *
  */

 void de_tar()
 {
         long        size;
         int        header_std, c;
         char        *workfile;

         for (;;)  {
                 if ( fread((char *)head, 1, 512, fdi) == EOF)  {
                         fclose(fdi);
                         return;
                 }

                 decode_header(head, &hstat, &header_std);
                 workfile = convert(head->header.name);

                 printf("Extracting: %s\n", workfile);

                 fdo = fopen(workfile, "w");
                 size = hstat.st_size;

                 while ((c = getc(fdi)) != EOF)  {

                         /*
                          *        Convert Linefeed to MSDOS
                          *        Carriage Return, Linefeed pair
                          *
                          */

                         if (c == 0x0A)
                                 putc('\n', fdo);
                         else
                                 putc(c, fdo);

                         if (--size == 0L)  {

                            /*
                             *        Get to next 512 byte boundary
                             */

                            fseek(fdi, 512L - (hstat.st_size % 512L), 1);
                            break;
                         }
                 }

                 fclose(fdo);
         }
 }


 /*
  *        Break down the header info into stat info
  *
  *        Set "*stdp" to != 0 or == 0 depending whether
  *        header record is "Unix Standard" or "old" tar format.
  *
  */

 void decode_header(header, st, stdp)
 register union record        *header;
 register struct stat        *st;
 register int                *stdp;
 {
         st->st_mode  = (int)from_oct( 8, header->header.mode);
         st->st_mtime = from_oct(12, header->header.mtime);
         st->st_size  = from_oct(12, header->header.size);

         if (0 == strcmp(header->header.magic, TMAGIC)) {

                 /* Unix Standard tar archive */

                 *stdp = 1;
                 st->st_dev = 0;

         } else {

                 /* Old fashioned tar archive */

                 *stdp = 0;
                 st->st_uid = (int)from_oct(8, header->header.uid);
                 st->st_gid = (int)from_oct(8, header->header.gid);
                 st->st_dev = 0;
         }
 }


 /*
  *        Decode the mode string from a stat entry into a 9-char string
  */

 void demode(mode, string)
 register unsigned mode;
 register char          *string;
 {
         register unsigned mask;
         register char          *rwx = "rwxrwxrwx";

         for (mask = 0400; mask != 0; mask >>= 1) {
                 if (mode & mask)
                         *string++ = *rwx++;
                 else {
                         *string++ = '-';
                         rwx++;
                 }
         }

         if (mode & S_ISUID)
                 if (string[-7] == 'x')
                         string[-7] = 's';
                 else
                         string[-7] = 'S';

         if (mode & S_ISGID)
                 if (string[-4] == 'x')
                         string[-4] = 's';
                 else
                         string[-4] = 'S';

         if (mode & S_ISVTX)
                 if (string[-1] == 'x')
                         string[-1] = 't';
                 else
                         string[-1] = 'T';

         *string = '\0';
 }


 /*
  *        Quick and dirty octal conversion.
  *
  *        Result is -1 if the field is invalid (all blank, or nonoctal).
  */

 long from_oct(digs, where)
 register int        digs;
 register char        *where;
 {
         register long        value;

         while (isspace(*where)) {                /* Skip spaces */
                 where++;
                 if (--digs <= 0)
                         return -1;                /* All blank field */
         }

         value = 0;
         while (digs > 0 && isodigit(*where)) {        /* Scan til nonoctal */
                 value = (value << 3) | (*where++ - '0');
                 --digs;
         }

         if (digs > 0 && *where && !isspace(*where))
                 return -1;                        /* Ended on non-space/nul *

         return value;
 }


 /*
  *        Borrowed from comp.os.minix
  */

 char *ctime(time)
 long        *time;
 {
         long        tt;

         s_p_min  = 60L;
         s_p_hour = 60L * 60L;
         s_p_day  = 60L * 60L * 24L;
         s_p_year = 60L * 60L * 24L * 365L;

         tt = *time;
         cv_time(tt);

         sprintf(t_buf, "%s %s %02d %02d:%02d:%02d %04d\n",
            days[(tt / s_p_day) % 7], months[tm.month], tm.day, tm.hour,
              tm.min, tm.sec, tm.year);

         return(t_buf);
 }


 void cv_time(time)
 long        time;
 {
         tm.year = 0;
         tm.month = 0;
         tm.day = 1;
         tm.hour = 0;
         tm.min = 0;
         tm.sec = 0;

         while (time >= s_p_year)  {
                 if (((tm.year + 2) % 4) == 0)
                         time -= s_p_day;

                 tm.year += 1;
                 time -= s_p_year;
         }

         if (((tm.year + 2) % 4) == 0)
                 days_per_month[1]++;

         tm.year += 1970;

         while ( time >= (days_per_month[tm.month] * s_p_day))
                 time -= days_per_month[tm.month++] * s_p_day;

         while (time >= s_p_day) {
                 time -= s_p_day;
                 tm.day++;
         }

         while (time >= s_p_hour) {
                 time -= s_p_hour;
                 tm.hour++;
         }

         while (time >= s_p_min) {
                 time -= s_p_min;
                 tm.min++;
         }

         tm.sec = (int)time;
 }

 char *convert(unixname)
 register char *unixname;
 {
         static   char        temp[16];
         register char        *p;
         register int        have_dot;

         /* First get rid of directory specs */

         if ((p = strrchr(unixname, '/')) != (char *)NULL)
                 strcpy(temp, p + 1);
         else
                 strcpy(temp, unixname);

         /* Then make a basic MSDOS filename */

         if (p = strchr(temp, '.'))  {
                 if (strlen(p) > 4)
                         p[4] = '\0';

                 if ((p - temp) > 8)  {
                         temp[8] = '\0';
                         strcat(temp, p);
                 }
         }
         else
                 temp[8] = '\0';

         /* Now look for two dots in filename, only one allowed in MSDOS */
         /* substitute a dash for second dot */

         for (have_dot = 0, p = temp; *p; p++)  {
                 if (*p == '.')  {
                         if (have_dot)
                                 *p = '-';
                         else
                                 have_dot = 1;
                 }
         }

         return temp;
 }

 /* EOF */


 DF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TOOLS\DF.C

 <stdio.h>              /* Standard I/O definitions */
 <ctype.h>              /* Character type macros */
 <dos.h>                /* Msdos definitions */
 <errno.h>              /* error codes */
 #include <string.h>

 static char ID[]="## df.c 1.0 K.van Houten 230987 ##";
 union REGS r, o;
 char *getvol();

 main (argc, argv)
 int     argc;
 char   *argv[];
 {
     int i=3;

     printf("\
        ------- b y t e s ------   - c l u s t e r s -\n\
 drive   total     used     free   total   used   free  usage\n");

     if (argc > 1) {
         while (--argc > 0) {
             ++argv;
             if ((argv[0][1] == ':')&&(driveinfo(tolower(**argv) - 'a' + 1) !=
                 exit(0);
         }
     }

     while (driveinfo(i) == 0)
         i++;
 }

 /* get info of drive i ( 1=A, 2=B, etc...) */
 driveinfo(i)
 int i;
 {
     int tmp;
     union REGS r;
     unsigned long total, free;
     float clsize;

     r.h.ah = 0x36;   /* get free space */
     r.h.dl = i;
     tmp = intdos(&r,&r);
     if (r.x.ax == 0xffff)
         return(1);
     clsize =(float)((double)(r.x.ax * r.x.cx) / (double)1024);
     total  = r.x.dx;
     free   = r.x.bx;
     printf("  %c:  ",i+64);
     /*
     printf(" %-10s",getvol(i));
     */
     printf("%5ld K  ",(long)(total * clsize));
     printf("%5ld K  ",(long)((total - free) * clsize));
     printf("%5ld K   ",(long)(free * clsize));

     printf("%5ld  ",total);
     printf("%5ld  ",(total-free));
     printf("%5ld   ",free);

     printf("%3d%%",(int)(100 * (float)((double)(total - free) / (double)total

     printf("\n");
     return(0);
 }

 char *
 getvol(d)
 int d;                          /* drive number */
 {
 A_VOLUME        0x08    /* Volume label */

 struct date {
 unsigned    d_sec:      5;      /* Time, 2 second intervals */
 unsigned    d_min:      6;      /* Time, minutes */
 unsigned    d_hour:     5;      /* Time, hours */
 unsigned    d_day:      5;      /* Date, day of month */
 unsigned    d_month:    4;      /* Date, month of year */
 unsigned    d_year:     7;      /* Date, year since 1980 */
 };
 struct find {
     char    fnd_dosinfo[21];    /* Reserved for dos */
     char    fnd_attr;           /* File attribute */
     struct date fnd_date;       /* Date structure */
     long    fnd_size;           /* File size */
     char    fnd_name[13];       /* File name less path */
 };
     struct find f;              /* Used to return data from msdos */
     union REGS r;               /* Contains register values for intcall() */
     char file[20];
     char *t;


     r.h.ah = 0x1a;              /* SET DISK TRANSFER ADDRESS FUNCTION */
     r.x.dx = (int) & f;
     intdos (&r, &r);

     sprintf("%c:\\*.*",d+64);
     r.h.ah = 0x4e;              /* FINDFIRST function */
     r.x.cx = A_VOLUME;
     r.x.dx = (int) file;
     intdos (&r, &r);      /* Find first */
     if (r.x.cflag) {
         return(NULL);
     }
     t = (char *)malloc(13);
     if (t == NULL) {
         perror("volname");
         exit(2);
     }
     strcpy(t,f.fnd_name);
     return(t);
 }


 DFA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\DFA.C

 /*
  * Copyright (c) 1978 Charles H. Forsyth
  *
  * Modified 02-Dec-80 Bob Denny -- Conditionalize debug code for reduced size
  * Modified 29-May-81 Bob Denny -- Clean up overlay stuff for RSX.
  * More     19-Mar-82 Bob Denny -- New C library & compiler
  * More     03-May-82 Bob Denny -- Final touches, remove unreferenced autos
  * More     29-Aug-82 Bob Denny -- Clean up -d printouts
  * More     29-Aug-82 Bob Denny -- Reformat for readability and comment
  *                                 while learning about LEX.
  * More                20-Nov-83 Scott Guthery -- Adapt for IBM PC & DeSmet C
  */

 /*
  *    *********
  *    * DFA.C *
  *    *********
  *
  * LEX -- DFA construction routines
  */

 #include <stdio.h>
 #include "lexlex.h"

 extern struct set *eclosure();          /* Used only by DFA */
 extern struct dfa *defalt();            /* Used only by DFA */
 extern struct move *stbase();           /* Used only by DFA */

 /*
  * Build the DFA from the NFA
  */
 dfabuild()
    {
    struct trans *trp;
    struct nfa **vec, **tp, *np, *temp[MAXNFA+1];
    int a, i;
    struct set **sp, *stack[MAXDFA], **spp, *xp;  /* DFA set stack */
    struct dfa *state;                  /* --> current DFA state */
    struct xset *xs, *xse;

   /*
    * Simulate an epsilon transition from nfa state 0 to
    * the initial states of the machines for each
    * translation.
    */
    nfa[0].n_char = EPSILON;            /* Set NFA state 0 transition EPSILON
    /*
     * Allocate a state vector, each node of which will
     * point to an NFA starting state.  Each translation
     * generates an NFA, so the number of translations
     * equals the number of NFA start states.
     */
    vec = lalloc(i = (transp-trans)+1, sizeof(*vec), "dfabuild");
    /*
     * Fill in the start state vector
     */
    vec[0] = nfa;                       /* vec[0] always --> NFA state 0 */
    for (a = 1, trp = trans; trp < transp; trp++)  /* For each translation */
       vec[a++] = trp->t_start;         /* Pick up the NFA start state */
    /*
     * Now build the set sp --> e-CLOSURE(vec)
     */
    sp = eclosure(newset(vec, i, 1));

    free(vec);                          /* Deallocate the start state vector *

    /*
     * At this point state 0 of the DFA is constructed.
     * This is the start state of the DFA.
     * Mark it "added" and push it on to the stack.
     */
    sp->s_flag |= ADDED;
    spp = stack;
    *spp++ = sp;
    /*
     * From state 0, which is now stacked, all further DFA
     * states will be derived.
     */
    while (spp > stack)
       {
       sp = *--spp;
       for (a = 0; a < NCHARS; a++)
          insets[a] = 0;
       xse = sets;
       for (i = 0; i < sp->s_len; i++)
          xse = addset(sp->s_els[i], xse);
       state = newdfa();
       sp->s_state = state;
       state->df_name = sp;
 #ifdef DEBUG
       if (lldebug)
          {
          fprintf(lexlog, "build state %d ", state-dfa);
          pset(sp, 1);
          fprintf(lexlog, "\n");
          }
 #endif
       state->df_ntrans = xse-sets;
       for (xs = sets; xs < xse; xs++)
          {
          a = xs->x_char&0377;
          tp = temp;
          for (i = 0; i < sp->s_len; i++)
             if ((np = sp->s_els[i])->n_char==a ||
                 np->n_char==CCL &&
                 np->n_ccl[a/NBPC]&(1<<(a%NBPC)))
                add(temp, &tp, np->n_succ[0]);
          xp = newset(temp, tp-temp, 1);
          xp = eclosure(xp);
 #ifdef DEBUG
          if (lldebug)
             {
             putc('\t', lexlog);
             chprint(a);
             putc('\t', lexlog);
             pset(xp, 1);
             fprintf(lexlog, "\n");
             }
 #endif
          xs->x_set = xp;
          if (xp->s_state==0 && (xp->s_flag&ADDED)==0)
             {
             xp->s_flag |= ADDED;
             if (spp >= stack+MAXDFA)
                {
                error("dfabuild: stack overflow");

                exit(1);
                }
             *spp++ = xp;
             }
          }
       state->df_default = defalt(state, &xse);
       setbase(state, stbase(xse), xse);
       }
    }

 /*
  * If an nfa state is not already a member of the vector `base', add it.
  */
 add(base, tpp, np)
 struct nfa ***tpp, **base, *np;
    {
    register struct nfa **tp;

    for (tp = base; tp < *tpp; tp++)
       if (*tp == np)
          return;
    *(*tpp)++ = np;
    }

 /*
  * Add the character(s) on which state `np' branches to the transition vector
  */
 addset(np, xse)
 register struct nfa *np;
 struct xset *xse;
    {
    register a;
    register char *ccl;

    if ((a = np->n_char) < NCHARS)
       xse = addxset(a, xse);
    if (a != CCL)
       return(xse);
    ccl = np->n_ccl;
    for (a = 0; a < NCHARS; a++)
       if (ccl[a/NBPC]&(1<<(a%NBPC)))
          xse = addxset(a, xse);
    return(xse);
    }

 /*
  * Add a character to the transition vector, if it isn't there already.
  */
 addxset(a, xse)
 register a;
 struct xset *xse;
    {
    register struct xset *xs;
    register int temp;
    /*
    * VMS native doesn't do this correctly:
    *    if (insets[a]++)
    */
    temp = insets[a];
    insets[a] += 1;
    if (temp)
       return(xse);
    xs = xse++;
    xs->x_char = a;
    xs->x_set = NULL;
    xs->x_defsame = 0;
    return(xse);
    }


 DFILL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\DFILL.C

 /* DFILL.C - From page 352 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. Uses direct memory access to      */
 /* fill the screen. To quit, enter X.                           */
 /****************************************************************/

 #define LENGTH 2000

 main()
 {
 int far *farptr;
 int addr;
 char ch;

    printf("\nType character to start, another to change, X to exit.");
    farptr = (int far *) 0xB0000000;
    while((ch = getche()) != 'X')
       for(addr = 0; addr < LENGTH; addr++)
          *(farptr + addr) = ch | 0x0700;
 }



 DFILL2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\DFILL2.C

 /* DFILL2.C - From page 353 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. Uses direct memory access to      */
 /* fill the screen. To quit, enter X.                           */
 /****************************************************************/

 #define ROMAX 25
 #define COMAX 80

 main()
 {
 int far *farptr;
 int col, row;
 char ch;

    printf("\nType a character to start, another to change, X to exit.");
    farptr = (int far *) 0xB0000000;
    while((ch = getche()) != 'X')
       for(row = 0; row < ROMAX; row++)
          for(col = 0; col < COMAX; col++)
             *(farptr + row*COMAX + col) = ch | 0x0700;
 }



 DFILL3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\DFILL3.C

 /* DFILL3.C - From page 357 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. Uses direct memory access to      */
 /* fill the screen with blinking attribute. To quit, enter X.   */
 /****************************************************************/

 #define ROMAX 25
 #define COMAX 80

 main()
 {
 int far *farptr;
 int col, row;
 char ch;

    printf("\nType a character to start, another to change, X to exit.");
    farptr = (int far *) 0xB0000000;
    while((ch = getche()) != 'X')
       for(row = 0; row < ROMAX; row++)
          for(col = 0; col < COMAX; col++)
             *(farptr + row*COMAX + col) = ch | 0x8700;
 }



 DG10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\DG10.C

 /*
  * The routines in this file provide support for the Data General Model 10
  * Microcomputer.
  */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     DG10

 NROW    24                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        NPAUSE        100                        /* # times thru update to pau
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
 BEL     0x07                    /* BEL character.               */
 ESC     30                      /* DG10 ESC character.          */

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern        int        dg10kopen();
 extern        int        dg10kclose();
 extern  int     dg10move();
 extern  int     dg10eeol();
 extern  int     dg10eeop();
 extern  int     dg10beep();
 extern  int     dg10open();
 extern        int        dg10rev();
 extern        int        dg10close();
 extern        int        dg10cres();

 #if        COLOR
 extern        int        dg10fcol();
 extern        int        dg10bcol();

 int        cfcolor = -1;                /* current forground color */
 int        cbcolor = -1;                /* current background color */
 int        ctrans[] = {                /* emacs -> DG10 color translation tab
         0, 4, 2, 6, 1, 5, 3, 7};
 #endif

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         dg10open,
         dg10close,
         dg10kopen,
         dg10kclose,
         ttgetc,
         ttputc,
         ttflush,
         dg10move,
         dg10eeol,
         dg10eeop,
         dg10beep,
         dg10rev,
         dg10cres
 #if        COLOR
         , dg10fcol,
         dg10bcol
 #endif
 };

 #if        COLOR
 dg10fcol(color)                /* set the current output color */

 int color;        /* color to set */

 {
         if (color == cfcolor)
                 return;
         ttputc(ESC);
         ttputc(0101);
         ttputc(ctrans[color]);
         cfcolor = color;
 }

 dg10bcol(color)                /* set the current background color */

 int color;        /* color to set */

 {
         if (color == cbcolor)
                 return;
         ttputc(ESC);
         ttputc(0102);
         ttputc(ctrans[color]);
         cbcolor = color;
 }
 #endif

 dg10move(row, col)
 {
         ttputc(16);
         ttputc(col);
         ttputc(row);
 }

 dg10eeol()
 {
         ttputc(11);
 }

 dg10eeop()
 {
 #if        COLOR
         dg10fcol(gfcolor);
         dg10bcol(gbcolor);
 #endif
         ttputc(ESC);
         ttputc(0106);
         ttputc(0106);
 }

 dg10rev(state)                /* change reverse video state */

 int state;        /* TRUE = reverse, FALSE = normal */

 {
 #if        COLOR
         if (state == TRUE) {
                 dg10fcol(0);
                 dg10bcol(7);
         }
 #else
         ttputc(ESC);
         ttputc(state ? 0104: 0105);
 #endif
 }

 dg10cres()        /* change screen resolution */

 {
         return(TRUE);
 }

 spal()                /* change palette string */

 {
         /*        Does nothing here        */
 }

 dg10beep()
 {
         ttputc(BEL);
         ttflush();
 }

 dg10open()
 {
         strcpy(sres, "NORMAL");
         revexist = TRUE;
         ttopen();
 }

 dg10close()

 {
 #if        COLOR
         dg10fcol(7);
         dg10bcol(0);
 #endif
         ttclose();
 }

 dg10kopen()

 {
 }

 dg10kclose()

 {
 }

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else
 dg10hello()
 {
 }
 #endif


 DIMAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DI\DIMAIN.C

 /* DI : Directory listing utility.   By  John H. DuBois III.   v1.1.
    Last rev 11/29/87.   Full documentation in DI.DOC.
    Searches directories and prints matching files.
    Multiple file specifications can be given.
    Any filespec can include wildcards in both filename and path.
    Recursive search of directories can be specified.
    Attributes of files to search for are given in and-terms; multiple and-ter
     can be given and files which match any of them will be printed.
    Files found in each directory can be sorted according to various criteria
     before groups of files with non-differing criteria are sorted by filename
    Listing can be printed in long form, wide form, or with full path of files
    Pause after each page can be specified.
    Printing of free space on device can be toggled off.
    Printing of headers can be toggled off.
    Total space used by the files listed can be printed.
    Initial listing specifications and search attributes can be specified by a
     environment variable.   */

 #include <stdio.h>
 #include <dir.h>
 #include <dos.h>
 #include <string.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <io.h>
 #include "di.h"

 main(int argc,char *argv[])
 {
 NameNode *Files,        /* Linked list of directories to print */
 *Temp;                /* Points to entry to be disposed of */
 int Attribs[MAX_ATTS];
 int Cnt;        /* Number of parameters given in environment var + 1 */
 ListType ListSpec;
 static char *Defaults[3] = {"","*.*","/LI5HSV"};        /* Default listing:
  list all files in current dir; list Long; sort by dIr attrib; when listing
  wide, print 5 entries per line; print all entries except those with attribs
  Hidden, System, or Volume label. */
 EntryListType EntryList;        /* Matching files found in a dir */
 char *Vars[80];                /* Value of env var */

    setvbuf(stdout, NULL, _IOLBF, 0x200);
    setcbrk(1);        /* Turn on cntrl-brk checking at all DOS interupts */
    More(-1);        /* Initialize More() to disabled */
    Files = NULL;        /* Initialize Files to null list */
    ListSpec.PrintFree = TRUE;   /* Make free space printing the default */
    ListSpec.PrintHeaders = TRUE;        /* Make header printing the default *
    ListSpec.RecSearch = FALSE;        /* Make no recursive listing the defaul
    GetArgs(3,Defaults,Attribs,&ListSpec,&Files);        /* Set up internal
     defaults for search attribs, list specs, and files to list */
    if (GetEnvParams(&Cnt,Vars,"DI")) {        /* If "DI" env var exists, get
         new defaults from it */
       GetArgs(Cnt,Vars,Attribs,&ListSpec,&Files);
       free(Vars[0]);        /* Free copied env var */
    }
    GetArgs(argc,argv,Attribs,&ListSpec,&Files);        /* Convert command lin
            to search attribs, list specs, and file specs */
    if (!isatty(1)) /* If stdout is redirected, turn of More if it was
                            enabled */
       More(-1);
    if (ListSpec.PrintHeaders)
       PrintHeader(Files,ListSpec.PrintFree);        /* Print volume labels an
                    possibly free space for all drives given in file specs */
    while (Files != NULL) {        /* For each filespec given */
       /* Get all matching fls */
       GetEntries(&EntryList,Attribs,Files -> Name,!ListSpec.RecSearch);
       if (EntryList.NumEnts > 1)        /* If at least two matching files wer
                                         found, sort list as specified */
          SortList(&EntryList,ListSpec.Sort);
       PrintList(&EntryList,&ListSpec,Files -> Name); /* Print list */
       Temp = Files;        /* Discard list node */
       free(Files);
       Files = Temp -> Next;
    }
 }

 More(int Lines)
 /* Pauses and waits for a key to be struck when MORE_ROWS lines have been
    printed.  A call with Lines = 0 resets line count to 0 and enables More.
    A call with Lines = -1 disables More.  A call with a positive number
    increments the line count by that amount. If More is disabled, it will
    return from all calls without pausing until it is called with 0.
    More() is called each time new lines are printed, with Lines set to the
    number of lines printed. If a number of lines is printed between calls tha
    is larger than (screen height - MORE_ROWS), lines may be lost (scrolled ou
    without pausing).  If, when More() pauses for a key to be hit, <space>
    is pressed, the line count will be set to 0 and More will return.  If
    any other key except q is hit, the line count will be set to MORE_ROWS - 1
    and More will return.  In this case, the next time it is called it will
    pause again (unless it is called with 0). If 'q' is pressed, the program
    will be terminated with exit status - 1.  All output is directly to
    screen.  More returns its enable status (-1 if enabled, else 0) which
    is the inverse of the codes used to enable/disable More.  A call
    with a negative number other than -1 for Lines is a null call and will
    have no effect; it will only return the enable status.  Such a call can
    therefore be used to return a number which will toggle the enable status
    of More if it is called with it */
 {
 static int Line,        /* Line count */
 Enabled = FALSE;        /* Whether More is enabled */

    if (Lines > -2)
       switch (Lines) {
          case 0 :        Line = 0;
                         Enabled = TRUE;
                         break;
          case -1 :        Enabled = FALSE;
                         break;
          default :
             if (Enabled && (Line += Lines) >= MORE_ROWS) { /* Print message
                                                             to screen & pause
                fputs("--More--",stderr);
                switch (getch()) {
                   case ' ' :        Line = 0;
                                 break;
                   case 'q' :
                   case 'Q' :        fputs("\b\b\b\b\b\b\b\bQuit    \n",stderr
                                 exit(1);
                   default  :        Line = MORE_ROWS - 1;
                }
                fputs("\b\b\b\b\b\b\b\b        \b\b\b\b\b\b\b\b",stderr);
                                                         /* Erase message */
             }
    }
    return (Enabled);
 }

 char *Insert(char *Target,char *Source,int Pos)
 /* Inserts string Source into string Target at position Pos. If the length of
    Target is less than Pos, Source is appended to Target. */
 {
 unsigned SLen,TLen;        /* Length of source and target strings */

    SLen = strlen(Source);
    TLen = strlen(Target);
    if (TLen < Pos)
       strcat(Target,Source);
    else {
       memcpy(Target + Pos + SLen,Target + Pos,TLen - Pos + 1);        /* Make
                                         in target string for source string */
       memcpy(Target + Pos,Source,SLen); /* Copy source string to targ string
    }
    return(Target);
 }

 char *AttribWtoS(char A)
 /* Converts an attibute word (A) to a string of characters representing the
    word's active attributes, puts the string in a static buffer, and
    returns a pointer to the buffer */
 {
 static char Attribs[7];                /* Attribute character buffer */
 static char Convert[] = "RHSVDA";        /* Ordered attribute list */
 int I,        /* Which attribute is being tested */
 J,        /* Index to buffer */
 Mask;        /* Bit mask to get attribute flag */

    Mask = 1;        /* Start with bit 0 */
    J = 0;
    for (I = 0; I < 6; I++) {
       if (A & Mask)        /* Add attribute to buffer */
          Attribs[J++] = Convert[I];
       Mask <<= 1;        /* Check next attribute */
    }
    Attribs[J] = '\0';        /* Terminate string */
    return(Attribs);
 }

 void *MallocT(unsigned Size)
 /* Calls malloc() to allocate a block of memory of size Size and checks
    whether there was enough memory. Exits if not, otherwise returns a
    pointer to the block */
 {
 void *Temp;

    Temp = (void *) malloc(Size);
    if (Temp == NULL) {
       fputs("Error: Not enough memory.",stderr);
       exit(2);
    }
    return(Temp);
 }

 void *CallocT(unsigned NElem,unsigned Size)
 /* Calls calloc() to allocate a block of memory for NElem elements of size
    Size and checks whether there was enough memory. Exits if not, otherwise
    returns a pointer to the block */
 {
 void *Temp;

    Temp = (void *) calloc(NElem,Size);
    if (Temp == NULL) {
       fputs("Error: Not enough memory.",stderr);
       exit(2);
    }
    return(Temp);
 }

 void *ReallocT(void *Ptr,unsigned Size)
 /* Calls Realloc() to reallocate the block pointed to by Ptr to size Size
    and checks whether there was enough memory. Exits if not, otherwise
    returns a pointer to the block */
 {
 void *Temp;

    Temp = (void *) realloc(Ptr,Size);
    if (Temp == NULL) {
       fputs("Error: Not enough memory.",stderr);
       exit(2);
    }
    return(Temp);
 }



 DIPRINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DI\DIPRINT.C

 #include <stdio.h>
 #include <dir.h>
 #include <dos.h>
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
 #include <io.h>
 #include "di.h"
 long FreeSpace(int Drive);
 long SpaceUsed(Entry *Entries,int Num,int Drive);
 char *Label(int Drive);
 char *AddCommasL(long N);
 char *FileDate(int PDate);
 char *FileTime(int PTime);
 void PrintFull(Entry *Entries,int Num,char *Dir);
 void PrintLong(Entry *Entries,int Num);
 void PrintShort(Entry *Entries,int Num,int LineEnts);
 void FiltAttribs(int *OldAtts,int *NewAtts,int Att);
 AUSize(int Drive);
 MatchingAtts(int Attribs[],char Attrib);

 void PrintHeader(NameNode *Files,int PrintFree)
 /* Prints the volume label and, if PrintFree is true, the free space for all
    drives specified in the filespecs in Files, including the default drive if
    indicated by any filespec. */
 {
 int Drives[26],        /* One entry for each drive, indicating whether it sho
                    printed */
 Drive,        /* Specific or default drive specified in current filespec */
 CurDrive,        /* Default drive */
 I;
 char *Volume;        /* Volume label of a drive */

    CurDrive = getdisk();        /* Get default drive in case it is specified
    for (I = 0; I <= 25; I++)        /* Initialize array to no drives speced *
       Drives[I] = FALSE;
    while (Files != NULL) {        /* For each filespec */
       if (strchr(Files -> Name,':') == NULL)        /* If no drive speced, us
                                                          default drive */
          Drives[CurDrive] = TRUE;
       else {
          Drive = Files -> Name[0] - 'A';        /* Get drive number */
          if (0 <= Drive && Drive <= 25)        /* Make sure it is a letter */
             Drives[Drive] = TRUE;
       }
       Files = Files -> Next;
    }
    putchar('\n');        /* Put a blank line between program invokation and
                               first line of listing */
    for (I = 0; I <= 25; I++)        /* For each possible drive */
       if (Drives[I]) {        /* If drive was specified in any filespec */
          Volume = Label(I);        /* Get volume label */
          if (Volume == NULL)
             printf("Volume in drive %c has no label",I + 'A');
          else
             printf("Volume in drive %c is %s",I + 'A',Volume);
          if (PrintFree)        /* If PrintFree is true, print free space */
             printf("  : %s bytes free",AddCommasL(FreeSpace(I)));
          puts(".");
          More(1);
       }
 }

 int AUSize(int Drive)
 /* Returns the size of the allocation units on drive Drive, in bytes. */
 {
    struct fatinfo FatInfo;        /* Struct used by getfat() */
    getfat(Drive + 1,&FatInfo);
    /* Size of allocation units = # of sectors per cluster * bytes per sector
    return(FatInfo.fi_sclus * FatInfo.fi_bysec);
 }

 long SpaceUsed(Entry *Entries,int Num,int Drive)
 /* Returns the actual amount of space used by all of the files in Entries,
    assuming that they are on drive Drive */
 {
    int AU;        /* Size of allocation units on drive Drive */
    int I;
    long TotalSpace = 0L;        /* Total space used by the files */

    AU = AUSize(Drive);        /* Find size of alloc units */
    for (I = 0; I < Num; I++)        /* For each file, add the space it uses *
       TotalSpace += (Entries[I] -> ff_fsize + AU - 1) / AU * AU;
    return(TotalSpace);
 }

 char *AddCommasL(long N)
 /* Converts long integer N to a string, stores it in a static buffer,
    inserts commas where appropriate, and returns a pointer to the bufffer */
 {
 static char Buf[15];        /* Buffer */
 int Pos,        /* Current position that comma is being inserted at */
 Num,                /* Number of commas to insert */
 I;

    Pos = sprintf(Buf,"%ld",N);        /* Convert N to a string and put the le
                                       the string in Pos */
    Num = ((Buf[0] == '-' ? Pos - 1 : Pos) - 1) / 3;        /* Find num of com
                                                               to insert */
    for (I = 0; I < Num; I++) {
       Pos -= 3;                /* Find next location at which to insert comma
       Insert(Buf,",",Pos);
    }
    return(Buf);
 }

 long FreeSpace(int Drive)
 /* Returns the free space on drive Drive */
 {
 struct dfree DFree;        /* Structure used by getdfree */

    getdfree(Drive + 1,&DFree);        /* Get available clusters, sectors/clus
                                       and bytes/sector */
    ExTest(DFree.df_sclus == -1,"Disk error.");        /* Exit if error */
    return((long) DFree.df_avail * DFree.df_bsec * (long) DFree.df_sclus);
 }

 char *Label(int Drive)
 /* if drive Drive (0 = A, 1 = B, etc) has a label, it is put in a static
    buffer and a pointer to the buffer is returned. Otherwise a null
    pointer is returned */
 {
 static char *FileSpec = " :\\*.*",        /* Filespec that will by used to
                                 find label, with room for drive letter */
 Volume[13];        /* Buffer */
 struct ffblk FFBlk;        /* Structure used by findfirst() */
 char *Dot;        /* Start of file ext in volume label */

    FileSpec[0] = Drive + 'A';        /* Add drive letter to filespec */
    if (findfirst(FileSpec,&FFBlk,FA_LABEL))        /* Get label */
       return(NULL);        /* if no label, return null */
    else {
       strcpy(Volume,FFBlk.ff_name);        /* Copy label to volume */
       Dot = strchr(Volume,'.');
       if (Dot != NULL)        /* If volume had a dot in it, remove it */
          strcpy(Dot,Dot - Volume + FFBlk.ff_name + 1);
       return(Volume);
    }
 }

 void GetEntries(EntryListType *EntryList,int Attribs[],char Name[],int PrintC
 /* calloc() is used to make an array of pointers to the structure returned by
    findfirst/next.  The array is expanded with realloc() as neccessary.
    Elements of the array are made to point to matching directory entries.
    A dir entry will match if its name matches Name and its attribs match at
    least one of the attrib and-terms in Attribs.  "." and ".." dir entries wi
    match only attrib specs that specifically include dirs, and only if PrintC
    is true.  The entry list and number of matching entries found are returned
    in EntryList. */
 {
 int Done,        /* Whether all matching files have been found */
 NumEnts,        /* Number of matching entries found */
 DirAttribs[MAX_ATTS];        /* Attribute list containing those attrib terms
                            Attribs that specifically include directories */
 unsigned Length;        /* Current length that the entry array has been
                            c/realloc()ed to */
 Entry *Entries;                /* Entry array */

    if (PrintCP)
       FiltAttribs(Attribs,DirAttribs,FA_DIREC);        /* Copy all entries in
                            that specifically include dirs into DirAttribs */
    else
       *DirAttribs = NO_AT;
    Length = ENTRY_INC;        /* Do initial allocation for Entries */
    Entries = (Entry *) CallocT(Length,sizeof(Entry));
    NumEnts = 0;                /* No entries found yet */
    Entries[0] = (Entry) MallocT(sizeof(struct ffblk));        /* Start with o
                                                            empty entry */
    Done = findfirst(Name,Entries[0],0x3f);
    while (!Done) {  /* For each entry in specified dir that matches Name */
      if (MatchingAtts(CPDir(Entries[NumEnts] -> ff_name) ?
       DirAttribs : Attribs,Entries[NumEnts] -> ff_attrib)) { /* Check whether
        the attribs of the found entry match any of those in Attribs if the
        found entry is not the current or parent dir ("." or ".."), or in
        DirAttribs if it is one of them.  The current or parent dir will
        therefore only be printed if directories have specifically been
        requested */
         if (NumEnts == Length - 1) {  /* Reallocate Entries with more space *
            Length += ENTRY_INC;
            Entries = (Entry *) ReallocT(Entries,Length * sizeof(Entry));
         }
         Entries[++NumEnts] = (Entry) MallocT(sizeof(struct ffblk));  /* Add
                                                         new empty node */
         *(Entries[NumEnts]) = *(Entries[NumEnts - 1]); /* copy last matching
                         entry to new node for next call to findnext() */
       }
       Done = findnext(Entries[NumEnts]);         /* Get next matching entry *
    }
    free(Entries[NumEnts]);        /* Get rid of last node added, since it is
                                       one that findnext() failed on */
    EntryList -> NumEnts = NumEnts;        /* Copy array & num of entries to
                                               EntryList */
    EntryList -> Entries = Entries;
 }

 void FiltAttribs(int OldAtts[],int NewAtts[],int Att)
 /* Copies all attributes in OldAtts that have at least one of the attribs
    indicated in Att, or that have no attribs (= 0) to NewAtts */
 {
 int I,
 NumAtts;        /* Number of matching attrib terms found */

    NumAtts = I = 0;
    while (OldAtts[I] != NO_AT) {
       if (OldAtts[I] & Att || OldAtts[I] == 0)
          NewAtts[NumAtts++] = OldAtts[I];
       I++;
    }
    NewAtts[NumAtts] = NO_AT;        /* Mark end of array */
 }

 void PrintList(EntryListType *EntryList, /* Entry list and length of list */
  ListType *ListSpec, /* Specifies what type of listing to do */
  char *Dir /* Name of path that list was produced from */)
 /* Print list of dir entries according to ListSpec */
 {
 int J,
 NumEnts;        /* Number of entries in list */
 Entry *Entries;        /* Entry list */

    Entries = EntryList -> Entries;
    NumEnts = EntryList -> NumEnts;
    if (ListSpec -> ListType != 'F' && ListSpec -> PrintHeaders) {
       /* If list type is not "full path" and headers are to be printed...*/
       printf("Directory of %s  : %d matching file(s)",Dir,NumEnts);
       if (ListSpec -> PrintFree)        /* Print total space used by files */
          printf(" using %ldk",
           (SpaceUsed(Entries,NumEnts,(int) *Dir - 'A') + 1023) >> 10);
       puts(".\n");
       More(2);
    }
    if (NumEnts) {        /* If at least one matching entry for dir */
       switch (ListSpec -> ListType) {
          case 'W' : PrintShort(Entries,NumEnts,ListSpec -> LineEnts);
                     break;
          case 'L' : PrintLong(Entries,NumEnts);
                     break;
          case 'F' : PrintFull(Entries,NumEnts,Dir);
       }
       for (J = 0; J < NumEnts; J++) /* Free entry nodes pointed to by array *
          free(Entries[J]);
    }
    free(Entries);        /* Free array */
 }

 MatchingAtts(int Attribs[],char Attrib)
 /* Returns true if Attrib matches any of the attrib and-terms in Attribs;
    otherwise returns false.  Attrib will match a term if it has all of the
    attributes specified in the low byte of the term and none of the attribs
    specified in the high byte of the term */
 {
 int I,
 FullAtt;        /* Full attribute */

    FullAtt = Attrib | (~((int) Attrib) << 8);        /* Produce full attrib b
     copying Attrib in true form into the low byte and complemented form
     into the high byte. */
    I = 0;
    while (Attribs[I] != NO_AT && (Attribs[I] & FullAtt) != Attribs[I])
     /* Check whether Attrib matches any of the attribute terms given in
        Attribs. To check for match, FullAtt is first ANDed with an attrib
        term.  Since Attrib is true in the low byte of FullAtt, all attrib
        bits that Attrib has and are specified in lo byte of the term (attribs
        that Attrib must have to match) will be on in the low byte of the
        result.  Since Attrib is complemented in the high
        byte of FullAtt, all attrib bits that Attrib does not have and are
        specified in the high byte of the term (attribs that Attrib cannot
        have if it is to match) will be on in the high byte of the result.
        In order to match, the result must therefor be equal to the term. */
       I++;
    return(Attribs[I] != NO_AT);
 }

 void PrintShort(Entry *Entries,int Num,int LineEnts)
 /* Prints a 'short' listing of the entries in Entries.  Prints the file names
    only, with LineEnts names on each line.  A backslash is appended to
    directory entries. Num is the number of entries in Entries */
 {
 int I,
 Width,                /* Width to print each name with (padding with blanks)
 NotEven;        /* Whether the entries will exactly fit on a line */
 char *Name,        /* Points to the name being printed (either the original
                     list entry or a copy of it with a backslash appended) */
 Dir[14];        /* Copy of the file name, with a backslash appended to
                    indicate that it is a directory */

    Width = 80 / LineEnts;        /* Find width to print each name with */
    NotEven = 80 % LineEnts;        /* Determine whether LineEnts names will
                                    exactly fit on a line */
    for (I = 0; I < Num; I++) {        /* For each entry */
       if (Entries[I] -> ff_attrib & FA_DIREC) {        /* If the entry is a d
        a copy of it, append a backslash to it, & make Name point to the copy
          strcpy(Dir,Entries[I] -> ff_name);
          strcat(Dir,"\\");
          Name = Dir;
       }
       else        /* Otherwise make Name point to the original name */
          Name = Entries[I] -> ff_name;
       printf("%-*s",Width,Name);        /* Print the name */
       if ((I + 1) % LineEnts == 0) {        /* If it was the last name on a l
          if (NotEven)        /* If LineEnts entries do not exactly fit on a l
           the cursor will not have automatically wrapped around to the next
           line; print a newline */
             putchar('\n');
          More(1);
       }
    }
    if (I % LineEnts) {        /* If the last name printed was not the last on
                            a line and therefore did not cause a CR, print one
       putchar('\n');
       More(1);
    }
 }

 void PrintLong(Entry *Entries,int Num)
 /* Print a 'long' dir listing. Prints each file's name, ext, size, time, date
    and attributes.  Dirs and the volume label report a size of 0, so they are
    printed with a special label in the size column.  The list is modified. */
 {
 int I;
 Entry File;        /* Entry being printed */
 char Size[12],        /* File size converted to a string, or a special label
                    dirs and the volume label */
 *Ext;                /* Start of the extension of the file name */

    for (I = 0; I < Num; I++) {
       File = Entries[I];
       if (File -> ff_attrib & FA_DIREC)        /* If entry is a dir or the vo
                                         give it a label instead of a file siz
          strcpy(Size,"<DIR>  ");
       else if (File -> ff_attrib & FA_LABEL)
          strcpy(Size,"<LAB>  ");
       else
          sprintf(Size,"%ld",File -> ff_fsize);
       Ext = strchr(File -> ff_name,'.');        /* Find the start of the ext
                                                          of the file name */
       if (Ext == NULL || CPDir(File -> ff_name))        /* If there is no ext
        or the first dot in the entry for the current or parent dir was found,
        make Ext point to a null string */
          Ext = "";
       else {
          *Ext = '\0';        /* Otherwise make Ext point to the start of the
           ext and replace the dot with a null char so that when the file name
           is printed it will not include the file ext */
          Ext++;
       }
       printf("%-9s%-3s%9s%10s%8s   %-6s\n",File -> ff_name,Ext,Size,
        FileDate(File -> ff_fdate),FileTime(File -> ff_ftime),
        AttribWtoS(File -> ff_attrib));
       More(1);
    }
 }

 char *FileDate(int PDate)
 /* Converts the file date word PDate into a string of the form mm-dd-yy,
    puts it in a static buffer and returns a pointer to the buffer */
 {
 static char Date[9];

    sprintf(Date,"%2u-%02u-%02u",(PDate >> 5) & 0xf,PDate & 0x1f,
     ((PDate >> 9) & 0x7f) + 80);
    return(Date);
 }

 char *FileTime(int PTime)
 /* Converts the file time word PTime to a string of the form HH:MMm, where m
    is 'a' for AM and 'p' for PM, puts it in a static buffer, and returns a
    pointer to the buffer */
 {
 static char Time[7];
 int NHour;        /* File hour in 12-hour format */

    NHour = ((PTime >> 11) & 0x1f) % 12;
    if (NHour == 0)
       NHour = 12;
    sprintf(Time,"%2u:%02u%c",NHour,(PTime >> 5) & 0x3f,
     ((PTime >> 11) & 0x1f) > 11 ? 'p' : 'a');
    return(Time);
 }

 void PrintFull(Entry *Entries,int Num,char *Dir)
 /* Print 'Full Path' listing of the file names in Entries.  The entries in
    Entries are assumed to have been produced from the path given in Dir.
    Dir is copied, and the filename is removed from it.  For each file name in
    Entries, prints the file's size, time, date, and attributes; then Dir is
    printed followed by the filename.  If the entry is a dir, a backslash is
    printed at the end.
    Dirs and the volume label report a size of 0, so they are printed with a
    special label in the size column.
    The list is modified. Num is the # of entries in Entries. */
 {
 char Name[MAXPATH];        /* Full path name of the file name */
 int I;
 Entry File;        /* Entry being printed */
 char Size[12];        /* File size converted to a string, or a special label
                    dirs and the volume label */

    strcpy(Name,Dir);
    *(strrchr(Name,'\\') + 1) = '\0';        /* Remove the file name from Dir
    for (I = 0; I < Num; I++) {
       File = Entries[I];
       if (File -> ff_attrib & FA_DIREC)        /* If entry is a dir or the vo
                                         give it a label instead of a file siz
          strcpy(Size,"<DIR>  ");
       else if (File -> ff_attrib & FA_LABEL)
          strcpy(Size,"<LAB>  ");
       else
          sprintf(Size,"%ld",File -> ff_fsize);
       /* If the entry is a directory, follow it with a backslash */
       printf("%9s%10s%8s  %-6s%s%s%s\n",Size,FileDate(File -> ff_fdate),
        FileTime(File -> ff_ftime),AttribWtoS(File -> ff_attrib),Name,
        File -> ff_name,File -> ff_attrib & FA_DIREC ? "\\" : "");
       More(1);
    }
 }

 void SortList(EntryListType *EntryList,char Sort)
 /* Sorts EntryList according the sort specification Sort.  Any groups of
    entries that are not differentiated by the first sort are then sorted
    by name. The sort specs are:
      X = alpha by file eXtension; T = by Time & date, oldest to newest;
      Z = by file siZe, smallest to largest; I = by directory attribute,
      dirs first, then other files; N = sort by Name only;   */
 {
 int Num,        /* Number of entries */
 Start,                /* Start of a group of undifferentiated entries */
 I;
 Entry *List;        /* List to sort */
 int (*CompFunc)(Entry *E1,Entry *E2), /* Comparison func to be used in sort *
  ExtComp(Entry *E1,Entry *E2),TDComp(Entry *E1,Entry *E2),
  SizeComp(Entry *E1,Entry *E2),DAComp(Entry *E1,Entry *E2),
  NameComp(Entry *E1,Entry *E2);  /* Comparison functions */

    Num = EntryList -> NumEnts;
    List = EntryList -> Entries;
    if (Sort != 'N') {        /* Do a first sort */
       switch (Sort) {        /* Select sort function */
          case 'X' :        CompFunc = ExtComp;
                           break;
          case 'T' :        CompFunc = TDComp;
                           break;
          case 'Z' :        CompFunc = SizeComp;
                           break;
          case 'I' :        CompFunc = DAComp;
       }
       qsort(List,Num,sizeof(Entry),CompFunc);        /* Do first sort */
    }
    Start = 0;        /* Intialize undiffentiated entries start to 0 */
    for (I = 1; I < Num; I++)
       if ((*CompFunc)(&List[I - 1],&List[I])) {        /* If comp func differ
                                             current entry from the previous o
          if (I - Start > 1) /* If more than one entry was passed before
           differentiation was found, sort undifferentiated entries by name */
             qsort(List + Start,I - Start,sizeof(Entry),NameComp);
          Start = I;        /* Make start of undiff ents be current ent */
       }
    if (I - Start > 1)        /* If the last entry was the last of a group of
                             undiffed entries, sort them */
       qsort(List + Start,I - Start,sizeof(Entry),NameComp);
 }

 DAComp(Entry *E1,Entry *E2)
 /* Compares file dir attribs.  Returns a negative int if E1 is a dir and
    E2 is not; 0 if they both are or are not, and a positive int if E2 is
    and E1 is not */
 {
    return(((*E2) -> ff_attrib & FA_DIREC) - ((*E1) -> ff_attrib & FA_DIREC));
 }

 NameComp(Entry *E1,Entry *E2)
 /* Compares the names of E1 and E2.  Returns a neg int, zero, or a pos int if
    the name of E1 is lexicographically less than, equal to, or greater than
    the name of E2.  Since strings are terminated with a null (lex value 0),
    a file name will be less than the same initial name with extra characters,
    including an ext. Because '.' has a value less than any letter, a file nam
    with an extension will be less than a file name with the same initial name
    but other extra chars instead of an ext. */
 {
    return(strcmp((*E1) -> ff_name,(*E2) -> ff_name));
 }

 ExtComp(Entry *E1,Entry *E2)
 /* Compares file names by their extension.  Returns a neg int, zero, or a
    pos int if the ext of E1 is lexicographically less than, equal to, or
    greater than the ext of E2.  A file name without an ext will be less than
    a file name with one. */
 {
 char *Ext1,*Ext2;        /* Exts of the files, or null strings if they did
                            not have exts */

    Ext1 = strchr((*E1) -> ff_name,'.');
    if (Ext1 == NULL)
       Ext1 = "";
    Ext2 = strchr((*E2) -> ff_name,'.');
    if (Ext2 == NULL)
       Ext2 = "";
    return(strcmp(Ext1,Ext2));
 }

 TDComp(Entry *E1,Entry *E2)
 /* Compares the time and date of E1 and E2.  Returns -1, 0, or +1 if the
    file date if E1 is earlier than, the same as, or later than the file
    date of E2 */
 {
    return(Sign((((long) ((*E1) -> ff_fdate) << 16) + (*E1) -> ff_ftime) -
           (((long) ((*E2) -> ff_fdate) << 16) + (*E2) -> ff_ftime)));
 }

 SizeComp(Entry *E1,Entry *E2)
 /* Compares the size fo E1 and E2.  Returns -1, 0, or +1 if E1 is smaller
    than, the same size as, or larger than E2 */
 {
    return(Sign((*E1) -> ff_fsize - (*E2) -> ff_fsize));
 }



 DISETUP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DI\DISETUP.C

 #include <stdio.h>
 #include <dir.h>
 #include <dos.h>
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
 #include "di.h"
 char *Tokenize(char S[],char SepChar);
 char *NextMatchFile(char FileSpec[],int Attributes);
 NameNode *LastElem(NameNode *List);
 NameNode *GetMatchFiles(char *Path,int Attribs);
 NameNode *ExpandPath(char Path[]);
 NameNode *CreateNameList(void);
 NameNode *CatNameLists(NameNode *Target,NameNode *Source);
 void AddFileWC(char File[]);
 void AddNode(NameNode *Node);
 void InsertList(NameNode *Target,NameNode *Source);
 void AddCDirs(NameNode *List);
 void AddAllWC(char Path[]);
 void FirstWild(char Path[],char *Head,char *WildSpec,char *Tail);
 void AddString(NameNode *List,char *S);
 void DeleteNext(NameNode *List);
 void FreeList(NameNode *List);
 void MakePathsFull(NameNode **List);
 void AddFlag(char *Flag,int *Attribute,ListType *ListSpec);
 FlagErr(int ErrWord);
 GetFullPath(char *Path);
 NullPath(char *Path);
 IsRoot(char *Dir);
 GetFullDir(char *Path);
 IsDir(char *Path);
 FindInt(int Arr[],int Targ);

 void GetArgs(int argc,char *argv[],int Attribs[],ListType *ListSpec,
  NameNode **Files)
 /* Converts an argument list to an array of search attribs (Attribs),
    a list of filespecs (Files), and a set of listing type specifications
    (ListSpec).        If any attrib flags are given, the previous values in
    Attribs are erased.        If any filespecs are given, the previous Files
    list is replaced & freed. */
 {
 int I,
 Attrib,         /* Search attributes given by one argument */
 NumAtts,        /* Number of attribute groups found */
 FileSpecGiven,        /* Whether any argument was a filespec */
 OldNum;         /* Number of attributes previously given in array */
 NameNode *PathList,        /* List of paths produced by expanding the wildcar
                            in a filespec arg */
 *List,                /* List of paths produced from filespec args */
 *CurFile;        /* Current end of the path list */

    List = CurFile = CreateNameList();        /* Initially set List and CurFil
                                            point to an empty node */
    OldNum = FindInt(Attribs,NO_AT);        /* Find number of attribs previous
                                            in Attribs */
    NumAtts = 0;         /* Initialize current number of attribs to 0 */
    FileSpecGiven = FALSE;
    for (I = 1; I < argc; I++) {         /* For each argument */
       if (strchr(FLAGSPECS,argv[I][0]) != NULL) { /* If arg is a flag group *
          AddFlag(argv[I],&Attrib,ListSpec);        /* Interpret flag
                                                 group and set variables */
          if (Attrib != NO_AT) {         /* If group contained attributes */
             ExTest(NumAtts == MAX_ATTS - 1,"Too many attribute groups.");
             Attribs[NumAtts++] = Attrib; /* Add attrib and-term to Attribs */
          }
       }
       else {
          FileSpecGiven = TRUE;
          PathList = ExpandPath(argv[I]);        /* Expand wildcards in arg */
          if (PathList == NULL)
             fprintf(stderr,"Invalid directory in path \"%s\".\n",argv[I]);
          else
             CurFile = CatNameLists(CurFile,PathList);        /* Add all paths
                         indicated by the arg to the total paths list */
       }
    }
    CurFile = List;                /* Get rid of initial empty node */
    List = List -> Next;
    free(CurFile);
    if (FileSpecGiven) {         /* If filespecs found, replace original path
                                    list with new list */
       FreeList(*Files);
       *Files = List;
    }
    if (ListSpec -> RecSearch)        /* If recursive search flag was given, f
     all subdirs of the lowest-level dir given in each path and add them to
     the list, with each added path having the file name of the path it was
     derived from */
       AddCDirs(*Files);
    if (NumAtts == 0)        /* If no attrib flags were given, attrib array is
                            unchanged; set num of attribs to original num */
       NumAtts = OldNum;
    Attribs[NumAtts] = NO_AT;        /* Mark end of attrib array */
 }

 void AddFlag(char *Flag,int *Attribute,ListType *ListSpec)
 /* Sets Attribute, ListSpec, and More() according to the flags in
    Flag.  If Flag contains any attribute flags, they are combined to produce
    attribute and-term Attribute.  Lower case attrib flags are interpreted
    as 'true' (a file must have that attribute to match) and the corresponding
    bit (as indicated by the FA_* constants) in the low byte of Attribute is
    set.  Upper case flags are interpreted as 'false' (a file can not have
    that attrib to match) and the corresponding bit in the high byte of
    Attribute is set.  The 'e' flag (everything) sets Attribute to 0. An error
    message is printed if both a true and a false flag are given in the same
    and-term.
    The value of RecSearch and the status of More() are toggled if their
    corresponding flags are found.  The list specs ListType, Sort, and
    LineEnts take on the value of the last flag that applies to them.
    No error message is printed if more than one flag for one of them is
    found while the env var and command line args are being read, so that
    a command line flag can override an env var flag without a message.
    If an illegal flag is given, an error message is printed. */
 {
 static char FlagDesc[] =        /* Printed if any illegal flags were given */
 "     DI: Directory Listing Utility   by  John H. DuBois III        v1.1\n"
 "Flags are:   Pause during listing;  list Long, Wide, or with Full path;\n"
 "print 1-6 entries / line if listing wide;  search directories reCursively;\n
 "sort first by dIr attrib, eXtension, Time and date, siZe, or Name only;\n"
 "Kill headers;        print Unused (free) space on device in main header;\n"
 "print files with attribs: Everything (print all files), or\n"
 "Read only, Hidden, System, Directory, Volume label, Archive.\n";

 int I,
 Attrib,         /* Attrib that one flag translated to */
 AttGiven,        /* Whether any attributes were given in the flag list */
 BadFlag;        /* Whether any illegal flags were found in the flag list */
 char F;         /* Upper case version of flag being interpreted */

    *Attribute = 0;        /* Initialize to no attributes */
    AttGiven = BadFlag = FALSE;
    if (Flag[1] == '\0') /* If arg started with a flag specifier but no flags
                            were given */
       fputs("Empty flag.",stderr);
    else
       for (I = 1; Flag[I] != '\0'; I++) {        /* For each flag */
          F = UpCase(Flag[I]);
          Attrib = NO_AT;        /* Initially set Attrib to a value that no
           attribute term can have, so that it can be determined if Attrib was
           set by a flag */
          switch(F) {
             case 'F' :
             case 'L' :
             case 'W' :        ListSpec -> ListType = F; break;
             case 'X' :
             case 'Z' :
             case 'N' :
             case 'I' :
             case 'T' :        ListSpec -> Sort = F; break;
             case '1' :
             case '2' :
             case '3' :
             case '4' :
             case '5' :
             case '6' :        ListSpec -> LineEnts = F - '0'; break;
             case 'P' :        More(More(-2)); break;
             case 'U' :        ListSpec -> PrintFree = !ListSpec -> PrintFree;
             case 'K' :        ListSpec -> PrintHeaders = !ListSpec -> PrintHe
                            break;
             case 'C' :        ListSpec -> RecSearch = !ListSpec -> RecSearch;
             case 'R' :        Attrib = FA_RDONLY;  break;
             case 'H' :        Attrib = FA_HIDDEN;  break;
             case 'S' :        Attrib = FA_SYSTEM;  break;
             case 'V' :        Attrib = FA_LABEL;   break;
             case 'D' :        Attrib = FA_DIREC;   break;
             case 'A' :        Attrib = FA_ARCH;    break;
             case 'E' :        Attrib = 0;             break;
             default :        fprintf(stderr,"Bad flag: %c\n",Flag[I]);
                         BadFlag = TRUE;
          }
          if (Attrib != NO_AT) { /* Flag list contained attribute flags */
             AttGiven = TRUE;
             if (islower(Flag[I])) {        /* 'true' flag was given. Check
              whether the corresponding 'false' flag has already been set */
                if (!FlagErr((*Attribute >> 8) & Attrib))
                   *Attribute |= Attrib; /* Set the correct bit in lo byte */
             }
             else        /* 'false' flag was given. Check whether the
              corresponding 'true' flag has already been set */
                if (!FlagErr(*Attribute & Attrib))
                   *Attribute |= Attrib << 8;        /* Set the bit in hi byte
          }
       }
    if (!AttGiven)        /* If no attrib flags found, indicate this */
       *Attribute = NO_AT;
    if (BadFlag) /* If any bad flags were found, print list of valid flags */
       fputs(FlagDesc,stderr);
 }

 FlagErr(int ErrWord)
 /* ErrWord is produced by ANDing the one-byte version of an attrib with
    a word containing previously given attribs, with the inverse byte
    shifted to the low byte.  If an attribute flag with the opposite
    value has already been read, the corresponding bit in ErrWord will
    be set.  If any bits in ErrWord are set, an error message and the flag
    are printed and TRUE is returned;  otherwise FALSE is returned */
 {

    if (ErrWord != 0) {
       fprintf(stderr,"Conflicting attribute flag: %s\n",
        AttribWtoS((char) ErrWord));
       return(TRUE);
    }
    else
       return(FALSE);
 }

 GetEnvParams(int *Cnt,char *Vars[],char *Name)
 /* Convert the value of environment var Name to a list of parameters with
    the same format as argv and argc.  Parameters in the var are separated
    by spaces and tabs. A copy of the var value is made with
    strdup(); the space after each param is converted to a null char; and a
    pointer to the start of each param is put in Vars. The first element in
    Vars is set to point to the start of the copied string so it can be freed.
    Cnt is set to the number of args found + 1.        If the var is not found
    the environment, Cnt is set to 0 and FALSE is returned; otherwise TRUE is
    returned.
 */
 {
 char *Envar,        /* Found environment var */
 *Value;         /* Copied env var */
 int Num;        /* Number of args found so far + 1 */

    *Cnt = Num = 0;
    if ((Envar = getenv(Name)) == NULL)        /* Get env var */
       return(FALSE);        /* If not found return FALSE */
    else {
       Value = strdup(Envar);        /* Copy env var value */
       Vars[0] = Value;        /* Make first pointer point to string */
       Num = 1;        /* Start with 1 to account for pointer set to Value */
       Vars[1] = strtok(Value," \t");        /* Tokenize Value and put
                                            pointers in Vars */
       while (Vars[Num] != NULL)
          Vars[++Num] = strtok(NULL," ");
       *Cnt = Num;
       return(TRUE);
    }
 }

 NameNode *ExpandPath(char Path[])
 {
 NameNode *List, /* Start of the filespec list */
  *Temp,         /* A node that is to be freed */
  *Last,         /* End of the filespec list */
  *NewDirs;        /* The directory list that a wildcard dir spec expanded to
 char Head[MAXPATH],        /* The portion of the path before the first compon
                            containing wildcards */
 Wild[MAXPATH],        /* The first component of the path containing wildcards
 Tail[MAXPATH],        /* The portion of the path after the first component co
                    wildcards */
 Dir[MAXPATH];        /* The current wildcard dir spec being expanded */

    Last = List = CreateNameList();        /* Initialize List with an empty no
                                            and make Last be the same node */
    strupr(Path);        /* Convert Path to all upper case */
    strcpy(List -> Name,Path);        /* Copy Path to the first node in the li
    AddAllWC(List -> Name);        /* Expand all implicit wildcard in the path
    FirstWild(List -> Name,Head,Wild,Tail);        /* Find the first wildcard
     specification in the path that must be expanded to a list of directories
    while (Tail[0] != '\0') {        /* As long as Tail is not a null string,
     will contain the last component of the path (the file name).  Path
     expansion should stop when the file name is reached since only the dir
     wildcards are to be expanded.  Because all final paths will have the same
     number of dirs expanded from wildcards in the path, as soon as one
     completely expanded path is found all paths will have been completely
     expanded */
       strcpy(Dir,Head); /* Make Dir consist of the Head (which will contain n
        wildcards) as dir path and Wild as the filename */
       strcat(Dir,Wild);
       NewDirs = GetMatchFiles(Dir,FA_REALDIR);        /* Get the full paths o
                                                    dir names that match Dir *
       AddString(NewDirs,Tail);        /* Add the unexpanded portion of the pa
                                    all dirs found */
       Last = CatNameLists(Last,NewDirs);        /* Add the new dirs found to
                                                    the end of the dir list */
       Temp = List;        /* Get rid of the first element of the list (the di
                            that has been expanded */
       List = List -> Next;
       free(Temp);
       FirstWild(List -> Name,Head,Wild,Tail);        /* Split up the next pat
                                                    the list */
    }
    MakePathsFull(&List);        /* Convert relative paths to full path names
                                    and get rid of invalid paths */
    return(List);
 }

 void AddCDirs(NameNode *List)
 /* Adds child dirs to List with the same file name.  The name of each path in
    List is split into directory and filename.  All subdirs of each dir are
    found and inserted in the list immediately after the parent dir, with
    the file name from the original path appended to them.  The same proceedur
    is performed on each new dir found, so that at the end all decendant dirs
    of the dir in the original path will have been added to the list with the
    original file name appended. */
 {
 char Dir[MAXPATH],        /* The path being searched for subdirs, with the
                            original filename replaced by "*.*" */
 *NameStrt,                /* Start of the filename of the path */
 Name[13];                /* The original filename of the path */
 NameNode *SubList;        /* List of subdirs found */

    Name[13] = '\0';        /* If a file name was more than 12 chars, it will
                         truncated.  Ensures that it will be null terninated *
    while (List != NULL) {
       strcpy(Dir,List -> Name);         /* Copy path so it can be altered */
       NameStrt = strrchr(Dir,'\\');        /* Find start of file name */
       strncpy(Name,NameStrt,12);        /* Save original file name */
       strcpy(NameStrt + 1,"*.*");        /* Replace it in path with "*.*"
                                            so all subdirs will be found */
       SubList = GetMatchFiles(Dir,FA_REALDIR);        /* Find subdirs, but no
                                                    "." and ".." entries */
       AddString(SubList,Name);        /* Add orig file name to all subdirs fo
       InsertList(List,SubList); /* Insert list of child dirs immediately afte
         parent dir, so they will be the next to be searched for child dirs */
       List = List -> Next;
    }
 }

 NameNode *GetMatchFiles(char *Path,int Attribs)
 /* Finds & makes a list of all files that match Path and Attribs. Returns a
    pointer to the list */
 {
 NameNode *Temp, /* End of the list of matching files */
 *List;        /* List of matching files */
 char *File;        /* The name of a matching file */

    Temp = List = CreateNameList();        /* Initialize Temp and List to an
                                            empty node */
    File = NextMatchFile(Path,Attribs);        /* Get the first matching file
    while (File != NULL) {        /* Do until no more matching files */
       AddNode(Temp);                /* Add a new empty node to the list */
       Temp = Temp -> Next;        /* Move Temp to point to it */
       strcpy(Temp -> Name,File);        /* Copy the name of the matching file
                                            to the new node */
       File = NextMatchFile(NULL,0);        /* Get next matching file */
    }
    Temp = List;         /* Get rid of the first empty node */
    List = List -> Next;
    free(Temp);
    return(List);
 }

 NameNode *CreateNameList()
 /* Creates a new NameNode, sets its Next pointer to NULL, and returns
    a pointer to it */
 {
 NameNode *Temp;

    Temp = (NameNode *) MallocT(sizeof(NameNode));
    Temp -> Next = NULL;
    return(Temp);
 }

 FindInt(int Arr[],int Targ)
 /* Searches array Arr for Targ & returns its index */
 {
 int I;

    for (I = 0; Arr[I] != Targ; I++) ;
    return(I);
 }

 void FreeList(NameNode *List)
 /* Frees all of the nodes in List */
 {
 NameNode *Temp;

    while (List != NULL) {
       Temp = List;
       List = List -> Next;
       free(Temp);
    }
 }

 void AddAllWC(char Path[])
 /* Converts all implicit wildcards in Path, except for those in the last
    file name given, to explicit wildcards.  A filename
    is assumed to exist between every two backslashes and after the last
    backslash.  If Path contains no backslashes, it is assumed to be one
    filename.  */
 {
 char NewPath[MAXPATH],        /* The new path as it is being created from Pat
 *FSpec,         /* The file name being converted */
 Temp[12];
 int NameStart;

    strcpy(NewPath,Path);        /* Copy Path to NewPath so that possible
                         drive spec and leading backslash will be in NewPath *
    if (Path[0] != '\0' && Path[1] == ':')        /* Find the first file name
     in Path (at index 0 or 2, depending on whether a drive was specified */
       NameStart = 2;
    else
       NameStart = 0;
    FSpec = Tokenize(Path + NameStart,'\\');        /* Find the first filename
                                                    Path */
    if (NewPath[NameStart] == '\\') {        /* If Path began with a backslash
     first name returned by Tokenize will by the null string that preceded the
     backslash, which should not be expanded.  Call Tokenize again, and make
     NewPath end immediately after the first backslash */
       FSpec = Tokenize(NULL,'\\');
       NewPath[NameStart + 1] = '\0';
    }
    else
       NewPath[NameStart] = '\0';        /* Remove everything except the drive
                                            spec, if given, from NewPath */
    while (FSpec != NULL) { /* While there are filenames left to be converted
       strcpy(Temp,FSpec);        /* Copy the file name to Temp so it can be
                                    converted */
       FSpec = Tokenize(NULL,'\\');        /* Find next file name */
       if (FSpec != NULL)        /* Convert filename only if it is not the las
                                    file name */
          AddFileWC(Temp);
       strcat(NewPath,Temp);        /* Add name to new path */
       strcat(NewPath,"\\");        /* Add a backslash */
    }
    NewPath[strlen(NewPath) - 1] = '\0'; /* Get rid of the last bckslsh added
    strcpy(Path,NewPath);        /* Copy converted path back to Path */
 }

 void AddFileWC(char File[])
 /* Converts the implicit wildcards in File to explicit wildcards.  An implici
    file name of "*" exists if File has no file name, and an implicit file
    extension of ".*" exists if File has no file ext. If File is "." or "..",
    it is not altered. */
 {
 char *Ext;        /* Start of the file ext of File */

    Ext = strchr(File,'.');
    if (Ext == File && !CPDir(File) || File[0] == '\0')        /* If File star
     a dot and is not the current or parent dir ("." or ".."), then it has no
     file name; make the file name "*". */
       Insert(File,"*",0);
    if (Ext == NULL)        /* If there was no dot in File, it has no file ext
                            make the file ext ".*" */
       strcat(File,".*");
 }

 char *Tokenize(char S[],char SepChar)
 /* Converts S to tokens. On the first call, S should be the string to tokeniz
    on subsequent calls it should be null.  S is a string of tokens separated
    by single instances of SepChar.  If two SepChar's occur adjacent to each
    other, a null token ("") is assumed to exist between them.  If S has a
    leading or trailing SepChar, a null token is assumed to exist before or
    after the string, respectively.  SepChar can be different between calls.
    After each call to Tokenize, a null is written immediately after the token
    found and a pointer to its start is returned.  Null tokens are returned as
    empty strings.  When no more tokens are found, a NULL pointer is returned.
    */
 {
 static char *List;        /* Start of list of tokens */
 char *Pos,        /* Position of end of current token */
 *Token; /* Start of token */

    if (S != NULL)  /* If first call to function, set List to string given */
       List = S;
    Token = List;   /* Current token starts at start of List */
    if (List != NULL) {                        /* If some tokens are left */
       Pos = strchr(List,SepChar);        /* Find end of token */
       if (Pos == NULL)        /* If no more tokens, the next call will return
          List = NULL;
       else {
          *Pos = '\0';        /* Otherwise, add null termination to current to
                            and make List point to start of next token */
          List = Pos + 1;
       }
    }
    return(Token);
 }

 void FirstWild(char Path[],char *Head,char *WildSpec,char *Tail)
 /* Finds the first wildcard filename in Path.  The portion of the path
    preceeding that filename (if any), including trailing backslash, is
    copied to Head.  The wildcard filename (without leading or trailing
    backslashes) is copied to WildSpec.        The portion of the path after
    the wildcard filename (including leading backslash) is copied to Tail */
 {
 char *PostSep,
 *PreSep,
 *FirstWC;

    strcpy(Head,Path);        /* Copy Path to Head so it can be altered */
    FirstWC = Head + strcspn(Head,"*?"); /* Make FirstWC point to the first
                                            wildcard in Head */
    if (*FirstWC == '\0') {        /* If no wildcards found, leave the entire
                 string in Head and make WildSpec and Tail null strings */
       WildSpec[0] = '\0';
       Tail[0] = '\0';
    }
    else {
       PostSep = strchr(FirstWC,'\\');        /* Find the first backslash afte
                                            first wildcard */
       if (PostSep != NULL) {        /* If there was one, then it is the start
        the tail and the end of the first wildcard spec */
          strcpy(Tail,PostSep);
          *PostSep = '\0';
       }
       else
          Tail[0] = '\0';        /* If not, make Tail a null string */
       PreSep = strrchr(Head,'\\');        /* Find the first backslash before
                                            the first wildcard */
       if (PreSep != NULL) {        /* If there was one, the char after it is
       start of the the first wildcard spec and the end of the Head */
          strcpy(WildSpec,PreSep + 1);
          *(PreSep + 1) = '\0';
       }
       else {
          strcpy(WildSpec,Head); /* If not, everything in Head is the first
                                    wildcard spec */
          Head[0] = '\0';
       }
    }
 }

 void AddString(NameNode *List,char *S)
 /* Adds string S to every name in List */
 {
    while (List != NULL) {
       strcat(List -> Name,S);
       List = List -> Next;
    }
 }

 void InsertList(NameNode *Target,NameNode *Source)
 /* Inserts list Source into the list in which Target is a node, immediately
    after target. */
 {
 NameNode *Next;

    if (Source != NULL) {
       Next = Target -> Next;
       Target -> Next = Source;
       LastElem(Source) -> Next = Next;
    }
 }

 NameNode *CatNameLists(NameNode *Target,NameNode *Source)
 /* Target points to the last node in a list.  Catenates Source to Target
    and returns a pointer to the last node of the new list */
 {

    ExTest(Target == NULL,"Error: Null Target in CatNameLists().");
    Target -> Next = Source;
    return(LastElem(Target));
 }

 NameNode *LastElem(NameNode *List)
 /* Returns a pointer to the last element of List */
 {
    ExTest(List == NULL,"Error: Null pointer passed to LastElem()");
    while(List -> Next != NULL)
       List = List -> Next;
    return(List);
 }

 void AddNode(NameNode *Node)
 /* Creates a new node; links Node to it; and makes its Next pointer null */
 {
    ExTest(Node == NULL,"NULL pointer passed to AddNode");
    Node -> Next = (NameNode *) MallocT(sizeof(NameNode));
    Node -> Next -> Next = NULL;
 }

 char *NextMatchFile(char FileSpec[],int Attributes)
 /* Finds files that match FileSpec and have all attributes indicated by
    Attributes, and returns the full path of the file,
    including the drive and directory given in FileSpec. On the first call,
    FileSpec and Attribs are given; on subsequent calls FileSpec should be
    NULL.  The found file is put in a static buffer and a pointer to the
    buffer is returned. If no matching file is found, a null pointer is
    returned. */
 {
 static char File[MAXPATH],        /* Full file name buffer */
 Drive[MAXDRIVE],Dir[MAXDIR];        /* Drive and dir given in the filespec, t
                                    be added to each file found */
 static struct ffblk FFBlk;        /* Structure for directory searching routin
 char Name[MAXFILE],Ext[MAXEXT]; /* Name and extension of found file */
 int Done;        /* Whether dir searching routine found a matching file */
 static int Attribs,        /* Saves Attributes between calls */
 RealDir;        /* Search for real dirs only */

    if (FileSpec != NULL) {        /* First call to function */
       fnsplit(FileSpec,Drive,Dir,NULL,NULL); /* Get drive & dir of filespec *
       if (Attributes & FA_REALDIR) {        /* If one of the attributes given
        the psuedo-attrib FA_REALDIR (match real dirs only, not "." or "..")
        then set the variable that will save the search attribs between calls
        to Attributes, with the psuedo-attrib replaced with the dir attrib,
        and set RealDir */
          Attribs = (Attributes & ~FA_REALDIR) | FA_DIREC;
          RealDir = TRUE;
       }
       else {        /* Save attribs */
          Attribs = Attributes;
          RealDir = FALSE;
       }
       Done = findfirst(FileSpec,&FFBlk,Attribs);  /* Find first match file */
    }
    else         /* Use FFBlk set up by previous call */
       Done = findnext(&FFBlk);
    while (!Done && ((FFBlk.ff_attrib & Attribs) != Attribs ||
     RealDir && CPDir(FFBlk.ff_name)))        /* Find next file that has all o
      attribs specified in Attribs and, if RealDir is set, is not the current
      or parent dir entry ("." or "..") */
       Done = findnext(&FFBlk);
    if (Done)        /* If no more matching files return NULL */
       return(NULL);
    else {
       fnsplit(FFBlk.ff_name,NULL,NULL,Name,Ext); /* Split matching file name
                                                     into Name & Extension */
       fnmerge(File,Drive,Dir,Name,Ext); /* Merge Name & Ext with previously
                                            given Drive & Dir */
       return(File);
    }
 }

 void MakePathsFull(NameNode **List)
 /* Converts the relative paths given in List to full path names, and deletes
    invalid paths from the list. If paths are removed from the front of the
    list, List is changed to point to the new start of the list */
 {
 NameNode  *Last,        /* The last path converted */
  *Temp;         /* Pointer to list as it is stepped through */

    while (*List != NULL && !GetFullPath((*List) -> Name)) {        /* Find th
     path in List (deleting invalid ones) and convert it to a full path */
       Temp = *List;
       *List = (*List) -> Next;
       free(Temp);
    }
    if (*List != NULL) { /* If any valid dirs were given */
       Temp = (*List) -> Next;        /* Start with the next node, since the c
                                    one has already been converted */
       Last = *List;        /* The previous loop insured that there is a 'last
        node that can have its Next pointer moved beyond the current node, in
        order to delete that node */
       while (Temp != NULL) { /* For all of the rest of the paths in the list
          if (GetFullPath(Temp -> Name)) {        /* If path is valid */
             Last = Temp;                /* Make Last point to the current
                                            path, then move to the next path *
             Temp = Temp -> Next;
          }
          else { /* If the path is not valid */
             DeleteNext(Last);        /* Delete the current path from the list
              by making the Next pointer of the previous node point the next
              node and freeing the current node */
             Temp = Last -> Next;        /* Move to the next path */
          }
       }
    }
 }

 void DeleteNext(NameNode *List)
 /* Deletes the node that follows List by making List's Next pointer point to
    the node beyond the next node, and freeing the deleted node */
 {
 NameNode *Temp; /* Node to be freed */

    ExTest(List == NULL || List -> Next == NULL,"Null pointer to DeleteNode");
    Temp = List -> Next;
    List -> Next = Temp -> Next;
    free(Temp);
 }

 GetFullPath(char *Path)
 /*
    Given a relative path to a file or directory, finds the full path name
    of the file or directory and replaces the original string with it.
    If a drive is not specified in the path, the current drive is used.
    Returns TRUE if the file is found, otherwise FALSE.
 */
 {
 char Drive[MAXDRIVE],Dir[MAXDIR],FileName[MAXFILE],Ext[MAXEXT], /* Used to
                                         split up and reassemble path */
 FindPath[MAXPATH];        /* New path */
 int Comps;        /* Components found in path */

    strcpy(FindPath,Path);        /* Make working copy of Path */
    if (FindPath[0] == '\0' || FindPath[1] == ':' && strlen(FindPath) == 2)
         /* If no path or only a drive is given, make path be the current
             directory on the default or given drive. */
       strcat(FindPath,".\\");
    else if (IsDir(FindPath) && FindPath[strlen(FindPath) - 1] != '\\')
      /* If path is a directory, append a backslash to it to indicate this */
       strcat(FindPath,"\\");
    Comps = fnsplit(FindPath,Drive,Dir,FileName,Ext);        /* Split path int
                                                            components */
    strcpy(FindPath,Drive);        /* Generate path pointing to given director
                                    or parent dirctory of given file */
    strcat(FindPath,Dir);
    strcat(FindPath,".");
    if (strcmp(FileName,".") == 0 || !GetFullDir(FindPath))        /* Convert
     directory path to full dir name; if dir specified in path was invalid, or
     specified a parent directory beyond the root directory, return FALSE */
       return(FALSE);
    if (!(Comps & DRIVE)) {        /* If a drive was not specified, make path
                                    drive be the current drive */
       Drive[0] = getdisk() + 'A';
       Drive[1] = ':';
    }
    if (!(Comps & FILENAME))        /* If no file name given, make file name "
       strcpy(FileName,"*");
    if (!(Comps & EXTENSION))        /* if no file ext given, make file ext ".
       strcpy(Ext,".*");
    fnmerge(Path,Drive,FindPath,FileName,Ext); /* Create full path from comps
    return(TRUE);
 }

 GetFullDir(char *Path)
 /* Given a path to a directory, converts it to a full directory name. If
    given path did not point to a dir, returns FALSE; else returns TRUE */
 {
 struct ffblk FFBlk;        /* Structure for directory searching routine */
 char Dir[MAXPATH];        /* Temp storage of full path */

    if (!IsDir(Path))        /* If invalid directory, return FALSE */
       return(FALSE);
    Dir[0] = '\0';                /* Clear directory string */
    while (!findfirst(Path,&FFBlk,0x3f)) {        /* Get name of directory
      pointed to by Path until no more directories can be found */
       if (!IsRoot(Path)) {        /* Check whether directory name found is th
         name of the dir that is at the root of the drive given in the path,
         which it could be if the drive is a substituded drive. If not,
         insert the name followed by a backslash at the begining of Dir */
          Insert(Dir,"\\",0);
          Insert(Dir,FFBlk.ff_name,0);
       }
       strcat(Path,"\\..");        /* Append "\.." to Path so it will point
        to the parent directory (if it exists) of the dir just found */
    }
    Insert(Dir,"\\",0);        /* Make Dir have a leading backslash */
    strcpy(Path,Dir);        /* Move full dir name to Path */
    return(TRUE);
 }

 IsRoot(char *Dir)
 /* Returns TRUE if Dir is a path to the root of a real or substituted drive,
    or is an invalid directory. Otherwise returns FALSE. */
 {
 struct ffblk FFBlk;        /* For dir searching routine */
 char Temp[MAXPATH];        /* Path to parent of Dir, if it exists */

    strcpy(Temp,Dir);
    strcat(Temp,"\\..\\*.*");        /* Make Temp point to parent of Dir */
    return(findfirst(Temp,&FFBlk,0x3f)); /* Return TRUE if Dir has no parent.
 }

 IsDir(char *Path)
 /* Returns true if Path is a directory, otherwise false. */
 {
 char Temp[MAXPATH];        /* Test string */
 struct ffblk FFBlk;        /* For directory searching routine */

    strcpy(Temp,Path);
    if (Temp[0] != '\0' && Temp[strlen(Temp) - 1] != '\\')        /* If string
     not null and does not end in a backslash, append a backslash to it so it
     will specify a directory */
       strcat(Temp,"\\");
    strcat(Temp,"*.*");        /* Make temp specify any file in the given dire
    return(!findfirst(Temp,&FFBlk,0x3f) || NullPath(Path));        /* If any f
      are found, or it is a null path (contains only single .'s or backslashes
      it must be a directory. The only directory that does not have
      any files is a root dir without ordinary files, directories, system file
      or volume label. A path to such a directory must be a null path. */
 }

 NullPath(char *Path)
 /* Checks whether Path is a null path (contains only single '.s and
    backslashes). Returns TRUE if so, else returns FALSE. */
 {
 char Temp[MAXPATH];


    if (DriveSpeced(Path))
       strcpy(Temp,Path + 2);
    else
       strcpy(Temp,Path);
    strcat(Temp,"\\");        /* Pad string with '\' so strstr will work despi
                            its bug */
    return(strspn(Temp,"\\.") == strlen(Temp) && strstr(Temp,"..") == NULL);
      /* Check that temp contains only \'s and .'s, and no two .'s are
         adjacent */
 }



 DISPIOF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\DISPIOF.C

 /*      Small functions which use DISPIO BIOS calls and include file       */
 /* DISPIO.H.                                                               */
 /*                                                                         */
 /* set_dfull()                  - Set up display parameters except         */
 /*                                the attribute (d_attr).                  */
 /*                                                                         */
 /* d_tomono()                   - Change monitor to mono                   */
 /* d_toc80()                    - Change monitor to 80 column color        */
 /* d_toc40()                    - Change monitor to 40 column color        */
 /*                                                                         */
 /* i = d_newmode(newmode)       - Change mode to newmode.  i = 1 if mode   */
 /*                                newmode is valid for this monitor, 0     */
 /*                                otherwise.                               */
 /*                                                                         */
 /* i = d_newpage(newpage)       - Change active page to newpage.  i = 1    */
 /*                                if newpage is valid for this mode, 0     */
 /*                                otherwise.                               */
 /*                                                                         */
 /* clrscr()                     - Clear the current window.  Leave the     */
 /*                                cursor in the upper left hand corner.    */
 /*                                                                         */
 /* d_erasel()                   - Erase current line.  Leave cursor at its */
 /*                                start.                                   */
 /*                                                                         */
 /* d_ereol()                    - Erase from the cursor to the end of the  */
 /*                                current line.  Do not move the cursor.   */
 /*                                                                         */
 /* d_nextc()                    - Move the cursor to the next position.    */
 /*                                If at the end of the window, scroll up   */
 /*                                one line and move to the lower left      */
 /*                                corner.                                  */
 /*                                                                         */
 /* d_nextl()                    - Move the cursor to the next line.  If    */
 /*                                at the end of the window, scroll up one  */
 /*                                line and move to the lower left corner.  */
 /*                                                                         */
 /* d_putc(ch)                   - Write a single character at the cursor   */
 /*                                position and move the cursore to the     */
 /*                                next position.  If at the end of the     */
 /*                                window, scroll up one line and move to   */
 /*                                the lower left hand corner.              */
 /*                                                                         */
 /* i = d_puts(s)                - Write the string s, starting at the      */
 /*                                cursor position.  If the window would    */
 /*                                overflow, scroll it up enough lines to   */
 /*                                fit.  The cursor ends one position       */
 /*                                after the end of the string.  The        */
 /*                                function returns the number of           */
 /*                                characters written.                      */
 /*                                                                         */
 /*      Draw vertical lines                                                */
 /*      If length > 0, draw down, but not beyond the bottom of the screen  */
 /*      If length < 0, draw up, but not beyond the top of the screen       */
 /*      The functions return the number of characters written, 0 for       */
 /* error.  They leave the cursor one beyone the end of the line drawn.     */
 /* verline(ch, length)          - draw a vertical line of length length    */
 /*                                starting at the current cursor position  */
 /* vline(row, col, ch, length) - draw a vertical line of length length     */
 /*                                characters ch, starting at row, col.     */
 /*                                Checks row and col for validity.         */
 /*      row is in the range 0 - 24.                                        */
 /*      col is either in range 0 - 39 or 0 - 79                            */
 /* _vline(row, col, ch, length) - draw a vertical line of length length    */
 /*                                characters ch, starting at row, col.     */
 /*                                Does not check row and col.              */
 /*                                                                         */
 /*      Draw horizontal lines                                              */
 /*      If width > 0, draw down, but not beyond the bottom of the screen   */
 /*      If width < 0, draw up, but not beyond the top of the screen        */
 /*      The functions return the number of characters written, 0 for       */
 /* error.  They leave the cursor one beyone the end of the line drawn.     */
 /* horline(ch, width)           - draw a horizontal line of width width    */
 /*                                starting at the current cursor position  */
 /* hline(row, col, ch, width)   - draw a horizontal line of width width    */
 /*                                characters ch, starting at row, col.     */
 /*                                Checks row and col for validity.         */
 /*      row is in the range 0 - 24.                                        */
 /*      col is either in range 0 - 39 or 0 - 79                            */
 /* _hline(row, col, ch, width)  - draw a horizontal line of width width    */
 /*                                characters ch, starting at row, col.     */
 /*                                Does not check row and col.              */
 /*                                                                         */
 /* Lew Paper                                                               */
 /*                                                                         */
 /*                                                                         */

 #include "dispio.h"

 #undef PAGE
 #define PAGE d_page

 #undef WRTCHAR
 #define WRTCHAR(CH) write_ac(d_attr, CH, PAGE, 1);

 /*  Initial values for display parameters.  Change to suit the application */
 /*  These are for the full screen of the monochrome monitor*/
 INIT_DMODE     7        /* Monochrome */
 INIT_DCOLS    80        /* 80 columns wide */
 INIT_DPAGE     0        /* Page 0 */
 INIT_DTOP      0        /* Top row is 0 */
 INIT_DBOTTOM  24        /* Bottom row is 24 */
 INIT_DLEFT     0        /* Left hand column is 0 */
 INIT_DRIGHT   79        /* Right hand column is 79 */
 INIT_DULC      0        /* Upper left hand corner */
 INIT_DLRC 0x184f        /* Lower right hand corner, (24<<8) + 79 */
 INIT_DATTR     7        /* Standard attribute */

 #define MAXSTRING 254

 #define SCRL_UP1 dispio(0x0601, STD_CHAR, d_ulc, d_lrc)

 /* Display parameters.  Note that they can be declared external in other
    modules */
 int d_mode = INIT_DMODE;
 int d_cols = INIT_DCOLS;
 int d_page = INIT_DPAGE;
 int d_top = INIT_DTOP;
 int d_bottom = INIT_DBOTTOM;
 int d_left = INIT_DLEFT;
 int d_right = INIT_DRIGHT;
 int d_ulc = INIT_DULC;
 int d_lrc = INIT_DLRC;
 int d_attr = INIT_DATTR;

 int set_dfull()

 {

    dispio(GET_STATE, &d_mode, &d_cols, &d_page);
    d_top = d_left = d_ulc = 0;
    d_bottom = 24;
    d_right = d_cols - 1;
    d_lrc = (24 << 8) + d_right;

 }

 int d_tomono()

 {

    mono_dsp();
    set_dfull();

 }

 int d_toc80()

 {

    c80_disp();
    set_dfull();

 }

 int d_toc40()

 {

    c40_disp();
    set_dfull();

 }

 int d_newmode(newmode)

 int newmode;

 {

    if (d_mode == 7 || newmode < 0 || newmode > 6) return(0);
    dispio(newmode);
    set_dfull();
    return(1);

 }

 int d_newpage(new_page)

 int new_page;

 {

    if (new_page < 0) return(0);
    switch (d_mode) {
       case 2: case 3:
          if (new_page > 3) return(0);
          break;
       case 0: case 1:
          if (new_page > 7) return(0);
          break;
       default: return(0);
    }
    dispio(SELECT_PAGE + new_page);
    d_page = new_page;
    return(1);

 }

 int clrscr() {

    if (d_top == d_bottom) {
       CURPOS(d_top, d_left);
       write_ac(STD_CHAR, ' ', PAGE, d_right - d_left + 1);
    }
    /* SCROLL_UP has number of columns = 0, so the next line
       clears the window */
       else dispio(SCROLL_UP, STD_CHAR, d_ulc, d_lrc);
    dispio(SET_CUR, PAGE, d_ulc);

 }

 int d_erasel()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    CURPOS(row, d_left);
    write_ac(STD_CHAR, ' ', PAGE, d_right - d_left + 1);
    CURPOS(row, d_left);

 }

 int d_ereol()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    write_ac(STD_CHAR, ' ', PAGE, d_right - col + 1);
    CURPOS(row, col);
 }

 int d_nextc()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    if (col < d_right) ++col;
    else {
       col = d_left;
       if (row < d_bottom) ++row;
       else SCRL_UP1;
    }
    CURPOS(row, col);

 }

 int d_nextl()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    col = d_left;
    if (row < d_bottom) ++row;
    else SCRL_UP1;
    CURPOS(row, col);

 }

 int d_putc(ch)

 char ch;

 {

    if (ch == '\n') d_nextl();
    else {
       WRTCHAR(ch);
       d_nextc();
    }

 }

 int d_puts(s)

 char *s;

 {

    char *i, c;
    int row, col, j;

    read_loc(PAGE, &row, &col);

    for (i = s, j = MAXSTRING; j; --j, ++i) {
       if (!(c = *i)) break; /* End of string */
       if (c != '\n') {
          WRTCHAR(*i);
          if (col < d_right) {  /* Stay on same line */
             ++col;
             CURPOS(row, col);
             continue;
          }
       }
       col = d_left;              /* Go to next line */
       if (row < d_bottom) ++row;
       else SCRL_UP1;
       CURPOS(row, col);
    }
    return(i - s);
 }

 int verline(ch, length)

 char ch;
 int length;

 {
    int row, col;

    read_loc(d_page, &row, &col);
    return(_vline(row, col, ch, length));

 }

 int vline(row, col, ch, length)

 char ch;
 int row, col, length;

 {

    if (row < d_top || row > d_bottom || col < d_left || col > d_right)
        return(0);
    return(_vline(row, col, ch, length));

 }

 int _vline(row, col, ch, length)

 char ch;
 int row, col, length;

 {

    int start_r, end_r, count, return_r;

    if (length == 0) return(0);

    if (length > 0) {
       start_r = row;
       end_r = start_r + length - 1;
       if (end_r > d_bottom) end_r = d_bottom;  /* Don't go beyond bottom */
       count = end_r - start_r + 1;
       return_r = end_r + (end_r < d_bottom);   /* Don't go beyond bottom */
    }
    else {
       start_r = row + length + 1;  /* length < 0, so start_r < row */
       if (start_r < d_top) start_r = d_top;  /* Don't go beyond top */
       end_r = row;
       count = start_r - end_r - 1;
       return_r = start_r -(start_r > d_top); /* Don't go beyone top */
    }

    for ( ; start_r <= end_r; ++start_r) {
       CURPOS(start_r, col);
       WRTCHAR(ch);
    }

    CURPOS(return_r, col);
    return(count);

 }

 int horline(ch, width)

 char ch;
 int width;

 {
    int row, col;

    read_loc(d_page, &row, &col);
    return(_hline(row, col, ch, width));

 }

 int hline(row, col, ch, width)

 char ch;
 int row, col, width;

 {

    if (row < d_top || row > d_bottom || col < d_left || col > d_right)
        return(0);
    return(_hline(row, col, ch, width));

 }

 int _hline(row, col, ch, width)

 char ch;
 int row, col, width;

 {

    int start_c, end_c, count, return_c;

    if (width == 0) return(0);

    if (width > 0) {
       start_c = col;
       end_c = start_c + width - 1;
       if (end_c > d_right) end_c = d_right;  /* Don't go beyond right end */
       return_c = end_c + (end_c < d_right);   /* Don't go beyond right end */
    }
    else {
       start_c = col + width + 1;  /* width < 0, so start_c < col */
       if (start_c < d_left) start_c = d_left;  /* Don't go beyond left end */
       end_c = col;
       return_c = start_c -(start_c > d_left); /* Don't go beyone left end */
    }

    CURPOS(row, start_c);
    count = end_c - start_c + 1;
    write_ac(d_attr, ch, PAGE, count);

    CURPOS(row, return_c);
    return(width > 0 ? count: -count);

 }



 DISPIOF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DISPIO\DISPIOF.C

 /*      Small functions which use DISPIO BIOS calls and include file       */
 /* DISPIO.H.                                                               */
 /*                                                                         */
 /* set_dfull()                  - Set up display parameters except         */
 /*                                the attribute (d_attr).                  */
 /*                                                                         */
 /* d_tomono()                   - Change monitor to mono                   */
 /* d_toc80()                    - Change monitor to 80 column color        */
 /* d_toc40()                    - Change monitor to 40 column color        */
 /*                                                                         */
 /* i = d_newmode(newmode)       - Change mode to newmode.  i = 1 if mode   */
 /*                                newmode is valid for this monitor, 0     */
 /*                                otherwise.                               */
 /*                                                                         */
 /* i = d_newpage(newpage)       - Change active page to newpage.  i = 1    */
 /*                                if newpage is valid for this mode, 0     */
 /*                                otherwise.                               */
 /*                                                                         */
 /* clrscr()                     - Clear the current window.  Leave the     */
 /*                                cursor in the upper left hand corner.    */
 /*                                                                         */
 /* d_erasel()                   - Erase current line.  Leave cursor at its */
 /*                                start.                                   */
 /*                                                                         */
 /* d_ereol()                    - Erase from the cursor to the end of the  */
 /*                                current line.  Do not move the cursor.   */
 /*                                                                         */
 /* d_nextc()                    - Move the cursor to the next position.    */
 /*                                If at the end of the window, scroll up   */
 /*                                one line and move to the lower left      */
 /*                                corner.                                  */
 /*                                                                         */
 /* d_nextl()                    - Move the cursor to the next line.  If    */
 /*                                at the end of the window, scroll up one  */
 /*                                line and move to the lower left corner.  */
 /*                                                                         */
 /* d_putc(ch)                   - Write a single character at the cursor   */
 /*                                position and move the cursore to the     */
 /*                                next position.  If at the end of the     */
 /*                                window, scroll up one line and move to   */
 /*                                the lower left hand corner.              */
 /*                                                                         */
 /* i = d_puts(s)                - Write the string s, starting at the      */
 /*                                cursor position.  If the window would    */
 /*                                overflow, scroll it up enough lines to   */
 /*                                fit.  The cursor ends one position       */
 /*                                after the end of the string.  The        */
 /*                                function returns the number of           */
 /*                                characters written.                      */
 /*                                                                         */
 /*      Draw vertical lines                                                */
 /*      If length > 0, draw down, but not beyond the bottom of the screen  */
 /*      If length < 0, draw up, but not beyond the top of the screen       */
 /*      The functions return the number of characters written, 0 for       */
 /* error.  They leave the cursor one beyone the end of the line drawn.     */
 /* verline(ch, length)          - draw a vertical line of length length    */
 /*                                starting at the current cursor position  */
 /* vline(row, col, ch, length) - draw a vertical line of length length     */
 /*                                characters ch, starting at row, col.     */
 /*                                Checks row and col for validity.         */
 /*      row is in the range 0 - 24.                                        */
 /*      col is either in range 0 - 39 or 0 - 79                            */
 /* _vline(row, col, ch, length) - draw a vertical line of length length    */
 /*                                characters ch, starting at row, col.     */
 /*                                Does not check row and col.              */
 /*                                                                         */
 /*      Draw horizontal lines                                              */
 /*      If width > 0, draw down, but not beyond the bottom of the screen   */
 /*      If width < 0, draw up, but not beyond the top of the screen        */
 /*      The functions return the number of characters written, 0 for       */
 /* error.  They leave the cursor one beyone the end of the line drawn.     */
 /* horline(ch, width)           - draw a horizontal line of width width    */
 /*                                starting at the current cursor position  */
 /* hline(row, col, ch, width)   - draw a horizontal line of width width    */
 /*                                characters ch, starting at row, col.     */
 /*                                Checks row and col for validity.         */
 /*      row is in the range 0 - 24.                                        */
 /*      col is either in range 0 - 39 or 0 - 79                            */
 /* _hline(row, col, ch, width)  - draw a horizontal line of width width    */
 /*                                characters ch, starting at row, col.     */
 /*                                Does not check row and col.              */
 /*                                                                         */
 /* Lew Paper                                                               */
 /*                                                                         */
 /*                                                                         */

 #include "dispio.h"

 #undef PAGE
 #define PAGE d_page

 #undef WRTCHAR
 #define WRTCHAR(CH) write_ac(d_attr, CH, PAGE, 1);

 /*  Initial values for display parameters.  Change to suit the application */
 /*  These are for the full screen of the monochrome monitor*/
 INIT_DMODE     7        /* Monochrome */
 INIT_DCOLS    80        /* 80 columns wide */
 INIT_DPAGE     0        /* Page 0 */
 INIT_DTOP      0        /* Top row is 0 */
 INIT_DBOTTOM  24        /* Bottom row is 24 */
 INIT_DLEFT     0        /* Left hand column is 0 */
 INIT_DRIGHT   79        /* Right hand column is 79 */
 INIT_DULC      0        /* Upper left hand corner */
 INIT_DLRC 0x184f        /* Lower right hand corner, (24<<8) + 79 */
 INIT_DATTR     7        /* Standard attribute */

 #define MAXSTRING 254

 #define SCRL_UP1 dispio(0x0601, STD_CHAR, d_ulc, d_lrc)

 /* Display parameters.  Note that they can be declared external in other
    modules */
 int d_mode = INIT_DMODE;
 int d_cols = INIT_DCOLS;
 int d_page = INIT_DPAGE;
 int d_top = INIT_DTOP;
 int d_bottom = INIT_DBOTTOM;
 int d_left = INIT_DLEFT;
 int d_right = INIT_DRIGHT;
 int d_ulc = INIT_DULC;
 int d_lrc = INIT_DLRC;
 int d_attr = INIT_DATTR;

 int set_dfull()

 {

    dispio(GET_STATE, &d_mode, &d_cols, &d_page);
    d_top = d_left = d_ulc = 0;
    d_bottom = 24;
    d_right = d_cols - 1;
    d_lrc = (24 << 8) + d_right;

 }

 int d_tomono()

 {

    mono_dsp();
    set_dfull();

 }

 int d_toc80()

 {

    c80_disp();
    set_dfull();

 }

 int d_toc40()

 {

    c40_disp();
    set_dfull();

 }

 int d_newmode(newmode)

 int newmode;

 {

    if (d_mode == 7 || newmode < 0 || newmode > 6) return(0);
    dispio(newmode);
    set_dfull();
    return(1);

 }

 int d_newpage(new_page)

 int new_page;

 {

    if (new_page < 0) return(0);
    switch (d_mode) {
       case 2: case 3:
          if (new_page > 3) return(0);
          break;
       case 0: case 1:
          if (new_page > 7) return(0);
          break;
       default: return(0);
    }
    dispio(SELECT_PAGE + new_page);
    d_page = new_page;
    return(1);

 }

 int clrscr() {

    if (d_top == d_bottom) {
       CURPOS(d_top, d_left);
       write_ac(STD_CHAR, ' ', PAGE, d_right - d_left + 1);
    }
    /* SCROLL_UP has number of columns = 0, so the next line
       clears the window */
       else dispio(SCROLL_UP, STD_CHAR, d_ulc, d_lrc);
    dispio(SET_CUR, PAGE, d_ulc);

 }

 int d_erasel()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    CURPOS(row, d_left);
    write_ac(STD_CHAR, ' ', PAGE, d_right - d_left + 1);
    CURPOS(row, d_left);

 }

 int d_ereol()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    write_ac(STD_CHAR, ' ', PAGE, d_right - col + 1);
    CURPOS(row, col);
 }

 int d_nextc()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    if (col < d_right) ++col;
    else {
       col = d_left;
       if (row < d_bottom) ++row;
       else SCRL_UP1;
    }
    CURPOS(row, col);

 }

 int d_nextl()

 {

    int row, col;

    read_loc(PAGE, &row, &col);
    col = d_left;
    if (row < d_bottom) ++row;
    else SCRL_UP1;
    CURPOS(row, col);

 }

 int d_putc(ch)

 char ch;

 {

    if (ch == '\n') d_nextl();
    else {
       WRTCHAR(ch);
       d_nextc();
    }

 }

 int d_puts(s)

 char *s;

 {

    char *i, c;
    int row, col, j;

    read_loc(PAGE, &row, &col);

    for (i = s, j = MAXSTRING; j; --j, ++i) {
       if (!(c = *i)) break; /* End of string */
       if (c != '\n') {
          WRTCHAR(*i);
          if (col < d_right) {  /* Stay on same line */
             ++col;
             CURPOS(row, col);
             continue;
          }
       }
       col = d_left;              /* Go to next line */
       if (row < d_bottom) ++row;
       else SCRL_UP1;
       CURPOS(row, col);
    }
    return(i - s);
 }

 int verline(ch, length)

 char ch;
 int length;

 {
    int row, col;

    read_loc(d_page, &row, &col);
    return(_vline(row, col, ch, length));

 }

 int vline(row, col, ch, length)

 char ch;
 int row, col, length;

 {

    if (row < d_top || row > d_bottom || col < d_left || col > d_right)
        return(0);
    return(_vline(row, col, ch, length));

 }

 int _vline(row, col, ch, length)

 char ch;
 int row, col, length;

 {

    int start_r, end_r, count, return_r;

    if (length == 0) return(0);

    if (length > 0) {
       start_r = row;
       end_r = start_r + length - 1;
       if (end_r > d_bottom) end_r = d_bottom;  /* Don't go beyond bottom */
       count = end_r - start_r + 1;
       return_r = end_r + (end_r < d_bottom);   /* Don't go beyond bottom */
    }
    else {
       start_r = row + length + 1;  /* length < 0, so start_r < row */
       if (start_r < d_top) start_r = d_top;  /* Don't go beyond top */
       end_r = row;
       count = start_r - end_r - 1;
       return_r = start_r -(start_r > d_top); /* Don't go beyone top */
    }

    for ( ; start_r <= end_r; ++start_r) {
       CURPOS(start_r, col);
       WRTCHAR(ch);
    }

    CURPOS(return_r, col);
    return(count);

 }

 int horline(ch, width)

 char ch;
 int width;

 {
    int row, col;

    read_loc(d_page, &row, &col);
    return(_hline(row, col, ch, width));

 }

 int hline(row, col, ch, width)

 char ch;
 int row, col, width;

 {

    if (row < d_top || row > d_bottom || col < d_left || col > d_right)
        return(0);
    return(_hline(row, col, ch, width));

 }

 int _hline(row, col, ch, width)

 char ch;
 int row, col, width;

 {

    int start_c, end_c, count, return_c;

    if (width == 0) return(0);

    if (width > 0) {
       start_c = col;
       end_c = start_c + width - 1;
       if (end_c > d_right) end_c = d_right;  /* Don't go beyond right end */
       return_c = end_c + (end_c < d_right);   /* Don't go beyond right end */
    }
    else {
       start_c = col + width + 1;  /* width < 0, so start_c < col */
       if (start_c < d_left) start_c = d_left;  /* Don't go beyond left end */
       end_c = col;
       return_c = start_c -(start_c > d_left); /* Don't go beyone left end */
    }

    CURPOS(row, start_c);
    count = end_c - start_c + 1;
    write_ac(d_attr, ch, PAGE, count);

    CURPOS(row, return_c);
    return(width > 0 ? count: -count);

 }



 DISPLAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\DISPLAY.C

 /*
  * The functions in this file handle redisplay. There are two halves, the
  * ones that update the virtual display screen, and the ones that make the
  * physical display screen the same as the virtual display screen. These
  * functions use hints that are left in the windows by the commands.
  *
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 typedef struct  VIDEO {
         int        v_flag;                 /* Flags */
 #if        COLOR
         int        v_fcolor;                /* current forground color */
         int        v_bcolor;                /* current background color */
         int        v_rfcolor;                /* requested forground color */
         int        v_rbcolor;                /* requested background color */
 #endif
         char    v_text[1];              /* Screen data. */
 }       VIDEO;

 VFCHG   0x0001                  /* Changed flag                        */
        VFEXT        0x0002                        /* extended (beyond column
        VFREV        0x0004                        /* reverse video status
        VFREQ        0x0008                        /* reverse video request
        VFCOL        0x0010                        /* color change requested

 VIDEO   **vscreen;                      /* Virtual screen. */
 #if        MEMMAP == 0
 VIDEO   **pscreen;                      /* Physical screen. */
 #endif

 /*
  * Initialize the data structures used by the display code. The edge vectors
  * used to access the screens are set up. The operating system's terminal I/O
  * channel is set up. All the other things get initialized at compile time.
  * The original window has "WFCHG" set, so that it will get completely
  * redrawn on the first call to "update".
  */
 vtinit()
 {
     register int i;
     register VIDEO *vp;
     char *malloc();

     TTopen();                /* open the screen */
     TTkopen();                /* open the keyboard */
     TTrev(FALSE);
     vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));

     if (vscreen == NULL)
         exit(1);

 #if        MEMMAP == 0
     pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));

     if (pscreen == NULL)
         exit(1);
 #endif

     for (i = 0; i < term.t_mrow; ++i)
         {
         vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);

         if (vp == NULL)
             exit(1);

         vp->v_flag = 0;
 #if        COLOR
         vp->v_rfcolor = 7;
         vp->v_rbcolor = 0;
 #endif
         vscreen[i] = vp;
 #if        MEMMAP == 0
         vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);

         if (vp == NULL)
             exit(1);

         vp->v_flag = 0;
         pscreen[i] = vp;
 #endif
         }
 }

 /*
  * Clean up the virtual terminal system, in anticipation for a return to the
  * operating system. Move down to the last line and clear it out (the next
  * system prompt will be written in the line). Shut down the channel to the
  * terminal.
  */
 vttidy()
 {
     mlerase();
     movecursor(term.t_nrow, 0);
     TTflush();
     TTclose();
     TTkclose();
 }

 /*
  * Set the virtual cursor to the specified row and column on the virtual
  * screen. There is no checking for nonsense values; this might be a good
  * idea during the early stages.
  */
 vtmove(row, col)
 {
     vtrow = row;
     vtcol = col;
 }

 /* Write a character to the virtual screen. The virtual row and
    column are updated. If we are not yet on left edge, don't print
    it yet. If the line is too long put a "$" in the last column.
    This routine only puts printing characters into the virtual
    terminal buffers. Only column overflow is checked.
 */

 vtputc(c)

 int c;

 {
         register VIDEO *vp;        /* ptr to line being updated */

         vp = vscreen[vtrow];

         if (c == '\t') {
                 do {
                         vtputc(' ');
                 } while (((vtcol + taboff)&0x07) != 0);
         } else if (vtcol >= term.t_ncol) {
                 ++vtcol;
                 vp->v_text[term.t_ncol - 1] = '$';
         } else if (c < 0x20 || c == 0x7F) {
                 vtputc('^');
                 vtputc(c ^ 0x40);
         } else {
                 if (vtcol >= 0)
                         vp->v_text[vtcol] = c;
                 ++vtcol;
         }
 }

 /*
  * Erase from the end of the software cursor to the end of the line on which
  * the software cursor is located.
  */
 vteeol()
 {
     register VIDEO      *vp;

     vp = vscreen[vtrow];
     while (vtcol < term.t_ncol)
         vp->v_text[vtcol++] = ' ';
 }

 /* upscreen:        user routine to force a screen update
                 always finishes complete update                */

 upscreen(f, n)

 {
         update(TRUE);
         return(TRUE);
 }

 /*
  * Make sure that the display is right. This is a three part process. First,
  * scan through all of the windows looking for dirty ones. Check the framing,
  * and refresh the screen. Second, make sure that "currow" and "curcol" are
  * correct for the current window. Third, make the virtual and physical
  * screens the same.
  */
 update(force)

 int force;        /* force update past type ahead? */

 {
         register WINDOW *wp;

 #if        TYPEAH
         if (force == FALSE && typahead())
                 return(TRUE);
 #endif
 #if        VISMAC == 0
         if (force == FALSE && kbdmode == PLAY)
                 return(TRUE);
 #endif

         /* update any windows that need refreshing */
         wp = wheadp;
         while (wp != NULL) {
                 if (wp->w_flag) {
                         /* if the window has changed, service it */
                         reframe(wp);        /* check the framing */
                         if ((wp->w_flag & ~WFMODE) == WFEDIT)
                                 updone(wp);        /* update EDITed line */
                         else if (wp->w_flag & ~WFMOVE)
                                 updall(wp);        /* update all lines */
                         if (wp->w_flag & WFMODE)
                                 modeline(wp);        /* update modeline */
                         wp->w_flag = 0;
                         wp->w_force = 0;
                 }
                 /* on to the next window */
                 wp = wp->w_wndp;
         }

         /* recalc the current hardware cursor location */
         updpos();

 #if        MEMMAP
         /* update the cursor and flush the buffers */
         movecursor(currow, curcol - lbound);
 #endif

         /* check for lines to de-extend */
         upddex();

         /* if screen is garbage, re-plot it */
         if (sgarbf != FALSE)
                 updgar();

         /* update the virtual screen to the physical screen */
         updupd(force);

         /* update the cursor and flush the buffers */
         movecursor(currow, curcol - lbound);
         TTflush();
         return(TRUE);
 }

 /*        reframe:        check to see if the cursor is on in the window
                         and re-frame it if needed or wanted                */

 reframe(wp)

 WINDOW *wp;

 {
         register LINE *lp;
         register int i;

         /* if not a requested reframe, check for a needed one */
         if ((wp->w_flag & WFFORCE) == 0) {
                 lp = wp->w_linep;
                 for (i = 0; i < wp->w_ntrows; i++) {

                         /* if the line is in the window, no reframe */
                         if (lp == wp->w_dotp)
                                 return(TRUE);

                         /* if we are at the end of the file, reframe */
                         if (lp == wp->w_bufp->b_linep)
                                 break;

                         /* on to the next line */
                         lp = lforw(lp);
                 }
         }

         /* reaching here, we need a window refresh */
         i = wp->w_force;

         /* how far back to reframe? */
         if (i > 0) {                /* only one screen worth of lines max */
                 if (--i >= wp->w_ntrows)
                         i = wp->w_ntrows - 1;
         } else if (i < 0) {        /* negative update???? */
                 i += wp->w_ntrows;
                 if (i < 0)
                         i = 0;
         } else
                 i = wp->w_ntrows / 2;

         /* backup to new line at top of window */
         lp = wp->w_dotp;
         while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
                 --i;
                 lp = lback(lp);
         }

         /* and reset the current line at top of window */
         wp->w_linep = lp;
         wp->w_flag |= WFHARD;
         wp->w_flag &= ~WFFORCE;
         return(TRUE);
 }

 /*        updone:        update the current line        to the virtual screen

 updone(wp)

 WINDOW *wp;        /* window to update current line in */

 {
         register LINE *lp;        /* line to update */
         register int sline;        /* physical screen line to update */
         register int i;

         /* search down the line we want */
         lp = wp->w_linep;
         sline = wp->w_toprow;
         while (lp != wp->w_dotp) {
                 ++sline;
                 lp = lforw(lp);
         }

         /* and update the virtual line */
         vscreen[sline]->v_flag |= VFCHG;
         vscreen[sline]->v_flag &= ~VFREQ;
         vtmove(sline, 0);
         for (i=0; i < llength(lp); ++i)
                 vtputc(lgetc(lp, i));
 #if        COLOR
         vscreen[sline]->v_rfcolor = wp->w_fcolor;
         vscreen[sline]->v_rbcolor = wp->w_bcolor;
 #endif
         vteeol();
 }

 /*        updall:        update all the lines in a window on the virtual scre

 updall(wp)

 WINDOW *wp;        /* window to update lines in */

 {
         register LINE *lp;        /* line to update */
         register int sline;        /* physical screen line to update */
         register int i;

         /* search down the lines, updating them */
         lp = wp->w_linep;
         sline = wp->w_toprow;
         while (sline < wp->w_toprow + wp->w_ntrows) {

                 /* and update the virtual line */
                 vscreen[sline]->v_flag |= VFCHG;
                 vscreen[sline]->v_flag &= ~VFREQ;
                 vtmove(sline, 0);
                 if (lp != wp->w_bufp->b_linep) {
                         /* if we are not at the end */
                         for (i=0; i < llength(lp); ++i)
                                 vtputc(lgetc(lp, i));
                         lp = lforw(lp);
                 }

                 /* on to the next one */
 #if        COLOR
                 vscreen[sline]->v_rfcolor = wp->w_fcolor;
                 vscreen[sline]->v_rbcolor = wp->w_bcolor;
 #endif
                 vteeol();
                 ++sline;
         }

 }

 /*        updpos:        update the position of the hardware cursor and handl
                 lines. This is the only update for simple moves.        */

 updpos()

 {
         register LINE *lp;
         register int c;
         register int i;

         /* find the current row */
         lp = curwp->w_linep;
         currow = curwp->w_toprow;
         while (lp != curwp->w_dotp) {
                 ++currow;
                 lp = lforw(lp);
         }

         /* find the current column */
         curcol = 0;
         i = 0;
         while (i < curwp->w_doto) {
                 c = lgetc(lp, i++);
                 if (c == '\t')
                         curcol |= 0x07;
                 else
                         if (c < 0x20 || c == 0x7f)
                                 ++curcol;

                 ++curcol;
         }

         /* if extended, flag so and update the virtual line image */
         if (curcol >=  term.t_ncol - 1) {
                 vscreen[currow]->v_flag |= (VFEXT | VFCHG);
                 updext();
         } else
                 lbound = 0;
 }

 /*        upddex:        de-extend any line that derserves it

 upddex()

 {
         register WINDOW *wp;
         register LINE *lp;
         register int i,j;

         wp = wheadp;

         while (wp != NULL) {
                 lp = wp->w_linep;
                 i = wp->w_toprow;

                 while (i < wp->w_toprow + wp->w_ntrows) {
                         if (vscreen[i]->v_flag & VFEXT) {
                                 if ((wp != curwp) || (lp != wp->w_dotp) ||
                                    (curcol < term.t_ncol - 1)) {
                                         vtmove(i, 0);
                                         for (j = 0; j < llength(lp); ++j)
                                                 vtputc(lgetc(lp, j));
                                         vteeol();

                                         /* this line no longer is extended */
                                         vscreen[i]->v_flag &= ~VFEXT;
                                         vscreen[i]->v_flag |= VFCHG;
                                 }
                         }
                         lp = lforw(lp);
                         ++i;
                 }
                 /* and onward to the next window */
                 wp = wp->w_wndp;
         }
 }

 /*        updgar:        if the screen is garbage, clear the physical screen
                 the virtual screen and force a full update                */

 updgar()

 {
         register char *txt;
         register int i,j;

         for (i = 0; i < term.t_nrow; ++i) {
                 vscreen[i]->v_flag |= VFCHG;
 #if        REVSTA
                 vscreen[i]->v_flag &= ~VFREV;
 #endif
 #if        COLOR
                 vscreen[i]->v_fcolor = gfcolor;
                 vscreen[i]->v_bcolor = gbcolor;
 #endif
 #if        MEMMAP == 0
                 txt = pscreen[i]->v_text;
                 for (j = 0; j < term.t_ncol; ++j)
                         txt[j] = ' ';
 #endif
         }

         movecursor(0, 0);                 /* Erase the screen. */
         (*term.t_eeop)();
         sgarbf = FALSE;                         /* Erase-page clears */
         mpresf = FALSE;                         /* the message area. */
 #if        COLOR
         mlerase();                        /* needs to be cleared if colored *
 #endif
 }

 /*        updupd:        update the physical screen from the virtual screen

 updupd(force)

 int force;        /* forced update flag */

 {
         register VIDEO *vp1;
         register int i;

         for (i = 0; i < term.t_nrow; ++i) {
                 vp1 = vscreen[i];

                 /* for each line that needs to be updated*/
                 if ((vp1->v_flag & VFCHG) != 0) {
 #if        TYPEAH
                         if (force == FALSE && typahead())
                                 return(TRUE);
 #endif
 #if        MEMMAP
                         updateline(i, vp1);
 #else
                         updateline(i, vp1, pscreen[i]);
 #endif
                 }
         }
         return(TRUE);
 }

 /*        updext: update the extended line which the cursor is currently
                 on at a column greater than the terminal width. The line
                 will be scrolled right or left to let the user see where
                 the cursor is
                                                                 */

 updext()

 {
         register int rcursor;        /* real cursor location */
         register LINE *lp;        /* pointer to current line */
         register int j;                /* index into line */

         /* calculate what column the real cursor will end up in */
         rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
         taboff = lbound = curcol - rcursor + 1;

         /* scan through the line outputing characters to the virtual screen *
         /* once we reach the left edge
         vtmove(currow, -lbound);        /* start scanning offscreen */
         lp = curwp->w_dotp;                /* line to output */
         for (j=0; j<llength(lp); ++j)        /* until the end-of-line */
                 vtputc(lgetc(lp, j));

         /* truncate the virtual line, restore tab offset */
         vteeol();
         taboff = 0;

         /* and put a '$' in column 1 */
         vscreen[currow]->v_text[0] = '$';
 }

 /*
  * Update a single line. This does not know how to use insert or delete
  * character sequences; we are using VT52 functionality. Update the physical
  * row and column variables. It does try an exploit erase to end of line. The
  * RAINBOW version of this routine uses fast video.
  */
 #if        MEMMAP
 /*        UPDATELINE specific code for the IBM-PC and other compatables */

 updateline(row, vp1)

 int row;                /* row of screen to update */
 struct VIDEO *vp1;        /* virtual screen image */

 {
 #if        COLOR
         scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
         vp1->v_fcolor = vp1->v_rfcolor;
         vp1->v_bcolor = vp1->v_rbcolor;
 #else
         if (vp1->v_flag & VFREQ)
                 scwrite(row, vp1->v_text, 0, 7);
         else
                 scwrite(row, vp1->v_text, 7, 0);
 #endif
         vp1->v_flag &= ~(VFCHG | VFCOL);        /* flag this line as changed

 }

 #else

 updateline(row, vp1, vp2)

 int row;                /* row of screen to update */
 struct VIDEO *vp1;        /* virtual screen image */
 struct VIDEO *vp2;        /* physical screen image */

 {
 #if RAINBOW
 /*        UPDATELINE specific code for the DEC rainbow 100 micro        */

     register char *cp1;
     register char *cp2;
     register int nch;

     /* since we don't know how to make the rainbow do this, turn it off */
     flags &= (~VFREV & ~VFREQ);

     cp1 = &vp1->v_text[0];                    /* Use fast video. */
     cp2 = &vp2->v_text[0];
     putline(row+1, 1, cp1);
     nch = term.t_ncol;

     do
         {
         *cp2 = *cp1;
         ++cp2;
         ++cp1;
         }
     while (--nch);
     *flags &= ~VFCHG;
 #else
 /*        UPDATELINE code for all other versions                */

         register char *cp1;
         register char *cp2;
         register char *cp3;
         register char *cp4;
         register char *cp5;
         register int nbflag;        /* non-blanks to the right flag? */
         int rev;                /* reverse video flag */
         int req;                /* reverse video request flag */


         /* set up pointers to virtual and physical lines */
         cp1 = &vp1->v_text[0];
         cp2 = &vp2->v_text[0];

 #if        COLOR
         TTforg(vp1->v_rfcolor);
         TTbacg(vp1->v_rbcolor);
 #endif

 #if        REVSTA | COLOR
         /* if we need to change the reverse video status of the
            current line, we need to re-write the entire line     */
         rev = (vp1->v_flag & VFREV) == VFREV;
         req = (vp1->v_flag & VFREQ) == VFREQ;
         if ((rev != req)
 #if        COLOR
             || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_
 #endif
 #if        HP150
         /* the HP150 has some reverse video problems */
             || req || rev
 #endif
                         ) {
                 movecursor(row, 0);        /* Go to start of line. */
                 /* set rev video if needed */
                 if (rev != req)
                         (*term.t_rev)(req);

                 /* scan through the line and dump it to the screen and
                    the virtual screen array                                */
                 cp3 = &vp1->v_text[term.t_ncol];
                 while (cp1 < cp3) {
                         TTputc(*cp1);
                         ++ttcol;
                         *cp2++ = *cp1++;
                 }
                 /* turn rev video off */
                 if (rev != req)
                         (*term.t_rev)(FALSE);

                 /* update the needed flags */
                 vp1->v_flag &= ~VFCHG;
                 if (req)
                         vp1->v_flag |= VFREV;
                 else
                         vp1->v_flag &= ~VFREV;
 #if        COLOR
                 vp1->v_fcolor = vp1->v_rfcolor;
                 vp1->v_bcolor = vp1->v_rbcolor;
 #endif
                 return(TRUE);
         }
 #endif

         /* advance past any common chars at the left */
         while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
                 ++cp1;
                 ++cp2;
         }

 /* This can still happen, even though we only call this routine on changed
  * lines. A hard update is always done when a line splits, a massive
  * change is done, or a buffer is displayed twice. This optimizes out most
  * of the excess updating. A lot of computes are used, but these tend to
  * be hard operations that do a lot of update, so I don't really care.
  */
         /* if both lines are the same, no update needs to be done */
         if (cp1 == &vp1->v_text[term.t_ncol]) {
                  vp1->v_flag &= ~VFCHG;                /* flag this line is c
                 return(TRUE);
         }

         /* find out if there is a match on the right */
         nbflag = FALSE;
         cp3 = &vp1->v_text[term.t_ncol];
         cp4 = &vp2->v_text[term.t_ncol];

         while (cp3[-1] == cp4[-1]) {
                 --cp3;
                 --cp4;
                 if (cp3[0] != ' ')                /* Note if any nonblank */
                         nbflag = TRUE;                /* in right match. */
         }

         cp5 = cp3;

         /* Erase to EOL ? */
         if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
                 while (cp5!=cp1 && cp5[-1]==' ')
                         --cp5;

                 if (cp3-cp5 <= 3)                /* Use only if erase is */
                         cp5 = cp3;                /* fewer characters. */
         }

         movecursor(row, cp1 - &vp1->v_text[0]);        /* Go to start of line
 #if        REVSTA
         TTrev(rev);
 #endif

         while (cp1 != cp5) {                /* Ordinary. */
                 TTputc(*cp1);
                 ++ttcol;
                 *cp2++ = *cp1++;
         }

         if (cp5 != cp3) {                /* Erase. */
                 TTeeol();
                 while (cp1 != cp3)
                         *cp2++ = *cp1++;
         }
 #if        REVSTA
         TTrev(FALSE);
 #endif
         vp1->v_flag &= ~VFCHG;                /* flag this line as updated */
         return(TRUE);
 #endif
 }
 #endif

 /*
  * Redisplay the mode line for the window pointed to by the "wp". This is the
  * only routine that has any idea of how the modeline is formatted. You can
  * change the modeline format by hacking at this routine. Called by "update"
  * any time there is a dirty window.
  */
 modeline(wp)
     WINDOW *wp;
 {
     register char *cp;
     register int c;
     register int n;                /* cursor position count */
     register BUFFER *bp;
     register i;                        /* loop index */
     register lchar;                /* character to draw line in buffer with *
     register firstm;                /* is this the first mode? */
     char tline[NLINE];                /* buffer for part of mode line */

     n = wp->w_toprow+wp->w_ntrows;              /* Location. */
     vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
 #if        COLOR
     vscreen[n]->v_rfcolor = 0;                        /* black on */
     vscreen[n]->v_rbcolor = 7;                        /* white.....*/
 #endif
     vtmove(n, 0);                               /* Seek to right line. */
     if (wp == curwp)                                /* mark the current buffe
         lchar = '=';
     else
 #if        REVSTA
         if (revexist)
                 lchar = ' ';
         else
 #endif
                 lchar = '-';

     vtputc(lchar);
     bp = wp->w_bufp;

     if ((bp->b_flag&BFCHG) != 0)                /* "*" if changed. */
         vtputc('*');
     else
         vtputc(lchar);

     n  = 2;
     strcpy(tline, " ");                                /* Buffer name. */
     strcat(tline, PROGNAME);
     strcat(tline, " ");
     strcat(tline, VERSION);
     strcat(tline, " (");

     /* display the modes */

         firstm = TRUE;
         for (i = 0; i < NUMMODES; i++)        /* add in the mode flags */
                 if (wp->w_bufp->b_mode & (1 << i)) {
                         if (firstm != TRUE)
                                 strcat(tline, " ");
                         firstm = FALSE;
                         strcat(tline, modename[i]);
                 }
         strcat(tline,") ");

     cp = &tline[0];
     while ((c = *cp++) != 0)
         {
         vtputc(c);
         ++n;
         }

 #if 0
     vtputc(lchar);
     vtputc((wp->w_flag&WFCOLR) != 0  ? 'C' : lchar);
     vtputc((wp->w_flag&WFMODE) != 0  ? 'M' : lchar);
     vtputc((wp->w_flag&WFHARD) != 0  ? 'H' : lchar);
     vtputc((wp->w_flag&WFEDIT) != 0  ? 'E' : lchar);
     vtputc((wp->w_flag&WFMOVE) != 0  ? 'V' : lchar);
     vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
     vtputc(lchar);
     n += 8;
 #endif

     vtputc(lchar);
     vtputc(lchar);
     vtputc(' ');
     n += 3;
     cp = &bp->b_bname[0];

     while ((c = *cp++) != 0)
         {
         vtputc(c);
         ++n;
         }

     vtputc(' ');
     vtputc(lchar);
     vtputc(lchar);
     n += 3;

     if (bp->b_fname[0] != 0)            /* File name. */
         {
         vtputc(' ');
         ++n;
         cp = "File: ";

         while ((c = *cp++) != 0)
             {
             vtputc(c);
             ++n;
             }

         cp = &bp->b_fname[0];

         while ((c = *cp++) != 0)
             {
             vtputc(c);
             ++n;
             }

         vtputc(' ');
         ++n;
         }

     while (n < term.t_ncol)             /* Pad to full width. */
         {
         vtputc(lchar);
         ++n;
         }
 }

 upmode()        /* update all the mode lines */

 {
         register WINDOW *wp;

         wp = wheadp;
         while (wp != NULL) {
                 wp->w_flag |= WFMODE;
                 wp = wp->w_wndp;
         }
 }

 /*
  * Send a command to the terminal to move the hardware cursor to row "row"
  * and column "col". The row and column arguments are origin 0. Optimize out
  * random calls. Update "ttrow" and "ttcol".
  */
 movecursor(row, col)
     {
     if (row!=ttrow || col!=ttcol)
         {
         ttrow = row;
         ttcol = col;
         TTmove(row, col);
         }
     }

 /*
  * Erase the message line. This is a special routine because the message line
  * is not considered to be part of the virtual screen. It always works
  * immediately; the terminal buffer is flushed via a call to the flusher.
  */
 mlerase()
     {
     int i;

     movecursor(term.t_nrow, 0);
     if (discmd == FALSE)
             return;

 #if        COLOR
      TTforg(7);
      TTbacg(0);
 #endif
     if (eolexist == TRUE)
             TTeeol();
     else {
         for (i = 0; i < term.t_ncol - 1; i++)
             TTputc(' ');
         movecursor(term.t_nrow, 1);        /* force the move! */
         movecursor(term.t_nrow, 0);
     }
     TTflush();
     mpresf = FALSE;
     }

 /*
  * Write a message into the message line. Keep track of the physical cursor
  * position. A small class of printf like format items is handled. Assumes th
  * stack grows down; this assumption is made by the "++" in the argument scan
  * loop. Set the "message line" flag TRUE.
  */

 mlwrite(fmt, arg)

 char *fmt;        /* format string for output */
 char *arg;        /* pointer to first argument to print */

 {
         register int c;                /* current char in format string */
         register char *ap;        /* ptr to current data field */

         /* if we are not currently echoing on the command line, abort this */
         if (discmd == FALSE) {
                 movecursor(term.t_nrow, 0);
                 return;
         }

 #if        COLOR
         /* set up the proper colors for the command line */
         TTforg(7);
         TTbacg(0);
 #endif

         /* if we can not erase to end-of-line, do it manually */
         if (eolexist == FALSE) {
                 mlerase();
                 TTflush();
         }

         movecursor(term.t_nrow, 0);
         ap = (char *) &arg;
         while ((c = *fmt++) != 0) {
                 if (c != '%') {
                         TTputc(c);
                         ++ttcol;
                 } else {
                         c = *fmt++;
                         switch (c) {
                                 case 'd':
                                         mlputi(*(int *)ap, 10);
                                         ap += sizeof(int);
                                         break;

                                 case 'o':
                                         mlputi(*(int *)ap,  8);
                                         ap += sizeof(int);
                                         break;

                                 case 'x':
                                         mlputi(*(int *)ap, 16);
                                         ap += sizeof(int);
                                         break;

                                 case 'D':
                                         mlputli(*(long *)ap, 10);
                                         ap += sizeof(long);
                                         break;

                                 case 's':
                                         mlputs(*(char **)ap);
                                         ap += sizeof(char *);
                                         break;

                                 case 'f':
                                         mlputf(*(int *)ap);
                                         ap += sizeof(int);
                                         break;

                                 default:
                                         TTputc(c);
                                         ++ttcol;
                         }
                 }
         }

         /* if we can, erase to the end of screen */
         if (eolexist == TRUE)
                 TTeeol();
         TTflush();
         mpresf = TRUE;
 }

 /*        Force a string out to the message line regardless of the
         current $discmd setting. This is needed when $debug is TRUE
         and for the write-message and clear-message-line commands
 */

 mlforce(s)

 char *s;        /* string to force out */

 {
         register oldcmd;        /* original command display flag */

         oldcmd = discmd;        /* save the discmd value */
         discmd = TRUE;                /* and turn display on */
         mlwrite(s);                /* write the string out */
         discmd = oldcmd;        /* and restore the original setting */
 }

 /*
  * Write out a string. Update the physical cursor position. This assumes that
  * the characters in the string all have width "1"; if this is not the case
  * things will get screwed up a little.
  */
 mlputs(s)
     char *s;
     {
     register int c;

     while ((c = *s++) != 0)
         {
         TTputc(c);
         ++ttcol;
         }
     }

 /*
  * Write out an integer, in the specified radix. Update the physical cursor
  * position.
  */
 mlputi(i, r)
     {
     register int q;
     static char hexdigits[] = "0123456789ABCDEF";

     if (i < 0)
         {
         i = -i;
         TTputc('-');
         }

     q = i/r;

     if (q != 0)
         mlputi(q, r);

     TTputc(hexdigits[i%r]);
     ++ttcol;
     }

 /*
  * do the same except as a long integer.
  */
 mlputli(l, r)
     long l;
     {
     register long q;

     if (l < 0)
         {
         l = -l;
         TTputc('-');
         }

     q = l/r;

     if (q != 0)
         mlputli(q, r);

     TTputc((int)(l%r)+'0');
     ++ttcol;
     }

 /*
  *        write out a scaled integer with two decimal places
  */

 mlputf(s)

 int s;        /* scaled integer to output */

 {
         int i;        /* integer portion of number */
         int f;        /* fractional portion of number */

         /* break it up */
         i = s / 100;
         f = s % 100;

         /* send out the integer portion */
         mlputi(i, 10);
         TTputc('.');
         TTputc((f / 10) + '0');
         TTputc((f % 10) + '0');
         ttcol += 3;
 }

 #if RAINBOW

 putline(row, col, buf)
     int row, col;
     char buf[];
     {
     int n;

     n = strlen(buf);
     if (col + n - 1 > term.t_ncol)
         n = term.t_ncol - col + 1;
     Put_Data(row, col, n, buf);
     }
 #endif



 DOLOCK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\DOLOCK.C

 #if        0
 /*        dolock:        MDBS specific Unix 4.2BSD file locking mechinism
                 this is not to be distributed generally                */

 #include        <mdbs.h>
 #include        <mdbsio.h>
 #include        <sys/types.h>
 #include        <sys/stat.h>

 /* included by port.h: mdbs.h, mdbsio.h, sys/types.h, sys/stat.h */


 #ifndef bsdunix
 char *dolock(){return(NULL);}
 char *undolock(){return(NULL);}
 #else

 #include <pwd.h>
 #include <errno.h>

 extern int errno;

 #define LOCKDIR ".xlk"

 #define LOCKMSG "LOCK ERROR -- "
 #define LOCKMSZ sizeof(LOCKMSG)
 #define LOCKERR(s) { strcat(lmsg,s); oldumask = umask(oldumask); return(lmsg)

 /**********************
  *
  * dolock -- lock the file fname
  *
  * if successful, returns NULL
  * if file locked, returns username of person locking the file
  * if other error, returns "LOCK ERROR: explanation"
  *
  * Jon Reid, 2/19/86
  *
  *********************/

 BOOL parent = FALSE;
 BOOL tellall = FALSE;

 char *gtname(filespec)                /* get name component of unix-style fil
 char *filespec;
 {
         char *rname, *rindex();

         rname = rindex(filespec,'/');

         if (rname != NULL)
                 return(rname);
         else
                 return(filespec);
 }

 char *getpath(filespec)
 char *filespec;
 {
         char rbuff[LFILEN];
         char *rname, *rindex();

         strcpy(rbuff,filespec);
         rname = rindex(rbuff,'/');

         if (rname == NULL)
                 return(NULL);
         else
         {
                 *(++rname) = '\0';
                 return(rbuff);
         }

 }

 char *dolock(fname)
         char *fname;
 {
         static char lockname[LFILEN] = LOCKDIR;
         static char username[12];
         static char lmsg[40] = LOCKMSG;
         char *pathfmt;
         struct stat statblk;
         struct passwd *pblk;
         long pid, getpid();
         FILE *lf, *fopen();
         int oldumask;

         oldumask = umask(0);        /* maximum access allowed to lock files *


           if (*fname != '/')
            pathfmt = "./%s%s";
           else
            pathfmt = "%s/%s";
           sprintf(lockname,pathfmt,getpath(fname), LOCKDIR);

           if (tellall) printf("checking for existence of %s\n",lockname);

           if (stat(lockname,&statblk))
           {
                  if (tellall) printf("making directory %s\n",lockname);
                  mkdir(lockname,0777);
           }

           sprintf(lockname,"%s/%s",lockname,gtname(fname));

           if (tellall) printf("checking for existence of %s\n",lockname);

           if (stat(lockname,&statblk))
           {
 makelock:          if (tellall) printf("creating %s\n",lockname);

                 if ((lf = fopen(lockname,FOP_TW)) == NULL)
                   LOCKERR("could not create lock file")
                 else
                   {
                         if (parent)
                          pid = getppid();        /* parent pid */
                         else
                          pid = getpid();        /* current pid */

                          if (tellall)
                           printf("pid is %ld\n",pid);

                          fprintf(lf,"%ld",pid); /* write pid to lock file */

                         fclose(lf);
                         oldumask = umask(oldumask);
                         return(NULL);
                 }
           }
           else
           {
                 if (tellall) printf("reading lock file %s\n",lockname);
                 if ((lf = fopen(lockname,FOP_TR)) == NULL)
                   LOCKERR("could not read lock file")
                 else
                   {
                         fscanf(lf,"%ld",&pid); /* contains current pid */
                         fclose(lf);
                         if (tellall)
                          printf("pid in %s is %ld\n",lockname, pid);
                         if (tellall)
                          printf("signaling process %ld\n", pid);
                         if (kill(pid,0))
                                 switch (errno)
                                 {
                                   case ESRCH:        /* process not found */
                                                 goto makelock;
                                                 break;
                                   case EPERM:        /* process exists, not y
                                                  if (tellall)
                                                  puts("process exists");
                                                 break;
                                   default:
                                         LOCKERR("kill was bad")
                                         break;
                                 }
                         else
                          if (tellall) puts("kill was good; process exists");
                 }
                 if ((pblk = getpwuid(statblk.st_uid)) == NULL)
                   sprintf(username,"uid %d",atoi(statblk.st_uid));
                 else
                   strcpy(username,pblk->pw_name);

                 oldumask = umask(oldumask);
                 return(username);
           }
 }

 /**********************
  *
  * undolock -- unlock the file fname
  *
  * if successful, returns NULL
  * if other error, returns "LOCK ERROR: explanation"
  *
  * Jon Reid, 2/19/86
  *
  *********************/

 char *undolock(fname)
         char *fname;
 {
         static char lockname[LFILEN] = LOCKDIR;
         static char lmsg[40] = LOCKMSG;
         char *pathfmt;

           if (*fname != '/')
            pathfmt = "./%s%s";
           else
            pathfmt = "%s/%s";
           sprintf(lockname,pathfmt,getpath(fname), LOCKDIR);

           sprintf(lockname,"%s/%s",lockname,gtname(fname));

           if (tellall) printf("attempting to unlink %s\n",lockname);

           if (unlink(lockname))
           {
                 strcat(lmsg,"could not remove lock file");
                 return(lmsg);
           }
           else
                     return(NULL);
 }

 #endif

 /******************
  * end dolock module
  *******************/

 #else
 dolhello()
 {
 }
 #endif



 DOSDATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\DOSDATE.C

 #include <dos.h>
 dosdate(date)
 char date[];
 {
          char mon[3],
                  day[3],
                  yy[5];
         union REGS DREG;
         DREG.h.ah=0x2a;
         intdos(&DREG.h,&DREG.h);
         stcu_d(mon,DREG.h.dh,3);
         stcu_d(day,DREG.h.dl,3);
         stcu_d(yy,DREG.x.cx,5);
         strcpy(date,mon);
         strcat(date,"-");
         strcat(date,day);
         strcat(date,"-");
         strcat(date,yy);

 }



 DOSEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DOSEX.C

 /******************************************************************/
 /* This is an example program to illustrate how to;               */
 /*  1. Get the time and date from DOS                             */
 /*  2. Set the cursor to any position on the screen               */
 /*  3. Read characters from the keyboard and display their codes  */
 /*  4. How to scroll a window up on the monitor                   */
 /*  5. Format a program for ease of reading and understanding     */
 /*  6. How to do proper prototyping                               */
 /******************************************************************/

 void draw_box(void);
 void disp_char(int inchar);
 void get_time(int *hour,int *minute,int *second);
 void disp_time_date(void);
 void pos_cursor(char row,char column);
 void scroll_window(void);

 #include "stdio.h"
 #include "dos.h"
 #include "conio.h"

 int main()
 {
 int hour, minute, sec, old_sec;
 int character;

    draw_box();              /* draw the boxes around the fields */
    old_sec = 0;             /* this variable stores the old time
                                so we can look for a change      */

    do {
       if (kbhit()) {                     /* has a key been hit? */
          character = getch();            /* read it in          */
          disp_char(character);           /* display it          */
       }

       get_time(&hour,&minute,&sec);      /* get the time of day */
       if (sec != old_sec) {              /* if it has changed,  */
          disp_time_date();               /* update the display  */
          old_sec = sec;                  /* save new time       */
       }

    } while (character != 'Q');        /* Quit when a Q is found */

    pos_cursor(0,0);              /* put cursor at top of screen */
 }


 /* **************************************************** drawbox */
 /* This routine draws a box on the screen. The keys hit, and    */
 /* the time and date are displayed in these boxes. There is     */
 /* nothing special about these boxes, they are simply output    */
 /* using the printf function.                                   */
 /* ************************************************************ */
 void draw_box(void)
 {
 int index;
 char line[81];

    for (index = 0;index < 80;index++)       /* three blank rows */
       line[index] = ' ';
    line[80] = NULL;                            /* end of string */
    for (index = 0;index < 3;index++)
       printf("%s",line);

    line[8] = 201;                       /* draw top line of box */
    for (index = 9;index < 70;index++)
       line[index] = 205;
    line[70] = 187;
    printf("%s",line);

    line[8] = 186;                    /* draw sides of large box */
    for (index = 9;index < 70;index++)
       line[index] = ' ';
    line[70] = 186;
    for (index = 0;index < 15;index++)
       printf("%s",line);

    line[8] = 204;                    /* draw line between boxes */
    for (index = 9;index < 70;index++)
       line[index] = 205;
    line[70] = 185;
    printf("%s",line);

    line[8] = 186;                    /* sides for time/date box */
    for (index = 9;index < 70;index++)
       line[index] = ' ';
    line[70] = 186;
    printf("%s",line);

    line[8] = 200;                     /* bottom line of the box */
    for (index = 9;index < 70;index++)
       line[index] = 205;
    line[70] = 188;
    printf("%s",line);

    for (index = 0;index < 80;index++)       /* three blank rows */
       line[index] = ' ';
    for (index = 0;index < 3;index++)
       printf("%s",line);

 }


 /* ************************************************** disp_char */
 /* This routine displays the characters hit on the monitor. If  */
 /* the first character is a zero, a special character has been  */
 /* hit, and the zero is displayed. The next character is read,  */
 /* and it is displayed on the monitor.                          */
 /* ************************************************************ */
 void disp_char(int inchar)
 {
    scroll_window();
    pos_cursor(17,15);          /* position of message on screen */

    if(inchar == 0) {
       printf(" 00 ");            /* a special character was hit */
       inchar = getch();          /* get the next part of it     */
       switch (inchar) {
          case 59  :
          case 60  :
          case 61  :
          case 62  :
          case 63  :              /* these are the function keys */
          case 64  :
          case 65  :
          case 66  :
          case 67  :
          case 68  : printf("%4d Function key F%d\n",inchar,inchar-58);
                     break;

          case 94  :
          case 95  :
          case 96  :
          case 97  :
          case 98  :         /* these are the ctrl-function keys */
          case 99  :
          case 100 :
          case 101 :
          case 102 :
          case 103 : printf("%4d Function key Ctrl-F%d\n",inchar,
                        inchar-93);
                     break;

          case 84  :
          case 85  :
          case 86  :
          case 87  :        /* these are the upper-function keys */
          case 88  :
          case 89  :
          case 90  :
          case 91  :
          case 92  :
          case 93  : printf("%4d Function key Upper-F%d\n",inchar,
                        inchar-83);
                     break;

          case 104 :
          case 105 :
          case 106 :
          case 107 :
          case 108 :          /* these are the alt-function keys */
          case 109 :
          case 110 :
          case 111 :
          case 112 :
          case 113 : printf("%4d Function key Alt-F%d\n",inchar,
                        inchar-103);
                     break;

          default  : printf("%4d Special key hit\n",inchar);
       }

    } else                        /* a regular character was hit */
       printf("    %4d (%c) Character Hit.\n",inchar,inchar);

    pos_cursor(25,1);        /* hide the cursor on the 26th line */
 }


 /* *************************************************** get_time */
 /* This routine calls the DOS function call for time of day. It */
 /* returns the time of day to the calling program in the three  */
 /* pointers used in the call.                                   */
 /* ************************************************************ */
 void get_time(int *hour,int *minute,int *second)
 {
 union REGS inregs;
 union REGS outregs;

    inregs.h.ah = 44;               /* Hex 2C - Get current time */
    int86(0x21,&inregs,&outregs);
    *hour = outregs.h.ch;
    *minute = outregs.h.cl;
    *second = outregs.h.dh;
 }


 /* ********************************************* disp_time_date */
 /* This routine displays the time and date on the monitor in a  */
 /* fixed position. It gets the time from the get_time function, */
 /* and gets the date from its own built in DOS call. Good       */
 /* programming practice would move the date to another function */
 /* but this is an illustrative example to display methods of    */
 /* doing things. This routine also calls the cursor positioning */
 /* function to put the time and date where we want them.        */
 /* ************************************************************ */
 void disp_time_date(void)
 {
 int hour, minute, second;
 union REGS inregs;
 union REGS outregs;

    pos_cursor(19,19);  /* position the cursor for date and time */

    inregs.h.ah = 42;              /* hex 2A - What is the date? */
    int86(0x21,&inregs,&outregs);  /* interrupt 21               */
    printf("Date = %2d/%2d/%2d    ",
       outregs.h.dh,                 /* month - 1 to 12          */
       outregs.h.dl,                 /* day - 1 to 31            */
       outregs.x.cx);                /* year - 1980 to 2099      */

    get_time(&hour, &minute, &second);
    printf("Time = %2d:%2d:%2d\n",hour, minute, second);

    pos_cursor(25,1);        /* hide the cursor on the 26th line */
 }

 /* ************************************************* pos_cursor */
 /* This routine positions the cursor at the requested row and   */
 /* column. The upper left corner is row 0 and column 0          */
 /* ************************************************************ */
 void pos_cursor(char row,char column)
 {
 union REGS inregs;
 union REGS outregs;

    inregs.h.ah = 2;        /* service 2 - position the cursor   */
    inregs.h.dh = row;
    inregs.h.dl = column;
    inregs.h.bh = 0;
    int86(0x10,&inregs,&outregs);                /* interrupt 10 */
 }


 /* ********************************************** scroll_window */
 /* This routine scrolls all of the material in the key hit      */
 /* window up one space leaving room for another entry.          */
 /* ************************************************************ */
 void scroll_window(void)
 {
 union REGS inregs;
 union REGS outregs;

    inregs.h.ah = 6;      /* service 6 - scroll window           */
    inregs.h.al = 1;      /* number of lines to scroll           */
    inregs.h.ch = 3;      /* top row of window                   */
    inregs.h.cl = 9;      /* left column of window               */
    inregs.h.dh = 17;     /* bottom row of window                */
    inregs.h.dl = 69;     /* right column of window              */
    inregs.h.bh = 7;      /* attribute of blank line             */
    int86(0x10,&inregs,&outregs);                /* interrupt 10 */

 }


 DOSTIME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\DOSTIME.C

 /********************************************************
  *  THIS FUNCTION DOES A CALL TO THE MS-DOS OPERATING   *
  *  SYSTEM AND RETURNS THE TIME.  YOU SHOULD PASS A 11  *
  *  CHARACTER ARRAY ADDRESS TO THE FUNCTION IN  WHICH
  *  THE TIME WILL BE PLACED UPON RETURN.  THE CALL IS   *
  *  AS FOLLOWS.
  *                char time[11];
  *                                         dostime(time);
  *  TIME WILL HAVE THE SYSTEM TIME IN IT IN THE FORM    *
  *                HH:MM:SS:HH                           *
  *  HAVE FUN AND GOOD LUCK                              *
  *                                                      *
  *                LYNN LONG                             *
  *                TULSA IBBS C-SIG                      *
  *                1200 BAUD, 24 HOURS                   *
  *                SUBSCRIPTION BBS                      *
  *                918-749-0718                          *
  ********************************************************/

 #include <dos.h>
 dostime(time)
 char time[];
 {
         char hr[3],
                  mm[3],
                  ss[3],
                  hh[3];
         struct HREG TREG;
         TREG.ah=0x2c;
         intdos(&TREG,&TREG);
          stcu_d(hr,TREG.ch,3);
         stcu_d(mm,TREG.cl,3);
         stcu_d(ss,TREG.dh,3);
         stcu_d(hh,TREG.dl,3);
         strcpy(time,hr);
         strcat(time,":");
         strcat(time,mm);
         strcat(time,":");
         strcat(time,ss);
         strcat(time,":");
         strcat(time,hh);

 }



 DOWHILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DOWHILE.C

                                           /* Chapter 3 - Program 2 */
 /* This is an example of a do-while loop */

 main()
 {
 int i;

    i = 0;
    do {
       printf("The value of i is now %d\n",i);
       i = i + 1;
    } while (i < 5);
 }


 DRAW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\DRAW.C

 /* DRAW.C - A program from Microsoft C Programming for the IBM  */
 /* by Robert Lafore, page 260. Press the arrow keys to move     */
 /* cursor and leave trail.                                      */
 /****************************************************************/

 #define CLEAR "\x1B[2J"
 #define C_LEFT "\x1B[D"
 #define C_RITE "\x1B[C"
 #define C_UPUP "\x1B[A"
 #define C_DOWN "\x1B[B"
 #define L_ARRO 75
 #define R_ARRO 77
 #define U_ARRO 72
 #define D_ARRO 80
 #define ACROSS 205
 #define UPDOWN 186

 main()
 {
 int key;

    printf(CLEAR);
    while((key = getch()) == 0) {
       key = getch();
       switch(key) {
          case L_ARRO:
             printf(C_LEFT);
             putch(ACROSS);
             break;
          case R_ARRO:
             printf(C_RITE);
             putch(ACROSS);
             break;
          case U_ARRO:
             printf(C_UPUP);
             putch(UPDOWN);
             break;
          case D_ARRO:
             printf(C_DOWN);
             putch(UPDOWN);
             break;
       }
       printf(C_LEFT);
    }
 }





 DSKERRMS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\DSKERRMS.C

 /****************************************************************************
 *
 *  return pointer to error message, based on bios return code
 *
 *****************************************************************************
 char *dskerrmsg(error_num)
 char error_num;
 {

 int j=0;
 static char *ferr [] = { "\xe0Status",
                          "\xccWrite Fault",
                          "\xbbUndefined",
                          "\xaaNot Ready",
                          "\x80Fail Respond",
                          "\x40Bad Seek",
                          "\x20Controller",
                          "\x11ECC Corrected",
                          "\x10CRC",
                          "\x0aBad Sector Flag",
                          "\x09DMA Boundary",
                          "\x08DMA",
                          "\x07Parm Activity",
                          "\x06Media Change",
                          "\x05Reset",
                          "\x04Sector Not Found",
                          "\x03Write Protect",
                          "\x02Addr Mark",
                          "\x01Parameter",
                          "\x00Unknown" };
   while (*ferr[j])
     {
     if (error_num == *ferr[j]) break;
     j++;
     }
   return((ferr[j]+1));
 }


 DSKTST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\DSKTST.C

 #include <stdio.h>
 #include <dos.h>

 extern char *dskerrmsg();
 union xxx {
   char secbuffer [512];

   struct hdr {
     char spare [11];
     int  sectorsize;
     char clustersize;
     int  reserved_sectors;
     char number_of_fats;
     int  root_entries;
     unsigned  total_sectors;
     char media_type;
     int  fat_size;
     int  track_size;
     int  head_count;
     unsigned  hidden_sectors;
     } dh;

   struct ptab {
     char spare[446];
     char boot_ind;
     char br_head;
     char br_sect;
     char br_cyl;
     } pt;

 };

 union xxx db;




 main(argc, argv)
 int argc;
 char **argv;


 {
 char diskdrive[128];
 int total_errors = 0;                   /* total bad sectors */
 int drive = 0;
 int head = 0;
 int cyl = 0;
 int rec = 0;
 int err, i, cyl_count;
 char *trakbuf;                           /* buffer for the track - allocated
 int row = 0;
 int col = 0;                           /* current cursor position */
 char media = 0;

 /****************************************************************************
 *
 *  read the input parameter string to determine drive
 *
 *****************************************************************************
 printf("Diskette/Fixed disk verifier program\n");
 printf("Non-Copyrighted -- by Bob Murphy\n");

 diskdrive[0] = '\0';               /* null the string */
 if (argc > 1)
   {
   char **p;
   p=argv;                           /* p points to first argument pointer */
   p++;                                   /* point to drive id */
   strcpy(diskdrive,*p);            /* copy the drive id */
   i = strlen(diskdrive);           /* get the length */
   while(i >= 0)
     {                                   /* convert to upper case */
     if (diskdrive[i] >= 'a' && diskdrive[i] <= 'z')
         diskdrive[i] = (diskdrive[i] - 32);
     i--;
     }
   }
 if (diskdrive[0] >= 'A' && diskdrive[0] <= 'D' && diskdrive[1] == ':')
   drive = diskdrive[0] - 'A';
 else
   { drive = defdrv();
     strcpy(diskdrive,"A:");
     diskdrive[0] = 'A' + drive;
   }
 media = getfatid(drive+1);           /* find out if its a hard disk */
 if (media == (char) 0xf8)  drive = (drive - 2) | 0x80; /* if yes - set hard *



 locate(row,col);
 clrcrt(7);                         /* erase & home, color = w on bk */
 printf("Drive %s\n",diskdrive);

 /****************************************************************************
 *
 *  read in the first record from the disk
 *
 *****************************************************************************
 i=3;                                   /* allow 3 retries */
 while (i)
 {
   err = absread(drive,0,0,1,1,&db);    /* read sector 1, first track */
   if (! err) break;
   i--;
 }


 if ((! err) && (drive == 0x80))
   {
   char *ptptr;                           /* partition table pointer */
   ptptr = &db.pt.boot_ind;           /* point to boot indicator */
   i = 4; err=0xffff;
   while (i)
     {
     if (*ptptr == (char) 0x80)
       {
       head = *(++ptptr);             /* read starting head from part table */
       i = *(++ptptr);                  /* read starting sec from part table *
       cyl  = *(++ptptr);             /* read starting cyl from part table */
       rec = (i & 0x3f);              /* strip out cylinder bits */
       cyl = ((i & 0xc0) << 2) + cyl; /* set up the cylinder */
       err = 0;
       break;
       }
     i--; ptptr = ptptr + 16;

     }                                   /* end while */
     if (! err) err = absread(drive,cyl,head,rec,1,&db); /* read dos boot rec
   }                                   /* endif */
 if (db.dh.track_size == 0 && err == 0) err = 0xff; /*err ff = wierd disk */
 /*



 */
 if (! err)
   {
   char mdb[5];                           /* scratchpad for media descriptor *
   sprintf(&mdb[0],"%x",media);
   printf("%u Reserved Sector(s)\n",db.dh.reserved_sectors);
   printf("%u Bytes / sector\n",db.dh.sectorsize);
   printf("%u Allocation Tables\n",db.dh.number_of_fats);
   printf("%u Root Directory Entries\n",db.dh.root_entries);
   printf("%u Total DOS Sectors\n",db.dh.total_sectors);
   printf("%u Sectors in a FAT\n",db.dh.fat_size);
   printf("%u Sectors / Track\n",db.dh.track_size);
   printf("%u Surfaces\n",db.dh.head_count);
   printf("%u Hidden Sectors\n",db.dh.hidden_sectors);
   printf("%s Media Descriptor\n",&mdb [2]);
   }
 else
   printf("%s Error reading boot sector -- program aborting\n",dskerrmsg(err))


 /****************************************************************************
 *
 *  allocate track buffer, and read tracks looking for errors
 *
 *****************************************************************************

 if (! err)
   {
   i = db.dh.track_size * db.dh.sectorsize; /* buffer size for 1 track */
   trakbuf = malloc(i);                           /* allocate buffer */
   cyl_count = (db.dh.total_sectors / db.dh.track_size /db.dh.head_count);

   while (cyl < cyl_count)
     {
     csrpos(&row,&col);               /* get current cursor */
     printf("cyl=%d",cyl);
     locate(row,col);
     err = absread(drive,cyl,head++,1,db.dh.track_size,trakbuf);
     if (err)
       {
       head--;                           /* reset head back to correct surface
       i = 1;                           /* current sector number */
       while (i <= db.dh.track_size)
         {
         err = absread(drive,cyl,head,i,1,trakbuf);  /* READ 1 SECTOR */
         if (err)
           {
           char *mptr;
           mptr = dskerrmsg(err);
           printf("%s Error -- Cyl %d Head %d Record %d\n",mptr,cyl,head,i);
           total_errors++;
           }

         i++;                           /* bump current sector */
         }
       head++;                           /* set head to next surface */
       }                            /* end of if (err) */
     if (head >= db.dh.head_count) { head = 0; cyl++; }
     }                                   /* end of while (cyl <= cyl_count) */

   if (total_errors) printf("          \n%d Total Bad Sectors\n",total_errors)
   else printf("          \nDiskette is error free\n");

   }                                   /* end of if (! err) */

 }                                   /* end of main */


 DU.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TOOLS\DU.C

 /*
  *  Attribute bits:
  *      d - directory
  *      r - read only file
  *      h - hidden file
  *      s - system file
  *      a - archive bit
  *
  *  Files within each directory are sorted alphabetically.
  *  Directories are listed separate from other files.
  */

 <stdio.h>              /* Standard I/O definitions */
 <ctype.h>              /* Character type macros */
 <dos.h>                /* Msdos definitions */
 <errno.h>              /* error codes */
 #include <string.h>
 #include <malloc.h>

 A_RONLY         0x01    /* Read only file */
 A_HIDDEN        0x02    /* Hidden file */
 A_SYSTEM        0x04    /* System file */
 A_DIRECTORY     0x10    /* Directory file */
 A_ARCHIVE       0x20    /* Archive bit */

 static char ID[]="## du.c 1.0 K.van Houten 092387 ##";
 struct date {
 unsigned    d_sec:      5;      /* Time, 2 second intervals */
 unsigned    d_min:      6;      /* Time, minutes */
 unsigned    d_hour:     5;      /* Time, hours */
 unsigned    d_day:      5;      /* Date, day of month */
 unsigned    d_month:    4;      /* Date, month of year */
 unsigned    d_year:     7;      /* Date, year since 1980 */
 };
 struct find {
     char    fnd_dosinfo[21];    /* Reserved for dos */
     char    fnd_attr;           /* File attribute */
     struct date fnd_date;       /* Date structure */
     long    fnd_size;           /* File size */
     char    fnd_name[13];       /* File name less path */
 };
 long addir();
 struct find f;                  /* Used to return data from msdos */
 union REGS r, o;                /* Contains register values for intcall() */
 int   tmp, i;
 int bsize=8*1024;               /* size of disk allocation */
 int kpb;                        /* Kbytes per block */
 int     sflg = 0;               /* summarize */
 long total;
 extern int clsize();            /* get cluster size */

 main (argc, argv)
 int     argc;                   /* Number of command line arguments */
 char   *argv[];                 /* Array of pointers to arguments */
 {
     char    buf[70];
     bsize=clsize(defdrv());
     kpb=bsize/1024;

     for (argc--,argv++; argc>0; argc--,argv++) {
         if (**argv == '-') {
             while (*++(*argv)) {
                 switch (**argv) {
                 case 's':
                     sflg++;
                     break;
                 default:
                     printf("Usage: du directory\n");
                     exit(1);
                 }
             }
         }
         else
             break;
     }

     r.h.ah = 0x1a;              /* SET DISK TRANSFER ADDRESS FUNCTION */
     r.x.dx = (int) & f;
     tmp = intdos (&r, &o);
 /*  Produces error 0 ???
     if (o.x.cflag) {
         perror ("SETTING DTA ");
         exit (1);
     }
 */
     if (argc == 0) {
         total=addir(".");
     }
     else {
         findf(*argv);
         if (o.x.cflag) {
             printf("du: entry not found\n");
             exit(1);
         }
         if (!(f.fnd_attr & A_DIRECTORY)) {
             printf("du: %s: not a directory\n",f.fnd_name);
             exit(1);
         }
         total=addir(*argv);
     }
     if (sflg) {
         if (argc) {
             printf("%10ld %s\n",kpb*total,strlwr(*argv));
         }
         else {
             printf("%10ld .\n",kpb*total);
         }
     }
 }

 long
 addir(dir)
 char *dir;
 {
     char *dirlist[100];  /* for subdirs */
     char buf[100];       /* for filename */
     int dircnt=0;        /* nr of subdirs */
     int i;
     long dtot=0;         /* total of this level */

     strcpy(buf,dir);
     strcat(buf,"/*.*");
 /*    printf("Scanning %s\n",dir); */
     findf(buf);
     while (o.x.cflag == 0) {
         if (f.fnd_attr & A_DIRECTORY) {
             if (!(*f.fnd_name == '.')) {
                 dirlist[dircnt]=malloc(sizeof(f.fnd_name)+1);
                 if (dirlist[dircnt] == NULL) {
                     perror("du ");
                     exit(1);
                 }
                 strcpy(dirlist[dircnt++],f.fnd_name);
             }
         }
         else {
           dtot+=((f.fnd_size%bsize)?(f.fnd_size/bsize+1):(f.fnd_size/bsize));
         }
         findn();
     }
     /* all entrys done,
      * now scan subdirs.
      */
     for(i=0;i<dircnt;i++) {
         strcpy(buf,dir);
         strcat(buf,"/");
         strcat(buf,dirlist[i]);
 /*        printf("nesting: %s\n",buf); */
         dtot += addir(buf);
     }
     if (sflg ==0)
         printf("%10ld %s\n",kpb*dtot,strlwr(dir));
     return(dtot);
 }

 /*
  * Find first entry, return info in find structure.
  */
 findf (file)
 char *file;
 {
     r.h.ah = 0x4e;              /* FINDFIRST function */
     r.x.cx = A_HIDDEN | A_SYSTEM | A_DIRECTORY |
         A_RONLY | A_ARCHIVE;
     r.x.dx = (int) file;
     tmp = intdos (&r, &o);      /* Find first */
 }

 /*
  * Find next entry
  */
 findn ()
 {
     r.h.ah = 0x4f;              /* Now use FINDNEXT function */
     tmp = intdos (&r, &o);      /* Find next */
 }

 int
 defdrv()
 {
     int tmp;
     union REGS r;

     r.h.ah = 0x19;  /* get default drive */
     tmp = intdos(&r,&r);
     if (r.x.cflag != 0) {
         printf("Error reading def. drive: %d\n",tmp);
         exit(1);
     }
     return(r.h.al);
 }


 DUMBCONV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DUMBCONV.C

                                         /* Chapter 3 - Program 9 */
 main()
 {
 int x1,x2,x3;

    printf("Centigrade to Farenheit temperature table\n\n");

    for(x1 = -2;x1 <= 12;x1 = x1 + 1){
       x3 = 10 * x1;
       x2 = 32 + (x3 * 9)/5;
       printf("  C =%4d   F =%4d  ",x3,x2);
       if (x3 == 0)
          printf(" Freezing point of water");
       if (x3 == 100)
          printf(" Boiling point of water");
       printf("\n");
    }
 }


 DUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\DUMP.C

 /*
 **                HEX FILE DUMP UTILITY
 **   Displays any file in hex and character representation
 **   in color or monochrome, depending upon type of video
 **   card installed.  Displays 20 lines per screen and waits
 **   for a keypress.
 **
 **   This program was originally distributed by Datalight with
 **   the Datalight C Developer's Kit.  The program has been
 **   extensively modified by Steven E. Margison, Downers Grove, IL.
 **   It is placed into the public domain by S.E. Margison, with the
 **   understanding of all users that portions may be copyrighted
 **   by Datalight and/or others.  No charge may be made for this
 **   program under any circumstances.  Exception: a copying charge
 **   may be made if this program is included on a disk with other
 **   PD or shareware programs.
 **
 **   Rev 1.10   3-16-87  S.E. Margison
 **
 **   As distributed, this program requires (for compilation):
 **     "Steve's Datalight Library" version 1.10 or later
 **   which may be obtained without registration from many Bulletin
 **   Board Systems including:
 **      Compuserve IBMSW
 **      Cul-De-Sac (Holliston, MA.)
 **      HAL-PC BBS (Houston, TX.)
 **   and software library houses including:
 **      Public (Software) Library (Houston, TX.)
 **
 **   or by registration:
 **      $10 for Docs, Small Model Library
 **      $25 for Docs, S, D, L, P libraries, and complete library source
 **              in C and Assembler
 **     Steven E. Margison
 **     124 Sixth Street
 **     Downers Grove, IL, 60515
 **
 **
 ** Program requires at least one parameter, the name of the file to dump.
 ** A second parameter is taken to be an offset value to start dumping,
 ** default is the start of the file.  If a third value is present it is
 ** taken to be a hex byte value to highlite whenever encountered in the file.
 */

 #include <stdio.h>
 #include <ctype.h>
 #include <smdefs.h>
 #include <screen.h>

 int adrclr,    /* address field color */
     hexclr,    /* hex data color */
     highclr,   /* highlite color */
     prompt,    /* prompt line color */
     ascclr;    /* ascii color */

 main(argc,argv)
 int argc;
 char *argv[];
 {
    FILE *f;
    int i, buffer[16], lines, view, vflag;
    unsigned long offset = 0;

    vflag = NO;      /* default highlite off */

    if ((argc < 2) or (argc > 4))
       error("Use: dump file [starting offset in hex] [highlite byte]");

    if((f = fopen(argv[1], "rb")) is NULL) cant(argv[1]);

    if (argc > 2) {  /* get an offset if so indicated */
       sscanf(argv[2],"%lx",&offset);
       fseek(f,offset,0);
       }

    if (argc is 4) {  /* get the value to highlite */
       sscanf(argv[3], "%02x", &view);
       vflag = YES;
       }

    i = stuff(0);   /* check video type */
    if(i is MONO) {
       prompt = BLINKING;
       adrclr = WHITE;
       hexclr = HIWHITE;
       ascclr = WHITE;
       highclr = HIGHBLINK;
       }
    else {         /* for CGA cards */
       prompt = BROWN;
       adrclr = LTGREEN;
       hexclr = YELLOW;
       ascclr = LTCYAN;
       highclr = HIWHITE;
       }

    disp_open();    /* use Datalight direct video access routines */
    disp_cls();
    disp_move(0,0);
    disp_flush();
    lines = 20;
    while (TRUE) {
       for (i = 0; i < 16; i++) buffer[i] = fgetc(f);
       if (buffer[0] == -1) break;   /* done */
       disp_setattr(adrclr);   /* set address color */
       disp_printf("%04lx: ",offset);  /* display address */
       disp_setattr(hexclr);   /* set hex value color */
       for (i = 0; i < 16; i++) {
          if (buffer[i] != -1) {
             if(vflag and (buffer[i] is view)) {  /* highlite this byte? */
                disp_setattr(highclr);
                disp_printf("%02x ", buffer[i]);
                disp_setattr(hexclr);
                }
             else disp_printf("%02x ", buffer[i]);
             }
          else disp_puts("   ");
          }
       disp_setattr(ascclr);  /* display ascii data color */
       disp_puts("   ");
       for (i = 0; i < 16; i++) {
          if (buffer[i] != -1) {
             if (!isprint(buffer[i])) buffer[i] = '.';
             disp_putc(buffer[i]);
             }
          else disp_putc(' ');
          }
       disp_putc('\n');
       if(lines-- is 0) {
          disp_setattr(prompt);
          disp_say(22, 10, "Press any key to continue...");
          getkey();
          disp_cls();
          disp_flush();
          lines = 20;
          }
       offset += 16;
       }  /* end of while */
    disp_setattr(prompt);
    disp_say(22, 10, "End of File Encountered");
    disp_flush();
 }


 disp_puts(buf)
 char *buf;
 {
    while(*buf isnot NULL) disp_putc(*buf++);
 }



 DUMP_GRA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\DUMP_GRA.C

 /*                                                        DUMP GRAPHICS
 **************************************************************************
 *                       --------------------------                       *
 *                      |    Max W. Medley, Jr.    |                      *
 *                      |   13550 San Rafael Dr.   |                      *
 *                      |  Largo, Florida  33544   |                      *
 *                      |   (813) - 595 - 5051     |                      *
 *                       --------------------------                       *
 *                                                                        *
 * Dump graphic screen (high resolution) to an MX-80 printer with the     *
 * GRAFTRAX80 rom.  STTY should be used to set all options OFF for $lpt.  *
 * All characters must be passed directly to the printer without change.  *
 * Default value for tab is used to position the output. If desired, the  *
 * position may be changed by either setting a different tab stop or      *
 * using spaces (20h).                                                    *
 **************************************************************************
 */
 #include <stdio.h>

 main()
 {
         register int row, j, cr;
         unsigned int fp,bit,dot,col;
         char *pd,chr;
         set_extra_segment(0xb800);
         fp = fopen("$lpt", "w");                                /* open print
         putc(0x0a,fp); putc(0x0a,fp); putc(0x0a,fp); putc(0x0a,fp); putc(0x0d
         putc(0x1b,fp); putc(0x41,fp); putc(0x08,fp);        /* 8/72 lines per
         for(cr=0; cr<640; cr += 8) {                        /* Column loop */
                 putc(0x09,fp);
                 putc(0x1b,fp); putc(0x4b,fp); putc(0x90,fp); putc(0x01,fp); /
                 for(row=199; row>=0; row--) {                /* Row loop */
                         chr = 0;
                         bit = 0x80;
                         for(j=0; j<8; j++) {                        /* read 8
                                 col = cr + j;
                                 pd = (0x28 * (row & 0xfe)) + (col >> 3);
                                 if(row & 1)
                                         pd += 0x2000;
                                 dot = (@pd & (0x80 >> (7 & (col & 0xff))));
                                 chr += ((dot) ? bit : 0);
                                 bit >>= 1;
                         }
                         putc(chr,fp); putc(chr,fp);                /* Two gra
                 }
                 putc(0x0a,fp); putc(0x0d,fp);                /* LF - CR */
         }
 }


 DYNLINK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DYNLINK.C

                                           /* Chapter 12 - Program 3 */
 "stdio.h"    /* this is needed only to define the NULL     */
 #define RECORDS 6

 main()
 {
 struct animal {
    char name[25];       /* The animals name                         */
    char breed[25];      /* The type of animal                       */
    int age;             /* The animals age                          */
    struct animal *next; /* a pointer to another record of this type */
 } *point, *start, *prior; /* this defines 3 pointers, no variables  */
 int index;

                        /* the first record is always a special case */

    start = (struct animal *)malloc(sizeof(struct animal));
    strcpy(start->name,"General");
    strcpy(start->breed,"Mixed Breed");
    start->age = 4;
    start->next = NULL;
    prior = start;
        /* a loop can be used to fill in the rest once it is started */

    for (index = 0;index < RECORDS;index++) {
       point = (struct animal *)malloc(sizeof(struct animal));
       strcpy(point->name,"Frank");
       strcpy(point->breed,"Laborador Retriever");
       point->age = 3;
       prior->next = point;  /* point last "next" to this record */
       point->next = NULL;   /* point this "next" to NULL        */
       prior = point;        /* this is now the prior record     */
    }

        /* now print out the data described above */

    point = start;
    do {
       prior = point->next;
       printf("%s is a %s, and is %d years old.\n", point->name,
               point->breed, point->age);
       point = point->next;
    } while (prior != NULL);

        /* good programming practice dictates that we free up the */
        /* dynamically allocated space before we quit.            */

    point = start;            /* first block of group      */
    do {
       prior = point->next;   /* next block of data        */
       free(point);           /* free present block        */
       point = prior;         /* point to next             */
    } while (prior != NULL);  /* quit when next is NULL    */
 }


 DYNLIST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\DYNLIST.C

                                          /* Chapter 12 - Program 1 */
 main()
 {
 struct animal {
    char name[25];
    char breed[25];
    int age;
 } *pet1, *pet2, *pet3;

    pet1 = (struct animal *)malloc(sizeof(struct animal));
    strcpy(pet1->name,"General");
    strcpy(pet1->breed,"Mixed Breed");
    pet1->age = 1;

    pet2 = pet1;   /* pet2 now points to the above data structure */

    pet1 = (struct animal *)malloc(sizeof(struct animal));
    strcpy(pet1->name,"Frank");
    strcpy(pet1->breed,"Labrador Retriever");
    pet1->age = 3;

    pet3 = (struct animal *)malloc(sizeof(struct animal));
    strcpy(pet3->name,"Krystal");
    strcpy(pet3->breed,"German Shepherd");
    pet3->age = 4;

        /* now print out the data described above */

    printf("%s is a %s, and is %d years old.\n", pet1->name,
            pet1->breed, pet1->age);

    printf("%s is a %s, and is %d years old.\n", pet2->name,
            pet2->breed, pet2->age);

    printf("%s is a %s, and is %d years old.\n", pet3->name,
            pet3->breed, pet3->age);

    pet1 = pet3;   /* pet1 now points to the same structure that
                       pet3 points to                           */
    free(pet3);    /* this frees up one structure               */
    free(pet2);    /* this frees up one more structure          */
 /* free(pet1);    this cannot be done, see explanation in text */
 }


 D_PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DISPIO\D_PRINTF.C

 /*
 **       name         printf -- formatted write to console.
 **
 **       Same as Lattice C printf() function, but much faster.
 ******************************
 **       Renamed and modified to use the DISPIO function d_puts()
 **       L. Paper
 */

 d_printf(cs, args)
 char *cs, *args;
 {
         int i, c, n;
         char *p, **na, *_pfmt();
         char work[256];

         na =  &args;           /* point to first arg */
         while (*cs)
         {
                 c = *cs++;
                 if (c == '%')
                         if (*cs == '%')
                         {
                                 c = *cs++;
                                 d_putc(c);
                         }
                 else
                 {
                         p = _pfmt(cs, work, &na, &n);
                         if (p)
                         {
                                 cs = p;
                                 for (i=0; i<n; i++)
                                         d_putc(work[i]);
                         }
                 }
                 else
                         d_putc(c);
         }
         return;
 }



 D_PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\D_PRINTF.C

 /*
 **       name         printf -- formatted write to console.
 **
 **       Same as Lattice C printf() function, but much faster.
 ******************************
 **       Renamed and modified to use the DISPIO function d_puts()
 **       L. Paper
 */

 d_printf(cs, args)
 char *cs, *args;
 {
         int i, c, n;
         char *p, **na, *_pfmt();
         char work[256];

         na =  &args;           /* point to first arg */
         while (*cs)
         {
                 c = *cs++;
                 if (c == '%')
                         if (*cs == '%')
                         {
                                 c = *cs++;
                                 d_putc(c);
                         }
                 else
                 {
                         p = _pfmt(cs, work, &na, &n);
                         if (p)
                         {
                                 cs = p;
                                 for (i=0; i<n; i++)
                                         d_putc(work[i]);
                         }
                 }
                 else
                         d_putc(c);
         }
         return;
 }



 ECLOSU.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\ECLOSU.C

 /*
  * Copyright (c) 1978 Charles H. Forsyth
  */

 #include <stdio.h>
 #include "lexlex.h"

 /*
  * Construct the epsilon closure of a given set; this is the set of states
  * that may be reached by some number of epsilon transitions from that state.
  */
 struct set *
 eclosure(t)
 struct set *t;
 {
         register struct nfa *np, *xp;
         register i;
         struct nfa **sp, **tp, **ip, *stack[MAXNFA], *temp[MAXNFA];

         tp = temp;
         for (sp = stack, i = 0; i < t->s_len; i++)
                 if (sp <= stack+MAXNFA)
                         *tp++ = *sp++ = t->s_els[i];
                 else {
                         error("Stack overflow in `eclosure'");
                         exit(1);
                 }
         while (sp > stack) {
                 np = *--sp;
                 if (np->n_char==EPSILON)
                 for (i = 0; i < 2; i++)
                         if (xp = np->n_succ[i]) {
                                 for (ip = temp; ip < tp;)
                                         if (*ip++ == xp)
                                                 goto cont;
                                 if (tp >= temp+MAXNFA) {
                                         error("eclosure: list overflow");
                                         exit(1);
                                 }
                                 *sp++ = *tp++ = xp;
                         cont:;
                         }
         }
         t = newset(temp, tp-temp, 1);
         return(t);
 }



 ED0.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED0.C

 /* ED0.C */

 MAXLEN        80        /* 80 character video screen */
 MAXLEN1 81        /* MAXLEN+1 */
 #define SYSFNMAX 15
 #define EOS        0
 #define OK        1
 #define ERR        -1
 #define EOF        -2
 #define YES        1
 #define NO        0
 #define CR        13
 #define LF        10
 #define TAB        9
 #define HUGE        32000


 ED10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED10.C

 /* ED10.C */

 #include "b:ed0.c"
 #include "b:ed1.ccc"
 int bufcflag;
 char *bufbot;
 char *bufp;
 char *bufpmax;
 char *bufend;
 int bufline;
 int bufmaxln;
 bufnew()
 {
         bufp=bufpmax=bufbot=_memory()+1;
         bufend=sysend();
         bufline=1;
         bufmaxln=0;
         *(bufp-1)=CR;
         bufcflag=NO;
 }
 bufln()
 {
         return(bufline);
 }
 bufchng()
 {
         return(bufcflag);
 }
 bufsaved()
 {
         bufcflag=NO;
 }
 buffree()
 {
         return(bufend-bufp);
 }
 bufgo(line) int line;
 {
         line=min(bufmaxln+1,line);
         line=max(1,line);
         if (line==bufline) {
                 return(OK);
         }
         while (line<bufline) {
                 if (bufup()==ERR) {
                         return(ERR);
                 }
         }
         while (line>bufline) {
                 if (bufdn()==ERR) {
                         return(ERR);
                 }
         }
         return(OK);
 }
 bufup()
 {
 char *oldbufp;
         oldbufp=bufp;
         if (bufattop()) {
                 return(OK);
         }
         if (*--bufp!=CR) {
                 syserr("bufup:        missing CR");
                 bufp=oldbufp;
                 sysabort();
                 return(ERR);
         }
         while (*--bufp!=CR) {
                 ;
         }
         bufp++;
         if (bufp<bufbot) {
                 syserr ("bufup: bufp underflow");
                 bufp=oldbufp;
                 sysabort();
                 return(ERR);
         }
         bufline--;
         return(OK);
 }
 bufdn()
 {
 char *oldbufp;
         oldbufp=bufp;
         if (bufatbot()) {
                 return(OK);
         }
         while (*bufp++!=CR) {
                 ;
         }
         if (bufp>bufpmax) {
                 syserr("bufdn: bufp overflow");
                 bufp=oldbufp;
                 sysabort();
                 return(ERR);
         }
         bufline++;
         return(OK);
 }
 bufins(p,n) char *p; int n;
 {
 int k;
         if(bufext(n+1)==ERR) {
                 return(ERR);
         }
         k=0;
         while (k<n) {
                 *(bufp+k)= *(p+k);
                 k++;
         }
         *(bufp+k)=CR;
         bufmaxln++;
         if ((n==0)&(bufnrbot())) {
                 ;
         }
         else {
                 bufcflag=YES;
         }
         return(OK);
 }
 buf1ins(p,n) char *p; int n;         /* altered: a full buffer does not trunc
 {                                /*   line, but issues warning and returns
 int k, x;                        /*   ERR - allows editing of large files
         x = 0;                        /*   in pieces */
         if(bufstrch(n+1)==ERR) {
                 x = 1;
         }
         k=0;
         while (k<n) {
                 *(bufp+k)= *(p+k);
                 k++;
         }
         *(bufp+k)=CR;
         bufmaxln++;
         if ((n==0)&(bufnrbot())) {
                 ;
         }
         else {
                 bufcflag=YES;
         }
         if (x == 0) {
                 return(OK);
         }
         else {
                 sysabort();
                 return(ERR);
         }
 }
 bufdel()
 {
         return(bufndel(1));
 }
 bufndel(n) int n;
 {
 int oldline;
 int k;
 char *oldbufp;
         oldline=bufline;
         oldbufp=bufp;
         k=0;
         while ((n--)>0) {
                 if (bufatbot()) {
                         break;
                 }
                 if (bufdn()==ERR) {
                         bufline=oldline;
                         bufp=oldbufp;
                         return(ERR);
                 }
                 k++;
         }
         bufupmov(bufp,bufpmax-1,bufp-oldbufp);
         bufpmax=bufpmax-(bufp-oldbufp);
         bufp=oldbufp;
         bufline=oldline;
         bufmaxln=bufmaxln-k;
         bufcflag=YES;
         return(OK);
 }
 bufrepl(p,n) char *p; int n;
 {
 int oldlen, k;
 char *nextp;
         if (bufatbot()) {
                 return(bufins(p,n));
         }
         if (bufdn()==ERR) {
                 return(ERR);
         }
         nextp=bufp;
         if (bufup()==ERR) {
                 return(ERR);
         }
         n=n+1;
         oldlen=nextp-bufp;
         if (oldlen<n) {
                 if (bufext(n-oldlen)==ERR) {
                         return(ERR);
                 }
            /*        bufpmax=bufpmax+n-oldlen;   Note: Error in original list
         }
         else if (oldlen>n) {
                 bufupmov(nextp,bufpmax-1,oldlen-n);
                 bufpmax=bufpmax-(oldlen-n);
         }
         k=0;
         while (k<(n-1)) {
                 bufp[k]=p[k];
                 k++;
         }
         bufp[k]=CR;
         bufcflag=YES;
         return(OK);
 }
 bufgetln(p,n) char *p; int n;
 {
 int k;
         if (bufatbot()) {
                 return(0);
         }
         k=0;
         while (k<n) {
                 if (*(bufp+k)==CR) {
                         return(k);
                 }
                 *(p+k)= *(bufp+k);
                 k++;
         }
         while (*(bufp+k)!=CR) {
                 k++;
         }
         return(k);
 }
 bufdnmov(from,to,length) char *from, *to; int length;
 {
         sysdnmov(to-from+1,from+length,from);  /*altered for _move */
 }
 bufupmov(from,to,length) char *from, *to; int length;
 {
         sysupmov(to-from+1,from-length,from);
 }
 bufatbot()
 {
         return(bufline>bufmaxln);
 }
 bufnrbot()
 {
         return(bufline>=bufmaxln);
 }
 bufattop()
 {
         return(bufline==1);
 }
 bufout(topline,topy,nlines) int topline, topy, nlines;
 {
 int l,p;
         l=bufline;
         p=bufp;
         while ((nlines--)>0) {
                 outxy(0,topy++);
                 buflnout(topline++);
         }
         bufline=l;
         bufp=p;
 }
 buflnout(line) int line;
 {
 int c;
         if (bufgo(line)==ERR) {
                 diskerr(" line deleted");
                 outdeol();
                 sysabort();
                 return;
         }
         if (bufatbot()) {
                 outdeol();
         }
         else {
                 c=fmtsout(bufp,0);                /* c= added */
                 if (c<SCRNW1) {                  /* now allows full screen */
                 outdeol();
                 }
         }
 }
 bufext(length) int length;
 {
         if ((bufpmax+length)>=bufend) {
                 error("main buffer is full");
                 sysabort();
                 return(ERR);
         }
         bufdnmov(bufp,bufpmax-1,length);
         bufpmax=bufpmax+length;
         return(OK);
 }
 /* bufstrch is bufext modifed to allow entering beyond buffer with warning */
 bufstrch(length) int length;
 {
         if ((bufpmax+length)>=bufend) {
                 bufdnmov(bufp,bufpmax-1,length);
                 bufpmax=bufpmax+length;
                 message("Caution: main buffer is full");
                 sysabort();
                 return(ERR);
         }
         bufdnmov(bufp,bufpmax-1,length);
         bufpmax=bufpmax+length;
         return(OK);
 }
 buflength(first,n) int first, n;   /* new: returns length of n lines from  */
 {                                   /* first line specified */
 char *start;
 int i,len,line;
         if (n<=0) {
                 len=0;
                 return(len);
         }
         if (bufgo(first)==ERR) {
                 len=0;
                 return(len);
         }
         start=bufp;
         i=1;
         line = first;
         while (i++<=n) {
                 if (bufgo(++line)==ERR) {
                         len=0;
                         return(len);
                 }
         }
         len=bufp-start;
         return(len);
 }
 bufcopy(from,to,n) int from,to,n;        /* new: copies "n" lines from "from"
 {                                        /*        to "to" */
 int length;
 char *source,*dest;
         if (from==to){
                 return;
         }
         if ((length=buflength(from,n))==0){
                 return;
         }
         if (bufgo(from)==ERR){
                 return;
         }
         source=bufp;
         if (bufgo(to)==ERR){
                 return;
         }
         dest=bufp;
         if ((bufpmax+length)>=bufend) {
                 error("insufficient room in buffer for copy or move");
                 sysabort();
                 return;
         }
         if (bufext(length)==ERR){
                 return;
         }
         bufgo(1);
         bufmaxln=bufmaxln+n;
         if (from<to) {
                 sysupmov(length,dest,source);
         }
         else {
                 sysupmov(length,dest,source+length);
         }
 }
 buftopick(dest,start_line,nlines) char *dest; int start_line,nlines;
         /* move nlines from main- to pick-buffer */
 {
 int length;
 char *source;
         if (nlines==0) {
                 return(OK);
         }
         if ((length=buflength(start_line,nlines))==0){
                 return(OK);
         }
         if (bufgo(start_line)==ERR){
                 return(ERR);
         }
         source=bufp;
         sysupmov(length,dest,source);
         return(OK);
 }
 picktobuf(source,length,lines) char *source; int length,lines;
         /* move indicated pick buffer to main buffer */
 {
 char *dest;
         if (length==0)
         {
                 return(OK);
         }
         dest=bufp;
         if ((bufpmax+length)>=bufend){
                 error("insufficient room in buffer for put");
                 sysabort();
                 return(ERR);
         }
         if (bufext(length)==ERR){
                 return(ERR);
         }
         bufgo(1);
         bufmaxln=bufmaxln+lines;
         sysdnmov(length,dest,source);
         return(OK);
 }






 ED2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED2.C

 /* ED2.C */

 #include "ed0.c"
 #include "ed1.ccc"
 #define SIGNON "E.K. Ream/Dr Dobb's Editor - IBM PC enhancement: Mar. 10, 198
 #define SIGNNN "            Modified by Alan D. Howard"
 #define HELP1 "open <f/n> | name <f/n> | rename <f/n> | delname <f/n>"
 #define HELP2 "load <f/n> | append <f/n> | rest | read <n> | write <n> | save
 #define HELP3 "extract [<f t>] | closeread | closewrite"
 #define HELP4 "clear | delete [<f t>] | move [<f t n>] | copy [<f t n>]"
 #define HELP5 "find | search [<f t>] | change [<f t>] | list [<f t>]"
 #define HELP6 "tabs <n> | showtab | hidetab | help | dos | g <n> | count <n>"
 #define CMNDMODE        1
 #define INSMODE         2
 #define EDITMODE        3
 #define EXITMODE        4
 int        begin_line, end_line, buf_picked;
 main(argc,argv) char *argv[];
 {
 int mode;
 int i;
         sysinit();
         fmtassn(NO);
         fmtset(8);
         fmtntab();
         outclr();
         outxy(0,SCRNL1);
         message(SIGNON);
         message(SIGNNN);
         outxy(0,1);
         fileclear();        /* make sure no read or write files indicated */
         bufnew();
         begin_line=(-1);        /* imaginary to start with */
         end_line=(-1);
         buf_picked=NO;
         mode=CMNDMODE;
         if (argc>1) {
                 openf(argv[1],NO);
                 rest(argv[0]);
                 outxy(0,1);
         }
         edgetln();
         while(1){
                 if (mode ==EXITMODE) {
                         sysfinish();
                         break;
                 }
                 else if (mode==CMNDMODE) {
                         mode=command();
                 }
                 else if (mode==EDITMODE) {
                         mode=edit();
                 }
                 else if (mode==INSMODE) {
                         mode=insert();
                 }
                 else {
                         syserr("main: no mode");
                         mode=EDITMODE;
                 }
         }
 }
 edit()
 {
 char c;
         pmtedit();
         while(1){
                 c=syscin();        /* tolower eliminated */
                 if (c==ESC1) {                /* enter command mode */
                         return(CMNDMODE);
                 }
                 else if (c==INS1) {        /* enter insert mode */
                         return(INSMODE);
                 }
                 else if (special(c)==YES) {
                         if (c==UP1){        /* DOWN1 now treated separately *
                                 return(INSMODE);
                         }
                         else {
                                 continue;
                         }
                 }
                 else if (c==DOWN1) {        /* DOWN1 now does not         */
                         eddn();         /* enter insert mode but */
                         pmtline();        /* just advances to next line */
                         edbegin();
                         pmtcol();
                 }
                 else if (c==DTOCH){        /* kill to character entered */
                         pmtmode("edit:        kill");
                         c=syscin();
                         if ((special(c)==NO) &
                             (control(c)==NO)) {
                                 edkill(c);
                         }
                         pmtedit();
                 }
                 else if (c==GTOCH){        /* search to character entered */
                         pmtmode("edit: search");
                         c=syscin();
                         if ((special(c)==NO) &
                             (control(c)==NO)) {
                                 edsrch(c);
                         }
                         pmtedit();
                 }
                 else {                /* editor now exchanges any other chara
                         if ((special(c)==NO) &        /* with cursor */
                             (control(c)==NO)) {
                                 edchng(c);
                         }
                         pmtcol();
                 }
         }
 }
 insert()
 {
 char c;
         pmtmode("insert");
         while(1) {
                 c=syscin();
                 if (c==ESC1) {
                         return(CMNDMODE);
                 }
                 else if (c==EDIT1) {
                         return(EDITMODE);
                 }
                 else if (c==INS1) {
                         ;
                 }
                 else if (c==DOWN1) {        /* in insert mode DOWN1 treated
                         ednewdn();        /* differently from edit mode
                         pmtline();        /* inserts new line */
                         continue;
                 }
                 else if (c==DTOCH){        /* kill to character entered */
                         pmtmode("Insert: kill");
                         c=syscin();
                         if ((special(c)==NO) &
                             (control(c)==NO)) {
                                 edkill(c);
                         }
                 }
                 else if (c==GTOCH){        /* search to character entered */
                         pmtmode("Insert: search");
                         c=syscin();
                         if ((special(c)==NO) &
                             (control(c)==NO)) {
                                 edsrch(c);
                         }
                 }
                 else if (special(c)==YES) {
                         continue;
                 }
                 else if (control(c)==YES) {
                         continue;
                 }
                 else {
                         edins(c);
                         pmtcol();
                 }
         }
 }
 control(c) char c;
 {
         if (c==TAB) {
                 return(NO);
         }
         else if (c>=127) {
                 return(YES);
         }
         else if (c<32) {
                 return(YES);
         }
         else {
                 return(NO);
         }
 }
 special(c) char c;
 {
 char sbuffer[SCRNW1];
 int v,x,y;
 int k;
         if (c==JOIN1) {
                 edjoin();
                 pmtline();
                 return(YES);
         }
         if (c==SPLT1) {
                 edsplit();
                 pmtline();
                 return(YES);
         }
         if (c==ABT1) {
                 edabt();
                 pmtcol();
                 return(YES);
         }
         else if (c==LFTDEL) {                /* delete to left of cursor */
                 edldel();
                 pmtcol();
                 return(YES);
         }
         else if (c==DEL1) {                /* delete at cursor */
                 edcdel();
                 pmtcol();
                 return(YES);
         }
         else if (c==ZAP1) {
                 edzap();
                 pmtline();
                 return(YES);
         }
         else if (c==UP2) {
                 edup();
                 pmtline();
                 return(YES);
         }
         else if (c==UP1) {
                 ednewup();
                 pmtline();
                 return(YES);
         }

 /* DOWN1 (CR) is no longer a special character */

         else if (c==DOWN2) {
                 eddn();
                 pmtline();
                 return(YES);
         }
         else if (c==ABSLEFT) {                /* left one column */
                 edabsleft();
                 pmtcol();
                 return(YES);
         }
         else if (c==ABSRGHT) {         /* right one column */
                 edabsright();
                 pmtcol();
                 return(YES);
         }
         else if (c==LEFT1) {          /* left one character */
                 edleft();
                 pmtcol();
                 return(YES);
         }
         else if (c==RIGHT1) {         /* right one character */
                 edright();
                 pmtcol();
                 return(YES);
         }
         else if (c==BEGINPL) {                /* mark beginning line */
                 begin_line=bufln();
                 pmtmode("marked buff top");
                 return(YES);
                 }
         else if (c==ENDPL) {                /* mark ending line */
                 end_line=bufln();
                 pmtmode("marked buff end");
                 return(YES);
                 }
         else if (c==PICKIT) {                /* pick marked lines to buffer *
                 if (edpick(begin_line,end_line)!=ERR) {
                         pmtmode("buffer picked");
                         buf_picked=YES;
                         }
                 return(YES);
                 }
         else if (c==RIGHT1) {        /* go to end of line */
                 edright();
                 pmtcol();
                 return(YES);
         }
         else if (c==ERASE) {        /* erase to end of line */
                 ederase();
                 pmtcol();
                 return(YES);
         }
         else if (c==HOME) {        /* move cursor alternatingly to */
                 edhome();        /* top and bottom of screen */
                 pmtline();
                 sysabort();
                 return(YES);
         }
         else if (c==LSTRT) {        /* move to beginning of line */
                 edbegin();
                 pmtcol();
                 return(YES);
         }
         else if (c==PUTIT) {   /* put buffer before line*/
                 if (buf_picked==YES) {
                         edput();
                         begin_line=(-1);
                         end_line=(-1);
                         }
                 pmtline();
                 return(YES);
         }
         else if (c==DSCROL) {        /* scroll down */
                 pmtmode("Scroll down");
                 while (bufnrbot()==NO) {
                         if (chkkey()==YES) {
                                 break;
                         }
                         if (eddn()==ERR) {
                                 break;
                         }
                 }
                 pmtline();
                 return(YES);
         }
         else if (c==LEND){        /* move to end of line */
                 edend();
                 pmtcol();
                 return(YES);
         }
         else if (c==PAGEUP) {  /* move up 20 lines */
                 y=bufln();
                 y=max(y-20,1);
                 if (bufattop()!=YES) {
                         edgo(y,0);
                 }
                 pmtline();
                 return(YES);
         }
         else if (c==PAGEDN) {   /*move down 20 lines */
                 y=bufln();
                 y=y+20;
                 if (bufnrbot()!=YES) {
                         edgo(y,0);
                 }
                 pmtline();
                 return(YES);
         }
         else if (c==GOTO){        /* go to line entered */
                 x=outxget();
                 y=outyget();
                 pmtcmnd("Goto: ",sbuffer);
                 if(number(sbuffer,&v)) {
                         edgo(v,0);
                 }
                 else {
                         outxy(x,y);
                 }
                 return(YES);
         }
         else if (c==USCROL) {        /* scroll up */
                 pmtmode("Scroll up");
                 while (bufattop()==NO) {
                         if (chkkey()==YES) {
                                 break;
                         }
                         if (edup()==ERR) {
                                 break;
                         }
                 }
                 pmtline();
                 return(YES);
         }
         else  {
                 return(NO);
         }
 }
 command()
 {
 int v;
 char c;
 char args[SCRNW1];
 char *argp;
 int topline;
 int ypos;
 int oldline;
 int k;
         edrepl();
         oldline=bufln();
         ypos=outyget();
         topline=oldline-ypos+1;
         while(1) {
                 outxy(0,SCRNL1);
                 fmtcrlf();
                 pmtmode("command:");
                 getcmnd(args,0);
                 fmtcrlf();
                 pmtline();
                 c=args[0];
                 if ((c==EDIT1)|(c==INS1)) {
                         if (oldline==bufln()) {
                                 edgetln();
                                 bufout(topline,1,SCRNL1);
                                 outxy(0,ypos);
                         }
                         else {
                                 edgo(bufln(),0);
                         }
                         if (c==EDIT1) {
                                 return(EDITMODE);
                         }
                         else {
                                 return(INSMODE);
                         }
                 }
                 else if (tolower(args[0])=='g'){
                         argp=skipbl(args+1);
                         if (argp[0]==EOS) {
                                 edgo(oldline,0);
                                 return(EDITMODE);
                         }
                         else if (number(argp,&v)==YES) {
                                 edgo(v,0);
                                 return(EDITMODE);
                         }
                         else {
                                 message("bad line number");
                         }
                 }
                 else if (lookup(args,"append")) {
                         append(args);
                 }
                 else if (lookup(args,"change")) {
                         change(args,begin_line,end_line);
                 }
                 else if (lookup(args,"clear")) {
                         sysabort();
                         clear();
                 }
                 else if (lookup(args,"count")) { /* repeat count for replay *
                         count(args);
                 }
                 else if (lookup(args,"delete")) {
                         delete(args,begin_line,end_line);
                         begin_line=(-1);
                         end_line=(-1);
                         buf_picked=YES;
                 }
                 else if (lookup(args,"dos")) {
                         sysabort();
                         if (chkbuf()==YES) {
                                 closewrite();        /* write file closed on
                                 return(EXITMODE);
                         }
                 }
                 else if (lookup(args,"find")) {
                         if ((k=find()) >= 0) {
                                 edgo(bufln(),k);
                                 return(EDITMODE);
                         }
                         else {
                                 bufgo(oldline);
                                 edgetln();
                                 message("pattern not found");
                         }
                 }
                 else if (lookup(args,"list")) {
                         list(args,begin_line,end_line);
                 }
                 else if (lookup(args,"open")) {         /* new */
                         sysabort();
                         openf(args,YES);
                 }
                 else if (lookup(args,"load")) {         /* changed */
                         sysabort();
                         openf(args,YES);
                         rest(args);
                 }
                 else if (lookup(args,"name")) {
                         sysabort();
                         name(args);
                 }
                 else if (lookup(args,"write")) {        /* new */
                         sysabort();
                         writel(args);
                 }
                 else if (lookup(args,"rename")) {        /* new */
                         sysabort();
                         rename(args);
                 }
                 else if (lookup(args,"delname")) {        /* new */
                         sysabort();
                         delname(args);
                 }
                 else if (lookup(args,"closewrite")) {        /* new */
                         sysabort();
                         closewrite(args);
                 }
                 else if (lookup(args,"showtab")) {    /* new */
                         fmtytab();
                 }
                 else if (lookup(args,"hidetab")) {    /* new */
                         fmtntab();
                 }
                 else if (lookup(args,"closeread")) {        /* new */
                         sysabort();
                         closeread(args);
                 }
                 else if (lookup(args,"help")) {         /* new */
                         sysabort();
                         outclr();
                         outxy(0,SCRNL1);
                         message(HELP1);
                         message(HELP2);
                         message(HELP3);
                         message(HELP4);
                         message(HELP5);
                         message(HELP6);
                 }
                 else if (lookup(args,"save")) {
                         sysabort();
                         save(args);
                 }
                 else if (lookup(args,"read")) {          /* new */
                         sysabort();
                         getit(args);
                 }
                 else if (lookup(args,"move")) {         /* new */
                         moveit(args,begin_line,end_line,bufln());
                         begin_line=(-1);
                         end_line=(-1);
                 }
                 else if (lookup(args,"copy")) {         /* new */
                         copyit(args,begin_line,end_line,bufln());
                         begin_line=(-1);
                         end_line=(-1);
                 }
                 else if (lookup(args,"search")) {
                         sysabort();
                         search(args,begin_line,end_line);
                 }
                 else if (lookup(args,"tabs")) {
                         tabs(args);
                 }
                 else if (lookup(args,"rest")) {         /* new */
                         sysabort();
                         rest(args);
                 }
                 else if (lookup(args,"extract")) {        /* new */
                         sysabort();
                         extract(args);
                 }
                 else {
                         sysabort();
                         message("command not found");
                 }
         }
 }
 lookup(line,command) char *line, *command;
 {
         while(*command) {
                 if (tolower(*line++)!=*command++) {
                         return(NO);
                 }
         }
         if((*line==EOS)|(*line==' ')|(*line==TAB)) {
                 return(YES);
         }
         else {
                 return(NO);
         }
 }
 getcmnd(args,offset) char *args; int offset;
 {
 int j,k;
 char c;
         outxy(offset++,outyget());
         outdeol();
         scr_chr_attr(SETINTENSE);  /* set up prompt */
         scr_chr_attr(SETBLINK);
         syscout('>');
         scr_chr_attr(NOBLINK);
         k=0;
         while ((c=syscin())!=CR) {
                 if ((c==EDIT1)|(c==INS1)) {
                         args[0]=c;
                         return;
                 }
                 if ((c==DEL1)|(c==LEFT1)) {
                         if (k>0) {
                                 outxy(offset,outyget());
                                 outdeol();
                                 k--;
                                 j=0;
                                 while (j<k) {
                                         outchar(args[j++]);
                                 }
                         }
                 }
                 else if (c==ABT1) {
                         outxy(offset,outyget());
                         outdeol();
                         k=0;
                 }
                 else if ((c!=TAB)&((c<32)|(c==127))) {
                         continue;
                 }
                 else {
                         if ((k+offset)<SCRNW1) {
                                 args[k++]=c;
                                 outchar(c);
                         }
                 }
         }
         args[k]=EOS;
         scr_chr_attr(SETFAINT);
         offset--;                        /* erase prompt */
         outxy(offset,outyget());
         syscout(' ');
 }


 ED3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED3.C

 /* ED3.C */

 #include "ed0.c"
 #include "ed1.ccc"
 int readfile = -1;        /* separate read and write files */
 int writefile = -1;        /* -1 for inactive, file channel no. for active */
 char rfilename[SYSFNMAX];        /* file names */
 char wfilename[SYSFNMAX];
 char databuf[MAXLEN1];                /* single buffer replaces redundant buf
 fileclear()                /* initializes filenames to zero length */
 {
         rfilename[0] = EOS;
         wfilename[0] = EOS;
 }
 append(args) char *args;
 {
 int file;
 int n;
 int topline;
 char locfn[SYSFNMAX];
         if (name1(args,locfn)==ERR) {
                 return;
         }
         if (locfn[0]==EOS) {
                 message("no file argument");
                 return;
         }
         if ((file=sysopen(locfn,"r"))==ERR) {
                 message("file not found");
                 return;
         }
         while ((n=readline(file,databuf,MAXLEN))>=0) {
                 if (n>MAXLEN) {
                         message("line truncated");
                         n=MAXLEN;
                 }
                 if (bufins(databuf,n)==ERR) {
                         break;
                 }
                 if (bufdn()==ERR) {
                         break;
                 }
         }
         sysclose(file);
         topline=max(1,bufln()-SCRNL2);
         bufout(topline,2,SCRNL2);
         bufgo(topline);
 }
 change(args,begin,end) char *args; int begin,end;
 {
 char oldline[MAXLEN1];
 char newline[MAXLEN1];
 char oldpat[MAXLEN1];
 char newpat[MAXLEN1];
 int from, to, col, n, k;
         if (get2args(args,&from,&to)==ERR) {
                 if (check2mark(begin,end,&from,&to)==ERR){
                         sysabort();
                         return;
                 }
         }
         scr_chr_attr(SETINTENSE);
         fmtsout("search mask ?        ",0);
         getcmnd(oldpat,15);
         fmtcrlf();
         if(oldpat[0]==EOS) {
                 return;
         }
         pmtline();
         scr_chr_attr(SETINTENSE);
         fmtsout("change mask ?        ",0);
         getcmnd(newpat,15);
         fmtcrlf();
         while (from<=to) {
                 if (chkkey()==YES) {
                         break;
                 }
                 if (bufgo(from++)==ERR) {
                         sysabort();
                         break;
                 }
                 if (bufatbot()==YES) {
                         sysabort();
                         break;
                 }
                 n=bufgetln(oldline,MAXLEN);
                 n=min(n,MAXLEN);
                 oldline[n]=EOS;
                 if (oldpat[0]=='^') {
                         if (amatch(oldline,oldpat+1,NO)==YES) {
                                 k=replace(oldline,newline,
                                         oldpat+1,newpat,0);
                                 if (k==ERR) {
                                         sysabort();
                                         return;
                                 }
                                 fmtcrlf();
                                 putdec(bufln(),5);
                                 fmtsout(newline,5);
                                 outdeol();
                                 bufrepl(newline,k);
                         }
                         continue;
                 }
                 if ((col=amatch(oldline,oldpat,YES))>=0) {
                         k=replace(oldline,newline,
                                 oldpat,newpat,col);
                         if (k==ERR) {
                                 sysabort();
                                 return;
                         }
                         fmtcrlf();
                         putdec(bufln(),5);
                         fmtsout(newline,5);
                         outdeol();
                         bufrepl(newline,k);
                 }
         }
         fmtcrlf();
 }
 clear()
 {
         if (chkbuf()==YES) {
                 outclr();
                 outxy(0,SCRNL1);
                 bufnew();
                 message("buffer cleared");
                 return(YES);
         }
         else{
                 return(NO);
         }
 }
 delete(args,begin,end) char *args; int begin,end;
 {
 int from, to;
         if(get2args(args,&from,&to)==ERR) {
                 if (check2mark(begin,end,&from,&to)==ERR){
                         sysabort();
                         return;
                 }
         }
         if (from>to) {
                 return;
         }
         if (edpick(from,to)==OK){
                 message ("deleted lines saved in pick buffer");
         }
         if (bufgo(from)==ERR) {
                 return;
         }
         if (bufndel(to-from+1)==ERR) {
                 sysabort();
                 return;
         }
         bufout(bufln(),1,SCRNL1);
 }
 find()
 {
         return(suurch(bufln()+1,HUGE,YES));
 }
 list(args,begin,end) char *args; int begin,end;
 {
 int n;
 int from, to, line, oldline;
         oldline=bufln();
         if (get2args(args,&from,&to)==ERR) {
                 if (check2mark(begin,end,&from,&to)==ERR) {
                         sysabort();
                         return;
                 }
         }
         line=from;
         while (line<=to) {
                 fmtassn(NO);
                 if (chkkey()==YES) {
                         break;
                 }
                 fmtassn(YES);
                 if (bufgo(line++)!=OK) {
                         break;
                 }
                 if (bufatbot()) {
                         sysabort();
                         break;
                 }
                 n=bufgetln(databuf,MAXLEN1);
                 n=min(n,MAXLEN);
                 databuf[n]=CR;
                 fmtsout(databuf,0);
                 fmtcrlf();
         }
         fmtassn(NO);
         bufgo(oldline);
 }
 extract(args,begin,end) char *args; int begin,end;
         /* write indicated line range to writefile */
 {
 /*char args1[SCRNW1];
 char *argp;
 int file;
 char locfn[SYSFNMAX];        */
 int oldline, from, to, n;
         if (writefile == -1) {
                 message("file not opened");
                 return;
         }
         oldline = bufln();
         if (get2args(args,&from,&to)==ERR) {/* from and to are line range */
                 if (check2mark(begin,end,&from,&to)==ERR){
                         return;
                 }
         }
 /*        message("enter file name");  */ /* request the file name */
 /*        getcmnd(args1,0);
         argp=skipbl(args1);
         if (syschkfn(argp)==ERR) {
                 return;
         }
         syscopfn(argp,locfn);
         if (locfn[0]==EOS) {
                 message("no file argument");
                 return;
         }
         if ((file=sysopen(locfn,"w"))==ERR){
                 return;
         }        */
         if (bufgo(from)==ERR){
            /*          sysclose(file);        */
                 return;
         }
         while ((bufatbot()==NO)&(bufln()<=to)) {        /* do the writing */
                 n=bufgetln(databuf,MAXLEN);
                 n=min(n,MAXLEN);
                 if (pushline(writefile,databuf,n)==ERR){
                         break;
                 }
                 if (bufdn()==ERR) {
                         break;
                 }
         }
         bufgo(oldline);
 /*          sysclose(file);        */  /* close the file */
 }
 openf (args,flag) char *args; int flag;
 {
 /* open a file for reading */
 char locfn [SYSFNMAX];
 int n;
 int file;
 int topline;
         if (readfile > 0) {                /* check for open readfile */
                 message("read file still open");
                 return;
         }
         if (flag==YES) {
                 if (name1(args,locfn)==ERR) {
                         return;
                 }
         }
         else  {
                 if (name3(args,locfn)==ERR) {
                         return;
                 }
         }
         if (locfn[0]==EOS) {
                 message("no file argument");
                 return;
         }
         if (chkbuf()==NO) {
                 return;
         }
         if ((file=sysopen(locfn,"r"))==ERR) {
                 message("file not found");
                 return;
         }
         syscopfn(locfn, rfilename);        /* make the file name the readfile
         readfile = file;
         pmtrfile(rfilename);
         bufnew();
 }
 getit (args) char *args;        /* new: add n lines to buffer if room */
 {
 int n;
 int topline;
 int nlines,npoint;
         if (readfile == -1) {
                 message ("no read file");
                 return;
         }
         pmtrfile(rfilename);
         if (getarg(args,&nlines)==ERR) {
                 return;
         }
         if (nlines<1) {
                 return;
         }
         if (bufgo(HUGE)==ERR) {
                 return;
         }
         npoint=1;
         while (npoint<=nlines) {        /* add the lines */
                 npoint++;
                 if ((n=readline(readfile,databuf,MAXLEN))>=0) {
                         if (n>MAXLEN) {
                                 message("line truncated");
                                 n=MAXLEN;
                         }
                         if (buf1ins(databuf,n)==ERR) {
                                 bufgo(1);
                                 topline=max(1,bufln()-SCRNL2);
                                 bufout(topline,2,SCRNL2);
                                 bufgo(topline);
                                 return;
                         }
                         if (bufdn()==ERR) {
                                 break;
                         }
                 }
                 else {
                         npoint = HUGE;           /* reached end of file - clo
                         sysclose(readfile);
                         readfile = -1;
                         rfilename[0] = EOS;
                         pmtrfile(rfilename);
                 }
         }
         bufgo(1);
         topline=max(1,bufln()-SCRNL2);
         bufout(topline,2,SCRNL2);
         bufgo(topline);
 }
 rest (args) char *args; /* new: try to read rest of readfile into buffer */
 {
 int n;
 int topline;
         if (readfile == -1) {
                 message ("no read file");
                 return;
         }
         pmtrfile(rfilename);
 /* if buffer has been changed and not saved, give option of clearing, */
 /* otherwise add to end of buffer */
         if(bufchng()==YES) {
                 scr_chr_attr(SETINTENSE);

                 fmtsout("buffer not saved. clear? ",0);
                 scr_chr_attr(SETFAINT);
                 pmtline();
                 if (tolower(syscout(syscin()))=='y'){
                         outclr();
                         outxy(0,SCRNL1);
                         bufnew();
                         message("buffer cleared");
                 }
                 else {
                         bufgo(HUGE);
                 }
         }
         else{
                 outclr();
                 outxy(0,SCRNL1);
                 bufnew();
                 message("buffer cleared");

         }
         while ((n=readline(readfile,databuf,MAXLEN))>=0) {
                 if (n>MAXLEN) {
                         message("line truncated");
                         n=MAXLEN;
                 }
                 if (buf1ins(databuf,n)==ERR) {
                         bufgo(1);
                         topline=max(1,bufln()-SCRNL2);
                         bufout(topline,2,SCRNL2);
                         bufgo(topline);
                         return;
                 }
                 if (bufdn()==ERR) {
                         break;
                 }
         }
         sysclose(readfile);        /* close file if all read */
         readfile = -1;
         rfilename[0] = EOS;
         pmtrfile(rfilename);
         bufgo(1);
         topline=max(1,bufln()-SCRNL2);
         bufout(topline,2,SCRNL2);
         bufgo(topline);
 }
 rename(args) char *args;        /* new: change name of writefile */
 {
         if (writefile == -1) {
                 message("no write file - call name");
                 return;
         }
         sysclose(writefile);
         writefile = -1;
         wfilename[0]=EOS;
         pmtwfile(wfilename);
         if (name0(args,wfilename)==ERR) {
                 return;
         }
         pmtwfile(wfilename);
 }
 name(args) char *args;                /* altered definition: name the writefi
 {
         if (writefile > 0) {
                 message("write file open");
                 return;
         }
         if (name0(args,wfilename)==ERR){
                 return;
         }
         pmtwfile(wfilename);
 }
 name0(args,wfilename) char *args, *wfilename;        /* names new writefile *
 {
 int file;
         args=skiparg(args);
         args=skipbl(args);
         if (syschkfn(args)==ERR) {
                 return(ERR);
         }
         syscopfn(args,wfilename);
         if ((file=sysopen(wfilename,"r"))!=ERR) {
                 sysclose(file);
                 message("disk file exists");
                 return(ERR);
         }
         if ((file=syscreate(wfilename))==ERR) {
                 return(ERR);
         }
         writefile = file;
         return(OK);
 }
 delname(args) char *args;        /* new: similar to old resave command, */
 {                                /* but doesn't automatically write file */
         if (writefile > 0) {
                 message("write file open");
                 return;
         }
         if (name2(args,wfilename)==ERR){
                 return;
         }
         pmtwfile(wfilename);
 }
 name2(args,wfilename) char *args, *wfilename;        /* open writefile: no er
 {                                                /* file exists */
 int file;
         args=skiparg(args);
         args=skipbl(args);
         if (syschkfn(args)==ERR) {
                 return(ERR);
         }
         syscopfn(args,wfilename);
         if ((file=sysopen(wfilename,"w"))==ERR) {
                 return(ERR);
         }
         writefile = file;
         return(OK);
 }
 name1(args,filename) char *args, *filename;
 {
         args=skiparg(args);
         args=skipbl(args);
         if (syschkfn(args)==ERR) {
                 return(ERR);
         }
         syscopfn(args,filename);
         return(OK);
 }
 name3(args,filename) char *args, *filename;
 {
         if (syschkfn(args)==ERR) {
                 return(ERR);
         }
         syscopfn(args,filename);
         return(OK);
 }
 count(args) char *args;  /* get repeat count for buffer macro replay */
 {
 int n;
         if (getarg(args,&n)==ERR) {
                 return;
         }
         syscount(n);
 }
 writel(args) char *args;        /* new: write first n lines of buffer to */
 {                                /* writefile and delete from buffer */
 int n, to;
         if (writefile == -1) {
                 message("file not opened");
                 return;
         }
         if (getarg(args,&to)==ERR) {
                 return;
         }
         if (bufgo(1)==ERR) {
                 sysclose(writefile);
                 writefile = -1;
                 wfilename[0] = EOS;
                 pmtwfile(wfilename);
                 return;
         }
         while ((bufatbot()==NO)&(bufln()<=to)) {
                 n=bufgetln(databuf,MAXLEN);
                 n=min(n,MAXLEN);
                 if (pushline(writefile,databuf,n)==ERR) {
                         return;
                 }
                 if (bufdn()==ERR) {
                         return;
                 }
         }
         if (bufgo(1)==ERR) {
                 return;
         }
         if (bufndel(to)==ERR){
                 return;
         }
         bufout(bufln(),1,SCRNL1);
         if (bufatbot()) {
                 bufsaved();
         }
         bufgo(1);
 }
 save()
 {
 int n, oldline;
         if (writefile == -1) {                         /* changed to writefil
                 message("file not opened");         /* file assumed already o
                 return;
         }
         oldline=bufln();
         if (bufgo(1)==ERR) {
                 sysclose(writefile);        /* close the writefile if error *
                 writefile = -1;
                 wfilename[0]=EOS;
                 pmtwfile(wfilename);
                 return;
         }
         while (bufatbot()==NO) {
                 n=bufgetln(databuf,MAXLEN);
                 n=min(n,MAXLEN);
                 if (pushline(writefile,databuf,n)==ERR) {
                         break;
                 }
                 if (bufdn()==ERR) {
                         break;
                 }
         }
         if (bufatbot()) {
                 bufsaved();
         }
         bufgo(oldline);
                                         /* writefile no longer closed */
 }
 closeread()                                /* new: close the readfile */
 {
         if (readfile!= -1) {
                 sysclose(readfile);
                 readfile= -1;
                 rfilename[0]=EOS;
                 pmtrfile(rfilename);
         }
 }
 closewrite()                                /* new: close the writefile */
 {
         if (writefile != -1) {
                 sysclose(writefile);
                 writefile= -1;
                 wfilename[0]=EOS;
                 pmtwfile(wfilename);
         }
 }
 search (args,begin,end) char *args; int begin,end;
 {
 int from, to;
         if (get2args(args,&from,&to)==ERR) {
                 if (check2mark(begin,end,&from,&to)==ERR) {
                         sysabort();
                         return;
                 }
         }
         suurch(from,to,NO);
 }
 suurch(from,to,flag) int from, to, flag;   /* old "search1" */
 {
                                         /* now uses module buffer */
 char pat [MAXLEN1];
 int col, n;
         scr_chr_attr(SETINTENSE);
         fmtsout("search mask ?        ",0);
         getcmnd(pat,15);
         fmtcrlf();
         if (pat[0]==EOS) {
                 return (-1);
         }
         while (from<=to) {
                 if (chkkey()==YES) {
                         break;
                 }
                 if (bufgo(from++)==ERR) {
                         sysabort();
                         break;
                 }
                 if (bufatbot()==YES) {
                         sysabort();
                         break;
                 }
                 n=bufgetln(databuf,MAXLEN);
                 n=min(n,MAXLEN);
                 databuf[n]=EOS;
                 if (pat[0]=='^') {
                         if (amatch(databuf,pat+1,NO)==0) {
                                 if (flag==NO) {
                                         fmtcrlf();
                                         putdec(bufln(),5);
                                         fmtsout(databuf,5);
                                         outdeol();
                                 }
                                 else {
                                         return(0);
                                 }
                         }
                         continue;
                 }
                 if ((col=amatch(databuf,pat,YES))>=0) {
                         if (flag==NO) {
                                 fmtcrlf();
                                 putdec(bufln(),5);
                                 fmtsout(databuf,5);
                                 outdeol();
                         }
                         else {
                                 return(col);
                         }
                 }
         }
         if (flag==YES) {
                 return(-1);
         }
         else {
                 fmtcrlf();
         }
 }
 tabs(args) char *args;
 {
 int n,junk;
         if (get2args(args,&n,&junk)==ERR) {
                 sysabort();
                 return;
         }
         fmtset(n);
 }
 chkbuf()
 {
         if (bufchng()==NO) {
                 return(YES);
         }
         scr_chr_attr(SETINTENSE);
         fmtsout("Buffer not saved.  Proceed  ? ",0);
         scr_chr_attr(SETFAINT);
         pmtline();
         if (tolower(syscout(syscin()))!='y') {
                 fmtcrlf();
                 message("cancelled");
                 return(NO);
         }
         else {
                 fmtcrlf();
                 return(YES);
         }
 }
 message(s) char *s;
 {
                 scr_chr_attr(SETINTENSE);
                 fmtsout(s,0);
                 fmtcrlf();
                 scr_chr_attr(SETFAINT);
 }
 getarg(args,val) char *args; int *val;        /* new: get a single argument *
 {
         args=skiparg(args);
         args=skipbl(args);
         if (*args==EOS) {
                 *val=1;
                 return(ERR);
         }
         if (number(args,val)==NO) {
                 message("bad argument");
                 return(ERR);
         }
         return(OK);
 }
 /* new: get three arguments                                                */
 get3args(args,val1,val2,val3) char *args; int *val1, *val2,*val3;
 {
         args=skiparg(args);
         args=skipbl(args);
         if (*args==EOS) {
                 return(ERR);
         }
         if (number(args,val1)==NO) {
                 message("bad argument");
                 return(ERR);
         }
         args=skiparg(args);
         args=skipbl(args);
         if(*args==EOS) {
                 return(ERR);
         }
         if (number(args,val2)==NO) {
                 message("bad argument");
                 return(ERR);
         }
         args=skiparg(args);
         args=skipbl(args);
         if(*args==EOS) {
                 return(ERR);
         }
         if (number(args,val3)==NO) {
                 message("bad argument");
                 return(ERR);
         }
         else {
                 return(OK);
         }
 }
 get2args(args,val1,val2) char *args; int *val1, *val2;
 {
         args=skiparg(args);
         args=skipbl(args);
         if (*args==EOS) {
 /*                *val1=1;
                 *val2=HUGE;   */
                 return(ERR);
         }
         if (number(args,val1)==NO) {
                 message("bad argument");
                 return(ERR);
         }
         args=skiparg(args);
         args=skipbl(args);
         if(*args==EOS) {
         /*        *val2=HUGE;  */
                 return(ERR);
         }
         if (number(args,val2)==NO) {
                 message("bad argument");
                 return(ERR);
         }
         else {
                 return(OK);
         }
 }
 skiparg(args) char *args;
 {
         while ((*args!=EOS)&(*args!=' ')) {
                 args++;
         }
         return(args);
 }
 skipbl(args) char *args;
 {
         while(*args==' ') {
                 args++;
         }
         return(args);
 }
 chkkey()
 {
 int c;
         c=syscstat();
         if (c==-1) {                /* note correction from original version
                 return(NO);
         }
         else if (c==' ') {
                 pmtline();
                 if (syscin()==' ') {
                         return(NO);
                 }
         }
         return(YES);
 }
 /*
 amatch(line,pat,col) char *line, *pat; int col;
 {
 int k;
         k=0;
         while (pat[k]!=EOS) {
                 if (pat[k]==line[col]) {
                         k++;
                         col++;
                 }
                 else if ((pat[k]=='?')&(line[col]!=EOS)) {
                         k++;
                         col++;
                 }
                 else {
                         return(NO);
                 }
         }
         return(YES);
 }
 */
 replace(oldline,newline,oldpat,newpat,col)
 char *oldline, *newline, *oldpat, *newpat; int col;
 {
 int k;
 char *tail, *pat;
         k=0;
         while (k<col) {
                 newline[k++]= *oldline++;
         }
         tail=oldline;
         pat=oldpat;
         while (*pat++!=EOS) {
                 tail++;
         }
         while (*newpat!=EOS) {
                 if (k>MAXLEN-1) {
                         message("new line too long");
                         sysabort();
                         return(ERR);
                 }
                 if (*newpat!='?') {
                         newline[k++]= *newpat++;
                         continue;
                 }
                 while (*oldpat!='?') {
                         if (*oldpat==EOS) {
                                 message(
                                 "too many ?'s in change mask"
                                 );
                                 sysabort();
                                 return(ERR);
                         }
                         oldpat++;
                         oldline++;
                 }
                 newline[k++]= *oldline++;
                 oldpat++;
                 newpat++;
         }
         while (*tail!=EOS) {
                 if (k>MAXLEN-1) {
                         message("new line too long");
                         sysabort();
                         return(ERR);
                 }
                 newline[k++]= *tail++;
         }
         newline[k]=EOS;
         return(k);
 }
 copyit (args,begin,end,dest) char *args; int begin,end,dest;
         /* new: copies "lenn" lines from "from"   */
 {                                /* to "to" */
 int from,to,lenn;
 int topline;
         if (get3args(args,&from,&to,&lenn)==ERR) {
                 if (check3mark(begin,end,dest,&from,&to,&lenn)==ERR) {
                         sysabort();
                         return;
                 }
         }
         if (to == from) {
                 return;
         }
         if ((to>from)&(to<=(from+lenn))) {
                 message("interleaving not permitted");
                 sysabort();
                 return;
         }
         bufcopy(from,to,lenn);
         bufgo(1);
         topline=max(1,bufln()-SCRNL2);
         bufout(topline,2,SCRNL2);
         bufgo(topline);
 }
 moveit (args,begin,end,dest) char *args; int begin,end,dest;

         /* new: moves "lenn" lines from "from" */
 {                                /* to "to" - same as copyit except deletes *
 int from,to,lenn;                /* old lines */
 int topline;
         if (get3args(args,&from,&to,&lenn)==ERR) {
                 if (check3mark(begin,end,dest,&from,&to,&lenn)==ERR) {
                         sysabort();
                         return;
                 }
         }
         if (to == from) {
                 return;
         }
         if ((to>from)&(to<=(from+lenn))) {
                 message("interleaving not permitted");
                 sysabort();
                 return;
         }
         bufcopy(from,to,lenn);
         if (to>from){
                 bufgo(from);
                 bufndel(lenn);
         }
         else {
                 bufgo(from+lenn);
                 bufndel(lenn);
         }
         bufgo(1);
         topline=max(1,bufln()-SCRNL2);
         bufout(topline,2,SCRNL2);
         bufgo(topline);
 }
 check2mark(begin,end,from,to) int begin,end,*from,*to;
 {
         if ((begin==(-1))|(end==(-1))){
                 return(ERR);
         }
         if        (begin>end) {
                 return(ERR);
         }
         *from=begin;
         *to=end;
         return(OK);
 }
 check3mark(begin,end,dest,from,to,lenn) int begin,end,dest;
         int *from,*to,*lenn;
 {
         if ((begin==(-1))|(end==(-1))){
                 return(ERR);
         }
         if (begin>end) {
                 return(ERR);
         }
         *from=begin;
         *to=dest;
         *lenn=end-begin;
 }








 ED4.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED4.C

 /* ED4.C */

 #include "ed0.c"
 #include "ed1.ccc"
 char        editbuf[MAXLEN];
 char pickbuf[PUTBUFLN]; /* pick buffer */
 int picklines, pickend; /* pick buffer parameters */
 int        editp;
 int        editpmax;
 int        edcflag;
 edabt()
 {
         edgetln();
         edredraw();
         edbegin();
         edcflag=NO;
 }
 edbegin()
 {
         editp=0;
         outxy(0,outyget());
 }
 ederase()        /* new: erase from cursor to end of line */
 {
         if (editp==editpmax) {
                 return;
         }
         edcflag=YES;
         editpmax=editp;
         edredraw();
 }
 edhome()        /* new: home cursor.  subsequent calls alternate */
 {                /* cursor to top and bottom of screen */
 int ypos;
         if (edrepl()!=OK){
                 return;
         }
         if ((ypos=outyget())<SCRNL3) {
                 while((ypos<SCRNL1)&&(!bufnrbot())){
                         if (bufdn()!=OK){
                                 return(ERR);
                         }
                         ypos++;
                 }
         }
         else {
                 while((ypos>1)&&(!bufattop())){
                         if (bufup()!=OK){
                                 return(ERR);
                         }
                         ypos--;
                 }
         }
         edgetln();
         outxy(edxpos(),ypos);
 }
 edpick(begin,end) int begin,end; {        /* pick marked lines to buffer */
 int oldline,oldx,oldy,len,nlines;
         if ((begin==(-1))|(end==(-1))|(end<begin)){
                 sysabort();
                 return(ERR);
                 }
         oldx=outxget();
         oldy=outyget();
         if (edrepl()!=OK) {
                 return(ERR);
                 }
         oldline=bufln();
         nlines=end-begin+1;
         len=buflength(begin,nlines);
         if (len>PUTBUFLN){
                 pmtmode("Not picked: no room");
                 sysabort();
                 return(ERR);
                 }
         pickend=len;
         buftopick(pickbuf,begin,nlines);
         bufgo(oldline);
         edgetln();
         editp=edscan(oldx);
         outxy(oldx,oldy);
         edredraw();
         picklines=nlines;
         return(OK);
         }
 edput() {                /* put lines in pick buffer into main buffer */
                         /* before current line */
 int k,oldline,oldx,oldy;
         if (pickend==0){
                 return(OK);
                 }
         oldx=outxget();
         oldy=outyget();
         if (edrepl()!=OK){
                 return(ERR);
                 }
         oldline=bufln();
         if (picktobuf(pickbuf,pickend,picklines)!=OK) {
                 return(ERR);
                 }
         bufgo(oldline);
         if (edatbot()){
                 ;
         }
         else{
                 bufout(bufln()+1,oldy+1,SCRNL1-oldy);
                 }
         edgetln();
         outxy(0,oldy);
         edredraw();
         editp=min(oldx,editpmax);
         outxy(edxpos(),oldy);
         return(OK);
         }
 edchng(c) char c;
 {
 char oldc;
 int k,kk,n,m,tabpos;
         if (editp>=editpmax) {
                 edins(c);
                 return;
         }
 /* experimental code for better treatment of virtual columns */
         if (editbuf[editp]==c) {
                 edright();
                 return;
         }
         tabpos=outxget()%tablength();
         if ((editbuf[editp]==TAB)&(tabpos!=tablength()-1)) {
                 edins(c);
                 return;
         }
         kk=editp-1;
         m=NO;
         if ((kk>=0)&(editbuf[kk]==TAB)&(tabpos!=0)) {
                 editp--;
                 n=outxget()-edxpos();
                 if ((n+fmtlen(editbuf,editpmax)+1)<SCRNW1) {
                         k=editpmax;
                         while (k>(editp+1)) {
                                 editbuf[k+n-1]=editbuf[k-1];
                                 k--;
                         }
                         while (n-- >0) {
                                 editbuf[editp++]=' ';
                                 editpmax++;
                         }
                         m=YES;
                         fmtadj(editbuf,kk,editpmax);
                 }
         }
 /* end experimental code */
         oldc=editbuf[editp];
         editbuf[editp]=c;
         fmtadj(editbuf,editp,editpmax);
         k=fmtlen(editbuf,editpmax);
         if (k>SCRNW1) {
                 editbuf[editp]=oldc;
                 fmtadj(editbuf,editp,editpmax);
         }
         else {
                 edcflag=YES;
                 editp++;
                 if ((c==TAB)|(oldc==TAB)) {
                 edredraw();
                 }
                 else {
                 fmtchdev(c);
                 }
         }
 /* begin experimental code */
         if ((m==YES)&(tabpos!=(tablength()-1))) {
                 k=editpmax;
                 while (k>editp) {
                         editbuf[k]=editbuf[k-1];
                         k--;
                 }
                 editbuf[editp]=TAB;
                 editpmax++;
                 fmtadj(editbuf,editp,editpmax);
                 edredraw();
         }
 /* end experimental code */
 }
 edldel()   /* deletes character before cursor */
 /* eddel() in original version: no change in code */
 {
 int k;
         if(edxpos() < outxget()) {
                 outxy(outxget()-1, outyget());
                 return;
         }
         if (editp==0) {
                 return;
         }
         edcflag=YES;
         k=editp;
         while (k<editpmax) {
                 editbuf[k-1]=editbuf[k];
                 k++;
         }
         editp--;
         editpmax--;
         edredraw();
 }
 edcdel()   /* deletes character at cursor */
 {
 int k;
         if(edxpos() < outxget()) {
                 outxy(outxget()-1, outyget());
                 return;
         }
         edcflag=YES;
         if (editp == editpmax)        {
                 if (editp==0) {
                         return;
                 }
                 editp--;
                 editpmax--;
                 edredraw();
                 return;
         }
         k=editp;
         while (k<(editpmax-1)) {
                 editbuf[k]=editbuf[k+1];
                 k++;
         }
         editpmax--;
         edredraw();
 }
 eddn()
 {
 int oldx;
         oldx=outxget();
         if (edrepl()!=OK) {
                 return(ERR);
         }
         if (bufnrbot()) {
                 sysabort();
                 return(OK);
         }
         if (bufdn()!=OK) {
                 return(ERR);
         }
         edgetln();
         editp=edscan(oldx);
         if (edatbot()) {
                 edsup(bufln()-SCRNL2);
                 outxy(oldx,SCRNL1);
         }
         else {
                 outxy(oldx,outyget()+1);
         }
         return(OK);
 }
 edend()
 {
         editp=editpmax;
         outxy(edxpos(),outyget());
 }
 edgo(n, p) int n, p;
 {
         if (edrepl()==ERR) {
                 return(ERR);
         }
         if (bufgo(n)==ERR) {
                 return(ERR);
         }
         if (bufatbot()) {
                 if (bufup()==ERR) {
                         return(ERR);
                 }
         }
         bufout(bufln(),1,SCRNL1);
         edgetln();
         editp=min(p,editpmax);
         outxy(edxpos(),1);
         return(OK);
 }
 edins(c) char c;
 {
 int k,kk,n,l;
         if (editpmax>=MAXLEN){
                 return;
         }
         if ((editp==editpmax) & (edxpos()<outxget())) {
                 k=outxget() - edxpos();
                 editpmax=editpmax+k;
                 while (k-- > 0) {
                         editbuf [editp++] = ' ';
                 }
                 editp=editpmax;
         }
 /* experimental code for better treatment of virtual columns */
         kk=editp-1;
         if ((kk>=0)&(editbuf[kk]==TAB)&((l=outxget()%tablength())!=0)) {
                 editp--;
                 n=outxget()-edxpos();
                 if ((n+fmtlen(editbuf,editpmax)+1)<SCRNW1) {
                         k=editpmax;
                         while (k>(editp+1)) {
                                 editbuf[k+n-1]=editbuf[k-1];
                                 k--;
                         }
                         while (n-- >0) {
                                 editbuf[editp++]=' ';
                                 editpmax++;
                         }
                         editbuf[editp]=c;
                         editp++;
                         if (l!=(tablength()-1)) {
                                 k=editpmax;
                                 while (k>editp) {
                                         editbuf[k]=editbuf[k-1];
                                         k--;
                                 }
                                 editbuf[editp]=TAB;
                                 editpmax++;
                         }
                         fmtadj(editbuf,kk,editpmax);
                         edredraw();
                         return;
                 }
         }
 /* end experimental code */
         k=editpmax;
         while (k>editp) {
                 editbuf[k]=editbuf[k-1];
                 k--;
         }
         editbuf[editp]=c;
         editp++;
         editpmax++;
         fmtadj(editbuf,editp-1,editpmax);
         k=fmtlen(editbuf,editpmax);
         if (k>SCRNW1) {
                 edldel();
         }
         else {
                 edcflag=YES;
                 edredraw();
         }
 }
 edjoin()
 {
 int k;
         if (bufattop()) {
                 return;
         }
         if (edrepl()!=OK) {
                 return;
         }
         if (bufup()!=OK) {
                 return;
         }
         k = bufgetln(editbuf,MAXLEN);
         if (bufdn()!=OK) {
                 return;
         }
         k=k+bufgetln(editbuf+k,MAXLEN-k);
         if (k>SCRNW1) {
                 bufgetln(editbuf,MAXLEN);
                 return;
         }
         if (bufup()!=OK) {
                 return;
         }
         editpmax=k;
         edcflag=YES;
         if (edrepl()!=OK) {
                 return;
         }
         if (bufdn()!=OK) {
                 return;
         }
         if (bufdel()!=OK) {
                 return;
         }
         if (bufup()!=OK) {
                 return;
         }
         if (edattop()) {
                 edredraw();
         }
         else {
                 k=outyget()-1;
                 bufout(bufln(),k,SCRNL-k);
                 outxy(0,k);
                 edredraw();
         }
 }
 edkill(c) char c;
 {
 int k,p;
         if (editp==editpmax) {
                 return;
         }
         edcflag=YES;
         k=1;
         while ((editp+k)<editpmax) {
                 if (editbuf[editp+k]==c){
                         break;
                 }
                 else {
                         k++;
                 }
         }
         p=editp+k;
         while (p<editpmax) {
                 editbuf[p-k]=editbuf[p];
                 p++;
         }
         editpmax=editpmax-k;
         edredraw();
 }
 edleft()
 {
 int k;
         if (edxpos()<outxget()){
                 outxy(max(0,outxget()-1),outyget());
         }
         else if (editp!=0){
                 editp--;
                 outxy(edxpos(),outyget());
         }
 }
 ednewdn()
 {
 int k;
         if (bufatbot()){
                 if (bufins(editbuf,editpmax)!=OK){
                         return;
                 }
         }
         else if (edrepl()!=OK){
                         return;
         }
         if (bufdn()!=OK){
                 return;
         }
         if (bufins(editbuf,0)!=OK){
                 return;
         }
         edgetln();
         if (edatbot()){
                 edsup(bufln()-SCRNL2);
                 outxy(edxpos(),SCRNL1);
         }
         else {
                 k=outyget();
                 bufout(bufln(),k+1,SCRNL1-k);
                 outxy(edxpos(),k+1);
         }
 }
 ednewup()
 {
 int k;
         if (edrepl()!=OK) {
                 return;
         }
         if (bufins(editbuf,0)!=OK){
                 return;
         }
         edgetln();
         if (edattop()){
                 edsdn(bufln());
                 outxy(edxpos(),1);
         }
         else {
                 k=outyget();
                 bufout(bufln(),k,SCRNL-k);
                 outxy(edxpos(),k);
         }
 }
 edright()        /* right one literal character - tabs move to next tab stop
 {
         if (edxpos()<outxget()){
                 outxy(min(SCRNW1,outxget()+1),outyget());
         }
         else if (edxpos()>outxget()){
                 outxy(edxpos(),outyget());
         }
         else if (editp<editpmax){
                 editp++;
                 outxy(edxpos(),outyget());
         }
         else {
                 outxy(min(SCRNW1,outxget()+1),outyget());
         }
 }
 edsplit()
 {
 int p,q;
 int k;
         edcflag = NO;
         if (bufatbot()){
                 if (bufins(editbuf,editp)!=OK){
                         return;
                 }
         }
         else {
                 if (bufrepl(editbuf,editp)!=OK){
                         return;
                 }
         }
         p=editpmax;
         q=editp;
         editpmax=editp;
         editp=0;
         edredraw();
         editp=0;
         while (q<p){
                 editbuf[editp++] = editbuf[q++];
         }
         editpmax=editp;
         editp=0;
         if (bufdn()!=OK){
                 return;
         }
         if (bufins(editbuf,editpmax)!=OK) {
                 return;
         }
         if (edatbot()) {
                 edsup(bufln()-SCRNL2);
                 outxy(1,SCRNL1);
                 edredraw();
         }
         else {
                 k=outyget();
                 bufout(bufln(),k+1,SCRNL1-k);
                 outxy(1,k+1);
                 edredraw();
         }
 }
 edsrch(c) char c;
 {
         if (editp==editpmax){
                 return;
         }
         editp++;
         while (editp<editpmax) {
                 if (editbuf[editp]==c) {
                         break;
                 }
                 else {
                         editp++;
                 }
         }
         outxy(edxpos(),outyget());
 }
 edabsright()  /* right one column - one virtual character */
 {
 int xpos;
         xpos=outxget();
         if (xpos<SCRNW1) {
                 outxy(++xpos,outyget());
                 editp=edscan(xpos);
         }
 }
 edabsleft()   /* left one column - one virtual character */
 {
 int xpos;
         xpos=outxget();
         if (xpos>0) {
                 outxy(--xpos,outyget());
                 editp=edscan(xpos);
         }
 }
 edup()
 {
 int oldx;
         oldx=outxget();
         if (edrepl()!=OK) {
                 return(ERR);
         }
         if (bufattop()) {
                 sysabort();
                 return(OK);
         }
         if (bufup()!=OK){
                 return(ERR);
         }
         edgetln();
         editp=edscan(oldx);
         if (edattop()) {
                 edsdn(bufln());
                 outxy(oldx,1);
         }
         else {
                 outxy(oldx,outyget()-1);
         }
         return(OK);
 }
 edzap()
 {
 int k;
         if (bufdel()!=OK){
                 return;
         }
         if (bufatbot()){
                 if (bufup()!=OK){
                         return;
                 }
                 edgetln();
                 if (edattop()) {
                         edredraw();
                 }
                 else {
                         outdelln();
                         outxy(0,outyget()-1);
                 }
                 return;
         }
         edgetln();
         if (edattop()) {
                 edsup (bufln());
                 outxy(0,1);
         }
         else {
                 k=outyget();
                 bufout(bufln(),k,SCRNL-k);
                 outxy(0,k);
         }
 }
 edatbot()
 {
         return(outyget()==SCRNL1);
 }
 edattop()
 {
         return(outyget()==1);
 }
 edredraw()
 {
         fmtadj(editbuf,0,editpmax);
         fmtsubs(editbuf,max(0,editp-1),editpmax);
         outxy(edxpos(),outyget());
 }
 edxpos()
 {
         return(min(SCRNW1,fmtlen(editbuf,editp)));
 }
 edgetln()
 {
 int k;
         editp=0;
         edcflag=NO;
         k=bufgetln(editbuf,MAXLEN);
         if (k>MAXLEN) {
                 error("line truncated");
                 editpmax=MAXLEN;
         }
         else {
                 editpmax=k;
         }
         fmtadj(editbuf,0,editpmax);
 }
 edrepl()
 {
         if (edcflag==NO) {
                 return(OK);
         }
         edcflag=NO;
         if (bufatbot()){
                 return(bufins(editbuf,editpmax));
         }
         else {
                 return(bufrepl(editbuf,editpmax));
         }
 }
 edscan(xpos) int xpos;
 {
         editp=0;
         while (editp<editpmax){
                 if (fmtlen(editbuf,editp)<xpos){
                         editp++;
                 }
                 else {
                         break;
                 }
         }
         return(editp);
 }
 edsup(topline) int topline;
 {
         if (outuphas()==YES){
                 outsup();
                 bufout(topline+SCRNL2,SCRNL1,1);
         }
         else {
                 bufout(topline,1,SCRNL1);
         }
 }
 edsdn(topline) int topline;
 {
         if (outdnhas()==YES) {
                 outsdn();
                 bufout(topline,1,1);
         }
         else {
                 bufout(topline,1,SCRNL1);
         }
 }


 ED5.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED5.C

 /* ED5.C */

 #include "ed0.c"
 #include "ed1.ccc"
 int fmtrev;
 int fmttab;
 int fmtdev;
 int fmtwidth;
 int fmtcol[MAXLEN1];
 tablength()
 {
         return(fmttab);
 }
 fmtytab()
 {
         fmtrev=YES;
 }
 fmtntab()
 {
         fmtrev=NO;
 }
 fmtassn(listflag) int listflag;
 {
         if (listflag==YES) {
                 fmtdev=YES;
                 fmtwidth=LISTW;
         }
         else {
                 fmtdev=NO;
                 fmtwidth=SCRNW1;
         }
 }
 fmtadj(buf,minind,maxind) char *buf; int minind,maxind;
 {
 int k;
         fmtcol[0]=0;
         k=minind;
         while (k<maxind) {
                 if (buf[k]==CR) {
                         break;
                 }
                 fmtcol[k+1]=fmtcol[k]+fmtchlen(buf[k],fmtcol[k]);
                 k++;
         }
 }
 fmtlen(buf,i) char *buf; int i;
 {
         return(fmtcol[i]);
 }
 fmtsubs(buf,i,j) char *buf; int i,j;
 {
 int k;
         if (fmtcol[i]>=fmtwidth) {
                 return;
         }
         outxy(fmtcol[i],outyget());
         while (i<j) {
                 if (buf[i]==CR) {
                         break;
                 }
                 if (fmtcol[i+1]>fmtwidth) {
                         break;
                 }
                 fmtoutch(buf[i],fmtcol[i]);
                 i++;
         }
         if (fmtcol[i]<SCRNW1) {    /* modified to allow full screen width */
         outdeol();
         }
 }
 fmtsout(buf,offset) char *buf; int offset;
 {
 char c;
 int col,k;
         col=0;
         while (c= *buf++) {
                 if (c==CR) {
                         break;
                 }
                 k=fmtchlen(c,col);
                 if ((col+k+offset)>fmtwidth) {
                         break;
                 }
                 fmtoutch(c,col);
                 col=col+k;
         }
         return(col);                /* fmtsout() now returns column value */
 }
 fmtchlen(c,col) char c; int col;
 {
         if (c==TAB) {
                 return(fmttab-(col%fmttab));
         }
         else if ((c<32)&(fmtdev==NO)) {
                 return(2);
         }
         else {
                 return(1);
         }
 }
 fmtoutch(c,col) char c; int col;
 {
 int k;
         if (c==TAB) {
                 k=fmtchlen(TAB,col);
                 if ((fmtdev==NO)&(fmtrev==YES)) {
 /*show tab characters in reverse video */
                         scr_chr_attr(SETREVERSE);
                 }
                 while ((k--)>0) {
                         fmtchdev(' ');
                 }
                 if ((fmtdev==NO)&(fmtrev==YES)) {
                         scr_chr_attr(SETNORMAL);
                 }
         }
         else if (c<32) {
 /* show control characters in reverse video */
                 if (fmtdev==NO) {
                         scr_chr_attr(SETREVERSE);
                         fmtchdev(c+64);
                         scr_chr_attr(SETNORMAL);
                 }
                 else {
                         fmtchdev('^');
                         fmtchdev(c+64);
                 }
         }
         else {
                 fmtchdev(c);
         }
 }
 fmtchdev(c) char c;
 {
         if (fmtdev==YES) {
                 syslout(c);
         }
         else {
                 outchar(c);
         }
 }
 fmtcrlf()
 {
         if (fmtdev==YES) {
                 syslout(CR);
                 syslout(LF);
         }
         else {
                 outxy(0,SCRNL1);
                 syscout(CR);
                 syscout(LF);
         }
 }
 fmtset(n) int n;
 {
         fmttab=max(1,n);
 }


 ED6.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED6.C

 /* ED6.C */

 #include "ed0.c"
 #include "ed1.ccc"
 int outx,outy;
 outxget()
 {
         return(outx);
 }
 outyget()
 {
         return(outy);
 }
 outchar(c) char c;
 {
         syscout(c);
         outx++;
         return(c);
 }
 outxy(x,y) int x,y;
 {
         outx=x;
         outy=y;
         scr_rowcol(y,x);
 }
 outclr()
 {
         scr_clr();
 }
 outdelln()
 {
         outxy(0,outy);
         outdeol();
 }
 outdeol()
 {
         scr_clrl();
 }
 outuphas()
 {
         return(YES);
 }
 outdnhas()
 {
         return(YES);
 }
 outsup()
 {
         outxy(0,SCRNL1);
         sysdelay();
         scr_scup();
 }
 outsdn()
 {
         outxy(0,0);
         sysdelay();
         scr_scdn();
 }


 ED7.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED7.C

 /* ED7.C */

 #include "ed0.c"
 #include "ed1.ccc"
 char pmtln[MAXLEN];
 char pmtrfn[SYSFNMAX];                /* now both read and write filenames */
 char pmtwfn[SYSFNMAX];
 pmtmess(s1,s2) char *s1, *s2;
 {
 int x,y;
         x=outxget();
         y=outyget();
         outxy(0,0);
         outdelln();
         pmt1line();
         pmt1col(x);
         scr_chr_attr(SETINTENSE);
         fmtsout(s1,outxget());
         fmtsout(s2,outxget());
         scr_chr_attr(SETFAINT);
         syscin();
         pmt1line();
         pmt1col(x);
         pmt1file(pmtrfn);
         pmt2file(pmtwfn);
         pmt1mode(pmtln);
         outxy(x,y);
 }
 pmtmode(s) char *s;
 {
 int x,y;
         x=outxget();
         y=outyget();
         outxy(0,0);
         outdelln();
         pmt1line();
         pmt1col(x);
         pmt1file(pmtrfn);
         pmt2file(pmtwfn);
         pmt1mode(s);
         outxy(x,y);
 }
 pmtrfile(s) char *s;        /*changed: readfile */
 {
 int x,y;
         x=outxget();
         y=outyget();
         outxy(0,0);
         outdelln();
         pmt1line();
         pmt1col(x);
         pmt1file(s);
         pmt2file(pmtwfn);  /* add writefile */
         pmt1mode(pmtln);
         outxy(x,y);
 }
 pmtwfile(s) char *s;        /* new: writefile */
 {
 int x,y;
         x=outxget();
         y=outyget();
         outxy(0,0);
         outdelln();
         pmt1line();
         pmt1col(x);
         pmt1file(pmtrfn);
         pmt2file(s);
         pmt1mode(pmtln);
         outxy(x,y);
 }
 pmtedit()
 {
         pmtmode("edit:         ");        /* add blanks to assure erasing "co
 }
 pmtline()
 {
 int x,y;
         x=outxget();
         y=outyget();
         outxy(0,0);
         outdelln();
         pmt1line();
         pmt1col(x);
         pmt1file(pmtrfn);        /* change: separate read and write files */
         pmt2file(pmtwfn);
         pmt1mode(pmtln);
         outxy(x,y);
 }
 pmtcol()
 {
 int x,y;
         x=outxget();
         y=outyget();
         pmt1col(x);
         outxy(x,y);
 }
 pmtcmnd(mode,buffer) char *mode, *buffer;
 {
 int x,y;
         x=outxget();
         y=outyget();
         pmt1mode(mode);
         getcmnd(buffer,outxget());
 }
 pmt1mode(s) char *s;
 {
 int i;
         outxy(60,0);                /* change of column location */
         scr_chr_attr(SETINTENSE);
         fmtsout(s,60);
         scr_chr_attr(SETFAINT);
         i=0;
         while (pmtln[i++]= *s++) {
                 ;
         }
 }
 pmt1file(s) char *s;
 {
 int i;
         outxy(25,0);
         scr_chr_attr(SETINTENSE);
         if (*s==EOS) {
                 fmtsout("no rdfile",25);        /* change of message */
         }
         else {
                 fmtsout(s,25);
         }
         scr_chr_attr(SETFAINT);
         i=0;
         while (pmtrfn[i++]= *s++) {
                 ;
         }
 }
 pmt2file(s) char *s;        /* new: write out writefile name or "no wrtfile"
 {
 int i;
         outxy(40,0);
         scr_chr_attr(SETINTENSE);
         if (*s==EOS) {
                 fmtsout("no wrtfile",40);
         }
         else {
                 fmtsout(s,40);
         }
         scr_chr_attr(SETFAINT);
         i=0;
         while (pmtwfn[i++]= *s++) {
                 ;
         }
 }
 pmt1line()
 {
         outxy(0,0);
         scr_chr_attr(SETINTENSE);
         fmtsout("line: ",0);
         putdec(bufln(),5);
         scr_chr_attr(SETFAINT);
 }
 pmt1col(x) int x;
 {
         outxy(12,0);
         scr_chr_attr(SETINTENSE);
         fmtsout("column: ",12);
         putdec(x,3);
         scr_chr_attr(SETFAINT);
 }


 ED8.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED8.C

 /* ED8.C */

 #include "ed0.c"
 #include "ed1.ccc"
 char        keybuf[MAXKEY];  /* macro buffer for keystroke record and replay
 int        replay_count; /* how many times to replay */
 int        replay_number; /* current replay number */
 int        replay_flag;  /* are we replaying from buffer? */
 int        record_flag;  /* are we recording to buffer? */
 int        key_position; /* current position in buffer */
 sysabort()        /*  abort replay of buffer */
 {
         record_flag=NO;
         replay_flag=NO;
         key_position=0;
         replay_number=0;
 }
 syscount(count) int count;        /* set number of replays */
 {
         replay_count=count;
 }
 syscstat()
 {
 int c;
         c=scr_csts();
         if (c==0){                /* correction of original version */
                 return(-1);
         }
         else {
                 return(c);
         }
 }
 syscin() /* extensively altered to permit recording and replay of buffer */
 {
 int c;
         if (replay_flag==YES) {  /* proceed if we are replaying */
                 if ((c=syscstat())>0) {
                         pmtmode("       "); /* abort replay if key pressed */
                         record_flag=NO;
                         replay_flag=NO;
                         key_position=0;
                         replay_number=0;
                         return(c);
                 }
                 else {
                         c=keybuf[key_position++]; /* otherwise replay */
                         if (c==EOS) {
                                 key_position=0;
                                 if((++replay_number)==replay_count) {
                                         pmtmode("        "); /* finished */
                                         replay_flag=NO;
                                         replay_number=0;
                                 }
                         }
                         return(c);
                 }
         }
         else {
                 while ((c=scr_ci())==0) {
                         ;
                 }
                 if (c==RECORD) {
                         if (record_flag==NO) {  /* begin record */
                                 pmtmode("record");
                                 record_flag=YES;
                                 replay_flag=NO;
                                 key_position=0;
                                 keybuf[key_position]=EOS;
                         }
                         else {
                                 pmtmode("end record"); /* end record */
                                 record_flag=NO;
                         }
                         return(c);
                 }
                 else if (c==REPLAY) {  /* start replay */
                         pmtmode("replay");
                         replay_flag=YES;
                         record_flag=NO;
                         replay_number=0;
                         key_position=0;
                         return(c);
                 }
                 else if (record_flag==YES) {
                         if (key_position<MAXKEY1) {
                                 keybuf[key_position++]=c;
                                 keybuf[key_position]=EOS;
                                 return(c);
                         }
                         else {
                                 record_flag=NO;
                                 key_position=0;
                                 keybuf[key_position]=EOS;
                                 error("record overflow");
                                 return(c);
                         }
                 }
                 else  {
                         return(c);
                 }
         }
 }
 syscout(c) char c;
 {
         scr_co(c);
         return(c);
 }
 syslout(c) char c;
 {
         _os(5,c);
         return(c);
 }
 sysend()
 {
         return(_showsp()-200);
 }        /* added */
 syscreate(name) char *name;
 {
 int file;
         if ((file=creat(name))==0) {
                 return(ERR);
         }
         else {
                 return(file);
         }
 }
 sysopen(name,mode) char *name, *mode;
 {
 int file;
         if ((file=fopen(name,mode))==0) {
                 return(ERR);
         }
         else {
                 return(file);
         }
 }
 sysclose(file) int file;
 {
         close(file);
         return(OK);
 }
 sysrdch(file) int file;
 {
 int c;
         if ((c=getc(file))==-1) {
                 return(EOF);
         }
         else if (c==LF) {
                 if ((c=getc(file))==-1) {
                         return(EOF);
                         }
         }
         return(c);
 }
 syspshch(c,file) char c; int file;
 {
         if (putc(c,file)==-1) {
                         error("disk write failed");
                         return(ERR);
         }
         if (c==CR) {
                 if (putc(LF,file)==-1) {
                 error("disk write failed");
                 return(ERR);
                 }
         }
         return(c);
 }
 syspopch(file) int file;
 {
         error("syspopch() not implemented");
         return(ERR);
 }
 syschkfn(args) char *args;
 {
         if (args[0] == EOS) {        /* add check for zero-length file name *
                 message("no file name");
                 return(ERR);
         }
         else {
                 return(OK);
         }
 }
 syscopfn(args,buffer) char *args, *buffer;
 {
 int n;
         n=0;
         while (n<SYSFNMAX-1) {
                 if (args[n]==EOS) {
                         break;
                 }
                 else {
                         buffer[n]=args[n];
                         n++;
                 }
         }
         buffer[n]=EOS;
 }
 sysdnmov(n,d,s) int n,*d,*s;
 {
         if (n==0) {
                 return;
         }
         _move(n,s,d);
 }        /* added */
 sysupmov (n,d,s) int n,*d,*s;
 {
         if (n==0) {
                 return;
         }
         _move(n,s,d);
 }        /* added */
 amatch (a,b,c) int a,b,c;
 /* matches pattern at b to line at a
    all all question marks match
    if flag c is NO match is only at beginning of line
 */
 {
 #asm
         mov        bx,[bp+06]
         mov        dx,[bp+04]
         mov        al,[bx]
         cmp        al,0
         je        no_match
         mov        cx,0
         mov        si,[bp+04]
 cycles:        mov        ah,[si]
         cmp        ah,0
         je        no_match
         cmp        al,ah
         jne        not_so_far
 reprieve:        inc        bx
         inc        si
         mov        al,[bx]
         cmp        al,0
         je        success
         jmp        cycles
 not_so_far:        cmp        al,'?'
         je        reprieve
         mov        ax,[bp+08]
         cmp        ax,0
         je        no_match
         inc        dx
         inc        cx
         mov        si,dx
         mov        bx,[bp+06]
         mov        al,[bx]
         jmp        cycles
 success:        mov        ax,cx
         jmp        returns
 no_match:        mov        ax,0ffffh
 returns:        nop
 #
 }
 sysdelay()
 {
 }
 sysinit()
 {
         scr_setup(); /* start things up & initialize */
         scr_setmode(3);
         scr_clr();
         scr_chr_attr(SETNORMAL);
         scr_chr_attr(SETFAINT);
         scr_chr_attr(NOBLINK);
         replay_flag=NO;
         record_flag=NO;
         replay_count=1;
         keybuf[0]=EOS;
         key_position=0;
 }
 sysfinish()
 {
         scr_chr_attr(SETNORMAL); /* finish up loose ends */
         scr_chr_attr(SETFAINT);
         scr_chr_attr(NOBLINK);
         scr_clr();
         scr_rowcol(0,0);
 }


 ED9.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT_C\ED9.C

 /* ED9.C */

 #include "ed0.c"
 #include "ed1.ccc"
 toupper(c) int c;
 {
         if ((c<'a')|(c>'z')) {
                 return(c);
         }
         else {
                 return(c-32);
         }
 }
 tolower(c) int c;
 {
         if ((c<'A')|(c>'Z')) {
                 return(c);
         }
         else {
                 return(c+32);
         }
 }
 number(args,val) char *args; int *val;
 {
 char c;
         c= *args++;
         if ((c<'0')|(c>'9')) {
                 return(NO);
         }
         *val=c-'0';
         while (c= *args++) {
                 if ((c<'0')|(c>'9')) {
                         break;
                 }
                 *val=(*val*10)+c-'0';
         }
         return(YES);
 }
 ctoi(buf,index) char *buf; int index;
 {
 int k;
         while ((buf[index]==' ')|
                 (buf[index]==TAB)){
                 index++;
         }
         k=0;
         while ((buf[index]>='0')&(buf[index]<='9')) {
                 k=(k*10)+buf[index]-'0';
                 index++;
         }
         return(k);
 }
 max(m,n) int m,n;
 {
         if (m>=n) {
                 return(m);
         }
         else {
                 return(n);
         }
 }
 min(m,n) int m,n;
 {
         if (m<=n) {
                 return(m);
         }
         else {
                 return(n);
         }
 }
 putdec(n,w) int n,w;
 {
 char chars[10];
 int i,nd;
         nd=itoc(n,chars,10);
         i=0;
         while (i<nd) {
                 syscout(chars[i++]);
         }
         i=nd;
         while (i++<w) {
                 syscout(' ');
         }
 }
 itoc(n,str,size) int n; char *str; int size;
 {
 int absval;
 int len;
 int i,j,k;
         absval=abs(n);
         str[0]=0;
         i=1;
         while (i<size) {
                 str[i++]=(absval%10)+'0';
                 absval=absval/10;
                 if (absval==0) {
                         break;
                 }
         }
         if ((i<size)&(n<0)) {
                 str[i++]='-';
         }
         len=i-1;
         i--;
         j=0 ;
         while (j<i) {
                 k=str[i];
                 str[i]=str[j];
                 str[j]=k;
                 i--;
                 j++;
         }
         return(len);
 }
 abs(n) int n;
 {
         if (n<0) {
                 return(-n);
         }
         else {
                 return(n);
         }
 }
 syserr(s) char *s;
 {
         scr_chr_attr(SETBLINK);
         pmtmess("system error: ",s);
         scr_chr_attr(NOBLINK);
 }
 error(s) char *s;
 {
         scr_chr_attr(SETBLINK);
         pmtmess("error: ",s);
         scr_chr_attr(NOBLINK);
 }
 diskerr(s) char *s;
 {
         scr_chr_attr(SETBLINK);
         pmtmess("disk error: ",s);
         scr_chr_attr(NOBLINK);
 }
 readline(file,p,n) int file; char *p; int n;
 {
 int c;
 int k;
         k=0;
         while (1) {
                 c=sysrdch(file);
                 if (c==ERR) {
                         return(ERR);
                 }
                 if (c==EOF) {
                         return(EOF);
                 }
                 if (c==CR) {
                         return(k);
                 }
                 if (k<n) {
                         *p++=c;
                 }
                 k++;
         }
 }
 pushline(file,p,n) int file; char *p; int n;
 {
         while((n--)>0) {
                 if (syspshch(*p++,file)==ERR) {
                         return(ERR);
                 }
         }
         return(syspshch(CR,file));
 }
 popline(file,p,n) int file; char *p; int n;
 {
 int c;
 int k, kmax, t;
         c=syspopch(file);
         if (c==EOF) {
                 return(EOF);
         }
         if (c==CR) {
                 *p++ =CR;
                 k=1;
         }
         else {
                 syserr("popline:  missing CR");
                 return(ERR);
         }
         while (1) {
                 c=syspopch(file);
                 if (c==ERR) {
                         return(ERR);
                 }
                 if (c==EOF) {
                         break;
                 }
                 if (c==CR) {
                         if (syspshch(CR,file)==ERR) {
                                 return(ERR);
                         }
                         break;
                 }
                 if (k<n) {
                         *p++ =c;
                 }
                 k++;
         }
         kmax=k;
         k=min(k,n-1);
         t=0;
         while (k>t) {
                 c=p[k];
                 p[k]=p[t];
                 p[t]=c;
                 k--;
                 t++;
         }
         return(kmax);
 }


 EDINPUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUTILS\EDINPUT.C

 /*
                 AUTHOR          Jon Wesener
                 DATE            7 / 18 / 85
                 PURPOSE         This routine will give interactive input
                                 from the screen with editing functions.
 */

 /*
         KEYGETS will get a string of max size length from the keyboard.
                 The passed in string should be buffered out maximally.

         keygets(string, length, row, col, page, upper);

         RETURN:         nothing
 */

 #define         ESC     27
 #define         BKSP    8
 #define         CR      13
 #define         NORM    15
 #define         RESET   7
 #define         INV     112
 #include        "key.h"

 keygets(str,len,row,col,page,upper)
 char    *str;
 int     len, row, col, page, upper;
 {
         int     bol, eol, cnt, ins=0, tmp;
         char    *ptr, ch, *cpy;

         bol=col;
         eol=col+len-2;
         ptr=str;
         atputs(ptr,page,row,col,NORM);
         atputc(*ptr,page,row,col,INV);
         while ( (ch=getcw()) != CR)
         {
                 atputc(*ptr,page,row,col,NORM);
                 switch(ch){
                 case    LFTCH : if (col > bol)
                                         {ptr--;col--;}
                                 break;

                 case    RGTCH : if (col < eol)
                                         {ptr++;col++;}
                                 break;

                 case    DEL   : strcpy(ptr,ptr+1);
                                 str[len-2]=' ';
                                 atputs(ptr,page,row,col,NORM);
                                 break;

                 case    BKSP  : if (col > bol)
                                 {       ptr--; col--;
                                         strcpy(ptr,ptr+1);
                                         str[len-2]=' ';
                                         atputs(ptr,page,row,col,NORM);
                                 }
                                 break;
                 case    BOL   : ptr=str;
                                 col=bol;
                                 break;

                 case    EOL   : ptr=str+len-2;
                                 col=eol;
                                 break;

                 case    INS   : ins= !ins;
                                 break;

                 default       : if ( (ch >= ' ') && (ch <= '~') )
                                 {
                                 if ( (upper) && (ch >= 'a') && (ch <= 'z') )
                                         ch=ch-'a'+'A';
                                 if (ins)
                                   {for(tmp=eol,cpy=str+len-2;tmp>col;tmp--)
                                         *(cpy--)=*cpy;
                                   atputs(ptr,page,row,col,NORM);
                                   }
                                 *ptr=ch;
                                 atputc(ch,page,row,col,NORM);
                                 if (col < eol)
                                         {ptr++;col++;}
                                 }
                                 break;
                 }
                 atputc(*ptr,page,row,col,INV);
         }
         atputs(str,page,row,bol,RESET);
 }


 EDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\EDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==EAST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 EDIT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\EDIT.C

 /*
  * STevie - ST editor for VI enthusiasts.     ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 /*
  * This flag is used to make auto-indent work right on lines where only
  * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
  * and reset when any other editting is done on the line. If an <ESC>
  * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
  */
 bool_t        did_ai = FALSE;

 void
 edit()
 {
         int c;
         char *p, *q;

         Prenum = 0;

         /* position the display and the cursor at the top of the file. */
         *Topchar = *Filemem;
         *Curschar = *Filemem;
         Cursrow = Curscol = 0;

         for ( ;; ) {

         /* Figure out where the cursor is based on Curschar. */
         cursupdate();

         windgoto(Cursrow,Curscol);

         c = vgetc();

         if (State == NORMAL) {

                 /* We're in the normal (non-insert) mode. */

                 /* Pick up any leading digits and compute 'Prenum' */
                 if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
                         Prenum = Prenum*10 + (c-'0');
                         continue;
                 }
                 /* execute the command */
                 normal(c);
                 Prenum = 0;

         } else {

                 switch (c) {        /* We're in insert mode */

                 case ESC:        /* an escape ends input mode */

                         set_want_col = TRUE;

                         /* Don't end up on a '\n' if you can help it. */
                         if (gchar(Curschar) == NUL && Curschar->index != 0)
                                 dec(Curschar);

                         /*
                          * The cursor should end up on the last inserted
                          * character. This is an attempt to match the real
                          * 'vi', but it may not be quite right yet.
                          */
                         if (Curschar->index != 0 && !endofline(Curschar))
                                 dec(Curschar);

                         State = NORMAL;
                         msg("");
                         *Uncurschar = *Insstart;
                         Undelchars = Ninsert;
                         /* Undobuff[0] = '\0'; */
                         /* construct the Redo buffer */
                         p=Redobuff;
                         q=Insbuff;
                         while ( q < Insptr )
                                 *p++ = *q++;
                         *p++ = ESC;
                         *p = NUL;
                         updatescreen();
                         break;

                 case CTRL('D'):
                         /*
                          * Control-D is treated as a backspace in insert
                          * mode to make auto-indent easier. This isn't
                          * completely compatible with vi, but it's a lot
                          * easier than doing it exactly right, and the
                          * difference isn't very noticeable.
                          */
                 case BS:
                         /* can't backup past starting point */
                         if (Curschar->linep == Insstart->linep &&
                             Curschar->index <= Insstart->index) {
                                 beep();
                                 break;
                         }

                         /* can't backup to a previous line */
                         if (Curschar->linep != Insstart->linep &&
                             Curschar->index <= 0) {
                                 beep();
                                 break;
                         }

                         did_ai = FALSE;
                         dec(Curschar);
                         delchar(TRUE);
                         Insptr--;
                         Ninsert--;
                         cursupdate();
                         updateline();
                         break;

                 case CR:
                 case NL:
                         *Insptr++ = NL;
                         Ninsert++;
                         opencmd(FORWARD, TRUE);                /* open a new
                         cursupdate();
                         updatescreen();
                         break;

                 default:
                         did_ai = FALSE;
                         insertchar(c);
                         break;
                 }
         }
         }
 }

 /*
  * Special characters in this context are those that need processing other
  * than the simple insertion that can be performed here. This includes ESC
  * which terminates the insert, and CR/NL which need special processing to
  * open up a new line. This routine tries to optimize insertions performed
  * by the "redo" command, so it needs to know when it should stop and defer
  * processing to the "normal" mechanism.
  */
 #define        ISSPECIAL(c)        ((c) == NL || (c) == CR || (c) == ESC)

 void
 insertchar(c)
 int c;
 {
         char *p;

         if ( ! anyinput() ) {
                 inschar(c);
                 *Insptr++ = c;
                 Ninsert++;
                 /*
                  * The following kludge avoids overflowing the statically
                  * allocated insert buffer. Just dump the user back into
                  * command mode, and print a message.
                  */
                 if (Insptr+10 >= &Insbuff[1024]) {
                         stuffin(mkstr(ESC));
                         emsg("No buffer space - returning to command mode");

 /* added for turbo c port 6-14-88 dlm */

 #ifdef TURBO
                         msleep(2);
 #else
                         sleep(2);
 #endif
                 }
         }
         else {
                 /* If there's any pending input, grab it all at once. */
                 p = Insptr;
                 *Insptr++ = c;
                 Ninsert++;
                 for (c = vpeekc(); !ISSPECIAL(c) ;c = vpeekc()) {
                         c = vgetc();
                         *Insptr++ = c;
                         Ninsert++;
                 }
                 *Insptr = '\0';
                 insstr(p);
         }
         updateline();
 }

 void
 getout()
 {
         windgoto(Rows-1,0);
         putchar('\r');
         putchar('\n');
         windexit(0);
 }

 void
 scrolldown(nlines)
 int nlines;
 {
         register LPTR        *p;
         register int        done = 0;        /* total # of physical lines don

         /* Scroll up 'nlines' lines. */
         while (nlines--) {
                 if ((p = prevline(Topchar)) == NULL)
                         break;
                 done += plines(p);
                 *Topchar = *p;
                 if (Curschar->linep == Botchar->linep->prev)
                         *Curschar = *prevline(Curschar);
         }
         s_ins(0, done);
 }

 void
 scrollup(nlines)
 int nlines;
 {
         register LPTR        *p;
         register int        done = 0;        /* total # of physical lines don
         register int        pl;                /* # of plines for the current

         /* Scroll down 'nlines' lines. */
         while (nlines--) {
                 pl = plines(Topchar);
                 if ((p = nextline(Topchar)) == NULL)
                         break;
                 done += pl;
                 if (Curschar->linep == Topchar->linep)
                         *Curschar = *p;
                 *Topchar = *p;

         }
         s_del(0, done);
 }

 /*
  * oneright
  * oneleft
  * onedown
  * oneup
  *
  * Move one char {right,left,down,up}.  Return TRUE when
  * sucessful, FALSE when we hit a boundary (of a line, or the file).
  */

 bool_t
 oneright()
 {
         set_want_col = TRUE;

         switch (inc(Curschar)) {

         case 0:
                 return TRUE;

         case 1:
                 dec(Curschar);                /* crossed a line, so back up *
                 /* fall through */
         case -1:
                 return FALSE;
         }
 }

 bool_t
 oneleft()
 {
         set_want_col = TRUE;

         switch (dec(Curschar)) {

         case 0:
                 return TRUE;

         case 1:
                 inc(Curschar);                /* crossed a line, so back up *
                 /* fall through */
         case -1:
                 return FALSE;
         }
 }

 void
 beginline(flag)
 bool_t        flag;
 {
         while ( oneleft() )
                 ;
         if (flag) {
                 while (isspace(gchar(Curschar)) && oneright())
                         ;
         }
         set_want_col = TRUE;
 }

 bool_t
 oneup(n)
 {
         LPTR p, *np;
         int k;

         p = *Curschar;
         for ( k=0; k<n; k++ ) {
                 /* Look for the previous line */
                 if ( (np=prevline(&p)) == NULL ) {
                         /* If we've at least backed up a little .. */
                         if ( k > 0 )
                                 break;        /* to update the cursor, etc. *
                         else
                                 return FALSE;
                 }
                 p = *np;
         }
         *Curschar = p;
         /* This makes sure Topchar gets updated so the complete line */
         /* is one the screen. */
         cursupdate();
         /* try to advance to the column we want to be at */
         *Curschar = *coladvance(&p, Curswant);
         return TRUE;
 }

 bool_t
 onedown(n)
 {
         LPTR p, *np;
         int k;

         p = *Curschar;
         for ( k=0; k<n; k++ ) {
                 /* Look for the next line */
                 if ( (np=nextline(&p)) == NULL ) {
                         if ( k > 0 )
                                 break;
                         else
                                 return FALSE;
                 }
                 p = *np;
         }
         /* try to advance to the column we want to be at */
         *Curschar = *coladvance(&p, Curswant);
         return TRUE;
 }


 EDIT1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\EDIT1.C

 /*                EDIT.C  - Screen Editor
                 by Bill Kinnersley
                 MSU Physics Dept
                 January 1982
 EDIT has many of the conveniences of WordStar, but is a much smaller and
 faster program.  The program is presently limited to editing files of less
 than 44K total length, and lines shorter than 80 characters. */

 ESC                0x1b                /* escape */
 #define BELL                0x07
 DC1                0x11                /* dc1 = x-on */
 DC3                0x13                /* dc3 = x-off */
 EOFCHAR                0x1a                /* end-of-file marker */

 #include stdio.h

 char *topmem;                        /* pointer to top of memory */
 char *topfile;                        /* pointer to top of file */
 char *botfile;                        /* pointer to bottom of file */
 char *topscr;                        /* pointer to top of screen */
 char *botscr;                        /* pointer to bottom of screen */
 char *cursor;                        /* pointer to current cursor position in
 char *null;                        /* null pointer*/
 char *mark;                        /* temporary pointer */
 int lines;                        /* line # where botscr is (1 <= lines <=25)
 int csr_col;                        /* current cursor column # */
 int want_col;                        /* cursor column desired */
 int csr_line;                        /* current cursor line # */
 int next_char;                        /* next input char, input during screen
 int ch;                                /* current character input from keyboa
 int flag;                        /* true if cursor==topscr */
 int itop;                        /* topfile as an integer */
 int ibot;                        /* botfile as an integer */
 int mar_left;                        /* left margin */
 int mar_right;                        /* right margin */
 char bufin[80];
 char fid[28];                        /* name of file to edit */
 char backup[28];                /* name of backup file */
 int file;                        /* file descriptor # used by C */
 int new;                        /* true if file was new */
 int i;                                /* number of records written to disk */
 main(argc,argv)
 int argc;                        /* number of arguments in command line */
 int *argv[];                        /* pointers to those arguments */
 {
         topmem = CCAVAIL() - 4096;        /* get size of available memory */
         cursor = CCALLOC(topmem);
         *cursor++ = '\n';                /* dummy new/line */
         botfile = topfile = botscr = topscr = cursor;
         topmem = botfile + topmem;        /* point to top of available memory
         null = "";
         next_char = 0;
         mar_left = 0; mar_right = 79;        /* set margins */
         term_init();
         if (argc == 1)                /* no command tail */
         {        fputs("\nFILE? : ",stderr);        /* ask for fid */
                 gets(fid);
         }
         else strcpy(fid,argv[1]);        /* fid from command line */
         fid[26] = 0;                        /* trim to 26 chars */
         new = - swapin(fid,topfile);                /* try to read in */
         clear_screen();
         csr_line = csr_col = want_col = 0;
         if (new)
         {        fputs("NEW FILE\n\n",stderr);        /* must be new file*/
                 lines = 3;
                 *botfile = EOFCHAR;
                 csr_line = 2;
         }
         else
         {        while (*botfile != EOFCHAR) botfile++;        /* look for bo
                 lines = 1;
                 setbot();
                 putscr(topfile);
                 home();
         }

         while(TRUE)
         {        ch = get_conin();        /* wait for console input */
                 if (ch == ESC ) ch = escape();        /* convert escape seque
                 if (((ch >= ' ') && (ch < 127)) || (ch == '\t') || (ch == '\r
                         ins_character();
                 else if (special())        /* process special characters */
                         return;                /* quit */
         }
 }
 ins_character()
 /* insert character c at current cursor position */
 {        disable_keyboard();
         e_eol();
         ibot = ++botfile; itop = ++cursor;
         ++botscr;
         movmem(cursor-1,cursor,ibot-itop+1);
         if (ch == '\r') ch = '\n';        /* convert CR to NEW/LINE */
         *(cursor-1) = ch;
         if (ch == '\n')
                 {where();
                 csr_col = want_col = 0;
                 if (csr_line == 23)
                         {botscr = cursor;
                         lines = 25;
                         printbot();
                         }
                 else
                         {putch('\n');
                         setbot();
                         ins_line();
                         putline(cursor);
                         csr_line++;
                         put_cursor(csr_line,csr_col);
                         }
                 }
         else
                 {putch(ch);
                 if (ch != '\t') csr_col++;
                 else csr_col = ((csr_col>>3)+1)<<3;
                 want_col = csr_col;
                 putline(cursor);
                 position();
                 }
         enable_keyboard();
 }
 special()
 /* procedure to process special characters */
 {                switch (ch) {
 /* cursor right */        case 'D'-64 :if (cursor == botfile) break;
                                 else if ((ch=*cursor++)=='\n')
                                         {printbot(); csr_col=0;}
                                 else if (ch=='\t')
                                         {putch('\t');
                                         csr_col = ((csr_col>>3)+1)<<3;}
                                 else {cup_right(); csr_col++;}
                                 want_col = csr_col;
                                 break;
 /* cursor left */        case 'S'-64 :
                         case 'H'-64 : flag = (cursor==topscr);
                                 if (cursor==topfile) break;
                                 else if ((ch=*--cursor)=='\n')
                                         {reverse_index();
                                         if (flag)
                                                 {topscr=startline(cursor);
                                                 setbot();
                                                 putch('\r');
                                                 putline(topscr);}
                                         position();
                                         }
                                 else if (ch=='\t') position();
                                 else {putch('\b'); csr_col--;}
                                 want_col = csr_col;
                                  break;
 /* cursor up */                case 'E'-64 :
                                 if ((mark=startline(cursor))==topfile) break;
                                 cursor = startline(mark-1);
                                 disable_keyboard();
                                 reverse_index();
                                 where();
                                 if (mark==topscr) {topscr = cursor;
                                                 setbot();
                                                 cup_home();
                                                 putline(topscr);}
                                 set_cursor();
                                 enable_keyboard();
                                 break;
 /* cursor down */        case 'X'-64 :
                         case 'J'-64 : if ((mark = next(cursor))==null) break;
                                 cursor = mark;
                                 printbot();
                                 where();
                                 set_cursor();
                                 break;
 /* up screenful */        case 'R'-64 : if (topscr==topfile) break;
                                 disable_keyboard();
                                 where();
                                 botscr = topscr;
                                 settop();
                                 newscr();
                                 enable_keyboard();
                                 break;
 /* down screenful */        case 'C'-64 : if (botscr==botfile) break;
                                 disable_keyboard();
                                 topscr = botscr;
                                 setbot();
                                 newscr();
                                 enable_keyboard();
                                 break;
 /* top file */                case 'T'-64 : if (topscr==topfile) break;
                                 topscr = topfile;
                                 setbot();
                                 newscr();
                                 break;
 /* bottom file */        case 'B'-64 : if (botscr==botfile) break;
                                 botscr = botfile;
                                 settop();
                                 lines = 24;
                                 newscr();
                                 cursor=botscr;
                                 csr_line=23; csr_col=0;
                                 put_cursor(csr_line,csr_col);
                                 break;
 /* scroll down */        case 'Z'-64 : if (botscr==botfile) break;
                                 where();
                                 put_cursor(23,0);
                                 bdos(6,'\n');
                                 botscr=next(botscr);
                                 settop();
                                 putline(startline(botscr-1));
                                 if (cursor < topscr) cursor=next(cursor);
                                 if (csr_line > 0) csr_line--;
                                 set_cursor();
                                 break;
 /* scroll up */                case 'W'-64 : if (topscr==topfile) break;
                                 cup_down();        /* move cursor down */
                                 where();        /* save current cursor positi
                                 cup_home();
                                 reverse_index();
                                 topscr=startline(topscr-1);
                                 setbot();
                                 putline(topscr);
                                 if (cursor >= botscr) cursor=startline(botscr
                                 set_cursor();
                                 break;
 /* find */                case 'F'-64 : clear_screen(); con_flush();
                                 fputs("FIND? :",stderr);
                                 gets(bufin);
                                 cursor = topfile;
 /* refind */                case 'L'-64 : for (mark=cursor; mark!=botfile; ma
                                         if (*mark == bufin[0])
                                                 if (comp())
                                                         {topscr=startline(mar
                                                         setbot();
                                                         newscr();
                                                         cursor=mark;
                                                         position();
                                                         break;}
                                 if (mark==botfile) {
                                         putch(BELL);
                                         /* goto top; */
                                         if (cursor == topfile) {
                                                 topscr=startline(cursor);
                                                 setbot();
                                                 newscr();
                                                 position();
                                         }
                                 }
                                 break;
 /* keep */                case 'K'-64 : clear_screen(); con_flush();
                                 fputs("Saving ",stderr);
                                 fputs(fid,stderr);
                                 fputs(".\n",stderr);
                                 if (!new) {strcpy(backup,fid);
                                         for (ch=0; ch<15; ch++)
                                                 if (backup[ch] == '.' || back
                                                         backup[ch]=0;
                                         strcat(backup,".BACKUP");
                                         unlink(backup); rename(fid,backup);
                                         }
                                 if ((file=creat(fid))==NULL) {
                                         fputs("Can't open ",stderr);
                                         fputs(fid,stderr);
                                         fputs(".\n",stderr);
                                         return;
                                 }
                                 ibot = botfile;        /* change pointers */
                                 itop = topfile;        /* to integers  */
                                 i = (ibot-itop)/128+1;
                                 if (write(file,topfile,i)!=i)
                                          fputs("WRITE ERROR\nDisk full?",stde
                                 term_reset();
                                 exit(0);
 /* quit */                case 'Q'-64 : clear_screen(); con_flush();
                                 fputs("QUIT? ",stderr);
                                 if((ch=getchar())=='Y'||ch=='y'||ch=='Y'-64)
                                         {fputs("\nEdit Abandoned\n",stderr);
                                         term_reset(); return TRUE;}
                                 clear_screen();
                                 putscr(cursor=topscr);
                                 home();
                                 break;
 /* delete character */        case 'G'-64 : if (cursor == botfile) break;
                                 disable_keyboard();
                                 ibot = --botfile; itop = cursor;
                                 --botscr;
                                 ch = *cursor;
                                 movmem(cursor+1,cursor,ibot-itop);
                                 if (ch == '\n')
                                         {position();
                                          where();
                                          setbot();
                                          putline(cursor);
                                          putch('\n');
                                          delete_line();
                                          put_cursor(csr_line,csr_col);
                                         }
                                 else {putline(cursor);
                                         position();}
                                 enable_keyboard();
                                 break;
 /* delete */                case 0x7f : if (cursor == topfile) break;
                                 disable_keyboard();
                                 flag = (cursor == topscr);
                                 ibot = --botfile; itop = --cursor;
                                 --botscr;
                                 ch = *cursor;
                                 movmem(cursor+1,cursor,ibot-itop+1);
                                 if (flag)
                                         {putline(topscr=startline(cursor));
                                         position();
                                         }
                                 else if (ch == '\n')
                                         {cup_up();
                                          position();
                                          where();
                                          setbot();
                                          putline(cursor);
                                          putch('\n');
                                          delete_line();
                                          put_cursor(csr_line,csr_col);
                                         }
                                 else {if (ch == '\t') position();
                                                 else putch('\b');
                                         putline(cursor);
                                         position();}
                                 enable_keyboard();
                                 break;
                         default: putch(BELL);        /* invalid character */
         }
         return FALSE;
 }
 comp()
 {int i;
         for (i=0; bufin[i]!=0; i++) if (bufin[i] != mark[i]) return FALSE;
         mark = mark + i;
         return TRUE;
 }
 newscr()
 /* puts a new screen */
 {        clear_screen();
         putscr(cursor=topscr);
         home();
 }
 startline(start)
 char *start;
 /* returns pointer to first character in current line */
 {char *mark;
         for(mark=start-1; mark!=topfile; mark--)
                 if (*mark=='\n') return ++mark;
         return topfile;
 }
 next(start)
 char *start;
 /* returns pointer to first character in next line */
 {char *mark;
         for(mark=start; mark!=botfile; mark++)
                 if (*mark=='\n') return ++mark;
         return null;
 }
 position()
 /* positions screen cursor in the current line */
 {char *mark,i;
         csr_col=0;
         for (mark=startline(cursor); mark!=cursor; mark++)
                 if (*mark=='\t')
                         csr_col=((csr_col>>3)+1)<<3;/* count up column positi
                         else csr_col++;
         put_cursor(26,csr_col);        /* dummy for H19 */
         want_col = csr_col;
 }
 set_cursor()
 /* positions file cursor to position screen cursor on desired column */
 {int tab_col;
         csr_col=0;
         for (cursor=startline(cursor); *cursor!='\n'; cursor++) {
                 if (cursor == botfile) break;
                 if (csr_col == want_col) break;
                 if (*cursor != '\t') csr_col++;
                 else {
                         tab_col=((csr_col>>3)+1)<<3;
                         if (want_col < tab_col) break;
                         csr_col = tab_col;
                 }
         }
         put_cursor(csr_line,csr_col);
 }
 putline(start)
 char *start;
 /* outputs from "start" to end of current line;
    returns pointer to first char in next line */
 {char *mark; int i;
         e_eol();
         for (mark=start; mark!=botfile; mark++)
                 if (*mark=='\n') return mark+1;
                 else putch(*mark);
         return botfile;
 }
 printbot()
 /* prints a line at the bottom of screen and scrolls up */
 {        putch('\n');
         if (cursor == botscr)
                 {if (lines==25) while (*topscr++ != '\n');
                 if (botscr == botfile);
                 botscr = putline(cursor);
                 putch('\r');
                 }
 }
 setbot()
 /* measures down 24 lines from topscr to set botscr */
 {        lines=0;
         for (botscr=topscr; botscr!=null; botscr=next(botscr))
                  if (++lines==25) return;
         botscr=botfile;
 }
 putscr(start)
 char *start;
 /* outputs from "start" to botscr */
 {char *mark;
         if (start==botscr) return;
         e_eol();
         for (mark=start; mark!=(botscr-1); mark++) {
                 if (*mark == '\n') {
                         e_eol();                /* erase to end of line */
                         bdos(6,'\r');                /* output carriage retur
                         if (mark != (botscr-1)) bdos(6,'\n');
                 }
                 else putch(*mark);
                 if (!next_char) {
                         next_char = bdos(6,-1);        /* look-ahead for dc3
                         if (next_char == DC3) {
                                 while (!(next_char=bdos(6,-1)));
                                 if (next_char == DC1) next_char = 0;
                         }
                 }
         }
         if (lines<25) putch(*mark);
         e_eos();
 }
 home()
 {        cup_home();
         csr_line = csr_col = want_col = 0;
 }
 settop()
 /* measures up 23 or 24 lines from "botscr" */
 {int i,j;
         i = j = (botscr == botfile);
         for (topscr=botscr; topscr!=topfile; topscr=startline(topscr-1))
                         if (++i==25) break;
         lines = i - j;
         setbot();
 }
 reverse_index()
 /* move cursor up one line, scrolling screen down if at top */
 {        putch(ESC); putch('M');
 }
 ins_line()
 /* insert new blank line on screen at current position */
 {        putch(ESC); putch('['); putch('L');
 }
 delete_line()
 /* delete the current line, scroll bottom of screen, output bottom line */
 {        putch(ESC); putch('['); putch('M');
         if (lines<25) return;
         putch(ESC); putch('['); putch('2'); putch('4'); putch(';');
         putch('1'); putch('H');
         putline(startline(botscr-1));
 }
 putch(c)
 int c;
 /* replacement for library putc (will not swallow characters) */
 {        if (c == '\n') bdos(6,'\r');
         bdos(6,c);
 }
 get_conin()
 {int c;
         c = next_char;
         if (c) next_char = 0;
         else while (!(c=bdos(6,-1)));;
         return c;
 }
 con_flush()
 {        while(bdos(6,-1));                /* flush type-ahead */
 }
 escape()
 /* procedure to process escape sequences */
 {int c;
         c = get_conin();        /* get next character */
         if (c == '[') {
                 c = get_conin();        /* get next character */
                 switch(c) {
 /* cursor up */                case 'A' : c = 'E'-64; break;
 /* cursor down */        case 'B' : c = 'X'-64; break;
 /* cursor forward */        case 'C' : c = 'D'-64; break;
 /* cursor backword */        case 'D' : c = 'S'-64; break;
 /* home */                case 'H' : c = 'T'-64; break;
 /* delete character */        case 'P' : c = 'G'-64; break;
                         default : c = 0; putch(BELL);
                 }
         }
         else if (c == 'O') {        /* keypad or function key */
                 c = get_conin();        /* get next character */
                 switch(c) {
 /* blue */                case 'P' : c = 'K'-64; break;
 /* red */                case 'Q' : c = 'Q'-64; break;
 /* f1 */                case 'S' : c = 'F'-64; break;
 /* f2 */                case 'T' : c = 'L'-64; break;

 /* shift down */        case 'r' : c = 'C'-64; break;
 /* shift home */        case 'u' : c = 'B'-64; break;
 /* shift up */                case 'x' : c = 'R'-64; break;
                         default : c = 0; putch(BELL);
                 }
         }
         else {c = 0; putch(BELL);}
         return c;        /* return modified character */
 }
 where()
 {        int c;
         putch(ESC); putch('['); putch('6'); putch('n');/* get cursor position
         while (get_conin() != ESC);
         while (get_conin() != '[');
         csr_line = csr_col = 0;
         while ((c = get_conin()) != ';') csr_line = csr_line * 10 + c - '0';
         while ((c = get_conin()) != 'R') csr_col = csr_col * 10 + c - '0';
         --csr_line; --csr_col;                /* adjust cursor to 0-origin */
 }
 put_cursor(line,col)
 int line;
 int col;
 {        bdos(6,ESC); bdos(6,'[');
         ++line; ++col;
         if (line > 9) bdos(6,line/10 + '0');
         bdos(6,line%10 + '0');
         bdos(6,';');
         if (col > 9) bdos(6,col/10 + '0');
         bdos(6,col%10 + '0');
         bdos(6,'H');
 }
 clear_screen()
 {        cup_home();
         bdos(6,ESC); bdos(6,'['); bdos(6,'J');
 }
 e_eol()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'K');
 }
 e_eos()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'J');
 }
 cup_home()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'H');
 }
 cup_up()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'A');
 }
 cup_down()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'B');
 }
 cup_right()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'C');
 }
 disable_keyboard()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'2'); bdos(6,'h');
 }
 enable_keyboard()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'2'); bdos(6,'l');
 }
 term_init() {
         bdos(6,ESC); bdos(6,'['); bdos(6,'>');
         bdos(6,'6');                        /* Enter keypad shifted mode */
         bdos(6,';');
         bdos(6,'7');                        /* Enter alternate keypad mode */
         bdos(6,'h');
 }
 term_reset()
 {        bdos(6,ESC); bdos(6,'['); bdos(6,'>');
         bdos(6,'6');                        /* Exit keypad shifted mode */
         bdos(6,';');
         bdos(6,'7');                        /* Exit alternate keypad mode */
         bdos(6,'h');
 }
 bdos (bc, de) int bc, de; {
 #asm
         MOVE.L        8(SP),D0        get bc (function)
         CMPI.B        #6,D0
         BEQ.S        *+4
         RTS
         MOVE.L        4(SP),D2        get de
         BMI.S        CON_IN        console input
         MOVEQ        #8,D1
         SC        SC:DEVOUT
         RTS
 CON_IN        DS        0
         MOVEQ        #8,D1
         SC        SC:DEVSTS
         BNE.S        CON_IN1
         MOVEQ        #0,D0
         RTS
 CON_IN1        DS        0
         MOVEQ        #8,D1
         SC        SC:DEVIN
         MOVE.L        #$FF,D0
         AND.L        D1,D0
 ;        RTS                supplied by CC
 #endasm
 }
 strcpy( d, s) char *d, *s; {
         while (*s) *d++ = *s++;
         *d = 0;
 }
 strcat( d, s) char *d, *s; {
         while (*d) ++d;                        /* locate end of destination s
         while (*s) *d++ = *s++;                /* copy source to destination
         *d = 0;
 }
 movmem(s, d, l) char *s, *d; int l; {
 #asm
         MOVE.L        4(SP),D0        get length
         BGT.S        *+4                don't move if zero
         RTS
         CMPI.L        #$1FFFF,D0
         BLT.S        *+6
         TRAP        15
         DC        0        breakpoint trap
         MOVE.L        12(SP),A0        get source address
         MOVE.L        8(SP),A1        get destination address
         CMPA.L        A1,A0        compare source with destination
         BLT.S        MOVE_0        move top to bottom
         SUBQ.L        #1,D0        adjust for DBRA counter
         MOVE.B        (A0)+,(A1)+
         DBRA        D0,*-2
         ADDQ.W        #1,D0
         SUBQ.L        #1,D0
         BGT        *-8
         RTS
 MOVE_0        DS        0
         ADD.L        D0,A0
         ADD.L        D0,A1
         SUBQ.L        #1,D0        adjust for DBRA counter
         MOVE.B        -(A0),-(A1)
         DBRA        D0,*-2
         ADDQ.W        #1,D0
         SUBQ.L        #1,D0
         BGT        *-8
 ;        RTS                        ; return supplied by CC
 #endasm
 }
 gets(s) char *s; {
         return (fgets(s, 20, stderr));
 }
 swapin( fname, addr) char *fname, *addr; {
         int i;
         if ((file=fopen(fname,"r"))==NULL) return 1;
         while (1) {
                 if ((fgets(addr,topmem-addr,file))==0) break;
                 while (*addr) ++addr;
                 *addr++ = '\n';
         }
         *addr = EOFCHAR;
         fclose(file);
         return 0;
 }
 rename(from, to) char *from, *to; {
         if (CCRENAME(from, to) == ERR) fputs("Error on rename\n",stderr);
 }
 creat(fname) char *fname; {
         return fopen(fname,"w");
 }
 write(file,buf,sects) int file, sects; char *buf; {
         *botfile = 0;
         fputs(buf,file);
         return sects;
 }


 EGATEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGASAVE\EGATEST.C

 #include <graph.h>
 #include <stdio.h>
 #include <memory.h>
 #include <dos.h>
 #include <malloc.h>



 /* DEMONSTRATION OF SAVE_SCREEN AND GET_SCREEN  */
 /* THESE ROUTINES DEMONSTRATE HOW TO QUICKLY SAVE */
 /* AND RETREIVE THE 16 COLOR 640X350 EGA SCREEN */
 /* THERE IS MINIMAL ERROR CHECKING IN THE CODE */
 /* WRITTEN BY R.W. SIMPSON   DEC 21, 1987 */
 /*            EDEN PRAIRIE, MN  */
 /* MICROSOFT C VERSION 5 SMALL MODEL */
 /* PROGRAM REQUIRES 128K EGA CARD AND MONITOR  */





 main ()

 {

       char filename[13];
       int flag;            /* error flag */


       printf("\nEnter the filename for the test >");
       scanf("%s",filename);




       if ((_setvideomode(_ERESCOLOR)) == 0)
             exit();


       _setcolor(12);


       _rectangle(_GFILLINTERIOR, 80, 50, 240, 150);

       _setcolor(14);
       _rectangle(_GFILLINTERIOR,100,200,340,340);

       flag = save_screen(filename);

       if (flag != 0)
           {  _setvideomode(_DEFAULTMODE);
              printf("\nERROR SAVING SCREEN # %i",flag);
              exit();
           }

       _clearscreen(_GCLEARSCREEN);

       printf("\n Now to retrieve the screen \n Hit a key to procede ");

       while (!kbhit());
       getch();

       flag = get_screen(filename);

       if (flag !=0)
          { _setvideomode(_DEFAULTMODE);
            printf("\nERROR READING IMAGE # %i",flag);
            exit();
          }


       _settextposition(20,1);
       _outtext("Done, hit a key to terminate");
       while (!kbhit());
       getch();

       _setvideomode(_DEFAULTMODE);
       printf("Program terminated without error");

  }


 ENCRPT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\ENCRPT.C

 /*                      Encrypt

         This program encrypts the standard input and writes it to
         the standard output. It requires one parameter: the key for
         the encryption, which can be up to eight characters long.
         Decryption is done by simply running the program again on the
         encrypted file with the same key -- i.e., encryption and
         decryption are the same operation.
 */

 #include <fcntl.h>
 #include <io.h>
 #include <stdio.h>

 BUFSIZE 20480    /* I/O buffer size. */
 KEYSIZE 9       /* Maximum size of key (plus one for null). */

 CALIBRATE       /* Define for start/end prompts. */

 char buffer[BUFSIZE];   /* The I/O buffer. */

 STDINFILE 0     /* Standard input non-stream file number. */
 STDOUTFILE 1    /* Standard output file number. */

 #define TRUE 1
 #define FALSE 0

 /*      main(argc,argv)

         Function: Encrypt the standard input and write it to the
         standard output, using the single command line parameter
         as the key.

         Algorithm: Get the key and rearrange it to improve security,
         then encrypt using exclusive-or with the key.
 */

 main(argc,argv)

 int argc;
 char *argv[];

 {
         char key[KEYSIZE];      /* The key. */
         char *cp, *cp2;
         char c;

         /* Check if we've got the right number of command line
            parameters. */
         if (argc != 2) {
                 /* If not, remind him how to use this program. */
                 fputs("Usage: encrpt key <plainText >cipherText",stderr);
                 exit(1);
         };

         /* Check if we've got a decent sized key. */
         if ((argv[1][0] == 0) || (argv[1][1] == 0)) {
                 /* If not, tell him he needs a bigger key. */
                 fputs("Key must be at least 2 characters in size.",stderr);
                 exit(1);
         };

         /* Get the key. */
         for (cp = key, cp2 = argv[1];
              (cp < &key[KEYSIZE-1]) && (*cp2 != 0); *cp++ = *cp2++);
         /* Distribute the last byte amoung the top bits of the earlier
            ones, and toggle some of the bits in each key byte. All of
            this helps ensure a more secure key. */
         for (c = *(--cp), *cp = 0; cp >= key; cp--) {
                 *cp |= (c & 1) << 7;
                 *cp ^= 0x55;
                 c >>= 1;
         };

         /* Use binary I/O mode. For two reasons: (1) We want to be
            able to encrypt binary files; (2) characters may be
            turned into LFs in the encryption process, which would
            erroneously be translated into CRLF. */
         setmode(STDINFILE,O_BINARY);
         setmode(STDOUTFILE,O_BINARY);

         /* Encrypt it. */
 #ifdef CALIBRATE
         fputs("Starting...",stderr);
 #endif CALIBRATE
         encrypt(STDINFILE,STDOUTFILE,key);
 #ifdef CALIBRATE
         fputs("done.\n",stderr);
 #endif CALIBRATE
 }

 /*      encrypt(inFile,outFile,theKey)

         Function: Encrypt the file specified by inFile, using
         theKey, and write it to outFile.

         Algorithm: Exclusive-or the bytes with theKey, recycling
         theKey as needed.
 */

 encrypt(inFile,outFile,theKey)

 int inFile;
 int outFile;
 char *theKey;

 {
         register char *keyPtr;
         register char *bufPtr;
         int bufCnt;
         int sizeRead;

         keyPtr = theKey;
         /* Cycle until nothing left to read. */
         while (TRUE) {
                 /* Read in a bufferfull. */
                 sizeRead = bufCnt = read(inFile,buffer,BUFSIZE);
                 if (sizeRead <= 0) break;
                 /* Encrypt it. */
                 for (bufPtr = buffer; sizeRead-- > 0; *bufPtr++ ^= *keyPtr++)
                         if (*keyPtr == 0) keyPtr = theKey;
                 /* Write it out. */
                 write(outFile,buffer,bufCnt);
         };
 }



 ENTAB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TABS\ENTAB.C

 /* ------------------------------------------- */
 /*     ENTAB - Convert blanks to tabs          */
 /*             Adapted from Software Tools     */
 /*             By Kernighan and Plauger        */
 /*                                             */
 /*             written by Michael Burton       */
 /*             Last Update: 14 Jan 1984       */
 /* ------------------------------------------- */
 /*     USAGE:                                  */
 /*             ENTAB FROMFILE TOFILE N         */
 /*               N is the number of columns    */
 /*                 between tab stops           */
 /* ------------------------------------------- */
 #include "stdio.h"

 main(argc,argv)
        int argc;
        char *argv[];
 {
        static int col = 1, n, *fd, *td, newcol;
        static char c, *sp;

        if (argc != 4)
        {
                fputs("Usage: ENTAB FROMFILE TOFILE N\007\n",stdout);
                return;
        }
        sp = argv[1];
        while ((*sp = toupper(*sp)) != EOS) sp++;
        sp = argv[2];
        while ((*sp = toupper(*sp)) != EOS) sp++;
        if ((fd = fopen(argv[1],"r")) == 0)
        {
                fputs(argv[1],stdout);
                fputs(" not found\007\n",stdout);
                return;
        }
        if ((td = fopen(argv[2],"w")) == 0)
        {
                fputs("Unable to open ",stdout);
                fputs(argv[2],stdout);
                fputs("\007\n",stdout);
                return;
        }
        n = atoi(argv[3]);
        if (n < 1 || n > 32) fputs("Tabs < 1 or > 32\007\n",stdout);

        while(1)
        {
                newcol = col;
                while ((c = fgetc(fd)) == ' ')
                {
                        newcol++;
                        if ((newcol % n) == 0)
                        {
                                fputc('\t',td);
                                col = newcol;
                        }
                }
                for (; col < newcol; col++) fputc(' ',td);
                if (c == EOF) return;
                fputc(c,td);
                switch(c)
                {
                        case '\n':
                                col = 1;
                                break;
                        case '\t':
                                col += n-(col % n);
                                break;
                        default:
                                col++;
                }
        }
        fflush(fd);
        fflush(td);
        fclose(fd);
        fclose(td);
 }


 ENUM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\ENUM.C

                                          /* Chapter 6 - Program 3 */
 main()
 {
 enum {win,tie,bye,lose,no_show} result;
 enum {sun,mon,tues,wed,thur,fri,sat} days;

    result = win;
    printf("    win = %d\n",result);
    result = lose;
    printf("   lose = %d\n",result);
    result = tie;
    printf("    tie = %d\n",result);
    result = bye;
    printf("    bye = %d\n",result);
    result = no_show;
    printf("no show = %d\n\n",result);

    for(days = mon;days < fri;days++)
       printf("The day code is %d\n",days);
 }


 ENUMS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\ENUMS.C

 /* ENUMS.C - From page 545 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. This program is an example of     */
 /* using enumerated data types. This program gives an error:    */
 /* Fatal error:L1101 Invalid object module when linking.        */
 /* In Quick C Programmers Guide user is requested to contact    */
 /* Microsoft.                                                   */
 /****************************************************************/

 main()
 {
 enum empcats {
    management,
    research,
    clerical,
    sales
 };
 struct {
    char name[30];
    float salary;
    enum empcats category;
 } employee;

    strcpy(employee.name, "Benjamin Franklin");
    employee.salary = 118.50;
    employee.category = research;

    printf("\n\nName = %s", employee.name);
    printf("\nSalary = %6.2f", employee.salary);
    printf("\nCategory = %d", employee.category);

    if(employee.category == clerical)
       printf("\n\nEmployee category is clerical.");
    else
       printf("\nEmployee category is not clerical.");
 }



 EPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\EPRINTF.C

 /* 1.2  01-08-86                                                 (eprintf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/

 eprintf(fmt, args)        /* formatted print to stderr of args.

 /*----------------------------------------------------------------------*/
 STRING fmt;
 unsigned args;
 {
         int _eputc();

         return format(_eputc, fmt, &args);
 }

 /************************************************************************/
         LOCAL
 _eputc(c)                /* print character c on stderr.

 /*----------------------------------------------------------------------*/
 {
         return eputc(c);
 }


 EPUTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\EPUTS.C

 /* 1.0  12-10-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 eputs(s)                /* Put the string s, followed by newline, to the
                            stderr device. Return newline if ok, or
                            EOF if not.
 /*----------------------------------------------------------------------*/
 FAST STRING s;
 {
         while (*s)
                 if (eputc(*s++) IS EOF)
                         return EOF;

         return eputc('\n');
 }


 EQLIST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\EQLIST.C

 /* EQLIST.C - From page 366 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. This program lists the number     */
 /* of Kbytes of memory in computer and the type of equipment    */
 /* on the computer system.                                      */
 /****************************************************************/

 EQLIST 0x410       /*Location of equipment list word*/
 MEMSIZ 0x413       /*Location of memory size word*/

 main()
 {
 int far *farptr;
 unsigned int eq, data;

    farptr = (int far *) EQLIST;
    eq = *(farptr);
    data = eq >> 14;              /*printers*/
    printf("\nNumber of printers is %d.\n", data);
    if(eq & 0x2000)               /*serial printer*/
       printf("Serial printer is present.\n");
    data = (eq >> 9) & 7;         /*serial ports*/
    printf("Number of serial ports is %d.\n", data);
    if(eq & 1) {                  /*diskette drives*/
       data = (eq >> 6) & 3;
       printf("Number of diskette drives is %d.\n", data + 1);
    }
    else
       printf("No diskette drives attached.\n");
    data = (eq >> 4) & 3;         /*video mode*/
    switch (data) {
       case 1:
          printf("Video is 40 column color.\n");
          break;
       case 2:
          printf("Video is 80 column color.\n");
          break;
       case 3:
          printf("Video is 80 column monochrome.\n");
          break;
    }
    farptr = (int far *) MEMSIZ;       /*reset to mem size word*/
    printf("Memory is %d Kybtes.\n", *(farptr));
 }



 EQUIPMNT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\ADVC\EQUIPMNT.C

 #include <dos.h>

 int commports()                       /* get number of serial ports */
 {
    union REGS inregs;
    union REGS outregs;
    int86(0x11,&inregs,&outregs);
    return((outregs.h.ah & 15) >> 1);
 }



 int displaytype()                     /* get display type */
 {
    union REGS inregs;
    union REGS outregs;

    inregs.h.ah = 15;
    int86(0x10,&inregs,&outregs);
    return((outregs.h.al != 7));
 }



 long drivespace(drv)                  /* get free space on a given drive */
    char drv;
 {
    union REGS inregs;
    union REGS outregs;

    inregs.h.ah = 0x36;
    if (drv == '@') inregs.h.dl = 0;
    else inregs.h.dl = toupper(drv) - 'A' + 1;
    intdos(&inregs,&outregs);
    return((long) outregs.x.ax * outregs.x.bx * outregs.x.cx);
 }



 char getdrive()                       /* get default drive */
 {
    return((bdos(0x19,0,0) & 255)+'A');
 }



 int joystick()                        /* see if there's a joystick */
 {
    union REGS inregs;
    union REGS outregs;
    int86(0x11,&inregs,&outregs);
    return((outregs.h.ah >> 4) & 1);
 }



 int limmfree()                        /* get free pages of expanded memory */
 {
    int freemem = 0;
    union REGS inregs;
    union REGS outregs;

    inregs.h.ah = 0x42;
    int86(0x67,&inregs,&outregs);
    if (!outregs.h.ah) freemem = outregs.x.bx;
    return(freemem);
 }



 int limmtotal()                       /* get total pages of expanded memory *
 {
    int totalmem = 0;
    union REGS inregs;
    union REGS outregs;

    inregs.h.ah = 0x42;
    int86(0x67,&inregs,&outregs);
    if (!outregs.h.ah) totalmem = outregs.x.dx;
    return(totalmem);
 }



 int printports()                      /* get number of parallel ports */
 {
    union REGS inregs;
    union REGS outregs;
    int86(0x11,&inregs,&outregs);
    return(outregs.h.ah >> 6);
 }



 int totalmem()                        /* get Kbytes of installed RAM */
 {
    union REGS inregs;
    union REGS outregs;
    int86(0x12,&inregs,&outregs);
    return(outregs.x.ax);
 }


 ERAQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\ERAQ.C

 /* ERAQ.C  a program to traverse DOS's tree-structured directory, looking
    for the file(s) specified. They are then displayed on the screen
    and the user is prompted for ERASE or NOT ERASE. Basically, I got
    damned tired of DOS not having an ERAQ like CPM.
     The basic traverse from directory to directory portion is a
    very versatile toy around which many useful utilities can (and will,
    I'm sure!) be written. Here's one of them. I'll do more as time
    and inclination permits, but I'll turn this one loose first because
    I think it's useful.
     This is written for MSDOS 2.0 or better, using the LATTICE C Compiler,
    on a Compaq. 7-20-84 jjw
    ps I know this could be shortened drastically and speeded up by
    combining some of the modules into larger functions, but this way was
    much easier to write & de-bug modularly and so I left it that way. Also,
    some of the modules might be useful in themselves to build into a
    library. This program differs from most C code I've seen before because
    1.) it does something useful.
    2.) it does not have pointers to pointers to arrays of pointers to functio
        returning pointers. It is easy and straight-forward, at the expense of
        some speed and length.
    3.) it is commented. Not extensively, but fairly well. The hard parts have
        to do with the dirstak, which is not a stack but a queue (dirqueue
        looked too silly to me and d_queue made me think of peanut buster
        parfaits). If puzzled, follow it through but keep the msdos manual
        handy to see what byte is what.
    If you have any questions about this, drop me a note. I frequent almost
    every tech-oriented CPM bulletin board around Chicago, Il.
    Name is John Welch, or just jjw.
            2397 John Smith Dr. Apt B
            Schaumburg, Il 60194 */

 #include "dos.h"
 #include "stdio.h"

 main(argc,argv)
 int argc;
 char *argv[];
 {
 char look[15],start[100],init_dir[100],drive[2],flag1,stuff[100];
 int first,last,temp,temp1,ret;

 printf("ERAQ.C Ver 1.00 1-25-85 John J. Welch\n");
 printf("(for help, type ERAQ HELP)\n\n");

 if (argc == 1)
  {
   /* get the filename to erase */
   printf("Filename to be erased -->");
   scanf("%s",look);

   /* get the drive we're going to do the erasing on */
   printf("Enter the drive letter -->");
   scanf("%s",stuff);
   drive[1] = stuff[0];

   /* get starting directory */
   printf("Directory to start in (absolute path from root) -->");
   scanf("%s",start);

   /* do we want to do all sub-directories, too, or just this one? */
   printf("Traverse all sub-directories under this one -->");
   scanf("%s",stuff);
   if ((stuff[0] == 'y') || (stuff[0] == 'Y'))
    flag1 = 1; /* if they specified Y, set the flag */
   else
    flag1 = 0; /* anything but Y or y means NO */

   }
 else
  {
   if (argc != 2)
    {
 HERE:
     printf("For prompts, just type ERAQ.\n");
     printf("Command line syntax is ERAQ  [drive:][starting path]file.ext[/y]\
     printf("where [drive:] is optional drive,\n");
     printf("  [starting path] is optional path to start at,\n");
     printf("  file.ext is the file name (wildcards ok) to delete,\n");
     printf("  [/y] is optionally if you want to do all sub-directories under
     printf("  starting directory (default value is no).\n");
     return;
    }
   else
    {
     if ((strcmp(argv[1],"HELP") == 0) || (strcmp(argv[1],"help") == 0))
      goto HERE;

     first = 0; /* first character of the command line */
     drive[1] = 255; /* set up to default to current drive */
     flag1 = 0; /* default it to not do sub-dirs */
     if (argv[1][1] == ':') /* if there was a drive specified, pick the letter
     { /*off and store it someplace */
      drive[1] = argv[1][0];
      first = 2; /* now, the first character in the command line is #2 */
     }
     last = strlen(argv[1]); /* get the length of the command line */
     if (argv[1][last-2] == '/') /* if they used the toggle, set it up */
     {
      if ((argv[1][last-1] == 'y') || (argv[1][last-1] == 'Y'))
       flag1 = 1; /* if they specified Y, set the flag */
      else
       flag1 = 0; /* anything but Y or y means NO */
      last -= 2; /* bump the last character down */
      argv[1][last] = 0; /* and now, null terminate the command line */
     }

     for (temp = last; ((argv[1][temp] != ':') && (temp >= first) && (argv[1][

     for (temp1 = first; temp1 < temp+1; temp1++) /* get pathname (if any) */
     {start[temp1-first] = argv[1][temp1];}
     start[temp1-first] = 0; /* null terminate it */

     for (temp1 = temp+1; temp1 <= last; temp1++) /* get the filename to look
     {look[temp1-(temp+1)] = argv[1][temp1];}
     look[temp1-(temp+1)] = 0; /* null terminate this */

    }
   }

 /* get the drive we started in */
 get_drive(drive);

 if (drive[1] == 255) /* if the default was for current drive, use it */
  drive[1] = drive[0];
 else /* otherwise, normalize whatever they typed in to start with a=0 */
  if ((drive[1] > 'A') && (drive[1] < 'Z'))
    drive[1] = drive[1] - 'A';
  else
    drive[1] = drive[1] - 'a';

 /* change to the starting drive */
 ret=chg_drive(drive[1]);

 if (ret < drive[1])
   printf("invalid drive selected...\n");
 else
  {
   /* get the directory we started in */
   init_dir[0] = '\\';
   get_dir(init_dir+1);

   if (start[0] == 0) /* if there was no starting path, use the current one */
    strcpy(start,init_dir);

   /* do the actual work */
   doit(look,start,flag1);

   /* change back to the initial drive */
   chg_drive(drive[0]);

   /* now, change back to the initial directory */
   chg_dir(init_dir);
  } /* end else */

 } /* end function */

 doit(look,start,flag1)
 char *look,*start,flag1;

 {
  char file[3],name[128],*dirstak,curdir[140],*getmem();
  int ret,tmp,top_ndx,bottom_ndx;

  dirstak = getmem(10000); /* get a hunk of memory for the directory queue */
  if (dirstak == 0) /* if the getmem returned a null, error */
  {printf("not enough memory...\n");
   return;}

 /* set the DTA to someplace we can use */
  put_dta(name);

  top_ndx = 0;    /* set pointer to top of directory queue */
  bottom_ndx = 0; /* set pointer to bottom of queue */

  /* put the starting directory in the queue */
  for (tmp = 0; start[tmp] != 0; tmp++)
   {dirstak[bottom_ndx++] = start[tmp];}
  dirstak[bottom_ndx++] = 0;

  while (top_ndx != bottom_ndx)
   {
    /* check for any sub-directories */
    ret = dirscan(file,name,curdir,dirstak,&top_ndx,&bottom_ndx);

    if (ret != 3)
     {
      /* run through the directory, querying for each file */
      filscan(look,name);
     }

    /* if only do this one directory, end here */
    if (flag1 == 0)
    {
     rlsmem(dirstak,10000);
     return(1);
    }

   } /* end while loop */
   rlsmem(dirstak,10000);

 } /* end function */

 dirscan(file,name,curdir,dirstak,top_ptr,bot_ptr)
 char *file,*name,*curdir,*dirstak;
 int *top_ptr,*bot_ptr;
 {
  int ret,tmp,top_ndx,bottom_ndx,*p_file;

  bottom_ndx = *bot_ptr;
  top_ndx = *top_ptr;

  /* initialize the file name for the directory search */
  file[0] = '*';
  file[1] = '.';
  file[2] = 0;

  tmp = 0;
  for (top_ndx; dirstak[top_ndx] != 0; top_ndx++)
   { curdir[tmp++] = dirstak[top_ndx];}
  curdir[tmp] = 0;
  ++top_ndx;
  ret = chg_dir(curdir);
  if (ret != 3)
   {
    printf("\n   ON DIRECTORY %s\n",curdir);
    find_dir(name,file,curdir,dirstak,&bottom_ndx);
   }
  *bot_ptr = bottom_ndx;
  *top_ptr = top_ndx;

  return(ret);
 }

 find_dir(name,file,curdir,dirstak,bot_ndx)
 char *name,*file,*curdir,*dirstak;
 int *bot_ndx;
 {
  int ret,tmp,bottom_ndx;
  unsigned temp;

  bottom_ndx = *bot_ndx; /* set the local variable = the real thing. */

 /* search for first directory entry */
  temp = 0x0010;
  ret = srch1st(file,temp);

 /* while the return from search is successful, check for dir attribute
    and make sure it isn't a . or .. entry, put the whole pathname (null
    terminated) at the bottom of the queue */

  while (ret != 18)
  { if ((name[21] == 0x10) && (name[30] != '.'))
    {
     for (tmp = 0; curdir[tmp] != 0; tmp++)
     {dirstak[bottom_ndx] = curdir[tmp];
      ++bottom_ndx;}
     if (curdir[1] != 0)
      {dirstak[bottom_ndx++] = '\\';}
    for (tmp = 30; name[tmp] != 0; tmp++)
     {dirstak[bottom_ndx] = name[tmp];
      ++bottom_ndx;}
    dirstak[bottom_ndx++] = 0;

    } /* end if */
     ret = srchnext(file); /* get another directory entry */
  } /* end while */

  *bot_ndx = bottom_ndx; /*now restore the real value to its proper place */

 } /* end function */

 filscan(look,name)
 char *look,*name;
 {
  int ret;
  char tmp;
  unsigned temp;

  temp = 0x0000;
  ret = srch1st(look,temp); /* start looking for files */

  while (ret != 18)
  {
   printf("%s -->",name+30);
   tmp = getch(); /* get the key directly from keyboard */
   printf("%c\n",tmp); /* echo it back with <cr/lf> */
   if ((tmp == 'y') || (tmp == 'Y'))
     era_file(name+30);

   ret = srchnext(look); /* get another directory entry */
  } /* end while */

 } /* end function */

 put_dta(p_dta)
 char *p_dta;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x1a;
  inreg.x.dx = p_dta;

  intdos(&inreg,&outreg);

  return(0);
 }

 srch1st(p_file,attr)
 int *p_file;
 unsigned attr;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x4e;
  inreg.x.cx = attr;
  inreg.x.dx = p_file;

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 srchnext(p_file)
 int *p_file;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x4f;

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 chg_dir(curdir)
 char *curdir;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x3b;
  inreg.x.dx = curdir;

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 get_dir(temp)
 char *temp;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x47;
  inreg.h.dl = 0; /* relative drive */
  inreg.x.si = temp; /* where to put the pathname */

  intdos(&inreg,&outreg);

  return(outreg.x.ax);
 }

 get_drive(where)
 char *where;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x19;

  intdos(&inreg,&outreg);

  *where = outreg.h.al;
 }

 era_file(which)
 char *which;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x41;
  inreg.x.dx = which; /* pointer to filename */

  intdos(&inreg,&outreg);

  /* there's no easy way to check for errors, so don't even do it.
     dos returns error flag in carry flag, LATTICE C can't access it without
     your own assembler routine. I have one, but it's a bit hairy. For those
     who insist on doing things right, drop me a note. jjw */
 }

 chg_drive(drive)
 char drive;
 {
  union REGS inreg;
  union REGS outreg;

  inreg.h.ah = 0x0e;
  inreg.h.dl = drive;

  intdos(&inreg,&outreg);

  return(outreg.h.al);
 }


 ERF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ERF.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathcons.h"

 /*   Coefficients from J. L. Schonfelder, Math. Comp. Vol. 32, No. 144,
  *   Oct. 1978, pp. 1232-1240.  Converted from Chebyshev coefficients
  *   to polynomial coefficients.
  */

 #define bDEGREE 19
 static double b[bDEGREE+1] =
 {        /* b[0] */         6.74933236039655050263e-01,
         /* b[1] */        -2.61111860931245377287e-01,
         /* b[2] */         1.19479138609851943329e-01,
         /* b[3] */        -4.86627774491551332176e-02,
         /* b[4] */         1.71283445718166884035e-02,
         /* b[5] */        -5.23487583615739131346e-03,
         /* b[6] */         1.40509142365203239024e-03,
         /* b[7] */        -3.35143533535934984684e-04,
         /* b[8] */         7.18010084384964546189e-05,
         /* b[9] */        -1.39462736935665598139e-05,
         /* b[10] */         2.47580204969781916589e-06,
         /* b[11] */        -4.04509593030131189153e-07,
         /* b[12] */         6.11956771414692047983e-08,
         /* b[13] */        -8.61749835843079723418e-09,
         /* b[14] */         1.13482488917751004919e-09,
         /* b[15] */        -1.40320352244567126036e-10,
         /* b[16] */         1.63314151643890654668e-11,
         /* b[17] */        -1.79944661052623065189e-12,
         /* b[18] */         1.97235204103604890406e-13,
         /* b[19] */        -1.95488364156685071066e-14
 };

 #define cDEGREE 21
 static double c[cDEGREE+1] =
 {        /* c[0] */         5.40464821348814759403e-01,
         /* c[1] */        -2.61515522487415932119e-02,
         /* c[2] */        -2.88573438386340392753e-03,
         /* c[3] */        -5.29353396945768734440e-04,
         /* c[4] */        -8.54344544297635788098e-05,
         /* c[5] */        -1.74905253140942193568e-05,
         /* c[6] */        -3.06142196558938128874e-06,
         /* c[7] */        -6.87177932914162287489e-07,
         /* c[8] */        -1.18400244002269115299e-07,
         /* c[9] */        -3.04457664850508328527e-08,
         /* c[10] */        -4.49026736274657305330e-09,
         /* c[11] */        -1.55646576715015340596e-09,
         /* c[12] */        -1.22012057640254963189e-10,
         /* c[13] */        -1.01539218332404736429e-10,
         /* c[14] */         4.97278086303190793842e-12,
         /* c[15] */        -8.76177272209771675989e-12,
         /* c[16] */         3.33713910876554204151e-12,
         /* c[17] */        -1.94148792669164948165e-12,
         /* c[18] */        -2.99117077089093858376e-13,
         /* c[19] */         2.10106516619397560135e-13,
         /* c[20] */         3.40434284957405645400e-13,
         /* c[21] */        -1.73433792163219535723e-13,
 };

 /************************************************************************/
         double
 erf(x)                /* return the error function of x, as defined in
                    Handbook of Mathematical Functions, National Bureau of
                    Standards AMS-55, pp. 297.
 /*----------------------------------------------------------------------*/
 double x;
 {
         int minus, k;
         double val, t, erfc();

         minus = (x < 0 ? 1 : 0);
         t = (minus ? -x : x);
         if (t > 2.0)
         {        t = 1.0 - erfc(t);
                 return (minus ? -t : t);
         }
         else
         {        t = x * x / 2.0 - 1.0;
                 val = b[bDEGREE];
                 for (k = bDEGREE-1; k >= 0; k--)
                         val = val * t + b[k];
                 return (x * val);
         }
 }

 /*\p*********************************************************************/
         double
 erfc(x)                        /* complementary error function, 1-erf(x)

 /*----------------------------------------------------------------------*/
 double x;
 {
         int k, minus, chrstc();
         double t, val, y, z, erf(), exp();

         minus = (x < 0.0 ? 1 : 0);
         z = (minus ? -x : x);
         if (z < 2.0)
                 return (1.0 - erf(x));

         y = x * x;
         t = (10.5 - y)/(2.5 + y);
         val = c[cDEGREE];
         for (k = cDEGREE-1; k >= 0; k--)
                 val = val * t + c[k];
         val = exp(-y) * val / z;
         return (minus ? 2.0 - val : val);
 }


 ERR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\ERR.C

 /* SDB - error messages */

 #include "sdbio.h"

 char *db_ertxt(msg)
   int msg;
 {
     char *txt;

     /* select the appropriate message text */
     switch (msg) {
     case INSMEM:
         txt = "insufficient memory";
         break;
     case RELFNF:
         txt = "relation file not found";
         break;
     case BADHDR:
         txt = "bad relation header";
         break;
     case TUPINP:
         txt = "tuple input error";
         break;
     case TUPOUT:
         txt = "tuple output error";
         break;
     case RELFUL:
         txt = "relation file full";
         break;
     case RELCRE:
         txt = "error creating relation file";
         break;
     case DUPATT:
         txt = "duplicate attribute";
         break;
     case MAXATT:
         txt = "too many attributes";
         break;
     case INSBLK:
         txt = "insufficient disk space";
         break;
     case SYNTAX:
         txt = "syntax error";
         break;
     case ATUNDF:
         txt = "undefined attribute";
         break;
     case ATAMBG:
         txt = "ambiguous attribute";
         break;
     case RLUNDF:
         txt = "undefined relation";
         break;
     case CDSIZE:
         txt = "boolean expression too complex";
         break;
     case INPFNF:
         txt = "input file not found";
         break;
     case OUTCRE:
         txt = "error creating output file";
         break;
     case INDFNF:
         txt = "indirect command file not found";
         break;
     case BADSET:
         txt = "bad set parameter";
         break;
     default:
         txt = "undefined error";
         break;
     }

     /* return the message text */
     return (txt);
 }



 EVAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\EVAL.C

 /*        EVAL.C:        Expresion evaluation functions for
                 MicroEMACS

         written 1986 by Daniel Lawrence                                */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"
 #include        "evar.h"

 varinit()                /* initialize the user variable list */

 {
         register int i;

         for (i=0; i < MAXVARS; i++)
                 uv[i].u_name[0] = 0;
 }

 char *gtfun(fname)        /* evaluate a function */

 char *fname;                /* name of function to evaluate */

 {
         register int fnum;                /* index to function to eval */
         register int status;                /* return status */
         char arg1[NSTRING];                /* value of first argument */
         char arg2[NSTRING];                /* value of second argument */
         char arg3[NSTRING];                /* value of third argument */
         static char result[2 * NSTRING];        /* string result */
 #if        ENVFUNC
         char *getenv();
 #endif

         /* look the function up in the function table */
         fname[3] = 0;        /* only first 3 chars significant */
         mklower(fname);        /* and let it be upper or lower case */
         for (fnum = 0; fnum < NFUNCS; fnum++)
                 if (strcmp(fname, funcs[fnum].f_name) == 0)
                         break;

         /* return errorm on a bad reference */
         if (fnum == NFUNCS)
                 return(errorm);

         /* if needed, retrieve the first argument */
         if (funcs[fnum].f_type >= MONAMIC) {
                 if ((status = macarg(arg1)) != TRUE)
                         return(errorm);

                 /* if needed, retrieve the second argument */
                 if (funcs[fnum].f_type >= DYNAMIC) {
                         if ((status = macarg(arg2)) != TRUE)
                                 return(errorm);

                         /* if needed, retrieve the third argument */
                         if (funcs[fnum].f_type >= TRINAMIC)
                                 if ((status = macarg(arg3)) != TRUE)
                                         return(errorm);
                 }
         }


         /* and now evaluate it! */
         switch (fnum) {
                 case UFADD:        return(itoa(atoi(arg1) + atoi(arg2)));
                 case UFSUB:        return(itoa(atoi(arg1) - atoi(arg2)));
                 case UFTIMES:        return(itoa(atoi(arg1) * atoi(arg2)));
                 case UFDIV:        return(itoa(atoi(arg1) / atoi(arg2)));
                 case UFMOD:        return(itoa(atoi(arg1) % atoi(arg2)));
                 case UFNEG:        return(itoa(-atoi(arg1)));
                 case UFCAT:        strcpy(result, arg1);
                                 return(strcat(result, arg2));
                 case UFLEFT:        return(strncpy(result, arg1, atoi(arg2)))
                 case UFRIGHT:        return(strcpy(result, &arg1[atoi(arg2)-1
                 case UFMID:        return(strncpy(result, &arg1[atoi(arg2)-1]
                                         atoi(arg3)));
                 case UFNOT:        return(ltos(stol(arg1) == FALSE));
                 case UFEQUAL:        return(ltos(atoi(arg1) == atoi(arg2)));
                 case UFLESS:        return(ltos(atoi(arg1) < atoi(arg2)));
                 case UFGREATER:        return(ltos(atoi(arg1) > atoi(arg2)));
                 case UFSEQUAL:        return(ltos(strcmp(arg1, arg2) == 0));
                 case UFSLESS:        return(ltos(strcmp(arg1, arg2) < 0));
                 case UFSGREAT:        return(ltos(strcmp(arg1, arg2) > 0));
                 case UFIND:        return(getval(arg1));
                 case UFAND:        return(ltos(stol(arg1) && stol(arg2)));
                 case UFOR:        return(ltos(stol(arg1) || stol(arg2)));
                 case UFLENGTH:        return(itoa(strlen(arg1)));
                 case UFUPPER:        return(mkupper(arg1));
                 case UFLOWER:        return(mklower(arg1));
                 case UFTRUTH:        return(ltos(atoi(arg1) == 42));
                 case UFASCII:        return(itoa((int)arg1[0]));
                 case UFCHR:        result[0] = atoi(arg1);
                                 result[1] = 0;
                                 return(result);
                 case UFGTKEY:        result[0] = tgetc();
                                 result[1] = 0;
                                 return(result);
                 case UFRND:        return(itoa((ernd() % abs(atoi(arg1))) + 1
                 case UFABS:        return(itoa(abs(atoi(arg1))));
                 case UFSINDEX:        return(itoa(sindex(arg1, arg2)));
                 case UFENV:
 #if        ENVFUNC
                                 return(getenv(arg1) == NULL ? "" : getenv(arg
 #else
                                 return("");
 #endif
                 case UFBIND:        return(transbind(arg1));
         }

         exit(-11);        /* never should get here */
 }

 char *gtusr(vname)        /* look up a user var's value */

 char *vname;                /* name of user variable to fetch */

 {

         register int vnum;        /* ordinal number of user var */

         /* scan the list looking for the user var name */
         for (vnum = 0; vnum < MAXVARS; vnum++)
                 if (strcmp(vname, uv[vnum].u_name) == 0)
                         break;

         /* return errorm on a bad reference */
         if (vnum == MAXVARS)
                 return(errorm);

         return(uv[vnum].u_value);
 }

 char *gtenv(vname)

 char *vname;                /* name of environment variable to retrieve */

 {
         register int vnum;        /* ordinal number of var refrenced */
         char *getkill();

         /* scan the list, looking for the referenced name */
         for (vnum = 0; vnum < NEVARS; vnum++)
                 if (strcmp(vname, envars[vnum]) == 0)
                         break;

         /* return errorm on a bad reference */
         if (vnum == NEVARS)
                 return(errorm);

         /* otherwise, fetch the appropriate value */
         switch (vnum) {
                 case EVFILLCOL:        return(itoa(fillcol));
                 case EVPAGELEN:        return(itoa(term.t_nrow + 1));
                 case EVCURCOL:        return(itoa(getccol(FALSE)));
                 case EVCURLINE: return(itoa(getcline()));
                 case EVRAM:        return(itoa((int)(envram / 1024l)));
                 case EVFLICKER:        return(ltos(flickcode));
                 case EVCURWIDTH:return(itoa(term.t_nrow));
                 case EVCBUFNAME:return(curbp->b_bname);
                 case EVCFNAME:        return(curbp->b_fname);
                 case EVSRES:        return(sres);
                 case EVDEBUG:        return(ltos(macbug));
                 case EVSTATUS:        return(ltos(cmdstatus));
                 case EVPALETTE:        return(palstr);
                 case EVASAVE:        return(itoa(gasave));
                 case EVACOUNT:        return(itoa(gacount));
                 case EVLASTKEY: return(itoa(lastkey));
                 case EVCURCHAR:
                         return(curwp->w_dotp->l_used ==
                                         curwp->w_doto ? itoa('\n') :
                                 itoa(lgetc(curwp->w_dotp, curwp->w_doto)));
                 case EVDISCMD:        return(ltos(discmd));
                 case EVVERSION:        return(VERSION);
                 case EVPROGNAME:return(PROGNAME);
                 case EVSEED:        return(itoa(seed));
                 case EVDISINP:        return(ltos(disinp));
                 case EVWLINE:        return(itoa(curwp->w_ntrows));
                 case EVCWLINE:        return(itoa(getwpos()));
                 case EVTARGET:        saveflag = lastflag;
                                 return(itoa(curgoal));
                 case EVSEARCH:        return(pat);
                 case EVREPLACE:        return(rpat);
                 case EVMATCH:        return((patmatch == NULL)? "": patmatch)
                 case EVKILL:        return(getkill());
                 case EVCMODE:        return(itoa(curbp->b_mode));
                 case EVGMODE:        return(itoa(gmode));
                 case EVTPAUSE:        return(itoa(term.t_pause));
                 case EVPENDING:
 #if        TYPEAH
                                 return(ltos(typahead()));
 #else
                                 return(falsem);
 #endif
                 case EVLWIDTH:        return(itoa(llength(curwp->w_dotp)));
                 case EVLINE:        return(getctext());
         }
         exit(-12);        /* again, we should never get here */
 }

 char *getkill()                /* return some of the contents of the kill buf

 {
         register int size;        /* max number of chars to return */
         char value[NSTRING];        /* temp buffer for value */

         if (kbufh == NULL)
                 /* no kill buffer....just a null string */
                 value[0] = 0;
         else {
                 /* copy in the contents... */
                 if (kused < NSTRING)
                         size = kused;
                 else
                         size = NSTRING - 1;
                 strncpy(value, kbufh->d_chunk, size);
         }

         /* and return the constructed value */
         return(value);
 }

 int setvar(f, n)                /* set a variable */

 int f;                /* default flag */
 int n;                /* numeric arg (can overide prompted value) */

 {
         register int status;        /* status return */
 #if        DEBUGM
         register char *sp;        /* temp string pointer */
         register char *ep;        /* ptr to end of outline */
 #endif
         VDESC vd;                /* variable num/type */
         char var[NVSIZE+1];        /* name of variable to fetch */
         char value[NSTRING];        /* value to set variable to */

         /* first get the variable to set.. */
         if (clexec == FALSE) {
                 status = mlreply("Variable to set: ", &var[0], NVSIZE);
                 if (status != TRUE)
                         return(status);
         } else {        /* macro line argument */
                 /* grab token and skip it */
                 execstr = token(execstr, var);
         }

         /* check the legality and find the var */
         findvar(var, &vd);

         /* if its not legal....bitch */
         if (vd.v_type == -1) {
                 mlwrite("%%No such variable as '%s'", var);
                 return(FALSE);
         }

         /* get the value for that variable */
         if (f == TRUE)
                 strcpy(value, itoa(n));
         else {
                 status = mlreply("Value: ", &value[0], NSTRING);
                 if (status != TRUE)
                         return(status);
         }

         /* and set the appropriate value */
         status = svar(&vd, value);

 #if        DEBUGM
         /* if $debug == TRUE, every assignment will echo a statment to
            that effect here. */

         if (macbug) {
                 strcpy(outline, "(((");

                 /* assignment status */
                 strcat(outline, ltos(status));
                 strcat(outline, ":");

                 /* variable name */
                 strcat(outline, var);
                 strcat(outline, ":");

                 /* and lastly the value we tried to assign */
                 strcat(outline, value);
                 strcat(outline, ")))");

                 /* expand '%' to "%%" so mlwrite wont bitch */
                 sp = outline;
                 while (*sp)
                         if (*sp++ == '%') {
                                 /* advance to the end */
                                 ep = --sp;
                                 while (*ep++)
                                         ;
                                 /* null terminate the string one out */
                                 *(ep + 1) = 0;
                                 /* copy backwards */
                                 while(ep-- > sp)
                                         *(ep + 1) = *ep;

                                 /* and advance sp past the new % */
                                 sp += 2;
                         }

                 /* write out the debug line */
                 mlforce(outline);
                 update(TRUE);

                 /* and get the keystroke to hold the output */
                 if (get1key() == abortc) {
                         mlforce("[Macro aborted]");
                         status = FALSE;
                 }
         }
 #endif

         /* and return it */
         return(status);
 }

 findvar(var, vd)        /* find a variables type and name */

 char *var;        /* name of var to get */
 VDESC *vd;        /* structure to hold type and ptr */

 {
         register int vnum;        /* subscript in varable arrays */
         register int vtype;        /* type to return */

 fvar:        vtype = -1;
         switch (var[0]) {

                 case '$': /* check for legal enviromnent var */
                         for (vnum = 0; vnum < NEVARS; vnum++)
                                 if (strcmp(&var[1], envars[vnum]) == 0) {
                                         vtype = TKENV;
                                         break;
                                 }
                         break;

                 case '%': /* check for existing legal user variable */
                         for (vnum = 0; vnum < MAXVARS; vnum++)
                                 if (strcmp(&var[1], uv[vnum].u_name) == 0) {
                                         vtype = TKVAR;
                                         break;
                                 }
                         if (vnum < MAXVARS)
                                 break;

                         /* create a new one??? */
                         for (vnum = 0; vnum < MAXVARS; vnum++)
                                 if (uv[vnum].u_name[0] == 0) {
                                         vtype = TKVAR;
                                         strcpy(uv[vnum].u_name, &var[1]);
                                         break;
                                 }
                         break;

                 case '&':        /* indirect operator? */
                         var[4] = 0;
                         if (strcmp(&var[1], "ind") == 0) {
                                 /* grab token, and eval it */
                                 execstr = token(execstr, var);
                                 strcpy(var, getval(var));
                                 goto fvar;
                         }
         }

         /* return the results */
         vd->v_num = vnum;
         vd->v_type = vtype;
         return;
 }

 int svar(var, value)                /* set a variable */

 VDESC *var;        /* variable to set */
 char *value;        /* value to set to */

 {
         register int vnum;        /* ordinal number of var refrenced */
         register int vtype;        /* type of variable to set */
         register int status;        /* status return */
         register int c;                /* translated character */
         register char * sp;        /* scratch string pointer */

         /* simplify the vd structure (we are gonna look at it a lot) */
         vnum = var->v_num;
         vtype = var->v_type;

         /* and set the appropriate value */
         status = TRUE;
         switch (vtype) {
         case TKVAR: /* set a user variable */
                 if (uv[vnum].u_value != NULL)
                         free(uv[vnum].u_value);
                 sp = malloc(strlen(value) + 1);
                 if (sp == NULL)
                         return(FALSE);
                 strcpy(sp, value);
                 uv[vnum].u_value = sp;
                 break;

         case TKENV: /* set an environment variable */
                 status = TRUE;        /* by default */
                 switch (vnum) {
                 case EVFILLCOL:        fillcol = atoi(value);
                                 break;
                 case EVPAGELEN:        status = newsize(TRUE, atoi(value));
                                 break;
                 case EVCURCOL:        status = setccol(atoi(value));
                                 break;
                 case EVCURLINE:        status = gotoline(TRUE, atoi(value));
                                 break;
                 case EVRAM:        break;
                 case EVFLICKER:        flickcode = stol(value);
                                 break;
                 case EVCURWIDTH:status = newwidth(TRUE, atoi(value));
                                 break;
                 case EVCBUFNAME:strcpy(curbp->b_bname, value);
                                 curwp->w_flag |= WFMODE;
                                 break;
                 case EVCFNAME:        strcpy(curbp->b_fname, value);
                                 curwp->w_flag |= WFMODE;
                                 break;
                 case EVSRES:        status = TTrez(value);
                                 break;
                 case EVDEBUG:        macbug = stol(value);
                                 break;
                 case EVSTATUS:        cmdstatus = stol(value);
                                 break;
                 case EVPALETTE:        strncpy(palstr, value, 48);
                                 spal(palstr);
                                 break;
                 case EVASAVE:        gasave = atoi(value);
                                 break;
                 case EVACOUNT:        gacount = atoi(value);
                                 break;
                 case EVLASTKEY:        lastkey = atoi(value);
                                 break;
                 case EVCURCHAR:        ldelete(1, FALSE);        /* delete 1
                                 c = atoi(value);
                                 if (c == '\n')
                                         lnewline(FALSE, 1);
                                 else
                                         linsert(1, c);
                                 backchar(FALSE, 1);
                                 break;
                 case EVDISCMD:        discmd = stol(value);
                                 break;
                 case EVVERSION:        break;
                 case EVPROGNAME:break;
                 case EVSEED:        seed = atoi(value);
                                 break;
                 case EVDISINP:        disinp = stol(value);
                                 break;
                 case EVWLINE:        status = resize(TRUE, atoi(value));
                                 break;
                 case EVCWLINE:        status = forwline(TRUE,
                                                 atoi(value) - getwpos());
                                 break;
                 case EVTARGET:        curgoal = atoi(value);
                                 thisflag = saveflag;
                                 break;
                 case EVSEARCH:        strcpy(pat, value);
                                 rvstrcpy(tap, pat);
                                 mcclear();
                                 break;
                 case EVREPLACE:        strcpy(rpat, value);
                                 break;
                 case EVMATCH:        break;
                 case EVKILL:        break;
                 case EVCMODE:        curbp->b_mode = atoi(value);
                                 curwp->w_flag |= WFMODE;
                                 break;
                 case EVGMODE:        gmode = atoi(value);
                                 break;
                 case EVTPAUSE:        term.t_pause = atoi(value);
                                 break;
                 case EVPENDING:        break;
                 case EVLWIDTH:        break;
                 case EVLINE:        putctext(value);
                 }
                 break;
         }
         return(status);
 }

 /*        atoi:        ascii string to integer......This is too
                 inconsistant to use the system's        */

 atoi(st)

 char *st;

 {
         int result;        /* resulting number */
         int sign;        /* sign of resulting number */
         char c;                /* current char being examined */

         result = 0;
         sign = 1;

         /* skip preceding whitespace */
         while (*st == ' ' || *st == '\t')
                 ++st;

         /* check for sign */
         if (*st == '-') {
                 sign = -1;
                 ++st;
         }
         if (*st == '+')
                 ++st;

         /* scan digits, build value */
         while ((c = *st++))
                 if (c >= '0' && c <= '9')
                         result = result * 10 + c - '0';
                 else
                         return(0);

         return(result * sign);
 }

 /*        itoa:        integer to ascii string.......... This is too
                 inconsistant to use the system's        */

 char *itoa(i)

 int i;        /* integer to translate to a string */

 {
         register int digit;                /* current digit being used */
         register char *sp;                /* pointer into result */
         register int sign;                /* sign of resulting number */
         static char result[INTWIDTH+1];        /* resulting string */

         /* record the sign...*/
         sign = 1;
         if (i < 0) {
                 sign = -1;
                 i = -i;
         }

         /* and build the string (backwards!) */
         sp = result + INTWIDTH;
         *sp = 0;
         do {
                 digit = i % 10;
                 *(--sp) = '0' + digit;        /* and install the new digit */
                 i = i / 10;
         } while (i);

         /* and fix the sign */
         if (sign == -1) {
                 *(--sp) = '-';        /* and install the minus sign */
         }

         return(sp);
 }

 int gettyp(token)        /* find the type of a passed token */

 char *token;        /* token to analyze */

 {
         register char c;        /* first char in token */

         /* grab the first char (this is all we need) */
         c = *token;

         /* no blanks!!! */
         if (c == 0)
                 return(TKNUL);

         /* a numeric literal? */
         if (c >= '0' && c <= '9')
                 return(TKLIT);

         switch (c) {
                 case '"':        return(TKSTR);

                 case '!':        return(TKDIR);
                 case '@':        return(TKARG);
                 case '#':        return(TKBUF);
                 case '$':        return(TKENV);
                 case '%':        return(TKVAR);
                 case '&':        return(TKFUN);
                 case '*':        return(TKLBL);

                 default:        return(TKCMD);
         }
 }

 char *getval(token)        /* find the value of a token */

 char *token;                /* token to evaluate */

 {
         register int status;        /* error return */
         register BUFFER *bp;        /* temp buffer pointer */
         register int blen;        /* length of buffer argument */
         register int distmp;        /* temporary discmd flag */
         char pad[20];                /* pad 20 bytes on stack for safety */
         char buf[NSTRING];        /* string buffer for some returns */

         switch (gettyp(token)) {
                 case TKNUL:        return("");

                 case TKARG:        /* interactive argument */
                                 strcpy(token, getval(&token[1]));
                                 distmp = discmd;        /* echo it always! */
                                 discmd = TRUE;
                                 status = getstring(token,
                                            buf, NSTRING, ctoec('\n'));
                                 discmd = distmp;
                                 if (status == ABORT)
                                         return(errorm);
                                 return(buf);

                 case TKBUF:        /* buffer contents fetch */

                                 /* grab the right buffer */
                                 strcpy(token, getval(&token[1]));
                                 bp = bfind(token, FALSE, 0);
                                 if (bp == NULL)
                                         return(errorm);

                                 /* if the buffer is displayed, get the window
                                    vars instead of the buffer vars */
                                 if (bp->b_nwnd > 0) {
                                         curbp->b_dotp = curwp->w_dotp;
                                         curbp->b_doto = curwp->w_doto;
                                 }

                                 /* make sure we are not at the end */
                                 if (bp->b_linep == bp->b_dotp)
                                         return(errorm);

                                 /* grab the line as an argument */
                                 blen = bp->b_dotp->l_used - bp->b_doto;
                                 if (blen > NSTRING)
                                         blen = NSTRING;
                                 strncpy(buf, bp->b_dotp->l_text + bp->b_doto,
                                         blen);
                                 buf[blen] = 0;

                                 /* and step the buffer's line ptr ahead a lin
                                 bp->b_dotp = bp->b_dotp->l_fp;
                                 bp->b_doto = 0;

                                 /* if displayed buffer, reset window ptr vars
                                 if (bp->b_nwnd > 0) {
                                         curwp->w_dotp = curbp->b_dotp;
                                         curwp->w_doto = 0;
                                         curwp->w_flag |= WFMOVE;
                                 }

                                 /* and return the spoils */
                                 return(buf);

                 case TKVAR:        return(gtusr(token+1));
                 case TKENV:        return(gtenv(token+1));
                 case TKFUN:        return(gtfun(token+1));
                 case TKDIR:        return(errorm);
                 case TKLBL:        return(itoa(gtlbl(token)));
                 case TKLIT:        return(token);
                 case TKSTR:        return(token+1);
                 case TKCMD:        return(token);
         }
 }

 gtlbl(token)        /* find the line number of the given label */

 char *token;        /* label name to find */

 {
         return(1);
 }

 int stol(val)        /* convert a string to a numeric logical */

 char *val;        /* value to check for stol */

 {
         /* check for logical values */
         if (val[0] == 'F')
                 return(FALSE);
         if (val[0] == 'T')
                 return(TRUE);

         /* check for numeric truth (!= 0) */
         return((atoi(val) != 0));
 }

 char *ltos(val)                /* numeric logical to string logical */

 int val;        /* value to translate */

 {
         if (val)
                 return(truem);
         else
                 return(falsem);
 }

 char *mkupper(str)        /* make a string upper case */

 char *str;                /* string to upper case */

 {
         char *sp;

         sp = str;
         while (*sp) {
                 if ('a' <= *sp && *sp <= 'z')
                         *sp += 'A' - 'a';
                 ++sp;
         }
         return(str);
 }

 char *mklower(str)        /* make a string lower case */

 char *str;                /* string to lower case */

 {
         char *sp;

         sp = str;
         while (*sp) {
                 if ('A' <= *sp && *sp <= 'Z')
                         *sp += 'a' - 'A';
                 ++sp;
         }
         return(str);
 }

 int abs(x)        /* take the absolute value of an integer */

 int x;

 {
         return(x < 0 ? -x : x);
 }

 int ernd()        /* returns a random integer */

 {
         seed = abs(seed * 1721 + 10007);
         return(seed);
 }

 int sindex(source, pattern)        /* find pattern within source */

 char *source;        /* source string to search */
 char *pattern;        /* string to look for */

 {
         char *sp;        /* ptr to current position to scan */
         char *csp;        /* ptr to source string during comparison */
         char *cp;        /* ptr to place to check for equality */

         /* scanning through the source string */
         sp = source;
         while (*sp) {
                 /* scan through the pattern */
                 cp = pattern;
                 csp = sp;
                 while (*cp) {
                         if (!eq(*cp, *csp))
                                 break;
                         ++cp;
                         ++csp;
                 }

                 /* was it a match? */
                 if (*cp == 0)
                         return((int)(sp - source) + 1);
                 ++sp;
         }

         /* no match at all.. */
         return(0);
 }


 EXAMPLE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\GLOB\EXAMPLE.C

 /* Example program demonstrating the use of glob() */

 #include "glob.h"

  main() {
          char **names;
          names = glob("*.?");
          if (names) {
             printf("expansion of *.? is:\n");
              print(names);
          } else
              printf("glob() error number %d (see glob.h)\n",globerror);
         recover(names);
  }

  recover(names)                /* free() all the space used up by **names; */
  char **names;
  {
      int i = 0;
      while (names[i] != (char *)0) {
          free(names[i]);
          i++;
      }
      free(names);
  }

  print(names)                /* print out all the filenames returned by glob(
  char **names;
  {
      int i;
      i = 0;
      while (names[i] != (char *)0) {
          printf("%s\n",names[i]);
          i++;
      }
  }


 EXC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\EXC.C

 /*              Example C Program

         This program simply prints "Hello, world!"
  */

 main()

 {
         printf("Hello, world!\n");
 }



 EXEC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\EXEC.C

 /*        This file is for functions dealing with execution of
         commands, command lines, buffers, files and startup files

         written 1986 by Daniel Lawrence                                */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 /* namedcmd:        execute a named command even if it is not bound */

 namedcmd(f, n)

 int f, n;        /* command arguments [passed through to command executed] */

 {
         register (*kfunc)();        /* ptr to the requexted function to bind
         int (*getname())();

         /* prompt the user to type a named command */
         mlwrite(": ");

         /* and now get the function name to execute */
         kfunc = getname();
         if (kfunc == NULL) {
                 mlwrite("[No such function]");
                 return(FALSE);
         }

         /* and then execute the command */
         return((*kfunc)(f, n));
 }

 /*        execcmd:        Execute a command line command to be typed in
                         by the user                                        */

 execcmd(f, n)

 int f, n;        /* default Flag and Numeric argument */

 {
         register int status;                /* status return */
         char cmdstr[NSTRING];                /* string holding command to exe

         /* get the line wanted */
         if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
                 return(status);

         execlevel = 0;
         return(docmd(cmdstr));
 }

 /*        docmd:        take a passed string as a command line and translate
                 it to be executed as a command. This function will be
                 used by execute-command-line and by all source and
                 startup files. Lastflag/thisflag is also updated.

         format of the command line is:

                 {# arg} <command-name> {<argument string(s)>}

 */

 docmd(cline)

 char *cline;        /* command line to execute */

 {
         register int f;                /* default argument flag */
         register int n;                /* numeric repeat value */
         register int i;
         int (*fnc)();                /* function to execute */
         int status;                /* return status of function */
         int oldcle;                /* old contents of clexec flag */
         char *oldestr;                /* original exec string */
         char tkn[NSTRING];        /* next token off of command line */
         int (*fncmatch())();

         /* if we are scanning and not executing..go back here */
         if (execlevel)
                 return(TRUE);

         oldestr = execstr;        /* save last ptr to string to execute */
         execstr = cline;        /* and set this one as current */

         /* first set up the default command values */
         f = FALSE;
         n = 1;
         lastflag = thisflag;
         thisflag = 0;

         if ((status = macarg(tkn)) != TRUE) {        /* and grab the first to
                 execstr = oldestr;
                 return(status);
         }

         /* process leadin argument */
         if (gettyp(tkn) != TKCMD) {
                 f = TRUE;
                 strcpy(tkn, getval(tkn));
                 n = atoi(tkn);

                 /* and now get the command to execute */
                 if ((status = macarg(tkn)) != TRUE) {
                         execstr = oldestr;
                         return(status);
                 }
         }

         /* and match the token to see if it exists */
         if ((fnc = fncmatch(tkn)) == NULL) {
                 mlwrite("[No such Function]");
                 execstr = oldestr;
                 return(FALSE);
         }

         /* save the arguments and go execute the command */
         oldcle = clexec;                /* save old clexec flag */
         clexec = TRUE;                        /* in cline execution */
         status = (*fnc)(f, n);                /* call the function */
         cmdstatus = status;                /* save the status */
         clexec = oldcle;                /* restore clexec flag */
         execstr = oldestr;
         return(status);
 }

 /* token:        chop a token off a string
                 return a pointer past the token
 */

 char *token(src, tok)

 char *src, *tok;        /* source string, destination token string */

 {
         register int quotef;        /* is the current string quoted? */

         /* first scan past any whitespace in the source string */
         while (*src == ' ' || *src == '\t')
                 ++src;

         /* scan through the source string */
         quotef = FALSE;
         while (*src) {
                 /* process special characters */
                 if (*src == '~') {
                         ++src;
                         if (*src == 0)
                                 break;
                         switch (*src++) {
                                 case 'r':        *tok++ = 13; break;
                                 case 'n':        *tok++ = 10; break;
                                 case 't':        *tok++ = 9;  break;
                                 case 'b':        *tok++ = 8;  break;
                                 case 'f':        *tok++ = 12; break;
                                 default:        *tok++ = *(src-1);
                         }
                 } else {
                         /* check for the end of the token */
                         if (quotef) {
                                 if (*src == '"')
                                         break;
                         } else {
                                 if (*src == ' ' || *src == '\t')
                                         break;
                         }

                         /* set quote mode if qoute found */
                         if (*src == '"')
                                 quotef = TRUE;

                         /* record the character */
                         *tok++ = *src++;
                 }
         }

         /* terminate the token and exit */
         if (*src)
                 ++src;
         *tok = 0;
         return(src);
 }

 macarg(tok)        /* get a macro line argument */

 char *tok;        /* buffer to place argument */

 {
         int savcle;        /* buffer to store original clexec */
         int status;

         savcle = clexec;        /* save execution mode */
         clexec = TRUE;                /* get the argument */
         status = nextarg("", tok, NSTRING, ctoec('\n'));
         clexec = savcle;        /* restore execution mode */
         return(status);
 }

 /*        nextarg:        get the next argument        */

 nextarg(prompt, buffer, size, terminator)

 char *prompt;                /* prompt to use if we must be interactive */
 char *buffer;                /* buffer to put token into */
 char *size;                /* size of the buffer */
 int terminator;                /* terminating char to be used on interactive

 {
         /* if we are interactive, go get it! */
         if (clexec == FALSE)
                 return(getstring(prompt, buffer, size, terminator));

         /* grab token and advance past */
         execstr = token(execstr, buffer);

         /* evaluate it */
         strcpy(buffer, getval(buffer));
         return(TRUE);
 }

 /*        storemac:        Set up a macro buffer and flag to store all
                         executed command lines there                        *

 storemac(f, n)

 int f;                /* default flag */
 int n;                /* macro number to use */

 {
         register struct BUFFER *bp;        /* pointer to macro buffer */
         char bname[NBUFN];                /* name of buffer to use */

         /* must have a numeric argument to this function */
         if (f == FALSE) {
                 mlwrite("No macro specified");
                 return(FALSE);
         }

         /* range check the macro number */
         if (n < 1 || n > 40) {
                 mlwrite("Macro number out of range");
                 return(FALSE);
         }

         /* construct the macro buffer name */
         strcpy(bname, "[Macro xx]");
         bname[7] = '0' + (n / 10);
         bname[8] = '0' + (n % 10);

         /* set up the new macro buffer */
         if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
                 mlwrite("Can not create macro");
                 return(FALSE);
         }

         /* and make sure it is empty */
         bclear(bp);

         /* and set the macro store pointers to it */
         mstore = TRUE;
         bstore = bp;
         return(TRUE);
 }

 #if        PROC
 /*        storeproc:        Set up a procedure buffer and flag to store all
                         executed command lines there                        *

 storeproc(f, n)

 int f;                /* default flag */
 int n;                /* macro number to use */

 {
         register struct BUFFER *bp;        /* pointer to macro buffer */
         register int status;                /* return status */
         char bname[NBUFN];                /* name of buffer to use */

         /* a numeric argument means its a numbered macro */
         if (f == TRUE)
                 return(storemac(f, n));

         /* get the name of the procedure */
         if ((status = mlreply("Procedure name: ", &bname[1], NBUFN-2)) != TRU
                 return(status);

         /* construct the macro buffer name */
         bname[0] = '[';
         strcat(bname, "]");

         /* set up the new macro buffer */
         if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
                 mlwrite("Can not create macro");
                 return(FALSE);
         }

         /* and make sure it is empty */
         bclear(bp);

         /* and set the macro store pointers to it */
         mstore = TRUE;
         bstore = bp;
         return(TRUE);
 }

 /*        execproc:        Execute a procedure

 execproc(f, n)

 int f, n;        /* default flag and numeric arg */

 {
         register BUFFER *bp;                /* ptr to buffer to execute */
         register int status;                /* status return */
         char bufn[NBUFN+2];                /* name of buffer to execute */

         /* find out what buffer the user wants to execute */
         if ((status = mlreply("Execute procedure: ", &bufn[1], NBUFN)) != TRU
                 return(status);

         /* construct the buffer name */
         bufn[0] = '[';
         strcat(bufn, "]");

         /* find the pointer to that buffer */
         if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
                 mlwrite("No such procedure");
                 return(FALSE);
         }

         /* and now execute it as asked */
         while (n-- > 0)
                 if ((status = dobuf(bp)) != TRUE)
                         return(status);
         return(TRUE);
 }
 #endif

 /*        execbuf:        Execute the contents of a buffer of commands

 execbuf(f, n)

 int f, n;        /* default flag and numeric arg */

 {
         register BUFFER *bp;                /* ptr to buffer to execute */
         register int status;                /* status return */
         char bufn[NSTRING];                /* name of buffer to execute */

         /* find out what buffer the user wants to execute */
         if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
                 return(status);

         /* find the pointer to that buffer */
         if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
                 mlwrite("No such buffer");
                 return(FALSE);
         }

         /* and now execute it as asked */
         while (n-- > 0)
                 if ((status = dobuf(bp)) != TRUE)
                         return(status);
         return(TRUE);
 }

 /*        dobuf:        execute the contents of the buffer pointed to
                 by the passed BP

         Directives start with a "!" and include:

         !endm                End a macro
         !if (cond)        conditional execution
         !else
         !endif
         !return                Return (terminating current macro)
         !goto <label>        Jump to a label in the current macro
         !force                Force macro to continue...even if command fails
         !while (cond)        Execute a loop if the condition is true
         !endwhile

         Line Labels begin with a "*" as the first nonblank char, like:

         *LBL01
 */

 dobuf(bp)

 BUFFER *bp;        /* buffer to execute */

 {
         register int status;        /* status return */
         register LINE *lp;        /* pointer to line to execute */
         register LINE *hlp;        /* pointer to line header */
         register LINE *glp;        /* line to goto */
         LINE *mp;                /* Macro line storage temp */
         int dirnum;                /* directive index */
         int linlen;                /* length of line to execute */
         int i;                        /* index */
         int force;                /* force TRUE result? */
         WINDOW *wp;                /* ptr to windows to scan */
         WHBLOCK *whlist;        /* ptr to !WHILE list */
         WHBLOCK *scanner;        /* ptr during scan */
         WHBLOCK *whtemp;        /* temporary ptr to a WHBLOCK */
         char *einit;                /* initial value of eline */
         char *eline;                /* text of line to execute */
         char tkn[NSTRING];        /* buffer to evaluate an expresion in */

 #if        DEBUGM
         char *sp;                        /* temp for building debug string */
         register char *ep;        /* ptr to end of outline */
 #endif

         /* clear IF level flags/while ptr */
         execlevel = 0;
         whlist = NULL;
         scanner = NULL;

         /* scan the buffer to execute, building WHILE header blocks */
         hlp = bp->b_linep;
         lp = hlp->l_fp;
         while (lp != hlp) {
                 /* scan the current line */
                 eline = lp->l_text;
                 i = lp->l_used;

                 /* trim leading whitespace */
                 while (i-- > 0 && (*eline == ' ' || *eline == '\t'))
                         ++eline;

                 /* if theres nothing here, don't bother */
                 if (i <= 0)
                         goto nxtscan;

                 /* if is a while directive, make a block... */
                 if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') {
                         whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
                         if (whtemp == NULL) {
 noram:                                mlwrite("%%Out of memory during while s
 failexit:                        freewhile(scanner);
                                 freewhile(whlist);
                                 return(FALSE);
                         }
                         whtemp->w_begin = lp;
                         whtemp->w_type = BTWHILE;
                         whtemp->w_next = scanner;
                         scanner = whtemp;
                 }

                 /* if is a BREAK directive, make a block... */
                 if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') {
                         if (scanner == NULL) {
                                 mlwrite("%%!BREAK outside of any !WHILE loop"
                                 goto failexit;
                         }
                         whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
                         if (whtemp == NULL)
                                 goto noram;
                         whtemp->w_begin = lp;
                         whtemp->w_type = BTBREAK;
                         whtemp->w_next = scanner;
                         scanner = whtemp;
                 }

                 /* if it is an endwhile directive, record the spot... */
                 if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) {
                         if (scanner == NULL) {
                                 mlwrite("%%!ENDWHILE with no preceding !WHILE
                                         bp->b_bname);
                                 goto failexit;
                         }
                         /* move top records from the scanner list to the
                            whlist until we have moved all BREAK records
                            and one WHILE record */
                         do {
                                 scanner->w_end = lp;
                                 whtemp = whlist;
                                 whlist = scanner;
                                 scanner = scanner->w_next;
                                 whlist->w_next = whtemp;
                         } while (whlist->w_type == BTBREAK);
                 }

 nxtscan:        /* on to the next line */
                 lp = lp->l_fp;
         }

         /* while and endwhile should match! */
         if (scanner != NULL) {
                 mlwrite("%%!WHILE with no matching !ENDWHILE in '%s'",
                         bp->b_bname);
                 goto failexit;
         }

         /* let the first command inherit the flags from the last one..*/
         thisflag = lastflag;

         /* starting at the beginning of the buffer */
         hlp = bp->b_linep;
         lp = hlp->l_fp;
         while (lp != hlp) {
                 /* allocate eline and copy macro line to it */
                 linlen = lp->l_used;
                 if ((einit = eline = malloc(linlen+1)) == NULL) {
                         mlwrite("%%Out of Memory during macro execution");
                         freewhile(whlist);
                         return(FALSE);
                 }
                 strncpy(eline, lp->l_text, linlen);
                 eline[linlen] = 0;        /* make sure it ends */

                 /* trim leading whitespace */
                 while (*eline == ' ' || *eline == '\t')
                         ++eline;

                 /* dump comments and blank lines */
                 if (*eline == ';' || *eline == 0)
                         goto onward;

 #if        DEBUGM
                 /* if $debug == TRUE, every line to execute
                    gets echoed and a key needs to be pressed to continue
                    ^G will abort the command */

                 if (macbug) {
                         strcpy(outline, "<<<");

                         /* debug macro name */
                         strcat(outline, bp->b_bname);
                         strcat(outline, ":");

                         /* debug if levels */
                         strcat(outline, itoa(execlevel));
                         strcat(outline, ":");

                         /* and lastly the line */
                         strcat(outline, eline);
                         strcat(outline, ">>>");

                         /* change all '%' to ':' so mlwrite won't expect argu
                         sp = outline;
                         while (*sp)
                         if (*sp++ == '%') {
                                 /* advance to the end */
                                 ep = --sp;
                                 while (*ep++)
                                         ;
                                 /* null terminate the string one out */
                                 *(ep + 1) = 0;
                                 /* copy backwards */
                                 while(ep-- > sp)
                                         *(ep + 1) = *ep;

                                 /* and advance sp past the new % */
                                 sp += 2;
                         }

                         /* write out the debug line */
                         mlforce(outline);
                         update(TRUE);

                         /* and get the keystroke */
                         if (get1key() == abortc) {
                                 mlforce("[Macro aborted]");
                                 freewhile(whlist);
                                 return(FALSE);
                         }
                 }
 #endif

                 /* Parse directives here.... */
                 dirnum = -1;
                 if (*eline == '!') {
                         /* Find out which directive this is */
                         ++eline;
                         for (dirnum = 0; dirnum < NUMDIRS; dirnum++)
                                 if (strncmp(eline, dname[dirnum],
                                             strlen(dname[dirnum])) == 0)
                                         break;

                         /* and bitch if it's illegal */
                         if (dirnum == NUMDIRS) {
                                 mlwrite("%%Unknown Directive");
                                 freewhile(whlist);
                                 return(FALSE);
                         }

                         /* service only the !ENDM macro here */
                         if (dirnum == DENDM) {
                                 mstore = FALSE;
                                 bstore = NULL;
                                 goto onward;
                         }

                         /* restore the original eline....*/
                         --eline;
                 }

                 /* if macro store is on, just salt this away */
                 if (mstore) {
                         /* allocate the space for the line */
                         linlen = strlen(eline);
                         if ((mp=lalloc(linlen)) == NULL) {
                                 mlwrite("Out of memory while storing macro");
                                 return (FALSE);
                         }

                         /* copy the text into the new line */
                         for (i=0; i<linlen; ++i)
                                 lputc(mp, i, eline[i]);

                         /* attach the line to the end of the buffer */
                                bstore->b_linep->l_bp->l_fp = mp;
                         mp->l_bp = bstore->b_linep->l_bp;
                         bstore->b_linep->l_bp = mp;
                         mp->l_fp = bstore->b_linep;
                         goto onward;
                 }


                 force = FALSE;

                 /* dump comments */
                 if (*eline == '*')
                         goto onward;

                 /* now, execute directives */
                 if (dirnum != -1) {
                         /* skip past the directive */
                         while (*eline && *eline != ' ' && *eline != '\t')
                                 ++eline;
                         execstr = eline;

                         switch (dirnum) {
                         case DIF:        /* IF directive */
                                 /* grab the value of the logical exp */
                                 if (execlevel == 0) {
                                         if (macarg(tkn) != TRUE)
                                                 goto eexec;
                                         if (stol(tkn) == FALSE)
                                                 ++execlevel;
                                 } else
                                         ++execlevel;
                                 goto onward;

                         case DWHILE:        /* WHILE directive */
                                 /* grab the value of the logical exp */
                                 if (execlevel == 0) {
                                         if (macarg(tkn) != TRUE)
                                                 goto eexec;
                                         if (stol(tkn) == TRUE)
                                                 goto onward;
                                 }
                                 /* drop down and act just like !BREAK */

                         case DBREAK:        /* BREAK directive */
                                 if (dirnum == DBREAK && execlevel)
                                         goto onward;

                                 /* jump down to the endwhile */
                                 /* find the right while loop */
                                 whtemp = whlist;
                                 while (whtemp) {
                                         if (whtemp->w_begin == lp)
                                                 break;
                                         whtemp = whtemp->w_next;
                                 }

                                 if (whtemp == NULL) {
                                         mlwrite("%%Internal While loop error"
                                         freewhile(whlist);
                                         return(FALSE);
                                 }

                                 /* reset the line pointer back.. */
                                 lp = whtemp->w_end;
                                 goto onward;

                         case DELSE:        /* ELSE directive */
                                 if (execlevel == 1)
                                         --execlevel;
                                 else if (execlevel == 0 )
                                         ++execlevel;
                                 goto onward;

                         case DENDIF:        /* ENDIF directive */
                                 if (execlevel)
                                         --execlevel;
                                 goto onward;

                         case DGOTO:        /* GOTO directive */
                                 /* .....only if we are currently executing */
                                 if (execlevel == 0) {

                                         /* grab label to jump to */
                                         eline = token(eline, golabel);
                                         linlen = strlen(golabel);
                                         glp = hlp->l_fp;
                                         while (glp != hlp) {
                                                 if (*glp->l_text == '*' &&
                                                     (strncmp(&glp->l_text[1],
                                                             linlen) == 0)) {
                                                         lp = glp;
                                                         goto onward;
                                                 }
                                                 glp = glp->l_fp;
                                         }
                                         mlwrite("%%No such label");
                                         freewhile(whlist);
                                         return(FALSE);
                                 }
                                 goto onward;

                         case DRETURN:        /* RETURN directive */
                                 if (execlevel == 0)
                                         goto eexec;
                                 goto onward;

                         case DENDWHILE:        /* ENDWHILE directive */
                                 if (execlevel) {
                                         --execlevel;
                                         goto onward;
                                 } else {
                                         /* find the right while loop */
                                         whtemp = whlist;
                                         while (whtemp) {
                                                 if (whtemp->w_type == BTWHILE
                                                     whtemp->w_end == lp)
                                                         break;
                                                 whtemp = whtemp->w_next;
                                         }

                                         if (whtemp == NULL) {
                                                 mlwrite("%%Internal While loo
                                                 freewhile(whlist);
                                                 return(FALSE);
                                         }

                                         /* reset the line pointer back.. */
                                         lp = whtemp->w_begin->l_bp;
                                         goto onward;
                                 }

                         case DFORCE:        /* FORCE directive */
                                 force = TRUE;

                         }
                 }

                 /* execute the statement */
                 status = docmd(eline);
                 if (force)                /* force the status */
                         status = TRUE;

                 /* check for a command error */
                 if (status != TRUE) {
                         /* look if buffer is showing */
                         wp = wheadp;
                         while (wp != NULL) {
                                 if (wp->w_bufp == bp) {
                                         /* and point it */
                                         wp->w_dotp = lp;
                                         wp->w_doto = 0;
                                         wp->w_flag |= WFHARD;
                                 }
                                 wp = wp->w_wndp;
                         }
                         /* in any case set the buffer . */
                         bp->b_dotp = lp;
                         bp->b_doto = 0;
                         free(einit);
                         execlevel = 0;
                         freewhile(whlist);
                         return(status);
                 }

 onward:                /* on to the next line */
                 free(einit);
                 lp = lp->l_fp;
         }

 eexec:        /* exit the current function */
         execlevel = 0;
         freewhile(whlist);
         return(TRUE);
 }

 freewhile(wp)        /* free a list of while block pointers */

 WHBLOCK *wp;        /* head of structure to free */

 {
         if (wp == NULL)
                 return;
         if (wp->w_next)
                 freewhile(wp->w_next);
         free(wp);
 }

 execfile(f, n)        /* execute a series of commands in a file */

 int f, n;        /* default flag and numeric arg to pass on to file */

 {
         register int status;        /* return status of name query */
         char fname[NSTRING];        /* name of file to execute */
         char *fspec;                /* full file spec */

         if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRU
                 return(status);

 #if        1
         /* look up the path for the file */
         fspec = flook(fname, TRUE);

         /* if it isn't around */
         if (fspec == NULL)
                 return(FALSE);

 #endif
         /* otherwise, execute it */
         while (n-- > 0)
                 if ((status=dofile(fspec)) != TRUE)
                         return(status);

         return(TRUE);
 }

 /*        dofile:        yank a file into a buffer and execute it
                 if there are no errors, delete the buffer on exit */

 dofile(fname)

 char *fname;        /* file name to execute */

 {
         register BUFFER *bp;        /* buffer to place file to exeute */
         register BUFFER *cb;        /* temp to hold current buf while we read
         register int status;        /* results of various calls */
         char bname[NBUFN];        /* name of buffer */

         makename(bname, fname);                /* derive the name of the buff
         if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
                 return(FALSE);

         bp->b_mode = MDVIEW;        /* mark the buffer as read only */
         cb = curbp;                /* save the old buffer */
         curbp = bp;                /* make this one current */
         /* and try to read in the file to execute */
         if ((status = readin(fname, FALSE)) != TRUE) {
                 curbp = cb;        /* restore the current buffer */
                 return(status);
         }

         /* go execute it! */
         curbp = cb;                /* restore the current buffer */
         if ((status = dobuf(bp)) != TRUE)
                 return(status);

         /* if not displayed, remove the now unneeded buffer and exit */
         if (bp->b_nwnd == 0)
                 zotbuf(bp);
         return(TRUE);
 }

 /*        cbuf:        Execute the contents of a numbered buffer        */

 cbuf(f, n, bufnum)

 int f, n;        /* default flag and numeric arg */
 int bufnum;        /* number of buffer to execute */

 {
         register BUFFER *bp;                /* ptr to buffer to execute */
         register int status;                /* status return */
         static char bufname[] = "[Macro xx]";

         /* make the buffer name */
         bufname[7] = '0' + (bufnum / 10);
         bufname[8] = '0' + (bufnum % 10);

         /* find the pointer to that buffer */
         if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
                 mlwrite("Macro not defined");
                 return(FALSE);
         }

         /* and now execute it as asked */
         while (n-- > 0)
                 if ((status = dobuf(bp)) != TRUE)
                         return(status);
         return(TRUE);
 }

 cbuf1(f, n)

 {
         cbuf(f, n, 1);
 }

 cbuf2(f, n)

 {
         cbuf(f, n, 2);
 }

 cbuf3(f, n)

 {
         cbuf(f, n, 3);
 }

 cbuf4(f, n)

 {
         cbuf(f, n, 4);
 }

 cbuf5(f, n)

 {
         cbuf(f, n, 5);
 }

 cbuf6(f, n)

 {
         cbuf(f, n, 6);
 }

 cbuf7(f, n)

 {
         cbuf(f, n, 7);
 }

 cbuf8(f, n)

 {
         cbuf(f, n, 8);
 }

 cbuf9(f, n)

 {
         cbuf(f, n, 9);
 }

 cbuf10(f, n)

 {
         cbuf(f, n, 10);
 }

 cbuf11(f, n)

 {
         cbuf(f, n, 11);
 }

 cbuf12(f, n)

 {
         cbuf(f, n, 12);
 }

 cbuf13(f, n)

 {
         cbuf(f, n, 13);
 }

 cbuf14(f, n)

 {
         cbuf(f, n, 14);
 }

 cbuf15(f, n)

 {
         cbuf(f, n, 15);
 }

 cbuf16(f, n)

 {
         cbuf(f, n, 16);
 }

 cbuf17(f, n)

 {
         cbuf(f, n, 17);
 }

 cbuf18(f, n)

 {
         cbuf(f, n, 18);
 }

 cbuf19(f, n)

 {
         cbuf(f, n, 19);
 }

 cbuf20(f, n)

 {
         cbuf(f, n, 20);
 }

 cbuf21(f, n)

 {
         cbuf(f, n, 21);
 }

 cbuf22(f, n)

 {
         cbuf(f, n, 22);
 }

 cbuf23(f, n)

 {
         cbuf(f, n, 23);
 }

 cbuf24(f, n)

 {
         cbuf(f, n, 24);
 }

 cbuf25(f, n)

 {
         cbuf(f, n, 25);
 }

 cbuf26(f, n)

 {
         cbuf(f, n, 26);
 }

 cbuf27(f, n)

 {
         cbuf(f, n, 27);
 }

 cbuf28(f, n)

 {
         cbuf(f, n, 28);
 }

 cbuf29(f, n)

 {
         cbuf(f, n, 29);
 }

 cbuf30(f, n)

 {
         cbuf(f, n, 30);
 }

 cbuf31(f, n)

 {
         cbuf(f, n, 31);
 }

 cbuf32(f, n)

 {
         cbuf(f, n, 32);
 }

 cbuf33(f, n)

 {
         cbuf(f, n, 33);
 }

 cbuf34(f, n)

 {
         cbuf(f, n, 34);
 }

 cbuf35(f, n)

 {
         cbuf(f, n, 35);
 }

 cbuf36(f, n)

 {
         cbuf(f, n, 36);
 }

 cbuf37(f, n)

 {
         cbuf(f, n, 37);
 }

 cbuf38(f, n)

 {
         cbuf(f, n, 38);
 }

 cbuf39(f, n)

 {
         cbuf(f, n, 39);
 }

 cbuf40(f, n)

 {
         cbuf(f, n, 40);
 }




 EXECF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\BISICC\EXECF.C

 /*                execf.c                execute another program and return s

 #include <stdio.h>

 struct {unsigned int ax,bx,cx,dx,si,di,ds,es;} r;
 unsigned char cline[128],*ep,*envfind();
 int status=-1;

 #define NUMINTS 30
 static char *internals[] = {"copy","ren","rename","del","erase","chdir","cd",
 "md","mkdir","dir","rd","rmdir","type","cls","ctty","date","time",\
 "path","prompt","set","ver","verify","vol","echo","rem","goto","if",\
 "shift","pause","for"};

 fork(cmdl)                                /* parses off name and cmdl for exe
 char *cmdl;
 {
         char *sp;
         char *name;
         char comlin[128];
         int er;

         sp = strcpy(name,cmdl);
         strcat(name," ");                                        /* pad for f
         while(*++sp != ' ');                                /* find 1st space
         *sp++ = '\0';                                                /* term
         strcpy(comlin,sp);                                /* get command line
         er= execf(name,comlin);
         return(er);
 }

 execf(name,cmdl)                /* executes name with command line cmdl */
 char *name;
 char *cmdl;
 {
         int i,er;
         char tp[255];
         char *ts;
         char *path;
         char *findexecf();
         char lcmdl[255];                /* local command line */

         lcmdl[0] = ' ';                        /* tack on a space at the begi
         strcpy(lcmdl+1,cmdl);        /* to keep DOS happy */
         name = lower(name);                /* convert to lowercase for search
         for (i=0;i<NUMINTS;i++) {
                 if (!strcmp(name,internals[i]))        /* check for an intern
                         return (system(strcat(name,lcmdl)));        /* use c8
         }
         /* it's not an internal command, process it */

         path = alloc(255);
         curdrv(path);                        /* get current drive */
         getpath(path);                /* and path */
         ep = envfind("PATH");
         if (*ep != ';') strcat(path,";");        /* if none at beginning alre
         strcat(path,ep);
         free(ep);
         while (*path) {
                 strcpy(tp,path);
                 i = 0;
                 while (*path++ != ';') i++;                /* find end of pat
                 tp[i] = '\0';
                 if (tp[i-2] != '\\' || tp[i-2] != '/') strcat(tp,"/");
                 if ((ts=findexecf(tp,name))) {
                         er = _execf(ts,lcmdl);
                         if (!er) {
                                 r.ax = 0x4d00;
                                 sysint21(&r,&r);
                                 er = r.ax&0xff;
                         }
                         return(er);
                 }
         }
         return(-1);
 }

 char *findexecf(path,name)                                /* tries to find an
 char *path,*name;
 {
         char tn[255];
         char *first,*next;
         static char *exet[] = {".COM",".EXE",".BAT"};
         int i;

         name = upper(name);
         strcpy(tn,path);
         strcat(tn,name);
         strcat(tn,".*");                        /* add wildcard to find all *
         first = filedir(tn,0);        /* look for all normal files */
         strcpy(tn,name);
         for (next=first;*next != '\0';) {
                 for (i=0;i<3;i++) {
                         if (!(strcmp(strcat(tn,exet[i]),next))) return(strcat
                         strcpy(tn,name);                /* nope, try again */
                 }
                 next += strlen(next)+1;                /* look at next name i
         }
         return(NULL);                                                /* didn'
 }

 _execf(path,cmdl)                                /* execs path(incl. name.ext
 char *path,*cmdl;
 {
         int er;
         struct {
                 int env_seg;
                 char *line_off,*line_seg;
                 char *fcb1_off,*fcb1_seg;
                 char *fcb2_off,*fcb2_seg;
         } ctrl;

         cline[0] = strlen(cmdl);                /* put in length */
         strcpy(cline+1,cmdl);                        /* copy in command line
         strcat(cline,"\r");                                /* add a CR */
         segread(&r.si);                                        /* get current
         ctrl.env_seg=0;                                        /* no environm
         ctrl.line_off=cline;                                /* offset of comm
         ctrl.line_seg=r.ds;                                /* segment of comm
         er = loadexec(path,r.ds,&ctrl,r.ds,0);        /* launch! */
         return(er);
 }

 /* curdrv - get current default drive */

 curdrv(sp)
 char *sp;
 {
         struct { int ax, bx, cx;
                  char *dx, *si, *di, *ds, *es;
                } r;

         r.ax = 0x1900;
         sysint(0x21, &r, &r);                                /* gets current
         *sp++ = r.ax + 'a';                                        /* convert
         *sp++ = ':';
         *sp++ = '\0';
         sp--;
         return;
 }

 /* getpath - get path to directory on indicated drive */

 getpath(sp)
 char *sp;
 {
         struct { int ax, bx, cx, dx;
                  char *si;
                  int di, ds, es;
                } r;
         extern int _showds();

         strcat(sp, "/");                                /* append root file s

         r.ax = 0x4700;                                        /* DOS interrup
         r.dx = *sp - '`';                                /* convert drive nam
         r.ds = _showds();
         r.si = sp + 3;                                        /* paste string
         sysint(0x21, &r, &r);
         return;
 }

 _showds()
 {
         struct{int cs, ss, ds, es;} r;

         segread(&r);
         return(r.ds);
 }


 EXP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\EXP.C

 /* 1.0  01-09-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  *        Programmmed using the algorithm given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 60-83.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define P0         0.249999999999999993e+0
 #define P1         0.694360001511792852e-2
 #define P2         0.165203300268279130e-4
 #define P(z)        ((P2*z+P1)*z+P0)

 #define Q0         0.5
 #define Q1         0.555538666969001188e-1
 #define Q2         0.495862884905441294e-3
 #define Q(z)         ((Q2*z+Q1)*z+Q0)

 C1        0.693359375                        /* = 355 / 512                */
 C2        2.121944400546905827697e-4        /* C1 - C2 = LOG2        */

 /*\p*********************************************************************/
         double
 exp(x)                                /* exponential function of x, e^x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double x2, xn, g, r, z;
         int n;

         if (x > LOGINFINITY)
         {        errno = ERANGE;
                 return INFINITY;
         }
         if (x < LOGLEAST)
         {        errno = ERANGE;
                 return 0.0;
         }
         if (ABS(x) < WASHOUT)
                 return 1.0;

         x2 = modf(x * LOG2e, &xn);
         if (x2 >= 0.5)
                 ++xn;
         else if (x2 <= -0.5)
                 --xn;
         n = xn;
         x2 = modf(x, &x);                /* in case no guard digit (p. 68) */
         g = ((x - xn * C1) + x2) + xn * C2;
         z = g * g;
         r = P(z) * g;
         r = 0.5 + r / (Q(z) - r);
         return ldexp(r, n + 1);
 }


 EXP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\EXP.C


 /***************************************************
  *        Exponential Routine                      *
  *                                                 *
  *        IBM PC "C" Language Board                *
  *        Tulsa, OK 1918-664-8737                  *
  *        SYSOP Lynn Long                          *
  ***************************************************/


 #include "math.h"
 #include "errno.h"

 #define P0 0.249999999999999993e+0
 #define P1 0.694360001511792852e-2
 #define P2 0.165203300268279130e-4
 #define Q0 0.500000000000000000e+0
 #define Q1 0.555538666969001188e-1
 #define Q2 0.495862884905441294e-3

 #define P(z) ((P2*z + P1)*z + P0)
 #define Q(z) ((Q2*z + Q1)*z + Q0)

 #define EPS     2.710505e-20

 double
 exp(x)
 double x;
 {
         int n;
         double xn, g, r, z;
         extern int errno;

         if (x > LOGHUGE) {
                 errno = ERANGE;
                 return HUGE;
         }
         if (x < LOGTINY) {
                 errno = ERANGE;
                 return 0.0;
         }
         if (fabs(x) < EPS)
                 return 1.0;
         n = z = x * 1.4426950408889634074;
         if (n < 0)
                 --n;
         if (z-n >= 0.5)
                 ++n;
         xn = n;
         g = ((x - xn*0.693359375)) + xn*2.1219444005469058277e-4;
         z = g*g;
         r = P(z)*g;
         r = 0.5 + r/(Q(z)-r);
         return ldexp(r,n+1);
 }



 EXPR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\EXPR.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 TYP             stdint = { bt_long, 0, 4, {0, 0}, 0, 0 };
 TYP             stdchar = {bt_char, 0, 1, {0, 0}, 0, 0 };
 TYP             stdstring = {bt_pointer, 1, 4, {0, 0}, &stdchar, 0};
 TYP             stdfunc = {bt_func, 1, 0, {0, 0}, &stdint, 0};
 extern TYP      *head;          /* shared with decl */

 /*
  *      expression evaluation
  *
  *      this set of routines builds a parse tree for an expression.
  *      no code is generated for the expressions during the build,
  *      this is the job of the codegen module. for most purposes
  *      expression() is the routine to call. it will allow all of
  *      the C operators. for the case where the comma operator is
  *      not valid (function parameters for instance) call exprnc().
  *
  *      each of the routines returns a pointer to a describing type
  *      structure. each routine also takes one parameter which is a
  *      pointer to an expression node by reference (address of pointer).
  *      the completed expression is returned in this pointer. all
  *      routines return either a pointer to a valid type or NULL if
  *      the hierarchy of the next operator is too low or the next
  *      symbol is not part of an expression.
  */

 TYP     *expression();  /* forward declaration */
 TYP     *exprnc();      /* forward declaration */
 TYP     *unary();       /* forward declaration */

 struct enode    *makenode(nt, v1, v2)
 /*
  *      build an expression node with a node type of nt and values
  *      v1 and v2.
  */
 int                             nt;
 char            *v1, *v2;
 {       struct enode    *ep;
         ep = xalloc(sizeof(struct enode));
         ep->nodetype = nt;
         ep->constflag = 0;
         ep->v.p[0] = v1;
         ep->v.p[1] = v2;
         return ep;
 }

 deref(node,tp)
 /*
  *      build the proper dereference operation for a node using the
  *      type pointer tp.
  */
 struct enode    **node;
 TYP             *tp;
 {       switch( tp->type ) {
                 case bt_char:
                         *node = makenode(en_b_ref,*node,0);
                         tp = &stdint;
                         break;
                 case bt_short:
                 case bt_enum:
                         *node = makenode(en_w_ref,*node,0);
                         tp = &stdint;
                         break;
                 case bt_long:
                 case bt_pointer:
                 case bt_unsigned:
                         *node = makenode(en_l_ref,*node,0);
                         break;
                 default:
                         error(ERR_DEREF);
                         break;
                 }
         return tp;
 }

 TYP     *nameref(node)
 /*
  *      nameref will build an expression tree that references an
  *      identifier. if the identifier is not in the global or
  *      local symbol table then a look-ahead to the next character
  *      is done and if it indicates a function call the identifier
  *      is coerced to an external function name. non-value references
  *      generate an additional level of indirection.
  */
 struct enode    **node;
 {       SYM             *sp;
         TYP             *tp;
         sp = gsearch(lastid);
         if( sp == 0 ) {
                 while( isspace(lastch) )
                         getch();
                 if( lastch == '(') {
                         ++global_flag;
                         sp = xalloc(sizeof(SYM));
                         sp->tp = &stdfunc;
                         sp->name = litlate(lastid);
                         sp->storage_class = sc_external;
                         insert(sp,&gsyms);
                         --global_flag;
                         tp = &stdfunc;
                         *node = makenode(en_nacon,sp->name,0);
                         (*node)->constflag = 1;
                         }
                 else    {
                         tp = 0;
                         error(ERR_UNDEFINED);
                         }
                 }
         else    {
                 if( (tp = sp->tp) == 0 ) {
                         error(ERR_UNDEFINED);
                         return 0;       /* guard against untyped entries */
                         }
                 switch( sp->storage_class ) {
                         case sc_static:
                                 *node = makenode(en_labcon,sp->value.i,0);
                                 (*node)->constflag = 1;
                                 break;
                         case sc_global:
                         case sc_external:
                                 *node = makenode(en_nacon,sp->name,0);
                                 (*node)->constflag = 1;
                                 break;
                         case sc_const:
                                 *node = makenode(en_icon,sp->value.i,0);
                                 (*node)->constflag = 1;
                                 break;
                         default:        /* auto and any errors */
                                 if( sp->storage_class != sc_auto)
                                         error(ERR_ILLCLASS);
                                 *node = makenode(en_autocon,sp->value.i,0);
                                 break;
                         }
                 if( tp->val_flag == 0)
                         tp = deref(node,tp);
                 }
         getsym();
         return tp;
 }

 struct enode    *parmlist()
 /*
  *      parmlist will build a list of parameter expressions in
  *      a function call and return a pointer to the last expression
  *      parsed. since parameters are generally pushed from right
  *      to left we get just what we asked for...
  */
 {       struct enode    *ep1, *ep2;
         ep1 = 0;
         while( lastst != closepa) {
                 exprnc( &ep2);          /* evaluate a parameter */
                 ep1 = makenode(en_void,ep2,ep1);
                 if( lastst != comma)
                         break;
                 getsym();
                 }
         return ep1;
 }

 int     castbegin(st)
 /*
  *      return 1 if st in set of [ kw_char, kw_short, kw_long, kw_int,
  *      kw_float, kw_double, kw_struct, kw_union ]
  */
 int     st;
 {       return  st == kw_char || st == kw_short || st == kw_int ||
                 st == kw_long || st == kw_float || st == kw_double ||
                 st == kw_struct || st == kw_union || st== kw_unsigned;
 }

 TYP     *primary(node)
 /*
  *      primary will parse a primary expression and set the node pointer
  *      returning the type of the expression parsed. primary expressions
  *      are any of:
  *                      id
  *                      constant
  *                      string
  *                      ( expression )
  *                      primary[ expression ]
  *                      primary.id
  *                      primary->id
  *                      primary( parameter list )
  */
 struct enode    **node;
 {       struct enode    *pnode, *qnode, *rnode;
         SYM             *sp;
         TYP             *tptr;
         switch( lastst ) {

                 case id:
                         tptr = nameref(&pnode);
                         break;
                 case iconst:
                         tptr = &stdint;
                         pnode = makenode(en_icon,ival,0);
                         pnode->constflag = 1;
                         getsym();
                         break;
                 case sconst:
                         tptr = &stdstring;
                         pnode = makenode(en_labcon,stringlit(laststr),0);
                         pnode->constflag = 1;
                         getsym();
                         break;
                 case openpa:
                         getsym();
                         if( !castbegin(lastst) ) {
                                 tptr = expression(&pnode);
                                 needpunc(closepa);
                                 }
                         else    {       /* cast operator */
                                 decl(); /* do cast declaration */
                                 decl1();
                                 tptr = head;
                                 needpunc(closepa);
                                 if( unary(&pnode) == 0 ) {
                                         error(ERR_IDEXPECT);
                                         tptr = 0;
                                         }
                                 }
                         break;
                 default:
                         return 0;
                 }
         for(;;) {
                 switch( lastst ) {
                         case openbr:    /* build a subscript reference */
                                 if( tptr->type != bt_pointer )
                                         error(ERR_NOPOINTER);
                                 else
                                         tptr = tptr->btp;
                                 getsym();
                                 qnode = makenode(en_icon,tptr->size,0);
                                 qnode->constflag = 1;
                                 expression(&rnode);
 /*
  *      we could check the type of the expression here...
  */
                                 qnode = makenode(en_mul,qnode,rnode);
                                 qnode->constflag = rnode->constflag &&
                                         qnode->v.p[0]->constflag;
                                 pnode = makenode(en_add,qnode,pnode);
                                 pnode->constflag = qnode->constflag &&
                                         pnode->v.p[1]->constflag;
                                 if( tptr->val_flag == 0 )
                                         tptr = deref(&pnode,tptr);
                                 needpunc(closebr);
                                 break;
                         case pointsto:
                                 if( tptr->type != bt_pointer )
                                         error(ERR_NOPOINTER);
                                 else
                                         tptr = tptr->btp;
                                 if( tptr->val_flag == 0 )
                                         pnode = makenode(en_l_ref,pnode,0);
 /*
  *      fall through to dot operation
  */
                         case dot:
                                 getsym();       /* past -> or . */
                                 if( lastst != id )
                                         error(ERR_IDEXPECT);
                                 else    {
                                         sp = search(lastid,tptr->lst.head);
                                         if( sp == 0 )
                                                 error(ERR_NOMEMBER);
                                         else    {
                                                 tptr = sp->tp;
                                                 qnode = makenode(en_icon,sp->
                                                 qnode->constflag = 1;
                                                 pnode = makenode(en_add,pnode
                                                 pnode->constflag = pnode->v.p
                                                 if( tptr->val_flag == 0 )
                                                     tptr = deref(&pnode,tptr)
                                                 }
                                         getsym();       /* past id */
                                         }
                                 break;
                         case openpa:    /* function reference */
                                 getsym();
                                 if( tptr->type != bt_func &&
                                         tptr->type != bt_ifunc )
                                         error(ERR_NOFUNC);
                                 else
                                         tptr = tptr->btp;
                                 pnode = makenode(en_fcall,pnode,parmlist());
                                 needpunc(closepa);
                                 break;
                         default:
                                 goto fini;
                         }
                 }
 fini:   *node = pnode;
         return tptr;
 }

 int     lvalue(node)
 /*
  *      this function returns true if the node passed is an lvalue.
  *      this can be qualified by the fact that an lvalue must have
  *      one of the dereference operators as it's top node.
  */
 struct enode    *node;
 {       switch( node->nodetype ) {
                 case en_b_ref:
                 case en_w_ref:
                 case en_l_ref:
                 case en_ub_ref:
                 case en_uw_ref:
                 case en_ul_ref:
                         return 1;
                 case en_cbl:
                 case en_cwl:
                 case en_cbw:
                         return lvalue(node->v.p[0]);
                 }
         return 0;
 }

 TYP     *unary(node)
 /*
  *      unary evaluates unary expressions and returns the type of the
  *      expression evaluated. unary expressions are any of:
  *
  *                      primary
  *                      primary++
  *                      primary--
  *                      !unary
  *                      ~unary
  *                      ++unary
  *                      --unary
  *                      -unary
  *                      *unary
  *                      &unary
  *                      (typecast)unary
  *                      sizeof(typecast)
  *
  */
 struct enode    **node;
 {       TYP             *tp, *tp1;
         struct enode    *ep1, *ep2;
         int             flag, i;
         flag = 0;
         switch( lastst ) {
                 case autodec:
                         flag = 1;
                 /* fall through to common increment */
                 case autoinc:
                         getsym();
                         tp = unary(&ep1);
                         if( tp == 0 ) {
                                 error(ERR_IDEXPECT);
                                 return 0;
                                 }
                         if( lvalue(ep1)) {
                                 if( tp->type == bt_pointer )
                                         ep2 = makenode(en_icon,tp->btp->size,
                                 else
                                         ep2 = makenode(en_icon,1,0);
                                 ep2->constflag = 1;
                                 ep1 = makenode(flag ? en_assub : en_asadd,ep1
                                 }
                         else
                                 error(ERR_LVALUE);
                         break;
                 case minus:
                         getsym();
                         tp = unary(&ep1);
                         if( tp == 0 ) {
                                 error(ERR_IDEXPECT);
                                 return 0;
                                 }
                         ep1 = makenode(en_uminus,ep1,0);
                         ep1->constflag = ep1->v.p[0]->constflag;
                         break;
                 case not:
                         getsym();
                         tp = unary(&ep1);
                         if( tp == 0 ) {
                                 error(ERR_IDEXPECT);
                                 return 0;
                                 }
                         ep1 = makenode(en_not,ep1,0);
                         ep1->constflag = ep1->v.p[0]->constflag;
                         break;
                 case compl:
                         getsym();
                         tp = unary(&ep1);
                         if( tp == 0 ) {
                                 error(ERR_IDEXPECT);
                                 return 0;
                                 }
                         ep1 = makenode(en_compl,ep1,0);
                         ep1->constflag = ep1->v.p[0]->constflag;
                         break;
                 case star:
                         getsym();
                         tp = unary(&ep1);
                         if( tp == 0 ) {
                                 error(ERR_IDEXPECT);
                                 return 0;
                                 }
                         if( tp->btp == 0 )
                                 error(ERR_DEREF);
                         else
                                 tp = tp->btp;
                         if( tp->val_flag == 0 )
                                 tp = deref(&ep1,tp);
                         break;
                 case and:
                         getsym();
                         tp = unary(&ep1);
                         if( tp == 0 ) {
                                 error(ERR_IDEXPECT);
                                 return 0;
                                 }
                         if( lvalue(ep1))
                                 ep1 = ep1->v.p[0];
                         tp1 = xalloc(sizeof(TYP));
                         tp1->size = 4;
                         tp1->type = bt_pointer;
                         tp1->btp = tp;
                         tp1->val_flag = 0;
                         tp1->lst.head = 0;
                         tp1->sname = 0;
                         tp = tp1;
                         break;
                 case kw_sizeof:
                         getsym();
                         needpunc(openpa);
                         decl();
                         decl1();
                         if( head != 0 )
                                 ep1 = makenode(en_icon,head->size,0);
                         else    {
                                 error(ERR_IDEXPECT);
                                 ep1 = makenode(en_icon,1,0);
                                 }
                         ep1->constflag = 1;
                         tp = &stdint;
                         needpunc(closepa);
                         break;
                 default:
                         tp = primary(&ep1);
                         if( tp != 0 ) {
                                 if( tp->type == bt_pointer )
                                         i = tp->btp->size;
                                 else
                                         i = 1;
                                 if( lastst == autoinc) {
                                         if( lvalue(ep1) )
                                                 ep1 = makenode(en_ainc,ep1,i)
                                         else
                                                 error(ERR_LVALUE);
                                         getsym();
                                         }
                                 else if( lastst == autodec ) {
                                         if( lvalue(ep1) )
                                                 ep1 = makenode(en_adec,ep1,i)
                                         else
                                                 error(ERR_LVALUE);
                                         getsym();
                                         }
                                 }
                         break;
                 }
         *node = ep1;
         return tp;
 }

 TYP     *forcefit(node1,tp1,node2,tp2)
 /*
  *      forcefit will coerce the nodes passed into compatable
  *      types and return the type of the resulting expression.
  */
 struct enode    **node1, **node2;
 TYP             *tp1, *tp2;
 {       switch( tp1->type ) {
                 case bt_char:
                 case bt_short:
                 case bt_long:
                         if( tp2->type == bt_long ||
                                 tp2->type == bt_short ||
                                 tp2->type == bt_char)
                                 return &stdint;
                         else if( tp2->type == bt_pointer ||
                                 tp2->type == bt_unsigned )
                                 return tp2;
                         break;
                 case bt_pointer:
                         if( isscalar(tp2) || tp2->type == bt_pointer)
                                 return tp1;
                         break;
                 case bt_unsigned:
                         if( tp2->type == bt_pointer )
                                 return tp2;
                         else if( isscalar(tp2) )
                                 return tp1;
                         break;
                 }
         error( ERR_MISMATCH );
         return tp1;
 }

 int     isscalar(tp)
 /*
  *      this function returns true when the type of the argument is
  *      one of char, short, unsigned, or long.
  */
 TYP             *tp;
 {       return  tp->type == bt_char ||
                 tp->type == bt_short ||
                 tp->type == bt_long ||
                 tp->type == bt_unsigned;
 }

 TYP     *multops(node)
 /*
  *      multops parses the multiply priority operators. the syntax of
  *      this group is:
  *
  *              unary
  *              multop * unary
  *              multop / unary
  *              multop % unary
  */
 struct enode    **node;
 {       struct enode    *ep1, *ep2;
         TYP             *tp1, *tp2;
         int                      oper;
         tp1 = unary(&ep1);
         if( tp1 == 0 )
                 return 0;
         while( lastst == star || lastst == divide || lastst == modop ) {
                 oper = lastst;
                 getsym();       /* move on to next unary op */
                 tp2 = unary(&ep2);
                 if( tp2 == 0 ) {
                         error(ERR_IDEXPECT);
                         *node = ep1;
                         return tp1;
                         }
                 tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                 switch( oper ) {
                         case star:
                                 if( tp1->type == bt_unsigned )
                                         ep1 = makenode(en_umul,ep1,ep2);
                                 else
                                         ep1 = makenode(en_mul,ep1,ep2);
                                 break;
                         case divide:
                                 if( tp1->type == bt_unsigned )
                                         ep1 = makenode(en_udiv,ep1,ep2);
                                 else
                                         ep1 = makenode(en_div,ep1,ep2);
                                 break;
                         case modop:
                                 if( tp1->type == bt_unsigned )
                                         ep1 = makenode(en_umod,ep1,ep2);
                                 else
                                         ep1 = makenode(en_mod,ep1,ep2);
                                 break;
                         }
                 ep1->constflag = ep1->v.p[0]->constflag &&
                         ep1->v.p[1]->constflag;
                 }
         *node = ep1;
         return tp1;
 }

 TYP     *addops(node)
 /*
  *      addops handles the addition and subtraction operators.
  */
 struct enode    **node;
 {       struct enode    *ep1, *ep2, *ep3;
         TYP             *tp1, *tp2;
         int             oper, i;
         tp1 = multops(&ep1);
         if( tp1 == 0 )
                 return 0;
         while( lastst == plus || lastst == minus ) {
                 oper = (lastst == plus);
                 getsym();
                 tp2 = multops(&ep2);
                 if( tp2 == 0 ) {
                         error(ERR_IDEXPECT);
                         *node = ep1;
                         return tp1;
                         }
                 if( tp1->type == bt_pointer ) {
                         tp2 = forcefit(0,&stdint,&ep2,tp2);
                         ep3 = makenode(en_icon,tp1->btp->size,0);
                         ep3->constflag = 1;
                         ep2 = makenode(en_mul,ep3,ep2);
                         ep2->constflag = ep2->v.p[1]->constflag;
                         }
                 else if( tp2->type == bt_pointer ) {
                         tp1 = forcefit(0,&stdint,&ep1,tp1);
                         ep3 = makenode(en_icon,tp2->btp->size,0);
                         ep3->constflag = 1;
                         ep1 = makenode(en_mul,ep3,ep1);
                         ep1->constflag = ep1->v.p[1]->constflag;
                         }
                 tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                 ep1 = makenode( oper ? en_add : en_sub,ep1,ep2);
                 ep1->constflag = ep1->v.p[0]->constflag &&
                         ep1->v.p[1]->constflag;
                 }
         *node = ep1;
         return tp1;
 }

 TYP     *shiftop(node)
 /*
  *      shiftop handles the shift operators << and >>.
  */
 struct enode    **node;
 {       struct enode    *ep1, *ep2;
         TYP             *tp1, *tp2;
         int             oper;
         tp1 = addops(&ep1);
         if( tp1 == 0)
                 return 0;
         while( lastst == lshift || lastst == rshift) {
                 oper = (lastst == lshift);
                 getsym();
                 tp2 = addops(&ep2);
                 if( tp2 == 0 )
                         error(ERR_IDEXPECT);
                 else    {
                         tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                         ep1 = makenode(oper ? en_lsh : en_rsh,ep1,ep2);
                         ep1->constflag = ep1->v.p[0]->constflag &&
                                 ep1->v.p[1]->constflag;
                         }
                 }
         *node = ep1;
         return tp1;
 }

 TYP     *relation(node)
 /*
  *      relation handles the relational operators < <= > and >=.
  */
 struct enode    **node;
 {       struct enode    *ep1, *ep2;
         TYP             *tp1, *tp2;
         int             nt;
         tp1 = shiftop(&ep1);
         if( tp1 == 0 )
                 return 0;
         for(;;) {
                 switch( lastst ) {

                         case lt:
                                 if( tp1->type == bt_unsigned )
                                         nt = en_ult;
                                 else
                                         nt = en_lt;
                                 break;
                         case gt:
                                 if( tp1->type == bt_unsigned )
                                         nt = en_ugt;
                                 else
                                         nt = en_gt;
                                 break;
                         case leq:
                                 if( tp1->type == bt_unsigned )
                                         nt = en_ule;
                                 else
                                         nt = en_le;
                                 break;
                         case geq:
                                 if( tp1->type == bt_unsigned )
                                         nt = en_uge;
                                 else
                                         nt = en_ge;
                                 break;
                         default:
                                 goto fini;
                         }
                 getsym();
                 tp2 = shiftop(&ep2);
                 if( tp2 == 0 )
                         error(ERR_IDEXPECT);
                 else    {
                         tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                         ep1 = makenode(nt,ep1,ep2);
                         ep1->constflag = ep1->v.p[0]->constflag &&
                                 ep1->v.p[1]->constflag;
                         }
                 }
 fini:   *node = ep1;
         return tp1;
 }

 TYP     *equalops(node)
 /*
  *      equalops handles the equality and inequality operators.
  */
 struct enode    **node;
 {       struct enode    *ep1, *ep2;
         TYP             *tp1, *tp2;
         int             oper;
         tp1 = relation(&ep1);
         if( tp1 == 0 )
                 return 0;
         while( lastst == eq || lastst == neq ) {
                 oper = (lastst == eq);
                 getsym();
                 tp2 = relation(&ep2);
                 if( tp2 == 0 )
                         error(ERR_IDEXPECT);
                 else    {
                         tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                         ep1 = makenode( oper ? en_eq : en_ne,ep1,ep2);
                         ep1->constflag = ep1->v.p[0]->constflag &&
                                 ep1->v.p[1]->constflag;
                         }
                 }
         *node = ep1;
         return tp1;
 }

 TYP     *binop(node,xfunc,nt,sy)
 /*
  *      binop is a common routine to handle all of the legwork and
  *      error checking for bitand, bitor, bitxor, andop, and orop.
  */
 struct enode    **node;
 TYP             *(*xfunc)();
 int             nt, sy;
 {       struct enode    *ep1, *ep2;
         TYP             *tp1, *tp2;
         tp1 = (*xfunc)(&ep1);
         if( tp1 == 0 )
                 return 0;
         while( lastst == sy ) {
                 getsym();
                 tp2 = (*xfunc)(&ep2);
                 if( tp2 == 0 )
                         error(ERR_IDEXPECT);
                 else    {
                         tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                         ep1 = makenode(nt,ep1,ep2);
                         ep1->constflag = ep1->v.p[0]->constflag &&
                                 ep1->v.p[1]->constflag;
                         }
                 }
         *node = ep1;
         return tp1;
 }

 TYP     *bitand(node)
 /*
  *      the bitwise and operator...
  */
 struct enode    **node;
 {       return binop(node,equalops,en_and,and);
 }

 TYP     *bitxor(node)
 struct enode    **node;
 {       return binop(node,bitand,en_xor,uparrow);
 }

 TYP     *bitor(node)
 struct enode    **node;
 {       return binop(node,bitxor,en_or,or);
 }

 TYP     *andop(node)
 struct enode    **node;
 {       return binop(node,bitor,en_land,land);
 }

 TYP     *orop(node)
 struct enode    **node;
 {       return binop(node,andop,en_lor,lor);
 }

 TYP     *conditional(node)
 /*
  *      this routine processes the hook operator.
  */
 struct enode    **node;
 {       TYP             *tp1, *tp2, *tp3;
         struct enode    *ep1, *ep2, *ep3;
         tp1 = orop(&ep1);       /* get condition */
         if( tp1 == 0 )
                 return 0;
         if( lastst == hook ) {
                 getsym();
                 if( (tp2 = conditional(&ep2)) == 0) {
                         error(ERR_IDEXPECT);
                         goto cexit;
                         }
                 needpunc(colon);
                 if( (tp3 = conditional(&ep3)) == 0) {
                         error(ERR_IDEXPECT);
                         goto cexit;
                         }
                 tp1 = forcefit(&ep2,tp2,&ep3,tp3);
                 ep2 = makenode(en_void,ep2,ep3);
                 ep1 = makenode(en_cond,ep1,ep2);
                 }
 cexit:  *node = ep1;
         return tp1;
 }

 TYP     *asnop(node)
 /*
  *      asnop handles the assignment operators. currently only the
  *      simple assignment is implemented.
  */
 struct enode    **node;
 {       struct enode    *ep1, *ep2, *ep3;
         TYP             *tp1, *tp2;
         int             op;
         tp1 = conditional(&ep1);
         if( tp1 == 0 )
                 return 0;
         for(;;) {
                 switch( lastst ) {
                         case assign:
                                 op = en_assign;
 ascomm:                         getsym();
                                 tp2 = asnop(&ep2);
 ascomm2:                        if( tp2 == 0 || !lvalue(ep1) )
                                         error(ERR_LVALUE);
                                 else    {
                                         tp1 = forcefit(&ep1,tp1,&ep2,tp2);
                                         ep1 = makenode(op,ep1,ep2);
                                         }
                                 break;
                         case asplus:
                                 op = en_asadd;
 ascomm3:                        tp2 = asnop(&ep2);
                                 if( tp1->type == bt_pointer ) {
                                         ep3 = makenode(en_icon,tp1->btp->size
                                         ep2 = makenode(en_mul,ep2,ep3);
                                         }
                                 goto ascomm;
                         case asminus:
                                 op = en_assub;
                                 goto ascomm3;
                         case astimes:
                                 op = en_asmul;
                                 goto ascomm;
                         case asdivide:
                                 op = en_asdiv;
                                 goto ascomm;
                         case asmodop:
                                 op = en_asmod;
                                 goto ascomm;
                         case aslshift:
                                 op = en_aslsh;
                                 goto ascomm;
                         case asrshift:
                                 op = en_asrsh;
                                 goto ascomm;
                         case asand:
                                 op = en_asand;
                                 goto ascomm;
                         case asor:
                                 op = en_asor;
                                 goto ascomm;
                         default:
                                 goto asexit;
                         }
                 }
 asexit: *node = ep1;
         return tp1;
 }

 TYP     *exprnc(node)
 /*
  *      evaluate an expression where the comma operator is not legal.
  */
 struct enode    **node;
 {       TYP     *tp;
         tp = asnop(node);
         if( tp == 0 )
                 *node = 0;
         return tp;
 }

 TYP     *commaop(node)
 /*
  *      evaluate the comma operator. comma operators are kept as
  *      void nodes.
  */
 struct enode    **node;
 {       TYP             *tp1;
         struct enode    *ep1, *ep2;
         tp1 = asnop(&ep1);
         if( tp1 == 0 )
                 return 0;
         if( lastst == comma ) {
                 tp1 = commaop(&ep2);
                 if( tp1 == 0 ) {
                         error(ERR_IDEXPECT);
                         goto coexit;
                         }
                 ep1 = makenode(en_void,ep1,ep2);
                 }
 coexit: *node = ep1;
         return tp1;
 }

 TYP     *expression(node)
 /*
  *      evaluate an expression where all operators are legal.
  */
 struct enode    **node;
 {       TYP     *tp;
         tp = commaop(node);
         if( tp == 0 )
                 *node = 0;
         return tp;
 }



 FABS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FABS.C


 #define FABS_INIT "12345678901234567890123456789012345678901234567890"

 /*            F A B S    K E Y   L E N G T H
               ==============================

     Format is M\<file #>

     This function will get the length of the FABS key.
     The following parameters are required :

     1. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_key_len( file_num )
 unsigned file_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "M", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /*  printf("FABS key len string is %s\n", cmd ) ;   */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Length", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_key_len */

 call_fabs( command )
 char *command ;
 { int rec_num, key_adr, err=0 ;
   extern int rec_fabs, key_fabs, err_fabs ;
   char *cmnd ;

   cmnd = "????" ;    /* initialize command pointer */
   rec_num = 0 ;      /* initialize record and address */
   key_adr = 0 ;
 /*  printf("FABS string is %s\n",command ) ; */
   callfb( command, strlen( command ), cmnd, &err, &rec_num, &key_adr ) ;
   rec_fabs = rec_num ;
   key_fabs = key_adr ;
   return( err_fabs = err ) ;
 }

 /*    Check error code for not found. If not found return with a
       1 to indicate not found error. Otherwise print message and
       end program.
 */
 fabs_error( txt, cmd, err )
 char *txt, *cmd ;
 int err ;
 {
    if ( ( err > 11 ) & ( err < 17 ) )
      return ;

    switch ( err )
      { case 23 :
        case 24 :
        case 25 :
        case 27 : printf( "\n\t\tFABS %s:Disk error is %d\n", txt, err );
                  printf( "\t\tFABS String was %s\n", cmd ) ;
                  cputs( "\t\tPress any key to continue: " ) ;
                  if ( !getch() ) getch() ;       /* get any key */
                  return ;
      }

    printf( "\n\t\tFABS %s:Fatal error is %d\n", txt, err ) ;
    printf( "\t\tFABS String was %s\n", cmd ) ;
    exit( 1 ) ;
 }


 add_num( num, adr, cmd, last )
 unsigned num  ;
 int      adr  ;
 char    *cmd  ;
 int      last ;
 { char wrk_stg[ 5 ] ;

   stcu_d( wrk_stg, num, sizeof( wrk_stg) ) ;
   return( fill_fabs( cmd, wrk_stg, adr, last ) ) ;
 }

 fill_fabs( to, from, start, end )
 char *to, *from ;
 int  start,end ;
 { int k = 0 ;
   while ( to[ start++ ] = from [ k++ ] ) ;

   if ( end )
     to[ start-1 ] = '\0' ;     /* EOS */
   else
     to[ start-1 ] = '\\' ;     /* '\' */

   return( start ) ;
 }    /* end of fill_fabs */

 fabs_get_key( file_num, key )
 unsigned file_num ;
 char *key ;
 { int key_adr ;
   extern int key_fabs ;

   key_adr = key_fabs ;            /* save key address */
   fabs_key_len( file_num ) ;      /* get key length */
 /*  printf("Key address is %d\n", key_adr );
     printf("Key length is %d\n", rec_fabs );
 */
   callky( key, rec_fabs, key_adr ) ;

 }
 /*              F A B S    C R E A T E
                 ======================

     Format is C\<file name>\<max key len>\<#keys>\<key type>\<file#>

     This function will create a file under fabs. The following
     parameters are required :

     1. The file name as [d:]<filename>[.ext].
     2. The key length > 0 and < 101.
     3. The number of primary keys for this file.
     4. The key type ( I for integer or A for ASCII ).
     5. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_create( fname, key_length, num_keys, key_type, file_num )
 char fname[];
 unsigned key_length ;
 unsigned num_keys ;
 char key_type ;
 unsigned file_num ;
 { int err, adr ;
   char wrk_stg[ 5 ] ;
   char cmnd[ 4 ] ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "C", adr, 0 ) ;
   adr = fill_fabs( cmd, fname, adr, 0 ) ;
   adr = add_num( key_length, adr, cmd, 0 ) ;
   adr = add_num( num_keys, adr, cmd, 0 ) ;
   wrk_stg[ 0 ] = key_type ;
   wrk_stg[ 1 ] = '\0' ;
   adr = fill_fabs( cmd, wrk_stg,adr,0) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /* printf("FABS create string is %s\n", cmd ) ; */

    if ( err = call_fabs( cmd ) )
     return( fabs_error( "Create", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_create */
 /*              F A B S    O P E N
                 ==================

     Format is O\<file name>\<file #>

     This function will open a FABS file. The following
     parameters are required :

     1. The file name as [d:]<filename>[.ext].
     2. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_open( fname, file_num )
 char fname[];
 unsigned file_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "O", adr, 0 ) ;
   adr = fill_fabs( cmd, fname, adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /* printf("FABS open string is %s\n",*cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Open", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_open */
 /*                 F A B S    C L O S E
                    ====================

     Format is K\<file #>

     This function will close an open FABS file. The following
     parameters are required :

     1. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_close( file_num )
 unsigned file_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "K", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /*  printf("FABS close string is %s\n", cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Close", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_close */
 /*                  F A B S    I N S E R T
                     ======================

     Format is I\<file number>\<key1>\..\<keyn>

     This function will insert a record into a FABS file. The following
     parameters are required :

     1. The file number > 0 and < 7.
     2. The keys seperated by '\'.

     The program aborts if a FABS error occures.

 */
 fabs_insert( keys, file_num )
 unsigned file_num ;
 char keys[];
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "I", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 0 ) ;
   adr = fill_fabs( cmd, keys, adr, 1 ) ;

 /* printf("FABS insert string is %s\n",cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return ( fabs_error( "Insert", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_insert */
 /*              F A B S    F I R S T
                 ====================

     Format is F\<key #>\<file #>

     This function will find the first record in a FABS file.
     The following parameters are required :

     1. The file number > 0 and < 7.
     2. The key number.

     The program aborts if a FABS error occures.

 */
 fabs_first( file_num, key_num )
 unsigned file_num, key_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "F", adr, 0 ) ;
   adr = add_num( key_num, adr, cmd, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /*  printf("FABS first string is %s\n", cmd ) ;   */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "First", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_first */
 /*              F A B S    L A S T
                 ==================

     Format is L\<key #>\<file #>

     This function will find the last record in a FABS file.
     The following parameters are required :

     1. The file number > 0 and < 7.
     2. The key number.

     The program aborts if a FABS error occures.

 */
 fabs_last( file_num, key_num )
 unsigned file_num, key_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "L", adr, 0 ) ;
   adr = add_num( key_num, adr, cmd, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /* printf("FABS last string is %s\n", cmd ) ; */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Last", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_last */
 /*                 F A B S    N E X T
                    ==================

     Format is N\<file #>

     This function will find the next key in a FABS file. The following
     parameters are required :

     1. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_next( file_num )
 unsigned file_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "N", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /*  printf("FABS next string is %s\n", cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Next", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_next */
 /*                 F A B S    P R E V I O U S
                    ==========================

     Format is P\<file #>

     This function will find the previous key in a FABS file.
     The following parameters are required :

     1. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_previous( file_num )
 unsigned file_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "P", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /* printf("FABS previous string is %s\n", cmd ) ;   */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Previous", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_previous */
 /*                 F A B S    S E A R C H
                    ======================

     Format is G\<key #>\<file #>\<key>

     This function will search a FABS file for a key. The following
     parameters are required :

     1. The key number .
     2. The file number > 0 and < 7.
     3. The value of the key.

     The program aborts if a FABS error occures.

 */
 fabs_search( key_num, file_num, key )
 unsigned key_num, file_num ;
 char *key ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "S", adr, 0 ) ;
   adr = add_num( key_num, adr, cmd, 0 ) ;
   adr = add_num( file_num, adr, cmd, 0 ) ;
   adr = fill_fabs( cmd, key, adr, 1 ) ;

 /* printf("FABS search string is %s\n",cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Specific", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_search */
 /*            F A B S    G E N E R I C    S E A R C H
               =======================================

     Format is G\<key #>\<file #>\<key>

     This function will search a FABS file for the first record equal to
     greater than key. The following parameters are required :

     1. The key number .
     2. The file number > 0 and < 7.
     3. The value of the key.

     The program aborts if a FABS error occures.

 */
 fabs_generic( key_num, file_num, key )
 unsigned key_num, file_num ;
 char *key ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "G", adr, 0 ) ;
   adr = add_num( key_num, adr, cmd, 0 ) ;
   adr = add_num( file_num, adr, cmd, 0 ) ;
   adr = fill_fabs( cmd, key, adr, 1 ) ;

 /* printf("FABS generic string is %s\n", cmd ) ;   */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Generic", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_generic */
 /*                  F A B S    B U I L D   K E Y
                     ============================

     Format is B\<file number>\<key1>\..\<keyn>

     This function will insert a record into a FABS file without
     updating the map file. A write map FABS call must be executed
     after a series of build calls. The following parameters are
     required :

     1. The file number > 0 and < 7.
     2. The keys seperated by '\'.

     The program aborts if a FABS error occures.

 */
 fabs_build( keys, file_num )
 unsigned file_num ;
 char keys[];
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   ad( keys, file_num )
 unsigned file_num ;
 char keys[];
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "B", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 0 ) ;
   adr = fill_fabs( cmd, keys, adr, 1 ) ;

 /* printf("FABS insert string is %s\n",cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return ( fabs_error( "Build", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_build */
 /*                   F A B S    M A P
                      ================

     Format is W\<file #>

     This function will write the map file. This function must be
     executed after a series of build commands. The following
     parameters are required :

     1. The file number > 0 and < 7.

     The program aborts if a FABS error occures.

 */
 fabs_map( file_num )
 unsigned file_num ;
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "W", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 1 ) ;

 /*  printf("FABS write string is %s\n", cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return( fabs_error( "Write", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_map */
 /*                  F A B S    D E L E T E
                     ======================

     Format is D\<record number>\<SBDF>\<file number>\<key1>\..\<keyn>

     This function will delete a record from a FABS file. The following
     parameters are required :

     1. The file record number.
     1. The search before delete flag.
     1. The file number > 0 and < 7.
     2. The keys seperated by '\'.

     The program aborts if a FABS error occures.

 */
 fabs_delete( rec_num, SBDF, keys, file_num )
 unsigned file_num ;
 unsigned rec_num ;
 char SBDF;
 char keys[];
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "D", adr, 0 ) ;
   adr = add_num( rec_num, adr, cmd, 0 ) ;
   if ( SBDF == 'N' )
     adr = fill_fabs( cmd, "N", adr, 0 ) ;
   else
     adr = fill_fabs( cmd, "Y", adr, 0 ) ;
   adr = add_num( file_num, adr, cmd, 0 ) ;
   adr = fill_fabs( cmd, keys, adr, 1 ) ;

 /* printf("FABS delete string is %s\n",cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return ( fabs_error( "Delete", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_delete */
 /*                  F A B S    R E P L A C E
                     ========================

     Format is R\<key num>\<rec num>\<file num>\<old key>\<new key>

     This function will replace a single key with another key using the
     same record number and primary key number.The following
     parameters are required :

     1. The key number.
     2. The record number to replace.
     3. The file number > 0 and < 7.
     4. The old key.
     5. The new key.

     The program aborts if a FABS error occures.

 */
 fabs_replace( key_num, rec_num,file_num, old_key, new_key )
 unsigned key_num, rec_num, file_num ;
 char old_key[], new_key[];
 { int adr, err ;
   char *cmd ;

   cmd = FABS_INIT ;
   adr = 0 ;
   adr = fill_fabs( cmd, "R", adr, 0 ) ;
   adr = add_num( key_num, adr, cmd, 0 ) ;
   adr = add_num( rec_num, adr, cmd, 0 ) ;
   adr = add_num( file_num, adr, cmd, 0 ) ;
   adr = fill_fabs( cmd, old_key, adr, 0 ) ;
   adr = fill_fabs( cmd, new_key, adr, 1 ) ;

 /* printf("FABS replace string is %s\n",cmd ) ;  */

   if ( err = call_fabs( cmd ) )
     return ( fabs_error( "Replace", cmd, err ) ) ;

   return( err ) ;

 }  /* end of fabs_replace */


 FABS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FABS.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         double
 fabs(x)                /* return double absolute value of double x

 /*----------------------------------------------------------------------*/
 double x;
 {
         return ABS(x);
 }


 FAHR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FAHR.C


 main()
 {
         int fahr;

         for (fahr = 0 ; fahr <= 300 ; fahr = fahr + 20)
                 printf("%4d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
 }



 FASTWR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\TCLIB\FASTWR.C

 /*;fastwrite.c         -        a modification of FastWrite.PAS
   ;                                 to run under Microsoft C using the MASM A
   ;                                 Writes directly to the screen buffer
   ;
   ;                                 modified yet again to run under Turbo C
   ;                                 by Jim Texter [71426,417]
   ;                                 compile using -B compiler switch
   ;
   ;   This routine is based on the FastWrite routine submitted
   ;   to the Borland SIG on CompuServe. It has been tested for
   ;   use with programs written under the Turbo C Compiler,
   ;   version 1.0. I have tested it under the large and hughe
   ;   memory models only.
   ;   In calling the routine from a C program, the value for
   ;   the string 'st' can be supplied by passing a pointer to
   ;   a string or, as is convenient with C, a string literal
   ;   itself (the program will take the address of the 0th element
   ;   of the string).
   ;
   ;   Acknowledgements:
   ;   Brian Foley submitted the Turbo Pascal inline code version
   ;   of this routine to the Borland SIG on CompuServe. David B.
   ;   Rein helped to convert the code, and some final modifications
   ;   were done by Michael D. Most.
   ;
   ;   Questions may be answered by contacting Brian Foley on
   ;   CompuServe [76317,3247], or Mike Most [70446,1244].
   ;
   ;
   ;**********************************************************
   ;*
   ;*                        usage:        fastwrite(st,row,col,attr)
   ;*                                         char *st;
   ;*                                         int row, col, attr;
   ;*
   ;**********************************************************/


 fastwrite (char *st, int row, int col, int attr)
 {
                         asm  mov          bx,si                    /*save SI
                         asm  mov          ax,40h                   /*get vide
                         asm  mov          es,ax
                         asm  mov          dl,es:[49h]           /*DL=Video mo
                         asm  mov          di,row                   /*DI=Row
                         asm  dec          di                           /*make
                         asm  mov          cl,4                           /*CL
                         asm  shl          di,cl                    /*DI=Row*3
                         asm  mov          ax,di                    /*store in
                         asm  shl          di,1                           /*DI
                         asm  shl          di,1                           /*DI
                         asm  add          di,ax                    /*di=row*8
                         asm  add          di,col                   /*Add (Col
                         asm  dec          di                           /*DI=(
                         asm  shl          di,1                           /*ac
                         asm  lds          si,st                    /*DS:SI po
                         asm  mov          ah,attr                   /*AH = at
                         asm  cmp          dl,7                           /*Mo
                         asm  je           mono
                         asm  mov          dx,0b800h            /*base of vide
                         asm  mov          es,dx                    /*ES = seg
                         asm  mov          dx,03dah                   /*6845 p
 getnext:        asm  lodsb                                           /*load n
                         asm  or           al,al                    /*test for
                         asm  jz           exit                           /*ex
                         asm  mov          cx,ax                    /*store vi
                         asm  cli                                           /*
 waitnoh:        asm  in           al,dx                    /*get 6845 status
                         asm  test          al,8                           /*V
                         asm  jnz          store                    /*if so, g
                         asm  rcr          al,1                           /*el
                         asm  jc           waitnoh                   /*horizon
 waith:                asm  in           al,dx                    /*get 6845 s
                         asm  rcr          al,1                           /*wa
                         asm  jnc           waith                   /*retrace
 store:                asm  mov           ax,cx                   /*move word
                         asm  stosw
                         asm  sti                                           /*
                         asm  jmp          short getnext    /*get next charact
 mono:                asm  mov          dx,0b000h
                         asm  mov          es,dx                    /*ES = seg
 next:                asm  lodsb                                           /*L
                         asm  or           al,al                    /*Test for
                         asm  jz           exit                           /*Ex
                         asm  stosw
                         asm  jmp          short next           /*get next cha
 exit:                asm  mov          si,bx                    /*restore SI


 }








 FCOMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\FCOMP.C

 /*
         HEADER:                CUG236;
         TITLE:                Compare Text Files;
         DATE:                05/17/1987;
         DESCRIPTION:        "Best version of DIFF (file comparator) from Jan
                         issue of Software Practice and Experience.";
         VERSION:        1.1;
         KEYWORDS:        File Comparator, File Compare, File Comparison, File
                         Comparison Utility;
         FILENAME:        FCOMP.C;
         SEE-ALSO:        DIFF;
         COMPILERS:        vanilla;
         AUTHORS:        Chuck Allison;
 */

 /* fcomp.c:        file comparator that beats DIFF! */

 #include <stdio.h>

 /*
  * Portability Note:  8-bit systems often don't have header file string.h.
  * If your system doesn't have it, uncomment the following #define.
  */

 /*
 #define NO_STRING_H
 */

 /*
  * Portability Note:  Back in K & R days, standard library function malloc()
  * was called alloc().        Some compilers (e.g. Eco-C under CP/M) haven't
  * the name change.  If yours is one of these compilers, uncomment the
  * following #define:
  */

 /*
 #define malloc(p)        alloc(p)
 */

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * pair of #defines if you are running AZTEC C:
  */

 /*
 #define getc(f)                agetc(f)
 #define putc(c,f)        aputc(c,f)
 */

 #ifdef        NO_STRING_H
 int strcmp(), strlen();
 #else
 #include <string.h>
 #endif

 #define MAXLINES 1000
 #define ORIGIN MAXLINES
 #define INSERT 1
 #define DELETE 2

 struct edit {
    struct edit *link;
    int op;
    int line1;
    int line2;
 };

 char *A[MAXLINES], *B[MAXLINES];

 void exit();

 void main(argc,argv)
 int argc;
 char *argv[];
 {
    int         col, d, k, lower, m, max_d, n, row, upper;
    int last_d[2*MAXLINES+1];
    struct edit *new, *script[2*MAXLINES+1];
    char *malloc();
    int atoi(), in_file();
    void exceed(), fatal(), put_scr();

    if (argc > 1 && argv[1][0] == '-')
    {
       max_d = atoi(&argv[1][1]);
       ++argv;
       --argc;
    }
    else
       max_d = 2*MAXLINES;

    if(argc != 3)
       fatal("fcomp requires two file names.");

    m = in_file(argv[1],A);
    n = in_file(argv[2],B);

    for (row=0 ; row<m && row < n && strcmp(A[row],B[row]) == 0 ; ++row)
       ;
    last_d[ORIGIN] = row;
    script[ORIGIN] = NULL;
    lower = (row == m) ? ORIGIN + 1 : ORIGIN - 1;
    upper = (row == n) ? ORIGIN - 1 : ORIGIN + 1;
    if (lower > upper)
    {
       puts("The files are identical.");
       exit(0);
    }

    for (d = 1 ; d <= max_d ; ++d)
    {
       for ( k = lower ; k <= upper ; k +=2)
       {
          new = (struct edit *) malloc(sizeof(struct edit));
          if (new == NULL)
             exceed(d);

          if (k == ORIGIN-d || k != ORIGIN+d && last_d[k+1] >= last_d[k-1])
          {
             row = last_d[k+1]+1;
             new->link = script[k+1];
             new->op = DELETE;
          }
          else
          {
             row = last_d[k-1];
             new->link = script[k-1];
             new->op = INSERT;
          }
          new->line1 = row;
          new->line2 = col = row + k - ORIGIN;
          script[k] = new;

          while(row < m && col < n && strcmp(A[row],B[col]) == 0)
          {
             ++row;
             ++col;
          }
          last_d[k] = row;

          if (row == m && col == n)
          {
             put_scr(script[k]);
             exit(!0);
          }
          if (row == m)
             lower = k+2;

          if (col == n)
             upper = k-2;
       }
       --lower;
       ++upper;
    }
    exceed(d);
 }

 int in_file(filename,P)
 char *filename, *P[];
 {
    char buf[100], *malloc(), *save, *b;
    FILE *fp;
    int lines = 0;
    void fatal();

    if ((fp = fopen(filename,"r")) == NULL)
    {
       fprintf(stderr, "Cannot open file %s.\n",filename);
       exit(!0);
    }

    while(fgets(buf,100,fp) != NULL)
    {
       if (lines >= MAXLINES)
          fatal("File is too large for diff.");
       if ((save = malloc(strlen(buf)+1)) == NULL)
          fatal("Not enough room to save the files.");
       P[lines++] = save;
       for (b = buf ; *save++ = *b++ ; )
          ;
    }
    fclose(fp);
    return(lines);
 }

 void put_scr(start)
 struct edit *start;
 {
    struct edit *ep, *behind, *ahead, *a, *b;
    int change;

    ahead = start;
    ep = NULL;
    while (ahead != NULL)
    {
       behind = ep;
       ep = ahead;
       ahead = ahead->link;
       ep->link = behind;
    }

    while( ep != NULL)
    {
       b = ep;
       if (ep->op == INSERT)
          printf("Inserted after line %d:\n",ep->line1);
       else
       {
          do
          {
             a = b;
             b = b->link;
          } while (b!=NULL && b->op == DELETE && b->line1 == a->line1+1);

          change = (b!=NULL && b->op == INSERT && b->line1 == a->line1);
          if (change)
             printf("\nChanged ");
          else
             printf("\nDeleted ");
          if (a == ep)
             printf("line %d\n",ep->line1);
          else
             printf("lines %d-%d:\n",ep->line1,a->line1);

          do
          {
             printf(" %s",A[ep->line1-1]);
             ep = ep->link;
          } while (ep != b);

          if (!change)
             continue;
          printf("To:\n");
       }
       do
       {
          printf(" %s",B[ep->line2-1]);
          ep = ep->link;
       } while (ep != NULL && ep->op == INSERT && ep->line1 == b->line1);
    }
 }

 void fatal(msg)
 char *msg;
 {
    fprintf(stderr,"%s\n",msg);
    exit(!0);
 }

 void exceed(d)
 int d;
 {
    fprintf(stderr,"The files differ in at least %d lines. \n",d);
    exit(!0);
 }


 FDIRES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\STAYRESC\FDIRES.C


 /****************************************************************************
 /*                                                                          *
 /*     FDIRES.C   Version 1.0  10/23/85                Brian Irvine         *
 /*                                                                          *
 /*        Released to the Public Domain for use without profit              *
 /*                                                                          *
 /****************************************************************************
 /*                                                                          *
 /* fdires.c - Program to demonstrate use of stayres.c in creating a         *
 /*            terminate-and-stay-resident program in DeSmet C.              *
 /*                                                                          *
 /*            This program demonstrates the techniques used to create a     *
 /*            program which will terminate but remain resident as part      *
 /*            of DOS.  The program is a sorted directory displayer which    *
 /*            will show a sorted and formatted listing of files on the      *
 /*            current directory.  It is supplied mainly to demonstrate      *
 /*            the techniques involved in creating TSR programs.             *
 /*                                                                          *
 /*            The program must be linked with the other module in this      *
 /*            library using the -s option of bind with a stack allowance    *
 /*            of 0x1000 (4096 decimal).  This should be more than           *
 /*            adequate for 99% of all applications.                         *
 /*                                                                          *
 /*             Brian Irvine                                                 *
 /*             3379 St Marys Place                                          *
 /*             Santa Clara, CA 95051                                        *
 /*             [71016,544]                                                  *
 /*                                                                          *
 /****************************************************************************

 #include   "stdio.h"

 #define    MAX_DIRS        1000

 #define    DOS_INT         0x21
 #define    GET_DRV         0x19

    FILE_NOT_FOUND  2           /* DOS function error codes */
 #define    INVALID_DRIVE   15
 #define    NO_MORE_FILES   18

 struct {
         char   reserved[21];           /* disk transfer area */
         char   attribute;
         int    time;
         int    date;
         long   file_size;
         char   name[13];
         } dta;

 struct dir_entry{                      /* directory entry */
         char    e_attribute;
         int     e_time;
         int     e_date;
         long    e_file_size;
         char    e_name[13];
         } entry[MAX_DIRS];             /* enough room for 1000 entries */

 long   free_space;
 long   total_space;
 int    entries = 0;
 int    _rax, _rbx, _rcx, _rdx,     /* variables to hold register values */
               _rsi, _rdi, _rds, _res;
 int    row, column;                /* cursor position - must be global */

 extern char    _carryf;

 char   label [12];
 char   pathname [65];
 char   buffer [65];
 static char   save_screen[4000];          /* save the screen here */
 long   get_free ();


 extern void    stayres();      /* the code to terminate and stay resident */


 /*----- Main ---------------------------------------------------------------*
 /*                                                                          *
 /*     In this application all we have to do is call the tsr code.  Other   *
 /*     initialization can be performed here before fencing ourselves off.   *
 /*                                                                          *
 /*--------------------------------------------------------------------------*

 main ()
 {

    stayres ();

 }

 /*----- Main program entry point -------------------------------------------*

 fdir ()
 {

    int     n, stat, curr_drv;
    int     mode;
    unsigned    screen_seg;

    /* get the video mode */

    mode = get_mode ();

    /* save the user's screen and cursor position */

    find_cursor ();
    if ( mode == 7 )
        screen_seg = 0xB000;
    else
        screen_seg = 0xB800;
    _lmove ( 4000, 0, screen_seg, save_screen, _showds() );
    scr_clr ();
    scr_rowcol (0,0);

    entries = 0;
    _setmem (buffer, 65, '\0' );        /* initialize buffers explicitly each
    _setmem (pathname, 65, '\0' );      /* time through because it changes */
    if ( get_path () == ERR )
        {
        puts ("Invalid drive specifier.\n");
        exit(1);
        }

 /*     Now construct the path name using current drive                      *

    curr_drv = get_curr_drv ();
    buffer[0] = curr_drv + 'A';
    buffer[1] = ':';
    if ( strlen ( pathname ) == 0 )
        buffer[2] = '\0';
    else
        {
        buffer[2] = '\\';
        buffer[3] = '\0';
        }

    strcat ( buffer, pathname );
    strcpy ( pathname, buffer );
    n = ( 80 - strlen ( pathname ) - 14 ) / 2;
    strncpy ( buffer, "                                ", n);
    strcat ( buffer, "Directory of " );
    strcat ( buffer, pathname );
    printf ( "%s\n\n", buffer );
    set_dta ();

 /*     Get the first matching directory entry                               *

    if ( get_first () )
        {
        puts ("File not found.\n");
        exit (1);
        }

 /*     Now collect all the other matching names                             *

    while ( ( stat = get_next () ) != NO_MORE_FILES )
        ;
    free_space = get_free ();
    sort_files ();
    print_files ();

    /* now put everything back where it was */

    puts ("\nPress any key to continue...");
    while ( !scr_csts() )
        ;

    _lmove ( 4000, save_screen, _showds(), 0, screen_seg );
    scr_rowcol ( row, column );

 }



 /*----- Get the current drive number ---------------------------------------*

 int    get_curr_drv ()
 {

    return ( _os ( GET_DRV, 0 ) );

 }



 /*----- Get path name of current directory ---------------------------------*

 int    get_path ()
 {

    _rax = 0x4700;
    _rdx = 0;
    _rsi = &pathname[0];
    _rds = _showds();
    _doint ( DOS_INT );
    if ( _carryf )
        return ERR;

 }



 /*----- Give the DTA address to DOS ----------------------------------------*

 void   set_dta ()
 {

    _rax = 0x1A00;
    _rdx = &dta;
    _rds = _showds();
    _doint ( DOS_INT );

 }



 /*----- Get the first matching directory entry -----------------------------*

 int    get_first ()
 {

    strcat ( pathname,"\\*.*" );    /* look for all files */
    _rax = 0x4E00;
    _rdx = &pathname;
    _rcx = 0xFF;                    /* attribute = all */
    _doint ( DOS_INT );
    if ( _carryf )                  /* if there's an error */
        return  ( _rax );           /* send back the code */
    _move ( 22, &dta.attribute, &entry[entries++] );    /* else move data to a
    return ( 0 );

 }



 /*----- Get next matching directory entry ----------------------------------*

 void   get_next ()
 {

    _rax = 0x4F00;
    _doint ( DOS_INT );
    if ( _carryf )
        return  ( _rax );
    _move ( 22, &dta.attribute, &entry[entries++] );
    return ( 0 );

 }


 /*----- Get free space left on disk ----------------------------------------*

 long   get_free ()
 {

    _rdx = 0;
    _rax = 0x3600;
    _doint ( DOS_INT );
    total_space = ((long) ( (long)_rax * (long)_rdx * (long)_rcx ));
    return ((long) ( (long)_rax * (long)_rbx * (long)_rcx ));

 }



 /*----- Comparison routine for qsort() -------------------------------------*

 int    compare ( first, second )
 struct dir_entry *first, *second;
 {

    return ( strcmp (first -> e_name, second -> e_name ) );

 }



 /*----- Sort the directory entries by name ---------------------------------*

 void   sort_files ()
 {

    qsort ( entry, entries, 22, compare );

 }



 /*----- Get the cursor location --------------------------------------------*


 void   find_cursor()
 {
    _rax = 0x0300;
    _rbx = 0;
    _doint(0x10);
    row = _rdx >> 8;
    column = _rdx & 0x00FF;

 }


 /*----- Get the current video mode -----------------------------------------*

 int    get_mode ()
 {
    _rax = 0x0F00;
    _doint ( 0x10 );
    return ( _rax & 0x00FF );

 }


 /*----- Print the directory entries and free space -------------------------*
 /*                                             this code needs to be redone *

 void   print_files ()
 {
    int i, middle, count, pm, dir, hour;
    struct dir_entry *next;
    char    namebuf[20];
    char    extbuf [4];
    char    *buf, *dirln;

    pm = hour = count = 0;
    next = &entry;
    middle = (entries + 1)/2;
    puts ("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
    puts ("Filename Ext   Size     Date     Time  ³ Filename Ext   Size     Da
    puts ("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
    for ( count = 0; count < middle; count++ )
        {
        buf = &namebuf;
        dirln = &entry[count].e_name;
        *buf = '\0';
        dir = FALSE;
        if ( entry[count].e_attribute & 0x10 )
            dir = TRUE;
        while ( *dirln && (*dirln != '.'))
            *buf++ = *dirln++;
        *buf = '\0';
        buf = &extbuf;
        *buf = '\0';
        if ( *dirln )
            dirln++;
        strcat( extbuf, dirln );
        hour = ( entry[count].e_time >> 11 ) & 0x001F;
        pm = FALSE;
        if ( hour > 12 )
            {
            hour -= 12;
            pm = TRUE;
            }
        if ( hour == 0 )
            hour = 12;
        if ( dir )
            {
            if ( strlen ( namebuf ) == 0 )
                strcpy ( namebuf, "." );
            else
                ;
            printf ("%-8s %-3s  [Dir]   %2d-%2d-%2d  %2d:%02d%1c ³",
                    namebuf,
                    extbuf,
                    (entry[count].e_date >> 5) & 0x000F,
                    (entry[count].e_date & 0x001F),
                    (entry[count].e_date >> 9) + 80,
                    hour,
                    (entry[count].e_time >> 5) & 0x003F,
                    (pm) ? 'p' : 'a');
            }
        else
            printf ("%-8s %-3s  %6D  %2d-%2d-%2d  %2d:%02d%1c ³" ,
                    namebuf,
                    extbuf,
                    entry [count].e_file_size,
                    (entry[count].e_date >> 5) & 0x000F,
                    (entry[count].e_date & 0x001F),
                    (entry[count].e_date >> 9) + 80,
                    hour,
                    (entry[count].e_time >> 5) & 0x003F,
                    (pm) ? 'p' : 'a');
        if ( (count + middle) < entries )
            {
            buf = &namebuf;
            dirln = &entry[count + middle].e_name;
            *buf = '\0';
            dir = FALSE;
            if ( entry[count+middle].e_attribute & 0x10 )
                dir = TRUE;
            while ( *dirln && (*dirln != '.'))
                *buf++ = *dirln++;
            *buf = '\0';
            buf = &extbuf;
            *buf = '\0';
            if ( *dirln )
                dirln++;
            strcat( extbuf, dirln );
            hour = ( entry[count + middle].e_time >> 11 ) & 0x001F;
            pm = 0;
            if ( hour > 12 )
                {
                hour -= 12;
                pm = 1;
                }
            if ( hour == 0 )
                hour = 12;
            if ( dir )
                {
                if ( strlen ( namebuf ) == 0 )
                    strcpy ( namebuf, "." );
                else
                    ;
                printf (" %-8s %-3s  [Dir]   %2d-%2d-%2d  %2d:%02d%1c\n",
                        namebuf,
                        extbuf,
                        (entry[count+middle].e_date >> 5) & 0x000F,
                        (entry[count+middle].e_date & 0x001F),
                        (entry[count+middle].e_date >> 9) + 80,
                        hour,
                        (entry[count+middle].e_time >> 5) & 0x003F,
                        (pm) ? 'p' : 'a');
                }
            else
                printf (" %-8s %-3s  %6D  %2d-%2d-%2d  %2d:%02d%1c\n" ,
                        namebuf,
                        extbuf,
                        entry [count+middle].e_file_size,
                        (entry[count+middle].e_date >> 5) & 0x000F,
                        (entry[count+middle].e_date & 0x001F),
                        (entry[count+middle].e_date >> 9) + 80,
                        hour,
                        (entry[count+middle].e_time >> 5) & 0x003F,
                        (pm) ? 'p' : 'a');
            }
        else
            puts ("\n" );
        if ( ( (count + 1) % 17 ) == 0 )
            {
            puts ("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Press any key to continue ÄÄÄÄÄ
            while ( !scr_csts () )
                ;
            }
        }
    puts ("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
    printf (" %3d directory %s                 ³", entries, (entries > 1) ? "e
    printf ("  %D bytes free         %3d%% used\n", free_space, 100 * (total_s
    puts ("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

 }




 FDIRTSR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\STAYRESC\FDIRTSR.C


 /****************************************************************************
 /*
 /*     FDIRTSR.C   Version 1.0        10/23/85               Brian Irvine
 /*
 /*          Released to the Public Domain for use without profit
 /*
 /****************************************************************************
 /*
 /* stayres.c - Code which can be used in a general way to create programs   *
 /*               in C which will terminate and stay resident.  This code
 /*               will allow the use of DOS I/O without having the stack and
 /*               registers clobbered.  This code is written in DeSmet C and
 /*               uses library functions which may not be available in other
 /*               C compilers.  It also makes heavy use of the #asm compiler
 /*               directive to allow in-line assembly language within the C
 /*               code.  This code provides a general outline for a main()
 /*               function which can be modified to suit the users needs. All
 /*               the code necessary to terminate and stay resident is
 /*               contained in this module; the user's program can be contain-
 /*               ed entirely externally.        The program does not have to
 /*               COM file, and the amount of memory reserved is not limited
 /*               to 64K. The code has not been tested on program files with
 /*               greater than 64K of code.
 /*
 /*               This code is based on a set of routines written in Turbo
 /*               Pascal by Lane H. Ferris which are available on the Borland
 /*               SIG on Compuserve.
 /*
 /*               Brian Irvine
 /*               3379 St Marys Place
 /*               Santa Clara, CA 95051
 /*               [71016,544]
 /*
 /****************************************************************************

 #include   "stdio.h"

 /*----- Global variables ---------------------------------------------------*

 unsigned   dos_regs [10];               /* save DOS registers here */
 unsigned   dos_dseg;                       /* save the DS and SS regs */
 unsigned   dos_sseg;                       /* for later convenience */
 unsigned   dos_sp;                       /* storage for DOS stack pointer */
 unsigned   c_sseg;                       /* save our stack segment here */
 unsigned   c_sp;                       /* and our stack pointer here */
 unsigned   stacksize;                       /* size of DOS/local stack */
 int           _rax, _rbx, _rcx, _rdx,     /* variables hold register values *
            _rsi, _rdi, _rds, _res;

 /*--------------------------------------------------------------------------*
 /* note: storage to save the DOS/C data segments must be allocated in the   *
 /*         code segment, so variable must be defined inside "#asm - #" area.
 /*--------------------------------------------------------------------------*

 /*----- Constants ----------------------------------------------------------*

    KB_INT      0x16    /* BIOS software int keyboard service routine */
    DOS_INT     0x21    /* DOS kitchen sink interrupt */
    USER_INT    0x67    /* INT 16H vector is moved to here */

    WAKEUP      0x71    /* scan code for Alt-F10 */
    PARAGRAPHS  0x1000  /* # of paragraphs of memory to keep */

 /*----- Externals ----------------------------------------------------------*

 extern unsigned _PCB;        /* DeSmet C stores original sp value at _PCB + 2
 extern void    fdir ();              /* user's program module entry point */

 /*--------------------------------------------------------------------------*
 /*     Initial program startup code
 /*--------------------------------------------------------------------------*

 void        stayres ()
 {

 /* Save the C data segment and reserve storage in code segment for later use

 #asm

            jmp           get_ds

 active_:   db           0
 c_ds_:           dw           0
 dos_ds_:   dw           0

 get_ds:    push    ax
            mov           ax,ds
            mov           cs:c_ds_,ax
            pop           ax

 #
    /* initialize program stack segment variable */

    c_sseg = _showds();

    /* get the current address of INT 16H and save it */

    _res = 0;                       /* just for DOS 3.0 */
    _rax = 0x3500 + USER_INT;
    _doint (DOS_INT);

    if ( _res != 0 )
        puts ("\nInterrupt 67H in use.  Can't install program.\n");
    else
        {

 /*--------------------------------------------------------------------------*
 /*     Do your program initialization here because you won't get hold of    *
 /*     it again until it is entered with the wakeup key sequence.
 /*--------------------------------------------------------------------------*

        /* get address of current INT 16H routine */

        _rax = 0x3500 + KB_INT;
        _doint (DOS_INT);

        /* set the old INT 16H code up as INT 67H for later use */

        _rax = 0x2500 + USER_INT;
        _rds = _res;
        _rdx = _rbx;
        _doint (DOS_INT);

        /*  now set the INT 16H vector to point to our new service routine */

        _rax = 0x2500 + KB_INT;
        _rds = _showcs();

 #asm
            push    bx
            lea           bx, back_door_
            mov           word _rdx_,bx
            pop           bx
 #
        _doint (DOS_INT);


 /*----- Now terminate while staying resident -------------------------------*


 /****************************************************************************
 /*
 /*     note:
 /*     DeSmet C lays claim to the entire 64K of the data segment by using   *
 /*     it for the stack segment as well.  The data resides at the bottom    *
 /*     of the segment while the stack starts at the top and works down.     *
 /*     Because of this arrangement, we must reserve at least 64k of space   *
 /*     in addition to the amount of memory occupied by code.  Cware to the  *
 /*     rescue, however.  The DeSmet bind program allows you to specify a    *
 /*     maximum stack size when the modules are combined at link time. By    *
 /*     using the "-shhhh" option, you can specify a stack of 4K, which      *
 /*     should be more than adequate for most applications.  The object
 /*     module of this program must be combined with the "fdires.o" module   *
 /*     with a bind command like:                                            *
 /*
 /*                       bind fdires fdirtsr -s1000
 /*
 /*     The stack size is specified in hex.
 /*
 /****************************************************************************


        /* calculate how much memory we need to reserve (in paragraphs)
        /*                                                                  */
        /*      size = ds - cs + (sp/16) + 0x10 + 0x10 + 1                  */
        /*                                                                  */
        /* ds - cs gives the number of paragraphs of code in our program.  */
        /* sp/16 gives us a fair idea of where the end of the data segment */
        /* is located, but by the time we get to here, the stack pointer   */
        /* will have been moved around so we need to fudge a little.
        /* The first "+ 0x10" is to allow for the program segment prefix,  */
        /* the second "+ 0x10" is a fudge factor, so is the "+ 1" because  */
        /*      (1) _showsp () doesn't show the top of the stack           */
        /*      (2) we must always round up with integer division          */
        /* If you run the program and it seems to operate fine, but          *
        /* when you try to run another program above it you get
        /* a DOS message "Memory allocation error can't load COMMAND.COM"  */
        /* it means you haven't allocated enough memory for your program   */
        /* and your stack has destroyed the memory allocation linked list. */
        /* Try recompiling with more memory reserved.

        _rax = 0x3100;
        _rdx = _showds() - _showcs() + ( _showsp() / 16 ) + 0x20 + 1;
        printf ( "FDIRES now installed.\nPress Alt-F10 to activate.\n", _rdx )
        _doint (DOS_INT);

        }

 }


 /*----- Interrupt 16H service routine --------------------------------------*
 /*
 /*     This function replaces the standard BIOS INT 16H service routine.    *
 /*     It is called by DOS and our application program to get the next
 /*     character from the queue, check the shift status, or just see if     *
 /*     there is a character in the queue.  All type 1 and 2 requests are    *
 /*     passed through to the original service routine, through a long
 /*     jump to that address.  Type 0 requests (get the next character)
 /*     are handled through an INT 67H call to the original service rou-     *
 /*     tine.  The character obtained is checked to see if it is the
 /*     designated wakeup key.  If not, it is passed on to DOS.        If it i
 /*     then part of the DOS stack is saved on the local stack, all the
 /*     processor registers are saved in memory and the program is
 /*     started up.  The C program environment and registers are estab-
 /*     lished and the DOS environment is saved for later restoration.
 /*     Upon return from the user's program, the DOS stack is restored       *
 /*     from the data saved on the local stack, bringing DOS back to
 /*     where it was before the user program was turned on.
 /*     These operations allow programs to be written in C without having    *
 /*     to worry about the resident routines destroying the DOS registers    *
 /*     when file I/O is used.  It also allows the use of printf().
 /*
 /*--------------------------------------------------------------------------*



 void   back_door()
 {
 /*
    Current stack contents:
                sp -> DOS ip
            sp + 2 -> DOS cs
            sp + 4 -> DOS flags

    C function prologue:
            push    bp
            mov           bp,sp
 */

 #asm
            pop           bp                       ;toss out the bp from the p
            cmp           cs:active_,1        ;if the program is currently act
            jne           not_on               ;go service the request
 ;
 ; long jump to F000:E82E
 ;
            db           0EAH
            dw           0E82EH
            dw           0F000H
 ;
 not_on:    cmp           ah,0                ;if this is a character request
            jz           chr_rqst               ;check a little further
 ;
 ; long jump to F000:E82E
 ;
            db           0EAH
            dw           0E82EH
            dw           0F000H
 ;
 chr_rqst:
            int           67H                       ;get the next character fr
            cmp           ah,71H               ;if it's not the wakeup charact
            jne           skipall               ;then take it back to the call
            mov           cs:active_,1        ;else set the 'program active' f
 ;
 ;  now we enter the program
 ;
            cli                               ;no interrupts for now
            mov           cs:dos_ds_,ds       ;save the DOS data segment
            mov           ds,cs:c_ds_               ;establish our data segmen
            push    bp                       ;save bp
            mov           bp,offset dos_regs_ ;point to dos_regs
            mov           ds:[bp+0], ax       ;copy the current registers into
            mov           ds:[bp+2], bx       ;array in the local data segment
            mov           ds:[bp+4], cx
            mov           ds:[bp+6], dx
            pop           ds:[bp+8]               ;get the bp and save it
            mov           ds:[bp+10], si
            mov           ds:[bp+12], di
            push    ax
            mov           ax, cs:dos_ds_      ;save the DOS ds reg
            mov           ds:[bp+14], ax
            pop           ax
            mov           ds:[bp+16], es      ;save es
            pushf                       ;save the flags too
            pop           ds:[bp+18]
            mov           word dos_sseg_,ss   ;save DOS stack segment
            mov           si,ss               ;if DOS stack segment and C stac
            mov           es,si               ;segment are the same, then use
            mov           ss,word c_sseg_     ;current stack pointer for savin
            cmp           si,word c_sseg_     ;the registers. If not the same,
            mov           si,sp               ;we are entering the program so
            je           keep_sp               ;the starting stack pointer
            mov           si,ss:_PCB_ + 2
 keep_sp:   xchg    sp,si               ;save the registers on the stack
                                        ;now using local stack (ds = ss)
            push    [bp+0]               ;save ax
            push    [bp+2]               ;save bx
            push    [bp+4]               ;save cx
            push    [bp+6]               ;save dx
                                        ;don't save bp
            push    [bp+10]               ;save si
            push    [bp+12]               ;save di
            push    [bp+14]               ;save ds
            push    [bp+16]               ;save es
                                        ;don't save flags
            sub           cx,cx               ;now save 40 words or less from
            sub           cx,si               ;DOS stack onto the current stac
            shr           cx,1                ;If the stack size is less than
            cmp           cx,40               ;save 'stacksize' words, else sa
            jle           under40
            mov           cx,40
 under40:   mov           word stacksize_,cx
 restack:   push    es:[si]
            inc           si
            inc           si
            loop    restack
            push    si                       ;save the count of words pushed o
            mov           word c_sp_,sp       ;save current stack pointer
            sti
            push    bp                       ;do the C function prologue here
            mov           bp,sp

 #

 /*----- Call your program from here ----------------------------------------*

            fdir ();

 /*----- Restore everything -------------------------------------------------*

 #asm
 restore:
            pop           bp
            cli                               ;no interrupts
            mov           sp,word c_sp_       ;get the stack pointer back
            pop           si                       ;get pointer to top of word
            mov           cx,word stacksize_  ;get count of words to move
            mov           es,word dos_sseg_   ;point es to caller's stack
 unstack:   dec           si                       ;back up one word
            dec           si
            pop           es:[si]               ;restore the caller's stack fr
            loop    unstack
            mov           bp,si               ;save pointer to top of caller's
            pop           es                       ;pop registers off the stac
            pop           di                       ;don't restore ds just yet
            pop           di
            pop           si
            pop           dx
            pop           cx
            pop           bx
            pop           ax
            mov           sp,bp               ;restore the caller's stack poin
            mov           ax,0                ;tell caller there was no charac
            mov           ss,word dos_sseg_   ;switch back to the caller's sta
            mov           bp,offset dos_regs_
            push    ds:[bp+18]               ;restore the flags from memory
            popf
            mov           bp,ds:[bp+8]        ;restore the caller's bp reg
            mov           cs:active_,0        ;reset the 'program active' flag
            mov           ds,cs:dos_ds_       ;finally restore caller's data s
 skipall:   iret                        ;head on back

 #

 }




 FDOPEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FDOPEN.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 extern        FILE        _iob[];

 FILE *fdopen(h, mode)
 register int h;
 register char *mode;
 /*
  *        Associates a stream with the already open file <h>.  The <mode>
  *        values are the same as for fopen(), but MUST be compatible with
  *        the mode in which <h> was open()ed.  This functions allows use
  *        of a file opened with the low level open()/creat() calls to be
  *        used as a buffered/translated stream.  A pointer to a FILE struct
  *        is returned, or NULL for errors.
  */
 {
         register FILE *fp = NULL;
         register char *p = NULL;
         register int i, j = FALSE, f = 0;
         char *malloc();

         for(i=0; (!fp && (i < MAXFILES)); ++i)
                 if(!(_iob[i].F_stat & (F_READ | F_WRITE)))   /* empty slot? *
                         fp = &_iob[i];
         if(!fp)
                 return(NULL);
         while(*mode) {
                 switch(*mode++) {
                         case 'r':
                                 f |= F_READ;
                                 break;
                         case 'w':
                                 f |= F_WRITE;
                                 break;
                         case 'a':
                                 f |= F_WRITE;
                                 j = TRUE;
                                 break;
                         case '+':
                                 f |= (F_READ | F_WRITE);
                                 break;
                         case 'b':
                                 f |= F_BINARY;
                                 break;
                         case 't':
                                 f &= ~F_BINARY;
                                 break;
                         default:
                                 fputs(stderr, "Illegal file mode.\n");
                                 return(NULL);
                 }
         }
         if((i = (f & (F_READ | F_WRITE))) == 0)
                 return(NULL);
         if((p=malloc(BUFSIZ)) != NULL)        /* set up file buffer */
                 f |= F_BUFFER;
         if(j)                                /* append mode. move to eof. */
                 lseek(h, 0L, _LSKend);
         fp->F_h = h;                        /* file handle */
         fp->F_stat = f;                        /* file status flags */
         fp->F_buf = p;                        /* base of file buffer */
         fp->F_bp = p;                        /* current buffer pointer */
         fp->F_bsiz = (p ? BUFSIZ : 0);        /* buffer size */
         fp->F_cnt = 0;                        /* # of bytes in buffer */
         fp->F_unc1 = '\0';                /* primary ungotten character */
         fp->F_unc2 = '\0';                /* secondary ungotten character */
         return(fp);
 }


 FFLUSH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FFLUSH.C

 #include <stdio.h>

 int fflush(fp)
 register FILE *fp;
 /*
  *        Flush the output buffer of the stream <fp>.  The buffer is
  *        automatically flushed when it is full, the stream is closed,
  *        or the program terminates through exit().  This function has
  *        no effect if the stream in unbuffered.
  */
 {
         register int f, rv = 0;

         f = fp->F_stat;
         if(!(f & F_BUFFER))                        /* file not buffered */
                 return(0);
         if(!(f & (F_READ | F_WRITE)))                /* file not open! */
                 return(0);
         if((f & F_IODIR) && (fp->F_cnt)) {        /* have data to be written?
                 if(write(fp->F_h, fp->F_buf, fp->F_cnt) < 0)
                         fp->F_stat |= F_ERROR;
         }
         fp->F_bp = fp->F_buf;
         fp->F_cnt = 0;
         fp->F_unc1 = fp->F_unc2 = '\0';
 }


 FGETC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FGETC.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 static int        _fgetc2 = FALSE;        /* "2nd time in" flag */

 int fgetc(fp)
 register FILE *fp;
 /*
  *        Get a character from <fp>.  Returns the character or EOF.
  */
 {
         register int f, m;
         unsigned char c;

         f = fp->F_stat;
         if(!(f & F_READ))                        /* stream opened for read? *
                 return(EOF);
         m = (F_BUFFER | F_WRITE | F_IODIR);
         if((f & m) == m)                        /* r/w direction switch */
                 fflush(fp);
         fp->F_stat &= ~F_IODIR;
         if(f & (F_ERROR | F_EOF))                /* error/eof conditions */
                 return(EOF);
         if(fp->F_unc1) {                        /* ungotten character */
                 c = fp->F_unc1;
                 fp->F_unc1 = fp->F_unc2;
                 fp->F_unc2 = '\0';
         }
         else if(f & F_BUFFER) {
                 if(!((fp->F_cnt)--)) {
                         if((m = read(fp->F_h, fp->F_buf, fp->F_bsiz)) < 0) {
                                 fp->F_stat |= F_ERROR;
                                 return(EOF);
                         }
                         if(m == 0) {
                                 fp->F_stat |= F_EOF;
                                 return(EOF);
                         }
                         fp->F_cnt = (m - 1);
                         fp->F_bp = fp->F_buf;
                 }
                 c = *(fp->F_bp)++;
         }
         else {
                 if((m = read(fp->F_h, &c, 1)) < 0) {
                         fp->F_stat |= F_ERROR;
                         return(EOF);
                 }
                 if(m == 0) {
                         fp->F_stat |= F_EOF;
                         return(EOF);
                 }
         }
         if((c == '\r') && !_fgetc2 && !(f & F_BINARY)) {
                 _fgetc2 = TRUE;
                 if(f & F_DEVICE)                        /* translated device
                         c = '\n';
                 else if((c = fgetc(fp)) != '\n') {        /* translated strea
                         fungetc(c, fp);
                         c = '\r';
                 }
                 _fgetc2 = FALSE;
         }
         else if((c == '\n') && !(f & F_BINARY) && (f & F_DEVICE))
                 c = fgetc(fp);                                /* filter <LF>
         else if((c == 0x1A) && !(f & F_BINARY)) {        /* ^Z xlat to EOF */
                 fp->F_stat |= F_EOF;
                 return(EOF);
         }
         return(c);
 }

 int fungetc(c, fp)
 char c;
 register FILE *fp;
 /*
  *        Push the character <c> back to be gotten by the next fgetc()
  *        call on <fp>.  Only 1 character may be ungotten at a time on
  *        each stream.  Subsequent calls to fungetc() will write over
  *        the currently saved character.
  */
 {
         if(fp->F_stat & (F_ERROR | F_EOF))
                 return(EOF);
         fp->F_unc2 = fp->F_unc1;
         return(fp->F_unc1 = c);
 }


 FGETS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FGETS.C


 /* Copyright (C) 1981,1982 by Manx Software Systems and Thomas Fenwick */
 #include "stdio.h"

 char *gets(line)
 char *line;
 {
         register char *cp;
         register int i;

         cp = line;
         while ((i = getchar()) != EOF && i != '\n')
                 *cp++ = i;
         *cp = 0;
         if (i == EOF && cp == line)
                 return NULL;
         return line;
 }

 char *fgets(s, n, fp)
 char *s; FILE *fp;
 {
         register c;
         register char *cp;

         cp = s;
         while (--n > 0 && (c = agetc(fp)) != EOF) {
                 *cp++ = c;
                 if (c == '\n')
                         break;
         }
         *cp = 0;
         if (c == EOF && cp == s)
                 return NULL;
         return(s);
 }

 agetc(ptr)
 register FILE *ptr;
 {
         register int c;

 top:
         if ((c = getc(ptr)) != EOF) {
                 switch (c &= 127) {
                 case 0x1a:
                         --ptr->_bp;
                         return EOF;
                 case '\r':
                 case 0:
                         goto top;
                 }
         }
         return c;
 }




 FGETS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FGETS.C

 /* 1.0  02-06-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         STRING
 fgets(s, n, fp)                /* Get a string s from FILE fp, at most n char
                            up to newline or EOF. Newline is part of s.
                            Return s if ok, or NULL if empty and EOF.        *
 /*----------------------------------------------------------------------*/
 STRING s;
 FILE *fp;
 {
         FAST c;
         STRING t;

         t = s;
         while (--n > 0 AND (c = getca(fp)) ISNT EOF)
         {        *s++ = c;
                 if (c IS '\n')
                         break;
         }
         *s = NULL;
         if (c IS EOF AND s IS t)
                 return NULL;

         return t;
 ;
 }



 FGETS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FGETS.C

 #include <stdio.h>

 char *fgets(data, limit, fp)
 char *data;
 register int limit;
 register FILE *fp;
 /*
  *        Get data from <fp> and puts it in the <data> buffer.  At most,
  *        <limit>-1 characters will be read.  Input will also be terminated
  *        when a newline is read.  <data> will be '\0' terminated and the
  *        newline, if read, will be included.  A pointer to the start of
  *        <data> is returned, or NULL for EOF.
  */
 {
         register char *p = data;
         register int c;

         while((--limit > 0) && ((c = fgetc(fp)) != EOF))
                 if((*p++ = c) == '\n')
                         break;
         *p = '\0';
         return((c == EOF && p == data) ? NULL : data);        /* NULL == EOF
 }


 FIELD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\FIELD.C

 /*
  *    field.c
  *      adapted from the unix utility of the same name by :
  *
  *      Torensoft
  *      1405 Prince of Wales
  *      Suite 602
  *      Ottawa ON Canada
  *      K2C 3J9
  *
  *      Uses prototypes as defined in Ansi X3J11
  */

 #include <stdio.h>
 #include <ctype.h>

 #define VERSION "field V0.1"
 #define MAXF 3000
 #define MAXL 20000
 #define IFS '\t'
 #define TRUE 0
 #define FALSE 1


 int arguments [MAXF];     /* numerical equivalent of command line parameters
 int num_columns;          /* number of columns to print */
 int num_fields;           /* number of fields in the current record */
 char *fp [MAXF];          /* pointers into line at field boundaries */
 char line [MAXL];         /* current line buffer */
 int separator = IFS;      /* the field separator */
 int check = FALSE;        /* true if you should check for field errors */
 int error = FALSE;        /* true if a check error occurs */

 /* prototypes for functions in this file */
 void explain (char *string);
 int fixup (int value);
 void putf (int n);


 main (argcount, argvalue)
 int argcount;
 char *argvalue [];
 {
         char *cp;
         char **ap;
         int  c;
         int  f;          /* the field counter -- -1 initially */
         int  fc;
         char *parameter;   /* pointer to each command line parameter */

         num_columns = 0;
         f = -1;

         if (argcount <= 1) {
            explain ("no parameters selected.");
         }

         /*
          * read parameters into arguments.
          */
         while (argcount > 1) {
               if (num_columns >= MAXF) {
                  fprintf (stderr, "field: you cannot have more than %d fields
                  exit (1);
               }
               parameter = argvalue [1];
               if (isdigit (parameter [0])) {
                  if ((arguments [num_columns++] = atoi (parameter)) <= 0) {
                     explain ("all fields are numbered from 1.");
                  }

               } else if (parameter [0] == '-') {
                      switch (tolower (parameter [1])) {
                             case 't' : separator = fixup (parameter [2]); bre
                             case 'c' : check = TRUE; break;
                             default  : explain ("bad option."); break;
                      }

               } else {
                 explain ("all fields are numbers.");
               }
               argcount --; argvalue ++;
         }

         if (num_columns <= 0) {
            explain ("you must select at least one field.");
         }

         /*
          * read and copy the input.
          */
         num_columns --;
         cp = line;
         ap = fp;
         *ap++ = cp;
         while (1) {
               c = getchar ();
               if (c == '\n' || c == EOF) {
                  if (cp == line && c == EOF){
                     break;
                  }
                  *cp++ = '\0';
                  num_fields = ap - fp;

                  /*
                   * check to see if all lines have the same number of fields.
                   * if f is negative then this is the first line we are proce
                   */
                  if (f < 0) {
                     f = num_fields;
                  } else {
                     if (f != num_fields) {
                        error = TRUE;
                     }
                  }

                  /*
                   * print this line.
                   */
                  for (fc = 0; fc <= num_columns; fc++) {
                      putf (arguments [fc] - 1);
                      if (fc != num_columns) {
                         putchar (separator);
                      }
                  }
                  if (c == EOF) {
                     break;
                  }
                  putchar ('\n');
                  cp = line;
                  ap = fp;
                  *ap++ = cp;
               } else if (c == separator) {
                  *cp++ = '\0';
                  if (ap >= fp + MAXF) {
                     fprintf (stderr, "field: some lines have more than %d fie
                     exit (1);
                  }
                  *ap++ = cp;
               } else {
                  if (cp >= line + MAXL) {
                     fprintf (stderr, "field: some lines have more than %d cha
                     exit (1);
                  }
                  *cp++ = c;
               }


         }

         /*
          * print the error message if we have to.
          */
         if (error && check) {
            fprintf (stderr, "field: not all lines had the same number of fiel
         }

         exit (0);
 }


 /*
  * output field n from the current line to the standard output.
  */

 void putf (n)
 int n;
 {
         char *cp = fp [n];
         int c;

         if (n < 0 || n >= num_fields) {
            return;
         }
         while (c = *cp++) {
               putchar (c);
         }
 }

 void explain (string)
 char *string;
 {
         fprintf (stderr, "\n%s\n\n", string);
         fprintf (stderr, "%s:\nusage: [-tc -c] n [n n ...]\n", VERSION);
         fprintf (stderr, "Selects fields or columns from a file.\n");
         fprintf (stderr, "Fields are numbered from 1 and a field may be reque
         fprintf (stderr, "Options:\n-tc\tSet the field separator to c (defaul
         fprintf (stderr, "-c\tCheck that all input records contain the same n
         exit (2);
 }

 /*
  * compensates for someone typing "-t " to get space for a separator.
  * this is needed since "-t " is changed to "-t" on the command line
  */

 int fixup (value)
 int value;
 {
         if (value == 0) {
            value = ' ';
         }
         return (value);
 }



 FILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\FILE.C

 /*     FILE.C   FILE.C    FILE.C    FILE.C    FILE.C    FILE.C

 FILE INPUT AND OUTPUT         XXXXX  XXX  X      XXXXX
                               X       X   X      X
 July 1,1987                   X       X   X      X
                               XXX     X   X      XXX
                               X       X   X      X
                               X       X   X      X
                               X      XXX  XXXXX  XXXXX
 */
 #include "stdio.h"
 #include "string.h"
 #include "alloc.h"
 #include "struct.def"
 #include "defin.h"

 int lastline = 0;
 int arrowln = 0;
 extern struct lines *top, *bot, *q, *p, *arrow, *trnsend;
 extern struct vars allvars[];
 extern int varinuse;
 extern int printit;
 extern char inline[];
 extern int errcode;
 extern int ignore;
 extern int trnsattr;

 /* ******************************************************** fileout */
 /* This routine opens a disk file and writes the marked lines in the*/
 /* transcript to that file.                                         */
 void fileout(void)
 {
 char *lpt, fileout[25];
 struct lines *pt;
 int i;
 FILE *fp2;

    poscurs(23,1);                  /* read in filename to output to */
    printf("     filename >                    <");
    poscurs(23,17);
    for (i = 0;(fileout[i] = getchar()) != '\n';++i);
    fileout[i] = 0;                /* filename read in, ready to use */
    fp2 = fopen(fileout,"w");                           /* open file */
    pt = top;                        /* start at top of llinked list */
    do {
       lpt = pt->lineloc;                     /* line of text stored */
       if (pt->marked){                  /* only output marked lines */
          fputs(lpt,fp2);                           /* output a line */
          fputs("\n",fp2);                         /* and a linefeed */
       }
       pt = pt->dn;                             /* get the next line */
    } while (pt != NULL);
    fflush(fp2);                           /* flush the file to disk */
    fclose(fp2);                                   /* close the file */
    poscurs(23,7);
    printf("  input >                     ");
 }

 /* ********************************************************* filein */
 /* A diskfile is opened and read into the transcript window while   */
 /* all calculations are done as the file is input. If any errors are*/
 /* found, the calculations are not done, zero is returned as a      */
 /* result and the remainder of the file is read in. It is assumed   */
 /* that the equations are correct before the file was originally    */
 /* written.                                                         */
 char filenam[25] = "help";        /* default filename to start with */
 void filein(void)
 {
 char filein[25];
 char *fc;
 int i;
 FILE *fp2;

    poscurs(23,1);                      /*read in filename for input */
    printf("     filename >                    <");
    poscurs(23,17);
    for (i = 0; (filein[i] = getchar()) != '\n';++i);
    filein[i] = 0;                /* filename read in , ready to use */
    if (filein[0] == 0)                  /* if no filename was input */
       strcpy(filein,filenam);            /* use last valid filemane */
    else
       strcpy(filenam,filein);                 /* save for later use */
    fp2 = fopen(filein,"r");                            /* open file */
    if (fp2 == NULL) {                         /* file doesn't exist */
       errcode = 11;
       errout();
    }
    else {
       do {
          fc = (fgets(inline,62,fp2));
          if (fc == NULL) break;
          for (i=0;inline[i];++i);
          inline[i-1] = 0;
           parse();
          if ((ignore == 1) || errcode)
             strtrans(inline,0);
          else
             strtrans(inline,1);
          transout();
       } while (i != NULL);
    }
    for (i = 0;i < 200;++i) inline[i] = 0;       /* clear input area */
    poscurs(23,7);
    printf("  input >                      ");
 }

 /* ******************************************************* strtrans */
 /* A line from the input area or from a file input is stored in the */
 /* transcript area. It is stored in the transcript array here, and  */
 /* output to the transcript window in the "transout" function.      */
 /* This function uses a linked list to store the lines of data.     */
 void strtrans(char line[],int type)
 {
 int i;
 long int temp;
 char *pt;
 char buffer[25];     /* this is long enough to include an overwrite */
 double xx;                                    /* temporary variable */
 extern FILE *prtfile;                          /* print file output */

    p = (struct lines *)malloc(sizeof(struct lines));
    pt = (char *)malloc(1 + strlen(line));
    if ((p == NULL) || (pt == NULL)) {              /* out of memory */
       errcode = 13;
       errout();
    }

    else {                  /* there is enough memory for this entry */
       if (top == NULL){                               /* first entry */
           top = bot = p;
           p->dn = NULL;
           p->up = NULL;
       }
       else {                                  /* additional entries */
           bot->dn = p;
           p->up = bot;
           p->dn = NULL;
           bot = p;
       }

       p->lineloc = pt;
       i = strlen(line);
       p->isvalue = type;
       p->marked = type;
       p->linelngt = i;
       if (type) {
          xx = allvars[varinuse].value;
          if (xx < 0.0) xx = -xx;
          if ((xx > 9999999.0) || (xx < .001))
             sprintf(buffer,"%12.5e",allvars[varinuse].value);
          else
             sprintf(buffer,"%12.6f",allvars[varinuse].value);
          buffer[12] = 0;
          if (varinuse > 5) {                /* variable I through N */
             temp = allvars[varinuse].value;
             temp = temp & 077777777;
             if (allvars[varinuse].outtype == 'D')
                sprintf(buffer,"(D) %8ld",temp);
             if (allvars[varinuse].outtype == 'O')
                sprintf(buffer,"(O) %8lo",temp);
             if ((allvars[varinuse].outtype == 'X') ||
                 (allvars[varinuse].outtype == 'H'))
                sprintf(buffer,"(H) %8lx",temp);
          }
          strcpy(p->strval,buffer);
       }
       else
          strcpy(p->strval,"            ");
       line[i] = '\0';                            /* line terminator */
       strcpy(pt,line);
       if (type && printit){
          fprintf(prtfile,"%13s  %-62s\n",buffer,line);
       }
       arrow = p;
       trnsend = p;
       lastline++;
       arrowln = lastline;
    }
 }

 /* ******************************************************* transout */
 /* This function outputs the transcript to the transcript window    */
 extern char strngout[];
 void transout(void)
 {
 int i;
 int maxm = 13;       /* number of lines to output to the trans wind */
 char *pt;
    p = trnsend;
    for (i = 0;i < maxm;++i){           /* count up max from trnsend */
       if (p->up == NULL) break;                /* stop if top found */
       p = p->up;
    }
    for (i = 0;i <= maxm;++i){       /* output max fields to viddisp */
       pt = p->lineloc;                 /* pt now points to the line */
       strcpy(strngout,p->strval);
       strngdis(8+i,1,trnsattr);       /* output the formatted value */
       strcpy(strngout,pt);
       blnkline(8+i,16);                     /* write blanks to line */
       if (p->marked)
          chardis(8+i,15,trnsattr,'*');          /* marked indicator */
       else
          chardis(8+i,15,trnsattr,' ');                     /* blank */
       strngdis(8+i,17,trnsattr);
       if (arrow == p)
          chardis(8+i,14,trnsattr,16);                 /* arrow char */
       else
          chardis(8+i,14,trnsattr,' ');                     /* blank */
       if (p->dn == NULL) break;             /* stop if bottom found */
       p = p->dn;
    }
    poscurs(23,3);
    printf("%4d",arrowln);
 }

 /* ******************************************************* movarrow */
 /* This function is used to move the arrow up or down in the window */
 /* and to control where the window begins and ends in the transcript*/
 /* data. The arrow is always two lines from the top or bottom if it */
 /* is possible to do so.                                            */
 void movarrow(int where)
 {
 int index;
 struct lines *temp;
 int iend, iarrow, itrnsend;
    iend = iarrow = itrnsend = 0;
    if (where > 0) {
       for (index = where;index && (arrow != bot);--index)
          arrow = arrow->dn;                  /* move arrow down one */
       for (temp = top,index = 0;temp != bot;index++) {
          if (temp == arrow) iarrow = index;         /* locate arrow */
          if (temp == trnsend) itrnsend = index;  /* loc display end */
          temp = temp->dn;
       }
       if (temp == arrow) iarrow = index;          /* if they are at */
       if (temp == trnsend) itrnsend = index;      /* the bottom end */
       iend = index;
            /* now trnsend must be >= arrow, but not by more than 10 */
       if (iarrow == iend) index = iend - itrnsend;
       else if (itrnsend < (iarrow+1)) index = iarrow - itrnsend + 1;
       else index = 0;
    }
    else {
       for (index = -where;index && (arrow != top);--index)
          arrow = arrow->up;                    /* move arrow up one */
 /*    if (arrow == top) arrow = arrow->dn;      move one field down */
       for (temp = top,index = 0;temp != bot;index++) {
          if (temp == arrow) iarrow = index;         /* locate arrow */
          if (temp == trnsend) itrnsend = index;  /* loc display end */
          temp = temp->dn;
       }
       if (temp == arrow) iarrow = index;          /* if they are at */
       if (temp == trnsend) itrnsend = index;      /* the bottom end */
       iend = index;
            /* now trnsend must be >= arrow, but not by more than 12 */
       if (iarrow == 0) index = (iend > 13?13:iend) - itrnsend;
       else if ((itrnsend - iarrow) > 12) index = iarrow-itrnsend+12;
       else index = 0;
    }
    if (index > 0)
       for (;index > 0;--index)
          trnsend = trnsend->dn;
    else if (index < 0)
       for (;index < 0;++index)
          trnsend = trnsend->up;
    arrowln = iarrow;
    transout();
 }


 FILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\FILE.C

 /*        FILE.C:   for MicroEMACS

         The routines in this file handle the reading, writing
         and lookup of disk files.  All of details about the
         reading and writing of the disk are in "fileio.c".

 */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 /*
  * Read a file into the current
  * buffer. This is really easy; all you do it
  * find the name of the file, and call the standard
  * "read a file into the current buffer" code.
  * Bound to "C-X C-R".
  */
 fileread(f, n)
 {
         register int    s;
         char fname[NFILEN];

         if (restflag)                /* don't allow this command if restricte
                 return(resterr());
         if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
                 return(s);
         return(readin(fname, TRUE));
 }

 /*
  * Insert a file into the current
  * buffer. This is really easy; all you do it
  * find the name of the file, and call the standard
  * "insert a file into the current buffer" code.
  * Bound to "C-X C-I".
  */
 insfile(f, n)
 {
         register int    s;
         char fname[NFILEN];

         if (restflag)                /* don't allow this command if restricte
                 return(resterr());
         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
                 return(s);
         return(ifile(fname));
 }

 /*
  * Select a file for editing.
  * Look around to see if you can find the
  * fine in another buffer; if you can find it
  * just switch to the buffer. If you cannot find
  * the file, create a new buffer, read in the
  * text, and switch to the new buffer.
  * Bound to C-X C-F.
  */
 filefind(f, n)
 {
         char fname[NFILEN];        /* file user wishes to find */
         register int s;                /* status return */

         if (restflag)                /* don't allow this command if restricte
                 return(resterr());
         if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
                 return(s);
         return(getfile(fname, TRUE));
 }

 viewfile(f, n)        /* visit a file in VIEW mode */
 {
         char fname[NFILEN];        /* file user wishes to find */
         register int s;                /* status return */
         register WINDOW *wp;        /* scan for windows that need updating */

         if (restflag)                /* don't allow this command if restricte
                 return(resterr());
         if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
                 return (s);
         s = getfile(fname, FALSE);
         if (s) {        /* if we succeed, put it in view mode */
                 curwp->w_bufp->b_mode |= MDVIEW;

                 /* scan through and update mode lines of all windows */
                 wp = wheadp;
                 while (wp != NULL) {
                         wp->w_flag |= WFMODE;
                         wp = wp->w_wndp;
                 }
         }
         return(s);
 }

 #if        CRYPT
 resetkey()        /* reset the encryption key if needed */

 {
         register int s;        /* return status */

         /* turn off the encryption flag */
         cryptflag = FALSE;

         /* if we are in crypt mode */
         if (curbp->b_mode & MDCRYPT) {
                 if (curbp->b_key[0] == 0) {
                         s = setkey(FALSE, 0);
                         if (s != TRUE)
                                 return(s);
                 }

                 /* let others know... */
                 cryptflag = TRUE;

                 /* and set up the key to be used! */
                 /* de-encrypt it */
                 crypt((char *)NULL, 0);
                 crypt(curbp->b_key, strlen(curbp->b_key));

                 /* re-encrypt it...seeding it to start */
                 crypt((char *)NULL, 0);
                 crypt(curbp->b_key, strlen(curbp->b_key));
         }

         return(TRUE);
 }
 #endif

 getfile(fname, lockfl)

 char fname[];                /* file name to find */
 int lockfl;                /* check the file for locks? */

 {
         register BUFFER *bp;
         register LINE   *lp;
         register int    i;
         register int    s;
         char bname[NBUFN];        /* buffer name to put file */

 #if        MSDOS
         mklower(fname);                /* msdos isn't case sensitive */
 #endif
         for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
                 if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0)
                         swbuffer(bp);
                         lp = curwp->w_dotp;
                         i = curwp->w_ntrows/2;
                         while (i-- && lback(lp)!=curbp->b_linep)
                                 lp = lback(lp);
                         curwp->w_linep = lp;
                         curwp->w_flag |= WFMODE|WFHARD;
                         mlwrite("[Old buffer]");
                         return (TRUE);
                 }
         }
         makename(bname, fname);                 /* New buffer name.     */
         while ((bp=bfind(bname, FALSE, 0)) != NULL) {
                 /* old buffer name conflict code */
                 s = mlreply("Buffer name: ", bname, NBUFN);
                 if (s == ABORT)                 /* ^G to just quit      */
                         return (s);
                 if (s == FALSE) {               /* CR to clobber it     */
                         makename(bname, fname);
                         break;
                 }
         }
         if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
                 mlwrite("Cannot create buffer");
                 return (FALSE);
         }
         if (--curbp->b_nwnd == 0) {             /* Undisplay.           */
                 curbp->b_dotp = curwp->w_dotp;
                 curbp->b_doto = curwp->w_doto;
                 curbp->b_markp = curwp->w_markp;
                 curbp->b_marko = curwp->w_marko;
         }
         curbp = bp;                             /* Switch to it.        */
         curwp->w_bufp = bp;
         curbp->b_nwnd++;
         return(readin(fname, lockfl));          /* Read it in.          */
 }

 /*
         Read file "fname" into the current buffer, blowing away any text
         found there.  Called by both the read and find commands.  Return
         the final status of the read.  Also called by the mainline, to
         read in a file specified on the command line as an argument.
         The command bound to M-FNR is called after the buffer is set up
         and before it is read.
 */

 readin(fname, lockfl)

 char    fname[];        /* name of file to read */
 int        lockfl;                /* check for file locks? */

 {
         register LINE   *lp1;
         register LINE   *lp2;
         register int    i;
         register WINDOW *wp;
         register BUFFER *bp;
         register int    s;
         register int    nbytes;
         register int    nline;
         register char        *sptr;                /* pointer into filename s
         int                lflag;                /* any lines longer than all
         char mesg[NSTRING];

 #if        FILOCK
         if (lockfl && lockchk(fname) == ABORT)
                 return(ABORT);
 #endif
 #if        CRYPT
         s = resetkey();
         if (s != TRUE)
                 return(s);
 #endif
         bp = curbp;                             /* Cheap.               */
         if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
                 return (s);
         bp->b_flag &= ~(BFINVS|BFCHG);
         strcpy(bp->b_fname, fname);

         /* let a user macro get hold of things...if he wants */
         execute(META|SPEC|'R', FALSE, 1);

         /* turn off ALL keyboard translation in case we get a dos error */
         TTkclose();

         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
                 goto out;

         if (s == FIOFNF) {                      /* File not found.      */
                 mlwrite("[New file]");
                 goto out;
         }

         /* read the file in */
         mlwrite("[Reading file]");
         nline = 0;
         lflag = FALSE;
         while ((s=ffgetline()) == FIOSUC) {
                 nbytes = strlen(fline);
                 if ((lp1=lalloc(nbytes)) == NULL) {
                         s = FIOMEM;             /* Keep message on the  */
                         break;                  /* display.             */
                 }
                 lp2 = lback(curbp->b_linep);
                 lp2->l_fp = lp1;
                 lp1->l_fp = curbp->b_linep;
                 lp1->l_bp = lp2;
                 curbp->b_linep->l_bp = lp1;
                 for (i=0; i<nbytes; ++i)
                         lputc(lp1, i, fline[i]);
                 ++nline;
         }
         ffclose();                              /* Ignore errors.       */
         strcpy(mesg, "[");
         if (s==FIOERR)
                 strcat(mesg, "I/O ERROR, ");
         if (s == FIOMEM)
                 strcat(mesg, "OUT OF MEMORY, ");
         sprintf(&mesg[strlen(mesg)], "Read %d line", nline);
         if (nline > 1)
                 strcat(mesg, "s");
         strcat(mesg, "]");
         mlwrite(mesg);

 out:
         TTkopen();        /* open the keyboard again */
         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
                 if (wp->w_bufp == curbp) {
                         wp->w_linep = lforw(curbp->b_linep);
                         wp->w_dotp  = lforw(curbp->b_linep);
                         wp->w_doto  = 0;
                         wp->w_markp = NULL;
                         wp->w_marko = 0;
                         wp->w_flag |= WFMODE|WFHARD;
                 }
         }
         if (s == FIOERR || s == FIOFNF)                /* False if error.
                 return(FALSE);
         return (TRUE);
 }

 /*
  * Take a file name, and from it
  * fabricate a buffer name. This routine knows
  * about the syntax of file names on the target system.
  * I suppose that this information could be put in
  * a better place than a line of code.
  */
 makename(bname, fname)
 char    bname[];
 char    fname[];
 {
         register char *cp1;
         register char *cp2;

         cp1 = &fname[0];
         while (*cp1 != 0)
                 ++cp1;

 #if     AMIGA
         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
                 --cp1;
 #endif
 #if     VMS
         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
                 --cp1;
 #endif
 #if     CPM
         while (cp1!=&fname[0] && cp1[-1]!=':')
                 --cp1;
 #endif
 #if     MSDOS
         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
                 --cp1;
 #endif
 #if     ST520
         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\')
                 --cp1;
 #endif
 #if     FINDER
         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
                 --cp1;
 #endif
 #if     V7 | USG | BSD
         while (cp1!=&fname[0] && cp1[-1]!='/')
                 --cp1;
 #endif
         cp2 = &bname[0];
         while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
                 *cp2++ = *cp1++;
         *cp2 = 0;
 }

 unqname(name)        /* make sure a buffer name is unique */

 char *name;        /* name to check on */

 {
         register char *sp;

         /* check to see if it is in the buffer list */
         while (bfind(name, 0, FALSE) != NULL) {

                 /* go to the end of the name */
                 sp = name;
                 while (*sp)
                         ++sp;
                 if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) {
                         *sp++ = '0';
                         *sp = 0;
                 } else
                         *(--sp) += 1;
         }
 }

 /*
  * Ask for a file name, and write the
  * contents of the current buffer to that file.
  * Update the remembered file name and clear the
  * buffer changed flag. This handling of file names
  * is different from the earlier versions, and
  * is more compatable with Gosling EMACS than
  * with ITS EMACS. Bound to "C-X C-W".
  */
 filewrite(f, n)
 {
         register WINDOW *wp;
         register int    s;
         char            fname[NFILEN];

         if (restflag)                /* don't allow this command if restricte
                 return(resterr());
         if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
                 return (s);
         if ((s=writeout(fname)) == TRUE) {
                 strcpy(curbp->b_fname, fname);
                 curbp->b_flag &= ~BFCHG;
                 wp = wheadp;                    /* Update mode lines.   */
                 while (wp != NULL) {
                         if (wp->w_bufp == curbp)
                                 wp->w_flag |= WFMODE;
                         wp = wp->w_wndp;
                 }
         }
         return (s);
 }

 /*
  * Save the contents of the current
  * buffer in its associatd file. No nothing
  * if nothing has changed (this may be a bug, not a
  * feature). Error if there is no remembered file
  * name for the buffer. Bound to "C-X C-S". May
  * get called by "C-Z".
  */
 filesave(f, n)
 {
         register WINDOW *wp;
         register int    s;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
                 return (TRUE);
         if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
                 mlwrite("No file name");
                 return (FALSE);
         }
         if ((s=writeout(curbp->b_fname)) == TRUE) {
                 curbp->b_flag &= ~BFCHG;
                 wp = wheadp;                    /* Update mode lines.   */
                 while (wp != NULL) {
                         if (wp->w_bufp == curbp)
                                 wp->w_flag |= WFMODE;
                         wp = wp->w_wndp;
                 }
         }
         return (s);
 }

 /*
  * This function performs the details of file
  * writing. Uses the file management routines in the
  * "fileio.c" package. The number of lines written is
  * displayed. Sadly, it looks inside a LINE; provide
  * a macro for this. Most of the grief is error
  * checking of some sort.
  */
 writeout(fn)
 char    *fn;
 {
         register int    s;
         register LINE   *lp;
         register int    nline;

 #if        CRYPT
         s = resetkey();
         if (s != TRUE)
                 return(s);
 #endif
         /* turn off ALL keyboard translation in case we get a dos error */
         TTkclose();

         if ((s=ffwopen(fn)) != FIOSUC) {        /* Open writes message. */
                 TTkopen();
                 return (FALSE);
         }
         mlwrite("[Writing...]");                /* tell us were writing */
         lp = lforw(curbp->b_linep);             /* First line.          */
         nline = 0;                              /* Number of lines.     */
         while (lp != curbp->b_linep) {
                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
                         break;
                 ++nline;
                 lp = lforw(lp);
         }
         if (s == FIOSUC) {                      /* No write error.      */
                 s = ffclose();
                 if (s == FIOSUC) {              /* No close error.      */
                         if (nline == 1)
                                 mlwrite("[Wrote 1 line]");
                         else
                                 mlwrite("[Wrote %d lines]", nline);
                 }
         } else                                  /* Ignore close error   */
                 ffclose();                      /* if a write error.    */
         TTkopen();
         if (s != FIOSUC)                        /* Some sort of error.  */
                 return (FALSE);
         return (TRUE);
 }

 /*
  * The command allows the user
  * to modify the file name associated with
  * the current buffer. It is like the "f" command
  * in UNIX "ed". The operation is simple; just zap
  * the name in the BUFFER structure, and mark the windows
  * as needing an update. You can type a blank line at the
  * prompt if you wish.
  */
 filename(f, n)
 {
         register WINDOW *wp;
         register int    s;
         char            fname[NFILEN];

         if (restflag)                /* don't allow this command if restricte
                 return(resterr());
         if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
                 return (s);
         if (s == FALSE)
                 strcpy(curbp->b_fname, "");
         else
                 strcpy(curbp->b_fname, fname);
         wp = wheadp;                            /* Update mode lines.   */
         while (wp != NULL) {
                 if (wp->w_bufp == curbp)
                         wp->w_flag |= WFMODE;
                 wp = wp->w_wndp;
         }
         curbp->b_mode &= ~MDVIEW;        /* no longer read only mode */
         return (TRUE);
 }

 /*
  * Insert file "fname" into the current
  * buffer, Called by insert file command. Return the final
  * status of the read.
  */
 ifile(fname)
 char    fname[];
 {
         register LINE   *lp0;
         register LINE   *lp1;
         register LINE   *lp2;
         register int    i;
         register BUFFER *bp;
         register int    s;
         register int    nbytes;
         register int    nline;
         int                lflag;                /* any lines longer than all
         char mesg[NSTRING];

         bp = curbp;                             /* Cheap.               */
         bp->b_flag |= BFCHG;                        /* we have changed
         bp->b_flag &= ~BFINVS;                        /* and are not temporar
         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
                 goto out;
         if (s == FIOFNF) {                      /* File not found.      */
                 mlwrite("[No such file]");
                 return(FALSE);
         }
         mlwrite("[Inserting file]");

 #if        CRYPT
         s = resetkey();
         if (s != TRUE)
                 return(s);
 #endif
         /* back up a line and save the mark here */
         curwp->w_dotp = lback(curwp->w_dotp);
         curwp->w_doto = 0;
         curwp->w_markp = curwp->w_dotp;
         curwp->w_marko = 0;

         nline = 0;
         lflag = FALSE;
         while ((s=ffgetline()) == FIOSUC) {
                 nbytes = strlen(fline);
                 if ((lp1=lalloc(nbytes)) == NULL) {
                         s = FIOMEM;             /* Keep message on the  */
                         break;                  /* display.             */
                 }
                 lp0 = curwp->w_dotp;        /* line previous to insert */
                 lp2 = lp0->l_fp;        /* line after insert */

                 /* re-link new line between lp0 and lp2 */
                 lp2->l_bp = lp1;
                 lp0->l_fp = lp1;
                 lp1->l_bp = lp0;
                 lp1->l_fp = lp2;

                 /* and advance and write out the current line */
                 curwp->w_dotp = lp1;
                 for (i=0; i<nbytes; ++i)
                         lputc(lp1, i, fline[i]);
                 ++nline;
         }
         ffclose();                              /* Ignore errors.       */
         curwp->w_markp = lforw(curwp->w_markp);
         strcpy(mesg, "[");
         if (s==FIOERR)
                 strcat(mesg, "I/O ERROR, ");
         if (s == FIOMEM)
                 strcat(mesg, "OUT OF MEMORY, ");
         sprintf(&mesg[strlen(mesg)], "Inserted %d line", nline);
         if (nline > 1)
                 strcat(mesg, "s");
         strcat(mesg, "]");
         mlwrite(mesg);

 out:
         /* advance to the next line and mark the window for changes */
         curwp->w_dotp = lforw(curwp->w_dotp);
         curwp->w_flag |= WFHARD | WFMODE;

         /* copy window parameters back to the buffer structure */
         curbp->b_dotp = curwp->w_dotp;
         curbp->b_doto = curwp->w_doto;
         curbp->b_markp = curwp->w_markp;
         curbp->b_marko = curwp->w_marko;

         if (s == FIOERR)                        /* False if error.      */
                 return (FALSE);
         return (TRUE);
 }


 FILEIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\FILEIO.C

 /*
  * STEVIE - ST Editor for VI Enthusiasts   ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 void
 filemess(s)
 char *s;
 {
         smsg("\"%s\" %s", (Filename == NULL) ? "" : Filename, s);
 }

 void
 renum()
 {
         LPTR        *p;
         unsigned int l = 0;

         for (p = Filemem; p != NULL ;p = nextline(p), l += LINEINC)
                 p->linep->num = l;

         Fileend->linep->num = 0xffff;
 }

 #ifdef        MEGAMAX
 overlay "fileio"
 #endif

 bool_t
 readfile(fname,fromp,nochangename)
 char        *fname;
 LPTR        *fromp;
 bool_t        nochangename;        /* if TRUE, don't change the Filename */
 {
         FILE        *f, *fopen();
         LINE        *curr;
         char        buff[1024];
         char        *p;
         int        i, c;
         long        nchars;
         int        unprint = 0;
         int        linecnt = 0;
         bool_t        wasempty = bufempty();

         curr = fromp->linep;

         if ( ! nochangename )
                 Filename = strsave(fname);

         if ( (f=fopen(fname,"r")) == NULL )
                 return TRUE;

         filemess("");

         for (i=nchars=0; (c=getc(f)) != EOF ;nchars++) {
                 if (c >= 0x80) {
                         c -= 0x80;
                         unprint++;
                 }

                 /*
                  * Nulls are special, so they can't show up in the file.
                  * We should count nulls seperate from other nasties, but
                  * this is okay for now.
                  */
                 if (c == NUL) {
                         unprint++;
                         continue;
                 }

                 if (c == '\n') {        /* process the completed line */
                         int        len;
                         LINE        *lp;

                         buff[i] = '\0';
                         len = strlen(buff) + 1;
                         if ((lp = newline(len)) == NULL)
                                 exit(1);

                         strcpy(lp->s, buff);

                         curr->next->prev = lp;        /* new line to next one
                         lp->next = curr->next;

                         curr->next = lp;        /* new line to prior one */
                         lp->prev = curr;

                         curr = lp;                /* new line becomes current
                         i = 0;
                         linecnt++;
                 }
                 else
                         buff[i++] = c;
         }
         fclose(f);

         /*
          * If the buffer was empty when we started, we have to go back
          * and remove the "dummy" line at Filemem and patch up the ptrs.
          */
         if (wasempty) {
                 LINE        *dummy = Filemem->linep;        /* dummy line ptr

                 free(dummy->s);                                /* free string
                 Filemem->linep = Filemem->linep->next;
                 free(dummy);                                /* free LINE stru
                 Filemem->linep->prev = NULL;

                 Curschar->linep = Filemem->linep;
                 Topchar->linep  = Filemem->linep;
         }

         if ( unprint > 0 )
                 p="\"%s\" %d lines, %ld characters (%d un-printable))";
         else
                 p="\"%s\" %d lines, %ld characters";

         sprintf(buff, p, fname, linecnt, nchars, unprint);
         msg(buff);
         renum();
         return FALSE;
 }


 /*
  * writeit - write to file 'fname' lines 'start' through 'end'
  *
  * If either 'start' or 'end' contain null line pointers, the default
  * is to use the start or end of the file respectively.
  */
 bool_t
 writeit(fname, start, end)
 char        *fname;
 LPTR        *start, *end;
 {
         FILE        *f, *fopen();
         FILE        *fopenb();                /* open in binary mode, where n
         char        buff[80];
         char        backup[16], *s;
         long        nchars;
         int        lines;
         LPTR        *p;

         sprintf(buff, "\"%s\"", fname);
         msg(buff);

         /*
          * Form the backup file name - change foo.* to foo.bak
          */
         strcpy(backup, fname);
         for (s = backup; *s && *s != '.' ;s++)
                 ;
         *s = NUL;
         strcat(backup, ".bak");

         /*
          * Delete any existing backup and move the current version
          * to the backup. For safety, we don't remove the backup
          * until the write has finished successfully. And if the
          * 'backup' option is set, leave it around.
          */
         rename(fname, backup);


         f = P(P_CR) ? fopen(fname, "w") : fopenb(fname, "w");

         if ( f == NULL ) {
                 emsg("Can't open file for writing!");
                 return FALSE;
         }

         /*
          * If we were given a bound, start there. Otherwise just
          * start at the beginning of the file.
          */
         if (start == NULL || start->linep == NULL)
                 p = Filemem;
         else
                 p = start;

         lines = nchars = 0;
         do {
                 fprintf(f, "%s\n", p->linep->s);
                 nchars += strlen(p->linep->s) + 1;
                 lines++;

                 /*
                  * If we were given an upper bound, and we just did that
                  * line, then bag it now.
                  */
                 if (end != NULL && end->linep != NULL) {
                         if (end->linep == p->linep)
                                 break;
                 }

         } while ((p = nextline(p)) != NULL);

         fclose(f);
         sprintf(buff,"\"%s\" %d lines, %ld characters", fname, lines, nchars)
         msg(buff);
         UNCHANGED;

         /*
          * Remove the backup unless they want it left around
          */
         if (!P(P_BK))
                 remove(backup);

         return TRUE;
 }


 FILEIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\FILEIO.C

 /*
  * The routines in this file read and write ASCII files from the disk. All of
  * the knowledge about files are here.
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 FILE        *ffp;                /* File pointer, all functions. */
 int eofflag;                /* end-of-file flag */

 /*
  * Open a file for reading.
  */
 ffropen(fn)
 char    *fn;
 {
         if ((ffp=fopen(fn, "r")) == NULL)
                 return (FIOFNF);
         eofflag = FALSE;
         return (FIOSUC);
 }

 /*
  * Open a file for writing. Return TRUE if all is well, and FALSE on error
  * (cannot create).
  */
 ffwopen(fn)
 char    *fn;
 {
 #if     VMS
         register int    fd;

         if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
         || (ffp=fdopen(fd, "w")) == NULL) {
 #else
         if ((ffp=fopen(fn, "w")) == NULL) {
 #endif
                 mlwrite("Cannot open file for writing");
                 return (FIOERR);
         }
         return (FIOSUC);
 }

 /*
  * Close a file. Should look at the status in all systems.
  */
 ffclose()
 {
         /* free this since we do not need it anymore */
         if (fline) {
                 free(fline);
                 fline = NULL;
         }

 #if        MSDOS & CTRLZ
         fputc(26, ffp);                /* add a ^Z at the end of the file */
 #endif

 #if     V7 | USG | BSD | (MSDOS & (LATTICE | MSC | TURBO))
         if (fclose(ffp) != FALSE) {
                 mlwrite("Error closing file");
                 return(FIOERR);
         }
         return(FIOSUC);
 #else
         fclose(ffp);
         return (FIOSUC);
 #endif
 }

 /*
  * Write a line to the already opened file. The "buf" points to the buffer,
  * and the "nbuf" is its length, less the free newline. Return the status.
  * Check only at the newline.
  */
 ffputline(buf, nbuf)
 char    buf[];
 {
         register int    i;
 #if        CRYPT
         char c;                /* character to translate */

         if (cryptflag) {
                 for (i = 0; i < nbuf; ++i) {
                         c = buf[i] & 0xff;
                         crypt(&c, 1);
                         fputc(c, ffp);
                 }
         } else
                 for (i = 0; i < nbuf; ++i)
                         fputc(buf[i]&0xFF, ffp);
 #else
         for (i = 0; i < nbuf; ++i)
                 fputc(buf[i]&0xFF, ffp);
 #endif

 #if        ST520
         fputc('\r', ffp);
 #endif
         fputc('\n', ffp);

         if (ferror(ffp)) {
                 mlwrite("Write I/O error");
                 return (FIOERR);
         }

         return (FIOSUC);
 }

 /*
  * Read a line from a file, and store the bytes in the supplied buffer. The
  * "nbuf" is the length of the buffer. Complain about long lines and lines
  * at the end of the file that don't have a newline present. Check for I/O
  * errors too. Return status.
  */
 ffgetline()

 {
         register int c;                /* current character read */
         register int i;                /* current index into fline */
         register char *tmpline;        /* temp storage for expanding line */

         /* if we are at the end...return it */
         if (eofflag)
                 return(FIOEOF);

         /* dump fline if it ended up too big */
         if (flen > NSTRING) {
                 free(fline);
                 fline = NULL;
         }

         /* if we don't have an fline, allocate one */
         if (fline == NULL)
                 if ((fline = malloc(flen = NSTRING)) == NULL)
                         return(FIOMEM);

         /* read the line in */
         i = 0;
         while ((c = fgetc(ffp)) != EOF && c != '\n') {
                 fline[i++] = c;
                 /* if it's longer, get more room */
                 if (i >= flen) {
                         if ((tmpline = malloc(flen+NSTRING)) == NULL)
                                 return(FIOMEM);
                         strncpy(tmpline, fline, flen);
                         flen += NSTRING;
                         free(fline);
                         fline = tmpline;
                 }
         }

 #if        ST520
         if(fline[i-1] == '\r')
                 i--;
 #endif

         /* test for any errors that may have occured */
         if (c == EOF) {
                 if (ferror(ffp)) {
                         mlwrite("File read error");
                         return(FIOERR);
                 }

                 if (i != 0)
                         eofflag = TRUE;
                 else
                         return(FIOEOF);
         }

         /* terminate and decrypt the string */
         fline[i] = 0;
 #if        CRYPT
         if (cryptflag)
                 crypt(fline, strlen(fline));
 #endif
         return(FIOSUC);
 }

 #if        AZTEC & MSDOS
 #undef        fgetc
 /*        a1getc:                Get an ascii char from the file input stream
                         but DO NOT strip the high bit
 */

 int a1getc(fp)

 FILE *fp;

 {
         int c;                /* translated character */

         c = getc(fp);        /* get the character */

         /* if its a <LF> char, throw it out  */
         while (c == 10)
                 c = getc(fp);

         /* if its a <RETURN> char, change it to a LF */
         if (c == '\r')
                 c = '\n';

         /* if its a ^Z, its an EOF */
         if (c == 26)
                 c = EOF;

         return(c);
 }
 #endif


 FILEIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\FILEIO.C

 /****************************************************************************
 /*                                                                          *
 /* This function was written by Jim Niederriter for the Lattice `C' Compiler*
 /* on the IBM Personal Computer or compatible, running DOS 2.0.             *
 /*                                                                          *
 /****************************************************************************
 /*  fileio.c  */

 /*  This file is a group of several useful I/O functions */

 /*  open_fil()  */
 /*  this function opens a disk file in untranslated mode. The arguments */
 /*  required are the filename pointer, and the mode of operation.  */
 /*  It returns the file number.  */
 /*  Valid modes are: 0=read, 1=write, 2=read/write  */
 /*  NOTE: Untranslated mode is required for binary files, but not for */
 /*  ASCII files. Untranslated is specified by turning on bit 15 of    */
 /*  the MODE value.  */

 int open_fil(filename, mode)
 char filename[];
 int mode;
 {
      int f1;                            /* declare file numberint */
      mode |= 0x8000;                    /* set on bit 15 of mode  */
      f1 = open(filename, mode);
      return(f1);                        /* return file number  */
 }
 Š


 /*  get_rec()  */
 /*  this function gets a specific record from a random file. The */
 /*  required arguments are the file number, file length, relative record */
 /*  number, and a pointer to the input data structure.  */
 /*  It returns 0 if successful, or 1 if unsuccessful (read past EOF) */

 int get_rec(filenum, filelgth, recno, structur)
 int filenum, filelgth, recno;
 char  structur[];
 {
      int stats;
      long offset, rtrn, lseek();

      offset = (long) (recno-1) * filelgth;
      rtrn = lseek(filenum, offset, 0);
      stats = read(filenum, structur, filelgth);
      if (stats > 0l) {
           return(0);
      }    else {
                return(1);
           }
 }

 /*  wrt_rec()  */
 /*  this function writes a specific record to a random file. The */
 /*  required arguments are the file number, file length, relative record */
 /*  number, and a pointer to the input data structure.  */
 /*  It returns 0 if successful, or 1 if unsuccessful */

 int wrt_rec(filenum, filelgth, recno, structur)
 int filenum, filelgth, recno;
 char structur[];
 {
      int stats, c;
      long offset, rtrn, lseek();

      offset = (long) (recno-1) * filelgth;
      rtrn = lseek(filenum, offset, 0);
      stats = write(filenum, structur, filelgth);
      if (stats > 0l) {
           return(0);
      } else {
           return(1);
      }
 }

 /*  wrt_add()  */
 /*  this function appends a record to the end of a sequential file. The  */
 /*  required arguments are the file number, file length, and a pointer  */
 /*  to the input data structure.  */
 /*  It returns 0 if successful, or 1 if unsuccessful */

 int wrt_add(filenum, filelgth, structur)
 int filenum, filelgth;
 char structur[];
 {
      int stats, c;
      long rtrn, lseek();

      rtrn = lseek(filenum, 0L, 2);
      stats = write(filenum, structur, filelgth);
      if (stats > 0l) {
           return(0);
      } else {
           return(1);
      }
 }


 FINDFILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FINDFILE.C

 #include <stdio.h>
 #include <io.h>

 char *findfile(afn, ext)
 register char *afn, *ext;
 /*
  *        Return full file spec for <afn> if found. If <afn> has no extension
  *        extensions from <ext> are tried until a match is found, or the list
  *        ends.  <ext> is a list of extensions separated by '\0' characters
  *        and ending with an additional '\0', ie. "ttp\0tos\0ttp\0" (note tha
  *        the final null is by the compiler to the string constant.  If <afn>
  *        alerady has an extension, <ext> is not used.  If no matching files
  *        are found, NULL is returned.  The pointer returned when a match is
  *        found points to a buffer which is internal to fullpath().  If you
  *        want to save the value returned, you must make a copy before the
  *        buffer is overwritten by subsequent calls.
  */
 {
         char *fullpath(), *strrchr(), *strchr(), *strcpy();
         register char *p;

         afn = fullpath(NULL, afn);
         if((p = strrchr(afn, '\\')) &&
            (p = strchr(p, '.')))                /* .EXT specified */
                 return(access(afn, _ACCr) ? afn : NULL);
         p = strrchr(afn, '\0');
         *p++ = '.';
         do {                                                /* try list .EXT'
                 strcpy(p, ext);
                 if(access(afn, _ACCr))
                         return(afn);
                 while(*ext++)
                         ;
         } while(*ext);
         return(NULL);
 }


 FINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FINT.C

 /* 1.0  06-27-85                                                (fint.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         double
 fint(x)                        /* return integer part of x as double

 /*----------------------------------------------------------------------*/
 double x;
 {
         int i, ex2, byte;
         BITS bitmask;
         TBITS *xp;
         LOCAL TBITS mask[8] =
                 {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};

         xp = (char *) &x;

 #ifdef ECOSOFT
         ex2 = (((int) xp[0]) - 0x80);/* implied normalized bit, but sign is *
         byte = ex2 / 8 + 1;        /*         in the normalized place
         bitmask = mask[ex2 & 7];        /* i.e., % 8        */
 #endif

 #ifdef AZTEC
         ex2 = (((int) (xp[0] & 0x7f)) - 0x40); /* base 256        */
         byte = 1 + ex2;
         bitmask = 0;
 #endif

 #ifdef CPM86
         ex2 = (((int) (((xp[7] << 4) + (xp[6] >> 4)) & 0x7ff)) - 0x3fe + 3);
         byte = 6 - ex2 / 8;        /* has implied normalized bit        */
         bitmask = mask[ex2 & 7];
 #endif

 #ifdef UNIVERSE
         ex2 = (((int)(((*xp << 1) + (xp[1] &0x80 ? 1 : 0)) & 0xff)) - 0x80);
         byte = 1 + ex2 / 8; /* has normalized bit, but extended exponent */
         bitmask = mask[ex2 & 7];
 #endif
 /*\p*/

 #ifdef SUN
         ex2 = (int)(((*xp & 0x7f)<<4) + ((xp[1]>>4) & 0xf) - 0x3fe);
         byte = (i = ex2 + 11) / 8;        /* i is location of dec. pt.
         bitmask = mask[i & 7];
 #endif

         if (ex2 < 1)
                 return 0.0;

 #ifdef CPM86
         if (byte > -1)
         {        xp[byte] &= bitmask;
                 for (i = --byte; i > -1; i--)
                         xp[i] = 0;
         }
 #else
         if (byte < 8)
         {        xp[byte] &= bitmask;
                 for (i = ++byte; i < 8; i++)
                         xp[i] = 0;
         }
 #endif
         return x;
 }


 FIRSTEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\FIRSTEX.C

 main()
 {
 int index;

    for (index = 0;index < 7;index = index + 1)
       printf("First example program.\n");
 }


 FLINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\CSR20A\FLINE.C

 /*
 **  F I R S T   L I N E
 **
 **  A Structured Programming Tool.
 **
 **  Copyright 1986 Bob Pritchett
 **
 **  Created: 03/02/86  Last Updated: 03/02/86
 **
 */

 #include <stdio.h>
 #include <ctype.h>

 FILE *in, *out;

 main(argc,argv)
  int argc;
  char *argv[];
  {
   char *line;
   if ( argc != 3 )
      help();
   strcpy(argv[1],strupr(argv[1]));
   strcpy(argv[2],strupr(argv[2]));
   if ( strcmp(argv[1],argv[2]) == 0 )
    {
     printf("FLINE: Source and Output File Must be Different Files.\n");
     exit(0);
    }
   if ( ( in = fopen(argv[1],"r") ) == 00 )
    {
     printf("FLINE: Unable to open source file.\n");
     exit(0);
    }
   if ( ( out = fopen(argv[2],"w") ) == 00 )
    {
     printf("FLINE: Unable to open output file.\n");
     exit(0);
    }
   fprintf(out,"FLINE Output File for %s.\n\n",argv[1]);
   while ( fgets(line,100,in) )
    {
     if ( ! isspace(*line) )
        fprintf(out,"%s",line);
    }
   fclose(out);
   fclose(in);
   printf("FLINE: Successful.\n");
   exit(0);
  }

 help()
  {
   printf("\n    First Line is a utility for programmers who write formatted\n
   printf(" source code.  FLine goes through a source file and puts all\n");
   printf(" lines beginning with a non-whitespace character into the\n");
   printf(" output file.  This creates and easy reference file with the\n");
   printf(" name and argument list for all functions contained in the\n");
   printf(" source in addition to all global variables and include files.\n");
   printf("    Call FLine like:\n\n");
   printf("    FLINE <source> <output>\n\n");
   printf("  Version 1.1  Copyright 1986 Bob Pritchett\n");
   printf("           New Dimension Software\n");
   exit(0);
  }


 FLOAT88.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\FLOAT88.C

 /*
 ** BYTE Small-C Floating-Point Benchmark
 ** Version 1 for 8088/8086/80286
 ** March, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Operation:
 ** 1. Initialize the coprocessor.
 ** 2. Execute fourbang(), which:
 **    a. Generates space for temporaries and constants.
 **    b. Turns on stopwatch.
 **    c. Executes loop FCOUNT times.  Loop consists of:
 **       8 each of floating add, subtract, multiply, divide.
 **    d. Turns off stopwatch.
 **    e. Calculates time for an empty loop.
 **    f. Reports time and result of operations.
 ** 3. Executes finteg(), which:
 **    a. Generates space for temporaries and constants.
 **    b. Turns on stopwatch.
 **    c. Executes a trapezoidal integration method for sin(x)
 **       from 0 to pi/2.
 **    d. Turns off stopwatch.
 **    e. Calculates time for an empty loop.
 **    f. Reports time and result of operation.
 **    g. Turns on stopwatch.
 **    h. Executes a trapezoidal integration method for e^(x)
 **       from 0 to 1.
 **    i. Turns off stopwatch.
 **    j. Calculates time for an empty loop.
 **    k. Reports time and result of operation.
 ** 4. Exits.
 **
 ** NOTE:
 ** Since Small-C does not support floating-point, we simply
 ** manipluate floating-point numbers as 4-element integer
 ** arrays.  The floating-point library functions handle the
 ** actual calls to the coprocessor, including the routine
 ** to print out a floating-point number.
 **
 ** Expected results:
 ** For first test: 1.000000000E1  (10.0)
 ** For trapezoidal of sine(x): 1.000000000E0  (1.0)
 ** For trapezoidal of e^x: 1.718281828E0 (e-1)
 */

 #include stdio.h

 FCOUNT 20000        /* Number of times the four-banger test */
                         /* is repeated.                                */
 ICOUNT 32000        /* Stepsize for the integration test        */

 /* Timer holding variables */
 int tblock[4];
 int mtblock[4];                /* For empty loop timing */

 main()
 {
         /* Announce yourself */
         printf("BYTE Small-C Floating-Point Coprocessor Benchmark\n\n");

         /* Initialize the math coprocessor */
         finit();

         /* Do four-banger test */
         fourbang();

         /* Do integration */
         finteg();

         /* Go home */
         finit();

         printf("Press RETURN to exit:");
         fgetc(stdin);

         exit(0);
 }

 /*
 ** fourbang()
 ** Executes a loop of floating add, subtract, multiplies, and divides.
 */
 fourbang()
 {
         int ten[4];        /* Holder for 10 */
         int one[4];        /* Holder for one */
         int temp[4];        /* Temporary storage */
         int i;

         /* Announce yourself */
         printf("Basic Math Test (+,-,*,/)\n");

         /* First set up constants */
         ten[0]=10;
         ten[1]=ten[2]=ten[3]=0;
         fint2float(ten);
         fconst(1);
         fstore(one);

         /* Initialize temp location */
         fload(ten);
         fstore(temp);

         gtime(tblock);
         /* Do the operation */
         for(i=0;i<FCOUNT;++i)
         {
                 f2add(temp,one,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2add(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2add(temp,one,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2add(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2add(temp,one,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2add(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2add(temp,one,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2div(temp,ten,temp);
                 f2sub(temp,one,temp);
                 f2mult(temp,ten,temp);
                 f2add(temp,ten,temp);
                 f2div(temp,ten,temp);
         }
         calctim(tblock);

         /* Now calculate an empty loop */
         gtime(mtblock);
         for(i=0;i<FCOUNT;++i) ;
         calctim(mtblock);

         /* Report results */
         printf("***Results: (All times are HH:MM:SS:1/100ths\n");

         printf("Total time: %d:%d:%d:%d\n",tblock[0],tblock[1],
                 tblock[2],tblock[3]);

         printf("Empty loop time: %d:%d:%d:%d\n",mtblock[0],mtblock[1],
                 mtblock[2],mtblock[3]);
         printf("Value:");
         fltprint(10,temp);
         printf("\n\n");

         return;
 }

 /*
 ** finteg()
 ** Do integration.
 **
 */

 finteg()
 {

         int two[4];                /* Holder for two */
         int pitwo[4];                /* Holder for pi/2 */
         int temp[4];                /* Temp location */
         int sinex[4];                /* Sine value */
         int ex[4];                /* e^x value */
         int accum[4];                /* Accumulator */
         int x[4];                /* Holder for x */
         int i;

         /* Announce yourself */
         printf("Trapezoidal rule for sin(x) 0->x->pi/2 \n");

         /* Generate 2 */
         two[0]=2;
         two[1]=two[2]=two[3]=0;
         fint2float(two);

         /* Generate pi/2 */
         fgetpi2();                /* Get pi over two */
         fstore(pitwo);                /* Store pi over two */

         /* Generate stepsize */
         temp[0]=ICOUNT;
         temp[1]=temp[2]=temp[3]=0;
         fint2float(temp);
         f2div(pitwo,temp,temp);        /* Stepsize in temp */

         /* Clear accumulator */
         fconst(0);
         fstore(accum);

         /* Store x(0) */
         fconst(0);
         fstore(x);

 /* Do trapezoidal rule for sine(x) */
         gtime(tblock);
         for(i=0;i<ICOUNT+1;++i)
         {
                 fsin(x,sinex);                /* Get sinex */
                 f2add(accum,sinex,accum);
                 if((i!=0)&&(i!=ICOUNT))
                   f2add(accum,sinex,accum);
                 f2add(x,temp,x);        /* Increment by step */
         }
         f2mult(accum,temp,accum);        /* Times stepsize */
         f2div(accum,two,accum);                /* Divided by 2 */

         /* Calculate time */
         calctim(tblock);

         /* Get time for an empty loop */
         gtime(mtblock);
         for(i=0;i<ICOUNT+1;++i) ;
         calctim(mtblock);

         /* Report results */
         printf("**** Results: (All times are HH:MM:SS:1/100ths)\n");

         printf("Total time:  %d:%d:%d:%d\n",tblock[0],tblock[1],
                 tblock[2],tblock[3]);
         printf("Empty loop time: %d:%d:%d:%d\n",mtblock[0],mtblock[1],
                 mtblock[2],mtblock[3]);

         printf("Value:");
         fltprint(10,accum);
         printf("\n\n");

 /* Now do trapezoidal rule for e^x */

         printf("Trapezoidal rule for e^x  0->x->1\n");

         /* Generate stepsize */
         temp[0]=ICOUNT;
         temp[1]=temp[2]=temp[3]=0;
         fint2float(temp);
         fconst(1);

         fdiv(temp);
         fstore(temp);                /* Stepsize in temp */

         /* Clear accumulator */
         fconst(0);
         fstore(accum);

         /* Store x(0) */
         fconst(0);
         fstore(x);

         /* Do trapezoidal rule */
         gtime(tblock);
         for(i=0;i<ICOUNT+1;++i)
         {
                 fex(x,ex);                /* Get sinex */
                 f2add(accum,ex,accum);
                 if((i!=0)&&(i!=ICOUNT))
                   f2add(accum,ex,accum);
                 f2add(x,temp,x);        /* Increment by step */
         }
         f2mult(accum,temp,accum);        /* Times stepsize */
         f2div(accum,two,accum);                /* Divided by 2 */

         /* Calculate time */
         calctim(tblock);

         /* Get time for an empty loop */
         gtime(mtblock);
         for(i=0;i<ICOUNT+1;++i) ;
         calctim(mtblock);

         /* Report results */
         printf("**** Results: (All times are HH:MM:SS:1/100ths)\n");

         printf("Total time:  %d:%d:%d:%d\n",tblock[0],tblock[1],
                 tblock[2],tblock[3]);
         printf("Empty loop time: %d:%d:%d:%d\n",mtblock[0],mtblock[1],
                 mtblock[2],mtblock[3]);

         printf("Value:");
         fltprint(10,accum);
         printf("\n\n");

         /* Go home */
         return;
 }

 /*
 ** fgetpi2()
 ** Puts the value pi/2 on top of the floating-point stack.
 */
 fgetpi2()
 {
         int two[4];        /* Holder for 2 */

         two[0]=2;
         two[1]=two[2]=two[3]=0;
         fint2float(two);

         fconst(2);        /* Get pi on top of stack */
         fdiv(two);        /* pi/2 now on floating point stack top */
         return;
 }


 FLOATSQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\FLOATSQ.C

                                          /* Chapter 5 - Program 3 */
 float z;   /* This is a global variable */

 main()
 {
 int index;
 float x,y,sqr(),glsqr();

    for (index = 0;index <= 7;index++){
       x = index;  /* convert int to float */
       y = sqr(x); /* square x to a floating point variable */
       printf("The square of %d is %10.4f\n",index,y);
    }

    for (index = 0; index <= 7;index++) {
       z = index;
       y = glsqr();
       printf("The square of %d is %10.4f\n",index,y);
    }
 }

 float sqr(inval)  /* square a float, return a float */
 float inval;
 {
 float square;

    square = inval * inval;
    return(square);
 }

 float glsqr()    /* square a float, return a float */
 {
    return(z*z);
 }


 FLOATSQ2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\FLOATSQ2.C

                                          /* Chapter 5 - Program 7 */
 "stdio.h"   /* Prototypes for standard Input/Outputs     */

 float sqr(float inval);
 float glsqr(void);

 float z;   /* This is a global variable */

 main()
 {
 int index;
 float x,y;

    for (index = 0;index <= 7;index++){
       x = index;  /* convert int to float */
       y = sqr(x); /* square x to a floating point variable */
       printf("The square of %d is %10.4f\n",index,y);
    }

    for (index = 0; index <= 7;index++) {
       z = index;
       y = glsqr();
       printf("The square of %d is %10.4f\n",index,y);
    }
 }

 float sqr(float inval)  /* square a float, return a float */
 {
 float square;

    square = inval * inval;
    return(square);
 }

 float glsqr(void)    /* square a float, return a float */
 {
    return(z*z);
 }


 FLOOR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FLOOR.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/
         double
 floor(x)                /* return greatest integer less or equal to x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double fint(), ceil();

         if (x < 0.0)
                 return -ceil(-x);
         else        return (fint(x));
 }

 /************************************************************************/
         double
 ceil(x)                        /* return least integer greater or equal to x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double modf(), floor();
         int i;

         if (x < 0.0)
                 return -floor(-x);
         if (modf(x, &x) > 0.0)
                 ++x;
         return x;
 }


 FLOOR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FLOOR.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/


 #include "math.h"

 double floor(d)
 double d;
 {
         if (d < 0.0)
                 return -ceil(-d);
         modf(d, &d);
         return d;
 }

 double ceil(d)
 double d;
 {
         if (d < 0.0)
                 return -floor(-d);
         if (modf(d, &d) > 0.0)
                 ++d;
         return d;
 }



 FMINMAX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FMINMAX.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         double
 fmax(x, y)                        /* return larger of x and y, double

 /*----------------------------------------------------------------------*/
 double x, y;
 {
         return MAX(x,y);
 }

 /************************************************************************/
         double
 fmin(x, y)                        /* return lesser of x and y, double

 /*----------------------------------------------------------------------*/
 double x, y;
 {
         return MIN(x,y);
 }


 FOPEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FOPEN.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

        LAST_DEVICE        -3                /* lowest character device handle

 extern        FILE        _iob[];

 static FILE *_fopen(filename, mode, fp)
 char *filename;
 register char *mode;
 register FILE *fp;
 /*
  *        INTERNAL FUNCTION.  Attempt to open <filename> in the given
  *        <mode> and attach it to the stream <fp>
  */
 {
         register char *p = NULL;
         register int h, i, j = FALSE, f = 0;
         char *malloc();

         while(*mode) {
                 switch(*mode++) {
                         case 'r':
                                 f |= F_READ;
                                 break;
                         case 'w':
                                 f |= F_WRITE;
                                 break;
                         case 'a':
                                 f |= F_WRITE;
                                 j = TRUE;
                                 break;
                         case '+':
                                 f |= (F_READ | F_WRITE);
                                 break;
                         case 'b':
                                 f |= F_BINARY;
                                 break;
                         case 't':
                                 f &= ~F_BINARY;
                                 break;
                         default:
                                 fputs(stderr, "Illegal file mode.\n");
                                 return(NULL);
                 }
         }
         if((i = (f & (F_READ | F_WRITE))) == 0)
                 return(NULL);
         if(i == F_READ)
                 h = open(filename, _OPNr);
         else if(!j && (i == F_WRITE))
                 h = creat(filename, _CRErw);
         else {
                 i = ((i == F_WRITE) ? _OPNw : _OPNrw);
                 if ((h = open(filename, i)) < LAST_DEVICE)
                         h = creat(filename, _CRErw);
         }
         if(h < 0) {
                 if (h < LAST_DEVICE)
                         return(NULL);                /* file open/create erro
                 else
                         f |= F_DEVICE;                /* character device han
         }
         else {
                 if((p=malloc(BUFSIZ)) != NULL)        /* set up file buffer *
                         f |= F_BUFFER;
                 if(j)                                /* append mode. move to
                         lseek(h, 0L, _LSKend);
         }
         fp->F_h = h;                        /* file handle */
         fp->F_stat = f;                        /* file status flags */
         fp->F_buf = p;                        /* base of file buffer */
         fp->F_bp = p;                        /* current buffer pointer */
         fp->F_bsiz = (p ? BUFSIZ : 0);        /* buffer size */
         fp->F_cnt = 0;                        /* # of bytes in buffer */
         fp->F_unc1 = '\0';                /* primary ungotten character */
         fp->F_unc2 = '\0';                /* secondary ungotten character */
         return(fp);
 }

 FILE *fopen(filename, mode)
 char *filename;
 char *mode;
 /*
  *        Open <filename> as a stream file.  This is the normal open way
  *        to open a file.  The <mode> is a string specifying the mode(s)
  *        that are relevent to the file open.  Valid <mode> characters are:
  *                r                read mode
  *                w                write mode
  *                a                append mode
  *                b                binary mode
  *                t                text (translated) mode
  *        At least one of "r", "w" or "a" must be specified.  "t" is assumed
  *        and indicates that <nl> is translated to <cr><lf> on output and
  *        vica-versa on input.  "b" overides "t" and indicated that character
  *        are not translated during i/o operations.  "a" represents append
  *        mode and means that the file pointer will initially be placed at
  *        the end of the file.  "w" mode will create a file if it doesn't
  *        exists, or zero an existing file.  If "r" is the only mode specifie
  *        the file must already exist.  A (FILE *) is returned if the open
  *        succeeds, or NULL if it fails.
  */
 {
         register int i;
         register FILE *fp = NULL;

         for(i=0; (!fp && (i < MAXFILES)); ++i)
                 if(!(_iob[i].F_stat & (F_READ | F_WRITE)))   /* empty slot? *
                         fp = &_iob[i];
         if(fp)
                 return(_fopen(filename, mode, fp));
         else
                 return(NULL);
         /* return(fp ? _fopen(filename, mode, fp) : NULL); */
 }

 FILE *freopen(filename, mode, fp)
 char *filename;
 char *mode;
 FILE *fp;
 /*
  *        Closes the file associated with <fp> and opens the new file as with
  *        fopen(), except that a new FILE structure is not created.  The
  *        existing FILE structure pointed to by <fp> is re-initialized with
  *        the new file information.  This is typically used to redirect i/o
  *        to standard streams "stdin", "stdout", "stderr", "stdprn", "stdaux"
  *        <fp> is returned for success, or NULL for failure.
  */
 {
         if(fclose(fp))
                 return(NULL);
         else
                 return(_fopen(filename, mode, fp));
         /* return(fclose(fp) ? NULL : _fopen(filename, mode, fp)); */
 }

 int fclose(fp)
 register FILE *fp;
 /*
  *        Close the stream <fp>, flushing the buffer.  Returns 0 on success.
  */
 {
         if((fp->F_stat & (F_READ | F_WRITE)) == 0)
                 return(ERROR);                                /* file not ope
         fflush(fp);
         if(fp->F_stat & F_BUFFER)
                 free(fp->F_buf);                        /* free buffer */
         fp->F_stat = 0;                                        /* clear statu
         fp->F_buf = NULL;
         fp->F_bsiz = 0;
         return(close(fp->F_h) ? EOF : 0);
 }


 FOPEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FOPEN.C

 /* 1.2  12-17-85                                                (fopen.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 fclose(fp)                /* flush the FILE fp buffer, and close the file.
                            Return EOF on error, NULL otherwise.         */
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 {
         int err;
         METACHAR fflush();

         err = NULL;
         if (fp->_flags)
         {        if (fp->_flags & _DIRTY)   /* if modifed, flush buffer
                         err = fflush(fp);
                 err |= close(fp->_unit);
                 if (fp->_flags & _ALLBUF)        /* put the buffer back in */
                         liberate(fp->_buff, BUFSIZ);        /* the free list.
         }
         fp->_flags = NULL;
         return err;
 }

 /************************************************************************/
         METACHAR
 fflush(fp)                /* Write characters in the FILE fp buffer onto
                            the file.  Return EOF on error.                */
 /*----------------------------------------------------------------------*/
 FILE *fp;
 {
         METACHAR flush();

         return flush(fp, EOF);
 }
 /*\p*********************************************************************/
         FILE *
 fopen(name, type)        /* Open name file according to given type. Return
                            pointer to stream, or NULL on failure.        */
 /*----------------------------------------------------------------------*/
 STRING name, type;
 {
         FAST FILE *fp;
         FAST BOOL t;
         FAST int fd;

         for (fp = IObuffs; fp->_flags; ) /* look for a blank flag field. */
                 if (++fp >= IObuffs + MAXSTREAM)
                         return (NULL);

         t = (type[1] IS '+');
         switch (*type)
         {        case 'r':
                         if ((fd = open(name, t? _RDWRIT : _RDONLY)) IS EOF)
                                 return (NULL);
                         break;
                 case 'w':
                         if ((fd = creat(name, PMODE)) IS EOF)
                                 return (NULL);
                         if (t)
                         {        close(fd);
                                 fd = open(name, _RDWRIT);
                         }
                         break;
                 case 'a':
                         if ((fd = open(name, t? _RDWRIT : _WRONLY)) IS EOF)
                         {        if ((fd = creat(name, PMODE)) IS EOF)
                                         return (NULL);

                                 close(fd);
                                 fd = open(name, t ? _RDWRIT : _WRONLY);
                                 break;
                         }
                         lseek(fd, 0L, 2);
                         break;
                 default:
                         errno = EINVAL;
                         return NULL;
         }
         fp->_unit = fd;
         fp->_flags = _BUSY;
         fp->_buflen = BUFSIZ;
         fp->_buff = fp->_bend = fp->_bptr = NULL;
         return (fp);
 }


 FORLOOP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\FORLOOP.C

                                           /* Chapter 3 - Program 3 */
 /* This is an example of a for loop */

 main()
 {
 int index;

    for(index = 0;index < 6;index = index + 1)
      printf("The value of the index is %d\n",index);
 }


 FORMAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FORMAT.C

 /* 1.4  02-10-86                                                (format.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "ctype.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/

 format(xputc, fmt, args)        /* Formatted output of args using fmt;
                                    xputc() puts a character on the proper
                                    medium.  Return no. of chars printed
                                    or EOF if printing fails.                *
 /*----------------------------------------------------------------------*/
 FAST int (*xputc)();
 FAST STRING fmt;
 unsigned *args;
 {
         FAST int c;
         int cc, i, k, rjust, filler, precis, width;
         long value;
         STRING cp, ftoa(), ltoab();
         char s[MAXLINE];
         double dval;

         for (cc = 0; c = *fmt++; )
         {        if (c ISNT '%')
                 {        cc++;
                         if ((*xputc)(c) < 0)
                                 return EOF;
                 }
                 else
                 {        rjust = TRUE;
                         filler = ' ';
                         precis = MAXLINE;
                         if ((c = *fmt++) IS '-')
                         {        rjust = FALSE;
                                 c = *fmt++;
                         }
                         if (c IS '0')
                         {        filler = '0';
                                 c = *fmt++;
                         }
 /*\p*/
                         if (c IS '*')
                         {        width = *args++;
                                 c = *fmt++;
                         }
                         else
                                 for (width = 0; isdigit(c) ; c = *fmt++)
                                 {        width *= 10;
                                         width += (c - '0');
                                 }
                         if (width > MAXLINE)
                                 width = MAXLINE;
                         if (c IS '.')
                                 if ((c = *fmt++) IS '*')
                                 {        precis = *args++;
                                         c = *fmt++;
                                 }
                                 else
                                         for (precis = 0; isdigit(c); c = *fmt
                                         {        precis *= 10;
                                                 precis += (c - '0');
                                         }
                         switch(c)
                         {   case 'l':
                                 c = *fmt++;
                             case 'D': case 'O': case 'X': case  'U':
                                 value = *((long *) args)++;
                                 break;
                             case 'd':
                                 value = (int) *args++;
                                 break;
                             case 'e': case 'f': case 'g':
                                 dval = *((double *) args)++;
                                 break;
                             case 'o': case 'x': case 'u': case 's': case 'c':
                                 value = *args++;
                                 break;
                         }
                         if (rjust)
                                 k = (filler IS '0' AND width) ? -width : widt
                         else
                                 k = 0;
 /*\p*/
                         switch (TOLOWER(c))
                         {   case 'd':
                                 ltoab(s, value, k, 10);
                                 break;
                             case 'o':
                                 ultoab(s, value, k, 8);
                                 break;
                             case 'u':
                                 ultoab(s, value, k, 10);
                                 break;
                             case 'x':
                                 ultoab(s, value, k, 16);
                                 break;
                             case 'e':
                             case 'f':
                             case 'g':
                                 i = (precis IS MAXLINE) ? 6 : precis;
                                 lpadn(ftoa(s, dval, i, c), filler, k);
                                 precis = MAXLINE;
                                 break;
                             case 's':
                                 if (precis > MAXLINE)
                                         precis = MAXLINE;
                                 strncpy(s, (STRING) (unsigned) value, precis)
                                 break;
                             case 'c':
                                 c = value;
                             default:
                                 *s = c;
                                 s[1] = NULL;
                         }
                         if ((i = strlen(s)) > precis)
                                 i = precis;
                         i = width - i;
                         if (rjust)
                                 for ( ; i-- > 0; cc++)
                                         if ((*xputc)(filler) < 0)
                                                 return EOF;

                         for (k = 0, cp = s; *cp AND k < precis; ++k, cc++)
                                 if((*xputc)(*cp++) < 0)
                                         return EOF;

                         for ( ; i-- > 0; cc++)
                                 if ((*xputc)(' ') < 0)
                                         return EOF;
                 }
         }
         return cc;
 }
 /*\p*********************************************************************/
         LOCAL
 lpadn(s, fill, n)        /* left-pad the numeric string s to width n using
                            the fill character.  Return s.                */
 /*----------------------------------------------------------------------*/
 FAST STRING s;
 FAST int n;
 {
         FAST int k, L;

         n -= (L = strlen(s));
         if (n > 0)
         {        for (k = L; k >= 0; k--)        /* move everybody down
                          s[k + n] = s[k];
                 for (k = 0; k < n; k++)                /* and fill the holes.
                         s[k] = fill;
                 if (fill IS '0')
                 {        if (s[n] IS '-')
                                 *s = '-';        /* move the minus sign
                         s[n] = fill;                /* plug up the gap.
                 }
         }
 }

 /************************************************************************/
         LOCAL VOID
 ultoab(s, n, w, b)        /* Convert unsigned long n to ascii string s, with
                            minimum width w, base b.  Return s.
 /*----------------------------------------------------------------------*/
 long n;
 STRING s;
 {
         int low, hb;
         STRING p, ltoab();

         if (n < 0)
         {        low = (int) n & 1;        /* save the low bit of n.        *
                 hb = (b >> 1);                /* hb = half the base b.
                 n = LURSHIFT(n, 1);        /* n is now (n - low)/2).        *
                 low += ((int)(n % hb) << 1); /* the low digit base b        *
                 low += (low > 9) ? 'W' - 10 : '0';/* now ascii.        Note '
                 n /= hb;                /* is 'a' - 10.  Reduce n,        */
                 w -= SGN(w);                /* reduce the width.
         }
         else
                 low = NULL;
         p = s + strlen(ltoab(s, n, w, b));
         *p++ = low;
         *p = NULL;
         return;
 }


 FORMOUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\FORMOUT.C

                                         /* Chapter 10 - Program 1 */
 #include "stdio.h"
 main()
 {
 FILE *fp;
 char stuff[25];
 int index;

    fp = fopen("TENLINES.TXT","w");   /* open for writing */
    strcpy(stuff,"This is an example line.");

    for (index = 1;index <= 10;index++)
       fprintf(fp,"%s  Line number %d\n",stuff,index);

    fclose(fp);    /* close the file before ending program */
 }


 FPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FPRINTF.C

 #include <stdio.h>

 extern        int        fputc();

 fprintf(fp, fmt, arg)
 FILE *fp;
 char *fmt;
 int arg;
 {
         return(_printf(fp, fputc, fmt, &arg));
 }

 printf(fmt, arg)
 char *fmt;
 int arg;
 {
         return(_printf(stdout, fputc, fmt, &arg));
 }


 FPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FPRINTF.C

 /* 1.3  01-08-86                                                 (fprintf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 LOCAL FILE *Fp;                /* global FILE pointer for _putc deposit.

 /************************************************************************/

 fprintf(fp, fmt, args)        /* formatted printf to FILE fp of args.

 /*----------------------------------------------------------------------*/
 FILE *fp;
 STRING fmt;
 unsigned args;
 {
         int _putc();

         Fp = fp;
         return format(_putc, fmt, &args);
 }

 /************************************************************************/
         LOCAL
 _putc(c)                /* Put character c on global FILE Fp.

 /*----------------------------------------------------------------------*/
 {
         return putca(c, Fp);
 }


 FPUTC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FPUTC.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 static int        _fputc2 = FALSE;        /* "2nd time in" flag */

 int fputc(c, fp)
 char c;
 register FILE *fp;
 /*
  *        Put the character <c> to the stream <fp>.
  */
 {
         register int f, m;

         f = fp->F_stat;
         if(!(f & F_WRITE))                        /* stream opened for write?
                 return(EOF);
         m = (F_BUFFER | F_READ | F_IODIR);
         if((f & m) == (F_BUFFER | F_READ))        /* r/w direction switch */
                 fflush(fp);
         fp->F_stat |= F_IODIR;
         if(f & (F_ERROR | F_EOF))                /* error/eof conditions */
                 return(EOF);
         if((c == '\n') && !_fputc2 && !(f & F_BINARY)) {
                 _fputc2 = TRUE;
                 m = fputc('\r', fp);
                 _fputc2 = FALSE;
                 if(m < 0)
                         return(EOF);
         }
         if(f & F_BUFFER) {
                 *(fp->F_bp)++ = c;
                 if((++(fp->F_cnt)) >= fp->F_bsiz) {
                         fp->F_cnt = 0;
                         fp->F_bp = fp->F_buf;
                         m = fp->F_bsiz;
                         if(write(fp->F_h, fp->F_buf, m) != m) {
                                 fp->F_stat |= F_ERROR;
                                 return(EOF);
                         }
                 }
         }
         else {
                 if(write(fp->F_h, &c, 1) != 1)
                         return(EOF);
         }
         return(c);
 }


 FPUTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FPUTS.C

 #include <stdio.h>

 void fputs(data, fp)
 register char *data;
 register FILE *fp;
 /*
  *        Write the characters in <data> to the stream <fp>.  A newline
  *        WILL NOT be added.
  */
 {
         while(*data)
                 fputc(*data++, fp);
 }

 void puts(data)
 char *data;
 /*
  *        Write the characters in <data> to stdout.  A newline WILL be
  *        written after the data.
  */
 {
         fputs(data, stdout);
         fputc('\n', stdout);
 }


 FPUTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FPUTS.C

 /* 1.1  01-08-86                                                 (fputs.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 fputs(s, fp)                /* Put the string s out to the FILE fp.  Return
                            NULL if ok, EOF if not.                        */
 /*----------------------------------------------------------------------*/
 FAST STRING s;
 FILE *fp;
 {
         while (*s)
                 if (putca(*s++, fp) IS EOF)
                         return(EOF);

         return NULL;
 }


 FRAC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FRAC.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/
         double
 frac(x)                        /* return fractional part of x as double.

 /*----------------------------------------------------------------------*/
 double x;
 {
         double fint();

         return (x - fint(x));
 }


 FRAME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\FRAME.C

 /*                             *** frame.c ***                       */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Function to draw a box given the upper left corner and the lower  */
 /* right corner.  Uses the extended character set - graphics board   */
 /* not needed.  Uses direct BIOS calls.  Returns a 0 if successful   */
 /* or a -1 if invalid parameters.                                    */
 /*                                                                   */
 /* *** NOTE ***                                                      */
 /* The upper left corner of the screen is 0,0 and the bottom right   */
 /* corner is 24,79.                                                  */
 /*                                                                   */
 /* Written by L. Cuthbertson, May 1984.                              */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */
 /* Added the nlines argument.  If = 1, single line frame.            */
 /* If = 2, double line frame.                                        */
 /* Lew Paper, 7/4/85                                                 */

 #include "dispio.h"

 #define biosset CURPOS
 #define bioswc(char, n) write_ch(char, PAGE, n)

 int dispio(), write_ch();

 int frame(ulrow,ulcol,lrrow,lrcol, nlines)
 int ulrow,ulcol,lrrow,lrcol, nlines;
 {
         static int horbar[2] = {0xC4, 0xCD};
         static int verbar[2] = {0xB3, 0xBA};
         static int ulcorn[2] = {0xDA, 0xC9};
         static int urcorn[2] = {0xBF, 0xBB};
         static int llcorn[2] = {0xC0, 0xC8};
         static int lrcorn[2] = {0xD9, 0xBC};
         int count,irow;
         int ndx, verchar;

         /* error checking */
         if (ulrow < 0 || ulrow > 24) return(-1);
         if (ulcol < 0 || ulcol > 79) return(-1);
         if (lrrow < 0 || lrrow > 24) return(-1);
         if (lrcol < 0 || lrcol > 79) return(-1);
         if (lrrow < ulrow) return(-1);
         if (lrcol < ulcol) return(-1);
         if (nlines < 1 || nlines > 2) return(-1);

         ndx = nlines - 1;
         verchar = verbar[ndx];

         /* do top line first */
         biosset(ulrow,ulcol);
         bioswc(ulcorn[ndx],1);
         count = lrcol-ulcol-1;
         if (count > 0) {
                 biosset(ulrow,ulcol+1);
                 bioswc(horbar[ndx],count);
         }
         biosset(ulrow,lrcol);
         bioswc(urcorn[ndx],1);

         /* do both sides at once */
         irow = ulrow + 1;
         while (irow < lrrow) {
                 biosset(irow,ulcol);
                 bioswc(verchar,1);
                 biosset(irow,lrcol);
                 bioswc(verchar,1);
                 irow++;
         }

         /* do bottom line */
         biosset(lrrow,ulcol);
         bioswc(llcorn[ndx],1);
         count = lrcol-ulcol-1;
         if (count > 0) {
                 biosset(lrrow,ulcol+1);
                 bioswc(horbar[ndx],count);
         }
         biosset(lrrow,lrcol);
         bioswc(lrcorn[ndx],1);

         /* done */
         return(0);
 }


 FRAME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\FRAME.C

 /**********************************************************
  *   This function builds a nice looking frame for a      *
  *   menu.  The function is passed the parameters for     *
  *   the upper left corner row, upper left corner column  *
  *   the height of the frame and the width.  Depending    *
  *   on your particular compiler characteristics you      *
  *   will have to substitute its functions for clear-     *
  *   ing the screen and locating at the correct row       *
  *   and column on the screen. the functions you will     *
  *   need to replace with your own are scr_clr() and      *
  *   scr_rowcol(x, y).                                    *
  *                                                        *
  *          Program By                                    *
  *          Lynn Long                                     *
  *          Tulsa, OK RBBS "C" Bulletin Board             *
  *          918-664-8737                                  *
  *********************************************************/









 #define                        ULCOR                        201
 #define                        URCOR                        187
 #define                        LLCOR                        200
 #define                        LRCOR                        188
 #define                        VBAR                        186
 #define                        HBAR                        205

 frame(row, col, hgt, wdth)
 int row, col, hgt, wdth;

 {
         int x, y;


         scr_clr();                                /*  insert your code here t
         scr_rowcol(row, col);                     /*  insert your function to
         putchar(ULCOR);
     for(x = col + 1; x <=(col + wdth -1); x++)
              putchar(HBAR);
         putchar(URCOR);
         for(x = row + 1; x <=(row + hgt - 1); x++){
         scr_rowcol(x, col);
         putchar(VBAR);
         scr_rowcol(x, col+wdth);
         putchar(VBAR);
    }
     scr_rowcol(x, col);
     putchar(LLCOR);
     for(x= col + 1; x <=(col + wdth -1); x++)
             putchar(HBAR);
             putchar(LRCOR);
 }


 FRAME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FRAME.C


 /**********************************************************
  *   This function builds a nice looking frame for a      *
  *   menu.  The function is passed the parameters for     *
  *   the upper left corner row, upper left corner column  *
  *   the height of the frame and the width.  Depending    *
  *   on your particular compiler characteristics you      *
  *   will have to substitute its functions for clear-     *
  *   ing the screen and locating at the correct row       *
  *   and column on the screen. the functions you will     *
  *   need to replace with your own are scr_clr() and      *
  *   scr_rowcol(x, y).                                    *
  *                                                        *
  *          Program By                                    *
  *          Lynn Long                                     *
  *          Tulsa, OK RBBS "C" Bulletin Board             *
  *          918-664-8737                                  *
  *********************************************************/

 #define                 ULCOR                   201
 #define                 URCOR                   187
 #define                 LLCOR                   200
 #define                 LRCOR                   188
 #define                 VBAR                    186
 #define                 HBAR                    205

 frame(row, col, hgt, wdth)
 int row, col, hgt, wdth;

 {
         int x, y;


         scr_clr();                                /*  insert your code here t
         scr_rowcol(row, col);                     /*  insert your function to
         putchar(ULCOR);
     for(x = col + 1; x <=(col + wdth -1); x++)
         putchar(HBAR);
         putchar(URCOR);
         for(x = row + 1; x <=(row + hgt - 1); x++){
         scr_rowcol(x, col);
         putchar(VBAR);
         scr_rowcol(x, col+wdth);
         putchar(VBAR);
    }
     scr_rowcol(x, col);
     putchar(LLCOR);
     for(x= col + 1; x <=(col + wdth -1); x++)
         putchar(HBAR);
         putchar(LRCOR);
 }



 FRAME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\FRAME.C


 /**********************************************************
  *   This function builds a nice looking frame for a      *
  *   menu.  The function is passed the parameters for     *
  *   the upper left corner row, upper left corner column  *
  *   the height of the frame and the width.  Depending    *
  *   on your particular compiler characteristics you      *
  *   will have to substitute its functions for clear-     *
  *   ing the screen and locating at the correct row       *
  *   and column on the screen. the functions you will     *
  *   need to replace with your own are scr_clr() and      *
  *   scr_rowcol(x, y).                                    *
  *                                                        *
  *          Program By                                    *
  *          Lynn Long                                     *
  *          Tulsa, OK RBBS "C" Bulletin Board             *
  *          918-664-8737                                  *
  *********************************************************/

 #define                 ULCOR                   201
 #define                 URCOR                   187
 #define                 LLCOR                   200
 #define                 LRCOR                   188
 #define                 VBAR                    186
 #define                 HBAR                    205

 frame(row, col, hgt, wdth)
 int row, col, hgt, wdth;

 {
         int x, y;


         scr_clr();                                /*  insert your code here t
         scr_rowcol(row, col);                     /*  insert your function to
         putchar(ULCOR);
     for(x = col + 1; x <=(col + wdth -1); x++)
         putchar(HBAR);
         putchar(URCOR);
         for(x = row + 1; x <=(row + hgt - 1); x++){
         scr_rowcol(x, col);
         putchar(VBAR);
         scr_rowcol(x, col+wdth);
         putchar(VBAR);
    }
     scr_rowcol(x, col);
     putchar(LLCOR);
     for(x= col + 1; x <=(col + wdth -1); x++)
         putchar(HBAR);
         putchar(LRCOR);
 }



 FRAME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DISPIO\FRAME.C

 /*                             *** frame.c ***                       */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Function to draw a box given the upper left corner and the lower  */
 /* right corner.  Uses the extended character set - graphics board   */
 /* not needed.  Uses direct BIOS calls.  Returns a 0 if successful   */
 /* or a -1 if invalid parameters.                                    */
 /*                                                                   */
 /* *** NOTE ***                                                      */
 /* The upper left corner of the screen is 0,0 and the bottom right   */
 /* corner is 24,79.                                                  */
 /*                                                                   */
 /* Written by L. Cuthbertson, May 1984.                              */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */
 /* Added the nlines argument.  If = 1, single line frame.            */
 /* If = 2, double line frame.                                        */
 /* Lew Paper, 7/4/85                                                 */

 #include "dispio.h"

 #define biosset CURPOS
 #define bioswc(char, n) write_ch(char, PAGE, n)

 int dispio(), write_ch();

 int frame(ulrow,ulcol,lrrow,lrcol, nlines)
 int ulrow,ulcol,lrrow,lrcol, nlines;
 {
         static int horbar[2] = {0xC4, 0xCD};
         static int verbar[2] = {0xB3, 0xBA};
         static int ulcorn[2] = {0xDA, 0xC9};
         static int urcorn[2] = {0xBF, 0xBB};
         static int llcorn[2] = {0xC0, 0xC8};
         static int lrcorn[2] = {0xD9, 0xBC};
         int count,irow;
         int ndx, verchar;

         /* error checking */
         if (ulrow < 0 || ulrow > 24) return(-1);
         if (ulcol < 0 || ulcol > 79) return(-1);
         if (lrrow < 0 || lrrow > 24) return(-1);
         if (lrcol < 0 || lrcol > 79) return(-1);
         if (lrrow < ulrow) return(-1);
         if (lrcol < ulcol) return(-1);
         if (nlines < 1 || nlines > 2) return(-1);

         ndx = nlines - 1;
         verchar = verbar[ndx];

         /* do top line first */
         biosset(ulrow,ulcol);
         bioswc(ulcorn[ndx],1);
         count = lrcol-ulcol-1;
         if (count > 0) {
                 biosset(ulrow,ulcol+1);
                 bioswc(horbar[ndx],count);
         }
         biosset(ulrow,lrcol);
         bioswc(urcorn[ndx],1);

         /* do both sides at once */
         irow = ulrow + 1;
         while (irow < lrrow) {
                 biosset(irow,ulcol);
                 bioswc(verchar,1);
                 biosset(irow,lrcol);
                 bioswc(verchar,1);
                 irow++;
         }

         /* do bottom line */
         biosset(lrrow,ulcol);
         bioswc(llcorn[ndx],1);
         count = lrcol-ulcol-1;
         if (count > 0) {
                 biosset(lrrow,ulcol+1);
                 bioswc(horbar[ndx],count);
         }
         biosset(lrrow,lrcol);
         bioswc(lrcorn[ndx],1);

         /* done */
         return(0);
 }


 FREAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FREAD.C

 #include <osbind.h>
 #include <stdio.h>

 int fread(data, size, count, fp)
 register char *data;
 int size;
 int count;
 register FILE *fp;
 /*
  *        Read <count> items of <size> characters each from stream <fp>.
  *        Data is stored in the buffer pointed to by <data>.  The number of
  *        full items actually read is returned, or a negative error code.
  */
 {
         register long n, lsiz;

         lsiz = ((long) size);
         n = ((long) count) * lsiz;
         n = Fread(fileno(fp), n, data);
         return((n > 0) ? (n / lsiz) : n);
 }


 FREAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FREAD.C

 /* 1.0  12-14-84                                                 (fread.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/

 fread(ptr, ptrsiz, nitems, fp)        /* Read nitems of data of type *ptr fro
                                    FILE fp into block beginning at ptr.
                                    Return number of items read.
 /*----------------------------------------------------------------------*/
 FAST BUFFER ptr;
 FILE *fp;
 {
         int items;
         FAST int c, i;
         METACHAR getc();

         for (items = 0; items < nitems; ++items)
         {        for (i = ptrsiz; i; --i)
                 {        if ((c = getc(fp)) IS EOF)
                                 return items;

                         *ptr++ = c;
                 }
         }
         return items;
 }


 FREE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FREE.C

 #include <osbind.h>
 #include <stdio.h>

 #define        MAXBLK                16
 #define        FREE                0x00
 #define        USED                0x80
 #define        NULLBLK                0x80000000L

 extern        char        *_mblk[];                /* memory heap pointers */
 extern        long        _msiz[];                /* memory heap sizes */

 static mergeblk(i)
 int i;
 /*
  *        Merge adjacent "free" blocks in heap <i>.  Links in the free chain
  *        are guarenteed to be in forward order.
  */
 {
         register long n, *p, *q;

         p = _mblk[i];
         if((p = *p) == NULL)                        /* empty chain */
                 return;
         while(q = p[1]) {
                 n = *p;
                 if(((char *) p)+n == q)        {        /* free blocks are ad
                         p[1] = q[1];                /* re-link free chain */
                         *p += *q;                /* adjust block size */
                 }
                 else
                         p = q;
         }
         /* check to see if the entire heap can be returned to the OS */
         q = ((char *) p) + (*p);
         if((_mblk[i] == (p - 1)) && ((*q) == NULLBLK)) {
                 Mfree(_mblk[i]);
                 _mblk[i] = NULL;
                 _msiz[i] = 0L;
         }
 }

 /*--------------------- Documented Functions ---------------------------*/

 free(addr)
 register long *addr;
 /*
  *        Release the memory block at <addr> back into the free memory pool.
  *        If <addr> doesn't point to a block allocated by calloc(), malloc(),
  *        lalloc() or realloc(), very bad, unpredictable things will happen.
  */
 {
         register int i;
         register long *p, *q;

         --addr;                                        /* point to block head
         for(i=0; i<MAXBLK; ++i) {
                 if((p = _mblk[i]) == NULL)
                         continue;                /* skip unavailable blocks *
                 if((addr < p) || (addr > ((char *) p)+_msiz[i]))
                         continue;                /* block range check */
                 while(q = *p) {
                         ++q;
                         if((addr < q) && (addr > p))
                                 break;
                         p = q;
                 }
                 *((char *) addr) = FREE;        /* link into free chain */
                 addr[1] = *p;
                 *p = addr;
                 mergeblk(i);
                 return(TRUE);
         }
         return(FALSE);
 }


 FREXP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FREXP.C

 /* 1.1  07-10-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "mathcons.h"

 /************************************************************************/
         double
 frexp(x, np)                /* returns mantissa of x and *np contains the
                            characteristic of x (i.e., log2(x)).
 /*----------------------------------------------------------------------*/
 double x;
 int *np;
 {
         double ldexp();
         int chrstc();

         return ldexp(x, -(*np = chrstc(x)));
 }

 /*\p*********************************************************************/
         double
 ldexp(x, m)        /* return value = x * (2^m)

 /*----------------------------------------------------------------------*/
 double x;
 int m;
 {
         FAST n;
         int chrstc();
         TBITS *xp;
         LOCAL double raiseto[8] =
                 {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0};

         if (x IS 0.0)
                 return 0.0;

         xp = (char *) &x;

 #ifdef ECOSOFT
         n = chrstc(x) + m;
         *xp = (n = (n > 0x7f ? 0x7f : n) + 0x80);
 #endif

 #ifdef AZTEC
         n = m / 8;
         if ((m %= 8) < 0)
         {        n--;
                 m += 8;
         }
         if ((n += (*xp & 0x7f)) > 0x7f)
                 n = 0x7f;
         *xp = n | (*xp & 0x80);
         x *= raiseto[m];
 #endif

 #ifdef CPM86
         n = chrstc(x) + m;
         n = (n > 0x400 ? 0x400 : n) + 0x3fe;
         xp[7] = (xp[7] & 0x80) | ((n >> 4) & 0x7f);
         xp[6] = (xp[6] & 0x0f) | (n << 4);
 #endif

 #ifdef UNIVERSE
         n = chrstc(x) + m;
         n = (n > 0x7f ? 0x7f : n) + 0x80;
         *xp = (*xp++ & 0x80) | ((n >> 1) & 0x7f);
         *xp = (*xp & 0x7f) | (n & 1 ? 0x80 : 0);
 #endif
 /*\p*/

 #ifdef SUN
         n = chrstc(x) + m + 0x3fe;
         if (n >= 0x7ff)
                 return INFINITY;

         *xp = (*xp & 0x80) | (n>>4);
         xp[1] = (xp[1] & 0xf) | ((n & 0xf)<<4);
 #endif

         if (n < 1)
                 return 0.0;
         else
                 return x;
 }



 FSCANF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FSCANF.C

 #include <stdio.h>

 extern int fgetc(), fungetc();

 fscanf(fp, fmt, arg)
 FILE *fp;
 char *fmt;
 char *arg;
 {
         return(_scanf(fp, fgetc, fungetc, fmt, &arg));
 }

 scanf(fmt, arg)
 char *fmt;
 char *arg;
 {
         return(_scanf(stdin, fgetc, fungetc, fmt, &arg));
 }


 FSCANF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FSCANF.C

 /* 1.1  01-08-86                                                 (fscanf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /*----------------------------------------------------------------------*/

 LOCAL FILE *Fp;
 LOCAL int lastch;

 /************************************************************************/

 fscanf(fp, fmt, arg)        /* Read FILE fp using format fmt, and deposit
                            information into arguments in arg list. Return
                            count of items read, or EOF on error.        */
 /*----------------------------------------------------------------------*/
 FILE *fp;
 STRING fmt;
 unsigned *arg;
 {
         int _getc(), unformat();

         lastch = EOF;
         Fp = fp;
         return unformat(_getc, fmt, &arg);
 }

 /************************************************************************/
         LOCAL
 _getc(forward)                /* Return a character from the stdin.
                            If forward is TRUE, get next character and
                            advance; else, unget the character unless the
                            end has been reached. Return EOF if so.        */
 /*----------------------------------------------------------------------*/
 BOOL forward;
 {
         METACHAR getca(), ungetc();

         return (lastch = (forward ? (feof(Fp) ? EOF : getca(Fp))
                 : ungetc(lastch, Fp)));
 }



 FSEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\FSEARCH.C

 /* FSEARCH.C - From page 464 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. Searches a file for a phrase.     */
 /* Usage:  A>fsearch filename.ext phrase                        */
 /****************************************************************/

 "fcntl.h"            /*needed for oflags*/
 "stdio.h"            /*needed for NULL etc.*/
 "memory.h"           /*needed for memchr();*/
 #define BUFFSIZE 1024
 char buff[BUFFSIZE];

 main(argc, argv)
 int argc;
 char *argv[];
 {
 int inhandle, bytes;

    if(argc != 3) {
       printf("\nFormat:  A>fsearch filename.ext phrase");
       exit();
    }
    if((inhandle = open(argv[1], O_RDONLY)) < 0) {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    while((bytes = read(inhandle, buff, BUFFSIZE)) > 0)
       search(argv[2], bytes);
    close(inhandle);
    printf("\nPhrase not found");
 }

 /* search() */    /* searches buffer for phrase */
 search(phrase, buflen)
 char *phrase;
 int buflen;
 {
 char *ptr, *p;

    ptr = buff;
    while((ptr = memchr(ptr, phrase[0], buflen)) != NULL)
       if(memcmp(ptr, phrase, strlen(phrase)) == 0) {
          printf("\nFirst occurrence of phrase:\n\n");
          for(p = ptr - 100; p < ptr + 100; p++)
             putchar(*p);
          exit();
       }
       else ptr++;
 }





 FSEEK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FSEEK.C

 /* 1.2  01-08-86                                                (fseek.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 fseek(fp, offset, where)        /* Position the FILE fp at offset bytes
                                    from where. Return EOF on error.        */
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 long offset;
 {
         long lseek();
         METACHAR fflush();

         fp->_flags &= ~_EOF;
         if (fp->_flags & _DIRTY)        /* if something in the write buffer *
         {        if (fflush(fp))
                         return EOF;
         }
         else if (where IS CURPOS AND fp->_bptr)        /* or read buffer
                 offset -= (fp->_bend - fp->_bptr);
         fp->_bptr = fp->_bend = NULL;
         if (lseek(fp->_unit, offset, where) < 0)
                 return EOF;

         return NULL;
 }


 FSEEK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FSEEK.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 long fseek(fp, offset, origin)
 FILE *fp;
 long offset;
 int origin;
 /*
  *        Operates like lseek(), except it works on streams.  Note that
  *        stream file positions may be misleading due to translation of
  *        <nl> characters during i/o.  ftell() may be used reliably with
  *        fseek() to reposition a file to a prior location.
  */
 {
         fflush(fp);
         return(Fseek(offset, fileno(fp), origin));
 }

 void rewind(fp)
 register FILE *fp;
 /*
  *        Operates like fseek(f,0L,_LSKbeg), except it also clears the
  *        end-of-file and error flags for <fp>.  There is no return value.
  */
 {
         fseek(fp, 0L, _LSKbeg);
         fp->F_stat &= ~(F_EOF|F_ERROR);
 }


 FTELL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FTELL.C

 /* 1.0  12-17-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         long
 ftell(fp)                /* Return offset in bytes relative to ORIGIN of
                            FILE fp.                                        */
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 {
         long offset, lseek();

         offset = lseek(fp->_unit, 0L, CURPOS);        /* locate current posit
         if (fp->_flags & _DIRTY)                /* add that in the buffer  */
                 offset += (fp->_bptr - fp->_buff); /* not yet written.
         else if (fp->_bptr)                        /* or in read buffer
                 offset -= (fp->_bend - fp->_bptr);
         return offset;
 }


 FTOA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FTOA.C

 /* 1.3  10-08-85                                                (ftoa.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "ctype.h"
 #include "stdtyp.h"
 #include "mathcons.h"

 /************************************************************************/
         STRING
 ftoa(s, x, pr, mode)        /* Convert x to ascii string s with precision pr
                            in mode 'e', 'f', or 'g' format.
                            Return pointer to s.
 /*----------------------------------------------------------------------*/
 STRING s;
 double x;
 {
         BOOL minus;
         STRING p, astoi();
         int d;
         double normalize();

         p = s;                /* save string pointer for returns        */
         *s = NULL;
         if (pr > DPRECISION)
                 pr = DPRECISION;
         if (minus = ((x < 0.0) ? TRUE : FALSE)) /* work with pos. numbers */
                 x = -x;
         x = normalize(x, &d);
         *s++ = (minus ? '-' : ' ');        /* put sign into string        */
         switch (tolower(mode))
         {        case 'e':
                 case 0:
                         expform(s, x, d, pr);
                         break;
                 case 'f':
                 case 1:
                         floatform(s, x, d, pr);
                         break;
                 case 'g':
                 case 2:
                         minform(s, x, d, pr);
                         break;
                 default:
                         ;
         }
         return p;
 }

 /*\p*********************************************************************/
         LOCAL double
 normalize(x, d)                /* return x * 10^-d in [1, 10), with d set so
                            this condition is met.                        */
 /*----------------------------------------------------------------------*/
 double x;
 int *d;
 {
         /****************************************************************
          * This array contains 2^n powers of 10 up to n = BIG10X-1        *
          ****************************************************************/

         LOCAL double tentothe2tothe[BIG10X] =
         {        10., 100., 10000., 100000000., 10000000000000000.,
                 100000000000000000000000000000000.
 #ifdef AZTEC
                 , 1.0e64, 1.0e128
 #endif

 #ifdef SUN
                 , 1.0e64, 1.0e128, 1.0e256
 #endif
         };

         /********************************************************
          * Also, make this array be 2^n up to 2^(BIG10X-1)        *
          ********************************************************/

         LOCAL int twoto[BIG10X] =
         {        1, 2, 4, 8, 16, 32
 #ifdef AZTEC
                 , 64, 128
 #endif

 #ifdef SUN
                 , 64, 128, 256
 #endif
         };

         int i;

         *d = 0;
         if (x ISNT 0.0)
                 if (x < 1.0)
                 {        for (i = 1; x < SYMLEAST; i++)
                                 x *= 10.0;
                         x = 10.0 / normalize(1.0 / x, d);
                         *d = -*d - i;
                         if (x >= 10.0)        /* compensate if on the edge.
                         {        x /= 10.0;
                                 ++*d;
                         }
                 }
                 else
                         for (i = BIG10X; x >= 10.0 AND --i >= 0; )
                                 if (x >= tentothe2tothe[i])
                                 {        x /= tentothe2tothe[i];
                                         *d += twoto[i];
                                 }
         return x;
 }

 /*\p*********************************************************************/
         LOCAL VOID
 floatform(s, x, d, pr)        /* put x * 10^d (precision pr) into string s
                            in f-format.
 /*----------------------------------------------------------------------*/
 STRING s;
 double x;
 {
         double roundoff();
         int i;

         x = roundoff(x, &d, pr + ((d > 0) ? d : 0));
         if (d < 0)
                 *s++ = '0';
         else
                 while (d >= 0)
                 {        *s++ = pickdigit(&x);
                         d--;
                 }
         if ((i = pr) >= 0)
                 *s++ = '.';
         while (++d < 0 AND i-- > 0)
                 *s++ = '0';
         while (i-- > 0)
                 *s++ = pickdigit(&x);
         *s = NULL;
 }

 /************************************************************************/
         LOCAL VOID
 expform(s, x, d, pr)        /* put x * 10^d (precision pr) into string s
                            in e-format
 /*----------------------------------------------------------------------*/
 STRING s;
 double x;
 {
         double roundoff();
         int i;

         x = roundoff(x, &d, i = pr);
         *s++ = pickdigit(&x);
         *s++ = '.';
         while (i-- > 0)
                 *s++ = pickdigit(&x);
         *s++ = 'e';
         itoa(s, d, 0);        /* minimum width */
 }

 /*\p*********************************************************************/
         LOCAL VOID
 minform(s, x, d, pr)        /* put x * 10^d into string s in minimum format
                            with precision pr                                *
 /*----------------------------------------------------------------------*/
 STRING s;
 double x;
 {
         int i, j;

         if (d < 5)
         {        floatform(s, x, d, pr);
                 i = strlen(s) - 1;
                 while (s[i] IS '0')
                         s[i--] = NULL;
                 if (s[i] IS '.')
                         s[i--] = NULL;
         }
         else
         {        expform(s, x, d, pr);
                 j = strlen(s) - 1;
                 while (s[j] ISNT 'e')
                         j--;
                 for (i = j - 1; s[i] IS '0'; i--)
                         ;
                 strcpy(&s[++i], &s[j]);
         }
 }

 /************************************************************************/
         LOCAL
 pickdigit(x)        /* return ascii leading digit of x, strip it off, and
                    prepare x for extraction of next digit.                */
 /*----------------------------------------------------------------------*/
 double *x;
 {
         int n;

         n = *x;                        /* take integer part.
         *x = 10 * ( *x - n);        /* strip it off, and renormalize x
         return (n + '0');
 }
 /*\p*********************************************************************/
         LOCAL double
 roundoff(x, d, p)        /* return x * 10^*d rounded to precision p        */

 /*----------------------------------------------------------------------*/
 double x;
 int *d;
 {                                   /*************************************/
         LOCAL double rounder[21] = /* NOTE: DPRECISION must be no larger*/
                                    /* than the number of elements in        *
                                    /* this array.                        */
                                    /*************************************/
         {        0.5,     0.5e-1,  0.5e-2,  0.5e-3,  0.5e-4,  0.5e-5,
                 0.5e-6,  0.5e-7,  0.5e-8,  0.5e-9,  0.5e-10, 0.5e-11,
                 0.5e-12, 0.5e-13, 0.5e-14, 0.5e-15, 0.5e-16, 0.5e-17,
                 0.5e-18, 0.5e-19, 0.5e-20
         };
         double y;

         if ((y = x) ISNT 0.0)
                 if (p <= DPRECISION)
                         if ((x += rounder[p]) >= 10.0)
                         {        x = y / 10.0 + rounder[p];
                                 ++*d;
                         }
         return x;
 }


 FTOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FTOC.C


   /* print Fahrenheit-Celsius table
         for f = 0, 20, ..., 300
         (This program is from p. 8 of the Kernighan and Ritchie text)
         */
 main()
 {
     int lower, upper, step;
     float fahr, celsius;

     lower = 0;         /* lower limit of temperature table */
     upper = 300;       /* upper limit */
     step = 20;         /* step size */

     fahr = lower;
     while (fahr <= upper) {
         celsius = (5.0/9.0) * (fahr-32.0);
         printf("%4.0f %6.1f\n", fahr, celsius);
         fahr = fahr + step;
     }
 }



 FULLPATH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FULLPATH.C

 #include <osbind.h>
 #include <stdio.h>

 char *fullpath(full, part)
 register char *full;
 register char *part;
 /*
  *        <part> is a (possibly) ambiguous file/path specification.  A
  *        non-ambiguous file/path spec is created which includes a drive
  *        letter and all intermediate sub-directories.  If the partial
  *        specification is not valid, NULL is returned, otherwise a
  *        pointer to <full> is returned.  If NULL is specified for <full>,
  *        an internal buffer is used and a pointer to it is returned.
  */
 {
         static char buf[PATHSIZE];
         register char *bp = buf;
         register int drv;
         char *strlwr(), *strcpy();

         if (*part && (part[1] == ':')) {
                 drv = *bp++ = *part++;
                 drv = ((drv - 1) & 0xF);
                 *bp++ = *part++;
         }
         else {
                 *bp++ = (drv = Dgetdrv()) + 'a';
                 *bp++ = ':';
         }
         if (*part == '\\')
                 ++part;
         else {
                 Dgetpath(bp, drv+1);        /* 1 BASED drive number here */
                 while(*bp++)
                         ;
                 --bp;
         }
         *bp++ = '\\';
         *bp = '\0';
         while(*part) {                        /* handle dots and copy path &
                 if (*part == '.') {
                         if (*++part == '.') {
                                 if (*++part == '\\') {        /* parent */
                                         --bp;
                                         while((*--bp != '\\') && (*bp != ':')
                                                 ;
                                         if (*bp++ == ':')
                                                 ++bp;
                                         ++part;
                                 }
                                 else
                                         return(NULL);        /* illegal pathn
                         }
                         else if (*part++ != '\\')
                                 return(NULL);                /* illegal pathn
                 }
                 else
                         while(*part && ((*bp++ = *part++) != '\\'))
                                 ;
         }
         *bp = '\0';
         if (full == NULL)        /* special case to use local buffer */
                 full = buf;
         return(strlwr(strcpy(full, buf)));        /* lowercase and return */
 }


 FUNC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\FUNC.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 /*      function compilation routines           */

 funcbody(sp)
 /*
  *      funcbody starts with the current symbol being either
  *      the first parameter id or the begin for the local
  *      block. If begin is the current symbol then funcbody
  *      assumes that the function has no parameters.
  */
 SYM     *sp;
 {       char    *names[20];             /* 20 parameters maximum */
         int     nparms, poffset, i;
         SYM     *sp1, *makeint();
         global_flag = 0;
         poffset = 8;            /* size of return block */
         nparms = 0;
         if(lastst == id) {              /* declare parameters */
                 while(lastst == id) {
                         names[nparms++] = litlate(lastid);
                         getsym();
                         if( lastst == comma)
                                 getsym();
                         else
                                 break;
                         }
                 needpunc(closepa);
                 dodecl(sc_member);      /* declare parameters */
                 for(i = 0;i < nparms;++i) {
                         if( (sp1 = search(names[i],lsyms.head)) == 0)
                                 sp1 = makeint(names[i]);
                                                 if( sp1->tp->size < 4 )
                                                 {
                                                         sp1->value.i = poffse
                                                         poffset += 4;
                                                 }
                                                 else
                                                 {
                                                         sp1->value.i = poffse
                                                         poffset += sp1->tp->s
                                                 }
                         sp1->storage_class = sc_auto;
                                         }
                 }
         if(lastst != begin)
                 error(ERR_BLOCK);
         else    {
                 cseg();
                 gen_strlab(sp->name);
                 block();
                 funcbottom();
                 }
         global_flag = 1;
 }

 SYM     *makeint(name)
 char    *name;
 {       SYM     *sp;
         TYP     *tp;
         sp = xalloc(sizeof(SYM));
         tp = xalloc(sizeof(TYP));
         tp->type = bt_long;
         tp->size = 4;
         tp->btp = tp->lst.head = 0;
         tp->sname = 0;
         sp->name = name;
         sp->storage_class = sc_auto;
         sp->tp = tp;
         insert(sp,&lsyms);
         return sp;
 }

 check_table(head)
 SYM     *head;
 {       while( head != 0 ) {
                 if( head->storage_class == sc_ulabel )
                         fprintf(list,"*** UNDEFINED LABEL - %s\n",head->name)
                 head = head->next;
                 }
 }

 funcbottom()
 {       nl();
         check_table(lsyms.head);
         lc_auto = 0;
         fprintf(list,"\n\n*** local symbol table ***\n\n");
         list_table(&lsyms,0);
         fprintf(list,"\n\n\n");
         release_local();        /* release local symbols */
 }

 block()
 {       needpunc(begin);
         dodecl(sc_auto);
                 cseg();
         genfunc(compound());
         flush_peep();
 }



 FUNKEY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FUNKEY.C


 /*           FUNKEY.C - a program for redefining fyunction keys  */
 /*                                                               */
 /*           Copyright  (C)  1983  Kenneth C. Wood               */
 /*                                                               */
 /*           From PC Magazine - - June 1983  Page 424            */
 /*                                                               */
 /*     Works with IBM PC-DOS 2.0 - to use it, have on your       */
 /*     system disk the files:                                    */
 /*     ANSI.SYS - supplied with DOS                              */
 /*     CONFIG.SYS - file with the line "device = ansi.sys" in it */
 /*     and one or more files with the extension .KEY i.e.        */
 /*     WORDSTAR.KEY, MYOWN.KEY, FUNKEY.KEY, or                   */
 /*     DOS.KEY - supplied by you and containing                  */
 /*     your chosen new key definitions, and of course            */
 /*     FUNKEY.EXE - the compiled and linked FUNKEY.C             */
 /*                                                               */
 /*     Now when the system is booted, the ANSI terminal          */
 /*     emulator device driver will be installed, giving          */
 /*     you the capability to do marvelous things, including      */
 /*     redefine the function keys by issuing the command:        */
 /*              FUNKEY MYOWN.KEY                                 */


  SEQ "\033[0;"       /* Initial sequence to ANSI driver */

 "stdio.h"          /* Copy in the standard I/O routines */

 main(argc,argv)
 int argc;
 char *argv[];

 {
         FILE *fp, *fopen();

         if  (argc == 1)
                 {
                 printf("\nEnter new key definitions\n\n");
                 fkey(stdin);         /* get input from keyboard */
                 }
         else
                 {
                 fp = fopen(*++argv,"r");
                 fkey(fp);       /* get input from the file */
                 }
 }

 int count = 0;  /* counter for tracking size of the table */

 fkey(fp)
 FILE *fp;
 {
         int c,offset;
         /* input character and function key identifier */

         while((c=getch(fp)) != EOF)
         {
                 switch (c)
                 {
                 case 'f':       /* F1 through F10 */
                         offset = 58;
                         func(getch(fp),offset,fp);
                         break;
                 case 's':       /* Shift F1 through F10 */
                         offset = 83;
                         func(getch(fp),offset,fp);
                         break;
                 case 'c':       /* Control F1 through F10 */
                         offset = 93;
                         func(getch(fp),offset,fp);
                         break;
                 case 'a':       /* Alt F1 through F10 */
                         offset = 103;
                         func(getch(fp),offset,fp);
                         break;
                 case 'F':       /* F1 through F10 */
                         offset = 58;
                         func(getch(fp),offset,fp);
                         break;
                 case 'S':       /* Shift F1 through F10 */
                         offset = 83;
                         func(getch(fp),offset,fp);
                         break;
                 case 'C':       /* Control F1 through F10 */
                         offset = 93;
                         func(getch(fp),offset,fp);
                         break;
                 case 'A':       /* Alt F1 through F10 */
                         offset = 103;
                         func(getch(fp),offset,fp);
                         break;
                 default:
                         printf("Unknown function key\n");
                         break;
                 }
         }
 }

 getch(fp)
 /* throw away white space until a character */
 FILE *fp;
 {
 int x;

         while((x=getc(fp)) == ' '|| x == '\n' || x == '\t')
                 ;       /* ignore white space */
         return(x);
 }


 func(c,offset,fp)
 /* send out the required definition sequence */
 int c,offset;
 FILE  *fp;
 {
         int x,save;

         save = ' ';
         while ((x = getch(fp)) != '=')
                 if (x == '0') c = ':';
                 /* read until get = sign */
                 /* if character is 0 then F10 was chosen */
                 /* rather than F1.  Change c so that offset is */
                 /* calculated correctly */
         printf(SEQ);
         printf("%d",offset+(c-'0'));

 /*      putchar(';');
         putchar('"');
 */
         while ((x = getc(fp)) != '\n')
                 {
                 if (x != '!')
                         {
 /*                      putchar(x);  */
                         printf(";%2d",x);

                         if (++count == 128)
                         {
                 printf("\nTable size exceeded.  Program terminated...\n");
                 exit();
                         }
                 }
                 else
                         save = x;
         }
         /*putchar('"');*/
         if (save == '!')
                 {
                 printf(";13p");
                 count++;
                 }
         else
                 printf("p");
         save = ' ';
         if (count  == 128)
         {
                 printf("\nTable size exceeded.  Program terminated...\n");
                 exit();
         }
 }

 /* end of Program Funkey.C  */



 FUNKEY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\FUNKEY.C

 /* FUNKEY.C - Typed from Microsoft C Programming for the IBM    */
 /* by Robert Lafore, page 275. Assigns function key to string   */
 /* typed by user, uses any number of command line arguments.    */
 /****************************************************************/

 main(argc,argv)
 int argc;
 char *argv[];
 {


 FUNKEY0.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\FUNKEY0.C

 /* FUNKEY0.C - Typed from Microsoft C Programming for the IBM   */
 /* by Robert Lafore, page 274. Assigns function key to string   */
 /* typed by user, uses command line arguments.                  */
 /****************************************************************/

 main(argc,argv)
 int argc;
 char *argv[];
 {
 int key;

    if(argc != 3) {
       printf("Example usage: A>funkey0 2 dir");
       exit();
    }
    key = atoi(arcv[1]);
    printf("\x1B[0;%d;\"%s\";13p", key+58, argv[2]);
 }



 FWRITE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\FWRITE.C

 /* 1.0  12-14-84                                                 (fwrite.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/

 fwrite(ptr, ptrsiz, nitems, fp)        /* Append at most nitems of data of ty
                                    *ptr to FILE fp.  Return number of
                                    items actually written.                */
 /*----------------------------------------------------------------------*/
 FAST BUFFER ptr;
 FILE *fp;
 {
         int items;
         FAST int c, i;
         METACHAR putc();

         for (items = 0; items < nitems; ++items)
         {        for (i = ptrsiz; i; --i)
                 {        if (putc(*ptr++, fp) IS EOF)
                                 return items;
                 }
         }
         return items;
 }


 FWRITE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\FWRITE.C

 #include <osbind.h>
 #include <stdio.h>

 int fwrite(data, size, count, fp)
 register char *data;
 int size;
 int count;
 register FILE *fp;
 /*
  *        Write <count> items of <size> characters each to stream <fp>.
  *        Data is read from the buffer pointed to by <data>.  The number of
  *        full items actually written is returned, or a negative error code.
  */
 {
         register long n, lsiz;

         lsiz = ((long) size);
         n = ((long) count) * lsiz;
         n = Fwrite(fileno(fp), n, data);
         return((n > 0) ? (n / lsiz) : n);
 }


 FXOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\FXOC.C


 /**
 * name         fxu -- function extract utility
 *
 * usage        fxu filename function
 *
 *              where "filename" is the name of a file containing
 *              several C functions, and "function" is the name of
 *              the particular function to be extracted.  If the
 *              named function is found, then (1) standard input is
 *              copied to the standard output until EOF, and (2) the
 *              text of the named function is written to the standard
 *              output.  The first option allows header information
 *              to be prepended to the output file.
 *
 **/

 #include "stdio.h"
 #include "ctype.h"

 MAX 16        /* maximum characters in function name */
 MAXBUF 2000   /* maximum characters buffered between functions */

 main(argc, argv)
 int argc;
 char *argv[];
 {
 int c, brace, cnest, nc;
 int i, ns, copy, inlit, delim, pc;
 FILE *sfp;
 char symbol[MAX+1];
 char text[MAXBUF];

 if (argc != 3)
    {
    fputs("Usage: fxu filename function\n", stderr);
    exit(1);
    }
 if ((sfp = fopen(argv[1], "r")) == NULL)
    {
    fputs("Can't open source file\n", stderr);
    exit(1);
    }
 brace = cnest = nc = ns = copy = inlit = pc = 0;
 c = getc(sfp);        /* get first char */
 while (c != EOF)
    {                 /* scan through source file */
    if (ns == MAXBUF)
        {
        fputs("Maximum buffer size exceeded\n", stderr);
        exit(1);
        }
    if (copy == 0)
        {
        if (brace == 0) text[ns++] = c;  /* save chars between functions */
        }
    else
        if (putchar(c) == EOF)
            {
            fputs("Copy error\n", stderr);
            exit(1);
            }
    if (c == '/')
        {             /* possible comment */
        nc = 0;
        if ((c = getc(sfp)) == '*')
            {
            ++cnest;   /* bump nesting level */
            if (copy) putchar(c);
            else if (brace == 0) text[ns++] = c;
            c = getc(sfp);
            }
        continue;
        }
    if (cnest != 0)
        {             /* inside comment */
        if (c == '*')
            {
            if ((c = getc(sfp)) == '/')
               {
               --cnest;       /* reduce nesting level */
               if (copy) putchar(c);
               else if (brace == 0) text[ns++] = c;
               c = getc(sfp);
               }
            continue;
            }
        nc = 0;
        }
    else if (inlit)
        {               /* inside literal string */
        if (c == '\\' && pc == '\\') c = 0;
        if (c == delim && pc != '\\') inlit = 0;
        pc = c;         /* save previous character */
        }
    else if (c == '\'' || c == '\"')
        {               /* enter literal string */
        inlit = 1;
        pc = 0;
        delim = c;
        }
    else if (c == '{') ++brace;
    else if (c == '}')
        {             /* right brace */
        nc = 0;
        if (--brace == 0)
            if (copy == 0) ns = 0;      /* reset save index if not found */
            else
                {               /* copy complete */
                putchar('\n');
                exit(0);
                }
        }
    else if (brace == 0)
        {
        if (nc == 0)
            {             /* symbol not started yet */
            if (iscsymf(c))
                symbol[nc++] = c;  /* start new symbol */
            }
        else if (iscsym(c) || c == '$')
                      /* continue symbol */
            if (nc < MAX) symbol[nc++] = c;
            else symbol[0] = '\0';
        else if (nc != 0)
            {             /* end of current symbol */
            symbol[nc++] = '\0';
            if (strcmp(symbol,argv[2]) == 0)
                {               /* named function has been found */
                while ((c = getchar()) != EOF)
                    putchar(c);         /* copy standard input to output */
                for (i = 0; i < ns; i++)
                    putchar(text[i]);           /* copy saved characters */
                copy = 1;       /* turn on copy flag */
                }
            nc = 0;
            }
        }
    c = getc(sfp);      /* get next char */
    }

 fputs("Named function not found\n", stderr);
 exit(1);
 }



 FXOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\FXOC.C


 /**
 * name         fxu -- function extract utility
 *
 * usage        fxu filename function
 *
 *              where "filename" is the name of a file containing
 *              several C functions, and "function" is the name of
 *              the particular function to be extracted.  If the
 *              named function is found, then (1) standard input is
 *              copied to the standard output until EOF, and (2) the
 *              text of the named function is written to the standard
 *              output.  The first option allows header information
 *              to be prepended to the output file.
 *
 **/

 #include "stdio.h"
 #include "ctype.h"

 MAX 16        /* maximum characters in function name */
 MAXBUF 2000   /* maximum characters buffered between functions */

 main(argc, argv)
 int argc;
 char *argv[];
 {
 int c, brace, cnest, nc;
 int i, ns, copy, inlit, delim, pc;
 FILE *sfp;
 char symbol[MAX+1];
 char text[MAXBUF];

 if (argc != 3)
    {
    fputs("Usage: fxu filename function\n", stderr);
    exit(1);
    }
 if ((sfp = fopen(argv[1], "r")) == NULL)
    {
    fputs("Can't open source file\n", stderr);
    exit(1);
    }
 brace = cnest = nc = ns = copy = inlit = pc = 0;
 c = getc(sfp);        /* get first char */
 while (c != EOF)
    {                 /* scan through source file */
    if (ns == MAXBUF)
        {
        fputs("Maximum buffer size exceeded\n", stderr);
        exit(1);
        }
    if (copy == 0)
        {
        if (brace == 0) text[ns++] = c;  /* save chars between functions */
        }
    else
        if (putchar(c) == EOF)
            {
            fputs("Copy error\n", stderr);
            exit(1);
            }
    if (c == '/')
        {             /* possible comment */
        nc = 0;
        if ((c = getc(sfp)) == '*')
            {
            ++cnest;   /* bump nesting level */
            if (copy) putchar(c);
            else if (brace == 0) text[ns++] = c;
            c = getc(sfp);
            }
        continue;
        }
    if (cnest != 0)
        {             /* inside comment */
        if (c == '*')
            {
            if ((c = getc(sfp)) == '/')
               {
               --cnest;       /* reduce nesting level */
               if (copy) putchar(c);
               else if (brace == 0) text[ns++] = c;
               c = getc(sfp);
               }
            continue;
            }
        nc = 0;
        }
    else if (inlit)
        {               /* inside literal string */
        if (c == '\\' && pc == '\\') c = 0;
        if (c == delim && pc != '\\') inlit = 0;
        pc = c;         /* save previous character */
        }
    else if (c == '\'' || c == '\"')
        {               /* enter literal string */
        inlit = 1;
        pc = 0;
        delim = c;
        }
    else if (c == '{') ++brace;
    else if (c == '}')
        {             /* right brace */
        nc = 0;
        if (--brace == 0)
            if (copy == 0) ns = 0;      /* reset save index if not found */
            else
                {               /* copy complete */
                putchar('\n');
                exit(0);
                }
        }
    else if (brace == 0)
        {
        if (nc == 0)
            {             /* symbol not started yet */
            if (iscsymf(c))
                symbol[nc++] = c;  /* start new symbol */
            }
        else if (iscsym(c) || c == '$')
                      /* continue symbol */
            if (nc < MAX) symbol[nc++] = c;
            else symbol[0] = '\0';
        else if (nc != 0)
            {             /* end of current symbol */
            symbol[nc++] = '\0';
            if (strcmp(symbol,argv[2]) == 0)
                {               /* named function has been found */
                while ((c = getchar()) != EOF)
                    putchar(c);         /* copy standard input to output */
                for (i = 0; i < ns; i++)
                    putchar(text[i]);           /* copy saved characters */
                copy = 1;       /* turn on copy flag */
                }
            nc = 0;
            }
        }
    c = getc(sfp);      /* get next char */
    }

 fputs("Named function not found\n", stderr);
 exit(1);
 }



 GENCODE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\GENCODE.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 /*
  *      this module contains all of the code generation routines
  *      for evaluating expressions and conditions.
  */

 extern struct amode     push[], pop[];

 struct amode    *gen_expr();            /* forward declaration */

 struct amode    *make_label(lab)
 /*
  *      construct a reference node for an internal label number.
  */
 int     lab;
 {       struct enode    *lnode;
         struct amode    *ap;
         lnode = xalloc(sizeof(struct enode));
         lnode->nodetype = en_labcon;
         lnode->v.i = lab;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_direct;
         ap->offset = lnode;
         return ap;
 }

 struct amode    *make_immed(i)
 /*
  *      make a node to reference an immediate value i.
  */
 int     i;
 {       struct amode    *ap;
         struct enode    *ep;
         ep = xalloc(sizeof(struct enode));
         ep->nodetype = en_icon;
         ep->v.i = i;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_immed;
         ap->offset = ep;
         return ap;
 }

 struct amode    *make_offset(node)
 /*
  *      make a direct reference to a node.
  */
 struct enode    *node;
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_direct;
         ap->offset = node;
         return ap;
 }

 make_legal(ap,flags,size)
 /*
  *      make_legal will coerce the addressing mode in ap1 into a
  *      mode that is satisfactory for the flag word.
  */
 struct amode    *ap;
 int             flags, size;
 {       struct amode    *ap2;
         if( ((flags & F_VOL) == 0) || ap->tempflag )
                 {
                 switch( ap->mode )
                         {
                         case am_immed:
                                 if( flags & F_IMMED )
                                         return;         /* mode ok */
                                 break;
                         case am_areg:
                                 if( flags & F_AREG )
                                         return;
                                 break;
                         case am_dreg:
                                 if( flags & F_DREG )
                                         return;
                                 break;
                         case am_ind:    case am_indx:
                         case am_indx2:  case am_xpc:
                         case am_direct: case am_indx3:
                                 if( flags & F_MEM )
                                         return;
                                 break;
                         }
                 }
         if( flags & F_DREG )
                 {
                 freeop(ap);             /* maybe we can use it... */
                 ap2 = temp_data();      /* allocate to dreg */
                 gen_code(op_move,size,ap,ap2);
                 ap->mode = am_dreg;
                 ap->preg = ap2->preg;
                 ap->deep = ap2->deep;
                 ap->tempflag = 1;
                 return;
                 }
         if( size == 1 )
                 {
                 freeop(ap);
                 ap2 = temp_data();
                 gen_code(op_move,1,ap,ap2);
                 gen_code(op_ext,2,ap2,0);
                 freeop(ap);
                 ap->mode = ap2->mode;
                 ap->preg = ap2->preg;
                 ap->deep = ap2->deep;
                 size = 2;
                 }
         freeop(ap);
         ap2 = temp_addr();
         gen_code(op_move,size,ap,ap2);
         ap->mode = am_areg;
         ap->preg = ap2->preg;
         ap->deep = ap2->deep;
         ap->tempflag = 1;
 }

 do_extend(ap,isize,osize,flags)
 /*
  *      if isize is not equal to osize then the operand ap will be
  *      loaded into a register (if not already) and if osize is
  *      greater than isize it will be extended to match.
  */
 struct amode    *ap;
 int             isize, osize, flags;
 {       if( isize == osize )
                 return;
         if( ap->mode != am_areg && ap->mode != am_dreg )
                 make_legal(ap,flags & (F_AREG | F_DREG),isize);
         if( ap->mode == am_areg )
                 return;         /* extend is automagic */
         switch( isize )
                 {
                 case 1:
                         gen_code(op_ext,2,ap,0);
                 case 2:
                         if( osize == 4 )
                                 gen_code(op_ext,4,ap,0);
                 }
 }

 int     isshort(node)
 /*
  *      return true if the node passed can be generated as a short
  *      offset.
  */
 struct enode    *node;
 {       return node->nodetype == en_icon &&
                 (node->v.i >= -65536 && node->v.i <= 65535);
 }

 int     isbyte(node)
 /*
  *      return true if the node passed can be evaluated as a byte
  *      offset.
  */
 struct enode    *node;
 {       return node->nodetype == en_icon &&
                 (-128 <= node->v.i && node->v.i <= 127);
 }

 struct amode    *gen_index(node)
 /*
  *      generate code to evaluate an index node (^+) and return
  *      the addressing mode of the result. This routine takes no
  *      flags since it always returns either am_ind or am_indx.
  */
 struct enode    *node;
 {       struct amode    *ap1, *ap2;
         if( node->v.p[0]->nodetype == en_tempref &&
                 node->v.p[1]->nodetype == en_tempref &&
                 ( node->v.p[0]->v.i >= 8 || node->v.p[1]->v.i >= 8 ))
                 {       /* both nodes are registers, one is address */
                 if( node->v.p[0]->v.i < 8 )
                         {
                         ap1 = gen_expr(node->v.p[1],F_AREG,4);
                         ap1->sreg = node->v.p[0]->v.i;
                         ap1->mode = am_indx2;   /* 0(Ax,Dx) */
                         ap1->offset = makenode(en_icon,0,0);
                         return ap1;
                         }
                 ap1 = gen_expr(node->v.p[0],F_AREG,4);
                 ap2 = gen_expr(node->v.p[1],F_AREG | F_DREG,4);
                 if( ap2->mode == am_dreg )
                         {
                         ap1->mode = am_indx2;
                         ap1->sreg = ap2->preg;
                         }
                 else
                         {
                         ap1->mode = am_indx3;
                         ap1->sreg = ap2->preg;
                         }
                 ap1->offset = makenode(en_icon,0,0);
                 return ap1;
                 }
         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4);
         if( ap1->mode == am_immed && isshort(ap1->offset) )
                 {
                 ap2 = gen_expr(node->v.p[1],F_AREG,4);
                 ap2->mode = am_indx;
                 ap2->offset = ap1->offset;
                 return ap2;
                 }
         ap2 = gen_expr(node->v.p[1],F_ALL,4);   /* get right op */
         if( ap2->mode == am_immed && isshort(ap2->offset) &&
                         ap1->mode == am_areg ) /* make am_indx */
                 {
                 ap2->mode = am_indx;
                 ap2->preg = ap1->preg;
                 ap2->deep = ap1->deep;
                 return ap2;
                 }
         validate(ap1);
         make_legal(ap1,F_AREG | F_VOL,4);
         gen_code(op_add,4,ap2,ap1);             /* add left to address reg */
         ap1->mode = am_ind;             /* make indirect */
         freeop(ap2);                    /* release any temps in ap2 */
         return ap1;                     /* return indirect */
 }

 struct amode    *gen_deref(node,flags,size)
 /*
  *      return the addressing mode of a dereferenced node.
  */
 struct enode    *node;
 int             flags, size;
 {       struct amode    *ap1;
         int             siz1;
         switch( node->nodetype )        /* get load size */
                 {
                 case en_b_ref:
                         siz1 = 1;
                         break;
                 case en_w_ref:
                         siz1 = 2;
                         break;
                 case en_l_ref:
                         siz1 = 4;
                         break;
                 }
         if( node->v.p[0]->nodetype == en_add )
                 {
                 ap1 = gen_index(node->v.p[0]);
                 do_extend(ap1,siz1,size,flags);
                 make_legal(ap1,flags,size);
                 return ap1;
                 }
         else if( node->v.p[0]->nodetype == en_autocon )
                 {
                 ap1 = xalloc(sizeof(struct amode));
                 ap1->mode = am_indx;
                 ap1->preg = 6;
                 ap1->offset = makenode(en_icon,node->v.p[0]->v.i);
                 do_extend(ap1,siz1,size,flags);
                 make_legal(ap1,flags,size);
                 return ap1;
                 }
         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4); /* generate address
         if( ap1->mode == am_areg )
                 {
                 ap1->mode = am_ind;
                 do_extend(ap1,siz1,size,flags);
                 make_legal(ap1,flags,size);
                 return ap1;
                 }
         ap1->mode = am_direct;
         do_extend(ap1,siz1,size,flags);
         make_legal(ap1,flags,size);
         return ap1;
 }

 struct amode    *gen_unary(node,flags,size,op)
 /*
  *      generate code to evaluate a unary minus or complement.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap;
         ap = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
         gen_code(op,size,ap,0);
         make_legal(ap,flags,size);
         return ap;
 }

 struct amode    *gen_binary(node,flags,size,op)
 /*
  *      generate code to evaluate a binary node and return
  *      the addressing mode of the result.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap1, *ap2;
         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG | F_AREG,size);
         ap2 = gen_expr(node->v.p[1],F_ALL,size);
         validate(ap1);          /* in case push occurred */
         gen_code(op,size,ap2,ap1);
         freeop(ap2);
         make_legal(ap1,flags,size);
         return ap1;
 }

 struct amode    *gen_xbin(node,flags,size,op)
 /*
  *      generate code to evaluate a restricted binary node and return
  *      the addressing mode of the result.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap1, *ap2;
         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG,size);
         ap2 = gen_expr(node->v.p[1],F_DREG,size);
         validate(ap1);          /* in case push occurred */
         gen_code(op,size,ap2,ap1);
         freeop(ap2);
         make_legal(ap1,flags,size);
         return ap1;
 }
 struct amode    *gen_shift(node,flags,size,op)
 /*
  *      generate code to evaluate a shift node and return the
  *      address mode of the result.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap1, *ap2;
         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,1);
         validate(ap1);
         gen_code(op,size,ap2,ap1);
         freeop(ap2);
         make_legal(ap1,flags,size);
         return ap1;
 }

 struct amode    *gen_modiv(node,flags,size,op,modflag)
 /*
  *      generate code to evaluate a mod operator or a divide
  *      operator. these operations are done on only long
  *      divisors and word dividends so that the 68000 div
  *      instruction can be used.
  */
 struct enode    *node;
 int             flags, op, size, modflag;
 {       struct amode    *ap1, *ap2;
         if( node->v.p[0]->nodetype == en_icon )
                 swap_nodes(node);
         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
         ap2 = gen_expr(node->v.p[1],F_ALL,2);
         validate(ap1);
         gen_code(op,0,ap2,ap1);
         if( modflag )
                 gen_code(op_swap,0,ap1,0);
         gen_code(op_ext,4,ap1,0);
         make_legal(ap1,flags,4);
         freeop(ap2);
         return ap1;
 }

 swap_nodes(node)
 /*
  *      exchange the two operands in a node.
  */
 struct enode    *node;
 {       struct enode    *temp;
         temp = node->v.p[0];
         node->v.p[0] = node->v.p[1];
         node->v.p[1] = temp;
 }

 struct amode    *gen_mul(node,flags,size,op)
 /*
  *      generate code to evaluate a multiply node. both operands
  *      are treated as words and the result is long and is always
  *      in a register so that the 68000 mul instruction can be used.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap1, *ap2;
         if( node->v.p[0]->nodetype == en_icon )
                 swap_nodes(node);
         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,2);
         ap2 = gen_expr(node->v.p[1],F_ALL,2);
         validate(ap1);
         gen_code(op,0,ap2,ap1);
         freeop(ap2);
         make_legal(ap1,flags,4);
         return ap1;
 }

 struct amode    *gen_hook(node,flags,size)
 /*
  *      generate code to evaluate a condition operator node (?:)
  */
 struct enode    *node;
 int             flags, size;
 {       struct amode    *ap1, *ap2;
         int             false_label, end_label;
         false_label = nextlabel++;
         end_label = nextlabel++;
         flags = (flags & (F_AREG | F_DREG)) | F_VOL;
         falsejp(node->v.p[0],false_label);
         node = node->v.p[1];
         ap1 = gen_expr(node->v.p[0],flags,size);
         freeop(ap1);
         gen_code(op_bra,0,make_label(end_label),0);
         gen_label(false_label);
         ap2 = gen_expr(node->v.p[1],flags,size);
         if( !equal_address(ap1,ap2) )
                 {
                 freeop(ap2);
                 if( ap1->mode == am_dreg )
                         temp_data();
                 else
                         temp_addr();
                 gen_code(op_move,size,ap2,ap1);
                 }
         gen_label(end_label);
         return ap1;
 }

 struct amode    *gen_asadd(node,flags,size,op)
 /*
  *      generate a plus equal or a minus equal node.
  */
 struct enode    *node;
 int             flags,size,op;
 {       struct amode    *ap1, *ap2;
         int             ssize, mask0, mask1;
         ssize = natural_size(node->v.p[0]);
         if( ssize > size )
                 size = ssize;
         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
         ap2 = gen_expr(node->v.p[1],F_DREG | F_AREG | F_IMMED,size);
         validate(ap1);
         gen_code(op,ssize,ap2,ap1);
         freeop(ap2);
         do_extend(ap1,ssize,size);
         make_legal(ap1,flags,size);
         return ap1;
 }

 struct amode    *gen_aslogic(node,flags,size,op)
 /*
  *      generate a and equal or a or equal node.
  */
 struct enode    *node;
 int             flags,size,op;
 {       struct amode    *ap1, *ap2, *ap3;
         int             ssize, mask0, mask1;
         ssize = natural_size(node->v.p[0]);
         if( ssize > size )
                 size = ssize;
         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,size);
         validate(ap1);
         if( ap1->mode != am_areg )
                 gen_code(op,ssize,ap2,ap1);
         else
                 {
                 ap3 = temp_data();
                 gen_code(op_move,4,ap1,ap3);
                 gen_code(op,size,ap2,ap3);
                 gen_code(op_move,size,ap3,ap1);
                 freeop(ap3);
                 }
         freeop(ap2);
         do_extend(ap1,ssize,size);
         make_legal(ap1,flags,size);
         return ap1;
 }

 gen_asshift(node,flags,size,op)
 /*
  *      generate shift equals operators.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap1, *ap2, *ap3;
         ap1 = gen_expr(node->v.p[0],F_ALL,size);
         if( ap1->mode != am_dreg )
                 {
                 ap3 = temp_data();
                 gen_code(op_move,size,ap1,ap3);
                 }
         else
                 ap3 = ap1;
         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,size);
         validate(ap3);
         gen_code(op,size,ap2,ap3);
         freeop(ap2);
         if( ap3 != ap1 )
                 {
                 gen_code(op_move,size,ap3,ap1);
                 freeop(ap3);
                 }
         make_legal(ap1,flags,size);
         return ap1;
 }

 struct amode    *gen_asmul(node,flags,size)
 /*
  *      generate a *= node.
  */
 struct enode    *node;
 int             flags, size;
 {       struct amode    *ap1, *ap2, *ap3;
         int             siz1;
         siz1 = natural_size(node->v.p[0]);
         ap1 = gen_expr(node->v.p[1],F_DREG | F_VOL,2);
         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
         if( siz1 == 1 || ap2->mode == am_areg )
                 {
                 ap3 = temp_data();
                 gen_code(op_move,siz1,ap2,ap3);
                 if( siz1 == 1 )
                         gen_code(op_ext,2,ap3,0);
                 freeop(ap3);
                 }
         else
                 ap3 = ap2;
         gen_code(op_muls,0,ap3,ap1);
         gen_code(op_move,siz1,ap1,ap2);
         freeop(ap2);
         return ap1;
 }

 struct amode    *gen_asmodiv(node,flags,size,op)
 /*
  *      generate /= and %= nodes.
  */
 struct enode    *node;
 int             flags, size, op;
 {       struct amode    *ap1, *ap2, *ap3;
         int             siz1;
         siz1 = natural_size(node->v.p[0]);
         ap1 = temp_data();
         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
         validate(ap1);
         gen_code(op_move,siz1,ap2,ap1);
         do_extend(ap1,siz1,4);
         ap3 = gen_expr(node->v.p[1],F_ALL & ~F_AREG,2);
         validate(ap2);
         validate(ap1);
         gen_code(op_divs,0,ap3,ap1);
         freeop(ap3);
         if( op != op_divs )
                 gen_code(op_swap,0,ap1,0);
         gen_code(op_ext,4,ap1,0);
         gen_code(op_move,siz1,ap1,ap2);
         freeop(ap2);
         make_legal(ap1,flags,size);
         return ap1;
 }

 struct amode    *gen_assign(node,flags,size)
 /*
  *      generate code for an assignment node. if the size of the
  *      assignment destination is larger than the size passed then
  *      everything below this node will be evaluated with the
  *      assignment size.
  */
 struct enode    *node;
 int             flags, size;
 {       struct amode    *ap1, *ap2;
         int             ssize;
         switch( node->v.p[0]->nodetype )
                 {
                 case en_b_ref:
                         ssize = 1;
                         break;
                 case en_w_ref:
                         ssize = 2;
                         break;
                 case en_l_ref:
                 case en_tempref:
                         ssize = 4;
                         break;
                 }
         if( ssize > size )
                 size = ssize;
         ap2 = gen_expr(node->v.p[1],F_ALL,size);
         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
         validate(ap2);
         gen_code(op_move,ssize,ap2,ap1);
         freeop(ap1);
         return ap2;
 }

 struct amode    *gen_aincdec(node,flags,size,op)
 /*
  *      generate an auto increment or decrement node. op should be
  *      either op_add (for increment) or op_sub (for decrement).
  */
 struct enode    *node;
 int             flags, size;
 {       struct amode    *ap1, *ap2;
         int             siz1;
         siz1 = natural_size(node->v.p[0]);
         if( flags & F_NOVALUE )         /* dont need result */
                 {
                 ap1 = gen_expr(node->v.p[0],F_ALL,siz1);
                 gen_code(op,siz1,make_immed(node->v.p[1]),ap1);
                 freeop(ap1);
                 return ap1;
                 }
         if( flags & F_DREG )
                 ap1 = temp_data();
         else
                 ap1 = temp_addr();
         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
         validate(ap1);
         gen_code(op_move,siz1,ap2,ap1);
         gen_code(op,siz1,make_immed(node->v.p[1]),ap2);
         freeop(ap2);
         do_extend(ap1,siz1,size);
         return ap1;
 }

 push_param(ep)
 /*
  *      push the operand expression onto the stack.
  */
 struct enode    *ep;
 {       struct amode    *ap;
         ap = gen_expr(ep,F_ALL,4);
         gen_code(op_move,4,ap,push);
         freeop(ap);
 }

 int     gen_parms(plist)
 /*
  *      push a list of parameters onto the stack and return the
  *      number of parameters pushed.
  */
 struct enode    *plist;
 {       int     i;
         i = 0;
         while( plist != 0 )
                 {
                 push_param(plist->v.p[0]);
                 plist = plist->v.p[1];
                 ++i;
                 }
         return i;
 }

 struct amode    *gen_fcall(node,flags)
 /*
  *      generate a function call node and return the address mode
  *      of the result.
  */
 struct enode    *node;
 {       struct amode    *ap, *result;
         int             i;
         result = temp_addr();
         temp_addr();                    /* push any used addr temps */
         freeop(result); freeop(result);
         result = temp_data();
         temp_data(); temp_data();       /* push any used data registers */
         freeop(result); freeop(result); freeop(result);
         i = gen_parms(node->v.p[1]);    /* generate parameters */
         if( node->v.p[0]->nodetype == en_nacon )
                 gen_code(op_jsr,0,make_offset(node->v.p[0]),0);
         else
                 {
                 ap = gen_expr(node->v.p[0],F_AREG,4);
                 ap->mode = am_ind;
                 freeop(ap);
                 gen_code(op_jsr,0,ap,0);
                 }
         if( i != 0 )
                 gen_code(op_add,4,make_immed(i * 4),makeareg(7));
         if( flags & F_DREG )
                 result = temp_data();
         else
                 result = temp_addr();
         if( result->preg != 0 || (flags & F_DREG) == 0 )
                 gen_code(op_move,4,makedreg(0),result);
         return result;
 }

 struct amode    *gen_expr(node,flags,size)
 /*
  *      general expression evaluation. returns the addressing mode
  *      of the result.
  */
 struct enode    *node;
 int             flags, size;
 {       struct amode    *ap1, *ap2;
         int             lab0, lab1;
         int             natsize;
         if( node == 0 )
                 {
                 printf("DIAG - null node in gen_expr.\n");
                 return 0;
                 }
         switch( node->nodetype )
                 {
                 case en_icon:
                 case en_labcon:
                 case en_nacon:
                         ap1 = xalloc(sizeof(struct amode));
                         ap1->mode = am_immed;
                         ap1->offset = node;
                         make_legal(ap1,flags,size);
                         return ap1;
                 case en_autocon:
                         ap1 = temp_addr();
                         ap2 = xalloc(sizeof(struct amode));
                         ap2->mode = am_indx;
                         ap2->preg = 6;          /* frame pointer */
                         ap2->offset = node;     /* use as constant node */
                         gen_code(op_lea,0,ap2,ap1);
                         make_legal(ap1,flags,size);
                         return ap1;             /* return reg */
                 case en_b_ref:
                 case en_w_ref:
                 case en_l_ref:
                         return gen_deref(node,flags,size);
                 case en_tempref:
                         ap1 = xalloc(sizeof(struct amode));
                         if( node->v.i < 8 )
                                 {
                                 ap1->mode = am_dreg;
                                 ap1->preg = node->v.i;
                                 }
                         else
                                 {
                                 ap1->mode = am_areg;
                                 ap1->preg = node->v.i - 8;
                                 }
                         ap1->tempflag = 0;      /* not a temporary */
                         make_legal(ap1,flags,size);
                         return ap1;
                 case en_uminus:
                         return gen_unary(node,flags,size,op_neg);
                 case en_compl:
                         return gen_unary(node,flags,size,op_not);
                 case en_add:
                         return gen_binary(node,flags,size,op_add);
                 case en_sub:
                         return gen_binary(node,flags,size,op_sub);
                 case en_and:
                         return gen_binary(node,flags,size,op_and);
                 case en_or:
                         return gen_binary(node,flags,size,op_or);
                                 case en_xor:
                                                 return gen_xbin(node,flags,si
                 case en_mul:
                         return gen_mul(node,flags,size,op_muls);
                 case en_umul:
                         return gen_mul(node,flags,size,op_mulu);
                 case en_div:
                         return gen_modiv(node,flags,size,op_divs,0);
                 case en_udiv:
                         return gen_modiv(node,flags,size,op_divu,0);
                 case en_mod:
                         return gen_modiv(node,flags,size,op_divs,1);
                 case en_umod:
                         return gen_modiv(node,flags,size,op_divu,1);
                 case en_lsh:
                         return gen_shift(node,flags,size,op_asl);
                 case en_rsh:
                         return gen_shift(node,flags,size,op_asr);
                 case en_asadd:
                         return gen_asadd(node,flags,size,op_add);
                 case en_assub:
                         return gen_asadd(node,flags,size,op_sub);
                 case en_asand:
                         return gen_aslogic(node,flags,size,op_and);
                 case en_asor:
                         return gen_aslogic(node,flags,size,op_or);
                 case en_aslsh:
                         return gen_asshift(node,flags,size,op_asl);
                 case en_asrsh:
                         return gen_asshift(node,flags,size,op_asr);
                 case en_asmul:
                         return gen_asmul(node,flags,size);
                 case en_asdiv:
                         return gen_asmodiv(node,flags,size,op_divs);
                 case en_asmod:
                         return gen_asmodiv(node,flags,size,op_muls);
                 case en_assign:
                         return gen_assign(node,flags,size);
                 case en_ainc:
                         return gen_aincdec(node,flags,size,op_add);
                 case en_adec:
                         return gen_aincdec(node,flags,size,op_sub);
                 case en_land:   case en_lor:
                 case en_eq:     case en_ne:
                 case en_lt:     case en_le:
                 case en_gt:     case en_ge:
                 case en_ult:    case en_ule:
                 case en_ugt:    case en_uge:
                 case en_not:
                         lab0 = nextlabel++;
                         lab1 = nextlabel++;
                         falsejp(node,lab0);
                         ap1 = temp_data();
                         gen_code(op_moveq,0,make_immed(1),ap1);
                         gen_code(op_bra,0,make_label(lab1),0);
                         gen_label(lab0);
                         gen_code(op_clr,4,ap1,0);
                         gen_label(lab1);
                         return ap1;
                 case en_cond:
                         return gen_hook(node,flags,size);
                 case en_void:
                         natsize = natural_size(node->v.p[0]);
                         freeop(gen_expr(node->v.p[0],F_ALL | F_NOVALUE,natsiz
                         return gen_expr(node->v.p[1],flags,size);
                 case en_fcall:
                         return gen_fcall(node,flags);
                 default:
                         printf("DIAG - uncoded node in gen_expr.\n");
                         return 0;
                 }
 }

 int     natural_size(node)
 /*
  *      return the natural evaluation size of a node.
  */
 struct enode    *node;
 {       int     siz0, siz1;
         if( node == 0 )
                 return 0;
         switch( node->nodetype )
                 {
                 case en_icon:
                         if( -128 <= node->v.i && node->v.i <= 127 )
                                 return 1;
                         if( -32768 <= node->v.i && node->v.i <= 32767 )
                                 return 2;
                         return 4;
                 case en_fcall:  case en_labcon:
                 case en_nacon:  case en_autocon:
                 case en_l_ref:  case en_tempref:
                 case en_cbl:    case en_cwl:
                         return 4;
                 case en_b_ref:
                         return 1;
                 case en_cbw:
                 case en_w_ref:
                         return 2;
                 case en_not:    case en_compl:
                 case en_uminus: case en_assign:
                 case en_ainc:   case en_adec:
                         return natural_size(node->v.p[0]);
                 case en_add:    case en_sub:
                 case en_mul:    case en_div:
                 case en_mod:    case en_and:
                 case en_or:     case en_xor:
                 case en_lsh:    case en_rsh:
                 case en_eq:     case en_ne:
                 case en_lt:     case en_le:
                 case en_gt:     case en_ge:
                 case en_land:   case en_lor:
                 case en_asadd:  case en_assub:
                 case en_asmul:  case en_asdiv:
                 case en_asmod:  case en_asand:
                 case en_asor:   case en_aslsh:
                 case en_asrsh:
                         siz0 = natural_size(node->v.p[0]);
                         siz1 = natural_size(node->v.p[1]);
                         if( siz1 > siz0 )
                                 return siz1;
                         else
                                 return siz0;
                 case en_void:   case en_cond:
                         return natural_size(node->v.p[1]);
                 default:
                         printf("DIAG - natural size error.\n");
                         break;
                 }
         return 0;
 }

 gen_compare(node)
 /*
  *      generate code to do a comparison of the two operands of
  *      node.
  */
 struct enode    *node;
 {       struct amode    *ap1, *ap2;
         int             size;
         size = natural_size(node);
         ap1 = gen_expr(node->v.p[0],F_AREG | F_DREG, size);
         ap2 = gen_expr(node->v.p[1],F_ALL,size);
         validate(ap1);
         gen_code(op_cmp,size,ap2,ap1);
         freeop(ap2);
         freeop(ap1);
 }

 truejp(node,label)
 /*
  *      generate a jump to label if the node passed evaluates to
  *      a true condition.
  */
 struct enode    *node;
 int             label;
 {       struct amode    *ap1;
         int             siz1;
         int             lab0;
         if( node == 0 )
                 return;
         switch( node->nodetype )
                 {
                 case en_eq:
                         gen_compare(node);
                         gen_code(op_beq,0,make_label(label),0);
                         break;
                 case en_ne:
                         gen_compare(node);
                         gen_code(op_bne,0,make_label(label),0);
                         break;
                 case en_lt:
                         gen_compare(node);
                         gen_code(op_blt,0,make_label(label),0);
                         break;
                 case en_le:
                         gen_compare(node);
                         gen_code(op_ble,0,make_label(label),0);
                         break;
                 case en_gt:
                         gen_compare(node);
                         gen_code(op_bgt,0,make_label(label),0);
                         break;
                 case en_ge:
                         gen_compare(node);
                         gen_code(op_bge,0,make_label(label),0);
                         break;
                 case en_ult:
                         gen_compare(node);
                         gen_code(op_blo,0,make_label(label),0);
                         break;
                 case en_ule:
                         gen_compare(node);
                         gen_code(op_bls,0,make_label(label),0);
                         break;
                 case en_ugt:
                         gen_compare(node);
                         gen_code(op_bhi,0,make_label(label),0);
                         break;
                 case en_uge:
                         gen_compare(node);
                         gen_code(op_bhs,0,make_label(label),0);
                         break;
                 case en_land:
                         lab0 = nextlabel++;
                         falsejp(node->v.p[0],lab0);
                         truejp(node->v.p[1],label);
                         gen_label(lab0);
                         break;
                 case en_lor:
                         truejp(node->v.p[0],label);
                         truejp(node->v.p[1],label);
                         break;
                 case en_not:
                         falsejp(node->v.p[0],label);
                         break;
                 default:
                         siz1 = natural_size(node);
                         ap1 = gen_expr(node,F_ALL,siz1);
                         gen_code(op_tst,siz1,ap1,0);
                         freeop(ap1);
                         gen_code(op_bne,0,make_label(label),0);
                         break;
                 }
 }

 falsejp(node,label)
 /*
  *      generate code to execute a jump to label if the expression
  *      passed is false.
  */
 struct enode    *node;
 int             label;
 {       struct amode    *ap;
         int             siz1;
         int             lab0;
         if( node == 0 )
                 return;
         switch( node->nodetype )
                 {
                 case en_eq:
                         gen_compare(node);
                         gen_code(op_bne,0,make_label(label),0);
                         break;
                 case en_ne:
                         gen_compare(node);
                         gen_code(op_beq,0,make_label(label),0);
                         break;
                 case en_lt:
                         gen_compare(node);
                         gen_code(op_bge,0,make_label(label),0);
                         break;
                 case en_le:
                         gen_compare(node);
                         gen_code(op_bgt,0,make_label(label),0);
                         break;
                 case en_gt:
                         gen_compare(node);
                         gen_code(op_ble,0,make_label(label),0);
                         break;
                 case en_ge:
                         gen_compare(node);
                         gen_code(op_blt,0,make_label(label),0);
                         break;
                 case en_ult:
                         gen_compare(node);
                         gen_code(op_bhs,0,make_label(label),0);
                         break;
                 case en_ule:
                         gen_compare(node);
                         gen_code(op_bhi,0,make_label(label),0);
                         break;
                 case en_ugt:
                         gen_compare(node);
                         gen_code(op_bls,0,make_label(label),0);
                         break;
                 case en_uge:
                         gen_compare(node);
                         gen_code(op_blo,0,make_label(label),0);
                         break;
                 case en_land:
                         falsejp(node->v.p[0],label);
                         falsejp(node->v.p[1],label);
                         break;
                 case en_lor:
                         lab0 = nextlabel++;
                         truejp(node->v.p[0],lab0);
                         falsejp(node->v.p[1],label);
                         gen_label(lab0);
                         break;
                 case en_not:
                         truejp(node->v.p[0],label);
                         break;
                 default:
                         siz1 = natural_size(node);
                         ap = gen_expr(node,F_ALL,siz1);
                         gen_code(op_tst,siz1,ap,0);
                         freeop(ap);
                         gen_code(op_beq,0,make_label(label),0);
                         break;
                 }
 }



 GENINDEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\WNDWBOSS\GENINDEX.C

 /*
 ** GENINDEX - Create index from text file.
 **
 ** Support Program for The Window BOSS
 **
 ** Copyright (c) 1984,1985,1986 - Philip A. Mongelluzzo
 ** All rights reserved.
 **
 ** Note: The GENINDEX.EXE file was created using the CI86 compiler.
 **       If you attempt to recompile this program with either Lattice
 **       or MSC you may have to adjust the logic to account for the way
 **       the various compilers treat <CR><LF> sequences.  This usually
 **       amounts to nothing more than chaning the "rb" to "r" in the
 **       fopen statement.
 */

 <stdio.h>                      /* Standard stuff */

 FILE *fopen();                          /* keep the compilers happy */
 long ftell();

 main(argc,argv)
 int argc;
 char *argv[];
 {
 FILE *fp;
 FILE *fo;
 char buf[132];
 static char fname[132];
 unsigned i;
 long pos;
 char *p;

   if(argc < 2) {                        /* check command line */
     printf("Usage: genindex <filename.ext>");
     exit(1);
   }

   p = argv[1];                          /* parse input filename */
   i = 0;
   while(*p) {
     fname[i++] = *p++;
     if(*p == ' ' || *p == '.') break;
   }
   strcat(fname, ".ndx");                /* create output filename */

   fp = fopen(argv[1], "rb");            /* open input */
   if(!fp) {
     printf("Open failed: %s", argv[1]);
     exit(1);
   }
   printf("Creating: %s\n", fname);      /* say whats going on */
   fo = fopen(fname, "w");               /* open output */

   while(fgets(&buf[0],132,fp)) {        /* read lines till eof */
     if(buf[0] == '%') {                 /* look for subject heading key */
       fputs(buf, fo);                   /* write to index file */
       fputs(buf, stdout);               /* display on console */
       pos = ftell(fp);                  /* get file position */
       printf("%ld\n", pos);             /* display on console */
       fprintf(fo, "%ld\n", pos);        /* write in output file */
     }
   }
   fclose(fp);                           /* close files */
   fclose(fo);
 }

 /* End */


 GENSTMT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\GENSTMT.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 int     breaklab;
 int     contlab;
 int     retlab;

 extern TYP              stdfunc;
 extern struct amode     push[], pop[];

 struct amode    *makedreg(r)
 /*
  *      make an address reference to a data register.
  */
 int     r;
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_dreg;
         ap->preg = r;
         return ap;
 }

 struct amode    *makeareg(r)
 /*
  *      make an address reference to an address register.
  */
 int     r;
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_areg;
         ap->preg = r;
         return ap;
 }

 struct amode    *make_mask(mask)
 /*
  *      generate the mask address structure.
  */
 int     mask;
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_mask;
         ap->offset = mask;
         return ap;
 }

 struct amode    *make_direct(i)
 /*
  *      make a direct reference to an immediate value.
  */
 int     i;
 {       return make_offset(makenode(en_icon,i,0));
 }

 struct amode    *make_strlab(s)
 /*
  *      generate a direct reference to a string label.
  */
 char    *s;
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_direct;
         ap->offset = makenode(en_nacon,s,0);
         return ap;
 }

 genwhile(stmt)
 /*
  *      generate code to evaluate a while statement.
  */
 struct snode    *stmt;
 {       int     lab1, lab2;
         initstack();            /* initialize temp registers */
         lab1 = contlab;         /* save old continue label */
         lab2 = breaklab;        /* save old break label */
         contlab = nextlabel++;  /* new continue label */
         gen_label(contlab);
         if( stmt->s1 != 0 )      /* has block */
                 {
                 breaklab = nextlabel++;
                 initstack();
                 falsejp(stmt->exp,breaklab);
                 genstmt(stmt->s1);
                 gen_code(op_bra,0,make_label(contlab),0);
                 gen_label(breaklab);
                 breaklab = lab2;        /* restore old break label */
                 }
         else                                                /* no loop code *
                 {
                 initstack();
                 truejp(stmt->exp,contlab);
                 }
         contlab = lab1;         /* restore old continue label */
 }

 gen_for(stmt)
 /*
  *      generate code to evaluate a for loop
  */
 struct snode    *stmt;
 {       int     old_break, old_cont, exit_label, loop_label;
         old_break = breaklab;
         old_cont = contlab;
         loop_label = nextlabel++;
         exit_label = nextlabel++;
         contlab = loop_label;
         initstack();
         if( stmt->label != 0 )
                 gen_expr(stmt->label,F_ALL | F_NOVALUE
                         ,natural_size(stmt->label));
         gen_label(loop_label);
         initstack();
         if( stmt->exp != 0 )
                 falsejp(stmt->exp,exit_label);
         if( stmt->s1 != 0 )
                 {
                 breaklab = exit_label;
                 genstmt(stmt->s1);
                 }
         initstack();
         if( stmt->s2 != 0 )
                 gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
         gen_code(op_bra,0,make_label(loop_label),0);
         breaklab = old_break;
         contlab = old_cont;
         gen_label(exit_label);
 }

 genif(stmt)
 /*
  *      generate code to evaluate an if statement.
  */
 struct snode    *stmt;
 {       int     lab1, lab2, oldbreak;
         lab1 = nextlabel++;     /* else label */
         lab2 = nextlabel++;     /* exit label */
         oldbreak = breaklab;    /* save break label */
         initstack();            /* clear temps */
         falsejp(stmt->exp,lab1);
         if( stmt->s1 != 0 && stmt->s1->next != 0 )
                 if( stmt->s2 != 0 )
                         breaklab = lab2;
                 else
                         breaklab = lab1;
         genstmt(stmt->s1);
         if( stmt->s2 != 0 )             /* else part exists */
                 {
                 gen_code(op_bra,0,make_label(lab2),0);
                 gen_label(lab1);
                 if( stmt->s2 == 0 || stmt->s2->next == 0 )
                         breaklab = oldbreak;
                 else
                         breaklab = lab2;
                 genstmt(stmt->s2);
                 gen_label(lab2);
                 }
         else                            /* no else code */
                 gen_label(lab1);
         breaklab = oldbreak;
 }

 gendo(stmt)
 /*
  *      generate code for a do - while loop.
  */
 struct snode    *stmt;
 {       int     oldcont, oldbreak;
         oldcont = contlab;
         oldbreak = breaklab;
         contlab = nextlabel++;
         gen_label(contlab);
         if( stmt->s1 != 0 && stmt->s1->next != 0 )
                 {
                 breaklab = nextlabel++;
                 genstmt(stmt->s1);      /* generate body */
                 initstack();
                 truejp(stmt->exp,contlab);
                 gen_label(breaklab);
                 }
         else
                 {
                 genstmt(stmt->s1);
                 initstack();
                 truejp(stmt->exp,contlab);
                 }
         breaklab = oldbreak;
         contlab = oldcont;
 }

 call_library(lib_name)
 /*
  *      generate a call to a library routine.
  */
 char    *lib_name;
 {       SYM     *sp;
         sp = gsearch(lib_name);
         if( sp == 0 )
                 {
                 ++global_flag;
                 sp = xalloc(sizeof(SYM));
                 sp->tp = &stdfunc;
                 sp->name = lib_name;
                 sp->storage_class = sc_external;
                 insert(sp,&gsyms);
                 --global_flag;
                 }
         gen_code(op_jsr,0,make_strlab(lib_name),0);
 }

 genswitch(stmt)
 /*
  *      generate a linear search switch statement.
  */
 struct snode    *stmt;
 {       int             curlab;
         struct snode    *defcase;
         struct amode    *ap;
         curlab = nextlabel++;
         defcase = 0;
         initstack();
         ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
         if( ap->preg != 0 )
                 gen_code(op_move,4,ap,makedreg(0));
         stmt = stmt->s1;
         call_library("c%switch");
         while( stmt != 0 )
                 {
                 if( stmt->s2 )          /* default case ? */
                         {
                         stmt->label = curlab;
                         defcase = stmt;
                         }
                 else
                         {
                         gen_code(op_dc,4,make_label(curlab),
                                 make_direct(stmt->label));
                         stmt->label = curlab;
                         }
                 if( stmt->s1 != 0 && stmt->next != 0 )
                         curlab = nextlabel++;
                 stmt = stmt->next;
                 }
         if( defcase == 0 )
                 gen_code(op_dc,4,make_direct(0),make_label(breaklab));
         else
                 gen_code(op_dc,4,make_direct(0),make_label(defcase->label));
 }

 gencase(stmt)
 /*
  *      generate all cases for a switch statement.
  */
 struct snode    *stmt;
 {       while( stmt != 0 )
                 {
                 if( stmt->s1 != 0 )
                         {
                         gen_label(stmt->label);
                         genstmt(stmt->s1);
                         }
                 else if( stmt->next == 0 )
                         gen_label(stmt->label);
                 stmt = stmt->next;
                 }
 }

 genxswitch(stmt)
 /*
  *      analyze and generate best switch statement.
  */
 struct snode    *stmt;
 {       int     oldbreak;
         oldbreak = breaklab;
         breaklab = nextlabel++;
         genswitch(stmt);
         gencase(stmt->s1);
         gen_label(breaklab);
         breaklab = oldbreak;
 }

 genreturn(stmt)
 /*
  *      generate a return statement.
  */
 struct snode    *stmt;
 {       struct amode    *ap;
         if( stmt != 0 && stmt->exp != 0 )
                 {
                 initstack();
                 ap = gen_expr(stmt->exp,F_ALL,4);
                 if( ap->mode != am_dreg || ap->preg != 0 )
                         gen_code(op_move,4,ap,makedreg(0));
                 }
         if( retlab == -1 )
                 {
                 retlab = nextlabel++;
                 gen_label(retlab);
                 if( save_mask != 0 )
                         gen_code(op_movem,4,pop,make_mask(save_mask));
                 gen_code(op_unlk,0,makeareg(6),0);
                 gen_code(op_rts,0,0,0);
                 }
         else
                 gen_code(op_bra,0,make_label(retlab),0);
 }

 genstmt(stmt)
 /*
  *      genstmt will generate a statement and follow the next pointer
  *      until the block is generated.
  */
 struct snode    *stmt;
 {       while( stmt != 0 )
                 {
                 switch( stmt->stype )
                         {
                         case st_label:
                                 gen_label(stmt->label);
                                 break;
                         case st_goto:
                                 gen_code(op_bra,0,make_label(stmt->label),0);
                                 break;
                         case st_expr:
                                 initstack();
                                 gen_expr(stmt->exp,F_ALL | F_NOVALUE,
                                         natural_size(stmt->exp));
                                 break;
                         case st_return:
                                 genreturn(stmt);
                                 break;
                         case st_if:
                                 genif(stmt);
                                 break;
                         case st_while:
                                 genwhile(stmt);
                                 break;
                         case st_for:
                                 gen_for(stmt);
                                 break;
                         case st_continue:
                                 gen_code(op_bra,0,make_label(contlab),0);
                                 break;
                         case st_break:
                                 gen_code(op_bra,0,make_label(breaklab),0);
                                 break;
                         case st_switch:
                                 genxswitch(stmt);
                                 break;
                         default:
                                 printf("DIAG - unknown statement.\n");
                                 break;
                         }
                 stmt = stmt->next;
                 }
 }

 genfunc(stmt)
 /*
  *      generate a function body.
  */
 struct snode    *stmt;
 {       retlab = contlab = breaklab = -1;
                 if( lc_auto & 1 )        /* if frame size odd */
                         ++lc_auto;                /* make it even */
         gen_code(op_link,0,makeareg(6),make_immed(-lc_auto));
         opt1(stmt);
         genstmt(stmt);
         genreturn(0);
 }



 GET.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\GET_IT\GET.C

 /* GET.C - From page 20 of Micro Cornucopia, No. 40,            */
 /* March/April 1988.                                            */
 /****************************************************************/

 #include <stdio.h>
 <stdlib.h>     /* Has prototypes for "un-headered" functs */
 <string.h>     /* Need for string functions */

 DATAFILE "get.dat" /* Name of directory-info file */
 #define MAXBUFF 256
 #define MATCH 0
 #define FAIL 1

 char buff[MAXBUFF],     /* Input buffer for file reads  */
      path[MAXBUFF],     /* Buffer for full path name    */
      drive[3];          /* Buffer for disk drive        */
    /*** Prototypes for non-standard functions ***/
 int search_file(FILE *fp, char *where);
 int do_switch(void);
 FILE *open_data_file(char *name);

 int main(int argc, char **argv)
 {
 int flag;
 FILE *fpin;

    if (argc != 2) {
       fprintf(stderr, "Usage: GET directory_abbreviation_name");
       exit(0);
    }
    fpin = open_data_file(DATAFILE);    /* Open the data file */
    flag = search_file(fpin, argv[1]);  /* Find the pseudo-name */
    fclose(fpin);                       /* We're done reading */

    if (flag == FAIL) {
       fprintf(stderr, "\nCannot find %s in data file.\n", argv[1]);
       exit(0);
    }

    flag = do_switch();           /* Try the change */
    if (flag != MATCH) {
       fprintf(stderr, "\nCannot find directory %s\n", path);
       exit(0);
    }
 }

 /*
    do_switch()
    Function to do the work.
    Argument list:    void
    Return value:     int      0 if successful, 1 on error
 */

 int do_switch(void)
 {
 int flag;
 int res;
 res = system(drive);       /* Function to issue command to command.com */
 if(res < 0)       /* and places us on the correct drive.      */
    perror("System call error");
 flag = chdir(path);  /* We should be there now.                  */
 if(flag < 0)
    perror("Change directory error");
 system("DIR");
 return flag;
 }

 /*
    search_file()
    Function reads the data file that holds the information about the
    directory locations, lookeng for a match on the string passed in.
    The format for the input file is:

    abbreviation  drive   full_pathname\n

    where:
       abbreviation  --  the abbreviation for the full path name
              drive  --  the disk drive designator for the search
      full_pathname  --  the full MSDOS pathname desired
                 \n  --  a newline terminates the data for each
                         possible directory
    Example:

    tut   c  \lessons\prog\tutorial

    When the user types: go tut, the user is moved to the \lessons\prog\
                         \tutorial directory on drive C:

    Argument list:    FILE *fp       a FILE pointer to the open file.
                      char *where    a string constant that is the short
                                     name for the directory desired.
    Return value:     int            0 if successful, 1 on no match
 */

 int search_file(FILE *fp, char *where)
 {
 char *ptr, temp[MAXBUFF];
 int c, i;

    i = 0;
    while ((c = fgetc(fp)) != EOF) {
       if (c != '\n') {
          buff[i++] = (char) c;
          continue;
       }
       buff[i] = '\0';
       strcpy(temp, buff);
       ptr = strtok(temp, " ");
       if (strcmp(ptr, where) == MATCH) {
          ptr = strtok((char *) 0, " ");      /* Get the disk drive */
          strcpy(drive, ptr);
 /*       strcat(drive, ":");   */ /* Removed from book version-doesn't work*/
          ptr = strtok((char *) 0, " ");      /* Get full path name */
          strcpy(path, ptr);
          return MATCH;                    /* ... and we're done */
       }
       i = 0;                  /* No match, start over */
    }
    return FAIL;
 }

 /*
          open_data_file()
    Function attempts to open the data file that holds the information
    about the directory locations. It does this by searching the PATH
    environment variable. The program assumes that the dat file is in
    the PATH directory.

    Argument list:    char *name     a string constant that is the name
                                     of the file containing the directory
                                     information.
    Return value:     FILE *fp       a FILE pointer to the open file if
                                     successful, program aborts on error.
 */

 FILE *open_data_file(char *name)
 {
 char *ptr, p[MAXBUFF], temp[MAXBUFF];
 FILE *fpin;

    ptr = getenv("PATH");            /* Find out where go.dat is.        */
                                     /* NOTE: PATH must be in caps       */
    if (ptr == NULL) {
       fprintf(stderr, "\nPATH not set. Program and data file must \
 be on PATH.\n");
       exit(0);
    }
    strcpy(p, ptr);
    ptr = strtok(p, ";");            /* Find first PATH                  */
    while (ptr != NULL) {
       strcpy(temp, ptr);            /* Save a copy of substring         */
 /*    strcat(temp, "\\");  */ /* Form a path and file name-doesn't work*/
       strcat(temp, name);
       if ((fpin = fopen(temp, "r")) == NULL) {
          temp[0] = '\0';            /* Start over again         */
          ptr = strtok((char *) 0, ";");   /* Try next path      */
       }
       else
          break;               /* Must have a good fpin          */
    }
    if (fpin == NULL) {
       fprintf(stderr, "\nCannot find %s on default path(s).\n", name);
       exit(0);
    }
    else
       return fpin;
 }



 GETBUF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETBUF.C

 /* 1.3  01-08-86                                                  (getbuf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /*----------------------------------------------------------------------*

                  STANDARD I/O STREAM DEFINITIONS:                        */

 FILE         IObuffs[MAXSTREAM] =         /* i/0 file stream table
 {        {0, 0, BUFSIZ,        0, 0, _BUSY, STDIN},
         {0, 0,        1,        0, 0, _BUSY, STDOUT},
         {0, 0,        1,      0, 0, _BUSY, STDERR},
         {0, 0,        0,      0, 0,         0,         0},
         {0, 0,        0,      0, 0,         0,        0},
         {0, 0,        0,      0, 0,         0,        0},
         {0, 0,        0,      0, 0,         0,         0},
         {0, 0,        0,      0, 0,         0,         0},
         {0, 0,        0,      0, 0,         0,         0},
         {0, 0,        0,      0, 0,         0,        0}        /* MAXSTREAM
 };

 /************************************************************************/
         VOID
 getbuf(fp)                /* Get a std buffer either from allot(), or use
                            the bytbuf if none.        Attach to the FILE fp.
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 {
         BUFFER buffer, allot();

         if ((fp->_buflen < sizeof(HEADER))
            OR ((buffer = allot(fp->_buflen)) IS NULL))
         {        fp->_buff = &fp->_bytbuf;
                 fp->_buflen = 1;
                 return;
         }

         fp->_flags |= _ALLBUF;                /* indicate an allocated buffer
         fp->_buff = buffer;
         return;
 }


 GETC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETC.C

 /* 1.3  01-08-86                                                 (getc.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 getc(fp)                /* Get and return next character from FILE fp.
                            Return EOF if unable to do so.                */
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 {
         FAST int siz, c;

         if (fp->_bptr >= fp->_bend)
         {        if (fp->_flags & (_EOF | _IOERR)) /* if past end of file */
                         return EOF;

                 fp->_flags &= ~_DIRTY;                /* clean the flush flag
                 if (fp->_buff IS NULL)                /* attach a buffer,
                         getbuf(fp);                /*   if not yet done.
                 if ((siz = read(fp->_unit, fp->_buff, fp->_buflen)) <= 0)
                 {        fp->_flags |= (siz IS 0) ? _EOF : _IOERR;
                         return EOF;
                 }

                 fp->_bend = (fp->_bptr = fp->_buff) + siz;
         }
         _rowcol(c = *fp->_bptr++ & 0xff, fp);
         return c;

         redirbuf();        /* a dummy call to be sure redirbuf is linked in
                            when a getc is made and input is redirected
 }

 /*\p*********************************************************************/
         METACHAR
 getca(fp)                /* Get and return next ASCII character from FILE
                            fp.  Return EOF if unable to do so. Suppress
                            '\r', file is assumed text.
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 {
         FAST int c;

         c = getc(fp);
 #ifdef SYS_EOF
         if (c IS SYS_EOF)
         {        --fp->_bptr;
                 return EOF;
         }
 #endif
 #ifdef CRINSUP
         if (c IS '\r' OR c IS NULL)
                 c = getca(fp);
 #endif
         return c;
 }


 GETCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\GETCH.C

 #include <osbind.h>
 #include <stdio.h>

 static int        _cfg_ch = _CIOch;        /* getch()/putch() configuration *
 unsigned long        _getch = 0L;                /* raw getch() value from OS

 cfg_ch(cfg)
 int cfg;
 /*
  *        Configure getch()/putch() operation.  The following are legal
  *        values for <cfg> and may be combined with the | operator:
  *                _CIOb                Use BIOS level i/o calls
  *                _CIOch                8-bit character codes only (cf:getch)
  *                _CIOvt                Enable VT-52 escape sequence processi
  *        Return the previous value.  If <cfg> == -1, just return current val
  */
 {
         register int oldcfg;

         oldcfg = _cfg_ch;
         if(cfg != -1)
                 _cfg_ch = cfg;
         return(oldcfg);
 }

 int getch()
 /*
  *        Machine dependent console input function.  This function normally
  *        gets a character from the keyboard by calling the GEMDOS "Cconin"
  *        function.  If cfg_ch() is given the _CIOb option, input is gotten
  *        from the BIOS "Bconin" function instead.  The BIOS level functions
  *        don't process ^C, ^S or ^Q, while the GEMDOS functions do.  The
  *        most common use for getch() is when keyboard scan codes are needed
  *        to process special function keys.  The return value from getch()
  *        consists of the scan code in the high-order byte, and the ascii
  *        character code in the low-order byte.  If cfg_ch() is given the
  *        _CIOch option, the return value is always an 8-bit quantity,
  *        either the scan code with the 8th bit set, or the ascii code with
  *        the 8th bit clear.  This is somewhat less informative, since the
  *        scan code form is returned only if the ascii value is 0.  In any
  *        case, the global unsigned long variable "_getch" will contain the
  *        full value returned by the OS.
  */
 {
         register unsigned long cc;
         register unsigned int c;

         _getch = cc = (_cfg_ch & _CIOb) ? Bconin(2) : Crawcin();
         if(_cfg_ch & _CIOch) {
                 if((c = cc) == 0)                /* null character code */
                         c = (cc >> 16) | 0x80;        /* get scan code instea
                 c &= 0xFF;                        /* make it 8-bit only */
         }
         else
                 c = (0x00FF & cc) | (0xFF00 & (cc >> 8));
         return(c);
 }

 char putch(c)
 register char c;
 /*
  *        Machine dependent (typically quite fast) console output function.
  */
 {
         if(_cfg_ch & _CIOb)
                 if((c < ' ') || (_cfg_ch & _CIOvt))
                         Bconout(2, c);
                 else
                         Bconout(5, c);
         else
                 Cconout(c);
         return(c);
 }

 int getche()
 /*
  *        Same as getch() but calls putch() to echo the character.
  */
 {
         register char c;

         c = getch();                        /* do normal getch() */
         putch((char) _getch);                /* echo from raw OS code */
         return(c);
 }

 int kbhit()
 /*
  *        Machine dependent function to detect if input is waiting for the
  *        getch() function.  Returns non-zero if the console has data ready.
  */
 {
         return((_cfg_ch & _CIOb) ? Bconstat(2) : Cconis());
 }


 GETDATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\GETDATE.C

 /*                            *** getdate.c ***                      */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Function to return a string containing the date in the format     */
 /* MM/DD/YY.                                                         */
 /*                                                                   */
 /* Written by L. Cuthbertson, May 1984                               */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define DELIM        '/'

 int getdate(string)
 char string[];
 {
         char month[3],day[3],year[5];
         int imo,iday,iyr;
         int i,j;

         /* call assembler routine to get date in integer format */
         dosdate(&imo,&iday,&iyr);

         /* convert integers into strings */
         sprintf(month,"%02d",imo);
         sprintf(day,"%02d",iday);
         sprintf(year,"%02d",iyr);

         /* build output string */
         j = 0;
         for(i=0;month[i] != NULL;i++)
                 string[j++] = month[i];

         string[j++] = DELIM;

         for(i=0;day[i] != NULL;i++)
                 string[j++] = day[i];

         string[j++] = DELIM;

         for(i=2;year[i] != NULL;i++)        /* skip century identifier */
                 string[j++] = year[i];

         string[j] = NULL;

         /* done */
         return(0);
 }


 GETDATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\GETDATE.C

 /*                            *** getdate.c ***                      */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Function to return a string containing the date in the format     */
 /* MM/DD/YY.                                                         */
 /*                                                                   */
 /* Written by L. Cuthbertson, May 1984                               */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define DELIM        '/'

 int getdate(string)
 char string[];
 {
         char month[3],day[3],year[5];
         int imo,iday,iyr;
         int i,j;

         /* call assembler routine to get date in integer format */
         dosdate(&imo,&iday,&iyr);

         /* convert integers into strings */
         sprintf(month,"%02d",imo);
         sprintf(day,"%02d",iday);
         sprintf(year,"%02d",iyr);

         /* build output string */
         j = 0;
         for(i=0;month[i] != NULL;i++)
                 string[j++] = month[i];

         string[j++] = DELIM;

         for(i=0;day[i] != NULL;i++)
                 string[j++] = day[i];

         string[j++] = DELIM;

         for(i=2;year[i] != NULL;i++)        /* skip century identifier */
                 string[j++] = year[i];

         string[j] = NULL;

         /* done */
         return(0);
 }


 GETENV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\GETENV.C

 #include <stdio.h>

 extern char        *_envp;

 static char *findenv(var)
 register char *var;
 /*
  *        INTERNAL FUNCTION.  This functions attempts to locate <var> in
  *        the environment.  If <var> is not found, NULL is returned.  If
  *        the environment is NULL, NULL is returned.  If <var> is found,
  *        a pointer to the beginning of <var> in the environment is returned.
  *        BOTH MS-DOS AND TOS ENVIRONMENT FORMATS ARE ACCOMODATED.
  */
 {
         register char *p;
         register int len;

         if((p = _envp) == NULL)
                 return(NULL);
         len = strlen(var);
         while(*p) {
                 if((p[len] == '=') && !strncmp(p, var, len))
                         return(p);
                 while(*p++)                /* move to next arg */
                         ;
         }
         return(NULL);
 }

 char *getenv(var)
 register char *var;
 /*
  *        Search for <var> in the environment.  If <var> is found, a pointer
  *        to it's value is returned.  NULL is returned if <var> is not found.
  *        WARNING:  The returned pointer points into the environment and
  *        must not be modified!
  */
 {
         register char *p, *q;
         register int len;

         len = strlen(var);
         if(p = findenv(var)) {
                 p += (len + 1);
                 if(*p == '\0') {        /* TOS env format or empty value */
                         q = p+1;
                         if(*q == '\0')                /* empty value + end of
                                 return(p);
                         while(*q && (*q != '='))
                                 ++q;
                         if(*q)                        /* empty value */
                                 return(p);
                         else                        /* TOS env format */
                                 return(p+1);
                 }
         }
         return(p);
 }


 GETF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETF.C

 /* 1.1  01-08-86                                                (getf.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         double
 getf(prompt, check, low, high)        /* Print prompt on stdout, then get and
                                    return double input from stdin.  If
                                    check is true, verify within bounds.
 /*----------------------------------------------------------------------*/
 STRING prompt;
 BOOL check;
 double low, high;
 {
         double value, atof();
         char s[MAXLINE];

         FOREVER
         {        value = atof(getns(prompt, s, MAXLINE - 1));
                 if (NOT check OR (low <= value AND value <= high))
                         break;
                 putstr("\nValue out of range, please reenter.\n");
         }
         return (value);
 }


 GETI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETI.C

 /* 1.1  01-08-86                                                (geti.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 #define MAXDIGITS        6

 /************************************************************************/

 geti(prompt, check, low, high)        /* Print prompt on stdout, then get and
                                    return integer input from stdin.  If
                                    check is true, verify within bounds.
 /*----------------------------------------------------------------------*/
 STRING prompt;
 BOOL check;
 {
         int value, atoi();
         char s[MAXDIGITS];

         FOREVER
         {        value = atoi(getns(prompt, s, MAXDIGITS - 1));
                 if (NOT check OR (low <= value AND value <= high))
                         break;
                 printf("\nValue out of range, please reenter:\n");
         }
         return (value);
 }


 GETKEYWO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\GETKEYWO.C


 #include <stdio.h>
 #include <string.h>
 #include "expert.h"


 /******************************************************************
 **
 **
 **                GET KEYWORD
 **
 **
 ******************************************************************/

 /*
 **
 **        getKeyWord(infile,keyWords,lineNum) ;
 **
 **        returns either KEY_EOF, or number of keyword, or indications
 **                that keyword was not first word on line.
 **
 */

 int        getKeyWord (infile,keyWords,lineNum)

 FILE        *infile ;
 char        *keyWords[] ;
 int        *lineNum ;

 {
 int        firstc,c,i,j ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-GET_KEYWORD") ;
 #endif

 /*
 **        get first non blank character
 */

 i = 0 ;
 while( TRUE )
         {
         c = getc(infile);
         putchar(c) ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-GET_KEYWORD character= %c,%x",c,c) ;
 #endif
         if( c == EOF )
                 return (KEY_EOF) ;
         if( (i == 0) && (c == COMMENT_CHAR) )        /* ignore comment line *
                 {
                 while(  c != EOL )
                         {
 #ifdef DEBUG
         fprintf(stdout,"\nDEBUG-GET_KEYWORD (delete comment) character=%c,%x"
 #endif
                         c = getc(infile) ;
                         if( c == EOF)
                                 return (KEY_EOF) ;
                         putchar(c) ;
                         }
                 printf("%04d  ",*lineNum) ;
                 *lineNum += 1 ;
                 i = 0 ;
                 }
         else
                 {
                 i = 1 ;
                 if( c != BLANK )
                         {
                         if(c == EOF)
                                 return(KEY_EOF) ;
                         break ;
                         }
                 }
         }

 /*
 **        locate first keyword with matching first character
 */

 for( i = 0 ; i < NUM_KEYWORDS ; i++ )
         {
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-GET_KEYWORD i=%d, keyword=%c",i,*(keyWords[i]
 #endif
         if ( *(keyWords[i]) == c )
                 break ;
         }
 if( i == NUM_KEYWORDS )
         return (KEY_WORD_ERROR)  ;

 /*
 **        find the key word if there
 **
 **        Note that this search algrorithm is very dependant on having
 **        the keyWord file being in strict alphabetical order!!!
 **
 */

 j=0 ;
 firstc = c ;

 while( i < NUM_KEYWORDS  )
         {
         if( (c=getc(infile)) == *(keyWords[i]+(++j)) )
                 {
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-GET_KEYWORD char=%c,keyword=%c",c,*((keyWords
 #endif
                 putchar(c) ;
                 if( c == BLANK )
                         return (i) ;
                 if( c == EOF )
                         return(KEY_EOF) ;
                 }
 /*
 **        increment the keyWord pointer to be tested
 **        decrement the character pointer in keyWord
 **        and put the last character tested back.
 */

 /*
 **        since the keyWord array is alphabetical, testing
 **        for a first character change would indicate that
 **        the possible keywords have been exhausted.
 */

         else
                 {
                 i++ ;
                 j-- ;
                 ungetc(c,infile) ;
                 if( c == EOF )
                         return (KEY_EOF) ;
                 if( firstc != *(keyWords[i]))
                         return (KEY_WORD_ERROR) ;
                 }
         }

 /*
 **        no keywords were found because we exhausted the keyWord array
 */

 return (KEY_WORD_ERROR)  ;
 }



 GETL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETL.C

 /* 1.1  01-08-86                                                (getl.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 MAXLDIGITS        11        /* Maximum digits in a long, + 1.        */

 /************************************************************************/
         long
 getl(prompt, check, low, high)        /* Print prompt on stdout, then get and
                                    return long integer input from stdin.
                                    If check is true, verify bounds.        */
 /*----------------------------------------------------------------------*/
 STRING prompt;
 BOOL check;
 long low, high;
 {
         long value, atol();
         char s[MAXLDIGITS];

         FOREVER
         {        value = atol(getns(prompt, s, MAXLDIGITS-1));
                 if (NOT check OR (low <= value AND value <= high))
                         break;
                 printf("\nValue out of range, please reenter:\n");
         }
         return (value);
 }


 GETLN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\GETLN.C

        KEY_UNDO        0x1B                /* escape */
 #define        KEY_CR                0x0D
 #define        KEY_LF                0x0A
 #define        KEY_BS                0x08
 #define        KEY_DEL                0x7F

 char *getln(ip, get, put, buffer, limit)
 char *ip;
 register int (*get)();
 register int (*put)();
 char *buffer;
 register int limit;
 /*
  *        Get a line of input from the user.  Allow simple editing of the lin
  *        with BS/DEL, ESC, and CR/LF to terminate input.  Characters are
  *        retreived by a (*get)(ip) and echoed with (*put)().  A pointer to
  *        <buffer> is returned in any case.
  */
 {
         register char *bp = buffer;
         register int c, i = 0;

         for(;;) {
                 c = (*get)(ip) & 0xFF;
                 if(c == KEY_UNDO) {
                         *(bp = buffer) = '\0';
                         i = 0;
                         break;
                 }
                 else if((c == KEY_CR) || (c == KEY_LF)) {
                         *bp = '\0';
                         break;
                 }
                 else if(((c == KEY_BS) || (c == KEY_DEL)) && (bp != buffer))
                         --bp;
                         (*put)('\b');
                         (*put)(' ');
                         (*put)('\b');
                         --i;
                 }
                 else if((c >= ' ') && (i < limit)) {
                         (*put)(*bp++ = c);
                         ++i;
                 }
         }
         return(buffer);
 }


 GETNS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETNS.C

 /* 1.2  01-08-86                                                (getns.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         STRING
 getns(p, s, n)                /* Prompt with message p on stdout, then get
                            string s of maximum n characters from stdin.
                            Return pointer to s.
 /*----------------------------------------------------------------------*/
 STRING p, s;
 {
         char line[MAXLINE];

         fputs(p, stdout);
         gets(line);
         strncpy(s, line, n);
         return s;
 }


 GETOPT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\CPG\GETOPT.C

 /*        @(#)getopt.c        1.5        */
 /*        3.0 SID #        1.2        */
 /*LINTLIBRARY*/
 #define NULL        0
 #define EOF        (-1)
 #define ERR(s, c)        if(opterr){\
         extern int strlen(), write();\
         char errbuf[2];\
         errbuf[0] = c; errbuf[1] = '\n';\
         (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
         (void) write(2, s, (unsigned)strlen(s));\
         (void) write(2, errbuf, 2);}

 extern int strcmp();
 extern char *strchr();

 int        opterr = 1;
 int        optind = 1;
 int        optopt;
 char        *optarg;

 int
 getopt(argc, argv, opts)
 int        argc;
 char        **argv, *opts;
 {
         static int sp = 1;
         register int c;
         register char *cp;

         if(sp == 1)
                 if(optind >= argc ||
                    argv[optind][0] != '-' || argv[optind][1] == '\0')
                         return(EOF);
                 else if(strcmp(argv[optind], "--") == NULL) {
                         optind++;
                         return(EOF);
                 }
         optopt = c = argv[optind][sp];
         if(c == ':' || (cp=strchr(opts, c)) == NULL) {
                 ERR(": illegal option -- ", c);
                 if(argv[optind][++sp] == '\0') {
                         optind++;
                         sp = 1;
                 }
                 return('?');
         }
         if(*++cp == ':') {
                 if(argv[optind][sp+1] != '\0')
                         optarg = &argv[optind++][sp+1];
                 else if(++optind >= argc) {
                         ERR(": option requires an argument -- ", c);
                         sp = 1;
                         return('?');
                 } else
                         optarg = argv[optind++];
                 sp = 1;
         } else {
                 if(argv[optind][++sp] == '\0') {
                         sp = 1;
                         optind++;
                 }
                 optarg = NULL;
         }
         return(c);
 }


 GETPID.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\GETPID.C

 extern char        *_base;

 int getpid()
 /*
  *        Return an integer value unique for this process.
  */
 {
         register unsigned long n;

         n = _base;                        /* load process base address */
         return(0x7FFF & (n>>8));        /* create unique pid from it */
 }


 GETS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\GETS.C

 /* 1.0  12-17-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         STRING
 gets(line)                /* get line up to newline or EOF from stdin.
                            Return line if ok, NULL if empty and EOF.        *
 /*----------------------------------------------------------------------*/
 STRING line;
 {
         FAST STRING s;
         FAST int i;

         s = line;
         while (((i = getchar()) ISNT EOF) AND (i ISNT '\n'))
                 *s++ = i;
         *s = NULL;
         if ((i IS EOF) AND (s IS line))
                 return NULL;

         return line;
 }


 GETS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\GETS.C

 #include <stdio.h>

 char *gets(data)
 register char *data;
 /*
  *        Get data from stdin and puts it in the <data> buffer.  Input is
  *        terminated when a newline is read.  The        newline will be repl
  *        by a '\0' to terminate the string.  A pointer to the start of
  *        <data> is returned, or NULL for EOF.
  */
 {
         register char *p = data;
         register int c;

         while(((c = fgetc(stdin)) != EOF) && (c != '\n')) {
                 if(c == '\b') {
                         if(p > data)
                                 --p;
                 }
                 else
                         *p++ = c;
         }
         *p = '\0';
         return(((c == EOF) && (p == data)) ? NULL : data);  /* NULL == EOF */
 }


 GETSYM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\GETSYM.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 static int      errno[80];
 static int      numerrs;
 static char     inline[132];
 int             total_errors = 0;
 char            *lptr;          /* shared with preproc */
 FILE            *inclfile[10];  /* shared with preproc */
 int             inclline[10];   /* shared with preproc */
 int             incldepth;      /* shared with preproc */
 char            *linstack[20];  /* stack for substitutions */
 char            chstack[20];    /* place to save lastch */
 int             lstackptr = 0;  /* substitution stack pointer */

 int     isalnum(c)
 char    c;
 {       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
                 (c >= '0' && c <= '9');
 }

 int     isidch(c)
 char    c;
 {       return isalnum(c) || c == '_' || c == '$';
 }

 int     isspace(c)
 char    c;
 {       return c == ' ' || c == '\t' || c == '\n';
 }

 int     isdigit(c)
 char    c;
 {       return (c >= '0' && c <= '9');
 }

 initsym()
 {       lptr = inline;
         inline[0] = 0;
         numerrs = 0;
         total_errors = 0;
         lineno = 0;
 }

 int     getline(listflag)
 int     listflag;
 {       int     rv;
         if( lineno > 0 && listflag) {
                 fprintf(list,"%6d\t%s",lineno,inline);
                 while(numerrs--)
                         fprintf(list," *** error %d\n",errno[numerrs]);
                 numerrs = 0;
                 }
         ++lineno;
         rv = (fgets(inline,131,input) == NULL);
         if( rv && incldepth > 0 ) {
                 fclose(input);
                 input = inclfile[--incldepth];
                 lineno = inclline[incldepth];
                 return getline(0);
                 }
         if( rv )
                 return 1;
         lptr = inline;
         if(inline[0] == '#')
                 return preprocess();
         return 0;
 }

 /*
  *      getch - basic get character routine.
  */
 int     getch()
 {       while( (lastch = *lptr++) == '\0') {
                 if( lstackptr > 0 ) {
                         lptr = linstack[--lstackptr];
                         lastch = chstack[lstackptr];
                         return lastch;
                         }
                 if(getline(incldepth == 0))
                         return lastch = -1;
                 }
         return lastch;
 }

 /*
  *      error - print error information
  */
 error(n)
 int     n;
 {       errno[numerrs++] = n;
         ++total_errors;
 }

 /*
  *      getid - get an identifier.
  *
  *      identifiers are any isidch conglomerate
  *      that doesn't start with a numeric character.
  *      this set INCLUDES keywords.
  */
 int     getid()
 {       register int    i;
         i = 0;
         while(isidch(lastch)) {
                 if(i < 19)
                         lastid[i++] = lastch;
                 getch();
                 }
         lastid[i] = '\0';
         lastst = id;
 }

 /*
  *      getsch - get a character in a quoted string.
  *
  *      this routine handles all of the escape mechanisms
  *      for characters in strings and character constants.
  */
 int     getsch()        /* return an in-quote character */
 {       register int    i, j;
         if(lastch == '\n')
                 return -1;
         if(lastch != '\\') {
                 i = lastch;
                 getch();
                 return i;
                 }
         getch();        /* get an escaped character */
         if(isdigit(lastch)) {
                 i = 0;
                 for(i = 0;j < 3;++j) {
                         if(lastch <= '7' && lastch >= '0')
                                 i = (i << 3) + lastch - '0';
                         else
                                 break;
                         getch();
                         }
                 return i;
                 }
         i = lastch;
         getch();
         switch(i) {
                 case '\n':
                         getch();
                         return getsch();
                 case 'b':
                         return '\b';
                 case 'f':
                         return '\f';
                 case 'n':
                         return '\n';
                 case 'r':
                         return '\r';
                                 case 't':
                                                 return '\t';
                 default:
                         return i;
                 }
 }

 int     radix36(c)
 char    c;
 {       if(isdigit(c))
                 return c - '0';
         if(c >= 'a' && c <= 'z')
                 return c - 'a' + 10;
         if(c >= 'A' && c <= 'Z')
                 return c - 'A' + 10;
         return -1;
 }

 /*
  *      getbase - get an integer in any base.
  */
 getbase(b)
 {       register int    i, j;
         i = 0;
         while(isalnum(lastch)) {
                 if((j = radix36(lastch)) < b) {
                         i = i * b + j;
                         getch();
                         }
                 else break;
                 }
         ival = i;
         lastst = iconst;
 }

 /*
  *      getfrac - get fraction part of a floating number.
  */
 getfrac()
 {       double  frmul;
         frmul = 0.1;
         while(isdigit(lastch)) {
                 rval += frmul * (lastch - '0');
                 getch();
                 frmul *= 0.1;
                 }
 }

 /*
  *      getexp - get exponent part of floating number.
  *
  *      this algorithm is primative but usefull.  Floating
  *      exponents are limited to +/-255 but most hardware
  *      won't support more anyway.
  */
 getexp()
 {       double  expo, exmul;
         expo = 1.0;
         if(lastst != rconst)
                 rval = ival;
         if(lastch = '-') {
                 exmul = 0.1;
                 getch();
                 }
         else
                 exmul = 10.0;
         getbase(10);
         if(ival > 255)
                 error(ERR_FPCON);
         else
                 while(ival--)
                         expo *= exmul;
         rval *= expo;
 }

 /*
  *      getnum - get a number from input.
  *
  *      getnum handles all of the numeric input. it accepts
  *      decimal, octal, hexidecimal, and floating point numbers.
  */
 getnum()
 {       register int    i, j, k;
         i = 0;
         if(lastch == '0') {
                 getch();
                 if(lastch == 'x' || lastch == 'X') {
                         getch();
                         getbase(16);
                         }
                 else getbase(8);
                 }
         else    {
                 getbase(10);
                 if(lastch == '.') {
                         getch();
                         rval = ival;    /* float the integer part */
                         getfrac();      /* add the fractional part */
                         lastst = rconst;
                         }
                 if(lastch == 'e' || lastch == 'E') {
                         getch();
                         getexp();       /* get the exponent */
                         }
                 }
 }

 /*
  *      getsym - get next symbol from input stream.
  *
  *      getsym is the basic lexical analyzer.  It builds
  *      basic tokens out of the characters on the input
  *      stream and sets the following global variables:
  *
  *      lastch:         A look behind buffer.
  *      lastst:         type of last symbol read.
  *      laststr:        last string constant read.
  *      lastid:         last identifier read.
  *      ival:           last integer constant read.
  *      rval:           last real constant read.
  *
  *      getsym should be called for all your input needs...
  */
 int     getsym()
 {       register int    i, j, k;
         SYM             *sp;
 restart:        /* we come back here after comments */
         while(isspace(lastch))
                 getch();
         if( lastch == -1)
                 lastst = eof;
         else if(isdigit(lastch))
                 getnum();
         else if(isidch(lastch)) {
                 getid();
                 if( (sp = search(lastid,defsyms.head)) != 0 ) {
                         linstack[lstackptr] = lptr;
                         chstack[lstackptr++] = lastch;
                         lptr = sp->value.s;
                         getch();
                         goto restart;
                         }
                 }
         else switch(lastch) {
                 case '+':
                         getch();
                         if(lastch == '+') {
                                 getch();
                                 lastst = autoinc;
                                 }
                         else if(lastch == '=') {
                                 getch();
                                 lastst = asplus;
                                 }
                         else lastst = plus;
                         break;
                 case '-':
                         getch();
                         if(lastch == '-') {
                                 getch();
                                 lastst = autodec;
                                 }
                         else if(lastch == '=') {
                                 getch();
                                 lastst = asminus;
                                 }
                         else if(lastch == '>') {
                                 getch();
                                 lastst = pointsto;
                                 }
                         else lastst = minus;
                         break;
                 case '*':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = astimes;
                                 }
                         else lastst = star;
                         break;
                 case '/':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = asdivide;
                                 }
                         else if(lastch == '*') {
                                 getch();
                                 for(;;) {
                                         if(lastch == '*') {
                                                 getch();
                                                 if(lastch == '/') {
                                                         getch();
                                                         goto restart;
                                                         }
                                                 }
                                         else
                                                 getch();
                                         }
                                 }
                         else lastst = divide;
                         break;
                 case '^':
                         getch();
                         lastst = uparrow;
                         break;
                 case ';':
                         getch();
                         lastst = semicolon;
                         break;
                 case ':':
                         getch();
                         lastst = colon;
                         break;
                 case '=':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = eq;
                                 }
                         else lastst = assign;
                         break;
                 case '>':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = geq;
                                 }
                         else if(lastch == '>') {
                                 getch();
                                 if(lastch == '=') {
                                         getch();
                                         lastst = asrshift;
                                         }
                                 else lastst = rshift;
                                 }
                         else lastst = gt;
                         break;
                 case '<':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = leq;
                                 }
                         else if(lastch == '<') {
                                 getch();
                                 if(lastch == '=') {
                                         getch();
                                         lastst = aslshift;
                                         }
                                 else lastst = lshift;
                                 }
                         else lastst = lt;
                         break;
                 case '\'':
                         getch();
                         ival = getsch();        /* get a string char */
                         if(lastch != '\'')
                                 error(ERR_SYNTAX);
                         else
                                 getch();
                         lastst = iconst;
                         break;
                 case '\"':
                         getch();
                         for(i = 0;i < MAX_STRLEN;++i) {
                                 if(lastch == '\"')
                                         break;
                                 if((j = getsch()) == -1)
                                         break;
                                 else
                                         laststr[i] = j;
                                 }
                         laststr[i] = 0;
                         lastst = sconst;
                         if(lastch != '\"')
                                 error(ERR_SYNTAX);
                         else
                                 getch();
                         break;
                 case '!':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = neq;
                                 }
                         else lastst = not;
                         break;
                 case '%':
                         getch();
                         if(lastch == '=') {
                                 getch();
                                 lastst = asmodop;
                                 }
                         else lastst = modop;
                         break;
                 case '~':
                         getch();
                         lastst = compl;
                         break;
                 case '.':
                         getch();
                         lastst = dot;
                         break;
                 case ',':
                         getch();
                         lastst = comma;
                         break;
                 case '&':
                         getch();
                         if( lastch == '&') {
                                 lastst = land;
                                 getch();
                                 }
                         else if( lastch == '=') {
                                 lastst = asand;
                                 getch();
                                 }
                         else
                                 lastst = and;
                         break;
                 case '|':
                         getch();
                         if(lastch == '|') {
                                 lastst = lor;
                                 getch();
                                 }
                         else if( lastch == '=') {
                                 lastst = asor;
                                 getch();
                                 }
                         else
                                 lastst = or;
                         break;
                 case '(':
                         getch();
                         lastst = openpa;
                         break;
                 case ')':
                         getch();
                         lastst = closepa;
                         break;
                 case '[':
                         getch();
                         lastst = openbr;
                         break;
                 case ']':
                         getch();
                         lastst = closebr;
                         break;
                 case '{':
                         getch();
                         lastst = begin;
                         break;
                 case '}':
                         getch();
                         lastst = end;
                         break;
                 case '?':
                         getch();
                         lastst = hook;
                         break;
                 default:
                         getch();
                         error(ERR_ILLCHAR);
                         goto restart;   /* get a real token */
                 }
         if(lastst == id)
                 searchkw();
 }

 needpunc(p)
 enum e_sym      p;
 {       if( lastst == p)
                 getsym();
         else
                 error(ERR_PUNCT);
 }



 GETTIME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\GETTIME.C

 /*                            *** gettime.c ***                      */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Function to return a string containing the time in the format     */
 /* HH:MM:SS (military time).                                         */
 /*                                                                   */
 /* Written by L. Cuthbertson, May 1984                               */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define DELIM   ':'

 int gettime(string)
 char string[];
 {
         char hours[3],minutes[3],seconds[3];
         int ih,im,is,iths;
         int i,j;

         /* call assembler routine to get time in integer format */
         dostime(&ih,&im,&is,&iths);

         /* convert integers to strings - ignore 1/100ths of second */
         sprintf(hours,"%02d",ih);
         sprintf(minutes,"%02d",im);
         sprintf(seconds,"%02d",is);

         /* build output string */
         j = 0;
         for(i=0;hours[i] != NULL;i++)
                 string[j++] = hours[i];

         string[j++] = DELIM;

         for(i=0;minutes[i] != NULL;i++)
                 string[j++] = minutes[i];

         string[j++] = DELIM;

         for(i=0;seconds[i] != NULL;i++)
                 string[j++] = seconds[i];

         string[j] = NULL;

         /* done */
         return(0);
 }


 GETTIME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\GETTIME.C

 /*                            *** gettime.c ***                      */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Function to return a string containing the time in the format     */
 /* HH:MM:SS (military time).                                         */
 /*                                                                   */
 /* Written by L. Cuthbertson, May 1984                               */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define NULL        '\000'
 #define DELIM   ':'

 int gettime(string)
 char string[];
 {
         char hours[3],minutes[3],seconds[3];
         int ih,im,is,iths;
         int i,j;

         /* call assembler routine to get time in integer format */
         dostime(&ih,&im,&is,&iths);

         /* convert integers to strings - ignore 1/100ths of second */
         sprintf(hours,"%02d",ih);
         sprintf(minutes,"%02d",im);
         sprintf(seconds,"%02d",is);

         /* build output string */
         j = 0;
         for(i=0;hours[i] != NULL;i++)
                 string[j++] = hours[i];

         string[j++] = DELIM;

         for(i=0;minutes[i] != NULL;i++)
                 string[j++] = minutes[i];

         string[j++] = DELIM;

         for(i=0;seconds[i] != NULL;i++)
                 string[j++] = seconds[i];

         string[j] = NULL;

         /* done */
         return(0);
 }


 GETTOK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\GETTOK.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 extern char *llend, llbuf[];

 gettoken(lltb, lltbsiz)
 char *lltb;
 {
         register char *lp, *tp, *ep;

         tp = lltb;
         ep = tp+lltbsiz-1;
         for (lp = llbuf; lp < llend && tp < ep;)
                 *tp++ = *lp++;
         *tp = 0;
         return(tp-lltb);
 }


 GETTRUTH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\GETTRUTH.C



 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /*************************************************
 **
 **        getTruth(antecedent)
 **
 **        asks user for the truth of a string or
 **        returns --
 **                TRUE if user says the statement is TRUE
 **                FALSE if the user says the statement is FALSE
 **
 *************************************************/

 #include <stdio.h>

 #ifdef MSDOS
 #include <conio.h>
 #endif

 #include "expert.h"
 #include "inference.h"

 int getTruth(cnsquent)
         int        cnsquent ;
 {
 int done,c ;
 done = FALSE ;

 while(!done)
         {
         printf("\n Is the following statement True?  (T/F,Y/N)\n\n ") ;
         printf("%s    ?",&strBuff[ruleBuff[cnsquent].string]) ;
 #ifdef MSDOS
         c = getche() ;
 #endif
 #ifdef UNIXSV
         c = getchar() ;
         getchar() ;
 #endif
         switch(c)
                 {
                 case 'y' :
                 case 'Y' :
                 case 't' :
                 case 'T' :
                         printf("\n\n") ;
                         return(TRUE) ;
                 case 'n' :
                 case 'N' :
                 case 'f' :
                 case 'F' :
                         printf("\n\n") ;
                         return(FALSE) ;
                 case 'w' :
                 case 'W' :
                         printf("\n Why is not implemented \n") ;
                 default :
                         printf("\n Please try again \"T\" or \"F\" \n ") ;
                 }
         }
 }






 GETW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\GETW.C

 #include <stdio.h>

 int getw(fp)
 FILE *fp;
 /*
  *        Get a 2-byte value from the stream <fp>.  The high-order byte is
  *        read first.
  */
 {
         register int n, c;

         if((c = fgetc(fp)) == EOF)
                 return(EOF);
         n = (c << 8);
         if((c = fgetc(fp)) == EOF)
                 return(EOF);
         n |= (c & 0xFF);
 }

 int putw(n, fp)
 register int n;
 FILE *fp;
 /*
  *        Put the 2-byte value <n> to the stream <fp>.  The high-order byte
  *        is written first.
  */
 {
         register int m;

         m = (n >> 8);
         fputc((m & 0xFF), fp);
         fputc((n & 0xFF), fp);
 }


 GLOB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\GLOB\GLOB.C


 /*
  *        Copyright 1985, 1986  by John Plocher  Non-commercial use approved
  *
  *        glob        expand a given pathname with wildcards into
  *                an argv[] type array of 'strings' which are
  *                the files (directories) which result from the
  *                expansion of the pathname.  (All characters in
  *                the returned list of filenames are in lower case)
  *
  *        usage:        char **glob(pathname) char *pathname;
  *
  *                pathname is an absolute or relative pathname which may
  *                contain DOS type wildcards wherever desired:
  *
  *                        names = glob("\\usr\\pl*\\*.c");
  *
  *        It requires an externally declared int in the main function
  *        named globerror:
  *
  *                extern int globerror;
  *
  *        to be used to return an error indication if glob() fails.
  *        If glob() fails, it returns NULL with
  *
  *        globerror set to GE_BADPATH        invalid path - directory not fou
  *        globerror set to GE_AMBIGUOUS        ambiguous directory spec
  *        globerror set to GE_MAXFILES        too many files found (MAXFILES)
  *        globerror set to GE_NOMEM        out of memory
  *
  *        else it returns a pointer to a NULL terminated array of pointers
  *        to 'strings':
  *
  *        +-[ MAIN.C ]----------------------------------------------------+
  *        |                                                                |
  *        | #include "glob.h"
  *        | main() {                                                        |
  *        |         char **glob();
  *        |         char **names;
  *        |         names = glob("/u??/p*");                                |
  *        |         if (names)
  *        |             printf("the first name returned is %s\n",names[0]);
  *        |         else
  *        |             printf("glob() error number %d\n",globerror);
  *        |        recover(names);
  *        | }
  *        |                                                                |
  *        +---------------------------------------------------------------+
  *
  *        ALL strings and the array *names[] are made with calls to
  *        malloc().  Thus, be sure to free() *names[x] AND names when done!
  *
  *        +-[sample routines]---------------------------------------------+
  *        |                                                                |
  *        |        (* free() all the space used up by **names; *)
  *        | recover(names)                                                |
  *        | char **names;
  *        | {
  *        |     int i = 0;                                                |
  *        |                                                                |
  *        |     while (names[i] != (char *)0) {
  *        |         free(names[i]);
  *        |         i++;
  *        |     }
  *        |     free(names);                                                |
  *        | }
  *        |                                                                 |
  *        |                                                                 |
  *        |        (* print out all the filenames returned by glob() *)
  *        | print(names)
  *        | char **names;
  *        | {
  *        |     int i;
  *        |     i = 0;
  *        |     while (names[i] != (char *)0) {
  *        |         printf("%s\n",names[i]);                                |
  *        |         i++;
  *        |     }
  *        | }
  *        +---------------------------------------------------------------+
  *
  *        Compile as follows:        (Structures MUST be packed in order for
  *                                 the program to interface correctly with DO
  *                cl -c -Zp glob.c        ** Microsoft C v3 or 4 **
  *
  *        Using the example given above, compile and link main program:
  *                cl main.c glob
  *
  *        Written December, 1985 by John Plocher with MicroSoft C 3.0
  *        Change log:
  *
  *        version        date                who        comments
  *        ------- ----                ---        --------
  *        1.0        10-Dec-85        jmp        Orig. coding
  *        1.1        16-Jan-86        jmp        added globerror
  *        1.2        05-Feb-86        jmp        added comments and doccument
  *
  */

 static char *scssid = "5-Feb-86 (Plocher) @(#)glob.c        1.2";
 static char *copyright =
         "Copyright 1985, 1986 John Plocher.  Non-commercial use approved";

 #include        <stdio.h>
 #include        <dos.h>
 #include        <memory.h>
 #include        <direct.h>
 #include        <string.h>
 #include        "glob.h"


 /* Change the following if you might have more than this many    */
 /* files returned by glob()                                      */

 MAXFILES        256        /* max files returned by glob() */


 static char *list[MAXFILES];        /* MAXFILES entries per sub-dir */


 extern char *strlwr();
 extern int getdir();
 extern char *pos();

 int globerror;                        /* PUBLIC - global error number */

 /*
  *        glob()
  */
 char **
 glob(proposed)
 char *proposed;
 {
     int i,j,k,needdir,n;
     char *end, filename[128], newpath[127], tmppath[127];
     char *f, *p1, *p2;
     char **names;

     strcpy(filename, proposed);

     /* add on current directory if first char is not '/' or '\' */
     if (*filename != '/' && *filename != '\\') {
         getcwd(tmppath,128);
         p2 = strchr(tmppath,'\0');
         p2--;
         if (*p2 != '/' && *p2 != '\\')
             strcat(tmppath,"/");
         strcat(tmppath,filename);
         strcpy(filename, tmppath);
     }
     for (i=strlen(filename); i; i--)
         if (filename[i] == '\\')
             filename[i] = '/';
     i = 0; j = 0;
     p2 = strchr(filename,'\0');
     p2--;
     if (*p2 == '.')
         strcat(filename,"/");
     while ((p1 = pos("/./",filename)) != NULL) {
         memccpy(p1+1, p1+3, '\0',strlen(p1));
     }
     while ((p1 = pos("../",filename)) != NULL) {
         char tmp;
         tmp = *(p1 - 1);
         *(p1 - 1) = '\0';
         p2 = strrchr(filename,'/');
         if (p2 == NULL) {
             globerror = GE_BADFILE;
             return(NULL);
         }
         *(p1 - 1) = tmp;
         memccpy(p2+1, p1+3, '\0',strlen(p1));
     }
     p2 = strchr(filename,'\0');
     p2--;
     if (*p2 == '/')
         *p2 = '\0';
 loop:
     while (filename[i]  != 0 &&                /* copy till hit a wildcard */
            filename[i]  != '*' &&
            filename[i]  != '?') {
         tmppath[j++] = filename[i++];
     }
     if (filename[i] != 0)        /* wildcard found */
         while (filename[i]  != 0 &&
                filename[i]  != '/')
             tmppath[j++] = filename[i++];
     if (filename[i] != 0)        /* need directory here */
         needdir = 1;
     else                        /* any file will do */
         needdir = 0;
     tmppath[j] = 0;
     strcpy(newpath,tmppath);
     end = strrchr(newpath,'/');
     if  (end != NULL)
       *end = '\0';

     n = getdir(tmppath,needdir);

     if (n == -2) {        /* out of dynamic memory */
         globerror = GE_NOMEM;
         return(NULL);
     }
     if (n == -1) {        /* exceeded filecount */
         globerror = GE_MAXFILES;
         return(NULL);
     }
     if (n == 0) { /* file not found */
         globerror = GE_BADFILE;
         return(NULL);
     }
     if (needdir && n != 1) { /* ambiguous directory reference */
         for (i = 0; i < n; i++)                /* This is an arbitrary limit
             free(list[i]);                /* one could follow all paths */
         globerror = GE_AMBIGUOUS;        /* and not just the first...  */
         return(NULL);
     }
     if (needdir) {
         strcpy(tmppath,newpath);
         strcat(tmppath,"/");
         strcat(tmppath,list[0]);
         free(list[0]);
         j = strlen(tmppath);
         goto loop;
     }

     names = (char **)malloc((n+1) * sizeof(char *));
     for (i = 0; i < n; i++) {
         sprintf(tmppath,"%s/%s", newpath, list[i]);
         names[i] = strdup(tmppath);
         free(list[i]);
     }
     names[n] = (char *)0;

     return(names);
 }


 /*
  *        pos(target, src)
  *                        find target string within src
  */
 static char *pos(s1,s2)
 char *s1, *s2;
 {
     int temploc, dist;
     char *tp;

     if (*s1) {
         for (;;) {
             tp = strchr(s2, *s1);
             if (tp == NULL) {                /* couldn't even find first char
                 return(NULL);
             }
             if (!strncmp(s1,tp,strlen(s1)))        /* match */ {
                 return(tp);
             }
             s2 = tp + 1;
         }
     }
 }


 /*
  *        File attributes
  */

 AT_RO                0x01        /* Read Only */
 AT_HIDDEN        0x02        /* hidden file */
        AT_SYSTEM        0x04        /* System file */
 AT_LABEL        0x08        /* volume label */
 AT_DIR                0x10        /* sub directory */
 AT_ARCH                0x20        /* archive bit */

 static struct REGS rregs;
 static struct SREGS sregs;


 static struct DMA {                        /* For reading directory entry
     char res[21];
     char attr;
     unsigned sec : 5, min : 6, hour : 5;
     unsigned day : 5, mon : 4, year : 7;
     long size;
     char name[13];
 } dma;

 /*
  *        getdir                gather all the files found in this directory
  */
 static int
 getdir(path, needdir)        /* return number of 'files' found in this path *
 char  *path;                /* this is where to look */
 int needdir;                /* 1 = we want ONLY AT_DIR type entries */
                         /* 0 = we will take EVERYTHING */
 {
     int i, j, n;
     char *entry;

     bdos(0x1a, &dma,0);

     n = 0;
     rregs.h.ah = 0x4e;
     rregs.x.cx = AT_RO | AT_HIDDEN | AT_SYSTEM | AT_DIR;
     rregs.x.dx = (unsigned int) path;
     j = intdos(&rregs, &rregs);                /* Search for first        */
     while(j == 0) {
         strlwr(dma.name);
         if (needdir && (dma.attr & AT_DIR != AT_DIR)){ /* skip this entry */
             rregs.h.ah = 0x4f;                /* wes needs dirs, and this ain
             j = intdos(&rregs, &rregs);/* Search for next        */
             continue;
         }
         entry = strdup(dma.name);
         if (entry == NULL) {                /* out of memory */
             for (i = 0; i < n; i++)
                 free(list[i]);
             return (-2);
         }
         if (n >= MAXFILES)                /* too many files found */
             return(-1);
         for (i = n++; i > 0; --i) {        /* alphabetize */
             if (strcmp(entry, list[i - 1]) >= 0)
                 break;
             list[i] = list[i - 1];
         }
         list[i] = entry;
         rregs.h.ah = 0x4f;
         j = intdos(&rregs, &rregs);                /* Search for next
     }
     return(n);
 }



 GOODFORM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\GOODFORM.C

 main()  /* Main program starts here */
 {
    printf("Good form ");
    printf          ("can aid in ");
    printf                     ("understanding a program.\n");
    printf("And bad form ");
    printf             ("can make a program ");
    printf                                ("unreadable.\n");
 }


 GOODIE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\GOODIE.C

 #include <stdio.h>
 #include <time.h>

 /*
  *        goodie.c -- Goofy little program to print random selections from
  *                a list contained in a 'goodiefile'.
  *
  *                Version 1.01, Copyright (C) 1987 by David Sandberg
  *
  *                To use this program, you will want to create a file
  *                called 'goodies.fil' in the \etc directory (you may change
  *                the filename by changing the first 'if', but I highly recom
  *                using an absolute pathname at least, so the program can fin
  *                it no matter where it is executed from), which may contain
  *                number of goofy quips and quotes you like. If the quip or
  *                quote is more than one line long, each line after the first
  *                must begin with a space character (ASCII 32) - this is how
  *                program determines that it is a continuation line.
  *                EXAMPLE:

 "Now is the time for all good men to
  come to the aid of their country."

  *                will be interpreted correctly as one contiguous entry, whil

 "Now is the time for all good men to
 come to the aid of their country."

  *                will be treated incorrectly as two separate entries.
  *
  *                Note that you should have a carriage return after the last
  *                entry in your 'goodiefile', so that the program can properl
  *                read the last entry. On an editor such as 'vi', this means
  *                a blank line will appear at the end of the list of 'goodies
  *
  *                If you run the program dozens of times in a few minutes, yo
  *                may start to see patterns arise. Since the randomize functi
  *                is driven by the time of day, this seems unavoidable. The
  *                algorithm is quite suitable for less rigorous applications,
  *                however - I use it in my AUTOEXEC.BAT file to give myself a
  *                random greeting upon powerup, with good results.
  *
  *                This program was compiled using Microsoft C version 4.00. T
  *                compile it with a different C compiler will likely require
  *                mods to the random and time functions. If anyone does so, o
  *                if someone comes up with a better random device, I'd like t
  *                see the results (simply out of curiosity) - write me on
  *                the C Station, (612) 938-4809.
  *
  *                D. Sandberg -- 10/10/87
  */

 main()

 {
     FILE *goodiefile;
     int filelen, line_no;

     randomize();
     if ((goodiefile = fopen("/etc/goodies.fil", "r")) == NULL) {
         printf("goodiefile missing.\n");
         exit(0);
     }
     filelen = find_size(goodiefile);
     line_no = (rand() % filelen) + 1;
     pick_line(goodiefile, line_no);
 }

 randomize()

 {
     long *timeval, time();

     time(timeval);
     srand((int)*timeval);
 }

 find_size(goodiefile)
 FILE *goodiefile;

 {
     char buf[83];
     int filelen = 0;

     while (!feof(goodiefile)) {
         fgets(buf, 82, goodiefile);
         if (buf[0] != ' ')
             ++filelen;
     }
     rewind(goodiefile);
     return(filelen-2);
 }

 pick_line(goodiefile, line_no)
 FILE *goodiefile;
 int line_no;

 {
     int i=0;
     char buf[83];

     while (i<line_no) {
         fgets(buf, 82, goodiefile);
         if (buf[0] != ' ')
             ++i;
     }
     printf("\n%s", buf);
     fgets(buf, 82, goodiefile);
     while (buf[0] == ' ') {
         printf("%s", buf);
         fgets(buf, 82, goodiefile);
     }
 }


 GOTHIC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\GOTHIC\GOTHIC.C


 /*
  *                G o t h i c   P r i n t e r
  *
  *
  * Compile with gottab.c
  *
  * Prints the arguments, if none, it prompts for an output file and
  * reads stdin.
  *
  *        If the first argument is -h, the display is halved.
  *
  *        / in the text reverses the background
  *
  * The following characters are displayed:
  *
  *        #.(@!$);-,?:'"  A-Z  a-z  0-9
  *
  * All others become blanks.
  *
  */
 #include <stdio.h>

 char                outbuf[133];
 char                line[133];
 int                background        = 0;                /* Background color
 int                half                = 0;                /* Set to halve di

 main (argc, argv)
 int                argc;
 char                *argv[];

 {
         register int                i;

         if (argc > 1 && argv[1][0] == '-' && (argv[1][1] | 040) == 'h') {
                 argc--;
                 argv++;
                 half++;
         }
         if (argc <= 1) {
                 printf("Gothic output file <terminal>: ");
                 fflush(stdout);
                 if (gets(outbuf) == NULL)
                         panic("No output file", NULL);
                 if (half == 0) {
                         printf("Half size (Yes/No) <N>: ");
                         fflush(stdout);
                         if (gets(line) == NULL)
                                 panic("Unexpected EOF", NULL);
                         if ((line[0] | 040) == 'y')
                                 half++;
                 }
                 if (outbuf[0] != 0) {
                         if (freopen(outbuf, "w", stdout) == NULL)
                                 panic("Can't open", outbuf);
                 }
                 while (gets(line) != NULL) {
                         dotext(line);
                 }
         }
         else {
                 for (i = 1; i < argc; i++) {
                         dotext(argv[i]);
                 }
                 puts("\f");
         }
 }

 dotext(text)
 char                *text;
 /*
  * Convert text to gothic letters, write them to stdout
  */
 {
         register char        *tp;
         register int        c;

         for (tp = text; (c = *tp++) != 0;) {
                 if (c == '/')
                         background = (background) ? 0 : 2;
                 else        gothic(c);
         }
 }

 gothic(character)
 int                character;
 /*
  * Process the character
  */
 {
         char                        *gp;
         register char                *op;
         register int                i;
         register int                byte;
         int                        index;
         extern char                *gottab[];
         int                        lhalf;                /* Line half flag
         int                        chalf;                /* Column half flag

         index = (background) ? -1 : 0;
         lhalf = chalf = 0;
         gp = gottab[character & 127];
         op = outbuf;
         for (;;) {
                 if ((i = (*gp++ & 0377)) >= 254) {
                         if (background) {
                                 while (op < &outbuf[132])
                                         *op++ = 'X';
                         }
                         *op = 0;
                         lhalf = ~lhalf;
                         chalf = 0;
                         if (half) {
                                 if (lhalf) {
                                         outbuf[132 / 2] = 0;
                                         puts(outbuf);
                                 }
                         }
                         else {
                                 puts(outbuf);
                         }
                         op = outbuf;
                         if (i == 255)
                                 break;
                 }
                 else {
                         byte = "O X "[background - (index = (-1 - index))];
                         while (--i >= 0) {
                                 if (half) {
                                         chalf = ~chalf;
                                         if (chalf) {
                                                 *op++ = byte;
                                         }
                                 }
                                 else {
                                         *op++ = byte;
                                 }
                         }
                         if (op >= &outbuf[132])
                                 panic("big line", NULL);
                 }
         }
 }

 panic(s, arg)
 char                *s;
 char                *arg;
 /*
  * Fatal error exit
  */
 {
         fprintf(stderr, "?Gothic-E-fatal error %s", s);
         if (arg != NULL)
                 fprintf(stderr, ": \"%s\"", arg);
         fprintf(stderr, "\n");
         exit(1);
 }


 GOTOEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\GOTOEX.C

                                          /* Chapter 3 - Program 7 */
 main()
 {
 int dog,cat,pig;

    goto real_start;

    some_where:
    printf("This is another line of the mess.\n");
    goto stop_it;

 /* the following section is the only section with a useable goto */
    real_start:
    for(dog = 1;dog < 6;dog = dog + 1) {
       for(cat = 1;cat < 6;cat = cat + 1) {
          for(pig = 1;pig < 4;pig = pig + 1) {
             printf("Dog = %d  Cat = %d  Pig = %d\n",dog,cat,pig);
             if ((dog + cat + pig) > 8 ) goto enough;
          };
       };
    };
    enough: printf("Those are enough animals for now.\n");
 /* this is the end of the section with a useable goto statement */

    printf("\nThis is the first line out of the spaghetti code.\n");
    goto there;

    where:
    printf("This is the third line of spaghetti.\n");
    goto some_where;

    there:
    printf("This is the second line of the spaghetti code.\n");
    goto where;

    stop_it:
    printf("This is the last line of this mess.\n");

 }


 GOTOXY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CXREF\GOTOXY.C

 #include <stdio.h>

 void GotoXY(x, y)
 int x, y;
 {
    struct
    {
       int AX, BX, CX, DX, SI, DI;
    } Regs;

    Regs.DX = (y << 8) | (x & 0xFF);
    Regs.BX = 0;
    Regs.AX = 0x200;
    int86(0x10, &Regs, $Regs);
 }


 GOTTAB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\GOTHIC\GOTTAB.C


 /*
  * "#"
  */
 static char c__001[] = {
  254,
  254,
  47, 21, 254,
  46, 23, 254,
  45, 25, 254,
  44, 27, 254,
  43, 29, 254,
  42, 8, 21, 2, 254,
  41, 8, 23, 2, 254,
  40, 8, 25, 2, 254,
  39, 8, 27, 2, 254,
  38, 8, 29, 2, 254,
  37, 8, 29, 4, 254,
  25, 19, 29, 16, 254,
  25, 18, 29, 17, 254,
  36, 8, 27, 8, 254,
  37, 8, 25, 8, 254,
  38, 8, 23, 8, 254,
  39, 8, 21, 8, 254,
  40, 8, 20, 7, 254,
  41, 5, 24, 4, 254,
  254,
  255 };

 /*
  * "."
  */
 static char c__002[] = {
  254,
  254,
  30, 1, 254,
  30, 3, 254,
  29, 6, 254,
  27, 10, 254,
  25, 13, 254,
  25, 13, 254,
  26, 10, 254,
  28, 6, 254,
  30, 3, 254,
  254,
  255 };

 /*
  * "("
  */
 static char c__003[] = {
  254,
  254,
  40, 1, 48, 1, 254,
  39, 52, 254,
  38, 54, 254,
  37, 56, 254,
  36, 58, 254,
  35, 60, 254,
  34, 2, 58, 2, 254,
  33, 2, 60, 2, 254,
  32, 2, 62, 2, 254,
  31, 2, 64, 2, 254,
  30, 2, 66, 2, 254,
  29, 2, 68, 2, 254,
  28, 2, 70, 2, 254,
  27, 2, 72, 2, 254,
  26, 2, 74, 2, 254,
  254,
  255 };

 /*
  * "@"
  */
 static char c__004[] = {
  254,
  254,
  73, 1, 16, 1, 254,
  38, 21, 14, 19, 254,
  37, 23, 13, 20, 254,
  36, 25, 11, 22, 254,
  35, 27, 9, 24, 254,
  34, 29, 8, 25, 254,
  33, 31, 6, 27, 254,
  32, 10, 21, 2, 4, 9, 18, 2, 254,
  31, 10, 23, 2, 2, 9, 17, 5, 254,
  30, 10, 25, 11, 16, 8, 254,
  29, 10, 25, 11, 16, 10, 254,
  28, 10, 24, 12, 15, 13, 254,
  27, 10, 22, 14, 15, 15, 254,
  26, 10, 19, 17, 15, 17, 254,
  25, 10, 16, 19, 17, 18, 254,
  26, 8, 12, 22, 18, 14, 254,
  27, 6, 9, 23, 21, 12, 254,
  28, 4, 6, 25, 23, 10, 254,
  29, 2, 3, 23, 28, 9, 254,
  30, 23, 32, 8, 254,
  29, 20, 36, 7, 254,
  27, 17, 41, 7, 254,
  25, 15, 46, 5, 254,
  25, 11, 50, 3, 254,
  25, 9, 1, 19, 33, 2, 254,
  25, 8, 3, 19, 33, 1, 254,
  25, 7, 5, 19, 254,
  25, 7, 6, 19, 254,
  27, 5, 7, 19, 254,
  254,
  255 };

 /*
  * "!"
  */
 static char c__005[] = {
  254,
  254,
  30, 1, 63, 4, 254,
  30, 3, 62, 6, 254,
  29, 6, 60, 8, 254,
  27, 10, 40, 27, 254,
  25, 13, 4, 63, 254,
  25, 13, 4, 63, 254,
  26, 10, 14, 54, 254,
  28, 6, 31, 39, 254,
  30, 3, 49, 21, 254,
  254,
  255 };

 /*
  * "$"
  */
 static char c__006[] = {
  254,
  254,
  35, 3, 20, 9, 254,
  37, 4, 15, 14, 254,
  38, 5, 11, 19, 254,
  39, 5, 10, 9, 10, 2, 254,
  39, 6, 9, 8, 10, 5, 254,
  39, 7, 7, 8, 10, 7, 254,
  39, 7, 7, 8, 9, 10, 254,
  25, 64, 254,
  25, 64, 254,
  39, 8, 6, 8, 7, 9, 254,
  38, 9, 6, 8, 7, 8, 254,
  25, 64, 254,
  25, 64, 254,
  35, 10, 8, 8, 8, 7, 254,
  37, 7, 9, 8, 8, 7, 254,
  38, 5, 9, 8, 10, 6, 254,
  40, 2, 9, 9, 11, 5, 254,
  42, 18, 12, 5, 254,
  45, 14, 15, 4, 254,
  254,
  255 };

 /*
  * ")"
  */
 static char c__007[] = {
  254,
  254,
  25, 2, 76, 2, 254,
  26, 2, 74, 2, 254,
  27, 2, 72, 2, 254,
  28, 2, 70, 2, 254,
  29, 2, 68, 2, 254,
  30, 2, 66, 2, 254,
  31, 2, 64, 2, 254,
  32, 2, 62, 2, 254,
  33, 2, 60, 2, 254,
  34, 2, 58, 2, 254,
  35, 60, 254,
  36, 58, 254,
  37, 56, 254,
  38, 54, 254,
  39, 52, 254,
  254,
  255 };

 /*
  * ";"
  */
 static char c__008[] = {
  254,
  254,
  50, 1, 254,
  50, 2, 22, 1, 254,
  51, 2, 21, 3, 254,
  38, 1, 12, 3, 19, 6, 254,
  38, 2, 10, 5, 16, 10, 254,
  39, 3, 7, 7, 13, 13, 254,
  40, 17, 12, 13, 254,
  41, 15, 14, 10, 254,
  42, 13, 17, 6, 254,
  44, 10, 20, 3, 254,
  254,
  255 };

 /*
  * "-"
  */
 static char c__009[] = {
  254,
  254,
  49, 5, 254,
  51, 6, 254,
  52, 7, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  52, 8, 254,
  53, 7, 254,
  55, 6, 254,
  254,
  255 };

 /*
  * ","
  */
 static char c__010[] = {
  254,
  254,
  50, 1, 254,
  50, 2, 254,
  51, 2, 254,
  38, 1, 12, 3, 254,
  38, 2, 10, 5, 254,
  39, 3, 7, 7, 254,
  40, 17, 254,
  41, 15, 254,
  42, 13, 254,
  44, 10, 254,
  254,
  255 };

 /*
  * "?"
  */
 static char c__011[] = {
  254,
  254,
  92, 1, 254,
  76, 18, 254,
  75, 20, 254,
  74, 22, 254,
  73, 24, 254,
  72, 26, 254,
  73, 26, 254,
  30, 1, 22, 7, 14, 7, 17, 2, 254,
  30, 3, 16, 15, 11, 5, 19, 2, 254,
  29, 6, 11, 21, 9, 3, 19, 4, 254,
  27, 10, 7, 24, 9, 1, 19, 6, 254,
  25, 13, 4, 28, 26, 8, 254,
  25, 13, 3, 3, 12, 15, 24, 10, 254,
  26, 10, 4, 2, 16, 14, 22, 10, 254,
  28, 6, 26, 12, 21, 10, 254,
  30, 3, 29, 11, 19, 10, 254,
  32, 1, 30, 11, 17, 10, 254,
  64, 10, 16, 10, 254,
  65, 34, 254,
  66, 32, 254,
  66, 31, 254,
  67, 29, 254,
  67, 28, 254,
  254,
  255 };

 /*
  * ":"
  */
 static char c__012[] = {
  254,
  254,
  30, 1, 31, 1, 254,
  30, 3, 29, 3, 254,
  29, 6, 26, 6, 254,
  27, 10, 22, 10, 254,
  25, 13, 19, 13, 254,
  25, 13, 19, 13, 254,
  26, 10, 22, 10, 254,
  28, 6, 26, 6, 254,
  30, 3, 29, 3, 254,
  254,
  255 };

 /*
  * "'"
  */
 static char c__013[] = {
  254,
  254,
  99, 1, 254,
  99, 2, 254,
  86, 1, 12, 3, 254,
  86, 2, 10, 5, 254,
  87, 3, 7, 7, 254,
  88, 17, 254,
  89, 15, 254,
  90, 13, 254,
  92, 10, 254,
  254,
  255 };

 /*
  * """
  */
 static char c__014[] = {
  254,
  254,
  94, 6, 254,
  92, 10, 254,
  90, 13, 254,
  89, 15, 254,
  88, 17, 254,
  87, 3, 7, 7, 254,
  86, 2, 10, 5, 254,
  86, 1, 12, 3, 254,
  99, 2, 254,
  99, 1, 254,
  254,
  94, 6, 254,
  92, 10, 254,
  90, 13, 254,
  89, 15, 254,
  88, 17, 254,
  87, 3, 7, 7, 254,
  86, 2, 10, 5, 254,
  86, 1, 12, 3, 254,
  99, 2, 254,
  254,
  255 };

 /*
  * "a"
  */
 static char c__015[] = {
  254,
  254,
  32, 16, 12, 2, 254,
  31, 17, 13, 2, 254,
  30, 19, 13, 2, 254,
  29, 20, 14, 2, 254,
  28, 22, 14, 2, 254,
  27, 8, 14, 1, 15, 2, 254,
  26, 8, 15, 2, 13, 4, 254,
  25, 8, 17, 1, 12, 6, 254,
  26, 6, 18, 2, 10, 8, 254,
  27, 4, 20, 1, 9, 8, 254,
  28, 3, 20, 2, 7, 8, 254,
  29, 3, 20, 1, 6, 8, 254,
  30, 36, 254,
  29, 36, 254,
  28, 36, 254,
  27, 36, 254,
  26, 36, 254,
  25, 8, 254,
  27, 5, 254,
  254,
  255 };

 /*
  * "b"
  */
 static char c__016[] = {
  254,
  254,
  90, 1, 254,
  89, 3, 254,
  32, 61, 254,
  31, 63, 254,
  30, 65, 254,
  29, 66, 254,
  28, 66, 254,
  27, 8, 28, 2, 24, 3, 254,
  26, 8, 30, 2, 24, 1, 254,
  25, 8, 32, 2, 254,
  26, 6, 32, 4, 254,
  27, 4, 32, 6, 254,
  28, 2, 32, 8, 254,
  29, 2, 30, 8, 254,
  30, 2, 28, 8, 254,
  31, 36, 254,
  32, 34, 254,
  33, 32, 254,
  34, 30, 254,
  254,
  255 };

 /*
  * "c"
  */
 static char c__017[] = {
  254,
  254,
  37, 21, 254,
  36, 23, 254,
  35, 25, 254,
  34, 27, 254,
  33, 29, 254,
  32, 8, 21, 2, 254,
  31, 8, 23, 2, 254,
  30, 8, 25, 2, 254,
  29, 8, 27, 2, 254,
  28, 8, 29, 2, 254,
  27, 8, 29, 4, 254,
  26, 8, 29, 6, 254,
  25, 8, 29, 8, 254,
  26, 8, 27, 8, 254,
  27, 8, 25, 8, 254,
  28, 8, 23, 8, 254,
  29, 8, 21, 8, 254,
  30, 8, 20, 7, 254,
  31, 5, 24, 4, 254,
  254,
  255 };

 /*
  * "d"
  */
 static char c__018[] = {
  254,
  254,
  32, 28, 254,
  31, 30, 28, 1, 254,
  30, 32, 25, 5, 254,
  29, 34, 22, 9, 254,
  28, 36, 19, 12, 254,
  27, 8, 28, 2, 16, 13, 254,
  26, 8, 30, 2, 13, 13, 254,
  25, 8, 32, 2, 10, 13, 254,
  26, 6, 34, 2, 7, 13, 254,
  27, 4, 36, 2, 4, 13, 254,
  28, 2, 38, 2, 1, 13, 254,
  29, 2, 38, 13, 254,
  30, 2, 35, 13, 254,
  29, 49, 254,
  28, 48, 254,
  27, 47, 254,
  26, 46, 254,
  25, 45, 254,
  27, 4, 254,
  254,
  255 };

 /*
  * "e"
  */
 static char c__019[] = {
  254,
  254,
  37, 21, 254,
  36, 23, 254,
  35, 25, 254,
  34, 27, 254,
  33, 29, 254,
  32, 8, 7, 2, 12, 2, 254,
  31, 8, 9, 2, 12, 2, 254,
  30, 8, 11, 2, 12, 2, 254,
  29, 8, 13, 2, 12, 2, 254,
  28, 8, 15, 2, 12, 2, 254,
  27, 8, 17, 2, 10, 4, 254,
  26, 8, 19, 2, 8, 6, 254,
  25, 8, 21, 2, 6, 8, 254,
  26, 8, 21, 2, 4, 8, 254,
  27, 8, 21, 2, 2, 8, 254,
  28, 8, 21, 10, 254,
  29, 8, 21, 8, 254,
  30, 8, 21, 6, 254,
  31, 5, 24, 4, 254,
  254,
  255 };

 /*
  * "f"
  */
 static char c__020[] = {
  254,
  254,
  60, 1, 254,
  60, 3, 254,
  60, 5, 254,
  60, 7, 254,
  28, 1, 31, 8, 254,
  27, 59, 254,
  26, 61, 254,
  25, 63, 254,
  26, 63, 254,
  27, 63, 254,
  28, 1, 31, 8, 21, 2, 254,
  60, 8, 22, 2, 254,
  61, 7, 21, 4, 254,
  63, 5, 20, 6, 254,
  65, 3, 19, 8, 254,
  67, 1, 13, 13, 254,
  81, 12, 254,
  81, 11, 254,
  81, 10, 254,
  254,
  255 };

 /*
  * "g"
  */
 static char c__021[] = {
  254,
  254,
  9, 6, 17, 28, 254,
  8, 7, 16, 30, 254,
  7, 8, 15, 32, 254,
  6, 9, 14, 34, 254,
  5, 10, 13, 36, 254,
  4, 7, 16, 8, 28, 2, 254,
  3, 7, 16, 8, 30, 2, 254,
  2, 7, 16, 8, 32, 2, 254,
  1, 7, 18, 6, 32, 4, 254,
  0, 7, 20, 4, 32, 6, 254,
  1, 5, 22, 2, 32, 8, 254,
  2, 3, 24, 2, 30, 8, 254,
  3, 2, 25, 2, 28, 8, 254,
  4, 63, 254,
  5, 61, 254,
  6, 59, 254,
  7, 57, 254,
  254,
  255 };

 /*
  * "h"
  */
 static char c__022[] = {
  254,
  254,
  90, 1, 254,
  28, 1, 60, 3, 254,
  27, 66, 254,
  26, 68, 254,
  25, 70, 254,
  26, 68, 254,
  27, 66, 254,
  28, 1, 33, 2, 25, 3, 254,
  64, 2, 24, 1, 254,
  65, 2, 254,
  64, 4, 254,
  63, 6, 254,
  62, 8, 254,
  28, 1, 32, 8, 254,
  27, 41, 254,
  26, 41, 254,
  25, 41, 254,
  26, 39, 254,
  27, 37, 254,
  254,
  255 };

 /*
  * "i"
  */
 static char c__023[] = {
  254,
  254,
  66, 1, 9, 1, 254,
  29, 39, 7, 3, 254,
  28, 41, 5, 5, 254,
  27, 43, 3, 7, 254,
  26, 43, 5, 5, 254,
  25, 43, 7, 3, 254,
  26, 7, 33, 1, 9, 1, 254,
  27, 5, 254,
  28, 3, 254,
  29, 2, 254,
  254,
  255 };

 /*
  * "j"
  */
 static char c__024[] = {
  254,
  254,
  8, 7, 254,
  7, 8, 254,
  6, 9, 254,
  5, 10, 254,
  4, 11, 254,
  3, 7, 254,
  2, 7, 254,
  1, 7, 254,
  0, 7, 254,
  1, 5, 254,
  2, 3, 254,
  3, 2, 254,
  4, 2, 60, 1, 9, 1, 254,
  5, 63, 7, 3, 254,
  6, 63, 5, 5, 254,
  7, 63, 3, 7, 254,
  8, 61, 5, 5, 254,
  9, 59, 7, 3, 254,
  254,
  255 };

 /*
  * "k"
  */
 static char c__025[] = {
  254,
  254,
  90, 1, 254,
  28, 1, 60, 3, 254,
  27, 66, 254,
  26, 68, 254,
  25, 70, 254,
  26, 68, 254,
  27, 66, 254,
  28, 1, 18, 2, 14, 2, 24, 3, 254,
  48, 1, 15, 2, 24, 1, 254,
  47, 3, 15, 2, 254,
  46, 4, 14, 4, 254,
  45, 6, 12, 6, 254,
  44, 7, 11, 8, 254,
  28, 1, 14, 9, 9, 8, 254,
  27, 23, 1, 1, 8, 8, 254,
  26, 23, 2, 16, 254,
  25, 23, 4, 14, 254,
  26, 21, 5, 13, 254,
  27, 19, 7, 11, 254,
  254,
  255 };

 /*
  * "l"
  */
 static char c__026[] = {
  254,
  254,
  28, 1, 62, 1, 254,
  27, 66, 254,
  26, 68, 254,
  25, 70, 254,
  26, 68, 254,
  27, 66, 254,
  254,
  255 };

 /*
  * "m"
  */
 static char c__027[] = {
  254,
  254,
  63, 1, 254,
  28, 1, 34, 3, 254,
  27, 41, 254,
  26, 44, 254,
  25, 45, 254,
  26, 42, 254,
  27, 39, 254,
  28, 1, 33, 2, 254,
  63, 2, 254,
  64, 2, 254,
  65, 2, 254,
  64, 4, 254,
  63, 6, 254,
  28, 1, 33, 8, 254,
  27, 42, 254,
  26, 42, 254,
  25, 42, 254,
  26, 40, 254,
  27, 38, 254,
  28, 1, 35, 2, 254,
  65, 2, 254,
  64, 4, 254,
  63, 6, 254,
  28, 1, 33, 8, 254,
  27, 42, 254,
  26, 42, 254,
  25, 42, 254,
  26, 40, 254,
  27, 38, 254,
  254,
  255 };

 /*
  * "n"
  */
 static char c__028[] = {
  254,
  254,
  63, 1, 254,
  28, 1, 34, 3, 254,
  27, 41, 254,
  26, 44, 254,
  25, 45, 254,
  26, 42, 254,
  27, 39, 254,
  28, 1, 33, 2, 254,
  63, 2, 254,
  64, 2, 254,
  65, 2, 254,
  64, 4, 254,
  63, 6, 254,
  28, 1, 33, 8, 254,
  27, 42, 254,
  26, 42, 254,
  25, 42, 254,
  26, 40, 254,
  27, 38, 254,
  254,
  255 };

 /*
  * "o"
  */
 static char c__029[] = {
  254,
  254,
  34, 26, 254,
  33, 28, 254,
  32, 30, 254,
  31, 32, 254,
  30, 34, 254,
  29, 8, 26, 2, 254,
  28, 8, 28, 2, 254,
  27, 8, 30, 2, 254,
  26, 8, 30, 4, 254,
  25, 8, 30, 6, 254,
  26, 6, 30, 8, 254,
  27, 4, 30, 8, 254,
  28, 2, 30, 8, 254,
  29, 2, 28, 8, 254,
  30, 2, 26, 8, 254,
  31, 34, 254,
  32, 32, 254,
  33, 30, 254,
  34, 28, 254,
  254,
  255 };

 /*
  * "p"
  */
 static char c__030[] = {
  254,
  254,
  4, 1, 60, 1, 254,
  3, 3, 58, 3, 254,
  2, 66, 254,
  1, 68, 254,
  0, 70, 254,
  1, 67, 254,
  2, 64, 254,
  3, 3, 21, 8, 28, 2, 254,
  4, 1, 21, 8, 30, 2, 254,
  25, 8, 32, 2, 254,
  26, 6, 32, 4, 254,
  27, 4, 32, 6, 254,
  28, 2, 32, 8, 254,
  29, 2, 30, 8, 254,
  30, 2, 28, 8, 254,
  31, 36, 254,
  32, 34, 254,
  33, 32, 254,
  34, 30, 254,
  254,
  255 };

 /*
  * "q"
  */
 static char c__031[] = {
  254,
  254,
  32, 28, 254,
  31, 30, 254,
  30, 32, 254,
  29, 34, 254,
  28, 36, 254,
  27, 8, 28, 2, 254,
  26, 8, 30, 2, 254,
  25, 8, 32, 2, 254,
  26, 6, 32, 4, 254,
  27, 4, 32, 6, 254,
  28, 2, 32, 8, 254,
  4, 1, 24, 2, 30, 8, 254,
  3, 3, 24, 2, 28, 8, 254,
  2, 65, 254,
  1, 65, 254,
  0, 65, 254,
  1, 63, 254,
  2, 61, 254,
  3, 3, 254,
  254,
  255 };

 /*
  * "r"
  */
 static char c__032[] = {
  254,
  254,
  63, 1, 254,
  28, 1, 34, 3, 254,
  27, 41, 254,
  26, 44, 254,
  25, 45, 254,
  26, 42, 254,
  27, 39, 254,
  28, 1, 33, 2, 254,
  63, 2, 254,
  64, 2, 254,
  65, 2, 254,
  64, 4, 254,
  63, 6, 254,
  62, 8, 254,
  61, 8, 254,
  57, 11, 254,
  57, 10, 254,
  57, 9, 254,
  57, 8, 254,
  254,
  255 };

 /*
  * "s"
  */
 static char c__033[] = {
  254,
  254,
  25, 3, 20, 9, 254,
  27, 4, 15, 14, 254,
  28, 5, 11, 19, 254,
  29, 5, 10, 9, 10, 2, 254,
  29, 6, 9, 8, 10, 5, 254,
  29, 7, 7, 8, 10, 7, 254,
  29, 7, 7, 8, 9, 10, 254,
  29, 8, 6, 8, 8, 10, 254,
  29, 8, 6, 8, 8, 9, 254,
  29, 8, 6, 8, 7, 9, 254,
  28, 9, 6, 8, 7, 8, 254,
  27, 9, 7, 8, 7, 8, 254,
  26, 10, 7, 8, 7, 8, 254,
  25, 10, 8, 8, 8, 7, 254,
  27, 7, 9, 8, 8, 7, 254,
  28, 5, 9, 8, 10, 6, 254,
  30, 2, 9, 9, 11, 5, 254,
  32, 18, 12, 5, 254,
  35, 14, 15, 4, 254,
  254,
  255 };

 /*
  * "t"
  */
 static char c__034[] = {
  254,
  254,
  68, 1, 254,
  68, 2, 254,
  68, 3, 254,
  68, 4, 254,
  68, 5, 254,
  68, 6, 254,
  68, 7, 254,
  29, 54, 254,
  28, 56, 254,
  27, 58, 254,
  26, 60, 254,
  25, 62, 254,
  26, 6, 36, 7, 254,
  27, 4, 38, 6, 254,
  28, 2, 40, 5, 254,
  29, 2, 40, 4, 254,
  30, 2, 40, 3, 254,
  73, 2, 254,
  254,
  255 };

 /*
  * "u"
  */
 static char c__035[] = {
  254,
  254,
  65, 1, 254,
  64, 4, 254,
  29, 41, 254,
  28, 41, 254,
  27, 41, 254,
  26, 41, 254,
  25, 41, 254,
  26, 6, 254,
  27, 4, 254,
  28, 2, 254,
  29, 2, 254,
  30, 2, 33, 1, 254,
  30, 3, 31, 4, 254,
  29, 41, 254,
  27, 42, 254,
  25, 43, 254,
  25, 42, 254,
  27, 39, 254,
  29, 3, 254,
  254,
  255 };

 /*
  * "v"
  */
 static char c__036[] = {
  254,
  254,
  65, 1, 254,
  64, 4, 254,
  33, 37, 254,
  32, 37, 254,
  31, 37, 254,
  30, 37, 254,
  29, 37, 254,
  28, 8, 30, 1, 254,
  27, 8, 32, 1, 254,
  26, 8, 33, 2, 254,
  25, 8, 33, 4, 254,
  26, 6, 33, 6, 254,
  27, 4, 33, 8, 254,
  29, 2, 32, 10, 254,
  30, 4, 27, 13, 254,
  32, 4, 22, 15, 254,
  34, 6, 14, 18, 254,
  36, 34, 254,
  39, 29, 254,
  42, 23, 254,
  254,
  255 };

 /*
  * "w"
  */
 static char c__037[] = {
  254,
  254,
  66, 1, 254,
  30, 38, 254,
  29, 40, 254,
  28, 42, 254,
  27, 42, 254,
  26, 42, 254,
  25, 8, 33, 1, 254,
  26, 6, 254,
  27, 4, 254,
  28, 2, 254,
  29, 2, 35, 1, 254,
  30, 38, 254,
  29, 40, 254,
  28, 42, 254,
  27, 42, 254,
  26, 42, 254,
  25, 8, 33, 1, 254,
  27, 4, 254,
  28, 2, 254,
  29, 2, 35, 1, 254,
  30, 38, 254,
  31, 38, 254,
  32, 38, 254,
  33, 36, 254,
  34, 34, 254,
  254,
  255 };

 /*
  * "x"
  */
 static char c__038[] = {
  254,
  254,
  25, 1, 41, 1, 254,
  26, 2, 39, 2, 254,
  27, 3, 37, 3, 254,
  26, 5, 35, 4, 254,
  25, 6, 34, 5, 254,
  28, 6, 29, 6, 254,
  33, 5, 22, 8, 254,
  36, 5, 10, 16, 254,
  40, 26, 254,
  34, 30, 254,
  31, 30, 254,
  29, 27, 254,
  28, 17, 9, 5, 254,
  27, 9, 21, 5, 254,
  26, 6, 29, 6, 254,
  25, 5, 34, 6, 254,
  25, 4, 35, 5, 254,
  25, 3, 37, 3, 254,
  26, 2, 39, 2, 254,
  254,
  255 };

 /*
  * "y"
  */
 static char c__039[] = {
  254,
  254,
  65, 1, 254,
  64, 4, 254,
  7, 8, 14, 41, 254,
  6, 9, 13, 41, 254,
  5, 10, 12, 41, 254,
  4, 11, 11, 41, 254,
  3, 12, 10, 41, 254,
  2, 7, 17, 4, 254,
  1, 7, 19, 2, 254,
  0, 7, 21, 2, 254,
  1, 5, 23, 2, 254,
  2, 3, 25, 2, 33, 1, 254,
  3, 2, 26, 2, 31, 4, 254,
  4, 66, 254,
  5, 64, 254,
  6, 62, 254,
  7, 60, 254,
  254,
  255 };

 /*
  * "z"
  */
 static char c__040[] = {
  254,
  254,
  25, 3, 34, 1, 254,
  25, 5, 32, 3, 254,
  26, 6, 30, 5, 254,
  26, 5, 1, 2, 27, 8, 254,
  27, 5, 3, 2, 24, 9, 254,
  27, 5, 5, 2, 22, 8, 254,
  27, 6, 6, 2, 20, 7, 254,
  27, 6, 9, 2, 17, 7, 254,
  27, 7, 10, 2, 15, 7, 254,
  27, 7, 12, 2, 13, 7, 254,
  27, 7, 15, 2, 10, 7, 254,
  27, 7, 17, 2, 8, 7, 254,
  27, 7, 20, 2, 6, 6, 254,
  27, 7, 22, 2, 4, 6, 254,
  26, 8, 24, 2, 3, 5, 254,
  25, 9, 26, 2, 1, 5, 254,
  26, 8, 28, 7, 254,
  28, 5, 32, 4, 254,
  30, 3, 34, 3, 254,
  254,
  255 };

 /*
  * "A"
  */
 static char c__041[] = {
  254,
  254,
  25, 4, 254,
  27, 4, 254,
  28, 5, 254,
  29, 5, 254,
  29, 6, 254,
  29, 7, 254,
  29, 7, 32, 2, 254,
  28, 9, 32, 3, 254,
  27, 15, 28, 4, 254,
  27, 8, 5, 7, 24, 5, 254,
  26, 8, 11, 8, 18, 7, 254,
  26, 8, 17, 8, 12, 8, 254,
  25, 8, 24, 8, 6, 9, 254,
  25, 8, 27, 21, 16, 1, 254,
  25, 8, 27, 22, 16, 2, 254,
  25, 8, 27, 8, 4, 10, 17, 3, 254,
  26, 7, 27, 8, 10, 10, 11, 4, 254,
  28, 6, 26, 8, 16, 9, 6, 5, 254,
  31, 4, 25, 8, 22, 15, 254,
  35, 2, 23, 8, 27, 10, 254,
  60, 8, 23, 14, 254,
  60, 8, 16, 20, 254,
  60, 8, 9, 26, 254,
  60, 8, 2, 31, 254,
  60, 38, 254,
  56, 36, 254,
  49, 36, 254,
  42, 36, 254,
  35, 36, 254,
  31, 34, 254,
  29, 28, 254,
  27, 23, 254,
  26, 17, 254,
  25, 12, 254,
  25, 8, 254,
  25, 7, 254,
  25, 7, 254,
  26, 6, 254,
  28, 5, 254,
  254,
  255 };

 /*
  * "B"
  */
 static char c__042[] = {
  254,
  254,
  25, 1, 60, 4, 254,
  26, 3, 59, 6, 254,
  27, 3, 61, 6, 254,
  27, 5, 26, 1, 33, 7, 254,
  28, 5, 26, 3, 31, 7, 254,
  28, 6, 26, 5, 29, 7, 254,
  28, 7, 26, 6, 27, 8, 254,
  29, 7, 25, 7, 26, 8, 254,
  29, 7, 25, 8, 25, 8, 254,
  29, 8, 24, 9, 23, 8, 254,
  29, 8, 24, 10, 22, 8, 254,
  29, 9, 22, 11, 22, 8, 254,
  29, 64, 1, 8, 254,
  29, 9, 1, 55, 1, 7, 254,
  29, 10, 1, 55, 1, 7, 254,
  29, 10, 3, 54, 2, 5, 254,
  29, 11, 4, 54, 3, 3, 254,
  29, 11, 7, 54, 2, 2, 254,
  29, 11, 33, 2, 18, 12, 254,
  29, 12, 32, 2, 18, 12, 254,
  29, 12, 32, 2, 18, 12, 254,
  29, 12, 32, 2, 18, 11, 254,
  29, 12, 32, 2, 18, 11, 254,
  29, 12, 31, 3, 17, 12, 254,
  29, 11, 31, 4, 17, 11, 254,
  29, 11, 30, 5, 17, 10, 254,
  29, 11, 29, 6, 16, 11, 254,
  28, 12, 28, 7, 16, 10, 254,
  28, 11, 28, 8, 15, 11, 254,
  27, 12, 27, 9, 15, 10, 254,
  27, 12, 25, 8, 1, 2, 14, 10, 254,
  26, 12, 25, 9, 1, 2, 14, 9, 254,
  25, 13, 23, 10, 3, 2, 12, 9, 254,
  26, 12, 21, 11, 4, 3, 9, 10, 254,
  28, 9, 20, 13, 4, 5, 6, 10, 254,
  30, 7, 18, 14, 6, 19, 254,
  31, 5, 17, 15, 8, 17, 254,
  33, 3, 14, 17, 10, 14, 254,
  36, 3, 5, 21, 13, 11, 254,
  38, 25, 18, 5, 254,
  41, 20, 254,
  254,
  255 };

 /*
  * "C"
  */
 static char c__043[] = {
  254,
  254,
  58, 9, 254,
  52, 21, 254,
  47, 31, 254,
  44, 37, 254,
  41, 43, 254,
  39, 47, 254,
  37, 23, 5, 2, 10, 11, 254,
  35, 20, 11, 4, 12, 8, 254,
  33, 18, 16, 5, 14, 5, 254,
  32, 16, 19, 7, 13, 1, 1, 3, 254,
  31, 15, 21, 8, 13, 1, 2, 3, 254,
  30, 14, 22, 10, 13, 1, 3, 2, 254,
  29, 62, 3, 2, 254,
  28, 13, 1, 50, 3, 2, 254,
  27, 12, 4, 50, 4, 1, 254,
  26, 12, 6, 50, 254,
  26, 11, 8, 50, 254,
  26, 10, 10, 50, 254,
  25, 10, 59, 4, 254,
  25, 9, 59, 7, 254,
  25, 8, 59, 10, 254,
  25, 8, 58, 14, 254,
  25, 7, 58, 14, 254,
  25, 7, 57, 14, 254,
  25, 6, 57, 14, 254,
  25, 6, 56, 14, 254,
  25, 5, 56, 14, 254,
  25, 5, 55, 14, 254,
  25, 5, 54, 14, 254,
  26, 4, 54, 13, 254,
  26, 4, 54, 12, 254,
  27, 3, 54, 12, 254,
  27, 4, 53, 11, 254,
  28, 3, 54, 9, 254,
  29, 3, 54, 8, 254,
  30, 2, 55, 7, 254,
  31, 2, 55, 6, 254,
  32, 2, 56, 4, 254,
  254,
  255 };

 /*
  * "D"
  */
 static char c__044[] = {
  254,
  254,
  25, 1, 60, 4, 254,
  26, 3, 59, 6, 254,
  27, 3, 61, 6, 254,
  27, 5, 26, 1, 33, 7, 254,
  28, 5, 26, 3, 31, 7, 254,
  28, 6, 26, 5, 29, 7, 254,
  28, 7, 26, 6, 27, 8, 254,
  29, 7, 25, 7, 26, 8, 254,
  29, 7, 25, 8, 25, 8, 254,
  29, 8, 24, 9, 23, 8, 254,
  29, 8, 24, 10, 22, 8, 254,
  29, 9, 22, 11, 22, 8, 254,
  29, 64, 1, 8, 254,
  29, 9, 1, 55, 1, 7, 254,
  29, 10, 1, 55, 1, 7, 254,
  29, 10, 3, 54, 2, 5, 254,
  29, 11, 4, 54, 3, 3, 254,
  29, 11, 7, 54, 2, 2, 254,
  29, 11, 53, 12, 254,
  29, 12, 52, 12, 254,
  29, 12, 51, 12, 254,
  29, 12, 50, 13, 254,
  29, 12, 50, 12, 254,
  29, 12, 49, 13, 254,
  29, 11, 49, 14, 254,
  29, 11, 48, 14, 254,
  29, 11, 47, 14, 254,
  28, 12, 46, 14, 254,
  28, 11, 45, 15, 254,
  27, 12, 44, 15, 254,
  27, 12, 42, 16, 254,
  26, 12, 42, 15, 254,
  25, 13, 40, 16, 254,
  26, 12, 38, 16, 254,
  28, 9, 37, 17, 254,
  30, 7, 35, 17, 254,
  31, 5, 33, 18, 254,
  33, 3, 30, 19, 254,
  36, 3, 23, 20, 254,
  39, 5, 12, 21, 254,
  44, 28, 254,
  254,
  255 };

 /*
  * "E"
  */
 static char c__045[] = {
  254,
  254,
  25, 1, 60, 4, 254,
  25, 3, 60, 6, 254,
  26, 4, 61, 6, 254,
  27, 4, 27, 1, 33, 7, 254,
  28, 4, 27, 3, 31, 7, 254,
  29, 5, 26, 5, 29, 7, 254,
  29, 6, 26, 6, 27, 8, 254,
  29, 7, 25, 7, 26, 8, 254,
  29, 8, 24, 8, 25, 8, 254,
  29, 9, 23, 9, 23, 8, 254,
  30, 8, 23, 10, 22, 8, 254,
  30, 9, 21, 11, 22, 8, 254,
  30, 63, 1, 8, 254,
  29, 65, 1, 7, 254,
  29, 11, 1, 54, 1, 7, 254,
  29, 11, 3, 53, 2, 5, 254,
  28, 12, 5, 53, 3, 3, 254,
  27, 12, 9, 53, 2, 2, 254,
  27, 12, 24, 3, 27, 12, 254,
  26, 13, 25, 4, 24, 12, 254,
  26, 12, 25, 7, 22, 11, 254,
  26, 12, 24, 10, 20, 10, 254,
  25, 13, 23, 10, 21, 10, 254,
  25, 12, 23, 10, 22, 10, 254,
  25, 12, 22, 10, 24, 8, 254,
  25, 12, 21, 10, 25, 8, 254,
  25, 11, 24, 8, 26, 7, 254,
  25, 11, 26, 6, 26, 7, 254,
  25, 11, 27, 4, 28, 6, 254,
  25, 11, 29, 2, 28, 6, 254,
  25, 11, 60, 6, 254,
  25, 11, 61, 5, 254,
  27, 9, 62, 4, 254,
  29, 7, 63, 4, 254,
  31, 6, 64, 3, 254,
  33, 5, 65, 2, 254,
  35, 3, 254,
  37, 2, 254,
  254,
  255 };

 /*
  * "F"
  */
 static char c__046[] = {
  254,
  254,
  25, 1, 60, 4, 254,
  25, 3, 60, 6, 254,
  26, 4, 61, 6, 254,
  27, 4, 27, 1, 33, 7, 254,
  28, 4, 27, 3, 31, 7, 254,
  29, 5, 26, 5, 29, 7, 254,
  29, 6, 26, 6, 27, 8, 254,
  29, 7, 25, 7, 26, 8, 254,
  29, 8, 24, 8, 25, 8, 254,
  29, 9, 23, 9, 23, 8, 254,
  29, 10, 22, 10, 22, 8, 254,
  30, 9, 21, 11, 22, 8, 254,
  30, 63, 1, 8, 254,
  31, 63, 1, 7, 254,
  32, 63, 1, 7, 254,
  33, 63, 2, 5, 254,
  35, 63, 3, 3, 254,
  37, 64, 2, 2, 254,
  63, 3, 27, 12, 254,
  64, 4, 24, 12, 254,
  63, 7, 22, 11, 254,
  62, 10, 20, 10, 254,
  61, 10, 21, 10, 254,
  60, 10, 22, 10, 254,
  59, 10, 24, 8, 254,
  58, 10, 25, 8, 254,
  60, 8, 26, 7, 254,
  62, 6, 26, 7, 254,
  63, 4, 28, 6, 254,
  64, 2, 29, 6, 254,
  96, 6, 254,
  97, 5, 254,
  98, 4, 254,
  99, 4, 254,
  101, 3, 254,
  254,
  255 };

 /*
  * "G"
  */
 static char c__047[] = {
  254,
  254,
  58, 9, 254,
  52, 21, 254,
  47, 31, 254,
  44, 37, 254,
  41, 43, 254,
  39, 47, 254,
  37, 23, 5, 2, 10, 11, 254,
  35, 20, 11, 4, 12, 8, 254,
  33, 18, 16, 5, 14, 5, 254,
  32, 16, 19, 7, 13, 1, 1, 3, 254,
  31, 15, 21, 8, 13, 1, 2, 3, 254,
  30, 14, 22, 10, 13, 1, 3, 2, 254,
  29, 62, 3, 2, 254,
  28, 13, 1, 50, 3, 2, 254,
  27, 12, 4, 50, 4, 1, 254,
  26, 12, 6, 50, 254,
  26, 11, 8, 50, 254,
  26, 10, 10, 50, 254,
  25, 10, 26, 2, 31, 4, 254,
  25, 9, 28, 3, 28, 7, 254,
  25, 8, 30, 5, 24, 10, 254,
  25, 8, 31, 6, 21, 14, 254,
  25, 7, 33, 5, 1, 2, 17, 14, 254,
  25, 7, 33, 6, 2, 2, 14, 14, 254,
  25, 6, 35, 6, 2, 3, 11, 14, 254,
  25, 6, 35, 7, 2, 3, 9, 14, 254,
  25, 5, 36, 7, 3, 3, 7, 14, 254,
  25, 5, 36, 8, 3, 3, 5, 14, 254,
  26, 4, 36, 8, 4, 3, 3, 14, 254,
  26, 4, 36, 8, 4, 3, 3, 13, 254,
  27, 3, 36, 8, 4, 3, 3, 12, 254,
  27, 4, 34, 8, 5, 3, 3, 11, 254,
  28, 3, 34, 8, 6, 3, 2, 10, 254,
  29, 2, 33, 8, 7, 3, 3, 9, 254,
  30, 2, 31, 8, 8, 3, 4, 8, 254,
  31, 2, 28, 9, 10, 3, 4, 7, 254,
  33, 1, 25, 10, 12, 3, 4, 6, 254,
  34, 2, 21, 10, 16, 3, 4, 4, 254,
  36, 2, 16, 11, 20, 3, 4, 2, 254,
  38, 3, 7, 16, 24, 3, 2, 2, 254,
  41, 19, 31, 2, 254,
  254,
  255 };

 /*
  * "H"
  */
 static char c__048[] = {
  254,
  254,
  25, 3, 58, 4, 254,
  27, 4, 57, 6, 254,
  28, 5, 58, 6, 254,
  28, 7, 23, 1, 33, 7, 254,
  28, 8, 23, 3, 31, 7, 254,
  29, 8, 23, 5, 29, 7, 254,
  29, 8, 24, 6, 27, 8, 254,
  29, 9, 23, 7, 26, 8, 254,
  29, 9, 23, 8, 25, 8, 254,
  28, 9, 24, 9, 23, 8, 254,
  28, 9, 24, 10, 22, 8, 254,
  28, 8, 24, 11, 22, 8, 254,
  28, 65, 1, 8, 254,
  27, 8, 1, 58, 1, 7, 254,
  26, 9, 2, 58, 1, 7, 254,
  26, 8, 5, 57, 2, 5, 254,
  0, 1, 24, 8, 8, 57, 3, 3, 254,
  1, 2, 22, 8, 12, 35, 13, 12, 254,
  2, 3, 20, 8, 42, 2, 15, 12, 254,
  3, 3, 19, 8, 43, 2, 14, 11, 254,
  3, 5, 17, 8, 43, 3, 13, 10, 254,
  4, 5, 16, 8, 42, 5, 12, 10, 254,
  5, 5, 16, 8, 40, 7, 11, 10, 254,
  6, 6, 15, 7, 39, 9, 11, 8, 254,
  7, 7, 15, 6, 38, 10, 10, 8, 254,
  8, 8, 16, 4, 36, 12, 10, 7, 254,
  9, 9, 17, 3, 34, 11, 11, 7, 254,
  10, 11, 51, 10, 13, 6, 254,
  12, 12, 47, 11, 13, 6, 254,
  13, 68, 15, 6, 254,
  15, 66, 16, 5, 254,
  18, 62, 18, 4, 254,
  20, 60, 19, 4, 254,
  22, 58, 21, 3, 254,
  26, 54, 23, 2, 254,
  75, 6, 254,
  77, 5, 254,
  80, 3, 254,
  254,
  255 };

 /*
  * "I"
  */
 static char c__049[] = {
  254,
  254,
  25, 1, 60, 4, 254,
  25, 3, 60, 6, 254,
  26, 4, 61, 6, 254,
  27, 4, 27, 1, 33, 7, 254,
  28, 4, 27, 3, 31, 7, 254,
  29, 5, 26, 5, 29, 7, 254,
  29, 6, 26, 6, 27, 8, 254,
  29, 7, 25, 7, 26, 8, 254,
  29, 8, 24, 8, 25, 8, 254,
  29, 9, 23, 9, 23, 8, 254,
  28, 11, 22, 10, 22, 8, 254,
  28, 11, 21, 11, 22, 8, 254,
  27, 66, 1, 8, 254,
  26, 68, 1, 7, 254,
  26, 69, 1, 7, 254,
  25, 71, 2, 5, 254,
  27, 71, 3, 3, 254,
  254,
  255 };

 /*
  * "J"
  */
 static char c__050[] = {
  254,
  254,
  34, 13, 254,
  30, 20, 254,
  28, 24, 254,
  27, 27, 32, 4, 254,
  27, 15, 3, 10, 33, 6, 254,
  26, 12, 12, 6, 35, 6, 254,
  26, 9, 18, 5, 8, 1, 25, 7, 254,
  25, 8, 22, 5, 4, 2, 27, 7, 254,
  25, 7, 25, 8, 29, 7, 254,
  25, 6, 28, 4, 31, 8, 254,
  26, 4, 64, 8, 254,
  26, 4, 64, 8, 254,
  27, 4, 46, 8, 8, 8, 254,
  28, 4, 36, 21, 4, 8, 254,
  29, 4, 30, 29, 1, 8, 254,
  30, 5, 20, 38, 1, 8, 254,
  32, 62, 1, 7, 254,
  34, 61, 1, 7, 254,
  36, 36, 16, 8, 2, 5, 254,
  39, 26, 26, 7, 3, 3, 254,
  44, 14, 36, 6, 3, 2, 254,
  97, 5, 254,
  254,
  255 };

 /*
  * "K"
  */
 static char c__051[] = {
  254,
  254,
  25, 3, 58, 4, 254,
  27, 4, 57, 6, 254,
  28, 5, 58, 6, 254,
  28, 7, 23, 1, 33, 7, 254,
  28, 8, 23, 3, 31, 7, 254,
  29, 8, 23, 5, 29, 7, 254,
  29, 8, 24, 6, 27, 8, 254,
  29, 9, 23, 7, 26, 8, 254,
  29, 9, 23, 8, 25, 8, 254,
  28, 9, 24, 9, 23, 8, 254,
  28, 9, 24, 10, 22, 8, 254,
  28, 8, 24, 11, 22, 8, 254,
  28, 65, 1, 8, 254,
  27, 8, 1, 58, 1, 7, 254,
  26, 9, 2, 58, 1, 7, 254,
  26, 8, 5, 57, 2, 5, 254,
  25, 8, 8, 57, 3, 3, 254,
  25, 8, 12, 56, 2, 2, 254,
  25, 8, 25, 2, 16, 2, 15, 12, 254,
  25, 8, 26, 2, 16, 2, 13, 12, 254,
  25, 8, 26, 3, 16, 2, 12, 11, 254,
  25, 8, 26, 4, 14, 4, 11, 10, 254,
  25, 8, 26, 5, 11, 7, 10, 10, 254,
  26, 8, 25, 6, 8, 10, 9, 10, 254,
  27, 7, 24, 8, 5, 13, 9, 8, 254,
  29, 6, 22, 10, 2, 16, 8, 8, 254,
  32, 4, 19, 10, 1, 17, 11, 7, 254,
  35, 3, 14, 12, 3, 14, 13, 7, 254,
  44, 20, 4, 11, 16, 6, 254,
  35, 28, 6, 8, 18, 6, 254,
  31, 31, 8, 5, 21, 6, 254,
  29, 32, 10, 2, 24, 5, 254,
  28, 30, 40, 4, 254,
  27, 23, 49, 4, 254,
  26, 16, 59, 3, 254,
  26, 11, 66, 2, 254,
  25, 9, 254,
  25, 7, 254,
  25, 6, 254,
  26, 4, 254,
  27, 3, 254,
  254,
  255 };

 /*
  * "L"
  */
 static char c__052[] = {
  254,
  254,
  25, 1, 60, 4, 254,
  25, 3, 60, 6, 254,
  26, 4, 61, 6, 254,
  27, 4, 27, 1, 33, 7, 254,
  28, 4, 27, 3, 31, 7, 254,
  28, 6, 26, 5, 29, 7, 254,
  29, 6, 26, 6, 27, 8, 254,
  30, 6, 25, 7, 26, 8, 254,
  30, 7, 24, 8, 25, 8, 254,
  31, 7, 23, 9, 23, 8, 254,
  31, 8, 22, 10, 22, 8, 254,
  31, 8, 21, 11, 22, 8, 254,
  31, 62, 1, 8, 254,
  30, 9, 1, 54, 1, 7, 254,
  30, 10, 1, 54, 1, 7, 254,
  29, 11, 3, 53, 2, 5, 254,
  29, 11, 5, 53, 3, 3, 254,
  28, 11, 9, 53, 2, 2, 254,
  28, 11, 54, 12, 254,
  27, 12, 53, 10, 254,
  27, 11, 54, 9, 254,
  26, 12, 55, 7, 254,
  26, 11, 57, 5, 254,
  26, 10, 59, 4, 254,
  25, 10, 61, 3, 254,
  25, 10, 62, 3, 254,
  25, 9, 65, 2, 254,
  25, 9, 254,
  26, 8, 254,
  26, 8, 254,
  27, 7, 254,
  27, 7, 254,
  28, 6, 254,
  29, 5, 254,
  30, 4, 254,
  32, 3, 254,
  34, 2, 254,
  36, 2, 254,
  254,
  255 };

 /*
  * "M"
  */
 static char c__053[] = {
  254,
  254,
  25, 2, 59, 4, 254,
  27, 3, 58, 6, 254,
  28, 4, 59, 6, 254,
  29, 4, 25, 1, 33, 7, 254,
  29, 6, 24, 3, 31, 7, 254,
  29, 7, 24, 5, 29, 7, 254,
  29, 8, 24, 6, 27, 8, 254,
  29, 9, 23, 7, 26, 8, 254,
  29, 9, 23, 8, 25, 8, 254,
  29, 10, 22, 9, 23, 8, 254,
  29, 10, 22, 10, 22, 8, 254,
  28, 11, 21, 11, 22, 8, 254,
  27, 66, 1, 8, 254,
  25, 69, 1, 7, 254,
  26, 69, 1, 7, 254,
  28, 68, 2, 5, 254,
  30, 68, 3, 3, 254,
  34, 67, 2, 2, 254,
  93, 12, 254,
  92, 12, 254,
  58, 1, 32, 12, 254,
  59, 3, 28, 12, 254,
  60, 5, 24, 12, 254,
  61, 6, 21, 12, 254,
  61, 7, 19, 12, 254,
  61, 8, 17, 12, 254,
  30, 1, 30, 9, 15, 12, 254,
  29, 3, 29, 10, 13, 12, 254,
  28, 5, 27, 11, 12, 12, 254,
  27, 67, 254,
  26, 67, 254,
  25, 67, 254,
  26, 65, 254,
  27, 63, 254,
  28, 61, 254,
  29, 5, 25, 10, 19, 3, 254,
  30, 3, 26, 9, 22, 3, 254,
  31, 1, 28, 8, 24, 3, 254,
  61, 7, 26, 3, 254,
  62, 6, 27, 4, 254,
  63, 5, 26, 7, 254,
  64, 5, 25, 9, 254,
  67, 3, 23, 12, 254,
  30, 1, 39, 1, 22, 11, 254,
  29, 3, 60, 11, 254,
  28, 5, 59, 10, 254,
  27, 74, 254,
  26, 75, 254,
  25, 76, 254,
  26, 75, 254,
  27, 75, 254,
  28, 74, 254,
  29, 5, 64, 5, 254,
  30, 3, 66, 4, 254,
  31, 1, 69, 3, 254,
  254,
  255 };

 /*
  * "N"
  */
 static char c__054[] = {
  254,
  254,
  25, 2, 34, 3, 31, 2, 254,
  26, 3, 34, 4, 29, 3, 254,
  27, 4, 33, 5, 28, 4, 254,
  28, 5, 32, 6, 26, 5, 254,
  28, 6, 31, 7, 25, 6, 254,
  29, 6, 30, 8, 23, 8, 254,
  29, 7, 28, 10, 21, 10, 254,
  29, 76, 254,
  29, 76, 254,
  29, 75, 254,
  29, 10, 47, 17, 254,
  28, 11, 43, 19, 254,
  28, 12, 39, 20, 254,
  27, 13, 36, 20, 254,
  25, 15, 33, 20, 254,
  27, 13, 30, 20, 254,
  29, 11, 27, 20, 254,
  31, 9, 24, 20, 254,
  32, 8, 21, 20, 254,
  35, 4, 19, 20, 254,
  37, 1, 17, 20, 17, 1, 254,
  52, 20, 19, 4, 254,
  49, 20, 21, 7, 254,
  46, 20, 24, 9, 254,
  43, 20, 27, 11, 254,
  40, 20, 30, 13, 254,
  37, 20, 33, 15, 254,
  34, 20, 36, 13, 254,
  31, 20, 39, 12, 254,
  28, 20, 43, 11, 254,
  27, 18, 46, 10, 254,
  26, 75, 254,
  25, 76, 254,
  25, 76, 254,
  25, 11, 58, 7, 254,
  25, 10, 60, 6, 254,
  26, 8, 62, 6, 254,
  28, 6, 63, 5, 254,
  30, 4, 65, 4, 254,
  32, 3, 66, 3, 254,
  254,
  255 };

 /*
  * "O"
  */
 static char c__055[] = {
  254,
  254,
  58, 9, 254,
  53, 21, 254,
  47, 31, 254,
  44, 38, 254,
  41, 43, 254,
  39, 47, 254,
  37, 23, 6, 2, 9, 11, 254,
  35, 20, 12, 3, 10, 2, 1, 7, 254,
  33, 18, 16, 5, 9, 2, 4, 5, 254,
  32, 16, 19, 6, 9, 2, 5, 4, 254,
  31, 15, 21, 7, 9, 2, 6, 3, 254,
  30, 14, 22, 9, 9, 2, 7, 2, 254,
  29, 58, 254,
  28, 12, 3, 45, 254,
  27, 12, 5, 45, 254,
  27, 11, 7, 46, 254,
  26, 11, 10, 45, 254,
  26, 10, 15, 43, 254,
  25, 10, 58, 3, 254,
  26, 8, 58, 6, 254,
  28, 5, 58, 10, 254,
  29, 3, 58, 15, 254,
  30, 2, 58, 14, 254,
  31, 2, 56, 14, 254,
  33, 2, 53, 15, 254,
  34, 2, 51, 15, 254,
  36, 2, 47, 16, 254,
  37, 3, 44, 16, 254,
  39, 4, 40, 16, 254,
  40, 6, 35, 17, 254,
  42, 7, 29, 18, 254,
  44, 8, 23, 19, 254,
  46, 11, 14, 21, 254,
  48, 41, 254,
  51, 36, 254,
  53, 31, 254,
  56, 25, 254,
  59, 19, 254,
  254,
  255 };

 /*
  * "P"
  */
 static char c__056[] = {
  254,
  254,
  25, 3, 58, 4, 254,
  27, 4, 57, 6, 254,
  28, 5, 58, 6, 254,
  28, 7, 23, 1, 33, 7, 254,
  28, 8, 23, 3, 31, 7, 254,
  29, 8, 23, 5, 29, 7, 254,
  29, 8, 24, 6, 27, 8, 254,
  29, 9, 23, 7, 26, 8, 254,
  29, 9, 23, 8, 25, 8, 254,
  28, 9, 24, 9, 23, 8, 254,
  28, 9, 24, 10, 22, 8, 254,
  28, 8, 24, 11, 22, 8, 254,
  28, 65, 1, 8, 254,
  27, 8, 1, 58, 1, 7, 254,
  26, 9, 2, 58, 1, 7, 254,
  26, 8, 5, 57, 2, 5, 254,
  25, 8, 8, 57, 3, 3, 254,
  25, 8, 12, 56, 2, 2, 254,
  25, 8, 31, 4, 25, 12, 254,
  25, 8, 30, 7, 23, 11, 254,
  25, 8, 29, 10, 20, 11, 254,
  25, 8, 28, 13, 18, 11, 254,
  25, 8, 28, 11, 19, 11, 254,
  26, 8, 26, 10, 21, 11, 254,
  27, 7, 25, 9, 22, 11, 254,
  29, 6, 24, 8, 23, 11, 254,
  32, 4, 23, 7, 23, 11, 254,
  35, 3, 20, 7, 24, 10, 254,
  58, 6, 24, 10, 254,
  58, 5, 24, 10, 254,
  58, 5, 23, 10, 254,
  59, 3, 23, 10, 254,
  59, 3, 22, 9, 254,
  59, 3, 20, 10, 254,
  60, 2, 18, 10, 254,
  61, 2, 15, 10, 254,
  62, 2, 12, 9, 254,
  64, 18, 254,
  254,
  255 };

 /*
  * "Q"
  */
 static char c__057[] = {
  254,
  254,
  58, 9, 254,
  53, 21, 254,
  47, 31, 254,
  44, 38, 254,
  41, 43, 254,
  39, 47, 254,
  37, 23, 6, 2, 9, 11, 254,
  35, 20, 12, 3, 10, 2, 1, 7, 254,
  33, 18, 16, 5, 9, 2, 4, 5, 254,
  32, 16, 19, 6, 9, 2, 5, 4, 254,
  31, 15, 21, 7, 9, 2, 6, 3, 254,
  30, 14, 22, 9, 9, 2, 7, 2, 254,
  29, 58, 254,
  28, 12, 1, 47, 254,
  27, 12, 3, 47, 254,
  27, 11, 4, 49, 254,
  26, 11, 5, 4, 1, 45, 254,
  26, 10, 6, 5, 4, 43, 254,
  25, 10, 7, 6, 45, 3, 254,
  26, 8, 7, 7, 44, 6, 254,
  28, 5, 7, 9, 42, 10, 254,
  29, 3, 6, 11, 41, 15, 254,
  30, 2, 4, 12, 42, 14, 254,
  31, 16, 42, 14, 254,
  30, 15, 43, 15, 254,
  28, 16, 43, 15, 254,
  27, 15, 43, 16, 254,
  26, 14, 44, 16, 254,
  25, 13, 1, 4, 40, 16, 254,
  25, 11, 4, 6, 35, 17, 254,
  25, 9, 8, 7, 29, 18, 254,
  25, 8, 11, 8, 23, 19, 254,
  25, 8, 13, 11, 14, 21, 254,
  25, 8, 15, 41, 254,
  26, 7, 18, 36, 254,
  27, 6, 20, 31, 254,
  28, 5, 23, 25, 254,
  29, 4, 26, 19, 254,
  30, 4, 30, 9, 254,
  31, 3, 254,
  33, 2, 254,
  254,
  255 };

 /*
  * "R"
  */
 static char c__058[] = {
  254,
  254,
  25, 3, 58, 4, 254,
  27, 4, 57, 6, 254,
  28, 5, 58, 6, 254,
  28, 7, 23, 1, 33, 7, 254,
  28, 8, 23, 3, 31, 7, 254,
  29, 8, 23, 5, 29, 7, 254,
  29, 8, 24, 6, 27, 8, 254,
  29, 9, 23, 7, 26, 8, 254,
  29, 9, 23, 8, 25, 8, 254,
  28, 9, 24, 9, 23, 8, 254,
  28, 9, 24, 10, 22, 8, 254,
  28, 8, 24, 11, 22, 8, 254,
  28, 65, 1, 8, 254,
  27, 8, 1, 58, 1, 7, 254,
  26, 9, 2, 58, 1, 7, 254,
  26, 8, 5, 57, 2, 5, 254,
  25, 8, 8, 57, 3, 3, 254,
  25, 8, 12, 56, 2, 2, 254,
  25, 8, 29, 2, 29, 12, 254,
  25, 8, 29, 2, 29, 11, 254,
  25, 8, 29, 2, 29, 11, 254,
  25, 8, 30, 2, 28, 10, 254,
  25, 8, 30, 2, 28, 10, 254,
  26, 8, 29, 2, 28, 9, 254,
  27, 7, 29, 3, 26, 10, 254,
  29, 6, 28, 4, 25, 10, 254,
  32, 4, 26, 6, 24, 9, 254,
  35, 3, 23, 8, 22, 10, 254,
  59, 11, 21, 10, 254,
  57, 14, 19, 10, 254,
  29, 43, 18, 10, 254,
  27, 43, 1, 2, 16, 10, 254,
  26, 44, 2, 2, 14, 11, 254,
  25, 43, 5, 3, 10, 12, 254,
  25, 41, 9, 4, 5, 14, 254,
  25, 37, 14, 20, 254,
  25, 5, 48, 16, 254,
  25, 4, 51, 12, 254,
  25, 4, 54, 6, 254,
  26, 3, 254,
  27, 3, 254,
  254,
  255 };

 /*
  * "S"
  */
 static char c__059[] = {
  254,
  254,
  25, 3, 254,
  27, 4, 254,
  29, 4, 254,
  31, 4, 254,
  32, 5, 254,
  33, 5, 43, 2, 254,
  34, 5, 40, 5, 254,
  34, 6, 37, 8, 254,
  35, 6, 34, 11, 254,
  35, 7, 32, 13, 254,
  36, 7, 30, 15, 254,
  36, 7, 29, 17, 254,
  36, 8, 27, 19, 254,
  36, 8, 26, 17, 2, 3, 254,
  36, 9, 11, 2, 11, 16, 6, 3, 254,
  35, 10, 10, 1, 12, 16, 9, 3, 254,
  35, 10, 9, 1, 12, 16, 10, 5, 254,
  34, 11, 9, 1, 12, 15, 10, 9, 254,
  33, 12, 10, 1, 10, 15, 10, 14, 254,
  32, 12, 12, 2, 7, 15, 10, 13, 254,
  31, 13, 15, 2, 4, 14, 11, 11, 254,
  30, 13, 19, 16, 11, 11, 254,
  28, 14, 22, 13, 12, 9, 254,
  25, 17, 21, 13, 12, 10, 254,
  26, 14, 23, 12, 12, 11, 254,
  26, 13, 23, 12, 1, 2, 10, 11, 254,
  27, 11, 24, 12, 4, 2, 6, 12, 254,
  28, 8, 25, 12, 8, 2, 3, 11, 254,
  29, 6, 26, 12, 11, 13, 254,
  29, 5, 26, 12, 14, 11, 254,
  30, 2, 28, 12, 14, 11, 254,
  31, 2, 26, 12, 16, 10, 254,
  32, 2, 24, 12, 17, 10, 254,
  33, 2, 22, 13, 18, 9, 1, 2, 254,
  34, 3, 19, 13, 20, 8, 4, 2, 254,
  35, 3, 16, 13, 23, 7, 6, 1, 254,
  36, 4, 11, 14, 27, 6, 6, 1, 254,
  38, 25, 31, 5, 5, 1, 254,
  40, 20, 36, 4, 3, 1, 254,
  254,
  255 };

 /*
  * "T"
  */
 static char c__060[] = {
  254,
  254,
  58, 9, 23, 1, 254,
  52, 21, 18, 2, 254,
  47, 31, 15, 2, 254,
  44, 37, 13, 3, 254,
  41, 43, 11, 4, 254,
  39, 47, 10, 4, 254,
  37, 23, 17, 11, 9, 4, 254,
  35, 20, 27, 8, 8, 4, 254,
  33, 18, 14, 2, 19, 5, 7, 5, 254,
  32, 16, 18, 3, 20, 3, 6, 6, 254,
  31, 15, 21, 4, 20, 3, 4, 6, 254,
  30, 14, 23, 5, 21, 2, 3, 7, 254,
  29, 13, 25, 6, 21, 2, 2, 7, 254,
  28, 13, 26, 7, 21, 10, 254,
  27, 12, 27, 8, 22, 9, 254,
  26, 60, 9, 10, 254,
  26, 11, 1, 49, 7, 10, 254,
  26, 10, 3, 49, 5, 10, 254,
  25, 10, 5, 49, 3, 11, 254,
  25, 9, 7, 49, 1, 11, 254,
  25, 8, 9, 60, 254,
  25, 8, 57, 11, 254,
  25, 7, 58, 11, 254,
  25, 7, 57, 11, 254,
  25, 6, 58, 11, 254,
  25, 6, 58, 11, 254,
  25, 5, 60, 9, 254,
  25, 5, 60, 9, 254,
  25, 5, 60, 9, 254,
  26, 4, 61, 8, 254,
  26, 4, 61, 8, 254,
  27, 3, 62, 8, 254,
  27, 4, 62, 7, 254,
  28, 3, 62, 7, 254,
  29, 3, 62, 6, 254,
  30, 2, 63, 6, 254,
  31, 2, 63, 5, 254,
  32, 2, 64, 4, 254,
  254,
  255 };

 /*
  * "U"
  */
 static char c__061[] = {
  254,
  254,
  25, 2, 36, 3, 29, 2, 254,
  26, 4, 34, 5, 28, 3, 254,
  27, 5, 33, 6, 27, 4, 254,
  28, 5, 33, 6, 26, 5, 254,
  28, 6, 32, 7, 25, 6, 254,
  28, 7, 31, 8, 24, 7, 254,
  29, 7, 29, 10, 22, 8, 254,
  29, 76, 254,
  29, 76, 254,
  29, 75, 254,
  29, 74, 254,
  28, 73, 254,
  27, 71, 254,
  27, 12, 254,
  26, 13, 254,
  25, 14, 254,
  26, 12, 254,
  27, 11, 254,
  28, 9, 254,
  29, 7, 254,
  30, 6, 61, 2, 254,
  31, 4, 63, 4, 254,
  32, 2, 65, 4, 254,
  33, 2, 64, 5, 254,
  34, 2, 62, 7, 254,
  35, 70, 254,
  33, 72, 254,
  31, 74, 254,
  29, 76, 254,
  27, 77, 254,
  25, 78, 254,
  26, 13, 57, 7, 254,
  27, 10, 60, 6, 254,
  28, 7, 63, 5, 254,
  29, 4, 67, 4, 254,
  30, 2, 71, 2, 254,
  31, 2, 254,
  254,
  255 };

 /*
  * "V"
  */
 static char c__062[] = {
  254,
  254,
  25, 2, 36, 3, 31, 2, 254,
  26, 4, 34, 5, 29, 4, 254,
  27, 5, 33, 6, 28, 4, 254,
  28, 5, 32, 7, 27, 5, 254,
  28, 6, 30, 9, 26, 6, 254,
  28, 77, 254,
  29, 76, 254,
  29, 76, 254,
  29, 76, 254,
  29, 75, 254,
  29, 74, 254,
  28, 10, 58, 7, 254,
  27, 11, 59, 6, 254,
  27, 12, 59, 5, 254,
  26, 13, 61, 4, 254,
  25, 14, 64, 2, 254,
  26, 12, 254,
  27, 11, 254,
  28, 9, 254,
  29, 7, 254,
  30, 6, 254,
  31, 4, 254,
  32, 2, 254,
  33, 2, 254,
  34, 2, 51, 9, 254,
  35, 3, 33, 28, 254,
  36, 65, 254,
  38, 64, 254,
  40, 63, 254,
  42, 62, 254,
  45, 33, 18, 8, 254,
  48, 14, 36, 7, 254,
  100, 5, 254,
  101, 3, 254,
  102, 2, 254,
  254,
  255 };

 /*
  * "W"
  */
 static char c__063[] = {
  254,
  254,
  25, 2, 36, 3, 29, 2, 254,
  26, 4, 34, 5, 28, 3, 254,
  27, 5, 33, 6, 27, 4, 254,
  28, 5, 33, 6, 26, 5, 254,
  28, 6, 32, 7, 25, 6, 254,
  28, 7, 31, 8, 24, 7, 254,
  29, 7, 29, 10, 22, 8, 254,
  29, 76, 254,
  29, 76, 254,
  29, 75, 254,
  29, 74, 254,
  28, 73, 254,
  27, 71, 254,
  27, 13, 254,
  26, 14, 254,
  25, 15, 254,
  26, 12, 25, 3, 254,
  27, 11, 26, 5, 254,
  28, 9, 28, 6, 26, 2, 254,
  29, 7, 30, 6, 26, 4, 254,
  30, 6, 30, 7, 26, 4, 254,
  31, 4, 31, 8, 25, 5, 254,
  32, 3, 30, 10, 23, 7, 254,
  33, 72, 254,
  31, 74, 254,
  29, 76, 254,
  27, 78, 254,
  25, 80, 254,
  25, 79, 254,
  26, 8, 28, 10, 23, 8, 254,
  27, 5, 31, 8, 25, 7, 254,
  28, 2, 34, 7, 26, 6, 254,
  29, 2, 34, 6, 27, 5, 254,
  30, 2, 34, 6, 28, 4, 254,
  31, 2, 35, 5, 30, 2, 254,
  32, 3, 36, 3, 254,
  33, 4, 49, 6, 254,
  34, 7, 41, 14, 254,
  35, 11, 22, 31, 254,
  36, 65, 254,
  38, 64, 254,
  40, 63, 254,
  42, 62, 254,
  45, 33, 18, 8, 254,
  48, 14, 36, 7, 254,
  52, 6, 42, 5, 254,
  101, 3, 254,
  102, 2, 254,
  254,
  255 };

 /*
  * "X"
  */
 static char c__064[] = {
  254,
  254,
  25, 3, 64, 4, 254,
  26, 5, 63, 5, 254,
  27, 6, 63, 6, 254,
  27, 7, 62, 7, 254,
  28, 7, 18, 3, 40, 8, 254,
  28, 8, 18, 5, 37, 9, 254,
  27, 9, 19, 6, 34, 10, 254,
  27, 9, 20, 7, 31, 11, 254,
  27, 10, 20, 8, 27, 13, 254,
  26, 11, 21, 9, 22, 15, 254,
  26, 11, 21, 10, 18, 17, 254,
  25, 12, 21, 12, 12, 20, 254,
  31, 6, 22, 12, 7, 22, 254,
  36, 6, 17, 12, 3, 24, 254,
  42, 6, 11, 36, 254,
  48, 6, 4, 33, 254,
  54, 33, 254,
  58, 24, 254,
  55, 23, 254,
  51, 23, 254,
  47, 29, 254,
  43, 29, 4, 6, 254,
  39, 32, 11, 6, 254,
  35, 36, 17, 6, 254,
  30, 24, 6, 12, 21, 6, 254,
  28, 21, 13, 10, 21, 12, 254,
  27, 17, 19, 9, 21, 11, 254,
  26, 15, 24, 8, 20, 11, 254,
  25, 13, 29, 7, 19, 10, 254,
  25, 11, 33, 6, 19, 9, 254,
  25, 10, 36, 5, 18, 9, 254,
  25, 9, 40, 3, 17, 8, 254,
  26, 8, 61, 7, 254,
  27, 7, 62, 7, 254,
  28, 6, 63, 6, 254,
  31, 5, 63, 5, 254,
  254,
  255 };

 /*
  * "Y"
  */
 static char c__065[] = {
  254,
  254,
  25, 1, 33, 3, 33, 2, 254,
  25, 3, 33, 4, 31, 4, 254,
  26, 4, 32, 5, 30, 5, 254,
  27, 4, 31, 7, 28, 6, 254,
  0, 2, 25, 6, 29, 8, 27, 7, 254,
  2, 3, 22, 7, 28, 9, 25, 9, 254,
  3, 4, 21, 7, 26, 11, 23, 10, 254,
  4, 5, 19, 77, 254,
  5, 5, 18, 77, 254,
  5, 6, 17, 77, 254,
  6, 6, 16, 76, 254,
  6, 6, 16, 75, 254,
  6, 7, 14, 73, 254,
  6, 7, 14, 11, 52, 3, 254,
  6, 8, 12, 12, 54, 3, 254,
  6, 8, 11, 12, 57, 3, 254,
  6, 9, 12, 10, 58, 4, 254,
  5, 10, 14, 8, 57, 7, 254,
  5, 10, 16, 5, 58, 9, 254,
  5, 10, 18, 3, 57, 12, 254,
  4, 11, 20, 3, 55, 11, 254,
  4, 11, 22, 3, 53, 10, 254,
  3, 11, 25, 3, 50, 11, 254,
  3, 11, 27, 3, 48, 10, 254,
  2, 12, 29, 3, 46, 10, 254,
  1, 12, 20, 69, 254,
  0, 13, 16, 72, 254,
  1, 11, 15, 74, 254,
  2, 9, 14, 76, 254,
  3, 7, 13, 78, 254,
  4, 5, 12, 80, 254,
  5, 3, 11, 16, 60, 7, 254,
  6, 3, 8, 16, 63, 6, 254,
  8, 23, 66, 6, 254,
  10, 18, 71, 5, 254,
  14, 11, 77, 3, 254,
  254,
  255 };

 /*
  * "Z"
  */
 static char c__066[] = {
  254,
  254,
  25, 3, 52, 5, 254,
  27, 3, 46, 14, 254,
  28, 4, 42, 19, 254,
  29, 5, 39, 5, 6, 11, 254,
  29, 6, 37, 3, 11, 11, 254,
  30, 7, 35, 2, 13, 12, 254,
  30, 10, 32, 1, 15, 13, 254,
  30, 11, 47, 15, 254,
  31, 8, 2, 2, 45, 17, 254,
  31, 9, 3, 2, 43, 16, 254,
  31, 9, 5, 2, 40, 16, 254,
  31, 10, 6, 2, 11, 5, 22, 15, 254,
  31, 10, 8, 2, 11, 7, 17, 15, 254,
  31, 11, 9, 2, 10, 8, 15, 14, 254,
  31, 11, 11, 2, 8, 9, 13, 14, 254,
  31, 11, 13, 2, 6, 9, 13, 14, 254,
  31, 11, 15, 2, 4, 9, 13, 14, 254,
  31, 12, 16, 2, 2, 9, 13, 13, 254,
  31, 12, 18, 11, 12, 14, 254,
  31, 12, 20, 9, 12, 14, 254,
  31, 12, 20, 9, 12, 14, 254,
  31, 12, 20, 9, 12, 14, 254,
  30, 13, 20, 9, 13, 13, 254,
  30, 13, 20, 10, 12, 13, 254,
  30, 13, 20, 9, 1, 2, 10, 13, 254,
  29, 14, 20, 9, 3, 2, 9, 12, 254,
  28, 15, 20, 9, 5, 2, 7, 12, 254,
  28, 15, 20, 9, 7, 2, 5, 12, 254,
  27, 15, 22, 8, 9, 2, 4, 11, 254,
  26, 16, 24, 7, 10, 2, 2, 11, 254,
  25, 17, 28, 5, 10, 2, 1, 10, 254,
  26, 15, 46, 12, 254,
  27, 14, 12, 2, 34, 10, 254,
  29, 12, 13, 2, 35, 9, 254,
  31, 11, 11, 4, 36, 7, 254,
  33, 10, 9, 5, 38, 6, 254,
  35, 10, 5, 6, 41, 4, 254,
  37, 18, 44, 3, 254,
  39, 14, 48, 2, 254,
  254,
  255 };

 /*
  * "0"
  */
 static char c__067[] = {
  254,
  254,
  35, 44, 254,
  34, 46, 254,
  33, 48, 254,
  32, 50, 254,
  31, 52, 254,
  30, 8, 44, 2, 254,
  29, 8, 46, 2, 254,
  28, 8, 48, 2, 254,
  27, 8, 48, 4, 254,
  26, 8, 48, 6, 254,
  25, 8, 48, 8, 254,
  26, 6, 48, 8, 254,
  27, 4, 48, 8, 254,
  28, 2, 48, 8, 254,
  29, 2, 46, 8, 254,
  30, 54, 254,
  31, 52, 254,
  32, 50, 254,
  33, 48, 254,
  254,
  255 };

 /*
  * "1"
  */
 static char c__068[] = {
  254,
  254,
  25, 1, 58, 1, 254,
  26, 2, 57, 1, 254,
  27, 2, 56, 2, 254,
  28, 60, 254,
  29, 60, 254,
  30, 58, 254,
  31, 56, 254,
  32, 54, 254,
  33, 2, 254,
  34, 2, 254,
  254,
  255 };

 /*
  * "2"
  */
 static char c__069[] = {
  254,
  254,
  25, 7, 34, 15, 254,
  26, 6, 1, 4, 30, 15, 254,
  26, 7, 4, 4, 27, 15, 254,
  27, 7, 7, 3, 25, 15, 254,
  27, 7, 10, 3, 23, 15, 254,
  28, 7, 12, 2, 33, 4, 254,
  28, 7, 14, 2, 32, 4, 254,
  27, 7, 17, 2, 29, 6, 254,
  27, 7, 18, 2, 27, 8, 254,
  26, 7, 21, 2, 24, 8, 254,
  26, 7, 22, 2, 22, 8, 254,
  25, 7, 24, 2, 20, 8, 254,
  25, 7, 25, 2, 18, 8, 254,
  25, 6, 27, 2, 16, 8, 254,
  25, 6, 28, 2, 14, 8, 254,
  25, 6, 29, 22, 254,
  26, 6, 29, 20, 254,
  27, 6, 29, 18, 254,
  28, 6, 29, 16, 254,
  254,
  255 };

 /*
  * "3"
  */
 static char c__070[] = {
  254,
  254,
  35, 1, 45, 1, 254,
  34, 4, 43, 2, 254,
  33, 7, 41, 3, 254,
  32, 8, 41, 4, 254,
  31, 8, 19, 1, 22, 5, 254,
  30, 8, 19, 3, 21, 6, 254,
  29, 8, 19, 5, 20, 7, 254,
  28, 8, 19, 7, 19, 8, 254,
  27, 8, 19, 9, 18, 8, 254,
  26, 8, 19, 8, 1, 2, 17, 8, 254,
  25, 8, 19, 8, 3, 2, 16, 8, 254,
  26, 6, 19, 8, 5, 2, 15, 8, 254,
  27, 4, 19, 8, 7, 2, 14, 8, 254,
  28, 2, 19, 8, 9, 2, 13, 8, 254,
  29, 2, 17, 8, 11, 2, 11, 9, 254,
  30, 25, 13, 21, 254,
  31, 23, 15, 19, 254,
  32, 21, 17, 17, 254,
  33, 19, 19, 15, 254,
  254,
  255 };

 /*
  * "4"
  */
 static char c__071[] = {
  254,
  254,
  54, 1, 254,
  54, 3, 254,
  54, 5, 254,
  55, 6, 254,
  55, 8, 254,
  55, 10, 254,
  56, 7, 1, 3, 254,
  56, 7, 3, 3, 254,
  56, 7, 5, 3, 254,
  57, 7, 6, 3, 254,
  57, 7, 8, 3, 254,
  57, 7, 10, 3, 254,
  57, 7, 12, 3, 254,
  56, 7, 15, 3, 254,
  29, 1, 25, 8, 17, 3, 254,
  28, 3, 24, 7, 20, 3, 254,
  27, 60, 254,
  26, 63, 254,
  25, 64, 254,
  26, 63, 254,
  27, 62, 254,
  28, 3, 24, 7, 254,
  29, 1, 27, 5, 254,
  254,
  255 };

 /*
  * "5"
  */
 static char c__072[] = {
  254,
  254,
  35, 1, 15, 38, 254,
  34, 4, 14, 36, 254,
  33, 7, 13, 8, 20, 6, 254,
  32, 8, 14, 8, 18, 7, 254,
  31, 8, 16, 8, 16, 7, 254,
  30, 8, 18, 8, 15, 7, 254,
  29, 8, 20, 8, 14, 6, 254,
  28, 8, 22, 8, 12, 7, 254,
  27, 8, 24, 8, 11, 7, 254,
  26, 8, 26, 8, 10, 7, 254,
  25, 8, 28, 8, 9, 7, 254,
  26, 6, 28, 8, 10, 7, 254,
  27, 4, 28, 8, 11, 7, 254,
  28, 2, 28, 8, 13, 6, 254,
  29, 2, 26, 8, 14, 6, 254,
  30, 34, 16, 6, 254,
  31, 32, 17, 6, 254,
  32, 30, 21, 4, 254,
  33, 28, 24, 3, 254,
  254,
  255 };

 /*
  * "6"
  */
 static char c__073[] = {
  254,
  254,
  35, 44, 254,
  34, 46, 254,
  33, 48, 254,
  32, 50, 254,
  31, 52, 254,
  30, 8, 25, 2, 17, 2, 254,
  29, 8, 27, 2, 17, 2, 254,
  28, 8, 29, 2, 17, 2, 254,
  27, 8, 31, 2, 15, 4, 254,
  26, 8, 31, 4, 13, 6, 254,
  25, 8, 31, 6, 11, 8, 254,
  26, 6, 31, 8, 9, 8, 254,
  27, 4, 31, 9, 8, 8, 254,
  28, 2, 31, 8, 9, 8, 254,
  29, 2, 29, 8, 9, 8, 254,
  30, 37, 9, 8, 254,
  31, 35, 9, 8, 254,
  32, 33, 10, 7, 254,
  33, 31, 13, 4, 254,
  254,
  255 };

 /*
  * "7"
  */
 static char c__074[] = {
  254,
  254,
  25, 2, 54, 1, 254,
  26, 2, 53, 3, 254,
  27, 2, 52, 5, 254,
  28, 5, 48, 7, 254,
  29, 12, 40, 8, 254,
  30, 19, 32, 7, 254,
  31, 23, 27, 7, 254,
  32, 29, 20, 6, 254,
  33, 31, 17, 6, 254,
  34, 2, 10, 21, 15, 5, 254,
  35, 2, 16, 17, 12, 5, 254,
  36, 2, 21, 14, 9, 5, 254,
  64, 11, 8, 4, 254,
  69, 9, 5, 4, 254,
  73, 7, 4, 4, 254,
  76, 6, 2, 4, 254,
  79, 9, 254,
  83, 5, 254,
  86, 3, 254,
  254,
  255 };

 /*
  * "8"
  */
 static char c__075[] = {
  254,
  254,
  34, 16, 13, 16, 254,
  33, 19, 10, 18, 254,
  32, 22, 7, 20, 254,
  31, 24, 5, 22, 254,
  30, 26, 3, 24, 254,
  29, 8, 17, 3, 1, 8, 16, 2, 254,
  28, 8, 20, 9, 18, 2, 254,
  27, 8, 21, 8, 20, 2, 254,
  26, 8, 21, 8, 20, 4, 254,
  25, 8, 21, 8, 20, 6, 254,
  26, 6, 21, 8, 20, 8, 254,
  27, 4, 21, 8, 20, 8, 254,
  28, 2, 21, 8, 20, 8, 254,
  29, 2, 19, 9, 19, 8, 254,
  30, 2, 17, 8, 1, 3, 16, 8, 254,
  31, 25, 3, 25, 254,
  32, 23, 5, 23, 254,
  33, 21, 7, 21, 254,
  34, 19, 10, 18, 254,
  254,
  255 };

 /*
  * "9"
  */
 static char c__076[] = {
  254,
  254,
  34, 1, 20, 25, 254,
  33, 4, 17, 27, 254,
  32, 7, 14, 29, 254,
  31, 8, 13, 31, 254,
  30, 8, 13, 33, 254,
  29, 8, 13, 8, 25, 2, 254,
  28, 8, 13, 8, 27, 2, 254,
  27, 8, 13, 8, 27, 4, 254,
  26, 8, 13, 8, 27, 6, 254,
  25, 8, 15, 6, 27, 8, 254,
  26, 6, 17, 4, 27, 8, 254,
  27, 4, 19, 2, 27, 8, 254,
  28, 2, 21, 2, 25, 8, 254,
  29, 2, 21, 2, 23, 8, 254,
  30, 2, 21, 2, 21, 8, 254,
  31, 52, 254,
  32, 50, 254,
  33, 48, 254,
  34, 46, 254,
  35, 44, 254,
  254,
  255 };

 /*
  * ""
  */
 static char c__077[] = {
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  254,
  255 };
 char *gottab[] = {

 c__077, c__077, c__077, c__077, c__077, c__077, c__077, c__077,
 c__077, c__077, c__077, c__077, c__077, c__077, c__077, c__077,
 c__077, c__077, c__077, c__077, c__077, c__077, c__077, c__077,
 c__077, c__077, c__077, c__077, c__077, c__077, c__077, c__077,
 c__077, c__005, c__014, c__001, c__006, c__077, c__077, c__013,
 c__003, c__007, c__077, c__077, c__010, c__009, c__002, c__077,
 c__067, c__068, c__069, c__070, c__071, c__072, c__073, c__074,
 c__075, c__076, c__012, c__008, c__077, c__077, c__077, c__011,
 c__004, c__041, c__042, c__043, c__044, c__045, c__046, c__047,
 c__048, c__049, c__050, c__051, c__052, c__053, c__054, c__055,
 c__056, c__057, c__058, c__059, c__060, c__061, c__062, c__063,
 c__064, c__065, c__066, c__077, c__077, c__077, c__077, c__077,
 c__077, c__015, c__016, c__017, c__018, c__019, c__020, c__021,
 c__022, c__023, c__024, c__025, c__026, c__027, c__028, c__029,
 c__030, c__031, c__032, c__033, c__034, c__035, c__036, c__037,
 c__038, c__039, c__040, c__077, c__077, c__077, c__077, c__077

 };



 GRAPH88.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\GRAPH88.C

 /*
 ** BYTE Small-C Graphics Display Benchmark
 ** Version 1 for 8088/8086/80286 PC Machines
 ** March, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Operation:
 ** 1. Prompt for which mode the user wants to test.
 ** 2. Save current graphics mode, flip to new mode.
 ** 3. Calculate center of screen based on new mode.
 ** 4. Turn on timer.
 ** 5. Draw an initial circle of radius 20.
 ** 6. Draw NUMCIRC circles, performing flood fill of doughnut
 **    area formed for each circle.
 ** 7. Turn off stopwatch.
 ** 8. Flip back to original mode.
 ** 9. Report results and exit.
 **
 */

 #include stdio.h

 NUMCIRC 7        /* Number of circles to draw */

 int tblock[4];                /* Timer block */
 int vblock[3];                /* Video block */
 int mode;                /* Global variable for mode */
 int esseg;                /* ES register */

 extern svmode();
 extern gvmode();
 extern setp();

 main()
 {
         int cx,cy;        /* Center of screen */
         int color;        /* color */
         int i,radius;
 int j;
 /*
 ** Save current video mode
 */
         gvmode(vblock);
 /*
 ** Prompt for new mode
 */
         printf("BYTE Graphics Benchmark\n");
         printf("What video mode?\n");
         printf("(Enter 255 for Hercules Monochrome):");
         fscanf(stdin,"%d",&mode);
 /*
 ** Verify valid mode
 */
         switch(mode) {

         case 4:
         case 5:
         case 6:
         case 13:
         case 14:
         case 15:
         case 16:
         case 17:
         case 18:
         case 19:
         case 255: break;
         default: {
           printf("Not a valid mode\n");
           exit(0);
         }
         }
 /*
 ** Set the new video mode
 */
         svmode(mode);
 /*
 ** Set up foreground colors and cx,cy based on mode
 */

         switch(mode) {
           case 4:
           case 5:  cx=160;
                    cy=100;
                    color=3;        /* Set to white */
                    esseg=-18432; /* b800h for es */
                    if(mode==4) setcga4(); /* Set the color palettes */
                    break;

           case 6:  cx=320;
                    cy=100;
                    color=1;        /* Set to white */
                    esseg=-18432; /* b800h for es */
                    setcga6(15); /* Set color palette */
                    break;

           case 13: cx=160;
                    cy=100;
                    color=7;        /* Set to white */
                    esseg=-24576; /* a000h for es */
                    break;

           case 14: cx=320;
                    cy=100;
                    color=15;        /* Set to white */
                    esseg=-24576; /* a000h for es */
                    break;

           case 15: cx=320;
                    cy=175;
                    color=1;
                    esseg=-24576; /* a000h for es */
                    break;

           case 16: cx=320;
                    cy=175;
                    color=7;        /* Mid-intensity white */
                    esseg=-24576; /* a000h for es */
                    break;

           case 17:
           case 18: cx=320;
                    cy=240;
                    color=1;        /* Whatever */
                    esseg=-24576;  /* a000h for es */
                    break;

           case 19: cx=160;
                    cy=100;
                    color=15;        /* CGA default white */
                    esseg=-24576; /* a000h for es */
                    break;
            case 255: cx=360;        /* Hercules */
                      cy=174;
                      color=1;
                      esseg=-20480; /* b000h for es */
                      break;
         }
 /*
 ** Set the ES register
 */
 #asm
         MOV        AX,_ESSEG
         MOV        ES,AX
 #endasm
 /*
 ** Start the timer
 */
         gtime(tblock);
 /*
 ** Draw a circle of radius 20
 */
         radius=20;
         circ(cx,cy,radius,color);

 /*
 ** Alternately draw new circles of radius 30,40,50,60,70, 80 and 90,
 ** and flood the region in between.
 */
         for(i=0;i<NUMCIRC;++i) {
           radius+=10;
           circ(cx,cy,radius,color);
           flood(cx+radius-5,cy,color);
         }
 /*
 ** Shut off timer
 */
         calctim(tblock);

 /*
 ** Flip back to original mode
 */
         svmode(vblock[0]);

 /*
 ** End of test -- report results
 */
         printf("Elapsed time (HH:MM:SS:1/100ths)\n");
         printf("%d:%d:%d:%d\n",tblock[0],tblock[1],tblock[2],tblock[3]);

         exit(0);
 }

 /*
 ** Set cga palette for mode 4
 */
 setcga4()
 {
 #asm
         MOV        AH,0BH
         MOV        BX,257
         INT        10H                ;Select cyan-violet-white
 #endasm
 }
 /*
 ** Set cga palette for mode 6
 */
 setcga6(color)  int color;
 {
 #asm
         MOV        AH,0BH
         MOV        BP,SP
         MOV        BL,2[BP]
         MOV        BH,0
         INT        10H
 #endasm
 }

 /*
 ** Draw a circle of color, radius r.  Centered at cx,cy.
 ** Note that we assume (ha!) square pixels and global variable
 ** mode is set.
 ** This routine uses an algorithm given by David Troendle
 ** in the May-June 1984 issue of Sextant Magazine
 */
 circ(cx,cy,r,color)
 int cx,cy,r,color;
 {
         int x,y,dv;
 int ch;
 /*
 ** Do initial 4 corners
 */
         setp(cx+r,cy,color,mode);
         setp(cx,cy+r,color,mode);
         setp(cx-r,cy,color,mode);
         setp(cx,cy-r,color,mode);
 /*
 ** Do arc from 0 to 45 degrees
 */
         x=r;
         y=0;
         dv=0;
         do {
           dv=dv+y+y+1;        /* Deviation change due to y */
           y+=1;
           if (dv>x) {
                     dv=dv-x-x+1;        /* Reduce deviation */
                   x-=1;
                   }
 /*
 ** Now do reflections
 */
           setp(cx+x,cy+y,color,mode);
           setp(cx-x,cy+y,color,mode);
           setp(cx+x,cy-y,color,mode);
           setp(cx-x,cy-y,color,mode);
           if(x!=y) {
             setp(cx+y,cy+x,color,mode);
             setp(cx-y,cy+x,color,mode);
             setp(cx+y,cy-x,color,mode);
             setp(cx-y,cy-x,color,mode);
           }
         } while (y<x);
    return 0;
 }

 /*
 ** flood(sx,sy,color)
 ** Flood a region with color, starting at sx,sy.
 ** This is a fill until ... it fills until it encounters
 ** color.
 ** NOTE: This routine assumes that global variable mode is
 ** set, and the ES register is loaded with the proper value.
 ** Also...this version does not check for hitting the edge of
 ** the screen.  So your region BETTER be closed.
 */
 flood(sx,sy,color)
 int sx,sy,color;
 {
         setp(sx,sy,color,mode);
         if(getp(sx+1,sy,mode)!=color) flood(sx+1,sy,color);
         if(getp(sx-1,sy,mode)!=color) flood(sx-1,sy,color);
         if(getp(sx,sy+1,mode)!=color) flood(sx,sy+1,color);
         if(getp(sx,sy-1,mode)!=color) flood(sx,sy-1,color);
         return;
 }



 GRDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\GRAPH\GRDEMO.C

 /*--------------------------------------------------------------------
  *                                grdemo.c
  *
  *         illustrates the use of the graphic functions in graph.lib
  *
  *                     copyright 1987 by Michael Allen
  *
  *
  *--------------------------------------------------------------------*/

 #include <stdio.h>
 #include <stdlib.h>
 #include <dos.h>
 #include "glob_defs.h"
 #include "global.h"
 #include "graph.h"

 void
 p(int x, int y, char *item)
 {
   gotoxy(x, y);
   puts(item);
 }

 main()
 {
    register int x, y, i;

    hires();
    hirescolor(WHITE);

    p(20,8,"testing plot...");
    for (i=0;i < 1500;i++)
       plot(rand() % xmax, rand() % ymax);
    getchar();

    p(20,10,"testing draw_line...");
    for (i=0,x = 20;x < 220;x+=6,i++)
       draw_line(x, 1, x+150+i, 190);
    getchar();
    clearscreen();

    hirescolor(BLUE);
    p(20,12,"testing draw_box...");
    for (i=0,y = 10,x = 10;x < 350;x+=4,y+=2,i+=2)
       draw_box(x, y, x+50+i, y+25);
    getchar();
    clearscreen();

    hirescolor(GREEN);
    p(20,13,"testing draw_circle...");
    for (y = 10,x = 320;y < 100;y+=2)
       draw_circle(320,100, x, y);
    getchar();
    clearscreen();

    hirescolor(YELLOW);
    p(20,14,"testing draw_ellipse...");
    for (i = 0,y = 20,x = 150;x < 300;x+=4,y+=2,i+=2)
       lips(x,y,x+150,y+20+i);
    getchar();

    hirescolor(CYAN);
    p(20,16,"draw boxes with xor_mode...");
    draw_option = XOR_MODE;
    for (y = 0,x = 150;x < 500;x+=2,y++)
    {
       draw_box(x, y, x + 48, y + 24);
            for (i = 0;i < 1000;i++);         /* pause */
       draw_box(x, y, x + 48, y + 24);
    }
    draw_option = NORMAL;
    draw_box(x, y, x + 48, y + 24);

    getchar();

    textmode();

 }


 GR_DEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\HSA_TC\GR_DEMO.C

 /************************************************************************/
 /*
 /*                                   G R _ D E M O . C - Demo of HSA_GRAF
 /*
 /************************************************************************/

 /************************************************************************/
 /*
 /*                          Copyright (c) Hardwood Software Associates 1987
 /*
 /*                                           Hardwood Software Associates
 /*                                                          364 Benson Road
 /*                                                   Northbridge, Ma 01534
 /*
 /************************************************************************/

 /************************************************************************
  *                        G R _ D E M O . C    E D I T    L O G
  *
  *        Edit        Date        Person                Modification
  *        ----        ----        ------                ------------
  *
  ************************************************************************/

 /************************************************************************
  *
  *        Author: R. Evans
  *        Date:        July, 1987
  *
  ************** GR_DEMO - Demo of HSA_GRAF
  * SYNOPSIS:
  *                                gr_demo
  * DESCRIPTION:
  *                                Demo some of the important aspects of the H
  *
  ************************************************************************/
 #include "stdio.h"
 #include "hsa_gr.h"
 #include "ctype.h"

 #define FALSE        0
 #define TRUE        1
 #define BUFFER_SIZE        16384
 #define XC        3000
 #define YC        2500
 #define XC1 6500
 #define ARCS        8
 #define Y_TEXT        210

 int crt_type;
 int buffer [BUFFER_SIZE];
 unsigned _STACK=0x6800;

 main ()
 {
 crt_type = initialize ();
 g_origin (1);
 do_circle ();
 if (crt_type != EGA)                                                        /
         g_save (buffer,BUFFER_SIZE);
 do_square ();
 if (crt_type != EGA)                                                        /
         {
         g_restore (buffer,BUFFER_SIZE);
         getch ();
         }
 bye ();
 } /* Of gr_demo */

 /************************************************************************/
 /*
 /*                   C L E A R _ S C R E E N - Clear Screen and Draw Logo
 /*
 /************************************************************************/

 void clear_screen ()
 {
 g_clr ();
 g_fore_color (SCR_CYAN);
 hsa_logo (10,4000,1300,SCR_CYAN);                                /* Draw HSA
 g_fore_color (SCR_WHITE);
 } /* Of clear_screen */

 /************************************************************************/
 /*
 /*                                          D O _ S Q U A R E - Mazy Square
 /*
 /************************************************************************/
 #define WIDTH        250
 #define SIZE        3500
 do_square ()
 {
 int x=2000;
 int y=WIDTH;
 register int yy;
 register int size=SIZE;
 int i;

 clear_screen ();
 yy=5000;
 gs_str_h (6000,yy-=Y_TEXT,"This demo is only a");
 gs_str_h (6000,yy-=Y_TEXT,"very small example");
 gs_str_h (6000,yy-=Y_TEXT,"of what can be done");
 gs_str_h (6000,yy-=Y_TEXT,"using HSA_GRAF.");

 gs_point (x,y);
 while (size > 4*WIDTH)
         {
         gs_line (-1,-1,-1,y+=size);
         size -= WIDTH;
         gs_line (-1,-1,x+=size,-1);
         size -= WIDTH;
         gs_line (-1,-1,-1,y-=size);
         size -= WIDTH;
         gs_line (-1,-1,x-=size,-1);
         size -= WIDTH;
         }
 size += (2*WIDTH);
 gs_line (-1,-1,-1,y-=WIDTH);
 i=2;
 while (size < SIZE)
         {
         gs_line (-1,-1,x+=size,-1);
         size += (i*WIDTH);
         i=1;
         gs_line (-1,-1,-1,y+=size);
         size += WIDTH;
         gs_line (-1,-1,x-=size,-1);
         size += WIDTH;
         if (size > SIZE+WIDTH)
                 size = SIZE + WIDTH;
         gs_line (-1,-1,-1,y-=size);
         size += WIDTH;
         }
 gs_line (-1,-1,x+WIDTH,-1);
 g_loc (&x,&y);
 g_fill (x-1,y+1,SCR_RED);
 pause ("");
 } /* Of do_square */

 /************************************************************************/
 /*
 /*                                   D O _ C I R C L E - Draw Some Circles
 /*
 /************************************************************************/
 do_circle ()
 {
 int x1;
 int x,y;
 int color = 1;
 int i;

 clear_screen ();
 y=5000;
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"HSA_GRAF has a single");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"simple function that");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"will draw full or");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"partial circles quickly");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"and accurately.");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"Another function will");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"fill an enclosed");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"boundary with a");
 gs_str_h (XC+8*(XC/10),y-=Y_TEXT,"specified color");

 for (x1=XC-WIDTH;x1>2*WIDTH;x1-=WIDTH)
         {
         g_fore_color (SCR_WHITE);
         gs_arc (x1,YC,x1,YC,XC,YC,1);
         g_loc (&x,&y);
         g_fore_color (color);
         g_fill (x+1,y+1,color);
         if (crt_type != EGA)
                 color = !color;
         else
                 color++;
         }
 gs_line (XC1-ARCS*WIDTH/2,YC,XC1+ARCS*WIDTH/2,YC);
 for (x1=XC1-WIDTH/2,i=0;i<ARCS;x1-=(WIDTH/2),i++)
         {
         g_fore_color (SCR_WHITE);
         gs_arc (x1,YC,x1+2*(i+1)*(WIDTH/2),YC,XC1,YC,0);
         g_loc (&x,&y);
         g_fore_color (color);
         g_fill (x-2,y-1,color);
         if (crt_type != EGA)
                 color = !color;
         else
                 color++;
         }
 g_fore_color (SCR_WHITE);
 pause ("");
 } /* Of do_circle */

 /************************************************************************/
 /*
 /*                        I N I T I A L I Z E - Initialize for Graphics Demo
 /*
 /************************************************************************/

 initialize ()
 {
 int crt_type;
 int x,y;
 int s,seg;
 short mode;
 short xdots,ydots;
 char buffer[80];

 for (;;)
         {
         printf ("\n\nHSA_GRAF -  Graphics Library Demonstration\n\n");
         printf ("Select graphics adapter for demonstration:\n\n");
         printf ("\t1. Hercules Monochrome\n");
         printf ("\t2. Color Graphics Adapter (CGA)\n");
         printf ("\t3. Extended Graphics Adapter (EGA)\n");
         printf ("\t4. Other brand of graphics adapter\n");
         printf ("\t9. Quit\n\n");
         printf ("Enter selection: ");
         gets (buffer);
         sscanf (buffer,"%d",&crt_type);
         if (crt_type == 9)
                 exit (0);
         if (crt_type < 1 || crt_type > 4)
                 continue;
         switch (crt_type)
                 {
         case 1:
                 crt_type = MONOCHROME;
                 g_page (1);
                 break;
         case 2:
                 crt_type = CGA;
                 g_cga_hr ();
                 break;
         case 3:
                 crt_type = EGA;
                 g_ega_hr_co ();
                 break;
         case 4:
                 crt_type = CGA;
                 printf ("Enter X,Y pixels: ");
                 scanf ("%d,%d",&x,&y);
                 printf ("Enter scans, segment: ");
                 scanf ("%d,%x",&s,&seg);
                 printf ("Enter X,Y dots per inch <640x200 = 80,37>: ");
                 gets (buffer);
                 if (strlen (buffer) > 0)
                         sscanf (buffer,"%d,%d",&xdots,&ydots);
                 else
                         {
                         xdots = 80;
                         ydots = 37;
                         }
                 printf ("Enter graphics mode function call <IBM = 6>: ");
                 gets (buffer);
                 if (strlen (buffer) > 0)
                         sscanf (buffer,"%d",&mode);
                 else
                         mode = 6;
                 g_other (x,y,s,seg,mode);
                 g_scale (x,y);
                 break;
                 }
         break;
         }
 printf ("Press any key to switch to graphics mode."); getch ();
 g_page(1);
 g_clr();
 disp_graph();
 return (crt_type);

 } /* Of initialize */
 /************************************************************************/
 /*
 /*                                           B Y E - All Done with GR_DEMO
 /*
 /************************************************************************/

 bye ()
 {
 disp_text(3);
 printf("All done\n");
 exit(0);
 } /* Of bye */

 /************************************************************************/
 /*
 /*                                        P A U S E - Wait for User Reaction
 /*
 /************************************************************************/

 pause (type)
 char *type;
 {
 int answer;

 g_str_h (0,10,type);
 g_str_h (-1,-1,"Press any key to continue, \"Q\" to quit.");
 answer = getch ();
 if (toupper (answer) == 'Q')
         bye ();
 } /* Of pause */




 GTOD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\GTOD.C

 /*
 **                GET TIME OF DAY UTILITY
 **
 ** S.E. Margison  Copyright 1986  All rights reserved
 ** 9-18-86 A  V1.01  Datalight C
 **
 **  Options default to date, time, 12 hour format, no seconds, American
 **          style reporting.  Either - or / used for options, or none.
 **  -d   report (D)ate only
 **  -t   report (T)ime only
 **  -s   report (S)econds (only if -t option used)
 **  -l   Report date in (L)ong format
 **  -n   Include the (N)ame of the weekday, if -l format
 **  -m   report time in (M)ilitary format (12 hour format if not used)
 **  -e   report date in (E)uropean format
 **  -r   for time and date reporting, (R)everse order to time first
 **  If any options are used, no default values are assumed.
 **  No options is the same as -dt
 **
 **   As distributed, this program requires (for compilation):
 **     "Steve's Datalight Library" version 1.10 or later
 **   which may be obtained without registration from many Bulletin
 **   Board Systems including:
 **      Compuserve IBMSW
 **      Cul-De-Sac (Holliston, MA.)
 **      HAL-PC BBS (Houston, TX.)
 **   and software library houses including:
 **      Public (Software) Library (Houston, TX.)
 **
 **   or by registration:
 **      $10 for Docs, Small Model Library
 **      $25 for Docs, S, D, L, P libraries, and complete library source
 **              in C and Assembler
 **     Steven E. Margison
 **     124 Sixth Street
 **     Downers Grove, IL, 60515
 **
 */

 #include <stdio.h>
 #include <time.h>
 #include <smdefs.h>

 int nf, tf, df, sf, mf, rf, ef, lf;   /* option flags */

 char datestr[64],   /* place for formatted date string */
      timestr[16];   /* place for formatted time sring */

 extern char *wkdayname();
 extern char *monthis();

 struct tm *ptm;
 long clockval;

 main(argc, argv)
 int argc;
 char *argv[];
 {

     /* first thing to do is read the clock! */

    clockval = time(0);
    ptm = localtime(&clockval);

    doargs(argc, argv);  /* parse any options */

    if(!tf && !df) tf = df = YES;

    if(!tf) timestr[0] = NULL;   /* skip the time */
    else mktime();

    if(!df) datestr[0] = NULL;   /* skip the date */
    else mkdate();

    if(!rf) printf("%s  %s\n", datestr, timestr);
    else printf("%s  %s\n", timestr, datestr);
 }

 doargs(argc, argv)
 int argc;
 char *argv[];
 {
    int i;
    nf = tf = df = sf = mf = rf = ef = lf = NO;
    while(--argc > 0) {
       i = 0;
       while(argv[argc][i] != NULL) {
          switch(tolower(argv[argc][i++])) {
             case '-': case '/':
                break;
             case 'n':
                nf = YES;
                break;
             case 'd':
                df = YES;
                break;
             case 't':
                tf = YES;
                break;
             case 's':
                sf = YES;
                break;
             case 'm':
                mf = YES;
                break;
             case 'r':
                rf = YES;
                break;
             case 'e':
                ef = YES;
                break;
             case 'l':
                lf = YES;
                break;
             case 'v':
                fputs("GTOD Version 1.02\n", stderr);
                fputs("GTOD ? for usage message\n", stderr);
                error("Copyright 1986 S.E. Margison");
             case '?':
                usage();
             default:
                fputc(argv[argc][--i], stderr);
                error(": invalid option");
             }  /* end of switch */
          } /* end of inner while */
       }  /* end of outer while */
    }

 mkdate()
 {
    int i, mpos, dpos;
    char *mstr, dstr[6];
    mpos = 0;
    dpos = 3;
    if(lf) {
       dstr[0] = (ptm->tm_mday / 10) | '0';
       if(dstr[0] == '0') dstr[0] = ' ';
       dstr[1] = (ptm->tm_mday % 10) | '0';
       dstr[2] = NULL;
       if(nf) {
          i = weekday(ptm->tm_mon+1, ptm->tm_mday, ptm->tm_year+1900);
          mstr = wkdayname(i);
          strcpy(datestr, mstr);
          strcat(datestr, ", ");
          }
       mstr = monthis(ptm->tm_mon);
       if(ef) {
          strcat(datestr, dstr);
          strcat(datestr, " ");
          strcat(datestr, mstr);
          }
       else {
          strcat(datestr, mstr);
          strcat(datestr, " ");
          strcat(datestr, dstr);
          }
       strcat(datestr, ", ");
       i_dstr(dstr, ptm->tm_year+1900);
       strcat(datestr, dstr);
       return;
       }

    if(ef) { mpos = 3; dpos = 0; }

    ptm->tm_mon++;      /* Datalight calls month 0 = January */
    datestr[mpos++] = (ptm->tm_mon / 10) | '0';
    datestr[mpos] = (ptm->tm_mon % 10) | '0';
    datestr[2] = datestr[5] = '/';
    datestr[dpos++] = (ptm->tm_mday / 10) | '0';
    datestr[dpos] = (ptm->tm_mday % 10) | '0';
    i = ptm->tm_year;
    if(i > 100) i -= 100;
    datestr[6] = (i / 10) | '0';
    datestr[7] = (i % 10) | '0';
    datestr[8] = NULL;
    }

 mktime()
 {
    int hrs, eos;
    timestr[2] = ':';
    timestr[3] = (ptm->tm_min / 10) | '0';
    timestr[4] = (ptm->tm_min % 10) | '0';
    if(sf) {
       timestr[5] = ':';
       timestr[6] = (ptm->tm_sec / 10) | '0';
       timestr[7] = (ptm->tm_sec % 10) | '0';
       eos = 8;
       }
    else eos = 5;
    if(mf) {
       timestr[0] = (ptm->tm_hour / 10) | '0';
       timestr[1] = (ptm->tm_hour % 10) | '0';
       timestr[eos] = NULL;
       }
    else {
       timestr[eos++] = ' ';
       timestr[eos] = 'A';

       if(ptm->tm_hour >= 12) timestr[eos] = 'P';  /* set PM */

       if(ptm->tm_hour > 12) hrs = ptm->tm_hour - 12;
       else if(ptm->tm_hour == 0) hrs = 12;   /* midnight = 12AM */
       else hrs = ptm->tm_hour;

       timestr[++eos] = 'M';
       timestr[++eos] = NULL;
       timestr[0] = (hrs / 10) | '0';
       timestr[1] = (hrs % 10) | '0';
       if(timestr[0] == '0') timestr[0] = ' ';
       }
    }

 usage() {
 puts("GTOD <options> or <-options> or </options>");
 puts("redirect stdout as desired");
 puts("d   report (D)ate only");
 puts("t   report (T)ime only");
 puts("s   report (S)econds (only if time is enabled)");
 puts("l   Report date in (L)ong format  (September 10, 1986)");
 puts("n   Include the (N)ame of the weekday, if -l format");
 puts("m   report time in (M)ilitary format (else, 12 hour format with AM/PM)"
 puts("e   report date in (E)uropean format  (DD/MM/YY)");
 puts("r   for time and date reporting, (R)everse order to time first");
 puts("    No options is the same as -dt:  MM/DD/YY hh:mm");
 puts("v   Version, Serial No., Copyright message");
 puts("?   You know this one already!");
 aabort(BELL);
    }



 GTOJ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\GTOJ.C

 /*                   *** gtoj.c ***                                  */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* integer function that returns the julian date (1 = 1st day AD)    */
 /* associated with a gregorian date in the form mm/dd/yy.  Returns a */
 /* -1 if an error occured.                                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1983.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */
 /* Corrected bug in call to sscanf.  Lew Paper, 6/13/85              */
 /*                                                                   */
 /*********************************************************************/

 CENTRY 19        /* current century */

 long gtoj(indate)
 char indate[];
 {
         static int monthd[] = {31,28,31,30,31,30,31,31,30,31,30,31};
         int i;
         int leapd,iyr,imo,iday;
         static long cdays = 36524, ydays = 365;

         /* convert into expanded format if necessary */
         if ((cvtdate(indate)) != 0) return(-1);

         /* parse gregorian date into its pieces */
         sscanf(indate,"%2d%*1c%2d%*1c%2d",&imo,&iday,&iyr); /*Add &'s, L.P.*/

         /* adjust month array for leap year/non-leap year */
         if (iyr < 0 || iyr > 99) return(-1);
         if (iyr%4 == 0 && iyr != 0 || CENTRY%4 == 0)
                 monthd[1] = 29;
         else
                 monthd[1] = 28;

         /* check for invalid month */
         if (imo < 1 || imo > 12) return(-1);

         /* check for invalid day */
         if (iday < 1 || iday > monthd[imo-1]) return(-1);

         /* determine the number of "extra" leap years caused by the  */
         /* %400 criteria and add to it the number of leap years that */
         /* has occured up to the prior year of current century.      */
         leapd = CENTRY/4;
         if (iyr != 0) leapd += (iyr-1)/4;

         /* determine number of days elapsed in current year */
         for (i=0;i<(imo-1);i++)
                 iday = iday + monthd[i];

         /* calculate julian date */
         return (CENTRY*cdays + iyr*ydays + leapd + iday);
 }


 GTOJ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\GTOJ.C

 /*                   *** gtoj.c ***                                  */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* integer function that returns the julian date (1 = 1st day AD)    */
 /* associated with a gregorian date in the form mm/dd/yy.  Returns a */
 /* -1 if an error occured.                                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1983.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */
 /* Corrected bug in call to sscanf.  Lew Paper, 6/13/85              */
 /*                                                                   */
 /*********************************************************************/

 CENTRY 19        /* current century */

 long gtoj(indate)
 char indate[];
 {
         static int monthd[] = {31,28,31,30,31,30,31,31,30,31,30,31};
         int i;
         int leapd,iyr,imo,iday;
         static long cdays = 36524, ydays = 365;

         /* convert into expanded format if necessary */
         if ((cvtdate(indate)) != 0) return(-1);

         /* parse gregorian date into its pieces */
         sscanf(indate,"%2d%*1c%2d%*1c%2d",&imo,&iday,&iyr); /*Add &'s, L.P.*/

         /* adjust month array for leap year/non-leap year */
         if (iyr < 0 || iyr > 99) return(-1);
         if (iyr%4 == 0 && iyr != 0 || CENTRY%4 == 0)
                 monthd[1] = 29;
         else
                 monthd[1] = 28;

         /* check for invalid month */
         if (imo < 1 || imo > 12) return(-1);

         /* check for invalid day */
         if (iday < 1 || iday > monthd[imo-1]) return(-1);

         /* determine the number of "extra" leap years caused by the  */
         /* %400 criteria and add to it the number of leap years that */
         /* has occured up to the prior year of current century.      */
         leapd = CENTRY/4;
         if (iyr != 0) leapd += (iyr-1)/4;

         /* determine number of days elapsed in current year */
         for (i=0;i<(imo-1);i++)
                 iday = iday + monthd[i];

         /* calculate julian date */
         return (CENTRY*cdays + iyr*ydays + leapd + iday);
 }


 GTSCREEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGASAVE\GTSCREEN.C

 #include <graph.h>
 #include <stdio.h>
 #include <memory.h>
 #include <dos.h>
 #include <malloc.h>

 /*       error =  get_screen(filename);               */
 /*                                                    */
 /*       Routine for retrieving EGA screens           */
 /*       Used for 16 color 350x640 resolution         */
 /*       No packing or unpacking of image             */
 /*       Created for MSC V5.0  small model            */
 /*                                                    */
 /*       error of type int, returned as below         */
 /*       filename - array of type char, length 13     */
 /*       Routine uses a 28K buffer for fast retrieval */
 /*       if data segment space is at a premium,       */
 /*       could rewrite to use smaller buffers.        */
 /*                                                    */
 /*       If using a model with a large data space     */
 /*       then all data calls are far and no buffer is */
 /*       needed.  Use fread to write directly to      */
 /*       video memory.                                */
















 /* DEFINE A BUFFER TO HOLD ONE OF THE FOUR PLANES */

 unsigned char buffer[28000];





 get_screen (filename)

 char *filename;       /* filename passed, 12 character max */

 {
         int flag = 0; /* return integer flag     */
                       /* flag = 0  success       */
                       /* flag = 1  error opening */
                       /* flag = 2  error reading */


         struct SREGS segregs;    /* structure for segread call */

         FILE *screen_file;       /* image file */





         segread(&segregs);       /* get data segment for movedata below */

         _setvideomode(_ERESCOLOR);  /* set EGA 640x350 16 color mode */
                                     /* 128 K required */

         if (!(_setvideomode(_ERESCOLOR)))
             {
               flag = 3;
               return(flag);
             }

         if ((screen_file = fopen(filename,"rb")) != NULL)

               {

                  outp(0x3C4,2);        /* set color plane for read */
                  outp(0x3C5,0x01);
                  fread(buffer,1,28000,screen_file); /* read 1 plane */
                  movedata(segregs.ds,(unsigned int)buffer,0xA000,0x0000,28000

                  /* segregs.ds is data segment for variable "buffer"  */
                  /* buffer is the offset in that segment for "buffer" */
                  /* A0000000 is the far pointer to EGA video memory   */
                  /*          0xA000 = seg      0x0000 = offset        */
                  /* 28000 is the size of one 640x350 color plane      */


                                      /* repeat for the other three planes */
                  outp(0x3C4,2);
                  outp(0x3C5,0x02);
                  fread(buffer,1,28000,screen_file);
                  movedata(segregs.ds,(unsigned int)buffer,0xA000,0x0000,28000



                  outp(0x3C4,2);
                  outp(0x3C5,0x04);
                  fread(buffer,1,28000,screen_file);
                  movedata(segregs.ds,(unsigned int)buffer,0xA000,0x0000,28000





                  outp(0x3C4,2);
                  outp(0x3C5,0x08);
                  fread(buffer,1,28000,screen_file);
                  movedata(segregs.ds,(unsigned int)buffer,0xA000,0x0000,28000

            if (ferror(screen_file))      /* check for read error */
                  flag = 2;



         fclose(screen_file);

                }


         else
              flag = 1;    /* set flag if failed to open file */

        return(flag);

        }


 GT_301.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\GT_301.C

 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[0]>3010)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 GT_302.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\GT_302.C

 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[0]>=3020)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 HEAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\HEAD.C

 /*
         HEADER:                CUG236;
         TITLE:                List Head of Text Files;
         DATE:                04/04/1987;
         DESCRIPTION:        "Lists the first n lines of each of a list of fil
                         is variable as is the tab increment of the listing.";
         VERSION:        2.0;
         FILENAME:        HEAD.C;
         COMPILERS:        vanilla;
         AUTHORS:        W. C. Colley III, E. H. Mallory;
 */

 /*
         Utility to Print the First n Lines of a List of Files

         Based upon Eugene H. Mallory's HEAD.C (copyright 1983)

         Rewrite by William C. Colley, III -- 4 APR 1987

 The purpose of this rewrite is to get a portable version of HEAD.C as the
 original was coded in BDS C.  This involves some loss of functionality as the
 BDS C function wildexp() is irrevokably CP/M dependent.         The differenc

         1)  Wild-carded file names cannot be expanded unless the host operati
             system provides this facility as part of command-line argument
             passing.  UNIX does, MSDOS and CP/M do not.

         2)  I punted the sorting of the argument list.        This allows the
             options to apply to particular files.  Thus, if you want to see t
             first 10 lines of FOO.C and the first 20 lines of BAR.C, you can
             do it with the following command:

                 HEAD -L10 FOO.C -L20 BAR.C

         3)  The -H option has been dropped to simplify things.        If you
             the command HEAD with no arguments, you will still get the usage
             reminder.

         4)  Only the first WIDTH characters of a line are displayed.  The res
             are sent to the bit bucket.         The usual procedure would be
             WIDTH to the width of your terminal or printer.

         5)  Controllable tab expansion size has been added with the -T option
             Thus, you can expand FOO.C's tabs on 4-space intervals with the
             following command:

                 HEAD -T4 FOO.C

         6)  Bit 7 is stripped on all displayed characters so that WordStar
             images and the like don't generate funny graphics junk on some
             terminals.
 */

 #include <stdio.h>

 /*  Uncomment the following #define if you are using an AZTEC C compiler.  */

 /*
 #define getc(x)                agetc(x)
 */

 /*  User-adjustable default settings:

 WIDTH                79        /* Max length of line to display.        */
 HEADLEN                10        /* Default length of head to display.
 TABSIZE                8        /* Default tab size.                        *

 int main(argc,argv)
 int argc;
 char **argv;
 {
     char *bp, buf[WIDTH + 1];
     int i, j;
     FILE *f;
     static char opts[] = "[ -Lnn | -Tnn | <filename> ]";
     static int err = 0, headlen = HEADLEN, tabsize = TABSIZE;
     int atoi();

     if (argc < 2) {
         printf("Usage:\tHEAD %s %s*\n",opts,opts);
         err = !0;
     }
     else while (--argc) {
         if (**++argv == '-') {
             i = *(*argv + 1);
             switch (i) {
                 case 'l':
                 case 'L':   if ((i = atoi(*argv + 2)) < 1) {
                                 printf("ERROR:  Head length < 1\n\n");
                                 err = !0;
                             }
                             else headlen = i;
                             break;

                 case 't':
                 case 'T':   if ((i = atoi(*argv + 2)) < 1) {
                                 printf("ERROR:  Tab size < 1\n\n");
                                 err = !0;
                             }
                             else tabsize = i;
                             break;

                 default:    printf("ERROR:  Illegal option %s\n\n",*argv);
                             err = !0;  break;
             }
         }
         else {
             if (!(f = fopen(*argv,"r"))) {
                 printf("ERROR:  Cannot find file %s\n\n",*argv);
                 err = !0;
             }
             else {
                 printf("FILE:   %s\n\n",*argv);
                 for (i = headlen; i && !feof(f); --i) {
                     for (bp = buf; ; ) {
                         if ((j = getc(f)) == EOF || (j &= 0177) == '\n') brea
                         if (j == '\t')
                             while (bp < buf + WIDTH) {
                                 *bp++ = ' ';
                                 if (!((bp - buf) % tabsize)) break;
                             }
                         else if (bp < buf + WIDTH) *bp++ = j;
                     }
                     *bp = '\0';         printf("%s\n",buf);
                 }
                 printf("\n");  fclose(f);
             }
         }
     }
     return err;
 }


 HELLO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\WNDWBOSS\HELLO.C

 #include "windows.h"
 main()
 {
 WINDOWPTR w1;                   /* window handle */
 int batrib;                     /* border atrib */
 int watrib;                     /* window atrib */
 register i;

 /*
  * Set attributes:
  *
  *      border - blue/white box
  *      window - white background/black letters
  *
 */

   batrib = v_setatr(BLUE,WHITE,0,0);
   watrib = v_setatr(WHITE,BLACK,0,0);

 /*
  * Open window at 0,0 - 25 cells wide and 10 cells high
 */

   w1 = wn_open(0,0,0,25,10,watrib,batrib);
   if(!w1) exit();

 /*
  * Print the famous string and wait for key to be struck.
  * Close window on key strike.. exit.
 */

   wn_printf(w1,"Hello World...");
   v_getch();
   wn_close(w1);
 }

 /* End */



 HELP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\WNDWBOSS\HELP.C

 /*
 ** HELP - Help driver for The Window Boss
 **
 ** Copyright (c) 1985 - Philip A. Mongelluzzo
 ** All rights reserved.
 **
 ** Comments:
 **
 **  Help files must be formatted properly, use GENINDEX to create the index
 **  file.
 **
 */

 /* Header files */

 #include "windows.h"
 "math.h"                       /* needed for atol */

 /* Equates & definitions */

 MAXKEY 255                      /* ISAM file length (# of keys) */
 FALSE 0                         /* lies */
 TRUE ~FALSE                     /* Science */
 RD "rb"                         /* file access mode */

 K_PGUP 0x49                     /* a few scan codes */
 #define ESC    0x01

 CI86                                /* Compiler specific stuff */
 #define atol atoi
 #endif

 /* Function declarations */

 extern FILE *fopen();                   /* Stream I/O */
 extern char *malloc();                  /* memory mgmt */
 extern char *fgets();                   /* file line input */
 extern char *strcpy();                  /* string copy */
 extern char *strcat();                  /* concat function */
 extern long atol();                     /* ascii to integer */
 extern int fseek();                     /* DASD seek */
 extern long ftell();                    /* where are we DASD */

 static struct list {                    /* master list structure */
   char *key;                            /* pointer to %info string */
   long loc;                             /* file offset */
   int type;                             /* type <0=toc; 1=page; 2=menu> */
 } master[MAXKEY];                       /* master ISAM structure */

 static char *scrbuf[26];                /* screen buffer (array of ptrs) */
 static char line[80];                   /* line buffer */
 static int cpg, eoh;                    /* clear screen, end of help flags */
 static FILE *fp;                        /* stream file pointer */

 static WINDOWPTR wn1;                   /* window pointer */
 static int row, col;                    /* original cursor location */

 /*
 *************
 * help_init *
 *************
 */

 help_init(help_file_name)               /* init help function */
 char *help_file_name;
 {
   if(!help("@"))                        /* allocate the memory */
     return(FALSE);                      /* return if error */
   return(help(help_file_name));         /* setup help ISAM */
 }

 /*
 ********
 * help *
 ********
 */

 help(subject)                           /* help function */
 char *subject;                          /* help subject request */
 {
 char tmpname[30];                       /* temporary filename */
 char *p;                                /* scratch pointer */
 int i,j,k,l,m,n;                        /* scratch integers */
 int showpage();                         /* display page function */
 int showmenu();                         /* display menu function */
 static initflg = FALSE;                 /* init complete flag */

   switch(subject[0]) {                  /* on first char of subject ... */
     case '%':                           /* subject page */
       wn1 = wn_open(0, 0, 0, 78, 23, BLUE<<4 | WHITE, BLUE<<4 | WHITE);
       if(!wn1) return(FALSE);           /* error return */
       wn_wrap(wn1,FALSE);               /* no wrap thank you */
       v_rcpos(0, &row, &col);           /* remember current location */
       v_hidec();                        /* hide the physical cursor */
       wn_locate(wn1,0,0);               /* home virtual cursor */
       if(!initflg) return(FALSE);       /* illegal sequence of calls */
       i=0;                              /* start search index */
       while(i < MAXKEY) {               /* look for match in key table */
         if(!strcmp(subject,master[i].key)) {
           showpage(master[i].loc);      /* display all pages */
           return(TRUE);                 /* return .. all is well */
         }
         i++;
       }
       wn_printf(wn1," Sorry... No info on %s\n", subject);
       wn_printf(wn1," Press any key to continue...");
       v_getch();
       wn_close(wn1);
       return(FALSE);                    /* no match !! */
       break;
     case '$':                           /* menu page */
       break;                            /* sometime in the future */
     case '@':                           /* Initialize (allocate memory) */
       for(i=0; i<MAXKEY; i++) {
         master[i].key = malloc(25);     /* keys can be 25 chars long */
         if(!master[i].key) return(FALSE);
       }
       for(i=0; i<25; i++) {             /* allocate memory for screen */
         scrbuf[i] =  malloc(81);        /* buffer */
         if(!scrbuf[i]) return(FALSE);
       }
       initflg = TRUE;
       return(TRUE);
       break;
     default:                            /* assume help filename */
       if(!initflg) return(FALSE);       /* illegal sequence of calls */
       strcpy(tmpname,subject);          /* form filename from root */
       strcat(tmpname,".ndx");
       if(!(fp = fopen(tmpname,RD))) {   /* index file cant be found ! */
         printf("Can't find index file\n");
         printf("Press any key to continue...");
         v_getch();
         return(FALSE);
       }
       i = 0;                            /* read and process key file */
       while(fgets(line,80,fp)) {        /* build the master index table */
         strcpy(master[i].key, line);
         if(line[0] != '%')              /* ignore all but subects */
           continue;
         fgets(line,80,fp);
         master[i].loc = atol(line);
         i++;
       }
       fclose(fp);                       /* close index file */
       strcpy(tmpname, subject);         /* form help file name from root */
       strcat(tmpname, ".hlp");          /* open and leave open ! */
       if(!(fp = fopen(tmpname, RD))) return(FALSE);
       return(TRUE);
       break;
   }
 }

 /*
 ************
 * showpage *
 ************
 */

 static showpage(offset)                 /* display page function */
 long offset;
 {
 int i,j;                                /* scratch integers */
 long pages[MAXKEY];                     /* stack of pages */
 int pndx;                               /* stack pointer */
 int keyflg;                             /* vaild key flag */

   pndx = 0;                             /* init stack pointer */
   pages[0] = offset;                    /* initial page */

   while(TRUE) {                         /* till forever ... */
     i = filbuf(offset);                 /* fill the buffer */
     for(j=0; j<i; j++)                  /* display buffer */
       wn_puts(wn1,j,0,scrbuf[j]);
     wn1->style |= BOLD;                 /* toggle bold on */
     if(eoh)
       wn_puts(wn1, 22, 0, " End of help, PgUp for previous screen, any other
     else
       wn_puts(wn1, 22, 0, " Esc to quit help, PgUp for previous screen, any o
     wn1->style ^= BOLD;                 /* toggle bold off */
     keyflg = FALSE;                     /* valid key flag */
     do {                                /* loop till vaild key */
       switch (v_getch() >> 8) {         /* based on user input */
         case K_PGUP:                    /* do all the right things */
           pndx--;
           if(pndx <0) {
             wn_close(wn1);
             v_locate(0, row, col);
             return;
           }
           offset = pages[pndx];
           keyflg = TRUE;
           eoh = FALSE;                  /* force clear screen */
           cpg = TRUE;                   /* and cancel end of help flag */
           break;
         case ESC:
           wn_close(wn1);
           v_locate(0, row, col);
           return;
         default:
           offset = pages[++pndx] = ftell(fp);
           keyflg = TRUE;
           break;
       }
     } while (!keyflg);                  /* loop till valid key */
     if(cpg) wn_clr(wn1);
     if(eoh) {
       wn_close(wn1);
       v_locate(0, row, col);
       return;
     }
   }
 }

 /*
 **********
 * filbuf *
 **********
 */
 static filbuf(offset)                   /* fill screen buffer */
 long offset;
 {
 int i,j;
 char *p, *p1;

   i=0;                                  /* initialize */
   cpg = eoh = FALSE;                    /* assume nothing */
   fseek(fp, offset, 0);                 /* position file */
   do {
     fgets(line, 80, fp);                /* fetch a line */
       cpg = !strcmp(".cp\r\n", line);   /* lite clear screen and */
       eoh = !strcmp("*END*\r\n",line);  /* end of help flags */
       if(cpg || eoh) break;
       p = &line[0];                     /* a long way around to */
       p1 = scrbuf[i];                   /* filter the carriage */
       while (*p) {                      /* returns !! */
         switch (*p) {
           case '\r':
           case '\n':
             p++;
             break;
           default:
             *p1++ = *p++;
             break;
         }
       }
       *p1 = NULL;
       i++;
   } while (TRUE);
   return(i);                            /* return the # of lines on page */
 }

 /* End */


 HELP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\HELP.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 char        *Version = "STEVIE - Version 3.10";

 static        int        helprow;

 #ifdef        HELP

 #ifdef        MEGAMAX
 overlay "help"
 #endif

 static        void        longline();

 bool_t
 help()
 {

 /***********************************************************************
  * First Screen:   Positioning within file, Adjusting the Screen
  ***********************************************************************/

         outstr(T_ED);
         windgoto(helprow = 0, 0);

 longline("\
    Positioning within file\n\
    =======================\n\
       ^F             Forward screenfull             Original version by:\n\
       ^B             Backward screenfull                Tim Thompson\n");
 longline("\
       ^D             scroll down half screen\n\
       ^U             scroll up half screen          Extensive hacks by:\n");
 longline("\
       G              Goto line (end default)            Tony Andrews\n\
       ]]             next function\n\
       [[             previous function\n\
       /re            next occurence of regular expression 're'\n");
 longline("\
       ?re            prior occurence of regular expression 're'\n\
       n              repeat last / or ?\n\
       N              reverse last / or ?\n\
       %              find matching (, ), {, }, [, or ]\n");
 longline("\
 \n\
    Adjusting the screen\n\
    ====================\n\
       ^L             Redraw the screen\n\
       ^E             scroll window down 1 line\n\
       ^Y             scroll window up 1 line\n");
 longline("\
       z<RETURN>      redraw, current line at top\n\
       z-             ... at bottom\n\
       z.             ... at center\n");

         windgoto(0, 52);
         longline(Version);

         windgoto(helprow = Rows-2, 47);
         longline("<Press space bar to continue>\n");
         windgoto(helprow = Rows-1, 47);
         longline("<Any other key will quit>");

         if ( vgetc() != ' ' )
                 return TRUE;

 /***********************************************************************
  * Second Screen:   Character positioning
  ***********************************************************************/

         outstr(T_ED);
         windgoto(helprow = 0, 0);

 longline("\
    Character Positioning\n\
    =====================\n\
       ^              first non-white\n\
       0              beginning of line\n\
       $              end of line\n\
       h              backward\n");
 longline("\
       l              forward\n\
       ^H             same as h\n\
       space          same as l\n\
       fx             find 'x' forward\n");
 longline("\
       Fx             find 'x' backward\n\
       tx             upto 'x' forward\n\
       Tx             upto 'x' backward\n\
       ;              Repeat last f, F, t, or T\n");
 longline("\
       ,              inverse of ;\n\
       |              to specified column\n\
       %              find matching (, ), {, }, [, or ]\n");

         windgoto(helprow = Rows-2, 47);
         longline("<Press space bar to continue>\n");
         windgoto(helprow = Rows-1, 47);
         longline("<Any other key will quit>");

         if ( vgetc() != ' ' )
                 return TRUE;

 /***********************************************************************
  * Third Screen:   Line Positioning, Marking and Returning
  ***********************************************************************/

         outstr(T_ED);
         windgoto(helprow = 0, 0);

 longline("\
     Line Positioning\n\
     =====================\n\
     H           home window line\n\
     L           last window line\n\
     M           middle window line\n");
 longline("\
     +           next line, at first non-white\n\
     -           previous line, at first non-white\n\
     CR          return, same as +\n\
     j           next line, same column\n\
     k           previous line, same column\n");

 longline("\
 \n\
     Marking and Returning\n\
     =====================\n\
     ``          previous context\n\
     ''          ... at first non-white in line\n");
 longline("\
     mx          mark position with letter 'x'\n\
     `x          to mark 'x'\n\
     'x          ... at first non-white in line\n");

         windgoto(helprow = Rows-2, 47);
         longline("<Press space bar to continue>\n");
         windgoto(helprow = Rows-1, 47);
         longline("<Any other key will quit>");

         if ( vgetc() != ' ' )
                 return TRUE;
 /***********************************************************************
  * Fourth Screen:   Insert & Replace,
  ***********************************************************************/

         outstr(T_ED);
         windgoto(helprow = 0, 0);

 longline("\
     Insert and Replace\n\
     ==================\n\
     a           append after cursor\n\
     i           insert before cursor\n\
     A           append at end of line\n\
     I           insert before first non-blank\n");
 longline("\
     o           open line below\n\
     O           open line above\n\
     rx          replace single char with 'x'\n\
     R           replace characters (not yet)\n");

 longline("\
 \n\
     Words, sentences, paragraphs\n\
     ============================\n\
     w           word forward\n\
     b           back word\n\
     e           end of word\n\
     )           to next sentence (not yet)\n\
     }           to next paragraph (not yet)\n");
 longline("\
     (           back sentence (not yet)\n\
     {           back paragraph (not yet)\n\
     W           blank delimited word\n\
     B           back W\n\
     E           to end of W\n");

         windgoto(helprow = Rows-2, 47);
         longline("<Press space bar to continue>\n");
         windgoto(helprow = Rows-1, 47);
         longline("<Any other key will quit>");

         if ( vgetc() != ' ' )
                 return TRUE;

 /***********************************************************************
  * Fifth Screen:   Misc. operations,
  ***********************************************************************/

         outstr(T_ED);
         windgoto(helprow = 0, 0);

 longline("\
     Undo  &  Redo\n\
     =============\n\
     u           undo last change (partially done)\n\
     U           restore current line (not yet)\n\
     .           repeat last change\n");

 longline("\
 \n\
     File manipulation\n\
     =================\n");
 longline("\
     :w          write back changes\n\
     :wq         write and quit\n\
     :x          write if modified, and quit\n\
     :q          quit\n\
     :q!         quit, discard changes\n\
     :e name     edit file 'name'\n");
 longline("\
     :e!         reedit, discard changes\n\
     :e #        edit alternate file\n\
     :w name     write file 'name'\n");
 longline("\
     :n          edit next file in arglist\n\
     :n args     specify new arglist (not yet)\n\
     :rew        rewind arglist\n\
     :f          show current file and lines\n");
 longline("\
     :f file     change current file name\n\
     :ta tag     to tag file entry 'tag'\n\
     ^]          :ta, current word is tag\n");

         windgoto(helprow = Rows-2, 47);
         longline("<Press space bar to continue>\n");
         windgoto(helprow = Rows-1, 47);
         longline("<Any other key will quit>");

         if ( vgetc() != ' ' )
                 return TRUE;

 /***********************************************************************
  * Sixth Screen:   Operators, Misc. operations, Yank & Put
  ***********************************************************************/

         outstr(T_ED);
         windgoto(helprow = 0, 0);

 longline("\
     Operators (double to affect lines)\n\
     ==================================\n\
     d           delete\n\
     c           change\n");
 longline("\
     <           left shift\n\
     >           right shift\n\
     y           yank to buffer\n");

 longline("\n\
     Miscellaneous operations\n\
     ========================\n\
     C           change rest of line\n\
     D           delete rest of line\n\
     s           substitute chars\n");
 longline("\
     S           substitute lines (not yet)\n\
     J           join lines\n\
     x           delete characters\n\
     X           ... before cursor\n");

 longline("\n\
     Yank and Put\n\
     ============\n\
     p           put back text\n\
     P           put before\n\
     Y           yank lines");

         windgoto(helprow = Rows-1, 47);
         longline("<Press any key>");

         vgetc();

         return TRUE;
 }

 static void
 longline(p)
 char *p;
 {
         char *s;

         for ( s = p; *s ;s++ ) {
                 if ( *s == '\n' )
                         windgoto(++helprow, 0);
                 else
                         outchar(*s);
         }
 }
 #else

 bool_t
 help()
 {
         msg("Sorry, help not configured");
         return FALSE;
 }
 #endif


 HEXCHARS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\HEXCHARS.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 /*
  * This file shows how to display characters on the screen. This is
  * approach is something of an overkill. It's a remnant from the
  * original code that isn't worth messing with for now. TABS are
  * special-cased depending on the value of the "list" parameter.
  */

 struct charinfo chars[] = {
         /* 000 */        1, NULL,
         /* 001 */        2, "^A",
         /* 002 */        2, "^B",
         /* 003 */        2, "^C",
         /* 004 */        2, "^D",
         /* 005 */        2, "^E",
         /* 006 */        2, "^F",
         /* 007 */        2, "^G",
         /* 010 */        2, "^H",
         /* 011 */        2, "^I",
         /* 012 */        7, "[ERROR]",        /* shouldn't occur */
         /* 013 */        2, "^K",
         /* 014 */        2, "^L",
         /* 015 */        2, "^M",
         /* 016 */        2, "^N",
         /* 017 */        2, "^O",
         /* 020 */        2, "^P",
         /* 021 */        2, "^Q",
         /* 022 */        2, "^R",
         /* 023 */        2, "^S",
         /* 024 */        2, "^T",
         /* 025 */        2, "^U",
         /* 026 */        2, "^V",
         /* 027 */        2, "^W",
         /* 030 */        2, "^X",
         /* 031 */        2, "^Y",
         /* 032 */        2, "^Z",
         /* 033 */        2, "^[",
         /* 034 */        2, "^\\",
         /* 035 */        2, "^]",
         /* 036 */        2, "^^",
         /* 037 */        2, "^_",
         /* 040 */        1, NULL,
         /* 041 */        1, NULL,
         /* 042 */        1, NULL,
         /* 043 */        1, NULL,
         /* 044 */        1, NULL,
         /* 045 */        1, NULL,
         /* 046 */        1, NULL,
         /* 047 */        1, NULL,
         /* 050 */        1, NULL,
         /* 051 */        1, NULL,
         /* 052 */        1, NULL,
         /* 053 */        1, NULL,
         /* 054 */        1, NULL,
         /* 055 */        1, NULL,
         /* 056 */        1, NULL,
         /* 057 */        1, NULL,
         /* 060 */        1, NULL,
         /* 061 */        1, NULL,
         /* 062 */        1, NULL,
         /* 063 */        1, NULL,
         /* 064 */        1, NULL,
         /* 065 */        1, NULL,
         /* 066 */        1, NULL,
         /* 067 */        1, NULL,
         /* 070 */        1, NULL,
         /* 071 */        1, NULL,
         /* 072 */        1, NULL,
         /* 073 */        1, NULL,
         /* 074 */        1, NULL,
         /* 075 */        1, NULL,
         /* 076 */        1, NULL,
         /* 077 */        1, NULL,
         /* 100 */        1, NULL,
         /* 101 */        1, NULL,
         /* 102 */        1, NULL,
         /* 103 */        1, NULL,
         /* 104 */        1, NULL,
         /* 105 */        1, NULL,
         /* 106 */        1, NULL,
         /* 107 */        1, NULL,
         /* 110 */        1, NULL,
         /* 111 */        1, NULL,
         /* 112 */        1, NULL,
         /* 113 */        1, NULL,
         /* 114 */        1, NULL,
         /* 115 */        1, NULL,
         /* 116 */        1, NULL,
         /* 117 */        1, NULL,
         /* 120 */        1, NULL,
         /* 121 */        1, NULL,
         /* 122 */        1, NULL,
         /* 123 */        1, NULL,
         /* 124 */        1, NULL,
         /* 125 */        1, NULL,
         /* 126 */        1, NULL,
         /* 127 */        1, NULL,
         /* 130 */        1, NULL,
         /* 131 */        1, NULL,
         /* 132 */        1, NULL,
         /* 133 */        1, NULL,
         /* 134 */        1, NULL,
         /* 135 */        1, NULL,
         /* 136 */        1, NULL,
         /* 137 */        1, NULL,
         /* 140 */        1, NULL,
         /* 141 */        1, NULL,
         /* 142 */        1, NULL,
         /* 143 */        1, NULL,
         /* 144 */        1, NULL,
         /* 145 */        1, NULL,
         /* 146 */        1, NULL,
         /* 147 */        1, NULL,
         /* 150 */        1, NULL,
         /* 151 */        1, NULL,
         /* 152 */        1, NULL,
         /* 153 */        1, NULL,
         /* 154 */        1, NULL,
         /* 155 */        1, NULL,
         /* 156 */        1, NULL,
         /* 157 */        1, NULL,
         /* 160 */        1, NULL,
         /* 161 */        1, NULL,
         /* 162 */        1, NULL,
         /* 163 */        1, NULL,
         /* 164 */        1, NULL,
         /* 165 */        1, NULL,
         /* 166 */        1, NULL,
         /* 167 */        1, NULL,
         /* 170 */        1, NULL,
         /* 171 */        1, NULL,
         /* 172 */        1, NULL,
         /* 173 */        1, NULL,
         /* 174 */        1, NULL,
         /* 175 */        1, NULL,
         /* 176 */        1, NULL,
         /* 177 */        5, "[DEL]",
 };


 HEXDUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\DUMPS\HEXDUMP.C

 /****************************************************************************
 /*                                                                          *
 /* HEXDUMP.C                                                                *
 /*                                                                          *
 /* This program prints the HEX values and actual text for the file          *
 /* specified as the first command line argument. It reads the file a block  *
 /* at a time and prints the decimal value of each character, then prints    *
 /* the translated characters at the end of the line. It translates certain  *
 /* special characters like BELL, LF, FF to spaces for printing              *
 /*                                                                          *
 /* Written by: Jim Niederriter   12/26/83                                   *
 /*                                                                          *
 /****************************************************************************
 /*                                                                          *
 /* This program was written for the Lattice `C' Compiler, and works under   *
 /* version 1.04 or 2.00.                                                    *
 /*                                                                          *
 /****************************************************************************

 #include <stdio.h>
 #define  BELL   7
 #define  MAXCHR 40
 #define  NULL   0

 main(argc, argv)
 int argc;
 char *argv[];
 {
      int loopx, linecnt;
      int x, f1, stats, flag, fmode;
      long countr;
      char buffer[MAXCHR + 1];
      FILE *f2, *fopen();

 /****** Looks for filename as first command line argument *******************

      if (argc < 2)
      {
           puts("Requires file name in command line\n");
           putch(BELL);
           exit(1);
      }

 /****** Opens printer as LPT1 ***********************************************

      if ((f2 = fopen("LPT1:", "w")) == NULL)
      {
           puts("Can't open printer file\n");
           putch(BELL);
           exit(1);
      }
 /****** Open file as read-only, and in `untranslated' mode...(does not   */
 /****** convert CR/LF). *************************************************/

      fmode = 0;          /* mode for `read-only' */
      fmode = 0x8000;     /* set to read in `untranslated' or binary mode */

      if ((f1 = open(argv[1], fmode)) == NULL)
      {
           printf("Can't open file %s.\n", argv[1]);
           putch(BELL);
           exit(1);
      }
 /***** Printer codes are set up for EPSON FX (change to match your printer */

      fprintf(f2, "\x1BP\x0F");     /* set printer to PICA, CONDENSED  */

 /**** This one sets the `skip over perforation' to 3 lines *****************/

      fprintf(f2, "\x1BN\x03\nCount                              File ");
      fprintf(f2, "dump for file name: %s \n", argv[1]);

      countr = loopx = linecnt = 0;
      flag = 1;
      while (flag)
      {
           flag = 0;
           setmem(buffer, MAXCHR, NULL);               /* clear buffer  */
           if ((stats = read(f1, buffer, MAXCHR)) > 0) /* read blk from file *
           {
                fprintf(f2, "%05ld   ", countr);        /* print char count */
                countr += MAXCHR;
                flag = 1;

                for (x=0; x <= (MAXCHR-1); x++)
                {
                     fprintf(f2, "%02x", buffer[x]);  /* print hex value */

 /****** change any special characters to SPACE for printing *****************

                     if (buffer[x] < 32 || buffer[x] > 128)
                          buffer[x] = ' ';    /* get rid of unprintables */

                     if ((loopx +=1) == 5)
                     {
                          fprintf(f2, " ");            /* 5 at a time */
                          loopx = 0;
                     }
                }
                fprintf(f2, "*");             /* print translated characters *
                for (x=0; x <= (MAXCHR-1); x++)
                     fprintf(f2, "%c", buffer[x]);
                fprintf(f2, "*\n");
                if ((linecnt += 1) == 5)
                {
                     fprintf(f2, "\n");       /* skip 1 after every 5 lines */
                     linecnt = 0;
                }
           }
      }
      fprintf(f2, "\x1BP\x0C");     /* set back to normal & do forms feed */
      fflush(f2);
      fclose(f2);
 }


 HEXTOBIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\HEXTOBIN.C

 /* HEX2BIN.C - From page 342 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. Converts hex to binary.           */
 /****************************************************************/

 #define TRUE 1

 main()
 {
 int j, num, bit;
 unsigned int mask;
 char string[10];

    while(TRUE) {
       mask = 0x8000;          /* 1000000 binary */
       printf("\nEnter number: ");
       scanf("%x", &num);
       printf("\nBinary of %04x is:  ", num);
       for (j = 0; j < 16; j++) {    /*for each bit*/
          bit = (mask & num) ? 1 : 0;      /*bit is 1 or 0*/
          printf("%d ", bit);
          if (j == 7)
             printf("-- ");
          mask >>= 1;             /*shift mask to right 1*/
       }
       printf("\n");
    }
 }



 HISTCLIB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\HISTCLIB.C

 /*              Histogram Library; C portion.
  */

 /*      prHist(hist)

         Function: Given a pointer to a table of 1025 histogram counters,
         print out the address that each counter covers, the count for that
         counter, and the percentage of the total both with and without
         the "other" counter included. Don't print counters that are zero.

         Algorithm: Add up all the counters. Print out the heading. Then
         cycle through all the counters, printing out the information.
 */

 prHist(hist)

 long *hist;

 {
         float total, totalWo;
         long *hptr;
         unsigned addr;

         /* Alert the user that we're done running, and are now computing
            the histogram. */
         printf("Program done. Compiling histogram data.\n\n");
         /* Add up all the counters. */
         for (total = 0, hptr = hist+1; hptr < hist+1025; total += *hptr++);
         /* Compute the total without the "other" category. */
         totalWo = total + ((float) *hist);
         /* Print the total count without "other." */
         printf("Total recorded hits: %15.0f.\n\n",totalWo);
         /* Print the header for the main list. */
         printf(" Address     Count    %% with Other  %% without Other\n");
         printf("---------  ---------  ------------  ---------------\n");
         /* Print the "other" counter. */
         printf("  Other    %9ld      %7.3f%%\n",*hist,
                100.0*(((float) *hist)/total));
         /* Loop through all of the counters... */
         for (hptr = hist+1, addr = 0; hptr < hist+1025; hptr++, addr += 64)
                 /* If it isn't zero, print it. */
                 if (*hptr != 0L)
                         printf("%4x-%4x  %9ld      %7.3f%%         %7.3f%%\n"
                                addr,addr+63,*hptr,
                                100.0*(((float) *hptr)/totalWo),
                                100.0*(((float) *hptr)/total));
 }



 HP110.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\HP110.C

 /*
  *        HP110:        Hewlett Packard 110 Screen Driver
  */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     HP110

 NROW    16                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        NPAUSE        100                        /* # times thru update to pau
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
 BEL     0x07                    /* BEL character.               */
 ESC     0x1B                    /* ESC character.               */

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     h110move();
 extern  int     h110eeol();
 extern  int     h110eeop();
 extern  int     h110beep();
 extern  int     h110open();
 extern        int        h110rev();
 extern        int        h110cres();
 extern        int        h110close();
 extern        int        h110kopen();
 extern        int        h110kclose();

 #if        COLOR
 extern        int        h110fcol();
 extern        int        h110bcol();

 int        cfcolor = -1;                /* current forground color */
 int        cbcolor = -1;                /* current background color */
 #endif

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         h110open,
         h110close,
         h110kopen,
         h110kclose,
         ttgetc,
         ttputc,
         ttflush,
         h110move,
         h110eeol,
         h110eeop,
         h110beep,
         h110rev,
         h110cres
 #if        COLOR
         , h110fcol,
         h110bcol
 #endif
 };

 #if        COLOR
 h110fcol(color)                /* set the current output color */

 int color;        /* color to set */

 {
         if (color == cfcolor)
                 return;
         ttputc(ESC);
         ttputc('[');
         h110parm(color+30);
         ttputc('m');
         cfcolor = color;
 }

 h110bcol(color)                /* set the current background color */

 int color;        /* color to set */

 {
         if (color == cbcolor)
                 return;
         ttputc(ESC);
         ttputc('[');
         h110parm(color+40);
         ttputc('m');
         cbcolor = color;
 }
 #endif

 h110move(row, col)
 {
         ttputc(ESC);
         ttputc('[');
         h110parm(row+1);
         ttputc(';');
         h110parm(col+1);
         ttputc('H');
 }

 h110eeol()
 {
         ttputc(ESC);
         ttputc('[');
         ttputc('0');
         ttputc('K');
 }

 h110eeop()
 {
 #if        COLOR
         h110fcol(gfcolor);
         h110bcol(gbcolor);
 #endif
         ttputc(ESC);
         ttputc('[');
         ttputc('0');
         ttputc('J');
 }

 h110rev(state)                /* change reverse video state */

 int state;        /* TRUE = reverse, FALSE = normal */

 {
 #if        COLOR
         int ftmp, btmp;                /* temporaries for colors */
 #endif

         ttputc(ESC);
         ttputc('[');
         ttputc(state ? '7': '0');
         ttputc('m');
 #if        COLOR
         if (state == FALSE) {
                 ftmp = cfcolor;
                 btmp = cbcolor;
                 cfcolor = -1;
                 cbcolor = -1;
                 h110fcol(ftmp);
                 h110bcol(btmp);
         }
 #endif
 }

 h110cres()        /* change screen resolution */

 {
         return(TRUE);
 }

 spal()                /* change pallette register */

 {
         /*   not here */
 }

 h110beep()
 {
         ttputc(BEL);
         ttflush();
 }

 h110parm(n)
 register int    n;
 {
         register int q,r;

         q = n/10;
         if (q != 0) {
                 r = q/10;
                 if (r != 0) {
                         ttputc((r%10)+'0');
                 }
                 ttputc((q%10) + '0');
         }
         ttputc((n%10) + '0');
 }

 h110open()
 {
         strcpy(sres, "15LINE");
         revexist = TRUE;
         ttopen();
 }

 h110close()

 {
 #if        COLOR
         h110fcol(7);
         h110bcol(0);
 #endif
         ttclose();
 }

 h110kopen()

 {
 }

 h110kclose()

 {
 }

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else
 h110hello()
 {
 }
 #endif


 HP150.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\HP150.C

 /*
  * The routines in this file provide support for HP150 screens
  * and routines to access the Keyboard through KEYCODE mode.
  * It compiles into nothing if not an HP150 screen device.
  * added by Daniel Lawrence
  */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     HP150

 NROW    24                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
        NPAUSE        15                        /* # times thru update to paus
 BEL     0x07                    /* BEL character.               */
 ESC     0x1B                    /* ESC character.               */

 extern  int     openhp();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern        int        hpflush();
 extern  int     closehp();
 extern        int        hp15kopen();
 extern        int        hp15kclose();
 extern  int     hp15move();
 extern  int     hp15eeol();
 extern  int     hp15eeop();
 extern  int     hp15beep();
 extern        int        gethpkey();
 extern        int        hp15rev();
 extern        int        hp15cres();
 #if        COLOR
 extern        int        hp15fcol();
 extern        int        hp15bcol();
 #endif

 /* weird to ascii translation table */

 char trans[][2] = {
         0x24,        9,        /* tab */
         0x25,        13,        /* ret */
         0x27,        8,        /* backspace */
         0x30,        48,        /* zero */
         0x31,        49,        /* one */
         0x32,        50,        /* two */
         0x33,        51,        /* three */
         0x34,        52,        /* four */
         0x35,        53,        /* five */
         0x36,        54,        /* six */
         0x37,        55,        /* seven */
         0x38,        56,        /* eight */
         0x39,        57,        /* nine */
         0x50,        13,        /* enter */
         0x54,        27,        /* break -> ESC */
         0x55,        27,        /* esc */
         0x58,        24,        /* stop -> ^X */
         0x70,        45,        /* N-minus */
         0x71,        42,        /* N-asterisk */
         0x72,        43,        /* N-plus */
         0x73,        47,        /* N-slash */
         0x74,        44,        /* N-comma */
         0x75,        13,        /* N-enter */
         0x76,        9,        /* N-tab */
         0x77,        46        /* N-period */
 };

 #define NTRANS        sizeof(trans) / 2

 union REGS r;                /* register set for bios and dos (AGIOS) calls *
 int capslock = 0;        /* caps lock flag */

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         openhp,
         closehp,
         hp15kopen,
         hp15kclose,
         gethpkey,
         ttputc,
         hpflush,
         hp15move,
         hp15eeol,
         hp15eeop,
         hp15beep,
         hp15rev,
         hp15cres
 #if        COLOR
         , hp15fcol,
         hp15bcol
 #endif
 };

 hp15move(row, col)
 {
         ttputc(ESC);
         ttputc('&');
         ttputc('a');
         hp15parm(col);
         ttputc('c');
         hp15parm(row);
         ttputc('R');
 }

 hpflush()

 {

 }

 hp15eeol()
 {
         ttputc(ESC);
         ttputc('K');
 }

 hp15eeop()
 {
         ttputc(ESC);
         ttputc('J');
 }

 hp15rev(status)                /* change the reverse video status */

 int status;        /* TRUE = on, FALSE = off */

 {
         ttputc(ESC);
         ttputc('&');
         ttputc('d');
         ttputc((status != FALSE) ? 'B': '@');
 }

 hp15cres()        /* change screen resolution */

 {
         return(TRUE);
 }

 spal()                /* change pallette register */

 {
         /*   not here */
 }

 hp15beep()
 {
         ttputc(BEL);
         ttflush();
 }

 hp15parm(n)
 register int    n;
 {
         register int    q;

         q = n/10;
         if (q != 0)
                 hp15parm(q);
         ttputc((n%10) + '0');
 }

 #if        COLOR
 hp15fcol()        /* we really can't do colors here, so just ignore it */
 {
 }

 hp15bcol()        /* we really can't do colors here, so just ignore it */
 {
 }
 #endif

 gethpkey()        /* get a key from the HP keyboard while in keycode mode */

 {
         static int keepflag = 0;        /* kept ahead char flag */
         static int keepchar = 0;        /* kept ehead flag */
         int c;
         int devid;                        /* device ID */
         int ctype;                        /* type of character gotten */
         int shiftb;                        /* state of shift keys */
         int i;

         /* if we are in an extended char sequence, finish it */
         if (keepflag != 0) {
                 keepflag = 0;
                 return(keepchar);
         }

         /* grab the next 4 char sequence */
 next:        shiftb = ttgetc();
         devid = ttgetc();
         c = ttgetc();
         ttgetc();                /* skip null byte */

         /* make sure we are from the keyboard */
         if (devid != 192)
                 goto next;

         /* if normal ascii, return it */
         if ((shiftb & 0x80) == 0) {
                 if (capslock && c >= 'a' && c <= 'z')
                         c -= 32;
                 return(c);
         }

         /* check specifically for the caps lock key */
         if (c == 0x56) {
                 capslock = ~capslock;
                 goto next;
         }

         /* check to see if it needs translation */
         for (i=0; i < NTRANS; i++)
                 if (trans[i][0] == c)
                         return((int)trans[i][1]);

         /* other wise, shove it in the keep char and return the leadin code *
         keepchar = c;
         keepflag = 1;
         return(0);
 }

 openhp()                /* open the HP150 screen for input */

 {
         strcpy(sres, "NORMAL");
         revexist = TRUE;
 }

 closehp()                /* close the HP150 screen for input */

 {
 }

 hp15kopen()                /* open the HP150 keyboard for input */

 {
         /* define key charectoristics with AGIOS call (0, 40) */
         defkey();

         /* Turn on RAW mode with MSDOS call 44h */
         rawon();

         /* Turn off Control-C checking  MS-DOS 33h */
         ckeyoff();

         /* Turn on keycode mode with AGIOS call (0,43) */
         keycon();

         /* display the application softkey labels */
         dsplbls();
 }

 hp15kclose()                /* close the HP150 keyboard for input */

 {
         /* define key charectoristics with AGIOS call (0, 40) */
         undefkey();

         /* Turn off RAW mode with MSDOS call 44h */
         rawoff();

         /* Turn on Control-C checking  MS-DOS 33h */
         ckeyon();

         /* Turn off keycode mode with AGIOS call (0,43) */
         keycoff();
 }

 rawon()                /* put the HP150 keyboard into RAW mode */

 {
         /* get the IO control info */

         r.x.ax = 0x4400;        /* IO ctrl get device information */
         r.x.bx = 0x0001;        /* File handle; 1 for console */
         intdos(&r, &r);                /* go fer it */

         r.h.dh = 0;                /* clear high byte for put */
         r.h.dl |= 0x20;                /* set raw bit */

         /* and put it back */

         r.x.ax = 0x4401;        /* IO ctrl put device information */
         r.x.bx = 0x0001;        /* File handle; 1 for console */
         intdos(&r, &r);                /* go fer it */
 }

 rawoff()        /* put the HP150 keyboard into COOKED mode */

 {
         /* get the IO control info */

         r.x.ax = 0x4400;        /* IO ctrl get device information */
         r.x.bx = 0x0001;        /* File handle; 1 for console */
         intdos(&r, &r);                /* go fer it */

         r.h.dh = 0;                /* clear high byte for put */
         r.h.dl &= 0xdf;                /* set raw bit */

         /* and put it back */

         r.x.ax = 0x4401;        /* IO ctrl put device information */
         r.x.bx = 0x0001;        /* File handle; 1 for console */
         intdos(&r, &r);                /* go fer it */
 }


 ckeyoff()        /* turn control-C trapping off */

 {
         r.h.ah = 0x33;        /* ctrl-break check */
         r.h.al = 1;        /* set the state of the ctrl-break check */
         r.h.dl = 0;        /* turn it off */
         intdos(&r, &r);
 }

 ckeyon()        /* turn control-C trapping on */

 {
         r.h.ah = 0x33;        /* ctrl-break check */
         r.h.al = 1;        /* set the state of the ctrl-break check */
         r.h.dl = 1;        /* turn it on */
         intdos(&r, &r);
 }

 #ifdef        unsigned
 #undef        unsigned
 #endif

 agios(buf, len)        /* perform an AGIOS call */

 char *buf;        /* sequence of bytes in command */
 int len;        /* length of command in bytes */

 {
         r.x.ax = 0x4403;        /* I/O ctrl write */
         r.x.bx = 1;                /* console handle */
         r.x.cx = len;                /* buffer length */
         r.x.dx = (unsigned)buf;        /* buffer address */
         return(intdos(&r, &r));        /* do it */
 }

 keycon()        /* turn keycode mode on */

 {
         static char cmd[] = {43, 0, 1};

         return(agios(&cmd[0], 3));
 }

 keycoff()        /* turn keycode mode off */

 {
         static char cmd[] = {43, 0, 0};

         return(agios(&cmd[0], 3));
 }

 defkey()        /* change all special keys to intercept mode */

 {
         static char cmd[] = {40, 0, 2, 0, 0xfe, 0};

         return(agios(&cmd[0], 6));
 }

 undefkey()        /* change all special keys to intercept mode */

 {
         static char cmd[] = {40, 0, 0, 0, 0xfe, 0};

         return(agios(&cmd[0], 6));
 }

 dsplbls()        /* display the application softkey labels on the screen */

 {
         static char cmd[] = {11, 0};

         return(agios(&cmd[0], 2));
 }

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument */

 {
         register int status;        /* return status */
         register int i;                /* loop index */
         char lbl[17];        /* returned label contents */
         /* AGIOS command buffer */
         static char cmd[] = {8, 0, 1, 0, 7, 7, 7, 7, 10, 0, 10, 0};
         /*                   code  key#  ptr to      top    bottom
                                          label string  attribute */
         union {                /* union to cast ptr into AGIOS arg string */
                 char *ptr;        /* pointer to arg string */
                 char cstr[4];
         } ptru;

         /* must have a numeric argument */
         if (f == FALSE) {
                 mlwrite("%Need function key number");
                 return(FALSE);
         }

         /* and it must be a legal key number */
         if (n < 1 || n > 8) {
                 mlwrite("%Function key number out of range");
                 return(FALSE);
         }

         /* get the string to send */
         status = mlreply("Label contents: ", &lbl[0], 17);
         if (status != TRUE)
                 return(status);

         /* pad the label out */
         for (i=0; i < 17; i++) {
                 if (lbl[i] == 0)
                         break;
         }
         for (; i < 16; i++)
                 lbl[i] = ' ';
         lbl[16] = 0;

         /* set up the parameters */
         cmd[2] = n;                        /* function key number */
         ptru.ptr = &lbl[0];                /* set up pointer to label string
 force:        cmd[4] = ptru.cstr[0];
         cmd[5] = ptru.cstr[1];
         cmd[6] = ptru.cstr[2];
         cmd[7] = ptru.cstr[3];

         /* and send it out */
         agios(&cmd[0], 12);
         return(TRUE);
 }
 #endif
 #else

 h15hello()

 {
 }
 #endif


 HSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\HSORT.C

 /*
  *        Heap sorting functions
  */

 static _wsift(base, i, n, cmp)
 register int *base;
 register int i;
 register int n;
 register int (*cmp)();
 {
         register int j, t;

         while((j = ((i << 1) + 1)) < n) {
                 if((j < (n - 1)) && ((*cmp)((base+j), (base+j+1)) < 0))
                         ++j;
                 if((cmp)((base+i), (base+j)) < 0) {
                         t = base[i];
                         base[i] = base[j];
                         base[j] = t;
                         i = j;
                 }
                 else
                         break;
         }
 }

 static _whsort(base, num, cmp)
 register int *base;
 register int num;
 register int (*cmp)();
 {
         register int i, j;

         for(i = ((num >> 1) - 1); (i > 0); --i)
                 _wsift(base, i, num, cmp);
         i = num;
         while(i > 1) {
                 _wsift(base, 0, i--, cmp);
                 j = *base;
                 *base = *(base + i);
                 *(base + i) = j;
         }
 }

 static _lsift(base, i, n, cmp)
 register long *base;
 register int i;
 register int n;
 register int (*cmp)();
 {
         register int j;
         register long t;

         while((j = ((i << 1) + 1)) < n) {
                 if((j < (n - 1)) && ((*cmp)((base+j), (base+j+1)) < 0))
                         ++j;
                 if((cmp)((base+i), (base+j)) < 0) {
                         t = base[i];
                         base[i] = base[j];
                         base[j] = t;
                         i = j;
                 }
                 else
                         break;
         }
 }

 static _lhsort(base, num, cmp)
 register long *base;
 register int num;
 register int (*cmp)();
 {
         register int i;
         register long j;

         for(i = ((num >> 1) - 1); (i > 0); --i)
                 _lsift(base, i, num, cmp);
         i = num;
         while(i > 1) {
                 _lsift(base, 0, i--, cmp);
                 j = *base;
                 *base = *(base + i);
                 *(base + i) = j;
         }
 }

 static _nswap(pa, pb, n)
 register char *pa;
 register char *pb;
 register int n;
 {
         register char c;

         while(n--) {
                 c = *pa;
                 *pa++ = *pb;
                 *pb++ = c;
         }
 }

 static _nsift(base, i, n, size, cmp)
 register char *base;
 register int i;
 register int n;
 register int size;
 register int (*cmp)();
 {
         register int j;
         register char *p;

         while((j = ((i << 1) + 1)) < n) {
                 p = (base+size*j);
                 if((j < (n - 1)) && ((*cmp)(p, p+size) < 0)) {
                         ++j;
                         p += size;
                 }
                 if((cmp)((base+size*i), p) < 0) {
                         _nswap((base+size*i), p, size);
                         i = j;
                 }
                 else
                         break;
         }
 }

 static _nhsort(base, num, size, cmp)
 register char *base;
 register int num;
 register int size;
 register int (*cmp)();
 {
         register int i, j;

         for(i = ((num >> 1) - 1); (i > 0); --i)
                 _nsift(base, i, num, size, cmp);
         i = num;
         while(i > 1) {
                 _nsift(base, 0, i--, size, cmp);
                 _nswap(base, (base+size*i), size);
         }
 }

 hsort(base, num, size, cmp)
 char *base;
 int num;
 int size;
 int (*cmp)();
 /*
  *        Perform an N*log(N) heap-sort on an array starting at <base>
  *        containing <num> elements of <size> bytes each.  The function
  *        pointed to by <cmp> is used to compare elements.  Pointers to
  *        two items in the array are passed to the function, which must
  *        return a number representing their relationship as follows:
  *                negative        item1 < item2
  *                0                item1 == item2
  *                positive        item1 > item2
  *        The hsort() function requires no extra storage, is not recursive,
  *        and has an almost constant N*log(N) sort time.  In the average
  *        case, it is about half as fast as qsort() on random data.  If
  *        portability is a concern, it should be noted that qsort() is
  *        almost always available, but hsort() is not.
  */
 {
         if(size == 2)
                 _whsort(base, num, cmp);
         else if(size == 4)
                 _lhsort(base, num, cmp);
         else
                 _nhsort(base, num, size, cmp);
 }


 HYPOT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\HYPOT.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /************************************************************************/
         double
 hypot(x, y)                /* return hypotenuse value of x-y triangle

 /*----------------------------------------------------------------------*/
 double x, y;
 {
         double mx, t;

         if (x < 0.0)
                 x = -x;
         if (y < 0.0)
                 y = -y;
         mx = MAX(x, y);
         if (x IS 0.00)
                 return y;

         if (y IS 0.0)
                 return x;

         if (mx < RTHLFINF)                /* we can use fast formula if true
                 return sqrt(x*x + y*y);

         if (x > y)                        /* otherwise, must use trig form.
                 t = atan2(y, x);
         else
                 t = atan2(x, y);
         t = cos(t);
         if (mx < INFINLEG)
                 return (mx / t);        /* ok because t > 0.707

         t = log(mx) - log(t);                /* but now it's time for drastic
         if (t < LOGINFINITY)                /* measures.
                 return exp(t);

         errno = ERANGE;                        /* but all has failed.
         return INFINITY;
 }


 IBMPC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\IBMPC.C

 /*
  * The routines in this file provide support for the IBM-PC and other
  * compatible terminals. It goes directly to the graphics RAM to do
  * screen output. It compiles into nothing if not an IBM-PC driver
  * Supported monitor cards include CGA, MONO and EGA.
  */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     IBMPC
 NROW        43                        /* Max Screen size.                */
 NCOL    80                      /* Edit if you want to.         */
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
        NPAUSE        200                        /* # times thru update to pau
 BEL     0x07                    /* BEL character.               */
 ESC     0x1B                    /* ESC character.               */
        SPACE        32                        /* space character

        SCADC        0xb8000000L                /* CGA address of screen RAM
        SCADM        0xb0000000L                /* MONO address of screen RAM
 SCADE        0xb8000000L                /* EGA address of screen RAM        *

 MONOCRSR 0x0B0D                        /* monochrome cursor            */
 CGACRSR 0x0607                        /* CGA cursor                    */
 EGACRSR 0x0709                        /* EGA cursor                    */

        CDCGA        0                        /* color graphics card
        CDMONO        1                        /* monochrome text card
        CDEGA        2                        /* EGA color adapter
        CDSENSE        9                        /* detect the card type

 NDRIVE        3                        /* number of screen drivers        */

 int dtype = -1;                                /* current display type
 char drvname[][8] = {                        /* screen resolution names
         "CGA", "MONO", "EGA"
 };
 long scadd;                                /* address of screen ram        */
 int *scptr[NROW];                        /* pointer to screen lines        */
 unsigned int sline[NCOL];                /* screen line image
 int egaexist = FALSE;                        /* is an EGA card available?
 extern union REGS rg;                        /* cpu register for use of DOS c

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     ibmmove();
 extern  int     ibmeeol();
 extern  int     ibmeeop();
 extern  int     ibmbeep();
 extern  int     ibmopen();
 extern        int        ibmrev();
 extern        int        ibmcres();
 extern        int        ibmclose();
 extern        int        ibmputc();
 extern        int        ibmkopen();
 extern        int        ibmkclose();

 #if        COLOR
 extern        int        ibmfcol();
 extern        int        ibmbcol();

 int        cfcolor = -1;                /* current forground color */
 int        cbcolor = -1;                /* current background color */
 int        ctrans[] =                /* ansi to ibm color translation table *
         {0, 4, 2, 6, 1, 5, 3, 7};
 #endif

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         ibmopen,
         ibmclose,
         ibmkopen,
         ibmkclose,
         ttgetc,
         ibmputc,
         ttflush,
         ibmmove,
         ibmeeol,
         ibmeeop,
         ibmbeep,
         ibmrev,
         ibmcres
 #if        COLOR
         , ibmfcol,
         ibmbcol
 #endif
 };

 #if        COLOR
 ibmfcol(color)                /* set the current output color */

 int color;        /* color to set */

 {
         cfcolor = ctrans[color];
 }

 ibmbcol(color)                /* set the current background color */

 int color;        /* color to set */

 {
         cbcolor = ctrans[color];
 }
 #endif

 ibmmove(row, col)
 {
         rg.h.ah = 2;                /* set cursor position function code */
         rg.h.dl = col;
         rg.h.dh = row;
         rg.h.bh = 0;                /* set screen page number */
         int86(0x10, &rg, &rg);
 }

 ibmeeol()        /* erase to the end of the line */

 {
         unsigned int attr;        /* attribute byte mask to place in RAM */
         unsigned int *lnptr;        /* pointer to the destination line */
         int i;
         int ccol;        /* current column cursor lives */
         int crow;        /*           row        */

         /* find the current cursor position */
         rg.h.ah = 3;                /* read cursor position function code */
         rg.h.bh = 0;                /* current video page */
         int86(0x10, &rg, &rg);
         ccol = rg.h.dl;                /* record current column */
         crow = rg.h.dh;                /* and row */

         /* build the attribute byte and setup the screen pointer */
 #if        COLOR
         if (dtype != CDMONO)
                 attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
         else
                 attr = 0x0700;
 #else
         attr = 0x0700;
 #endif
         lnptr = &sline[0];
         for (i=0; i < term.t_ncol; i++)
                 *lnptr++ = SPACE | attr;

         if (flickcode && (dtype == CDCGA)) {
                 /* wait for vertical retrace to be off */
                 while ((inp(0x3da) & 8))
                         ;

                 /* and to be back on */
                 while ((inp(0x3da) & 8) == 0)
                         ;
         }

         /* and send the string out */
         movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2);

 }

 ibmputc(ch)        /* put a character at the current position in the
                    current colors */

 int ch;

 {
         rg.h.ah = 14;                /* write char to screen with current att
         rg.h.al = ch;
 #if        COLOR
         if (dtype != CDMONO)
                 rg.h.bl = cfcolor;
         else
                 rg.h.bl = 0x07;
 #else
         rg.h.bl = 0x07;
 #endif
         int86(0x10, &rg, &rg);
 }

 ibmeeop()
 {
         int attr;                /* attribute to fill screen with */

         rg.h.ah = 6;                /* scroll page up function code */
         rg.h.al = 0;                /* # lines to scroll (clear it) */
         rg.x.cx = 0;                /* upper left corner of scroll */
         rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
                                 /* lower right corner of scroll */
 #if        COLOR
         if (dtype != CDMONO)
                 attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15)
         else
                 attr = 0;
 #else
         attr = 0;
 #endif
         rg.h.bh = attr;
         int86(0x10, &rg, &rg);
 }

 ibmrev(state)                /* change reverse video state */

 int state;        /* TRUE = reverse, FALSE = normal */

 {
         /* This never gets used under the IBM-PC driver */
 }

 ibmcres(res)        /* change screen resolution */

 char *res;        /* resolution to change to */

 {
         int i;                /* index */

         for (i = 0; i < NDRIVE; i++)
                 if (strcmp(res, drvname[i]) == 0) {
                         scinit(i);
                         return(TRUE);
                 }
         return(FALSE);
 }

 spal()        /* reset the pallette registers */

 {
         /* nothin here now..... */
 }

 ibmbeep()
 {
 #if        MWC86
         putcnb(BEL);
 #else
         bdos(6, BEL, 0);
 #endif
 }

 ibmopen()
 {
         scinit(CDSENSE);
         revexist = TRUE;
         ttopen();
 }

 ibmclose()

 {
 #if        COLOR
         ibmfcol(7);
         ibmbcol(0);
 #endif
         /* if we had the EGA open... close it */
         if (dtype == CDEGA)
                 egaclose();

         ttclose();
 }

 ibmkopen()        /* open the keyboard */

 {
 }

 ibmkclose()        /* close the keyboard */

 {
 }

 scinit(type)        /* initialize the screen head pointers */

 int type;        /* type of adapter to init for */

 {
         union {
                 long laddr;        /* long form of address */
                 int *paddr;        /* pointer form of address */
         } addr;
         int i;

         /* if asked...find out what display is connected */
         if (type == CDSENSE)
                 type = getboard();

         /* if we have nothing to do....don't do it */
         if (dtype == type)
                 return(TRUE);

         /* if we try to switch to EGA and there is none, don't */
         if (type == CDEGA && egaexist != TRUE)
                 return(FALSE);

         /* if we had the EGA open... close it */
         if (dtype == CDEGA)
                 egaclose();

         /* and set up the various parameters as needed */
         switch (type) {
                 case CDMONO:        /* Monochrome adapter */
                                 scadd = SCADM;
                                 newsize(TRUE, 25);
                                 break;

                 case CDCGA:        /* Color graphics adapter */
                                 scadd = SCADC;
                                 newsize(TRUE, 25);
                                 break;

                 case CDEGA:        /* Enhanced graphics adapter */
                                 scadd = SCADE;
                                 egaopen();
                                 newsize(TRUE, 43);
                                 break;
         }

         /* reset the $sres environment variable */
         strcpy(sres, drvname[type]);
         dtype = type;

         /* initialize the screen pointer array */
         for (i = 0; i < NROW; i++) {
                 addr.laddr = scadd + (long)(NCOL * i * 2);
                 scptr[i] = addr.paddr;
         }
         return(TRUE);
 }

 /* getboard:        Determine which type of display board is attached.
                 Current known types include:

                 CDMONO        Monochrome graphics adapter
                 CDCGA        Color Graphics Adapter
                 CDEGA        Extended graphics Adapter
 */

 /* getbaord:        Detect the current display adapter
                 if MONO                set to MONO
                    CGA                set to CGA        EGAexist = FALSE
                    EGA                set to CGA        EGAexist = TRUE
 */

 int getboard()

 {
         int type;        /* board type to return */

         type = CDCGA;
         int86(0x11, &rg, &rg);
         if ((((rg.x.ax >> 4) & 3) == 3))
                 type = CDMONO;

         /* test if EGA present */
         rg.x.ax = 0x1200;
         rg.x.bx = 0xff10;
         int86(0x10,&rg, &rg);                /* If EGA, bh=0-1 and bl=0-3 */
         egaexist = !(rg.x.bx & 0xfefc);        /* Yes, it's EGA */
         return(type);
 }

 egaopen()        /* init the computer to work with the EGA */

 {
         /* put the beast into EGA 43 row mode */
         rg.x.ax = 3;
         int86(16, &rg, &rg);

         rg.h.ah = 17;                /* set char. generator function code */
         rg.h.al = 18;                /*  to 8 by 8 double dot ROM         */
         rg.h.bl = 0;                /* block 0                           */
         int86(16, &rg, &rg);

         rg.h.ah = 18;                /* alternate select function code    */
         rg.h.al = 0;                /* clear AL for no good reason       */
         rg.h.bl = 32;                /* alt. print screen routine         */
         int86(16, &rg, &rg);

         rg.h.ah = 1;                /* set cursor size function code */
         rg.x.cx = 0x0607;        /* turn cursor on code */
         int86(0x10, &rg, &rg);

         outp(0x3d4, 10);        /* video bios bug patch */
         outp(0x3d5, 6);
 }

 egaclose()

 {
         /* put the beast into 80 column mode */
         rg.x.ax = 3;
         int86(16, &rg, &rg);
 }

 scwrite(row, outstr, forg, bacg)        /* write a line out*/

 int row;        /* row of screen to place outstr on */
 char *outstr;        /* string to write out (must be term.t_ncol long) */
 int forg;        /* forground color of string to write */
 int bacg;        /* background color */

 {
         unsigned int attr;        /* attribute byte mask to place in RAM */
         unsigned int *lnptr;        /* pointer to the destination line */
         int i;

         /* build the attribute byte and setup the screen pointer */
 #if        COLOR
         if (dtype != CDMONO)
                 attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) <<
         else
                 attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
 #else
         attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
 #endif
         lnptr = &sline[0];
         for (i=0; i<term.t_ncol; i++)
                 *lnptr++ = (outstr[i] & 255) | attr;

         if (flickcode && (dtype == CDCGA)) {
                 /* wait for vertical retrace to be off */
                 while ((inp(0x3da) & 8))
                         ;

                 /* and to be back on */
                 while ((inp(0x3da) & 8) == 0)
                         ;
         }

         /* and send the string out */
         movmem(&sline[0], scptr[row],term.t_ncol*2);
 }

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else
 ibmhello()
 {
 }
 #endif



 IBMTTY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\IBMTTY.C

 /*                          *** ibmtty.c ***                         */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS                                 */
 /*                                                                   */
 /* Terminal emulation program with file upload and download capabili-*/
 /* ties.  Optimized to communicate with a DEC VAX 11/780.            */
 /*                                                                   */
 /* Written by L. Cuthbertson, April 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #include <stdio.h>

 #define TRUE 1
 #define FALSE 0
 #define XON '\021'
 #define XOFF '\023'
 #define ESC '\033'
 #define CONZ '\032'
 #define DEL '\177'

 LCR 0x3FB        /* 8250 line control register */
 DLL 0x3F8        /* 8250 least significant divisor latch */
 DLM 0x3F9        /* 8250 most significant divisor latch */
 LSR 0x3FD        /* 8250 line status register */
 IIR 0x3FA        /* 8250 interrupt identification register */
 IER 0x3F9        /* 8250 interrupt enable register */
 MCR 0x3FC        /* 8250 modem control register */
 MSR 0x3FE        /* 8250 modem status register */
 RBR 0x3F8        /* 8250 receiver buffer register */
 THR 0x3F8        /* 8250 transmitter holding register */

 char *lcr=(char*)LCR, *dll=(char*)DLL, *dlm=(char*)DLM;
 char *lsr=(char*)LSR, *iir=(char*)IIR, *ier=(char*)IER;
 char *mcr=(char*)MCR, *msr=(char*)MSR, *rbr=(char*)RBR;
 char *thr=(char*)THR;

 struct buf {
         char *fbuf;
         char *wbuf,*rbuf;
         char *lbuf;
 };

 struct buf mem;                        /* file receiption/transmission buff *

 char combuf[64];                /* transmission buffer */
 struct buf com;

 char crtbuf[512];                /* receiption buffer */
 struct buf crt;

 char outfil[13];                /* transmit file name */
 FILE *outchan;

 char infil[13];                        /* receive file name */
 FILE *inchan;

 char lecho = FALSE;
 char gotxoff = FALSE;
 char sendxoff = FALSE;
 char sentxoff = FALSE;

 /*********************************************************************/
 /*                                                                   */
 main(argc,argv)
 int argc;
 char *argv[];
 {
         char *malloc();
         int iret,port;
         unsigned u;

         /* initialize file receiption/transmission */
         inchan = FALSE;
         outchan = FALSE;

         /* set up buffer structures */
         com.fbuf = com.wbuf = com.rbuf = &combuf[0];
         com.lbuf = &combuf[0] + sizeof(combuf) - 1;
         crt.fbuf = crt.wbuf = crt.rbuf = &crtbuf[0];
         crt.lbuf = &crtbuf[0] + sizeof(crtbuf) - 1;

         /* allocate as much memory as possible to file buffer */
         for (u=65023;;u -= 512) {
                 if (u < (512+(5*_BUFSIZ))) {
                         writes("\r\n\007*** not enough memory available ***")
                         exit();
                 }
                 mem.fbuf = malloc(u);
                 if (mem.fbuf != 0) {
                         free(mem.fbuf);
                         u -= 5*_BUFSIZ;
                         mem.fbuf = malloc(u);
                         break;
                 }
         }

         mem.wbuf = mem.rbuf = mem.fbuf;
         mem.lbuf = mem.fbuf + u - 1;

         /* determine communications port to use */
         if (argc > 1) {
                 sscanf(argv[1],"%d",&port);
                 port--;
                 if ((port < 0) || (port > 1)) {
                         writes("\r\n\007*** invalid communications port - ent
                         exit();
                 }
         } else {
                 port = 0;
         }

         /* adjust port addresses if neccessary */
         if (port == 1) {
                 lcr -= 0x100;
                 dll -= 0x100;
                 dlm -= 0x100;
                 lsr -= 0x100;
                 iir -= 0x100;
                 ier -= 0x100;
                 mcr -= 0x100;
                 msr -= 0x100;
                 rbr -= 0x100;
                 thr -= 0x100;
         }

         /* initialize 8250  - use DOS "MODE" command */
         outp(mcr,3);                /* send DTR and RTS */
         pause(1.);

         /* check for carrier */
         if ((inp(msr)&48) != 48) {
                 writes("\r\n\007*** carrier not detected - please check your
                 exit();
         }

         /* courtesy message */
         cursor(25,1);
         writes("\r\n*** you are now connected ***\r\n");

         /* polling loop */
         for (;;) {

                 /* check communications port for reception of data */
                 if ((readcomm()) != 0)
                         ;

                 /* check if screen output needed */
                 if ((wrtscr()) != 0)
                         ;

                 /* check communications port for receiption of data */
                 if ((readcomm()) != 0)
                         ;

                 /* write characters to comm port for transmission */
                 if ((wrtcomm()) != 0)
                         ;

                 /* check communications port for receiption of data */
                 if ((readcomm()) != 0)
                         ;

                 /* check for screen output */
                 if ((wrtscr()) != 0)
                         ;

                 /* check communications port for receiption of data */
                 if ((readcomm()) != 0)
                         ;

                 /* check for keyboard entry */
                 if ((readkey()) != 0)
                         ;

         }
 }

 /*********************************************************************/
 /* Check the comm port for receiption of data and puts recieved data */
 /* into buffers.  Returns a -1 if error detected, 0 if no data, or   */
 /* the character received.                                           */
 /*                                                                   */
 int readcomm()
 {
         static char oldc = NULL;
         static char c;
         static int iret;

         /* check comm port for data receiption */
         iret = inp(lsr);
         if ((iret&1) != 0) {

                 /* ignore data overrun errors */
                 /* expect to loose padd characters at high baud rate */
                 if ((iret&2) != 0) {
                         ;

                 /* framing or parity error */
                 } else if ((iret&12) != 0) {
                         writes("\007*** data reception error ***");
                         return(-1);

                 /* break currenly being sent */
                 } else if ((iret&16) != 0) {
                         return(0);        /* break detect */
                 }

                 /* read character */
                 c = inp(rbr)&127;

                 /* process character */
                 if (c == XOFF) {
                         gotxoff = TRUE;
                 } else if (c == XON) {
                         gotxoff = FALSE;
                 } else if (c != NULL) {

                         /* prevent CR CR LF line endings */
                         if ((c != '\r') || (oldc != '\r')) {

                                 /* store character in receiption buffer */
                                 if ((putbuf(&crt,c)) == (-1)) {
                                         writes("\007*** screen buffer overflo
                                         return(-1);
                                 }

                                 /* store character if file receiption buffer
                                 if (inchan) {
                                         if ((putbuf(&mem,c)) == (-1)) {
                                                 writes("\007*** file receipti
                                                 inchan = FALSE;
                                                 return(-1);
                                         }
                                 }
                         }
                         oldc = c;
                 }
                 return(c);
         }

         /* no character found */
         return(0);
 }

 /*********************************************************************/
 /* write characters from the screen buffer to the screen.  Returns a */
 /* -1 if error occured, 0 if no characters in buffer, or character   */
 /* written.                                                          */
 /*                                                                   */
 int wrtscr()
 {
         static char c;
         static int i,iret;

         /* get character from screen buffer */
         if ((iret = getbuf(&crt)) != (-1)) {
                 c = iret&127;        /* strip parity */

                 /* if line feed then scroll screen */
                 if (c == '\n') {
                         if ((iret = doscr()) == (-1)) {
                                 return(-1);
                         }

                 /* handle tabs seperatly */
                 } else if (c == '\t') {
                         if ((iret = dotab()) == (-1)) {
                                 return(-1);
                         }

                 /* output other characters */
                 } else {
                         biostty(c);
                 }
                 return(c);
         }

         /* no character in buffer */
         return(0);
 }

 /*********************************************************************/
 /* scroll the screen up one line at a time while checking the comm   */
 /* port for data receiption.  Returns a -1 if an error occured.      */
 /*                                                                   */
 int doscr()
 {
         static char fillchar;
         static int trow,tlcol,brow,brcol;
         static int iret;

         /* initialize */
         fillchar = 0x20;        /* fill opened line with blanks */
         tlcol = 0;                /* top left column of window */
         brcol = 79;                /* bottom right column of window */

         /* begin check and scroll loop */
         for(trow=0;trow<24;trow++) {

                 /* check comm port for data receiption */
                 if ((iret = readcomm()) == (-1)) {
                         return(-1);
                 }

                 /* scroll 1 line up */
                 brow = trow + 1;
                 biosup(1,trow,tlcol,brow,brcol,fillchar);
         }

         return(0);
 }

 /*********************************************************************/
 /* Output a horizontal tab to screen while checking communications   */
 /* port for transmission.  Returns a -1 if an error occured.         */
 /*                                                                   */
 int dotab()
 {
         static int iret,irow,icol;

         /* check comm port for receiption of data */
         if ((iret = readcomm()) == (-1)) {
                 return(-1);
         }

         /* find cursor position */
         iret = biospos();
         icol = iret & 255;        /* column returned in low order bits */
         irow = iret >> 8;        /* row returned in high order bits */

         /* check comm port for receiption of data */
         if ((iret = readcomm()) == (-1)) {
                 return(-1);
         }

         /* calculate tab position */
         icol++;
         while ((icol % 8) != 0) {
                 icol++;
         }

         /* set cursor to that position */
         biosset(irow,icol);

         return(0);
 }

 /*********************************************************************/
 /* write characters to communications port for transmission.  Return */
 /* a -1 if error, 0 if no characters written, or character written.  */
 /*                                                                   */
 int wrtcomm()
 {
         static char c,pushback;
         static int iret,lstat;

         /* write characters to communications port for transmission */
         lstat=inp(lsr);
         if (((lstat&32) != 0) && (!gotxoff)) {

                 /* write characters received from keyboard */
                 if ((iret=getbuf(&com)) != (-1)) {
                         c = iret&127;
                         outp(thr,c);
                         if (lecho) putbuf(&crt,c);
                         return(c);

                 /* write characters from file */
                 } else if (outchan) {
                         if (pushback != NULL) {
                                 outp(thr,pushback);
                                 pushback = NULL;
                                 if (lecho) putbuf(&crt,pushback);
                                 return(pushback);
                         }

                         if ((iret=getbuf(&mem)) == (-1)) {
                                 outp(thr,CONZ);
                                 fclose(outchan);
                                 outchan = FALSE;
                                 mem.wbuf = mem.rbuf = mem.fbuf;
                                 return(0);
                         }

                         c = iret&127;
                         if (c == '\n') {
                                 outp(thr,'\r');
                                 if (lecho) {
                                         putbuf(&crt,'\r');
                                         putbuf(&crt,'\n');
                                 } else {
                                         dowait();
                                 }
                         } else {
                                 outp(thr,c);
                                 if (lecho) putbuf(&crt,c);
                         }
                         return(c);
                 }
         }

         return(0);
 }

 /*********************************************************************/
 /* Function to wait until the receiption of a line feed after the    */
 /* transmission of a carriage return.                                */
 /*                                                                   */
 int dowait()
 {
         int iret;

         /* loop */
         while ((iret=readcomm()) != '\n') {
                 if (iret == -1) break;
         }

         return(0);
 }

 /*********************************************************************/
 /* Check the keyboard for receipt of a character and buffer it.      */
 /* Returns a -1 if error occured, 0 if no character at keyboard, or  */
 /* character typed.                                                  */
 /*                                                                   */
 /* kbhit() is a special IBM-PC microsoft "C" function.               */
 /*                                                                   */
 int readkey()
 {
         static char c;

         /* check for keyboard entry */
         if (kbhit()) {
                 c = readc();

                 /* display menu if ESCAPE entered */
                 if (c == ESC) {
                         doesc();
                         return(c);
                 }

                 /* character mapping */
                 if (c == '\b') {
                         c = DEL;
                 } else if (c == '\n') {
                         c = '\r';
                 }

                 /* store character in keyboard buffer */
                 if (putbuf(&com,c) == (-1)) {
                         writes("\007");                /* buffer full */
                         return(-1);
                 }
                 return(c);
         }

         return(0);
 }

 /*********************************************************************/
 /* Write a character into a buffer.  Returns a -1 if overflow.       */
 /*                                                                   */
 int putbuf(p,c)
 struct buf *p;
 char c;
 {
         *p->wbuf = c;

         /* increment (possible wrap-around) pointer */
         if (++p->wbuf > p->lbuf) p->wbuf = p->fbuf;

         /* if overflow, indicate */
         if (p->wbuf == p->rbuf) {
                 if (--p->wbuf < p->fbuf) p->wbuf = p->lbuf;
                 return(-1);
         }

         return(0);
 }

 /*********************************************************************/
 /* Read a character from a buffer.  Returns a -1 if buffer is empty. */
 /*                                                                   */
 int getbuf(p)
 struct buf *p;
 {
         static int c;

         /* empty */
         if (p->rbuf == p->wbuf) return(-1);

         /* get char, increment (possible wrap-around) pointer */
         c = *p->rbuf;
         if (++p->rbuf > p->lbuf) p->rbuf = p->fbuf;

         return(c);
 }

 /*********************************************************************/
 /* Function to do special features.                                  */
 /*                                                                   */
 int doesc()
 {
         char ans[3],memsiz[6];
         char c;
         int iret,ians;

         /* output special information */
         loop:
         escreen(2);                /* erase screen */

         writes("\r\n memory buffer is : ");
         sprintf(memsiz,"%u",(mem.wbuf-mem.fbuf));
         writes(memsiz);
         writes("/");
         sprintf(memsiz,"%u",(mem.lbuf-mem.fbuf));
         writes(memsiz);

         writes("\r\n receive file is  : ");
         writes((inchan)?infil:"<OFF>");

         writes("\r\n transmit file is : ");
         writes((outchan)?outfil:"<OFF>");

         writes("\r\n local echo is    : ");
         writes((lecho)?"<ON>":"<OFF>");

         /* output menu and accept choice */
         if ((ians=chosit("comm",ans,sizeof(ans))) == (-1)) {
                 writes("\r\n\007*** error displaying menu ***");
                 ians = 4;
         }

         /* execute command */
         switch (ians) {

                 case 5:
                         if (inchan) {
                                 wrtbuf();
                                 fclose(inchan);
                         }
                         if (outchan) fclose(outchan);
                         outp(mcr,0);        /* drop DTR and RTS */
                         writes("\r\n");
                         exit();
                         break;

                 case 4:
                         cursor(25,1);
                         writes("\r\n*** you are now back as a terminal ***\r\
                         return(0);
                         break;

                 case 3:
                         lecho = !lecho;
                         break;

                 case 2:
                         if (outchan) {
                                 fclose(outchan);
                                 outchan = FALSE;
                                 mem.wbuf = mem.rbuf = mem.fbuf;
                         } else {
                                 if (inchan) {
                                         wrtbuf();
                                         fclose(inchan);
                                         inchan = FALSE;
                                 }
                                 sendfile:
                                 writes("\r\n\nFilename? ");
                                 reads(outfil,sizeof(outfil));
                                 if (outfil[0] == NULL) goto done;

                                 if ((outchan=fopen(&outfil[0],"r")) == NULL)
                                         writes("\007  *** can't open file ***
                                         goto sendfile;
                                 }

                                 readbuf();
                         }
                         break;

                 case 1:
                         if (inchan) {
                                 wrtbuf();
                                 fclose(inchan);
                                 inchan = FALSE;
                         } else {
                                 if (outchan) {
                                         fclose(outchan);
                                         outchan = FALSE;
                                         mem.wbuf = mem.rbuf = mem.fbuf;
                                 }
                                 savefile:
                                 writes("\r\n\nFilename? ");
                                 reads(infil,sizeof(infil));
                                 if (infil[0] == NULL) goto done;

                                 if ((inchan=fopen(&infil[0],"w")) == NULL) {
                                         writes("\007  *** can't open file ***
                                         goto savefile;
                                 }
                         }
                         break;

         }
         done:
         goto loop;
 }

 /*********************************************************************/
 /* Function to write the data receiption buffer to output file.      */
 /*                                                                   */
 int wrtbuf()
 {
         for (mem.rbuf=mem.fbuf;mem.rbuf<mem.wbuf;mem.rbuf++) {
                 fputc(*mem.rbuf,inchan);
         }

         mem.wbuf = mem.rbuf = mem.fbuf;
         return(0);
 }

 /*********************************************************************/
 /* Function to read a file into the file transmission buffer.        */
 /* Returns a 0 if successful, or a -1 if buffer overflow.            */
 /*                                                                   */
 int readbuf()
 {
         static char c;
         static int iret;

         /* loop until end-of-file is found */
         while ((iret=getc(outchan)) != EOF) {
                 c = iret&127;
                 if ((putbuf(&mem,c)) == (-1)) {
                         writes("\r\n\007*** file transmission buffer overflow
                         return(-1);
                 }
         }

         return(0);
 }


 IEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\IEX.C

 /* SDB - import/export command routines */

 #include "stdio.h"
 #include "sdbio.h"

 extern int dbv_token;
 extern char dbv_tstring[];
 extern int dbv_tvalue;

 /* db_import - import tuples from a file */
 int *db_import(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct scan *sptr;
     struct attribute *aptr;
     char fname[STRINGMAX+1],avalue[STRINGMAX+1];
     int tcnt,astart,i,eofile;
     FILE *fp;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* checks for "<filename> into <relation-name>" */
     if (db_ntoken() == ID)
         strcat(dbv_tstring,".dat");
     else if (dbv_token != STRING)
         return (db_ferror(SYNTAX));
     strcpy(fname,dbv_tstring);
     if (db_ntoken() != INTO)
         return (db_ferror(SYNTAX));
     if (db_ntoken() != ID)
         return (db_ferror(SYNTAX));

     /* open the relation */
     if ((sptr = db_ropen(dbv_tstring)) == NULL)
         return (FALSE);

     /* open the input file */
     if ((fp = fopen(fname,"r")) == NULL)
         return (db_ferror(INPFNF));

     /* import tuples */
     eofile = FALSE;
     for (tcnt = 0; ; tcnt++) {

         /* get attribute values */
         astart = 1;
         for (i = 0; i < NATTRS; i++) {

             /* get a pointer to the current attribute */
             aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

             /* check for the last attribute */
             if (aptr->at_name[0] == 0)
                 break;

             /* input the tuple */
             if (fgets(avalue,STRINGMAX,fp) == 0) {
                 eofile = TRUE;
                 break;
             }
             avalue[strlen(avalue)-1] = EOS;

             /* store the attribute value */
             db_aput(aptr,&sptr->sc_tuple[astart],avalue);

             /* update the attribute start */
             astart += aptr->at_size;
         }

         /* store the new tuple */
         if (!eofile) {
             if (!db_rstore(sptr)) {
                 db_rclose(sptr);
                 return (FALSE);
             }
         }
         else
             break;
     }

     /* close the relation */
     db_rclose(sptr);

     /* close the input file */
     fclose(fp);

     /* check number of tuples imported */
     if (tcnt != 0) {

         /* print tuple count */
         printf("[ %d imported ]\n",tcnt);
     }
     else
         printf("[ none imported ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* db_export - export tuples to a file */
 int *db_export(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct scan *sptr;
     struct attribute *aptr;
     char rname[STRINGMAX+1],avalue[STRINGMAX+1];
     int tcnt,astart,i;
     FILE *fp;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* checks for "<relation-name> [ into <filename> ]" */
     if (db_ntoken() != ID)
         return (db_ferror(SYNTAX));
     strcpy(rname,dbv_tstring);
     if (!db_to(&fp,".dat"))
         return (FALSE);

     /* open the relation */
     if ((sptr = db_ropen(rname)) == NULL)
         return (FALSE);

     /* export tuples */
     for (tcnt = 0; db_rfetch(sptr); tcnt++) {

         /* get attribute values */
         astart = 1;
         for (i = 0; i < NATTRS; i++) {

             /* get a pointer to the current attribute */
             aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

             /* check for the last attribute */
             if (aptr->at_name[0] == 0)
                 break;

             /* get the attribute value */
             db_aget(aptr,&sptr->sc_tuple[astart],avalue);

             /* output the tuple */
             fprintf(fp,"%s\n",avalue);

             /* update the attribute start */
             astart += aptr->at_size;
         }
     }

     /* close the relation */
     db_rclose(sptr);

     /* close the output file */
     if (fp != stdout)
         fclose(fp);

     /* check number of tuples exported */
     if (tcnt != 0) {

         /* print tuple count */
         printf("[ %d exported ]\n",tcnt);
     }
     else
         printf("[ none exported ]\n");

     /* return successfully */
     return (TRUE);
 }

 /* db_squeeze - squeeze deleted tuples from a relation file */
 int *db_squeeze(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct scan *sptr;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* checks for "<relation-name>" */
     if (db_ntoken() != ID)
         return (db_ferror(SYNTAX));

     /* open the relation */
     if ((sptr = db_ropen(dbv_tstring)) == NULL)
         return (FALSE);

     /* compress the relation file */
     if (!db_rcompress(sptr)) {
         db_rclose(sptr);
         return (FALSE);
     }

     /* close the relation */
     db_rclose(sptr);

     /* return successfully */
     return (TRUE);
 }

 /* db_extract - extract a relation definition */
 int *db_extract(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct scan *sptr;
     struct attribute *aptr;
     char rname[STRINGMAX+1],aname[ANSIZE+1],*atype;
     int i;
     FILE *fp;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* checks for "<relation-name> [ into <filename> ]" */
     if (db_ntoken() != ID)
         return (db_ferror(SYNTAX));
     strcpy(rname,dbv_tstring);
     if (!db_to(&fp,".def"))
         return (FALSE);

     /* open the relation */
     if ((sptr = db_ropen(rname)) == NULL)
         return (FALSE);

     /* output the relation definition */
     fprintf(fp,"create %s (\n",rname);

     /* get attribute values */
     for (i = 0; i < NATTRS; i++) {

         /* get a pointer to the current attribute */
         aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

         /* check for the last attribute */
         if (aptr->at_name[0] == 0)
             break;

         /* get the attribute name */
         stccpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;

         /* determine the attribute type */
         switch (aptr->at_type) {
         case TCHAR:
                 atype = "char";
                 break;
         case TNUM:
                 atype = "num";
                 break;
         default:
                 atype = "<error>";
                 break;
         }

         /* output the attribute definition */
         if (strlen(aname) < 8)
             fprintf(fp,"\t%s\t\t%s\t%d\n",aname,atype,aptr->at_size);
         else
             fprintf(fp,"\t%s\t%s\t%d\n",aname,atype,aptr->at_size);
     }

     /* output the relation size */
     fprintf(fp,") %d\n",sptr->sc_relation->rl_tmax);

     /* close the relation */
     db_rclose(sptr);

     /* close the output file */
     if (fp != stdout)
         fclose(fp);

     /* return successfully */
     return (TRUE);
 }



 IFELSE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\IFELSE.C

                                          /* Chapter 3 - Program 4 */
 /* This is an example of the if and the if-else statements */

 main()
 {
 int data;

    for(data = 0;data < 10;data = data + 1) {

       if (data == 2)
          printf("Data is now equal to %d\n",data);

       if (data < 5)
          printf("Data is now %d, which is less than 5\n",data);
       else
          printf("Data is now %d, which is greater than 4\n",data);

    }  /* end of for loop */
 }


 IMPURE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\IMPURE.C

 /*
  * impure.c  -- Impure data for ytab.c and min.c
  *
  * Created 02-Dec-80 Bob Denny -- Impure data from ytab.c and min.c moved
  *                                                                     here s
  * More    19-Mar-82 Bob Denny -- New C library & compiler
  * More           20-Nov-83 Scott Guthery -- Adapt for IBM PC & DeSmet C
  */

 #include <stdio.h>
 #include "lexlex.h"
 #include "ytab.h"

 /*
  * min's
  */
 struct set **oldpart;
 int **newpart;
 int nold;
 int nnew;

 /*
  * ytab's
  */

 struct nlist {
         struct  nlist   *nl_next;
         struct  nfa     *nl_base;
         struct  nfa     *nl_end;
         struct  nfa     *nl_start;
         struct  nfa     *nl_final;
              } *nlist;

 #ifndef YYSTYPE
 #define YYSTYPE int
 #endif

 YYSTYPE yyval = 0;
 YYSTYPE *yypv;
 YYSTYPE yylval = 0;

 int nlook = 0;
 int yyline = 0;
 char *breakc;
 char *ignore;
 char *illeg;

 char buffer[150];
 int str_length;

 char ccl[(NCHARS+1)/NBPC];

 /*
  * Copied from ytab.c just before yyparse() ... kludgy.
  */
 #define YYMAXDEPTH 150

 /*
  * These are impure data for the parser driver yyparse().
  */

 int yydebug = 0;                /* Make this 1 for yyparse() debugging  */
 YYSTYPE yyv[YYMAXDEPTH];
 int yychar = -1;

 int yynerrs = 0;
 int yyerrflag = 0;



 INDEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INDEX.C

 /*
    This program indexes a text file.
    author: Greg Haley
    revision date: 04/02/85
    A text file containing a word list is used as input.
    Each word to index on is on a seperate line. Example:
            byte
              directive
             SAMPLE
    An index file will be created using the words byte, directive, and sample
    to index on. The words may be entered in upper or lower case.
    Pages are seperated by the ^L character (ASCII form feed) in the original
    text.

    Usage: index input_pathname output_pathname wordlist_pathname
 */

 #include <stdio.h>

 version "1.00"        /* Current version */
 w_length 30           /* Maximum # of chars in a word
                                 Be sure to change fscanf statement in the
                            function get_list to match this number */

 n_words 250        /* Maximum # of words to index on */
 max_num 20        /* Maximum # of pages per word */
 page_width 72   /* Number of columns to use for output */
 form_feed 12        /* ASCII form feed character */
 space 32            /* ASCII space character */


 /* Global Variables */
 char words [n_words] [w_length+1];        /* word list */
 int w_page [n_words] [max_num];                /* page numbers */
 int w_count [n_words];                        /* count of page numbers */
 int page;                                /* page counter */
 int num_words;                          /* actual number of words to index */
 char new_word [w_length+1];                /* buffer for 1 word */

 /* Main Program */
 main(argc, argv)
 int argc;
 char *argv[];
 {
         FILE *infile, *outfile, *wordlist, *fopen();
         int a, b, i, n;

   /* initialize */
   fprintf(stderr, "INDEX v%s by Greg Haley\n\n", version);

   for (a=0; a <= n_words; a++) {
     for (b=0; b <= w_length; b++) words [a] [b] = '\0';
   }

   for (a=0; a <= n_words; a++) {
     for (b=0; b <= max_num; b++) w_page [a] [b] = 0;
   }

   for (a=0; a <= max_num; a++) w_count [a] = 0;
   for (a=0; a <= max_num; a++) new_word [a] = '\0';

   /* open files */
   if (argc != 4) { /* wrong number of args; exit */
     fprintf(stderr, "Usage: index input_pathname output_pathname");
     fprintf(stderr, " wordlist_pathname\n\n");
     fprintf(stderr, "Maximum word length is %d characters\n", w_length);
     fprintf(stderr, "Maximum number of words is %d\n", n_words);
     fprintf(stderr, "Maximum number of pages per word is %d\n", max_num);
     exit(1);
   } else if ((infile = fopen(argv[1], "r")) == NULL) {
     fprintf(stderr, "Can't open input file.\n");
     exit(1);
   } else if ((outfile = fopen(argv[2], "w")) == NULL) {
     fprintf(stderr, "Can't open output file.\n");
     exit(1);
   } else if ((wordlist = fopen(argv[3], "r")) == NULL) {
     fprintf(stderr, "Can't open word list file.\n");
     exit(1);
   } else {

     /* Echo pathnames */
     fprintf(stderr, "Input pathname is %s\n", argv[1]);
     fprintf(stderr, "Output pathname is %s\n", argv[2]);
     fprintf(stderr, "Word list pathname is %s\n\n", argv[3]);

     /* Read word list */
     num_words = get_list(wordlist); /* Side effects changes global variables

     /* convert word list to lower case */
     for (a=1; a <= num_words; a++)
       for (b=0; words [a] [b] != '\0'; b++)
         if ((words [a] [b] >= 'A') && (words [a] [b] <= 'Z'))
           words [a] [b] += 32;

     /* sort word list */
     for (a=1; a < num_words; a++) {
       for (b=a+1; b <= num_words; b++) {
         if ((strcmp (words [a], words [b])) > 0) {
           for (n=0; n <= w_length; n++) {  /* Words [0] is temporary var */
             words [0] [n] = words [a] [n];
             words [a] [n] = words [b] [n];
             words [b] [n] = words [0] [n];
           }
         }
       }
     }

     /* index and write file */
     if (num_words == 0) {
       fprintf (stderr, "No words found in word list file.\n");
       exit(1);  /* Exit program if no words found */
     } else {
       fprintf (stderr, "%d words found in word list file.\n", num_words);
       index_it (infile);  /* Side effects change several global variables */
       print_it (outfile); /* Side effects change several global variables */
     }

     /* close files */
     fclose(infile);
     fclose(outfile);
     fclose(wordlist);
   }

   /* Normal exit */
   exit(0);
 }


 /* Function to get word list. Global variable words is accessed */
 /* Returns number of words found */
 get_list (fp)
 FILE *fp;
 {
     int a, c;

   a = 1;
   while (((fscanf(fp, "%30s", words[a])) != EOF) && (a < n_words)) a++;
   return (a-1);
 }


 /* Search input file and build index arrays. */
 /* All global variables accessed */
 index_it (fp)
 FILE *fp;
 {
         int a, no_match;
         char c;

   page = 1;
   while ((next_word(fp)) != EOF) {
     a = 0;
     no_match = 0;
     while ((a < num_words) && (no_match == 0)) {
       a++;
       if ((strcmp (new_word, words [a])) == 0) {
         no_match++;
         if (w_page [a] [w_count[a]] != page) {
           if (w_count [a] == max_num)
           fprintf(stderr, "number of pages exceeded for word %s\n", words [a]
           else w_count [a]++;
           w_page [a] [w_count[a]] = page;
         }
       }
     }
   }

   return (0);
 }


 /* Get next word from input file. */
 /* Increment page number if form feed encountered. */
 /* Returns the length of the string or EOF if error or EOF encountered. */
 /* Global variables new_word and page accessed. */
 next_word (fp)
 FILE *fp;
 {
         int a, c;

   /* skip white spaces */
   do {
     c = fgetc(fp);
     if (c == form_feed) page++;  /* increment page number */
   } while ((c <= space) && (c != EOF));
   if (c != EOF) {
     a = 0;
     if ((c >= 'A') && (c <= 'Z')) c += 32;  /* convert to lower case */
     new_word [a] = c;

     /* put chars in string until white space encountered */
     do {
       c = fgetc(fp);
       if ((c > space) && (c != EOF)) {
         a++;
         if ((c >= 'A') && (c <= 'Z')) c += 32;  /* convert to lower case */
         new_word [a] = c;
       } else if (c == form_feed) page++;  /* increment page number */
     } while ((c > space) && (c != EOF) && (a < w_length));
     a++;
     new_word [a] = '\0';  /* don't forget trailing null */
   }
   if (c == EOF) return (EOF); else return (a-1);
 }


 /* Print index from arrays */
 /* Global variables accessed but NOT altered. */
 print_it (fp)
 FILE *fp;
 {
         int a, b, i, limit;
   a =0;
   while (a < num_words) {
     a++;
     if (w_count [a] > 0) {
       fprintf (fp, "%s ", words [a]);
       limit = page_width - (strlen (words [a])) - (w_count [a] * 4);
       for (i=1; i <= limit; i++) fprintf (fp, "%c", '.');
       for (b=1; b <= w_count [a]; b++) {
         fprintf (fp, "%3d", w_page [a] [b]);
         if (b < w_count [a]) fprintf (fp, ",");
       }
       fprintf (fp, "\n");
     }
   }

   return (0);
 }


 INDEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\INDEX.C

 /* 1.1  01-08-86                                                (index.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 index(s, c)                /* return pointer to char c in string s, if it
                            occurs, NULL otherwise.                        */
 /*----------------------------------------------------------------------*/
 STRING s;
 {
         int i;

         while ((i = *s) AND c ISNT i)
                 s++;
         return (*s ? s : NULL);
 }


 INFERENC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\INFERENC.C

 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /*******************************************************************
 **
 **        inference engine main routine
 **
 *******************************************************************/

 #include <stdio.h>
 #include <string.h>

 #include "expert.h"
 #include "routine.h"

 #define        MAX_KNOWN        100

 int        numHypot, hypStack[MAX_HYPS],strBuffOfst ;
 char        strBuff[MAX_STRING_BUFF] ;
 int        ruleBuffOfst ;
 int        knownTrue[MAX_KNOWN], knownFalse[MAX_KNOWN] ;
 int        numTrue, numFalse ;
 struct  rule_statement_r ruleBuff[MAX_RULE_STATEMENTS] ;

 int        main(argc,argv)
 int argc ;
 char **argv ;

 {
 int        i,consequent ;
 int        proved ;
 int        p_value ;
 FILE        *infile ;

 for( proved = 0; proved < MAX_STRING_BUFF; proved ++ )
         strBuff[proved] = 0 ;

 proved = FALSE ;

 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP argc=%d ",argc) ;
 #endif

 if(argc != 2 )
         {
         fprintf(stdout, "\n\n Usage: inference in.file \n " ) ;
         exit(RETURN_ROUTINE_FALSE) ;
         }
 infile = fopen( argv[1], "rb" );
 if(infile == NULL)
         {
         fprintf(stdout,"\n\n Cannot open input file %s \n ", argv[1]);
         exit(RETURN_ROUTINE_FALSE) ;
         }
 for(i=0;i<MAX_KNOWN;i++)
         knownTrue[i]=knownFalse[i]=0 ;
 /*
 **
 **        read in the compiled rules
 **
 */

 fread(&numHypot,sizeof(int),1,infile) ;
 fread(hypStack,sizeof(int),numHypot,infile) ;
 fread(&ruleBuffOfst,sizeof(int),1,infile) ;
 fread(ruleBuff,2*sizeof(int),ruleBuffOfst,infile) ;
 fread(&strBuffOfst,sizeof(int),1,infile) ;
 fread(strBuff,1,strBuffOfst,infile) ;

 #ifdef        DEBUG

 printf("\nDEBUG-main, numHypot = %d",numHypot) ;
 for(i=0;i<numHypot;i++)
         {
         printf("\nDEBUG-main, consequent[%d]= %d, string=%s",i,hypStack[i],
                         &strBuff[(ruleBuff[hypStack[i]].string)] ) ;
         }
 printf("\nDEBUG-main, number of rules = %d",ruleBuffOfst) ;
 printf("\nDEBUG-main, number of bytes in stringbuffer=%d",strBuffOfst) ;
 for(i=0;i<ruleBuffOfst;i++)
         {
         if(ruleBuff[i].flag !=0)
                 {
                 printf("\nDEBUG-main, rule[%d].flag=%d, rule[%d].string= %d->
                           ,i,ruleBuff[i].flag,i,ruleBuff[i].string,&strBuff[r
                 }
         }
 printf("\n") ;

 #endif

 for( i=0 ; i < numHypot ; i++ )

         {
         consequent = hypStack[i] ;

 #ifdef DEBUG
         printf("\nDEBUG-main, consequent = %d ",consequent ) ;
 #endif

         if(weKnow(consequent,&p_value) == TRUE)
                 {
 #ifdef DEBUG
         printf("\nDEBUG-main, we knew this consequent was ") ;
         if(p_value == TRUE)
                 printf("-- TRUE") ;
         else
                 printf("-- FALSE") ;
 #endif
                 continue ;
                 }

         if ( verify(consequent) == TRUE )
                 {

 #ifdef DEBUG
                         printf("\nDEBUG-main, consequent verified TRUE " ) ;
 #endif

                 if( (ruleBuff[consequent].flag == ROUTINE_TRUE) ||
                         (ruleBuff[consequent].flag == ROUTINE_TRUE_HYP) )
                         {
                         if(weKnow(consequent,&p_value) == TRUE)
                                 continue ;
 #ifdef DEBUG
                         printf("\nRuning Routine %s",&strBuff[ruleBuff[conseq
 #endif
                         if (runRoutine(consequent) == TRUE)
                                 {
                                 knownTrue[numTrue++]=ruleBuff[consequent].str
 #ifdef DEBUG
                                 printf(" -- TRUE\n") ;
 #endif
                                 if(ruleBuff[consequent].flag == ROUTINE_TRUE_
                                         {
                                         printf("\nCONCLUSION\n") ;
                                         exit(RETURN_ROUTINE_TRUE) ;
                                         }
                                 }
                         else
                                 {
                                 knownFalse[numFalse++]=ruleBuff[consequent].s
 #ifdef DEBUG
                                 printf(" -- FALSE\n") ;
 #endif
                                 }
                         }
                 else
                         {
                         knownTrue[numTrue++]=ruleBuff[consequent].string ;
                         proved = TRUE ;
                         printf("\nI infer that : %s\n",&strBuff[ruleBuff[cons
                         if(ruleBuff[consequent].flag == STRING_TRUE_HYP)
                                 {
                                 printf("\nCONCLUSION\n") ;
                                 exit(RETURN_ROUTINE_TRUE) ;
                                 }
                         }
                 }
         else
                 {
 #ifdef DEBUG
                         printf("\nDEBUG-main, consequent not proved " ) ;
 #endif
                 }
         }
 if(proved == FALSE)
         {
         printf("\n I can't prove anything\n") ;
         exit(RETURN_ROUTINE_FALSE) ;
         }
 exit(RETURN_ROUTINE_TRUE) ;
 }

 /* --<<hidden tof */

 /******************************************************
 **
 **        known(hypot,knownFile,numKnown)
 **
 **        checks to see if hypot is in the stack knownFile of length
 **                numKnown
 **
 **        returns true if known, false otherwise
 **
 ******************************************************/



 known(hypot,knownFile,numKnown)
         int         hypot,numKnown ;
         int        knownFile[] ;
 {
 int i ;
 for (i = 0 ; i < numKnown ; i++ )
         if (ruleBuff[hypot].string == knownFile[i] )
                 return(TRUE) ;
 return(FALSE) ;
 }




 INIT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\INIT.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"
 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 doinit(sp)
 SYM     *sp;
 {       dseg();                 /* initialize into data segment */
         nl();                   /* start a new line in object */
         if(sp->storage_class == sc_static)
                 put_label(sp->value.i);
         else
                 gen_strlab(sp->name);
         if( lastst != assign)
                 genstorage(sp->tp->size);
         else    {
                 getsym();
                 inittype(sp->tp);
                 }
         endinit();
 }

 int     inittype(tp)
 TYP     *tp;
 {       int     nbytes;
         switch(tp->type) {

                 case bt_char:
                         nbytes = initchar();
                         break;
                 case bt_short:
                 case bt_enum:
                         nbytes = initshort();
                         break;
                 case bt_pointer:
                         if( tp->val_flag)
                                 nbytes = initarray(tp);
                         else
                                 nbytes = initpointer();
                         break;
                 case bt_long:
                         nbytes = initlong();
                         break;
                 case bt_struct:
                         nbytes = initstruct(tp);
                         break;
                 default:
                         error(ERR_NOINIT);
                         nbytes = 0;
                 }
         return nbytes;
 }

 initarray(tp)
 TYP     *tp;
 {       int     nbytes;
         char    *p;
         nbytes = 0;
         if( lastst == begin) {
                 getsym();               /* skip past the brace */
                 while(lastst != end) {
                         nbytes += inittype(tp->btp);
                         if( lastst == comma)
                                 getsym();
                         else if( lastst != end)
                                 error(ERR_PUNCT);
                         }
                 getsym();               /* skip closing brace */
                 }
         else if( lastst == sconst && tp->btp->type == bt_char) {
                 nbytes = strlen(laststr) + 1;
                 p = laststr;
                 while( *p )
                         genbyte(*p++);
                 genbyte(0);
                 getsym();
                 }
         else if( lastst != semicolon)
                 error(ERR_ILLINIT);
         if( nbytes < tp->size) {
                 genstorage( tp->size - nbytes);
                 nbytes = tp->size;
                 }
         else if( tp->size != 0 && nbytes > tp->size)
                 error(ERR_INITSIZE);    /* too many initializers */
         return nbytes;
 }

 initstruct(tp)
 TYP     *tp;
 {       SYM     *sp;
         int     nbytes;
         needpunc(begin);
         nbytes = 0;
         sp = tp->lst.head;      /* start at top of symbol table */
         while(sp != 0) {
                 while(nbytes < sp->value.i)     /* align properly */
                         nbytes += genbyte(0);
                 nbytes += inittype(sp->tp);
                 if( lastst == comma)
                         getsym();
                 else if(lastst == end)
                         break;
                 else
                         error(ERR_PUNCT);
                 sp = sp->next;
                 }
         if( nbytes < tp->size)
                 genstorage( tp->size - nbytes);
         needpunc(end);
         return tp->size;
 }

 initchar()
 {       genbyte(intexpr());
         return 1;
 }

 initshort()
 {       genword(intexpr());
         return 2;
 }

 initlong()
 {       genlong(intexpr());
         return 4;
 }

 initpointer()
 {       SYM     *sp;
         if(lastst == and) {     /* address of a variable */
                 getsym();
                 if( lastst != id)
                         error(ERR_IDEXPECT);
                 else if( (sp = gsearch(lastid)) == 0)
                         error(ERR_UNDEFINED);
                 else    {
                         getsym();
                         if( lastst == plus || lastst == minus)
                                 genref(sp,intexpr());
                         else
                                 genref(sp,0);
                         if( sp->storage_class == sc_auto)
                                 error(ERR_NOINIT);
                         }
                 }
         else if(lastst == sconst) {
                 gen_labref(stringlit(laststr));
                 getsym();
                 }
         else
                 genlong(intexpr());
         endinit();
         return 4;       /* pointers are 4 bytes long */
 }

 endinit()
 {       if( lastst != comma && lastst != semicolon && lastst != end) {
                 error(ERR_PUNCT);
                 while( lastst != comma && lastst != semicolon && lastst != en
                         getsym();
                 }
 }



 INITAGE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\INITAGE.C

 /****************************************************************/
 /* INITAGE.C - From page 295 of the book "Microsoft C Program-  */
 /* ming for the IBM by Robert Lafore. This is a continuation of */
 /* a simple database program developed from page 292 to         */
 /* the end of the chapter (9).                                  */
 /****************************************************************/

 struct personnel {
    char name [30];
    int agnumb;
 };

 struct personnel agent1 = {
    "Harrison Tweedbury", 012 };
 struct personnel agent2 = {
    "James Bond", 007 };

 main()
 {
    printf("\nList of agents:\n\n");
    printf("   Name: %s\n", agent1.name);
    printf("   Agent number: %03d\n", agent1.agnumb);
    printf("   Name: %s\n", agent2.name);
    printf("   Agent number: %03d\n", agent2.agnumb);
 }




 INITARGS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\INITARGS.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 #define        REDIRECT
 /*
  *        Since the operating system and many shells don't do i/o
  *        redirection like they should, this #define includes code
  *        to handle redirection during argument processing.  If
  *        you don't want this to happen, #undef REDIRECT
  */

 extern char        *_base;
 extern int        _argc;
 extern char        **_argv;
 extern char        *_envp;

 static char        args[512];                /* argc/argv buffer */

 void _initargs(cmdline, cmdlen)
 register char *cmdline;
 register int cmdlen;
 /*
  *        Process command line and retrieve the environment string.  This
  *        function is responsible for allocating space to hold the parsed
  *        command line arguments, etc.  Values to be passed to the user's
  *        main() function are stored in the global variables "_argc",
  *        "_argv" and "_envp".  _main() initiallizes these variables to
  *        indicate that no arguments are available.  If a program doesn't
  *        use command line arguments or the environment string, an
  *        _initargs() function, which does nothing, should be defined in
  *        the module containing main().  This will result in a smaller
  *        executable size and a smaller run-time image.
  */
 {
         register char *p, **q;
         register int i, j, n;
         char *t, *strtok();

         /* process command line args */
         if(q = p = args) {
                 n = 1;
                 p += 256;
                 _argv = q;
                 *q++ = p;
                 t = *((char **) (_base + 0x24));        /* parent's basepage
                 t = *((char **) (t + 0x20));                /* dta buffer */
                 t += 30;                                /* name field */
                 while(*p++ = *t++)                        /* make argv[0] */
                         ;
                 for(t=p; cmdlen--; *p++ = *cmdline++)
                         ;
                 *p = '\0';
                 p = strtok(t, " \t");
                 while(p) {
 #ifdef REDIRECT
                         switch(*p) {
                                 case '<':        /* redirect stdin */
                                         i = open(++p, _OPNr);
                                         if(i < 0) {
                                                 Cconws("Can't open ");
                                                 Cconws(p);
                                                 Cconws(" as stdin.\r\n");
                                                 exit(ERROR);
                                         }
                                         stdin->F_h = i;
                                         stdin->F_stat &= ~F_DEVICE;
                                         break;
                                 case '>':        /* redirect stdout */
                                         j = FALSE;
                                         if(*++p == '>') {        /* append */
                                                 i = open(++p, _OPNw);
                                                 j = TRUE;
                                         }
                                         else
                                                 i = creat(p, _CRErw);
                                         if(i < 0) {
                                                 Cconws("Can't open ");
                                                 Cconws(p);
                                                 Cconws(" as stdout.\r\n");
                                                 exit(ERROR);
                                         }
                                         if(j)
                                                 lseek(i, 0L, _LSKend);
                                         stdout->F_h = i;
                                         stdout->F_stat &= ~F_DEVICE;
                                         break;
                                 default:        /* normal argument */
                                         ++n;
                                         *q++ = p;
                         }
 #else
                         ++n;
                         *q++ = p;
 #endif
                         p = strtok(NULL, " \t");
                 }
                 _argc = n;
         }
 }

 /*------------------------------------------------------------------------*/
 /*        The following are alternate _initargs() implementations,          *
 /*        each of which has certain features that may be useful in          *
 /*        various applications.                                -Dal
 /*------------------------------------------------------------------------*/

 #ifdef NEVER

 /*
  *        This _initargs() function implements redirection and wildcard
  *        filename expansion, and allocates space for arguments dynamically.
  *        It does not support quoting of any kind.  This should be added.
  *                                                -Dal  (10/01/87)
  */

        ARGLIMIT        64                /* maximum number of arguments */
        WILDCARD        TRUE                /* expand wildcards */

 extern char        *_base;
 extern int        _argc;
 extern char        **_argv;
 extern char        *_envp;

 static char        *args[ARGLIMIT];        /* argv pointer buffer */

 void _initargs(cmdline, cmdlen)
 char *cmdline;
 int cmdlen;
 /*
  *        Process command line, handling redirection and wildcards.  This
  *        function is responsible for allocating space to hold the parsed
  *        command line arguments, etc.  Values to be passed to the user's
  *        main() function are stored in the global variables "_argc",
  *        "_argv" and "_envp".
  */
 {
     register char *p, **q, *s;
     register int i, j, n;
     STAT dir, *oldirp;
     char tmp[128];
     char *strtok(), *strdup(), *strrpbrk();

     /* process command line args */
     if(q = args) {
         n = 1;
         _argv = q;
         s = *((char **) (_base + 0x24));        /* parent's basepage */
         s = *((char **) (t + 0x20));                /* dta buffer */
         s += 30;                                /* name field */
         *q++ = strdup(s);                        /* make argv[0] */
         cmdline[cmdlen] = '\0';
         p = strtok(cmdline, " \t");
         while(p && (n < ARGLIMIT)) {
             switch(*p) {
                 case '<':        /* redirect stdin */
                         i = open(++p, _OPNr);
                         if(i < 0) {
                                 Cconws("Can't open ");
                                 Cconws(p);
                                 Cconws(" as stdin.\r\n");
                                 exit(ERROR);
                         }
                         stdin->F_h = i;
                         stdin->F_stat &= ~F_DEVICE;
                         break;
                 case '>':        /* redirect stdout */
                         j = FALSE;
                         if(*++p == '>') {        /* append */
                                 i = open(++p, _OPNw);
                                 j = TRUE;
                         }
                         else
                                 i = creat(p, _CRErw);
                         if(i < 0) {
                                 Cconws("Can't open ");
                                 Cconws(p);
                                 Cconws(" as stdout.\r\n");
                                 exit(ERROR);
                         }
                         if(j)
                                 lseek(i, 0L, _LSKend);
                         stdout->F_h = i;
                         stdout->F_stat &= ~F_DEVICE;
                         break;
                 default:
 #ifdef WILDCARD
                         if(strchr(p, '*') || strchr(p, '?')) {
                                 oldirp = Fgetdta();
                                 Fsetdta(&dir);
                                 if(Fsfirst(p, 0x00) == 0) {
                                         if(s = strrpbrk(p, ":\\"))
                                                 *++s = '\0';
                                         else
                                                 *p = '\0';
                                         do {
                                                 ++n;
                                                 strcpy(tmp, p);
                                                 strcat(tmp, dir.S_name);
                                                 *q++ = strdup(tmp);
                                         } while(Fsnext() == 0);
                                 }
                                 Fsetdta(oldirp);
                         }
                         else {                        /* normal argument */
                                 ++n;
                                 *q++ = strdup(p);
                         }
 /* !WILDCARD */
                         ++n;
                         *q++ = strdup(p);
 /* WILDCARD */
             }
             p = strtok(NULL, " \t");
         }
         _argc = n;
     }
 }

 /* NEVER */


 INMEM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\INMEM.C

                                           /* Chapter 9 - Program 6 */
 main()
 {
 int numbers[5], result[5], index;
 char line[80];

    numbers[0] = 74;
    numbers[1] = 18;
    numbers[2] = 33;
    numbers[3] = 30;
    numbers[4] = 97;

    sprintf(line,"%d %d      %d %d %d\n",numbers[0],numbers[1],
            numbers[2],numbers[3],numbers[4]);

    printf("%s",line);

    sscanf(line,"%d %d %d %d      %d",&result[4],&result[3],
            (result+2),(result+1),result);


    for (index = 0;index < 5;index++)
       printf("The final result is %d\n",result[index]);

 }


 INPATH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\INPATH.C

 /*
 **                INPATH UTILITY
 ** This is a program similar to many "filefind" programs, except that
 ** it works like the UNIX "whereis" command.  The command line argument
 ** (only one, please) is taken to be the name of an executable
 ** program, and is searched under extensions .BAT, .COM, and .EXE
 ** for the first occurance of the program.  The search starts
 ** in the current directory, and if not found, procedes using the
 ** PATH environment variable (if there is one).  The program reports the
 ** first occurance of the specified file, just as it would be found
 ** by DOS if executed.
 **
 ** The input filename need not contain an extension, since the
 ** extension is discarded anyway.
 **
 ** Version 1.03  for Datalight C
 ** 9-18-86 A
 **
 ** ======== COPYRIGHT 1986 BY STEVEN E. MARGISON ==============
 **
 **
 **   As distributed, this program requires (for compilation):
 **     "Steve's Datalight Library" version 1.10 or later
 **   which may be obtained without registration from many Bulletin
 **   Board Systems including:
 **      Compuserve IBMSW
 **      Cul-De-Sac (Holliston, MA.)
 **      HAL-PC BBS (Houston, TX.)
 **   and software library houses including:
 **      Public (Software) Library (Houston, TX.)
 **
 **   or by registration:
 **      $10 for Docs, Small Model Library
 **      $25 for Docs, S, D, L, P libraries, and complete library source
 **              in C and Assembler
 **     Steven E. Margison
 **     124 Sixth Street
 **     Downers Grove, IL, 60515
 **
 */

 #include <stdio.h>
 #include <smdefs.h>

 char paths[256],
      fullname[100],
      dirname[100],
      batname[14],
      comname[14],
      exename[14],
      fname[14];
 int current;

 main(argc, argv)
 int argc;
 char *argv[];
 {
    int i, j, k;
    char c;
    if(argc != 2) usage();
    strcpy(fname, argv[1]);   /* copy argument to fname */
    newext(fname, batname, "BAT");   /* make fname.bat */
    newext(fname, comname, "COM");   /* make fname.com */
    newext(fname, exename, "EXE");   /* make fname.exe */
    dirname[0] = NULL;
    current = YES;
    findpgm();
    current = NO;
    if((j = getpath(paths)) == 0) notfound();
    k = 0;
    while(j > 0) {
       i = 0;
       while(paths[k] != NULL) {
       c = paths[k];      /* save for slash check */
          dirname[i++] = paths[k++];
          --j;
          }
       if (c != '\\') dirname[i++] = '\\';
       dirname[i] = NULL;
       ++k;      /* position to next charcter in paths[] */
       --j;
       findpgm();
       }
    notfound();
    }

 findpgm() {
    FILE *fd;
    strcpy(fullname, dirname);   /* test for .com file */
    strcat(fullname, comname);
    if((fd = fopen(fullname, "r")) != NULL) goto found;
    strcpy(fullname, dirname);
    strcat(fullname, exename);   /* test for .exe file */
    if((fd = fopen(fullname, "r")) != NULL) goto found;
    strcpy(fullname, dirname);
    strcat(fullname, batname);   /* test for .bat file */
    if((fd = fopen(fullname, "r")) != NULL) goto found;
    return(NO);         /* file not found */

    found:
    if(current) puts("File found in current directory");
    fputs(fullname, stdout);
    fputc('\n', stdout);
    fclose(fd);
    exit(0);
    }

 notfound() {
    error("File not found in PATH");
    }

 usage() {
    fputs("INPATH Version 1.03\n", stderr);
    fputs("Copyright 1986, Steven E. Margison\n", stderr);
    error("usage:  inpath <filename>");
    }



 INPUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\INPUT.C

 /*        INPUT:        Various input routines for MicroEMACS
                 written by Daniel Lawrence
                 5/9/86                                                */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 /*
  * Ask a yes or no question in the message line. Return either TRUE, FALSE, o
  * ABORT. The ABORT status is returned if the user bumps out of the question
  * with a ^G. Used any time a confirmation is required.
  */

 mlyesno(prompt)

 char *prompt;

 {
         char c;                        /* input character */
         char buf[NPAT];                /* prompt to user */

         for (;;) {
                 /* build and prompt the user */
                 strcpy(buf, prompt);
                 strcat(buf, " [y/n]? ");
                 mlwrite(buf);

                 /* get the responce */
                 c = tgetc();

                 if (c == ectoc(abortc))                /* Bail out! */
                         return(ABORT);

                 if (c=='y' || c=='Y')
                         return(TRUE);

                 if (c=='n' || c=='N')
                         return(FALSE);
         }
 }

 /*
  * Write a prompt into the message line, then read back a response. Keep
  * track of the physical position of the cursor. If we are in a keyboard
  * macro throw the prompt away, and return the remembered response. This
  * lets macros run at full speed. The reply is always terminated by a carriag
  * return. Handle erase, kill, and abort keys.
  */

 mlreply(prompt, buf, nbuf)
     char *prompt;
     char *buf;
 {
         return(nextarg(prompt, buf, nbuf, ctoec('\n')));
 }

 mlreplyt(prompt, buf, nbuf, eolchar)

 char *prompt;
 char *buf;
 int eolchar;

 {
         return(nextarg(prompt, buf, nbuf, eolchar));
 }

 /*        ectoc:        expanded character to character
                 colapse the CTRL and SPEC flags back into an ascii code   */

 ectoc(c)

 int c;

 {
         if (c & CTRL)
                 c = c & ~(CTRL | 0x40);
         if (c & SPEC)
                 c= c & 255;
         return(c);
 }

 /*        ctoec:        character to extended character
                 pull out the CTRL and SPEC prefixes (if possible)        */

 ctoec(c)

 int c;

 {
         if (c>=0x00 && c<=0x1F)
                 c = CTRL | (c+'@');
         return (c);
 }

 /* get a command name from the command line. Command completion means
    that pressing a <SPACE> will attempt to complete an unfinished command
    name if it is unique.
 */

 int (*getname())()

 {
 #if        ST520 & LATTICE
 #define register
 #endif
         register int cpos;        /* current column on screen output */
         register int c;
         register char *sp;        /* pointer to string for output */
         register NBIND *ffp;        /* first ptr to entry in name binding tab
         register NBIND *cffp;        /* current ptr to entry in name binding
         register NBIND *lffp;        /* last ptr to entry in name binding tab
         char buf[NSTRING];        /* buffer to hold tentative command name */
         int (*fncmatch())();

         /* starting at the beginning of the string buffer */
         cpos = 0;

         /* if we are executing a command line get the next arg and match it *
         if (clexec) {
                 if (macarg(buf) != TRUE)
                         return(FALSE);
                 return(fncmatch(&buf[0]));
         }

         /* build a name string from the keyboard */
         while (TRUE) {
                 c = tgetc();

                 /* if we are at the end, just match it */
                 if (c == 0x0d) {
                         buf[cpos] = 0;

                         /* and match it off */
                         return(fncmatch(&buf[0]));

                 } else if (c == ectoc(abortc)) {        /* Bell, abort */
                         ctrlg(FALSE, 0);
                         TTflush();
                         return( (int (*)()) NULL);

                 } else if (c == 0x7F || c == 0x08) {        /* rubout/erase *
                         if (cpos != 0) {
                                 TTputc('\b');
                                 TTputc(' ');
                                 TTputc('\b');
                                 --ttcol;
                                 --cpos;
                                 TTflush();
                         }

                 } else if (c == 0x15) {        /* C-U, kill */
                         while (cpos != 0) {
                                 TTputc('\b');
                                 TTputc(' ');
                                 TTputc('\b');
                                 --cpos;
                                 --ttcol;
                         }

                         TTflush();

                 } else if (c == ' ') {
 /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
         /* attempt a completion */
         buf[cpos] = 0;                /* terminate it for us */
         ffp = &names[0];        /* scan for matches */
         while (ffp->n_func != NULL) {
                 if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
                         /* a possible match! More than one? */
                         if ((ffp + 1)->n_func == NULL ||
                            (strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0))
                                 /* no...we match, print it */
                                 sp = ffp->n_name + cpos;
                                 while (*sp)
                                         TTputc(*sp++);
                                 TTflush();
                                 return(ffp->n_func);
                         } else {
 /* << << << << << << << << << << << << << << << << << */
         /* try for a partial match against the list */

         /* first scan down until we no longer match the current input */
         lffp = (ffp + 1);
         while ((lffp+1)->n_func != NULL) {
                 if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
                         break;
                 ++lffp;
         }

         /* and now, attempt to partial complete the string, char at a time */
         while (TRUE) {
                 /* add the next char in */
                 buf[cpos] = ffp->n_name[cpos];

                 /* scan through the candidates */
                 cffp = ffp + 1;
                 while (cffp <= lffp) {
                         if (cffp->n_name[cpos] != buf[cpos])
                                 goto onward;
                         ++cffp;
                 }

                 /* add the character */
                 TTputc(buf[cpos++]);
         }
 /* << << << << << << << << << << << << << << << << << */
                         }
                 }
                 ++ffp;
         }

         /* no match.....beep and onward */
         TTbeep();
 onward:;
         TTflush();
 /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
                 } else {
                         if (cpos < NSTRING-1 && c > ' ') {
                                 buf[cpos++] = c;
                                 TTputc(c);
                         }

                         ++ttcol;
                         TTflush();
                 }
         }
 }

 /*        tgetc:        Get a key from the terminal driver, resolve any keybo
                 macro action                                        */

 int tgetc()

 {
         int c;        /* fetched character */

         /* if we are playing a keyboard macro back, */
         if (kbdmode == PLAY) {

                 /* if there is some left... */
                 if (kbdptr < kbdend)
                         return((int)*kbdptr++);

                 /* at the end of last repitition? */
                 if (--kbdrep < 1) {
                         kbdmode = STOP;
 #if        VISMAC == 0
                         /* force a screen update after all is done */
                         update(FALSE);
 #endif
                 } else {

                         /* reset the macro to the begining for the next rep *
                         kbdptr = &kbdm[0];
                         return((int)*kbdptr++);
                 }
         }

         /* fetch a character from the terminal driver */
         c = TTgetc();

         /* record it for $lastkey */
         lastkey = c;

         /* save it if we need to */
         if (kbdmode == RECORD) {
                 *kbdptr++ = c;
                 kbdend = kbdptr;

                 /* don't overrun the buffer */
                 if (kbdptr == &kbdm[NKBDM - 1]) {
                         kbdmode = STOP;
                         TTbeep();
                 }
         }

         /* and finally give the char back */
         return(c);
 }

 /*        GET1KEY:        Get one keystroke. The only prefixs legal here
                         are the SPEC and CTRL prefixes.
                                                                 */

 get1key()

 {
         int    c;
 #if        AMIGA
         int        d;
 #endif

         /* get a keystroke */
         c = tgetc();

 #if        MSDOS | ST520
         if (c == 0) {                                /* Apply SPEC prefix
                 c = tgetc();
                 if (c>=0x00 && c<=0x1F)                /* control key? */
                         c = CTRL | (c+'@');
                 return(SPEC | c);
         }
 #endif

 #if        AMIGA
         /* apply SPEC prefix */
         if ((unsigned)c == 155) {
                 c = tgetc();

                 /* first try to see if it is a cursor key */
                 if ((c >= 'A' && c <= 'D') || c == 'S' || c == 'T')
                         return(SPEC | c);

                 /* next, a 2 char sequence */
                 d = tgetc();
                 if (d == '~')
                         return(SPEC | c);

                 /* decode a 3 char sequence */
                 c = d + 32;
                 /* if a shifted function key, eat the tilde */
                 if (d >= '0' && d <= '9')
                         d = tgetc();
                 return(SPEC | c);
         }
 #endif

 #if  WANGPC
         if (c == 0x1F) {                        /* Apply SPEC prefix    */
                 c = tgetc();
                 return(SPEC | c);
         }
 #endif

         if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
                 c = CTRL | (c+'@');
         return (c);
 }

 /*        GETCMD:        Get a command from the keyboard. Process all applica
                 prefix keys
                                                         */
 getcmd()

 {
         int c;                /* fetched keystroke */

         /* get initial character */
         c = get1key();

         /* process META prefix */
         if (c == metac) {
                 c = get1key();
                 if (islower(c))                /* Force to upper */
                         c ^= DIFCASE;
                 if (c>=0x00 && c<=0x1F)                /* control key */
                         c = CTRL | (c+'@');
        1        /* temporary ESC sequence fix......... */
                 if (c == '[') {
                         c = get1key();
                         return(SPEC | c);
                 }
 #endif
                 return(META | c);
         }

         /* process CTLX prefix */
         if (c == ctlxc) {
                 c = get1key();
                 if (c>='a' && c<='z')                /* Force to upper */
                         c -= 0x20;
                 if (c>=0x00 && c<=0x1F)                /* control key */
                         c = CTRL | (c+'@');
                 return(CTLX | c);
         }

         /* otherwise, just return it */
         return(c);
 }

 /*        A more generalized prompt/reply function allowing the caller
         to specify the proper terminator. If the terminator is not
         a return ('\n') it will echo as "<NL>"
                                                         */
 getstring(prompt, buf, nbuf, eolchar)

 char *prompt;
 char *buf;
 int eolchar;

 {
         register int cpos;        /* current character position in string */
         register int c;
         register int quotef;        /* are we quoting the next char? */

         cpos = 0;
         quotef = FALSE;

         /* prompt the user for the input string */
         mlwrite(prompt);

         for (;;) {
                 /* get a character from the user */
                 c = get1key();

                 /* If it is a <ret>, change it to a <NL> */
                 if (c == (CTRL | 0x4d))
                         c = CTRL | 0x40 | '\n';

                 /* if they hit the line terminate, wrap it up */
                 if (c == eolchar && quotef == FALSE) {
                         buf[cpos++] = 0;

                         /* clear the message line */
                         mlwrite("");
                         TTflush();

                         /* if we default the buffer, return FALSE */
                         if (buf[0] == 0)
                                 return(FALSE);

                         return(TRUE);
                 }

                 /* change from command form back to character form */
                 c = ectoc(c);

                 if (c == ectoc(abortc) && quotef == FALSE) {
                         /* Abort the input? */
                         ctrlg(FALSE, 0);
                         TTflush();
                         return(ABORT);
                 } else if ((c==0x7F || c==0x08) && quotef==FALSE) {
                         /* rubout/erase */
                         if (cpos != 0) {
                                 outstring("\b \b");
                                 --ttcol;

                                 if (buf[--cpos] < 0x20) {
                                         outstring("\b \b");
                                         --ttcol;
                                 }

                                 if (buf[cpos] == '\n') {
                                         outstring("\b\b  \b\b");
                                         ttcol -= 2;
                                 }
                                 TTflush();
                         }

                 } else if (c == 0x15 && quotef == FALSE) {
                         /* C-U, kill */
                         while (cpos != 0) {
                                 outstring("\b \b");
                                 --ttcol;

                                 if (buf[--cpos] < 0x20) {
                                         outstring("\b \b");
                                         --ttcol;
                                 }
                         }
                         TTflush();

                 } else if (c == quotec && quotef == FALSE) {
                         quotef = TRUE;
                 } else {
                         quotef = FALSE;
                         if (cpos < nbuf-1) {
                                 buf[cpos++] = c;

                                 if ((c < ' ') && (c != '\n')) {
                                         outstring("^");
                                         ++ttcol;
                                         c ^= 0x40;
                                 }

                                 if (c != '\n') {
                                         if (disinp)
                                                 TTputc(c);
                                 } else {        /* put out <NL> for <ret> */
                                         outstring("<NL>");
                                         ttcol += 3;
                                 }
                                 ++ttcol;
                                 TTflush();
                         }
                 }
         }
 }

 outstring(s)        /* output a string of input characters */

 char *s;        /* string to output */

 {
         if (disinp)
                 while (*s)
                         TTputc(*s++);
 }

 ostring(s)        /* output a string of output characters */

 char *s;        /* string to output */

 {
         if (discmd)
                 while (*s)
                         TTputc(*s++);
 }



 INPUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\ADVC\INPUT.C

 #include <dos.h>
 #include <ctype.h>

 char getkey(str)
    char *str;
 {
    char c, *s;
    int done = 0;

    while (!done) {
       if (islower(c = getch()))
          c = toupper(c);
       if (*str) {
          s = str;
          while (*s && !done)
             done = (c == *s++);
          }
       else done = 1;
       }
    return(c);
 }



 int mousebuttons()                    /* see if mouse buttons are pressed */
 {
    union REGS inregs;
    union REGS outregs;
    inregs.x.ax = 6;
    int86(0x33,&inregs,&outregs);
    return(outregs.x.ax & 3);
 }



 int mousecheck()                      /* see if mouse exists, & # of buttons
 {
    union REGS inregs;
    union REGS outregs;
    inregs.x.ax = 0;
    int86(0x33,&inregs,&outregs);
    return(outregs.x.ax ? outregs.x.bx : 0);
 }



 int mouseclick()                      /* see if mouse buttons were clicked */
 {
    int click = 0;
    union REGS inregs;
    union REGS outregs;
    inregs.x.ax = 5;
    inregs.x.bx = 1;
    int86(0x33,&inregs,&outregs);
    click = outregs.x.bx << 1;
    inregs.x.bx--;
    int86(0x33,&inregs,&outregs);
    return(click | outregs.x.bx);
 }



 int mousecol()                        /* get column where mouse cursor is */
 {
    union REGS inregs;
    union REGS outregs;
    inregs.x.ax = 3;
    int86(0x33,&inregs,&outregs);
    return(outregs.x.cx);
 }



 void mousecursor(toggle)              /* turn mouse cursor on or off */
    int toggle;
 {
    union REGS inregs;
    union REGS outregs;
    if (toggle) inregs.x.ax = 1;
    else inregs.x.ax = 2;
    int86(0x33,&inregs,&outregs);
 }



 void mouseloc(column,row)             /* set location of mouse cursor */
    int column, row;
 {
    union REGS inregs;
    union REGS outregs;
    inregs.x.ax = 4;
    inregs.x.cx = column;
    inregs.x.dx = row;
    int86(0x33,&inregs,&outregs);
 }



 int mouserow()                        /* get row where mouse cursor is */
 {
    union REGS inregs;
    union REGS outregs;
    inregs.x.ax = 3;
    int86(0x33,&inregs,&outregs);
    return(outregs.x.dx);
 }


 INPUTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\INPUTS.C


 /* a function that accepts a string from the keyboard                   */

 inputs(s)
 char s[];
 {
         int i;

         for(i=0;(s[i]=getchar()) != '\n' && i<MAXLIN-1; ++i)
         ;
         s[i]='\0';
 }


 INT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\INT.C

 /* SDB - boolean expression evaluator */

 #include "sdbio.h"

 static struct operand *stack[STACKMAX],**sptr;
 static union codecell *cptr;

 /* db_interpret - interpret a boolean expression */
 int db_interpret(slptr)
   struct sel *slptr;
 {
     struct operand *result;
     int r;

     /* check for empty where clause */
     if ((cptr = slptr->sl_where) == NULL)
         return (TRUE);

     /* setup stack */
     sptr = stack;

     /* execute the code */
     while ((*(*cptr++).c_operator)())
         ;

     /* get the result from the top of stack */
     result = *--sptr;
     r = result->o_value.ov_boolean;
     if (result->o_type == TEMP)
         free(result);

     /* make sure the stack is empty */
     while (sptr != stack) {
         if ((*sptr)->o_type == TEMP)
             free(*sptr);
         sptr -= 1;
     }

     /* return result */
     return (r);
 }

 int db_xstop()
 {
     return (FALSE);
 }

 int db_xpush()
 {
     *sptr++ = (*cptr++).c_operand;
 }

 int db_xand()
 {
     return (boolean('&'));
 }

 int db_xor()
 {
     return (boolean('|'));
 }

 static int boolean(opr)
 {
     struct operand *lval,*rval,*result;
     int lv,rv,r;

     rval = *--sptr; lval = *--sptr;
     lv = lval->o_value.ov_boolean;
     rv = rval->o_value.ov_boolean;

     if ((result = malloc(sizeof(struct operand))) == NULL)
         return (db_ferror(INSMEM));
     result->o_type = TEMP;
     switch (opr) {
     case '&':   r = (lv && rv);
                 break;
     case '|':   r = (lv || rv);
                 break;
     }
     result->o_value.ov_boolean = r;
     *sptr++ = result;
     if (lval->o_type == TEMP)
         free(lval);
     if (rval->o_type == TEMP)
         free(rval);
     return (TRUE);
 }

 int db_xnot()
 {
     struct operand *val,*result;

     val = *--sptr;
     if ((result = malloc(sizeof(struct operand))) == NULL)
         return (db_ferror(INSMEM));
     result->o_type = TEMP;
     result->o_value.ov_boolean = !val->o_value.ov_boolean;
     *sptr++ = result;
     if (val->o_type == TEMP)
         free(val);
     return (TRUE);
 }

 int db_xlss()
 {
     return (compare(LSS));
 }

 int db_xleq()
 {
     return (compare(LEQ));
 }

 int db_xeql()
 {
     return (compare(EQL));
 }

 int db_xgeq()
 {
     return (compare(GEQ));
 }

 int db_xgtr()
 {
     return (compare(GTR));
 }

 int db_xneq()
 {
     return (compare(NEQ));
 }

 static int compare(cmp)
 {
     struct operand *lval,*rval,*result;
     int i;

     rval = *--sptr; lval = *--sptr;
     if ((result = malloc(sizeof(struct operand))) == NULL)
         return (db_ferror(INSMEM));
     result->o_type = TEMP;

     if (lval->o_value.ov_char.ovc_type == TCHAR)
         i = comp(lval,rval);
     else
         i = ncomp(lval,rval);

     switch (cmp) {
     case LSS:   i = (i < 0);
                 break;
     case LEQ:   i = (i <= 0);
                 break;
     case EQL:   i = (i == 0);
                 break;
     case GEQ:   i = (i >= 0);
                 break;
     case GTR:   i = (i > 0);
                 break;
     case NEQ:   i = (i != 0);
                 break;
     }
     result->o_value.ov_boolean = i;
     *sptr++ = result;
     if (lval->o_type == TEMP)
         free(lval);
     if (rval->o_type == TEMP)
         free(rval);
     return (TRUE);
 }

 static int comp(lval,rval)
   struct operand *lval,*rval;
 {
     char *lptr,*rptr; int lctr,rctr;
     int len;

     lptr = lval->o_value.ov_char.ovc_string;
     lctr = lval->o_value.ov_char.ovc_length;
     rptr = rval->o_value.ov_char.ovc_string;
     rctr = rval->o_value.ov_char.ovc_length;

     while (lctr > 0 && (lptr[lctr-1] == 0 || lptr[lctr-1] == ' '))
         lctr--;
     while (rctr > 0 && (rptr[rctr-1] == 0 || rptr[rctr-1] == ' '))
         rctr--;

     if (lctr < rctr)
         len = lctr;
     else
         len = rctr;

     while ((len--) > 0) {
         if (*lptr++ != *rptr++)
             if (*--lptr < *--rptr)
                 return (-1);
             else
                 return (1);
     }

     if (lctr == rctr)
         return (0);
     else if (lctr < rctr)
         return (-1);
     else
         return (1);
 }

 static int ncomp(lval,rval)
   struct operand *lval,*rval;
 {
     char lstr[NUMBERMAX+1],rstr[NUMBERMAX+1];
     int len;

     stccpy(lstr,lval->o_value.ov_char.ovc_string,
           (len = lval->o_value.ov_char.ovc_length)); lstr[len] = EOS;
     stccpy(rstr,rval->o_value.ov_char.ovc_string,
           (len = rval->o_value.ov_char.ovc_length)); rstr[len] = EOS;

     return (db_cmp(lstr,rstr));
 }



 INTARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\INTARRAY.C

                                           /* Chapter 7 - Program 3 */
 main()
 {
 int values[12];
 int index;

    for (index = 0;index < 12;index++)
       values[index] = 2 * (index + 4);

    for (index = 0;index < 12;index++)
       printf("The value at index = %2d is %3d\n",index,values[index]);

 }


 INTASIGN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\INTASIGN.C

                                          /* Chapter 4 - Program 1 */
 /* This program will illustrate the assignment statements         */

 main()
 {
 int a,b,c;    /* Integer variables for examples */

    a = 12;
    b = 3;
    c = a + b;          /* simple addition */
    c = a - b;          /* simple subtraction */
    c = a * b;          /* simple multiplication */
    c = a / b;          /* simple division */
    c = a % b;          /* simple modulo (remainder) */
    c = 12*a + b/2 - a*b*2/(a*c + b*2);
    c = c/4+13*(a + b)/3 - a*b + 2*a*a;
    a = a + 1;          /* incrementing a variable */
    b = b * 5;

    a = b = c = 20;     /* multiple assignment */
    a = b = c = 12*13/4;
 }


 INTEG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\INTEG.C

 /*
  * integ -- ascii to long (various bases)
  */
 long
 integ(cp, base)
 char *cp;
 register base;
 {
         register c;
         long n;

         n = 0;
         while (c = *cp++) {
                 if (c>='A' && c<='Z')
                         c += 'a'-'A';
                 if (c>='a' && c<='z')
                         c = (c-'a')+10+'0';
                 if (c < '0' || c > base+'0')
                         break;
                 n = n*base + c-'0';
         }
         return(n);
 }


 INTEXPR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\INTEXPR.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 intexpr()       /* simple integer value */
 {       int     temp;
         SYM     *sp;
         if(lastst == id) {
                 sp = search(lastid,lsyms.head);
                 if( sp == NULL)
                         sp = search(lastid,gsyms.head);
                 if(sp == NULL) {
                         error(ERR_UNDEFINED);
                         getsym();
                         return 0;
                         }
                 if(sp->storage_class != sc_const) {
                         error(ERR_SYNTAX);
                         getsym();
                         return 0;
                         }
                 getsym();
                 return sp->value.i;
                 }
         else if(lastst == iconst) {
                 temp = ival;
                 getsym();
                 return temp;
                 }
         getsym();
         error(ERR_SYNTAX);
         return 0;
 }



 INTIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\INTIN.C

                                           /* Chapter 9 - Program 4 */
 #include "stdio.h"

 main()
 {
 int valin;

    printf("Input a number from 0 to 32767, stop with 100.\n");

    do {
       scanf("%d",&valin);   /* read a single integer value in */
       printf("The value is %d\n",valin);
    } while (valin != 100);

    printf("End of program\n");
 }


 INVERF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\INVERF.C

 /* 1.1  10-08-85                                                (inverf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*

         This routine uses the approximations given in J. M. Blair,
 et. al., "Rational Chebyshev Approximations for the Inverse Error
 Function," Math Comp. Vol. 30, No. 136, Oct. 1976, pp. 827-830, with
 the appendices given in separate microfiche.

  *----------------------------------------------------------------------*/

 LOCAL int dP[4] = {7, 8, 11, 8};        /* degrees of P(x)                */
 LOCAL int dQ[4] = {7, 8, 10, 9};        /* degrees of Q(x)                */

 LOCAL double P[4][12] =                /* numerator polynomials
 {
 /* P[0][0] */        -.30866886527764497339e2, /* Table 19 of Ref. below
 /* P[0][1] */        0.20652786402942339589e3, /*    |x| <= 0.75
 /* P[0][2] */        -.52856770835093823310e3,
 /* P[0][3] */        0.64880509544036249088e3,
 /* P[0][4] */        -.39205509901971391289e3,
 /* P[0][5] */        0.10706278097770074402e3,
 /* P[0][6] */        -.10303488455439678272e2,
 /* P[0][7] */        0.15641510821923860000e0,
 /* P[0][8] */        0.0,
 /* P[0][9] */        0.0,
 /* P[0][10] */        0.0,
 /* P[0][11] */        0.0,

 /* P[1][0] */        0.94897362808681080020e-2, /* Table 39 of Ref. below
 /* P[1][1] */        -.24758242362823355485e0,  /* 0.75 <= x <= 0.9375
 /* P[1][2] */        0.25349389220714893916e1,
 /* P[1][3] */        -.12954198980646771502e2,
 /* P[1][4] */        0.34810057749357500873e2,
 /* P[1][5] */        -.47644367129787181802e2,
 /* P[1][6] */        0.29631331505876308122e2,
 /* P[1][7] */        -.64200071507209448654e1,
 /* P[1][8] */        0.21489185007307062000e0,
 /* P[1][9] */        0.0,
 /* P[1][10] */        0.0,
 /* P[1][11] */        0.0,

 /* P[2][0] */        0.19953288964537210824e-5, /* Table 60 of Ref. below
 /* P[2][1] */        0.21273702631785953343e-3, /* 0.9375 <= x <= 1 - 10^(-10
 /* P[2][2] */        0.58975595952407247651e-2,
 /* P[2][3] */        0.59481901452735809123e-1,
 /* P[2][4] */        0.31328289030932667506e0,
 /* P[2][5] */        0.13630199956442260990e1,
 /* P[2][6] */        0.34152815205652930673e1,
 /* P[2][7] */        0.30184181468933606839e1,
 /* P[2][8] */        0.20842433546207339433e1,
 /* P[2][9] */        0.85545635026743499993e0,
 /* P[2][10] */        0.40273918408712893132e-2,
 /* P[2][11] */        -.15196139115744716810e-3,

 /* P[3][0] */        .45344689563209398449e-11, /* Table 82 of Ref. below
 /* P[3][1] */        .46156006321345332510e-8,  /* 1 - 10^(-100) <= x
 /* P[3][2] */        .12964481560643197452e-5,  /*     <= 1 - 10^(-10000)
 /* P[3][3] */        .13714329569665128933e-3,
 /* P[3][4] */        .60537914739162189689e-2,
 /* P[3][5] */        .11279046353630280004e0,
 /* P[3][6] */        .82810030904462690215e0,
 /* P[3][7] */        .19507620287580568829e1,
 /* P[3][8] */        .69952990607058154857e0,
 /* P[3][9] */        0.0,
 /* P[3][10] */        0.0,
 /* P[3][11] */        0.0
 };

 LOCAL double Q[4][11] =                /* denominator polynomials
 {
 /* Q[0][0] */        -.28460290173882339383e2,        /* Table 19
 /* Q[0][1] */        0.20518924149238530630e3,
 /* Q[0][2] */        -.57617125090127638064e3,
 /* Q[0][3] */        0.79669388170563770334e3,
 /* Q[0][4] */        -.56509305564023424022e3,
 /* Q[0][5] */        0.19450320483954087700e3,
 /* Q[0][6] */        -.27371852306002662877e2,
 /* Q[0][7] */        1.0,
 /* Q[0][8] */        0.0,
 /* Q[0][9] */        0.0,
 /* Q[0][10] */        0.0,

 /* Q[1][0] */        0.67544512778850945940e-2,        /* Table 39
 /* Q[1][1] */        -.18611650627372178511e0,
 /* Q[1][2] */        0.20369295047216351160e1,
 /* Q[1][3] */        -.11315360624238054876e2,
 /* Q[1][4] */        0.33880176779595142684e2,
 /* Q[1][5] */        -.53715373448862143348e2,
 /* Q[1][6] */        0.41409991778428888715e2,
 /* Q[1][7] */        -.12831383833953226499e2,
 /* Q[1][8] */        1.0,
 /* Q[1][9] */        0.0,
 /* Q[1][10] */        0.0,

 /* Q[2][0] */        .19953210379374212953e-5,        /* Table 60
 /* Q[2][1] */        .21274156963404084598e-3,
 /* Q[2][2] */        .59037062023731354671e-2,
 /* Q[2][3] */        .59959150110861092334e-1,
 /* Q[2][4] */        .32318083080817836442e0,
 /* Q[2][5] */        .14378337804749344527e1,
 /* Q[2][6] */        .37644571508257969664e1,
 /* Q[2][7] */        .44081435698143841173e1,
 /* Q[2][8] */        .42508710497182804606e1,
 /* Q[2][9] */        .22127469427969785343e1,
 /* Q[2][10] */        1.0,

 /* Q[3][0] */        .45344687377088206782e-11,        /* Table 82
 /* Q[3][1] */        .46156017600933592558e-8,
 /* Q[3][2] */        .12964671850944981712e-5,
 /* Q[3][3] */        .13715891988350205065e-3,
 /* Q[3][4] */        .60574830550097140404e-2,
 /* Q[3][5] */        .11311889334355782064e0,
 /* Q[3][6] */        .84001814918178042918e0,
 /* Q[3][7] */        .21238242087454993541e1,
 /* Q[3][8] */        .15771922386662040545e1,
 /* Q[3][9] */        1.0,
 /* Q[3][10] */        0.0
 };

 /************************************************************************/
         double
 inverf(x)                /* inverse of erf(x), which see.                */

 /*----------------------------------------------------------------------*/
 double x;
 {
         int interval, sign;
         double y, inverfc(), ratfun();
         LOCAL double bias[2] = {0.5625, 0.87890625};

         sign = (x < 0.0 ? 1 : 0);
         if (sign)
                 x = -x;
         if (x >= 1.0)
         {        errno = EDOM;
                 return (sign ? -INFINITY : INFINITY);
         }
         if (x > 0.9375)
         {        y = inverfc(1.0 - x);
                 return (sign ? -y : y);
         }
         if (x < 0.75)
                 interval = 0;
         else        interval = 1;
         y = x * ratfun(x*x - bias[interval], P[interval], Q[interval],
                 dP[interval], dQ[interval]);
         return (sign ? -y : y);
 }

 BOUNDARY        0.065901028        /* 1 / sqrt(100 * log(10))        */

 /*\p*********************************************************************/
         double
 inverfc(x)        /* returns double inverse of erfc(y)

 /*----------------------------------------------------------------------*/
 double x;
 {
         int sign, interval;
         double y, log(), fabs(), inverf(), sqrt(), ratfun();

         y = fabs(1.0 - x);
         if (y >= 1.0)
         {        errno = EDOM;
                 return (x > 2 ? -INFINITY : INFINITY);
         }
         if (x > 1.0)
         {        x = 2.0 - x;
                 sign = 1;
         } else        sign = 0;
         if (x IS 0.0)
         {        errno = ERANGE;
                 return (sign ? -INFINITY : INFINITY);
         }
         if (x > 0.0625)
         {        y = inverf(1.0 - x);
                 return (sign ? -y : y);
         }
         y = 1.0 / sqrt(-log(x));
         if (y > BOUNDARY)
                 interval = 2;
         else        interval = 3;
         y = ratfun(y, P[interval], Q[interval], dP[interval], dQ[interval])/y
         return (sign ? -y : y);
 }


 IO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\IO.C

 /* SDB - relation file I/O routines */

 #include "stdio.h"
 #include "sdbio.h"

 /* global error code variable */
 int dbv_errcode;

 /* list of currently loaded relation definitions */
 static struct relation *relations = NULL;

 /* rfind - find the specified relation */
 static struct relation *rfind(rname)
   char *rname;
 {
     int fd;
     char filename[RNSIZE+5];
     struct relation *rptr;

     /* look for relation in list currently loaded */
     for (rptr = relations; rptr != NULL; rptr = rptr->rl_next)
         if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
             return (rptr);

     /* create a file name */
     make_fname(filename,rname);

     /* lookup the relation file */
 #ifdef Lattice
     if ((fd = open(filename,0x8000)) == -1)  /*NAs*/
 #else
     if ((fd = open(filename,0)) == -1)
 #endif
         return (db_nerror(RELFNF));

     /* allocate a new relation structure */
     if ((rptr = malloc(sizeof(struct relation))) == NULL) {
         close(fd);
         return (db_nerror(INSMEM));
     }

     /* initialize the relation structure */
     rptr->rl_scnref = 0;

     /* read the header block */
     if ( read(fd,&rptr->rl_header,512) != 512) {
         free(rptr);
         close(fd);
         return (db_nerror(BADHDR));
     }

     /* close the relation file */
     close(fd);

     /* extract header information */
     rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
     rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
     rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
     rptr->rl_size = db_cvword(rptr->rl_header.hd_size);

     /* store the relation name */
     stccpy(rptr->rl_name,rname,RNSIZE);

     /* link new relation into relation list */
     rptr->rl_next = relations;
     relations = rptr;

     /* return the new relation structure pointer */
     return (rptr);
 }

 /* db_ropen - open a relation file */
 struct scan *db_ropen(rname)
   char *rname;
 {
     struct relation *rptr;
     struct scan *sptr;
     char filename[RNSIZE+5];

     /* find the relation definition */
     if ((rptr = rfind(rname)) == NULL)
         return (NULL);

     /* allocate a new scan structure */
     if ((sptr = malloc(sizeof(struct scan))) == NULL)
         return (db_nerror(INSMEM));

     /* allocate a tuple buffer */
     if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) {
         free(sptr);
         return (db_nerror(INSMEM));
     }

     /* initialize the scan structure */
     sptr->sc_relation = rptr;           /* store the relation struct addrs */
     sptr->sc_dtnum = 0;                 /* desired tuple (non-existant) */
     sptr->sc_atnum = 0;                 /* actual tuple (non-existant) */
     sptr->sc_store = FALSE;             /* no store done since open */

     /* open relation file if necessary */
     if (rptr->rl_scnref++ == 0) {

         /* create the relation file name */
         make_fname(filename,rname);

         /* open the relation file */
 #ifdef Lattice
         if ((rptr->rl_fd = open(filename,0x8002)) == -1) {  /*dns*/
 #else
         if ((rptr->rl_fd = open(filename,2)) == -1) {
 #endif
             rptr->rl_scnref--;
             free(sptr->sc_tuple); free(sptr);
             return (db_nerror(RELFNF));
         }
     }

     /* return the new scan structure pointer */
     return (sptr);
 }

 /* db_rclose - close the relation file */
 int db_rclose(sptr)
   struct scan *sptr;
 {
     struct relation *rptr,*lastrptr;

     /* close relation file if this is the last reference */
     if (--sptr->sc_relation->rl_scnref == 0) {

         /* rewrite header if any stores took place */
         if (sptr->sc_store) {

             /* store the tuple count back in the header */
             db_cvbytes(sptr->sc_relation->rl_tcnt,
                        sptr->sc_relation->rl_header.hd_tcnt);

             /* write the header block */
             lseek(sptr->sc_relation->rl_fd,0L,0);
             if (write(sptr->sc_relation->rl_fd,
                       &sptr->sc_relation->rl_header,512) != 512) {
                 close(sptr->sc_relation->rl_fd);
                 free(sptr->sc_tuple); free(sptr);
                 return (db_ferror(BADHDR));
             }
         }

         /* close the relation file */
         close(sptr->sc_relation->rl_fd);

         /* free the relation header */
         lastrptr = NULL;
         for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) {
             if (rptr == sptr->sc_relation) {
                 if (lastrptr == NULL)
                     relations = rptr->rl_next;
                 else
                     lastrptr->rl_next = rptr->rl_next;
             }
             lastrptr = rptr;
         }
         free(sptr->sc_relation);
     }

     /* free the scan structure */
     free(sptr->sc_tuple); free(sptr);

     /* return successfully */
     return (TRUE);
 }

 /* db_rcompress - compress a relation file */
 int db_rcompress(sptr)
   struct scan *sptr;
 {
     unsigned int next,nextfree,tcnt;

     /* get the last used tuple */
     tcnt = sptr->sc_relation->rl_tcnt;

     /* loop through all of the tuples */
     for (next = nextfree = 1; next <= tcnt; next++) {

         /* read the tuple */
         seek(sptr,next);
         if (read(sptr->sc_relation->rl_fd,
                  sptr->sc_tuple,sptr->sc_relation->rl_size)
                         != sptr->sc_relation->rl_size)
             return (db_ferror(TUPINP));

         /* rewrite the tuple if it is active */
         if (sptr->sc_tuple[0] == ACTIVE) {

             /* rewrite it only if it must move */
             if (next != nextfree) {

                 /* write the tuple */
                 seek(sptr,nextfree);
                 if (write(sptr->sc_relation->rl_fd,
                           sptr->sc_tuple,sptr->sc_relation->rl_size)
                                 != sptr->sc_relation->rl_size)
                     return (db_ferror(TUPOUT));
             }

             /* update the next free tuple number */
             nextfree += 1;
         }
     }

     /* update the tuple count */
     sptr->sc_relation->rl_tcnt = nextfree - 1;

     /* remember which tuple is in the buffer */
     sptr->sc_atnum = sptr->sc_relation->rl_tcnt;

     /* reset the desired tuple */
     sptr->sc_dtnum = 0;

     /* remember that the index needs rewriting */
     sptr->sc_store = TRUE;

     /* return successfully */
     return (TRUE);
 }

 /* db_rbegin - begin scan at first tuple in relation */
 db_rbegin(sptr)
   struct scan *sptr;
 {
     /* begin with the first tuple in the file */
     sptr->sc_dtnum = 0;
 }

 /* db_rfetch - fetch the next tuple from the relation file */
 int db_rfetch(sptr)
   struct scan *sptr;
 {
     /* look for an active tuple */
     while (TRUE) {

         /* check for this being the last tuple */
         if (!db_rget(sptr,sptr->sc_dtnum + 1))
             return (FALSE);

         /* increment the tuple number */
         sptr->sc_dtnum += 1;

         /* return if the tuple found is active */
         if (sptr->sc_tuple[0] == ACTIVE)
             return (TRUE);
     }
 }

 /* db_rupdate - update the current tuple */
 int db_rupdate(sptr)
   struct scan *sptr;
 {
     /* make sure the status byte indicates an active tuple */
     sptr->sc_tuple[0] = ACTIVE;

     /* write the tuple */
     return (db_rput(sptr,sptr->sc_atnum));
 }

 /* db_rdelete - delete the current tuple */
 int db_rdelete(sptr)
   struct scan *sptr;
 {
     /* make sure the status byte indicates a deleted tuple */
     sptr->sc_tuple[0] = DELETED;

     /* write the tuple */
     return (db_rput(sptr,sptr->sc_atnum));
 }

 /* db_rstore - store a new tuple */
 int db_rstore(sptr)
   struct scan *sptr;
 {
     /* make sure there's room for this tuple */
     if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
         return (db_ferror(RELFUL));

     /* make sure the status byte indicates an active tuple */
     sptr->sc_tuple[0] = ACTIVE;

     /* write the tuple */
     if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1))
         return (FALSE);

     /* update the tuple count */
     sptr->sc_relation->rl_tcnt += 1;

     /* remember that a tuple was stored */
     sptr->sc_store = TRUE;

     /* return successfully */
     return (TRUE);
 }

 /* db_rget - get a tuple from the relation file */
 int db_rget(sptr,tnum)
   struct scan *sptr; unsigned int tnum;
 {
     /* check to see if the tuple is already in the buffer */
     if (tnum == sptr->sc_atnum)
         return (TRUE);

     /* check for this being beyond the last tuple */
     if (tnum > sptr->sc_relation->rl_tcnt)
         return (db_ferror(TUPINP));

     /* read the tuple */
     seek(sptr,tnum);
     if (read(sptr->sc_relation->rl_fd,
              sptr->sc_tuple,sptr->sc_relation->rl_size)
                 != sptr->sc_relation->rl_size)
         return (db_ferror(TUPINP));

     /* remember which tuple is in the buffer */
     sptr->sc_atnum = tnum;

     /* return successfully */
     return (TRUE);
 }

 /* db_rput - put a tuple to a relation file */
 int db_rput(sptr,tnum)
   struct scan *sptr; unsigned int tnum;
 {
     /* check for this being beyond the maximum tuple */
     if (tnum > sptr->sc_relation->rl_tmax)
         return (db_ferror(TUPOUT));

     /* write the tuple */
     seek(sptr,tnum);
     if (write(sptr->sc_relation->rl_fd,
               sptr->sc_tuple,sptr->sc_relation->rl_size)
                 != sptr->sc_relation->rl_size)
         return (db_ferror(TUPOUT));

     /* remember which tuple is in the buffer */
     sptr->sc_atnum = tnum;

     /* return successfully */
     return (TRUE);
 }

 /* seek - seek a tuple in a relation file */
 static seek(sptr,tnum)
   struct scan *sptr; unsigned int tnum;
 {
     long offset;

     offset = (long) sptr->sc_relation->rl_data +
                 ((long) (tnum - 1) * (long) sptr->sc_relation->rl_size);
     lseek(sptr->sc_relation->rl_fd,offset,0);
 }

 /* make_fname - make a relation name into a file name */
 static make_fname(fname,rname)
   char *fname,*rname;
 {
     stccpy(fname,rname,RNSIZE); fname[RNSIZE] = 0;
     strcat(fname,".sdb");
 }

 /* db_nerror - store the error code and return NULL */
 int db_nerror(errcode)
   int errcode;
 {
     dbv_errcode = errcode;
     return (NULL);
 }

 /* db_ferror - store the error code and return FALSE */
 int db_ferror(errcode)
   int errcode;
 {
     dbv_errcode = errcode;
     return (FALSE);
 }

 /* db_cvword - convert 2 bytes to a word */
 int db_cvword(bytes)
   char bytes[2];
 {
     return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
 }

 /* db_cvbytes - convert a word to 2 bytes */
 db_cvbytes(word,bytes)
   int word; char bytes[2];
 {
     bytes[0] = word;
     bytes[1] = word >> 8;
 }



 IOBNBF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\IOBNBF.C

 /*_ iob.c   Thu Oct 30 1986   Modified by: Walter Bright */

 #include        <stdio.h>

 FILE _iob[_NFILE] =
 {
         {0,0,0,_IOTRAN | _IOREAD,0,1},                /* stdin        */
         {0,0,0,_IOTRAN | _IOWRT | _IONBF ,1,1},        /* stdout        */
         {0,0,0,_IOTRAN | _IOWRT | _IONBF ,2,1},        /* stderr        */
         {0,0,0,_IOTRAN | _IORW  ,3,1},                /* stdaux        */
         {0,0,0,_IOTRAN | _IOWRT ,4,1},                /* stdprn        */

         /* the rest have all 0 entries        */
 };


 ISALNUM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISALNUM.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isalnum(c)                /* returns true if c is alphanumeric

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISALNUM(c));
 }


 ISALPHA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISALPHA.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isalpha(c)                /* returns true if c is alphabetic.

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISALPHA(c));
 }


 ISASCII.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISASCII.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isascii(c)                /* returns true if c is an ASCII char, c < 0x80.*/

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISASCII(c));
 }


 ISCHECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\ISCHECK.C


 /* ischeck()  program to check Microsoft C's issomething matrix.
  *            it has no other purpose.
  *            1 to 1 correspondence between 0 to 127 and 128 to 255!!!
  *            WHRauser   10-4-83     Microsoft C  Version 1.04
  */

 #include  <ctype.h>

 main()
 {
      int  i;

      printf("   dec   char   hex    XBCP SNLU    ");
      printf("   dec   char   hex    XBCP SNLU\n\n");

      for (i=0; i<128; i++) {
           printit(i);
           printit(i+128);
           printf("\n");
      }
 }/*main
 --------------------------------------------*/

 printit(i)
      int i;
 {
      int  t;
      int  alpha;
      int  x,b,c,p, s,n,l,u;     /* bit map */

      if isprint(i)
            alpha = i;
      else  alpha = ' ';

      t = _ctype[i+1];    /*Stupid, don't they know C is zero origin?*/

      x = t & 128 ? 1 : 0;    /*   X 128        hexadecimal flag */
      b = t &  64 ? 1 : 0;    /*   B 64         blank flag */
      c = t &  32 ? 1 : 0;    /*   C 32         control character flag */
      p = t &  16 ? 1 : 0;    /*   P 16         punctuation flag */
      s = t &   8 ? 1 : 0;    /*   S 8          space flag */
      n = t &   4 ? 1 : 0;    /*   N 4          number flag */
      l = t &   2 ? 1 : 0;    /*   L 2          lower case flag */
      u = t &   1 ? 1 : 0;    /*   U 1          upper case flag */

      printf("  %3d     %c    %3x     %1d%1d%1d%1d %1d%1d%1d%1d    ",
              i,alpha,t, x,b,c,p, s,n,l,u);
 }



 ISCHECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\ISCHECK.C

 /* ischeck()  program to check Microsoft C's issomething matrix.
  *              it has no other purpose.
  *              1 to 1 correspondence between 0 to 127 and 128 to 255!!!
  *              WHRauser         10-4-83     Microsoft C  Version 1.04
  */

 #include  <ctype.h>

 main()
 {
      int  i;

      printf("   dec   char   hex    XBCP SNLU    ");
      printf("   dec   char   hex    XBCP SNLU\n\n");

      for (i=0; i<128; i++) {
           printit(i);
           printit(i+128);
           printf("\n");
      }
 }/*main
 --------------------------------------------*/

 printit(i)
      int i;
 {
      int  t;
      int  alpha;
      int  x,b,c,p, s,n,l,u;        /* bit map */

      if isprint(i)
            alpha = i;
      else  alpha = ' ';

      t = _ctype[i+1];         /*Stupid, don't they know C is zero origin?*/

      x = t & 128 ? 1 : 0;    /*   X 128        hexadecimal flag */
      b = t &  64 ? 1 : 0;    /*   B 64               blank flag */
      c = t &  32 ? 1 : 0;    /*   C 32               control character flag *
      p = t &  16 ? 1 : 0;    /*   P 16               punctuation flag */
      s = t &   8 ? 1 : 0;    /*   S 8               space flag */
      n = t &   4 ? 1 : 0;    /*   N 4               number flag */
      l = t &   2 ? 1 : 0;    /*   L 2               lower case flag */
      u = t &   1 ? 1 : 0;    /*   U 1               upper case flag */

      printf("  %3d     %c    %3x     %1d%1d%1d%1d %1d%1d%1d%1d    ",
              i,alpha,t, x,b,c,p, s,n,l,u);
 }


 ISCNTRL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISCNTRL.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 iscntrl(c)                /* returns true if c is DEL or control char.

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISCNTRL(c));
 }


 ISDIGIT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISDIGIT.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isdigit(c)                /* returns true if c is a digit, 0-9.

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISDIGIT(c));
 }


 ISEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\ISEARCH.C

 /*
  * The functions in this file implement commands that perform incremental
  * searches in the forward and backward directions.  This "ISearch" command
  * is intended to emulate the same command from the original EMACS
  * implementation (ITS).  Contains references to routines internal to
  * SEARCH.C.
  *
  * REVISION HISTORY:
  *
  *        D. R. Banks 9-May-86
  *        - added ITS EMACSlike ISearch
  *
  *        John M. Gamble 5-Oct-86
  *        - Made iterative search use search.c's scanner() routine.
  *          This allowed the elimination of bakscan().
  *        - Put isearch constants into estruct.h
  *        - Eliminated the passing of 'status' to scanmore() and
  *          checknext(), since there were no circumstances where
  *          it ever equalled FALSE.
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if        ISRCH

 extern int scanner();                        /* Handy search routine */
 extern int eq();                        /* Compare chars, match case */

 /* A couple of "own" variables for re-eat */

 int        (*saved_get_char)();                /* Get character routine */
 int        eaten_char = -1;                /* Re-eaten char */

 /* A couple more "own" variables for the command string */

 int        cmd_buff[CMDBUFLEN];                /* Save the command args here
 int        cmd_offset;                        /* Current offset into command
 int        cmd_reexecute = -1;                /* > 0 if re-executing command


 /*
  * Subroutine to do incremental reverse search.  It actually uses the
  * same code as the normal incremental search, as both can go both ways.
  */

 int risearch(f, n)
 {
     LINE *curline;                        /* Current line on entry
     int  curoff;                        /* Current offset on entry

     /* remember the initial . on entry: */

     curline = curwp->w_dotp;                /* Save the current line pointer
     curoff  = curwp->w_doto;                /* Save the current offset

     /* Make sure the search doesn't match where we already are:

     backchar(TRUE, 1);                        /* Back up a character

     if (!(isearch(f, -n)))                /* Call ISearch backwards
     {                                        /* If error in search:
         curwp->w_dotp = curline;        /* Reset the line pointer
         curwp->w_doto = curoff;                /*  and the offset to original
         curwp->w_flag |= WFMOVE;        /* Say we've moved
         update(FALSE);                        /* And force an update
         mlwrite ("[search failed]");        /* Say we died
     } else mlerase ();                        /* If happy, just erase the cmd
 }

 /* Again, but for the forward direction */

 int fisearch(f, n)
 {
     LINE *curline;                        /* Current line on entry
     int  curoff;                        /* Current offset on entry

     /* remember the initial . on entry: */

     curline = curwp->w_dotp;                /* Save the current line pointer
     curoff  = curwp->w_doto;                /* Save the current offset

     /* do the search */

     if (!(isearch(f, n)))                /* Call ISearch forwards
     {                                        /* If error in search:
         curwp->w_dotp = curline;        /* Reset the line pointer
         curwp->w_doto = curoff;                /*  and the offset to original
         curwp->w_flag |= WFMOVE;        /* Say we've moved
         update(FALSE);                        /* And force an update
         mlwrite ("[search failed]");        /* Say we died
     } else mlerase ();                        /* If happy, just erase the cmd
 }

 /*
  * Subroutine to do an incremental search.  In general, this works similarly
  * to the older micro-emacs search function, except that the search happens
  * as each character is typed, with the screen and cursor updated with each
  * new search character.
  *
  * While searching forward, each successive character will leave the cursor
  * at the end of the entire matched string.  Typing a Control-S or Control-X
  * will cause the next occurrence of the string to be searched for (where the
  * next occurrence does NOT overlap the current occurrence).  A Control-R wil
  * change to a backwards search, META will terminate the search and Control-G
  * will abort the search.  Rubout will back up to the previous match of the
  * string, or if the starting point is reached first, it will delete the
  * last character from the search string.
  *
  * While searching backward, each successive character will leave the cursor
  * at the beginning of the matched string.  Typing a Control-R will search
  * backward for the next occurrence of the string.  Control-S or Control-X
  * will revert the search to the forward direction.  In general, the reverse
  * incremental search is just like the forward incremental search inverted.
  *
  * In all cases, if the search fails, the user will be feeped, and the search
  * will stall until the pattern string is edited back into something that
  * exists (or until the search is aborted).
  */

 isearch(f, n)
 {
     int                        status;                /* Search status */
     int                        col;                /* prompt column */
     register int        cpos;                /* character number in search st
     register int        c;                /* current input character */
     register int        expc;                /* function expanded input char
     char                pat_save[NPAT];        /* Saved copy of the old patte
     LINE                *curline;        /* Current line on entry
     int                        curoff;                /* Current offset on en
     int                        init_direction;        /* The initial search d

     /* Initialize starting conditions */

     cmd_reexecute = -1;                /* We're not re-executing (yet?)
     cmd_offset = 0;                        /* Start at the beginning of the b
     cmd_buff[0] = '\0';                /* Init the command buffer
     strncpy (pat_save, pat, NPAT);        /* Save the old pattern string
     curline = curwp->w_dotp;                /* Save the current line pointer
     curoff  = curwp->w_doto;                /* Save the current offset
     init_direction = n;                        /* Save the initial search dir

     /* This is a good place to start a re-execution: */

 start_over:

     /* ask the user for the text of a pattern */
     col = promptpattern("ISearch: ");                /* Prompt, remember the

     cpos = 0;                                        /* Start afresh
     status = TRUE;                                /* Assume everything's cool

     /*
        Get the first character in the pattern.  If we get an initial Control-
        or Control-R, re-use the old search string and find the first occurren
      */

     c = ectoc(expc = get_char());                /* Get the first character
     if ((c == IS_FORWARD) ||
         (c == IS_REVERSE) ||
         (c == IS_VMSFORW))                        /* Reuse old search string?
     {
             for (cpos = 0; pat[cpos] != 0; cpos++)        /* Yup, find the le
                 col = echochar(pat[cpos],col);        /*  and re-echo the str
         if (c == IS_REVERSE) {                        /* forward search?
             n = -1;                                /* No, search in reverse
             backchar (TRUE, 1);                        /* Be defensive about
         } else
             n = 1;                                /* Yes, search forward
         status = scanmore(pat, n);                /* Do the search
         c = ectoc(expc = get_char());                /* Get another character
     }

     /* Top of the per character loop */

     for (;;)                                        /* ISearch per character
     {
         /* Check for special characters first: */
         /* Most cases here change the search */

         if (expc == metac)                        /* Want to quit searching?
             return (TRUE);                        /* Quit searching now

         switch (c)                                /* dispatch on the input ch
         {
           case IS_ABORT:                        /* If abort search request
             return(FALSE);                        /* Quit searching again

           case IS_REVERSE:                        /* If backward search
           case IS_FORWARD:                        /* If forward search
           case IS_VMSFORW:                        /*  of either flavor
             if (c == IS_REVERSE)                /* If reverse search
                 n = -1;                                /* Set the reverse dir
             else                                /* Otherwise,
                 n = 1;                                /*  go forward
             status = scanmore(pat, n);                /* Start the search aga
             c = ectoc(expc = get_char());        /* Get the next char
             continue;                                /* Go continue with the

           case IS_NEWLINE:                        /* Carriage return
             c = '\n';                                /* Make it a new line
             break;                                /* Make sure we use it

           case IS_QUOTE:                        /* Quote character
           case IS_VMSQUOTE:                        /*  of either variety
             c = ectoc(expc = get_char());        /* Get the next char

           case IS_TAB:                                /* Generically allowed
           case '\n':                                /*  controlled characters
             break;                                /* Make sure we use it

           case IS_BACKSP:                        /* If a backspace:
           case IS_RUBOUT:                        /*  or if a Rubout:
             if (cmd_offset <= 1)                /* Anything to delete?
                 return (TRUE);                        /* No, just exit
             --cmd_offset;                        /* Back up over the Rubout
             cmd_buff[--cmd_offset] = '\0';        /* Yes, delete last char
             curwp->w_dotp = curline;                /* Reset the line pointer
             curwp->w_doto = curoff;                /*  and the offset
             n = init_direction;                        /* Reset the search di
             strncpy (pat, pat_save, NPAT);        /* Restore the old search s
             cmd_reexecute = 0;                        /* Start the whole mess
             goto start_over;                        /* Let it take care of it

           /* Presumably a quasi-normal character comes here */

           default:                                /* All other chars
             if (c < ' ')                        /* Is it printable?
             {                                        /* Nope.
                 reeat (c);                        /* Re-eat the char
                 return (TRUE);                        /* And return the last
             }
         }  /* Switch */

         /* I guess we got something to search for, so search for it

         pat[cpos++] = c;                        /* put the char in the buffer
         if (cpos >= NPAT)                        /* too many chars in string?
         {                                        /* Yup.  Complain about it
             mlwrite("? Search string too long");
             return(TRUE);                        /* Return an error
         }
         pat[cpos] = 0;                                /* null terminate the b
         col = echochar(c,col);                        /* Echo the character
         if (!status) {                                /* If we lost last time
             TTputc(BELL);                /* Feep again                      *
             TTflush();                        /* see that the feep feeps    *
         } else                                        /* Otherwise, we must h
             if (!(status = checknext(c, pat, n))) /* See if match
                 status = scanmore(pat, n);        /*  or find the next match
         c = ectoc(expc = get_char());                /* Get the next char
     } /* for {;;} */
 }

 /*
  * Trivial routine to insure that the next character in the search string is
  * still true to whatever we're pointing to in the buffer.  This routine will
  * not attempt to move the "point" if the match fails, although it will
  * implicitly move the "point" if we're forward searching, and find a match,
  * since that's the way forward isearch works.
  *
  * If the compare fails, we return FALSE and assume the caller will call
  * scanmore or something.
  */

 int checknext (chr, patrn, dir)        /* Check next character in search stri
 char        chr;                        /* Next char to look for
 char        *patrn;                        /* The entire search string (incl
 int        dir;                        /* Search direction
 {
     register LINE *curline;                /* current line during scan
     register int curoff;                /* position within current line
     register int buffchar;                /* character at current position
     int status;                                /* how well things go


     /* setup the local scan pointer to current "." */

     curline = curwp->w_dotp;                /* Get the current line structure
     curoff  = curwp->w_doto;                /* Get the offset within that lin

     if (dir > 0)                        /* If searching forward
     {
             if (curoff == llength(curline)) /* If at end of line
             {
             curline = lforw(curline);        /* Skip to the next line
             if (curline == curbp->b_linep)
                 return (FALSE);                /* Abort if at end of buffer
             curoff = 0;                        /* Start at the beginning of t
             buffchar = '\n';                /* And say the next char is NL
         } else
             buffchar = lgetc(curline, curoff++); /* Get the next char
         if (status = eq(buffchar, chr))        /* Is it what we're looking fo
         {
             curwp->w_dotp = curline;        /* Yes, set the buffer's point
             curwp->w_doto = curoff;        /*  to the matched character
             curwp->w_flag |= WFMOVE;        /* Say that we've moved
         }
         return (status);                /* And return the status
     } else                                /* Else, if reverse search:
         return (match_pat (patrn));        /* See if we're in the right place
 }

 /*
  * This hack will search for the next occurrence of <pat> in the buffer, eith
  * forward or backward.  It is called with the status of the prior search
  * attempt, so that it knows not to bother if it didn't work last time.  If
  * we can't find any more matches, "point" is left where it was before.  If
  * we do find a match, "point" will be at the end of the matched string for
  * forward searches and at the beginning of the matched string for reverse
  * searches.
  */

 int scanmore(patrn, dir)        /* search forward or back for a pattern
 char        *patrn;                        /* string to scan for
 int        dir;                        /* direction to search
 {
         int        sts;                        /* search status

             if (dir < 0)                                /* reverse search?
             {
                 rvstrcpy(tap, patrn);                /* Put reversed string i
                 sts = scanner(tap, REVERSE, PTBEG);
         }
         else
                 sts = scanner(patrn, FORWARD, PTEND);        /* Nope. Go forw

         if (!sts)
         {
                 TTputc(BELL);        /* Feep if search fails       */
                 TTflush();                /* see that the feep feeps    */
         }

         return(sts);                                /* else, don't even try
 }

 /*
  * The following is a worker subroutine used by the reverse search.  It
  * compares the pattern string with the characters at "." for equality. If
  * any characters mismatch, it will return FALSE.
  *
  * This isn't used for forward searches, because forward searches leave "."
  * at the end of the search string (instead of in front), so all that needs t
  * be done is match the last char input.
  */

 int match_pat (patrn)        /* See if the pattern string matches string at "
 char        *patrn;                /* String to match to buffer
 {
     register int  i;                        /* Generic loop index/offset
     register int buffchar;                /* character at current position
     register LINE *curline;                /* current line during scan
     register int curoff;                /* position within current line

     /* setup the local scan pointer to current "." */

     curline = curwp->w_dotp;                /* Get the current line structure
     curoff  = curwp->w_doto;                /* Get the offset within that lin

     /* top of per character compare loop: */

     for (i = 0; i < strlen(patrn); i++)        /* Loop for all characters in
     {
             if (curoff == llength(curline)) /* If at end of line
             {
             curline = lforw(curline);        /* Skip to the next line
             curoff = 0;                        /* Start at the beginning of t
             if (curline == curbp->b_linep)
                 return (FALSE);                /* Abort if at end of buffer
             buffchar = '\n';                /* And say the next char is NL
         } else
             buffchar = lgetc(curline, curoff++); /* Get the next char
         if (!eq(buffchar, patrn[i]))        /* Is it what we're looking for?
             return (FALSE);                /* Nope, just punt it then
     }
     return (TRUE);                        /* Everything matched? Let's celebr
 }

 /* Routine to prompt for I-Search string. */

 int promptpattern(prompt)
 char *prompt;
 {
     char tpat[NPAT+20];

     strcpy(tpat, prompt);                /* copy prompt to output string */
     strcat(tpat, " [");                        /* build new prompt string */
     expandp(pat, &tpat[strlen(tpat)], NPAT/2);        /* add old pattern */
     strcat(tpat, "]<META>: ");

     /* check to see if we are executing a command line */
     if (!clexec) {
         mlwrite(tpat);
     }
     return(strlen(tpat));
 }

 /* routine to echo i-search characters */

 int echochar(c,col)
 int        c;        /* character to be echoed */
 int        col;        /* column to be echoed in */
 {
     movecursor(term.t_nrow,col);                /* Position the cursor
     if ((c < ' ') || (c == 0x7F))                /* Control character?
     {
         switch (c)                                /* Yes, dispatch special ca
         {
           case '\n':                                /* Newline
             TTputc('<');
             TTputc('N');
             TTputc('L');
             TTputc('>');
             col += 3;
             break;

           case '\t':                                /* Tab
             TTputc('<');
             TTputc('T');
             TTputc('A');
             TTputc('B');
             TTputc('>');
             col += 4;
             break;

           case 0x7F:                                /* Rubout:
             TTputc('^');                /* Output a funny looking     */
             TTputc('?');                /*  indication of Rubout      */
             col++;                                /* Count the extra char
             break;

           default:                                /* Vanilla control char
             TTputc('^');                /* Yes, output prefix              */
                 TTputc(c+0x40);                /* Make it "^X"
             col++;                                /* Count this char
         }
     } else
         TTputc(c);                        /* Otherwise, output raw char */
     TTflush();                                /* Flush the output
     return(++col);                                /* return the new column no
 }

 /*
  * Routine to get the next character from the input stream.  If we're reading
  * from the real terminal, force a screen update before we get the char.
  * Otherwise, we must be re-executing the command string, so just return the
  * next character.
  */

 int get_char ()
 {
     int        c;                                /* A place to get a characte

     /* See if we're re-executing: */

     if (cmd_reexecute >= 0)                /* Is there an offset?
         if ((c = cmd_buff[cmd_reexecute++]) != 0)
             return (c);                        /* Yes, return any character

     /* We're not re-executing (or aren't any more).  Try for a real char

     cmd_reexecute = -1;                /* Say we're in real mode again
     update(FALSE);                        /* Pretty up the screen
     if (cmd_offset >= CMDBUFLEN-1)        /* If we're getting too big ...
     {
         mlwrite ("? command too long");        /* Complain loudly and bitterl
         return (metac);                        /* And force a quit
     }
     c = get1key();                /* Get the next character              */
     cmd_buff[cmd_offset++] = c; /* Save the char for next time        */
     cmd_buff[cmd_offset] = '\0';/* And terminate the buffer              */
     return (c);                                /* Return the character
 }

 /*
  * Hacky routine to re-eat a character.  This will save the character to be
  * re-eaten by redirecting the input call to a routine here.  Hack, etc.
  */

 /* Come here on the next term.t_getchar call: */

 int uneat()
 {
     int c;

     term.t_getchar = saved_get_char;        /* restore the routine address
     c = eaten_char;                        /* Get the re-eaten char
     eaten_char = -1;                        /* Clear the old char
     return(c);                                /* and return the last char
 }

 int reeat(c)
 int        c;
 {
     if (eaten_char != -1)                /* If we've already been here
         return/*(NULL)*/;                /* Don't do it again
     eaten_char = c;                        /* Else, save the char for later
     saved_get_char = term.t_getchar;        /* Save the char get routine
     term.t_getchar = uneat;                /* Replace it with ours
 }
 #else
 isearch()
 {
 }
 #endif


 ISHEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISHEX.C

 /* 1.0  07-26-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 ishex(c)                /* returns true if c is a hex number, 0-9, a-f.

 /*----------------------------------------------------------------------*/
 int c;
 {
         c = TOUPPER(c);
         return (ISDIGIT(c) OR ('A' <= c AND c <= 'F'));
 }


 ISLOWER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISLOWER.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 islower(c)                /* returns true if c is 'a' - 'z'                */

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISLOWER(c));
 }


 ISOCTAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISOCTAL.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isoctal(c)                /* returns true if c is an octal digit, 0-7.

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISOCTAL(c));
 }


 ISOK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISOK.C

 /* 1.0  01-22-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         BOOL
 isok(prompt)                /* Output prompt to stdout and accept y/n answer.
                            Return TRUE for y, FALSE for n.                */
 /*----------------------------------------------------------------------*/
 STRING prompt;
 {
         STRING getns();
         char c, ans[2];

         FOREVER
         {        getns(prompt, ans, 1);
                 c = tolower(*ans);
                 if ((c IS 'y') OR (c IS 'n'))
                         break;
                 puts("\nPlease respond with 'y' or 'no'.");
         }
         return ((c IS 'y') ? TRUE : FALSE);
 }


 ISPRINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISPRINT.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isprint(c)                /* returns true if c is printable, ' ' to '~'

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISPRINT(c));
 }


 ISPUNCT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISPUNCT.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 ispunct(c)                /* returns true if c is punctuation.

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISPUNCT(c));
 }


 ISSPACE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISSPACE.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isspace(c)                /* returns true if c is space, tab, cr, newline,
                           or formfeed.
 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISSPACE(c));
 }


 ISUPPER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ISUPPER.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         BOOL
 isupper(c)                /* returns true if c is 'A' to 'Z'                *

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (ISUPPER(c));
 }


 ITOA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ITOA.C

 /* 1.1  01-08-86                                                (itoa.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************
  *
  *        These functions are modified versions of itoa() found in Kernighan
  *        and Ritchie, page 60, with modifications as suggested in exercises
  *        3-3 and 3-5, and with returned pointer to result string.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"

 /************************************************************************/
         STRING
 itoa(s, n, w)        /* return pointer to s, which contains ascii value of
                    n to width |w|, 0-filled if w<0, else space-filled.
 /*----------------------------------------------------------------------*/
 STRING s;
 {
         STRING itoab();

         return itoab(s, n, w, 10);
 }

 /************************************************************************/
         STRING
 itoab(s, n, w, b)        /* convert n to a minimum of |w| ascii characters,
                            base b, and put  in s.  Return pointer to s.
                            0-fill if w<0, else space-fill.                */
 /*----------------------------------------------------------------------*/
 STRING s;
 {
         LOCAL char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
         int i, j;
         BOOL sign;
         char c, fill;

         if (n < 0)
         {        n = -n;
                 sign = TRUE;
         }
         else
                 sign = FALSE;
         if (w < 0)
         {        fill = '0';
                 w = -w;
         }
         else
                 fill = ' ';
         i = 0;
         do                        /* generate digits in reverse order:
         {        s[i++] = digits[n % b];
         } while (n /= b);
         if (sign)                        /* put the sign into the string.*/
                 s[j = i++] = '-';
         else
                 j = i - 1;
         while (i < w)                        /* expand to proper width.
                 s[i++] = fill;        /* i is just beyond last filled postion
         if (--i ISNT j AND sign AND fill IS '0')
         {        s[i] = s[j];                /* get the sign.
                 s[j] = fill;                /* fill in over it
         }
         s[++i] = NULL;                        /* add null terminator        *
         for (i--, j = 0; j < i; j++, i--) /*  now reverse chars */
         {        c = s[j];
                 s[j] = s[i];
                 s[i] = c;
         }
         return s;
 }


 JTOG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\JTOG.C

 /*                    *** jtog.c ***                                 */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* function to convert a julian date (1 = 1st day AD) into a         */
 /* gregorian date in the format mm/dd/yy.  Returns a 0 if successful */
 /* or a -1 if not.                                                   */
 /*                                                                   */
 /* WARNING - if outdate is not dimensioned at least 9 characters a   */
 /*           memory overwrite will occure.                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984                             */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define CENTRY 19
 #define TRUE 1
 #define FALSE 0

 int jtog(julian,outdate)
 char outdate[];
 register long julian;
 {
         static int monthd[] = {0,31,59,90,120,151,181,212,243,273,304,334};
         int centry,leap,i,iyr,imo,iday;
         static long cdays = 36524, ydays = 365;

         /* reduce julian from 1st day AD to 1st day of CENTRY */
         julian -= CENTRY*cdays + CENTRY/4;

         /* determine year */
         iyr = julian/ydays;
         if ((julian - (iyr*ydays + iyr/4)) < 0)
                 iyr -= 1;
         if (iyr < 0)
                 return(-1);

         /* determine if this is a leap year or not */
         if (iyr%4 == 0 && iyr != 0 || CENTRY%4 == 0)
                 leap = TRUE;
         else
                 leap = FALSE;

         /* determine month */
         julian = julian - (iyr*ydays + iyr/4);
         if (leap) julian += 1;
         for (imo=12;imo>0;imo--) {
                 i=0;
                 if ((leap) && (imo > 2)) i = -1;
                 if ((julian - monthd[imo-1] + i) > 0) break;
         }
         if (imo == 0) imo = 1;

         /* determine day */
         iday = julian - monthd[imo-1] + i;
         if (iday == 0) {
                 iyr -= 1;
                 if (iyr < 0) return(-1);
                 imo = 12;
                 iday = 31;
         }

         /* transfer into output string */
         if (imo > 9)
                 outdate[0] = '1';
         else
                 outdate[0] = '0';
         outdate[1] = (char)(imo%10 + '0');
         outdate[2] = '/';

         if (iday > 9)
                 outdate[3] = (char)(iday/10 + '0');
         else
                 outdate[3] = '0';
         outdate[4] = (char)(iday%10 + '0');
         outdate[5] = '/';

         if (iyr > 9)
                 outdate[6] = (char)(iyr/10 + '0');
         else
                 outdate[6] = '0';
         outdate[7] = (char)(iyr%10 + '0');
         outdate[8] = '\0';

         /* done */
         return(0);
 }


 JTOG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\JTOG.C

 /*                    *** jtog.c ***                                 */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* function to convert a julian date (1 = 1st day AD) into a         */
 /* gregorian date in the format mm/dd/yy.  Returns a 0 if successful */
 /* or a -1 if not.                                                   */
 /*                                                                   */
 /* WARNING - if outdate is not dimensioned at least 9 characters a   */
 /*           memory overwrite will occure.                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984                             */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #define CENTRY 19
 #define TRUE 1
 #define FALSE 0

 int jtog(julian,outdate)
 char outdate[];
 register long julian;
 {
         static int monthd[] = {0,31,59,90,120,151,181,212,243,273,304,334};
         int centry,leap,i,iyr,imo,iday;
         static long cdays = 36524, ydays = 365;

         /* reduce julian from 1st day AD to 1st day of CENTRY */
         julian -= CENTRY*cdays + CENTRY/4;

         /* determine year */
         iyr = julian/ydays;
         if ((julian - (iyr*ydays + iyr/4)) < 0)
                 iyr -= 1;
         if (iyr < 0)
                 return(-1);

         /* determine if this is a leap year or not */
         if (iyr%4 == 0 && iyr != 0 || CENTRY%4 == 0)
                 leap = TRUE;
         else
                 leap = FALSE;

         /* determine month */
         julian = julian - (iyr*ydays + iyr/4);
         if (leap) julian += 1;
         for (imo=12;imo>0;imo--) {
                 i=0;
                 if ((leap) && (imo > 2)) i = -1;
                 if ((julian - monthd[imo-1] + i) > 0) break;
         }
         if (imo == 0) imo = 1;

         /* determine day */
         iday = julian - monthd[imo-1] + i;
         if (iday == 0) {
                 iyr -= 1;
                 if (iyr < 0) return(-1);
                 imo = 12;
                 iday = 31;
         }

         /* transfer into output string */
         if (imo > 9)
                 outdate[0] = '1';
         else
                 outdate[0] = '0';
         outdate[1] = (char)(imo%10 + '0');
         outdate[2] = '/';

         if (iday > 9)
                 outdate[3] = (char)(iday/10 + '0');
         else
                 outdate[3] = '0';
         outdate[4] = (char)(iday%10 + '0');
         outdate[5] = '/';

         if (iyr > 9)
                 outdate[6] = (char)(iyr/10 + '0');
         else
                 outdate[6] = '0';
         outdate[7] = (char)(iyr%10 + '0');
         outdate[8] = '\0';

         /* done */
         return(0);
 }


 JTOJ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\JTOJ.C

 /*                   *** jtoj.c ***                                  */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* integer function that returns the julian date (1 = 1st day AD)    */
 /* associated with the julian date in the form (yddd).  Returns a -1 */
 /* if an error occured.                                              */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1983.                            */
 /*                                                                   */
 /*********************************************************************/

 CENTRY 19        /* current century */
 DECADE 80        /* current decade */

 long jtoj(jin)
 char jin[];
 {
         static int monthd[] = {31,28,31,30,31,30,31,31,30,31,30,31};
         int i;
         int leapd,iyr,idays;
         static long cdays = 36524, ydays = 365;

         /* parse input julian date into its pieces */
         sscanf(jin,"%1d%3d",iyr,idays);

         /* calculate year */
         iyr += DECADE;
         if (iyr < 0 || iyr > 99) return(-1);

         /* check for invalid number of days */
         if (idays < 1)
                 return(-1);

         if ((iyr%4 == 0) && ((iyr != 0) || (CENTRY%4 == 0))) {
                 if (idays > (ydays+1))
                         return(-1);
         } else {
                 if (idays > ydays)
                         return(-1);
         }

         /* determine the number of "extra" leap years caused by the  */
         /* %400 criteria and add to it the number of leap years that */
         /* has occured up to the prior year of current century.      */
         leapd = CENTRY/4;
         if (iyr != 0) leapd += (iyr-1)/4;

         /* calculate julian date */
         return (CENTRY*cdays + iyr*ydays + leapd + idays);
 }


 JTOJ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\JTOJ.C

 /*                   *** jtoj.c ***                                  */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* integer function that returns the julian date (1 = 1st day AD)    */
 /* associated with the julian date in the form (yddd).  Returns a -1 */
 /* if an error occured.                                              */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1983.                            */
 /*                                                                   */
 /*********************************************************************/

 CENTRY 19        /* current century */
 DECADE 80        /* current decade */

 long jtoj(jin)
 char jin[];
 {
         static int monthd[] = {31,28,31,30,31,30,31,31,30,31,30,31};
         int i;
         int leapd,iyr,idays;
         static long cdays = 36524, ydays = 365;

         /* parse input julian date into its pieces */
         sscanf(jin,"%1d%3d",iyr,idays);

         /* calculate year */
         iyr += DECADE;
         if (iyr < 0 || iyr > 99) return(-1);

         /* check for invalid number of days */
         if (idays < 1)
                 return(-1);

         if ((iyr%4 == 0) && ((iyr != 0) || (CENTRY%4 == 0))) {
                 if (idays > (ydays+1))
                         return(-1);
         } else {
                 if (idays > ydays)
                         return(-1);
         }

         /* determine the number of "extra" leap years caused by the  */
         /* %400 criteria and add to it the number of leap years that */
         /* has occured up to the prior year of current century.      */
         leapd = CENTRY/4;
         if (iyr != 0) leapd += (iyr-1)/4;

         /* calculate julian date */
         return (CENTRY*cdays + iyr*ydays + leapd + idays);
 }


 KBDTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\KBDTEST.C

 /*KBDTEST.C - Prints code of extended char set (F keys, Arrow, etc.).*/
 /* From the book "Microsoft C Programming for the IBM" by Robert     */
 /* Lafore, page 253.                                                 */
 /*********************************************************************/

 main()
 {
 char key, key2;

    while((key = getch()) != 'X')
       if (key == 0) {                     /* If extended code */
          key2 = getch();                  /* Read second code */
          printf("%4d, %4d\n", key, key2);
       }
       else
          printf("%4d, %12c\n", key, key);      /* Not extended code */
 }



 K_R_CH1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH1.C

 pr 1.*


 Jul 31 13:15 1984  1.00array.c Page 1


 /* example of arrays */

 #define EOF -1
 #define SZ  25
 main()  /* count digits 0 - 9 and store in elements 0 - 9 */
 {
         int c, i, digit[SZ];            /* declaration */
         while (i = 1; i < SZ; ++i)      /* initialization */
               digit[i - 1] = i;
         printf("digits =");
         for (i = 0; i < SZ; ++i)
                 printf("%4d", digit[i]);
         printf("\n");
 }

















































 Jul 27 17:12 1984  1.10first.c Page 1


 /* This is a C program that prints a
 /* message to standard output
 /* (usually your terminal) */

 main()
 {
         printf("This is a C program.\n");
 }























































 Jul 27 17:12 1984  1.29while.c Page 1


 /* print the numbers 1 - 10 with squares and cubes */

 main()
 {
         int     st, end, step, num, sq, cube;
         st = 1;
         end = 10;
         step = 1;
         num = st;
         while (num <= end)
         {       sq = num * num;
                 cube = num * sq;
                 printf("%6d %6d %6d\n", num, sq, cube);
                 num = num + step;
         }
 }















































 Jul 27 17:12 1984  1.49for.c Page 1


 /* also prints the numbers 1 - 10 with squares
    and cubes - this time with a "for" loop */

 main()
 {
         int n;

         for (n = 1; n <= 10; n = n + 1)
                 printf("%6d %6d %6d\n", n, n * n, n * n * n);
 }





















































 Jul 27 17:12 1984  1.53inc.c Page 1


 /* introduces the increment operator */

 main()
 {
         int n;

         for (n = 1; n <= 10; ++n)
                 printf("%6d %6d %6d\n", n, n * n, n * n * n);
 }






















































 Jul 27 17:12 1984  1.55symbolic.c Page 1


 /* introduces symbolic constants */

 #define MAX     10
 #define SQ      n * n
 #define CU      n * n * n
 main()
 {
         int n;

         for (n = 1; n <= MAX; ++n)
                 printf("%6d %6d %6d\n", n, SQ, CU);
 }



















































 Jul 27 17:12 1984  1.58copy.c Page 1


 /* copy input to output */

 #define EOF -1

 main()
 {
         int c;
         c = getchar();          /* see getc(3) */
         while (c != EOF) {
           putchar(c);           /* see putc(3) */
           c = getchar();
         }
 }


















































 Jul 27 17:12 1984  1.62copy2.c Page 1


 /* assignments within tests */

 #define EOF -1
 main()  /* copy input to output; 2nd version */
 {
         int c;

         while ((c = getchar()) != EOF)
                 putchar(c);
 }





















































 Jul 27 17:12 1984  1.64ccount.c Page 1


 /* character counting program */

 #define EOF -1
 main()  /* count number of characters received */
 {
         double  nc;

         for (nc = 0; getchar() != EOF; ++nc)
                         ;       /* do nothing */
         printf("char count is %.0f\n", nc);
 }




















































 Jul 27 17:12 1984  1.67lcount.c Page 1


 /* count lines */

 #define EOF -1
 main()  /* count number of lines in input */
 {
         int c;
         long nl = 0; /* combined declaration and initialization */

         while ((c = getchar()) != EOF)
                 if (c == '\n')
                         ++nl;
         printf("line count is %ld\n", nl);
 }


















































 Jul 27 17:12 1984  1.71uccount.c Page 1


 /* count upper case and others */

 #define EOF -1
 main()  /* print count of upper case letters
         /* & all other characters received */
 {
         int c, uc, oth;

         uc = oth = 0;   /* multiple assignment */
         while ((c = getchar()) != EOF)
                 if      (c >= 'A' && c <= 'Z')
                         ++uc;
                 else    ++oth;
         printf("uc is %d, oth is %d\n", uc, oth);
 }
















































 Jul 27 17:12 1984  1.73lwccount.c Page 1


 /* line, word, and char count */
 #define EOF -1
 #define YES  1
 #define NO   0
 main()  /* count lines, words, chars in input */
 {       int c, nl, nw, inword = NO;
         long nc;
         nl = nw = nc = 0;
         while ((c = getchar()) != EOF)
         {       ++nc;
                 if (c == '\n')
                         ++nl;
                 if      (c == ' ' || c == '\t' || c == '\n')
                         inword = NO;
                 else if (inword == NO)
                 {       inword = YES;
                         ++nw;
                 }
         }
         printf("lines, words, chars: %d %d %ld\n", nl, nw, nc);
 }










































 Jul 27 17:12 1984  1.77power.c Page 1


 /* example of function calls */

 main()  /* test power() for range 1 - 9 */
 {
         int i;
         printf("   Num   Sq\n");
         for (i = 1; i < 10; ++i)
                 printf("%5d %5d\n", i, power(i, 2));
 }
 power(x, n)     /* raise x to the n-th power; n > 0 */
 int x, n;       /* declaration of arguments */
 {
         int i, p = 1;
         for (i = 1; i <= n; ++i)
                 p = p * x;
         return (p);
 }














































 Jul 27 17:12 1984  1.85array.c Page 1


 /* example of arrays */

 #define EOF -1
 #define SZ  10
 main()  /* count digits 0 - 9 and store in elements 0 - 9 */
 {
         int c, i, digit[SZ];            /* declaration */
         for (i = 0; i < SZ; ++i)        /* initialization */
                 digit[i] = 0;
         while ((c = getchar()) != EOF)
                 if (c >= '0' && c <= '9')
                         ++digit[c - '0'];
         printf("digits =");
         for (i = 0; i < SZ; ++i)
                 printf("%4d", digit[i]);
         printf("\n");
 }














































 Jul 27 17:12 1984  1.91square.c Page 1


 /* example of call by value/reference */

 #define MAX 10
 main()  /* test of square() */
 {
         int answer[MAX], i;
         square(answer, MAX);
         for (i = 0; i < MAX; ++i)
                 printf("element %d contains %2d\n", i, answer[i]);
 }
 square(ar, sz)  /* fills array ar of size sz with the
                 /* square of the element number */
 int ar[], sz;
 {
         for (--sz; sz >= 0; --sz)
                 ar[sz] = sz * sz;
 }














































 Jul 27 17:12 1984  1.94getline.c Page 1


 /* example of character arrays */

 #define EOF -1
 #define MAX 30
 main()  /* use getline() to get a name from terminal */
 {
   char greet[6], name[MAX];

   printf("input name: ");
   if    (getline(name, MAX) > 1)
   {     greet[0] = 'H';
         greet[1] = 'E';
         greet[2] = 'L';
         greet[3] = 'L';
         greet[4] = 'O';
         greet[5] = '\0';
         printf("%s %s", greet, name);
   }
   else
         printf("no name received\n");
 }
 getline(line, lim)      /* function to read a line from std input;
                         /* insert NULL at end and return char count */
 char    line[];         /* array where line will be stored */
 int     lim;            /* max line size */
 {
   int   c, i;

   for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
         line[i] = c;
   if (c == '\n')                /* retain  */
         line[i++] = c;          /* newline */
   line[i] = '\0'; return (i);
 }





























 Jul 27 17:12 1984  1.98external.c Page 1


 /* example of external variables */
 int max;        /* external variable */
 main()
 {       int i, j;

         i = getint();
         j = getint();
         if (findmax(i, j))
                 printf("%d is largest\n", max);
         else    printf("%d and %d are equal\n", i, j);
 }
 findmax(x, y)
 int x, y;
 {
         if      (x == y)
                 return (0);
         else if (x < y)
                 max = y;
         else    max = x;
         return (1);
 }
 getint()        /* function to convert ASCII
                 /* input from terminal to an int */
 {       int     c, sign = 1, num = 0;

         printf("input integer: ");
         if      ((c = getchar()) == '-')
                 sign = -1;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         else
                 return (0);
         while ((c = getchar()) >= '0' && c <= '9')
                 num = num * 10 + (c - '0');
         return (num * sign);
 }

























 $


 K_R_CH2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH2.C

 pr 2.*


 Jul 27 17:12 1984  2.34conv.c Page 1


 /* type conversion */

 main()  /* print conversion table from cm to inches
         /* 1 inch = 2.54 cm - from 1 through 12 cm */
 {
         int cm;

         for (cm = 1; cm <= 12; ++cm)
           printf("cm = %3d, inch = %6.2f\n", cm, cm / 2.54);
 }





















































 Jul 27 17:12 1984  2.50comma.c Page 1


 main()  /* calculate the sum of all integers between and including
         /* 2 input integers, compute their average and remainder */
 { int   i, n1, n2, ct, sm;
   n1 = getint(); n2 = getint();
   if (n1 <= n2)
   { for (ct = sm = 0, i = n1; i <= n2; ++i)
     {   sm += i; ++ct;
     }
     printf("n1 = %d, n2 = %d, sum = %d, ave = %.2f, remainder = %d\n",
                 n1, n2, sm, (float) sm / ct, sm % ct);
   }
   else
   { printf("2nd number not big enough\n"); exit(1);
   }
 }
 getint()        /* function to convert ASCII
                 /* input from terminal to an int */
 {       int     c, sign = 1, num = 0;

         printf("input integer: ");
         if      ((c = getchar()) == '-')
                 sign = -1;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         else
                 return (0);
         while ((c = getchar()) >= '0' && c <= '9')
                 num = num * 10 + (c - '0');
         return (num * sign);
 }

































 Jul 27 17:12 1984  2.58itob.c Page 1


 SZ      8 * sizeof(int) /* for portabilty       */
 main()  /* function to test itob(), integer to binary */
 {       char asc[SZ+1];
         int i = getint();
         itob(i, asc);
         printf("dec = %d, octal = %o, binary = %s\n", i, i, asc);
 }
 itob(num, ar)   /* convert int to ASCII 0's and 1's */
 int num;        /* received int */
 char ar[];      /* array to store 0's and 1's */
 {       int cnt, mask = 1;
         for (cnt = SZ - 1; cnt >= 0; --cnt)
         {       ar[cnt] = ((num & mask)? '1': '0'); mask <<= 1;
         }
         ar[SZ] = '\0';
 }
 getint()        /* function to convert ASCII
                 /* input from terminal to an int */
 {       int     c, sign = 1, num = 0;

         printf("input integer: ");
         if      ((c = getchar()) == '-')
                 sign = -1;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         else
                 return (0);
         while ((c = getchar()) >= '0' && c <= '9')
                 num = num * 10 + (c - '0');
         return (num * sign);
 }






























 $


 K_R_CH3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH3.C

 pr 3.*


 Jul 27 17:12 1984  3.10while.c Page 1


 main()  /* example of nested while statements */
 {
         int x = 10, y;

         while (x >= 0)
         {       y = x;
                 while (y >= 0)
                 {       printf("%2d%c", y, (y == 0)? '\n': '\040');
                         --y;
                 }
                 --x;
         }
 }


















































 Jul 27 17:12 1984  3.14for.c Page 1


 main()  /* example of nested for statements */
 {       int i, j;

         for (i = 0; i < 5; ++i)
         {
                 for (j = 0; j < 5; ++j)
                         printf("%d,%d  ", i, j);
                 putchar('\n');
         }
 }





















































 Jul 27 17:12 1984  3.20wc.c Page 1


 #define EOF -1
 main()  /* emulation of wc(1) without options */
 {       int     c, inword;
         long    cc, lc, wc;
         inword = cc = lc = wc = 0;
         while ((c = getchar()) != EOF)
         {       ++cc;
                 switch (c)
                 { case '\n':    ++lc;
                   case '\t':
                   case '\040':  inword = 0; break;
                   default:      if (!inword)
                                         ++wc;
                                 inword = 1;
                 }
         }
         printf("%7ld %6ld %6ld\n", lc, wc, cc);
 }













































 Jul 27 17:12 1984  3.24strln.c Page 1


 #define EOF -1
 #define MAX 256
 main()  /* test strln() */
 { char stor[MAX];
   getline(stor, MAX);
   printf("string length including null at end is %d\n", strln(stor));
 }
 strln(str)      /* return length of char string stored in array str;
                 /* include null at end in count */
 char str[];
 {       int i = 0, length = 0;
         do
         {       ++length;
         } while (str[i++] != '\0');
         return (length);
 }
 getline(line, lim)      /* function to read a line from std input;
                         /* insert NULL at end and return char count */
 char    line[];         /* array where line will be stored */
 int     lim;            /* max line size */
 {
   int   c, i;

   for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
         line[i] = c;
   if (c == '\n')                /* retain  */
         line[i++] = c;          /* newline */
   line[i] = '\0'; return (i);
 }


































 Jul 27 17:12 1984  3.28bc.c Page 1


 main()  /* example of break and continue */
 {
         int     x, y;
         for (x = 10; x; --x)
         {       if      (x == 3)
                         break;
                 else    y = x - 1;
                 while   (y)
                 {       if (y == 3)
                         {       --y; continue;
                         }
                         printf("%3d,%d ", x, y--);
                 }
                 putchar('\n');
         }
 }















































 Jul 27 17:12 1984  3.32bcg.c Page 1


 main()  /* example of break, continue, and goto */
 {
         int     x, y;
         for (x = 10; x; --x)
         {       if      (x == 3)
                         break;
                 else    y = x - 1;
                 while   (y)
                 {       if (y == 3)
                         {       --y; continue;
                         }
                         else if (x == 5 && y == 1)
                                 goto done;
                         printf("%3d,%d ", x, y--);
                 }
                 putchar('\n');
         }
         done: printf(" DONE!\n");
 }










































 $


 K_R_CH4.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH4.C

 pr 4.*


 Jul 27 17:12 1984  4.08getdbl.c Page 1


 #define EOF -1
 int main()      /* obtain 3 dimensions and compute volume */
 {       double l, w, h, getdbl(), vol();

         l = getdbl(); w = getdbl(); h = getdbl();
         printf("(dimensions %.2f x %.2f x %.2f) vol is %.2f\n",
                 l, w, h, vol(l, w, h));
 }
 double vol(a, b, c)     /* given 3 dimensions compute volume */
 double a, b, c;         /* arg declarations */
 {
         return (a * b * c);
 }
 double  getdbl()        /* convert ASCII from terminal to dbl */
 {       int     c, sign = 1;    /* c = char input, sign = + */
         float   d = 1.0;        /* d = decimal place */
         double  num = 0.0;      /* num = converted number */
         printf("input number: ");
         if      ((c = getchar()) == '-')
                 sign = -1;                      /* sign = - */
         else if (c == '\n' || c == EOF)
                 return (0);
         else if (c == '.')
                 goto dot;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         while ((c = getchar()) != '\n' && c != '.' && c != EOF)
                 if (c >= '0' && c <= '9')
                         num = num * 10 + (c - '0');
         if (c == '.')
 dot:            while ((c = getchar()) != EOF && c != '\n')
                         if (c >= '0' && c <= '9')
                         { d /= 10.0; num += d * (c - '0');
                         }
         return (num * sign);
 }



























 Jul 27 17:12 1984  4.14vol_a.c Page 1


 double l, w, h, volume; /* external variables */

 int main()      /* obtain 3 dimensions and compute volume */
 {
         double getdbl();
         l = getdbl(); w = getdbl(); h = getdbl();
         vol_ext();
         printf("(dimensions %.2f x %.2f x %.2f) vol is %.2f\n",
                 l, w, h, volume);
 }





















































 Jul 27 17:12 1984  4.14vol_b.c Page 1


 extern double l, w, h, volume;  /* extern required if sep src file */

 vol_ext()       /* given 3 dimensions compute volume */
 {
         volume = l * w * h;
 }

























































 Jul 27 17:12 1984  4.14vol_c.c Page 1


 EOF -1          /* define moved to this file */
 double  getdbl()        /* convert ASCII from terminal to dbl */
 {       int     c, sign = 1;    /* c = char input, sign = + */
         float   d = 1.0;        /* d = decimal place */
         double  num = 0.0;      /* num = converted number */
         printf("input number: ");
         if      ((c = getchar()) == '-')
                 sign = -1;                      /* sign = - */
         else if (c == '\n' || c == EOF)
                 return (0);
         else if (c == '.')
                 goto dot;
         else if (c >= '0' && c <= '9')
                 num = (c - '0');
         while ((c = getchar()) != '\n' && c != '.' && c != EOF)
                 if (c >= '0' && c <= '9')
                         num = num * 10 + (c - '0');
         if (c == '.')
 dot:            while ((c = getchar()) != EOF && c != '\n')
                         if (c >= '0' && c <= '9')
                         { d /= 10.0; num += d * (c - '0');
                         }
         return (num * sign);
 }







































 Jul 27 17:12 1984  4.17perm.c Page 1


 main()  /* test stat() */
 {
         int i;
         for (i = 0; i <= 9; ++i)
                 stat();
 }
 stat()  /* demonstration of internal static */
 {
         int fgt = 0;
         static int rem;         /* count calls */

         printf("this is call %2d, fgt is %d\n", ++rem, ++fgt);
 }


















































 Jul 27 17:12 1984  4.18block.c Page 1


 char ABC[] = { 'A', 'B', 'C', '\0' };                           /* 1st declar
 main()  /* demonstration of static and scope rules */
 { printf("main() ABC[] is %s\n", ABC);
   sub(); sub();
 }
 sub()   /* declare, initialize, & access two ABC[]'s */
 { static int ABC[] = { 1, 2, 3 };                               /* 2nd declar
   { static long ABC[] = { 10000, 20000, 30000 };                /* 3rd declar
     printf("sub() sub-block ABC[1] is %ld\n", ABC[1]++);
   }
   printf("sub() ABC[1] is %d\n", ABC[1]++);
 }



















































 Jul 27 17:12 1984  4.26fact.c Page 1


 /* example of recursive function */

 main() /* test fact() for range 1 - 10 */
 {       register int i;
         double fact();
         for (i = 1; i <= 10; ++i)
                 printf("%2d! is %8.0f\n", i, fact(i));
 }
 double fact(num)        /* recursive function to compute and
                            return factorial (num!) for num > 0 */
 int num;
 {       if      (num > 1)
                 return (num * fact(num - 1));
         else    return 1;
 }
















































 Jul 27 17:12 1984  4.29prepro.c Page 1


 /* examples of #include & #define */

 <stdio.h>      /* EOF - used by getdbl() -
                         /* is defined in <stdio.h> */
 "getdbl.f"     /* assumes getdbl() is in
                         /* file getdbl.f in wd */
 #define max(A, B) ((A) > (B)? (A): (B))

 main()  /* test max macro */
 {
         double getdbl();
         double i = getdbl(), j = getdbl();
         printf("max is %f\n", max(i, j));
 }

















































 Jul 27 17:12 1984  4.30sqrt.c Page 1


 /* another #include and nested function calls
 /* compile as "cc filename -lm"
 /* see exp(3M) and start of section 3 (3M) */

 <math.h>       /* declares sqrt() as type double */
 <stdio.h>      /* provides EOF for getdbl() */
 "getdbl.f"     /* assumes getdbl() is in
                         /* file getdbl.f in wd */

 main() /* use sqrt() to compute square roots */
 {
         double getdbl();
         printf("square root is %f\n", sqrt(getdbl()));
 }















































 $


 K_R_CH5.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH5.C

 pr 5.*


 Aug  3 09:13 1984  5.12pdemo.c Page 1


 main()          /* demonstration of pointers */
 {
   int x, y;
   int *px;      /* declare px pointer to type int */

   x = 5;
   px = &x;      /* initialize px to address of x */
   y = *px;      /* initialize y to contents of address
                    contained in px */
   printf("addresses of x, y, px are...\n\t%8o, %8o, %8o\n",
                 &x, &y, &px);
   printf("values of x, y, px, *px are...\n\t%8d, %8d, %8o, %8d\n",
                 x, y, px, *px);
 y = 12;
 px = &y;
   printf("addresses of x, y, px are...\n\t%8o, %8o, %8o\n",
                 &x, &y, &px);
   printf("values of x, y, px, *px are...\n\t%8d, %8d, %8o, %8d\n",
                 x, y, px, *px);
 }











































 Jul 27 17:12 1984  5.14swap_ng.c Page 1


 /* swapping values - wrong way */

 "getint.f"     /* assumes getint() in
                            file getint.f in wd */
 main()
 {       int a = getint(), b = getint();

         printf("original a, b are\t%6d, %6d\n", a, b);
         swap_ng(a, b);
         printf("swapped a, b are\t%6d, %6d\n", a, b);
 }
 swap_ng(x, y)           /* call by value */
 int x, y;
 {       int tmp;
         tmp = x;
         x = y;
         y = tmp;
 }













































 Jul 27 17:12 1984  5.17swap.c Page 1


 /* swapping values - correct way */

 "getint.f"     /* assumes getint() in
                            file getint.f in wd */
 main()
 {       int a = getint(), b = getint();

         printf("original a, b are\t%6d, %6d\n", a, b);
         swap(&a, &b);
         printf("swapped a, b are\t%6d, %6d\n", a, b);
 }
 swap(px, py)            /* call by reference */
 int *px, *py;           /* px, py are pointers to type int */
 {       int tmp;
         tmp = *px;
         *px = *py;
         *py = tmp;
 }













































 Jul 27 17:12 1984  5.20ap.c Page 1


 /* demonstration of similarity between arrays and pointers */

 main()
 {       static char ar[] = "test";
         char *par;
         int i;
         par = ar;               /* "&" not used, WHY? */

         printf("array is\t\"%s\"\n", ar);
         printf("pointer is\t\"%s\"\n", par);
         printf("array\tpointer\n");
         for (i = 0; i < (sizeof(ar) - 1); ++i)
                 printf("  %c\t  %c\n", ar[i], *par++);
 }

















































 Jul 27 17:12 1984  5.26pcs.c Page 1


 /* pointers to "character strings" */

 main()
 {       static char arr1[] = { 'I', ' ', 'u', 's', 'e', '\0' };
         char *ptr1 = arr1;
         char *ptr2 = "pointers.";

         printf("%s %s\n", ptr1, ptr2);
 }






















































 Jul 27 17:12 1984  5.28strln_p.c Page 1


 /* pointer version of strln() */

 #define MAX 256
 <stdio.h>      /* getline() needs EOF */
 "getline.f"    /* assumes getline() is in
                            file getline.f in wd */
 main()  /* test strln_p() */
 {       char stor[MAX];
         getline(stor, MAX);
         printf("string length is %d\n", strln_p(stor));
 }
 strln_p(ptr)    /* return length of char string pointed to by ptr;
                 /* include null at end in count */
 char *ptr;
 {       register length = 0;
         do
         {       ++length;
         } while (*ptr++ != '\0');       /* ++ increments ptr by 1 */
         return (length);
 }











































 Jul 27 17:12 1984  5.30strcpy.c Page 1


 /* copying strings - array version */

 #define MAX 256
 <stdio.h>      /* getline() needs EOF */
 "getline.f"    /* assumes getline() is in
                            file getline.f in wd */
 main() /* test strcpy() */
 {       char src[MAX], dest[MAX];
         getline(src, MAX);
         strcpy(dest, src);
         printf("src, dest...\n%s%s", src, dest);
 }
 strcpy(d, s)    /* copy string in s[] into d[] */
 char d[], s[];
 {       register i;
         for (i = 0; d[i] = s[i]; ++i)
                 ;
 }













































 Jul 27 17:12 1984  5.33strcpy_p.c Page 1


 /* copying strings - pointer version */

 #define MAX 256
 <stdio.h>      /* getline() needs EOF */
 "getline.f"    /* assumes getline() is in
                            file getline.f in wd */
 main() /* test strcpy_p() */
 {       char src[MAX], dest[MAX];
         getline(src, MAX);
         strcpy_p(dest, src);
         printf("src, dest...\n%s%s", src, dest);
 }
 strcpy_p(d, s)  /* copy string *s to *d */
 char *d, *s;
 {
         while (*d++ = *s++)
                 ;
 }













































 Jul 27 17:12 1984  5.34strcmp.c Page 1


 /* comparing strings with pointers */

 #define MAX 256
 #include <stdio.h>
 #include "getline.f"
 main()  /* test strcmp() */
 {       char str1[MAX], str2[MAX];
         register ret;
         printf("input 1st string: "); getline(str1, MAX);
         printf("input 2nd string: "); getline(str2, MAX);
         if (!(ret = strcmp(str1, str2)))
                 printf("they are equal\n");
         else    printf("no match, char %d\n", ret);
 }
 strcmp(s1, s2)  /* compare 2 strings;
                 /* if match return 0 (else char count) */
 char    *s1, *s2;
 {       register i;
         for (i = 1; *s1 == *s2; ++i)
                 if (*s1++ == '\0')
                         return (0);
                 else s2++;
         return (i);
 }







































 Jul 27 17:12 1984  5.38mda1.c Page 1


 #define D1 3
 #define D2 5
 int a[D1][D2];  /* two-dimensional array */
 main()          /* demonstration of multi-dimensional array */
 { register i, j;

   for (i = 0; i < D1; ++i)
     for (j = 0; j < D2; ++j)
     { a[i][j] = (i * D2) + j + 1;
       printf("a[%d][%d] adr, value is %o, %2d\n",
                 i, j, &a[i][j], a[i][j]);
     }
 }


















































 Jul 27 17:12 1984  5.40mda2.c Page 1


 #define D1 3
 #define D2 5
 int a[][D2] =   { {  1,  2,  3,  4,  5 },
                   {  6,  7,  8,  9, 10 },
                   { 11, 12, 13, 14, 15 }
                 };      /* compiler initialized */
 main()  /* two-dimensional array; another version */
 { register i, j;

   for (i = 0; i < D1; ++i)
     for (j = 0; j < D2; ++j)
       printf("a[%d][%d] adr, value is %o, %2d\n",
                 i, j, &a[i][j], a[i][j]);
 }

















































 Jul 27 17:12 1984  5.44aop.c Page 1


 main()  /* demonstration of an array of pointers */
 {       register i;
         static char *arp[] =    { "I",
                                   "NEED",
                                   "HELP",
                                   ""
                                 };
         for (i = 0; *arp[i]; ++i)
                 printf("%s ", arp[i]);
         putchar('\n');
 }




















































 Jul 27 17:12 1984  5.49argdemo.c Page 1


 /* demonstration of arguments passed to main() */

 main(argc, argv, envp)          /* three args to main() */
 int     argc;                   /* argc is an int */
 char    *argv[], *envp[];       /* argv & envp are arrays
                                 /* of character pointers */
 {       register i;

         printf("argc is %d\n", argc);
         for (i = 0; i < argc; ++i)
                 printf("*argv[%d] is %s\n", i, argv[i]);
         for (i = 0; envp[i]; ++i)
                 printf("*envp[%d] is %s\n", i, envp[i]);
 }

















































 Jul 27 17:12 1984  5.50echo1.c Page 1


 main(argc, argv)        /* emulation of basic echo(1) command;
                         /* first version, array notation */
 int     argc;
 char    *argv[];
 {
   register i;

   for (i = 1; i < argc; ++i)
     printf("%s%c", argv[i], (i < argc - 1)? ' ': '\n');
 }





















































 Jul 27 17:12 1984  5.53echo2.c Page 1


 main(argc, argv)        /* emulation of basic echo(1) command;
                         /* second version, pointer notation */
 int     argc;
 char    **argv;         /* same as *argv[] */
 {
   while (--argc > 0)
     printf("%s%c", *++argv, (argc > 1)? ' ': '\n');
 }























































 Jul 27 17:12 1984  5.60frp.c Page 1


 /* demonstration of function returning pointer */

 main()                  /* test new version of getint() */
 {
   int *getintp();       /* getintp() returns pointer to type int */

   printf("%d\n", *getintp());
 }
 int *getintp()  /* function to convert ASCII
                 /* input from terminal to an int;
                 /* return pointer to int */
 { int   c, sign = 1, num = 0;

   printf("input integer: ");
   if    ((c = getchar()) == '-')
         sign = -1;
   else if (c >= '0' && c <= '9')
         num = (c - '0');
   else
         return (&num);
   while ((c = getchar()) >= '0' && c <= '9')
         num = num * 10 + (c - '0');
   num *= sign;
   return (&num);
 }






































 Jul 27 17:12 1984  5.63pfi.c Page 1


 /* demonstration of pointer to function */

 main()          /* test inter() */
 {
   int getint(); /* getint() must be declared */

   printf("%d\n", inter(getint));
 }
 inter(pfi)      /* call function via pointer arg */
 int (*pfi)();   /* pfi is pointer to function
                 /* returning type int */
 {
   return ((*pfi)());    /* (*pfi)() is a function call */
 }
 "getint.f"     /* assumes getint() is in
                         /* file getint.f in wd */













































 $


 K_R_CH6.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH6.C

 pr 6.*


 Jul 27 17:12 1984  6.14struct1.c Page 1


 /* demonstration of a structure, 1st version */

 struct data
 { char first[20];
   char  last[26];
   double     sal;
 };                      /* external definition */
 main()                  /* print structure contents */
 { static struct data emp = { "Linda",
                              "Sample",
                               39000.0
                            };   /* declare and init */
   printf("%s %s earns $%.2f per year\n",
                 emp.first, emp.last, emp.sal);
 }
















































 Jul 27 17:12 1984  6.17struct2.c Page 1


 /* demonstration of a structure, 2nd version */

 #define FSZ 20
 #define LSZ 26
 #include <stdio.h>
 "getlinepn.f"  /* does not retain newline */
 #include "getdbl.f"
 struct
 { char first[FSZ];
   char  last[LSZ];
   double     sal;
 } emp;  /* external definition and declaration */
 main()  /* populate then print structure */
 { double getdbl();
   printf("input first name: "); getlinepn(emp.first, FSZ);
   printf("input last name: ");  getlinepn(emp.last, LSZ);
   printf("(annual salary) ");   emp.sal = getdbl();
   printf("%s %s earns $%.2f per year\n",
                 emp.first, emp.last, emp.sal);
 }











































 Jul 27 17:12 1984  6.20aos.c Page 1


 /* demonstration of an array of structures */

 struct data
 { char first[20];
   char  last[26];
   double     sal;
 };              /* external definition */
 main()          /* find and print last names M - Z */
 { register i;
   static struct data ar[] = { { "Linda", "Sample", 39000.0 },
                               { "Sam", "Next", 37500.0 },
                               { "Larry", "Last", 34900.0 },
                              }; /* declare and init array ar */
   printf("employees with last names M - Z...\n");
   for (i = 0; i < (sizeof(ar) / sizeof(ar[0])); ++i)
     if (ar[i].last[0] >= 'M' && ar[i].last[0] <= 'Z')
         printf("\t%s %s earns $%.2f per year\n",
           ar[i].first, ar[i].last, ar[i].sal);
 }












































 Jul 27 17:12 1984  6.24cbv.c Page 1


 /* passing structures as arguments - by value */

 struct data
 { char first[20];
   char  last[26];
   double     sal;
 };              /* external definition */
 main()          /* test check() */
 { register i;
   double pay = 36000.0;
   static struct data ar[] = { { "Linda", "Sample", 39000.0 },
                               { "Sam", "Next", 37500.0 },
                               { "Larry", "Last", 34900.0 },
                              }; /* declare and init array ar */
   printf("employees earning more than $%.2f per year...\n", pay);
   for (i = 0; i < (sizeof(ar) / sizeof(ar[0])); ++i)
     if (check(ar[i], pay))
         printf("\t%s %s earns $%.2f per year\n",
           ar[i].first, ar[i].last, ar[i].sal);
 }
 check(str, lim)         /* return 1 if sal >= lim */
 struct data str;        /* struct declaration */
 double lim;
 { if (str.sal >= lim)
         return (1);
   return (0);
 }




































 Jul 27 17:12 1984  6.26cbr.c Page 1


 /* passing structures as arguments - by reference */

 struct data
 { char first[20];
   char  last[26];
   double     sal;
 };              /* external definition */
 main()          /* test check_p() */
 { register i;
   double pay = 36000.0;
   static struct data ar[] = { { "Linda", "Sample", 39000.0 },
                               { "Sam", "Next", 37500.0 },
                               { "Larry", "Last", 34900.0 },
                              }; /* declare and init array ar */
   printf("employees earning more than $%.2f per year...\n", pay);
   for (i = 0; i < (sizeof(ar) / sizeof(ar[0])); ++i)
     if (check_p(&ar[i], pay))
         printf("\t%s %s earns $%.2f per year\n",
           ar[i].first, ar[i].last, ar[i].sal);
 }
 check_p(pstr, lim)      /* return 1 if sal >= lim */
 struct data *pstr;      /* pointer to struct declaration */
 double lim;
 { if (pstr->sal >= lim)
         return (1);
   return (0);
 }




































 Jul 27 17:12 1984  6.34fields.c Page 1


 /* structure with fields */

 #define YES 1
 #define NO  0
 struct
 { char first[20];
   char  last[26];
   double     sal;
   unsigned retire : 1;  /* field width 1 bit */
   unsigned school : 1;  /* field width 1 bit */
 } ar[] = { { "Linda", "Sample", 39000.0, NO,  NO },
            { "Sam",   "Next",   37500.0, NO, YES },
            { "Larry", "Last",   34900.0, YES, NO },
          };     /* declare and init external array */
 main()  /* find and print active employees;
         /* note if in school */
 { register i;
   printf("active employees...\n");
   for (i = 0; i < (sizeof(ar) / sizeof(ar[0])); ++i)
   { if (!ar[i].retire)
     {   printf("\t%s %s earns $%.2f per year\n",
            ar[i].first, ar[i].last, ar[i].sal);
         if (ar[i].school)
            printf("\t\t(in school)\n");
     }
   }
 }




































 Aug  7 15:11 1984  6.40unions.c Page 1


 union utag
 { char  ca[256];        /* type 1 */
   int       num;        /* type 2 */
 };                      /* external definition */
 #include <stdio.h>
 #include "getline.f"
 #include "getint.f"
 main(argc, argv)        /* load union, call chk_u() */
 int argc;               /*      to test and print  */
 char **argv;
 { union utag udemo;     /* union declaration */
   ++argv;               /* point to argv[1]  */
   if (*++*argv != '\0') /* test 2nd char of *argv[1] */
     chk_u(0, &udemo);   /*      if not '\0' fail    */
   switch (*--*argv)     /* test 1st char of *argv[1] */
   { case '1': printf("input line: "); getline(udemo.ca, 256);
               chk_u(**argv, &udemo);
     case '2': udemo.num = getint(); chk_u(**argv, &udemo);
     default:  chk_u(**argv, &udemo);
   }
 }
 chk_u(utype, pun)       /* test, then print union and exit */
 char utype;
 union utag *pun;        /* pun is pointer to union */
 if(pun -> ca == pun ->num)
      printf("same size");
 else printf("different size");
 { switch(utype)
   { case '1': printf("type 1, content...\n\t%s", pun->ca);
               break;
     case '2': printf("type 2, value is %d\n", pun->num);
               break;
     default:  printf("usage: filename { 1 2 }\n");
               exit(1);  /* exit unsuccessfully */
   }
   exit(0);              /* exit successfully */
 }
























 $


 K_R_CH7.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\TUTOR\K_R\K_R_CH7.C

 pr 7.*


 Jul 27 17:12 1984  7.14getdbl_n.c Page 1


 #include <stdio.h>
 main()                  /* test getdbl_n() */
 {       double getdbl_n();
         printf("number is %f\n", getdbl_n());
 }
 double  getdbl_n()      /* convert ASCII to dbl - 2nd version */
 {       int     c, sign = 1;    /* c = char input, sign = + */
         float   d = 1.0;        /* d = decimal place */
         double  num = 0.0;      /* num = converted number */
         printf("input number: ");
         if      ((c = getc(stdin)) == '-')
                 sign = -1;              /* sign = - */
         else if (c == '\n' || c == EOF)
                 return (0);
         else if (c == '.' || (c >= '0' && c <= '9'))
                 ungetc(c, stdin);       /* return c to buffer */
         while ((c = getc(stdin)) != '\n' && c != '.' && c != EOF)
                 if (c >= '0' && c <= '9')
                         num = num * 10 + (c - '0');
         if (c == '.')
                 while ((c = getc(stdin)) != EOF && c != '\n')
                         if (c >= '0' && c <= '9')
                         { d /= 10.0; num += d * (c - '0');
                         }
         return (num * sign);
 }





































 Jul 27 17:12 1984  7.20cp.c Page 1


 #include <stdio.h>
 main(argc, argv)        /* modified cp(1) command */
 int argc;
 char *argv[];
 { FILE *fpr, *fpw;      /* pointers to type FILE */
   if (argc != 3)
   { printf("usage: %s src_file dest_file\n", argv[0]);
     exit(1);
   }
   if ((fpr = fopen(argv[1], "r")) == NULL)
   { printf("%s: cannot access %s\n", argv[0], argv[1]);
     exit(2);
   }
   if ((fpw = fopen(argv[2], "w")) == NULL)
   { printf("%s: cannot create %s\n", argv[0], argv[2]);
     exit(2);
   }
   if (copy(fpr, fpw) == EOF)
         exit(0);        /* success */
   exit(3);              /* failure */
 }
 copy(fp1, fp2)          /* copy fp1 to fp2 */
 FILE *fp1, *fp2;
 {
         int c;

         while ((c = getc(fp1)) != EOF)
                 putc(c, fp2);
         return (c);
 }

































 Jul 27 17:12 1984  7.27cat.c Page 1


 #include <stdio.h>
 main(argc, argv)        /* modified cat(1) command */
 int argc;
 char *argv[];
 {
   register i, c;
   FILE *fp;             /* fp is pointer to type FILE */

   for (i = 1; i < argc; ++i)
   { if ((fp = fopen(argv[i], "r")) == NULL)
     {   fprintf(stderr, "%s: cannot open %s\n",
                 argv[0], argv[i]);
         continue;
     }
     while ((c = getc(fp)) != EOF)
         putc(c, stdout);
     fclose(fp);
   }
 }












































 Jul 27 17:12 1984  7.34sscanf.c Page 1


 #include <stdio.h>
 char tst[] = "123456.78 592 89000 now is the time";
 main()  /* demonstration of sscanf() */
 {
   int   dec;
   float f;
   long  lg;
   char  s1[50], s2[50];
   int ret;

   ret = sscanf(tst, "%3d %f %*d %ld %s %[a-z ]",
                 &dec, &f, &lg, s1, s2);
   printf("return from sscanf() was %d\n", ret);
   printf("int dec is %d\n", dec);
   printf("float f is %.2f\n", f);
   printf("long lg is %ld\n", lg);
   printf("array s1 is \"%s\"\n", s1);
   printf("array s2 is \"%s\"\n", s2);
 }












































 Jul 27 17:12 1984  7.46atof.c Page 1


 /* another version of getdbl() */

 #include <stdio.h>
 #define MAX 256
 main()  /* test getdbl_a() */
 {       double getdbl_a();

         printf("num is %f\n", getdbl_a());
 }
 double getdbl_a()       /* use (3S) & (3C) functions */
 {       char stor[MAX];
         double atof();

         printf("input number: ");
         return (atof(fgets(stor, MAX, stdin)));
 }















































 Jul 27 17:12 1984  7.50create.c Page 1


 #include <stdio.h>
 #define SCORE 8
 struct record
 {       char name[48];
         float score[SCORE];
 };
 main()  /* create DATAFILE with student names and scores */
 {       struct record data;
         FILE *fp;
         if ((fp = fopen("DATAFILE", "w")) == NULL)
         {       fprintf(stderr, "cannot create DATAFILE\n");
                 exit(2);
         }
         while (load(&data))
                 fwrite(&data, sizeof (data), 1, fp);
         exit(0);
 }
 load(pstr)      /* get data from terminal; load structure */
 struct record *pstr;
 {
         register i;
         printf("\ninput name: ");
         gets(pstr->name);
         if (pstr->name[0] == '\0')
                 return (0);
         printf("input up to %d scores ('q' to quit): ", SCORE);
         for (i = 0; i < SCORE ; ++i)
                 if (scanf("%f", &pstr->score[i]) != 1)
                 {       pstr->score[i] = EOF;
                         break;
                 }
         while (getchar() != '\n')       /* buffer drain */
                 ;
         return (1);
 }




























 Jul 27 17:12 1984  7.52getinfo.c Page 1


 #include <stdio.h>
 #define SCORE 8
 struct record
 {       char name[48];
         float score[SCORE];
 };
 main()  /* get information from DATAFILE */
 {       struct record data;
         FILE *fp;
         if ((fp = fopen("DATAFILE", "r")) == NULL)
         {       fprintf(stderr, "cannot open DATAFILE\n");
                 exit(2);
         }
         while (fread(&data, sizeof (data), 1, fp))
                 print(&data);
         exit(0);
 }
 print(pstr)     /* compute student ave; provide printout */
 struct record *pstr;
 {
         register i, cnt = 0;
         double num = 0.0;
         for (i = 0; i < SCORE ; ++i)
                 if      (pstr->score[i] != EOF)
                 {       printf("%7.2f", pstr->score[i]);
                         num += pstr->score[i];
                         ++cnt;
                 }
                 else    for (   ; i < SCORE; ++i)
                                 printf("   --- ");
         if      (cnt > 0)
                 printf(" (%6.2f)", num / (double) cnt);
         else    printf(" (  --- )");
         printf(" %s\n", pstr->name);
 }




























 Jul 27 17:12 1984  7.56checknum.c Page 1


 #include <stdio.h>
 #define SCORE 8
 struct record
 {       char name[48];
         float score[SCORE];
 };
 main()  /* check number of entries in DATAFILE */
 {       struct record data;
         FILE *fp;
         if ((fp = fopen("DATAFILE", "r")) == NULL)
         {       fprintf(stderr, "cannot open DATAFILE\n");
                 exit(2);
         }
         fseek(fp, 0L, 2);       /* move pointer to end-of-file */
         printf("%5ld entries in DATAFILE\n", ftell(fp) / (long) sizeof (data)
         exit(0);
 }














































 Jul 27 17:12 1984  7.59system.c Page 1


 main()  /* use sh(1) to get
         /* long listing of DATAFILE
         /* and use same exit status */
 {
         unsigned ret;   /* machine independent */

         ret = system("ls -l DATAFILE");
         exit(ret >> 8); /* shift right 8 places
                         /* to get sh(1) exit status */
 }





















































 Jul 27 17:12 1984  7.70cp2.c Page 1


 <fcntl.h>      /* included for open(2) */
 main(argc, argv)        /* modified cp(1) command */
 int argc;               /* 2nd version */
 char *argv[];           /* using system calls */
 { int fdr, fdw;         /* file descriptors */
   if (argc != 3)
   { printf("usage: %s src_file dest_file\n", argv[0]);
     exit(1);
   }
   if ((fdr = open(argv[1], 0)) == -1)
   { printf("%s: cannot access %s\n", argv[0], argv[1]);
     exit(2);
   }
   if ((fdw = creat(argv[2], 0644)) == -1)
   { printf("%s: cannot create %s\n", argv[0], argv[2]);
     exit(2);
   }
   if (copy(fdr, fdw) == 0)
         exit(0);        /* success */
   exit(3);              /* failure */
 }
 copy(fd1, fd2)          /* copy fd1 to fd2 */
 int fd1, fd2;
 { register n;
   char buf[512];        /* temp character storage */

   while ((n = read(fd1, buf, 512)) > 0)
     write(fd2, buf, n);
   return (n);
 }































 $


 LABEL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\LABEL.C

 main()
 {
    /*                     label.c
     *
     *  This program will print a set of disk labels on standard mailing
     *  label forms using the IBM graphics printers.  The labels are the
     *  same ones issued with the distribution disks.  If you pass on a
     *  copy of the library please do it right and use proper labels.
     *  Thanks - Dave Miller
     *
     *  Copyright (c) 1987 by David A. Miller but placed in the public
     *  domain for the sole purpose of reprinting Unicorn Library Labels
     *  by library users.
     *
     */

    lprintf("\n");
    prtwidon();
    prtdubon();
    prtempon();
    lprintf(" Unicorn Library \n");
    prtempof();
    prtwidof();
    prtcomon();
    lprintf(" A graphics and general purpose library for TURBO C using\n");
    lprintf(" IBM and Tandy 1000 computers.  Disk 1,  Version 4.0\n");
    lprintf("                   Unicorn Software\n");
    lprintf("           Copyright (c) 1987 David A. Miller\n");
    prtcomof();


    lprintf("\n");
    prtwidon();
    prtdubon();
    prtempon();
    lprintf(" Unicorn Library \n");
    prtempof();
    prtwidof();
    prtcomon();
    lprintf(" A graphics and general purpose library for TURBO C using\n");
    lprintf(" IBM and Tandy 1000 computers.  Disk 2,  Version 4.0\n");
    lprintf("                   Unicorn Software\n");
    lprintf("           Copyright (c) 1987 David A. Miller\n");
    prtcomof();



 }


 LABLE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CTOOLBX1\LABLE.C

 main()
 {
    /*                     label.c
     *
     *  This program will print a set of disk labels on standard mailing
     *  label forms using the IBM graphics printers.  The labels are the
     *  same ones issued with the distribution disks.  If you pass on a
     *  copy of the library please do it right and use proper labels.
     *  Thanks - Dave Miller
     *
     *  Copyright (c) 1987 by David A. Miller but placed in the public
     *  domain for the sole purpose of reprinting Unicorn Library Labels
     *  by library users.
     *
     */

    lprintf("\n");
    prtwidon();
    prtdubon();
    prtempon();
    lprintf("   C Tool Box    \n");
    prtempof();
    prtwidoff();
    prtcomon();
    lprintf(" A graphics and general purpose library for TURBO C using\n");
    lprintf(" IBM and Tandy 1000 computers.  Disk 1,  Version 4.0\n");
    lprintf("                   Unicorn Software\n");
    lprintf("           Copyright (c) 1987 David A. Miller\n");
    prtcomof();


    lprintf("\n");
    prtwidon();
    prtdubon();
    prtempon();
    lprintf("   C Tool Box    \n");
    prtempof();
    prtwidoff();
    prtcomon();
    lprintf(" A graphics and general purpose library for TURBO C using\n");
    lprintf(" IBM and Tandy 1000 computers.  Disk 2,  Version 4.0\n");
    lprintf("                   Unicorn Software\n");
    lprintf("           Copyright (c) 1987 David A. Miller\n");
    prtcomof();



 }


 LABS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\LABS.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         long
 labs(n)                        /* return the long integer absolute value
                            of long n                                        *
 /*----------------------------------------------------------------------*/
 long n;
 {
         return ABS(n);
 }


 LAR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LAR.C

 /*
  * Lar - LU format library file maintainer
  * by Stephen C. Hemminger
  *        linus!sch        or        sch@Mitre-Bedford
  *
  *  Usage: lar key library [files] ...
  *
  *  Key functions are:
  *        u - Update, add files to library
  *        t - Table of contents
  *        e - Extract files from library
  *        p - Print files in library
  *        d - Delete files in library
  *        r - Reorginize library
  *  Other keys:
  *        v - Verbose
  *
  *  This program is public domain software, no warranty intended or
  *  implied.
  *
  *  DESCRPTION
  *     Lar is a Unix program to manipulate CP/M LU format libraries.
  *     The original CP/M library program LU is the product
  *     of Gary P. Novosielski. The primary use of lar is to combine several
  *     files together for upload/download to a personal computer.
  *
  *  PORTABILITY
  *     The code is modeled after the Software tools archive program,
  *     and is setup for Version 7 Unix.  It does not make any assumptions
  *     about byte ordering, explict and's and shift's are used.
  *     If you have a dumber C compiler, you may have to recode new features
  *     like structure assignment, typedef's and enumerated types.
  *
  *  BUGS/MISFEATURES
  *     The biggest problem is text files, the programs tries to detect
  *     text files vs. binaries by checking for non-Ascii (8th bit set) chars.
  *     If the file is text then it will throw away Control-Z chars which
  *     CP/M puts on the end.  All files in library are padded with Control-Z
  *     at the end to the CP/M sector size if necessary.
  *
  *     No effort is made to handle the difference between CP/M and Unix
  *     end of line chars.  CP/M uses Cr/Lf and Unix just uses Lf.
  *     The solution is just to use the Unix command sed when necessary.
  *
  *  * Unix is a trademark of Bell Labs.
  *  ** CP/M is a trademark of Digital Research.
  */

 #include <stdio.h>
 #include <ctype.h>

 #define ACTIVE        00
 #define UNUSED        0xff
 #define DELETED 0xfe
 #define CTRLZ        0x1a

 #define MAXFILES 256
 #define SECTOR         128
 #define DSIZE        ( sizeof(struct ludir) )
 #define SLOTS_SEC (SECTOR/DSIZE)
 #define equal(s1, s2) ( strcmp(s1,s2) == 0 )
 /* if you don't have void type just define as blank */
 #define VOID        (void)

 /* if no enum's then define false as 0 and true as 1 and bool as int */
 typedef enum {false=0, true=1} bool;

 /* Globals */
 char   *fname[MAXFILES];
 bool ftouched[MAXFILES];

 typedef struct {
     unsigned char   lobyte;
     unsigned char   hibyte;
 } word;

 /* convert word to int */
 #define wtoi(w) ( (w.hibyte<<8) + w.lobyte)
 #define itow(dst,src)        dst.hibyte = (src & 0xff00) >> 8;\
                                 dst.lobyte = src & 0xff;

 struct ludir {                        /* Internal library ldir structure */
     unsigned char   l_stat;        /*  status of file */
     char    l_name[8];                /*  name */
     char    l_ext[3];                /*  extension */
     word    l_off;                /*  offset in library */
     word    l_len;                /*  lengty of file */
     char    l_fill[16];                /*  pad to 32 bytes */
 } ldir[MAXFILES];

 int     errcnt, nfiles, nslots;
 bool        verbose = false;
 char        *cmdname;

 char   *getname(), *sprintf();
 int        update(), reorg(), table(), extract(), print(), delete();

 main (argc, argv)
 int        argc;
 char  **argv;
 {
     register char *flagp;
     char   *aname;                        /* name of library file */
     int           (*function)() = NULL;        /* function to do on library *
 /* set the function to be performed, but detect conflicts */
 #define setfunc(val)        if(function != NULL) conflict(); else function =

     cmdname = argv[0];
     if (argc < 3)
         help ();

     aname = argv[2];
     filenames (argc, argv);

     for(flagp = argv[1]; *flagp; flagp++)
         switch (*flagp) {
         case 'u':
             setfunc(update);
             break;
         case 't':
             setfunc(table);
             break;
         case 'e':
             setfunc(extract);
             break;
         case 'p':
             setfunc(print);
             break;
         case 'd':
             setfunc(delete);
             break;
         case 'r':
             setfunc(reorg);
             break;
         case 'v':
             verbose = true;
             break;
         default:
             help ();
     }

     if(function == NULL) {
         fprintf(stderr,"No function key letter specified\n");
         help();
     }

     (*function)(aname);
 }

 /* print error message and exit */
 help () {
     fprintf (stderr, "Usage: %s {utepdr}[v] library [files] ...\n", cmdname);
     fprintf (stderr, "Functions are:\n\tu - Update, add files to library\n");
     fprintf (stderr, "\tt - Table of contents\n");
     fprintf (stderr, "\te - Extract files from library\n");
     fprintf (stderr, "\tp - Print files in library\n");
     fprintf (stderr, "\td - Delete files in library\n");
     fprintf (stderr, "\tr - Reorginize library\n");

     fprintf (stderr, "Flags are:\n\tv - Verbose\n");
     exit (1);
 }

 conflict() {
    fprintf(stderr,"Conficting keys\n");
    help();
 }

 error (str)
 char   *str;
 {
     fprintf (stderr, "%s: %s\n", cmdname, str);
     exit (1);
 }

 cant (name)
 char   *name;
 {
     extern int  errno;
     extern char *sys_errlist[];

     fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]);
     exit (1);
 }

 /* Get file names, check for dups, and initialize */
 filenames (ac, av)
 char  **av;
 {
     register int    i, j;

     errcnt = 0;
     for (i = 0; i < ac - 3; i++) {
         fname[i] = av[i + 3];
         ftouched[i] = false;
         if (i == MAXFILES)
             error ("Too many file names.");
     }
     fname[i] = NULL;
     nfiles = i;
     for (i = 0; i < nfiles; i++)
         for (j = i + 1; j < nfiles; j++)
             if (equal (fname[i], fname[j])) {
                 fprintf (stderr, "%s", fname[i]);
                 error (": duplicate file name");
             }
 }

 table (lib)
 char   *lib;
 {
     FILE   *lfd;
     register int    i, total;
     int active = 0, unused = 0, deleted = 0;
     char *uname;

     if ((lfd = fopen (lib, "r")) == NULL)
         cant (lib);

     getdir (lfd);
     total = wtoi(ldir[0].l_len);
     if(verbose) {
          printf("Name          Index Length\n");
         printf("Directory           %4d\n", total);
     }

     for (i = 1; i < nslots; i++)
         switch(ldir[i].l_stat) {
         case ACTIVE:
                 active++;
                 uname = getname(ldir[i].l_name, ldir[i].l_ext);
                 if (filarg (uname))
                     if(verbose)
                         printf ("%-12s   %4d %4d\n", uname,
                             wtoi (ldir[i].l_off), wtoi (ldir[i].l_len));
                     else
                         printf ("%s\n", uname);
                 total += wtoi(ldir[i].l_len);
                 break;
         case UNUSED:
                 unused++;
                 break;
         default:
                 deleted++;
         }
     if(verbose) {
         printf("--------------------------\n");
         printf("Total sectors       %4d\n", total);
         printf("\nLibrary %s has %d slots, %d deleted %d active, %d unused\n"
                 lib, nslots, deleted, active, unused);
     }

     VOID fclose (lfd);
     not_found ();
 }

 getdir (f)
 FILE *f;
 {

     rewind(f);

     if (fread ((char *) & ldir[0], DSIZE, 1, f) != 1)
         error ("No directory\n");

     nslots = wtoi (ldir[0].l_len) * SLOTS_SEC;

     if (fread ((char *) & ldir[1], DSIZE, nslots, f) != nslots)
         error ("Can't read directory - is it a library?");
 }

 putdir (f)
 FILE *f;
 {

     rewind(f);
     if (fwrite ((char *) ldir, DSIZE, nslots, f) != nslots)
         error ("Can't write directory - library may be botched");
 }

 initdir (f)
 FILE *f;
 {
     register int    i;
     int     numsecs;
     char    line[80];
     static struct ludir blankentry = {
         UNUSED,
         { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
         { ' ', ' ', ' ' },
     };

     for (;;) {
         printf ("Number of slots to allocate: ");
         if (fgets (line, 80, stdin) == NULL)
             error ("Eof when reading input");
         nslots = atoi (line);
         if (nslots < 1)
             printf ("Must have at least one!\n");
         else if (nslots > MAXFILES)
             printf ("Too many slots\n");
         else
             break;
     }

     numsecs = nslots / SLOTS_SEC;
     nslots = numsecs * SLOTS_SEC;

     for (i = 0; i < nslots; i++)
         ldir[i] = blankentry;
     ldir[0].l_stat = ACTIVE;
     itow (ldir[0].l_len, numsecs);

     putdir (f);
 }

 /* convert nm.ex to a Unix style string */
 char   *getname (nm, ex)
 char   *nm, *ex;
 {
     static char namebuf[14];
     register char  *cp, *dp;

     for (cp = namebuf, dp = nm; *dp != ' ' && dp != &nm[8];)
         *cp++ = isupper (*dp) ? tolower (*dp++) : *dp++;
     *cp++ = '.';

     for (dp = ex; *dp != ' ' && dp != &ex[3];)
         *cp++ = isupper (*dp) ? tolower (*dp++) : *dp++;

     *cp = '\0';
     return namebuf;
 }

 putname (cpmname, unixname)
 char   *cpmname, *unixname;
 {
     register char  *p1, *p2;

     for (p1 = unixname, p2 = cpmname; *p1; p1++, p2++) {
         while (*p1 == '.') {
             p2 = cpmname + 8;
             p1++;
         }
         if (p2 - cpmname < 11)
             *p2 = islower(*p1) ? toupper(*p1) : *p1;
         else {
             fprintf (stderr, "%s: name truncated\n", unixname);
             break;
         }
     }
     while (p2 - cpmname < 11)
         *p2++ = ' ';
 }

 /* filarg - check if name matches argument list */
 filarg (name)
 char   *name;
 {
     register int    i;

     if (nfiles <= 0)
         return 1;

     for (i = 0; i < nfiles; i++)
         if (equal (name, fname[i])) {
             ftouched[i] = true;
             return 1;
         }

     return 0;
 }

 not_found () {
     register int    i;

     for (i = 0; i < nfiles; i++)
         if (!ftouched[i]) {
             fprintf (stderr, "%s: not in library.\n", fname[i]);
             errcnt++;
         }
 }

 
 extract(name)
 char *name;
 {
         getfiles(name, false);
 }

 print(name)
 char *name;
 {
         getfiles(name, true);
 }

 getfiles (name, pflag)
 char   *name;
 bool        pflag;
 {
     FILE *lfd, *ofd;
     register int    i;
     char   *unixname;

     if ((lfd = fopen (name, "r"))  == NULL)
         cant (name);

     ofd = pflag ? stdout : NULL;
     getdir (lfd);

     for (i = 1; i < nslots; i++) {
         if(ldir[i].l_stat != ACTIVE)
                 continue;
         unixname = getname (ldir[i].l_name, ldir[i].l_ext);
         if (!filarg (unixname))
             continue;
         fprintf(stderr,"%s", unixname);
         if (ofd != stdout)
             ofd = fopen (unixname, "w");
         if (ofd == NULL) {
             fprintf (stderr, "  - can't create");
             errcnt++;
         }
         else {
             VOID fseek (lfd, (long) wtoi (ldir[i].l_off) * SECTOR, 0);
             acopy (lfd, ofd, wtoi (ldir[i].l_len));
             if (ofd != stdout)
                 VOID fclose (ofd);
         }
         putc('\n', stderr);
     }
     VOID fclose (lfd);
     not_found ();
 }

 acopy (fdi, fdo, nsecs)
 FILE *fdi, *fdo;
 register unsigned int nsecs;
 {
     register int    i, c;
     int            textfile = 1;

     while( nsecs-- != 0)
         for(i=0; i<SECTOR; i++) {
                 c = getc(fdi);
                 if( feof(fdi) )
                         error("Premature EOF\n");
                 if( ferror(fdi) )
                     error ("Can't read");
                 if( !isascii(c) )
                     textfile = 0;
                 if( nsecs != 0 || !textfile || c != CTRLZ) {
                         putc(c, fdo);
                         if ( ferror(fdo) )
                             error ("write error");
                 }
          }
 }

 update (name)
 char   *name;
 {
     FILE *lfd;
     register int    i;

     if ((lfd = fopen (name, "r+")) == NULL) {
         if ((lfd = fopen (name, "w+")) == NULL)
             cant (name);
         initdir (lfd);
     }
     else
         getdir (lfd);                /* read old directory */

     if(verbose)
             fprintf (stderr,"Updating files:\n");
     for (i = 0; i < nfiles; i++)
         addfil (fname[i], lfd);
     if (errcnt == 0)
         putdir (lfd);
     else
         fprintf (stderr, "fatal errors - library not changed\n");
     VOID fclose (lfd);
 }

 addfil (name, lfd)
 char   *name;
 FILE *lfd;
 {
     FILE        *ifd;
     register int secoffs, numsecs;
     register int i;

     if ((ifd = fopen (name, "r")) == NULL) {
         fprintf (stderr, "%s: can't find to add\n",name);
         errcnt++;
         return;
     }
     if(verbose)
         fprintf(stderr, "%s\n", name);
     for (i = 0; i < nslots; i++) {
         if (equal( getname (ldir[i].l_name, ldir[i].l_ext), name) ) /* update
             break;
         if (ldir[i].l_stat != ACTIVE)
                 break;
     }
     if (i >= nslots) {
         fprintf (stderr, "%s: can't add library is full\n",name);
         errcnt++;
         return;
     }

     ldir[i].l_stat = ACTIVE;
     putname (ldir[i].l_name, name);
     VOID fseek(lfd, 0L, 2);                /* append to end */
     secoffs = ftell(lfd) / SECTOR;

     itow (ldir[i].l_off, secoffs);
     numsecs = fcopy (ifd, lfd);
     itow (ldir[i].l_len, numsecs);
     VOID fclose (ifd);
 }

 fcopy (ifd, ofd)
 FILE *ifd, *ofd;
 {
     register int total = 0;
     register int i, n;
     char sectorbuf[SECTOR];


     while ( (n = fread( sectorbuf, 1, SECTOR, ifd)) != 0) {
         if (n != SECTOR)
             for (i = n; i < SECTOR; i++)
                 sectorbuf[i] = CTRLZ;
         if (fwrite( sectorbuf, 1, SECTOR, ofd ) != SECTOR)
                 error("write error");
         ++total;
     }
     return total;
 }

 delete (lname)
 char   *lname;
 {
     FILE *f;
     register int    i;

     if ((f = fopen (lname, "r+")) == NULL)
         cant (lname);

     if (nfiles <= 0)
         error("delete by name only");

     getdir (f);
     for (i = 0; i < nslots; i++) {
         if (!filarg ( getname (ldir[i].l_name, ldir[i].l_ext)))
             continue;
         ldir[i].l_stat = DELETED;
     }

     not_found();
     if (errcnt > 0)
         fprintf (stderr, "errors - library not updated\n");
     else
         putdir (f);
     VOID fclose (f);
 }

 reorg (name)
 char  *name;
 {
     FILE *olib, *nlib;
     int oldsize;
     register int i, j;
     struct ludir odir[MAXFILES];
     char tmpname[SECTOR];

     VOID sprintf(tmpname,"%-10.10s.TMP", name);

     if( (olib = fopen(name,"r")) == NULL)
         cant(name);

     if( (nlib = fopen(tmpname, "w")) == NULL)
         cant(tmpname);

     getdir(olib);
     printf("Old library has %d slots\n", oldsize = nslots);
     for(i = 0; i < nslots ; i++)
             copymem( (char *) &odir[i], (char *) &ldir[i],
                         sizeof(struct ludir));
     initdir(nlib);
     errcnt = 0;

     for (i = j = 1; i < oldsize; i++)
         if( odir[i].l_stat == ACTIVE ) {
             if(verbose)
                 fprintf(stderr, "Copying: %-8.8s.%3.3s\n",
                         odir[i].l_name, odir[i].l_ext);
             copyentry( &odir[i], olib,  &ldir[j], nlib);
             if (++j >= nslots) {
                 errcnt++;
                 fprintf(stderr, "Not enough room in new library\n");
                 break;
             }
         }

     VOID fclose(olib);
     putdir(nlib);
     VOID fclose (nlib);

     if(errcnt == 0) {
         if ( unlink(name) < 0 || link(tmpname, name) < 0) {
             VOID unlink(tmpname);
             cant(name);
         }
     }
     else
         fprintf(stderr,"Errors, library not updated\n");
     VOID unlink(tmpname);

 }

 copyentry( old, of, new, nf )
 struct ludir *old, *new;
 FILE *of, *nf;
 {
     register int secoffs, numsecs;
     char buf[SECTOR];

     new->l_stat = ACTIVE;
     copymem(new->l_name, old->l_name, 8);
     copymem(new->l_ext, old->l_ext, 3);
     VOID fseek(of, (long) wtoi(old->l_off)*SECTOR, 0);
     VOID fseek(nf, 0L, 2);
     secoffs = ftell(nf) / SECTOR;

     itow (new->l_off, secoffs);
     numsecs = wtoi(old->l_len);
     itow (new->l_len, numsecs);

     while(numsecs-- != 0) {
         if( fread( buf, 1, SECTOR, of) != SECTOR)
             error("read error");
         if( fwrite( buf, 1, SECTOR, nf) != SECTOR)
             error("write error");
     }
 }

 copymem(dst, src, n)
 register char *dst, *src;
 register unsigned int n;
 {
         while(n-- != 0)
                 *dst++ = *src++;
 }


 LAR_C86.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\LAR_C86.C

 /*% cc -O lar.c -o lar
 From linus!sch Tue Jul 26 08:07:37 1983
 Subject: CP/M Lu library maintainer

 When transfering files to my personal computer, I often want to transfer
 several files at once using the Umodem program.  To do this I wrote
 the following small program to combine files for the CP/M LU program.

 No special treatment necessary, just:
         cc -O lar.c -o lar
 to make it.

 --
 Stephen Hemminger,  Mitre Corp. Bedford MA
         {allegra,genrad,ihnp4, utzoo}!linus!sch        (UUCP)
         linus!sch@mitre-bedford                        (ARPA)
 ----------------- lar.c ----------------------
 */
 /* May 1985  J. P. Worth
         Modifications and enhancements to original UNIX  c source
         to allow operation under CP/M, MS/DOS and compilation with
         the CI C86 compiler. All changes are transparent to the
         original lar.c source through the use of a define variable
         "C86". Compile using as one of the options  "-dC86" or
         include "#define        C86" as first line of source code
         All features checked and tested under CP/M 86 with Version
         2.20H of CI C86 compiler
 */

 /*
  * Lar - LU format library file maintainer
  * by Stephen C. Hemminger
  *        linus!sch        or        sch@Mitre-Bedford
  *
  *  Usage: lar key library [files] ...
  *
  *  Key functions are:
  *        u - Update, add files to library
  *        t - Table of contents
  *        e - Extract files from library
  *        p - Print files in library
  *        d - Delete files in library
  *        r - Reorginize library
  *  Other keys:
  *        v - Verbose
  *
  *  This program is public domain software, no warranty intended or
  *  implied.
  *
  *  DESCRPTION
  *     Lar is a Unix program to manipulate CP/M LU format libraries.
  *     The original CP/M library program LU is the product
  *     of Gary P. Novosielski. The primary use of lar is to combine several
  *     files together for upload/download to a personal computer.
  *
  *  PORTABILITY
  *     The code is modeled after the Software tools archive program,
  *     and is setup for Version 7 Unix.  It does not make any assumptions
  *     about byte ordering, explict and's and shift's are used.
  *     If you have a dumber C compiler, you may have to recode new features
  *     like structure assignment, typedef's and enumerated types.
  *
  *  BUGS/MISFEATURES
  *     The biggest problem is text files, the programs tries to detect
  *     text files vs. binaries by checking for non-Ascii (8th bit set) chars.
  *     If the file is text then it will throw away Control-Z chars which
  *     CP/M puts on the end.  All files in library are padded with Control-Z
  *     at the end to the CP/M sector size if necessary.
  *
  *     No effort is made to handle the difference between CP/M and Unix
  *     end of line chars.  CP/M uses Cr/Lf and Unix just uses Lf.
  *     The solution is just to use the Unix command sed when necessary.
  *
  *  * Unix is a trademark of Bell Labs.
  *  ** CP/M is a trademark of Digital Research.
  */

 #include <stdio.h>
 #include <ctype.h>
 #define        C86

 #define ACTIVE        00
 #define UNUSED        0xff
 #define DELETED 0xfe
 #define CTRLZ        0x1a

 #define MAXFILES 256
 #define SECTOR         128
 #define DSIZE        ( sizeof(struct ludir) )
 #define SLOTS_SEC (SECTOR/DSIZE)
 #define equal(s1, s2) ( strcmp(s1,s2) == 0 )
 /* if you don't have void type just define as blank */
 #ifndef        C86

 #define        VOID        (void)

 #else

 #define VOID

 #endif

 /* if no enum's then define false as 0 and true as 1 and bool as int */

 #ifndef        C86
 typedef enum {false=0, true=1} bool;



 #else
 #define        false        0
 #define        true        1


 #define        bool        int

 #endif


 /* Globals */
 char   *fname[MAXFILES];
 bool ftouched[MAXFILES];

 typedef struct {
     unsigned char   lobyte;
     unsigned char   hibyte;
 } word;

 /* convert word to int */
 #define wtoi(w) ( (w.hibyte<<8) + w.lobyte)
 #define itow(dst,src)        dst.hibyte = (src & 0xff00) >> 8;\
                                 dst.lobyte = src & 0xff;

 struct ludir {                        /* Internal library ldir structure */
     unsigned char   l_stat;        /*  status of file */
     char    l_name[8];                /*  name */
     char    l_ext[3];                /*  extension */
     word    l_off;                /*  offset in library */
     word    l_len;                /*  lengty of file */
     char    l_fill[16];                /*  pad to 32 bytes */
 } ldir[MAXFILES];

 int     errcnt, nfiles, nslots;
 bool        verbose = false;
 char        *cmdname;

 char   *getname(), *sprintf();
 int        update(), reorg(), table(), extract(), print(), delete();
 #ifdef        C86
 long        rewind(), ftell(), fseek();
 #endif

 main (argc, argv)
 int        argc;
 char  **argv;
 {
     register char *flagp;
     char   *aname;                        /* name of library file */
     int           (*function)() = NULL;        /* function to do on library *
 /* set the function to be performed, but detect conflicts */
 #define setfunc(val)        if(function != NULL) conflict(); else function =

     cmdname = "lar";        /* can't get command name in CPM with argv[0] */
     if (argc < 3)
         help ();

     aname = argv[2];
     filenames (argc, argv);

     for(flagp = argv[1]; *flagp; flagp++)
         switch (*flagp) {
         case '-':
                 break;
         case 'u':
             setfunc(update);
             break;
         case 't':
             setfunc(table);
             break;
         case 'e':
             setfunc(extract);
             break;
         case 'p':
             setfunc(print);
             break;
         case 'd':
             setfunc(delete);
             break;
         case 'r':
             setfunc(reorg);
             break;
         case 'v':
             verbose = true;
             break;
         default:
             help ();
     }

     if(function == NULL) {
         fprintf(stderr,"No function key letter specified\n");
         help();
     }

     (*function)(aname);
 }

 /* print error message and exit */
 help () {
     fprintf (stderr, "Usage: %s {utepdr}[v] library [files] ...\n", cmdname);
     fprintf (stderr, "Functions are:\n\tu - Update, add files to library\n");
     fprintf (stderr, "\tt - Table of contents\n");
     fprintf (stderr, "\te - Extract files from library\n");
     fprintf (stderr, "\tp - Print files in library\n");
     fprintf (stderr, "\td - Delete files in library\n");
     fprintf (stderr, "\tr - Reorginize library\n");

     fprintf (stderr, "Flags are:\n\tv - Verbose\n");
     exit (1);
 }

 conflict() {
    fprintf(stderr,"Conficting keys\n");
    help();
 }

 error (str)
 char   *str;
 {
     fprintf (stderr, "%s: %s\n", cmdname, str);
     exit (1);
 }


 /* Get file names, check for dups, and initialize */
 filenames (ac, av)
 char  **av;
 {
     register int    i, j;

     errcnt = 0;
     for (i = 0; i < ac - 3; i++) {
         fname[i] = av[i + 3];
         ftouched[i] = false;
         if (i == MAXFILES)
             error ("Too many file names.");
     }
     fname[i] = NULL;
     nfiles = i;
     for (i = 0; i < nfiles; i++)
         for (j = i + 1; j < nfiles; j++)
             if (equal (fname[i], fname[j])) {
                 fprintf (stderr, "%s", fname[i]);
                 error (": duplicate file name");
             }
 }

 table (lib)
 char   *lib;
 {
     FILE   *lfd;
     register int    i, total;
     int active = 0, unused = 0, deleted = 0;
     char *uname;

 #ifndef        C86
     if ((lfd = fopen (lib, "r")) == NULL) {
 #else
     if ((lfd = fopen (lib, "rb")) == NULL) {
 #endif
         fprintf(stderr, "%s: can't open\n", lib);
         exit(1);
         }

     getdir (lfd);
     total = wtoi(ldir[0].l_len);
     if(verbose) {
          printf("Name          Index Length\n");
         printf("Directory           %4d\n", total);
     }

     for (i = 1; i < nslots; i++)
         switch(ldir[i].l_stat) {
         case ACTIVE:
                 active++;
                 uname = getname(ldir[i].l_name, ldir[i].l_ext);
                 if (filarg (uname))
                     if(verbose)
                         printf ("%-12s   %4d %4d\n", uname,
                             wtoi (ldir[i].l_off), wtoi (ldir[i].l_len));
                     else
                         printf ("%s\n", uname);
                 total += wtoi(ldir[i].l_len);
                 break;
         case UNUSED:
                 unused++;
                 break;
         default:
                 deleted++;
         }
     if(verbose) {
         printf("--------------------------\n");
         printf("Total sectors       %4d\n", total);
         printf("\nLibrary %s has %d slots, %d deleted %d active, %d unused\n"
                 lib, nslots, deleted, active, unused);
     }

     VOID fclose (lfd);
     not_found ();
 }

 getdir (f)
 FILE *f;
 {

     rewind(f);

     if (fread ((char *) & ldir[0], DSIZE, 1, f) != 1)
         error ("No directory\n");

     nslots = wtoi (ldir[0].l_len) * SLOTS_SEC;

     if ( fread( (char *) & ldir[1], DSIZE, nslots, f) != nslots)
         error("Can't read directory - is it a library?");
 }

 putdir (f)
 FILE *f;
 {

     rewind(f);
     if (fwrite ((char *) ldir, DSIZE, nslots, f) != nslots)
         error ("Can't write directory - library may be botched");
 }

 initdir (f)
 FILE *f;
 {
     register int    i, j;
     int     numsecs;
     char    line[80];
     static struct ludir blankentry = {
         UNUSED,
         { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
         { ' ', ' ', ' ' },
     };

     for (;;) {
         printf ("Number of slots to allocate (multiple of 8):  ");
         if (fgets (line, 80, stdin) == NULL)
             error ("Eof when reading input");
         nslots = atoi (line);
         if (nslots < 1)
             printf ("Must have at least one!\n");
         else if (nslots > MAXFILES)
             printf ("Too many slots\n");
         else
             break;
     }

     numsecs = nslots / SLOTS_SEC;
     nslots = numsecs * SLOTS_SEC;

     for (i = 0; i < nslots; i++) {

 #ifndef        C86
         ldir[i] = blankentry;
 #else


         for(j = 0; j < 16; j++) {
                 ldir[i].l_ext[j%3] = blankentry.l_ext[j%3];
                 ldir[i].l_name[j%8] = blankentry.l_name[j%8];
                 ldir[i].l_fill[j] = blankentry.l_fill[j];
         }
         ldir[i].l_stat = blankentry.l_stat;
 #endif
     }
     ldir[0].l_stat = ACTIVE;
     itow (ldir[0].l_len, numsecs);

     putdir (f);
 }

 /* convert nm.ex to a Unix style string */
 char   *getname (nm, ex)
 char   *nm, *ex;
 {
     static char namebuf[14];
     register char  *cp, *dp;

     for (cp = namebuf, dp = nm; *dp != ' ' && dp != &nm[8];) {
         *cp++ = isupper (*dp) ? tolower (*dp) : *dp;
         ++dp;
     }
     *cp++ = '.';

     for (dp = ex; *dp != ' ' && dp != &ex[3];) {
         *cp++ = isupper (*dp) ? tolower (*dp) : *dp;
         ++dp;
     }

     *cp = '\0';
     return namebuf;
 }

 putname (cpmname, unixname)
 char   *cpmname, *unixname;
 {
     register char  *p1, *p2;

     for (p1 = unixname, p2 = cpmname; *p1; p1++, p2++) {
         while (*p1 == '.') {
             p2 = cpmname + 8;
             p1++;
         }
         if (p2 - cpmname < 11)
             *p2 = islower(*p1) ? toupper(*p1) : *p1;
         else {
             fprintf (stderr, "%s: name truncated\n", unixname);
             break;
         }
     }
     while (p2 - cpmname < 11)
         *p2++ = ' ';
 }

 /* filarg - check if name matches argument list */
 filarg (name)
 char   *name;
 {
     register int    i;
     char *strpname;

     if (nfiles <= 0)
         return 1;

     for (i = 0; i < nfiles; i++) {
 /* the following is a hack to strip the drive label and colon
    for use under CPM, MSDOS, etc  may 85 jpw   */
         strpname = fname[i];
         if ( *(fname[i] + 1) == ':')  strpname = fname[i] + 2;
         if (equal (name, strpname)) {
             ftouched[i] = true;
             return 1;
         }
     }

     return 0;
 }

 not_found () {
     register int    i;

     for (i = 0; i < nfiles; i++)
         if (!ftouched[i]) {
             fprintf (stderr, "%s: not in library.\n", fname[i]);
             errcnt++;
         }
 }

 
 extract(name)
 char *name;
 {
         getfiles(name, false);
 }

 print(name)
 char *name;
 {
         getfiles(name, true);
 }

 getfiles (name, pflag)
 char   *name;
 bool        pflag;
 {
     FILE *lfd, *ofd;
     register int    i;
     char   *unixname;

 #ifndef        C86
     if ((lfd = fopen (name, "r")) == NULL) {
 #else
     if ((lfd = fopen (name, "rb"))  == NULL) {
 #endif
         fprintf(stderr, "%s: can't open\n", name);
         exit(1);
         }

     ofd = pflag ? stdout : NULL;
     getdir (lfd);

     for (i = 1; i < nslots; i++) {
         if(ldir[i].l_stat != ACTIVE)
                 continue;
         unixname = getname (ldir[i].l_name, ldir[i].l_ext);
         if (!filarg (unixname))
             continue;
         fprintf(stderr,"%s", unixname);
         if (ofd != stdout)
 #ifndef        C86
             ofd = fopen (unixname, "w");
 #else
             ofd = fopen (unixname, "wb");
 #endif
         if (ofd == NULL) {
             fprintf (stderr, "  - can't create");
             errcnt++;
         }
         else {
             VOID fseek (lfd, (long) wtoi (ldir[i].l_off) * SECTOR, 0);
             acopy (lfd, ofd, wtoi (ldir[i].l_len));
             if (ofd != stdout)
                 VOID fclose (ofd);
         }
         putc('\n', stderr);
     }
     VOID fclose (lfd);
     not_found ();
 }

 acopy (fdi, fdo, nsecs)
 FILE *fdi, *fdo;
 register unsigned int nsecs;
 {
     register int    i, c;
     int            textfile = 1;

     while( nsecs-- != 0)
         for(i=0; i<SECTOR; i++) {
                 c = getc(fdi);
 #ifndef        C86
                 if( feof(fdi) )
 #else
                 if( c == EOF )
 #endif
                         error("Premature EOF\n");
                 if( ferror(fdi) )
                     error ("Can't read");
                 if( !isascii(c) )
                     textfile = 0;
                 if( nsecs != 0 || !textfile || c != CTRLZ) {
                         putc(c, fdo);
                         if ( ferror(fdo) )
                             error ("write error");
                 }
          }
 }

 update (name)
 char   *name;
 {
     FILE *lfd;
     register int    i;

 #ifndef        C86
    if ((lfd = fopen (name, "r+")) == NULL) {
 #else
     if ((lfd = fopen (name, "rwb")) == NULL) {
 #endif
 #ifndef        C86
         if ((lfd = fopen (name, "w+")) == NULL) {
 #else
         if ((lfd = fopen (name, "wrb")) == NULL) {
 #endif
         fprintf(stderr, "%s: can't open or create for update\n", name);
         exit(1);
         }
         initdir (lfd);
     }
     else
         getdir (lfd);                /* read old directory */

     if(verbose)
             fprintf (stderr,"Updating files:\n");
     for (i = 0; i < nfiles; i++)
         addfil (fname[i], lfd);
     if (errcnt == 0)
         putdir (lfd);
     else
         fprintf (stderr, "fatal errors - library not changed\n");
     VOID fclose (lfd);
 }

 addfil (name, lfd)
 char   *name;
 FILE *lfd;
 {
     FILE        *ifd;
     register int secoffs, numsecs;
     register int i;

 #ifndef        C86
     if ((ifd = fopen (name, "r")) == NULL) {
 #else
     if ((ifd = fopen (name, "rb")) == NULL) {
 #endif
         fprintf (stderr, "%s: can't find to add\n",name);
         errcnt++;
         return;
     }
  /* the following line is to remove drive label and colon if present
     may 85 jpw */
     if ( *(name+1) == ':')   name +=2 ;
     if(verbose)
         fprintf(stderr, "%s\n", name);
     for (i = 0; i < nslots; i++) {
         if (equal( getname (ldir[i].l_name, ldir[i].l_ext), name) ) /* update
             break;
         if (ldir[i].l_stat != ACTIVE)
                 break;
     }
     if (i >= nslots) {
         fprintf (stderr, "%s: can't add library is full\n",name);
         errcnt++;
         return;
     }

     ldir[i].l_stat = ACTIVE;
     putname (ldir[i].l_name, name);
     VOID fseek(lfd, 0L, 2);                /* append to end */
     secoffs =  (ftell(lfd) / SECTOR);

     itow (ldir[i].l_off, (unsigned) secoffs);
     numsecs = fcopy (ifd, lfd);
     itow (ldir[i].l_len, numsecs);
     VOID fclose (ifd);
 }

 fcopy (ifd, ofd)
 FILE *ifd, *ofd;
 {
     register int total = 0;
     register int i, n;
     char sectorbuf[SECTOR];


     while ( (n = fread( sectorbuf, 1, SECTOR, ifd)) != 0) {
         if (n != SECTOR)
             for (i = n; i < SECTOR; i++)
                 sectorbuf[i] = CTRLZ;
         if (fwrite( sectorbuf, 1, SECTOR, ofd ) != SECTOR)
                 error("write error");
         ++total;
     }
     return total;
 }

 delete (lname)
 char   *lname;
 {
     FILE *f;
     register int    i, j;

 #ifndef        C86
     if ((f = fopen (lname, "r+")) == NULL) {
 #else
     if ((f = fopen (lname, "rwb")) == NULL) {
 #endif
         fprintf(stderr, "%s: can't open\n", lname);
         exit(1);
         }

     if (nfiles <= 0)
         error("delete by name only");

     getdir (f);
     for (i = 0; i < nslots; i++) {
         if (!filarg ( getname (ldir[i].l_name, ldir[i].l_ext)))
             continue;
         ldir[i].l_stat = DELETED;
         for (j = 0; j < 8; j++) {
             ldir[i].l_ext[j%3] = ' ';
             ldir[i].l_name[j] = ' ';
         }
     }

     not_found();
     if (errcnt > 0)
         fprintf (stderr, "errors - library not updated\n");
     else
         putdir (f);
     VOID fclose (f);
 }

 reorg (name)
 char  *name;
 {
     FILE *olib, *nlib;
     int oldsize;
     register int i, j;
     struct ludir odir[MAXFILES];
     char tmpname[SECTOR];

     VOID sprintf(tmpname,"%-10.10s.TMP", name);

 #ifndef        C86
     if( (olib = fopen(name,"r")) == NULL) {
 #else
     if( (olib = fopen(name,"rb")) == NULL) {
 #endif
         fprintf(stderr, "%s: can't open\n", name);
         exit(1);
         }

 #ifndef        C86
     if( (nlib = fopen(tmpname, "w")) == NULL) {
 #else
     if( (nlib = fopen(tmpname, "wb")) == NULL) {
 #endif
         fprintf(stderr, "%s: can't open\n", tmpname);
         exit(1);
         }

     getdir(olib);
     printf("Old library has %d slots\n", oldsize = nslots);
     for(i = 0; i < nslots ; i++)
             copymem( (char *) &odir[i], (char *) &ldir[i],
                         sizeof(struct ludir));
     initdir(nlib);
     errcnt = 0;

     for (i = j = 1; i < oldsize; i++)
         if( odir[i].l_stat == ACTIVE ) {
             if(verbose)
                 fprintf(stderr, "Copying: %-8.8s.%3.3s\n",
                         odir[i].l_name, odir[i].l_ext);
             copyentry( &odir[i], olib,  &ldir[j], nlib);
             if (++j >= nslots) {
                 errcnt++;
                 fprintf(stderr, "Not enough room in new library\n");
                 break;
             }
         }

     VOID fclose(olib);
     putdir(nlib);
     VOID fclose (nlib);

     if(errcnt == 0) {
 #ifndef        C86
         if ( unlink(name) < 0 || link(tmpname, name) < 0) {
 #else
         if ( unlink(name) < 0 || rename(tmpname, name) < 0) {
 #endif
             VOID unlink(tmpname);
         fprintf(stderr, "%s: can't delete or rename\n", name);
         exit(1);
         }
     }
     else
         fprintf(stderr,"Errors, library not updated\n");
     VOID unlink(tmpname);

 }

 copyentry( old, of, new, nf )
 struct ludir *old, *new;
 FILE *of, *nf;
 {
     register int secoffs, numsecs;
     char buf[SECTOR];

     new->l_stat = ACTIVE;
     copymem(new->l_name, old->l_name, 8);
     copymem(new->l_ext, old->l_ext, 3);
     VOID fseek(of, (long) wtoi(old->l_off)*SECTOR, 0);
     VOID fseek(nf, 0L, 2);
     secoffs = ftell(nf) / SECTOR;

     itow (new->l_off, secoffs);
     numsecs = wtoi(old->l_len);
     itow (new->l_len, numsecs);

     while(numsecs-- != 0) {
         if( fread( buf, 1, SECTOR, of) != SECTOR)
             error("read error");
         if( fwrite( buf, 1, SECTOR, nf) != SECTOR)
             error("write error");
     }
 }

 copymem(dst, src, n)
 register char *dst, *src;
 register unsigned int n;
 {
         while(n-- != 0)
                 *dst++ = *src++;
 }


 LBN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LBN\LBN.C

 /*
  *        L B N . C
  *
  *
  *        0.a.3                current version number
  *        05jan84                date of last revision
  *
  *
  *        This is a Line number and Braces depth Numbering utility for C prog
  *
  *   Written by:
  *
  *        0.a.0        03sep82                Larry K. Blische
  *
  *
  *   Modified by:
  *
  *        0.a.1        10sep82                Larry K. Blische
  *                                fix backslash mishandling
  *
  *      0.a.2   20jan83         Philip N. Hisley
  *                              added user specified profile character
  *
  *        0.a.3        05jan84                Philip N. Hisley
  *                                modified to run under MSDOS via Lattice C
  *                                compiler
  */

 #include        <stdio.h>

 #define        MAXCHAR                        256
 #define        LINES_PER_PAGE                60
 #define        BAD                        0
 #define        GOOD                        1
 #define        FALSE                        0
 #define        TRUE                        1
 #define READ                        "r"
 #define WRITE                        "w"
 #define APPEND                        "a"
 #define PROC                        int

 static        int        line_number        = 1;
 static        int        temp_line_num        = 0;
 static        int        page_number        = 1;
 static        int        temp_page_num        = 0;

 static        int        braces_depth        = 0;
 static        int        neg_braces        = FALSE;
 static        int        paren_depth        = 0;
 static        int        neg_paren        = FALSE;

 static        int        backslash        = FALSE;
 static        int        quote                = FALSE;
 static        int        double_quote        = FALSE;
 static        int        comment                = FALSE;

 static  char    prfchr                        = '_';        /* profile charac
 static        char        file_name[25];
 static  char        date_buf[25];
 static  char        prt_buf[MAXCHAR];
 static        char        line_buf[MAXCHAR];
 static        char        prefix_buf[17];
 static        char        time_buf[25];

 PROC
 main( argc, argv )
 int        argc;
 char        *argv[];
 {
         register int        n, acnt = 0;
         FILE        *fio;

         /*
          * see if command line has enough parameters
          */

         if( argc < 2 ) {
                 printf("\nusage: lbn [ -c <char> ] fname.ext [ >fname.ext or
                 printf("\n         where: <char> is a user-specified\n");
                 printf("                profiling symbol ... the standard\n")
                 printf("                symbol is an underscore\n\n");
                 exit( BAD );
         }

         /*
          * get filename and time of day strings, try to open the file and the
          *        put out the first header
          */

         while( ++acnt < argc )
                 if( strcmp( argv[ acnt ], "-c" ) == 0 )
                         prfchr = *argv[ ++acnt ];
                 else
                         strcpy( &file_name, argv[ acnt ] );

         date( &date_buf, 7 );        /* Lattice library function */
         time( &time_buf, 6 );   /* Lattice library function */

         time_buf[ sprintf( &time_buf, "%s     %s  ", &time_buf, &date_buf ) ]

         if(( fio = fopen( &file_name, READ )) == NULL ) {
                 printf("\nlbn: *FATAL* can't open file %s\n", &file_name );
                 exit( BAD );
         }
         putheader();

         /*
          * while there are lines left in the file, print them
          */

         while( fgets( &line_buf, MAXCHAR, fio ) ) {
                 line_buf[ strlen( &line_buf ) ] = NULL;
                 set_prefix( &prefix_buf );
                 prt_buf[ 0 ] = NULL;
                 strcat( &prt_buf, &prefix_buf );
                 set_depth( &line_buf );
                 strcat( &prt_buf, &line_buf );
                 printf("%s", &prt_buf );
                 line_number++;
                 temp_line_num++;
                 if( temp_line_num == LINES_PER_PAGE ) {
                         temp_line_num = 0;
                         temp_page_num++;
                         putheader();
                 }
         }

         /*
          * close the file and print warnings
          */
         fclose( fio );
         print_warnings();
 }

 /*
  *        P U T H E A D E R
  *
  * prints the top line of each page with time, filename, pagenumber
  */

 PROC
 putheader()
 {
         char        page_buf[10];

         printf("\f\nLINE  DEPTH     SOURCE STATEMENTS");
         printf("     %s  %s     PAGE  %d.%-d", &time_buf, &file_name,
                 page_number, temp_page_num );
         printf("\n\n");
 }





 /*
  *        P R I N T _ W A R N I N G S
  *
  * prints braces, parens, quotes, and double quote mismatch warnings
  */

 PROC
 print_warnings()
 {
         if( braces_depth != 0 ) {
                 printf("\nlbn: *WARNING* Braces mismatch." );
                 printf("%3d unmatched ", abs( braces_depth ) );
                 printf( (braces_depth < 0) ? "'}'" : "'{'" );
                 printf( (abs( braces_depth ) == 1) ? ".\n" : "s.\n" );
         }
         if( neg_braces )
                 printf("\nlbn: *WARNING* Braces depth went negative.\n");

         if( paren_depth != 0 ) {
                 printf("\nlbn: *WARNING* Parenthesis mismatch." );
                 printf("%3d unmatched ", abs( paren_depth ) );
                 printf( (paren_depth < 0) ? "')'" : "'('" );
                 printf( (abs( paren_depth ) == 1) ? ".\n" : "s.\n" );
         }
         if( neg_paren )
                 printf("\nlbn: *WARNING* Parenthesis depth went negative.\n")
         if( quote )
                 printf("\nlbn: *WARNING* Single quote mismatch.\n" );

         if( double_quote )
                 printf("\nlbn: *WARNING* Double quote mismatch.\n" );
 }


 /*
  *        S E T _ P R E F I X
  *
  * formats prefix string with correct braces depth
  */

 PROC
 set_prefix( pbuf )
 char        *pbuf;
 {
         register int        i, j;
         char                depth_buf[25];

         if( braces_depth < 0 ) {
                 depth_buf[0] = '?';
                 j = 1;
         } else {
                 for( i = 1 ; i <= braces_depth ; i++ )
                         depth_buf[ i-1 ] = prfchr;
                 j = braces_depth;
         }
         for( i = j+1 ; i <= 10 ; i++ )
                 depth_buf[ i-1 ] = ' ';
         depth_buf[10] = NULL;
         sprintf( pbuf, "%4d  %s", line_number, &depth_buf );
 }

 /*
  *        S E T _ D E P T H
  *
  * determines braces depth, paren, quote, and double quote mismatch
  */

 PROC
 set_depth( pstr )
 char        *pstr;
 {
         FOREVER {
                 switch( *pstr++ ) {
                 case '{':
                         if( backslash )
                                 backslash = FALSE;
                         else if( !quote && !double_quote && !comment )
                                 braces_depth++;
                         break;

                 case '}':
                         if( backslash )
                                 backslash = FALSE;
                         else if( !quote && !double_quote && !comment )
                                 braces_depth--;
                         if( braces_depth < 0 )
                                 neg_braces = TRUE;
                         break;

                 case '(':
                         if( backslash )
                                 backslash = FALSE;
                         else if( !quote && !double_quote && !comment )
                                 paren_depth++;
                         break;

                 case ')':
                         if( backslash )
                                 backslash = FALSE;
                         else if( !quote && !double_quote && !comment )
                                 paren_depth--;
                         if( paren_depth < 0 )
                                 neg_paren = TRUE;
                         break;

                 case '\n':
                         return;

                 case '\\':
                         backslash = !backslash;
                         break;

                 case '\'':
                         if( backslash )
                                 backslash = FALSE;
                         else if( !comment && !double_quote )
                                 quote = !quote;
                         break;

                 case '\"':
                         if( backslash )
                                 backslash = FALSE;
                         else if( !comment && !quote )
                                 double_quote = !double_quote;
                         break;

                 case '/':
                         if( backslash )
                                 backslash = FALSE;
                         else if( *pstr++ == '*' )
                                 comment = TRUE;
                         else
                                 pstr--;
                         break;

                 case '*':
                         if( backslash )
                                 backslash = FALSE;
                         else if( *pstr++ == '/' )
                                 comment = FALSE;
                         else
                                 pstr--;
                         break;

                 case '\f':
                         page_number++;
                         temp_page_num = 0;
                         temp_line_num = 0;
                         putheader();
                         *(pstr-1) = NULL;        /* putheader has the \f */
                         break;

                 default:
                         backslash = FALSE;
                         break;
                 }
         }
 }


 LEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEX.C

 /*
  * Copyright (c) 1978 Charles H. Forsyth
  */

 /*
  * lex -- initialisation, allocation, set creation
  *
  *     Revised for PDP-11 (Decus) C by Martin Minow
  */

 /* Modified 02-Dec-80 Bob Denny -- Conditionalized debug code for smaller siz
  *                           01 -- Moved calls to dfa build, min, print, writ
  *                                  and to stat, and code for ending() into
  *                                  this module so that 'ytab' could be put
  *                                  into overlay region.
  *          29-May-81 Bob Denny -- More extern hacking for RSX overlaying.
  * More     19-Mar-82 Bob Denny -- New C library & compiler
  * More     03-May-82 Bob Denny -- Final touches, remove unreferenced autos
  *          28-Aug-82 Bob Denny -- Add "-s" switch to supress references to
  *                                  "stdio.h" in generated code.  Add switch
  *                                  comments in code. Add -e for "easy" com-
  *                                  mand line. "lex -e file" is the short way
  *                                  of saying:
  *                                      "lex -i file.lxi -o file.c -t file"
  * More(!)  30-Oct-82 Bob Denny -- Fix RSX ODL to put lots of FCS junk into
  *                                  overlay, pick up (badly needed) 3KW for
  *                                  NFA nodes, etc.  Change static allocation
  *                                  in LEXLEX.H for RSX so can do non-trivial
  *                                  things.  Task is now big on RSX and grows
  *                                  from big to huge as it runs.
  *                                 Fix "-s" support so it is again possible
  *                                  to do a lexswitch() (dumb!).
  *          14-Apr-83 Bob Denny    VAX-11 C workarounds.
  *                                 Fix definition of toupper().
  *                        20-Nov-83 Scott Guthery  Adapt for IBM PC & DeSmet
  */

 #ifdef  DOCUMENTATION

 title   lex     A Lexical Analyser Generator
 index           A Lexical Analyser Generator

 synopsis

         lex [-options] [-i grammar] [-o outfile] [-t table]

 description

         Lex compiles a lexical analyser from a grammar and description of
         actions.  It is described more fully in lex.doc: only usage is
         described.  The following options are available:
         .lm +16
         .s.i-16;-a              Disable recognition of non-ASCII characters
         (codes > 177 octal) for exception character classes (form [^ ...]).
         .s.i-16;-d              Enable debugging code within lex.  Normally
         needed only for debugging lex.
         .s.i-16;-e              "Easy" command line. Saying "lex#-e#name" is
         same as saying:
         .s.i 4;"lex -i name.lxi -o name.c -t name"
         .s
         Do not include devices or an extension on "name" or make it longer
         than 8 characters, or you'll get several error messages.
         .s.i-16;-i file         Read the grammar from the file.  If "-i" is n
         specified, input will be read from the standard input.
         .s.i-16;-m              Enable state minimization. Currently not

         implemented, switch is a no-op.
         .s.i-16;-o file         Write the output to the file.  If "-o" is not
         specified, output will be written to file "lextab.c".
         .s.i-16;-s              "Stand-alone" switch.  Supresses the line
         "#include <stdio.h>" normally generated in the lex output.  Use this
         if LEX is generating a module to be used in a program which does not
         use the "standard I/O" package.
         .s.i-16;-t table        Name the recognizer "table" instead of the
         default "lextab".  If -o is not given, output will be written to file
         "table.c".
         .s.i-16;-v [file]       Verify -- write internal tables to the
         indicated file.  If "-v" is given without a file name argument,
         tables will be written to "lex.out".
         .lm -16

 diagnostics

         The following error messages may occur on invocation.  See lex
         documentation for information on compilation errors.
         .lm +8
         .s.i -8;Can't create ...
         .s.i -8;Cannot open ...
         .s.i -8;Illegal option.
         .s.i -8;Illegal switch combination.
         .s
         "-i", "-o" or "-t" given with "-e" or vice-versa
         .s.i -8;Table name too long.
         .s
         The table name (argument to "-t") must not be longer than 8 bytes.
         .s.i -8;Missing table name.
         .s.i -8;Missing input file.
         .s.i -8;Missing output file.
         .s.i -8;Missing name.
         .lm -8

 author
         Charles Forsyth
         Modified by Martin Minnow, Bob Denny & Scott Guthery

 bugs

 #endif

 #include <stdio.h>
 "system.h"                /* includes system configuration constants */

 extern char *lalloc();
 extern char tolower();

 struct  nfa     nfa[MAXNFA];
 struct  nfa     *nfap = &nfa[1];

 struct  xset    sets[NCHARS];
 char    insets[NCHARS];

 struct  trans   trans[NTRANS];
 struct  trans   *transp = &trans[0];

 char    ccls[NCCLS][(NCHARS+1)/NBPC];
 int     nccls;

 int     ndfa;
 struct  dfa     dfa[MAXDFA];
 struct  move    move[NNEXT];

 char    *tabname = "lextab";
 char    tabfile[15];
 char    *infile         = NULL;
 char    *outfile        = NULL;

 #ifdef DEBUG
 char    *dumpfile       = "lex.out";
 int     lldebug = 0;
 #endif

 int  llnxtmax = 0;

 FILE llout;
 FILE lexin;
 FILE lexlog;

 /*
  * Flags.  Allow globals only for those requiring same. Some only
  * used for checking for bad combos.
  */
         int     aflag = 0;      /* Ignore non-ASCII in [^ ...] */
 static  int     eflag = 0;      /* Easy command line */
 static  int     iflag = 0;      /* "-i" given */
         int     mflag = 0;      /* Enable state minimization (not imp.) */
 static  int     oflag = 0;      /* "-o" given */
         int     sflag = 0;      /* Supress "#include <stdio.h>" in output */
 static  int     tflag = 0;      /* "-t" given */

 struct  set     *setlist = 0;

 main(argc, argv)
 int argc;
 char *argv[];
 {
         register char *cp, *cp2;

 #ifdef DEBUG
         int vflag;
         vflag = 0;
 #endif

         for (; argc>1 && *argv[1]=='-'; argv++, argc--)
         switch (tolower(argv[1][1])) {

 #ifdef DEBUG
         /*
          * Create "verification" file, describing the scanner.
          */
         case 'v':                               /* -v => lex.out        */
                 vflag++;                        /* -v x.out => x.out    */
                 if (argc > 2 && argv[2][1] != '1') {
                         --argc;
                         dumpfile = (++argv)[1];
                 }
                 break;
         /*
          * Enable debug displays
          */
         case 'd':
                 lldebug++;
                 break;
 #endif
         /*
          * Enable state minimization. Currently not implemented.
          */
         case 'm':
                 mflag++;
                 break;

         /*
          * Disable matching of non-ASCII characters (codes > 177(8))
          * for exception character classes (form "[^ ...]").
          */
         case 'a':
                 aflag++;
                 break;

         /*
          * Supress "#include <stdio.h>" in generated
          * code for programs not using standard I/O.
          */
         case 's':
                 sflag++;
                 break;

         /*
          * "Easy" command line
          */
         case 'e':
                 if(iflag || oflag || tflag) {
                         error("Illegal switch combination\n");
                         exit(1);
                 }
                 if (--argc <= 1) {
                         error("Missing name\n");
                         exit(1);
                 }
                 if (strlen(tabname = (++argv)[1]) > 8) {
                         error("Name too long\n");
                         exit(1);
                 }
                 infile = malloc(14);
                 outfile = malloc(12);
                                 strcpy(infile, tabname); strcat(infile, ".lxi
                                 printf("Input read from %s\n", infile);
                 if ((lexin = fopen(infile, "r")) == NULL) {
                         error("Cannot open input \"%s\"\n", infile);
                         exit(1);
                 }
                                 strcpy(outfile, tabname); strcat(outfile, ".c
                 break;

         /*
          * Specify input file name.
          */
         case 'i':
                 if (eflag) {

                         error("Illegal switch combination\n");
                         exit(1);
                 }
                 iflag++;
                 if (--argc <= 1) {
                         error("Missing input file\n");
                         exit(1);
                 }
                 infile = (++argv)[1];
                                 printf("Input read from %s\n", infile);
                 if ((lexin = fopen(infile, "r")) == NULL) {
                         error("Cannot open input \"%s\"\n", infile);
                         exit(1);
                 }
                 break;

         /*
          * Specify output file name. Default = "lextab.c"
          */
         case 'o':
                 if (eflag) {
                         error("Illegal switch combination\n");
                         exit(1);
                 }
                 oflag++;
                 if (--argc <= 1) {
                         error("Missing output file");
                         exit(1);
                 }
                 outfile = (++argv)[1];
                 break;

         /*
          * Specify table name.  Default = "lextab.c".  If "-o"
          * not given, output will go to "tabname.c".
          */
         case 't':
                 if (eflag) {
                         error("Illegal switch combination\n");
                         exit(1);
                 }
                 tflag++;
                 if (--argc <= 1) {
                         error("Missing table name");
                         exit(1);
                 }
                 if (strlen(tabname = (++argv)[1]) > 8) {
                         error("Table name too long\n");
                         exit(1);
                 }
                 break;

         default:
                 error("Illegal option: %s\n", argv[1]);
                 exit(1);
         }

 #ifdef DEBUG

         cp = (vflag) ? dumpfile : "NUL";
                 printf("Log written to %s\n", cp);
         if ((lexlog = fopen(cp, "w")) == NULL) {
                 error("Cannot open \"%s\"", cp);
                 exit(1);

         }
 #endif
         if (infile == NULL) {
                 infile = malloc(31);
                 strcpy(infile, "lex.lxi");
         }
         cp = infile;                    /* Fold infile to lower case */
 /*
  * The following 2 loops cannot use the form "*cp++ = tolower(*cp)"
  * due to a bug in VAX-11 C V1.0-09 where the pointer increment
  * is done too soon (!).
  */
         while(*cp)
                 {
                 *cp = tolower(*cp);
                 cp++;
                 }
         cp = tabname;                   /* Fold tabname to lower case */
         while(*cp)
                 {
                 *cp = tolower(*cp);
                 cp++;
                 }
         if (outfile == NULL) {
                 /*
                  * Typical hacker's idiom!
                  */
                 for (cp = tabname, cp2 = tabfile; *cp2 = *cp++;)
                         cp2++;
                 for (cp = ".c"; *cp2++ = *cp++;)
                         ;
                 outfile = tabfile;
         }
                 printf("Analyzer written to %s\n", outfile);
         if ((llout = fopen(outfile, "w"))==NULL) {
                 error("Can't create %s\n", outfile);
                 exit(1);
         }

         heading();
         fprintf(stderr, "Parse LEX source ...\n");
         if (yyparse())
                 error("Parse failed\n");
         fprintf(stderr, "Build NFA then DFA ...\n");
         dfabuild();                                             /* 01+ */
         fprintf(stderr, "Minimize DFA ...\n");
         dfamin();
         fprintf(stderr, "Create C source ...\n");
         dfaprint();
         dfawrite();
 #ifdef DEBUG
         stats();
                 fclose(lexlog);
                                                          /* 01- */
         fprintf(stderr, "\07LEX done.\n");

                 fclose(llout);
 } /** END OF MAIN **/

 /*
  * This module was moved here from out.c so it could be called from
  * ytab.c residing in same overlay region as out.c.
  * 02-Dec-80  Bob Denny.
  */
                                                                 /* 01+ */
 ending()
 {
         static int ended;

         if (ended++)
                 return;
         fprintf(llout, "\t}\n\treturn(LEXSKIP);\n}\n");
         setline();
 }

 #ifdef DEBUG
 stats()
 {
         fprintf(lexlog, "\n");
         fprintf(lexlog, "%d/%d NFA states, %d/%d DFA states\n",
                 nfap-nfa, MAXNFA, ndfa, MAXDFA);
         fprintf(lexlog, "%d/%d entries in move vectors\n", llnxtmax, NNEXT);
 }

 /*
  * Print a state set on { ... } form on lexlog.
  */
 pset(t, nf)
 register struct set *t;
 {
         register i;

         fprintf(lexlog, "{");
         for (i = 0; i < t->s_len; i++)
                 if (nf)
                         fprintf(lexlog, " %d", t->s_els[i]-nfa); else
                         fprintf(lexlog, " %d", t->s_els[i]);
         fprintf(lexlog, "}");
 }

 /*
  * Print a character to lexlog in readable form.
  * Returns the number of characters generated.
  */
 chprint(ch)
 {
         register char *s;

         ch &= 0377;
         switch (ch) {
         case '\t':
                 s = "\\t";
                 break;
         case '\n':
                 s = "\\n";
                 break;
         case '\b':
                 s = "\\b";

                 break;
         case '\r':
                 s = "\\r";
                 break;
         default:
                 if(ch<040 || ch>=0177)
                         {
                         fprintf(lexlog, "\\%03o", ch);
                         return(4);
                         }
                 else
                         {
                         putc(ch, lexlog);
                         return(1);
                         }
         }
         fprintf(lexlog, s);
         return(2);
 }
 #endif

 /*
  * The following functions simply
  * allocate various kinds of
  * structures.
  */
 struct nfa *
 newnfa(ch, nf1, nf2)
 struct nfa *nf1, *nf2;
 {
         register struct nfa *nf;

         if ((nf = nfap++) >= &nfa[MAXNFA]) {
                 error("Too many NFA states");
                 exit(1);
         }
         nf->n_char = ch;
         nf->n_succ[0] = nf1;
         nf->n_succ[1] = nf2;
         nf->n_trans = 0;
         nf->n_flag = 0;
         nf->n_look = 0;
         return(nf);
 }

 newdfa()
 {
         register struct dfa *df;

         if ((df = &dfa[ndfa++]) >= &dfa[MAXDFA]) {
                 error("Out of dfa states");
                 exit(1);
         }
         return(df);
 }

 char *
 newccl(ccl)
 char *ccl;
 {
         register char *p, *q;
         register i;

         int j;

         for (j = 0; j < nccls; j++) {
                 p = ccl;
                 q = ccls[j];
                 for (i = sizeof(ccls[j]); i--;)
                         if (*p++ != *q++)
                                 goto cont;
                 return(ccls[j]);
         cont:;
         }
         if (nccls >= NCCLS) {
                 error("Too many character classes");
                 exit(1);
         }
         p = ccl;
         q = ccls[j = nccls++];
         for (i = sizeof(ccls[j]); i--;)
                 *q++ = *p++;
         return(ccls[j]);
 }

 struct trans *
 newtrans(st, en)
 struct nfa *st, *en;
 {
         register struct trans *tp;

         if ((tp = transp++) >= &trans[NTRANS]) {
                 error("Too many translations");
                 exit(1);
         }
         tp->t_start = st;
         tp->t_final = en;
         en->n_trans = tp;
         return(tp);
 }

 /*
  * Create a new set. `sf', if set, indicates that the elements of the
  * set are states of an NFA). If `sf' is not set, the elements are state
  * numbers of a DFA.
  */
 struct set *
 newset(v, i, sf)
 register struct nfa **v;
 register i;
 {
         register struct set *t;
         register k;
         int setcomp();

         qsort(v, i, sizeof(*v), setcomp);
         for (t = setlist; t; t = t->s_next)
                 if (t->s_len==i && eqvec(t->s_els, v, i))
                         return(t);
         t = lalloc(1, sizeof(*t)+i*sizeof(t->s_els[0]), "set nodes");
         t->s_next = setlist;

         setlist = t;
         t->s_final = 0;
         t->s_state =  0;
         t->s_flag = 0;
         t->s_len = i;
         t->s_group = 0;
         t->s_look = 0;
         for (v += i; i;) {
                 --v;
                 if (sf) {
                         if ((*v)->n_char==FIN)
                                 t->s_final =  (*v)-nfa;
                         if ((*v)->n_flag&LOOK)
                                 t->s_look |= 1<<(*v)->n_look;
                 } else {
                         k = *v;
                         dfa[k].df_name->s_group = t;
                 }
                 t->s_els[--i] = *v;
         }
         return(t);
 }

 setcomp(n1p, n2p)
 struct nfa **n1p, **n2p;
 {
         register struct nfa *n1, *n2;

         n1 = *n1p;
         n2 = *n2p;
         if (n1 > n2)
                 return(1);
         if (n1==n2)
                 return(0);
         return(-1);
 }

 eqvec(a, b, i)
 register *a, *b, i;
 {
         if (i)
                 do {
                         if (*a++ != *b++)
                                 return(0);
                 } while (--i);
         return(1);
 }

 /*
  * Ask for core, and complain if there is no more.
  */
 char *
 lalloc(n, s, w)
 char *w;
 {
         register char *cp;

         if ((cp = calloc(n, s)) == NULL) {
                 fprintf(stderr, "No space for %s", w);
 #ifdef DEBUG
                 if (lldebug)

                         dfaprint();
 #endif
                 exit(1);
         }
         return(cp);
 }

 error(format, argument)
 char *format, *argument;
 {
         fprintf(stderr, format, argument);
 }


 LEXCHA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXCHA.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 extern char *llend, *llp2;

 lexchar()
 {
         return(llend<llp2? *llend++&0377: lexgetc());
 }


 LEXECH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXECH.C

 /*
  * lexech.c
  *
  * Bob Denny 28-Aug-82        Move stdio dependencies to lexerr(), lexget(),
  *                                            lexech() and mapch(). This is o
  *                                            in lexlib which depend upon the
  * Scott Guthery 20-Nov-83  Adapt for IBM PC & DeSmet C
  */

 #include <stdio.h>
 #include <lex.h"

 extern char *llend, llbuf[];

 lexecho(fp)
 register FILE fp;
 {
         register char *lp;

         for (lp = llbuf; lp < llend;)
                 putc(*lp++, fp);
 }


 LEXERR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXERR.C

 /*
  * Bob Denny 28-Aug-82        Move stdio dependencies to lexerr(), lexget(),
  *                                            lexech() and mapch(). This is o
  *                                                in lexlib which depend upon
  * Scott Guthery 20-Nov-83  Adapt for IBM PC & DeSmet C
  */

 #include <stdio.h>
 #include <lex.h>

 extern int yyline;

 lexerror(s, arg1, arg2, arg3)
 char *s;
 int arg1, arg2, arg3;
 {
         if (yyline)
                 fprintf(stderr, "%d: ", yyline);
         fprintf(stderr, s, arg1, arg2, arg3);
 }


 LEXGET.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXGET.C

 /*
  * lexget.c
  *
  * Bob Denny         28-Aug-82        Move stdio dependencies to lexerr(), le
  *                                                        lexech() and mapch(
  *                                                        in lexlib which dep
  *
  * Scott Guthery 20-Nov-83  Adapt for IBM PC & DeSmet C.  Endow DeSmet getc
  *                                                    with ungetc capabilitie
  */

 #include <stdio.h>
 #include <lex.h>

 lexgetc()
 {
         return(unix_getc(lexin));
 }

 static char getbuf[30], *getbufptr = getbuf;

 unix_getc(iop)
 FILE iop;
 {
         if(getbufptr == getbuf)
                 return(getc(iop));
         else
                 return(*--getbufptr);
 }

 ungetc(c, iop)
 char c;
 FILE iop; /* WARNING: iop ignored ... ungetc's are multiplexed!!! */
 {
         *getbufptr++ = c;
 }


 LEXLEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXLEN.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 extern char *llend, llbuf[];

 lexlength()
 /*
  * Return the length of the current token
  */
 {
         return(llend - llbuf);
 }


 LEXPEE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXPEE.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 extern char *llend, *llp2;

 lexpeekc()
 {
         return(llend<llp2? *llend&0377: EOF);
 }


 LEXSRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXSRT.C

 /*
  * Quick Sort
  */

 int     (*qs__cmp)();
 static  int     size;

 qsort(a, n, es, fc)
 char *a;
 int n, es;
 int (*fc)();
 {
         qs__cmp = fc;
         size = es;
         q_sort(a, a+n*es);
 }

 q_sort(a, l)
 char *a, *l;
 {
         register char *i, *j;
         register int es;
         char *lp, *hp;
         int n, c;

         es = size;

 start:
         if((n=l-a) <= es)
                 return;
         n = es * ( n/(2*es));
         hp = lp = a+n;
         i = a;
         j = l-es;
         for(;;) {
                 if(i < lp) {
                         if((c = (*qs__cmp)(i, lp)) == 0) {
                                 q_exc(i, lp -= es);
                                 continue;
                         }
                         if(c < 0) {
                                 i += es;
                                 continue;
                         }
                 }

 loop:
                 if(j > hp) {
                         if((c = (*qs__cmp)(hp, j)) == 0) {
                                 q_exc(hp += es, j);
                                 goto loop;
                         }
                         if(c > 0) {
                                 if(i == lp) {
                                         q_tex(i, hp += es, j);
                                         i = lp += es;
                                         goto loop;
                                 }
                                 q_exc(i, j);
                                 j -= es;
                                 i += es;

                                 continue;
                         }
                         j -= es;
                         goto loop;
                 }


                 if(i == lp) {
                         if(lp-a >= l-hp) {
                                 q_sort(hp+es, l);
                                 l = lp;
                         } else {
                                 q_sort(a, lp);
                                 a = hp+es;
                         }
                         goto start;
                 }
                 q_tex(j, lp -= es, i);
                 j = hp -= es;
         }
 }

 q_exc(i, j)
 char *i, *j;
 {
         register char *ri, *rj, c;
         int n;

         n = size;
         ri = i;
         rj = j;
         do {
                 c = *ri;
                 *ri++ = *rj;
                 *rj++ = c;
         } while(--n);
 }

 q_tex(i, j, k)
 char *i, *j, *k;
 {
         register char *ri, *rj, *rk;
         int c;
         int n;

         n = size;
         ri = i;
         rj = j;
         rk = k;
         do {
                 c = *ri;
                 *ri++ = *rk;
                 *rk++ = *rj;
                 *rj++ = c;
         } while(--n);
 }


 LEXSWI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LEXSWI.C

 /*
  * lexswitch -- switch lex tables
  */

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 extern struct lextab *_tabp;

 struct lextab *
 lexswitch(lp)
 struct lextab *lp;
 {
         register struct lextab *olp;

         olp = _tabp;
         _tabp = lp;
         return(olp);
 }


 LIFE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\LIFE.C

 /*        LIFE.C                The much implemented game of Life invented by

                                 This version was written to illustrate the us
                                 screen and keyboard interface.

                                 To generate:
                                 A>C88 B:LIFE
                                 A>ASM88 B:PCIO
                                 A>BIND B:LIFE B:PCIO                */


 /*
   global constant and data declarations
 */

 #define        ROWS        24
 #define COLS        80

 /* control key translations */
 #define up_char 30
 #define down_char        31
 #define left_char 29
 #define right_char 28
 #define bol_char 200
 #define eol_char 201
 #define pageup_char 202
 #define pagedown_char 203
 #define bof_char 204
 #define eof_char 205
 #define Ins_char 206
 #define Del_char 207
 #define NextWord_char 208
 #define PrevWord_char 209

 /* function keys */
 #define M1 210
 #define M2 211
 #define M3 212
 #define M4 213
 #define M5 214
 #define M6 215
 #define M7 216
 #define M8 217
 #define M9 218
 #define M10 219


 char world[ROWS][COLS],create_mode=1,quit_flag;
 int  population,generation,crow,ccol;

 main() {

         scr_clr();
         instruct();
         setup();

         do {
                 generation++;
                 cycle();
                 screen();
                 }
         while (population && !quit_flag);
         scr_rowcol(ROWS,10);
         if (population == 0)
                 puts("Nobody left, sorry about that.                       ")
         else puts("bye                                                 ");
         scr_curson();
         }

 instruct() {                /*        print instructions        */

 puts("                The game of Life by John Conroy\n\n");
 puts("      If started with a number, a random pattern starts the game.\n\n")
 puts("  Otherwise, move the cursor with the four arrow keys to create life.\n
 puts("     DEL changes cursor movement to mean that cells are deleted\n\n");
 puts("                 INS flips back to create mode.\n\n");
 puts("          The '+' key will toggle the game on or off.\n\n");
 puts("                     Hit ESC to bail out.\n\n");
 puts("            Enter starting number of cells or hit CR   ");
         }

 setup() {
         int rnumber;
         int i,row,col,seed,rnum;
         char ch;

         rnumber=0;
         while (1) {
                 while ((ch=scr_csts()) == 0) seed++;
                 if (ch < '0' || ch > '9') break;
                 scr_co(ch);
                 rnumber*=10;
                 rnumber+=ch-'0';
                 }
         scr_cursoff();
         scr_clr();
         scr_rowcol(ROWS,20);        /*        print population message
         puts("Generation    0     Population    0");

         srand(seed);                /*        initilize random number generat

         for (i=0; i < rnumber; i++) {
                 rnum=rand();
                 row=rnum%ROWS;
                 col=(rnum/ROWS)%COLS;
                 world[row][col]='X'; /* put in a cell */
                 scr_rowcol(row,col);
                 scr_co(2);
                 }
         if (rnumber == 0) create(1);
         }


 screen() {        /* update the screen and set world back to x's        */
         int  row,col;
         char cell;

         population=0;
         for (row=0; row < ROWS; row++) {
                 for (col=0; col < COLS; col++) {
                         cell=world[row][col];
                         /* stay alive if 3 neighbors, born if next to 2 or 3

                         if (cell && (cell == 3 || cell == 'X'+2 || cell == 'X
                                 population++;
                                 if (cell < 'X') {
                                         scr_rowcol(row,col);
                                         scr_co(2);
                                         }
                                 cell='X';
                                 }
                         else {
                                 if (cell >= 'X') {
                                         scr_rowcol(row,col);
                                         scr_co(' ');
                                         }
                                 cell=0;
                                 }
                         world[row][col]=cell;
                         }
                 }
         scr_rowcol(ROWS,31);
         printf("%4d",generation);
         scr_rowcol(ROWS,51);
         printf("%4d",population);
         }


 create(suspend)                        /*        see if need to create or kil
         char suspend; {
         char ch,wait;

         while ((ch=scr_csts()) || suspend) {
                 switch (ch) {
                         case up_char:        crow=crow ? crow-1: ROWS-1;
                                                         break;
                         case down_char:        crow=crow == ROWS-1 ? 0: crow+
                                                         break;
                         case left_char:        ccol=ccol ? ccol-1: COLS-1;
                                                         break;
                         case right_char:ccol=ccol == COLS-1 ? 0: ccol+1;
                                                         break;
                         case bol_char:        ccol=0;
                                                         break;
                         case eol_char:        ccol=COLS-1;
                                                         break;
                         case '+':                suspend=!suspend;
                                                         continue;
                         case Ins_char:        create_mode=1;
                                                         continue;
                         case Del_char:        create_mode=0;
                                                         continue;
                         case 0x1b:                quit_flag=1;        /* flag
                                                         return;
                         default:                continue;
                         }
                 world[crow][ccol]= create_mode ? 'X': 0;
                 scr_rowcol(crow,ccol);
                 if (create_mode) {
                         scr_co(2);
                         population++;
                         }
                 else {
                         wait=30;
                         while (wait--) {
                                 scr_co(1);
                                 scr_rowcol(crow,ccol);
                                 }
                         scr_co(' ');
                         }
                 }
         }

 cycle() {                                /* cycle to the next generation */
         int  row,col;

         create(0);
         /*        take care of left and right column first        */
         for (row=0; row < ROWS; row++) {
                 if (world[row][0] >= 'X') add8(row,0);
                 if (world[row][COLS-1] >= 'X') add8(row,COLS-1);
                 }

         /*        take care of top and bottom line        */
         for (col=1; col < COLS-1;col++) {
                 if (world[0][col] >= 'X') add8(0,col);
                 if (world[ROWS-1][col] >= 'X') add8(ROWS-1,col);
                 }

         /*        fill in the box, ignoring border conditions        */
         for (row=1; row < ROWS-1; row++) {
                 for (col=1; col < COLS-1; col++) {
                         if (world[row][col] >= 'X' ) {
                                 world[row-1][col-1]++;
                                 world[row-1][col]++;
                                 world[row-1][col+1]++;
                                 world[row][col-1]++;
                                 world[row][col+1]++;
                                 world[row+1][col-1]++;
                                 world[row+1][col]++;
                                 world[row+1][col+1]++;
                                 }
                         }
                 }
         }


 add8(row,col)
         int  row,col; {
         int  rrow,ccol,rr,cc;

         for (rr=row-1; rr <= row+1; rr++) {
                 for (cc=col-1; cc <= col+1; cc++) {
                         rrow=rr != -1 ? rr : ROWS-1;
                         ccol=cc != -1 ? cc : COLS-1;
                         if (rrow >= ROWS) rrow=0;
                         if (ccol >= COLS) ccol=0;
                         world[rrow][ccol]++;
                         }
                 }
         world[row][col]--;
         }



 LIFE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\LIFE.C

 /* LIFE.C - From page 576 of "Microsoft C Programming for       */
 /* the IBM" by Robert Lafore. Conway's Game of Life.            */
 /****************************************************************/

 #define MAXCOL 80
 #define MAXROW 50
 ERASE "\x1B[2J"          /* code to erase screen */

 main()
 {
 static char array[MAXCOL][MAXROW];  /* array echoes screen */
 void putscr(), getinit();
 char neigh, getscr();
 int col, row;
 int count = 0;                      /* generation counter */

    getinit();                       /* get initial cells */
    while (1)  {                     /* once per generation */
       for(col = 1; col < MAXCOL - 1; col++)  /*transfer screen*/
          for(row = 1; row < MAXROW - 1; row++)  /*to array*/
             array[col][row] = getscr(col, row);
       printf(ERASE);
       printf("\x1B[24;1H");         /* position cursor */
       printf("Generation %d", ++count);    /*print generation*/
       for(col = 1; col < MAXCOL - 1; col++)     /*for every cell*/
          for(row = 1; row < MAXROW - 1; row++)  {
             neigh =  array[col-1][row-1] +    /*find total no.*/
                      array[col  ][row-1] +      /* of neighbors*/
                      array[col+1][row-1] +
                      array[col-1][row  ] +
                      array[col+1][row  ] +
                      array[col-1][row+1] +
                      array[col  ][row+1] +
                      array[col+1][row+1];
             if(array[col][row] == 0)  {      /*if no cell*/
                if(neigh == 3)                /* & 3 neighbors*/
                   putscr(col, row);          /*a cell is born*/
             }
             else if(neigh == 2 || neigh == 3) /*if 2 or 3 neighbors*/
                putscr(col, row);             /*cell lives*/
          }                                   /*done one cell*/
       for(col = 0; col < MAXCOL; col++)      /*clear array*/
          for(row = 0; row < MAXROW; row++)
             array[col][row] = 0;
    }        /*end while*/  /*done generation*/
 }        /*end main*/

 /* getinit() */   /* gets initial elements, puts them on screen */
 #define END 79
 #define INSERT 82
 #define C_UPUP 72
 #define C_DOWN 80
 #define C_LEFT 75
 #define C_RITE 77
 void getinit()
 {
 int col,row;
 char keycode;
 void putscr();

    printf(ERASE);
    printf("\x1B[22;1H");               /*position cursor*/
    printf("Move cursor with arrow keys.\n");
    printf("Place cell with [Ins] key, [End] when done.");
    col = 40;
    row = 25;
    while(keycode != END)  {            /*return on [End] */
       if(kbhit())                      /*true if key struck*/
          if(getch() == 0)  {           /*extended code*/
             switch((keycode = getch()))  {   /*read code*/
                case C_UPUP:
                   --row;
                   break;
                case C_DOWN:
                   ++row;
                   break;
                case C_RITE:
                   ++col;
                   break;
                case C_LEFT:
                   --col;
                   break;
                case INSERT:
                   putscr(col, row);
                   break;
             }     /*end switch*/
          }     /*end if*/
    }     /*end while*/
 }     /*end getinit() */

 /* putscr() */    /*puts small square in screen mem at col, row*/
                   /*cols from 0 to 79, rows from 0 to 49*/
 TOP '\xDF'      /*upper half of char*/
 BOT '\xDC'      /*lower half of char*/
 BOTH '\xDB'     /*full char rectangle*/

 void putscr(col, row)
 int col, row;
 {
 char newch, ch;
 int far *farptr;                    /*ptr to screen mem*/
 int actrow;                         /*actual row num*/
 int topbot;                         /*top or bott of row*/

    farptr = (int far *) 0xB0000000;
    actrow = row >> 1;               /*row divided by 2*/
    topbot = row & 0x0001;           /*odd or even row*/
    ch = *(farptr + actrow*80 + col);   /*get actual char*/
    if(topbot)                       /*if we're placing bot*/
       if(ch == TOP || ch == BOTH)
          newch = BOTH;
       else
          newch = BOT;
    else                             /*if we're placing top*/
       if(ch == BOT || ch == BOTH)
          newch = BOTH;
       else
          newch = TOP;
    *(farptr + actrow*80 + col) = (newch & 0x00ff) | 0x0700;
 }

 /* getscr() */    /*returns 1 or 0 from screen location col, row*/
                   /*cols from 0 to 79, rows from 0 to 49 */
 TOP '\xDF'      /*upper half of char*/
 BOT '\xDC'      /*lower half of char*/
 BOTH '\xDB'     /*full char rectangle*/
 #define TRUE 1
 #define FALSE 0

 char getscr(col, row)
 int col, row;
 {
 char ch;
 int far *farptr;                    /*ptr to screen mem*/
 int actrow;                         /*actual row num*/
 int bottom;                         /*top or bott of row*/

    farptr = (int far *) 0xB0000000;
    actrow = row >> 1;               /*row divided by 2*/
    bottom = row & 0x0001;           /*odd or even row*/
    ch = *(farptr + actrow*80 + col);   /*get actual char*/
    if(ch == BOTH)
       return(TRUE);
    else
       if((bottom && ch == BOT) || (!bottom && ch == TOP))
          return(TRUE);
       else
          return(FALSE);
 }



 LINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\LINE.C

 /**********************************************************************
 LINE
 Description - draws a line from two points
 **********************************************************************
 Function - line(x0,y0,x1,y1) coord for point 0 and point 1
 Input - see above
 Output - to the screen
 #includes - none
 #defines  - none
 Routines Called - plotxy
 Notes - BYTE august 1981, pp414-16; digital differential analyzer DDA
 **********************************************************************/
 line(x0,y0,x1,y1)
 int x0,y0,x1,y1;
 {
   plotxy(x0,y0); /* print the first point */
   plotxy(x1,y1); /* print the end point */
   /* initialize the remaining variables and set the whole thing up */
   int d1,d2,d3,s1,s2,a1,a2,n1;
   d1=x1-x0;
   d2=y1-y0;
   s1=0;
   s2=1;
   a1=1;
   a2=0;
   if (d1<0){a1=-1;d1=-d1;}
   if (d2<0){d2=-d2;s2=-1;}
   if (d1<d2){ n1=d1;
               d1=d2;
               d2=n1;
               s1=a1;
               a1=0;
               a2=s2;
               s2=0;  }
   d3=d1/2;
   n1=1;

   /* heres where the work gets done */
   do{
       x0=x0+a1;
       y0=y0+a2;
       d3=d3+d2;
       n1=n1+1;
       if(d3>d1){d3=d3-d1; x0=x0+s1; y0=y0+s2;}
       plotxy(x0,y0);
     }while(n1<=d1);
   return;
 }
 /******************** end of function ********************************/


 LINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\LINE.C

 /*
  * The functions in this file are a general set of line management utilities.
  * They are the only routines that touch the text. They also touch the buffer
  * and window structures, to make sure that the necessary updating gets done.
  * There are routines in this file that handle the kill buffer too. It isn't
  * here for any good reason.
  *
  * Note that this code only updates the dot and mark values in the window lis
  * Since all the code acts on the current window, the buffer that we are
  * editing must be being displayed, which means that "b_nwnd" is non zero,
  * which means that the dot and mark values in the buffer headers are nonsens
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 KILL *ykbuf;        /* ptr to current kill buffer chunk being yanked */
 int ykboff;        /* offset into that chunk */

 /*
  * This routine allocates a block of memory large enough to hold a LINE
  * containing "used" characters. The block is always rounded up a bit. Return
  * a pointer to the new block, or NULL if there isn't any memory left. Print
  * message in the message line if no space.
  */
 LINE *lalloc(used)

 register int        used;

 {
         register LINE        *lp;
         register int        size;
         char *malloc();

         size = (used+NBLOCK-1) & ~(NBLOCK-1);
         if (size == 0)                                /* Assume that an empty
                 size = NBLOCK;                        /* line is for type-in.
         if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) {
                 mlwrite("[OUT OF MEMORY]");
                 return (NULL);
         }
         lp->l_size = size;
         lp->l_used = used;
         return (lp);
 }

 /*
  * Delete line "lp". Fix all of the links that might point at it (they are
  * moved to offset 0 of the next line. Unlink the line from whatever buffer i
  * might be in. Release the memory. The buffers are updated too; the magic
  * conditions described in the above comments don't hold here.
  */
 lfree(lp)
 register LINE        *lp;
 {
         register BUFFER *bp;
         register WINDOW *wp;

         wp = wheadp;
         while (wp != NULL) {
                 if (wp->w_linep == lp)
                         wp->w_linep = lp->l_fp;
                 if (wp->w_dotp        == lp) {
                         wp->w_dotp  = lp->l_fp;
                         wp->w_doto  = 0;
                 }
                 if (wp->w_markp == lp) {
                         wp->w_markp = lp->l_fp;
                         wp->w_marko = 0;
                 }
                 wp = wp->w_wndp;
         }
         bp = bheadp;
         while (bp != NULL) {
                 if (bp->b_nwnd == 0) {
                         if (bp->b_dotp        == lp) {
                                 bp->b_dotp = lp->l_fp;
                                 bp->b_doto = 0;
                         }
                         if (bp->b_markp == lp) {
                                 bp->b_markp = lp->l_fp;
                                 bp->b_marko = 0;
                         }
                 }
                 bp = bp->b_bufp;
         }
         lp->l_bp->l_fp = lp->l_fp;
         lp->l_fp->l_bp = lp->l_bp;
         free((char *) lp);
 }

 /*
  * This routine gets called when a character is changed in place in the curre
  * buffer. It updates all of the required flags in the buffer and window
  * system. The flag used is passed as an argument; if the buffer is being
  * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
  * mode line needs to be updated (the "*" has to be set).
  */
 lchange(flag)
 register int        flag;
 {
         register WINDOW *wp;

         if (curbp->b_nwnd != 1)                 /* Ensure hard.         */
                 flag = WFHARD;
         if ((curbp->b_flag&BFCHG) == 0) {        /* First change, so        *
                 flag |= WFMODE;                 /* update mode lines.
                 curbp->b_flag |= BFCHG;
         }
         wp = wheadp;
         while (wp != NULL) {
                 if (wp->w_bufp == curbp)
                         wp->w_flag |= flag;
                 wp = wp->w_wndp;
         }
 }

 insspace(f, n)        /* insert spaces forward into text */

 int f, n;        /* default flag and numeric argument */

 {
         linsert(n, ' ');
         backchar(f, n);
 }

 /*
  * Insert "n" copies of the character "c" at the current location of dot. In
  * the easy case all that happens is the text is stored in the line. In the
  * hard case, the line has to be reallocated. When the window list is updated
  * take special care; I screwed it up once. You always update dot in the
  * current window. You update mark, and a dot in another window, if it is
  * greater than the place where you did the insert. Return TRUE if all is
  * well, and FALSE on errors.
  */
 linsert(n, c)
 {
         register char        *cp1;
         register char        *cp2;
         register LINE        *lp1;
         register LINE        *lp2;
         register LINE        *lp3;
         register int        doto;
         register int        i;
         register WINDOW *wp;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         lchange(WFEDIT);
         lp1 = curwp->w_dotp;                        /* Current line         *
         if (lp1 == curbp->b_linep) {                /* At the end: special
                 if (curwp->w_doto != 0) {
                         mlwrite("bug: linsert");
                         return (FALSE);
                 }
                 if ((lp2=lalloc(n)) == NULL)        /* Allocate new line
                         return (FALSE);
                 lp3 = lp1->l_bp;                /* Previous line        */
                 lp3->l_fp = lp2;                /* Link in                */
                 lp2->l_fp = lp1;
                 lp1->l_bp = lp2;
                 lp2->l_bp = lp3;
                 for (i=0; i<n; ++i)
                         lp2->l_text[i] = c;
                 curwp->w_dotp = lp2;
                 curwp->w_doto = n;
                 return (TRUE);
         }
         doto = curwp->w_doto;                        /* Save for later.
         if (lp1->l_used+n > lp1->l_size) {        /* Hard: reallocate
                 if ((lp2=lalloc(lp1->l_used+n)) == NULL)
                         return (FALSE);
                 cp1 = &lp1->l_text[0];
                 cp2 = &lp2->l_text[0];
                 while (cp1 != &lp1->l_text[doto])
                         *cp2++ = *cp1++;
                 cp2 += n;
                 while (cp1 != &lp1->l_text[lp1->l_used])
                         *cp2++ = *cp1++;
                 lp1->l_bp->l_fp = lp2;
                 lp2->l_fp = lp1->l_fp;
                 lp1->l_fp->l_bp = lp2;
                 lp2->l_bp = lp1->l_bp;
                 free((char *) lp1);
         } else {                                /* Easy: in place        */
                 lp2 = lp1;                        /* Pretend new line
                 lp2->l_used += n;
                 cp2 = &lp1->l_text[lp1->l_used];
                 cp1 = cp2-n;
                 while (cp1 != &lp1->l_text[doto])
                         *--cp2 = *--cp1;
         }
         for (i=0; i<n; ++i)                        /* Add the characters
                 lp2->l_text[doto+i] = c;
         wp = wheadp;                                /* Update windows
         while (wp != NULL) {
                 if (wp->w_linep == lp1)
                         wp->w_linep = lp2;
                 if (wp->w_dotp == lp1) {
                         wp->w_dotp = lp2;
                         if (wp==curwp || wp->w_doto>doto)
                                 wp->w_doto += n;
                 }
                 if (wp->w_markp == lp1) {
                         wp->w_markp = lp2;
                         if (wp->w_marko > doto)
                                 wp->w_marko += n;
                 }
                 wp = wp->w_wndp;
         }
         return (TRUE);
 }

 /*
  * Insert a newline into the buffer at the current location of dot in the
  * current window. The funny ass-backwards way it does things is not a botch;
  * it just makes the last line in the file not a special case. Return TRUE if
  * everything works out and FALSE on error (memory allocation failure). The
  * update of dot and mark is a bit easier then in the above case, because the
  * split forces more updating.
  */
 lnewline()
 {
         register char        *cp1;
         register char        *cp2;
         register LINE        *lp1;
         register LINE        *lp2;
         register int        doto;
         register WINDOW *wp;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         lchange(WFHARD);
         lp1  = curwp->w_dotp;                        /* Get the address and
         doto = curwp->w_doto;                        /* offset of "."
         if ((lp2=lalloc(doto)) == NULL)         /* New first half line
                 return (FALSE);
         cp1 = &lp1->l_text[0];                        /* Shuffle text around
         cp2 = &lp2->l_text[0];
         while (cp1 != &lp1->l_text[doto])
                 *cp2++ = *cp1++;
         cp2 = &lp1->l_text[0];
         while (cp1 != &lp1->l_text[lp1->l_used])
                 *cp2++ = *cp1++;
         lp1->l_used -= doto;
         lp2->l_bp = lp1->l_bp;
         lp1->l_bp = lp2;
         lp2->l_bp->l_fp = lp2;
         lp2->l_fp = lp1;
         wp = wheadp;                                /* Windows
         while (wp != NULL) {
                 if (wp->w_linep == lp1)
                         wp->w_linep = lp2;
                 if (wp->w_dotp == lp1) {
                         if (wp->w_doto < doto)
                                 wp->w_dotp = lp2;
                         else
                                 wp->w_doto -= doto;
                 }
                 if (wp->w_markp == lp1) {
                         if (wp->w_marko < doto)
                                 wp->w_markp = lp2;
                         else
                                 wp->w_marko -= doto;
                 }
                 wp = wp->w_wndp;
         }
         return (TRUE);
 }

 /*
  * This function deletes "n" bytes, starting at dot. It understands how do de
  * with end of lines, etc. It returns TRUE if all of the characters were
  * deleted, and FALSE if they were not (because dot ran into the end of the
  * buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
  */
 ldelete(n, kflag)

 long n;         /* # of chars to delete */
 int kflag;        /* put killed text in kill buffer flag */

 {
         register char        *cp1;
         register char        *cp2;
         register LINE        *dotp;
         register int        doto;
         register int        chunk;
         register WINDOW *wp;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         while (n != 0) {
                 dotp = curwp->w_dotp;
                 doto = curwp->w_doto;
                 if (dotp == curbp->b_linep)        /* Hit end of buffer.
                         return (FALSE);
                 chunk = dotp->l_used-doto;        /* Size of chunk.        */
                 if (chunk > n)
                         chunk = n;
                 if (chunk == 0) {                /* End of line, merge.
                         lchange(WFHARD);
                         if (ldelnewline() == FALSE
                         || (kflag!=FALSE && kinsert('\n')==FALSE))
                                 return (FALSE);
                         --n;
                         continue;
                 }
                 lchange(WFEDIT);
                 cp1 = &dotp->l_text[doto];        /* Scrunch text.        */
                 cp2 = cp1 + chunk;
                 if (kflag != FALSE) {                /* Kill?
                         while (cp1 != cp2) {
                                 if (kinsert(*cp1) == FALSE)
                                         return (FALSE);
                                 ++cp1;
                         }
                         cp1 = &dotp->l_text[doto];
                 }
                 while (cp2 != &dotp->l_text[dotp->l_used])
                         *cp1++ = *cp2++;
                 dotp->l_used -= chunk;
                 wp = wheadp;                        /* Fix windows
                 while (wp != NULL) {
                         if (wp->w_dotp==dotp && wp->w_doto>=doto) {
                                 wp->w_doto -= chunk;
                                 if (wp->w_doto < doto)
                                         wp->w_doto = doto;
                         }
                         if (wp->w_markp==dotp && wp->w_marko>=doto) {
                                 wp->w_marko -= chunk;
                                 if (wp->w_marko < doto)
                                         wp->w_marko = doto;
                         }
                         wp = wp->w_wndp;
                 }
                 n -= chunk;
         }
         return (TRUE);
 }

 /* getctext:        grab and return a string with the text of
                 the current line
 */

 char *getctext()

 {
         register LINE *lp;        /* line to copy */
         register int size;        /* length of line to return */
         register char *sp;        /* string pointer into line */
         register char *dp;        /* string pointer into returned line */
         char rline[NSTRING];        /* line to return */

         /* find the contents of the current line and its length */
         lp = curwp->w_dotp;
         sp = lp->l_text;
         size = lp->l_used;
         if (size >= NSTRING)
                 size = NSTRING - 1;

         /* copy it across */
         dp = rline;
         while (size--)
                 *dp++ = *sp++;
         *dp = 0;
         return(rline);
 }

 /* putctext:        replace the current line with the passed in text        *

 putctext(iline)

 char *iline;        /* contents of new line */

 {
         register int status;

         /* delete the current line */
         curwp->w_doto = 0;        /* starting at the beginning of the line */
         if ((status = killtext(TRUE, 1)) != TRUE)
                 return(status);

         /* insert the new line */
         while (*iline) {
                 if (*iline == '\n') {
                         if (lnewline() != TRUE)
                                 return(FALSE);
                 } else {
                         if (linsert(1, *iline) != TRUE)
                                 return(FALSE);
                 }
                 ++iline;
         }
         status = lnewline();
         backline(TRUE, 1);
         return(status);
 }

 /*
  * Delete a newline. Join the current line with the next line. If the next li
  * is the magic header line always return TRUE; merging the last line with th
  * header line can be thought of as always being a successful operation, even
  * if nothing is done, and this makes the kill buffer work "right". Easy case
  * can be done by shuffling data around. Hard cases require that lines be mov
  * about in memory. Return FALSE on error and TRUE if all looks ok. Called by
  * "ldelete" only.
  */
 ldelnewline()
 {
         register char        *cp1;
         register char        *cp2;
         register LINE        *lp1;
         register LINE        *lp2;
         register LINE        *lp3;
         register WINDOW *wp;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         lp1 = curwp->w_dotp;
         lp2 = lp1->l_fp;
         if (lp2 == curbp->b_linep) {                /* At the buffer end.
                 if (lp1->l_used == 0)                /* Blank line.
                         lfree(lp1);
                 return (TRUE);
         }
         if (lp2->l_used <= lp1->l_size-lp1->l_used) {
                 cp1 = &lp1->l_text[lp1->l_used];
                 cp2 = &lp2->l_text[0];
                 while (cp2 != &lp2->l_text[lp2->l_used])
                         *cp1++ = *cp2++;
                 wp = wheadp;
                 while (wp != NULL) {
                         if (wp->w_linep == lp2)
                                 wp->w_linep = lp1;
                         if (wp->w_dotp == lp2) {
                                 wp->w_dotp  = lp1;
                                 wp->w_doto += lp1->l_used;
                         }
                         if (wp->w_markp == lp2) {
                                 wp->w_markp  = lp1;
                                 wp->w_marko += lp1->l_used;
                         }
                         wp = wp->w_wndp;
                 }
                 lp1->l_used += lp2->l_used;
                 lp1->l_fp = lp2->l_fp;
                 lp2->l_fp->l_bp = lp1;
                 free((char *) lp2);
                 return (TRUE);
         }
         if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
                 return (FALSE);
         cp1 = &lp1->l_text[0];
         cp2 = &lp3->l_text[0];
         while (cp1 != &lp1->l_text[lp1->l_used])
                 *cp2++ = *cp1++;
         cp1 = &lp2->l_text[0];
         while (cp1 != &lp2->l_text[lp2->l_used])
                 *cp2++ = *cp1++;
         lp1->l_bp->l_fp = lp3;
         lp3->l_fp = lp2->l_fp;
         lp2->l_fp->l_bp = lp3;
         lp3->l_bp = lp1->l_bp;
         wp = wheadp;
         while (wp != NULL) {
                 if (wp->w_linep==lp1 || wp->w_linep==lp2)
                         wp->w_linep = lp3;
                 if (wp->w_dotp == lp1)
                         wp->w_dotp  = lp3;
                 else if (wp->w_dotp == lp2) {
                         wp->w_dotp  = lp3;
                         wp->w_doto += lp1->l_used;
                 }
                 if (wp->w_markp == lp1)
                         wp->w_markp  = lp3;
                 else if (wp->w_markp == lp2) {
                         wp->w_markp  = lp3;
                         wp->w_marko += lp1->l_used;
                 }
                 wp = wp->w_wndp;
         }
         free((char *) lp1);
         free((char *) lp2);
         return (TRUE);
 }

 /*
  * Delete all of the text saved in the kill buffer. Called by commands when a
  * new kill context is being created. The kill buffer array is released, just
  * in case the buffer has grown to immense size. No errors.
  */
 kdelete()
 {
         KILL *kp;        /* ptr to scan kill buffer chunk list */

         if (kbufh != NULL) {

                 /* first, delete all the chunks */
                 kbufp = kbufh;
                 while (kbufp != NULL) {
                         kp = kbufp->d_next;
                         free(kbufp);
                         kbufp = kp;
                 }

                 /* and reset all the kill buffer pointers */
                 kbufh = kbufp = NULL;
                 kused = KBLOCK;
         }
 }

 /*
  * Insert a character to the kill buffer, allocating new chunks as needed.
  * Return TRUE if all is well, and FALSE on errors.
  */

 kinsert(c)

 int c;                /* character to insert in the kill buffer */

 {
         KILL *nchunk;        /* ptr to newly malloced chunk */

         /* check to see if we need a new chunk */
         if (kused >= KBLOCK) {
                 if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL)
                         return(FALSE);
                 if (kbufh == NULL)        /* set head ptr if first time */
                         kbufh = nchunk;
                 if (kbufp != NULL)        /* point the current to this new on
                         kbufp->d_next = nchunk;
                 kbufp = nchunk;
                 kbufp->d_next = NULL;
                 kused = 0;
         }

         /* and now insert the character */
         kbufp->d_chunk[kused++] = c;
         return(TRUE);
 }

 /*
  * Yank text back from the kill buffer. This is really easy. All of the work
  * is done by the standard insert routines. All you do is run the loop, and
  * check for errors. Bound to "C-Y".
  */
 yank(f, n)
 {
         register int        c;
         register int        i;
         register char        *sp;        /* pointer into string to insert */
         KILL *kp;                /* pointer into kill buffer */

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);
         /* make sure there is something to yank */
         if (kbufh == NULL)
                 return(TRUE);                /* not an error, just nothing */

         /* for each time.... */
         while (n--) {
                 kp = kbufh;
                 while (kp != NULL) {
                         if (kp->d_next == NULL)
                                 i = kused;
                         else
                                 i = KBLOCK;
                         sp = kp->d_chunk;
                         while (i--) {
                                 if ((c = *sp++) == '\n') {
                                         if (lnewline() == FALSE)
                                                 return (FALSE);
                                 } else {
                                         if (linsert(1, c) == FALSE)
                                                 return (FALSE);
                                 }
                         }
                         kp = kp->d_next;
                 }
         }
         return (TRUE);
 }


 LINEFUNC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\LINEFUNC.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 /*
  * nextline(curr)
  *
  * Return a pointer to the beginning of the next line after the one
  * referenced by 'curr'. Return NULL if there is no next line (at EOF).
  */

 LPTR *
 nextline(curr)
 LPTR *curr;
 {
         static        LPTR        next;

         if (curr->linep->next != Fileend->linep) {
                 next.index = 0;
                 next.linep = curr->linep->next;
                 return &next;
         }
         return (LPTR *) NULL;
 }

 /*
  * prevline(curr)
  *
  * Return a pointer to the beginning of the line before the one
  * referenced by 'curr'. Return NULL if there is no prior line.
  */

 LPTR *
 prevline(curr)
 LPTR *curr;
 {
         static        LPTR        prev;

         if (curr->linep->prev != NULL) {
                 prev.index = 0;
                 prev.linep = curr->linep->prev;
                 return &prev;
         }
         return (LPTR *) NULL;
 }

 /*
  * coladvance(p,col)
  *
  * Try to advance to the specified column, starting at p.
  */

 LPTR *
 coladvance(p, col)
 LPTR        *p;
 int        col;
 {
         static        LPTR        lp;
         int        c, in;

         lp.linep = p->linep;
         lp.index = p->index;

         /* If we're on a blank ('\n' only) line, we can't do anything */
         if (lp.linep->s[lp.index] == '\0')
                 return &lp;
         /* try to advance to the specified column */
         for ( c=0; col-- > 0; c++ ) {
                 /* Count a tab for what it's worth (if list mode not on) */
                 if ( gchar(&lp) == TAB && !P(P_LS) ) {
                         in = ((P(P_TS)-1) - c%P(P_TS));
                         col -= in;
                         c += in;
                 }
                 /* Don't go past the end of */
                 /* the file or the line. */
                 if (inc(&lp)) {
                         dec(&lp);
                         break;
                 }
         }
         return &lp;
 }


 LIST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\LIST.C

 /* *************************************************************** */
 /* This program will read in any text file and list it on the      */
 /* monitor with line numbers and with page numbers.                */
 /* *************************************************************** */

 "stdio.h"                     /* standard I/O header file */
 "io.h"                        /* file I/O prototypes      */

 void open_file(int no,char *name);
 void open_print_file(void);
 void print_a_line(void);
 void top_of_page(void);

 MAXCHARS 255                     /* maximum size of a line */
 FILE *file_point;                    /* pointer to file to be read */
 FILE *print_file_point;                      /* pointer to pronter */
 char oneline[256];                     /* input string buffer area */

 main(number,name)
 int number;                 /* number of arguments on command line */
 char *name[];               /* arguments on the command line       */
 {
 char *c;                       /* variable to indicate end of file */
 char *point;

    point = name[1];
    open_file(number,point);     /* open the file to read and print */
    open_print_file();

    do {
       c = fgets(oneline,MAXCHARS,file_point);     /* read one line */
       if (c != NULL)
          print_a_line();                         /* print the line */
    } while (c != NULL);                      /* continue until EOF */

    top_of_page();                     /* move paper to top of page */
    fclose(file_point);                           /* close read file */
    fclose(print_file_point);                  /* close printer file */
 }


 LIST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\LIST.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 put_sc(scl)
 int     scl;
 {       switch(scl) {
                 case sc_static:
                         fprintf(list,"Static      ");
                         break;
                 case sc_auto:
                         fprintf(list,"Auto        ");
                         break;
                 case sc_global:
                         fprintf(list,"Global      ");
                         break;
                 case sc_external:
                         fprintf(list,"External    ");
                         break;
                 case sc_type:
                         fprintf(list,"Type        ");
                         break;
                 case sc_const:
                         fprintf(list,"Constant    ");
                         break;
                 case sc_member:
                         fprintf(list,"Member      ");
                         break;
                 case sc_label:
                         fprintf(list,"Label");
                         break;
                 case sc_ulabel:
                         fprintf(list,"Undefined label");
                         break;
                 }
 }

 put_ty(tp)
 TYP     *tp;
 {       if(tp == 0)
                 return;
         switch(tp->type) {
                 case bt_char:
                         fprintf(list,"Char");
                         break;
                 case bt_short:
                         fprintf(list,"Short");
                         break;
                 case bt_enum:
                         fprintf(list,"enum ");
                         goto ucont;
                 case bt_long:
                         fprintf(list,"Long");
                         break;
                 case bt_unsigned:
                         fprintf(list,"unsigned long");
                         break;
                 case bt_float:
                         fprintf(list,"Float");
                         break;
                 case bt_double:
                         fprintf(list,"Double");
                         break;
                 case bt_pointer:
                         if( tp->val_flag == 0)
                                 fprintf(list,"Pointer to ");
                         else
                                 fprintf(list,"Array of ");
                         put_ty(tp->btp);
                         break;
                 case bt_union:
                         fprintf(list,"union ");
                         goto ucont;
                 case bt_struct:
                         fprintf(list,"struct ");
 ucont:                  if(tp->sname == 0)
                                 fprintf(list,"<no name> ");
                         else
                                 fprintf(list,"%s ",tp->sname);
                         break;
                 case bt_ifunc:
                 case bt_func:
                         fprintf(list,"Function returning ");
                         put_ty(tp->btp);
                         break;
                 }
 }

 list_var(sp,i)
 SYM     *sp;
 int     i;
 {       int     j;
         for(j = i; j; --j)
                 fprintf(list,"    ");
         fprintf(list,"%-10s =%06x ",sp->name,sp->value.u);
         if( sp->storage_class == sc_external)
                 fprintf(output,"\tglobal\t%s\n",sp->name);
         else if( sp->storage_class == sc_global )
                 fprintf(output,"\tglobal\t%s\n",sp->name);
         put_sc(sp->storage_class);
         put_ty(sp->tp);
         fprintf(list,"\n");
         if(sp->tp == 0)
                 return;
         if((sp->tp->type == bt_struct || sp->tp->type == bt_union) &&
                 sp->storage_class == sc_type)
                 list_table(&(sp->tp->lst),i+1);
 }

 list_table(t,i)
 TABLE   *t;
 int     i;
 {       SYM     *sp;
         sp = t->head;
         while(sp != NULL) {
                 list_var(sp,i);
                 sp = sp->next;
                 }
 }




 LISTC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LISTC.C

 /**********************************************************
  ***                                                    ***
  ***    Copyright (c) 1981 by David M. Fogg             ***
  ***                                                   ***
  ***            2632 N.E. Fremont                       ***
  ***            Portland, OR 97212                      ***
  ***                                                    ***
  ***        (503) 288-3502{HM} || 223-8033{WK}          ***
  ***                                                    ***
  ***    Permission is herewith granted for non-         ***
  ***    commercial distribution through the BDS C       ***
  ***    User's Group; any and all forms of commercial   ***
  ***    redistribution are strenuously unwished-for.    ***
  ***                                                    ***
  **********************************************************/

 /*
           ---> TEXT FILE LISTING PROGRAM <---

    Coded by David M. Fogg @ New Day Computing Co., Portland, OR

          *** (C) COPYRIGHT 1980, New Day Computing Co. ***

    24 OCT 80: creation day
    5 Nov - add optional line numbering
    6 NOV - Chg to xpand tabs
    21 Nov: Filter Form Feeds
    8 Jan 81: add line folding & opt line length spec
    6 Mar: chg DEFLL->128; chg puts->printf 2 show actual DEFLL
    27 mar 1984: extensive revisions to convert this program to
         Lattice c. and ms.dos. (Pete Mack - Simi Valley RCPM)

     USAGE: list filnam "Title String"  {list a single file}
            list [no arguments]   {list multiple files: title/filnam prompts}
                 [no arguments] allows changing:
                                  line numbering   (default: NO)
                                  line length      (default: 70)
                                  initial formfeed (default: NO)

 */

 #include "stdio.h"
 #include "ctype.h"

 MAXF   64       /* MAX # OF FILES */
 MAXFNL 15       /* MAX FILNAM LENGTH (INCL NUL TERMINATOR) */
 MAXLNS 60       /* MAX LINES/PAGE */
 NSTARS 85       /* # OF ASTERISKS IN STAR LINE */
 TABX    8       /* TAB EXPANSION MODULUS */
 DEFLL  128      /* DEFAULT LINE LENGTH */
 FILE *LST, *f1;

 main (argc, argv)
 int argc;
 char *argv[];
 {
    char fnbuf[MAXFNL*MAXF];      /* file name buffer */
    char *pfnbuf;                 /* pointo curr pos in fnbuf */
    char *filnam[MAXF];           /* file names (pointers) */
    char titbuf[100];             /* page title (usu. incl. date) buffer */
    char *titl;                   /* pointer to title */
    char stars[NSTARS+1];         /* asterisk line */
    int fno;                      /* file # being listed */
    int nfils;                    /* no. of files to list */
    int pagno;                    /* curr page # */
    int lino;                     /* curr line # on page */
    char iobuf[_BUFSIZ];          /* file I/O buffer */
    int filopn;                   /* holds fopen result */
    char lbuf[MAXLINE];           /* input line buffer */
    BOOL dilin;                   /* whether to disp line #s */
    int lines;                    /* tot lines in curr file */
    int linlen;                   /* maximum line length */
    char c;


    if((LST = fopen("PRN", "w")) == NULL){
         cprintf("I can't create PRN");
         exit(1);
    }

    pfnbuf = fnbuf;
    titl = titbuf + 2;
    *pfnbuf = (MAXFNL * MAXF) - 2;
    titbuf[0] = 98;

    setmem(stars, NSTARS, '*'); stars[NSTARS] = '\0';
    dilin = NO;
    linlen = DEFLL;

    if (argc > 1) {
       nfils = 1;
       filnam[0] = *++argv;
       if (argc > 2)
          titl = *++argv;
       else
          titbuf[0] = '\0';
    }
    else {
       dilin = getyn(0, 0, "\nLine Numbers");
       cprintf("\rLine Length (%d): \0", DEFLL);

          cgets(lbuf);
          linlen= atoi(lbuf);
          if (linlen < 1)
                  linlen = DEFLL;

       cputs("\n\rTitle: ");
       cgets(titbuf);
       nfils = 0;
       do {
          cprintf("\nFile # %2d : ", nfils + 1);
          filnam[nfils] = (char *) cgets(pfnbuf);
          pfnbuf += strlen(pfnbuf) + 1;
       }
         while (strlen(filnam[nfils++]) > 0 && nfils < MAXF);
       --nfils;
       if (nfils == 0)
          {
          fputs("Nothing to do...quitting",stderr);
          exit(1);
          }
       cputs("\nWant a Formfeed? ");

       c = getch();
       putch(c);
       if (toupper(c) == 'Y')
          putc(FFEED, LST);
          putchar('\n');
    }


 /*
          >>------> MAIN PRINT LOOP <------<<
 */

    for (fno = 0; fno < nfils; ++fno) {
         rewind(LST);
         if ((f1 = fopen(filnam[fno], "r")) == NULL) {
          cprintf("*** File I/O Error: %-15s\n", filnam[fno]);
          continue;
       }
       pagno = 0; lines = 0;
       lino = MAXLNS + 3;
       cprintf("\n\r---> Now listing %-15s\n\r", filnam[fno]);
         while (fgets(lbuf,MAXLINE,f1) != 0) {
          if (lino > MAXLNS) {
             if (pagno == 0) {
                if (fno > 0) putc(FFEED, LST);
                fputs(stars, LST); fputs("\n", LST);
                lino = 1;
             }
             else {
                putc(FFEED, LST);
                lino = 0;
             }
             fprintf(LST, "\n---> Listing of: %-15s    ", filnam[fno]);
             fprintf(LST, "%-35s  ", titl);
             fprintf(LST, "Page %2d <---\n", ++pagno);
             lino += 2;
             if (pagno == 1) {
                fputs("\n", LST); fputs(stars, LST); fputs("\n", LST);
                lino += 2;
             }
             fputs("\n\n\n", LST); lino += 3;
          }
          if (dilin)
             fprintf(LST, "%4d: ", ++lines);
          oplin(lbuf, linlen, &lino);
          ++lino;
       } /* while (fgets... */

 /*      fclose(iobuf); */
         fclose(f1);

    } /* for (fno... */

         fputs("\n\r",LST);
       fclose(LST);

 /*   if (filopn != NULL) putc(FFEED, LST); */

 } /* main() */


 oplin (lbuf, len, lno)    /* --<O/P A LINE W/ TAB XPANSION>-- */
 char lbuf[];
 int len;
 int *lno;
 {
    int cpos;      /* curr printhead pos */
    int i;

    cpos = 0;
    for (i = 0; i < strlen(lbuf); ++i) {
       if (lbuf[i] == '\n')
          fputs("\n", LST);
       else if (lbuf[i] == '\t') {
          putc(' ', LST);
          while (++cpos % TABX) putc(' ', LST);
       }
       else if (lbuf[i] != FFEED) {
          putc(lbuf[i], LST);
          if (++cpos > len) {
             fputs("\\\n", LST);
             cpos = 0;
             ++*lno;
          }
       }
    }
 }
 /*------------------------------------------------------------*/
 /* This function was originally designed to get an answer
    'yes' or 'no' at a specific xy coordinate..
     there is a current problem in that toupper doesnt appear
     to operate properly if we use the statement...
        ans = toupper(getch());
     consequently we have temporarily set up this scheme...(pm) */

 BOOL getyn (x, y, prom)         /* --<PROMPT 4 Y/N ANSWER>-- */
 int x,y;
 char *prom;
 {
    char ans;
    char anst;

 /*   if (x != 0) toxy(x, y);    */ /* set x=0 2 skip cursor pos */

    cprintf("%s (Y/N)? ", prom);

    do {
       anst = getch() & 0x7f;
       ans = toupper(anst);
    } while (ans != 'Y' && ans != 'N');

    putch(ans); putch('\n');

    return (ans == 'Y' ? YES : NO);
 }
 /************************************************
  atoi function from K&R pagew 58.
  atoi -- convert s to integer --
  rev 3-12-84 initial entry
 *************************************************/
 int atoi(s)
 char s[];
 {
         int i, n, sign;

         for( i=0; s[i] == ' ' || s[i] == '\n' || s[i] == '\t'; i++)
                 ; /* skip white space */
         sign = 1;
         if (s[i] == '+' || s[i] == '-')
                 sign = (s[i++] == '+') ? 1  : -1;

         for (n = 0; s[i] >= '0' && s[i] <= '9' ; i++)
                 n = 10 * n + s[i] - '0';
         return(sign * n);
 }


 LISTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\LISTF.C

 /* *************************************************************** */
 /* This module contains the functions called by the list.c program */
 /* program. If this were a program to be used for some specific    */
 /* purpose, it would probablly not be wise to break it up into two */
 /* separately compiled modules. It is only done here for purposes  */
 /* of illustration. It is a useful program.                        */
 /* *************************************************************** */

 MAXLINES 54            /* maximum number of lines per page */
 "stdio.h"                     /* standard I/O header file */
 "string.h"                    /* prototypes for strings   */

 void open_file(int no,char *name);
 void open_print_file(void);
 void print_a_line(void);
 void header(void);
 void top_of_page(void);

 extern FILE *file_point;         /* pointer to the file to be read */
 extern FILE *print_file_point;           /* pointer to the printer */
 extern char oneline[];                 /* input string buffer area */
 char filename[15];               /* filename from header or prompt */
 int line_number = 0;             /* line number initialized to one */
 int page_number = 1;             /* page number initialized to one */
 int lines_this_page = 0;              /* lines on this page so far */


 /* ***************************************************** open_file */
 /* This function opens the input file named on the command line,   */
 /* if there was one defined. Otherwise, it requests a file name to */
 /* open and opens the requested file.                              */
 /* *************************************************************** */
 void open_file(int no,char *name)
 {

    strcpy(filename,name);         /* copy name for printing header */
    file_point = NULL;           /* if no name was given in command */
    if (no == 2) {              /* 2nd field in command is filename */
       file_point = fopen(name,"r");         /* open requested file */
       if (file_point == NULL)        /* NULL if file doesn't exist */
          printf("Filename on command line doesn't exist!\n");
    }

    do {
       if (file_point == NULL) {                 /* no filename yet */
          printf("Enter filename -> ");
          scanf("%s",filename);
          file_point = fopen(filename,"r");            /* open file */
          if (file_point == NULL)          /* NULL if file no exist */
             printf("Filename doesn't exist, try again.\n");
       }
    } while (file_point == NULL);   /* continue until good filename */
 }


 /* *********************************************** open_print_file */
 /* This function opens the printer file to the standard printer.   */
 /* *************************************************************** */
 void open_print_file(void)
 {
    print_file_point = fopen("PRN","w");       /* open printer file */
 }


 /* ************************************************** print_a_line */
 /* This routine prints a line of text and checks to see if there   */
 /* is room for another line on the page. If not, it starts a new   */
 /* page with a new header. This routine calls several other local  */
 /* routines.                                                       */
 /* *************************************************************** */
 void print_a_line(void)
 {
 int index;

    header();
    printf("%5d %s",line_number,oneline);

                        /* This prints a line of less than 72 chars */
    if (strlen(oneline) < 72)
       fprintf(print_file_point,"%5d %s",line_number,oneline);

                           /* This prints a line of 72 to 143 chars */
    else if (strlen(oneline) < 144) {
       fprintf(print_file_point,"%5d ",line_number);
       for (index = 0;index < 72;index++)
          fprintf(print_file_point,"%c",oneline[index]);
       fprintf(print_file_point,"<\n      ");
       for (index = 72;index < strlen(oneline);index++)
          fprintf(print_file_point,"%c",oneline[index]);
       lines_this_page++;
    }

                           /* This prints a line of 144 to 235 chars */
    else if (strlen(oneline) < 235) {
       fprintf(print_file_point,"%5d ",line_number);
       for (index = 0;index < 72;index++)
          fprintf(print_file_point,"%c",oneline[index]);
       fprintf(print_file_point,"<\n      ");
       for (index = 72;index < 144;index++)
          fprintf(print_file_point,"%c",oneline[index]);
       fprintf(print_file_point,"<\n      ");
       for (index = 144;index < strlen(oneline);index++)
          fprintf(print_file_point,"%c",oneline[index]);
       lines_this_page += 2;
    }
          /* the following line outputs a newline if there is none
                                       at the end of the last line */
    if (oneline[strlen(oneline)-1] != '\n')
       fprintf(print_file_point,"%c",'\n');
    line_number++;
    lines_this_page++;
 }


 /* ******************************************************** header */
 /* This routine checks to see if a header needs to be printed. It  */
 /* also checks for the end of a page. and spaces the paper up.     */
 /* *************************************************************** */
 void header(void)
 {
 int index;

                   /* first see if we are at the bottom of the page */
    if (lines_this_page > MAXLINES) {  /* space paper up for bottom */
    for (index = lines_this_page;index < 61;index++)
       fprintf(print_file_point,"\n");
    lines_this_page = 0;
    }

             /* put a monitor header out only at the very beginning */
    if (line_number == 0) {               /* display monitor header */
       printf("        Source file %s\n",filename);
       line_number = 1;
    }

          /* check to see if we are at the top of the page either   */
          /* through starting a file, or following a bottom of page */
    if (lines_this_page == 0) {        /* top of every printer page */
       fprintf(print_file_point,"\n\n\n        ");
       fprintf(print_file_point," Source file - %s        ",filename);
       fprintf(print_file_point,"          Page %d\n\n", page_number);
       page_number++;
    }
 }


 /* *************************************************** top_of_page */
 /* This function spaces the paper to the top of the next page so   */
 /* that another call to this function will start correctly. This   */
 /* is used only at the end of a complete printout.                 */
 /* *************************************************************** */
 void top_of_page(void)
 {
 int index;

    for (index = lines_this_page;index < 61;index++)
       fprintf(print_file_point,"\n");
 }


 LLSAVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LLSAVE.C

 /*
  * This is linked from lexlib to resolve a global in yylex which
  * will be undefined if the user grammar has not defined any rules
  * with right-context (look-ahead)
  */
 char    *llsave[1];             /* Look ahead buffer            */


 LMINMAX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\LMINMAX.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         long
 lmax(x, y)                        /* return larger of x and y, long        */

 /*----------------------------------------------------------------------*/
 long x, y;
 {
         return MAX(x,y);
 }

 /************************************************************************/
         long
 lmin(x, y)                        /* return lesser of x and y, long        */

 /*----------------------------------------------------------------------*/
 long x, y;
 {
         return MIN(x,y);
 }


 LMOVB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LMOVB.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 _lmovb(lp, c, st)
 register c, st;
 register struct lextab *lp;
 {
         int base;

         while ((base = lp->llbase[st]+c) > lp->llnxtmax ||
                         (lp->llcheck[base] & 0377) != st) {

                 if (st != lp->llendst) {
 /*
  * This miscompiled on Decus C many years ago:
  *                      st = lp->lldefault[st] & 0377;
  */
                         base = lp->lldefault[st] & 0377;
                         st = base;
                 }
                 else
                         return(-1);
         }
         return(lp->llnext[base]&0377);
 }


 LMOVI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\LMOVI.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 _lmovi(lp, c, st)
 register int    c;
 register int    st;
 register struct lextab *lp;
 {
         int base;

         while ((base = lp->llbase[st]+c) > lp->llnxtmax ||
                         (int *)(lp->llcheck)[base]!=st)
                 if (st != lp->llendst) {
 /*
  * This miscompiled on Decus C many years ago
  *                      st = ((int *)lp->lldefault)[st];
  */
                         base = ((int *)lp->lldefault)[st];
                         st = base;
                 }
                 else
                         return(-1);
         return(((int *)lp->llnext)[base]);
 }


 LOCATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DSKTST\LOCATE.C

 #include "dos.h"
 /****************************************************************************
 *
 *  locate the cursor
 *
 *****************************************************************************
 locate(row,col)                    /* cursor  row, col, attribute */
 int row,col;
 {
   union REGS reg;
   reg.h.bh = 0;                    /* page number */
   reg.h.dh = row;                   /* set row number */
   reg.h.dl = col;                   /* set col number */
   reg.h.ah = 2;                    /* set csr command */
   int86(0x10,&reg,&reg);           /* clr the screen */
 }


 LOCATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\LOCATE.C

 #include <dos.h>
 locate(row,col)
 int row,col;
 {
         struct HREG REGS;

         REGS.ah=02;
         REGS.bh=00;
         REGS.dh=row;
         REGS.dl=col;
         int86(0x10,&REGS,&REGS);


 }


 LOCATE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LOCATE.C

 /**************************************************************/
 /*                                                              */
 /*  NAME                                                      */
 /*                                                              */
 /*         locate - position cursor on screen                      */
 /*                                                              */
 /*  SYNOPSIS                                                      */
 /*                                                              */
 /*         locate(row,col);                                      */
 /*         short row;            row to place cursor on              */
 /*         short col;            column to place cursor on              */
 /*                                                              */
 /*  DESCRIPTION                                               */
 /*                                                              */
 /*         This function directly controls the cursor              */
 /*         placing it on a specified row and column.  It              */
 /*         uses the "csysint" C-to-assembler interface.         */
 /*                                                              */
 /*  RETURNS                                                      */
 /*                                                              */
 /*         There are no return codes.                              */
 /*                                                              */
 /*  CAUTIONS                                                      */
 /*                                                              */
 /*         The arguements row and col are limited by the              */
 /*         terminal mode (i.e., 24x40, 24x80) and are in              */
 /*         the range 1-24 and 1-40 or 1-80 respectively.              */
 /*         This routine does not check the arguements.              */
 /*                                                              */
 /**************************************************************/
 locate(row,col)
 short row,col;
 {
      struct regset {
           char al;
           char ah;
           char bl;
           char bh;
           char cl;
           char ch;
           char dl;
           char dh;
      };
      unsigned csysint();
      struct regset sreg;     /* registers passed to csysint */
      struct regset rreg;     /* registers returned from cysint */
      unsigned flags;             /* machine status register */
      int interrupt;             /* type of interrupt requested */

      interrupt = 0x10;
      sreg.ah = 0x02;
      sreg.al = 0;
      sreg.bl = 0;
      sreg.bh = 0;
      sreg.cl = 0;
      sreg.ch = 0;
      sreg.dh = row;
      sreg.dl = col;

      flags = csysint(interrupt,&sreg,&rreg);
 }
 /* routine to test the locate command  ---- commented out
 main()
 {
      short row,col;

      cls();                     /* clear the screen */

      row = 4; col = 20;
      locate(row,col);
      cprintf("Should be row 4, column 20.\n");

      locate(15,30);
      cprintf("Should be row 15, columen 30.\n");
 }
         --- end of commented code to test the locate command */


 LOCK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\LOCK.C

 /*        LOCK:        File locking command routines for MicroEMACS
                 written by Daniel Lawrence
                                                                 */

 #include <stdio.h>
 #include "estruct.h"
 #include "edef.h"

 #if        FILOCK
 #if        BSD
 #include <sys/errno.h>

 extern int sys_nerr;                /* number of system error messages define
 extern char *sys_errlist[];        /* list of message texts */
 extern int errno;                /* current error */

 char *lname[NLOCKS];        /* names of all locked files */
 int numlocks;                /* # of current locks active */

 /* lockchk:        check a file for locking and add it to the list */

 lockchk(fname)

 char *fname;        /* file to check for a lock */

 {
         register int i;                /* loop indexes */
         register int status;        /* return status */
         char *undolock();

         /* check to see if that file is already locked here */
         if (numlocks > 0)
                 for (i=0; i < numlocks; ++i)
                         if (strcmp(fname, lname[i]) == 0)
                                 return(TRUE);

         /* if we have a full locking table, bitch and leave */
         if (numlocks == NLOCKS) {
                 mlwrite("LOCK ERROR: Lock table full");
                 return(ABORT);
         }

         /* next, try to lock it */
         status = lock(fname);
         if (status == ABORT)        /* file is locked, no override */
                 return(ABORT);
         if (status == FALSE)        /* locked, overriden, dont add to table *
                 return(TRUE);

         /* we have now locked it, add it to our table */
         lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1);
         if (lname[numlocks - 1] == NULL) {        /* malloc failure */
                 undolock(fname);                /* free the lock */
                 mlwrite("Cannot lock, out of memory");
                 --numlocks;
                 return(ABORT);
         }

         /* everthing is cool, add it to the table */
         strcpy(lname[numlocks-1], fname);
         return(TRUE);
 }

 /*        lockrel:        release all the file locks so others may edit */

 lockrel()

 {
         register int i;                /* loop index */
         register int status;        /* status of locks */
         register int s;                /* status of one unlock */

         status = TRUE;
         if (numlocks > 0)
                 for (i=0; i < numlocks; ++i) {
                         if ((s = unlock(lname[i])) != TRUE)
                                 status = s;
                         free(lname[i]);
                 }
         numlocks = 0;
         return(status);
 }

 /* lock:        Check and lock a file from access by others
                 returns        TRUE = files was not locked and now is
                         FALSE = file was locked and overridden
                         ABORT = file was locked, abort command
 */

 lock(fname)

 char *fname;        /* file name to lock */

 {
         register char *locker;        /* lock error message */
         register int status;        /* return status */
         char msg[NSTRING];        /* message string */
         char *dolock();

         /* attempt to lock the file */
         locker = dolock(fname);
         if (locker == NULL)        /* we win */
                 return(TRUE);

         /* file failed...abort */
         if (strncmp(locker, "LOCK", 4) == 0) {
                 lckerror(locker);
                 return(ABORT);
         }

         /* someone else has it....override? */
         strcpy(msg, "File in use by ");
         strcat(msg, locker);
         strcat(msg, ", overide?");
         status = mlyesno(msg);                /* ask them */
         if (status == TRUE)
                 return(FALSE);
         else
                 return(ABORT);
 }

 /*        unlock:        Unlock a file
                 this only warns the user if it fails
                                                         */

 unlock(fname)

 char *fname;        /* file to unlock */

 {
         register char *locker;        /* undolock return string */
         char *undolock();

         /* unclock and return */
         locker = undolock(fname);
         if (locker == NULL)
                 return(TRUE);

         /* report the error and come back */
         lckerror(locker);
         return(FALSE);
 }

 lckerror(errstr)        /* report a lock error */

 char *errstr;                /* lock error string to print out */

 {
         char obuf[NSTRING];        /* output buffer for error message */

         strcpy(obuf, errstr);
         strcat(obuf, " - ");
         if (errno < sys_nerr)
                 strcat(obuf, sys_errlist[errno]);
         else
                 strcat(obuf, "[can not get system error message]");
         mlwrite(obuf);
 }
 #endif
 #else
 lckhello()        /* dummy function */
 {
 }
 #endif


 LOG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\LOG.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 35-59.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define A0         -0.64124943423745581147e+2
 #define A1         +0.16383943563021534222e+2
 #define A2         -0.78956112887491257267e+0
 #define A(w)         ((A2*w A1)*w A0)

 #define B0         -0.76949932108494879777e+3
 #define B1         +0.31203222091924532844e+3
 #define B2         -0.35667977739034646171e+2
 #define B3        +1.0
 #define B(w)        (((w B2)*w B1)*w B0)

 C1         0.693359375                        /* = 355 / 512                *
 C2         (-2.121944400546905827679e-4)        /* C1 + C2 = log(2)        */

 /*\p*********************************************************************/
         double
 log(x)                        /* return natural log (base e) of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double r, f, z, w, znum, zden, xn;
         int n;

         if (x <= 0.0)
         {        errno = EDOM;
                 return -INFINITY;
         }
         f = frexp(x, &n);
         if (f > ROOTHALF)
         {        znum = (f - 0.5) - 0.5;
                 zden = ldexp(f, -1) + 0.5;
         }
         else
         {        --n;
                 znum = f - 0.5;
                 zden = ldexp(znum, -1) + 0.5;
         }
         z = znum / zden;
         w = z * z;
         r = z + z * (w *
                  A(w)
                  /B(w));
         xn = n;
         return (xn * C2 + r) + xn * C1;
 }


 LOG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\LOG.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/


 #include "math.h"
 #include "errno.h"

 double log10(x)
 double x;
 {
         return log(x)*0.43429448190325182765;
 }

 #define A0 -0.64124943423745581147e+2
 #define A1 +0.16383943563021534222e+2
 #define A2 -0.78956112887491257267e+0
 #define A(w) ((A2*w A1)*w A0)

 #define B0 -0.76949932108494879777e+3
 #define B1 +0.31203222091924532844e+3
 #define B2 -0.35667977739034646171e+2
 #define B(w) (((w B2)*w B1)*w B0)

 #define C0 0.70710678118654752440
 #define C1 0.693359375
 #define C2 -2.121944400546905827679e-4

 double log(x)
 double x;
 {
         double Rz, f, z, w, znum, zden, xn;
         int n;
         extern int errno;

         if (x <= 0.0) {
                 errno = EDOM;
                 return -HUGE;
         }
         f = frexp(x, &n);
         if (f > C0) {
                 znum = (znum = f-0.5) - 0.5; /* the assignment prevents const
                 zden = f*0.5 + 0.5;
         } else {
                 --n;
                 znum = f - 0.5;
                 zden = znum*0.5 + 0.5;
         }
         z = znum/zden;
         w = z*z;
 /* the lines below are split up to allow expansion of A(w) and B(w) */
         Rz = z + z * (w *
                          A(w)
                         /B(w));
         xn = n;
         return (xn*C2 + Rz) + xn*C1;
 }




 LOG10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\LOG10.C

 /* 1.0  11-13-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "mathcons.h"

 /************************************************************************/
         double
 log10(x)                /* return common log (base 10) of x                */

 /*----------------------------------------------------------------------*/
 double x;
 {
         double log();

         return (LOG10e * log(x));
 }


 LOG2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\LOG2.C

 /* 1.0  11-13-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "mathcons.h"

 /************************************************************************/
         double
 log2(x)                        /* return binary logarithm (base 2) of x.

 /*----------------------------------------------------------------------*/
 double x;
 {
         double log();

         return log(x) * LOG2e;
 }


 LOTTYPES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\LOTTYPES.C

                                          /* Chapter 4 - Program 3 */
 main()
 {
 int a;              /* simple integer type                  */
 long int b;         /* long integer type                    */
 short int c;        /* short integer type                   */
 unsigned int d;     /* unsigned integer type                */
 char e;             /* character type                       */
 float f;            /* floating point type                  */
 double g;           /* double precision floating point      */

    a = 1023;
    b = 2222;
    c = 123;
    d = 1234;
    e = 'X';
    f = 3.14159;
    g = 3.1415926535898;

    printf("a = %d\n",a);      /* decimal output             */
    printf("a = %o\n",a);      /* octal output               */
    printf("a = %x\n",a);      /* hexadecimal output         */
    printf("b = %ld\n",b);     /* decimal long output        */
    printf("c = %d\n",c);      /* decimal short output       */
    printf("d = %u\n",d);      /* unsigned output            */
    printf("e = %c\n",e);      /* character output           */
    printf("f = %f\n",f);      /* floating output            */
    printf("g = %f\n",g);      /* double float output        */
    printf("\n");
    printf("a = %d\n",a);      /* simple int output          */
    printf("a = %7d\n",a);     /* use a field width of 7     */
    printf("a = %-7d\n",a);    /* left justify in field of 7 */
    c = 5;
    d = 8;
    printf("a = %*d\n",c,a);   /* use a field width of 5     */
    printf("a = %*d\n",d,a);   /* use a field width of 8     */
    printf("\n");
    printf("f = %f\n",f);      /* simple float output        */
    printf("f = %12f\n",f);    /* use field width of 12      */
    printf("f = %12.3f\n",f);  /* use 3 decimal places       */
    printf("f = %12.5f\n",f);  /* use 5 decimal places       */
    printf("f = %-12.5f\n",f); /* left justify in field      */
 }


 LS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TOOLS\LS.C

 /*
  *  Attribute bits:
  *      d - directory
  *      r - read only file
  *      h - hidden file
  *      s - system file
  *      a - archive bit
  *
  *  Files within each directory are sorted alphabetically.
  *  Directories are listed separate from other files.
  */

 <stdio.h>              /* Standard I/O definitions */
 <ctype.h>              /* Character type macros */
 <dos.h>                /* Msdos definitions */
 <errno.h>              /* error codes */
 #include <string.h>

 #define SIZE(x)         (sizeof(x)/sizeof(x[0]))
 A_RONLY         0x01    /* Read only file */
 A_HIDDEN        0x02    /* Hidden file */
 A_SYSTEM        0x04    /* System file */
 A_DIRECTORY     0x10    /* Directory file */
 A_ARCHIVE       0x20    /* Archive bit */
 FNLEN           80      /* Maximum filename length */
 MAXFILES        512     /* Max number of files/directory */

 static char ID[]="## ls.c 2.0 K.van Houten 230987 ##";
 struct date {
 unsigned    d_sec:      5;      /* Time, 2 second intervals */
 unsigned    d_min:      6;      /* Time, minutes */
 unsigned    d_hour:     5;      /* Time, hours */
 unsigned    d_day:      5;      /* Date, day of month */
 unsigned    d_month:    4;      /* Date, month of year */
 unsigned    d_year:     7;      /* Date, year since 1980 */
 };
 struct find {
     char    fnd_dosinfo[21];    /* Reserved for dos */
     char    fnd_attr;           /* File attribute */
     struct date fnd_date;       /* Date structure */
     long    fnd_size;           /* File size */
     char    fnd_name[13];       /* File name less path */
 };
 char   *nameptr ();
 char   *date ();
 char   *malloc ();
 char   *strrchr ();
 int     qscmp ();
 extern int clsize();            /* get cluster size */
 long clust();
 short   tmp;
 struct find f;                  /* Used to return data from msdos */
 union REGS r, o;                /* Contains register values for intcall() */
 int     count;                  /* Number of files/directory */
 char   *p;                      /* Pointer to filename */
 int     i;
 int     j;
 int     lflg = 0;               /* long */
 int     tflg = 0;               /* time sort */
 int     sflg = 0;               /* size in bloks */
 int     rflg = 0;               /* reverse sort */
 int     fflg = 0;               /* identify executables and subdirs */
 long    dirlen;                 /* Total length of one dir */
 char    line[FNLEN];            /* Filename buffer */
 char    dirs[20][50];           /* Subdir buffer */
 int     dirc;                   /* Subdir count */
 int drive;                      /* drive nr */
 char   *file;                   /* Command line argument */
 struct find *fnd[MAXFILES];     /* Pointers to file structures */
 int bsize;                      /* size of clusters */
 int spc;                        /* number of K's per cluster */

 static struct atr {             /* Attribute structure */
     int     a_mask;
     int     a_name;
 } atr[] = {
     A_DIRECTORY, 'd',
     A_RONLY,     'r',
     A_HIDDEN,    'h',
     A_SYSTEM,    's',
     A_ARCHIVE,   'a'
 };

 main (argc, argv)
 int     argc;                   /* Number of command line arguments */
 char   *argv[];                 /* Array of pointers to arguments */
 {
     char    buf[70];

     drive = defdrv();
     bsize=clsize(drive);
     spc=bsize/1024;
     for (argc--,argv++; argc>0; argc--,argv++) {
         if (**argv == '-') {
             while (*++(*argv)) {
                 switch (**argv) {
                 case 'l':
                     lflg++;
                     break;
                 case 't':
                     tflg++;
                     break;
                 case 's':
                     sflg++;
                     break;
                 case 'r':
                     rflg++;
                     break;
                 case 'F':
                     fflg++;
                     break;
                 default:
                     printf("Usage: ls [-Flrst] [file [file ...]]\n");
                     exit(1);
                 }
             }
         }
         else
             break;
     }

     r.h.ah = 0x1a;              /* SET DISK TRANSFER ADDRESS FUNCTION */
     r.x.dx = (int) & f;
     tmp = intdos (&r, &o);
 /*  Produces error 0 ???
     if (o.x.cflag) {
         perror ("SETTING DTA ");
         exit (1);
     }
 */
     dirc = 0;
     count = 0;

     if (argc == 0) {
         strcpy(dirs[dirc++],".");
     }
     else {
         while (file = *argv++, argc--) {
             /* handle relative directorys */
             if (strcmp(file,"..") == 0) {
                 strcpy(dirs[dirc++],"..\\.");
                 continue;
             }
             if (file[strlen(file)-1] == '.') {
                 strcpy(dirs[dirc++],file);
                 continue;
             }
             /* handle drive letters */
             if (strlen(file) == 2 && file[1] == ':') {
                 strcpy(dirs[dirc],file);
                 strcat(dirs[dirc++],".");
                 continue;
             }
             /* handle abs. dirs */
             if (file[strlen(file)-1] == '\\') {
                 strcpy(dirs[dirc], file);
                 strcat(dirs[dirc++],".");
                 continue;
             }
             findf ();
             if (o.x.cflag) {
                 continue;
             }
             for (;;) {
                 if (o.x.cflag) {
                     break;
                 }
                 if (f.fnd_attr & A_DIRECTORY) {
                     if (f.fnd_name[0] == '.')
                        goto next;
                     *dirs[dirc]='\0';
                     if (strrchr(file,'\\')!=NULL) {
                        strncpy(dirs[dirc],file,((strrchr(file,'\\')-file)+1))
                     }
                     strcat (dirs[dirc++], f.fnd_name);/* save subdir name */
                 }
                 else {
                     if ((fnd[count] =
                        (struct find *)malloc(sizeof(struct find))) == NULL)
                           fatal ("out of memory");
                     *fnd[count] = f;
                     /* Increment total size */
                     dirlen += clust(fnd[count]->fnd_size);
                     count++;
                 }
 next:           findn ();
             }
         }
         if (count == 0 && dirc == 0) {
             printf("File not found\n");
             exit(1);
         }
     }
     /* All arguments done, now print simple files */
     qsort (fnd, count, sizeof (struct find *), qscmp);

     for (i = 0; i < count; i++) {
         printentry(i);
         if ((lflg==0) && (((i+1) % (sflg?4:5)) == 0) && (i > 1))
             printf("\n");
     }
     for (i = 0; i < dirc; i++)
         printdir(i);
     return (1);
 }

 /*
  * Print one entry, format depends on options selected.
  */
 printentry(x)
 int x;
 {
     long sz;
     char pbuf[50];    /* print buffer */

     sz = fnd[x] -> fnd_size;

     /* block size */
     if (sflg)
     {
         if ((fnd[x] -> fnd_attr & A_DIRECTORY) == 0)
         {
            printf("%3d ",clust(sz));
         }
         else
            printf("  0 ");
     }
     if (lflg) {
         /* mode bits */
         for (j = 0; j < SIZE (atr); j++)
             if (atr[j].a_mask & fnd[x] -> fnd_attr)
                 putchar (atr[j].a_name);
             else
                 putchar ('-');

         /* file size */
         printf (" %10ld  ", sz);

         /* file date */
         printf ("%s  ", date (&fnd[x] -> fnd_date));
     }

     /* file name */
     if (fflg == 0)
         printf ("%-12s  " , strlwr (fnd[x] -> fnd_name));

     /* executable / subdir info */
     if (fflg)
     {
         if (fnd[x] -> fnd_attr & A_DIRECTORY)
             sprintf (pbuf,"%s/" , strlwr (fnd[x] -> fnd_name));
         else
         {
             if (isexe(fnd[x]->fnd_name))
                 sprintf (pbuf,"%s*" , strlwr (fnd[x] -> fnd_name));
             else
                 sprintf (pbuf,"%s " , strlwr (fnd[x] -> fnd_name));
         }
         printf ("%-12s  " , pbuf);
     }

     if (lflg)
         printf("\n");

     free (fnd[x]);          /* Free find structure */
 }


 printdir (x)
 int x;
 {
     int i;
     char fbuf[80]; /* to assemble filename */

     /* Complex, but needed for DOS 2.11 compatibility */
     if (dirs[x][strlen(dirs[x])-1] == '.') {
         dirs[x][strlen(dirs[x])-1] = '\0';
         strcpy(fbuf,dirs[x]);
         strcat(fbuf,"*.*");
     }
     else {
         strcpy(fbuf,dirs[x]);
         strcat(fbuf,"\\*.*");
     }
     if (dirs[x][1] == ':') { /* other drive */
         drive=tolower(*dirs[x])-'a';
     }
     else {
         drive=defdrv();
     }
     bsize=clsize(drive);
     spc=bsize/1024;
     file = fbuf;
     p = nameptr (file);
     count = p - file;
     if (count + sizeof (f.fnd_name) > FNLEN)
         fatal ("filename too long: %s", file);
     strncpy (line, file, count);
     p = line + count;
     count = 0;                  /* Init file count */
     dirlen = 0;

     findf ();
     for (;;) {
         if (o.x.cflag)
             break;
         if (count >= MAXFILES)
             fatal ("Too many files in one directory");
         if ((fnd[count] =
            (struct find *) malloc (sizeof (struct find))) == NULL)
               fatal ("out of memory");
         if (!((f.fnd_attr & A_DIRECTORY) &&
                     ((strcmp (f.fnd_name, ".") == 0) ||
                         (strcmp (f.fnd_name, "..") == 0)))) {
             memcpy (fnd[count], &f, sizeof f);
             /* Increment total size */
             dirlen += clust(fnd[count] -> fnd_size);
             count++;
         }
         findn ();
     }
     if (count)
         qsort (fnd, count, sizeof (struct find *), qscmp);

     if (*dirs[x] != '\0')
         printf("\n%s:\n", strlwr(dirs[x]));
     if (lflg) {
         printf ("Total %d\n",dirlen);
     }
     for (i = 0; i < count; i++) {
         printentry(i);
         if ((lflg==0) && (((i+1) % (sflg?4:5)) == 0) && (i > 1))
             printf("\n");
     }
 }

 /*
  * Find first entry, return info in find structure.
  */
 findf ()
 {
     r.h.ah = 0x4e;              /* FINDFIRST function */
     r.x.cx = A_HIDDEN | A_SYSTEM | A_DIRECTORY |
         A_RONLY | A_ARCHIVE;
     r.x.dx = (int) file;
     tmp = intdos (&r, &o);      /* Find first */
 }

 /*
  * Find next entry
  */
 findn ()
 {
     r.h.ah = 0x4f;              /* Now use FINDNEXT function */
     tmp = intdos (&r, &o);      /* Find next */
 }

 /*
  * Return a pointer to an ascii date, given a pointer
  * to a date structure
  */
 char    ad[40];

 char   *
         date (dp)
 register struct date   *dp;
 {
     static char *month[] = {
         "Jan",
         "Feb",
         "Mar",
         "Apr",
         "May",
         "Jun",
         "Jul",
         "Aug",
         "Sep",
         "Oct",
         "Nov",
         "Dec"
     };

     sprintf (ad, "%2d %s %4d  %02d:%02d:%02d",
             dp -> d_day,
             month[dp -> d_month - 1],
             dp -> d_year + 1980,
             dp -> d_hour,
             dp -> d_min,
             dp -> d_sec * 2);
     return (ad);
 }

 /*
  * Qsort compare routine
  * Directories first, other files second, sort alphabetically.
  * This routine is called by qsort and passed two pointers to
  * find structure pointers.
  */
 qscmp (p1, p2)
 struct find **p1;
 struct find **p2;
 {
     register struct find   *f1 = *p1;
     register struct find   *f2 = *p2;
     register int    cmp;
     int inv = 1;

     if (rflg)
         inv=-1;
 /*
     if (cmp = (f2 -> fnd_attr & A_DIRECTORY) - (f1 -> fnd_attr & A_DIRECTORY)
         return (cmp);
  */
     if (tflg) {
         if (cmp = (f2->fnd_date.d_year - f1->fnd_date.d_year))
             return(inv * cmp);
         if (cmp = (f2->fnd_date.d_month - f1->fnd_date.d_month))
             return(inv * cmp);
         if (cmp = (f2->fnd_date.d_day - f1->fnd_date.d_day))
             return(inv * cmp);
         if (cmp = (f2->fnd_date.d_hour - f1->fnd_date.d_hour))
             return(inv * cmp);
         if (cmp = (f2->fnd_date.d_min - f1->fnd_date.d_min))
             return(inv * cmp);
         if (cmp = (f2->fnd_date.d_sec - f1->fnd_date.d_sec))
             return(inv * cmp);
     }
     return (inv * strcmp (f1 -> fnd_name, f2 -> fnd_name));
 }

 /*
  * Return a pointer to the beginning of the filename (past pathname if any)
  */
 char   *
         nameptr (name)
 char   *name;
 {
     register char  *p1;

     if ((p1 = strrchr (name, '\\')) != NULL)
         return (++p1);
     else
         if ((p1 = strrchr (name, ':')) != NULL)
             return (++p1);
     return (name);
 }

 /*
  * Fatal error
  * The %r (recursive) printf format specifier is non-portable.
  */
 fatal (p)
 char   *p;
 {
     printf ("ls fatal error\n");
     exit (0);
 }

 long
 clust(sz)
 long sz;
 {
 return(spc*((sz % bsize) ? (sz / bsize + 1) : (sz / bsize)));
 }

 int
 defdrv()
 {
     int tmp;
     union REGS r;

     r.h.ah = 0x19;  /* get default drive */
     tmp = intdos(&r,&r);
     if (r.x.cflag != 0) {
         printf("Error reading def. drive: %d\n",tmp);
         exit(1);
     }
     return(r.h.al);
 }

 int
 isexe(n)
 char *n;
 {
     char *p,*t;

     if ((p=strchr(n,'.')) == NULL)
         return(0);
     p++;
     if (strncmp(p,"EXE",3) == 0)
         return(1);
     if (strncmp(p,"COM",3) == 0)
         return(1);
     if (strncmp(p,"BAT",3) == 0)
         return(1);
     return(0);
 }


 LS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\LS.C

 /*
 NAME
         dirc        -   UNIX-"ls" like directory listing utility written in '
                     Tested under PC-DOS using Lattice C rel 2.11.
                     This version allows limited recursive directory searches.

 AUTHOR
         Marty Ross,        Computing Resource Center,        Santa Monica, Ca

         For updates and more utilities of the like, call CRC-PC, or CRCBBS
         bulletin board system(s).  Currently at:

         (213) 829-1487        (300 baud, IBM-PC)
         (213) 828-1331  (300 baud, VM/370) <-- type "LOG DEMO DEMO" for acces

         NOTE: We are moving around late OCT., 1984 so above numbers will be
               invalid after OCT, 1984.

 SYNOPSIS
    [pc/ms-dos]
         A>dirc        [-options] [d:][/path/]filename[.ext]

    [as C function]
         ret =   dirc(s,op);
                 char *s;        /* Pointer to [d:][/path/]filename[.ext] */
                 char *op;        /* Pointer to option string */
                                 /* Will 'ret' urn 0 normally, or 2 if no find
 where:
         options
                   Is a string of lower case letters selecting
                 how many columns to generate, which files, according to
                 file attribute, should be displayed, and the selection
                 of file size/date of last access, volume header display,
                 subdirectory/time of creation, and file attribute bit
                 display.  The option string "shrvdzt1" for instance,
                 will generate one column (1), will display system files
                 (s), hidden files (h), read-only files (r), volume-header
                 entry [files] (v), subdirectories (d), siZe (z), and
                 date-Time (t) information when it outputs its list.
                 An added feature in this version is the 'e' option, which
                 will also enable the 'd' option to show subdirectories
                 (which match the filename - usually '*.*'), and invoke
                 itself recursively for that subdirectory.  Thus, an entire
                 hard-disk or other tree-structured file system can be
                 completely scanned with one command.

                 Note that because of DOS interfacing conventions, only
                 directories which match the file specification you typed
                 on the command line (if none, '*.*') will be shown.  This
                 disables a potentially very useful feature: ability to
                 selectively scan across directories for particular files.
                 I will most likely include that feature in the next release
                 of DIRC, when I invent my own subroutines to handle wildcard
                 symbols myself - i'll always ask DOS for *.* and do the
                 filtering myself!


         option letter                meaning
         -------------

                 1                Generate one column/line output.
                 2                Generate two columns/line output.
                 3                Generate three columns/line output.
                 4                Generate four colums/line output.

                 a                Archive bit.  Set on when file written
                                 to since last FDISK backup.  Allows DIRC to
                                 select only files changed since last backup.

                 b                Bits.  Causes file access (mode) bits to be
                                 displayed before each filename.

                 d                Directories.  Includes Subdirectories
                                 in file searches.

                 e                Expand.  Expand sub-directories which match
                                 given filename wildcard.  Should use "*.*"
                                 to get all subdirectories.

                 h                Hidden files. List files with 'hidden' statu

                 l                Long.  Include '.' and '..' subdir files.

                 q                Quiet.  Don't say "[/path/]filesp:" before d

                 r                Read-Only bit. Files which cannot be written

                 s                System file. Don't erase these files.

                 t                Time & Date.  Include for each file.

                 u                Un-archive bit.  See files which have not be
                                 changed since last FDISK BACKUP.

                 v                Volume header(s?)

                 x                Exclusive.  Don't list "normal" files.

                 z                siZe.  Include for each file.

                 ]                Right Justify filenames in filename field.

                 [                Left Justfy filenames.

         ----------------


 DESCRIPTION

         DIRC provides a flexible directory interface to the PC-DOS
 file system when using C under the Lattice compiler.  Output goes
 to STDOUT, and for this test version written as a PC-DOS command,
 input is via the first two 'argv[]' tokens.  Since it is a demonstration
 of the capabilities of the DIRC function only, a simple option passing scheme
 (using the second token), was chosen rather than the more standard
 UNIX option scheme, where the option comes (optionally) first.


         DIRC was written for PC-DOS using the Lattice C compiler.  The
 author claims to be no UNIX expert, but realizes that most of the features
 of the program are 'boarrowed' from that system.  The desired goal was a
 flexible way to provide directories from within C programs.  The first
 result of that effort lies herein, in a test 'shell' which calls DIRC
 using 'argv[1]' and 'argv[2]'.

         From PC-DOS, you can specify both file specification and option
 string as 'tokens', separating with a space.  Because DIRC options are
 lower case only (in the UNIX tradition), YOU MUST SPECIFY ALL OPTIONS
 IN LOWER CASE!

         Note that stack size is set large in case of deeply nested directorie
 when recursive option 'e' is used.  If '*** STACK OVERFLOW ***' error STILL
 occurs, then you may override the stack size, using the Lattice Compiler, by
 typing an equal sign, followed by the desired stack size, in decimal.

 I.E.:

 A>dirc =30000 *.*
 */

 int        _stack        =        25000;                /* large stack in cas

 /* Following imitations of key routines in SEDIT.H */
 int newline()
 {
 printf("\n");
 return 0;
 }

 spout(line,arg1,arg2)
 char *line;
 int arg1, arg2;
 {
 printf("%s",line);
 }

 /* Start of DIRC.C */
        <dos.h>                /* Note: Tested under Lattice Rel 2.11 */
                BLANK                " "        /* For SPOUT */
                DEF_OPTS        ""        /* Use internal defaults now */
 #define                DEF_FN                "*.*"

 main(argc,argv)
 int argc;
 char *argv[];
 {
 int i, rc;
 char *opts, *fn;

 if (argc<2) {
         opts = DEF_OPTS;
         fn = DEF_FN;
         }
 else if (argv[1][0]=='-') {
         if (argc<3) fn = DEF_FN;
         else fn = argv[2];
         opts = argv[1];        /* If options */
         }
 else {
         opts = DEF_OPTS;
         fn = argv[1];
         }
 rc=dirc(fn,opts);
 if (rc && rc!=2) printf("R(%d);\n",rc);
 }


                FIND_FILE        0x4E                /* DOS find file command
                NEXT_FILE        0x4F                /* DOS next file command
                NORMAL_ATTR        0x20                /* "NORMAL" file attr *
                DTA_SIZE        128                /* Size of DOS DTA */
                B_F_WIDTH        13                /* 'vanilla' field width */
                B_DIR_TYP        0                /* Default 'type' for DIR */
                B_DIR_OPT        0x0B                /* File and size only dfl
                K                1024                /* What is a 'K' ? */
                NA                0                /* No Argument - don't care
                SET_DTA                0x1A                /* Set DTA address

 char *filedate(), *filetime();                        /* Forward references *

                 /* Our attribute byte fields */
                F_RONLY                1                /* Read only bit */
         F_HIDDEN        2                /* File hidden */
                F_SYSTEM        4                /* System file */
                F_VOLUME        8                /* Volume */
                F_SUBDIR        16                /* Subdirectory */
                F_ARCHIVE        32                /* Archived */
 #define                F_B6                64
 #define                F_B7                128

 char        fatbits[]        = "rhsvda!?";                /* Meaning of attri

                 /* Our option bit flags image */
                O_WIDTH                3                /* Two bit width field
                O_NONORMAL        4                /* Don't show normal files
                O_ONLYARCH        8                /* Only show archived files
                O_NOARCH        16                /* Only show non archived fl
                O_DATE                32                /* Include date/time *
                O_SIZE                64                /* Show size of file *
                O_ATTRIBS        128                /* Show file attribute bit
                O_QUIET                256                /* Quiet flag */
                O_EXPAND        512                /* Expand sub-dirs */
                O_RJUST                1024                /* Right- justify *
                O_LONG                2048                /* Include '.' and '

 #define                COLON                ':'
 #define                ESCSYM                '\\'
 #define                ESCSTR                "\\"


         /* k l u d g e macro (sorry) */
                                 /* on if attrib selected */
 #define          L_Field        (((options&O_ATTRIBS)?9:0)+f_width)

 int mdirfile(fn,type,options)
 char *fn;
 char type;
 unsigned options;
 {
 int nff;
 int i, cp, rc;
 int r_col, f_width;
 char entr[81];                                        /* maximum length outpu
 char spbuf[10];
 char temp[40];
 char extbfr[128];                        /* For rcrsv subdir expansion */
 unsigned ds,dx, es, bx;
 int dat,siz,attrs,rjust;
 union {                                        /* DTA and DIR field image */
         char        disk_buffer[DTA_SIZE];
         struct        {
                         char          sys_data[21];
                         char          file_attribute;
                         unsigned file_time ;
                         unsigned file_date ;
                         long         file_size ;
                         char         fn_ext[13] ;
                         }  file_table;
         } my_dta;

 static int lvl;          /* Level of recursion - will be zero when prog begin

 lvl++;                                                /* First level */
 rc = 1001;                                        /* RC for no string given *
 if (*fn != '\0') {
         nff = 0;                                /* Zero files found so far */
         f_width = B_F_WIDTH;                        /* Fieldsize for plain di
         dat = (options & O_DATE);
         siz = (options & O_SIZE);                /* Size flag selected */
         attrs = (options & O_ATTRIBS);                /* Attributes required

         if (siz) f_width += 7;        /* adjust 'per field' size */
         if (dat) f_width += 16;        /* etc...*/

         r_col = ((options & O_WIDTH)+1)*L_Field;
         rjust = (options & O_RJUST);
         getdta(&ds,&dx);                /* Get and save current DTA */
         setdta(0,&my_dta);                /* Set up our own DTA */
         rc = bdos2(FIND_FILE,NA,NA,type,fn);
         if (rc==0) {                /* Look for ALL files */
                 while (rc==0) {
                         for (cp=0;cp<r_col&&rc==0;rc=bdos2(NEXT_FILE)) {
                                 if (!(options&O_LONG)) {
                                         if (!strcmp(my_dta.file_table.fn_ext,
                                             !strcmp(my_dta.file_table.fn_ext,
                                                 continue;
                                         }
                                 if (options&O_NONORMAL) {   /* -x */
                                         if (my_dta.file_table.file_attribute=
                                                 continue;
                                         }
                                 if (options&O_ONLYARCH) {   /* -a */
                                         if (!(my_dta.file_table.file_attribut
                                                 continue;
                                         }
                                 if (options&O_NOARCH) {     /* -u */
                                         if (my_dta.file_table.file_attribute&
                                                 continue;
                                         }
                                 if (nff++==0 && (options&O_QUIET)==0) {
                                         sprintf(temp,"%s;\n",fn);
                                         spout(temp,2,1);
                                         }
                                 if (attrs) {    /* -b */
                                         for (i=7;i>=0;i--) {
                                                 if (my_dta.file_table.file_at
                                                         stccpy(spbuf,fatbits+
                                                         spout(spbuf,2,1);
                                                         }
                                                 else spout("-",2,1);
                                                 }
                                         spout(BLANK,2,1);
                                         }
                                 if (rjust) sprintf(entr,"%12s",my_dta.file_ta
                                 else sprintf(entr,"%-12s",my_dta.file_table.f
                                 if (siz) {            /* -z */
                                         if (my_dta.file_table.file_attribute
                                                 F_VOLUME) sprintf(temp,"  <vo
                                         else if (my_dta.file_table.file_attri
                                                 F_SUBDIR) sprintf(temp,"  <di
                                         else sprintf(temp,"%6.1fK",
                                            (((float)my_dta.file_table.file_si
                                         strcat(entr,temp);
                                         }
                                 if (dat) {     /* -t */
                                         sprintf(temp,"  %s %s",
                                                 filedate(my_dta.file_table.fi
                                                 filetime(my_dta.file_table.fi
                                         strcat(entr,temp);
                                         }
                                 i = f_width - strlen(entr) - 1;
                                 while(i-->0) spout(BLANK,2,1);
                                 spout(entr,2,1);
                                 if ((my_dta.file_table.file_attribute&F_SUBDI
                                      && strcmp(my_dta.file_table.fn_ext,"..")
                                      && strcmp(my_dta.file_table.fn_ext,"."))
                                         spout("\n",2,1);
                                         mknwdir(extbfr,fn,my_dta.file_table.f
                                         rc = mdirfile(extbfr,type,options);
                                         cp = 0;
                                         if (rc==1) break;
                                         }
                                 else {
                                         cp+=L_Field;        /* Account for ho
                                         if (cp<r_col) {
                                                 spout(BLANK,2,1);
                                                 if (attrs || dat) spout(BLANK
                                                 }
                                         else if (newline()) {
                                                 rc=1;
                                                 break;
                                                 }
                                         }
                                 }        /* End FOR */
                         if (rc==1) break;
                         }         /* End WHILE */
                 }        /* End IF */
         setdta(ds,dx);                        /* Restore callers' DTA */
         } /* endif */

 if (nff==0) {
         if (lvl==1) spout("No file(s) found.\n",2,1); /* 1st level only */
         else {
                 if (!(options&O_NONORMAL)) {
                         sprintf(extbfr,"No files: %s\n",fn);
                         spout(extbfr,2,1);
                         }
                 }
         rc = 2;                        /* No files found */
         }
 else {
         if (rc==18) rc=0;        /* Get rid of error 18 if files found */
         if (cp && cp<r_col) spout("\n",2,1);
         if (lvl!=1) {
                 sprintf(extbfr,"(End of %s)\n",fn);
                 spout(extbfr,2,1);
                 }
         }
 return rc;
 }  /* enddir */

 int dirc(fn,optlist)
 char *fn;
 char *optlist;
 {
 unsigned opts;                /* directory listing option bits */
 char type;                /* File attribute */

 type = 0;                /* Normal files only */
 opts = 0;                /* Default one column */
                         /* Default size & date/time */
 /* if (!*optlist) opts = opts | O_SIZE | O_DATE;  */

 for (;*optlist;optlist++) {
         switch(*optlist) {
                 case '-': ;                        /* Freedom of option passi
         break;        case 'v': type = type | F_VOLUME;        /* Volume head
             break;        case 'r': type = type | F_RONLY;        /* Read-onl
             break;        case 'h': type = type | F_HIDDEN;        /* Hidden
         break;         case 'd': type = type | F_SUBDIR;        /* SubDirecto
         break;        case 's': type = type | F_SYSTEM;        /* System file
         break;        case '!': type = type | F_B6;                /* B6 ?? *
         break;        case '@': type = type | F_B7;                /* B7 ?? *
         break;        case 'x': opts = opts | O_NONORMAL;        /* Exclusive
         break;        case 'a': opts = opts | O_ONLYARCH;        /* Archived
                           type = type | F_ARCHIVE;        /* Search for it, t
         break;        case 'u': opts = opts | O_NOARCH;        /* Un archived
                           type = ((~F_ARCHIVE)&type);        /* Un-do the arc
         break;        case 't': opts = opts | O_DATE;                /* Show
         break;        case 'z': opts = opts | O_SIZE;                /* Show
         break;        case 'b': opts = opts | O_ATTRIBS;        /* Show attri
         break;        case 'q': opts = opts | O_QUIET;        /* Shut up */
         break;        case 'e': opts = opts | O_EXPAND;         /* Expand sub
                           type = type | F_SUBDIR;
         break;        case 'l': opts = opts | O_LONG;                /* Incl.
         break;        case ']': opts = opts | O_RJUST;        /* Right justif
         break;        case '[': opts = opts & ~O_RJUST;        /* Turn off RJ
         break;        case '1': ;                                   /* number
                 case '2': ;
                 case '3': ;
                 case '4': opts = (opts&~(unsigned)3) | ((*optlist)-'1');
         break;  default: {
                         spout("Bad internal dir opts\n",2,1);
                         return 1;
                         }
                 }
         }
 if (*fn=='\0') fn="*.*";                /* Default for current version */
 return (mdirfile(fn,type,opts));
 }

 mknwdir(buffer,curspec,newdir)
 char buffer[], curspec[], newdir[];
 {
 char mybuf[32];
 int i;

 split_file(curspec,buffer,mybuf);
 i = strlen(buffer);
 if (i) {
         if (buffer[--i]!=ESCSYM && buffer[i]!=COLON) strcat(buffer,ESCSTR);
         }
 strcat(buffer,newdir);
 strcat(buffer,ESCSTR);
 strcat(buffer,mybuf);
 }

 split_file(curspec,buffer,hisbuf)
 char *curspec, *buffer, *hisbuf;
 {
 int i;

 buffer[0] = hisbuf[0] = '\0';
 i = strlen(curspec);
 if (i) {
         while(curspec[--i]!=ESCSYM && curspec[i]!=COLON && i!=0);
         if (i) stccpy(buffer,curspec,++i+1);
         strcpy(hisbuf,curspec+i);
         }
 }

 char *filetime(codetime)
 unsigned codetime;
 {
 static char ftime[7];
 sprintf(ftime,"%02d:%02d",(codetime&0xF800)>>11,
                       (codetime&0x07E0)>>5);
 return(ftime);
 }

 char *filedate(codedate)
 unsigned codedate;
 {
 static char fdate[11];

 sprintf(fdate,"%02d/%02d/%02d",
         (codedate&0x01E0)>>5,
         (codedate&0x001F),
         ((codedate&0xFE00)>>9)+80);
 return(fdate);
 }

 #define                GETDTA        0x2F
 #define                SETDTA        0x1A

 /* (8)        register = mdos(ah,al,bx,cx,dx)        * Call DOS function (ah)
 bdos2(ah,al,bx,cx,dx)
 char ah,al;
 int bx,cx,dx;
 {
 union                 REGS         myregs;
 myregs.h.ah = ah;
 myregs.h.al = al;
 myregs.x.bx = bx;
 myregs.x.cx = cx;
 myregs.x.dx = dx;
 intdos(&myregs,&myregs);
 return myregs.x.ax;
 }

 getdta(esptr,bxptr)
 unsigned *esptr,*bxptr;
 {
 union                 REGS         myregs;
 struct                 SREGS        mysregs;
 segread(&mysregs);                /* Lattice suggests reading seg regs first
 myregs.h.ah = GETDTA;
 intdosx(&myregs,&myregs,&mysregs);
 *esptr = mysregs.es;                /* Get DTA outputs to ES:BX */
 *bxptr = myregs.x.bx;
 }

 setdta(es,bx)
 unsigned es,bx;
 {
 union                 REGS         myregs;
 struct                 SREGS        mysregs;
 segread(&mysregs);                /* Lattice suggests reading seg regs first
 myregs.h.ah = SETDTA;                /* Assign new DTA function code */
 myregs.x.dx = bx;                /* Assign new offset to DTA */
 if (es!=0) mysregs.ds = es;                /* If zero, use our data segment *
 intdosx(&myregs,&myregs,&mysregs);         /* Set DTA req's DS:DX as argument
 }


 LS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\KWMV\LS.C

 #include <stdio.h>

 typedef struct
 {
         char attribute;
         unsigned file_time;
         unsigned file_date;
         long file_size;
         char file_name[13];
 } file_desc;

 typedef struct
 {
         char dos_reserved[21];
         file_desc file;
 } fcb;

 #define maxfiles 64

 char printbuf[256];
 int mode = 0x10;
 file_desc *get_first(),*get_next();
 char *index(), *rindex();
 int verbose=0,column=4,recurse=0;

 main(argc,argv)
 char *argv[];
 {
         int noargs;
         char *current;
         char namebuf[128];
         /*
          * set up a default search name
          */
         if (noargs = (argc == 1))
                 argc++;
         while(--argc)
         {
                 if (noargs)
                         current = "*.*";
                 else
                         current = *(++argv);        /* get current file name
                 if (*current == '-')
                 {
                         ++current;        /* point past - */
                         while (*current)
                         {
                                 switch (*current++)
                                 {
                                 case 'l':
                                 case 'L':
                                         verbose = 1;
                                         if (column != 1)
                                                 column = 2;
                                         break;
                                 case 'c':
                                 case 'C':
                                         column = 1;
                                         break;
                                 case 'a':
                                 case 'A':
                                         mode = 0x2 + 0x4 + 0x10;
                                         break;
                                 case 'r':
                                 case 'R':
                                         recurse = 1;
                                         mode = 0x2 + 0x4 + 0x10;
                                         break;
                                 default:
                                         break;
                                 }
                         }
                         /* if we're down to one argument after looking at all
                            switches, we need to set noargs to true */
                         if (noargs = (argc == 1))
                                 argc++;
                         continue;
                 }
                 if (get_first(current)->attribute & 0x10 &&
                         NULL == index(current,'?') && NULL == index(current,'
                 {
                         strcpy(namebuf,current);
                         strcat(namebuf,"\\*.*");
                         current = namebuf;
                 }
                 do_dir(current);
         }
 }

 do_dir(current)
         char *current;
 {
         file_desc files[maxfiles];        /* as many as we'll likely need */
         file_desc *curr_file,*get_next();
         unsigned int time,date;
         int i,j,col;
         int files_cmp();
         char atts[4]; /* drw */
         /* look for match */
         i = 0;
         if (!(curr_file = get_first(current)))
         {
                 printf(stderr,"ls : no files matching %s\n",current);
                 return;
         }
         files[i++] = *curr_file;
         /* get all matching */
         while ((curr_file = get_next()) && i < maxfiles)
                 files[i++] = *curr_file;
         if (i > 1)
                 qsort(files,i,sizeof(file_desc),files_cmp);
         printf("%s\n",current);
         col = 1;
         for (j = 0; j < i; j++)
         {
                 register char *c = files[j].file_name;
                 if (*c == '.')
                         continue;        /* filter out . and .. */
                 while (*c)
                 {
                         *c = tolower(*c);
                         c++;
                 }
                 if (verbose)
                 {
                         register char att = files[j].attribute;
                         atts[3] = 0;        /* terminate string */
                         atts[0] = att & 0x10 ? 'd' : '-';
                         atts[1] = att & 2 ? '-' : 'r';
                         atts[2] = att & 1 ? '-' : 'w';
                         if (atts[0] == 'd')
                         {
                                 register int k;
                                 sprintf(printbuf,"%s %s\\",atts,files[j].file
                                 write(1,printbuf,strlen(printbuf));
                                 k = 12 - strlen(files[j].file_name)+7;
                                 while(k--)
                                         write(1," ",1);

                         }
                         else
                         {
                                 sprintf(printbuf,"%s %-12s %-6ld ",atts,files
                                                 files[j].file_size);
                                 write(1,printbuf,strlen(printbuf));
                         }
                         time = files[j].file_time;
                         date = files[j].file_date;
                         sprintf(printbuf,"%02d/%02d %02d:%02d ",
                                 ((date >> 5) & 0x0F),        /* month */
                                 date & 0x1F,                /* day        */
                                 (time >> 11) & 0x1F,                /* hours
                                 (time >> 5) & 0x3F);                /* minute
                         write(1,printbuf,strlen(printbuf));
                 }
                 else
                         if (files[j].attribute & 0x10)
                         {
                                 register int k;
                                 sprintf(printbuf,"%s\\",files[j].file_name);
                                 write(1,printbuf,strlen(printbuf));
                                 k = 16 - strlen(files[j].file_name);
                                 while(--k)
                                         write(1," ",1);

                         }
                         else
                         {
                                 sprintf(printbuf,"%-13s   ",files[j].file_nam
                                 write(1,printbuf,strlen(printbuf));
                         }
                 if (col == column)
                 {
                         col = 1;
                         write(1,"\r\n",2);
                 }
                 else
                         col++;
         }
         write(1,"\r\n",2);
         if (recurse)
                 for (j = 0; j < i; j++)
                 {
                         /* we've got a subdirectory */
                         if (files[j].attribute & 0x10 && files[j].file_name[0
                         {
                                 char *path;
                                 char dirname[48];
                                 if (!strcmp(current,"*.*"))
                                         dirname[0] = '\0';
                                 else
                                         strcpy(dirname,current);
                                 if (path = rindex(dirname,'\\'))
                                         *(++path) = '\0';
                                 strcat(dirname,files[j].file_name);        /*
                                 strcat(dirname,"\\*.*");
                                 do_dir(dirname);
                         }
                 }
 }
 files_cmp(a,b)
         file_desc *a,*b;
 {
         return strcmp(a->file_name,b->file_name);
 }

 fcb tmp;

 file_desc *get_first(fname)
         char *fname;
 {
         register int result;
         /* set the disk transfer address */
         bdos(0x1A,&tmp);
         result = bdos(0x4E,fname,mode);
         /* make the find first call */
         if(2 == result || 18 == result)
                 return NULL;
         return &(tmp.file);
 }

 file_desc *get_next()
 {
         register int result;
         /* set the disk transfer address */
         bdos(0x1A,&tmp);
         result = bdos(0x4f,0,0);
         /* make the find next call */
         if (18 == result)
                 return NULL;
         return &(tmp.file);
 }


 LSEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\LSEARCH.C

 #include <stdio.h>

 char *lfind(key, base, num, size, cmp)
 register char *key;
 register char *base;
 register int num;
 register int size;
 register int (*cmp)();
 /*
  *        Like lsearch(), but do not add elements which are not found.
  */
 {
         while(num--) {
                 if((cmp)(base, key) == 0)
                         return(base);
                 base += size;
         }
         return(NULL);
 }

 char *lsearch(key, base, num, size, cmp)
 char *key;
 char *base;
 int num;
 int size;
 int (*cmp)();
 /*
  *        Perform a linear search for <key> on the data at <base>. The
  *        <num>, <size> and <cmp> parameters are like the corresponding
  *        parameters to qsort().  A pointer to the first matching element
  *        is returned for success, or NULL for failure.  If <key> is not
  *        found, it will be added to the end of the array.
  */
 {
         register char *p;

         if(p = lfind(key, base, num, size, cmp))
                 return(p);
         blkcpy((base + (size * num)), key, size);
 }


 LSTYLE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGAPAINT\LSTYLE.C

 /**************************************************************************
  *                                                                        *
  *      Utility to change the line style.  Originally set up to           *
  *      use turbo's internal settings, but I had to modify it when I      *
  *      went to the exclusive OR mode custom lines for the grid           *
  *      function. It still looks real pretty.  All that needs to be done  *
  *      is to set a mask and use it in the line draw routine              *
  *                                                                        *
  **************************************************************************/

 #define FALSE 0
 #define TRUE  1

 #include <dos.h>
 #include <bios.h>
 #include <conio.h>
 #include <graphics.h>
 #include <alloc.h>
 #include <stdlib.h>
 #include <stdarg.h>

 extern int bkcolor, cc, maxx, maxy;
 extern unsigned scr_size[2];
 extern void *scr_buffer[2];
 extern int width;
 extern int gprintf( int xx, int yy, char *fmt, ... );

 int lstyle(void)
 {
         union {
                 int i;
                 unsigned char c[2];
         } key;

         struct {
                 int type;
                 int pattern;
         } style[25] = {
                 {0, 0},
                 {0, 0},
                 {1, 0},
                 {2, 0},
                 {3, 0},
                 {4, 0xfffe},
                 {4, 0xfffc},
                 {4, 0xfff8},
                 {4, 0xfff0},
                 {4, 0xffe0},
                 {4, 0xffc0},
                 {4, 0xff80},
                 {4, 0xff00},
                 {4, 0xfe00},
                 {4, 0xfc00},
                 {4, 0xf800},
                 {4, 0xf000},
                 {4, 0xe000},
                 {4, 0xc000},
                 {4, 0x8000},
                 {4, 0x1111},
                 {4, 0x3333},
                 {4, 0x5555},
                 {4, 0x7777},
                 {4, 0x9999}
         };


         struct textsettingstype oldtext;
         struct linesettingstype oldline;

         register int i = 10;
         int title_x, title_y;
         int hite, wide, max_i;
         int ret_flag = 0;
         void *text_buf;
         int index = 1;

     gettextsettings(&oldtext);
         setusercharsize(1, 1, 7, 8);
         settextstyle(SMALL_FONT, HORIZ_DIR, USER_CHAR_SIZE);
         hite = textheight("H");
         wide = textwidth("H");

         text_buf = malloc(hite*320);

         /* save the screen */

         scr_size[0] = imagesize(0, 0, maxx, ((maxy+1)/2)-1);
     scr_buffer[0] = malloc(scr_size[0]);
     if(scr_buffer[0] == NULL) {
                 free(scr_buffer[0]);
             return TRUE;
         }
         getimage(0, 0, maxx, ((maxy+1)/2)-1, scr_buffer[0]);

         scr_size[1] = imagesize(0, (maxy+1)/2, maxx, maxy);
     scr_buffer[1] = malloc(scr_size[1]);
     if(scr_buffer[1] == NULL) {
                 free(scr_buffer[0]);
                 free(scr_buffer[1]);
                 return TRUE;
         }
         getimage(0, (maxy+1)/2, maxx, maxy, scr_buffer[1]);

         setbkcolor(BLACK);
         setcolor(YELLOW);
         clearviewport();

         for(index = 1; index < 25; index++) {
                 gprintf(5, i, "%d ",index);
                 setlinestyle(style[index].type, style[index].pattern, width);
                 line(5*wide, i+4, 300, i+4);
                 i += hite;
         }

         /* indicate center line */

         outtextxy(310, (hite*2)+ 8, "C");
         outtextxy(313, (hite*2)+12, "L");

         max_i = (i/hite)-2;
         i = 300;
         outtextxy(170, i, "           Point to style with arrow keys");
         i += hite+4;
         outtextxy(170, i, "           Hit <ESC> to select and return");

         i = 0;
         getimage(0, (i*hite)+11, (wide*3)+7, ((i+1)*hite)+11, text_buf);
         putimage(0, (i*hite)+11, text_buf, NOT_PUT);

         while(!ret_flag) {
                 if(bioskey(1)) {
                         key.i = bioskey(0);
                         if(key.c[0] == 0x1b) {
                                 ret_flag = 1;
                                 setlinestyle(style[i+1].type, style[i+1].patt
                         } else {

                                 /* only use the cursor --- not the mouse  */

                                 if(!key.c[0]) {
                          if(key.c[1] == 72) {                /* up  */
                                                 getimage(0, (i*hite)+11, (wid
                                                 putimage(0, (i*hite)+11, text
                                                 i -= 1;
                                                 if(i < 0) i = 0;
                                                 getimage(0, (i*hite)+11, (wid
                                                 putimage(0, (i*hite)+11, text
                                         }
                          if(key.c[1] == 80) {                /* down  */
                                                 getimage(0, (i*hite)+11, (wid
                                                 putimage(0, (i*hite)+11, text
                                                 i += 1;
                                                 if(i >= max_i) i = max_i;
                                                 getimage(0, (i*hite)+11, (wid
                                                 putimage(0, (i*hite)+11, text
                                         }

                                 }
                         }
                 }

         }
         setbkcolor(bkcolor);
         clearviewport();
         setcolor(cc);
         settextjustify(oldtext.horiz, oldtext.vert);
         settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);

         /* retun the original picture, and free the buffers  */

         putimage(0, 0, scr_buffer[0], COPY_PUT);
         putimage(0, (maxy+1)/2, scr_buffer[1], COPY_PUT);
          free(scr_buffer[0]);
         free(scr_buffer[1]);
          free(text_buf);

         return FALSE;
 }



 LTOA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\LTOA.C

 char        _numstr[] = "0123456789ABCDEF";

 char *ultoa(n, buffer, radix)
 register unsigned long n;
 register char *buffer;
 register int radix;
 {
         register char *p = buffer;
         char *strrev();

         do {
                 *p++ = _numstr[n % radix];        /* grab each digit */
         } while((n /= radix) > 0);
         *p = '\0';
         return(strrev(buffer));                        /* reverse and return
 }

 char *ltoa(n, buffer, radix)
 register long n;
 register char *buffer;
 int radix;
 {
         register char *p = buffer;

         if (n < 0) {
                 *p++ = '-';
                 n = -n;
         }
         ultoa(n, p, radix);
         return(buffer);
 }

 char *itoa(n, buffer, radix)
 int n;
 char *buffer;
 int radix;
 {
         char *ltoa();

         return(ltoa(((long) n), buffer, radix));
 }


 LTOA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\LTOA.C

 /* 1.0  05-07-85                                                (ltoa.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  *
  *        These functions are modified versions of itoa() found in Kernighan
  *        and Ritchie, page 60, with modifications of exercises 3-3 and 3-5,
  *        for use with the long data type.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"

 /************************************************************************/
         STRING
 ltoa(s, n, w)

 /*----------------------------------------------------------------------*/
 STRING s;
 long n;
 {
         STRING ltoab();

         return ltoab(s, n, w, 10);
 }
 /*\p*********************************************************************/
         STRING
 ltoab(s, n, w, b)        /* convert n to a minimum of |w| ascii characters,
                            base b, and put in s.  Use 0-fill if w < 0.
                            Return pointer to s.
 /*----------------------------------------------------------------------*/
 STRING s;
 long n;
 {
         LOCAL char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
         int i, j;
         BOOL sign;
         char c, fill;

         if (n < 0L)
         {        n = -n;
                 sign = TRUE;
         }
         else
                 sign = FALSE;
         if (w < 0)
         {        fill = '0';
                 w = -w;
         }
         else
                 fill = ' ';
         i = 0;
         do                        /* generate digits in reverse order:
                 s[i++] = digits[(int)(n % b)];
         while (n /= b);
         if (sign)                        /* put the sign into the string.*/
                 s[j = i++] = '-';
         else
                 j = i - 1;
         while (i < w)                        /* expand to proper width.
                 s[i++] = fill;        /* i is just beyond last filled postion
         if (--i ISNT j AND sign AND fill IS '0')
         {        s[i] = s[j];                /* get the sign.
                 s[j] = fill;                /* fill in over it
         }
         s[++i] = NULL;                        /* add null terminator        *
         for (i--, j = 0; j < i; j++, i--) /*  now reverse chars */
         {        c = s[j];
                 s[j] = s[i];
                 s[i] = c;
         }
         return s;
 }


 LT_298.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\LT_298.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[0]<2980)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 LT_301.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\LT_301.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[0]<=3010)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 LU.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LU.C

 #include <stdio.h>
 #include <ctype.h>

 char *sbrk();
 char *getmem();

 /*
         T. Jennings 13 Jan 84


         LU Library Utility for all MSDOS and PC DOS machines. Can be used
 to pack multiple files into a single LBR file for modem transfers, extract,
 delete or update files within an LBR file, and reorganize one.

         NOTE: Reorganizing is desireable after deleting, adding, or updating
 a file in the library. This due to the way LBR files are organized; deleted
 files dont remove the data, and new files are added to the end. The LBR will
 become much more compact after a Reorganization.

 */

 ACTIVE 0        /* active, non-deleted file, */
 UNUSED 0xff        /* never used slot, */
 DELETED 0xfe        /* deleted file slot, */

 MAXNAMES 20        /* maximum number of names in command line, */
 MAXFILES 256        /* max files per LBR file, */

 char names[30][MAXNAMES];/* list of names from command line, */
 int num_names;                /* number of names in above list, */

 /* Fix some annoyances in the Lattice Library. */

 long lseek();                        /* not an annoyance, */
 tell(f) lseek(f,0L,1)        /* wierd */
 seek lseek                /* wrong name, */

 /* This is the structure of the LBR file directory. One per slot.
 THIS MUST BE COMPILED ON LATTICE WITH THE -B OPTION!!!! */

 struct _ludir {
         char stat;        /* file status, */
         char name[11];        /* FCB type filename, */
         unsigned off;        /* offset to data, (sectors) */
         unsigned len;        /* length (sectors) of data, */
         int fill[8];        /* fill out to 32 bytes */
 } ludir; /* (dummy ludir so we can sizeof() it) */

 struct _ludir ldir[MAXFILES];
 int num_slots;                /* number of slots in LBR file, */

 char lbrname[14];        /* LBR file name, */
 int lbr;                /* LBR file handle, */
 char *buf;                /* buffer from DOS, */
 int bufsize;                /* size of buffer, */

 main(argc,argv)
 int argc;
 char *argv[];
 {
 int i;
 char command;

         ++argv; --argc;
         if (argc < 2) {

                 printf("LU -- T. Jennings 15 Jan 84\n");
                 printf("  LU <cmd> lbrfile file file file ...   Where <cmd> i
                 printf("\tT List of files in LBR file,\n");
                 printf("\tL Same as T,\n");
                 printf("\tA Extract all files from the LBR file,\n");
                 printf("\tE Extract file(s) from LBR file,\n");
                 printf("\tU Add to or create LBR file,\n");
                 printf("\tD Delete a file from LBR file,\n");
                 printf("\tR Reorganize the LBR file.\n");
                 exit();
         }
         command= *argv[0];                /* get command char, */
         strcpy(lbrname,argv[1]);        /* blindly get LBR name, */
         for (i= 0; i < argc - 2; i++) {
                 strcpy(names[i],argv[i + 2]);
                 stoupper(names[i]);
         }
         num_names= i;

         allmem();                        /* find largest area to allocate */
         bufsize= sizmem() - (MAXFILES * sizeof(ludir)) - 2000;
         if (bufsize < 512) {
                 printf("Not enough memory\n");
                 exit();
         }
         buf = getmem(bufsize);

         switch (tolower(command)) {
                 case 'a':
                         unpack();
                         break;
                 case 't':
                 case 'l':
                         list();
                         break;
                 case 'e':
                         extract();
                         break;
                 case 'u':
                         update();
                         break;
                 case 'd':
                         delete();
                         break;
                 case 'r':
                         reorg();
                         break;
                 default:
                         printf("Not a command.\n");
                         break;
         }
 }
 /* Update: add or change a file. If the library file does not exist, then
 create it and ask for the number of slots. Delete any file of the same
 name first, then add it in. */

 update() {

 int i;

         if (get_directory() == -1) {                /* open or create, */
                 if (new_directory() == -1) {
                         printf("Error: cant create new directory\n");
                         return;                        /* error! */
                 }
         }
         for (i= 0; i < num_names; i++) {        /* add each file, */
                 if (find(names[i]) != -1) printf("Updating existing file %s\n
                 else printf("Adding new file %s\n",names[i]);
                 kill(names[i]);                        /* delete first, */
                 if (add_file(names[i]) == 0)        /* add in, if error, */
                         break;
         }
         put_directory();                        /* close LBR file, */
 }
 /* Delete all the specified names from the directory. */

 delete() {

 int i;
         if (get_directory() == -1) {
                 printf("Error: LBR file not found\n");
                 return;
         }
         for (i= 0; i < num_names; i++) {
                 if (find(names[i]) != -1)
                         printf("Deleting %s\n",names[i]);
                 else printf("%s not in library\n",names[i]);
                 kill(names[i]);
         }
         put_directory();
 }

 /* List all the files in the LBR file. */

 list() {

 int i;
 long size;
 char name[14];
 int active,deleted,empty;

         size= 0L; active= deleted= empty= 0;

         if (get_directory() == -1) {
                 printf("Error: LBR file not found\n");
                 return;
         }
         for (i= 0; i < num_slots; i++) {
                 if (ldir[i].stat == ACTIVE) {
                         cvt_from_fcb(ldir[i].name,name);
                         printf("%-16s %8lu %8u\n",name,
                           (long)ldir[i].len * 128L,ldir[i].off);
                         size+= (long)ldir[i].len * 128L;
                         ++active;
                 }
                 if (ldir[i].stat == DELETED) ++deleted;
                 if (ldir[i].stat == UNUSED) ++empty;
         }
         printf("%-16s %8lu total bytes\n","",size);
         printf("%u active files, %u deleted files, %u empty slots.\n",
                 active,deleted,empty);
 }

 /* Unpack all files from the library. */

 unpack() {

 int i;
 int slot;
 long pos,size;
 unsigned count;
 int file;
 char name[14];

         if (get_directory() == -1) {
                 printf("Error: LBR file not found\n");
                 return;
         }
         for (slot= 1; slot < num_slots; slot++) {
                 if (ldir[slot].stat == ACTIVE) {
                         cvt_from_fcb(ldir[slot].name,name);
                         printf("Extracting %s\n",name);
                         file= creat(name,0x8001);        /* make new file, */
                         if (file == -1) {                /* check error, */
                                 printf("Error: cant create %s\n",name);
                                 break;
                         }
                         pos= (long)ldir[slot].off * 128L;        /* find offs
                         size= (long)ldir[slot].len * 128L;        /* and file
                         seek(lbr,pos,0);                /* go there, */
                         while (size > 0L) {                /* copy out data,
                                 count= (size > bufsize ? bufsize : size);
                                 read(lbr,buf,count);        /* read data, */
                                 write(file,buf,count);        /* write it, */
                                 size-= count;                /* update count,
                         }
                         close(file);
                 }
         }
         close(lbr);
 }
 /* Extract all specified files. */

 extract() {

 int i;
 int slot;
 long pos,size;
 unsigned count;
 int file;

         if (get_directory() == -1) {
                 printf("Error: LBR file not found\n");
                 return;
         }
         for (i= 0; i < num_names; i++) {
                 slot= find(names[i]);
                 if (slot != -1) {
                         printf("Extracting %s\n",names[i]);
                         file= creat(names[i],0x8001);        /* make new file
                         if (file == -1) {                /* check error, */
                                 printf("Error: cant create %s\n",names[i]);
                                 break;
                         }
                         pos= (long)ldir[slot].off * 128L;        /* find offs
                         size= (long)ldir[slot].len * 128L;        /* and file
                         seek(lbr,pos,0);                /* go there, */
                         while (size > 0L) {                /* copy out data,
                                 count= (size > bufsize ? bufsize : size);
                                 read(lbr,buf,count);        /* read data, */
                                 write(file,buf,count);        /* write it, */
                                 size-= count;                /* update count,
                         }
                         close(file);
                 } else printf("%s not in library\n",names[i]);
         }
         close(lbr);
 }

 /* Find the specified file in the directory, return its slot number
 or -1 if not found. */

 find(name)
 char *name;
 {
 int i;
 char fname[14];

         for (i= 0; i < num_slots; i++) {                /* search all slots,
                 cvt_from_fcb(ldir[i].name,fname);        /* convert for compa
                 if (strcmp(name,fname) == 0)                /* if found, */
                         return(i);                        /* return slot numb
         }
         return(-1);                                        /* not found, */
 }
 /* Delete the specified file. No error return. */

 kill(name)
 char *name;
 {
 int slot;

         slot= find(name);                                /* find it, */
         if (slot != -1) ldir[slot].stat= DELETED;        /* delete it, */
 }

 /* Find a free slot in the directory. Return -1 if none. */

 free_slot() {

 int i;

         for (i= 0; i < num_slots; i++) {
                 if (ldir[i].stat == UNUSED) return(i);
                 if (ldir[i].stat == DELETED) return(i);
         }
         return(-1);
 }
 /* Add a file to the library. All files get added to the end. Returns 0
 if couldnt add; either file not found or no room. No check is made that the
 file might exist already, etc. */

 add_file(name)
 char *name;
 {

 int i,file,slot;
 unsigned count;
 long size,pos;

         slot= free_slot();                        /* find a free slot, */
         if (slot == -1) {                        /* if none, return 0 */
                 printf("No room in directory\n");
                 return(0);
         }
         file= open(name,0x8000);                /* get file, */
         if (file == -1) {
                 printf("Cant find %s\n",name);
                 return(0);
         }

         seek(lbr,0L,2);                                /* seek to end of file
         pos= tell(lbr);                                /* save position, */
         size= 0L;                                /* init file size, */
         while (count= read(file,buf,bufsize)) {        /* copy data, */
                 size+= count;                        /* get file size, */
                 write(lbr,buf,count);                /* write to library, */
         }

         for (i= 0; i < 128; i++)
                 buf[i]= 0x1a;                        /* clear dummy data, */
         count= 128 - (size % 128L);                /* make LBR file a */
         if (count > 0) write(lbr,buf,count);        /* multiple of 128, */
         cvt_to_fcb(name,ldir[slot].name);        /* install name, */
         ldir[slot].off= pos / 128L;                /* position, (sectors) */
         ldir[slot].len= (size + 127L) / 128L;        /* size, (sectors) */
         ldir[slot].stat= ACTIVE;

         close(file);
         return(1);
 }
 /* Reorganize an LBR file. This consists of creating a new LBR, and copying
 all entries to it. This removes any space comsumed by deleted files, etc. */

 reorg() {

 struct _ludir odir[MAXFILES];
 int old,i,n,count;
 long size,pos;
 char oldname[14],tempname[14],buff[512];
 int old_slots,slot;
 char *p,*s;

         if (get_directory() == -1) {
                 printf("Error: cant find library\n");
                 return;
         }
         p= (char *)&ldir[0];                /* copy old directory, */
         s= (char *)&odir[0];
         for (i= (num_slots * sizeof(ludir)); i; i--)
                 *s++= *p++;
         old= lbr;                        /* old LBR handle, */
         old_slots= num_slots;
         strcpy(oldname,lbrname);        /* old LBR name, */
         printf("Old library has %u slots\n",old_slots);
         strcpy(lbrname,"lu$$$$$$.tmp");        /* make temp file, */
         new_directory();                /* create new one, */

         slot= 0;
         for (i= 1; i < old_slots; i++) {
                 if (odir[i].stat == ACTIVE) {
                         if (++slot >= num_slots) {
                                 printf("Not enough room in new directory\n");
                                 break;
                         }
                         cvt_from_fcb(odir[i].name,tempname);
                         printf("Copying %s\n",tempname);
                         seek(old,(long)odir[i].off * 128L,0);        /* seek
                         seek(lbr,0L,2);                                /* EOF
                         pos= tell(lbr);                                /* cur
                         size= odir[i].len * 128L;
                         while (size > 0L) {
                                 count= (size > sizeof(buff) ? sizeof(buff) :
                                 read(old,buff,count);
                                 write(lbr,buff,count);
                                 size-= count;
                         }
                         ldir[slot].stat= ACTIVE;                /* update new
                         ldir[slot].len= odir[i].len;                /* direct
                         cvt_to_fcb(tempname,ldir[slot].name);
                         ldir[slot].off= (pos + 127L) / 128L;
                 }
         }
         put_directory();                /* close new directory, */
         close(old);                        /* close old, */
         unlink(oldname);                /* delete old one, */
         link("lu$$$$$$$.tmp",oldname);        /* back to original name */
 }
 /* Read the directory. */

 get_directory()
 {
 unsigned size;
 int i;

         lbr= open(lbrname,0x8002);
         if (lbr == -1) return(-1);

         if (read(lbr,&ldir[0],sizeof(ludir)) != sizeof(ludir))
                 return(-1);

         num_slots= (ldir[0].len * 128) / sizeof(ludir);
         size= (num_slots - 1) * sizeof(ludir);        /* already read one, */
         if (num_slots > MAXFILES) {
                 printf("Directory error: %s is bad or not an LBR file\n",lbrn
                 return(-1);
         }
         if (read(lbr,&ldir[1],size) != size) {
                 printf("Directory error: is %s an LBR file?\n",lbrname);
                 return(-1);
         }
         return(1);
 }

 /* Create a new directory. When we request the number of slots, always round
 up to the nearest 128 bytes, i.e. 4 slots. Since everything is a multiple
 of 128 anyways, all were doing is making otherwose wasted space available. */

 new_directory() {

 int i;

         num_slots= 0;
         do {        cprintf("Number of slots (4 - 256, 0 to abort): ");
                 getstring(buf);
                 cprintf("\r\n");
                 num_slots= atoi(buf);
         } while (num_slots > 256);
         if (num_slots == 0) return(-1);
         num_slots+= num_slots % (128 / sizeof(ludir));

         lbr= creat(lbrname,0x8002);
         if (lbr == -1) return(-1);
         cvt_to_fcb(".",ldir[0].name);
         ldir[0].len= (num_slots * sizeof(ludir)) / 128;
         ldir[0].stat= ACTIVE;
         for (i= 1; i < MAXFILES; i++) {        /* clear ALL slots, */
                 cvt_to_fcb(".",ldir[i].name);
                 ldir[i].len= 0;
                 ldir[i].off= 0;
                 ldir[i].stat= UNUSED;
         }
         put_directory();                /* write to disk, */
         return(get_directory());        /* read in new directory, */
 }

 /* Write the directory out.  */

 put_directory() {

 int count;

         count= ldir[0].len * 128;
         seek(lbr,0L,0);                        /* to start of file, */
         if (write(lbr,&ldir[0],count) != count)
                 printf("LBR close error: library may be trashed\n");
         close(lbr);
 }


 /* Convert a normal asciz string to MSDOS/CPM FCB format. Make the filename
 portion 8 characters, extention 3 maximum. */

 cvt_to_fcb(inname,outname)
 char *inname;
 char outname[];
 {
 char c;
 int i;

         if (inname[1] == ':')                         /* if a drive spec, */
                 inname= &inname[2];                /* lop it off, */

         for (i= 0; i < 11; i++)
                 outname[i]= ' ';                /* clear out name, */
         outname[i]= '\0';                        /* null terminate, */
         for (i= 0; i < 11; i++) {
                 if (*inname == '\0')                /* if null, */
                         outname[i]= ' ';        /* pad with blanks, */
                 else if (*inname == '.') {        /* if a dot, */
                         ++inname;                /* skip it, */
                         i= 7;                        /* skip to extention, */
                 } else {
                         outname[i]= toupper(*inname);
                         ++inname;
                 }
         }
         return;
 }
 /* Convert a CP/M like filename to a normal ASCIZ name. Filter out characters
 undersireable on MSDOS. */

 cvt_from_fcb(inname,outname)
 char *inname,*outname;
 {
 int i;
 char c;

         for (i= 8; i != 0; i--) {                /* do name portion, */
                 c= toupper(*inname);
                 ++inname;
                 if (c != ' ')                         /* if not space, */
                         *outname++= c;                /* set it, */
         }                                        /* do all 8 chars, */

         if (*inname != ' ') {                        /* if there is an extent
                 *outname++= '.';                /* add the dot, */
                 for (i= 3; i != 0; i--) {        /* do extention, */
                         c= toupper(*inname);
                         ++inname;
                         if (c == ' ')
                                 break;
                         *outname++= c;
                 }
         }
         *outname= '\0';                                /* terminate it, */
         return;
 }
 /* Get an input string; return NULL if error or empty line. Provide the
 usual minimum editing capabilities.  */

 getstring(string)
 char string[];
 {
 int count;
 char c;
 char *p;
 int pi;
         count= 0;

         while (1) {

                 c= getch();                        /* get a character, */
                 switch (c) {
                 case 0x0d:                        /* process it, */
                 case 0x0a:
                 case 0x1b:
                         string[count]= 0x00;        /* terminate string, */
                         return(count);                /* return string length
                         break;

                 case 0x08:
                 case 0x7f:                        /* delete character */
                 case 0x13:
                         if (count) {
                                 --count;        /* one less char, */
                                 putch('\010');
                                 putch(' ');
                                 putch('\010');
                         }
                         break;
                         case 0x18:
                 case 0x15:                        /* delete line */
                 case 0x19:
                 case 0x03:
                         while (count) {
                                 --count;
                                 putch('\010');
                                 putch(' ');
                                 putch('\010');
                         }
                         break;
                 case 0x04:                        /* retype character, */
                         if (string[count])
                                 putch(string[count++]);
                         break;
                 case 0x12:                        /* retype line, */
                         while (string[count]) {
                                 putch(string[count++]);
                         }
                         break;

                 default:                        /* insert character */
                         if ( (c > 0x1f) && (c < 0x7f) && (count < 80) ) {
                                 string[count++] =toupper(c);
                                 string[count]= 0x00;
                                 putch(c);
                         } else
                                 putch(0x07);
                         break;
                 }
         }
 }
 /* ATOI() function missing from Lattice C. From Kernighan and Richie. */

 atoi(s)
 char s[];
 {
 int i,n;

         n= 0;
         for (i= 0; s[i] >= '0' && s[i] <= '9'; ++i)
                 n= 10*n + s[i]-'0';
         return(n);
 }
 /* Convert a string to all upper case. */

 stoupper(s)
 char *s;
 {
         while (*s) {
                 *s= toupper(*s);
                 ++s;
         }
 }
 /* Missing Lattice C function: File rename

         error= link(oldname,newname); */

 link(old,new)
 char *old,*new;
 {
 char fcb[36];
 int i;
 char *p;

         for (i= 0; i < sizeof(fcb); i++)        /* clear it out first, */
                 fcb[i]= '\0';

         cvt_to_fcb(old,&fcb[1]);                /* first name, */
         cvt_to_fcb(new,&fcb[17]);                /* new name, */
         return(bdos(23,&fcb) == 0xff);                /* do it. */
 }



 LUCIFER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CIPHER2\LUCIFER.C

 /***************************** lucifer **************************
  * LUCIFER: encrypt/decrypt bytes using IBM's LUCIFER algorithm.
  * Programmed by R.W.Outerbridge
  *
  * Usage: lucifer (+|-)([ecb]|<cbc|cks>) key1 <ivec>
  *                EN/DE    MODES         KEYS
  *
  *      + :     ENcrypt (default if MODE specified)
  *      - :     DEcrypt (presumes encrypted input)
  *
  *      Modes of Operation (choose ONE):
  *
  *      ecb : (default) Electronic Code Book.  Only uses one key.
  *              If simply "+" or "-" is specified, ecb is used.
  *      cbc : Cipher Block Chaining.  Uses two keys.
  *      cks : ChecKSum.  Generates a 128-bit checksum using two keys.
  *
  *      Both keys may be as long as you wish.  The practical limit
  *      on keylength is the size of your system's argument buffer.
  *      WARNING: on some machines all arguments become CAPITALS.
  *      WARNING: non-ascii machines MAY get different results.
  *
  *      Any character may be used in keys - depending on the O/S -
  *      except ASCII NULL (0x00).  The one-letter key '#', when used
  *      for "key1", will cause lucifer to use a preset default key
  *      (for verification and testing).  Failing to specify "ivec", if
  *      required, will result in "key1" being used for both keys.  It
  *      is an error to omit "key1".  There is no provision for giving
  *      arbitrary, absolute, bit-valued keys.
  *
  *      As painful as they are to use, long keys are MUCH safer;
  *      think up nonsense phrases you can safely remember.
  *
  */

 #include <stdio.h>
 #define toascii(a)      ((a)&0177)
 #define EN      0
 #define DE      1
 #define CKS     2
 #define MODS    3
 typedef char    BYTE;   /* BYTE = (VAX) ? int : char;   */

 /* cryptographic declarations   */
 void copy16(), xor16(), getkey(), loadkey(), lucifer();
 BYTE Block[16], Link[16], Temp[16], IV[16];
 BYTE DFLTKY[16] = { 1,35,69,103,137,171,205,239,254,220,186,152,118,84,50,16
         /* DO NOT ALTER! => 0x0123456789abcdeffedcba9876543210 <=       */

 /* I/O declarations     */
 void ruderr(), put16(), vraiput(), initio();
 int IOedf, End, Once;
 BYTE Last[16];

 int Ecb(), Cbc(), Cks();
 struct modes {
         char *name;
         int (*func)();
         };
 struct modes ModsOp[MODS] = {   /* CAPS for CP/M - sorry!       */
         { "ECB", Ecb },
         { "CBC", Cbc },
         { "CKS", Cks }  };

 main(argc, argv)
 int argc;
 char **argv;
         {
         int (*xeqtr)();
         int step, ende, edio, ok, i;
         BYTE kv[16];

         argv++; argc--;
         if(argc > 3 || argc < 2) ruderr();

         for(step=0; argc > 0; step++) {
                 switch(step) {
                 case 0: /* set en/de and/or default mode        */
                         if(*argv[0] == '+' || *argv[0] == '-') {
                                 ende = (*argv[0] == '+') ? EN : DE;
                                 *argv[0]++ = NULL;
                                 if(*argv[0] == NULL) {
                                         xeqtr = Ecb;    /* default mode */
                                         edio = ende;
                                         argv++; argc--;
                                         break;
                                         }
                                 }
                         else ende = EN;

                         for(i=ok=0; i < MODS && !ok; i++) {
                                 if(strcmp(argv[0], ModsOp[i].name) == 0) {
                                         xeqtr = ModsOp[i].func;
                                         ok = 1;
                                         }
                                 }
                         if(!ok) {
                                 fprintf(stderr,
                                 "Lucifer: unknown mode >%s<.\n", argv[0]);
                                 ruderr();
                                 }
                         while(*argv[0]) *argv[0]++ = NULL;
                         argv++; argc--;

                         /* set appropriate IO modes     */
                         if(xeqtr == Cks) edio = CKS;
                         else edio = ende;

                 /* falling through....  */
                 case 1: /* get the key and IV, if needed and present    */
                         if(strcmp(argv[0], "#") == 0) copy16(DFLTKY, kv);
                         else getkey(argv[0], kv);
                         argv++; argc--;

                         /* if nothing left, but an IV needed, use the key
                         if(argc == 0) {
                                 if(xeqtr != Ecb) copy16(kv, IV);
                                 break;
                                 }
                         else if(xeqtr == Ecb) {
                                 fprintf(stderr, "Lucifer: ivec ignored.\n");
                                 while(*argv[0]) *argv[0]++ = NULL;
                                 argv++; argc--;
                                 break;
                                 }

                         else getkey(argv[0], IV);
                         argv++; argc--;
                         break;

                 default:
                         fprintf(stderr, "Lucifer: Programming error!\n");
                         exit(1);
                         break;
                         }       /* switch       */
                 }       /* argument parsing     */

         initio(edio);
         loadkey(kv, ende);
         (*xeqtr)(ende); /* ta-da!  Take it away xeqtr!  */
         exit(0);
         }       /* end of main  */

 void ruderr() {
         fprintf(stderr,
                 "Usage: lucifer (+|-)([ecb]|<cbc|cks>) key1 <ivec>\n");
         exit(1);
         }

 Cbc(e_d)        /* Cipher Block Chaining                */
 int e_d;        /* Ciphertext errors are self-healing.  */
         {
         copy16(IV, Link);
         while(get16(Block) != EOF) {
                 if(e_d == DE) {
                         copy16(Block, Temp);
                         lucifer(Block);
                         xor16(Block, Link);
                         copy16(Temp, Link);
                         }
                 else {
                         xor16(Block, Link);
                         lucifer(Block);
                         copy16(Block, Link);
                         }
                 put16(Block);
                 }
         return;
         }

 Cks(dummy)      /* CBC authentication checksum generator        */
 int dummy;      /* The banks use this for verifications.        */
         {
         int i, j, k;
         long count = 0L;
         copy16(IV, Link);
         while(get16(Block) != EOF) {
                 xor16(Block, Link);
                 lucifer(Block);
                 copy16(Block, Link);
                 count++;
                 }
         fprintf(stdout, ": %0ld bytes\t: ", count<<4);
         for(i=j=0; i < 4; i++) {
                 for(k=0; k < 4; k++, j++)
                         fprintf(stdout, "%02x", Link[j]&0377);
                 putc(' ', stdout);
                 }
         fprintf(stdout, ":\n");
         return;
         }

 Ecb(dummy)      /* Electronic Code Book : simple substitution   */
 int dummy;      /* Yawn.  For static data and random access.    */
         {
         while(get16(Block) != EOF) {
                 lucifer(Block);
                 put16(Block);
                 }
         return;
         }

 void copy16(from, to)
 register BYTE *from, *to;
         {
         register BYTE *ep;
         ep = &to[16];
         while(to < ep) *to++ = *from++;
         return;
         }

 void xor16(to, with)
 register BYTE *to, *with;
         {
         register BYTE *ep;
         ep = &to[16];
         while(to < ep) *to++ ^= *with++;
         return;
         }

 void put16(block)
 register BYTE *block;
         {
         if(IOedf == DE) copy16(block, Last);
         else vraiput(block, &block[16]);
         return;
         }

 get16(input)
 register BYTE *input;
         {
         register int i, j;
         if(End == 1) return(EOF);       /* no more input        */

         for(i=0; i < 16 && ((j = getc(stdin)) != EOF); i++) *input++ = j;

         if(IOedf == DE) {       /* DECRYPTION   */
                 /* complete block?  pending output?     */
                 if(i == 16 && (Once > 0)) vraiput(Last, &Last[16]);
                 else if(j == EOF) {
                         End = 1;
                         if(Once > 0) {
                                 /* incomplete block means no nulls      */
                                 if(i != 0) i = 0;
                                 else {
                                         i = Last[15]&0377;
                                         if(i > 16) i = 0;       /* huh? */
                                         }
                                 vraiput(Last, &Last[16-i]);
                                 }
                         return(EOF);
                         }
                 }
         else if(j == EOF) {     /* ENCRYPTION   */
                 End = 1;
                 if(i == 0 && (IOedf == EN || (Once > 0))) {
                         /* if no padding to do, print a kludge  */
                         if(IOedf == EN && (Once > 0)) putc('0', stdout);
                         return(EOF);
                         }
                 for(j=i; j < 15; j++) *input++ = NULL;
                 *input = 16-i;
                 }
         Once = 1;
         return(0);
         }

 void getkey(aptr, kptr)
 register char *aptr;
 register BYTE *kptr;
         {
         register BYTE *store;
         register int i, first;
         BYTE hold[16];
         first = 1;
         loadkey(DFLTKY, EN);
         copy16(DFLTKY, hold);
         while(*aptr || first) {
                 store = kptr;
                 for(i=0; i<16 && (*aptr != NULL); i++) {
                         *store++ = toascii(*aptr);
                         *aptr++ = NULL;
                         }
                 while(i++ < 16) *store++ = NULL;
                 xor16(kptr, hold);
                 lucifer(kptr);
                 copy16(kptr, hold);
                 first = 0;
                 }
         return;
         }

 void vraiput(cp, ep)
 register BYTE *cp, *ep;
         {
         while(cp < ep) putc((char)*cp++, stdout);
         return;
         }

 void initio(edf)
 int edf;
         {
         IOedf = edf;
         End = Once = 0;
         return;
         }

 /* LUCIFER is a cryptographic algorithm developed by IBM in the early
  *      seventies.  It was a predecessor of the DES, and is much simpler
  *      than that algorithm.  In particular, it has only two substitution
  *      boxes.  It does, however, use a 128 bit key and operates on
  *      sixteen byte data blocks...
  *
  *      This implementation of LUCIFER was crafted by Graven Cyphers at the
  *      University of Toronto, Canada, with programming assistance from
  *      Richard Outerbridge.  It is based on the FORTRAN routines which
  *      concluded Arthur Sorkin's article "LUCIFER: A Cryptographic Algorithm
  *      CRYPTOLOGIA, Volume 8, Number 1, January 1984, pp22-42.  The interest
  *      reader should refer to that article rather than this program for more
  *      details on LUCIFER.
  *
  *      These routines bear little resemblance to the actual LUCIFER algorith
  *      which has been severely twisted in the interests of speed.  They do
  *      perform the same transformations, and are believed to be UNIX portabl
  *      The package was developed for use on UNIX-like systems lacking crypto
  *      facilities.  They are not very fast, but the cipher is very strong.
  *      The routines in this file are suitable for use as a subroutine librar
  *      after the fashion of crypt(3).  When linked together with application
  *      routines they can also provide a high-level cryptographic system.
  *
  *      -DENHANCE : modify LUCIFER by changing the key schedule and performin
  *              an "autokeyed" encryption.  These may improve the algorithm.
  */

 #ifndef DE
 DE      1       /* for separate compilation     */
 #endif

 static BYTE Dps[64] = { /* Diffusion Pattern schedule   */
         4,16,32,2,1,8,64,128,   128,4,16,32,2,1,8,64,
         64,128,4,16,32,2,1,8,   8,64,128,4,16,32,2,1,
         1,8,64,128,4,16,32,2,   2,1,8,64,128,4,16,32,
         32,2,1,8,64,128,4,16,   16,32,2,1,8,64,128,4    };

 /* Precomputed S&P Boxes, Two Varieties */
 static BYTE TCB0[256] = {
         87, 21,117, 54, 23, 55, 20, 84,116,118, 22, 53, 85,119, 52, 86,
         223,157,253,190,159,191,156,220,252,254,158,189,221,255,188,222,
         207,141,237,174,143,175,140,204,236,238,142,173,205,239,172,206,
         211,145,241,178,147,179,144,208,240,242,146,177,209,243,176,210,
         215,149,245,182,151,183,148,212,244,246,150,181,213,247,180,214,
         95, 29,125, 62, 31, 63, 28, 92,124,126, 30, 61, 93,127, 60, 94,
         219,153,249,186,155,187,152,216,248,250,154,185,217,251,184,218,
         67,  1, 97, 34,  3, 35,  0, 64, 96, 98,  2, 33, 65, 99, 32, 66,
         195,129,225,162,131,163,128,192,224,226,130,161,193,227,160,194,
         199,133,229,166,135,167,132,196,228,230,134,165,197,231,164,198,
         203,137,233,170,139,171,136,200,232,234,138,169,201,235,168,202,
         75,  9,105, 42, 11, 43,  8, 72,104,106, 10, 41, 73,107, 40, 74,
         91, 25,121, 58, 27, 59, 24, 88,120,122, 26, 57, 89,123, 56, 90,
         71,  5,101, 38,  7, 39,  4, 68,100,102,  6, 37, 69,103, 36, 70,
         79, 13,109, 46, 15, 47, 12, 76,108,110, 14, 45, 77,111, 44, 78,
         83, 17,113, 50, 19, 51, 16, 80,112,114, 18, 49, 81,115, 48, 82 };

 static BYTE TCB1[256] = {
         87,223,207,211,215, 95,219, 67,195,199,203, 75, 91, 71, 79, 83,
         21,157,141,145,149, 29,153,  1,129,133,137,  9, 25,  5, 13, 17,
         117,253,237,241,245,125,249, 97,225,229,233,105,121,101,109,113,
         54,190,174,178,182, 62,186, 34,162,166,170, 42, 58, 38, 46, 50,
         23,159,143,147,151, 31,155,  3,131,135,139, 11, 27,  7, 15, 19,
         55,191,175,179,183, 63,187, 35,163,167,171, 43, 59, 39, 47, 51,
         20,156,140,144,148, 28,152,  0,128,132,136,  8, 24,  4, 12, 16,
         84,220,204,208,212, 92,216, 64,192,196,200, 72, 88, 68, 76, 80,
         116,252,236,240,244,124,248, 96,224,228,232,104,120,100,108,112,
         118,254,238,242,246,126,250, 98,226,230,234,106,122,102,110,114,
         22,158,142,146,150, 30,154,  2,130,134,138, 10, 26,  6, 14, 18,
         53,189,173,177,181, 61,185, 33,161,165,169, 41, 57, 37, 45, 49,
         85,221,205,209,213, 93,217, 65,193,197,201, 73, 89, 69, 77, 81,
         119,255,239,243,247,127,251, 99,227,231,235,107,123,103,111,115,
         52,188,172,176,180, 60,184, 32,160,164,168, 40, 56, 36, 44, 48,
         86,222,206,210,214, 94,218, 66,194,198,202, 74, 90, 70, 78, 82 };

 static BYTE Key[16], Pkey[128];
 static int P[8] = { 3,5,0,4,2,1,7,6 };
 static int Smask[16] = { 128,64,32,16,8,4,2,1 };

 void lucifer(bytes)
 BYTE *bytes;    /* points to a 16-byte array    */
         {
         register BYTE *cp, *sp, *dp;
         register int val, *sbs, tcb, j, i;
         BYTE *h0, *h1, *kc, *ks;

         h0 = bytes;     /* the "lower" half     */
         h1 = &bytes[8]; /* the "upper" half     */
         kc = Pkey;
         ks = Key;

         for(i=0; i<16; i++) {
                 tcb = *ks++;
                 sbs = Smask;
                 dp = Dps;
                 sp = &h0[8];
 #ifdef ENHANCE
                 for(j=0, cp=h1; j<8; j++) tcb ^= *cp++;
 #endif
                 for(j=0; j<8; j++) {
                         if(tcb&*sbs++) val = TCB1[h1[j]&0377];
                         else val = TCB0[h1[j]&0377];
                         val ^= *kc++;
                         for(cp=h0; cp<sp;) *cp++ ^= (val&*dp++);
                         }

                 /* swap (virtual) halves        */
                 cp = h0;
                 h0 = h1;
                 h1 = cp;
                 }

         /* REALLY swap halves   */
         dp = bytes;
         cp = &bytes[8];
         for(sp=cp; dp<sp; dp++, cp++) {
                 val = *dp;
                 *dp = *cp;
                 *cp = val;
                 }
         return;
         }

 void loadkey(keystr, edf)       /* precomputes the key schedules        */
 BYTE *keystr;
 register int edf;
         {
         register BYTE *ep, *cp, *pp;
         register int kc, i, j;
         BYTE kk[16], pk[16];
         cp = kk;
         pp = pk;
         ep = &kk[16];
         while(cp < ep) {
                 *cp++ = *keystr;
                 for(*pp=i=0; i<8; i++)
                         if(*keystr&Smask[i]) *pp |= Smask[P[i]];
                 keystr++;
                 pp++;
                 }
         cp = Key;
         pp = Pkey;
         kc = (edf == DE) ? 8 : 0;
         for(i=0; i<16; i++) {
                 if(edf == DE) kc = (++kc)&017;
 #ifdef ENHANCE
                 *cp++ = kk[( (kc == 0) ? 15 : (kc - 1) )];
 #else
                 *cp++ = kk[kc];
 #endif
                 for(j=0; j<8; j++) {
                         *pp++ = pk[kc];
                         if(j<7 || (edf == DE)) kc = (++kc)&017;
                         }
                 }
         return;
         }

 /* lucifer cks # < /dev/null
  *      : 16 bytes      : 32186510 6acf6094 87953eba 196f5a75 :
  *      (-DENHANCE)     : 378cfd5b bd54a07b 28513809 624e6071 :
  *                      (rwo/8412.03.18:10/V5.0)                */
 /************************ lucifer *******************************/


 LUCIFER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LUCIFER.C

 /*"void~" will have to be #define'd int*/

 /***************************** lucifer **************************
  * LUCIFER: encrypt/decrypt bytes using IBM's LUCIFER algorithm.
  * Programmed by R.W.Outerbridge
  *
  * Usage: lucifer (+|-)([ecb]|<cbc|cks>) key1 <ivec>
  *                EN/DE    MODES         KEYS
  *
  *      + :     ENcrypt (default if MODE specified)
  *      - :     DEcrypt (presumes encrypted input)
  *
  *      Modes of Operation (choose ONE):
  *
  *      ecb : (default) Electronic Code Book.  Only uses one key.
  *              If simply "+" or "-" is specified, ecb is used.
  *      cbc : Cipher Block Chaining.  Uses two keys.
  *      cks : ChecKSum.  Generates a 128-bit checksum using two keys.
  *
  *      Both keys may be as long as you wish.  The practical limit
  *      on keylength is the size of your system's argument buffer.
  *      WARNING: on some machines all arguments become CAPITALS.
  *      WARNING: non-ascii machines MAY get different results.
  *
  *      Any character may be used in keys - depending on the O/S -
  *      except ASCII NULL (0x00).  The one-letter key '#', when used
  *      for "key1", will cause lucifer to use a preset default key
  *      (for verification and testing).  Failing to specify "ivec", if
  *      required, will result in "key1" being used for both keys.  It
  *      is an error to omit "key1".  There is no provision for giving
  *      arbitrary, absolute, bit-valued keys.
  *
  *      As painful as they are to use, long keys are MUCH safer;
  *      think up nonsense phrases you can safely remember.
  *
  */

 #include <stdio.h>
 #define toascii(a)      ((a)&0177)
 #define EN      0
 #define DE      1
 #define CKS     2
 #define MODS    3
 typedef char    BYTE;   /* BYTE = (VAX) ? int : char;   */

 /* cryptographic declarations   */
 void copy16(), xor16(), getkey(), loadkey(), lucifer();
 BYTE Block[16], Link[16], Temp[16], IV[16];
 BYTE DFLTKY[16] = { 1,35,69,103,137,171,205,239,254,220,186,152,118,84,50,16
         /* DO NOT ALTER! => 0x0123456789abcdeffedcba9876543210 <=       */

 /* I/O declarations     */
 void ruderr(), put16(), vraiput(), initio();
 int IOedf, End, Once;
 BYTE Last[16];

 int Ecb(), Cbc(), Cks();
 struct modes {
         char *name;
         int (*func)();
         };
 struct modes ModsOp[MODS] = {   /* CAPS for CP/M - sorry!       */
         { "ECB", Ecb },
         { "CBC", Cbc },
         { "CKS", Cks }  };

 main(argc, argv)
 int argc;
 char **argv;
         {
         int (*xeqtr)();
         int step, ende, edio, ok, i;
         BYTE kv[16];

         argv++; argc--;
         if(argc > 3 || argc < 2) ruderr();

         for(step=0; argc > 0; step++) {
                 switch(step) {
                 case 0: /* set en/de and/or default mode        */
                         if(*argv[0] == '+' || *argv[0] == '-') {
                                 ende = (*argv[0] == '+') ? EN : DE;
                                 *argv[0]++ = NULL;
                                 if(*argv[0] == NULL) {
                                         xeqtr = Ecb;    /* default mode */
                                         edio = ende;
                                         argv++; argc--;
                                         break;
                                         }
                                 }
                         else ende = EN;

                         for(i=ok=0; i < MODS && !ok; i++) {
                                 if(strcmp(argv[0], ModsOp[i].name) == 0) {
                                         xeqtr = ModsOp[i].func;
                                         ok = 1;
                                         }
                                 }
                         if(!ok) {
                                 fprintf(stderr,
                                 "Lucifer: unknown mode >%s<.\n", argv[0]);
                                 ruderr();
                                 }
                         while(*argv[0]) *argv[0]++ = NULL;
                         argv++; argc--;

                         /* set appropriate IO modes     */
                         if(xeqtr == Cks) edio = CKS;
                         else edio = ende;

                 /* falling through....  */
                 case 1: /* get the key and IV, if needed and present    */
                         if(strcmp(argv[0], "#") == 0) copy16(DFLTKY, kv);
                         else getkey(argv[0], kv);
                         argv++; argc--;

                         /* if nothing left, but an IV needed, use the key
                         if(argc == 0) {
                                 if(xeqtr != Ecb) copy16(kv, IV);
                                 break;
                                 }
                         else if(xeqtr == Ecb) {
                                 fprintf(stderr, "Lucifer: ivec ignored.\n");
                                 while(*argv[0]) *argv[0]++ = NULL;
                                 argv++; argc--;
                                 break;
                                 }

                         else getkey(argv[0], IV);
                         argv++; argc--;
                         break;

                 default:
                         fprintf(stderr, "Lucifer: Programming error!\n");
                         exit(1);
                         break;
                         }       /* switch       */
                 }       /* argument parsing     */

         initio(edio);
         loadkey(kv, ende);
         (*xeqtr)(ende); /* ta-da!  Take it away xeqtr!  */
         exit(0);
         }       /* end of main  */

 void ruderr() {
         fprintf(stderr,
                 "Usage: lucifer (+|-)([ecb]|<cbc|cks>) key1 <ivec>\n");
         exit(1);
         }

 Cbc(e_d)        /* Cipher Block Chaining                */
 int e_d;        /* Ciphertext errors are self-healing.  */
         {
         copy16(IV, Link);
         while(get16(Block) != EOF) {
                 if(e_d == DE) {
                         copy16(Block, Temp);
                         lucifer(Block);
                         xor16(Block, Link);
                         copy16(Temp, Link);
                         }
                 else {
                         xor16(Block, Link);
                         lucifer(Block);
                         copy16(Block, Link);
                         }
                 put16(Block);
                 }
         return;
         }

 Cks(dummy)      /* CBC authentication checksum generator        */
 int dummy;      /* The banks use this for verifications.        */
         {
         int i, j, k;
         long count = 0L;
         copy16(IV, Link);
         while(get16(Block) != EOF) {
                 xor16(Block, Link);
                 lucifer(Block);
                 copy16(Block, Link);
                 count++;
                 }
         fprintf(stdout, ": %0ld bytes\t: ", count<<4);
         for(i=j=0; i < 4; i++) {
                 for(k=0; k < 4; k++, j++)
                         fprintf(stdout, "%02x", Link[j]&0377);
                 putc(' ', stdout);
                 }
         fprintf(stdout, ":\n");
         return;
         }

 Ecb(dummy)      /* Electronic Code Book : simple substitution   */
 int dummy;      /* Yawn.  For static data and random access.    */
         {
         while(get16(Block) != EOF) {
                 lucifer(Block);
                 put16(Block);
                 }
         return;
         }

 void copy16(from, to)
 register BYTE *from, *to;
         {
         register BYTE *ep;
         ep = &to[16];
         while(to < ep) *to++ = *from++;
         return;
         }

 void xor16(to, with)
 register BYTE *to, *with;
         {
         register BYTE *ep;
         ep = &to[16];
         while(to < ep) *to++ ^= *with++;
         return;
         }

 void put16(block)
 register BYTE *block;
         {
         if(IOedf == DE) copy16(block, Last);
         else vraiput(block, &block[16]);
         return;
         }

 get16(input)
 register BYTE *input;
         {
         register int i, j;
         if(End == 1) return(EOF);       /* no more input        */

         for(i=0; i < 16 && ((j = getc(stdin)) != EOF); i++) *input++ = j;

         if(IOedf == DE) {       /* DECRYPTION   */
                 /* complete block?  pending output?     */
                 if(i == 16 && (Once > 0)) vraiput(Last, &Last[16]);
                 else if(j == EOF) {
                         End = 1;
                         if(Once > 0) {
                                 /* incomplete block means no nulls      */
                                 if(i != 0) i = 0;
                                 else {
                                         i = Last[15]&0377;
                                         if(i > 16) i = 0;       /* huh? */
                                         }
                                 vraiput(Last, &Last[16-i]);
                                 }
                         return(EOF);
                         }
                 }
         else if(j == EOF) {     /* ENCRYPTION   */
                 End = 1;
                 if(i == 0 && (IOedf == EN || (Once > 0))) {
                         /* if no padding to do, print a kludge  */
                         if(IOedf == EN && (Once > 0)) putc('0', stdout);
                         return(EOF);
                         }
                 for(j=i; j < 15; j++) *input++ = NULL;
                 *input = 16-i;
                 }
         Once = 1;
         return(0);
         }

 void getkey(aptr, kptr)
 register char *aptr;
 register BYTE *kptr;
         {
         register BYTE *store;
         register int i, first;
         BYTE hold[16];
         first = 1;
         loadkey(DFLTKY, EN);
         copy16(DFLTKY, hold);
         while(*aptr || first) {
                 store = kptr;
                 for(i=0; i<16 && (*aptr != NULL); i++) {
                         *store++ = toascii(*aptr);
                         *aptr++ = NULL;
                         }
                 while(i++ < 16) *store++ = NULL;
                 xor16(kptr, hold);
                 lucifer(kptr);
                 copy16(kptr, hold);
                 first = 0;
                 }
         return;
         }

 void vraiput(cp, ep)
 register BYTE *cp, *ep;
         {
         while(cp < ep) putc((char)*cp++, stdout);
         return;
         }

 void initio(edf)
 int edf;
         {
         IOedf = edf;
         End = Once = 0;
         return;
         }

 /* LUCIFER is a cryptographic algorithm developed by IBM in the early
  *      seventies.  It was a predecessor of the DES, and is much simpler
  *      than that algorithm.  In particular, it has only two substitution
  *      boxes.  It does, however, use a 128 bit key and operates on
  *      sixteen byte data blocks...
  *
  *      This implementation of LUCIFER was crafted by Graven Cyphers at the
  *      University of Toronto, Canada, with programming assistance from
  *      Richard Outerbridge.  It is based on the FORTRAN routines which
  *      concluded Arthur Sorkin's article "LUCIFER: A Cryptographic Algorithm
  *      CRYPTOLOGIA, Volume 8, Number 1, January 1984, pp22-42.  The interest
  *      reader should refer to that article rather than this program for more
  *      details on LUCIFER.
  *
  *      These routines bear little resemblance to the actual LUCIFER algorith
  *      which has been severely twisted in the interests of speed.  They do
  *      perform the same transformations, and are believed to be UNIX portabl
  *      The package was developed for use on UNIX-like systems lacking crypto
  *      facilities.  They are not very fast, but the cipher is very strong.
  *      The routines in this file are suitable for use as a subroutine librar
  *      after the fashion of crypt(3).  When linked together with application
  *      routines they can also provide a high-level cryptographic system.
  *
  *      -DENHANCE : modify LUCIFER by changing the key schedule and performin
  *              an "autokeyed" encryption.  These may improve the algorithm.
  */

 #ifndef DE
 DE      1       /* for separate compilation     */
 #endif

 static BYTE Dps[64] = { /* Diffusion Pattern schedule   */
         4,16,32,2,1,8,64,128,   128,4,16,32,2,1,8,64,
         64,128,4,16,32,2,1,8,   8,64,128,4,16,32,2,1,
         1,8,64,128,4,16,32,2,   2,1,8,64,128,4,16,32,
         32,2,1,8,64,128,4,16,   16,32,2,1,8,64,128,4    };

 /* Precomputed S&P Boxes, Two Varieties */
 static BYTE TCB0[256] = {
         87, 21,117, 54, 23, 55, 20, 84,116,118, 22, 53, 85,119, 52, 86,
         223,157,253,190,159,191,156,220,252,254,158,189,221,255,188,222,
         207,141,237,174,143,175,140,204,236,238,142,173,205,239,172,206,
         211,145,241,178,147,179,144,208,240,242,146,177,209,243,176,210,
         215,149,245,182,151,183,148,212,244,246,150,181,213,247,180,214,
         95, 29,125, 62, 31, 63, 28, 92,124,126, 30, 61, 93,127, 60, 94,
         219,153,249,186,155,187,152,216,248,250,154,185,217,251,184,218,
         67,  1, 97, 34,  3, 35,  0, 64, 96, 98,  2, 33, 65, 99, 32, 66,
         195,129,225,162,131,163,128,192,224,226,130,161,193,227,160,194,
         199,133,229,166,135,167,132,196,228,230,134,165,197,231,164,198,
         203,137,233,170,139,171,136,200,232,234,138,169,201,235,168,202,
         75,  9,105, 42, 11, 43,  8, 72,104,106, 10, 41, 73,107, 40, 74,
         91, 25,121, 58, 27, 59, 24, 88,120,122, 26, 57, 89,123, 56, 90,
         71,  5,101, 38,  7, 39,  4, 68,100,102,  6, 37, 69,103, 36, 70,
         79, 13,109, 46, 15, 47, 12, 76,108,110, 14, 45, 77,111, 44, 78,
         83, 17,113, 50, 19, 51, 16, 80,112,114, 18, 49, 81,115, 48, 82 };

 static BYTE TCB1[256] = {
         87,223,207,211,215, 95,219, 67,195,199,203, 75, 91, 71, 79, 83,
         21,157,141,145,149, 29,153,  1,129,133,137,  9, 25,  5, 13, 17,
         117,253,237,241,245,125,249, 97,225,229,233,105,121,101,109,113,
         54,190,174,178,182, 62,186, 34,162,166,170, 42, 58, 38, 46, 50,
         23,159,143,147,151, 31,155,  3,131,135,139, 11, 27,  7, 15, 19,
         55,191,175,179,183, 63,187, 35,163,167,171, 43, 59, 39, 47, 51,
         20,156,140,144,148, 28,152,  0,128,132,136,  8, 24,  4, 12, 16,
         84,220,204,208,212, 92,216, 64,192,196,200, 72, 88, 68, 76, 80,
         116,252,236,240,244,124,248, 96,224,228,232,104,120,100,108,112,
         118,254,238,242,246,126,250, 98,226,230,234,106,122,102,110,114,
         22,158,142,146,150, 30,154,  2,130,134,138, 10, 26,  6, 14, 18,
         53,189,173,177,181, 61,185, 33,161,165,169, 41, 57, 37, 45, 49,
         85,221,205,209,213, 93,217, 65,193,197,201, 73, 89, 69, 77, 81,
         119,255,239,243,247,127,251, 99,227,231,235,107,123,103,111,115,
         52,188,172,176,180, 60,184, 32,160,164,168, 40, 56, 36, 44, 48,
         86,222,206,210,214, 94,218, 66,194,198,202, 74, 90, 70, 78, 82 };

 static BYTE Key[16], Pkey[128];
 static int P[8] = { 3,5,0,4,2,1,7,6 };
 static int Smask[16] = { 128,64,32,16,8,4,2,1 };

 void lucifer(bytes)
 BYTE *bytes;    /* points to a 16-byte array    */
         {
         register BYTE *cp, *sp, *dp;
         register int val, *sbs, tcb, j, i;
         BYTE *h0, *h1, *kc, *ks;

         h0 = bytes;     /* the "lower" half     */
         h1 = &bytes[8]; /* the "upper" half     */
         kc = Pkey;
         ks = Key;

         for(i=0; i<16; i++) {
                 tcb = *ks++;
                 sbs = Smask;
                 dp = Dps;
                 sp = &h0[8];
 #ifdef ENHANCE
                 for(j=0, cp=h1; j<8; j++) tcb ^= *cp++;
 #endif
                 for(j=0; j<8; j++) {
                         if(tcb&*sbs++) val = TCB1[h1[j]&0377];
                         else val = TCB0[h1[j]&0377];
                         val ^= *kc++;
                         for(cp=h0; cp<sp;) *cp++ ^= (val&*dp++);
                         }

                 /* swap (virtual) halves        */
                 cp = h0;
                 h0 = h1;
                 h1 = cp;
                 }

         /* REALLY swap halves   */
         dp = bytes;
         cp = &bytes[8];
         for(sp=cp; dp<sp; dp++, cp++) {
                 val = *dp;
                 *dp = *cp;
                 *cp = val;
                 }
         return;
         }

 void loadkey(keystr, edf)       /* precomputes the key schedules        */
 BYTE *keystr;
 register int edf;
         {
         register BYTE *ep, *cp, *pp;
         register int kc, i, j;
         BYTE kk[16], pk[16];
         cp = kk;
         pp = pk;
         ep = &kk[16];
         while(cp < ep) {
                 *cp++ = *keystr;
                 for(*pp=i=0; i<8; i++)
                         if(*keystr&Smask[i]) *pp |= Smask[P[i]];
                 keystr++;
                 pp++;
                 }
         cp = Key;
         pp = Pkey;
         kc = (edf == DE) ? 8 : 0;
         for(i=0; i<16; i++) {
                 if(edf == DE) kc = (++kc)&017;
 #ifdef ENHANCE
                 *cp++ = kk[( (kc == 0) ? 15 : (kc - 1) )];
 #else
                 *cp++ = kk[kc];
 #endif
                 for(j=0; j<8; j++) {
                         *pp++ = pk[kc];
                         if(j<7 || (edf == DE)) kc = (++kc)&017;
                         }
                 }
         return;
         }

 /* lucifer cks # < /dev/null
  *      : 16 bytes      : 32186510 6acf6094 87953eba 196f5a75 :
  *      (-DENHANCE)     : 378cfd5b bd54a07b 28513809 624e6071 :
  *                      (rwo/8412.03.18:10/V5.0)                */
 /************************ lucifer *******************************/


 LUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LUMPS\LUMP.C

 /* lump together a group of files. (Use UNLUMP to break apart */

 #include "stdio.h"

 FILE *infile, *outfile;

 main(argc,argv)
 int argc;
 char *argv[];
 {
    int c, i;

    if(argc<3)  { usage(); exit(0); }

    argc--;
    if( exists(argv[1]) )    { usage(); exit(1);  }
    if( (outfile=fopen(argv[1], "w")) == NULL )    { usage();  exit(1); }
    for( i=2; i<=argc; i++ ) {
       if( (infile=fopen(argv[i],"r")) == NULL )  { inerr(argv[i]); exit(2); }
       fprintf(outfile, "*FILE: %s\n", argv[i]);
       printf("*FILE: %s\n", argv[i]);
       while ( (c=getc(infile)) >= 0)
          putc(c,outfile);
       fclose(infile);
    }

 }


 usage()
 {
    printf("Usage:  lump outfile infile1 ... \n");
    printf("   Lump all input files into the output file,\n");
    printf("   each being preceeded with a line identifying itself:\n");
    printf("      *FILE: filename.ext\n\n");
 }


 inerr(s)
 char *s;
 {
    printf("\nError opening file %s\n", s);
 }


 exists(s)
 char *s;
 {
    FILE *f;
    if( (f=fopen(s,"r")) == NULL )  return 0;
    fclose(f);
    return 1;
 }


 LZWCOM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\LZW\LZWCOM.C

 /* LZWCOM - FILE COMPRESSOR UTILITY                                     */
 #include "stdio.h"
 #include "debug.h"
 #define FALSE    0
 #define TRUE     !FALSE
 #define TABSIZE  4096
 #define NO_PRED  0xFFFF
 #define EMPTY   0xFFFF
 #define NOT_FND 0xFFFF
 #define UEOF ((unsigned)EOF)
 struct entry {
   char used;
   unsigned int next;      /* hi bit is 'used' flag                        */
   unsigned int predecessor;               /* 12 bit code                  */
   unsigned char follower;
 } string_tab[TABSIZE];

 /*   routines common to compress and decompress, contained in CommLZW.c */
 unsigned hash();
 unsigned unhash();
 unsigned getcode();
 putcode();
 init_tab();
 upd_tab();

 FILE *op;
 main(argc,argv)
 int argc; char *argv[];
 {
   register unsigned int c, code, localcode;
   int code_count = TABSIZE - 256;
   FILE *infd, *outfd;
   if (3 != argc) {
     fprintf(stderr,"Usage : lzwcom oldfilename squeezefilename\n");
     exit(0);
   }
   if ( -1 == (infd = fopen( *++argv, "r")) ) {
     fprintf(stderr,"Cant open %s\n", *argv);
     exit(0);
   }
   if ( -1 == (outfd = fopen(*++argv,"w")) ) {
     fprintf(stderr,"Cant create %s\n",*argv);

     exit(0);
   }
   init_tab();                           /* initialize code table        */
   c = getc(infd);
   code = unhash(NO_PRED,c);             /* initial code for table       */
   DEBUGGER (\
         if (c >= ' ' || c <= '~' || c == '\n' || c == '\r')\
                   putchar(c);\
         else\
                 printf("[%2x]",c);\
   )
   while ( UEOF != (c = getc(infd)) )
   {
           DEBUGGER (\
                 if (c >= ' ' || c <= '~' || c == '\n' || c == '\r')\
                           putchar(c);\
                 else\
                         printf("[%2x]",c);\
           )
           if ( NOT_FND != (localcode = unhash(code,c)) )
           {
               code = localcode;
               continue;
           }
 /* when the above clause comes false, you have found the last known code */
       putcode(outfd,code);      /* only update table if table isn't full */
           DEBUGGER(printf( "\n%x\n",code);)
       if ( code_count )
           {
               upd_tab(code,c);
                   DEBUGGER(printf("\nadding %x %c = %x\n",code,c,unhash(code,
       --code_count;
       }
 /* start loop again with the char that didn't fit into last string      */
       code = unhash(NO_PRED,c);
   }
   putcode(outfd,code);                  /* once EOF reached, always     */
                                         /* one code left unsent         */
   DEBUGGER(fprintf(stderr,"\n%x\n",code);)
   flushout(outfd);                      /* make sure everything's written */
   exit(0);                              /* make sure everything gets closed *
 }



 LZWCOMM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\LZW\LZWCOMM.C

 /* COMMLZW - ROUTINES COMMON TO LZWCOM AND LZWUNC                       */
 #include "stdio.h"
 #include "debug.h"
 #define FALSE    0
 #define TRUE     !FALSE
 #define TABSIZE  4096
 #define NO_PRED  0xFFFF
 #define EMPTY    0xFFFF
 #define NOT_FND  0xFFFF
 #define SECTSIZE 128
 CTRLZ '\032' /* ascii end of file */
 extern struct entry {
   char used;
   unsigned int next;                    /* index of next in collision list */
   unsigned int predecessor;             /* 12 bit code                  */
   unsigned char follower;
 } string_tab[TABSIZE];

 /* h uses the 'mid-square' algorithm. I.E. for a hash val of n bits     */
 /* hash = middle binary digits of (key * key).  Upon collision, hash    */
 /* searches down linked list of keys that hashed to that key already.   */
 /* It will NOT notice if the table is full. This must be handled        */
 /* elsewhere                                                            */

 unsigned h(pred,foll)
 /* returns the mid square of pred + foll                                */
         unsigned int pred; unsigned char foll;
 {
   long temp, local;             /* 32 bit receiving field for local^2   */
   local = (pred + foll) | 0x0800;
   temp = local * local;
   local = (temp >> 6) & 0x0FFF;
   return local;                 /* middle 12 bits of result             */
 }

 unsigned eolist(index)
 /* return last element in a collision list                              */
 unsigned int index;
 {
   register int temp;
   while ( 0 != (temp = string_tab[index].next) )
     index = temp;
   return index;
 }

 unsigned hash(pred,foll,update)
 unsigned int pred; unsigned char foll; int update;
 {
   register unsigned int local, tempnext;
   register struct entry *ep;
   local = h(pred,foll);
   if ( !string_tab[local].used )
     return local;
   else {
   /* if collision has occured                                           */
     local = eolist(local);

   /* search for free entry from local + 101 */
     tempnext = (local + 101) & 0x0FFF;
     ep = &string_tab[tempnext];                 /* initialize pointer   */
     while ( ep->used ) {
       ++tempnext;
       if ( tempnext == TABSIZE ) {
         tempnext = 0;           /* handle wrap to beginning of table    */
         ep = string_tab;        /* address of first element of table    */
       } else
         ++ep;                   /* point to next element in table       */
     }

     /* put new tempnext into last element in collision list             */
     if ( update )               /* if update requested                  */
       string_tab[local].next = tempnext;
     return tempnext;
   }
 }

 /* unhash uses the 'next' field to go down the collision tree to find   */
 /* the entry corresponding to the passed key                            */
 /* passed key and returns either the matching entry # or NOT_FND        */

 unsigned unhash(pred,foll)
 unsigned int pred; unsigned char foll;
 {
   register unsigned int local, offset;
   register struct entry *ep;    /* pointer to current entry             */

   local = h(pred,foll);         /* initial hash                         */
   loop:
     ep = &string_tab[local];
     if ( (ep->predecessor == pred) && (ep->follower == foll) )
       return local;
     if ( ep->next == 0 )
       return NOT_FND;
     local = ep->next;
   goto loop;
 }

 init_tab() {
   register unsigned int i;
   setmem((char *)string_tab,sizeof(string_tab),0);
   for (i = 0; i <= 255; i++) {
     upd_tab(NO_PRED,i);
   }
 }

 #define UPDATE TRUE

 upd_tab(pred,foll)
   unsigned int pred, foll;
 {
   register struct entry *ep;    /* pointer to current entry     */
   /* calculate offset just once */
   ep = &string_tab[ hash(pred,foll,UPDATE) ];
   ep->used = TRUE;
   ep->next = 0;
   ep->predecessor = pred;
   ep->follower = foll;
 }


 unsigned int inbuf = EMPTY;
 unsigned int outbuf = EMPTY;

 /* getcode and putcode 'gallop' through input and output - they either  */
 /* output two bytes or one depending on the contents of the buffer.     */

 getcode(fd)
 FILE *fd;     {
   register unsigned int localbuf, returnval;
   if (EMPTY == inbuf) {         /* On code boundary                     */
     if (EOF == (localbuf = getch(fd)) ) {
                                 /* H L1 byte - on code boundary         */
       return EOF;
     }
     localbuf &= 0xFF;
         if (EOF == (inbuf = getch(fd)) ) {  /* L0 Hnext                     *
       return EOF;       /* The file should always end on code boundary  */
     }
     inbuf &= 0xFF;
         DEBUGGER(fprintf(stderr,"%x and %x read\n",localbuf,inbuf);)
     returnval = ((localbuf << 4) & 0xFF0) + ((inbuf >> 4) & 0x00F);
     DEBUGGER(fprintf(stderr,"returnval = %x\n",returnval);)
     inbuf &= 0x000F;
   } else {                      /* buffer contains nibble H             */
     if (EOF == (localbuf = getch(fd)) )
       return EOF;
     localbuf &= 0xFF;
     DEBUGGER(fprintf(stderr,"%x read, inbuf = %x\n",localbuf,inbuf);)
     returnval = localbuf + ((inbuf << 8) & 0xF00);
     inbuf = EMPTY;
     DEBUGGER(fprintf(stderr,"returnval = %x\n",returnval);)
   }
   return returnval;
 }

 putcode(fd,code)
 FILE *fd;
 unsigned int code;     {
   register int localbuf;
   if (EMPTY == outbuf) {
     putch( ((code >> 4) & 0xFF),fd);    /* H L1                        */
     outbuf = code & 0x000F;     /* L0                                   */
   } else {
     putch( ( ((outbuf << 4) & 0xFF0) + ((code >> 8) & 0x00F) ),fd );
                                 /* L0prev H                             */
     putch( (code & 0x00FF),fd);        /* L1 L0                        */
     outbuf = EMPTY;
   }
 }
 static int incount = 0, outcount = 0;
 static int ink = 0, outk = 0;
 putch(c,fp)
         char c;
         FILE *fp;
 {
         if (outcount == 0)
         {
                 reset_crc();
         }
         update_crc(c);
         putc(c,fp);
         outcount++;
         if (outcount == 1024)
         {
                 fprintf(stderr,"%dk written\r",++outk);
                 outcount = 0;
                 putw(get_crc(),fp);
         }
 }

 getch(fp)
         FILE *fp;
 {
         extern FILE *op;
         register int returnc;
         unsigned int crc;
         if (incount == 0)
         {
                 reset_crc();
         }
         if (EOF == (returnc = getc(fp)))
                 return EOF;
         update_crc(returnc);
         ++incount;
         if (incount == 1024)
         {
                 if (!isatty(fileno(op)))
                 {
                         fprintf(stderr,"%dk read\r",++ink);
                 }
                 incount = 0;
                 if (EOF == (crc = getw(fp)))
                         return EOF;
                 update_crc((crc & 0xFF));        /* lo byte */
                 update_crc(((crc >> 8) & 0xFF));        /* hi byte */
                 if (get_crc())
                 {
                         fprintf(stderr,"crc error - aborting");
                         exit(1);
                 }
         }
         return returnc;
 }

 flushout(fd)
 FILE *fd;
 {
         if ( EMPTY != outbuf)
                 putc(((outbuf << 4) & 0xFF0),fd);
 }


 LZWUNC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\LZW\LZWUNC.C


 /* LZWUNC - FILE UNCOMPRESSOR UTILITY                                   */
 #include "stdio.h"
 #include "debug.h"
 #define FALSE    0
 #define TRUE     !FALSE
 #define TABSIZE  4096
 #define STACKSIZE TABSIZE
 #define NO_PRED  0xFFFF
 #define EMPTY    0xF000
 #define NOT_FND  0xFFFF
 #define NO_UPDATE FALSE
 #define UEOF ((unsigned)EOF)

 struct entry {
   char used;
   unsigned int next;        /* hi bit is 'used' flag                        *
   unsigned int predecessor; /* 12 bit code                  */
   unsigned char follower;
 } string_tab[TABSIZE];

 /*   routines common to compress and decompress, contained in CommLZW.c */
 unsigned hash();
 unsigned unhash();
 unsigned getcode();
 putcode();
 init_tab();
 upd_tab();

 FILE *op; /* global file pointer - gets assigned from outfd so that getch can
              determine whether or not to print stuff to the screen */

 main(argc,argv)
 int argc; char *argv[];
 {
   register unsigned int c;
   int tempc, code, oldcode, incode, finchar,lastchar;
   char unknown = FALSE;
   int code_count = TABSIZE - 256;
   FILE *infd, *outfd;
   register struct entry *ep;

   if (3 != argc) {
     fprintf(stderr,"Usage : lzwunc squeezefilename newfilename\n");
     exit(0);
   }
   if ( -1 == (infd = fopen( *++argv, "r")) ) {
     fprintf(stderr,"Cant open %s\n", *argv);
     exit(0);
   }
   if ( -1 == (op = outfd = fopen(*++argv,"w")) ) {
     fprintf(stderr,"Cant create %s\n",*argv);
     exit(0);
   }

   init_tab();                           /* set up atomic code definitions*/
   code = oldcode = getcode(infd);
   c = string_tab[code].follower;        /* first code always known      */
   putc(c,outfd);
   DEBUGGER(\
            putc(c,stderr);\
            fprintf(stderr,"\n%x\n",code);\
   )
   finchar = c;

   while ( UEOF != (code = incode = getcode(infd)) ) {
         DEBUGGER(fprintf(stderr,"\n%x\n",code);)
     ep = &string_tab[code];             /* initialize pointer           */
     if ( !ep->used )
         {                  /* if code isn't known          */
           lastchar = finchar;
           code = oldcode;
           unknown = TRUE;
       ep = &string_tab[code];           /* re-initialize pointer        */
     }

     while (NO_PRED != ep->predecessor)
         {
       push( ep->follower);              /* decode string backwards into */
                                         /* stack                        */
       code = ep->predecessor;
       ep = &string_tab[code];
     }

     finchar = ep->follower;
     /* above loop terminates, one way or another, with                  */
     /* string_tab[code].follower = first char in string                 */

     putc(finchar,outfd);
     DEBUGGER(putc(finchar,stderr);)
     /* pop anything stacked during code parsing                         */
     while ( EMPTY != (tempc = pop()) )
         {
       putc(tempc,outfd);
           DEBUGGER(\
             putc(tempc,stderr);\
           )
     }
     if ( unknown ) {                  /* if code isn't known          */
       putc(finchar = lastchar,outfd); /* the follower char of last    */
           unknown = FALSE;
           DEBUGGER(\
                   putc(lastchar,stderr);\
                 fprintf(stderr,"\nunknown code\n");\
           )
         }
     if ( code_count )
         {
       upd_tab(oldcode,finchar);
       --code_count;
           DEBUGGER(fprintf(stderr,"\nAdding %x,%c = %x\n",\
                                   oldcode,finchar,unhash(oldcode,finchar));)
     }
     oldcode = incode;
   }
   flushout(outfd);      /* write out fractional buffer, if any          */
   exit(0);              /* close all files and quit                     */
 }

 char stack[STACKSIZE];  /* stack for pushing and popping characters     */
 int sp = 0;             /* current stack pointer                        */

 push(c)
 register int c;
 {
   stack[sp] = ((char) c);/* coerce passed integer into a character      */
   ++sp;
   if (sp >= STACKSIZE) {
     fprintf(stderr,"Stack overflow, aborting\n");
     exit(1);            /* non-0 exit parameter terminates batch job    */
   }
 }

 pop()
 {
   if (sp > 0)
   {
     --sp;               /* push leaves sp pointing to next empty slot   */
     return ( (int) stack[sp] ); /* make sure pop returns char           */
   }
   else
     return EMPTY;
 }




 MACRO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\MACRO.C

                                         /* Chapter 6 - Program 2 */
 WRONG(A) A*A*A          /* Wrong macro for cube     */
 CUBE(A) (A)*(A)*(A)     /* Right macro for cube     */
 SQUR(A) (A)*(A)         /* Right macro for square   */
 ADD_WRONG(A) (A)+(A)    /* Wrong macro for addition */
 ADD_RIGHT(A) ((A)+(A))  /* Right macro for addition */
 #define START 1
 #define STOP  7

 main()
 {
 int i,offset;

    offset = 5;
    for (i = START;i <= STOP;i++) {
       printf("The square of %3d is %4d, and its cube is %6d\n",
               i+offset,SQUR(i+offset),CUBE(i+offset));
       printf("The wrong of  %3d is %6d\n",i+offset,WRONG(i+offset));
    }

    printf("\nNow try the addition macro's\n");
    for (i = START;i <= STOP;i++) {
       printf("Wrong addition macro = %6d, and right = %6d\n"
                                ,5*ADD_WRONG(i),5*ADD_RIGHT(i));
    }
 }


 MAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\MAIN.C

 /*
  * STEVIE - ST Editor for VI Enthusiasts   ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 int Rows;                /* Number of Rows and Columns */
 int Columns;                /* in the current window. */

 char *Realscreen = NULL;        /* What's currently on the screen, a single *
                                 /* array of size Rows*Columns. */
 char *Nextscreen = NULL;        /* What's to be put on the screen. */

 char *Filename = NULL;        /* Current file name */

 LPTR *Filemem;                /* The contents of the file, as a single array.

 LPTR *Fileend;                /* Pointer to the end of the file in Filemem. *
                         /* (It points to the byte AFTER the last byte.) */

 LPTR *Topchar;                /* Pointer to the byte in Filemem which is */
                         /* in the upper left corner of the screen. */

 LPTR *Botchar;                /* Pointer to the byte in Filemem which is */
                         /* just off the bottom of the screen. */

 LPTR *Curschar;                /* Pointer to byte in Filemem at which the */
                         /* cursor is currently placed. */

 int Cursrow, Curscol;        /* Current position of cursor */

 int Cursvcol;                /* Current virtual column, the column number of
                         /* the file's actual line, as opposed to the */
                         /* column number we're at on the screen.  This */
                         /* makes a difference on lines that span more */
                         /* than one screen line. */

 int Curswant = 0;        /* The column we'd like to be at. This is used */
                         /* try to stay in the same column through up/down */
                         /* cursor motions. */

 bool_t set_want_col;        /* If set, then update Curswant the next time */
                         /* through cursupdate() to the current virtual */
                         /* column. */

 int State = NORMAL;        /* This is the current state of the command */
                         /* interpreter. */

 int Prenum = 0;                /* The (optional) number before a command. */

 LPTR *Insstart;                /* This is where the latest insert/append */
                         /* mode started. */

 bool_t Changed = 0;        /* Set to 1 if something in the file has been */
                         /* changed and not written out. */

 bool_t Debug = 0;

 char Redobuff[1024];        /* Each command should stuff characters into this
                         /* buffer that will re-execute itself. */

 char Undobuff[1024];        /* Each command should stuff characters into this
                         /* buffer that will undo its effects. */

 char Insbuff[1024];        /* Each insertion gets stuffed into this buffer. *

 LPTR *Uncurschar;        /* Curschar is restored to this before undoing. */

 int Ninsert = 0;        /* Number of characters in the current insertion. */
 int Undelchars = 0;        /* Number of characters to delete, when undoing. *
 char *Insptr = NULL;

 char **files;                /* list of input files */
 int  numfiles;                /* number of input files */
 int  curfile;                /* number of the current file */

 static void
 usage()
 {
         fprintf(stderr, "usage: stevie [file ...]\n");
         fprintf(stderr, "       stevie -t tag\n");
         fprintf(stderr, "       stevie +[num] file\n");
         fprintf(stderr, "       stevie +/pat  file\n");
         exit(1);
 }

 main(argc,argv)
 int        argc;
 char        *argv[];
 {
         char        *initstr, *getenv();        /* init string from the envir
         char        *tag = NULL;                /* tag from command line */
         char        *pat = NULL;                /* pattern from command line
         int        line = -1;                /* line number from command line

         /*
          * Process the command line arguments.
          */
         if (argc > 1) {
                 switch (argv[1][0]) {

                 case '-':                        /* -t tag */
                         if (argv[1][1] != 't')
                                 usage();

                         if (argv[2] == NULL)
                                 usage();

                         Filename = NULL;
                         tag = argv[2];
                         numfiles = 1;
                         break;

                 case '+':                        /* +n or +/pat */
                         if (argv[1][1] == '/') {
                                 if (argv[2] == NULL)
                                         usage();
                                 Filename = strsave(argv[2]);
                                 pat = &(argv[1][1]);
                                 numfiles = 1;

                         } else if (isdigit(argv[1][1]) || argv[1][1] == NUL)
                                 if (argv[2] == NULL)
                                         usage();
                                 Filename = strsave(argv[2]);
                                 numfiles = 1;

                                 line = (isdigit(argv[1][1])) ?
                                         atoi(&(argv[1][1])) : 0;
                         } else
                                 usage();

                         break;

                 default:                        /* must be a file name */
                         Filename = strsave(argv[1]);
                         files = &(argv[1]);
                         numfiles = argc - 1;
                         break;
                 }
         } else {
                 Filename = NULL;
                 numfiles = 1;
         }
         curfile = 0;

         windinit();

         /*
          * Allocate LPTR structures for all the various position pointers
          */
         if ((Filemem = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }
         if ((Fileend = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }
         if ((Topchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }
         if ((Botchar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }
         if ((Curschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }
         if ((Insstart = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }
         if ((Uncurschar = (LPTR *) malloc(sizeof(LPTR))) == NULL) {
                 fprintf(stderr, "Can't allocate data structures\n");
                 windexit(0);
         }

         screenalloc();
         filealloc();                /* Initialize Filemem & Fileend */

         screenclear();

         if ((initstr = getenv("EXINIT")) != NULL) {
                 char *lp, buf[128];

                 if ((lp = getenv("LINES")) != NULL) {
                         sprintf(buf, "%s lines=%s", initstr, lp);
                         readcmdline(':', buf);
                 } else
                         readcmdline(':', initstr);
         }

         if (Filename != NULL) {
                 if (readfile(Filename, Filemem, FALSE))
                         filemess("[New File]");
         } else
                 msg("Empty Buffer");

         setpcmark();

         updatescreen();

         if (tag) {
                 stuffin(":ta ");
                 stuffin(tag);
                 stuffin("\n");

         } else if (pat) {
                 stuffin(pat);
                 stuffin("\n");

         } else if (line >= 0) {
                 if (line > 0)
                         stuffnum(line);
                 stuffin("G");
         }

         edit();

         windexit(0);
         return(0);
 }

        RBSIZE        1280                /* should be a little bigger than YB
 static char getcbuff[RBSIZE];
 static char *getcnext = NULL;

 void
 stuffin(s)
 char *s;
 {
         if ( getcnext == NULL ) {
                 strcpy(getcbuff,s);
                 getcnext = getcbuff;
         } else
                 strcat(getcbuff,s);
 }

 void
 stuffnum(n)
 int        n;
 {
         char        buf[32];

         sprintf(buf, "%d", n);
         stuffin(buf);
 }

 void
 addtobuff(s,c1,c2,c3,c4,c5,c6)
 char *s;
 char c1, c2, c3, c4, c5, c6;
 {
         char *p = s;
         if ( (*p++ = c1) == NUL )
                 return;
         if ( (*p++ = c2) == NUL )
                 return;
         if ( (*p++ = c3) == NUL )
                 return;
         if ( (*p++ = c4) == NUL )
                 return;
         if ( (*p++ = c5) == NUL )
                 return;
         if ( (*p++ = c6) == NUL )
                 return;
 }

 int
 vgetc()
 {
         if ( getcnext != NULL ) {
                 int nextc = *getcnext++;
                 if ( *getcnext == NUL ) {
                         *getcbuff = NUL;
                         getcnext = NULL;
                 }
                 return(nextc);
         }
         return(inchar());
 }

 int
 vpeekc()
 {
         if ( getcnext != NULL )
                 return(*getcnext);
         return(-1);
 }

 /*
  * anyinput
  *
  * Return non-zero if input is pending.
  */

 bool_t
 anyinput()
 {
         return (getcnext != NULL);
 }


 MAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\MAIN.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 extern char        *_base;
 extern int        _argc;
 extern char        **_argv;
 extern char        *_envp;

 FILE        _iob[MAXFILES] =                        /* stream buffers */
 {
 /*in*/        {0, F_READ|F_DEVICE, NULL, NULL, 0, 0, '\0', '\0'},
 /*out*/        {1, F_WRITE|F_DEVICE, NULL, NULL, 0, 0, '\0', '\0'},
 /*err*/        {-1, F_WRITE|F_DEVICE, NULL, NULL, 0, 0, '\0', '\0'},
 /*prn*/        {-3, F_WRITE|F_DEVICE, NULL, NULL, 0, 0, '\0', '\0'},
 /*aux*/        {-2, F_READ|F_WRITE|F_DEVICE, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'},
         {0, 0, NULL, NULL, 0, 0, '\0', '\0'}
 };

 void _main(cmdline, cmdlen)
 char *cmdline;
 int cmdlen;
 /*
  *        Parses command line, opens standard files, plus other assorted
  *        general setup. Then calls user's main() function.  If main()
  *        returns, exit() is called with a 0 return value.  The following
  *        standard streams are initialized by _main():
  *                stdin                Standard input, may be redirected
  *                stdout                Standard output, may be redirected
  *                stderr                Usually the system console
  *                stdprn                The standard printer (output only)
  *                stdaux                The communication port (input/output)
  *        The _initargs() function is called to process the command line.
  *        The global variables "_argc", "_argv" and "_envp" are used to
  *        store the values to be passed to the user's main().
  */
 {
         void exit();

         _argc = 0;
         _argv = NULL;
         _envp = *((char **) (_base + 0x2C));
         _initargs(cmdline, cmdlen);
         main(_argc, _argv, _envp);
         exit(0);
 }

 void exit(status)
 int status;
 /*
  *        Flushes and closes all open streams.  Returns <status> value to
  *        the operating system.
  */
 {
         register int i, f;

         for(i=0; i<MAXFILES; ++i) {
                 f = _iob[i].F_stat;
                 if((f & (F_READ | F_WRITE)) && !(f & F_DEVICE))
                         fclose(&_iob[i]);
         }
         _exit(status);
 }


 MAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\MAIN.C

 /*
  *        MicroEMACS 3.9
  *                         written by Dave G. Conroy.
  *                        substatially modified by Daniel M. Lawrence
  *
  *        (C)opyright 1987 by Daniel M. Lawrence
  *        MicroEMACS 3.9 can be copied and distributed freely for any
  *        non-commercial purposes. MicroEMACS 3.9 can only be incorporated
  *        into commercial software with the permission of the current author.
  *
  * This file contains the main driving routine, and some keyboard processing
  * code, for the MicroEMACS screen editor.
  *
  * REVISION HISTORY:
  *
  * 1.0  Steve Wilhite, 30-Nov-85
  *      - Removed the old LK201 and VT100 logic. Added code to support the
  *        DEC Rainbow keyboard (which is a LK201 layout) using the the Level
  *        1 Console In ROM INT. See "rainbow.h" for the function key defs
  *      Steve Wilhite, 1-Dec-85
  *      - massive cleanup on code in display.c and search.c
  *
  * 2.0  George Jones, 12-Dec-85
  *      - Ported to Amiga.
  *
  * 3.0  Daniel Lawrence, 29-Dec-85
  *      - rebound keys/added new fast buffered I/O for AMIGA
  *        - added META- repeat commands
  *        - added reposition default to center screen (yeah!)
  *        - changed exit with modified buffers message
  *        - made filesave tell us what it is doing
  *        - changed search string entry to terminate with <ESC>
  *          so we can use <NL> in search/replace strings
  *        - updated version number in mode line to 3.0
  *        12-Jan-86
  *        - Added code to reconize the search/replace functions
  *        - Added code to perform search/replace & query functions
  *        14-Jan-86
  *        - moved search logic to separate function in search.c
  *        - added replace and query replace functions
  *        - separated out control key expansions to be used by others in sear
  *        15-Jan-86
  *        - changed "visiting" to finding
  *        - changed yes/no responses to not need return
  *        - cleaned up various messages
  *        16-jan-86
  *        - fixed spurious spawn message in MSDOS
  *        - added ^X-S synonym to save command
  *        - moved escape to shell to ^X-C
  *        21-jan-86
  *        - added code to suspend shell under BSD
  *        22-jan-86
  *        - added function key support (SPEC) under MSDOS
  *        - Abort now prints [Aborted] on message line
  *        23-jan-86
  *        - Added modes and commands to set/unset them
  *        24-jan-86
  *        - Added Goto Line command
  *        - added Rename Buffer command
  *        28-jan-86
  *        - added goto beginning and end of paragraph commands (META-P/META-N
  *        - re-wrote kdelete to use realloc. Gained MUCH speed here when
  *          doing large wipes on both UNIX and MSDOS. Changed kill buffer
  *          allocation block size from 256 bytes to 1 k
  *        29-jan-86
  *        - moved extern function declarations to efunc.h
  *        - made name[] name binding table
  *        30-jan-86
  *        - fixed Previous/Next paragraph command not to wrap around EOF
  *        - added Fill Paragraph command (META-Q)
  *        4-feb-86
  *        - added code to properly display long lines, scrolling them right
  *          to left
  *        5-feb-85
  *        - rewrote code to right/left scroll...much better
  *        - added shifted arrow keys on IBMPC
  *        6-feb-85
  *        - add option to allow forward-word to jump to beginning of
  *          next word instead of end of current one. This is different from
  *          other emacs' but can be configured off in estruct.h
  *        - added VIEW mode to allow a buffer to be read only
  *           (-v switch on command line will activate this)
  *        - changed quick exit to write out ALL changed buffers!!!
  *          MAKE SURE YOU KNOW THIS WHEN META-Zing
  *        10-feb-86
  *        - added handling of lines longer than allowed on file read in
  *          (they wrap on additional lines)
  *        - made having space clear the message line and NOT insert itself
  *          a configuration option in ed.h
  *        11-feb-86
  *        - added Describe-command and Help commands.
  *        13-feb-86
  *        - added View file command (^X ^V) and finished HELP command
  *        14-feb-86
  *        - added option to let main loop skip update if type ahead commands
  *           are queued up
  *        16-feb-86
  *        - added Insert File command
  *        17-feb-86
  *        - added scroll next window up/down commands
  *        18-feb-86
  *        - added CMODE indentation
  *        - re-arranged header files to standardize extern and global
  *          definitions
  *        - changed version number to 3.2
  *        - added numeric arguments to search, reverse search and
  *          search and replace
  *        24-feb-86
  *        - added Bind To Key function (^C for now) to allow the user
  *          to change his command keys
  *        - added Unbind key function (M-^C for now)
  *        - added execute named command to execute unbound commands (M-X)
  *        - added describe bindings command (not bound)
  *        - changed version number to 3.3
  *        25-feb-86
  *        - scrapped CERROR mode (too many compilers)
  *        - added EXACT mode for case sensitive searchers
  *        26-feb-86
  *        - added command completion on execute named command and
  *          all routined grabbing a command name
  *        - adding execute-command-line command and its support functions
  *          (in preparation for sourcing files)
  *        - added Execute Buffer command
  *        27-feb-86
  *        - added execute(source) file command and added code to automaticall
  *          execute emacs.rc (or .emacsrc on UNIX) before initial read in
  *        - changed version number to 3.4
  *        4-mar-86
  *        - changed word delete to be consistant with word move (it gets
  *          rid of the inter word space now) This is configurable with the
  *          NFWORD symbol in estruct.h
  *        - added B_ACTIVE entry to the buffer table. Let emacs read multiple
  *          file names from the command line and only read them in as needed
  *        5-mar-85
  *        - rewrote command line parser to get rid of my patchy code
  *        - changed version number to 3.5
  *        1-apr-86
  *        - added support for Aztec C 3.20e under MSDOS
  *        - fixed bug in mlwrite on ADM3's and their ilk under V7
  *        - added insertion of pounds in column one under CMODE
  *        - changed version number to 3.6
  *        3-apr-86
  *        - added next-buffer command (^X-X)
  *        5-apr-86
  *        - added kill paragraph command (M-^W)
  *        - changed fill-paragraph to leave 2 spaces after a period at the
  *          end of a word.
  *        - added OVERWRITE mode
  *        7-apr-86
  *        - fixed overwrite mode to handle tabs
  *        8-apr-86
  *        - added add/delete global mode (<ESC>M & <ESC> ^M) commands
  *        9-apr-86
  *        - added insert space command
  *        - moved bindings around                ^C        insert space
  *                                        M-K        bind-to-key
  *                                        INSERT        insert space
  *                                        DELETE        forwdel
  *        - added hunt forward and hunt reverse commands
  *        10-apr-86
  *        - fixed bug in DOBUF with non-terminated command string
  *        15-apr-86
  *        - fixed tab expansion bug in DISPLAY which hung the AMIGA
  *          (sent in by Dawn Banks)
  *        - fixed curcol problen if forwline/backline during keyboard
  *          macro execution (sent in by Ernst Christen)
  *        - added AMIGA function/cursor key support
  *        - fixed nonterminating <NL> replacement bug
  *        - fixed word wrapping problems
  *        16-apr-86
  *        - updated documentation and froze development for 3.6 net release
  *        23-apr-86        version 3.6a
  *        - added foreground and background colors. Setable with the
  *          add mode commands for the moment
  *        24-apr-86
  *        - added command to pipe CLI output to a buffer
  *        25-apr-86
  *        - added Dana Hoggatt's code to replace Lattice's sick system()
  *          function. Now we no longer care what the switchar is.
  *        - cleaned up the positioning on several of the spawing commands
  *        26-apr-86
  *        - added an output flush in vttidy(). Unix really appreciates this.
  *        - added filter-buffer (^X#) command to send a buffer through
  *          a DOS filter
  *        - made automatic CMODE on .c and .h file compilation dependant
  *          in estruct.h
  *        1-may-86
  *        - optimized some code in update(). It certainly need a lot more.
  *        - added Aztec profiling capabilities. These are conditional on
  *          the APROF symbol in estruct.h
  *        2-may-86
  *        - added (u)ndo command in query-replace. undoes last repalce.
  *        6-may-86
  *        - re-organized and wrote the update() function in display.c
  *          Now my color hacks are in the right places and the code can be
  *          understood.
  *        [Released version 3.6f for BETA test sites]
  *        8-may-86
  *        - fixed bug in new display routine to wrap cursor on extended
  *          lines at the right time
  *        - modified the buffer-position command to give reasonable info
  *        9-may-86
  *        - improved the word wrap algorithm as not to discard non-space
  *          delimiters. The backscan now looks for white space rather than
  *          !inword().
  *        [Released version 3.6g to Krannert]
  *        10-may-86
  *        - Added IBMPC.C an IBM-PC specific display driver. This makes pagin
  *          4-6 times faster. Also made some conditional changes to DISPLAY.C
  *          to eliminate the pscreen[] if using the PC driver.
  *        [changed version number to 3.6i]
  *        12-may-86
  *        - added delete-window (^X 0) command to dispose of a single window
  *        - fixed problem with multiple prefixes from a command line which
  *          was reported by John Gamble
  *        14-may-86
  *        - Added Aztec support for the IBMPC display driver. Had to
  *          readjust some includes and defines for this.
  *        - fixed bug in delete-window.
  *        - fixed some bizarre behavior with the cursor after coming back
  *          from spawn calls.
  *        [changed version number to 3.7 freezing development for net release
  *        15-may-86
  *        - (that didn't last long...) Added execute-macro-(1 thru 20) comman
  *          to execute macro buffers (named "[Macro nn]")
  *        - changed BFTEMP to BFINVS and cleaned up treatment of invisible
  *          buffers.
  *        16-may-86
  *        - added store-macro (unbound) to store any executed command lines t
  *          macro buffer.
  *        - added clear-message-line (unbound) command to do just that
  *        - added resize-window command to change a window's size to the
  *          specified argument
  *        - improved help's logic not to re-read the file if it was already
  *          in a buffer
  *        - added MAGIC mode to all structures and command tables, but the
  *          regular expression code that John Gamble is writing is not ready.
  *        18-may-86
  *        - added interactive prompt requests in command line execution (i.e.
  *          while executing a macro, a parameter starting with an at sign (@)
  *          causes emacs to prompt with the rest of the parameter and return
  *          the resulting input as the value of the parameter).
  *        - added arguments to split-current-window to force the cursor into
  *          the upper or lower window.
  *        20-may-86
  *        - added support for the Microsoft C compiler as per the changes
  *          sent in by Oliver Sharp
  *        - made some upgrades and fixes for VMS sent in by Guy Streeter
  *        21-may-86
  *        - fixed an Aztec bug in ttgetc by clearing the upper byte
  *        - fixed buf in CMODE with #preprocesser input (bug fix submitted by
  *          Willis of unknown path)
  *        - added support of alternative startup file ( @<filename> ) in
  *          the command line
  *        - added ^Q quoting in interactive input (mlreplyt()).
  *        - added re-binding of meta-prefix and ctlx-prefix
  *        22-may-86
  *        - reorganized getkey routines to make more sense and let prefix
  *          binding work properly.
  *        23-may-86
  *        - checked new code on BSD4.2 and made a few fixes
  *        - added optional fence matching while in CMODE
  *        - added goto and search command line arguments by Mike Spitzer
  *        26-may-86
  *        - added parameter fetching from buffers
  *        27-may-86
  *        - fixed some HP150 bugs......
  *        31-may-86
  *        - Added Wang PC keyboard support from modifications by
  *          Sid Shapiro @ Wang Institute
  *        - Fixed some reverse video bugs with code submitted by Peter Chubb
  *        - Fixed bug in nextbuffer reported by Dave Forslund
  *        - added system V support (USG) from Linwood Varney
  *        2-jun-86
  *        - changed defines to just define one Unix define (for example,
  *          just define BSD for Unix BSD 4.2)
  *        - Added Incremental search functions written by D. R. Banks
  *          in file ISEARCH.C
  *        - added insert-string (unbound) command to help the macro
  *          language out.
  *        - added unmark-buffer (M-~) command to turn off the current buffers
  *          change flag
  *        - fixed nxtarg to truncate strings longer than asked for max length
  *        4-jun-86
  *        - added special characters in command line tokens. Tilde (~) is
  *          the special lead-in character for "nrtb".
  *        - Fixed bad ifdef in Aztec code so it could look at HOME dir
  *          for startup, help, and emacs.rc files
  *        6-jun-86
  *        - make delete word commands clear the kill buffer if not after anot
  *          kill command
  *        11-jun-86
  *        - made ~@ in string arguments pass as char(192) to nxtarg() so one
  *          quote @ at the beginning of string arguments
  *        - changed buffer size vars in listbuffers() to long (for big files)
  *        - re-wrote buffer-position command to be much faster
  *        12-jun-86
  *        - added count-words (M-^C) command to count the words/chars and
  *          lines in a region
  *        - changed regions so they could be larger than 65535 (short ->
  *          long in the REGION structure)
  *        - changed ldelete() and all callers to use a long size. The kill
  *          buffer will still have a problem >65535 that can not be solved
  *          until I restructure it.
  *        - grouped paragraph commands and word count together under symbol
  *          WORDPRO to allow them to be conditionally made (or not)
  *        13-jun-86
  *        - re-wrote kill buffer routines again. Now they support an unlimite
  *          size kill buffer, and are (in theory) faster.
  *        - changed delete-next-word (M-D) to not eat the newline after a wor
  *          instead it checks and eats a newline at the cursor.
  *        17-jun-86
  *        - added numeric argument to next/previous-window to access the nth
  *          window from the top/bottom
  *        - added support for the Data General 10 MSDOS machine
  *        - added save-window (unbound) and restore-window (unbound) commands
  *          for the use of the menu script. Save-window remembers which windo
  *          is current, and restore-window returns the cursor to that window.
  *        20-jun-86
  *        - fixed a bug with the fence matching locking up near the beginning
  *          of a buffer
  *        - added argument to update to selectively force a complete update
  *        - added update-screen (unbound) command so macros can force a
  *          screen update
  *        21-jun-86
  *        - rearranged token() and nxtarg() calls so that command names and
  *          repeat counts could also be prompted and fetched from buffers
  *          [this broke later with the exec re-write....]
  *        - added write-message (unbound) command to write out a message
  *          on the message line (for macros)
  *        - changed ifdef's so that color modes are recognized as legal in
  *          b/w version, and simply do nothing (allowing us to use the same
  *          script files)
  *        [Released version 3.7 on July 1 to the net and elswhere]
  *        2-jul-86
  *        - Changed search string terminator to always be the meta character
  *          even if it is rebound.
  *        3-jul-86
  *        - removed extra calls to set color in startup code. This caused the
  *          original current window to always be the global colors.
  *        7-jul-86
  *        - Fixed bugs in mlreplyt() to work properly with all terminators
  *          including control and spec characters
  *        22-jul-86
  *        - fixed replaces() so that it will return FALSE properly on the
  *          input of the replacement string.
  *        - added a definition for FAILED as a return type.....
  *        - changed version number to 3.7b
  *        23-jul-86
  *        - fixed o -> 0 problem in TERMIO.C
  *        - made ^U universal-argument re-bindable
  *        - wrote atoi() for systems (like Aztec) where it acts strangely
  *        - changed version number to 3.7c
  *        25-jul-86
  *        - make ^G abort-command rebindable
  *        29-jul-86
  *        - added HP110 Portable Computer support
  *        - changed version number to 3.7d
  *        30-jul-86
  *        - Fixed a couple of errors in the new VMS code as pointer
  *          out by Ken Shacklford
  *        - split terminal open/close routines into screen and keyboard
  *          open/close routines
  *        - closed the keyboard during all disk I/O so that OS errors
  *          can be respoded to correctly (especially on the HP150)
  *        - changed version number to 3.7e
  *        31-jul-86
  *        - added label-function-key (unbound) command under symbol FLABEL
  *          (primarily for the HP150)
  *        4-aug-86
  *        - added fixes for Microsoft C as suggested by ihnp4!ihuxm!gmd1
  *                <<remember to fix [list] deletion bug as reported
  *                  by craig@hp-pcd>>
  *        8-aug-86
  *        - fixed beginning misspelling error everywhere
  *        - fixed some more MSC errors
  *        - changed version number to 3.7g
  *        20-aug-86
  *        - fixed CMODE .h scanning bug
  *        - changed version number to 3.7h
  *        30-aug-86
  *        - fixed killing renamed [list] buffer (it can't) as submitted
  *          by James Aldridge
  *        - Added code to allow multiple lines to display during
  *          vertical retrace
  *          [total disaster....yanked it back out]
  *        9-sep-86
  *        - added M-A (apropos) command to list commands containing a substri
  *        - fixed an inefficiency in the display update code submitted
  *          by William W. Carlson (wwc@pur-ee)
  *        10-sep-86
  *        - added Dana Hoggatt's code for encryption and spliced it into the
  *          proper commands. CRYPT mode now triggers encryption.
  *        - added -k flag to allow encryption key (no spaces) in command line
  *        14-sep-86
  *        - added missing lastflag/thisflag processing to docmd()
  *        - changed version to 3.7i and froze for partial release via mail
  *          and BBS
  *        05-oct-86
  *        - changed some strcpys in MAIN.C to strncpys as suggested by John
  *          Gamble
  *        - replaces SEARCH.C and ISEARCH.C with versions modified by
  *          John Gamble
  *        10-oct-86
  *        - removed references to lflick....it just won't work that way.
  *        - removed defines LAT2 and LAT3...the code no longer is Lattice
  *          version dependant.
  *        14-oct-86
  *        - changed spawn so that it will not not pause if executed from
  *          a command line
  *        15-oct-86
  *        - added argument concatination (+) to the macro parsing
  *        - added [] as fence pairs
  *        16-oct-86
  *        - rewrote all macro line parsing routines and rearranged the
  *          mlreply code. Saved 6K!!! Have blazed the path for expanding
  *          the command language.
  *        17-oct-86
  *        - added new keyboard macro routines (plus a new level to the
  *          input character function)
  *        22-oct-86
  *        - improved EGA cursor problems
  *        - added -r (restricted) switch to command line for BBS use
  *        06-nov-86
  *        - fixed terminator declarations from char to int in getarg() and
  *          nxtarg() in EXEC.C as pointed out by John Gamble
  *        07-nov-86
  *        - made wordrap() user callable as wrap-word (M-FNW) and changed
  *          the getckey() routine so that illegal keystrokes (too many
  *          prefixes set) could be used for internal bindings. When word
  *          wrap conditions are met, the keystroke M-FNW is executed. Added
  *          word wrap check/call to newline().
  *        11-nov-86
  *        - added and checked support for Mark Williams C 86
  *        12-nov-86
  *        - added goto-matching-fence (M-^F) command to jump to a matching
  *          fence "({[]})" or beep if there is none. This can reframe the
  *          screen.
  *        - added code and structure elements to support change-screen-size
  *          command (M-^S) to change the number of lines being used by
  *          MicroEMACS.
  *        15-nov-86
  *        - finished debugging change-screen-size
  *        17-nov-86
  *        - Incorporated in James Turner's modifications for the Atari ST
  *                23-sep-86
  *                - added support for the Atari ST line of computers (jmt)
  *                  - added a '\r' to the end of each line on output and stri
  *                    it on input for the SHOW function from the desktop
  *                  - added 3 new mode functions (HIREZ, MEDREZ, and LOREZ);
  *                    chgrez routine in TERM structure; and MULTREZ define in
  *                    ESTRUCT.H to handle multiple screen resolutions
  *        [note....ST still not running under Lattice yet...]
  *        25-nov-86
  *        - Made the filter-buffer (^X-#) command not work on VIEW mode
  *          buffers
  *        - Made the quick-exit (M-Z) command throw out a newline after
  *          each message so they could be seen.
  *        26-nov-86
  *        - fixed a couple of bugs in change-screen-size (M-^S) command
  *        - changed file read behavior on long lines and last lines
  *          with no newline (it no longer throws the partial line out)
  *        - [as suggested by Dave Tweten] Made adding a ^Z to the end
  *          of an output file under MSDOS configurable under the
  *          CTRL-Z symbol in ESTRUCT.H
  *        - [Dave Tweten] Spawn will look up the "TMP" environment variable
  *          for use during various pipeing commands.
  *        - [Dave Tweten] changed pipe command under MSDOS to use '>>'
  *          instead of '>'
  *        04-dec-86
  *        - moved processing of '@' and '#' so that they can be outside
  *          the quotes in an argument, and added hooks to process '%' for
  *          environment and user variables.
  *        - modified IBMPC.C to sense the graphics adapter (CGA and MONO)
  *          at runtime to cut down on the number of versions.
  *        05-dec-86
  *        - changed macro directive character to "!" instead of "$" (see
  *          below) and fixed the standard .rc file to comply.
  *        - added code to interpret environment variables ($vars). Added
  *          hooks for built in functions (&func). So, to recap:
  *
  *                @<string>        prompt and return a string from the user
  *                #<buffer name>        get the next line from a buffer and a
  *                %<var>                get user variable <var>
  *                $<evar>                get environment variable <evar>
  *                &<func>                evaluate function <func>
  *
  *        - allowed repeat counts to be any of the above
  *        - added code to allow insert-string (unbound) to use its
  *          repeat count properly
  *        - added set (^X-A) command to set variables. Only works on
  *          environmental vars yet.
  *        9-dec-86
  *        - added some code for user defined variables...more to come
  *        - added options for malloc() memory pool tracking
  *        - preliminary user variables (%) working
  *        - changed terminal calls to macro's (to prepare for the new
  *          terminal drivers)
  *        15-dec-86
  *        - changed previous-line (^P) and next-line (^N) to return a
  *          FALSE at the end or beginning of the file so repeated
  *          macros involving them terminate properly!
  *        - added code for $CURCOL and $CURLINE
  *        20-dec-86
  *        - set (^X-A) now works with all vars
  *        - added some new functions
  *                  &ADD &SUB &TIMES &DIV &MOD &NEG &CAT
  *        - once again rearranged functions to control macro execution. Did
  *          away with getarg()
  *        23-dec-86
  *        - added string functions
  *                  &LEFt &RIGht &MID
  *        31-dec-86
  *        - added many logical functions
  *                  &NOT &EQUal &LESs &GREater
  *        - added string functions
  *                  &SEQual &SLEss &SGReater
  *        - added variable indirection with &INDirect
  *        - made fixes to allow recursive macro executions
  *          (improved speed during macro execution as well)
  *        3-jan-87
  *        - added $FLICKER to control flicker supression
  *        - made spawn commands restricted
  *        - cleaned up lots of unintentional int<->char problems
  *        4-jan-87
  *        - Fixed broken pipe-command (^X-@) command under MSDOS
  *        - added !IF  !ELSE  !ENDIF  directives and changed the
  *          name of !END to !ENDM....real slick stuff
  *        5-jan-87
  *        - quick-exit (M-Z) aborts on any filewrite errors
  *        8-jan-87
  *        - debugged a lot of the new directive and evaluation code.
  *          BEWARE of stack space overflows! (increasing stack to
  *          16K under MSDOS)
  *        - removed non-standard DEC Rainbow keyboard support...let someone
  *          PLEASE implement this in the standard manner using key bindings
  *          and send the results to me.
  *        - added change-screen-width () command and $CURWIDTH variable
  *        11-jan-87
  *        - fixed an incredibly deeply buried bug in vtputc and combined
  *          it with vtpute (saving about 200 bytes!)
  *        16-jan-87
  *        - added code to handle controlling multiple screen resolutions...
  *          allowed the IBM-PC driver to force Mono or CGA modes.
  *        - added current buffer name and filename variables
  *          $cbufname and $cfname
  *        18-jan-87
  *        - added $sres variable to control screen resolution
  *        - added $debug variable to control macro debugging code (no longer
  *          is this activated by GLOBAL spell mode)
  *        - fixed bug in -g command line option
  *        - Released Version 3.8 to BBSNET
  *        21-jan-87
  *        - added $status variable to record return status of last command
  *        2-feb-87
  *        - added ATARI 1040 support...runs in all three modes right now
  *        - added $palette var with palette value in it
  *        - undefined "register" in BIND.C and INPUT.C for ST520 & LATTICE
  *          to get around a nasty Lattice bug
  *        4-feb-87
  *        - added, debugged code for switching all 1040ST color modes, added
  *          code for HIGH monochrome mode as well, DENSE still pending
  *        5-feb-87
  *        - with John Gamble, found and corrected the infamous bad matching
  *          fence problems.
  *        - added error return check in various add/delete mode commands
  *        10-feb-87
  *        - re-arrange code in docmd() so that labels are stored in
  *          macro buffers
  *        - fixed !RETURN to only return if (execlevel == 0) [If we are
  *          currently executing]
  *        14-feb-87
  *        - added to outp() calls in the EGA driver to fix a bug in the BIOS
  *        - adding code for 1040ST 40 line DENSE mode (not complete)
  *        25-feb-87
  *        - added auto-save "ASAVE" mode....variables $asave and $acount
  *          control the frequency of saving and count until next save
  *        - added &and and &or as functions for logical anding and oring
  *        - added string length &LEN, upper and lower case string funtions
  *          &LOWER and &UPPER
  *        27-feb-87
  *        - added $lastkey   last keystroke struck and
  *                $curchar    character under cursor
  *        28-feb-87
  *        - added code for trim-line (^X^T) command and table entries
  *          for the entab-line (^X^E) and detab-line (^X^D) commands.
  *          These are conditional on AEDIT (Advanced editing) in estruct.h
  *        18-mar-87
  *        - finished above three commands
  *        - added $version environment variable to return the current
  *          MicroEMACS version number
  *        - added $discmd emvironment variable. This is a logical flag that
  *          indicates if emacs should be echoing commands on the command line
  *          real useful in order to stop flashing macros and .rc files
  *        - added $progname environment variable. this always returns the
  *          string "MicroEMACS". OEM's should change this so that macros can
  *          tell if they are running on an unmodified emacs or not.
  *        - fixed a minor bug in the CGA/MONO detection routine in IBMPC.C
  *        20-mar-87
  *        - integrated EGAPC.C into IBMPC.C and eliminated the file. Now an
  *          EGA user can switch from EGA to CGA modes at will
  *        - A LOT of little fixes and corrections sent in by John Ruply
  *        25-mar-87
  *        - Fixed buffer variables so they will work when referencing the
  *          current buffer
  *        26-mar-87
  *        - Fixed atoi() to be more reasonable. trailing whitespace ignored,
  *          only one leading sign, no non-digits allowed after the sign.
  *        - fixed buffer variables to go from the point to the end of
  *          line.
  *        28-mar-87
  *        - fixed bugs with 8 bit chars as submited by Jari Salminen
  *        - replace AZTEC/MSDOS agetc() with a1getc() which won't strip
  *          the high order bit
  *        30-mar-87
  *        - changed list-buffers (^X^B) so that with any argument, it will
  *          also list the normally invisable buffers
  *        - added store-procedure and execute-procedure/run (M-^E)
  *          commands to store and execute named procedures.
  *        31-mar-87
  *        - Fixed infinite loop in ^X-X command (when [LIST] is the
  *          only buffer left) as pointed out by John Maline
  *        - made filenames in getfile() always lower case as pointed
  *          out by John Maline
  *        2-apr-87
  *        - Fixed buffer variables so they would work on non-current displaye
  *          buffers. They should now work with ALL buffers....
  *        3-apr-87
  *        - Yanked AZTEC profiling code....not very useful
  *        - Modified IBMPC driver so it will not start in EGA mode
  *        - allow the next-buffer (^X-X) command to have a preceding
  *          non-negative argument.
  *        14-apr-87
  *        - added John Gamble's modified search.c. The code has cut apx
  *          200-300 bytes off the executable.
  *        - added the &RND function to generate a random integer between
  *          1 and its arguments value. Also $SEED is availible as the
  *          random number seed.
  *        - changed the -k command line switch so if there is no argument,
  *          it will prompt for one when the file is read
  *        15-apr-87
  *        - added 20 bytes of buffer in getval()'s local argument alloc so
  *          when it returns a value, it has enough stack space to do at least
  *          one strcpy() before stomping on the returned value. ALWAYS call
  *          getval() ONLY from within a strcpy() call.
  *        - made $curcol return a 1 based value instead of a zero based one.
  *          [changed this back later for 3.8o   it was simply wrong.....]
  *        16-apr-87
  *        - re-wrote strncpy() for AZTEC & MSDOS so it null terminates the
  *          string.
  *        - changed pipe() to pipecmd() to avoid conflicts with various
  *          UNIX systems
  *        24-apr-87
  *        - changed open parameters on AMIGA window open to 0/0/640/200
  *        [Froze and released v3.8i via BBS net]
  *        14-may-87
  *        - added nop (M-FNC) that gets called on every command loop
  *        - added $wline, returns and sets # lines in current window
  *        - added $cwline, returns and set current line within window
  *        - added $target, returns/sets target for line moves
  *        - added $search, returns/sets default search string
  *        - added $replace, returns/sets default replace string
  *        - added $match, returns last matched string in magic search
  *        29-may-87
  *        - rewrote word deletes to not kill trailing non-whitespace after
  *          the last word. Also a zero argument will cause it to just delete
  *          the word and nothing else.
  *        - more fixes for the search pattern environment variables
  *        30-may-87
  *        - forced all windows to redraw on a width change
  *        2-jun-87
  *        - forced clear-message-line to overide $discmd
  *        - added mlforce() routine and call it in clear-message-line,
  *          write-message and when $debug is TRUE
  *        - recoded the startup sequence in main()....Much Better...
  *        4-jun-87
  *        - forced interactive arguments ( @"question" ) to ALWAYS be echoed
  *          regardless of the setting of $discmd.
  *        7-jun-87
  *        - started adding support for Turbo C under MSDOS
  *        11-jun-87
  *        - words now include ONLY upper/lower case alphas and digits
  *        - fixed some more bugs with the startup..(ORed in the global modes)
  *        - took more limits off the self-insert list....
  *        16-jun-87
  *        - macro debugging now displays the name of the current macro.
  *        - fixed a problem in expandp() in search.c that kept high-byte
  *          characters from working in search strings
  *        18-jun-87
  *        - added &sindex <str1> <str2> function which searches for string 2
  *          within string 1
  *        [released verion 3.8o internally]
  *        19-jun-87
  *        - added $cmode and $gmode to return and set the mode of the
  *          current buffer and the global mode
  *        - separated findvar() out from setvar() so it could be used in
  *          the !LOOP directive (which got canned....read on)
  *        - %No such variable message now types the name of the offending
  *          variable
  *        22-jun-87
  *        - fixed startup bug when editing the startup file
  *        - added the !LOOP <var> <label> directive
  *        26-jun-87
  *        - dumped !LOOP......added !WHILE. This needed and caused a vaste
  *          reorginization in exec.c which mainly involved moving all the
  *          directive handling from docmd() to dobuf(), in the process
  *          getting rid of a lot of junk and making the result smaller
  *          than it started.....(yea!)
  *        - added $tpause to control the fence flashing time in CMODE.
  *          The value is machine dependant, but you can multiply the
  *          original in macros to stay machine independant. (as
  *          suggested by Baron O.A. Grey)
  *        - added hook to execute M-FNR (null) during a file read, after
  *          the name is set and right before the file is read. Took out
  *          any auto-CMODE code, as this is now handled with a macro.
  *          (also suggested by Baron O.A. Grey)
  *        - Added Baron O.A. Grey's SYSTEM V typeahead() code...I hope
  *          this works....if you check this out, drop me a line.
  *        - Added new variable $pending, returns a logical telling if
  *          a typed ahead character is pending.
  *        29-jun-87
  *        - Made adjustmode() use curbp-> instead of curwp->w_bufp-> which
  *          fixed some bugs in the startup routines.
  *        - added $lwidth to return the length of the current line
  *        2-jul-87
  *        - Added &env <str> which returns the value of the environment
  *          variable <str> where possible
  *        - Fixed a NASTY bug in execbuf()..the buffer for the name
  *          of the buffer to execute was NBUFN long, and got overflowed
  *          with a long interactive argument.
  *        3-jul-87
  *        - Moved the loop to match a key against its binding out of execute(
  *          to getbind() so it could be used later elsewhere.
  *        - Added &bind <keyname> which returns the function bound to the
  *          named key
  *        - changed execute-file to look in the executable path first...
  *        6-jul-87
  *        - changed $curchar to return a newline at the end of a line and
  *          it no longer advances the cursor
  *        - a lot of minor changes sent by various people....
  *        7-jul-87
  *        - some amiga specific fixes as suggested by Kenn Barry
  *        - added $line [read/write] that contains the current line in the
  *          current buffer
  *        - changed $curcol so setting it beyond the end of the line will
  *          move the cursor to the end of the line and then fail.
  *        10-jul-87
  *        - added a number of fixes and optimizations along with the rest
  *          of the TURBO-C support as submited by John Maline
  *        13-jun-87
  *        - caused dobuf() to copy lastflag to thisflag so the first
  *          command executed will inherit the lastflag from the command
  *          before the execute-buffer command. (needed this for smooth
  *          scrolling to work)
  *        - made flook() look first in the $HOME directory, then in the
  *          current directory, then down the $PATH, and then in the
  *          list in epath.h
  *        14-jul-87
  *        - added some fixes for VMS along with support for the SMG
  *          screen package as submited by Curtis Smith
  *        15-jul-87
  *        - fixed M-^H (delete-previous-word) so it can delete the first
  *          word in a file....I think there may be more of this kind of thing
  *          to fix.
  *        16-jul-87
  *        - added code to allow arbitrary sized lines to be read from files..
  *          speed up file reading in the process.
  *        - made out of memory conditions safer.. especial on file reads
  *        - fixed a bug in bind having to do with uppercasing function
  *          key names (submitted by Jari Salminen)
  *        - made ST520 exit in the same resolution that EMACS was started in
  *          (for the 1040ST)
  *        [FROZE development and released version 3.9 to USENET]
  */

 #include        <stdio.h>

 /* for MSDOS, increase the default stack space */

 #if        MSDOS & LATTICE
 unsigned _stack = 32767;
 #endif

 #if        ATARI & LATTICE & 0
 int _mneed = 256000;                /* reset memory pool size */
 #endif

 #if        MSDOS & AZTEC
 int _STKSIZ = 32767/16;                /* stack size in paragraphs */
 int _STKRED = 1024;                /* stack checking limit */
 int _HEAPSIZ = 4096/16;                /* (in paragraphs) */
 int _STKLOW = 0;                /* default is stack above heap (small only) *
 #endif

 #if        MSDOS & TURBO
 unsigned _stklen = 32768;
 #endif

 /* make global definitions not external */
 #define        maindef

        "estruct.h"        /* global structures and defines */
        "efunc.h"        /* function declarations and name table        */
        "edef.h"        /* global definitions */
        "ebind.h"        /* default key bindings */

 #if     VMS
 #include        <ssdef.h>
 #define GOOD    (SS$_NORMAL)
 #endif

 #ifndef GOOD
 #define GOOD    0
 #endif

 main(argc, argv)
 char    *argv[];
 {
         register int    c;                /* command character */
         register int    f;                /* default flag */
         register int    n;                /* numeric repeat count */
         register int    mflag;                /* negative flag on repeat */
         register BUFFER *bp;                /* temp buffer pointer */
         register int        firstfile;        /* first file flag */
         register int        carg;                /* current arg to scan */
         register int        startflag;        /* startup executed flag */
         BUFFER *firstbp = NULL;                /* ptr to first buffer in cmd
         int basec;                        /* c stripped of meta character */
         int viewflag;                        /* are we starting in view mode?
         int gotoflag;                   /* do we need to goto a line at start
         int gline;                      /* if so, what line? */
         int searchflag;                 /* Do we need to search at start? */
         int saveflag;                        /* temp store for lastflag */
         char bname[NBUFN];                /* buffer name of file to read */
 #if        CRYPT
         int cryptflag;                        /* encrypting on the way in? */
         char ekey[NPAT];                /* startup encryption key */
 #endif
         char *strncpy();
         extern *pathname[];                /* startup file path/name array */

         /* initialize the editor */
         vtinit();                /* Display */
         edinit("main");                /* Buffers, windows */
         varinit();                /* user variables */

         viewflag = FALSE;        /* view mode defaults off in command line */
         gotoflag = FALSE;        /* set to off to begin with */
         searchflag = FALSE;        /* set to off to begin with */
         firstfile = TRUE;        /* no file to edit yet */
         startflag = FALSE;        /* startup file not executed yet */
 #if        CRYPT
         cryptflag = FALSE;        /* no encryption by default */
 #endif

         /* Parse the command line */
         for (carg = 1; carg < argc; ++carg) {

                 /* Process Switches */
                 if (argv[carg][0] == '-') {
                         switch (argv[carg][1]) {
                                 case 'e':        /* -e for Edit file */
                                 case 'E':
                                         viewflag = FALSE;
                                         break;
                                 case 'g':        /* -g for initial goto */
                                 case 'G':
                                         gotoflag = TRUE;
                                         gline = atoi(&argv[carg][2]);
                                         break;
 #if        CRYPT
                                 case 'k':        /* -k<key> for code key */
                                 case 'K':
                                         cryptflag = TRUE;
                                         strcpy(ekey, &argv[carg][2]);
                                         break;
 #endif
                                 case 'r':        /* -r restrictive use */
                                 case 'R':
                                         restflag = TRUE;
                                         break;
                                 case 's':        /* -s for initial search str
                                 case 'S':
                                         searchflag = TRUE;
                                         strncpy(pat,&argv[carg][2],NPAT);
                                         break;
                                 case 'v':        /* -v for View File */
                                 case 'V':
                                         viewflag = TRUE;
                                         break;
                                 default:        /* unknown switch */
                                         /* ignore this for now */
                                         break;
                         }

                 } else if (argv[carg][0]== '@') {

                         /* Process Startup macroes */
                         if (startup(&argv[carg][1]) == TRUE)
                                 /* don't execute emacs.rc */
                                 startflag = TRUE;

                 } else {

                         /* Process an input file */

                         /* set up a buffer for this file */
                         makename(bname, argv[carg]);
                         unqname(bname);

                         /* set this to inactive */
                         bp = bfind(bname, TRUE, 0);
                         strcpy(bp->b_fname, argv[carg]);
                         bp->b_active = FALSE;
                         if (firstfile) {
                                 firstbp = bp;
                                 firstfile = FALSE;
                         }

                         /* set the modes appropriatly */
                         if (viewflag)
                                 bp->b_mode |= MDVIEW;
 #if        CRYPT
                         if (cryptflag) {
                                 bp->b_mode |= MDCRYPT;
                                 crypt((char *)NULL, 0);
                                 crypt(ekey, strlen(ekey));
                                 strncpy(bp->b_key, ekey, NPAT);
                         }
 #endif
                 }
         }

         /* if invoked with no other startup files,
            run the system startup file here */
         if (startflag == FALSE) {

                 /* if emacs.rc is one of the input files....don't clobber it
                 if (!firstfile && strcmp(pathname[0], firstbp->b_bname) == 0)
                         c = firstbp->b_bname[0];
                         firstbp->b_bname[0] = '[';
                         startup("");
                         firstbp->b_bname[0] = c;
                 } else {
                         startup("");
                 }
                 startflag = TRUE;
         }

         /* if there are any files to read, read the first one! */
         bp = bfind("main", FALSE, 0);
         if (firstfile == FALSE) {
                 swbuffer(firstbp);
                 curbp->b_mode |= gmode;
                 zotbuf(bp);
         } else
                 bp->b_mode |= gmode;

         /* Deal with startup gotos and searches */
         if (gotoflag && searchflag) {
                 update(FALSE);
                 mlwrite("[Can not search and goto at the same time!]");
         }
         else if (gotoflag) {
                 if (gotoline(TRUE,gline) == FALSE) {
                         update(FALSE);
                         mlwrite("[Bogus goto argument]");
                 }
         } else if (searchflag) {
                 if (forwhunt(FALSE, 0) == FALSE)
                         update(FALSE);
         }

         /* setup to process commands */
         lastflag = 0;                           /* Fake last flags.     */

 loop:
         /* execute the "command" macro...normally null */
         saveflag = lastflag;        /* preserve lastflag through this */
         execute(META|SPEC|'C', FALSE, 1);
         lastflag = saveflag;

         /* Fix up the screen    */
         update(FALSE);

         /* get the next command from the keyboard */
         c = getcmd();

         /* if there is something on the command line, clear it */
         if (mpresf != FALSE) {
                 mlerase();
                 update(FALSE);
 #if        CLRMSG
                 if (c == ' ')                   /* ITS EMACS does this  */
                         goto loop;
 #endif
         }
         f = FALSE;
         n = 1;

         /* do META-# processing if needed */

         basec = c & ~META;                /* strip meta char off if there */
         if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
                 f = TRUE;                /* there is a # arg */
                 n = 0;                        /* start with a zero default */
                 mflag = 1;                /* current minus flag */
                 c = basec;                /* strip the META */
                 while ((c >= '0' && c <= '9') || (c == '-')) {
                         if (c == '-') {
                                 /* already hit a minus or digit? */
                                 if ((mflag == -1) || (n != 0))
                                         break;
                                 mflag = -1;
                         } else {
                                 n = n * 10 + (c - '0');
                         }
                         if ((n == 0) && (mflag == -1))        /* lonely - */
                                 mlwrite("Arg:");
                         else
                                 mlwrite("Arg: %d",n * mflag);

                         c = getcmd();        /* get the next key */
                 }
                 n = n * mflag;        /* figure in the sign */
         }

         /* do ^U repeat argument processing */

         if (c == reptc) {                  /* ^U, start argument   */
                 f = TRUE;
                 n = 4;                          /* with argument of 4 */
                 mflag = 0;                      /* that can be discarded. */
                 mlwrite("Arg: 4");
                 while ((c=getcmd()) >='0' && c<='9' || c==reptc || c=='-'){
                         if (c == reptc)
                                 if ((n > 0) == ((n*4) > 0))
                                         n = n*4;
                                 else
                                         n = 1;
                         /*
                          * If dash, and start of argument string, set arg.
                          * to -1.  Otherwise, insert it.
                          */
                         else if (c == '-') {
                                 if (mflag)
                                         break;
                                 n = 0;
                                 mflag = -1;
                         }
                         /*
                          * If first digit entered, replace previous argument
                          * with digit and set sign.  Otherwise, append to arg
                          */
                         else {
                                 if (!mflag) {
                                         n = 0;
                                         mflag = 1;
                                 }
                                 n = 10*n + c - '0';
                         }
                         mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
                 }
                 /*
                  * Make arguments preceded by a minus sign negative and chang
                  * the special argument "^U -" to an effective "^U -1".
                  */
                 if (mflag == -1) {
                         if (n == 0)
                                 n++;
                         n = -n;
                 }
         }

         /* and execute the command */
         execute(c, f, n);
         goto loop;
 }

 /*
  * Initialize all of the buffers and windows. The buffer name is passed down
  * as an argument, because the main routine may have been told to read in a
  * file by default, and we want the buffer name to be right.
  */
 edinit(bname)
 char    bname[];
 {
         register BUFFER *bp;
         register WINDOW *wp;
         char *malloc();

         bp = bfind(bname, TRUE, 0);             /* First buffer         */
         blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer   */
         wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window         */
         if (bp==NULL || wp==NULL || blistp==NULL)
                 exit(1);
         curbp  = bp;                            /* Make this current    */
         wheadp = wp;
         curwp  = wp;
         wp->w_wndp  = NULL;                     /* Initialize window    */
         wp->w_bufp  = bp;
         bp->b_nwnd  = 1;                        /* Displayed.           */
         wp->w_linep = bp->b_linep;
         wp->w_dotp  = bp->b_linep;
         wp->w_doto  = 0;
         wp->w_markp = NULL;
         wp->w_marko = 0;
         wp->w_toprow = 0;
 #if        COLOR
         /* initalize colors to global defaults */
         wp->w_fcolor = gfcolor;
         wp->w_bcolor = gbcolor;
 #endif
         wp->w_ntrows = term.t_nrow-1;           /* "-1" for mode line.  */
         wp->w_force = 0;
         wp->w_flag  = WFMODE|WFHARD;            /* Full.                */
 }

 /*
  * This is the general command execution routine. It handles the fake binding
  * of all the keys to "self-insert". It also clears out the "thisflag" word,
  * and arranges to move it to the "lastflag", so that the next command can
  * look at it. Return the status of command.
  */
 execute(c, f, n)
 {
         register int status;
         int (*execfunc)();                /* ptr to function to execute */
         int (*getbind())();

         /* if the keystroke is a bound function...do it */
         execfunc = getbind(c);
         if (execfunc != NULL) {
                 thisflag = 0;
                 status         = (*execfunc)(f, n);
                 lastflag = thisflag;
                 return (status);
         }

         /*
          * If a space was typed, fill column is defined, the argument is non-
          * negative, wrap mode is enabled, and we are now past fill column,
          * and we are not read-only, perform word wrap.
          */
         if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
             n >= 0 && getccol(FALSE) > fillcol &&
             (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
                 execute(META|SPEC|'W', FALSE, 1);

         if ((c>=0x20 && c<=0xFF)) {        /* Self inserting.      */
                 if (n <= 0) {                   /* Fenceposts.          */
                         lastflag = 0;
                         return (n<0 ? FALSE : TRUE);
                 }
                 thisflag = 0;                   /* For the future.      */

                 /* if we are in overwrite mode, not at eol,
                    and next char is not a tab or we are at a tab stop,
                    delete a char forword                        */
                 if (curwp->w_bufp->b_mode & MDOVER &&
                     curwp->w_doto < curwp->w_dotp->l_used &&
                         (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
                          (curwp->w_doto) % 8 == 7))
                                 ldelete(1L, FALSE);

                 /* do the appropriate insertion */
                 if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
                         status = insbrace(n, c);
                 else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
                         status = inspound();
                 else
                         status = linsert(n, c);

 #if        CFENCE
                 /* check for CMODE fence matching */
                 if ((c == '}' || c == ')' || c == ']') &&
                                 (curbp->b_mode & MDCMOD) != 0)
                         fmatch(c);
 #endif

                 /* check auto-save mode */
                 if (curbp->b_mode & MDASAVE)
                         if (--gacount == 0) {
                                 /* and save the file if needed */
                                 upscreen(FALSE, 0);
                                 filesave(FALSE, 0);
                                 gacount = gasave;
                         }

                 lastflag = thisflag;
                 return (status);
         }
         TTbeep();
         mlwrite("[Key not bound]");                /* complain
         lastflag = 0;                           /* Fake last flags.     */
         return (FALSE);
 }

 /*
  * Fancy quit command, as implemented by Norm. If the any buffer has
  * changed do a write on that buffer and exit emacs, otherwise simply exit.
  */
 quickexit(f, n)
 {
         register BUFFER *bp;        /* scanning pointer to buffers */
         register BUFFER *oldcb; /* original current buffer */
         register int status;

         oldcb = curbp;                          /* save in case we fail */

         bp = bheadp;
         while (bp != NULL) {
                 if ((bp->b_flag&BFCHG) != 0        /* Changed.             */
                 && (bp->b_flag&BFINVS) == 0) {        /* Real.
                         curbp = bp;                /* make that buffer cur
                         mlwrite("[Saving %s]",bp->b_fname);
                         mlwrite("\n");
                         if ((status = filesave(f, n)) != TRUE) {
                                 curbp = oldcb;        /* restore curbp */
                                 return(status);
                         }
                 }
         bp = bp->b_bufp;                        /* on to the next buffer */
         }
         quit(f, n);                             /* conditionally quit   */
         return(TRUE);
 }

 /*
  * Quit command. If an argument, always quit. Otherwise confirm if a buffer
  * has been changed and not written out. Normally bound to "C-X C-C".
  */
 quit(f, n)
 {
         register int    s;

         if (f != FALSE                          /* Argument forces it.  */
         || anycb() == FALSE                     /* All buffers clean.   */
                                                 /* User says it's OK.   */
         || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
 #if        FILOCK
                 if (lockrel() != TRUE) {
                         TTputc('\n');
                         TTputc('\r');
                         TTclose();
                         TTkclose();
                         exit(1);
                 }
 #endif
                 vttidy();
                 exit(GOOD);
         }
         mlwrite("");
         return (s);
 }

 /*
  * Begin a keyboard macro.
  * Error if not at the top level in keyboard processing. Set up variables and
  * return.
  */
 ctlxlp(f, n)
 {
         if (kbdmode != STOP) {
                 mlwrite("%%Macro already active");
                 return(FALSE);
         }
         mlwrite("[Start macro]");
         kbdptr = &kbdm[0];
         kbdend = kbdptr;
         kbdmode = RECORD;
         return (TRUE);
 }

 /*
  * End keyboard macro. Check for the same limit conditions as the above
  * routine. Set up the variables and return to the caller.
  */
 ctlxrp(f, n)
 {
         if (kbdmode == STOP) {
                 mlwrite("%%Macro not active");
                 return(FALSE);
         }
         if (kbdmode == RECORD) {
                 mlwrite("[End macro]");
                 kbdmode = STOP;
         }
         return(TRUE);
 }

 /*
  * Execute a macro.
  * The command argument is the number of times to loop. Quit as soon as a
  * command gets an error. Return TRUE if all ok, else FALSE.
  */
 ctlxe(f, n)
 {
         if (kbdmode != STOP) {
                 mlwrite("%%Macro already active");
                 return(FALSE);
         }
         if (n <= 0)
                 return (TRUE);
         kbdrep = n;                /* remember how many times to execute */
         kbdmode = PLAY;                /* start us in play mode */
         kbdptr = &kbdm[0];        /*    at the beginning */
         return(TRUE);
 }

 /*
  * Abort.
  * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
  * Sometimes called as a routine, to do general aborting of stuff.
  */
 ctrlg(f, n)
 {
         TTbeep();
         kbdmode = STOP;
         mlwrite("[Aborted]");
         return(ABORT);
 }

 /* tell the user that this command is illegal while we are in
    VIEW (read-only) mode                                */

 rdonly()

 {
         TTbeep();
         mlwrite("[Key illegal in VIEW mode]");
         return(FALSE);
 }

 resterr()

 {
         TTbeep();
         mlwrite("[That command is RESTRICTED]");
         return(FALSE);
 }

 nullproc()        /* user function that does NOTHING */

 {
 }

 meta()        /* dummy function for binding to meta prefix */
 {
 }

 cex()        /* dummy function for binding to control-x prefix */
 {
 }

 unarg()        /* dummy function for binding to universal-argument */
 {
 }

 /*****                Compiler specific Library functions        ****/

 #if        MWC86 & MSDOS
 movmem(source, dest, size)

 char *source;        /* mem location to move memory from */
 char *dest;        /* memory location to move text to */
 int size;        /* number of bytes to move */

 {
         register int i;

         for (i=0; i < size; i++)
                 *dest++ = *source++;
 }
 #endif

 #if        (AZTEC | MSC | TURBO | LATTICE) & MSDOS
 /*        strncpy:        copy a string...with length restrictions
                         ALWAYS null terminate
 */

 char *strncpy(dst, src, maxlen)

 char *dst;        /* destination of copied string */
 char *src;        /* source */
 int maxlen;        /* maximum length */

 {
         char *dptr;        /* ptr into dst */

         dptr = dst;
         while (*src && (maxlen-- > 0))
                 *dptr++ = *src++;
         *dptr = 0;
         return(dst);
 }
 #endif

 #if        RAMSIZE & LATTICE & MSDOS
 /*        These routines will allow me to track memory usage by placing
         a layer on top of the standard system malloc() and free() calls.
         with this code defined, the environment variable, $RAM, will
         report on the number of bytes allocated via malloc.

         with SHOWRAM defined, the number is also posted on the
         end of the bottom mode line and is updated whenever it is changed.
 */

 #undef        malloc
 #undef        free

 char *allocate(nbytes)        /* allocate nbytes and track */

 unsigned nbytes;        /* # of bytes to allocate */

 {
         char *mp;        /* ptr returned from malloc */
         char *malloc();

         mp = malloc(nbytes);
         if (mp) {
                 envram += nbytes;
 #if        RAMSHOW
                 dspram();
 #endif
         }

         return(mp);
 }

 release(mp)        /* release malloced memory and track */

 char *mp;        /* chunk of RAM to release */

 {
         unsigned *lp;        /* ptr to the long containing the block size */

         if (mp) {
                 lp = ((unsigned *)mp) - 1;

                 /* update amount of ram currently malloced */
                 envram -= (long)*lp - 2;
                 free(mp);
 #if        RAMSHOW
                 dspram();
 #endif
         }
 }

 #if        RAMSHOW
 dspram()        /* display the amount of RAM currently malloced */

 {
         char mbuf[20];
         char *sp;

         TTmove(term.t_nrow - 1, 70);
 #if        COLOR
         TTforg(7);
         TTbacg(0);
 #endif
         sprintf(mbuf, "[%lu]", envram);
         sp = &mbuf[0];
         while (*sp)
                 TTputc(*sp++);
         TTmove(term.t_nrow, 0);
         movecursor(term.t_nrow, 0);
 }
 #endif
 #endif


 MALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\MALLOC.C

 /* 1.4  02-11-86                                                 (malloc.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985, 86        *
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         char *
 malloc(nbytes)        /* Return pointer to block of memory nbytes in size, or
                    NULL if none available.                                 */
 /*----------------------------------------------------------------------*/
 FAST unsigned nbytes;
 {
         char *allot();
         FAST HEADER *p;
         unsigned n_units();

         nbytes = (1 + n_units(nbytes)) * sizeof(HEADER);
         if (p = (HEADER *)allot(nbytes)) /* round up to align, allocate.*/
         {        p->s.size = nbytes;        /* size field in bytes.
                 p++;
         }
         return (char *) p;
 }

 /************************************************************************/
         VOID
 free(ap)                /* put block ap in free memory list.                *

 /*----------------------------------------------------------------------*/
 char *ap;
 {
         FAST HEADER *p;

         if (p)
         {        p = (HEADER *) ap - 1; /* at header left there by malloc() *
                 liberate(p, p->s.size);
         }
 }


 MALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\MALLOC.C

 #include <osbind.h>
 #include <stdio.h>
 #include <malloc.h>

 #define        MAXBLK                16
 #define        FREE                0x00
 #define        USED                0x80
 #define        NULLBLK                0x80000000L

 char        *_mblk[MAXBLK] = {                /* system memory heaps */
         NULL, NULL, NULL, NULL,
         NULL, NULL, NULL, NULL,
         NULL, NULL, NULL, NULL,
         NULL, NULL, NULL, NULL };

 long        _msiz[MAXBLK] = {                /* allocated heap sizes */
         0L, 0L, 0L, 0L,
         0L, 0L, 0L, 0L,
         0L, 0L, 0L, 0L,
         0L, 0L, 0L, 0L };

 /*
  *        Up to 16 heaps are allocated from the operating system as they are
  *        needed to fill requests for dynamic memory.  These heaps are them
  *        divided into blocks for parcelling out by the user-callable memory
  *        allocation routines.  If all the storage in a heap is freed, the he
  *        will be freed to the OS.  Each heap beings with a pointer to the fi
  *        free block, or NULL if there are no free blocks in this heap.  Each
  *        block begins with a 4-byte header which defines the number of bytes
  *        in the block, including the header.  Since blocks in a heap are kno
  *        to be contiguous, this value also defines the beginning of the next
  *        block in the heap.  The high bit of the header is set if the block
  *        is used and clear if it is free.  The heaps ends with a block heade
  *        which indicates a used block containing 0 bytes.  The is the consta
  *        value NULLBLK.  Free blocks contain an additional pointer field,
  *        immediatly following the header, which is a pointer to the header o
  *        the next free block, or NULL.
  */

 static char *makeblk(size)
 long size;
 /*
  *        Get a new major block from the system that will hold at least
  *        <size> bytes.
  */
 {
         register int i;
         register char *p;
         register long n, minsiz, bsiz, *q;

         minsiz = (size + 0x200L) & ~0x1FFL;        /* round up to nearest 512
         if(minsiz < _BLKSIZ)
                 bsiz = _BLKSIZ;
         else
                 bsiz = minsiz;
         for(i=0; i<MAXBLK; ++i) {
                 if(_mblk[i] != NULL)
                         continue;                /* skip used heaps */
                 n = Malloc(-1L);
                 n = ~0x1FFL & (n - 512L);        /* system memory available *
                 if(n < bsiz) {
                         if(n < minsiz)
                                 return(NULL);
                         else
                                 bsiz = minsiz;
                 }
                 _mblk[i] = p = Malloc(bsiz);
                 _msiz[i] = bsiz;
                 q = p + bsiz;                        /* thread starting block
                 q[-1] = NULLBLK;
                 q = p + 4L;
                 q[-1] = q;
                 q[0] = bsiz - 8L;
                 q[1] = NULL;
                 p[4] = FREE;
                 return(p);
         }
         return(NULL);
 }

 static char *splitblk(addr, size)
 register long **addr;
 register long size;
 /*
  *        Split block at *<addr> into a used block containing <size> bytes
  *        and a free block containing the remainder.
  */
 {
         register long n, *p, *q;

         n = *(p = *addr);                        /* get actual block size */
         if(n > (size + 8L)) {                        /* is it worth splitting
                 n -= size;
                 q = ((char *) p) + size;        /* calculate "break" point */
                 p[0] = size;
                 q[0] = n;
                 q[1] = p[1];
                 *addr = q;
         }
         else                                        /* not worth splitting */
                 *addr = p[1];                        /* remove from free list
         *((char *) p) = USED;                        /* mark block "used" */
         return(p);
 }

 static char *findblk(size)
 register long size;
 /*
  *        Find the smallest unused block containing at least <size> bytes.
  */
 {
         register int i;
         register long n, tsiz = 0x7FFFFFFFL, **p, *q, *tptr = NULL;

         for(i=0; i<MAXBLK; ++i) {
                 if((p = _mblk[i]) == NULL)
                         continue;                /* skip unavailable heaps */
                 while(q = *p) {
                         n = *q;
                         if((n >= size) && (n < tsiz)) {                /* it
                                 tsiz = n;
                                 tptr = p;
                         }
                         p = q + 1;
                 }
         }
         return(tptr);
 }

 /*--------------------- Documented Functions ---------------------------*/

 char *lalloc(size)
 register long size;
 /*
  *        Allocate at least <size> bytes of memory.  A pointer to the
  *        requested block is returned, or NULL if there is not enough
  *        free memory available.
  */
 {
         register char *p;

         if (size <= 4L)
                 size = 8L;                        /* minimum allocation */
         else
                 size = (size + 5L) & ~1L;        /* header & alignment */
         if((p = findblk(size)) == NULL)
                 if((p = makeblk(size)) == NULL)
                         return(NULL);
         p = splitblk(p, size);
         return(p + 4);                        /* skip over header */
 }

 char *malloc(size)
 unsigned int size;
 /*
  *        Allocate at least <size> bytes of memory.  A pointer to the
  *        requested block is returned, or NULL if there is not enough
  *        free memory available.
  */
 {
         return(lalloc((long) size));
 }

 char *calloc(n, size)
 unsigned int n;
 unsigned int size;
 /*
  *        Allocate space for an array of <n> element of <size> bytes each.
  *        If the storage can be allocated, it is initialized to all zero.
  *        NULL is returned is there is not enough free memory.
  */
 {
         register long total;
         register char *p, *q;

         total = (((long) n) * ((long) size));
         if(p = lalloc(total))
                 for(q=p; total--; *q++ = 0)
                         ;
         return(p);
 }


 MANDIMG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\MANDEL\MANDIMG.C

 /****************************************************************************
 /* MODULE NAME:                                                             *
 /*    MANDMAKE - Nmemonic "compute MANDelbrot set and MAKE an image file"   *
 /*
 /* MODULE DESCRIPTION:
 /*    Computes an image file for a given area with a specified magnification*
 /*
 /* USAGE:
 /*    mandel begin_c_real begin_c_imag Xdots Ydots Range Output_file_name   *
 /*
 /* INPUT:
 /*    double  A_begin        The real portion of the beginning complex coordi
 /*    double  B_begin        The imaginary portion of the beginning coordinat
 /*    int     Xdots        The number of pixles of the desplay device in X.
 /*    int     Ydots        The number of pixles of the desplay device in Y.
 /*    int     Range        The zoom factor to use for the display.
 /*    FILE    Out_fl_nm The file that will contain the itteration data.     *
 /*
 /* OUTPUT:
 /*   An image file.
 /*
 /****************************************************************************
 
 /*---> Standard definitions and declares <---*/
 #include <stdio.h>
 #include <dos.h>

 /*---> Initialize global constants <---*/
 #define then
 #define begin {
 #define end }
 #define TRUE 1
 #define FALSE 0
 extern        double atof() ;
 extern        double sqrt() ;

 /*---> Define Structures <---*/
 struct RHEADER begin            /********************************************
    char          NAME[30] ; /* Image name.                                  *
    unsigned int  PIX_HT   ; /* Image height in pixles
    unsigned int  PIX_WDT  ; /* Image width in pixles.
    unsigned int  DAT_WDT  ; /* Data width in bytes.
    unsigned int  PIX_SIZ  ; /* Size of pixle in bits.
    unsigned int  PIX_FRM  ; /* Pixle format ( ie. b&w, gray, color, etc ) */
    unsigned int  COL_SET  ; /* Color Set ( ie. none, RBG, CMW, etc. )
    unsigned int  CMP_FMT  ; /* Compression Format  ( none, blk supress,..)*/
    end ; /*rheader*/            /********************************************

 main( ARGC, ARGV )

    /*---> Define Parameters <---*/
    int                     ARGC             ; /*
    char             *ARGV[]             ; /*

 begin        /*MANDEL*/

    /*---> Define Local Variables <---*/
    int                     ITTER     = 1000; /* Maximum number of itterations

    FILE             *fp        =  0  ; /* Output image file
    struct RHEADER    HEADER             ; /* Header record for new image file
    int                     INDX      =  0  ; /* General purpose counter.
    int                     INDY      =  0  ; /* General purpose counter.
    int                     INDZ      =  0  ; /* General purpose counter.
    int                     XDOTS     =  0  ; /* Number of display pixles in X
    int                     YDOTS     =  0  ; /* Number of display pixles in Y
    int                     RET_CODE  =  0  ; /* General purpose return code.
    double             XINC      = 0.0 ; /* Distance between pixles
    double             YINC      = 0.0 ; /* Distance between pixles
    double             A_BEGIN   = 0.0 ; /* Beginning coordinate. Real.
    double             B_BEGIN   = 0.0 ; /* Beginning coordinate. Imaginary. *
    double             RANGE     = 0.0 ; /* Zoom factor
    double             CA        = 0.0 ; /* Current coordinate. Real.
    double             CB        = 0.0 ; /* Current coordinate. Imaginary.   *
    double             ZA        = 0.0 ; /* Current itteration. Real.
    double             ZB        = 0.0 ; /* Current itteration. Imaginary.   *
    double             ZSIZE     = 0.0 ; /* Real distance of Z(A,B) from 0,0 *
    double             ZNEWA     = 0.0 ; /* Next itteration. Real.           *
    double             ZNEWB     = 0.0 ; /* Next itteration. Immaginary.
 
    /*---> Process runtime arguments <---*/
    if( ARGC < 7 ) then begin
       printf( "INVALID ARGUMENT COUNT of %d . . . . . .\n", ARGC ) ;
       printf( "Use :\n" ) ;
       printf( "mandimg X_real Y_imag  Xdots  Ydots  Range    Out_file\n\n");

       printf( "  e.g.  -2.000  -1.250   320   200    2.500   mandata.tmp\n" )
       printf( "        -1.500  -0.500   320   200    0.500   mandata.tmp\n" )
       printf( "        -1.250  -0.200   320   200    0.100   mandata.tmp\n" )
       printf( "        -1.250  -0.180   320   200    0.030   mandata.tmp\n" )
       printf( "        -1.235  -0.171   320   200    0.006   mandata.tmp\n" )
       printf( "        -1.233  -0.169   320   200    0.001   mandata.tmp\n" )
       printf( "        -1.233  -0.169   320   200    0.0001  mandata.tmp\n" )
       printf( "        -1.233  -0.169   320   200    0.00001 mandata.tmp\n" )
       return ;
       end   /*if*/
    A_BEGIN =  atof( ARGV[ 2 ] ) ;
    B_BEGIN =  atof( ARGV[ 1 ] ) ;
    XDOTS   =  atoi( ARGV[ 3 ] ) ;
    YDOTS   =  atoi( ARGV[ 4 ] ) ;
    RANGE   =  atof( ARGV[ 5 ] ) ;

    /*---> Open output file <---*/
    fp = fopen( ARGV[6], "w" ) ;
    if( fp == 0 ) then begin
       printf("Open ERROR on output file  : %s \n", ARGV[6] ) ;
       return ;
       end   /*if*/

    /*---> Setup image header <---*/
    strcpy( HEADER.NAME, "                             " ) ;
    sprintf( HEADER.NAME, "MB (%8.4f,%8.4f) %7.5f", B_BEGIN, A_BEGIN, RANGE )
    HEADER.PIX_HT   = YDOTS ;
    HEADER.PIX_WDT  = XDOTS ;
    HEADER.DAT_WDT  = XDOTS ;
    HEADER.PIX_SIZ  = 8           ;
    HEADER.PIX_FRM  = 0           ;
    HEADER.COL_SET  = 0           ;
    HEADER.CMP_FMT  = 0           ;

    /*---> Output image header <---*/
    fwrite( &HEADER, 1, 44, fp ) ;

    /*---> Report new header information <---*/
    printf( "The header is as follows : \n" ) ;
    printf( "   Name       : %s\n", HEADER.NAME     ) ;
    printf( "   Pixle Ht.  : %u\n", HEADER.PIX_HT   ) ;
    printf( "   Pixle Wdt. : %u\n", HEADER.PIX_WDT  ) ;
    printf( "   Data  Wdt. : %u\n", HEADER.DAT_WDT  ) ;
    printf( "   Pixle size : %u\n", HEADER.PIX_SIZ  ) ;
    printf( "   Pixle Fmt. : %u\n", HEADER.PIX_FRM  ) ;
    printf( "   Color Set  : %u\n", HEADER.COL_SET  ) ;
    printf( "   Comp. Fmt. : %u\n", HEADER.CMP_FMT  ) ;
    printf( "Beginning creation of image file . . . . \n" ) ;

    /*---> Compute complex spacing between pixles <---*/
    XINC = RANGE / (float)XDOTS ;
    YINC = RANGE / (float)YDOTS ;
 
    /*---> Loop to compute each pixle column value on 2-D Complex grid <---*/
    for( INDY=0; INDY < YDOTS; INDY++ ) begin

       /*---> Initialize for new row <---*/
       CA = YINC * INDY + B_BEGIN ;

       for( INDX=0; INDX < XDOTS; INDX++ ) begin

          /*---> Initialize for new column ( and pixle ) <---*/
          ZA = 0.0 ;
          ZB = 0.0 ;
          CB = XINC * INDX + A_BEGIN ;
          ZSIZE = sqrt(        CA*CA + CB*CB ) ;


          /*---> Loop to itterate for each ( Z**2 + C ) <---*/
          for( INDZ=0; (ZSIZE < 2) && (INDZ <= ITTER); INDZ++ ) begin
             ZNEWA = ( ZA*ZA ) - ( ZB*ZB ) + CA ;
             ZNEWB = ( 2*ZA*ZB ) + CB ;
             ZSIZE = sqrt( ZNEWA*ZNEWA + ZNEWB*ZNEWB ) ;
             ZA          = ZNEWA ;
             ZB          = ZNEWB ;
             end   /* for INDZ */

          /*---> Output results <---*/
          putc( (char)(INDZ / 4), fp ) ;

          end   /*for INDX*/

       /*---> Check for user requested exit. <---*/
       RET_CODE = kbhit() ;
       if( RET_CODE ) then begin
          INDX = XDOTS ;
          INDY = YDOTS ;
          end   /*if*/

       /*---> Report progress to user. <---*/
       printf("Processing for line %d is complete\n", INDY ) ;

       end   /*for INDY*/

    /*---> Exit <---*/
    return ;
    end         /* MANDEL */


 MANDMAKE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\MANDEL\MANDMAKE.C

 /****************************************************************************
 /* MODULE NAME:                                                             *
 /*    MANDMAKE - Nmemonic "compute MANDelbrot set and MAKE an image file"   *
 /*
 /* MODULE DESCRIPTION:
 /*    Computes, and stores the itteration number for each pixle in a given  *
 /*    area with a specified magnification.
 /*
 /* USAGE:
 /*    mandel begin_c_real begin_c_imag Xdots Ydots Range Output_file_name   *
 /*
 /* INPUT:
 /*    double  A_begin        The real portion of the beginning complex coordi
 /*    double  B_begin        The imaginary portion of the beginning coordinat
 /*    int     Xdots        The number of pixles of the desplay device in X.
 /*    int     Ydots        The number of pixles of the desplay device in Y.
 /*    int     Range        The zoom factor to use for the display.
 /*    FILE    Out_fl_nm The file that will contain the itteration data.     *
 /*
 /* PROCESS:  (Pseudo code)
 /*         Initialize global constants.
 /*         Define parameters.
 /*         Begin MANDEL.
 /*            Define local variables.
 /*            --- Insert pseudo code here ---
 /*         End MANDEL.
 /*
 /* OUTPUT:
 /*
 /* EQUATIONS/ALGORITHMS:                                                    *
 /*
 /* REFERENCES:
 /*
 /****************************************************************************
 
 /*---> Standard definitions and declares <---*/
 #include <stdio.h>
 #include <dos.h>

 /*---> Initialize global constants <---*/
 #define then
 #define begin {
 #define end }
 #define TRUE 1
 #define FALSE 0
 extern        double atof() ;
 extern        double sqrt() ;

 /*---> Define non-standard stack size <---*/
 int        _stack        =  20000 ;

 main( ARGC, ARGV )

    /*---> Define Parameters <---*/
    int                     ARGC             ; /*
    char             *ARGV[]             ; /*

 begin        /*MANDEL*/

    /*---> Define "variable" Local Variables <---*/
    int                     ITTER     = 1000; /* Maximum number of itterations
    double             HIST[1024]      ; /* Histogram

    /*---> Define Local Variables <---*/
    FILE             *tp        =  0  ;
    FILE             *fp        =  0  ;
    int                     INDX      =  0  ; /* General purpose counter.
    int                     INDY      =  0  ; /* General purpose counter.
    int                     INDZ      =  0  ; /* General purpose counter.
    int                     XDOTS     =  0  ; /* Number of display pixles in X
    int                     YDOTS     =  0  ; /* Number of display pixles in Y
    int                     RET_CODE  =  0  ;
    int                     COLOR     =  0  ;
    int                     Z               =  0  ; /*
    double             XINC      = 0.0 ; /* Distance between pixles
    double             YINC      = 0.0 ; /* Distance between pixles
    double             A_BEGIN   = 0.0 ; /* Beginning coordinate. Real.
    double             B_BEGIN   = 0.0 ; /* Beginning coordinate. Imaginary. *
    double             RANGE     = 0.0 ; /* Zoom factor
    double             CA        = 0.0 ; /* Current coordinate. Real.
    double             CB        = 0.0 ; /* Current coordinate. Imaginary.   *
    double             ZA        = 0.0 ; /* Current itteration. Real.
    double             ZB        = 0.0 ; /* Current itteration. Imaginary.   *
    double             ZSIZE     = 0.0 ; /* Real distance of Z(A,B) from 0,0 *
    double             ZNEWA     = 0.0 ; /* Next itteration. Real.           *
    double             ZNEWB     = 0.0 ; /* Next itteration. Immaginary.
    double             N               = 0.0 ; /* Running sum of PELS computed
    double             ZSUM      = 0.0 ; /* Running sum of INDZ (itterations)*
    double             ZSUMSQ    = 0.0 ; /* Running sum of squares of INDZ   *
    double             BAND[12]             ; /*
    double             COUNT             ; /*
    char              IN_BUF[80]      ; /*                                   *
 
    /*---> Process runtime arguments <---*/
    if( ARGC < 7 ) then begin
       printf( "INVALID ARGUMENT COUNT of %d . . . . . .\n", ARGC ) ;
       printf( "Use :\n" ) ;
       printf( "mandmake X_real Y_imag  Xdots  Ydots  Range    Out_file\n\n");

       printf( "  e.g.  -2.000  -1.250   320   200    2.500   mandata.tmp\n" )
       printf( "        -1.500  -0.500   320   200    0.500   mandata.tmp\n" )
       printf( "        -1.250  -0.200   320   200    0.100   mandata.tmp\n" )
       printf( "        -1.250  -0.180   320   200    0.030   mandata.tmp\n" )
       printf( "        -1.235  -0.171   320   200    0.006   mandata.tmp\n" )
       printf( "        -1.233  -0.169   320   200    0.001   mandata.tmp\n" )
       printf( "        -1.233  -0.169   320   200    0.0001  mandata.tmp\n" )
       printf( "        -1.233  -0.169   320   200    0.00001 mandata.tmp\n" )
       return ;
       end   /*if*/
    A_BEGIN =  atof( ARGV[ 2 ] ) ;
    B_BEGIN =  atof( ARGV[ 1 ] ) ;
    XDOTS   =  atoi( ARGV[ 3 ] ) ;
    YDOTS   =  atoi( ARGV[ 4 ] ) ;
    RANGE   =  atof( ARGV[ 5 ] ) ;

    /*---> Initialize <---*/
    for( INDX=0; INDX < 1005; INDX++ ) HIST[ INDX ] = 0.0 ;
    for( INDX=0; INDX <         12; INDX++ ) BAND[ INDX ] = 0.0 ;

    /*---> Open output file <---*/
    tp = fopen( "mandtemp.dat", "w" ) ;
    if( tp == 0 ) then begin
       printf("Open ERROR on output file  : %s \n", "mandtemp.dat" ) ;
       return ;
       end   /*if*/

    /*---> Compute complex spacing between pixles <---*/
    XINC = RANGE / (float)XDOTS ;
    YINC = RANGE / (float)YDOTS ;
 
    /*---> Loop to compute each pixle column value on 2-D Complex grid <---*/
    for( INDY=0; INDY < YDOTS; INDY++ ) begin

       /*---> Initialize for new row <---*/
       CA = YINC * INDY + B_BEGIN ;

       for( INDX=0; INDX < XDOTS; INDX++ ) begin

          /*---> Initialize for new column ( and pixle ) <---*/
          ZA = 0.0 ;
          ZB = 0.0 ;
          CB = XINC * INDX + A_BEGIN ;
          ZSIZE = sqrt(        CA*CA + CB*CB ) ;

          /*---> Loop to itterate for each ( Z**2 + C ) <---*/
          for( INDZ=0; (ZSIZE < 2) && (INDZ <= ITTER); INDZ++ ) begin
             ZNEWA = ( ZA*ZA ) - ( ZB*ZB ) + CA ;
             ZNEWB = ( 2*ZA*ZB ) + CB ;
             ZSIZE = sqrt( ZNEWA*ZNEWA + ZNEWB*ZNEWB ) ;
             ZA          = ZNEWA ;
             ZB          = ZNEWB ;
             end   /* for INDZ */

          /*---> Compute statistics <---*/
          HIST[ INDZ ]++ ;

          /*---> Output results <---*/
          fprintf( tp, "%d\n", INDZ ) ;

          end   /*for INDX*/

       /*---> Check for user requested exit. <---*/
       RET_CODE = kbhit() ;
       if( RET_CODE ) then begin
          N    = (float)INDY * (float)INDX  ;
          INDX = XDOTS ;
          INDY = YDOTS ;
          end   /*if*/

       /*---> Report progress to user. <---*/
       printf("Processing for line %d is complete\n", INDY ) ;

       end   /*for INDY*/
 
    /*---> Display input and computational parameters <---*/
    printf("If you wish the statistical summary to be printed rather than\n" )
    printf("just displayed on the CRT, then : \n" ) ;
    printf("            Turn on the printer,\n" ) ;
    printf("            Then push <ctrl> <PrtSc>\n" ) ;
    printf("            Finally, push <return> to continue :\n" ) ;
    printf("Otherwise just push <return> to continue :\n" ) ;
    gets() ;

    printf( "\n\n\n************ Mnadelbrot Set Computation system ************
    printf( "\nInput parameters were as follows :\n\n" ) ;
    printf( "     Beginning Coordinate (real) :  %f\n", A_BEGIN  ) ;
    printf( "     Beginning Coordinate (imag) :  %f\n", B_BEGIN  ) ;
    printf( "     Size (X) of screen          :  %d\n", XDOTS    ) ;
    printf( "     Size (Y) of screen          :  %d\n", YDOTS    ) ;
    printf( "     Range                       :  %e\n", RANGE    ) ;
    printf( "     Increment between pels in X :  %e\n", XINC     ) ;
    printf( "     Increment between pels in Y :  %e\n", YINC     ) ;
    printf( "     Itterations per pel         :  %d\n", ITTER    ) ;
    printf( "     Output file name            :  %s\n", ARGV[6] ) ;

    if( N == 0.0 ) then        N = (float)XDOTS * (float)YDOTS ;

    printf("Total Count was actually %f pels.\n", N ) ;
    printf( "Total expected pels was %f \n", (float)XDOTS * (float)YDOTS ) ;

    printf( "\nHISTOGRAM summary : \n" ) ;
    for( INDX=0; INDX < ITTER; INDX += 10 ) begin
       if( (INDX % 100) == 0 ) then printf("\n" ) ;
       printf( "%4d-%4d   %5.0f %5.0f %5.0f %5.0f %5.0f %5.0f %5.0f %5.0f %5.0
          INDX, INDX+9,
          HIST[INDX  ],HIST[INDX+1],HIST[INDX+2],HIST[INDX+3],HIST[INDX+4],
          HIST[INDX+5],HIST[INDX+6],HIST[INDX+7],HIST[INDX+8],HIST[INDX+9] );
       end   /*for*/
    printf("\n1000-       %5.0f\n", HIST[ 1000 ] ) ;
 
    /*---> (Re)open file(s) <---*/
    fclose( tp ) ;
    tp = fopen( "mandtemp.dat", "r" ) ;
    if( tp == 0 ) then begin
       printf("Open ERROR on input file  : %s \n", "mandtemp.dat" ) ;
       return ;
       end   /*if*/
    fp = fopen( ARGV[6], "w" ) ;
    if( fp == 0 ) then begin
       printf("Open ERROR on output file  : %s \n", ARGV[6] ) ;
       return ;
       end   /*if*/

    /*---> Output size <---*/
    fprintf( fp, "%d\n", XDOTS ) ;
    fprintf( fp, "%d\n", YDOTS ) ;

    /*---> Compute values for color bands <---*/
    COUNT = 0.0 ;
    N =        N / 10.0 ;
    INDZ = 0 ;
    for( INDX=0; INDX <= 1000; INDX++ ) begin
       COUNT += HIST[ INDX ] ;
       if( COUNT < N )                  then BAND[ 0 ] = (float)INDX ;
          else if( COUNT < 2.0*N ) then BAND[ 1 ] = (float)INDX ;
          else if( COUNT < 3.0*N ) then BAND[ 2 ] = (float)INDX ;
          else if( COUNT < 4.0*N ) then BAND[ 3 ] = (float)INDX ;
          else if( COUNT < 5.0*N ) then BAND[ 4 ] = (float)INDX ;
          else if( COUNT < 6.0*N ) then BAND[ 5 ] = (float)INDX ;
          else if( COUNT < 7.0*N ) then BAND[ 6 ] = (float)INDX ;
          else if( COUNT < 8.0*N ) then BAND[ 7 ] = (float)INDX ;
          else if( COUNT < 9.0*N ) then BAND[ 8 ] = (float)INDX ;
       end   /*for*/
 
    printf("Band boundries are : \n" ) ;
    for(INDX=0;INDX<=8;INDX++) printf("   %4.0f", BAND[ INDX ] ) ;
    printf("\n");

    /*---> Loop for each pixle <---*/
    for( INDY=0; INDY < YDOTS; INDY++ ) begin
       for( INDX=0; INDX < XDOTS; INDX++ ) begin

          /*---> Read value of pixle from input file <---*/
          fgets( IN_BUF, 80, tp ) ;
          Z = atoi( IN_BUF ) ;

          /*---> Compute pixle color value <---*/
          COLOR = 16 ;
          if(             (float)Z < BAND[0] ) then COLOR = 1 ;
             else if( (float)Z < BAND[1] ) then COLOR = 2 ;
             else if( (float)Z < BAND[2] ) then COLOR = 3 ;
             else if( (float)Z < BAND[3] ) then COLOR = 1 ;
             else if( (float)Z < BAND[4] ) then COLOR = 2 ;
             else if( (float)Z < BAND[5] ) then COLOR = 3 ;
             else if( (float)Z < BAND[6] ) then COLOR = 1 ;
             else if( (float)Z < BAND[7] ) then COLOR = 2 ;
             else if( (float)Z < BAND[8] ) then COLOR = 3 ;
                                    else COLOR = 0 ;

          /*---> Output results <---*/
          fprintf( fp, "%d\n", COLOR ) ;

          end   /*for X*/
       end   /*for Y*/

    /*---> Exit <---*/
    return ;
    end         /* MANDEL */


 MANDSHOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\MANDEL\MANDSHOW.C

 /****************************************************************************
 /* MODULE NAME:                                                             *
 /*    MANDSHOW - Nmemonic "SHOW  MANDelbrot set"                            *
 /*
 /* MODULE DESCRIPTION:
 /*    Colors, and displays a MANDelbrot image file for CGA.
 /*
 /* USAGE:
 /*    mandel  mandelbrot_image_file_name                                    *
 /*
 /* INPUT:
 /*    FILE    fp        The mandelbrot image file name.                     *
 /*
 /* PROCESS:  (Pseudo code)
 /*         Initialize global constants.
 /*         Define parameters.
 /*         Begin MANDEL.
 /*            Define local variables.
 /*            --- Insert pseudo code here ---
 /*         End MANDEL.
 /*
 /* OUTPUT:
 /*
 /* EQUATIONS/ALGORITHMS:                                                    *
 /*
 /* REFERENCES:
 /*
 /****************************************************************************
 
 /*---> Standard definitions and declares <---*/
 #include <stdio.h>
 #include <dos.h>

 /*---> Initialize global constants <---*/
 #define then
 #define begin {
 #define end }
 #define TRUE 1
 #define FALSE 0
 extern double atof() ;

 main( ARGC, ARGV )

    /*---> Define Parameters <---*/
    int                     ARGC             ; /*
    char             *ARGV[]             ; /*

 begin        /*MANDEL*/

    /*---> Define Local Variables <---*/
    FILE             *fp              ;
    int                     INDX      =  0  ; /* General purpose counter.
    int                     INDY      =  0  ; /* General purpose counter.
    int                     Z               =  0  ; /* Itteration value
    int                     XDOTS     =  0  ; /* Number of display pixles in X
    int                     YDOTS     =  0  ; /* Number of display pixles in Y
    int                     INTNO     =  0  ;
    int                     COLOR     =  0  ;
    int                     RET_CODE  =  0  ;
    char             *IN_BUF    =  0  ;
    double             N               = 0.0 ; /* Running sum of PELS computed
    union REGS INREGS                 ;
    union REGS OUTREGS                 ;

    /*---> Process runtime arguments <---*/
    if( ARGC < 2 ) then begin
       printf( "INVALID ARGUMENT COUNT of %d . . . . . .\n", ARGC-1 ) ;
       printf( "Use :   mandshow  mandelbrot_image_file_name   \n" ) ;
       return ;
       end   /*if*/

    /*---> Open input file <---*/
    fp = fopen( ARGV[1], "r" ) ;
    if( fp == 0 ) then begin
       printf("Open ERROR on input file  : %s \n", ARGV[1] ) ;
       return ;
       end   /*if*/

    /*---> Read X,Y dimensions <---*/
    fgets( IN_BUF, 80, fp ) ;
    XDOTS = atoi( IN_BUF ) ;
    fgets( IN_BUF, 80, fp ) ;
    YDOTS = atoi( IN_BUF ) ;

    /*---> Generate interrupt to set 320x200 color mode on CRT <---*/
    INTNO       = 0x10 ;
    INREGS.h.ah = 0x00 ;
    INREGS.h.al = 0x04 ;
    int86( INTNO, &INREGS, &OUTREGS ) ;

    /*---> Generate interrupt to set background color (0-Black) <---*/
    INTNO       = 0x10 ;
    INREGS.h.ah = 0x0b ;
    INREGS.h.bh = 0x00 ;
    INREGS.h.bl = 0x00 ;
    int86( INTNO, &INREGS, &OUTREGS ) ;

    /*---> Generate interrupt to set color palette (1,2,3-RGY) <---*/
    INTNO       = 0x10 ;
    INREGS.h.ah = 0x0b ;
    INREGS.h.bh = 0x01 ;
    INREGS.h.bl = 0x00 ;
    int86( INTNO, &INREGS, &OUTREGS ) ;

    /*---> Generate interrupt to set test pattern <---*/
    INTNO       = 0x10                     ;
    INREGS.h.ah = 0x0c                     ;
    INREGS.h.al = 0                     ;
    INREGS.x.dx = 5                     ;
    INREGS.x.cx = 5                     ;
    int86( INTNO, &INREGS, &OUTREGS ) ;
    INREGS.h.al = 1                     ;
    INREGS.x.dx = 7                     ;
    INREGS.x.cx = 7                     ;
    int86( INTNO, &INREGS, &OUTREGS ) ;
    INREGS.h.al = 2                     ;
    INREGS.x.dx = 9                     ;
    INREGS.x.cx = 9                     ;
    int86( INTNO, &INREGS, &OUTREGS ) ;
    INREGS.h.al = 3                     ;
    INREGS.x.dx = 11                     ;
    INREGS.x.cx = 11                     ;
    int86( INTNO, &INREGS, &OUTREGS ) ;

    /*---> Loop to compute each pixle column value on 2-D Complex grid <---*/
    for( INDY=0; INDY < YDOTS; INDY++ ) begin
       for( INDX=0; INDX < XDOTS; INDX++ ) begin

          /*---> Read value of pixle from input file <---*/
          fgets( IN_BUF, 80, fp ) ;
          COLOR = atoi( IN_BUF ) ;

          /*---> Generate interrupt to set current pixle <---*/
          INTNO = 0x10 ;
          INREGS.h.ah = 0x0c ;
          INREGS.x.dx = INDY ;
          INREGS.h.al = (char)COLOR           ;
          INREGS.x.cx = INDX                   ;
          int86( INTNO, &INREGS, &OUTREGS ) ;

          end   /*for INDX*/
       end   /*for INDY*/

    /*---> Pause for user response <---*/
    getch() ;

    /*---> Loop to draw vertical grid <---*/
    for( INDY=0; INDY < YDOTS; INDY++ ) begin
       for( INDX=0; INDX < XDOTS; INDX += (XDOTS / 10) ) begin
          INTNO = 0x10 ;
          INREGS.h.ah = 0x0c ;
          INREGS.x.dx = INDY ;
          INREGS.h.al = 0x00 ;
          INREGS.x.cx = INDX ;
          int86( INTNO, &INREGS, &OUTREGS ) ;
          end   /*for INDX*/
       end   /*for INDY*/

    /*---> Loop to draw horizontal grid <---*/
    for( INDY=0; INDY < YDOTS; INDY += (YDOTS / 10) ) begin
       for( INDX=0; INDX < XDOTS; INDX++ ) begin
          INTNO = 0x10 ;
          INREGS.h.ah = 0x0c ;
          INREGS.x.dx = INDY ;
          INREGS.h.al = 0x00 ;
          INREGS.x.cx = INDX ;
          int86( INTNO, &INREGS, &OUTREGS ) ;
          end   /*for INDX*/
       end   /*for INDY*/

    /*---> Pause for user response <---*/
    getch() ;

    /*---> Generate interrupt to set color palette (1,2,3-CMW) <---*/
    INTNO       = 0x10 ;
    INREGS.h.ah = 0x0b ;
    INREGS.h.bh = 0x01 ;
    INREGS.h.bl = 0x01 ;
    int86( INTNO, &INREGS, &OUTREGS ) ;

    /*---> Pause for user response <---*/
    getch() ;

    /*---> Generate interrupt to set 320x200 color mode on CRT <---*/
    INTNO       = 0x10 ;
    INREGS.h.ah = 0x00 ;
    INREGS.h.al = 0x03 ;
    int86( INTNO, &INREGS, &OUTREGS ) ;

    /*---> Exit <---*/
    return ;
    end         /* MANDSHOW */


 MAPCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\MAPCH.C

 /*
  * Bob Denny     28-Aug-82 Move stdio dependencies to lexerr(), lexget(),
  *                                                   lexech() and mapch(). Th
  *                                                   lexlib which depend upon
  * Scott Guthery 20-Nov-83 Adapt for IBM PC & DeSmet C
  */

 /*
  * mapch -- handle escapes within strings
  */

 #include <stdio.h>
 #include <lex.h>

 extern int yyline;

 mapch(delim, esc)
 {
         register c, octv, n;

         if ((c = lexchar())==delim)
                 return(EOF);
         if (c==EOF || c=='\n') {
                 lexerror("Unterminated string");
                 ungetc(c, lexin);
                 return(EOF);
         }
         if (c!=esc)
                 return(c);
         switch (c=lexchar()) {
         case 't':
                 return('\t');
         case 'n':
                 return('\n');
         case 'f':
                 return('\f');
         case '\"': case '\'':
                 return(c);
         case 'e':
                 return('\e');
         case 'p':
                 return(033);
         case 'r':
                 return('\r');
         case '0': case '1': case '2': case '3':
         case '4': case '5': case '6': case '7':
                 octv = c-'0';
                 for (n = 1; (c = lexchar())>='0' && c<='7' && n<=3; n++)
                         octv = octv*010 + (c-'0');
                 ungetc(c, lexin);
                 return(octv);
         case '\n':

                 yyline++;
                 return(mapch(delim, esc));
         }
         return(c);
 }


 MARK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\MARK.C

 /*
  * STevie - ST editor for VI enthusiasts.
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 #ifdef        MEGAMAX
 overlay "mark"
 #endif

 /*
  * This file contains routines to maintain and manipulate marks.
  */

        NMARKS        10                /* max. # of marks that can be saved *

 struct        mark {
         char        name;
         LPTR        pos;
 };

 static        struct        mark        mlist[NMARKS];
 static        struct        mark        pcmark;                /* previous co
 static        bool_t        pcvalid = FALSE;        /* true if pcmark is vali

 /*
  * setmark(c) - set mark 'c' at current cursor position
  *
  * Returns TRUE on success, FALSE if no room for mark or bad name given.
  */
 bool_t
 setmark(c)
 char        c;
 {
         int        i;

         if (!isalpha(c))
                 return FALSE;

         /*
          * If there is already a mark of this name, then just use the
          * existing mark entry.
          */
         for (i=0; i < NMARKS ;i++) {
                 if (mlist[i].name == c) {
                         mlist[i].pos = *Curschar;
                         return TRUE;
                 }
         }

         /*
          * There wasn't a mark of the given name, so find a free slot
          */
         for (i=0; i < NMARKS ;i++) {
                 if (mlist[i].name == NUL) {        /* got a free one */
                         mlist[i].name = c;
                         mlist[i].pos = *Curschar;
                         return TRUE;
                 }
         }
         return FALSE;
 }

 /*
  * setpcmark() - set the previous context mark to the current position
  */
 void
 setpcmark()
 {
         pcmark.pos = *Curschar;
         pcvalid = TRUE;
 }

 /*
  * getmark(c) - find mark for char 'c'
  *
  * Return pointer to LPTR or NULL if no such mark.
  */
 LPTR *
 getmark(c)
 char        c;
 {
         register int        i;

         if (c == '\'' || c == '`')        /* previous context mark */
                 return pcvalid ? &(pcmark.pos) : (LPTR *) NULL;

         for (i=0; i < NMARKS ;i++) {
                 if (mlist[i].name == c)
                         return &(mlist[i].pos);
         }
         return (LPTR *) NULL;
 }

 /*
  * clrall() - clear all marks
  *
  * Used mainly when trashing the entire buffer during ":e" type commands
  */
 void
 clrall()
 {
         register int        i;

         for (i=0; i < NMARKS ;i++)
                 mlist[i].name = NUL;
         pcvalid = FALSE;
 }

 /*
  * clrmark(line) - clear any marks for 'line'
  *
  * Used any time a line is deleted so we don't have marks pointing to
  * non-existent lines.
  */
 void
 clrmark(line)
 LINE        *line;
 {
         register int        i;

         for (i=0; i < NMARKS ;i++) {
                 if (mlist[i].pos.linep == line)
                         mlist[i].name = NUL;
         }
         if (pcvalid && (pcmark.pos.linep == line))
                 pcvalid = FALSE;
 }


 MATRIX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\MATRIX.C

 /*
 ** BYTE Small-C Matrix Benchmark
 ** Version 1 for 8088/8086/80286
 ** March, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** NOTES:
 ** 1) This benchmark constructs only square matrices.
 ** 2) Small C only supports 1 dimentional arrays.  The
 **    the mathematics required to support 2-dimensional
 **    arrays therefore appears at the C-code level.
 ** 3) The routine printmat() is provided at the end of the
 **    program if you wish to print out the arrays and verify
 **    that the matrix operations function properly.
 **
 ** Operation:
 ** 1. Allocate space for 3 square matrices, each
 **    MATSIZ x MATSIZ big.
 ** 2. Fill the first 2 matrices with random numbers.
 ** 3. Turn on the stopwatch
 ** 4. Add the first 2 matrices, result in third.
 ** 5. Turn off the stopwatch.
 ** 6. Add elapsed time to total time.
 ** 7. Fill the first 2 matrices with random numbers.
 ** 8. Turn on the stopwatch.
 ** 9. Multiply the first 2 matrices, result in third.
 ** 10. Turn off the stopwatch.
 ** 11. Add elapsed time to total time.
 ** 12. Turn on the stopwatch.
 ** 13. Transpose matrix 1, result in matrix 2.
 ** 14. Turn off the stopwatch.
 ** 15. Add elapsed time to total time.
 ** 16. Report results.
 ** 17. Calculate empty loop time.
 ** 18. Report results.
 ** 19. Free the space claimed by the matrices.
 */

 #include stdio.h

 MATSIZ        60                /* Matrix dimension */
 BPINT        2                /* Bytes per integer */
 CEIL        15                /* Largest number allowed */
 int *mat1,*mat2,*mat3;                /* Pointers for matrices */
 int tblock[4];                        /* Timer block */
 int ttblock[4];                        /* Total time accumulator */
 int seed;                        /* Seed for random number generator */


 main()
 {
         int i;

         /* Announce yourself */
         printf("BYTE Small-C Matrix Benchmark\n");
         ttblock[0]=ttblock[1]=ttblock[2]=ttblock[3]=0;

         /* Set up the matrices */
         mat1=calloc(MATSIZ*MATSIZ,BPINT);
         if(mat1==NULL) {
           printf("No space for matrix 1\n");
           exit(0);
         }

         mat2=calloc(MATSIZ*MATSIZ,BPINT);
         if(mat2==NULL)         {
           printf("No space for matrix 2\n");
           exit(0);
         }

         mat3=calloc(MATSIZ*MATSIZ,BPINT);
         if(mat3==NULL) {
           printf("No space for matrix 3\n");
           exit(0);
         }

         /* Now fill up the first two matrices */
         seed=0;
         for(i=0;i<MATSIZ*MATSIZ;++i) {
           mat1[i]=randwc(CEIL);
           mat2[i]=randwc(CEIL);
         }

         /* Add the two matrices */
         printf("Adding two matrices...\n");
         gtime(tblock);
         madd(mat1,mat2,mat3,MATSIZ,MATSIZ);
         calctim(tblock);
         acctime();

         /* Regenerate the matrices */
         seed=0;
         for(i=0;i<MATSIZ*MATSIZ;++i) {
           mat1[i]=randwc(CEIL);
           mat2[i]=randwc(CEIL);
         }

         /* Multiply the two matrices */
         printf("Multiplying two matrices...\n");
         gtime(tblock);
         mmult(mat1,mat2,mat3,MATSIZ,MATSIZ,MATSIZ,MATSIZ);
         calctim(tblock);
         acctime();

         /* Transpose matrix 1 into matrix 2 */
         printf("Transpose...\n\n");
         gtime(tblock);
         mtrans(mat1,mat2,MATSIZ,MATSIZ);
         calctim(tblock);
         acctime();

         /* Report total time */
         printf("Results:  (HH:MM:SS:1/100ths)\n");
         printf("Time: %d:%d:%d:%d\n",ttblock[0],ttblock[1],
           ttblock[2],ttblock[3]);
         /* Calculate empty loop time */
         gtime(tblock);
         mtlptime(MATSIZ);
         calctim(tblock);
         printf("Empty loop: %d:%d:%d:%d\n\n",tblock[0],tblock[1],
           tblock[2],tblock[3]);

         /* Free up the space you claimed */
         free(mat3);
         free(mat2);
         free(mat1);

         printf("Press RETURN to exit:");
         fgetc(stdin);

         exit(0);
 }

 /*
 ** madd(aray1,aray2,aray3,trows,tcols)
 ** Adds matrix aray1 to matrix aray2, stores result in aray3.
 ** trows and tcols are the total rows and colums of the arrays
 */
 madd(aray1,aray2,aray3,trows,tcols)
 int aray1[],aray2[],aray3[];
 int trows,tcols;
 {
         int i,j;

         for(i=0;i<trows;++i)
           for(j=0;j<tcols;++j)
             aray3[i*tcols+j]=aray1[i*tcols+j]+
               aray2[i*tcols+j];
         return;
 }

 /*
 ** mmult(aray1,aray2,aray3,row1,col1,row2,col2)
 ** Multiplies aray1 by aray2, stores result in aray3.
 ** row1,col1 = dimension of aray1
 ** row2,col2 = dimension of aray2
 */
 mmult(aray1,aray2,aray3,row1,col1,row2,col2)
 int aray1[],aray2[],aray3[];
 int row1,col1,row2,col2;
 {
         int i,j,k;

         for(i=0;i<row1;++i)
           for(j=0;j<col2;++j)
           {  aray3[i*col1+j]=0;
              for(k=0;k<col1;++k)
                aray3[i*col1+j]+=aray1[i*col1+k]*
                                 aray2[k*col2+j];
           }
           return;
 }

 /*
 ** mtrans(aray1,aray2,row,col)
 ** Perform the matrix transpose of aray1, store result in aray2.
 ** row,col are the dimensions of the matrix (must be square)
 */
 mtrans(aray1,aray2,row,col)
 int aray1[],aray2[];
 int row,col;
 {
         int i,j;

         for(i=0;i<col;++i)
           for(j=0;j<row;++j)
             aray2[i*col+j]=aray1[j*row+i];
         return;
 }

 /*
 ** randwc(x)
 ** Get a random number (positive) with ceiling x.
 */
 randwc(x)
 int x;
 {

         if(x==0) return(0);
         seed=rand(seed);        /* Get a random number */
         return(seed%x);
 }

 /*
 ** Take the time interval stored in tblock[] and add that to
 ** the array holding total accumulated time (ttblock[]).
 */
 acctime()
 {
         ttblock[3]+=tblock[3];        /* Hundredths */
         if(ttblock[3]>=100) {
                 ttblock[2]+=1;
                 ttblock[3]-=100;
         }
         ttblock[2]+=tblock[2]; /* Seconds */
         if(ttblock[2]>=60) {
                 ttblock[1]+=1;
                 ttblock[2]-=60;
         }
         ttblock[1]+=tblock[1]; /* Minutes */
         if(ttblock[1]>=60) {
                 ttblock[0]+=1;
                 ttblock[1]-=60;
         }
         ttblock[0]+=tblock[0];        /* Hours */
         return;
 }

 /*
 ** mtlptime(msize)
 ** This routine executes a bunch of empty loops that
 ** are equivalent to the loops that occur inside the
 ** matrix add, multiply, and transpose functions.
 ** This function assumes the matrices are square.
 */
 mtlptime(msize)
 int msize;

 {        int i,j,k;

         /* Empty loop for an add */
         for(i=0;i<msize;++i)
           for(j=0;j<msize;++j) ;

         /* Empty loop for a multiply */
         for(i=0;i<msize;++i)
           for(j=0;j<msize;++j)
             for(k=0;k<msize;++k) ;

         /* Empty loop for a transpose */
         for(i=0;i<msize;++i)
           for(j=0;j<msize;++j) ;

         return;
 }

 /*
 ** printmat(aray,rows,cols)
 ** Print out a matrix
 ** This routine was added so you can print out matrices after
 ** operations were performed on them to verify that the results
 ** are correct.
 */
 printmat(aray,rows,cols)
 int aray[],rows,cols;
 {
         int i,j;

         for(i=0;i<rows;++i) {
           for(j=0;j<cols;++j)
             printf("%d ",aray[i*cols+j]);
           printf("\n");
         }
         return;
 }


 MAX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\MAX.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         int
 max(x, y)                        /* return larger of x and y, int        */

 /*----------------------------------------------------------------------*/
 int x, y;
 {
         return MAX(x,y);
 }


 MAZE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\MAZE.C

 /* MAZE.C - From page 588 of "Microsoft C Programming for       */
 /* the IBM" by Robert Lafore. This program used direct mem-     */
 /* ory access to draw a maze on the screen.                     */
 /****************************************************************/

 #include <stdio.h>
 #include <time.h>
 #define MAXROWS 23
 #define MAXCOLS 78
 #define FALSE 0
 #define TRUE 1
 #define RIGHT 0
 #define LEFT 1
 #define UP 2
 #define DOWN 3
 BLANK '\x20'    /* space */
 HORZ '\xCD'     /* vertical line */
 VERT '\xBA'     /* vertical pipe */
 NONE '\x07'     /* impossible combination */
 L_UP '\xBC'     /* L bend left to up */
 L_DN '\xBB'     /* L bend left to down */
 R_UP '\xC8'     /* L bend right to up */
 R_DN '\xC9'     /* L bend right to down */
 T_DN '\xCB'     /* T bend going down */
 T_UP '\xCA'     /* T bend going up */
 T_RT '\xCC'     /* T bend going right*/
 T_LF '\xB9'     /* T bend going left*/
 BORDER '\xB2'   /* grey square */
 int lastd;
       /* going to: rite  left  up    down      coming from */
 char table[4][4]={{HORZ, NONE, L_UP, L_DN},     /* left */
                   {NONE, HORZ, R_UP, R_DN},     /* right */
                   {R_DN, L_DN, VERT, NONE},     /* up */
                   {R_UP, L_UP, NONE, VERT} };   /* down */
 main()
 {
 int col, row, j;
 char getscr(), spot;

    cprintf("\x1B[2J");              /*clear screen*/
    border();
    col = 0; row = 12; lastd = RIGHT;   /*start at middle left*/
    randline(col, row);                 /*draw first line*/
    for(j = 1; !kbhit(); j++)  {        /*draw more lines*/
       do  {                            /*until key struck*/
          col = random(MAXCOLS - 1);    /*choose random spot*/
          row = random(MAXROWS - 1);
          spot = getscr(col, row);      /*find spot with line*/
       } while(spot != HORZ && spot != VERT); /*on it already*/
       tee(spot, col, row);       /*insert T in line, draw new line*/
       if(j == 200)               /*after 200 lines*/
          drawexit();
    }  /* end of for */
    goexit();                  /* all over */
 }  /*end of main*/

 /* randline() */  /* draws random line starting at x, y */
 randline(x, y)
 int x, y;
 {
 char trapped = FALSE;

    while (trapped == FALSE)  {
       switch (random(7))  {
          case 1:  /*draw line to right*/
          case 2:
          case 3:
          case 4:
             if(getscr(x + 1, y) == BLANK)
                turn(RIGHT, x++, y);
             break;
          case 5:     /*draw line to the left*/
             if(getscr(x - 1, y) == BLANK)
                turn(LEFT, x--, y);
             break;
          case 6:     /*draw line up (decrease y)*/
             if(getscr(x, y - 1) == BLANK)
                turn(UP, x, y--);
             break;
          case 7:     /*draw line down (increase y)*/
             if(getscr(x, y + 1) == BLANK)
                turn(DOWN, x, y++);
             break;
       }  /* end switch */
       /* see if this line trapped in cul-de-sac */
       if((getscr(x+1, y)!=BLANK) && (getscr(x-1, y) !=BLANK) &&
             (getscr(x, y+1)!=BLANK) && (getscr(x, y-1) !=BLANK))
          trapped = TRUE;         /*set flag*/
       if(kbhit() != 0)           /*if key struck*/
          goexit();
    }  /* end while */
 }  /* end randline */

 /* random() */    /* generates random number between 1 and rmax */
 int random(rmax)
 int rmax;
 {
 long seconds;
 static int rand;

    time(&seconds);
    rand = 0x7fff & ((int)seconds + rand*273) >> 4;
    return((rand % rmax) + 1);
 }

 /* turn() */   /* function to print correct character to make turn */
                /* direction is where we're going */
                /* lastd is where we're coming from */
                /* turn characters are in array table */
 turn(direction, x, y)
 int direction, x, y;
 {

    putscr( table[lastd][direction], x, y);
    lastd = direction;
 }

 /* border() */    /* draws border around screen */
 border()
 {
 int j;

    for( j = 0; j < MAXCOLS + 2; j++)  {
       putscr(BORDER, j, 0);               /*draw  top*/
       putscr(BORDER, j, MAXROWS + 1);     /*draw bottom*/
    }
    for( j = 0; j < MAXROWS + 2; j++)  {
       putscr(BORDER, 0, j);               /*draw  right*/
       putscr(BORDER, MAXCOLS + 1, j);     /*draw left*/
    }
 }

 /* tee() */    /* inserts T in existing horiz or vert line at col, row */
 tee(spot, col, row)
 int col, row;
 char spot;
 {

    if (spot == HORZ)  {                   /* HORIZ LINE */
       if (getscr(col, row + 1) == BLANK)  {        /*go down*/
          putscr(T_DN, col, row);
          lastd = DOWN;
          randline(col, ++row);
       }
       else
          if (getscr(col, row - 1) == BLANK)  {        /*go up*/
             putscr(T_UP, col, row);
             lastd = UP;
             randline(col, --row);
          }
    }
    else  {                                      /* VERT LINE */
       if (getscr(col + 1, row) == BLANK)  {        /*go right*/
          putscr(T_RT, col, row);
          lastd = RIGHT;
          randline(++col, row);
       }
       else
          if (getscr(col - 1, row) == BLANK)  {        /*go left*/
             putscr(T_LF, col, row);
             lastd = LEFT;
             randline(--col, row);
          }
    }  /* end else */
 }  /* end tee */

 /* drawexit() */  /* draws exit line on right edge of maze */
                   /* looks for vertical line to start on */
 drawexit()
 {
 int j;

                /* look for vert line */
    for(j = 6; getscr(MAXCOLS, j) != VERT; j++)
       ;
    putscr(T_RT, MAXCOLS, j);           /* insert right tee */
    putscr(HORZ, MAXCOLS + 1, j);       /* add horiz line */
 }

 /* goexit() */    /* puts cursor in lower right corner & exits */
 goexit()
 {

    printf("\x1B[%d;%dH", 24, 1);       /* move cursor */
    exit();
 }

 /* putscr() */    /* puts char on screen at location col, row */
                   /* (cols 0 to 79, rows 0 to 24) */
 putscr( ch, col, row)
 char ch;
 int col, row;
 {
 int far *farptr;
 int attr = 0x0700;         /* attribute for normal text */

    farptr = (int far *) 0xB0000000;    /* start of screen mem */
    *(farptr + row*80 + col) = ((int)ch & 0x00ff) | attr;
 }

 /* getscr */   /* returns char stored in screen mem */
                /* at location col, row */
 char getscr(col, row)
 int col, row;
 {
 int far *farptr;
 char ch;

    farptr = (int far *) 0xB0000000;
    ch = *(farptr + row*80 + col);
    return(ch);
 }



 MEMAVAIL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\MEMAVAIL.C

 #include <osbind.h>
 #include <stdio.h>

 #define        MAXBLK                16
 #define        FREE                0x00
 #define        USED                0x80

 extern        char        *_mblk[];                /* major memory blocks */

 long memavail()
 /*
  *        Return the size, in bytes, of the largest block of free memory
  *        available for allocation.  Note that this value is a long.
  */
 {
         register int i;
         register long n, tsiz = 0L, **p, *q;

         for(i=0; i<MAXBLK; ++i) {
                 if((p = _mblk[i]) == NULL)
                         continue;                /* skip unavailable heaps */
                 while(q = *p) {
                         n = *q;
                         if(n > tsiz)                /* largest block so far *
                                 tsiz = n;
                         p = q + 1;
                 }
         }
         if((n = Malloc(-1L)) < 1024)
                 return(tsiz);
         n -= (1024L + 16L);
         n &= ~0x1FFL;                        /* system memory available */
         return((n > tsiz) ? n : tsiz);
 }


 MEMCCPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\MEMCCPY.C

 char *memccpy(dst, src, c, cnt)
 register char *dst;
 register char *src;
 register char c;
 register int cnt;
 /*
  *        Copy bytes from <src> to <dst> until either <cnt> bytes have been
  *        copied, or the character <c> has been copied.  Returns <dst>.
  */
 {
         register char *p = dst;

         while(cnt--)
                 if((*dst++ = *src++) == c)
                         break;
         return(p);
 }


 MEMCHR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\MEMCHR.C

 #include <stdio.h>

 char *memchr(buf, c, cnt)
 register char *buf;
 register char c;
 register int cnt;
 /*
  *        Search the first <cnt> bytes of <buf> for <c>.  Returns a pointer t
  *        the matching character, or NULL if not found.
  */
 {
         while(cnt--)
                 if(*buf++ == c)
                         return(--buf);
         return(NULL);
 }


 MEMCLEAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MEMCLEAN\MEMCLEAN.C

 /*

         MEMORY CLEAN PROGRAM FOR THE IBM PERSONAL COMPUTER
         Version 1.00  3 May 1983

         COPYRIGHT (C) ROBERT J. BEILSTEIN, 1983

                       N O T I C E

       This program is supplied for your personal and
       non-commercial use only. No commercial use permitted.
       Users of this program are granted limited rights to
       reproduce and distribute this program, provided
       the following conditions are met:

       1) This program must be supplied in original form,
          with no modifications.
       2) Notices contained in this source file, and those
          produced by the executable program, must not be
          altered or removed.
       3) This program may not be sold. Providing this
          program for consideration of any sort, including
          copying or distribution fees, is prohibited.
       4) This program may not be used on timesharing
          systems where fees are charged for access,
          or or supplied as part of any other form of
          rental access computing, without the express
          written permission of the author.

       PLEASE SEND PROBLEM REPORTS AND SUGGESTIONS
       TO:
             ROBERT J. BEILSTEIN
             413 Wells Avenue, West
             North Syracuse, New York 13212

         This program is designed to be run immediately following
         powerup, and will fill all of expansion memory with good-parity
         data (thus avoiding problems with spurious parity checks
         if uninitialized memory is read).

         The program will write to all available memory locations
         above the 640K the ROM BIOS knows about.  That is:

         X'C0000' --> X'EFFFF'

         In addition, if 'SEGA' is specified on the command line,
         locations X'A0000' --> X'AFFFF' will be initialized.

         Also, for compatibility with pre-XT machines which have
         a limit on DOS-addressible RAM of 544K, specifying '544K'
         on the command line will start clearing at X'88000'.

 */

 #include <stdio.h>

 WRITE_DATA 0xaaaa   /* memory initialization value */

 main(argc,argv)     /* define entry point */

 int argc;           /* count of function arguments */
 char *argv[];       /* pointer array to argument strings */
 {
     unsigned int cur_segment;           /* current segment pointer */
     unsigned int cur_offset;            /* current offset within segment */
     unsigned int start_segment=0xa000;  /* starting segment */
     unsigned int start_offset=0;        /* starting offset within segment
                                            used to start 544k seg on 32k
                                            boundary */

                                         /* a bunch of useful flags */
         unsigned is_xt = 1;             /* if set, start at 640k */
         unsigned resv_ok = 0;           /* if set, clear reserved memory
                                            between X'A0000' and X'AFFFF' */
         unsigned no_high = 0;           /* if set, do not initialize
                                            X'C0000' or above */
         unsigned good_parm;             /* current parameter valid */

     int i;                              /* the canonical temporary */

     unsigned long bot,top;              /* for displaying limit values */

     printf("\nMEMCLEAN V1.00, COPYRIGHT (C) Robert J. Beilstein, 1983\n\n");

     for (i = 1;i < argc;i++)            /* check invocation parms */
     {
         good_parm = 0;                  /* reset good parm flag */

         if (!strcmp(argv[i],"544k") && strcmp(argv[i],"544K"))
         {
             is_xt = 0;                  /* start at X'88000' */

             good_parm = 1;
         }

         if (!strcmp(argv[i],"sega") && strcmp(argv[i],"SEGA"))
         {

             resv_ok = 1;                /* do X'A0000' --> X'AFFFF' */

             good_parm = 1;

         }

         if (!strcmp(argv[i],"nohigh") && strcmp(argv[i],"NOHIGH"))
         {

             no_high = 1;                /* skip X'C0000' --> X'EFFFF'  */

             good_parm = 1;

         }

         if (!good_parm)                 /* execute if a bad parm given */
             abort("INVALID PARAMETER TO <MEMCLEAN>:  \"%s\"\nVALID PARAMETERS
  ARE: \"544k\", \"sega\" and \"nohigh\"",argv[i]);
     }

     /* now that parameters are decoded, we can start doing something useful *

     if (!is_xt)                         /* if "544K" specified, reset addr */
     {

         start_segment = 0x8000;
         start_offset = 0x8000;

     }

     for (cur_segment = start_segment;cur_segment < 0xf000;cur_segment+=4096)
     {

         if ((!resv_ok) && cur_segment == 0xa000) continue;

         if (cur_segment == 0xb000) continue;    /* skip graphics ram */

         if (no_high && cur_segment >= 0xc000) break;    /* quit on "nohigh */

         bot = (unsigned long) cur_segment * 16 + start_offset;
         top = (unsigned long) cur_segment * 16 + 65535;

         printf("INITIALIZING %lx --> %lx\n",bot,top);   /* show same */

         for (cur_offset = start_offset;;cur_offset+=2)
         {
             pokew(cur_offset,cur_segment,WRITE_DATA);

             if (cur_offset == 0xfffe) break;

         }

         start_offset = 0;               /* subsequently start at offset 0 */

     }

     printf("ALL REQUESTED MEMORY INITIALIZED\n");

 }


 MEMMGT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\MEMMGT.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 struct blk {
         struct blk      *next;
         char            m[1];           /* memory area */
         };

 static int      glbsize = 0,    /* size left in current global block */
                 locsize = 0,    /* size left in current local block */
                 glbindx = 0,    /* global index */
                 locindx = 0;    /* local index */

 static struct blk       *locblk = 0,    /* pointer to local block */
                         *glbblk = 0;    /* pointer to global block */

 char    *xalloc(siz)
 int     siz;
 {       struct blk      *bp;
         char            *rv;
         if( siz & 1 )                /* if odd size */
                 siz += 1;        /* make it even */
         if( global_flag ) {
                 if( glbsize >= siz ) {
                         rv = &(glbblk->m[glbindx]);
                         glbsize -= siz;
                         glbindx += siz;
                         return rv;
                         }
                 else    {
                         bp = calloc(1,sizeof(struct blk) + 2047);
                         if( bp == NULL )
                         {
                                 printf(" not enough memory.\n");
                                 exit(1);
                         }
                         bp->next = glbblk;
                         glbblk = bp;
                         glbsize = 2048 - siz;
                         glbindx = siz;
                         return glbblk->m;
                         }
                 }
         else    {
                 if( locsize >= siz ) {
                         rv = &(locblk->m[locindx]);
                         locsize -= siz;
                         locindx += siz;
                         return rv;
                         }
                 else    {
                         bp = calloc(1,sizeof(struct blk) + 2047);
                         if( bp == NULL )
                         {
                                 printf(" not enough local memory.\n");
                                 exit(1);
                         }
                         bp->next = locblk;
                         locblk = bp;
                         locsize = 2048 - siz;
                         locindx = siz;
                         return locblk->m;
                         }
                 }
 }

 release_local()
 {       struct blk      *bp1, *bp2;
         int             blkcnt;
         blkcnt = 0;
         bp1 = locblk;
         while( bp1 != 0 ) {
                 bp2 = bp1->next;
                 free( bp1 );
                 ++blkcnt;
                 bp1 = bp2;
                 }
         locblk = 0;
         locsize = 0;
         lsyms.head = 0;
         printf(" releasing %d bytes local tables.\n",blkcnt * 2048);
 }

 release_global()
 {       struct blk      *bp1, *bp2;
         int             blkcnt;
         bp1 = glbblk;
         blkcnt = 0;
         while( bp1 != 0 ) {
                 bp2 = bp1->next;
                 free(bp1);
                 ++blkcnt;
                 bp1 = bp2;
                 }
         glbblk = 0;
         glbsize = 0;
         gsyms.head = 0;         /* clear global symbol table */
         printf(" releasing %d bytes global tables.\n",blkcnt * 2048);
         strtab = 0;             /* clear literal table */
 }



 MEMORY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\MEMORY.C

 /* memory.c
 */

 /*        determine system & available memory sizes
 */

        <_default.c>                /* diddle to make smaller */
        <stdio.h>              /* this is CI-C86 header file */

 struct        regval {
             unsigned ax,bx,cx,dx,si,di,ds,es;
             };

 extern        unsigned int *_PSPSEG;                /* pointer to DOS program
                                            everything below this addres is ve

 extern        long             ptrtoabs();        /* convert pointer to absol
 extern        unsigned int sysint();                /* invokes any INT */

 main()
 {

     struct   regval sysr;                    /* register arguments for INT */
     unsigned int    intstat;                    /* flags returned from INT */
     unsigned long   hdw_memsize,            /* total system memory, bytes */
                     ret_memsize;            /* total available to program */

     intstat = sysint( 0x12, &sysr, &sysr ); /* invoke BIOS INT 12h */
     hdw_memsize = sysr.ax * 1024L;            /* total system memory */

     ret_memsize = hdw_memsize - ptrtoabs(_PSPSEG);/* total available memory *

     printf( "%12lu bytes - system\n", hdw_memsize );
     printf( "%12lu bytes - available\n", ret_memsize );

     exit( 0 );                                /* exit to whomever, successful

     }        /* end main() */

                                         /* end memory.c */


 MEMSIZE0.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\MEMSIZE0.C

 /* MEMSIZE0.C - From page 323 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. It uses a ROM BIOS return to print*/
 /* the size of memory in a machine.                             */
 /****************************************************************/

 MEM 0x12           /*BIOS interrupt number*/

 main()
 {
 struct WORDREGS {          /*registers as 16 bit words*/
    unsigned int ax;
    unsigned int bx;
    unsigned int cx;
    unsigned int dx;
    unsigned int si;
    unsigned int di;
    unsigned int flags;
 };

 struct BYTEREGS {          /*registers as 8 bit bytes*/
    unsigned char al, ah;
    unsigned char bl, bh;
    unsigned char cl, ch;
    unsigned char dl, dh;
 };

 union REGS {               /*either bytes or words*/
    struct WORDREGS x;
    struct BYTEREGS h;
 };

 union REGS regs;           /*regs to be type union REGS*/
 unsigned int size;

    int86(MEM, &regs, &regs);  /*call memory interrupt*/
    size = regs.x.ax;          /*get value from AX register*/
    printf("\nMemory size is %dK bytes\n", size);
 }



 MENCON.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\MENCON\MENCON.C

 /*                         *** mencon.c ***                          */
 /*                                                                   */
 /* IBM-PC microsoft "C" under PC-DOS v2.0                            */
 /*                                                                   */
 /* Function to open a menu file and display it on the screen.        */
 /* Returns the number of entry fields found on the menu (nfield) or  */
 /* -1 if an error occured.  Places the r,c coordinates of the entry  */
 /* fields within the globally declared rc array.                     */
 /*                                                                   */
 /* To build a menu, use the text editor to create a file called      */
 /* xxxx.mnu   This file contains the menu test as it should appear   */
 /* on the screen.  The screen is not automatically erased when menus */
 /* are displayed to allow for overlaying.  Command lines control the */
 /* various display parameters.  See \comm\comm.mnu for a menu text   */
 /* example and \comm\ibmtty.c for a menu call example.               */
 /*                                                                   */
 /* Command summary - column 1 contains a '>'.                        */
 /*                                                                   */
 /*>BE                - ring bell                                          */
 /*>CC                - comment line                                       */
 /*>DA rr cc        - display system date at given row and column        */
 /*>DS xx        - toggle given screen attribute                      */
 /*                        0 = all attributes off                       */
 /*                        1 = BOLD                                     */
 /*                        4 = underscore                               */
 /*                        5 = blink                                    */
 /*                        7 = reverse video                            */
 /*                        8 = invisible                                */
 /*>ES                - erase screen                                       */
 /*>EL xx        - erase xx number lines                              */
 /*>FR ulr ulc lrr lrc        - draw a box                                 */
 /*>PA xx.        - pause xx seconds (must be a real number)           */
 /*>RP min max        - set valid range of responses (used by chosit)      */
 /*>ST ll        - set line counter (start diplaying) to given line   */
 /*>SK xx        - increment line counter (skip) xx lines             */
 /*>SC c                - change default input marker from '[' to 'c'        *
 /*>TI rr cc        - display time at given row and column               */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1984.                            */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #include <stdio.h>

 #define NULL                '\000'
 #define COMKEY                '>'
 #define SPACE                ' '
 #define LBRACK                '['

 int rc[50][2];
 int lenrc;
 int vrange[2];

 int mencon(menu)
 char menu[];
 {
         char line[81],menufile[30];
         char inchar;
         int irow,icol,nfield;
         FILE *mfp;

         /* build menu file menu */
         strcpy(menufile,menu);
         strcat(menufile,".mnu");

         /* open file */
         if ((mfp = fopen(menufile,"r")) == NULL) {
                 return(-1);
         }

         /* read loop */
         irow = 0;                /* line counter */
         nfield = 0;                /* entry field counter */
         inchar = LBRACK;        /* default input position marker */
         while (getline(mfp,line,sizeof(line)) != EOF) {

                 /* handle command lines */
                 if (line[0] == COMKEY) {
                         if (docomm(line,&irow,&inchar) == (-1)) {
                                 cursor(25,1);
                                 writes("\007*** invalid menu command ***");
                                 pause(2.);
                                 writes(line);
                                 pause(2.);
                         }
                         continue;
                 }

                 /* got a menu line - bump up line counter */
                 irow++;

                 /* check for blank line */
                 if (line[0] == NULL)
                         continue;

                 /* locate start of actual information on line */
                 for (icol=1;line[icol-1] == SPACE;icol++)
                         ;
                 cursor(irow,icol);

                 /* output information */
                 for (;line[icol-1] != NULL;icol++) {
                         writec(line[icol-1]);

                         /* check for input position */
                         if (line[icol-1] == inchar) {
                                 nfield++;
                                 rc[lenrc][0] = irow;
                                 rc[lenrc++][1] = (icol+1);
                         }
                 }

         }

         /* done */
         fclose(mfp);
         return(nfield);
 }

 /*********************************************************************/
 /*                                                                   */
 /*                        *** docomm.c ***                           */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* Function to execute menu commands for the function mencon.        */
 /* Returns a 0 if successful or a -1 if not.                         */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 #include <ctype.h>
 #define BELL                '\007'

 int docomm(line,icrow,inchar)
 char line[],*inchar;
 int *icrow;
 {
         char command[2],date[9],time[9];
         int i,irow,icol,irel;
         int iatt,ulrow,ulcol,lrrow,lrcol;
         float frel;

         /* get command */
         command[0] = toupper(line[1]);
         command[1] = toupper(line[2]);

         /* ring bell */
         if (command[0] == 'B' && command[1] == 'E') {
                 sscanf(line,"%*4s%d",&irel);
                 for(i=0;i<irel;i++) {
                         writec(BELL);
                 }

         /* check for comment line */
         } else if (command[0] == 'C' && command[1] == 'C') {
                 return (1);

         /* display date */
         } else if (command[0] == 'D' && command[1] == 'A') {
                 sscanf(line,"%*4s%d%d",&irow,&icol);
                 cursor(irow,icol);
                 getdate(date);
                 writes(date);

         /* toggle screen attribute */
         } else if (command[0] == 'D' && command[1] == 'S') {
                 sscanf(line,"%*4s%d",&iatt);
                 if (scratt(iatt) == (-1))
                         return(-1);

         /* erase screen */
         } else if (command[0] == 'E' && command[1] == 'S') {
                 lenrc = 0;                /* initialize rc array */
                 escreen(2);

         /* erase x number of lines */
         } else if (command[0] == 'E' && command[1] == 'L') {
                 sscanf(line,"%*4s%d%d",&irel,&icol);
                 for (i=0;i<irel;i++) {
                         cursor((*icrow+i+1),icol);
                         eline(0);
                 }
                 cursor(*icrow,1);

         /* frame */
         } else if (command[0] == 'F' && command[1] == 'R') {
                 sscanf(line,"%*4s%d%d%d%d",&ulrow,&ulcol,&lrrow,&lrcol);
                 if (frame(ulrow,ulcol,lrrow,lrcol) == (-1))
                         return(-1);

         /* pause */
         } else if (command[0] == 'P' && command[1] == 'A') {
                 sscanf(line,"%*4s%f",&frel);
                 pause(frel);

         /* set valid range */
         } else if (command[0] == 'R' && command[1] == 'P') {
                 sscanf(line,"%*4s%d%d",&vrange[0],&vrange[1]);

         /* set line counter directly */
         } else if (command[0] == 'S' && command[1] == 'T') {
                 sscanf(line,"%*4s%d",icrow);
                 *icrow -= 1;

         /* increment line counter directly */
         } else if (command[0] == 'S' && command[1] == 'K') {
                 sscanf(line,"%*4s%d",&irel);
                 *icrow += irel;

         /* set input position marker */
         } else if (command[0] == 'S' && command[1] == 'C') {
                 *inchar = line[4];

         /* display time */
         } else if (command[0] == 'T' && command[1] == 'I') {
                 sscanf(line,"%*4s%d%d",&irow,&icol);
                 cursor(irow,icol);
                 gettime(time);
                 writes(time);

         /* error */
         } else {
                 return (-1);
         }

         /* done */
         return(0);
 }


 MENU.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\MENU.C

 /*MENU.C - Menu program from "Microsoft C Programming for the   */
 /*IBM" by Robert Lafore, page267. Use the up and down arrow     */
 /*keys to move in the menu and the INSert ket to print the menu */
 /*item.                                                         */
 /****************************************************************/

 #define TRUE 1
 NUM 5                 /*Number of menu items*/
 CLEAR "\x1B[2J"       /*Clear screen*/
 ERASE "\x1B[K"        /*Erase line*/
 NORMAL "\x1B[0m"      /*Normal attribute*/
 REVERSE "\x1B[7m"     /*Reverse video attribute*/
 HOME "\x1B[1;1f"      /*Cursor to top left*/
 BOTTOM "\x1B[20;1f"   /*Cursor to lower left*/
 U_ARRO 72             /*up-arrow key*/
 D_ARRO 80             /*down-arrow key*/
 INSERT 82             /*"Ins" key*/

 main()
 {
 static char *items[NUM] = {         /*menu items*/
             "Open",
             "Close",
             "Save",
             "Print",
             "Quit"      };
 int curpos;                /*position of selected item*/
 int code;
 printf(CLEAR);             /*clear screen*/
 curpos = 0;                /*select top of menu*/

    while (TRUE) {
       display(items, NUM, curpos);     /*display menu*/
       code = getcode();                /*check keyboard*/
       switch (code) {         /*act on key pressed*/
                case U_ARRO:
                   if (curpos > 0)
                      --curpos;
                      break;
                case D_ARRO:
                   if (curpos < NUM - 1)
                      ++curpos;
                      break;
                case INSERT:
                   action(curpos);
                   break;
       }
    }
 }

 /* display() */
 /* displays menu */
 display(arr, size, pos)
 char *arr[];
 int size, pos;
 {
 int j;

    printf(HOME);                    /*cursor to top left */
    for(j = 0; j < size; j++) {      /*for each menu item*/
       if(j == pos)                  /*if selected*/
          printf(REVERSE);           /*print in reverse video*/
       printf("%s\n", *(arr + j));   /*print item*/
       printf(NORMAL);               /*restore normal attribute*/
    }
    printf(BOTTOM);                  /*cursor to lower left*/
 }

 /* getcode() */
 /* gets keyboard code */
 getcode()
 {
 int key;

    while(getch() != 0)              /*wait for initial 0*/
       ;                             /*ignores normal keys*/
    return(getch());                 /*return code*/
 }

 /* action() */
 /* performs action based on cursor position */
 action(pos)
 int pos;
 {
    printf(ERASE);                   /*erase lower line*/
    switch(pos) {
             case 0:                 /*calls to routines*/
                printf("Open");
                break;
             case 1:                 /*could be inserted here*/
                printf("Close");
                break;
             case 2:
                printf("Save");
                break;
             case 3:
                printf("Print");
                break;
             case 4:
                exit();
    }
 }



 MESSAGE1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\MESSAGE1.C

 #include <stdio.h>

 #include "routine.h"
 "weather.h"        /* common definitions for direction and stuff */


 int main()
 /*
 **        note that argv[1] is a pointer to our array of common value
 */

 {
 char        string[20] ;
 int        test ;
 int        value[20] ;
 FILE        *dataFile ;

 dataFile = fopen("WEATHER.DAT","wb") ;

 for(test = 0 ; test < 20 ; test++)
         value[test] = 0 ;

 /*
 **        value[0] = barometric pressure * 100
 **        value[1] = condition of pressure
 **                1-steady, 2-rise_slow, 3-rise_fast, 4-fall-slow, 5-fall-fas
 **        value[2] = direction of ground wind
 **                1-n, 2-ne, 3-e, 4-se, 5-s, 6-sw, 7-w, 8-nw
 **
 */

 printf("\n \nWEATHER EXPERT: \n") ;
 printf("\n This program attempts to prove one of the following:");
 printf("\n\tthe weather is ok\n\tthe weather is improving\n\tthe weather is d
 printf("\nNot all weather cases are included in the forecast algorithm.");
 printf("\n\nBefore we attempt a forecast, I need some data\n What is the baro
 test = 0 ;
 while((test < 2000) || (test > 4000))
         {
         printf("\n(Type in the pressure as an integer (BP*100) 30.1 = 3010...
         scanf("%d",&value[0]) ;
         test = value[0] ;
         }
 printf("\n\t Thankyou!,  \n\n Now I need to know how the barometer is acting\
 test = 0;
 while((test <1) || (test >5))
         {
         printf("\n\t Please input the correct number for the following:\n");
         printf("\n\t 1 -- It is steady\n\t 2 -- It is rising slowly\n\t 3 --
         printf("\n\t 4 -- It is falling slowly\n\t 5 -- It is falling rapidly
         scanf("%d",&value[1]);
         test = value[1] ;
         }
 test = 0 ;
 printf("\n\t Thankyou,") ;
 while((test < 1) || ( test > 8 ) )
         {
         printf("\n\nNow I need the wind direction, which direction is it blow
         printf("<n, ne, e, se, s, sw, w, nw>?") ;
         scanf("%s",string) ;
         if(0 == strcmp(string,"n"))
                 value[2]=NORTH ;
         if(0 == strcmp(string,"ne"))
                 value[2]=NORTH_EAST ;
         if(0 == strcmp(string,"e"))
                 value[2]=EAST ;
         if(0 == strcmp(string,"se"))
                 value[2]=SOUTH_EAST ;
         if(0 == strcmp(string,"s"))
                 value[2]=SOUTH ;
         if(0 == strcmp(string,"sw"))
                 value[2]=SOUTH_WEST ;
         if(0 == strcmp(string,"w"))
                 value[2]=WEST ;
         if(0 == strcmp(string,"nw"))
                 value[2]=NORTH_WEST ;
         if(0 == strcmp(string,"N"))
                 value[2]=NORTH ;
         if(0 == strcmp(string,"NE"))
                 value[2]=NORTH_EAST ;
         if(0 == strcmp(string,"E"))
                 value[2]=EAST ;
         if(0 == strcmp(string,"SE"))
                 value[2]=SOUTH_EAST ;
         if(0 == strcmp(string,"S"))
                 value[2]=SOUTH ;
         if(0 == strcmp(string,"SW"))
                 value[2]=SOUTH_WEST ;
         if(0 == strcmp(string,"W"))
                 value[2]=WEST ;
         if(0 == strcmp(string,"NW"))
                 value[2]=NORTH_WEST ;
         test = value[2] ;
         }
 printf("\n\n\n\n For the next question, you should stand outside with your ba
 printf("\nto the surface wind.  You now must observe the direction the");
 printf("\nupper level clouds are moving.  You observe them to be moving") ;
 printf("\nfrom your right, from your left, or in a direction parallel") ;
 printf("\nto that which your are facing.\n") ;
 printf("\nUse this information to answer the following question.  If you");
 printf("\nare unable to see the upper level clouds, answer no to the followin
 printf("\nquestion.\n\n") ;
 fwrite(value,2,20,dataFile) ;
 fclose(dataFile) ;
 exit(RETURN_ROUTINE_TRUE) ;
 }







 MFRACT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\MFRACT.C

 #include <graphics.h>
 SIZE 32   /* size of array */
 MSX 320   /* midscreen */
 XK 10 /* X scale */

 int TILT,ZK;
 int map[SIZE+1][SIZE+1];
 int ms[641];
 double frand();

 main(argc,argv)
 int argc;
 char *argv[];
 {
     int i,j,sx,sy,sx1,sy1,min,max;
     double f,w;
     if (argc != 4) {
         printf("syntax is: MFRACT tilt-factor z-scale seed-value\n");
         printf("try: mfract 2 3 1027\n");
         exit(0);
         }
    printf("working ...");
     for (i=0;i<641;i++) ms[i]=199;
     TILT=atoi(argv[1]);
     ZK=atoi(argv[2]);
     srand(atoi(argv[3]));

     sfract(0,0,SIZE);

     min=32766;
     max=-32766;
     for (i=0;i<=SIZE;i++)
      for (j=0;j<=SIZE;j++) {
          sy=(map[i][j]=(TILT*(i+j)+ZK*map[i][j]));
          if (sy<min) min=sy;
          if (sy>max) max=sy;
          }

     f = 199.0/(double)(max-min);
     for (i=0;i<=SIZE;i++)
      for (j=0;j<=SIZE;j++) map[i][j]=199-(int)(f*(map[i][j]-min));

     scr_setup();
     scr_setmode( 6 );
     scr_clr();
     for (i=0;i<=SIZE;i++) {
        for (j=0;j<=SIZE;j++) {
            sx=MSX+XK*(i-j);
            sy=map[i][j];
            if (j < SIZE) {
               sy1=map[i][j+1];
               sx1=sx-XK;
               hline(sx,sy,sx1,sy1);
               }
            if (i < SIZE ) {
               sx1=sx+XK;
               sy1=map[i+1][j];
               hline(sx,sy,sx1,sy1);
               }
            }
        }
    while ( 0 == scr_csts()) ;
    scr_setmode( 2 );
    scr_clr();
    exit(0);
 }

 hline(x,y,x1,y1)
 int x,y,x1,y1;
 {
    int dx,dy,hx,hy,hx0,hy0,hx1,hy1,hi;
    double hz;

    if (x <= x1) {
       dx = x1-x ;
       dy = y1-y ;
       hx0= x;
       hy0= y;

       }
       else {
          dx = x-x1 ;
          dy = y-y1 ;
          hx0 = x1;
          hy0 = y1;
       }
    hz = (double)dy/(double)dx;
    for (hi=0; hi < dx; hi++) {
        hx = hx0+hi;
        hy = hy0+hz*hi;
        if (ms[hx]>=hy) { ms[hx]=hy; pset(hx,hy,7) ; }
        }
    }

 sfract(x,y,d)
  int x,y,d;
  {
  int d2,xc,yc,xd,yd,lfract();

  xd=x+d;
  yd=y+d;
  d2=d>>1;
  xc=x+d2;
  yc=y+d2;
  map[x][yc] = lfract(x,y,x,yd,d);
  map[xc][y] = lfract(x,y,xd,y,d);
  map[xd][yc] = lfract(xd,y,xd,yd,d);
  map[xc][yd] = lfract(x,yd,xd,yd,d);
  map[xc][yc] = (lfract(x,yc,xd,yc,d) + lfract(xc,y,xc,yd,d))/2 ;

  if (d2 > 1) {
   sfract(x,y,d2);
   sfract(xc,y,d2);
   sfract(x,yc,d2);
   sfract(xc,yc,d2);
  }
 }

 int lfract(x1,y1,x2,y2,d3)
  int x1,y1,x2,y2,d3;
  {
  return(((map[x1][y1]+map[x2][y2])/2)+d3*(frand()-.5));
  }


 MIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\MIN.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         int
 min(x, y)                        /* return lesser of x and y, int        */

 /*----------------------------------------------------------------------*/
 int x, y;
 {
         return MIN(x,y);
 }


 MIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\MIN.C

 /*
  * Copyright (c) 1978 Charles H. Forsyth
  *
  * Modified 02-Dec-80 Bob Denny -- Conditionalize debug code for smaller size
  *  Also note other mods. Now minimization is turned on at run time by '-m'.
  * More     19-Mar-82 Bob Denny -- New C library & compiler
  *  This routine is unimplemented. Define MIN to turn it on. Have fun.
  */

 /*
  * lex -- dfa minimisation routines
  */

 #include <stdio.h>
 #include "lexlex.h"

 #ifdef  MIN
 #else
 /*
  * Dummy routine
  */
 dfamin()
 {
 }
 #endif

 #ifdef  MIN

 member(e, v, i)
 register e, *v, i;
 {

         while (i--)
                 if (e==*v++)
                         return(1);
         return(0);
 }

 extern struct set **oldpart;
 extern int **newpart;
 extern int nold, nnew;

 struct  xlist {
         struct  set     *x_set;
         struct  trans   *x_trans;
               };

 xcomp(a, b)
 struct xlist *a, *b;
 {
         if (a->x_trans > b->x_trans)
                 return(1);
         if (a->x_trans==b->x_trans)
                 return(0);
         return(-1);
 }

 dfamin()
 {
         struct xlist *temp, *tp, *xp, *zp;
         struct trans *trp;
         int *tp2, *ip;

         struct set *gp, **xch;
         int i, j, k, niter;

         if(mflag == 0) return;          /*** NOTE ***/

 #ifdef DEBUG
         fprintf(lexlog, "\nDFA minimisation (%d states)\n", ndfa);
 #endif

         temp = lalloc(ndfa, sizeof(*temp), "minimisation");
         oldpart = lalloc(ndfa, sizeof(*oldpart), "minimisation");
         newpart = lalloc(ndfa*2+1, sizeof(*newpart), "minimisation");
         setlist = 0;
 /*
  * partition first into final
  * states which identify different
  * translations, and non-final
  * states.
  */
         tp = temp;
         for (i = 0; i < ndfa; i++, tp++) {
                 tp->x_set = dfa[i].df_name;
                 if (tp->x_set->s_final)
                         tp->x_trans = nfa[tp->x_set->s_final].n_trans; else
                         tp->x_trans = 0;
         }
         qsort(temp, tp-temp, sizeof(*tp), xcomp);
         for (xp = temp; xp < tp; xp = zp) {
                 ip = newpart;
                 for (zp = xp; zp < tp && zp->x_trans==xp->x_trans; zp++)
                         *ip++ = zp->x_set->s_state-dfa;
                 oldpart[nold++] = newset(newpart, ip-newpart, 0);
         }
         free(temp);
 /*
  * create a new partition,
  * by considering each group in
  * the old partition.  For each
  * such group, create new subgroups
  * such that two states are in the
  * same subgroup iff they have
  * transitions on the same set of
  * characters into the same
  * set of groups in the old partition.
  * repeat this process until
  * a fixed point is reached.
  */
         niter = 0;
         do {
                 niter++;

 #ifdef DEBUG
                 fprintf(lexlog, "\n%d groups in partition %d\n", nold, niter)
 #endif

                 for (i = 0; i < nold; i++) {
                         fprintf(lexlog, "group %d: ", i);
                         pset(oldpart[i], 0);
                         fprintf(lexlog, "\n");
                 }
                 nnew = 0;
                 tp2 = newpart;

                 for (i = 0; i < nold; i++) {
                         gp = oldpart[i];
                         for (j = 0; j < gp->s_len; j++) {
                                 if (member(gp->s_els[j], newpart, tp2-newpart
                                         continue;
                                 *tp2++ = gp->s_els[j];
                                 for (k = 0; k < gp->s_len; k++)
                                         if (k!=j &&
                                             !member(gp->s_els[k], newpart,
                                                 tp2-newpart) &&
                                             eqstate(gp->s_els[j],gp->s_els[k]
                                                 *tp2++ = gp->s_els[k];
                                 *tp2++ = -1;
                         }
                 }
                 *tp2++ = -1;
                 for (tp2 = newpart; *tp2 != -1; tp2 = ++ip) {
                         for (ip = tp2; *ip != -1; ip++)
                                 ;
                         oldpart[nnew++] = newset(tp2, ip-tp2, 0);
                 }
                 i = nold; nold = nnew; nnew = i;
         } while (nnew!=nold);

 #ifdef DEBUG
         if (ndfa==nnew)
                 fprintf(lexlog, "\nno states saved by minimisation\n"); else
                 fprintf(lexlog, "\n%d states saved by minimisation\n", ndfa-n
 #endif

         free(newpart);
         free(oldpart);
 }

 eqstate(a, b)
 {
         register struct move *dp1, *dp2;

 /**  dfa vector has no element 'df_moves', transition entries have no element
         df_char nor df_set. Obviously unimplemented stuff.

         dp1 = dfa[a].df_moves;
         dp2 = dfa[b].df_moves;
         for (; dp1->df_set; dp1++, dp2++)
                 if (dp2->df_set==0)
                         return(0);
                 else if (dp1->df_char != dp2->df_char ||
                          dp1->df_set->s_group != dp2->df_set->s_group)
                         return(0);
         return(dp2->df_set==0);
 **/

 }
 #endif


 MINILINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MINILINT.C

 /****************************************************************
 *                                                                *
 *                        CC (C Checker)                                *
 *                                                                *
 *             C Source Paren, bracket and comment Checker         *
 *                                                                *
 *                 T. Jennings  -- Sometime in 1983                *
 *                Slightly tweaked and renamed MINILINT                *
 *                        KAB Aug 84                                *
 *                                                                *
 *                                                                *
 ****************************************************************/

 #include <stdio.h>
 #include <ctype.h>

 /* Very crude but very effective C source debugger. Counts the numbers of
 matching braces, parenthesis and comments, and displays them at the left edge
 of the screen. The best way to see what it does is to do it; try

         MINILINT MINILINT.C                /* C Check MINILINT.C */

 Properly handles parens and brackets inside comments; they are ignored.
 */

 main(argc,argv)
         int argc;
         char **argv;
 {
 int file;
 char c,lastc;
 int parens,brackets,comments;
 int line, col;
 char hdr[40];

         file= open(argv[1],0x8000);
         if (file == -1) {
                 cputs("File missing.\r\nTry MINILINT <filename.ext> \r\n");
                 exit();
         }
         brackets= parens= comments= 0;
         line= 0; col= 0;
         lastc= '\0';

         while (read(file,&c,1)) {
                 if (c == 0x1a) break;                        /* stop if ^Z */

                 if (col == 0) {
                         sprintf(hdr,"%d: {%d} (%d) /*%d*/",line,brackets,pare
                         while (strlen(hdr) < 23)        /* gross but works */
                                 strcat(hdr," ");        /* to hell with elega
                         cprintf("%s|",hdr);                /* we got a job to
                 }                                /* (real programmers dont ..

 /* Dont count parens and brackets that are inside comments. This of course
 assumes that comments are properly matched; in any case, that will be the
 first thing to look for. */

                 if (comments <= 0) {
                         if (c == '{') ++brackets;
                         if (c == '(') ++parens;
                         if (c == '}') --brackets;
                         if (c == ')') --parens;
                 }

 /* Now do comments. This properly handles nested comments;
 whether or not the compiler does is your responsibility */

                 if ((c == '*') && (lastc == '/')) ++comments;
                 if ((c == '/') && (lastc == '*')) --comments;

                 ++col;
                 if (c == 0x0a) {                /* newline == New Line */
                         col= 0;                        /* set column 0 */
                         ++line;
                 }
                 putchar(c);                        /* display text */
                 lastc= c;                        /* update last char */
         }
         cputs("\r\n\r\n");
         if (brackets) cputs("Unbalanced brackets\r\n");
         if (parens) cputs("Unbalanced parenthesis\r\n");
         if (comments) cputs("Unbalanced comments\r\n");
 }

 /* eof */


 MINIMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\MINIMO.C

 /* MINIMO.C - From page 503 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. This is a full modem program,     */
 /* although rather limited. I slightly changed this program.    */
 /* The #define BUFSIZE is changed from 8192 to 60416 and the    */
 /* check() function is called after all commands to the modem   */
 /* instead of only once as it is in the book.                   */
 /****************************************************************/

 <dos.h>        /*for union REGS*/
 <fcntl.h>      /*for system lovel I/O*/
 <types.h>      /* " */  /*extracted from subdir \include\sys*/
 <stat.h>       /* " */  /* " */
 COM 1           /*serial port no. (0 = COM1, 1 = COM2)*/
 CONF 0x83       /*1200 bps, no par, 1 stop, 8 bits*/
 RS232 0x14      /*RS232 serial port int number*/
 VIDEO 0x10      /*video int number*/
 DATAR 0x100     /*data ready bit in status word*/
 DELAY 500       /*make larger for faster computers*/
 #define TRUE 1
 #define FALSE 0
 OK 0            /*modem result code*/
 BUFSIZ 60416    /*size of disk file buffer*/
 union REGS inregs, outregs;   /* for ROM BIOS calls*/
 int far *fptr;          /*pointer to screen memory*/
 int row, col;           /*row and col of cursor position*/
 char buff[BUFSIZ];      /*disk file buffer*/
 int hnd;                /*disk file handle*/
 int bytes;              /*number of bytes stored in buffer*/
 int saveflag = FALSE;   /*TRUE when data being saved to disk*/

 main()
 {
 char ch, receive();

    init(CONF);          /*initialize port*/
    reset();             /*initialize modem*/
    while(TRUE)  {
       printf("\nPress  [F1] to dial a call");
       printf("\n       [F2] to await call");
       printf("\n       [F3] to resume call");
       printf("\n       [F4] save to disk");
       printf("\n       [F5] close disk file");
       printf("\n       [F10] return to function menu");
       printf("\nCommand: ");
       if(getche() == 0)  {       /*if extended code*/
          switch(getch())  {
             case 59:             /* [F1] dial & call */
                dial();
                sr();
                break;
             case 60:             /* [F2] await call */
                answ();
                sr();
                break;
             case 61:             /* [F3] resume call */
                sr();
                break;
             case 62:             /* [F4] save to disk */
                save();
                break;
             case 63:             /* [F5] close file */
                clo();
                break;
          }     /*end switch*/
       }     /*end if*/
    }     /*end while*/
 }     /*end main*/

 /* reset() */  /* reset modem parameters */
 reset()
 {

    command("AT Z\r");            /*reset modem*/
    check();                      /*check result code*/
    /***  echo on, full-duplex, send result codes, numer codes ***/
    command("AT E1 F1 Q0 V0\r");  /*initialize modem*/
    check();                      /*check result code*/
    command("AT\r");              /*reset bps rate*/
    check();                      /*check result code*/
 }

 /* clscr() */     /*clear the screen*/
 clscr()
 {
 int addr;

    fptr = (int far *) 0xB0000000;
    for(addr = 0; addr < 2000; addr++)
       *(fptr + addr) = 0x0700;
    row = 0; col = 0;          /*initialize for putscr()*/
    inregs.h.ah = 2;           /*'set cursor position' service*/
    inregs.h.dh = row;
    inregs.h.dl = col;
    inregs.h.bh = 0;           /*page number*/
    int86(VIDEO, &inregs, &outregs);
 }

 /* dial() */   /* dials number */
 dial()
 {
 char phonum[30];              /*space for phone number*/

    reset();                   /*resets modem*/
    printf("\n\nEnter phone number (example: 555-1212):  ");
    gets(phonum);
    command("AT DT ");         /*set up modem*/
    check();                      /*check result code*/
    command(phonum);           /*send number to modem*/
    check();                      /*check result code*/
    command("\r");             /*terminate command*/
    check();                      /*check result code*/
 }

 /* answ() */   /* sets up answer mode */
 answ()
 {

    reset();                   /*reset modem*/
    command("AT S0 = 1\r");    /*answer on first ring*/
    check();                      /*check result code*/
 }

 /* sr() */     /*send-receive, full-duplex communication*/
 sr()
 {
 char ch, receive();

    clscr();
    while(TRUE)  {
       if(kbhit())  {                /*keyboard char ?*/
          if((ch = getch()) != 0)    /*get char from keybd*/
             send(ch);               /*send normal char*/
          else if(getch() == 68)     /*if F[10] function key*/
             return;                 /*return to menu*/
       }
       if(ready())  {             /*port has char ? */
          ch = receive();
          putscr(ch);
          if(saveflag)  {         /*if saving to disk*/
             buff[bytes++] = ch;  /*put in disk buffer*/
             if(bytes > BUFSIZ)  {      /*if buffer full*/
                printf("\n\nBuffer full.\n");
                return;           /*return to menu*/
             }
          }
       }  /*end if(ready())*/
    }  /*end while*/
 }  /*end sr*/

 /* save() */   /* opens disk file, sets up saveflag to write disk */
 save()
 {
 char fname[20];

    printf("\n\nName of file to save to: ");
    gets(fname);
    if((hnd = open(fname,
                O_CREAT | O_WRONLY | O_TEXT, S_IWRITE)) < 0)
       printf("\n\nCan't open file.\n");
    else  {
       printf("\n\nFile opened. Press [F5] to close.\n");
       bytes = 0;              /*start of buffer*/
       saveflag = TRUE;        /* 'write to disk' flag */
    }
 }

 /* clo() */    /* writes data from buffer to file & closes file */
 clo()
 {

    write(hnd, buff, bytes);      /*write buffer to file*/
    close(hnd);
    saveflag = FALSE;             /*turn off flag*/
 }

 /* command */  /* send command string to modem */
 command(comstr)
 char *comstr;                    /*pointer to command*/
 {
 int j, k;
 long int jj;
 char ch;

    putch('*');                /*reassure user*/
    for(jj = 0; jj < 50*DELAY; jj++)    /*ensure last command done*/
       ;
    for(j = 0; (ch = *(comstr + j)) != '\0'; j++)  {
       send(ch);               /*send each char in turn*/
       for(k = 0; k < DELAY && !ready(); k++)    /*wait for echo*/
          ;                    /*before doing next one*/
       ch = receive();
    }
 }

 /* check() */  /* check that modem returns '0' for OK */
 check()
 {
 char ch;
 int j, k;

    for(j = 0; j < 10; j++)  {       /*read up to 10 chars ? */
       for(k = 0; k < DELAY && !ready(); k++)    /*wait for char*/
          ;
       ch = receive();               /*if we get an OK*/
       if(ch == OK)
          return;
    }                 /*otherwise error*/
    printf("\n\nCan't initialize modem.\n");
 }

 /* putscr() */    /* puts char on screen at row, col */
 putscr(ch)
 char ch;
 {
 int j;

    switch(ch)  {
       case(0x0A):             /*if return*/
          col = 0;             /*start at beginning of line*/
          break;
       case(0x0D):             /*if linefeed*/
          ++row;               /*go to next row*/
          break;
       case(0x08):             /*if backspace*/
          if(col > 0)
             --col;            /*backspace cursor*/
          *(fptr + col + row*80) = 0x0700;  /*print space*/
          break;
       default:
          *(fptr + col + row*80) = (int)ch | 0x0700;
          ++col;               /*display & go to next col*/
    }
    if(col >= 80)  {           /*if past end of row*/
       col = 0;                /*do carriage return and*/
       ++row;                  /*linefeed*/
    }
    if(row >= 25)              /*if below bottom row*/
       row = 0;                /*start at top*/
    if(col == 0)               /*if at beginning of line*/
       for(j = 0; j < 80; j++)    /*clear line*/
          *(fptr + j + row*80) = 0x0700;
    inregs.h.ah = 2;           /* 'set cursor position' service*/
    inregs.h.dh = row;
    inregs.h.dl = col;
    inregs.h.bh = 0;           /*page number*/
    int86(VIDEO, &inregs, &outregs);
 }

 /* init() */      /* initialize serial port */
 init(conf)
 char conf;        /*addr of configuration code*/
 {
    inregs.h.ah = 0;        /* 'initialize port' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = CONF;     /*configuration*/
    int86(RS232, &inregs, &outregs);
 }

 /* send() */      /* send char to serial port */
 send(c)
 char c;
 {
    inregs.h.ah = 1;        /* 'send char' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = c;        /*character*/
    int86(RS232, &inregs, &outregs);
 }

 /* ready */    /* get serial port ready status */
 ready()
 {
    inregs.h.ah = 3;        /* 'get status' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.x.ax & DATAR);    /*return 'data ready' status*/
 }

 /* receive */     /* get character from serial port */
 char receive()
 {
    inregs.h.ah = 2;        /* 'receive char' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.h.al & 0x7F);     /*return character*/
                                     /* (AND off 8th bit*/
 }



 MINIMO2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\MINIMO2.C

 /* MINIMO2.C - From page 512 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. This is a full modem program,     */
 /* although rather limited. I slightly changed this program.    */
 /* The #define BUFSIZE is changed from 8192 to 60416 and the    */
 /* check() function is called after all commands to the modem   */
 /* instead of only once as it is in the book. This program is   */
 /* a modification of MINIMO.C in that it uses the system clock  */
 /* rather than relying on timimg loops. Modifying it is des-    */
 /* cribed on page 512 of the book. After adding the function    */
 /* initime() to the program, each call to initime() with a      */
 /* decimal number argument must have that number cast to a long */
 /* in the call (3 different places) or the program won't work.  */
 /* The original function initime() was developed in the program */
 /* TIMER.C on page 511. In this program the call to initime()   */
 /* was made with a variable as an argument and the variable     */
 /* was declared a long hence no cast was needed.                */
 /****************************************************************/

 <dos.h>        /*for union REGS*/
 <fcntl.h>      /*for system lovel I/O*/
 <types.h>      /* " */  /*extracted from subdir \include\sys*/
 <stat.h>       /* " */  /* " */
 COM 1           /*serial port no. (0 = COM1, 1 = COM2)*/
 CONF 0x83       /*1200 bps, no par, 1 stop, 8 bits*/
 RS232 0x14      /*RS232 serial port int number*/
 VIDEO 0x10      /*video int number*/
 DATAR 0x100     /*data ready bit in status word*/
 DELAY 500       /*make larger for faster computers*/
 #define TRUE 1
 #define FALSE 0
 OK 0            /*modem result code*/
 BUFSIZ 60416    /*size of disk file buffer*/
 union REGS inregs, outregs;   /* for ROM BIOS calls*/
 int far *fptr;          /*pointer to screen memory*/
 int row, col;           /*row and col of cursor position*/
 char buff[BUFSIZ];      /*disk file buffer*/
 int hnd;                /*disk file handle*/
 int bytes;              /*number of bytes stored in buffer*/
 int saveflag = FALSE;   /*TRUE when data being saved to disk*/

 main()
 {
 char ch, receive();

    init(CONF);          /*initialize port*/
    reset();             /*initialize modem*/
    while(TRUE)  {
       printf("\nPress  [F1] to dial a call");
       printf("\n       [F2] to await call");
       printf("\n       [F3] to resume call");
       printf("\n       [F4] save to disk");
       printf("\n       [F5] close disk file");
       printf("\n       [F10] return to function menu");
       printf("\nCommand: ");
       if(getche() == 0)  {       /*if extended code*/
          switch(getch())  {
             case 59:             /* [F1] dial & call */
                dial();
                sr();
                break;
             case 60:             /* [F2] await call */
                answ();
                sr();
                break;
             case 61:             /* [F3] resume call */
                sr();
                break;
             case 62:             /* [F4] save to disk */
                save();
                break;
             case 63:             /* [F5] close file */
                clo();
                break;
          }     /*end switch*/
       }     /*end if*/
    }     /*end while*/
 }     /*end main*/

 /* reset() */  /* reset modem parameters */
 reset()
 {

    command("AT Z\r");            /*reset modem*/
    check();                      /*check result code*/
    /***  echo on, full-duplex, send result codes, numer codes ***/
    command("AT E1 F1 Q0 V0\r");  /*initialize modem*/
    check();                      /*check result code*/
    command("AT\r");              /*reset bps rate*/
    check();                      /*check result code*/
 }

 /* clscr() */     /*clear the screen*/
 clscr()
 {
 int addr;

    fptr = (int far *) 0xB0000000;
    for(addr = 0; addr < 2000; addr++)
       *(fptr + addr) = 0x0700;
    row = 0; col = 0;          /*initialize for putscr()*/
    inregs.h.ah = 2;           /*'set cursor position' service*/
    inregs.h.dh = row;
    inregs.h.dl = col;
    inregs.h.bh = 0;           /*page number*/
    int86(VIDEO, &inregs, &outregs);
 }

 /* dial() */   /* dials number */
 dial()
 {
 char phonum[30];              /*space for phone number*/

    reset();                   /*resets modem*/
    printf("\n\nEnter phone number (example: 555-1212):  ");
    gets(phonum);
    command("AT DT ");         /*set up modem*/
    check();                      /*check result code*/
    command(phonum);           /*send number to modem*/
    check();                      /*check result code*/
    command("\r");             /*terminate command*/
    check();                      /*check result code*/
 }

 /* answ() */   /* sets up answer mode */
 answ()
 {

    reset();                   /*reset modem*/
    command("AT S0 = 1\r");    /*answer on first ring*/
    check();                      /*check result code*/
 }

 /* sr() */     /*send-receive, full-duplex communication*/
 sr()
 {
 char ch, receive();

    clscr();
    while(TRUE)  {
       if(kbhit())  {                /*keyboard char ?*/
          if((ch = getch()) != 0)    /*get char from keybd*/
             send(ch);               /*send normal char*/
          else if(getch() == 68)     /*if F[10] function key*/
             return;                 /*return to menu*/
       }
       if(ready())  {             /*port has char ? */
          ch = receive();
          putscr(ch);
          if(saveflag)  {         /*if saving to disk*/
             buff[bytes++] = ch;  /*put in disk buffer*/
             if(bytes > BUFSIZ)  {      /*if buffer full*/
                printf("\n\nBuffer full.\n");
                return;           /*return to menu*/
             }
          }
       }  /*end if(ready())*/
    }  /*end while*/
 }  /*end sr*/

 /* save() */   /* opens disk file, sets up saveflag to write disk */
 save()
 {
 char fname[20];

    printf("\n\nName of file to save to: ");
    gets(fname);
    if((hnd = open(fname,
                O_CREAT | O_WRONLY | O_TEXT, S_IWRITE)) < 0)
       printf("\n\nCan't open file.\n");
    else  {
       printf("\n\nFile opened. Press [F5] to close.\n");
       bytes = 0;              /*start of buffer*/
       saveflag = TRUE;        /* 'write to disk' flag */
    }
 }

 /* clo() */    /* writes data from buffer to file & closes file */
 clo()
 {

    write(hnd, buff, bytes);      /*write buffer to file*/
    close(hnd);
    saveflag = FALSE;             /*turn off flag*/
 }

 /* command */  /* send command string to modem */
 command(comstr)
 char *comstr;                    /*pointer to command*/
 {
 int j;
 char ch;

    putch('*');                /*reassure user*/
    initime((long)100);        /*wait 1 sec to insure*/
    while(!timeout())          /*last command is done*/
       ;
    for(j = 0; (ch = *(comstr + j)) != '\0'; j++)  {
       send(ch);               /*send each char in turn*/
       initime((long)12);      /*set timer to 12/100 sec*/
       while(!timeout() && !ready())    /*wait for echo*/
          ;                    /*before doing next one*/
       ch = receive();
    }
 }

 /* check() */  /* check that modem returns '0' for OK */
 check()
 {
 char ch;
 int j;

    for(j = 0; j < 10; j++)  {       /*read up to 10 chars ? */
       initime((long)12);            /*set timer to 12/100 sec*/
       while(!timeout() && !ready())    /*wait for ready*/
          ;                    /*before doing next one*/
       ch = receive();               /*if we get an OK*/
       if(ch == OK)
          return;
    }                 /*otherwise error*/
    printf("\n\nCan't initialize modem.\n");
 }

 /* putscr() */    /* puts char on screen at row, col */
 putscr(ch)
 char ch;
 {
 int j;

    switch(ch)  {
       case(0x0A):             /*if return*/
          col = 0;             /*start at beginning of line*/
          break;
       case(0x0D):             /*if linefeed*/
          ++row;               /*go to next row*/
          break;
       case(0x08):             /*if backspace*/
          if(col > 0)
             --col;            /*backspace cursor*/
          *(fptr + col + row*80) = 0x0700;  /*print space*/
          break;
       default:
          *(fptr + col + row*80) = (int)ch | 0x0700;
          ++col;               /*display & go to next col*/
    }
    if(col >= 80)  {           /*if past end of row*/
       col = 0;                /*do carriage return and*/
       ++row;                  /*linefeed*/
    }
    if(row >= 25)              /*if below bottom row*/
       row = 0;                /*start at top*/
    if(col == 0)               /*if at beginning of line*/
       for(j = 0; j < 80; j++)    /*clear line*/
          *(fptr + j + row*80) = 0x0700;
    inregs.h.ah = 2;           /* 'set cursor position' service*/
    inregs.h.dh = row;
    inregs.h.dl = col;
    inregs.h.bh = 0;           /*page number*/
    int86(VIDEO, &inregs, &outregs);
 }

 /* init() */      /* initialize serial port */
 init(conf)
 char conf;        /*addr of configuration code*/
 {
    inregs.h.ah = 0;        /* 'initialize port' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = CONF;     /*configuration*/
    int86(RS232, &inregs, &outregs);
 }

 /* send() */      /* send char to serial port */
 send(c)
 char c;
 {
    inregs.h.ah = 1;        /* 'send char' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = c;        /*character*/
    int86(RS232, &inregs, &outregs);
 }

 /* ready */    /* get serial port ready status */
 ready()
 {
    inregs.h.ah = 3;        /* 'get status' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.x.ax & DATAR);    /*return 'data ready' status*/
 }

 /* receive */     /* get character from serial port */
 char receive()
 {
    inregs.h.ah = 2;        /* 'receive char' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.h.al & 0x7F);     /*return character*/
                                     /* (AND off 8th bit*/
 }

 /* initime() */   /* initializes time delay for timeout() function */
 /* delays number of hundredths of a second in argument */
 /* increments every 5 or 6 hundredths sec */

 <types.h>      /*defines time_b type in timeb*/
 <timeb.h>      /*defines time_b structure*/
 struct timeb xtime;     /*structure for time info*/
 long time1, time2;      /*start & running times*/
 long intval;            /*interval in hundredths*/

 initime(hsecs)
 long hsecs;
 {

    intval = (hsecs < 12) ? 12 : hsecs;    /*minimum is 12*/
    ftime(&xtime);
    time1 = (long)xtime.millitm/10 + xtime.time*100;
 }

 /* timeout() */   /* Returns 1 to function timer() */
 /* if time interval exceeded, 0 otherwise. */
 timeout()
 {

    ftime(&xtime);
    time2 = (long)xtime.millitm/10 + xtime.time*100;
    return((time2-time1 > intval) ? 1 : 0);
 }



 MISC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\ADVC\MISC.C

 #include <stdio.h>

 void delay(seconds)
    unsigned int seconds;
 {
    long dtime;

    dtime = time(NULL) + seconds;

    while (dtime != time(NULL));
 }


 MISC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\MISC.C

 /*
 This is a collection of miscellaneous routines written in CI-C86.  They use
 some of CI's library routines, although these are either standard or easily
 written.  I *think* the only non-standard one is sysint(irpt, regs, regs),
 where irpt is the interrupt desired, and regs are defined as:

         struct reg_set { int ax, bx, cx, dx, si, di, ds, es; } *regs;

 The functionality should be obvious.  I make no claims; specifically, I did
 not clean them up.  They aren't well documented, but are small and simple,
 so you shouldn't have many problems.

 The file format is CI's ARCHive format.  If you don't have ARCH, '-ARCHIVE-'
 starts lines separating files.  Just split them there with an editor (and get
 rid of the line).  The file name and size is also on the separator line.

 Questions, comments, flames, vegetables, etc. can be sent to Alan Batie via:


          >>----->>-------------( Nathan C. Myers )-----------------\
                /                                                    |
               |  ...!decvax!tektronix!ogcvax!hp-pcd!orstcs!nathan   |
               |           nathan.oregon-state@RAND-RELAY            |
                \___________________________________________________/


 ---------------------------------Tear off here-------------------------------
 */
 -ARCHIVE- beep.c 402
 beep(freq, length)
         int freq;
         double length;
         {
         int port_stat;
         int divisor;

         divisor = (long) 1193180 / (long) freq;

         outportb(0x43, 0xB6);        /*  Speaker control port  */
         outportb(0x42, (divisor & 0xFF));        /*  Set frequency  */
         outportb(0x42, ((divisor >> 8) & 0xFF));

         port_stat = inportb(0x61);
         outportb(0x61, port_stat | 0x03);
         pause(length);
         outportb(0x61, port_stat);
         }
 -ARCHIVE- itoa.c 830
 /*
  *  This itoa is not perfect by any means, but at least it doesn't call
  *  in the floating point library (sprintf), and is certainly quicker.
  *
  *  Written by Alan Batie & Nathan Myers, 3-1-1984
  */

 itoa(val, buf)
         int val;
         char *buf;
         {
         int buf_idx;
         int j;
         int div_idx;
         int first;
         static int divisors[] = { 10000, 1000, 100, 10, 1 };

         buf_idx = 0;


         if (val == 0)
                 {
                 buf[0] = '0';
                 buf[1] = '\0';
                 return;
                 }
         else if (val == -32768)
                 {
                 strcpy(buf, "-32768");
                 return;
                 }

         if (val < 0)
                 {
                 buf[buf_idx++] = '-';
                 val = -val;
                 }

         first = 1;
         div_idx = 0;

         while (val)
                 {
                 j = val / divisors[div_idx];
                 if (j != 0 || first != 1)
                         {
                         buf[buf_idx++] = j + '0';
                         first = 0;
                         }
                 val %= divisors[div_idx++];
                 }

         buf[buf_idx] = '\0';
         }
 -ARCHIVE- pause.c 133
 #define DELAY 25400

 pause(seconds)
 double seconds;
         {
         long timer;

         for (timer = seconds * DELAY; timer > 0; timer--);
         }
 -ARCHIVE- timedate.c 874
 /*
  *  File name:                timedate.c
  *
  *  Belongs to:                Extended C library
  *  Description:        Routines to return the current system date and time
  *
  *  Version:                1.1
  *  History:                x/x/84 - Original code
  *  Last change:        x/x/84 - Cleaned up for version 2 library
  *  Author:                Alan Batie
  */

 #include "stdio.h"
 #include "stdext.h"
 #include "timedate.h"

 get_date( date )
 struct date_struct *date;
 {
   struct reg_set regs;

   regs.ax = 0x2A00;
   sysint(0x21, &regs, &regs);

   date->month = (regs.dx >> 8) & 0xFF;
   date->day = regs.dx & 0xFF;
   date->year = regs.cx;
 }

 get_time( time )
 struct time_struct *time;
 {
   struct reg_set regs;

   regs.ax = 0x2C00;
   sysint(0x21, &regs, &regs);

   time->hours = (regs.cx >> 8) & 0xFF;
   time->minutes = regs.cx & 0xFF;
   time->seconds = (regs.dx >> 8) & 0xFF;
   time->centons = regs.dx & 0xFF;
 }
 -ARCHIVE- timedate.h 544

 /*  timedate.h - Structure definitions for use with the library routines
                  get_time and get_date (centons are hundredths of a second)

 struct date_struct { int month, day, year; };
 struct time_struct { int hours, minutes, seconds, centons; };

 #define clear_date(dt) dt.month = dt.day = dt.year = 0
 #define clear_time(tm) tm.hours = tm.minutes = tm.seconds = tm.centons = 0

 /*
  *  extern get_date(cur_date)
  *      struct date_struct *cur_date;
  *
  *  extern get_time(cur_time)
  *      struct time_struct *cur_time;
  */
 -ARCHIVE- timediff.c 436
 #include "timedate.h"

 long time_diff(xtime, ytime)
         struct time_struct *xtime;
         struct time_struct *ytime;
         {
         register long diff;

         diff = xtime->hours * 3600000L;
         diff += xtime->minutes * 60000L;
         diff += xtime->seconds * 1000L;
         diff += xtime->centons * 10L;

         diff -= ytime->hours * 3600000L;
         diff -= ytime->minutes * 60000L;
         diff -= ytime->seconds * 1000L;
         diff -= ytime->centons * 10L;

         return(diff);
         }




 MISCCMDS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\MISCCMDS.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 static        void        openfwd(), openbwd();

 extern        int        did_ai;

 /*
  * opencmd
  *
  * Add a blank line above or below the current line.
  */

 void
 opencmd(dir, can_ai)
 int        dir;
 int        can_ai;                        /* if true, consider auto-indent */
 {
         if (dir == FORWARD)
                 openfwd(can_ai);
         else
                 openbwd(can_ai);
 }

 static void
 openfwd(can_ai)
 int        can_ai;
 {
         LINE        *l;
         LPTR        *next;
         char        *s;                /* string to be moved to new line, if

         /*
          * If we're in insert mode, we need to move the remainder of the
          * current line onto the new line. Otherwise the new line is left
          * blank.
          */
         if (State == INSERT)
                 s = &Curschar->linep->s[Curschar->index];
         else
                 s = "";

         if ((next = nextline(Curschar)) == NULL)        /* open on last line
                 next = Fileend;

         /*
          * By asking for as much space as the prior line had we make sure
          * that we'll have enough space for any auto-indenting.
          */
         if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
                 return;

         if (*s != NUL)
                 strcpy(l->s, s);                /* copy string to new line */
 #if 0
         else if (can_ai && P(P_AI)) {
                 /*
                  * Auto-indent removed due to buggy implementation...
                  */
                  did_ai = TRUE;
         }
 #endif

         if (State == INSERT)                /* truncate current line at curso
                 *s = NUL;


         Curschar->linep->next = l;        /* link neighbors to new line */
         next->linep->prev = l;

         l->prev = Curschar->linep;        /* link new line to neighbors */
         l->next = next->linep;

         if (next == Fileend)                        /* new line at end */
                 l->num = Curschar->linep->num + LINEINC;

         else if ((l->prev->num) + 1 == l->next->num)        /* no gap, renumb
                 renum();

         else {                                        /* stick it in the midd
                 unsigned long        lnum;
                 lnum = ((long)l->prev->num + (long)l->next->num) / 2;
                 l->num = lnum;
         }

         *Curschar = *nextline(Curschar);        /* cursor moves down */
         Curschar->index = 0;

         s_ins(Cursrow+1, 1);        /* insert a physical line */

         updatescreen();                /* because Botchar is now invalid... *

         cursupdate();                /* update Cursrow before insert */
 }

 static void
 openbwd(can_ai)
 int        can_ai;
 {
         LINE        *l;
         LPTR        *prev;

         prev = prevline(Curschar);

         if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
                 return;

         Curschar->linep->prev = l;        /* link neighbors to new line */
         if (prev != NULL)
                 prev->linep->next = l;

         l->next = Curschar->linep;        /* link new line to neighbors */
         if (prev != NULL)
                 l->prev = prev->linep;

 #if 0
         if (can_ai && P(P_AI)) {
                 did_ai = TRUE;
         }
 #endif

         *Curschar = *prevline(Curschar);        /* cursor moves up */
         Curschar->index = 0;

         if (prev == NULL)                        /* new start of file */
                 Filemem->linep = l;

         renum();        /* keep it simple - we don't do this often */

         cursupdate();                        /* update Cursrow before insert
         if (Cursrow != 0)
                 s_ins(Cursrow, 1);                /* insert a physical line *

         updatescreen();
 }

 int
 cntllines(pbegin,pend)
 LPTR *pbegin, *pend;
 {
         LINE *lp;
         int lnum = 1;

         for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
                 lnum++;

         return(lnum);
 }

 /*
  * plines(p) - return the number of physical screen lines taken by line 'p'
  */
 int
 plines(p)
 LPTR        *p;
 {
         register int        col;
         register char        *s;

         s = p->linep->s;

         if (*s == NUL)                /* empty line */
                 return 1;

         /*
          * If list mode is on, then the '$' at the end of
          * the line takes up one extra column.
          */
         col = P(P_LS) ? 1 : 0;

         for (; *s != NUL ;s++) {
                 if ( *s == TAB && !P(P_LS))
                         col += P(P_TS) - (col % P(P_TS));
                 else
                         col += chars[(unsigned)(*s & 0xff)].ch_size;
         }
         return ((col + (Columns-1)) / Columns);
 }

 void
 fileinfo()
 {
         long        l1, l2;
         char        buf[80];

         if (bufempty()) {
                 msg("Buffer Empty");
                 return;
         }

         l1 = cntllines(Filemem, Curschar);
         l2 = cntllines(Filemem, Fileend) - 1;
         sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
                 (Filename != NULL) ? Filename : "No File",
                 Changed ? " [Modified]" : "",
                 l1, l2, (l1 * 100)/l2);
         msg(buf);
 }

 /*
  * gotoline(n) - return a pointer to line 'n'
  *
  * Returns a pointer to the last line of the file if n is zero, or
  * beyond the end of the file.
  */
 LPTR *
 gotoline(n)
 int n;
 {
         static        LPTR        l;

         l.index = 0;

         if ( n == 0 )
                 l = *prevline(Fileend);
         else {
                 LPTR        *p;

                 for (l = *Filemem; --n > 0 ;l = *p)
                         if ((p = nextline(&l)) == NULL)
                                 break;
         }
         return &l;
 }

 void
 inschar(c)
 int        c;
 {
         register char        *p, *pend;

         /* make room for the new char. */
         if ( ! canincrease(1) )
                 return;

         p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
         pend = &Curschar->linep->s[Curschar->index];

         for (; p > pend ;p--)
                 *p = *(p-1);

         *p = c;

         /*
          * If we're in insert mode and showmatch mode is set, then
          * check for right parens and braces. If there isn't a match,
          * then beep. If there is a match AND it's on the screen, then
          * flash to it briefly. If it isn't on the screen, don't do anything.
          */
         if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']'))
                 LPTR        *lpos, csave;

                 if ((lpos = showmatch()) == NULL)        /* no match, so beep
                         beep();
                 else if (LINEOF(lpos) >= LINEOF(Topchar)) {
                         updatescreen();                /* show the new char f
                         csave = *Curschar;
                         *Curschar = *lpos;        /* move to matching char */
                         cursupdate();
                         windgoto(Cursrow, Curscol);

 /* added for turbo c port 6-14-88 dlm */

 #ifdef TURBO
                         mdelay();                /* brief pause */
 #else
                         delay();
 #endif
                         *Curschar = csave;        /* restore cursor position
                         cursupdate();
                 }
         }

         inc(Curschar);
         CHANGED;
 }

 void
 insstr(s)
 register char *s;
 {
         register char *p, *endp;
         register int k, n = strlen(s);

         /* Move everything in the file over to make */
         /* room for the new string. */
         if (!canincrease(n))
                 return;

         endp = &Curschar->linep->s[Curschar->index];
         p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;

         for (; p>endp ;p--)
                 *p = *(p-n);

         p = &Curschar->linep->s[Curschar->index];
         for ( k=0; k<n; k++ ) {
                 *p++ = *s++;
                 inc(Curschar);
         }
         CHANGED;
 }

 bool_t
 delchar(fixpos)
 bool_t        fixpos;                /* if TRUE, fix the cursor position when
 {
         register int i;

         /* Check for degenerate case; there's nothing in the file. */
         if (bufempty())
                 return FALSE;

         if (lineempty())        /* can't do anything */
                 return FALSE;

         /* Delete the char. at Curschar by shifting everything */
         /* in the line down. */
         for ( i=Curschar->index+1; i < Curschar->linep->size ;i++)
                 Curschar->linep->s[i-1] = Curschar->linep->s[i];

         /* If we just took off the last character of a non-blank line, */
         /* we don't want to end up positioned at the newline. */
         if (fixpos) {
                 if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSER
                         Curschar->index--;
         }
         CHANGED;

         return TRUE;
 }


 void
 delline(nlines)
 {
         register LINE *p, *q;
         int        doscreen = TRUE;        /* if true, update the screen */

         /*
          * There's no point in keeping the screen updated if we're
          * deleting more than a screen's worth of lines.
          */
         if (nlines > (Rows - 1)) {
                 doscreen = FALSE;
                 s_del(Cursrow, Rows-1);        /* flaky way to clear rest of
         }

         while ( nlines-- > 0 ) {

                 if (bufempty())                        /* nothing to delete *
                         break;

                 if (buf1line()) {                /* just clear the line */
                         Curschar->linep->s[0] = NUL;
                         Curschar->index = 0;
                         break;
                 }

                 p = Curschar->linep->prev;
                 q = Curschar->linep->next;

                 if (p == NULL) {                /* first line of file so... *
                         Filemem->linep = q;        /* adjust start of file */
                         Topchar->linep = q;        /* and screen */
                 } else
                         p->next = q;
                 q->prev = p;

                 clrmark(Curschar->linep);        /* clear marks for the line

                 /*
                  * Delete the correct number of physical lines on the screen
                  */
                 if (doscreen)
                         s_del(Cursrow, plines(Curschar));

                 /*
                  * If deleting the top line on the screen, adjust Topchar
                  */
                 if (Topchar->linep == Curschar->linep)
                         Topchar->linep = q;

                 free(Curschar->linep->s);
                 free(Curschar->linep);

                 Curschar->linep = q;
                 Curschar->index = 0;                /* is this right? */
                 CHANGED;

                 /* If we delete the last line in the file, back up */
                 if ( Curschar->linep == Fileend->linep) {
                         Curschar->linep = Curschar->linep->prev;
                         /* and don't try to delete any more lines */
                         break;
                 }
         }
 }


 MODF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\MODF.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/
         double
 modf(x, y)        /* return fractional part of x as double, set *y to
                    integer part of x, also double.                        */
 /*----------------------------------------------------------------------*/
 double x, *y;
 {
         double fint();

         return (x - (*y = fint(x)));
 }


 MONO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DRIVERS\MONO.C

 /*
  *        monochrome device driver
  */

 #include "driver.h"

        VidSeg        0xB0000000        /*  addr of monochrome video RAM
        Attr        0x0700                /*  video attribute mask
        Blank        (Attr + ' ')        /*  a blank

 char        row,                        /*  current row number
         col;                        /*  current column number

 long        VidAddr;                /*  -> current display character        *


 Init()
         {
         cls();

         ((InitParms *)&ReqHdr)->EndAddr = EndAddr();
         ReqHdr.Status = Done;
         }


 Output()
         {
         InOutParms        *iop;        /*  our pointer                */
         long                ta;        /*  -> transfer addr        */
         int                ctr;        /*  byte count                */
         char                c;

         iop = (InOutParms *)&ReqHdr;
         ta = iop->Transfer;
         ctr = iop->Count;

         while (ctr--)
                 switch (c = PeekB(ta))
                         {
                         case '\r' :
                                 doCR();
                                 break;

                         case '\n' :
                                 doLF();
                                 break;

                         case '\b' :
                                 doBS();
                                 break;

                         case '\t' :
                                 doHT();
                                 break;

                         case 0x1A :
                                 cls();
                                 break;

                         default :
                                 putone(c);
                                 break;
                         }

         ReqHdr.Status = Done;
         }


 OutVerify()
         {
         Output();
         }


 OutStatus()
         {
         ReqHdr.Status = Done;
         }


 OutFlush()
         {
         ReqHdr.Status = Done;
         }


 static cls()
         {
         SetW(VidSeg, 2000, Blank);        /*  clear the screen  */

         row = col = 0;
         VidAddr = VidSeg;
         }


 static ScrollUp()
         {
         CopyW(VidSeg + 160, VidSeg, 1920);        /*  move up  */

         SetW(VidSeg + 3840, 80, Blank);                /*  clear last line  *

         VidAddr -= 160;
         row = 24;
         }


 static doCR()
         {
         VidAddr -= (col << 1);
         col = 0;
         }


 static doLF()
         {
         VidAddr += 160;
         if (++row > 24)
                 ScrollUp();
         }


 static doBS()
         {
         if (col)
                 {
                 --col;
                 VidAddr -= 2;
                 }
         }


 static doHT()
         {
         while (col & 7)
                 putone(' ');
         }


 static putone(c)
         char        c;
         {
         PokeW(Attr + c, VidAddr);
         VidAddr += 2;

         if (++col > 79)
                 {
                 col = 0;
                 doLF();
                 }
         }


 MONO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\TCDEV\MONO.C

 /* 78,63 */
 /* 07-14-87 00:06:06 clear the 25th line after scrolling. */
 /* 07-13-87 23:58:36 handle output status. */
 /* 07-13-87 23:53:31 position the cursor after writing. */
 /* 07-13-87 23:44:11 store the correct attributes. */
 #include <dos.h>
 #include <string.h>
 #include <mem.h>

 struct srh {
         char len;
         char unit;
         char cmd;
         int status;
         char res[8];
         union {
                 struct { /* init */
                         char units;
                         char far *kaddr;
                         char far *baddr;
                 } cin;
                 struct { /* media check */
                         char media, stat;
                 } cmc;
                 struct { /* build parameter block. */
                         char media;
                         char far *taddr;
                         char far *baddr;
                 } cbpb;
                 struct { /* reading and writing */
                         char media;
                         char far *taddr;
                         unsigned count;
                         unsigned start;
                 } crw;
                 struct { /* nondestructive read no wait */
                         char ch;
                 } cic;
         } c;
 };
 extern char dev_name[9];
 extern int dev_attr;


 #define WHITE 0x700
 int        row = 0, col = 0;

 device_driver(struct srh far *request)
 {
         char far *tptr;  /* pointer to the string of chars */
         int far *sptr;   /* pointer to the screen */
         unsigned count;
         extern char enddata;

         switch(request->cmd) {
         case  0: /* initialize */
                 strcpy(&dev_name, "MON     ");
                 dev_attr = 0x8000;
                 request->c.cin.kaddr = (char far *) &enddata;
                 request->status = 0x0100;  /* ready */
                 break;
         case  8: /* output */
         case  9: /* output with verify */
                 tptr = request->c.crw.taddr;
                 sptr = (int far *) MK_FP(0xb000, (row*80 + col) <<1);
                 count = request->c.crw.count;
                 while (count--) switch(*tptr) {
                         case 13:
                                 col = 0;
                                 sptr = (int far *) MK_FP(0xb000, (row*80 + co
                                 break;
                         case 10:
                                 if (++row > 24) {
                                         --row;
                                         movedata(0xb000, 160, 0xb000, 0, 24*8
                                         sptr = (int far *) MK_FP(0xb000, (row
                                         {        /* clear the bottom line. */
                                                 int count = 80;

                                                 while (count--) *sptr++ = WHI
                                         }
                                 }
                                 sptr = (int far *) MK_FP(0xb000, (row*80 + co
                                 break;
                         case 8:
                                 if (col) {
                                         col--;
                                         sptr--;
                                         }
                                 break;
                         case 9:
                                 if (col >= 80) break;
                                 while (++col & 7) *sptr++ = WHITE | ' ';
                                 break;
                         default:
                                 if (col++ >= 80) break;
                                 *sptr++ = WHITE | *tptr++;
                                 break;
                 }
                 {
                         int cursor_pos = FP_OFF(sptr) >> 1;
                         disable();
                         outportb(0x3b4, 14);
                         outportb(0x3b5, cursor_pos >> 8);
                         outportb(0x3b4, 15);
                         outportb(0x3b5, cursor_pos & 0xff);
                         enable();
                 }
                 request->status = 0x0100;  /* ready */
                 break;

         case 10: /* output status */
         case 11: /* output buffer flush */
                 request->status = 0x0100;  /* ready */
                 break;
         /* these are cases that we don't handle ourselves */
         case  1: /* media check */
         case  2: /* build bpb */
         case  3: /* input ioctl */
         case  4: /* input */
         case  5: /* input check (buffer status) */
         case  6: /* input status */
         case  7: /* input flush */
         case 12: /* output ioctl */
         default:
                 request->status = 0x8003;  /* unknown command */
                 break;
         }
 }


 MORTYPES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\MORTYPES.C

                                          /* Chapter 4 - Program 2 */
 /* The purpose of this file is to introduce additional data types */

 main()
 {
 int a,b,c;            /* -32768 to 32767 with no decimal point */
 char x,y,z;           /* -128 to 127 with no decimal point     */
 float num,toy,thing;  /* 3.4E-38 to 3.4E+38 with decimal point */

    a = b = c = -27;
    x = y = z = 'A';
    num = toy = thing = 3.6792;

    a = y;           /* a is now 65 (character A)               */
    x = b;           /* x is now -27                            */
    num = b;         /* num will now be -27.00                  */
    a = toy;         /* a will now be 3                         */

 }


 MOUSE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MOUSE\MOUSE.C

 /* mouse.c   - Mouse interface routines for DeSmet C.

                A library of the functions available on the MICROSOFT
                mouse via interrupt #51.  These are the functions 0-15
                which are described in the MS mouse documentation on pages
                49-85.  Each function has been defined so that it can be
                called directly from the DeSmet "C" compiler.  The code
                itself is not difficult to understand.  In fact, each call
                is nothing more than an assignment of the proper values
                to the 8088 registers and subsequent execution of DOS
                interrupt #51.  The DeSmet compiler uses a function called
                _doint() to accomplish the interrupt request.  The original mo
                makes use of global variables _rax, _rbx, etc to represent
                the microprocessor registers.  Adapting this code to other
                compilers should thus be a relatively easy task since all
                that needs to be done is to replace the calls to int86()
                with sysint() or whatever your compiler calls the routine.

                   In order to guarantee that outside subroutines would
                have access to the results of these functions, and to make
                function calls as simple as possible, I had to make use of
                a large number of external variables.  Their names are
                listed here so that they will not conflict with any of the
                variables within the scope of the calling functions:

                TYPE  -          NAME        -     PURPOSE
                ************************************************************
                int          mse_xin        x-input coordinate
                int          mse_yin        y-input coordinate
                int          prscnt[2]        array for count of button presse
                int          x_lstprs[2]        array of x-coords at last pres
                int          y_lstprs[2]        array of y-coords at last pres
                int          rlscnt[2]        array for count of button releas
                int          x_lstrls[2]        array of x-coords at last rele
                int          y_lstrls[2]        array of y-coords at last rele
                int          h_micks        horizontal motion counter
                int          v_micks        vertical motion counters


                   That's it for external variables.  You will need to use
                these names in your own programs to get the results of the
                various function calls.        I have tried to document each o
                the functions well enough that the user will not be confused
                about which external variables are needed.

                   The following is a list of the functions included at this
                point:
  m_installed()               - Returns 1 if a mouse is installed, NULL if non
                             NOTE:  This routine is NOT portable.  It is
                             very sensitive to the operating environment.
                             Please let me know if you come up with a better
                             way of checking for the mouse driver software.
  m_reset()               - Reset mouse driver and return current status
  m_showcur()               - Increment cursor flag and display cursor
  m_hidecur()               - Decrement cursor flag and hide cursor
  m_readloc()               - Read cursor position and status
  m_setloc()               - Set cursor position
  m_keyprs(button)      - Get mouse button press information
  m_keyrls(button)      - Get mouse button release information
  m_setxlim(xmin, xmax) - Set horizontal minimum and maximum
  m_setylim(ymin, ymax) - Set vertical minimum and maximum
  m_defgcur(hot_x, hot_y, curshape)     - Define graphics cursor
  m_deftcur(cur_type, scr_msk, cur_msk) - Define text cursor
  m_mickeys()               - Read mouse motion counters
  m_inpmsk()               - Set user-defined subroutine call mask
  m_penon()               - Turn light-pen emulation on
  m_penoff()               - Turn light-pen emulation off
  m_setasp()               - Set horizontal and vertical motion sensitivity

 The original Lattice functions were modified on 3-2-85 for use with DeSmet C.

  On to the functions! */

 /*************************************************************************/

 #define LEFT  0
 #define RIGHT 1
 #define int86(x)            _doint(x)

 int mse_xin, mse_yin;
 int prscnt[2], x_lstprs[2], y_lstprs[2];
 int rlscnt[2], x_lstrls[2], y_lstrls[2];
 int h_micks, v_micks;

 extern int _rax, _rbx, _rcx, _rdx;

 m_installed()            /* see if mouse driver software is installed */
 {
     /*        This is a TERRIBLE way to check for the driver software.  Pleas
     /*        send FidoMail to Jeff Porter on Fido 103/1985, 103/50, or 103/9
     /*        if you discover a better way of checking.  Thanks! */

     int seg, off;

     off = _peek(51*4, 0);        /* low byte of int. vector offset */
     off += _peek(51*4+1, 0)<<8; /* high byte of int. vector offset */
     seg = _peek(51*4+2, 0);        /* low byte of int. vector segment */
     seg += _peek(51*4+3, 0)<<8; /* high byte of int. vector segment */

     if ( off == 0 && seg == 0 ) /* vector is not set */
         return(0);
     if ( _peek( off, seg ) != 0xeb )        /* check byte of mouse driver */
         return(0);
     if ( _peek( off+1, seg ) != 0x64 )        /* next byte */ /* modified 7-1
         return(0);
     if ( _peek( off+2, seg ) != 0x55 )        /* and next */
         return(0);
     if ( _peek( off+3, seg ) != 0x8b )        /* and the next */
         return(0);
     return(1);                                /* four bytes ok, assume it is
 }

 /***************************************************************/

 m_reset()     /* reset mouse driver and return status of mouse */
 {
    _rax = 0;                    /* set mouse function call 0 */
    int86( 51 );             /* execute mouse interrupt */
    return(_rbx);            /* return status code */
 }

 /****************************************************************/

 m_showcur()    /* increment internal cursor flag and display cursor */
 {

    _rax = 1;                    /* set mouse function call 1 */
    int86( 51 );             /* execute mouse interrupt */
    return(0);                    /* no output from function */
 }


 /****************************************************************/

 m_hidecur()    /* decrement internal cursor flag and hide cursor */
 {

    _rax = 2;                    /* set mouse function call 2 */
    int86( 51 );             /* execute mouse interrupt */
    return(0);                    /* no output from function */
 }


 /****************************************************************/

 m_readloc()    /* get cursor position and button status */
 {
    extern int mse_xin;          /* global integer x-coordinate */
    extern int mse_yin;          /* global integer y-coordinate */

    _rax = 3;                    /* set mouse function call 3 */
    int86( 51 );             /* execute mouse interrupt */
    mse_xin = _rcx;            /* store new x-coordinate */
    mse_yin = _rdx;            /* store new y-coordinate */
    return(_rbx);            /* return button status */
 }

 /****************************************************************/

 m_setloc(x, y)          /* set mouse cursor location */
 int x;                  /* integer x-coordinate parameter */
 int y;                  /* integer y-coordinate parameter */
 {

    _rax = 4;                      /* set mouse function call 4 */
    _rcx = x;                      /* assign new x-coordinate */
    _rdx = y;                      /* assign new y-coordinate */
    int86( 51 );               /* execute mouse interrupt */
    return(0);                      /* no function output */
 }

 /******************************************************************/

 m_keyprs(button)    /* get button press information */
 int button;            /* parameter for left or right button */
 {
    extern int prscnt[];          /* array for count of button presses */
    extern int x_lstprs[];         /* array for x-coordinate at last press */
    extern int y_lstprs[];         /* array for y-coordinate at last press */

    _rax = 5;                /* set mouse function call 5 */
    _rbx = button;        /* pass parameter for left or right button */
    int86( 51 );         /* execute mouse interrupt */
    prscnt[button] = _rbx;    /* store updated press count */
    x_lstprs[button] = _rcx;  /* x-coordinate at last press */
    y_lstprs[button] = _rdx;  /* y-coordinate at last press */
    return(_rax);             /* return button status */
 }

 /******************************************************************/

 m_keyrls(button)    /* get button release information */
 int button;            /* parameter for left or right button */
 {
    extern int rlscnt[];          /* array for count of button releases */
    extern int x_lstrls[];         /* array for x-coordinate at last release *
    extern int y_lstrls[];         /* array for y-coordinate at last release *

    _rax = 6;                /* set mouse function call 6 */
    _rbx = button;        /* pass parameter for left or right button */
    int86( 51 );         /* execute mouse interrupt */
    rlscnt[button] = _rbx;    /* store updated release count */
    x_lstrls[button] = _rcx;  /* x-coordinate at last release */
    y_lstrls[button] = _rdx;  /* y-coordinate at last release */
    return(_rax);             /* return button status */
 }

 /******************************************************************/

 m_setxlim( xmin, xmax)        /* set horizontal minimum and maximum coordinat
 int xmin;                /* minimum x-coordinate for mouse activity */
 int xmax;                /* maximum x-coordinate for mouse activity */
 {

    _rax = 7;                /* set mouse function call 7 */
    _rcx = xmin;         /* load horizontal minimum parameter */
    _rdx = xmax;         /* load horizontal maximum parameter */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /******************************************************************/

 m_setylim( ymin, ymax)        /* set vertical minimum and maximum coordinates
 int ymin;                /* minimum y-coordinate for mouse activity */
 int ymax;                /* maximum y-coordinate for mouse activity */
 {

    _rax = 8;                /* set mouse function call 8 */
    _rcx = ymin;         /* load vertical minimum parameter */
    _rdx = ymax;         /* load vertical maximum parameter */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /******************************************************************/

 m_defgcur( hot_x, hot_y, cur_shape)   /* define graphics cursor attributes */
 int hot_x;                     /* cursor field x-coordinate hot-spot */
 int hot_y;                     /* cursor field y-coordinate hot-spot */
 int cur_shape;                     /* pointer to array of cursor and screen m
 {

    _rax = 9;                /* set mouse function call 9 */
    _rbx = hot_x;        /* load horizontal hot-spot */
    _rcx = hot_y;        /* load vertical hot-spot */
    _rdx = cur_shape;        /* load cursor array pointer address */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /******************************************************************/

 m_deftcur( cur_type, scr_msk, cur_msk)        /* define text cursor type and
 int cur_type;                      /* parameter for software or hardware curs
 int scr_msk;                      /* screen mask value - scan line start */
 int cur_msk;                      /* cursor mask value - scan line stop  */
 {

    _rax = 10;                /* set mouse function call 10 */
    _rbx = cur_type;        /* load cursor type parameter */
    _rcx = scr_msk;        /* load screen mask value */
    _rdx = cur_msk;        /* load cursor mask value */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /******************************************************************/

 m_mickeys()                         /* read mouse motion counters */
 {
    extern int h_micks;                 /* horizontal motion units accumulator
    extern int v_micks;                 /* vertical motion units accumulator *

    _rax = 11;                /* set mouse function call 11 */
    int86( 51 );         /* execute mouse interrupt */
    h_micks = _rcx;        /* store horizontal motion units */
    v_micks = _rdx;        /* store vertical motion units */
    return(0);                /* no function output */
 }

 /******************************************************************/

 m_inpmsk( call_msk, offset)         /* set user defined subroutine and mask *
 int call_msk;                         /* call mask - defines interrupt condit
 int offset;                         /* address offset to user subroutine */
 {

    _rax = 12;                /* set mouse function call 12 */
    _rcx = call_msk;        /* load call mask value */
    _rdx = offset;        /* load user subroutine address */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /*****************************************************************/

 m_penon()                /* turn light-pen emulation on */
 {

    _rax = 13;                /* set mouse function call 13 */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /*****************************************************************/

 m_penoff()                         /* turn light-pen emulation off */
 {

    _rax = 14;                /* set mouse function call 14 */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }

 /*****************************************************************/

 m_setasp( h_ratio, v_ratio)         /* set cursor motion counter sensitivity
 int h_ratio;                         /* horizontal mickey:pixel ratio */
 int v_ratio;                         /* vertical mickey:pixel ratio */
 {

    _rax = 15;                /* set mouse function call 15 */
    _rcx = h_ratio;        /* load horizontal ratio value */
    _rdx = v_ratio;        /* load vertical ratio value */
    int86( 51 );         /* execute mouse interrupt */
    return(0);                /* no function output */
 }



 MOUSE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGAPAINT\MOUSE.C

 /* mouse.c   - Mouse interface routines for Turbo C */

 #define LEFT  0
 #define RIGHT 1

 #include <dos.h>

 unsigned m_reset(void);                             /* reset mouse driver and
 void m_showcur(void);                 /* Increment cursor flag and display cu
 void m_hidecur(void);                 /* Decrement cursor flag and hide curso
 unsigned m_readloc(void);             /* get cursor position and button statu
 void m_setloc(unsigned x, unsigned y);         /* set mouse cursor location
 unsigned m_keyprs(unsigned button);         /* get button press information
 unsigned m_keyrls(unsigned button);         /* get button release information
 void m_setxlim(unsigned xmin,unsigned xmax);        /* set horizontal minimum
 void m_setylim(unsigned ymin,unsigned ymax);        /* set vertical minimum a
 void m_defgcur(unsigned hot_x,unsigned hot_y,unsigned cur_shape);    /* defin
 void m_deftcur(unsigned cur_type,unsigned scr_msk,unsigned cur_msk); /* defin
 void m_mickeys(void);                                      /* read mouse moti
 void m_inpmsk(unsigned call_msk, unsigned offset); /* set user defined subrou
 void m_penon(void);                                                 /* Turn l
 void m_penoff(void);                                        /* Turn light-pen
 void m_setasp(unsigned h_ratio,unsigned v_ratio);         /* set cursor motio


 unsigned mse_xin, mse_yin;
 static unsigned prscnt[3];                   /* array for count of button pre
 static unsigned x_lstprs[3];                  /* array for x-coordinate at la
 static unsigned y_lstprs[3];                  /* array for y-coordinate at la
 static unsigned rlscnt[3];          /* array for count of button releases */
 static unsigned x_lstrls[3];         /* array for x-coordinate at last releas
 static unsigned y_lstrls[3];         /* array for y-coordinate at last releas
 unsigned h_micks, v_micks;

 union REGS r;

 void cmouses(unsigned *func, unsigned *arg2, unsigned *arg3, unsigned *arg4)
 {
         switch(*func) {
                 case 0:
                         *func = m_reset();
                         break;
                 case 1:
                         m_showcur();
                         break;
                 case 2:
                         m_hidecur();
                         break;
                 case 3:
                         *arg2 = m_readloc();
             *arg3 = mse_xin;
                         *arg4 = mse_yin;
                         break;
                 case 4:
             m_setloc(*arg3, *arg4);
                         break;
                 case 5:
                         *func = m_keyprs(*arg2);
                         *arg3 = x_lstprs[*arg2];
                         *arg4 = y_lstprs[*arg2];
                         *arg2 = prscnt[*arg2];
                         break;
                 case 6:
                         *func = m_keyrls(*arg2);
                         *arg3 = x_lstprs[*arg2];
                         *arg4 = y_lstprs[*arg2];
                         *arg2 = prscnt[*arg2];
                         break;
                 case 7:
                         m_setxlim(*arg3, *arg4);
                         break;
                 case 8:
                         m_setylim(*arg3, *arg4);
                         break;
                 case 9:
                         m_defgcur(*arg3, *arg4, *arg2);
                         break;
                 case 10:
                         m_deftcur(*arg2, *arg3, *arg4);
             break;
                 case 11:
                 m_mickeys();
             *arg4 = h_micks;
                         *arg3 = v_micks;
                         break;
                 case 12:
                         m_inpmsk(*arg3, *arg4);
                         break;
                 case 13:
             m_penon();
                         break;
                 case 14:
                         m_penoff();
                         break;
                 case 15:
                         m_setasp(*arg3, *arg4);
                         break;
                 default: break;
         }
 }


 /***************************************************************/

 unsigned m_reset(void)     /* reset mouse driver and return status of mouse *
 {
    r.x.ax = 0;                    /* set mouse function call 0 */
    int86(51, &r, &r );             /* execute mouse interrupt */
    return(r.x.bx);            /* return status code */
 }

 /****************************************************************/

 void m_showcur(void)    /* increment internal cursor flag and display cursor
 {
         return;                                /* no function  */
 }

 /****************************************************************/

 void m_hidecur(void)    /* decrement internal cursor flag and hide cursor */
 {
         return;
 }

 /****************************************************************/

 unsigned m_readloc(void)    /* get cursor position and button status */
 {
    r.x.ax = 3;                    /* set mouse function call 3 */
    int86( 51, &r, &r );             /* execute mouse interrupt */
    mse_xin = r.x.cx;            /* store new x-coordinate */
    mse_yin = r.x.dx;            /* store new y-coordinate */
    return(r.x.bx);            /* return button status */
 }

 /****************************************************************/

 void m_setloc(unsigned x, unsigned y)          /* set mouse cursor location *
 {

    r.x.ax = 4;                      /* set mouse function call 4 */
    r.x.cx = x;                      /* assign new x-coordinate */
    r.x.dx = y;                      /* assign new y-coordinate */
    int86( 51, &r, &r );               /* execute mouse interrupt */
 }

 /******************************************************************/

 unsigned m_keyprs(unsigned button)    /* get button press information */
                                                 /* button is parameter for le
 {

    r.x.ax = 5;                /* set mouse function call 5 */
    r.x.bx = button;        /* pass parameter for left or right button */
    int86( 51, &r, &r );         /* execute mouse interrupt */
    prscnt[button] = r.x.bx;    /* store updated press count */
    x_lstprs[button] = r.x.cx;  /* x-coordinate at last press */
    y_lstprs[button] = r.x.dx;  /* y-coordinate at last press */
    return(r.x.ax);             /* return button status */
 }

 /******************************************************************/

 unsigned m_keyrls(unsigned button)    /* get button release information */
 {

    r.x.ax = 6;                /* set mouse function call 6 */
    r.x.bx = button;        /* pass parameter for left or right button */
    int86( 51, &r, &r );         /* execute mouse interrupt */
    rlscnt[button] = r.x.bx;    /* store updated release count */
    x_lstrls[button] = r.x.cx;  /* x-coordinate at last release */
    y_lstrls[button] = r.x.dx;  /* y-coordinate at last release */
    return(r.x.ax);             /* return button status */
 }

 /******************************************************************/

 void m_setxlim(unsigned xmin,unsigned xmax)        /* set horizontal minimum
 /* xmin = minimum x-coordinate for mouse activity */
 /* xmax = maximum x-coordinate for mouse activity */
 {

    r.x.ax = 7;                /* set mouse function call 7 */
    r.x.cx = xmin;         /* load horizontal minimum parameter */
    r.x.dx = xmax;         /* load horizontal maximum parameter */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /******************************************************************/

 void m_setylim(unsigned ymin,unsigned ymax)        /* set vertical minimum an
 /* ymin = minimum y-coordinate for mouse activity */
 /* ymax = maximum y-coordinate for mouse activity */
 {

    r.x.ax = 8;                /* set mouse function call 8 */
    r.x.cx = ymin;         /* load vertical minimum parameter */
    r.x.dx = ymax;         /* load vertical maximum parameter */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /******************************************************************/

 void m_defgcur(unsigned hot_x,unsigned hot_y,unsigned cur_shape)   /* define
 /* hot_x     = cursor field x-coordinate hot-spot */
 /* hot_y     = cursor field y-coordinate hot-spot */
 /* cur_shape = pointer to array of cursor and screen masks */
 {

    r.x.ax = 9;                /* set mouse function call 9 */
    r.x.bx = hot_x;        /* load horizontal hot-spot */
    r.x.cx = hot_y;        /* load vertical hot-spot */
    r.x.dx = cur_shape;        /* load cursor array pointer address */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /******************************************************************/

 void m_deftcur(unsigned cur_type,unsigned scr_msk,unsigned cur_msk)        /*
 /* cur_type = parameter for software or hardware cursor */
 /* scr_msk  = screen mask value - scan line start */
 /* cur_msk  = cursor mask value - scan line stop  */
 {

    r.x.ax = 10;                /* set mouse function call 10 */
    r.x.bx = cur_type;        /* load cursor type parameter */
    r.x.cx = scr_msk;        /* load screen mask value */
    r.x.dx = cur_msk;        /* load cursor mask value */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /******************************************************************/

 void m_mickeys(void)                         /* read mouse motion counters */
 {
    r.x.ax = 11;                /* set mouse function call 11 */
    int86( 51, &r, &r );         /* execute mouse interrupt */
    h_micks = r.x.cx;        /* store horizontal motion units */
    v_micks = r.x.dx;        /* store vertical motion units */
 }

 /******************************************************************/

 void m_inpmsk(unsigned call_msk, unsigned offset)         /* set user defined
 /* call_msk = call mask - defines interrupt condition */
 /* offset   = address offset to user subroutine */
 {

    r.x.ax = 12;                /* set mouse function call 12 */
    r.x.cx = call_msk;        /* load call mask value */
    r.x.dx = offset;        /* load user subroutine address */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /*****************************************************************/

 void m_penon(void)                /* turn light-pen emulation on */
 {

    r.x.ax = 13;                /* set mouse function call 13 */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /*****************************************************************/

 void m_penoff(void)                         /* turn light-pen emulation off *
 {

    r.x.ax = 14;                /* set mouse function call 14 */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }

 /*****************************************************************/

 void m_setasp(unsigned h_ratio,unsigned v_ratio)         /* set cursor motion
 /* h_ratio = horizontal mickey:pixel ratio */
 /* v_ratio = vertical mickey:pixel ratio */
 {

    r.x.ax = 15;                /* set mouse function call 15 */
    r.x.cx = h_ratio;        /* load horizontal ratio value */
    r.x.dx = v_ratio;        /* load vertical ratio value */
    int86( 51, &r, &r );         /* execute mouse interrupt */
 }



 MOVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\MOVE.C

 /****************************************************************/
 /* MOVE.C - A rocket program typed from the book "Microsoft C   */
 /* Programming for the IBM" by Robert Lafore. The program is on */
 /* page 241. This program doesn't work like it should. See      */
 /* the file ROCKET.C on this disk for one that works a little   */
 /* better.                                                      */
 /****************************************************************/

 #define ROWS 10
 #define COLS 5

 main()
 {
 int count, j, k;
 char *ptr[ROWS];           /*pointers to rows*/
 char *temp;                /*pointer storage*/
 static char pict[ROWS][COLS] = {       /* rocketship */
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       '\x1E',  0,       0          },
       { 0,        '\x1E',  '\x1E',  '\x1E',  0          }  };

 static char gnd[] =        /* ground line */
             { '\xCD', '\xCD', '\xCD', '\xCD', '\xCD' };

    for(count = 0; count < ROWS; count++)     /*set up pointers*/
       *(ptr + count) = *(pict + count);

    for(count = 0; count < ROWS - 1; count++) {
       for(j = 0; j < ROWS; j++) {            /*print rocket*/
          for(k = 0; k < COLS; k++)
             if (*(*(ptr + j) + k) != 0) {
                for(k = 0; k < COLS; k++)
                   printf("%c", *(*(ptr + j) + k));
                printf("%c", '\n');
                break;
             }
       }
       printf("%s\n", gnd);                   /*print ground*/
       temp = *ptr;               /*rotate pointers*/
       for(j = 0; j < ROWS - 1; j++)
          *(ptr + j) = *(ptr + j + 1);
       *(ptr + ROWS - 1) = temp;
    }
 }



 MOVE88.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\MOVE88.C

 /*
 ** BYTE Small-C String Move Benchmark
 ** Version 1 for 8088/8086/80286
 ** March, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** This benchmark moves strings from on location to another.
 ** The strings are moved byte-at-a-time and word-at-a-time.
 **
 ** Operation:
 ** 1. Allocate source and destination buffers.
 ** 2. Turn on stopwatch.
 ** 3. Move contents of source buffer to destination buffer,
 **    COUNT times, byte-at-a-time.
 ** 4. Turn off stopwatch.
 ** 5. Report results.
 ** 6. Modify source and destination buffer pointers to point
 **    to odd byte locations.
 ** 7. Turn on stopwatch.
 ** 8. Move contents of source buffer to destination buffer,
 **    COUNT times, word-at-a-time.
 ** 9. Turn off stopwatch.
 ** 10. Report results.
 ** 11. Modify source and destination buffer pointers to point
 **     to even byte locations.
 ** 12. Turn on stopwatch.
 ** 13. Move contents of source buffer to destination buffer,
 **     COUNT times, word-at-a-time.
 ** 14. Turn off stopwatch.
 ** 15. Report results.
 ** 16. Free allocated space and exit.
 */

 #include stdio.h

 BUFSIZE        10000                /* Buffer size */
 COUNT        10000                /* Repetition count */

 int tblock[4];                        /* Timer block */
 char *sbbuff;                        /* Byte pointer to source buffer */
 char *dbbuff;                        /* Byte pointer to dest. buffer */
 int *swbuff;                        /* Integer pointer to source buffer */
 int *dwbuff;                        /* Integer pointer to dest. buffer */

 main()
 {

         /* Announce yourself */
         printf("BYTE Small-C String Move Benchmark\n");


         /* Now get source and destination buffers */
         sbbuff=malloc(BUFSIZE+4);
         if (sbbuff==NULL) {
                 printf("Not enough memory for source buff.\n");
                 exit(0);
         }
         swbuff=sbbuff;

         dbbuff=malloc(BUFSIZE+4);
         if (dbbuff==NULL) {
                 printf("Not enough memory for dest. buff.\n");
                 exit(0);
         }
         dwbuff=dbbuff;

         /* Do byte-wide move */
         printf("Byte-wide move---\n");
         printf("bytes:%d repetitions:%d\n",BUFSIZE,COUNT);

         gtime(tblock);
         lsmovb(sbbuff,dbbuff,BUFSIZE,COUNT);
         calctim(tblock);

         printf("Time: %d:%d:%d:%d (HH:MM:SS:1/100ths)\n\n\n",
           tblock[0],tblock[1],tblock[2],tblock[3]);

         /* Do word-wide move */
         printf("Word-wide move---\n");

         /* Do first move on odd boundaries */
         if((swbuff&1)!=1) swbuff|=1;
         if((dwbuff&1)!=1) dwbuff|=1;

         printf("Odd byte boundary\n");
         printf("bytes:%d repetitions:%d\n",BUFSIZE,COUNT);

         gtime(tblock);
         lsmovw(swbuff,dwbuff,BUFSIZE/2,COUNT);
         calctim(tblock);

         printf("Time: %d:%d:%d:%d (HH:MM:SS:1/100ths)\n\n",
           tblock[0],tblock[1],tblock[2],tblock[3]);

         /* Now do even boundaries */
         swbuff^=1;
         dwbuff^=1;

         printf("Even byte boundary\n");
         printf("bytes:%d repetitions:%d\n",BUFSIZE,COUNT);

         gtime(tblock);
         lsmovw(swbuff,dwbuff,BUFSIZE/2,COUNT);
         calctim(tblock);

         printf("Time: %d:%d:%d:%d (HH:MM:SS:1/100ths)\n\n",
           tblock[0],tblock[1],tblock[2],tblock[3]);

         /* Free up space we claimed */
         free(dbbuff);
         free(sbbuff);

         /* Go home */
         exit(0);
 }


 /*
 ** lsmovb(src,dest,n,cnt)
 ** Moves n bytes from src to dest.  Repeats cnt time.
 */
 lsmovb(src,dest,n,cnt)
 char *src,*dest;
 int n,cnt;
 {
 #asm
         MOV        BP,SP                ;Get pointer to args
         CLD                        ;Clear direction
         MOV        DX,2[BP]        ;Repeat count
 LSMOVB1:
         MOV        CX,4[BP]        ;Count
         MOV        DI,6[BP]        ;Destination
         MOV        SI,8[BP]        ;Source
         REP        MOVSB                ;Do the move
         DEC        DX                ;Decr. repeat count
         JNZ        LSMOVB1
         XOR        CX,CX                ;For Small C
 #endasm
 }

 /*
 /*
 ** lsmovw(src,dest,n,cnt)
 ** Moves n words from src to dest.  Repeats cnt times.
 */
 lsmovw(src,dest,n,cnt)
 int *src,*dest;
 int n,cnt;
 {
 #asm
         MOV        BP,SP                ;Get pointer to args
         CLD                        ;Clear direction
         MOV        DX,2[BP]        ;Repeat count
 LSMOVW1:
         MOV        CX,4[BP]        ;Count
         MOV        DI,6[BP]        ;Destination
         MOV        SI,8[BP]        ;Source
         REP        MOVSW                ;Do the move
         DEC        DX                ;Decr. repeat count
         JNZ        LSMOVW1
         XOR        CX,CX                ;For Small C
 #endasm
 }



 MSIZE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\MSIZE.C

 long msize(addr)
 register long *addr;
 /*
  *        Return the size, in bytes, of the memory block at <addr>.  Note
  *        that the size is a long value, since the block may have been
  *        allocated by lalloc().
  */
 {
         return((addr[-1] & 0x00FFFFFF) - 4L);
 }


 MSSTUFF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\XLSP20\MSSTUFF.C

 /* msstuff.c - ms-dos specific routines */

 #include "xlisp.h"

 #define LBSIZE 200

 /* external variables */
 extern LVAL s_unbound,true;
 extern FILE *tfp;
 extern int errno;

 /* local variables */
 static char lbuf[LBSIZE];
 static int lpos[LBSIZE];
 static int lindex;
 static int lcount;
 static int lposition;
 static long rseed = 1L;

 /* osinit - initialize */
 osinit(banner)
   char *banner;
 {
     printf("%s\n",banner);
     lposition = 0;
     lindex = 0;
     lcount = 0;
 }

 /* osfinish - clean up before returning to the operating system */
 osfinish()
 {
 }

 /* oserror - print an error message */
 oserror(msg)
   char *msg;
 {
     printf("error: %s\n",msg);
 }

 /* osrand - return a random number between 0 and n-1 */
 int osrand(n)
   int n;
 {
     long k1;

     /* make sure we don't get stuck at zero */
     if (rseed == 0L) rseed = 1L;

     /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
     k1 = rseed / 127773L;
     if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
         rseed += 2147483647L;

     /* return a random number between 0 and n-1 */
     return ((int)(rseed % (long)n));
 }

 /* osaopen - open an ascii file */
 FILE *osaopen(name,mode)
   char *name,*mode;
 {
     return (fopen(name,mode));
 }

 /* osbopen - open a binary file */
 FILE *osbopen(name,mode)
   char *name,*mode;
 {
     char bmode[10];
     strcpy(bmode,mode); strcat(bmode,"b");
     return (fopen(name,bmode));
 }

 /* osclose - close a file */
 int osclose(fp)
   FILE *fp;
 {
     return (fclose(fp));
 }

 /* osagetc - get a character from an ascii file */
 int osagetc(fp)
   FILE *fp;
 {
     return (getc(fp));
 }

 /* osaputc - put a character to an ascii file */
 int osaputc(ch,fp)
   int ch; FILE *fp;
 {
     return (putc(ch,fp));
 }

 /* osbgetc - get a character from a binary file */
 int osbgetc(fp)
   FILE *fp;
 {
     return (getc(fp));
 }

 /* osbputc - put a character to a binary file */
 int osbputc(ch,fp)
   int ch; FILE *fp;
 {
     return (putc(ch,fp));
 }

 /* ostgetc - get a character from the terminal */
 int ostgetc()
 {
     int ch;

     /* check for a buffered character */
     if (lcount--)
         return (lbuf[lindex++]);

     /* get an input line */
     for (lcount = 0; ; )
         switch (ch = xgetc()) {
         case '\r':
                 lbuf[lcount++] = '\n';
                 xputc('\r'); xputc('\n'); lposition = 0;
                 if (tfp)
                     for (lindex = 0; lindex < lcount; ++lindex)
                         osaputc(lbuf[lindex],tfp);
                 lindex = 0; lcount--;
                 return (lbuf[lindex++]);
         case '\010':
         case '\177':
                 if (lcount) {
                     lcount--;
                     while (lposition > lpos[lcount]) {
                         xputc('\010'); xputc(' '); xputc('\010');
                         lposition--;
                     }
                 }
                 break;
         case '\032':
                 xflush();
                 return (EOF);
         default:
                 if (ch == '\t' || (ch >= 0x20 && ch < 0x7F)) {
                     lbuf[lcount] = ch;
                     lpos[lcount] = lposition;
                     if (ch == '\t')
                         do {
                             xputc(' ');
                         } while (++lposition & 7);
                     else {
                         xputc(ch); lposition++;
                     }
                     lcount++;
                 }
                 else {
                     xflush();
                     switch (ch) {
                     case '\003':        xltoplevel();        /* control-c */
                     case '\007':        xlcleanup();        /* control-g */
                     case '\020':        xlcontinue();        /* control-p */
                     case '\032':        return (EOF);        /* control-z */
                     default:                return (ch);
                     }
                 }
         }
 }

 /* ostputc - put a character to the terminal */
 ostputc(ch)
   int ch;
 {
     /* check for control characters */
     oscheck();

     /* output the character */
     if (ch == '\n') {
         xputc('\r'); xputc('\n');
         lposition = 0;
     }
     else {
         xputc(ch);
         lposition++;
    }

    /* output the character to the transcript file */
    if (tfp)
         osaputc(ch,tfp);
 }

 /* osflush - flush the terminal input buffer */
 osflush()
 {
     lindex = lcount = lposition = 0;
 }

 /* oscheck - check for control characters during execution */
 oscheck()
 {
     int ch;
     if (ch = xcheck())
         switch (ch) {
         case '\002':        /* control-b */
             xflush();
             xlbreak("BREAK",s_unbound);
             break;
         case '\003':        /* control-c */
             xflush();
             xltoplevel();
             break;
         case '\024':        /* control-t */
             xinfo();
             break;
         }
 }

 /* xinfo - show information on control-t */
 static xinfo()
 {
     extern int nfree,gccalls;
     extern long total;
     char buf[80];
     sprintf(buf,"\n[ Free: %d, GC calls: %d, Total: %ld ]",
             nfree,gccalls,total);
     errputstr(buf);
 }

 /* xflush - flush the input line buffer and start a new line */
 static xflush()
 {
     osflush();
     ostputc('\n');
 }

 /* xgetc - get a character from the terminal without echo */
 static int xgetc()
 {
     return (bdos(7) & 0xFF);
 }

 /* xputc - put a character to the terminal */
 static xputc(ch)
   int ch;
 {
     bdos(6,ch);
 }

 /* xcheck - check for a character */
 static int xcheck()
 {
     return (bdos(6,0xFF));
 }

 /* xsystem - execute a system command */
 LVAL xsystem()
 {
     char *cmd="COMMAND";
     if (moreargs())
         cmd = (char *)getstring(xlgastring());
     xllastarg();
     return (system(cmd) == 0 ? true : cvfixnum((FIXTYPE)errno));
 }

 /* xgetkey - get a key from the keyboard */
 LVAL xgetkey()
 {
     xllastarg();
     return (cvfixnum((FIXTYPE)xgetc()));
 }

 /* ossymbols - enter os specific symbols */
 ossymbols()
 {
 }


 MTH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\MTH.C

 /* SDB - string arithmetic routines */

 "ctype.h"  /*dns*/

 /* useful definitions */
 #define TRUE            1
 #define FALSE           0
 #define NUMBERMAX       99
 #define EOS             0

 /* db_cmp - compare two signed numeric strings */
 int db_cmp(arg1,arg2)
   char *arg1,*arg2;
 {
     int sign1,sign2;

     /* get the signs of the arguments */
     sign1 = getsign(&arg1);
     sign2 = getsign(&arg2);

     /* compute the result */
     if (sign1 == sign2) {
         if (sign1 == 1)
             return (compare(arg1,arg2));
         else
             return (compare(arg2,arg1));
     }

     /* signs are different */
     return (sign1);
 }

 /* db_add - add two signed numeric strings */
 db_add(result,arg1,arg2)
   char *result,*arg1,*arg2;
 {
     int signr,sign1,sign2;
     char rtmp[NUMBERMAX+2],*rptr;

     /* get the signs of the arguments */
     sign1 = getsign(&arg1);
     sign2 = getsign(&arg2);

     /* compute the result */
     if (sign1 == sign2) {
         signr = sign1;
         add(rtmp,arg1,arg2);
     }
     else
         switch (compare(arg1,arg2)) {
         case -1:
                 signr = sign2;
                 sub(rtmp,arg2,arg1);
                 break;
         case 0:
                 strcpy(result,"0");
                 return;
         case 1:
                 signr = sign1;
                 sub(rtmp,arg1,arg2);
                 break;
         }

     /* insert the sign */
     if (signr == -1)
         strcpy(result,"-");
     else
         result[0] = EOS;

     /* eliminate possible leading zeros */
     for (rptr = rtmp; *rptr == '0'; rptr++)
         ;

     /* copy the result */
     if (*rptr != EOS)
         strcat(result,rptr);
     else
         strcat(result,"0");
 }

 /* db_sub - subtract two signed numeric strings */
 db_sub(result,arg1,arg2)
   char *result,*arg1,*arg2;
 {
     int signr,sign1,sign2;
     char rtmp[NUMBERMAX+2],*rptr;

     /* get the signs of the arguments */
     sign1 = getsign(&arg1);
     sign2 = getsign(&arg2);

     /* invert the sign of arg2 */
     sign2 = -sign2;

     /* compute the result */
     if (sign1 == sign2) {
         signr = sign1;
         add(rtmp,arg1,arg2);
     }
     else
         switch (compare(arg1,arg2)) {
         case -1:
                 signr = sign2;
                 sub(rtmp,arg2,arg1);
                 break;
         case 0:
                 strcpy(result,"0");
                 return;
         case 1:
                 signr = sign1;
                 sub(rtmp,arg1,arg2);
                 break;
         }

     /* insert the sign */
     if (signr == -1)
         strcpy(result,"-");
     else
         result[0] = EOS;

     /* eliminate a possible leading zero */
     for (rptr = rtmp; *rptr == '0'; rptr++)
         ;

     /* copy the result */
     if (*rptr != EOS)
         strcat(result,rptr);
     else
         strcat(result,"0");
 }

 /* add - add two unsigned numeric strings */
 static add(result,arg1,arg2)
   char *result,*arg1,arg2;
 {
     char *vr,*v1,*v2,*vx;
     int carry,i,nmin,nmax,nd1,nd2;


     /* get number of digits in each argument */
     nd1 = getlen(arg1);
     nd2 = getlen(arg2);

     /* compute the address of the last digit + 1 */
     v1 = arg1 + nd1;
     v2 = arg2 + nd2;

     /* compute minimum and maximum of nd1 and nd2 */
     if (nd1 < nd2) {
         nmin = -nd1;
         nmax = -nd2;
         vx = v2;
     }
     else {
         nmin = -nd2;
         nmax = -nd1;
         vx = v1;
     }

     /* compute the address of the last result digit + 1 */
     vr = result - nmax; vr[0] = EOS;

     /* initialize the carry */
     carry = 0;

     /* add the digits */
     for (i = -1; i >= nmin; i--) {

         /* check for decimal point */
         if (v1[i] == '.')
             vr[i] = '.';
         else {

             /* add the current pair of digits with the carry */
             vr[i] = v1[i] + v2[i] + carry - '0';

             /* check for carry */
             if (vr[i] > '9') {
                 vr[i] -= 10;
                 carry = 1;
             }
             else
                 carry = 0;
         }
     }

     /* add the remaining digits */
     for (; i >= nmax; i--) {

         /* add the current digit with the carry */
         vr[i] = vx[i] + carry;

         /* check for carry */
         if (vr[i] > '9') {
             vr[i] -= 10;
             carry = 1;
         }
         else
             carry = 0;
     }

     /* check for a carry out and shift digits if necessary */
     if (carry == 1) {

         /* shift the digits */
         for (i = -nmax; i >= 0; i--)
             result[i+1] = result[i];
         result[0] = '1';
     }
 }

 /* sub - subtract two unsigned numeric strings */
 static sub(result,arg1,arg2)
   char *result,*arg1,arg2;
 {
     char *vr,*v1,*v2,*vx;
     int borrow,i,nmin,nmax,nd1,nd2;

     /* get number of digits in each argument */
     nd1 = getlen(arg1);
     nd2 = getlen(arg2);

     /* compute the address of the last digit + 1 */
     v1 = arg1 + nd1;
     v2 = arg2 + nd2;

     /* compute minimum and maximum of nd1 and nd2 */
     if (nd1 < nd2) {
         nmin = -nd1;
         nmax = -nd2;
         vx = v2;
     }
     else {
         nmin = -nd2;
         nmax = -nd1;
         vx = v1;
     }

     /* compute the address of the last result digit + 1 */
     vr = result - nmax; vr[0] = EOS;

     /* initialize the borrow */
     borrow = 0;

     /* subtract the digits */
     for (i = -1; i >= nmin; i--) {

         /* check for decimal point */
         if (v1[i] == '.')
             vr[i] = '.';
         else {

             /* subtract the current pair of digits with the borrow */
             vr[i] = v1[i] - v2[i] - borrow + '0';

             /* check for borrow */
             if (vr[i] < '0') {
                 vr[i] += 10;
                 borrow = 1;
             }
             else
                 borrow = 0;
         }
     }

     /* subtract the remaining digits */
     for (; i >= nmax; i--) {

         /* subtract the current digit with the borrow */
         vr[i] = vx[i] - borrow;

         /* check for borrow */
         if (vr[i] < '0') {
             vr[i] += 10;
             borrow = 1;
         }
         else
             borrow = 0;
     }
 }

 /* getsign - get the sign of a numeric string */
 static int getsign(parg)
   char **parg;
 {
     int sign;
     char *p;

     /* eliminate leading spaces */
     while (isspace(**parg))
         *parg += 1;

     /* get the sign */
     switch (**parg) {
     case '+':   *parg += 1;
                 sign = 1;
                 break;
     case '-':   *parg += 1;
                 sign = -1;
                 break;
     default:    sign = 1;
                 break;
     }

     /* eliminate leading spaces and zeros */
     while (isspace(**parg) || **parg == '0')
         *parg += 1;

     /* if the value is zero, make sure that the sign is positive */
     switch (**parg) {
     case EOS:   sign = 1;
                 break;
     case '.':   for (p = *parg + 1; *p == '0'; p++)
                     ;
                 if (*p == EOS)
                     sign = 1;
                 break;
     }

     /* return the sign */
     return (sign);
 }

 /* getlen - get the length of a numeric string */
 static int getlen(arg)
   char *arg;
 {
     int len;

     /* get the length of the string */
     len = strlen(arg);

     /* eliminate trailing spaces */
     while (isspace(arg[len-1]))
         len -= 1;

     /* return the length */
     return (len);
 }

 /* compare - compare two unsigned numeric strings */
 static int compare(arg1,arg2)
   char *arg1,*arg2;
 {
     int len1,len2;

     /* compare lengths */
     if ((len1 = getlen(arg1)) != (len2 = getlen(arg2)))
         if (len1 < len2)
             return (-1);
         else
             return (1);

     /* compare strings */
     return (strcmp(arg1,arg2));
 }



 MULTIARY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\MULTIARY.C

                                            /* Chapter 7 - Program 6 */
 main()
 {
 int i,j;
 int big[8][8],large[25][12];

    for (i = 0;i < 8;i++)
       for (j = 0;j < 8;j++)
          big[i][j] = i * j;       /* This is a multiplication table */

    for (i = 0;i < 25;i++)
       for (j = 0;j < 12;j++)
          large[i][j] = i + j;           /* This is an addition table */

    big[2][6] = large[24][10]*22;
    big[2][2] = 5;
    big[big[2][2]][big[2][2]] = 177;     /* this is big[5][5] = 177; */

    for (i = 0;i < 8;i++) {
       for (j = 0;j < 8;j++)
          printf("%5d ",big[i][j]);
       printf("\n");               /* newline for each increase in i */
    }
 }


 MV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\KWMV\MV.C

 #include <stdio.h>
 /* mv.c - implements a version of UNIX mv */
 char usage[] = "mv : usage mv file1 [file2 . . fileN] target\r\n";
 char target_name[128];
 main(argc,argv)
         int argc;
         register char *argv[];
 {
         char *target,*fname_part();
         register int i;
         if (argc < 3)
         {
                 write(2,usage,sizeof(usage));
                 exit(-1);
         }
         target = argv[argc-1];
         /* kill trailing backslashes */
         if (target[i = strlen(target)-1] == '\\')
                 target[i] = '\0';
         if (argc == 3)
         {
                 /* if the target doesn't exist and it's not a directory then
                 if (access(target,0) && !dirp(target))
                 {
                         fprintf(stderr,"moving %s to %s\n",argv[1],argv[2]);
                         rename(argv[1],argv[2]);
                 }
                 else
                 {
                         /* if the target is a directory copy to same name tha
                         if (dirp(target))
                         {
                                 int len;
                                 strcpy(target_name,target);
                                 if (target_name[(len = strlen(target_name))-1
                                 {
                                         target_name[len = strlen(target_name)
                                         target_name[len+1] = '\0';
                                 }
                                 strcat(target_name,fname_part(argv[1]));
                                 fprintf(stderr,"moving %s to %s\n",argv[1],ta
                                 filecopy(target_name,argv[1]);
                                 unlink(argv[1]);
                         }
                         else
                         {
                                 fprintf(stderr,"moving %s to %s\n",argv[1],ta
                                 filecopy(target,argv[1]);
                                 unlink(argv[1]);
                         }
                 }
                 exit(0);
         }
         if (!dirp(target))
         {
                 fprintf(stderr,"mv : %s isn't a directory\n",target);
                 exit(-1);
         }
         for (i = 1; i < argc-1; i++)
         {
                 int len;
                 strcpy(target_name,target);
                 if (target_name[(len = strlen(target_name))-1] != '\\')
                 {
                         target_name[len = strlen(target_name)] = '\\';
                         target_name[len+1] = '\0';
                 }
                 strcat(target_name,fname_part(argv[i]));
                 if (!filep(argv[i]))
                 {
                         fprintf(stderr,"mv : %s isn't a file\n",argv[i]);
                         continue;
                 }
                 fprintf(stderr,"moving %s to %s\n",argv[i],target_name);
                 filecopy(target_name,argv[i]);
                 unlink(argv[i]);
         }
 }
 #include <fcntl.h>
 char buffer[BUFSIZ*16];
 filecopy(target,source)
         char *target,*source;
 {
         int t,s,r;
         if (-1 == (s = open(source,O_RDONLY)))
         {
                 fprintf(stderr,"mv : can't open %s\n",target);
                 exit(-1);
         }
         if (-1 == (t = open(target,O_TRUNC)))
         {
                 fprintf(stderr,"mv : can't open %s\n",target);
                 exit(-1);
         }
         while(0 != (r = read(s,buffer,BUFSIZ*16)) && r != -1)
         {
                 if(-1 == write(t,buffer,r))
                 {
                         fprintf(stderr,"mv : error writing %s\n",target);
                         exit(-1);
                 }
         }
         close(t); close(s);
 }
 #include <errno.h>
 typedef struct
 {
         char dos_reserved[21];
         char attribute;
         unsigned file_time;
         unsigned file_date;
         long file_size;
         char file_name[13];
 } fcb;
 fcb dir;

 dirp(s)
         char *s;
 {
         register int result1,result2;
         /* set the disk transfer address */
         bdos(0x1A,&dir);
         /* do a search first for the directory path */
         return (bdos(0x4E,s,0x10) == 0 && bdos(0x4E,s,0) != 0);
 }

 filep(s)
         char *s;
 {
         register int result1,result2;
         /* set the disk transfer address */
         bdos(0x1A,&dir);
         /* do a search first for the directory path */
         return bdos(0x4E,s,0) == 0;
 }
 char *fname_part(s)
         char *s;
 {
         char *r,*rindex();
         if (r = rindex(s,'\\'))
         {
                 return r+1;
         }
         return s;
 }


 MV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TOOLS\MV.C

 /*
  *  mv.c move (rename a file or files)
  */

 <stdio.h>              /* Standard I/O definitions */
 <dos.h>                /* Msdos definitions */
 <errno.h>              /* error codes */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>

 static char ID[]="## mv.c 1.0 K.van Houten 230987 ##";
 struct stat statbuf;
 int iflg=0;
 int dflg=0;
 int i;
 int tmp=0;
 char errbuf[100];
 char nmbuf[100];
 char *dp;                       /* points to dest. dir argv[argc-1] */
 char *tp;

 union REGS r;
 struct SREGS s;

 main (argc, argv)
 int     argc;                   /* Number of command line arguments */
 char   *argv[];                 /* Array of pointers to arguments */
 {
     for (argc--,argv++; argc>0; argc--,argv++) {
         if (**argv == '-') {
             while (*++(*argv)) {
                 switch (**argv) {
                 case 'i':
                     iflg++;
                     printf("mv: -i not yet supported.\n");
                     exit(1);
                     break;
                 default:
 usage:              printf("Usage: mv [-i] file [file | [file...] directory]\
                     exit(1);
                 }
             }
         }

         else
             break;
     }
     /*
      * NOW THE ARGV[0] CONTAINS THE FIRST NON-OPTION ARGUMENT,
      * WHILE ARGC CONTAINS THE NUMBER OF ARGUMENTS LEFT.
      * SO WE HAVE AVAILABLE ARGV[0] -- ARGV[ARGC-1].
      */
     if (argc < 2)
         goto usage;
     dp = argv[argc-1];

     if (strcmp(dp,"\\")==0 || strcmp(dp,"..")==0 ||
      (dp[strlen(dp)]=='.' && dp[strlen(dp)-1]=='.' )) {
         dflg++;
     }
     else {
         if (stat(dp,&statbuf) == -1) {
             if (argc>2) {
                 sprintf(errbuf,"mv: %s ",dp);
                 perror(errbuf);
                 exit(1);
             }
         }
         else {
             if ((statbuf.st_mode & S_IFDIR) == 0) {
                 if (argc > 2) {
                     fprintf(stderr,"mv: destination must be directory\n");
                     exit(1);
                 }
             }
             else
                 dflg++;
         }
     }
     for (i=0; i< argc-1 ;i++) {
         if (dflg) {
             if ((tp=strrchr(argv[i],'\\'))==NULL)
                 tp=argv[i];
             else
                 tp++;
             strcpy(nmbuf,dp);
             strcat(nmbuf,"/");
             strcat(nmbuf,tp);
         }
         else {
             strcpy(nmbuf,argv[1]);
         }
         rename(argv[i],nmbuf);
         if (r.x.cflag) {
             sprintf(errbuf,"mv: Error %d ",errno);
             switch(errno) {
             case 2:
                 fprintf(stderr,"mv: File not found.\n");
                 exit(1);
             case 3:
                 fprintf(stderr,"mv: Path not found.\n");
                 exit(1);
             case 5:
                 if (unlink(nmbuf) == -1) {
                     fprintf(stderr,"mv: %s write protect.\n",nmbuf);
                     exit(1);
                 }
                 rename(argv[i],nmbuf);
                 if (r.x.cflag) {
                     fprintf(stderr,"mv: Unexpected Error %d\n",errno);
                     exit(1);
                 }
                 break;
             case 17:
                 fprintf(stderr,"mv: No cross device move\n");
                 exit(1);
             default:
                 fprintf(stderr,"mv: Unexpected ERROR.\n");
                 exit(1);
             }
         }
     }
     exit(0);
 }

 rename(c1,c2)
 char *c1, *c2;
 {
         segread(&s);
         s.es = s.ds;
         r.h.ah = 0x56;   /* Rename function */
         r.x.dx = (int)c1;
         r.x.di = (int)c2;
         errno = intdosx(&r, &r, &s);
 }




 M_COFACT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_COFACT.C

 static char *sccsid = "@(#)m_cofactor.c        4/5/82 (U of Maryland, FLB)";

 #include "mat.h"

 double
 m_cofactor(mat, i, j)
 register struct matrix *mat;
 register int i, j;
 {
 register struct matrix *result;
 register int row, col, o_row = 0, o_col = 0;
 double det;

 m_create(result, mat->m_rows - 1, mat->m_cols - 1);

 for (row = 0; row < mat->m_rows; row++)
         for (col = 0; col < mat->m_cols; col++)
                 if (row != i && col != j)
                         m_v(result, o_row++, o_col++) = m_v(mat, row, col);

 det = m_determinant(result);
 free(result);

 return(((i + j) & 01)? -det: det);
 }



 M_COPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_COPY.C

 static char *sccsid = "@(#)m_copy.c        4/5/82 (U of Maryland, FLB)";

 #include "mat.h"

 struct matrix *
 m_copy(mat)
 register struct matrix *mat;
 {
 register struct matrix *result;
 register int row, col;

 m_create(result, mat->m_rows, mat->m_cols);

 for (row = 0; row < mat->m_rows; row++)
         for (col = 0; col < mat->m_cols; col++)
                 m_v(result, row, col) = m_v(mat, row, col);

 return(result);
 }



 M_DETERM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_DETERM.C

 static char *sccsid = "@(#)m_determinant.c        4/5/82 (U of Maryland, FLB)

 #include "mat.h"

 double
 m_determinant(mat)
 register struct matrix *mat;
 {
 register int col;
 double det = 0.0;

 if (mat->m_rows == 1)
         return(m_v(mat, 0, 0));

 for (col = 0; col < mat->m_cols; col++)
         det +=         m_v(mat, 0, col) * m_cofactor(mat, 0, col);

 return(det);
 }



 M_DUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_DUMP.C

 static char *sccsid = "@(#)m_dump.c        4/6/82 (U of Maryland, FLB)";

 #include "mat.h"

 struct matrix *
 m_dump(mat)
 register struct matrix *mat;
 {
 register int row, col;

 printf("%d X %d\n", mat->m_rows, mat->m_cols);

 for (row = 0; row < mat->m_rows; row++) {
         for (col = 0; col < mat->m_cols; col++)
                 printf("%f, ", m_v(mat, row, col));
         putchar('\n');
         }
 }



 M_INVERT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_INVERT.C

 static char *sccsid = "@(#)m_invert.c        4/7/82 (U of Maryland, FLB)";

 #include "mat.h"

 struct matrix *
 m_invert(mat)
 register struct matrix *mat;
 {
 register struct matrix *result;
 register int row, col;
 double det;

 if((det = m_determinant(mat)) == 0.0) {
         printf("m_invert: singular matrix\n");
         return(M_NULL);
         }

 m_create(result, mat->m_cols, mat->m_rows);

 for (row = 0; row < mat->m_rows; row++)
         for (col = 0; col < mat->m_cols; col++)
                 m_v(result, col, row) = m_cofactor(mat, row, col) / det;

 return(result);
 }



 M_MULTIP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_MULTIP.C

 static char *sccsid = "@(#)m_multiply.c        4/6/82 (U of Maryland, FLB)";

 #include "mat.h"

 struct matrix *
 m_multiply(mat1, mat2)
 register struct matrix *mat1, *mat2;
 {
 register struct matrix *result;
 register int row, col, ix;
 double sum;

 if (mat1->m_cols != mat2->m_rows) {
         printf("m_multiply: matrices not compatible.\n");
         return(M_NULL);
         }

 m_create(result, mat1->m_rows, mat2->m_cols);

 for (row = 0; row < mat1->m_rows; row++)
         for (col = 0; col < mat2->m_cols; col++) {
                 sum = 0.0;
                 for (ix = 0; ix < mat1->m_cols; ix++)
                         sum += m_v(mat1, row, ix) * m_v(mat2, ix, col);
                 m_v(result, row, col) = sum;
                 }

 return(result);
 }



 M_READ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_READ.C

 static char *sccsid = "@(#)m_read.c        4/6/82 (U of Maryland, FLB)";

 #include <stdio.h>
 #include "mat.h"

 struct matrix *
 m_read()
 {
 register struct matrix *result;
 register int row, col;
 int rows, cols;

 scanf("%d%d", &rows, &cols);
 m_create(result, rows, cols);

 for (row = 0; row < rows; row++)
         for (col = 0; col < cols; col++)
                 scanf("%lf", &m_v(result, row, col));

 return(result);
 }



 M_SOLVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_SOLVE.C

 static char *sccsid = "@(#)m_solve.c        4/16/82 (U of Maryland, FLB)";

 #include "mat.h"

 struct matrix *
 m_solve(a, b)
 register struct matrix *a, *b;
 {
 register struct matrix *a_trans, *t, *t_inv, *t2, *x;

 if ((a->m_rows) < (a->m_cols)) {
         printf("m_solve: too few equations\n");
         return(M_NULL);
         }

 if ((a->m_rows) != (b->m_rows)) {
         printf("m_solve: arguments don't match: %d, %d.\n", a->m_rows, b->m_r
         return(M_NULL);
         }

 if (b->m_cols != 1) {
         printf("m_solve: arg2 must have 1 column.\n");
         return(M_NULL);
         }

 a_trans = m_transpose(a);                /* A' */
 t = m_multiply(a_trans, a);                /* A' A */
 t_inv = m_invert(t);                        /* (A' A)-1 */
 free(t);
 if (t_inv == M_NULL) {
         printf("m_solve: no solution\n");
         return(M_NULL);
         }
 t2 = m_multiply(t_inv, a_trans);        /* (A' A)-1 A' */
 free(t_inv);
 free(a_trans);
 x = m_multiply(t2, b);                        /* (A' A)-1 A' B */
 free(t2);

 return(x);
 }



 M_TRANSP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\MATRIX\M_TRANSP.C

 static char *sccsid = "@(#)m_transpose.c        4/5/82 (U of Maryland, FLB)";

 #include "mat.h"

 struct matrix *
 m_transpose(mat)
 register struct matrix *mat;
 {
 register struct matrix *result;
 register int row, col;

 m_create(result, mat->m_cols, mat->m_rows);

 for (row = 0; row < mat->m_rows; row++)
         for (col = 0; col < mat->m_cols; col++)
                 m_v(result, col, row) = m_v(mat, row, col);

 return(result);
 }



 NAMES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\BPLUS11\NAMES.C

 /*******************************************************************/
 /*                              NAMES.C                             */
 /*                                                                  */
 /* This example shows how easy it is to write a program for an      */
 /* online address book using the B-PLUS file indexing toolkit.      */
 /* The program creates a file of names, addresses, and telephone    */
 /* numbers.  A record is displayed on the screen by entering part   */
 /* or all of the name.  Although the program is usefully as written */
 /* it has purposely been kept simple.  You may want to add new      */
 /* features to the progran.                                         */
 /*                                                                  */
 /********************************************************************/


 #include <stdio.h>
 #include <string.h>
 #include "bplus.h"


 typedef struct              /* Here is the address record definition */
   {
      char lastname[16];     /* last name           */
      char firstname[16];    /* first name          */
      char address1[31];     /* first address line  */
      char address2[31];     /* second address line */
      char city[21];         /* the city            */
      char state[3];         /* the state           */
      char zipcode[6];       /* postal zip code     */
      char telephone[14];    /* telephone number    */
   }  ADDRESS;


 IX_DESC  nameindex;             /* index file variable  */
 FILE     *namefile;             /* data file pointer    */
 ADDRESS  person;                /* data record variable */


 void openfiles(void);
 void closefiles(void);
 int addrecord(void);
 void getstring(char*, int);
 void newaddress(void);
 void printname(ENTRY*);
 void getname(void);
 void nextname(void);
 void listnames(void);


 void openfiles()
   /* If the file NAMES.DAT already exist, open the index and data */
   /* file.  Otherwise, these files are created.                   */
   {
     if ((namefile = fopen("names.dat","r+")) != NULL)
       open_index("names.idx", &nameindex, 1);      /* open index file  */
     else
     {
       namefile = fopen("names.dat","w+");          /* create data file */
       if (namefile == NULL)
         {
           printf("Unable to open namefile\n");
           exit(1);
         }
       make_index("names.idx", &nameindex, 1);   /* creat index file     */
     }                                           /* allow duplicate keys */
   } /* openfiles */


 void closefiles()
   /* close all files and exit */
   {
     fclose(namefile);
     close_index(&nameindex);
     exit(0);
   } /* closefiles */


 int addrecord()
   /* add a new address to the data file - add index to index file */
   {
     ENTRY ee;
     char name[32];
     int ret;
     ret = fseek(namefile, 0L, SEEK_END);      /* seek to end of datafile  */
     if (ret == 0)
       {
         strcpy(ee.key, person.lastname);      /* key is last name followed */
         strcat(ee.key, person.firstname);     /* first name.  Capitalize   */
         strupr(ee.key);                       /*    and copy to ee.key.    */
         ee.recptr = ftell(namefile);          /* get position in datafile  */
         if (ee.recptr != -1L)
           {
             if (add_key(&ee, &nameindex) == IX_OK)     /* add key to index */
               {
                 fwrite(&person,sizeof(person),1,namefile);  /* add address */
                 return (IX_OK);
               }
           }
       }
     else printf("Seek error - data file");
     return (IX_FAIL);
   } /* addrecord */


 void getstring(mes, length)
   char *mes;
   int length;
   /* input a string and check that it is not too long   */
   {
     char message[80];
     gets(message);
     if (strlen(message) > length) message[length] = '\0';
     strcpy(mes,message);
   } /* getstring */


 void newaddress()
   /* add new address records */
   {
     while (1)
      {
        printf("\n\nLast Name      : ");
        getstring(person.lastname,15);
        if ( strlen(person.lastname) > 0)       /* quit if no last name */
          {
            printf("First Name     : ");
            getstring(person.firstname,15);
            printf("Address Line 1 : ");
            getstring(person.address1,30);
            printf("Address Line 2 : ");
            getstring(person.address2,30);
            printf("City           : ");
            getstring(person.city,20);
            printf("State          : ");
            getstring(person.state,2);
            printf("Zip Code       : ");
            getstring(person.zipcode,5);
            printf("Telephone      : ");
            getstring(person.telephone,13);
            addrecord();                     /* update data and index files */
            printf("\n");
          }
          else return ;
      }
   } /* newaddress */


 void printname(e)
   ENTRY *e;
   /* retrieve a data record and print it on the screen */
   {
     int ret;

     /* seek to the record address stored in ENTRY e->recptr */
     ret = fseek(namefile, e->recptr, SEEK_SET);

     if (ret == 0)     /* if OK read the record and display */
       {
         fread(&person,sizeof(person),1,namefile);
         printf("\n\n            %s %s" , person.firstname,person.lastname);
         printf("\n            %s", person.address1);
         if (strlen(person.address2) > 0)
            printf("\n            %s", person.address2);
         printf("\n            %s, %s  %s", person.city,person.state,person.zi
         printf("\n            %s\n", person.telephone);
       }
     else printf("Seek error - data file");
   } /* printname */


 void getname()
   /* Get an address record by entering part or all of name */
   /* Enter last name first then first name with no spaces  */
   {
     ENTRY ee;
     printf("\n\nEnter name: ");
     gets(ee.key);

     /* make all upper case letters and copy to ee.key */
     strupr(ee.key);

     /* use locate_key instead of find_key so an exact match not required */
     if (locate_key(&ee, &nameindex) != EOIX) printname(&ee);
     else printf("No key this large in index file\n");
   } /* getname */


 void nextname()
   /* display the next address in the address file */
   {
     ENTRY ee;
     if (next_key(&ee, &nameindex) == IX_OK) printname(&ee);
     else printf("\nEnd of index file\n");
   } /* nextname */


 void listnames()
   /* list all the names in the address file */
   {
     ENTRY ee;
     first_key(&nameindex);
     while (next_key(&ee, &nameindex) == IX_OK) printname(&ee);
   } /* listnames */

 main()
   /* Here is the main program loop */
   {
     char cmd;
     int  done;
     done = 0;
     openfiles();
     do
      {
        printf("\nCommand: A (Add Name), F (Find), N (Next), L (List), Q (Quit
        cmd = toupper(getche());
        switch (cmd)
         {
           case 'A': newaddress(); break;   /* add a name to address file   */
           case 'F': getname(); break;      /* find an address              */
           case 'N': nextname(); break;     /* display next address in file */
           case 'L': listnames(); break;    /* display all addresses        */
           case 'Q': closefiles();          /* quit and close files         */
         }
       }
     while (!done);
   } /* main */



 NDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\NDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==NORTH)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 NEDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\NEDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==NORTH_EAST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 NESTED.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\NESTED.C

                                      /* Chapter 11 - Program 4 */
 main()
 {
 struct person {
    char name[25];
    int age;
    char status;        /* M = married, S = single */
 } ;

 struct alldat {
    int grade;
    struct person descrip;
    char lunch[25];
 } student[53];

 struct alldat teacher,sub;

 teacher.grade = 94;
 teacher.descrip.age = 34;
 teacher.descrip.status = 'M';
 strcpy(teacher.descrip.name,"Mary Smith");
 strcpy(teacher.lunch,"Baloney sandwich");

 sub.descrip.age = 87;
 sub.descrip.status = 'M';
 strcpy(sub.descrip.name,"Old Lady Brown");
 sub.grade = 73;
 strcpy(sub.lunch,"Yogurt and toast");

 student[1].descrip.age = 15;
 student[1].descrip.status = 'S';
 strcpy(student[1].descrip.name,"Billy Boston");
 strcpy(student[1].lunch,"Peanut Butter");
 student[1].grade = 77;

 student[7].descrip.age = 14;
 student[12].grade = 87;

 }


 NOISE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\NOISE.C

 /*                      Noise Maker Main Program
  */

 #define FALSE 0
 #define TRUE 1

 /*      main()

         Function: Produce sound-effect. Repeatedly ask the user what
         sound to make, and then make it.

         Algorithm: Loop, asking the user for which sound and how many
         times to make it. Then repeat the sound generation code the
         number of times requested. To generate the sound, switch on the
         type of sound to generate. Each sound is generated by sweeping
         through a set of frequencies in a particular order at a particular
         rate.
 */

 main()

 {
         int snd;        /* Which sound to produce. */
         int cnt;        /* Number of times to repeat sound. */
         int note;       /* Current note, when sweeping frequencies. */

         while (TRUE) {
                 /* Make sure any previous sounds are turned off. */
                 sndOff();
                 /* Ask the user for which type of sound. */
                 printf("1-siren; 2-overload; 3-whoop; 4-phaser; 0-exit: ");
                 /* Read the answer. */
                 scanf("%d",&snd);
                 /* If the answer is to exit, do so. */
                 if (snd == 0) break;
                 /* Ask how many times to repeat the sound. */
                 printf("Number of times: ");
                 /* Get the answer. */
                 scanf("%d",&cnt);
                 /* Repeat the sound the number of time specified. */
                 while (cnt--) {
                         /* Switch on type of sound to produce. */
                         switch (snd) {
                                 case 1:
                                         /* Do a siren: sweep up. */
                                         for (note = 1000; note > 150;
                                              note -= 10) {
                                                 sound(note); delay(200);
                                         };
                                         /* Sweep down. */
                                         for (; note < 1000; note += 10) {
                                                 sound(note); delay(200);
                                         };
                                         break;
                                 case 2:
                                         /* Do an overload: sweep up. */
                                         for (note = 4000; note > 10;
                                              note -= 10) {
                                                 sound(note); delay(700);
                                         };
                                         break;
                                 case 3:
                                         /* Do a whoop: sweep up. */
                                         for (note = 1000; note > 10;
                                              note -= 10) {
                                                 sound(note); delay(200);
                                         };
                                         break;
                                 case 4:
                                         /* Do a phaser: sweep down. */
                                         for (note = 60; note < 2000;
                                              note += 10) {
                                                 sound(note); delay(100);
                                         };
                                         break;
                                 default:
                                         /* Unknown, ask again. */
                                         printf("Invalid entry; try again.\n")
                                         break;
                         };
                 };
         };
 }

 /*      delay(cnt)

         Function: Delay for an amount of time proportional to cnt.

         Algorithm: Just waste time in a for loop.
 */

 delay(cnt)

 {
         int i;

         /* Loop to burn time... */
         for (i = 0; i < cnt; i++);
 }



 NOISE2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\NOISE2.C

 /*                      Noise Maker Main Program
  */

 #define FALSE 0
 #define TRUE 1

 /*      main()

         Function: Produce sound-effect. Repeatedly ask the user what
         sound to make, and then make it.

         Algorithm: Loop, asking the user for which sound and how many
         times to make it. Then repeat the sound generation code the
         number of times requested. To generate the sound, switch on the
         type of sound to generate. Each sound is generated by sweeping
         through a set of frequencies in a particular order at a particular
         rate.
 */

 main()

 {
         int snd;        /* Which sound to produce. */
         int cnt;        /* Number of times to repeat sound. */
         int note;       /* Current note, when sweeping frequencies. */
         int adj100;     /* A delay of 100, adjusted for processor speed. */
         int adj200;     /* Delay of 200, adjusted for processor speed. */
         int adj700;     /* Delay of 700, adjusted for processor speed. */

         /* Calculate the delays needed for this processor. */
         adj100 = calib();
         adj200 = 2*adj100;
         adj700 = 7*adj100;

         while (TRUE) {
                 /* Make sure any previous sounds are turned off. */
                 sndOff();
                 /* Ask the user for which type of sound. */
                 printf("1-siren; 2-overload; 3-whoop; 4-phaser; 0-exit: ");
                 /* Read the answer. */
                 scanf("%d",&snd);
                 /* If the answer is to exit, do so. */
                 if (snd == 0) break;
                 /* Ask how many times to repeat the sound. */
                 printf("Number of times: ");
                 /* Get the answer. */
                 scanf("%d",&cnt);
                 /* Repeat the sound the number of time specified. */
                 while (cnt--) {
                         /* Switch on type of sound to produce. */
                         switch (snd) {
                                 case 1:
                                         /* Do a siren: sweep up. */
                                         for (note = 1000; note > 150;
                                              note -= 10) {
                                                 sound(note); delay(adj200);
                                         };
                                         /* Sweep down. */
                                         for (; note < 1000; note += 10) {
                                                 sound(note); delay(adj200);
                                         };
                                         break;
                                 case 2:
                                         /* Do an overload: sweep up. */
                                         for (note = 4000; note > 10;
                                              note -= 10) {
                                                 sound(note); delay(adj700);
                                         };
                                         break;
                                 case 3:
                                         /* Do a whoop: sweep up. */
                                         for (note = 1000; note > 10;
                                              note -= 10) {
                                                 sound(note); delay(adj200);
                                         };
                                         break;
                                 case 4:
                                         /* Do a phaser: sweep down. */
                                         for (note = 60; note < 2000;
                                              note += 10) {
                                                 sound(note); delay(adj100);
                                         };
                                         break;
                                 default:
                                         /* Unknown, ask again. */
                                         printf("Invalid entry; try again.\n")
                                         break;
                         };
                 };
         };
 }

 /*      delay(cnt)

         Function: Delay for an amount of time proportional to cnt.

         Algorithm: Just waste time in a for loop.
 */

 delay(cnt)

 {
         int i;

         /* Loop to burn time... */
         for (i = 0; i < cnt; i++);
 }



 NORMAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\NORMAL.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 /*
  * This file contains the main routine for processing characters in
  * command mode as well as routines for handling the operators.
  */

 #include "stevie.h"

 static        void        doshift(), dodelete(), doput(), dochange();
 static        void        tabinout(), startinsert();
 static        bool_t        dojoin(), doyank();

 /*
  * Macro evaluates true if char 'c' is a valid identifier character
  */
 #define        IDCHAR(c)        (isalpha(c) || isdigit(c) || (c) == '_')

 /*
  * 'can_undo' is a relatively temporary hack so I can debug the 'undo'
  * code for various operations independently. If 'can_undo' is set,
  * then the most recent edit can be undone. Otherwise, attempting to
  * undo an edit will result in an apologetic message. Can_undo is
  * cleared in the macro 'CHANGED', so that every change, by default,
  * cannot be undone. If the undo code for an edit works, 'can_undo'
  * should be set, AFTER the CHANGED macro is invoked.
  */
 bool_t        can_undo = FALSE;

 /*
  * Operators
  */
        NOP        0                /* no pending operation */
 #define        DELETE        1
 #define        YANK        2
 #define        CHANGE        3
 #define        LSHIFT        4
 #define        RSHIFT        5

        CLEAROP        (operator = NOP)        /* clear any pending operator *

 static        int        operator = NOP;                /* current pending op

 /*
  * When a cursor motion command is made, it is marked as being a character
  * or line oriented motion. Then, if an operator is in effect, the operation
  * becomes character or line oriented accordingly.
  *
  * Character motions are marked as being inclusive or not. Most char.
  * motions are inclusive, but some (e.g. 'w') are not.
  *
  * Generally speaking, every command in normal() should either clear any
  * pending operator (with CLEAROP), or set the motion type variable.
  */

 /*
  * Motion types
  */
        MBAD        (-1)                /* 'bad' motion type marks unusable ya
 #define        MCHAR        0
 #define        MLINE        1

 static        int        mtype;                        /* type of the current
 static        bool_t        mincl;                        /* true if char mot

 static        LPTR        startop;                /* cursor pos. at start of

 /*
  * Operators can have counts either before the operator, or between the
  * operator and the following cursor motion as in:
  *
  *        d3w or 3dw
  *
  * If a count is given before the operator, it is saved in opnum. If
  * normal() is called with a pending operator, the count in opnum (if
  * present) overrides any count that came later.
  */
 static        int        opnum = 0;


 #define        DEFAULT1(x)        (((x) == 0) ? 1 : (x))

 /*
  * normal
  *
  * Execute a command in normal mode.
  */

 void
 normal(c)
 int c;
 {
         char *p, *q;
         int n;
         bool_t flag = FALSE;
         int type = 0;                /* used in some operations to modify typ
         int dir = FORWARD;        /* search direction */
         int nchar = NUL;
         bool_t finish_op;

         /*
          * If there is an operator pending, then the command we take
          * this time will terminate it. Finish_op tells us to finish
          * the operation before returning this time (unless the operation
          * was cancelled.
          */
         finish_op = (operator != NOP);

         /*
          * If we're in the middle of an operator AND we had a count before
          * the operator, then that count overrides the current value of
          * Prenum. What this means effectively, is that commands like
          * "3dw" get turned into "d3w" which makes things fall into place
          * pretty neatly.
          */
         if (finish_op) {
                 if (opnum != 0)
                         Prenum = opnum;
         } else
                 opnum = 0;

         switch(c & 0xff){

         case K_HELP:
                 CLEAROP;
                 if (help()) {
                         screenclear();
                         updatescreen();
                 }
                 break;

         case CTRL('L'):
                 CLEAROP;
                 screenclear();
                 updatescreen();
                 break;

         case CTRL('D'):
                 CLEAROP;
                 if (Prenum)
                         P(P_SS) = (Prenum > Rows-1) ? Rows-1 : Prenum;
                 scrollup(P(P_SS));
                 onedown(P(P_SS));
                 updatescreen();
                 break;

         case CTRL('U'):
                 CLEAROP;
                 if (Prenum)
                         P(P_SS) = (Prenum > Rows-1) ? Rows-1 : Prenum;
                 scrolldown(P(P_SS));
                 oneup(P(P_SS));
                 updatescreen();
                 break;

         /*
          * ^F and ^B are neat hacks, but don't take counts. This is very
          * code-efficient, and does the right thing. I'll fix it later
          * to take a count. The old code took a count, but didn't do the
          * right thing in other respects (e.g. leaving some context).
          */
         case CTRL('F'):
 #if 1
                 screenclear();
                 stuffin("Lz\nM");
 #else
                 /*
                  * Old code
                  */
                 CLEAROP;
                 n = DEFAULT1(Prenum);
                 if ( ! onedown(Rows * n) )
                         beep();
                 cursupdate();
 #endif
                 break;

         case CTRL('B'):
 #if 1
                 screenclear();
                 stuffin("Hz-M");
 #else
                 /*
                  * Old code
                  */
                 CLEAROP;
                 n = DEFAULT1(Prenum);
                 if ( ! oneup(Rows * n) )
                         beep();
                 cursupdate();
 #endif
                 break;

         case CTRL('E'):
                 CLEAROP;
                 scrollup(DEFAULT1(Prenum));
                 updatescreen();
                 break;

         case CTRL('Y'):
                 CLEAROP;
                 scrolldown(DEFAULT1(Prenum));
                 updatescreen();
                 break;

         case 'z':
                 CLEAROP;
                 switch (vgetc()) {
                 case NL:                /* put Curschar at top of screen */
                 case CR:
                         *Topchar = *Curschar;
                         Topchar->index = 0;
                         updatescreen();
                         break;

                 case '.':                /* put Curschar in middle of screen
                         n = Rows/2;
                         goto dozcmd;

                 case '-':                /* put Curschar at bottom of screen
                         n = Rows-1;
                         /* fall through */

                 dozcmd:
                         {
                                 register LPTR        *lp = Curschar;
                                 register int        l = 0;

                                 while ((l < n) && (lp != NULL)) {
                                         l += plines(lp);
                                         *Topchar = *lp;
                                         lp = prevline(lp);
                                 }
                         }
                         Topchar->index = 0;
                         updatescreen();
                         break;

                 default:
                         beep();
                 }
                 break;

         case CTRL('G'):
                 CLEAROP;
                 fileinfo();
                 break;

         case 'G':
                 mtype = MLINE;
                 *Curschar = *gotoline(Prenum);
                 break;

         case 'H':
                 mtype = MLINE;
                 *Curschar = *Topchar;
                 for (n = Prenum; n && onedown(1) ;n--)
                         ;
                 beginline(TRUE);
                 break;

         case 'M':
                 mtype = MLINE;
                 *Curschar = *Topchar;
                 for (n = 0; n < Rows/2 && onedown(1) ;n++)
                         ;
                 beginline(TRUE);
                 break;

         case 'L':
                 mtype = MLINE;
                 *Curschar = *prevline(Botchar);
                 for (n = Prenum; n && oneup(1) ;n--)
                         ;
                 beginline(TRUE);
                 break;

         case 'l':
         case K_RARROW:
         case ' ':
                 mtype = MCHAR;
                 mincl = FALSE;
                 n = DEFAULT1(Prenum);
                 while (n--) {
                         if ( ! oneright() )
                                 beep();
                 }
                 set_want_col = TRUE;
                 break;

         case 'h':
         case K_LARROW:
         case CTRL('H'):
                 mtype = MCHAR;
                 mincl = FALSE;
                 n = DEFAULT1(Prenum);
                 while (n--) {
                         if ( ! oneleft() )
                                 beep();
                 }
                 set_want_col = TRUE;
                 break;

         case '-':
                 flag = TRUE;
                 /* fall through */

         case 'k':
         case K_UARROW:
         case CTRL('P'):
                 mtype = MLINE;
                 if ( ! oneup(DEFAULT1(Prenum)) )
                         beep();
                 if (flag)
                         beginline(TRUE);
                 break;

         case '+':
         case CR:
         case NL:
                 flag = TRUE;
                 /* fall through */

         case 'j':
         case K_DARROW:
         case CTRL('N'):
                 mtype = MLINE;
                 if ( ! onedown(DEFAULT1(Prenum)) )
                         beep();
                 if (flag)
                         beginline(TRUE);
                 break;

         /*
          * This is a strange motion command that helps make operators
          * more logical. It is actually implemented, but not documented
          * in the real 'vi'. This motion command actually refers to "the
          * current line". Commands like "dd" and "yy" are really an alternate
          * form of "d_" and "y_". It does accept a count, so "d3_" works to
          * delete 3 lines.
          */
         case '_':
         lineop:
                 mtype = MLINE;
                 onedown(DEFAULT1(Prenum)-1);
                 break;

         case '|':
                 mtype = MCHAR;
                 mincl = TRUE;
                 beginline(FALSE);
                 if (Prenum > 0)
                         *Curschar = *coladvance(Curschar, Prenum-1);
                 Curswant = Prenum - 1;
                 break;

         case CTRL(']'):                        /* :ta to current identifier *
                 CLEAROP;
                 {
                         char        c;
                         LPTR        save;

                         save = *Curschar;
                         /*
                          * First back up to start of identifier. This
                          * doesn't match the real vi but I like it a
                          * little better and it shouldn't bother anyone.
                          */
                         c = gchar(Curschar);
                         while (IDCHAR(c)) {
                                 if (!oneleft())
                                         break;
                                 c = gchar(Curschar);
                         }
                         if (!IDCHAR(c))
                                 oneright();

                         stuffin(":ta ");
                         /*
                          * Now grab the chars in the identifier
                          */
                         c = gchar(Curschar);
                         while (IDCHAR(c)) {
                                 stuffin(mkstr(c));
                                 if (!oneright())
                                         break;
                                 c = gchar(Curschar);
                         }
                         stuffin("\n");

                         *Curschar = save;        /* restore, in case of error
                 }
                 break;

         case '%':
                 mtype = MCHAR;
                 mincl = TRUE;
                 {
                         LPTR        *pos;

                         if ((pos = showmatch()) == NULL)
                                 beep();
                         else {
                                 setpcmark();
                                 *Curschar = *pos;
                                 set_want_col = TRUE;
                         }
                 }
                 break;

         /*
          * Word Motions
          */

         case 'B':
                 type = 1;
                 /* fall through */

         case 'b':
                 mtype = MCHAR;
                 mincl = FALSE;
                 set_want_col = TRUE;
                 for (n = DEFAULT1(Prenum); n > 0 ;n--) {
                         LPTR        *pos;

                         if ((pos = bck_word(Curschar, type)) == NULL) {
                                 beep();
                                 break;
                         } else
                                 *Curschar = *pos;
                 }
                 break;

         case 'W':
                 type = 1;
                 /* fall through */

         case 'w':
                 /*
                  * This is a little strange. To match what the real vi
                  * does, we effectively map 'cw' to 'ce', and 'cW' to 'cE'.
                  * This seems impolite at first, but it's really more
                  * what we mean when we say 'cw'.
                  */
                 if (operator == CHANGE)
                         goto doecmd;

                 mtype = MCHAR;
                 mincl = FALSE;
                 set_want_col = TRUE;
                 for (n = DEFAULT1(Prenum); n > 0 ;n--) {
                         LPTR        *pos;

                         if ((pos = fwd_word(Curschar, type)) == NULL) {
                                 beep();
                                 break;
                         } else
                                 *Curschar = *pos;
                 }
                 break;

         case 'E':
                 type = 1;
                 /* fall through */

         case 'e':
         doecmd:
                 mtype = MCHAR;
                 mincl = TRUE;
                 set_want_col = TRUE;
                 for (n = DEFAULT1(Prenum); n > 0 ;n--) {
                         LPTR        *pos;

                         if ((pos = end_word(Curschar, type)) == NULL) {
                                 beep();
                                 break;
                         } else
                                 *Curschar = *pos;
                 }
                 break;

         case '$':
                 mtype = MCHAR;
                 mincl = TRUE;
                 while ( oneright() )
                         ;
                 Curswant = 999;                /* so we stay at the end */
                 break;

         case '^':
                 flag = TRUE;
                 /* fall through */

         case '0':
                 mtype = MCHAR;
                 mincl = TRUE;
                 beginline(flag);
                 break;

         case 'x':
                 CLEAROP;
                 if (lineempty())        /* can't do it on a blank line */
                         beep();
                 if (Prenum)
                         stuffnum(Prenum);
                 stuffin("d.");
                 break;

 #if 0
                 /* Can't do it if we're on a blank line. */
                 if (lineempty())
                         beep();
                 else {
                         addtobuff(Redobuff,'x',NULL);
                         /* To undo it, we insert the same character back. */
                         resetundo();
                         addtobuff(Undobuff, 'i', gchar(Curschar), ESC, NUL);
                         *Uncurschar = *Curschar;
                         delchar(TRUE);
                         updateline();
                 }
                 break;
 #endif

         case 'X':
                 CLEAROP;
                 if (!oneleft())
                         beep();
                 else {
                         addtobuff(Redobuff, 'X', NUL);
                         resetundo();
                         addtobuff(Undobuff, 'i', gchar(Curschar), ESC, NUL);
                         *Uncurschar = *Curschar;
                         delchar(TRUE);
                         updateline();
                 }
                 break;

         case 'A':
                 set_want_col = TRUE;
                 while (oneright())
                         ;
                 /* fall through */

         case 'a':
                 CLEAROP;
                 /* Works just like an 'i'nsert on the next character. */
                 if (!lineempty())
                         inc(Curschar);
                 resetundo();
                 startinsert(mkstr(c), FALSE);
                 break;

         case 'I':
                 beginline(TRUE);
                 /* fall through */

         case 'i':
         case K_INSERT:
                 CLEAROP;
                 resetundo();
                 startinsert(mkstr(c), FALSE);
                 break;

         case 'o':
                 CLEAROP;
                 opencmd(FORWARD, TRUE);
                 resetundo();
                 addtobuff(Undobuff, 'J', NULL);
                 startinsert("o", TRUE);
                 break;

         case 'O':
                 CLEAROP;
                 opencmd(BACKWARD, TRUE);
                 resetundo();
                 startinsert("O", TRUE);
                 break;

         case 'd':
                 if (operator == DELETE)                /* handle 'dd' */
                         goto lineop;
                 if (Prenum != 0)
                         opnum = Prenum;
                 startop = *Curschar;
                 operator = DELETE;
                 break;

         /*
          * Some convenient abbreviations...
          */

         case 'D':
                 stuffin("d$");
                 break;

         case 'Y':
                 if (Prenum)
                         stuffnum(Prenum);
                 stuffin("yy");
                 break;

         case 'C':
                 stuffin("c$");
                 break;

         case 'c':
                 if (operator == CHANGE) {        /* handle 'cc' */
                         CLEAROP;
                         stuffin("0c$");
                         break;
                 }
                 if (Prenum != 0)
                         opnum = Prenum;
                 startop = *Curschar;
                 operator = CHANGE;
                 break;

         case 'y':
                 if (operator == YANK)                /* handle 'yy' */
                         goto lineop;
                 if (Prenum != 0)
                         opnum = Prenum;
                 startop = *Curschar;
                 operator = YANK;
                 break;

         case 'p':
                 doput(FORWARD);
                 break;

         case 'P':
                 doput(BACKWARD);
                 break;

         case '>':
                 if (operator == RSHIFT)                /* handle >> */
                         goto lineop;
                 if (Prenum != 0)
                         opnum = Prenum;
                 startop = *Curschar;
                 operator = RSHIFT;
                 break;

         case '<':
                 if (operator == LSHIFT)                /* handle << */
                         goto lineop;
                 if (Prenum != 0)
                         opnum = Prenum;
                 startop = *Curschar;        /* save current position */
                 operator = LSHIFT;
                 break;

         case 's':                                /* substitute characters */
                 if (Prenum)
                         stuffnum(Prenum);
                 stuffin("c.");
                 break;

         case '?':
         case '/':
         case ':':
                 CLEAROP;
                 readcmdline(c, NULL);
                 break;

         case 'n':
                 mtype = MCHAR;
                 mincl = FALSE;
                 set_want_col = TRUE;
                 repsearch(0);
                 break;

         case 'N':
                 mtype = MCHAR;
                 mincl = FALSE;
                 set_want_col = TRUE;
                 repsearch(1);
                 break;

         /*
          * Character searches
          */
         case 'T':
                 dir = BACKWARD;
                 /* fall through */

         case 't':
                 type = 1;
                 goto docsearch;

         case 'F':
                 dir = BACKWARD;
                 /* fall through */

         case 'f':
         docsearch:
                 mtype = MCHAR;
                 mincl = TRUE;
                 set_want_col = TRUE;
                 if ((nchar = vgetc()) == ESC)        /* search char */
                         break;
                 if (!searchc(nchar, dir, type))
                         beep();
                 break;

         case ',':
                 flag = 1;
                 /* fall through */

         case ';':
                 mtype = MCHAR;
                 mincl = TRUE;
                 set_want_col = TRUE;
                 if (!crepsearch(flag))
                         beep();
                 break;

         /*
          * Function searches
          */

         case '[':
                 dir = BACKWARD;
                 /* fall through */

         case ']':
                 mtype = MLINE;
                 set_want_col = TRUE;
                 if (vgetc() != c)
                         beep();

                 if (!findfunc(dir))
                         beep();
                 break;

         /*
          * Marks
          */

         case 'm':
                 CLEAROP;
                 if (!setmark(vgetc()))
                         beep();
                 break;

         case '\'':
                 flag = TRUE;
                 /* fall through */

         case '`':
                 {
                         LPTR        mtmp, *mark = getmark(vgetc());

                         if (mark == NULL)
                                 beep();
                         else {
                                 mtmp = *mark;
                                 setpcmark();
                                 *Curschar = mtmp;
                                 if (flag)
                                         beginline(TRUE);
                         }
                         mtype = flag ? MLINE : MCHAR;
                         mincl = TRUE;                /* ignored if not MCHAR
                         set_want_col = TRUE;
                 }
                 break;

         case 'r':
                 CLEAROP;
                 if (lineempty()) {        /* Nothing to replace */
                         beep();
                         break;
                 }
                 if ((nchar = vgetc()) == ESC)
                         break;
                 resetundo();

                 addtobuff(Undobuff, 'r', gchar(Curschar), NULL);
                 *Uncurschar = *Curschar;

                 /* Change current character. */
                 pchar(Curschar, nchar);

                 /* Save stuff necessary to redo it */
                 addtobuff(Redobuff, 'r', nchar, NULL);

                 CHANGED;
                 can_undo = TRUE;
                 updateline();
                 break;

         case '~':                /* swap case */
                 CLEAROP;
                 if (lineempty()) {
                         beep();
                         break;
                 }
                 c = gchar(Curschar);

                 if (isalpha(c)) {
                         stuffin("r");                /* replace with other ca
                         if (islower(c))
                                 stuffin(mkstr(toupper(c)));
                         else
                                 stuffin(mkstr(tolower(c)));
                 }
                 stuffin("l");                        /* move right when done

                 break;

         case 'J':
                 CLEAROP;

                 if (!dojoin())
                         beep();

                 resetundo();
                 *Uncurschar = *Curschar;
                 addtobuff(Undobuff, 'i', NL, ESC, NULL);
                 addtobuff(Redobuff,'J',NULL);
                 updatescreen();
                 break;

         case K_CGRAVE:                        /* shorthand command */
                 CLEAROP;
                 stuffin(":e #\n");
                 break;

         case 'Z':                        /* write, if changed, and exit */
                 if (vgetc() != 'Z') {
                         beep();
                         break;
                 }

                 if (Changed) {
                         if (Filename != NULL) {
                                 if (!writeit(Filename, NULL, NULL))
                                         return;
                         } else {
                                 emsg("No output file");
                                 return;
                         }
                 }
                 getout();
                 break;

         case '.':
                 /*
                  * If a delete is in effect, we let '.' help out the same
                  * way that '_' helps for some line operations. It's like
                  * an 'l', but subtracts one from the count and is inclusive.
                  */
                 if (operator == DELETE || operator == CHANGE) {
                         if (Prenum != 0) {
                                 n = DEFAULT1(Prenum) - 1;
                                 while (n--)
                                         if (! oneright())
                                                 break;
                         }
                         mtype = MCHAR;
                         mincl = TRUE;
                 } else {                        /* a normal 'redo' */
                         CLEAROP;
                         stuffin(Redobuff);
                 }
                 break;

         case 'u':
         case K_UNDO:
                 CLEAROP;
                 if (!can_undo) {
                         msg("Sorry, can't undo last edit");
                         break;
                 }

                 if ( *Undobuff != NUL ) {
                         *Curschar = *Uncurschar;
                         stuffin(Undobuff);
                         *Undobuff = NUL;
                 }
                 if ( Undelchars > 0 ) {
                         *Curschar = *Uncurschar;
                         /* construct the next Undobuff and Redobuff, which */
                         /* will re-insert the characters we're deleting. */
                         p = Undobuff;
                         q = Redobuff;
                         *p++ = *q++ = 'i';
                         /*
                          * Fix this loop to effectively turn nulls into
                          * NL's in the Undo and Redo buffs and do the
                          * joins needed.
                          */
                         while ( Undelchars-- > 0 ) {
                                 char        c = gchar(Curschar);

                                 if (c == NUL) {
                                         *p++ = *q++ = NL;
                                         dojoin();
                                 } else {
                                         *p++ = *q++ = c;
                                         delchar(FALSE);
                                 }
                         }
                         /* Finish constructing Uncursbuff, and Uncurschar */
                         /* is left unchanged. */
                         *p++ = *q++ = ESC;
                         *p = *q = NUL;
                         /* Undelchars has been reset to 0 */
                         updatescreen();
                 }
                 can_undo = FALSE;
                 break;

         default:
                 CLEAROP;
                 beep();
                 break;
         }

         /*
          * If an operation is pending, handle it...
          */
         if (finish_op) {                /* we just finished an operator */
                 if (operator == NOP)        /* ... but it was cancelled */
                         return;

                 switch (operator) {

                 case LSHIFT:
                 case RSHIFT:
                         doshift(operator, c, nchar, Prenum);
                         break;

                 case DELETE:
                         dodelete(c, nchar, Prenum);
                         break;

                 case YANK:
                         doyank();        /* no redo on yank... */
                         break;

                 case CHANGE:
                         dochange(c, nchar, Prenum);
                         break;

                 default:
                         beep();
                 }
                 operator = NOP;
         }
 }

 /*
  * doshift - handle a shift operation
  */
 static void
 doshift(op, c1, c2, num)
 int        op;
 char        c1, c2;
 int        num;
 {
         LPTR        top, bot;
         int        nlines;
         char        opchar;

         top = startop;
         bot = *Curschar;

         if (lt(&bot, &top))
                 pswap(&top, &bot);

         nlines = cntllines(&top, &bot);
         *Curschar = top;
         tabinout((op == LSHIFT), nlines);

         /* construct Redo buff */
         opchar = (op == LSHIFT) ? '<' : '>';
         if (num != 0)
                 sprintf(Redobuff, "%c%d%c%c", opchar, num, c1, c2);
         else
                 sprintf(Redobuff, "%c%c%c", opchar, c1, c2);

         /*
          * The cursor position afterward is the prior of the two positions.
          */
         *Curschar = top;

         /*
          * If we were on the last char of a line that got shifted left,
          * then move left one so we aren't beyond the end of the line
          */
         if (gchar(Curschar) == NUL && Curschar->index > 0)
                 Curschar->index--;

         updatescreen();

         if (nlines > P(P_RP))
                 smsg("%d lines %ced", nlines, opchar);
 }

 /*
  * dodelete - handle a delete operation
  */
 static void
 dodelete(c1, c2, num)
 char        c1, c2;
 int        num;
 {
         LPTR        top, bot;
         int        nlines;
         int        n;

         /*
          * Do a yank of whatever we're about to delete. If there's too much
          * stuff to fit in the yank buffer, then get a confirmation before
          * doing the delete. This is crude, but simple. And it avoids doing
          * a delete of something we can't put back if we want.
          */
         if (!doyank()) {
                 msg("yank buffer exceeded: press <y> to confirm");
                 if (vgetc() != 'y') {
                         msg("delete aborted");
                         *Curschar = startop;
                         return;
                 }
         }

         top = startop;
         bot = *Curschar;

         if (lt(&bot, &top))
                 pswap(&top, &bot);

         nlines = cntllines(&top, &bot);
         *Curschar = top;
         cursupdate();

         if (mtype == MLINE) {
                 delline(nlines);
         } else {
                 if (!mincl && bot.index != 0)
                         dec(&bot);

                 if (top.linep == bot.linep) {                /* del. within l
                         n = bot.index - top.index + 1;
                         while (n--)
                                 if (!delchar(TRUE))
                                         break;
                 } else {                                /* del. between lines
                         n = Curschar->index;
                         while (Curschar->index >= n)
                                 if (!delchar(TRUE))
                                         break;

                         top = *Curschar;
                         *Curschar = *nextline(Curschar);
                         delline(nlines-2);
                         Curschar->index = 0;
                         n = bot.index + 1;
                         while (n--)
                                 if (!delchar(TRUE))
                                         break;
                         *Curschar = top;
                         dojoin();
                 }
         }

         /* construct Redo buff */
         if (num != 0)
                 sprintf(Redobuff, "d%d%c%c", num, c1, c2);
         else
                 sprintf(Redobuff, "d%c%c", c1, c2);

         if (mtype == MCHAR && nlines == 1)
                 updateline();
         else
                 updatescreen();

         if (nlines > P(P_RP))
                 smsg("%d fewer lines", nlines);
 }

 /*
  * dochange - handle a change operation
  */
 static void
 dochange(c1, c2, num)
 char        c1, c2;
 int        num;
 {
         char        sbuf[16];
         bool_t        doappend;        /* true if we should do append, not in

         doappend = endofline( (lt(Curschar, &startop)) ? &startop: Curschar);

         if (mtype == MLINE) {
                 msg("multi-line changes not yet supported");
                 return;
         }

         dodelete(c1, c2, num);

         if (num)
                 sprintf(sbuf, "c%d%c%c", num, c1, c2);
         else
                 sprintf(sbuf, "c%c%c", c1, c2);

         if (doappend && !lineempty())
                 inc(Curschar);

         startinsert(sbuf);
 }

 #define        YBSIZE        1024

 static        char        ybuf[YBSIZE];
 static        int        ybtype = MBAD;

 static bool_t
 doyank()
 {
         LPTR        top, bot;
         char        *yptr = ybuf;
         char        *ybend = &ybuf[YBSIZE-1];
         int        nlines;

         top = startop;
         bot = *Curschar;

         if (lt(&bot, &top))
                 pswap(&top, &bot);

         nlines = cntllines(&top, &bot);

         ybtype = mtype;                        /* set the yank buffer type */

         if (mtype == MLINE) {
                 top.index = 0;
                 bot.index = strlen(bot.linep->s);
                 /*
                  * The following statement checks for the special case of
                  * yanking a blank line at the beginning of the file. If
                  * not handled right, we yank an extra char (a newline).
                  */
                 if (dec(&bot) == -1) {
                         ybuf[0] = NUL;
                         if (operator == YANK)
                                 *Curschar = startop;
                         return TRUE;
                 }
         } else {
                 if (!mincl) {
                         if (bot.index)
                                 bot.index--;
                 }
         }

         for (; ltoreq(&top, &bot) ;inc(&top)) {
                 *yptr = (gchar(&top) != NUL) ? gchar(&top) : NL;
                 if (++yptr >= ybend) {
                         msg("yank too big for buffer");
                         ybtype = MBAD;
                         return FALSE;
                 }
         }

         *yptr = NUL;

         if (operator == YANK) {        /* restore Curschar if really doing ya
                 *Curschar = startop;

                 if (nlines > P(P_RP))
                         smsg("%d lines yanked", nlines);
         }

         return TRUE;
 }

 static void
 doput(dir)
 int        dir;
 {
         if (ybtype == MBAD) {
                 beep();
                 return;
         }

         if (dir == FORWARD)
                 stuffin( (ybtype == MCHAR) ? "a" : "o" );
         else
                 stuffin( (ybtype == MCHAR) ? "i" : "O" );

         stuffin(ybuf);
         stuffin(mkstr(ESC));
 }

 /*
  * tabinout(inout,num)
  *
  * If inout==0, add a tab to the begining of the next num lines.
  * If inout==1, delete a tab from the beginning of the next num lines.
  */
 static void
 tabinout(inout, num)
 int        inout;
 int        num;
 {
         int        ntodo = num;
         LPTR        *p;

         /* construct undo stuff */
         resetundo();
         *Uncurschar = *Curschar;
         sprintf(Undobuff, "%d%s", num, (inout == 0) ? "<<" : ">>");

         beginline(FALSE);
         while ( ntodo-- > 0 ) {
                 beginline(FALSE);
                 if ( inout == 0 )
                         inschar(TAB);
                 else {
                         if ( gchar(Curschar) == TAB )
                                 delchar(TRUE);
                 }
                 if ( ntodo > 0 ) {
                         if ( (p=nextline(Curschar)) != NULL )
                                 *Curschar = *p;
                         else
                                 break;
                 }
         }
         can_undo = TRUE;
 }

 static void
 startinsert(initstr, startln)
 char *initstr;
 int        startln;        /* if set, insert point really at start of line */
 {
         char *p, c;

         *Insstart = *Curschar;
         if (startln)
                 Insstart->index = 0;
         Ninsert = 0;
         Insptr = Insbuff;
         for (p=initstr; (c=(*p++))!='\0'; )
                 *Insptr++ = c;
         State = INSERT;
         if (P(P_MO))
                 msg("Insert Mode");
 }

 void
 resetundo()
 {
         Undelchars = 0;
         *Undobuff = '\0';
         Uncurschar->linep = NULL;
 }

 static bool_t
 dojoin()
 {
         int        scol;                /* save cursor column */
         int        size;                /* size of the joined line */

         if (nextline(Curschar) == NULL)                /* on last line */
                 return FALSE;

         if (!canincrease(size = strlen(Curschar->linep->next->s)))
                 return FALSE;

         while (oneright())                        /* to end of line */
                 ;

         strcat(Curschar->linep->s, Curschar->linep->next->s);

         /*
          * Delete the following line. To do this we move the cursor
          * there briefly, and then move it back. Don't back up if the
          * delete made us the last line.
          */
         Curschar->linep = Curschar->linep->next;
         scol = Curschar->index;

         if (nextline(Curschar) != NULL) {
                 delline(1);
                 Curschar->linep = Curschar->linep->prev;
         } else
                 delline(1);

         Curschar->index = scol;

         oneright();                /* go to first char. of joined line */

         if (size != 0) {
                 /*
                  * Delete leading white space on the joined line
                  * and insert a single space.
                  */
                 while (gchar(Curschar) == ' ' || gchar(Curschar) == TAB)
                         delchar(TRUE);
                 inschar(' ');
         }

         return TRUE;
 }

 char *
 mkstr(c)
 char        c;
 {
         static        char        s[2];

         s[0] = c;
         s[1] = NUL;

         return s;
 }


 NPROB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\NPROB.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "mathcons.h"

 /************************************************************************/
         double
 nprob(x)                /* Normal probability function, unit variance,
                            zero mean, Pr{z <= x}                        */
 /*----------------------------------------------------------------------*/
 {
         double ldexp(), erfc();

         return ldexp(erfc(-x / ROOTTWO), -1);
 }

 /************************************************************************/
         double
 nprobc(x)                /* Normal probability complement function, unit
                            variance, zero mean, Pr{z >= x}                */
 /*----------------------------------------------------------------------*/
 {
         double erfc();

         return ldexp(erfc(x / ROOTTWO) , -1);
 }


 NTIME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\NTIME.C

 main(argc,argv)

 int argc;
 char *argv[];

 {
  int i, j;

  i = atoi(argv[1]);
  j = atoi(argv[2]);
  printf("Starting...");
  while (i--) delay(j);
  printf("done.\n");
 }

 delay(cnt)

 {
  int i;

  for (i = 0; i < cnt; i++);
 }



 NUMBIT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\NUMBIT.C

 #include <stdio.h>
 #define  MSOFT

 /*
  *  numbit.c
  *  For those times when you need to know the values of a number in another
  *  base.  As we all need Decimal, Octal, Hex and Binary forms from time to
  *  time.
  *  This will accept an entry in the following formats:
  *     Decimal   255
  *     Octal    0377
  *     Hex      0xff
  *
  *  The output will be given in all formats.  Numbers larger than 0xffff
  *  will be handled as 32 bit long integers.  Negative numbers will cause
  *  the upper bit to be set and thus will be erroneous.
  */

 #ifndef MSOFT
 long    stoi();                                  /* declare conversion */
 #else
 <stdlib.h>                              /* get library declaration */
 #endif

 main()
 {
 char    *endptr, buf[80];
 union  {
       long value;
       struct  {
         unsigned int lw_bit0:1;
         unsigned int lw_bit1:1;
         unsigned int lw_bit2:1;
         unsigned int lw_bit3:1;
         unsigned int lw_bit4:1;
         unsigned int lw_bit5:1;
         unsigned int lw_bit6:1;
         unsigned int lw_bit7:1;
         unsigned int lw_bit8:1;
         unsigned int lw_bit9:1;
         unsigned int lw_bit10:1;
         unsigned int lw_bit11:1;
         unsigned int lw_bit12:1;
         unsigned int lw_bit13:1;
         unsigned int lw_bit14:1;
         unsigned int lw_bit15:1;

         unsigned int hw_bit0:1;
         unsigned int hw_bit1:1;
         unsigned int hw_bit2:1;
         unsigned int hw_bit3:1;
         unsigned int hw_bit4:1;
         unsigned int hw_bit5:1;
         unsigned int hw_bit6:1;
         unsigned int hw_bit7:1;
         unsigned int hw_bit8:1;
         unsigned int hw_bit9:1;
         unsigned int hw_bit10:1;
         unsigned int hw_bit11:1;
         unsigned int hw_bit12:1;
         unsigned int hw_bit13:1;
         unsigned int hw_bit14:1;
         unsigned int hw_bit15:1;
       } bits;
     } num;

    do {
       printf("enter number to try   ");

       gets(buf);

 #ifndef MSOFT
       num.value = stoi(buf);
 #else
       num.value = strtol(buf, &endptr, 0);
 #endif

       printf("Decimal = %lu  Hex = %lx  Octal = %lo\n",
                num.value,
                num.value,
                num.value   );

       if( num.value > 0xffff )
       {
          printf("%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d ",
                 num.bits.hw_bit15,
                 num.bits.hw_bit14,
                 num.bits.hw_bit13,
                 num.bits.hw_bit12,
                 num.bits.hw_bit11,
                 num.bits.hw_bit10,
                 num.bits.hw_bit9,
                 num.bits.hw_bit8,
                 num.bits.hw_bit7,
                 num.bits.hw_bit6,
                 num.bits.hw_bit5,
                 num.bits.hw_bit4,
                 num.bits.hw_bit3,
                 num.bits.hw_bit2,
                 num.bits.hw_bit1,
                 num.bits.hw_bit0);
       }

       printf("%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d\n",
              num.bits.lw_bit15,
              num.bits.lw_bit14,
              num.bits.lw_bit13,
              num.bits.lw_bit12,
              num.bits.lw_bit11,
              num.bits.lw_bit10,
              num.bits.lw_bit9,
              num.bits.lw_bit8,
              num.bits.lw_bit7,
              num.bits.lw_bit6,
              num.bits.lw_bit5,
              num.bits.lw_bit4,
              num.bits.lw_bit3,
              num.bits.lw_bit2,
              num.bits.lw_bit1,
              num.bits.lw_bit0);
    } while (num.value != 0);

 }
 /*=============================================================*/
 MSOFT                                    /* cant use the library */
                                                  /* function strtol      */
 #define  islower(c)     ( 'a' <= (c) && (c) <= 'z' )
 #define  toupper(c)     ( islower(c) ? (c) - ('a' - 'A') : (c) )

 /* stoi.c       more powerful version of atoi.
  *
  *      copyright 1985 by Allen Holub.
  *      modified 5/86 by Jerry Pendergraft
  *          to return a long value, and work on a char pointer rather
  *          than a pointer to char pointer.
  */

 long    stoi(str)
 char    *str;
 {
 long    num = 0;
 int     sign = 1;

         while(*str == ' ' || *str == '\t' || *str == '\n' )
                 str++;

         if( *str == '-' )
            {
            sign = -1;
            str++;
            }

         if( *str == '0' )                        /* Octal or Hex form
            {
                 ++str;
                 if( *str == 'x' || *str == 'X' ) /* Hex form
                    {
                         str++;
                         while( ('0' <= *str && *str <= '9') ||
                                ('a' <= *str && *str <= 'f') ||
                                ('A' <= *str && *str <= 'F')  )
                            {
                            num *= 16;
                            num += ( '0' <= *str && *str <= '9' ) ?
                                     *str - '0'                   :
                                     toupper( *str ) - 'A' + 10   ;
                            str++;
                            }
                    }
                 else
                    {
                         while( '0' <= *str && *str <= '7' )
                            {
                            num *= 8;
                            num += *str++ - '0';
                            }
                    }
            }
         else                                     /* Decimal entry */
            {
                 while( '0' <= *str && *str <= '9' )
                    {
                    num *= 10;
                    num += *str++ - '0';
                    }
            }

 return( num * sign );
 }
 #endif


 NWDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\NWDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==NORTH_WEST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 OCT_DUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\OCT_DUMP.C

 /*
  * od.c 1-16-85 kpc
  * this is a replica of the UNIX od (octal dump) command
  * with some extensions.
  *
  * the spec for this command comes from the 7th edition Berkely UNIX manual
  *
  * NOTE: this program should also dump directories. (But! Alas, it does not.)
  *
  * usage:
  *     od [-bcduoxDUOXw] [-B{odxc}] [-A{odx}] [file] [[+]offset[.][b]]
  *
  *     'file' - is the file to be dumped, if missing stdin is read.
  *     'offset' - specifies the offset into the file where dumping is to begi
  *               this is normally in octal bytes, unless a period '.' is
  *               appended to the offset then it is interpreted as decimal byt
  *               if a 'b' is appended to the offset then it is interpreted as
  *               being the number of 512 byte blocks to skip.
  *               If the file argument is omitted, the offset must be preceede
  *               by a '+'.  All offsets start with zero, the first byte of a
  *               file is at offset zero, the first block of a file is at offs
  *               zero.
  *
  *     dumping continues until end-of-file.
  *
  *     a - ???
  *     w - produce wide (132 column) output  this prints 24 bytes per line
  *           versus 16 bytes per line.
  *
  *     b - interpret bytes in octal
  *     c - interpret bytes in ASCII. certain characters appear as C escapes;
  *           null = \0, bs = \b, ff = \f, nl = \n, cr = \r, tab = \t others a
  *           displayed as 3-digit octal number.
  *
  *     d - interpret shorts in decimal (16 bits)
  *     o - interpret shorts in octal   (16 bits)
  *     x - interpret shorts in hex     (16 bits)
  *
  *     D - interpret longs in decimal  (32 bits)
  *     O - interpret longs in octal    (32 bits)
  *     X - interpret longs in hex      (32 bits)
  *
  *     A{odx} - specifies the style that the offset should displayed in.
  *           o - octal bytes, x- hex bytes, d - decimal bytes.
  *
  *     B{odxc} - specifies the style that bytes should be displayed in.
  *           o - octal bytes, x- hex bytes, d - decimal bytes.
  *               this is an alternative to the -b and -c opts above
  *
  *[1] EDIT 1          1-21-85 kpc
  *[1]          od now prints the offset 'loffset' after hitting EOF, this
  *[1]          enables the user to determine the exact end of file.
  */

 /*  #define DEBUG */

 #include <stdio.h>
 #include <ctype.h>

 static char _sccsid[] ={ "@(#)od.c  v1.1  1-21-85  kpc"};

 #define    OCT           (0x01)
 #define    DEC           (0x02)
 #define    USGN    (0x04)
 #define    HEX           (0x08)
 #define    ASC           (0x10)

 #define    BLANK   (0x80)


    NARROW  (16)     /* number of bytes to print */
    WIDE    (24)     /* number of bytes to print */

 #define    FALSE   (0)
 #define    TRUE    (1)

 #define    BLOCK_SIZ   (512)
 #define    MAX_BUF     (48)

 #define    SWITCHAR    '-'


 /* mode for fopen() */
 char   opn_mode[] ={ "rb"};

 int    Off_prflg; /* whether or not the offset has been printed out yet */


 main( argc, argv)
 int    argc;
 char   **argv;
 {
    int           ap,           /* int pointer into argv */
            fn_p,   /* where the file name is in argv */
            off_p;  /* where the offset spec is in argv */

    int           width;  /* width of output */

    int           off_opt,    /* print fmt for the offset */
            byt_opt,    /* print fmt for the byt specs */
            sht_opt,    /* print fmt for the short specs */
            lng_opt;    /* print fmt for the long specs */

    int           num_byt;    /* number of bytes in the buffer */
    char    buf[ MAX_BUF + 1];  /* guess */
    char    l_buf[MAX_BUF + 1]; /* the last buf that was read in */
                                /* used to implement output compaction */
    int           quiet_flg;  /* this flag keeps track of the number of duplic
                        /* output lines so we can shut up during blocks of  */
                        /* duplicate records  */

    FILE    *fp;


    long    loffset,        /* cur offset into file */
            ioffset;        /* the initial offset */

    int           eof;
    int           c;               /* input character */
    int           msk;        /* msk to index the option flags */

    extern FILE *fopen();

    /* set defaults */
    off_opt = OCT;
    sht_opt = 0;

    byt_opt = 0;
    lng_opt = 0;

    fp = stdin;
    loffset = 0L;
    ioffset = 0L;

    width = NARROW;


    /* scan argv */
    /* set our flag/pointers */
    fn_p = -1;
    off_p = -1;

    /* now we're ready; if there were no opts, the loop falls through */
    /* and the defaults hold */
    for( ap = 1; ap < argc; ap++)
        if( argv[ap][0] == SWITCHAR )
        {
            /* then process as an option */
            /* we need a few local variables to rip the strings apart */
            char    *cp;

            /* here is a special case of only a '-' being entered */
            if( argv[ap][1] == '\0')
                /* this deserves the usage message */
                pr_usage();

            for( cp = &argv[ap][1]; *cp; cp++)
                switch( *cp)
                {
                    /* bytes as octal */
                    case 'b':
                        byt_opt |= OCT;
                        break;

                    /* bytes as... 'B' uses the next char as an argument */
                    case 'B':
                        switch( *(++cp))
                        {
                            case 'o':
                                byt_opt |= OCT;
                                break;

                            case 'd':
                                byt_opt |= DEC;
                                break;

                            case 'x':
                                byt_opt |= HEX;
                                break;

                            case 'c':
                                byt_opt |= ASC;
                                break;

                            default:
                                fprintf(stderr,
                                    "od: bad option 'B' argument: (%c)\n",*cp)
                                pr_usage();
                        }
                        break;

                    /* bytes as asc */
                    case 'c':
                        byt_opt |= ASC;
                        break;


                    /* shorts as decimal */
                    case 'd':
                        sht_opt |= USGN;
                        break;

                    /* shorts as unsigned decimal */
                    case 'u':
                        sht_opt |= USGN;
                        break;

                    /* shorts as octal */
                    case 'o':
                        sht_opt |= OCT;
                        break;

                    /* shorts as hex */
                    case 'x':
                        sht_opt |= HEX;
                        break;


                    /* longs as decimal */
                    case 'D':
                        lng_opt |= USGN;
                        break;

                    /* longs as unsigned decimal */
                    case 'U':
                        lng_opt |= USGN;
                        break;

                    /* longs as octal */
                    case 'O':
                        lng_opt |= OCT;
                        break;

                    /* longs as hex */
                    case 'X':
                        lng_opt |= HEX;
                        break;


                    /* wide output */
                    case 'w':
                        width = WIDE;
                        break;

                    /* offset displayed as... */
                    case 'A':
                        /* look for an argument */
                        switch( tolower( *(++cp) ) )
                        {
                            case 'o':
                                off_opt = OCT;
                                break;

                            case 'd':
                                off_opt = DEC;
                                break;

                            case 'x':
                                off_opt = HEX;
                                break;

                            default:
                                fprintf(stderr,
                                    "od: bad option 'A' argument: (%c)\n",*cp)
                                pr_usage();
                        }
                        break;

                    /* unknown option */
                    default:
                        /* this never returns */
                        pr_usage();
                }

        }
        else if( argv[ap][0] == '+' )
        {
            /* special offset indication */
            off_p = ap;
        }
        else
            if( fn_p == -1)
            {
                /* assume it is the file spec */
                fn_p = ap;
            }
            else if( off_p == -1)
            {
                /* we can assume it is the starting offset spec */
                off_p = ap;
            }
            else
                pr_usage();

    /*=================================*/

    /* the default (short OCT) if nothing else is specified */
    if( byt_opt == 0 && sht_opt == 0 && lng_opt == 0 )
        sht_opt = OCT;

    /* now we can deal with the file name and the offset */
    /* file specified? */
    if( fn_p != -1)
        if( (fp = fopen( argv[fn_p], opn_mode)) == NULL)
        {
            fprintf(stderr, "od: couldnt open input file (%s)\n", argv[fn_p]);
            exit( 2);
        }

    /* offset specified? */
    if( off_p != -1)
    {
        /* now this could be a little trickier */
        /* need some local variables */
        char    *cp,           /* rip through the string */
                *opt;           /* used to look for options */
        int     mult = 1,   /* multiplier for block offsets */
                base = 8;   /* radix of offset */

        cp = argv[off_p];

        /* skip possible indicator */
        if( *cp == '+')
            cp++;

        /* set opt to the end of string */
        opt = cp;
        while( *opt )
            opt++;

        opt--;

        if( !isdigit( *opt & 0x7f) )
        {
            /* could be a 'b' or a '.' */
            if( tolower( *opt ) == 'b')
            {
                mult = BLOCK_SIZ;
                opt--;
            }

            if( *opt == '.')
                base = 10;
            else if( !isdigit( *opt & 0x7f))
            {
                fprintf(stderr,"od: invalid offset spec: (%s)\n", cp);
                exit( 3);
            }
            else
                opt++;           /* dont obliterate a good digit */

            /* terminate the string */
            *opt = '\0';
        }

        /* convert to integer */
        while( isdigit( *cp))
            ioffset = ioffset * base + (*cp++ - '0');

        /* if its a block offset, then... */
        ioffset *= mult;
    }


    /*
     * all options have been dealt with and all flags set accordingly
     * we are ready to to the dump
     *  But first! we must seek to the right spot in the file
     */
    loffset = ioffset;

    if( ioffset != 0L )
    {
        int     fd;
        unsigned    cnt;
        char    eat_buf[ BLOCK_SIZ];

        fd = fileno( fp);

 #ifdef DEBUG
        printf("ioffset is: %ld. 0%lo\n", ioffset, ioffset );

        if( isatty( fd) == 1)
            printf("is tty\n");
 #endif

        while( ioffset > 0L)
        {
            cnt = (ioffset >= BLOCK_SIZ) ? (BLOCK_SIZ) : (ioffset);

            if( read( fd, eat_buf, cnt ) != cnt )
            {
                fprintf(stderr,"od: unable to read %d bytes\n", cnt);
                exit( 4);
            }

            ioffset -= cnt;
        }
    }


    /* ok, now we can dump the file */
    eof = FALSE;

 #ifdef DEBUG
    printf("oopt: 0x%02x  bopt: 0x%02x sopt: 0x%02x lopt: 0x%04x\n",
        off_opt, byt_opt, sht_opt, lng_opt);
 #endif

    /* clear out the last buffer */
    bclear( l_buf, MAX_BUF + 1);
    quiet_flg = -1;

    while( !eof )
    {
        bclear( buf, MAX_BUF + 1);

        /* get upto MAX_BUF bytes */
        for( num_byt=0; num_byt < width && (c = fgetc( fp)) != EOF; num_byt++)
            buf[num_byt] = c;

        /* if EOF then remember it */
        if( c == EOF)
            eof = TRUE;

        /*
         * the following ugly nested if stmnt implements the quiet
         * mode of operation.  ie only printing 2 duplicate lines,
         * and then a '*' line until a record that is different is read.
         */
        if( bcmp( l_buf, buf, MAX_BUF + 1))
        {
            if( quiet_flg == 2)
                /* we have already printed the '*' */
                continue;
            else if( quiet_flg == 1)
            {
                /* then we don't need to dump this buf */
                /* but we do need to say something */
                printf("*\n");
                quiet_flg = 2;
                continue;
            }
            else if( quiet_flg == 0)
                /* this and the prev rec are equal, dump it */
                quiet_flg = 1;
            else
                quiet_flg = 0;
        }
        else
        {
            /* they weren't equal */
            quiet_flg = 0;
            bcpy( l_buf, buf, MAX_BUF + 1);
        }


 #ifdef DEBUG
        printf("num_byt: %d\n", num_byt);
 #endif

        /* print the offset out */
        Off_prflg = FALSE;

        for( msk = OCT; msk <= ASC; msk<<=1)
        {
 #ifdef DEBUG
            printf("msk: 0x%02x\n", msk);
 #endif
            if( byt_opt & msk)
            {
                pr_off( off_opt, loffset);
                pr_byte( byt_opt & msk, num_byt, buf);
            }

            if( sht_opt & msk)
            {
                pr_off( off_opt, loffset);
                pr_short( sht_opt & msk, num_byt, buf);
            }

            if( lng_opt & msk)
            {
                pr_off( off_opt, loffset);
                pr_long( lng_opt & msk, num_byt, buf);
            }

        } /* end of for */

        loffset += num_byt;

    } /* end of while */

    /*[1]  1-21-85 kpc should print the offset once more so the person
     *[1] knows where the file ended.
     */
    Off_prflg = FALSE;                   /*[1]*/
    pr_off( off_opt, loffset);           /*[1]*/
    printf("\n");                   /*[1]*/

 } /*  end of main */




 pr_usage()
 {
    fprintf(stderr,
     "usage: od [-bcdoxDOX B{odxc} w A{odx}] [file] [[+]offset[.][b]]\n"
    );
    exit( 1);
 }

 bclear( p, n)
 char   *p;
 int    n;
 {
    while( n-- )
        *p++ = '\0';
 }

 bcmp( d, s, n)
 char   *d,
        *s;
 int    n;
 {
    while( n-- )
        if( *d++ != *s++ )
            return( FALSE);

    return( TRUE);
 }

 bcpy( d, s, n)
 char   *d,
        *s;
 int    n;
 {
    while( n--)
        *d++ = *s++;
 }


 /*
  * pr_byte()
  */
 pr_byte( opt, w, p)
 int    opt,
        w;      /* width */
 char   *p;
 {
    char    *fmt;

    switch( opt )
    {
        case OCT:
            fmt = "%1s%03o";
            break;

        case DEC:
            fmt = "%1s%3d";
            break;

        case HEX:
            fmt = "%2s%2x";
            break;

        case ASC:
            /* here we use our own loop... */
            for( ; w>0; w--,p++)
                if( *p >= ' ' && *p <= '~' )    /*GROT ascii only!!! */
                    printf("%4c", *p);
                else if( *p == '\0') /* null */
                    printf("  \\0");
                else if( *p == '\n') /* newline */
                    printf("  \\n");
                else if( *p == '\f') /* formfeed */
                    printf("  \\f");
                else if( *p == '\b') /* backspace */
                    printf("  \\b");
                else if( *p == '\r') /* carriage return */
                    printf("  \\r");
                else if( *p == '\t') /* tab */
                    printf("  \\t");
                else
                    printf(" %03o", *p & 0x00ff);

            printf("\n");
            return;

        default:
            return;
    }


    for( ; w>0; w--)
        printf( fmt, " ", *p++ & 0x00ff);

    printf("\n");
 }


 pr_short( opt, w, p)
 int    opt,
        w;      /* width */
 short  *p;
 {
    char    *fmt;

    switch( opt )
    {
        case OCT:
            fmt = "%2s%06o";
            break;

        case DEC:
            fmt = "%3s%05d";
            break;

        case USGN:
            fmt = "%3s%05u";
            break;

        case HEX:
            fmt = "%4s%04x";
            break;

        default:
            return;
    }


    for( w /= 2 ; w>0; w--)
        printf( fmt, " ", *p++);

    printf("\n");
 }


 /*
  * pr_long()
  * print out longs   either 4 or 6 longs depending on the width.
  */
 pr_long( opt, w, p)
 int    opt,
        w;         /* width */
 long   *p;
 {
    char    *fmt;

    switch( opt )
    {
        case OCT:
            fmt = "%4s%012lo";
            break;

        case DEC:
            fmt = "%6s%010ld";
            break;

        case USGN:
            fmt = "%6s%010lu";
            break;

        case HEX:
            fmt = "%8s%08lx";
            break;

        default:
            return;
    }


    for( w /= 4; w>0; w--)
        printf( fmt, " ", *p++);

    printf("\n");
 }


 /*
  * pr_off()
  * print the current offset or enough blanks to cover the space
  */
 pr_off( opt, lpos )
 int    opt;    /* formating option, OCT DEC HEX */
 long   lpos;   /* the current offset */
 {
    char    *fmt;

    if( Off_prflg)
        printf("%9s", " ");
    else
    {
        switch( opt)
        {
            case OCT:
                fmt = "%08lo ";
                break;

            case DEC:
                fmt = "%8ld.";
                break;

            case HEX:
                fmt = "%08lx ";
                break;
        }

        Off_prflg = TRUE;
        printf( fmt, lpos);
    }
 }


 OD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\OD.C

 #include <stdio.h>
 #include <ctype.h>

 /***
  *        od.c [09/30/84] - binary dump program, like UNIX utility.
  *
  *        Usage:
  *                od [-bcdoxm] [file] [+][offset][.][b]
  *                        -b     - output octal bytes
  *                        -c     - output character bytes
  *                        -d     - output decimal words
  *                        -o     - output octal words (default)
  *                        -x     - output hex words
  *                        -m     - pause for each output screen
  *                        file   - input file (stdin default)
  *                        offset - start offset
  *
  *                If 'file' is missing input is from standard input and
  *                'offset' must be preceeded by '+'.
  *                File is output starting at `offset` which is an octal
  *                value unless suffixed by `.`, in which case it is decimal.
  *                If `offset` is suffixed by `b` it is multiplied by 512.
  *                (UNIX block size)
  *
  *
  *                It is assumed that ints are two bytes long.
  *
  *                Compiles with CII-C86 ver 2.20d - others may need mods.
  */

 /*
  *        Copyright, 1984, Selene Associates, Ltd. - All rights reserved.
  *
  *        Permission is granted for the copying and use of this program
  *        if the following conditions are met:
  *
  *                1)        The use is not for direct commercial benefit.
  *                        Permission is NOT granted to sell this program
  *                        or to incorporate it in any product or for use
  *                        as a promotional tool or inducement to buy any
  *                        product or service.
  *                2)        The user agrees that this program is distributed
  *                        with no warrenties, expressed or implied, as to
  *                        its suitablity for use for any purpose.  And the
  *                        user assumes full responsibility for any damages
  *                        resulting in the use or the inability to use this
  *                        program.
  *                3)        That this entire comment block is included in any
  *                        copies or modifications of this program.
  *
  *        If you find this program to be of use to you, a donation of
  *        whatever you think it is worth will be cheerfully accepted.
  *
  *        Written by: David L. Messer, Selene Associates, Ltd.
  *                                P.O. Box 19130, Mpls, MN,  55119
  */

 int moreflag ;
 int nline ;
 #define NLINE        23


 int flags ;

 #define OFLAG        0x01
 #define OIND        0
 #define DFLAG        0x02
 #define DIND        1
 #define XFLAG        0x04
 #define XIND        2
 #define CFLAG        0x08
 #define CIND        3
 #define BFLAG        0x10
 #define BIND        4

 int wideflag ;


 union {
         unsigned char bbuf[16] ;
         unsigned wbuf[8] ;
         } buf1, buf2 ;


 main( argc, argv )
 int argc ;
 char **argv ;
 {
         register i,j,k,n ;
         FILE *stream ;
         char *cp ;
         long addr, acc, acc10 ;

         stream = stdin ;
         flags = 0 ;
         addr = acc = acc10 = 0L ;

         /*
          * Get flags
          */

         argv++ ;
         argc-- ;
         if( argc > 0 && **argv == '-' ) {
                 cp = *argv ;
                 argv++ ;
                 argc-- ;

                 while( *++cp ) {
                         switch ( *cp ) {
                                 case 'b':
                                         flags |= BFLAG ;
                                         wideflag++ ;
                                         break ;

                                 case 'c':
                                         flags |= CFLAG ;
                                         wideflag++ ;
                                         break ;

                                 case 'd':
                                         flags |= DFLAG ;
                                         break ;

                                 case 'o':
                                         flags |= OFLAG ;
                                         break ;

                                 case 'x':
                                         flags |= XFLAG ;
                                         break ;

                                 case 'm':
                                         moreflag++ ;
                                         break ;

                                 default:
                                         goto usage ;
                                 }
                         }
                 }

         /*
          * Get file name and offset.
          */

         if( argc > 0 ) {
                 if( **argv != '+' ) {
                         if( (stream = fopen( *argv, "rb" )) == NULL ) {
                                 printf( "od: Can`t open %s\n", *argv ) ;
                                 exit( 1 ) ;
                                 }
                         argv++ ;
                         argc-- ;
                         }

                 if( argc ) {
                         cp = *argv ;
                         if( *cp == '+' ) cp++ ;

                         while( isdigit( *cp ) ) {
                                 acc <<= 3 ;
                                 acc10 *= 10 ;
                                 acc10 += (long)(*cp - '0') ;
                                 acc += (long)(*cp - '0') ;
                                 cp++ ;
                                 }
                         if( *cp == '.' ) {
                                 acc = acc10 ;
                                 cp++ ;
                                 }
                         if( *cp == 'b' ) {
                                 acc *= 512L ;
                                 cp++ ;
                                 }
                         if( *cp != '\0' ) goto usage ;
                         argc-- ;
                         }
                 }
         if( argc > 0 ) goto usage ;

         if( flags == 0 ) flags = OFLAG ;


         /*
          * Skip bytes for offset.
          */

         addr = 0 ;
         while( addr != acc ) {
                 if( fgetc( stream ) == EOF ) break ;
                 addr++ ;
                 }


         /*
          * Print bytes, 16 at a time.
          */

         n = fread( buf1.bbuf, 1, 16, stream ) ;
         while( n > 0 ) {
                 if( n&1 ) buf1.bbuf[n] = 0 ;

                 printf( "%07lo", addr ) ;

                 for( i=0, k=flags; k; i++ ) {
                         if( k&1 ) {
                                 for( j=0; j<n; j++ ) {
                                         switch( i ) {
                                                 case OIND:
                                                         if( wideflag ) putcha
                                                         printf( " %06lo",
                                                                         (long
                                                         j++ ;
                                                         break ;

                                                 case XIND:
                                                         if( wideflag ) putcha
                                                         printf( "   %04lx",
                                                                         (long
                                                         j++ ;
                                                         break ;

                                                 case DIND:
                                                         if( wideflag ) putcha
                                                         printf( "  %05ld",
                                                                         (long
                                                         j++ ;
                                                         break ;

                                                 case BIND:
                                                         printf( " %03o", buf1
                                                         break ;

                                                 case CIND:
                                                         if( isprint( buf1.bbu
                                                                 printf( "   %
                                                                 }
                                                         else switch( buf1.bbu
                                                                 case '\0':
                                                                         print
                                                                         break

                                                                 case '\b':
                                                                         print
                                                                         break

                                                                 case '\f':
                                                                         print
                                                                         break

                                                                 case '\n':
                                                                         print
                                                                         break

                                                                 case '\r':
                                                                         print
                                                                         break

                                                                 case '\t':
                                                                         print
                                                                         break

                                                                 default:
                                                                         print
                                                                 }
                                                         break ;
                                                 }
                                         }
                                 putchar( '\n' ) ;
                                 more() ;
                                 k >>= 1 ;
                                 if( k ) printf( "       " ) ;
                                 }
                         else k >>= 1 ;
                         }

                 k = 0 ;
                 addr += n ;
                 if( n < 16 ) break ;
                 for(;;) {
                         n = fread( buf2.bbuf, 1, 16, stream ) ;
                         j = 0 ;
                         for( i=0; i<n; i++ ) {
                                 if( buf1.bbuf[i] != buf2.bbuf[i] ) j=1 ;
                                 }
                         if( j==0 && k==0 && n > 0 ) {
                                 printf( "*\n" ) ;
                                 more() ;
                                 k++ ;
                                 }
                         if( n!=16 || j!=0 ) break ;
                         addr += n ;
                         }

                 for( i=0; i<n; i++ ) {
                         buf1.bbuf[i] = buf2.bbuf[i] ;
                         }
                 }

         printf( "%07o\n", addr ) ;
         more() ;
         exit( 0 ) ;


         usage:
                 printf( "od [-bcdoxm] [file] [+][offset][.][b]\n" ) ;
                 printf( "        -b     - output octal bytes\n" ) ;
                 printf( "        -c     - output character bytes\n" ) ;
                 printf( "        -d     - output decimal words\n" ) ;
                 printf( "        -o     - output octal words (default)\n" ) ;
                 printf( "        -x     - output hex words\n" ) ;
                 printf( "        -m     - pause for each output screen\n" ) ;
                 printf( "        file   - input file (stdin default)\n" ) ;
                 printf( "        offset - start offset\n" ) ;
                 exit( 1 ) ;

         } /* main */





 /**
  *        more - if moreflag is set, pause every screen.  Must be called
  *               for every line-feed.
  */

 more()
 {
         char c ;

         if( !moreflag ) return ;

         if( ++nline < NLINE ) return ;
         nline = 0 ;
         printf( "--More--" ) ;
         while( (c = bdos(8)&0x7F) != ' ' && c != 'q' ) {
                 }
         printf( "\r        \r" ) ;
         if( c == 'q' ) exit( 0 ) ;

         } /* more */


 OKISET.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\OKISET.C

 /*
 **                OKIDATA PRINTER SETUP UTILITY
 ** Copyright 1987, S.E. Margison
 ** 1-11-87 A
 **
 **   As distributed, this program requires (for compilation):
 **     "Steve's Datalight Library" version 1.10 or later
 **   which may be obtained without registration from many Bulletin
 **   Board Systems including:
 **      Compuserve IBMSW
 **      Cul-De-Sac (Holliston, MA.)
 **      HAL-PC BBS (Houston, TX.)
 **   and software library houses including:
 **      Public (Software) Library (Houston, TX.)
 **
 **   or by registration:
 **      $10 for Docs, Small Model Library
 **      $25 for Docs, S, D, L, P libraries, and complete library source
 **              in C and Assembler
 **     Steven E. Margison
 **     124 Sixth Street
 **     Downers Grove, IL, 60515
 **
 */

 #include <stdio.h>
 #include <smdefs.h>
 #include <keys.h>

 #define NONE 0xff
 #define PICA 0
 #define COND 1
 #define DRAFT 0
 #define LQ 1
 #define beep putchar(BELL)

 short length, linespc, lqspc, pitch, style;
 short printer;  /* 0 = PRN, 1 = LPT1, 2 = LPT2 */

 char pica[] =  "NORMAL   ",
      cond[] =  "CONDENSED",
      draft[] = "DRAFT         ",
      lq[] =    "LETTER QUALITY",
      lpt1[] = "LPT1:",
      lpt2[] = "LPT2:",
      prn[] = "PRN: ";

 char line1[] = "OKIDATA ML84 CONFIGURATOR V1.10",
      line2[] = "- by Steven E. Margison -",
      line3[] = "Copyright 1986 -- All Rights Reserved",
      line4[] = "F1   Pitch: ",
      line5[] = "F2   Style: ",
      line6[] = "F3   LQ spacing: ",
      line7[] = "F4   Form Length (lines): ",
      line8[] = "F5   Line Spacing: ",
      line9[] = "F6   ",
      line10[]= "F7   Output Channel - ",
      line11[]= "F8   Normal Defaults",
      line12[]= "F9   Send Control Codes",
      line13[]= "FK10  -- Return to DOS --",
      line14[]= "Waiting...",
      cline[]="                                                        ";

 main() {           /* no command line arguments */
    int key;
    printer = 0;
    lqspc = linespc = pitch = style = length = NONE;
    domenu(NO);           /* initialize the screen */

    while(YES) {
       key = getkey();    /* get a function code */
       if(key < 0xff) {
          beep;
          continue;
          }
       key &= 0x7f;
       switch(key) {
          case FK1:   /* select pitch */
             dofk1();
             if((pitch is COND) and (style is LQ)) {
                style = DRAFT;
                putstyle();
                }
             prompt();
             break;
          case FK2:   /* select style */
             dofk2();
             if((style is LQ) and (pitch is COND)) {
                pitch = PICA;
                putpitch();
                }
             prompt();
             break;
          case FK3:   /* specify LQ character spacing */
             if((lqspc = get2digs(9, 32)) is NONE) { prompt(); break; }
             if(style isnot LQ) {
                style = LQ;
                putstyle();
                if(pitch is COND) {
                   pitch = PICA;
                   putpitch();
                   }
                }
             if(lqspc > 0x11) {
                lqspc = 0;
                warn(1);
                putlqspc();
                }
             prompt();
             break;
          case FK4:   /* specify Form length in lines */
             if((length = get2digs(10, 41)) is NONE) { prompt(); break; }
             if(length is 0) {
                length = 0x66;
                warn(2);
                putlength();
                }
             prompt();
             break;
          case FK5:  /* specify line spacing */
             dofk5();
             prompt();
             break;
          case FK6:
             beep;
             break;
          case FK7:  /* select output channel */
             dokey7();
             prompt();
             break;
          case FK8:   /* set normal options */
             linespc = 0;  /* 6 lpi */
             putlinespc();
             length = 0x66;
             putlength();
             style = DRAFT;
             putstyle();
             pitch = PICA;
             putpitch();
             lqspc = NONE;
             putlqspc();
             printer = 0;
             putprinter();
             prompt();
             break;
          case FK9:  /* write the codes out and exit */
             dofk9();
             break;
          case FK10:
             exit2dos();
             domenu(YES);
             break;
          default:
             beep;
          }   /* end of switch */
       }      /* end of main while */
    }         /* end of main() */


 domenu(cmd) int cmd; {
    int i;
    /* if cmd is YES, then place current setting in menu for each item */
    cls();
    mkbox(0, 0, 80, 22, 0);   /* place the border on blank screen */
    i = cntr(line1);
    d_say(3, i, line1);
    i = cntr(line2);
    d_say(4, i, line2);
    i = cntr(line3);
    d_say(5, i, line3);
    d_say(7, 15, line4);
    if(cmd and (pitch isnot NONE)) putpitch();
    d_say(8, 15, line5);
    if(cmd and (style isnot NONE)) putstyle();
    d_say(9, 15, line6);
    if(cmd and (lqspc isnot NONE)) putlqspc();
    d_say(10, 15, line7);
    if(cmd and (length isnot NONE)) putlength();
    d_say(11, 15, line8);
    if(cmd and (linespc isnot NONE)) putlinespc();
    d_say(12, 15, line9);
    d_say(13, 15, line10);
    putprinter();
    d_say(14, 15, line11);
    d_say(15, 15, line12);
    d_say(16, 15, line13);
    prompt();
    }

 cntr(str) char *str; {   /* returns column to start printing */
    int i;
    i = strlen(str);
    --i;     /* account for newline character */
    return(((80 - i) / 2) - 1);
    }

 prompt() {
    d_say(19, 15, cline);
    d_say(19, 15, line14);
    }

 warn(value) int value; {
    beep;
    switch(value) {
       case 1:
          d_say(19, 15, "Value too large.  Range is 0-11.");
          break;
       case 2:
          d_say(19, 15, "Length value of 0 meaningless.");
          break;
       default:
          prompt();
          return;
       }
    d_say(20, 15, "Strike any key to continue...");
    getkey();
    d_say(20, 15, cline);
    prompt();
    }


 putpitch() {
    if(pitch is PICA) { d_say(7, 27, pica); return; }
    if(pitch is COND) { d_say(7, 27, cond); return; }
    }

 putstyle() {
    if(style is DRAFT) { d_say(8, 27, draft); return; }
    if(style is LQ) { d_say(8, 27, lq); return; }
    }

 putlqspc() {
    char i;
    d_pos(9, 32, 0);
    if(lqspc is NONE) { fputs("  ", stdout); return; }
    i = (char)((lqspc >>4) | '0');
    fputc(i, stdout);
    i = (char)((lqspc & 0x0f) | '0');
    fputc(i, stdout);
    }

 putlength() {
    char i;
    d_pos(10, 41, 0);
    i = (char)((length >>4) | '0');
    fputc(i, stdout);
    i = (char)((length & 0x0f) | '0');
    fputc(i, stdout);
    }

 putlinespc() {
    d_pos(11, 34, 0);
    if(linespc is 0) puts("6 lpi");
    else puts("8 lpi");
    }

 putprinter() {
    d_pos(13, 37, 0);
    switch(printer) {
       case 0: default:
          puts(prn);
          return;
       case 1:
          puts(lpt1);
          return;
       case 2:
          puts(lpt2);
          return;
       }
    }

 dofk1() {
    char chr;
    if(pitch is NONE) { pitch = PICA; putpitch(); }
    d_pos(7, 27, 0);
    while((chr = getkey()) isnot '\r') {
       if(chr > 255) { beep; continue; }
       if(chr isnot ' ') { beep; continue; }
       ++pitch;
       pitch &= 0x01;  /* toggle between 0 and 1 only */
       putpitch();
       d_pos(7, 27, 0);
       }
    }

 dofk2() {
    char chr;
    if(style is NONE) { style = DRAFT; putstyle(); }
    d_pos(8, 27, 0);
    while((chr = getkey()) isnot '\r') {
       if(chr > 255) { beep; continue; }
       if(chr isnot ' ') { beep; continue; }
       ++style;
       style &= 0x01;  /* toggle between 0 and 1 only */
       putstyle();
       d_pos(8, 27, 0);
       }
    }

 dofk5() {
    char chr;
    if(linespc is NONE) { linespc = 0; putlinespc(); }
    d_pos(11, 34, 0);
    while((chr = getkey()) isnot '\r') {
       if(chr > 255) { beep; continue; }
       if(chr isnot ' ') { beep; continue; }
       ++linespc;
       linespc &= 0x01;  /* toggle between 0 and 1 only */
       putlinespc();
       d_pos(11, 34, 0);
       }
    }

 dokey7() {
    char chr;
    d_pos(13, 37, 0);
    while((chr = getkey()) isnot '\r') {
       if(chr > 255) { beep; continue; }
       if(chr isnot ' ') { beep; continue; }
       ++printer;
       if(printer > 2) printer = 0;  /* trap wrap around */
       putprinter();
       d_pos(13, 37, 0);
       }
    }

 dofk9() {
    short i, j;
    short codes[32];
    FILE *fd;
    i = 0;
    fputs("  Sending codes...", stdout);
    if(pitch is PICA) codes[i++] = 0x12;
    if(pitch is COND) codes[i++] = 0x0f;
    if(style isnot NONE) {
       codes[i++] = ESC;
       codes[i++] = 0x58;
       switch(style) {
          default:
             --i; --i; break;
          case DRAFT:
             codes[i++] = 0;
             break;
          case LQ:
             codes[i++] = 1;
             break;
          }
       }
    if((style is LQ) and (lqspc isnot NONE)) {
       codes[i++] = ESC;
       codes[i++] = 0x56;
       codes[i++] = (((lqspc >> 4) * 10) + (lqspc & 0x0f));
       }
    if(length isnot NONE) {
       codes[i++] = ESC;
       codes[i++] = 0x43;
       codes[i++] = (((length >> 4) * 10) + (length & 0x0f));
       }
    if(linespc is 0) {
       codes[i++] = ESC;
       codes[i++] = 0x32;
       }
    if(linespc is 1) {
       codes[i++] = ESC;
       codes[i++] = 0x30;
       }
    /* i has count of characters to place */

    if(printer is 1) fd = fopen("LPT1", "wb");
    if(printer is 2) fd = fopen("LPT2", "wb");
    else fd = stdprn;

    if(fd is NULL) error("Cannot open printer channel");

    for(j = 0; j < i; ++j) fputc(codes[j], fd);
    cls();
    exit(0);
    }


 get2digs(row, col) int row, col; {
    int i, j;
    char chr;
    i = j = 0;
    d_pos(row, col, 0);
    puts("  ");
    d_pos(row, col, 0);
    while((chr = getkey()) isnot '\r') {
       if(i > 2) { beep; continue; }
       if(chr > 255) { beep; continue; }
       if(chr is '\b') {
          j = i = 0;
          d_pos(row, col, 0);
          puts("  ");
          d_pos(row, col, 0);
          continue;
          }
       if(chr is ESC) {
          d_pos(row, col, 0);
          puts("  ");
          return(NONE);
          }
       if(!isdigit(chr)) { beep; continue; }
       putchar(chr);  /* echo it to screen */
       j = j<<4;
       j |= (chr & 0x0f);
       ++i;
       }
    if(i is 0) return(NONE);
    else return(j);
    }



 ONEINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\ONEINT.C

 main()
 {
 int index;
    index = 13;
    printf("The value of the index is %d\n",index);
    index = 27;
    printf("The value of the index is %d\n",index);
    index = 10;
    printf("The value of the index is %d\n",index);
 }


 OPTIMIZE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\OPTIMIZE.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 dooper(node)
 /*
  *      dooper will execute a constant operation in a node and
  *      modify the node to be the result of the operation.
  */
 struct enode    **node;
 {       struct enode    *ep;
         ep = *node;
         switch( ep->nodetype ) {
                 case en_add:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i + ep->v.p[1]->v.i;
                         break;
                 case en_sub:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i - ep->v.p[1]->v.i;
                         break;
                 case en_mul:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i * ep->v.p[1]->v.i;
                         break;
                 case en_div:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i / ep->v.p[1]->v.i;
                         break;
                 case en_lsh:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i << ep->v.p[1]->v.i;
                         break;
                 case en_rsh:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i >> ep->v.p[1]->v.i;
                         break;
                 case en_and:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i & ep->v.p[1]->v.i;
                         break;
                 case en_or:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i | ep->v.p[1]->v.i;
                         break;
                 case en_xor:
                         ep->nodetype = en_icon;
                         ep->v.i = ep->v.p[0]->v.i ^ ep->v.p[1]->v.i;
                         break;
                 }
 }

 int     pwrof2(i)
 /*
  *      return which power of two i is or -1.
  */
 int     i;
 {       int     p, q;
         q = 2;
         p = 1;
         while( q > 0 )
                 {
                 if( q == i )
                         return p;
                 q <<= 1;
                 ++p;
                 }
         return -1;
 }

 int     mod_mask(i)
 /*
  *      make a mod mask for a power of two.
  */
 int     i;
 {       int     m;
         m = 0;
         while( i-- )
                 m = (m << 1) | 1;
         return m;
 }

 opt0(node)
 /*
  *      opt0 - delete useless expressions and combine constants.
  *
  *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
  *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
  *      by node and combine obvious constant operations. It cannot
  *      combine name and label constants but will combine icon type
  *      nodes.
  */
 struct enode    **node;
 {       struct enode    *ep;
         int             val, sc;
         ep = *node;
         if( ep == 0 )
                 return;
         switch( (*node)->nodetype ) {
                 case en_b_ref:
                 case en_w_ref:          /* optimize unary node */
                 case en_l_ref:
                                 case en_cbw:
                                 case en_cbl:
                                 case en_cwl:
                                 case en_ainc:
                                 case en_adec:
                                 case en_not:
                                 case en_compl:
                         opt0( &((*node)->v.p[0]));
                         return;
                 case en_uminus:
                         opt0( &(ep->v.p[0]));
                         if( ep->v.p[0]->nodetype == en_icon )
                                 {
                                 ep->nodetype = en_icon;
                                 ep->v.i = -ep->v.p[0]->v.i;
                                 }
                         return;
                 case en_add:
                 case en_sub:
                         opt0(&(ep->v.p[0]));
                         opt0(&(ep->v.p[1]));
                         if( ep->v.p[0]->nodetype == en_icon ) {
                                 if( ep->v.p[1]->nodetype == en_icon ) {
                                         dooper(node);
                                         return;
                                         }
                                 if( ep->v.p[0]->v.i == 0 ) {
                                         if( ep->nodetype == en_sub )
                                         {
                                                 ep->v.p[0] = ep->v.p[1];
                                                 ep->nodetype = en_uminus;
                                         }
                                         else
                                                 *node = ep->v.p[1];
                                         return;
                                         }
                                 }
                         else if( ep->v.p[1]->nodetype == en_icon ) {
                                 if( ep->v.p[1]->v.i == 0 ) {
                                         *node = ep->v.p[0];
                                         return;
                                         }
                                 }
                         return;
                 case en_mul:
                         opt0(&(ep->v.p[0]));
                         opt0(&(ep->v.p[1]));
                         if( ep->v.p[0]->nodetype == en_icon ) {
                                 if( ep->v.p[1]->nodetype == en_icon ) {
                                         dooper(node);
                                         return;
                                         }
                                 val = ep->v.p[0]->v.i;
                                 if( val == 0 ) {
                                         *node = ep->v.p[0];
                                         return;
                                         }
                                 if( val == 1 ) {
                                         *node = ep->v.p[1];
                                         return;
                                         }
                                 sc = pwrof2(val);
                                 if( sc != -1 )
                                         {
                                         swap_nodes(ep);
                                         ep->v.p[1]->v.i = sc;
                                         ep->nodetype = en_lsh;
                                         }
                                 }
                         else if( ep->v.p[1]->nodetype == en_icon ) {
                                 val = ep->v.p[1]->v.i;
                                 if( val == 0 ) {
                                         *node = ep->v.p[1];
                                         return;
                                         }
                                 if( val == 1 ) {
                                         *node = ep->v.p[0];
                                         return;
                                         }
                                 sc = pwrof2(val);
                                 if( sc != -1 )
                                         {
                                         ep->v.p[1]->v.i = sc;
                                         ep->nodetype = en_lsh;
                                         }
                                 }
                         break;
                 case en_div:
                         opt0(&(ep->v.p[0]));
                         opt0(&(ep->v.p[1]));
                         if( ep->v.p[0]->nodetype == en_icon ) {
                                 if( ep->v.p[1]->nodetype == en_icon ) {
                                         dooper(node);
                                         return;
                                         }
                                 if( ep->v.p[0]->v.i == 0 ) {    /* 0/x */
                                         *node = ep->v.p[0];
                                         return;
                                         }
                                 }
                         else if( ep->v.p[1]->nodetype == en_icon ) {
                                 val = ep->v.p[1]->v.i;
                                 if( val == 1 ) {        /* x/1 */
                                         *node = ep->v.p[0];
                                         return;
                                         }
                                 sc = pwrof2(val);
                                 if( sc != -1 )
                                         {
                                         ep->v.p[1]->v.i = sc;
                                         ep->nodetype = en_rsh;
                                         }
                                 }
                         break;
                 case en_mod:
                         opt0(&(ep->v.p[0]));
                         opt0(&(ep->v.p[1]));
                         if( ep->v.p[1]->nodetype == en_icon )
                                 {
                                 if( ep->v.p[0]->nodetype == en_icon )
                                         {
                                         dooper(node);
                                         return;
                                         }
                                 sc = pwrof2(ep->v.p[1]->v.i);
                                 if( sc != -1 )
                                         {
                                         ep->v.p[1]->v.i = mod_mask(sc);
                                         ep->nodetype = en_and;
                                         }
                                 }
                         break;
                 case en_and:    case en_or:
                 case en_xor:    case en_rsh:
                 case en_lsh:
                         opt0(&(ep->v.p[0]));
                         opt0(&(ep->v.p[1]));
                         if( ep->v.p[0]->nodetype == en_icon &&
                                 ep->v.p[1]->nodetype == en_icon )
                                 dooper(node);
                         break;
                 case en_land:   case en_lor:
                                 case en_lt:                case en_le:
                                 case en_gt:                case en_ge:
                                 case en_eq:                case en_ne:
                 case en_asand:  case en_asor:
                 case en_asadd:  case en_assub:
                 case en_asmul:  case en_asdiv:
                 case en_asmod:  case en_asrsh:
                 case en_aslsh:  case en_cond:
                 case en_fcall:  case en_void:
                 case en_assign:
                         opt0(&(ep->v.p[0]));
                         opt0(&(ep->v.p[1]));
                         break;
                 }
 }

 int     xfold(node)
 /*
  *      xfold will remove constant nodes and return the values to
  *      the calling routines.
  */
 struct enode    *node;
 {       int     i;
         if( node == 0 )
                 return 0;
         switch( node->nodetype )
                 {
                 case en_icon:
                         i = node->v.i;
                         node->v.i = 0;
                         return i;
                 case en_add:
                         return xfold(node->v.p[0]) + xfold(node->v.p[1]);
                 case en_sub:
                         return xfold(node->v.p[0]) - xfold(node->v.p[1]);
                 case en_mul:
                         if( node->v.p[0]->nodetype == en_icon )
                                 return xfold(node->v.p[1]) * node->v.p[0]->v.
                         else if( node->v.p[1]->nodetype == en_icon )
                                 return xfold(node->v.p[0]) * node->v.p[1]->v.
                         else return 0;
                 case en_lsh:
                         if( node->v.p[0]->nodetype == en_icon )
                                 return xfold(node->v.p[1]) << node->v.p[0]->v
                         else if( node->v.p[1]->nodetype == en_icon )
                                 return xfold(node->v.p[0]) << node->v.p[1]->v
                         else return 0;
                 case en_uminus:
                         return - xfold(node->v.p[0]);
                 case en_rsh:    case en_div:
                 case en_mod:    case en_asadd:
                 case en_assub:  case en_asmul:
                 case en_asdiv:  case en_asmod:
                 case en_and:    case en_land:
                 case en_or:     case en_lor:
                 case en_xor:    case en_asand:
                 case en_asor:   case en_void:
                 case en_fcall:  case en_assign:
                         fold_const(&node->v.p[0]);
                         fold_const(&node->v.p[1]);
                         return 0;
                 case en_b_ref:  case en_w_ref:
                 case en_l_ref:  case en_compl:
                 case en_not:
                         fold_const(&node->v.p[0]);
                         return 0;
                 }
         return 0;
 }

 fold_const(node)
 /*
  *      reorganize an expression for optimal constant grouping.
  */
 struct enode    **node;
 {       struct enode    *ep;
         int             i;
         ep = *node;
         if( ep == 0 )
                 return;
         if( ep->nodetype == en_add )
                 {
                 if( ep->v.p[0]->nodetype == en_icon )
                         {
                         ep->v.p[0]->v.i += xfold(ep->v.p[1]);
                         return;
                         }
                 else if( ep->v.p[1]->nodetype == en_icon )
                         {
                         ep->v.p[1]->v.i += xfold(ep->v.p[0]);
                         return;
                         }
                 }
         else if( ep->nodetype == en_sub )
                 {
                 if( ep->v.p[0]->nodetype == en_icon )
                         {
                         ep->v.p[0]->v.i -= xfold(ep->v.p[1]);
                         return;
                         }
                 else if( ep->v.p[1]->nodetype == en_icon )
                         {
                         ep->v.p[1]->v.i -= xfold(ep->v.p[0]);
                         return;
                         }
                 }
         i = xfold(ep);
         if( i != 0 )
                 {
                 ep = makenode(en_icon,i,0);
                 ep = makenode(en_add,ep,*node);
                 *node = ep;
                 }
 }

 opt4(node)
 /*
  *      apply all constant optimizations.
  */
 struct enode    **node;
 {
                 opt0(node);
         fold_const(node);
         opt0(node);
 }



 OS2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\OS2.C

 /*
  * OS/2 System-dependent routines.
  */

 #include "stevie.h"

 /* added for turbo c port 6-15-88 dlm */

 #ifndef TURBO
 extern        far pascal DOSSLEEP();
 #endif

 /*
  * inchar() - get a character from the keyboard
  */
 int
 inchar()
 {
         int        c;

         flushbuf();                /* flush any pending output */

         c = getch();

         if (c == 0x1e)                /* control-^ */
                 return K_CGRAVE;
         else
           {
           switch (c) {
                 case 0x68: return K_HELP;
                 case 0x61: return K_UNDO;
                 case 0x52: return K_INSERT;
                 case 0x47: return K_HOME;
                 case 0x48: return K_UARROW;
                 case 0x50: return K_DARROW;
                 case 0x4b: return K_LARROW;
                 case 0x4d: return K_RARROW;
                 case 0x29: return K_CGRAVE;
                 default:   return c;
           }
           }
 }

 #define        BSIZE        2048
 static        char        outbuf[BSIZE];
 static        int        bpos = 0;

 flushbuf()
 {
         if (bpos != 0)
                 write(1, outbuf, bpos);
         bpos = 0;
 }

 /*
  * Macro to output a character. Used within this file for speed.
  */
 #define        outone(c)        outbuf[bpos++] = c; if (bpos >= BSIZE) flushb

 /*
  * Function version for use outside this file.
  */
 void
 outchar(c)
 register char        c;
 {
         outbuf[bpos++] = c;
         if (bpos >= BSIZE)
                 flushbuf();
 }

 void
 outstr(s)
 register char        *s;
 {
         while (*s) {
                 outone(*s++);
         }
 }

 void
 beep()
 {
         outone('\007');
 }

 /* added for turbo c port 6-14-88 dlm */

 #ifdef TURBO

 msleep(n)
 unsigned int        n;
 {
        sleep(60 * n);
 }

  /* not turbo compile */

 sleep(n)
 int n;
 {

         DOSSLEEP(1000L * n);
 }

 #endif

 #ifdef TURBO
 void
 mdelay()
 {
         delay(500U);
 }

   /* not turbo compile */

 void
 delay()
 {
         DOSSLEEP(500L);

 }

 #endif

 void
 windinit()
 {
         Columns = 80;
         P(P_LI) = Rows = 25;
 }

 void
 windexit(r)
 int r;
 {
         flushbuf();
         exit(r);
 }

 void
 windgoto(r, c)
 register int        r, c;
 {
         r += 1;
         c += 1;

         /*
          * Check for overflow once, to save time.
          */
         if (bpos + 8 >= BSIZE)
                 flushbuf();

         outbuf[bpos++] = '\033';
         outbuf[bpos++] = '[';
         if (r >= 10)
                 outbuf[bpos++] = r/10 + '0';
         outbuf[bpos++] = r%10 + '0';
         outbuf[bpos++] = ';';
         if (c >= 10)
                 outbuf[bpos++] = c/10 + '0';
         outbuf[bpos++] = c%10 + '0';
         outbuf[bpos++] = 'H';
 }

 FILE *
 fopenb(fname, mode)
 char        *fname;
 char        *mode;
 {
         FILE        *fopen();
         char        modestr[16];

         sprintf(modestr, "%sb", mode);
         return fopen(fname, modestr);
 }


 OUT1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\OUT1.C

 /*
  * Copyright (c) 1978 Charles H. Forsyth
  *
  * Modified 02-Dec-80 Bob Denny -- Conditionalize debug code for smaller size
  *                           01 -- Removed ending() function code from here
  *                                  to lex.c, so ytab.c code could share the
  *                                  same overlay region as this module.
  *                           02 -- Removed nfaprint(), llactr(), newcase(),
  *                                  cclprint(), chprint() and setline(),
  *                                  the rest of this can share an overlay.
  *                                  They're in 'out2.c'. This is now 'out1.c'
  *          29-May-81 Bob Denny -- More extern hacking for RSX overlaying.
  *          19-Mar-82 Bob Denny -- New compiler and library
  *          03-May-82 Bob Denny -- Final touches, remove unreferenced autos
  *          28-Aug-82 Bob Denny -- Put "=" into table initializers to make
  *                                  new compiler happy. Add "-s" code to
  *                                  supress "#include <stdio.h>" in output.
  *                                  Tables output 8 values/line instead of
  *                                  16.  Overran R.H. edge on 3 digit octals.
  *                                  Change output format for readability.
  *          31-Aug-82 Bob Denny -- Add lexswitch( ...) to llstin so table
  *                                  name selected by -t switch is automatical
  *                                  switched-to at yylex() startup time.  Rem
  *                                  hard reference to "lextab" from yylex();
  *                                  This module generates extern declaration
  *                                  for forward reference.
  *          14-Apr-83 Bob Denny -- Add VAX11C support.  Remove usage of remot
  *                                  formats (damn!) not supported on VAX-11 C
  *                                 Use "short int" for 16-bit table items und
  *                                  VAX-11 C to save size.
  *                                 Contitional out flaky debug code.  Probabl
  *                                  related to non-functional minimization.
  *                        20-Nov-83 Scott Guthery -- Adapt for IBM PC & DeSme
  *                        26-Dec-83 Scott Guthery -- Removed "extern FILE lex
  *
  */

 /*
  * lex -- output human- and machine-readable tables
  */

 #include <stdio.h>
 #include "lexlex.h"

 extern char *ignore;
 extern char *illeg;
 extern char *breakc;
 extern int nlook;

 char strdec1[] = "\nstruct lextab %s =\t{\n";
 char strdec2[] = "\t\t\t%d,\t\t/* Highest state */\n";
 char strdec3[] = "\t\t\t_D%s\t/* --> \"Default state\" table */\n";
 char strdec4[] = "\t\t\t_N%s\t/* --> \"Next state\" table */\n";
 char strdec5[] = "\t\t\t_C%s\t/* --> \"Check value\" table */\n";
 char strdec6[] = "\t\t\t_B%s\t/* --> \"Base\" table */\n";
 char strdec7[] = "\t\t\t%d,\t\t/* Index of last entry in \"next\" */\n";
 char strdec8[] = "\t\t\t%s,\t\t/* --> Byte-int move routine */\n";
 char strdec9[] = "\t\t\t_F%s\t/* --> \"Final state\" table */\n";
 char strdec10[] = "\t\t\t_A%s\t/* --> Action routine */\n";
 char strdec11[] = "\n\t\t\t%s%s\t/* Look-ahead vector */\n";


 char ptabnam[] = { "         " };

 /*
  * Print the minimised DFA, and at the same time, construct the vector which
  * indicates final states by associating them with their translation index.
  * (DFA printout supressed ifndef DEBUG.)
  */
 dfaprint()
 {
         register struct move *dp;
         register struct dfa *st;
         register i;
         int fi, k, l;

         vstart("LL16BIT _F%s", tabname);
 #ifdef DEBUG
         fprintf(lexlog, "\nMinimised DFA for complete syntax\n");
 #endif
         for (i = 0; i < ndfa; i++) {
 #ifdef DEBUG
                 fprintf(lexlog, "\nstate %d", i);
 #endif
                 st = &dfa[i];
                 k = -1;
                 if (fi = st->df_name->s_final) {
                         k = nfa[fi].n_trans - trans;
 #ifdef DEBUG
                         fprintf(lexlog, " (final %d[%d])", fi, k);
 #endif
                         if (nfa[fi].n_flag&FLOOK) {
                                 k |= (nfa[fi].n_look+1)<<11;
 #ifdef DEBUG
                                 fprintf(lexlog, " restore %d", nfa[fi].n_look
 #endif
                         }
                 }
                 if (l = st->df_name->s_look)
 #ifdef DEBUG
                         fprintf(lexlog, " look-ahead %o", l);
 #else
                         ;
 #endif
                 vel(" %d,", k);
 #ifdef MINIM_OK
                 k = st->df_name->s_group->s_els[0];
                 if (k!=i) {
                         fprintf(lexlog, " deleted\n");
                         continue;
                 }

                 fprintf(lexlog, "\n");
                 for (dp = st->df_base; dp < st->df_max; dp = range(st, dp))
                 if (st->df_default)
                       fprintf(lexlog, "\t.\tsame as %d\n", st->df_default-dfa
 #endif
         }
         vel(" %d,", -1);        /* blocking state */

         vend();
 }

 #ifdef MINIM_OK

 range(st, dp)
 register struct dfa *st;
 register struct move *dp;
 {
         int low, high, last;
         struct set *s;
         register a;

         while (dp < st->df_max && dp->m_check!=st)
                 dp++;
 /***************************************************
  * This always returns given the above statement ! *
  ***************************************************/
         if (dp >= st->df_max)
                 return(dp);

         low = dp - st->df_base;
 /*
         s = dp->m_next->s_group->s_els[0];
 */
         s = dp->m_next;
         for (last = low-1; dp < st->df_max &&
                            dp->m_check==st &&
                            (a = dp - st->df_base)==last+1 &&
 /*
                            dp->m_next->s_state->s_els[0]==s; dp++)
 */
                            dp->m_next==s; dp++)
                 last = a;
         high = last;
         fprintf(lexlog, "\t");
         if (high==low)
                 chprint(low);
         else {
                 fprintf(lexlog, "[");
                 if (high-low > 4) {
                         chprint(low);
                         fprintf(lexlog, "-");
                         chprint(high);
                 } else {
                         while (low<=high)
                                 chprint(low++);
                 }
                 fprintf(lexlog, "]");
         }
         if (s->s_state==NULL)
                 fprintf(lexlog, "\tNULL\n"); else
                 fprintf(lexlog, "\t%d\n", s->s_state-dfa);
         return(dp);
 }
 #endif

 heading()
 {
         char *ver;
         fprintf(llout,
          "/*\n * Created by IBM PC LEX from file \"%s\"\n", infile);
         if(sflag == 0)                  /* If "standalone" switch off */
                 {
                 fprintf(llout,
                         " *\t- for use with standard I/O\n */\n");
                 fprintf(llout, "\n#include <stdio.h>\n");
                 }
         else
                 fprintf(llout, " *\t- for use with stand-alone I/O\n */\n");

         fprintf(llout, "#include <lex.h>\n");
         fprintf(llout, "#define LL16BIT int\n");
         fprintf(llout, "extern int _lmov%c();\n",
                         (ndfa <= 255) ? 'b' : 'i');
                 fprintf(llout, "extern struct lextab *_tabp;\n");
                 fprintf(llout, "extern int lexval, yyline;\n");
                 fprintf(llout, "extern char lbuf[], *llend;\n");
 }

 dfawrite()
 {
         register struct move *dp;
         register i, a;
         struct dfa *st, *def;
         struct set *xp;
         char *xcp;

         setline();
         fprintf(llout,
                 "\n#define\tLLTYPE1\t%s\n", ndfa<=255? "char": "LL16BIT");
         vstart("LLTYPE1 _N%s", tabname);
         for (i = 0; i <= llnxtmax; i++)
                 if (xp = move[i].m_next)
                         vel(" %d,", xp->s_state-dfa); else
                         vel(" %d,", ndfa);
         vend();

         vstart("LLTYPE1 _C%s", tabname);
         for (i = 0; i <= llnxtmax; i++)
                 if (st = move[i].m_check)
                         vel(" %d,", st-dfa); else
                         vel(" %d,", -1);
         vend();
         vstart("LLTYPE1 _D%s", tabname);
         for (i = 0; i < ndfa; i++)
                 if (def = dfa[i].df_default)
                         vel(" %d,", def-dfa); else
                         vel(" %d,", ndfa); /* refer to blocking state */
         vend();
         vstart("LL16BIT _B%s", tabname);
         for (i = 0; i < ndfa; i++)
                 if (dp = dfa[i].df_base)
                         vel(" %d,", dp-move); else
                         vel(" %d,", 0);
         vel(" %d,", 0); /* for blocking state */
         vend();
         if (nlook) {
                 fprintf(llout, "char    *llsave[%d];\n", nlook);
                 vstart("LL16BIT _L%s", tabname);
                 a = nlook<=NBPC? NCHARS-1: -1;
                 for (i = 0; i < ndfa; i++)
                         vel(" 0%o,", dfa[i].df_name->s_look&a);
                 vel(" %d,", 0);
                 vend();
         }
         dospccl(ignore, "LLIGN", "X");
         dospccl(breakc, "LLBRK", "Y");
         dospccl(illeg, "LLILL", "Z");

         strcpy(ptabnam, tabname); strcat(ptabnam,",");
         fprintf(llout, strdec1, tabname);
         fprintf(llout, strdec2, ndfa);
         fprintf(llout, strdec3, ptabnam);
         fprintf(llout, strdec4, ptabnam);
         fprintf(llout, strdec5, ptabnam);
         fprintf(llout, strdec6, ptabnam);
         fprintf(llout, strdec7, llnxtmax);
         fprintf(llout, strdec8, ndfa<=255?"_lmovb":"_lmovi");
         fprintf(llout, strdec9, ptabnam);
         fprintf(llout, strdec10, ptabnam);
         fprintf(llout, strdec11, nlook?"_L":"", nlook?ptabnam:"NULL,   ");
         refccl(ignore, "Ignore", "X");
         refccl(breakc, "Break", "Y");
         refccl(illeg, "Illegal", "Z");
         fprintf(llout, "\t\t\t};\n");
         if(sflag == 0)                  /* If stdio flavor */
                 {
                 fprintf(llout, "\n/* Standard I/O selected */\n");
 /*
                 fprintf(llout, "extern FILE lexin;\n\n");
 */
                 fprintf(llout, "llstin()\n   {\n   if(lexin == NULL)\n");
                 fprintf(llout, "      lexin = stdin;\n");
                 }
         else                            /* Stand-alone flavor */
                 {
                 fprintf(llout, "\n/* Stand-alone selected */\n");
                 fprintf(llout, "\llstin()\n   {\n");
                 }
         fprintf(llout, "   if(_tabp == NULL)\n");
         fprintf(llout, "      lexswitch(&%s);\n   }\n\n", tabname);
         fclose(llout);
 }

 dospccl(cp, s, tag)
 register char *cp;
 char *s, *tag;
 {
         register n;
         char cclnam[16];

         if (cp==0)
                 return;
         fprintf(llout, "#define\t%s\t%s\n", s, tag);
         strcpy(cclnam, tag); strcat(cclnam, tabname);
         vstart("char _%s", cclnam);
         for (n = sizeof(ccls[0]); n--;)

                 vel(" 0%o,", *cp++&0377);
         vend();
 }

 refccl(cp, nm, tag)
 char *cp, *nm, *tag;
 {
         if (cp==0)
                 fprintf(llout, "\t\t\t0,\t\t/* No %s class */\n", nm);
         else
                 fprintf(llout, "\t_%s%s,\t/* %s class */\n", tag, tabname, nm
 }

 int     vnl;

 vstart(fmt, str)
 char *fmt;
 char *str;              /*** WATCH IT ***/
 {
         vnl = 0;
         putc('\n', llout);
         fprintf(llout, fmt, str);
         fprintf(llout, "[] =\n   {\n  ");
 }

 vend()
 {
         fprintf(llout, "\n   };\n");
 }

 vel(fmt, val)
 char *fmt;
 int val;                /*** WATCH IT ***/
 {
         fprintf(llout, fmt, val);
         if ((++vnl&07)==0)
                 fprintf(llout, "\n  ");
 }


 OUT2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\OUT2.C

 /*
  * out2.c  --     Some of Lex's output routines for overlaying, moved
  *                here from the original out.c as part of size reduction
  *                effort.
  *      Bob Denny
  *      03-Dec-80
  * More...
  *      Bob Denny
  *      29-May-81       RSX overlaying
  *      19-Mar-82 Bob Denny -- New compiler and library
  *      28-Aug-82 Bob Denny -- Change output format for readability. I know
  *                              you UNIX hackers are not going to like this
  *                              one.  Add code to generate llstin() per
  *                              setting of "-s" switch.  Fix cclprint() to
  *                              put 16 "characters" on a line. Clean up
  *                              nfaprint().
  *      29-Aug-82 Bob Denny -- Move chprint to root. Add llstin() to
  *                              default lexin to stdin for standard I/O
  *                              and no-op for stand-alone I/O.  Allows
  *                              sdtio-specific code to be removed from
  *                              yylex().
  *      31-Aug-82 Bob Denny -- Add lexswitch( ...) to llstin so table
  *                              name selected by -t switch is automatically
  *                              switched-to at yylex() startup time.  Removed
  *                              hard reference to "lextab" from yylex();
  *      30-Oct-82 Bob Denny -- Remove lexswitch() from llstin(). Made it
  *                              impossible to do a real lexswitch()! (dumb.)
  *                              Default the table by statically initializing
  *                              it to NULL and doing the lexswitch only if
  *                              _tabp is NULL.
  *                20-Nov-83 Scott Guthery -- Adapt for IBM PC & DeSmet C
  */

 #include <stdio.h>
 #include "lexlex.h"

 extern int yyline;

 #ifdef DEBUG

 nfaprint(np, base)
 register struct nfa *np;
 struct nfa *base;
 {
         register i;

         if (np->n_flag&NPRT)
                 return;
         np->n_flag |= NPRT;
         fprintf(lexlog, "state %d\n", np-base);
         switch (np->n_char) {
         case EPSILON:
                 for (i = 0; i < 2; i++)
                         if (np->n_succ[i])
                                 fprintf(lexlog, "\tepsilon  %d\n", np->n_succ
                 break;
         case FIN:
                 fprintf(lexlog, "\tfinal state\n");
                 break;
         case CCL:
                 fprintf(lexlog, "\t[");
                 cclprint(np->n_ccl);
                 fprintf(lexlog, "]  %d\n", np->n_succ[0]-base);

                 break;
         default:
                 putc('\t', lexlog);
                 chprint(np->n_char);
                 fprintf(lexlog, "  %d\n", np->n_succ[0]-base);
                 break;
         }
         putc('\n', lexlog);
         if (np->n_succ[0])
                 nfaprint(np->n_succ[0], base);
         if (np->n_succ[1])
                 nfaprint(np->n_succ[1], base);
 }

 cclprint(cp)
 register char *cp;
 {
         register i;
         register nc;

         nc = 0;
         for (i = 0; i < NCHARS; i++)
                 {
                 if (cp[i / NBPC] & (1 << (i % NBPC)))
                         nc += chprint(i);
                 if(nc >= 64)
                         {
                         nc = 0;
                         fprintf(lexlog, "\n\t ");
                         }
                 }
 }

 #endif

 llactr()
 {
         /*
          * Prior to generating the action routine, create
          * the llstin() routine, which initializes yylex(),
          * per the setting of the "-s" switch.  All hardwired
          * variables have now been removed from yylex(). This
          * allows analyzers to be independent of the standard
          * I/O library and the table name.
          */
         fprintf(llout, "_A%s(__na__)\t\t/* Action routine */\n   {\n", tabnam
 }


 newcase(i)
 {
         static int putsw;

         if (!putsw++)
                 fprintf(llout, "   switch (__na__)\n      {\n");
         fprintf(llout, "\n      case %d:\n", i);
         setline();
 }

 setline()
 {
         fprintf(llout, "\n#line %d\n", yyline);
 }


 OUTCODE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\OUTCODE.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 /*      variable initialization         */

 enum e_gt { nogen, bytegen, wordgen, longgen };
 enum e_sg { noseg, codeseg, dataseg };

 int               gentype = nogen;
 int               curseg = noseg;
 int        outcol = 0;

 struct oplst {
         char    *s;
         int     ov;
         }       opl[] =
         {       {"mov",op_move}, {"mov",op_moveq}, {"add",op_add},
                 {"add",op_addi}, {"add",op_addq}, {"sub",op_sub},
                 {"sub",op_subi}, {"sub",op_subq}, {"and",op_and},
                 {"or",op_or}, {"eor",op_eor}, {"muls",op_muls},
                 {"divs",op_divs}, {"swap",op_swap}, {"beq",op_beq},
                 {"bhi",op_bhi}, {"bhs",op_bhs}, {"blo",op_blo},
                 {"bls",op_bls}, {"mulu",op_mulu}, {"divu",op_divu},
                 {"bne",op_bne}, {"blt",op_blt}, {"ble",op_ble},
                 {"bgt",op_bgt}, {"bge",op_bge}, {"neg",op_neg},
                 {"not",op_not}, {"cmp",op_cmp}, {"ext",op_ext},
                 {"jmp",op_jmp}, {"jsr",op_jsr}, {"rts",op_rts},
                 {"lea",op_lea}, {"asr",op_asr}, {"asl",op_asl},
                 {"clr",op_clr}, {"link",op_link}, {"unlk",op_unlk},
                 {"bra",op_bra}, {"movm",op_movem}, {"pea",op_pea},
                 {"cmp",op_cmpi}, {"tst",op_tst}, {"dc",op_dc},
                 {0,0} };

 putop(op)
 int     op;
 {       int     i;
         i = 0;
         while( opl[i].s )
                 {
                 if( opl[i].ov == op )
                         {
                         fprintf(output,"\t%s",opl[i].s);
                         return;
                         }
                 ++i;
                 }
         printf("DIAG - illegal opcode.\n");
 }

 putconst(offset)
 /*
  *      put a constant to the output file.
  */
 struct enode    *offset;
 {       switch( offset->nodetype )
                 {
                 case en_autocon:
                 case en_icon:
                         fprintf(output,"%d",offset->v.i);
                         break;
                 case en_labcon:
                         fprintf(output,"L%%%d",offset->v.i);
                         break;
                 case en_nacon:
                         fprintf(output,"%s",offset->v.p[0]);
                         break;
                 case en_add:
                         putconst(offset->v.p[0]);
                         fprintf(output,"+");
                         putconst(offset->v.p[1]);
                         break;
                 case en_sub:
                         putconst(offset->v.p[0]);
                         fprintf(output,"-");
                         putconst(offset->v.p[1]);
                         break;
                 case en_uminus:
                         fprintf(output,"-");
                         putconst(offset->v.p[0]);
                         break;
                 default:
                         printf("DIAG - illegal constant node.\n");
                         break;
                 }
 }

 putlen(l)
 /*
  *      append the length field to an instruction.
  */
 int     l;
 {       switch( l )
                 {
                 case 0:
                         break;  /* no length field */
                 case 1:
                         fprintf(output,".b");
                         break;
                 case 2:
                         fprintf(output,".w");
                         break;
                 case 4:
                         fprintf(output,".l");
                         break;
                 default:
                         printf("DIAG - illegal length field.\n");
                         break;
                 }
 }

 putamode(ap)
 /*
  *      output a general addressing mode.
  */
 struct amode    *ap;
 {       switch( ap->mode )
                 {
                 case am_immed:
                         fprintf(output,"&");
                 case am_direct:
                         putconst(ap->offset);
                         break;
                 case am_areg:
                         fprintf(output,"%%a%d",ap->preg);
                         break;
                 case am_dreg:
                         fprintf(output,"%%d%d",ap->preg);
                         break;
                 case am_ind:
                         fprintf(output,"(%%a%d)",ap->preg);
                         break;
                 case am_ainc:
                         fprintf(output,"(%%a%d)+",ap->preg);
                         break;
                 case am_adec:
                         fprintf(output,"-(%%a%d)",ap->preg);
                         break;
                 case am_indx:
                         putconst(ap->offset);
                         fprintf(output,"(%%a%d)",ap->preg);
                         break;
                 case am_xpc:
                         putconst(ap->offset);
                         fprintf(output,"(%%d%d,%%pc)",ap->preg);
                         break;
                 case am_indx2:
                         putconst(ap->offset);
                         fprintf(output,"(%%a%d,%%d%d.l)",ap->preg,ap->sreg);
                         break;
                 case am_indx3:
                         putconst(ap->offset);
                         fprintf(output,"(%%a%d,%%a%d.l)",ap->preg,ap->sreg);
                         break;
                 case am_mask:
                         put_mask(ap->offset);
                         break;
                 default:
                         printf("DIAG - illegal address mode.\n");
                         break;
                 }
 }

 put_code(op,len,aps,apd)
 /*
  *      output a generic instruction.
  */
 struct amode    *aps, *apd;
 int             op, len;
 {       if( op == op_dc )
                 {
                 switch( len )
                         {
                         case 1: fprintf(output,"\tbyte"); break;
                         case 2: fprintf(output,"\tshort"); break;
                         case 4: fprintf(output,"\tlong"); break;
                         }
                 }
         else
                 {
                 putop(op);
                 putlen(len);
                 }
         if( aps != 0 )
                 {
                 fprintf(output,"\t");
                 if( op == op_cmp || op == op_cmpi )
                         putamode( apd );
                 else
                         putamode(aps);
                 if( apd != 0 )
                         {
                         fprintf(output,",");
                         if( op == op_cmp || op == op_cmpi )
                                 putamode( aps );
                         else
                                 putamode(apd);
                         }
                 }
         fprintf(output,"\n");
 }

 put_mask(mask)
 /*
  *      generate a register mask for restore and save.
  */
 int     mask;
 {       int     i;
         fprintf(output,"&0x%04x",mask);
 }

 putreg(r)
 /*
  *      generate a register name from a tempref number.
  */
 int     r;
 {       if( r < 8 )
                 fprintf(output,"D%d",r);
         else
                 fprintf(output,"A%d",r - 8);
 }

 gen_strlab(s)
 /*
  *      generate a named label.
  */
 char    *s;
 {       fprintf(output,"%s:\n",s);
 }

 put_label(lab)
 /*
  *      output a compiler generated label.
  */
 int     lab;
 {       fprintf(output,"L%%%d:\n",lab);
 }

 genbyte(val)
 int     val;
 {       if( gentype == bytegen && outcol < 60) {
                 fprintf(output,",%d",val & 0x00ff);
                 outcol += 4;
                 }
         else    {
                 nl();
                 fprintf(output,"\tbyte\t%d",val & 0x00ff);
                 gentype = bytegen;
                 outcol = 19;
                 }
 }

 genword(val)
 int     val;
 {       if( gentype == wordgen && outcol < 58) {
                 fprintf(output,",%d",val & 0x0ffff);
                 outcol += 6;
                 }
         else    {
                 nl();
                 fprintf(output,"\tshort\t%d",val & 0x0ffff);
                 gentype = wordgen;
                 outcol = 21;
                 }
 }

 genlong(val)
 int     val;
 {       if( gentype == longgen && outcol < 56) {
                 fprintf(output,",%d",val);
                 outcol += 10;
                 }
         else    {
                 nl();
                 fprintf(output,"\tlong\t%d",val);
                 gentype = longgen;
                 outcol = 25;
                 }
 }

 genref(sp,offset)
 SYM     *sp;
 int     offset;
 {       char    sign;
         if( offset < 0) {
                 sign = '-';
                 offset = -offset;
                 }
         else
                 sign = '+';
         if( gentype == longgen && outcol < 55 - strlen(sp->name)) {
                 if( sp->storage_class == sc_static)
                         fprintf(output,",L%%%d%c%d",sp->value.i,sign,offset);
                 else
                         fprintf(output,",%s%c%d",sp->name,sign,offset);
                 outcol += (11 + strlen(sp->name));
                 }
         else    {
                 nl();
                 if(sp->storage_class == sc_static)
                     fprintf(output,"\tlong\tL%%%d%c%d",sp->value.i,sign,offse
                 else
                     fprintf(output,"\tlong\t%s%c%d",sp->name,sign,offset);
                 outcol = 26 + strlen(sp->name);
                 gentype = longgen;
                 }
 }

 genstorage(nbytes)
 int     nbytes;
 {       nl();
         fprintf(output,"\tspace\t%d\n",nbytes);
 }

 gen_labref(n)
 int     n;
 {       if( gentype == longgen && outcol < 58) {
                 fprintf(output,",L%%%d",n);
                 outcol += 6;
                 }
         else    {
                 nl();
                 fprintf(output,"\tlong\tL%%%d",n);
                 outcol = 22;
                 gentype = longgen;
                 }
 }

 int     stringlit(s)
 /*
  *      make s a string literal and return it's label number.
  */
 char    *s;
 {       struct slit     *lp;
         ++global_flag;          /* always allocate from global space. */
         lp = xalloc(sizeof(struct slit));
         lp->label = nextlabel++;
         lp->str = litlate(s);
         lp->next = strtab;
         strtab = lp;
         --global_flag;
         return lp->label;
 }

 dumplits()
 /*
  *      dump the string literal pool.
  */
 {       char            *cp;
         while( strtab != 0) {
                 cseg();
                 nl();
                 put_label(strtab->label);
                 cp = strtab->str;
                 while(*cp)
                         genbyte(*cp++);
                 genbyte(0);
                 strtab = strtab->next;
                 }
         nl();
 }

 nl()
 {       if(outcol > 0) {
                 fprintf(output,"\n");
                 outcol = 0;
                 gentype = nogen;
                 }
 }

 cseg()
 {       if( curseg != codeseg) {
                 nl();
                 fprintf(output,"\ttext\n");
                 curseg = codeseg;
                 }
 }

 dseg()
 {       if( curseg != dataseg) {
                 nl();
                 fprintf(output,"\tdata\t2\n");
                 curseg = dataseg;
                 }
 }



 OUTSTNG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\OUTSTNG.C

 /********************************************************************
  *  This function will output a string to an asynch port.  The baud *
  *  rate divisors and  word  length  should already  be  set.  HXFD *
  *  should point to the line status register and HXF8 should  point *
  *  to the Transmitting Hold Register before calling this  routine. *
  *  If you are using an IBM PC with comm port #1 then these  values *
  *  should be hex 3fd and 3f8 respectively.  If you are using comm2 *
  *  these valute should be 2fd and 2f8.  I  declare HXFD  and  HXF9 *
  *  globally at the first  part of a  program rather  than  passing *
  *  parms all over the place but the routine could be modified very *
  *  easily to handle it in any manner preferred.                    *
  *                                                                  *
  *  This  routine  will  replace one I  earlier put  in the  public *
  *  called "sethayes.c".  If you want to initialize your Hayes then *
  *  pass this function the setup string and the routine will do  it *
  *  for you.  I don't know when I will be able to bring  the  TULSA *
  *  IBBS C-Sig board back on line so those of you who have used the *
  *  board  please be  patient and  hopefully we will  have it  back *
  *  bigger and better than ever before.                             *
  *                     Lynn Long                                    *
  *                     PO Box 471114                                *
  *                     Tulsa, OK 74147-1114                         *
  ********************************************************************/
 void outstng(outdata)
 char *outdata;
 {
         unsigned byte = 0x00;
          while(*outdata != '\0'){
                 byte=inp(1021);                                /*  3FD in dec
                 byte&=0x20;
                 if(byte==0x20){
                          outp(1016,*outdata);        /*  3F8 in decimal
                         *outdata++;
                 }
     }
  }


 PAINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGAPAINT\PAINT.C

 /**************************************************************************
  *                                                                        *
  *                               P A I N T                                *
  *                                 V?.??                                  *
  *                                                                        *
  *                        By: Jim Hudson                                  *
  *                            4600 Hillsboro Ave No                       *
  *                            New Hope, MN    55428                       *
  *                            612-533-4450                                *
  *                                                                        *
  *   All contributions, comments, improvements, praise, or whatever       *
  *    will not be reported to the IRS and will, be greatly appreciated    *
  *                                                                        *
  **************************************************************************/


 #ifndef TRUE
 #define TRUE 1
 #endif
 #ifndef FALSE
 #define FALSE 0
 #endif

 #define ON                   1
 #define OFF                  0

 #define NO_MOUSE  0x80
 #define NOT_MOVED 0
 #define RIGHT     1
 #define LEFT      2
 #define UP              3
 #define DOWN      4

 #define LEFTB          1
 #define RIGHTB          2
 #define CENTERB   4

 #define XHOME          320
 #define YHOME          170

 #define TIMED_OUT  300
 DELAY_TIME 1500                /* may need to be adjusted for processor speed
 #define STR_LENGTH 80
 #define sqr(X) ((X) * (X))
 #define round(x) (int)((x)<0?-floor(-(x)+.5):floor((x)+.5))

 #define len(A,B) ((A > B) ? (A - B) : (B - A))

 F11                0x2300                /* machine dependent  */
 #define F12                0x2400

 #define ENABLE 0x0f
 #define INDEXREG 0x3ce
 #define VALREG 0x3cf
 #define OUTINDEX(index, val) {outport(INDEXREG, index); outport(VALREG, val);
 #define EGABASE 0xa0000000L

 #include <dos.h>
 #include <stdio.h>
 #include <math.h>
 #include <bios.h>
 #include <conio.h>
 #include <ctype.h>
 #include <graphics.h>
 #include <alloc.h>
 #include <string.h>
 #include <process.h>
 #include <stdlib.h>
 #include <dir.h>

 extern int paint_help(void);
 extern void lstyle(void);
 void get_keyboard(void), text_mode(void), print_text(void), v_print_text(void
 void swap_page(void), save_pik(void), read_pik(void), get_scale(void);
 void vector(void), set_fill(void), delete_area(void);
 void xhair(int state), grid(int state);
 void help(void), capture(void), uncapture(void), check_flags(void);
 void p_message(char *str), xcircle(int state);
 void fill_box(void), fill_circle(void);
 void copy(void), move(void), save_pic(void), load_pic(void);
 void new_color(void), xrectangle(void), xellipse(void);
 void scr_restore(char *text), line_style(void);
 int scr_save(void), get_string(char *text, char name[]);
 void gprintf(int, int, char *fmt, ... );
 void wcomp(unsigned size, char *ptr, FILE *fd);
 void rcomp(unsigned size, char *ptr, FILE *fs);
 void pointf(int x, int y);
 void xline(int startx, int starty, int endx, int endy, int state);
 void xline1(int startx, int starty, int endx, int endy, int state);
 void xarc(int state);
 extern void printscr(int reverse);
 void center(double x[], double y[], double *xc, double *yc, double *r);

 /* mouse stuff */

 extern void cmouses(int *function, int *arg2, int *arg3, int *arg4);

 void swap_mouse(void), set_limits(void);
 void set_mouse_position(void), get_mouse_position(void);
 void mouse_motion(char *dx, char *dy), wait_on(int button);
 int r_button_pressed(void), l_button_pressed(void), mouse_reset(void);
 int c_button_pressed(void);

 char *color_num[] = {
                 "Black",
                 "Blue",
                 "Green",
                 "Cyan",
                 "Red",
                 "Magenta",
                 "Brown",
                 "Light Gray",
                 "Dark Gray",
         "Light Blue",
                 "Light Green",
                 "Light Cyan",
                 "Light Red",
                 "Light Magenta",
                 "Yellow",
                 "White"
 };
 char *fill_num[] = {
                 "Empty ",
                 "Solid ",
                 "Line ",
                 "Light Slash ",
                 "Heavy Slash ",
                 "Back Slash ",
                 "Lt Back Slash ",
                 "Hatch ",
                 "Heavy Hatch ",
                 "Interleave ",
                 "Wide Dot ",
                 "Close Dot "
 };
 char *line_width[] = {
                 "Narrow",
                 "      ",
                 "      ",
                 "wide"
 };

 int bkcolor = LIGHTGRAY, cc = BLUE, fill_style = SOLID_FILL, msg_color;
 int on_flag = FALSE, cap_flag = FALSE, first_point = TRUE, time_out = TIMED_O
 int first_flag = FALSE, second_flag = FALSE, kb_flag = TRUE, xhair_flag = FAL
 int maxx = 635, maxy = 349, minx = 5, miny = 20, inc = 10, x, y;
 int header = TRUE, page = 0, height, text_ok = 0, text_size = 5;
 int startx = 0, starty = 0, endx = 0, endy = 0, gf = FALSE;
 void *xhair_buf, *first, *second, *arc1;
 unsigned size, c_size;
 unsigned char *c_buffer;
 struct textsettingstype oldtext;
 char text_line[80], oldc;
 int cb_flag = FALSE, width = 0;
 double scale = 1.000;
 int grid_flag = OFF, arc_mode = 0, arc_count = 0;

 /* more mouse stuff */

 int mouse_flag = FALSE;                /* assume on */
 int function = 0, arg2 = 0, arg3 = 0, arg4 = 0;
 char deltax, deltay;                /* make sure this is a signed value  */

 /* This aspect ratio is preset because that's the way my monitor works   */
 /* properly, 'getaspectratio(&xasp, &yasp)' is called to return 7750 and */
 /* 10000 respectivly.  Either use the system call or adjust the xasp for */
 /* your needs.

 int xasp = 7180, yasp = 10000;

 union k {
         char c[2];
         int  i;
 } key;

 struct linesettingstype oldlinestyle;

 void main()
 {
         char info_line[120], temp[10], *info_ptr;
         register int i, oldx, oldy;
         int Gdriver = DETECT, Gmode;

         startx = starty = endx = endy = 0;

         if(registerfarbgidriver(EGAVGA_driver_far) < 0) exit(1);
         if(registerfarbgifont(small_font_far) < 0) exit(1);
         if(registerfarbgifont(triplex_font_far) < 0) exit(1);

         initgraph(&Gdriver, &Gmode, "");
         if(getgraphmode() != EGAHI) {
                 restorecrtmode();
                 printf("\n\nI'm sorry, but this program ONLY works with an EG
                 exit(0);
         }
     gettextsettings(&oldtext);
 /*        getaspectratio(&xasp, &yasp);        */
         height = textheight("H");
         oldx = x = XHOME;
         oldy = y = YHOME;
         setbkcolor(bkcolor);

         if(mouse_reset()) mouse_flag = NO_MOUSE;
         else {
                 set_mouse_position();
         set_limits();
         }
         setcolor(LIGHTGREEN);        /* first point marker  */
         line(x-2, y, x, y-2);
         line(x, y-2, x+2, y);
         line(x+2, y, x, y+2);
         line(x, y+2, x-2, y);
         line(x-7, y, x-4, y);
         line(x+4, y, x+7, y);
         line(x, y-7, x, y-4);
         line(x, y+4, x, y+7);
         size = imagesize(x-7, y-7, x+7, y+7);
         first = malloc(size);
         getimage(x-7, y-7, x+7, y+7, first);
         putimage(x-7, y-7, first, XOR_PUT);

         line(x-3, y-3, x+3, y-3);         /* second point marker */
         line(x+3, y-3, x+3, y+3);
         line(x+3, y+3, x-3, y+3);
         line(x-3, y+3, x-3, y-3);
         size = imagesize(x-3, y-3, x+3, y+3);
         second = malloc(size);
         getimage(x-3, y-3, x+3, y+3, second);
     putimage(x-3, y-3, second, XOR_PUT);

         line(x-4, y-3, x+4, y+3);
         line(x+4, y-3, x-4, y+3);
         size = imagesize(x-4, y-3, x+4, y+3);
         arc1 = malloc(size);
         getimage(x-4, y-3, x+4, y+3, arc1);
         putimage(x-4, y-3, arc1, XOR_PUT);

         setcolor(DARKGRAY);
         line(x - 5, y, x + 4, y);        /* cross hair marker  */
         line(x, y + 5, x, y - 4);
         size = imagesize(x-5, y-4, x+4, y+5);
         xhair_buf = malloc(size);
         getimage(x-5, y-4, x+4, y+5, xhair_buf);
     putimage(x-5, y-4, xhair_buf, XOR_PUT);

         while(TRUE){                  /* we exit this loop when we quit
                 if(kb_flag) {     /* only paint the header if a key was hit *
                         if(bkcolor == cc) cc = 0;
                         if(header) {
                                 setcolor(bkcolor);
                                 setviewport(0, 0, maxx, 9, 1);
                                 clearviewport();
                                 if (bkcolor == BLACK        || bkcolor == BLU
                                         bkcolor == RED          || bkcolor ==
                                         bkcolor == BROWN        || bkcolor ==
                                         bkcolor == LIGHTBLUE    || bkcolor ==
                                         bkcolor == LIGHTMAGENTA || bkcolor ==
                                         msg_color = WHITE;
                                 else msg_color = BROWN;
                                 setcolor(msg_color);
                                 setviewport(0, 0, maxx, maxy, 1);

                 /* build the information line, this is slower than just
                                    addessing unique X coordinates but with al
                                    I think it comes out alittle better.  Noti
                                    of 'stpcpy' - this updates the pointer whe
                                    does not.
                                 */

                                 info_ptr = info_line;
                                 info_ptr = stpcpy(info_ptr, "X: ");
                                 itoa(x, temp, 10);
                                 info_ptr = stpcpy(info_ptr, temp);
                                 info_ptr = stpcpy(info_ptr, " Y: ");
                                 itoa(y, temp, 10);
                                 info_ptr = stpcpy(info_ptr, temp);
                                 info_ptr = stpcpy(info_ptr, on_flag ? " Pen D
                                 if(second_flag) info_ptr = stpcpy(info_ptr, "
                                 else if(first_flag) info_ptr = stpcpy(info_pt
                                 info_ptr = stpcpy(info_ptr, "Inc = ");
                                 itoa(inc, temp, 10);
                                 info_ptr = stpcpy(info_ptr, temp);
                                 if(mouse_flag != NO_MOUSE) {
                                         info_ptr = stpcpy(info_ptr, mouse_fla
                                 }
                 strcpy(info_ptr, " Color: ");
                                 gprintf(5, 1, "%s", info_line);
                                 gprintf(580, 1, "Page %d", page+1);
                                 setcolor(cc);
                                 gprintf(textwidth(info_line), 1, "%s", color_
                                 if(!(arc_mode || text_ok)) p_message("  ");
                                 miny = 20;
                                 setcolor(msg_color);
                                 if(!(first_point || text_ok)) {
                                         gprintf(275, height+2,
                                                 "Delta X %+6.3f Delta Y %+6.3
                                                 ((x-startx)/66.000) * scale,
                                                 hypot(((x-startx)/66.000) * s
                                 }
                                 setcolor(cc);
                         } else miny = 10;
                         setviewport(0, 0, maxx, maxy, 1);
                         setcolor(cc);
                         xhair(ON);
                         kb_flag = FALSE;
                         set_mouse_position();
         }
                 if(bioskey(1)) get_keyboard();
                 if(!mouse_flag) {                                /* process t
                 /* if center button -- do last function  */
                         if(c_button_pressed()) {
                                 wait_on(CENTERB);
                                 if(key.c[0] >= 'a' && key.c[0] <= 'z') {
                                         cb_flag = TRUE;
                     get_keyboard();
                                 }
                         }
                         /* right button defines endpoints  */
                         if(r_button_pressed()) {
                                 if(first_point) {
                                         if(first_flag) check_flags();
                                         startx = x;
                                         starty = y;
                                         putimage(x-7, y-7, first, XOR_PUT);
                                         first_flag = TRUE;
                                 }
                                 else {
                                         if(second_flag) check_flags();
                                         endx = x;
                                         endy = y;
                                         putimage(x-3, y-3, second, XOR_PUT);
                                         second_flag = TRUE;
                                 }
                                 first_point = !first_point;
                             wait_on(RIGHTB);
                         }
                         oldx = x; oldy = y;
                         mouse_motion(&deltax, &deltay);
                         if(deltax || deltay) {
                                 xhair(OFF);
                                 get_mouse_position();
                                 if(l_button_pressed()) xline(oldx, oldy, x, y
                                 time_out = 0;
                         } else time_out++;
                         if(time_out == TIMED_OUT) {
                                 kb_flag = TRUE;
                         }
                         xhair(ON);
                 }
         }
 }

 void get_keyboard(void)
 {
                 kb_flag = TRUE;                                     /* make s
                 if(!cb_flag) key.i = bioskey(0); /* cb_flag says the center b
                 cb_flag = FALSE;                 /* mouse was hit - repeat la
                 xhair(OFF);
                 if (!key.c[0]) switch(key.c[1]) {
                         case 75:
                                 if((x - inc) < minx) break;
                                 if (on_flag) xline(x, y, x-inc, y, 0);
                                 x -= inc;
                                 break;
                         case 77:                        /* right */
                                 if((x + inc) > maxx) break;
                                 if (on_flag) xline(x, y, x+inc, y, 0);
                                 x += inc;
                                 break;
                         case 72:                        /* up */
                                 if((y - inc) < miny) break;
                                 if (on_flag) xline(x, y, x, y-inc, 0);
                                 y -= inc;
                                 break;
                         case 80:                        /* down */
                                 if((y + inc) > maxy) break;
                                 if (on_flag) xline(x, y, x, y+inc, 0);
                                 y += inc;
                                 break;
                         case 71:                        /* up left */
                                 if((x - inc) < minx || (y - inc) < miny) brea
                                 if (on_flag) xline(x, y, x-inc, y-inc, 0);
                                 x -= inc; y -= inc;
                                 break;
                         case 73:                        /* up right */
                                 if((x + inc) > maxx || (y - inc) < miny) brea
                                 if (on_flag) xline(x, y, x+inc, y-inc, 0);
                                 x += inc; y -= inc;
                                 break;
                         case 79:                        /* down left */
                                 if((x - inc) < minx || (y + inc) > maxy) brea
                                 if (on_flag) xline(x, y, x-inc, y+inc, 0);
                                 x -= inc; y += inc;
                                 break;
                         case 81:                        /* down right */
                                 if((x + inc) > maxx || (y + inc) > maxy) brea
                                 if (on_flag) xline(x, y, x+inc, y+inc, 0);
                                 x += inc; y += inc;
                                 break;
                         case 59:                                /* F1 */
                                 if(text_ok) {
                                         print_text();
                                         break;
                                 }
                                 inc = 1;
                                 break;
                         case 60:                                /* F2 */
                                 if(text_ok) {
                                         v_print_text();
                                         break;
                                 }
                                 inc = 5;
                                 break;
                         case 61: inc = 10;      /* F3 */
                                 break;
                         case 62: inc = 20;      /* F4 */
                                 break;
                         case 63:                /* F5 - Change background col
                                 bkcolor++;
                                 if(bkcolor >= MAXCOLORS) bkcolor = 0;
                                 setbkcolor(bkcolor);
                                 break;
                         case 64:                                /* F6 - Save
                                 save_pik();
                                 break;
                         case 65:                                  /* F7 - Res
                                 read_pik();
                                 break;
                         case 66:                                  /* F8 - Cle
                                 check_flags();
                                 break;
                         case 67:                /* F9 - Turn info lines on/of
                                 if(header) {
                                         p_message("WARNING --- ALL messages w
                                         delay(DELAY_TIME);
                                         setcolor(bkcolor);
                                         setviewport(0, 0, maxx, 19, 1);
                                         clearviewport();
                                         setviewport(0, 0, maxx, maxy, 1);
                                         setcolor(cc);
                                 }
                                 header ^= 1;
                                 set_limits();
                                 break;
                         case 68:                /* F10 - Turn mouse ON/OFF
                                 swap_mouse(); break;
                         case (F11 >> 8):                /* F11 - Change FILL
                                 set_fill(); break;
                         case (F12 >> 8):                /* F12 - Change line
                                 line_style(); break;
                         case 83:                                  /* DELETE k
                                 x = XHOME; y = YHOME; break;
                         case 119:
                                 x = 10; y = miny + 10; break;
                         case -124:
                                 x = 630; y = miny + 10; break;
                         case 115:
                                 x = 10; break;
                         case 116:
                                 x = 630; break;
                         case 117:
                                 x = 10; y = 340; break;
                         case 118:
                                 x = 630; y = 340; break;
             }
                 else if(!text_ok) switch(tolower(key.c[0])) {
                         case '1': cc = 1; break;
                         case '2': cc = 2; break;
                         case '3': cc = 3; break;
                         case '4': cc = 4; break;
                         case '5': cc = 5; break;
                         case '6': cc = 6; break;
                         case '7': cc = 7; break;
                         case '8': cc = 8; break;
                         case '9': cc = 9; break;
                         case '0': cc = 10; break;
                         case '!': cc = 11; break;
                         case '@': cc = 12; break;
                         case '#': cc = 13; break;
                         case '$': cc = 14; break;
                         case '%': cc = 15; break;
                         case '?': help(); break;
             case 'a': xarc(FALSE); break;
                         case 'b': xrectangle(); break;
                         case 'c': xcircle(TRUE); break;
             case 'd': delete_area(); break;
                         case 'e': xellipse(); break;
                         case 'f': break;
                         case 'g': grid_flag ? grid(OFF) : grid(ON); break;
                         case 'h': break;
                         case 'j': capture(); break;
                         case 'k': uncapture(); break;
                         case 'l': xline(startx, starty, endx, endy, 1); break
             case 'm': move(); break;
                         case 'n': new_color(); break;
                         case 'o': on_flag = !on_flag; break;
                         case 'p': swap_page(); break;
                         case 'p' - 0x60: printscr(0); break;
                         case 'q':
                     p_message("Do you really want to quit [Y/N]");
                                 key.i = bioskey(0);
                                 if(tolower(key.c[0]) == 'y') {
                                         closegraph();
                                         restorecrtmode();
                                         /* free any allocated buffers */
                                         free(first); free(second); free(xhair
                                         free(c_buffer);
                         exit(0);
                                 }
                                 break;
                         case 'r': load_pic(); break;
                         case 's': check_flags(); save_pic(); break;
                         case 's' - 0x60: get_scale(); break;
                         case 't': text_mode(); break;
                         case 'w':
                                 setfillstyle(fill_style, cc);
                                 floodfill(x, y, cc);
                                 break;
                         case 'v': vector(); break;
             case 'x': copy(); break;
                         case 'z':
                                 p_message("Attempt to clear display, Hit \"z\
                                 key.i = bioskey(0);
                                 if(tolower(key.c[0]) == 'z') {
                                         if(grid_flag) {
                                                 grid(OFF);
                                                 gf = TRUE;
                                         } else gf = FALSE;
                                         check_flags();
                                         clearviewport();
                                         x = XHOME;
                                         y = YHOME;
                                         if(gf) grid(ON);
                                 }
                                 break;
                         case '\r':
                                 if(arc_mode) {
                                         xarc(TRUE);
                                         break;
                                 }
                                 if(first_point) {
                                         if(first_flag) check_flags();
                                         startx = x;
                                         starty = y;
                                         putimage(x-7, y-7, first, XOR_PUT);
                                         first_flag = TRUE;
                                 }
                                 else {
                                         if(second_flag) check_flags();
                                         endx = x;
                                         endy = y;
                                         putimage(x-3, y-3, second, XOR_PUT);
                                         second_flag = TRUE;
                                 }
                                 first_point = !first_point;
                                 break;
             }
 }

 /* change the screen scale for the Delta X, Delta Y  display */
 void get_scale(void)
 {
         char temp[10], sc_string[80], *st_ptr;
     int gf = FALSE;

         p_message("                                                ");
         st_ptr = sc_string;
         st_ptr = stpcpy(st_ptr, "Enter new screen scale <CR> to abort [");
         sprintf(temp, "%2.4lf", scale);
         st_ptr = stpcpy(st_ptr, temp);
         strcpy(st_ptr, "] ");

         if(!get_string(sc_string, temp)) return;

         if(grid_flag) {
                 grid(OFF);
                 gf = TRUE;
         }
         sscanf(temp, "%lf", &scale);
         if(gf) grid(ON);
 }

 /* draw an ellipse after checking two endpoints were marked */
 void xellipse(void)
 {
         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }
         check_flags();
         ellipse(x, y, 0, 360, len(startx,endx) , len(starty,endy));

 }
 /* draw a retangle after checking two endpoints were marked */
 void xrectangle(void)
 {
         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }
         check_flags();

         xline(startx, starty, endx,   starty, 0);
         xline(endx,   starty, endx,   endy,   0);
         xline(endx,   endy,   startx, endy,   0);
         xline(startx, endy,   startx, starty, 0);
 }

 /* draw the normalized circle */

 void xcircle(int state)
 {
         long dx, dy;

         if(state) {
                 if(!(first_flag & second_flag)) {
                         p_message("Mark first AND second points");
                         delay(DELAY_TIME);
                         return;
                 }
                 check_flags();
         }
         dx = len(startx,endx);
     dy = len(starty,endy);

         if((!dx && !dy) || (dx && dy)) {
                 p_message("Indicate only one axis");
                 delay(DELAY_TIME);
                 return;
         }
     if(dx) dy = (dx * (long)xasp) / (long)yasp;
         if(dy) dx = (dy * (long)yasp) / (long)xasp;
         ellipse(startx, starty, 0, 360, (int)dx, (int)dy);
 }

 /* save the display  */
 void save_pic()
 {
         char fname[STR_LENGTH];
         char ftemp[STR_LENGTH];
         char fback[STR_LENGTH];
         char dr[MAXDRIVE];
         char dir[MAXDIR];
         char fil[MAXFILE];
         char ext[MAXEXT];
         FILE *fp;
     void *buffer_ul, *buffer_ll;
         char *file_ptr;
         int ok_flag = TRUE, gf = FALSE;
         unsigned size_ul, size_ll;

         while(ok_flag) {
                 if(!get_string("Enter filename: ",fname)) return; /* return i

                 fnsplit(fname, dr, dir, fil, ext);
                 strcpy(ext, ".BAK");
                 fnmerge(fback, dr, dir, fil, ext);
                 strcpy(ext, ".$$$");
                 fnmerge(ftemp, dr, dir, fil, ext);
                 strcpy(ext, ".PIC");
                 fnmerge(fname, dr, dir, fil, ext);

                 if(!(fp = fopen(ftemp, "wb"))) {
                         if(header) gprintf(320, height+2, "cannot open file %
                         delay(DELAY_TIME);
                 }
                 else ok_flag = FALSE;
         }
     p_message("Saving the screen to the file");
         if(grid_flag) {
                 grid(OFF);
                 gf = TRUE;
         }
         size_ul = imagesize(0, 0, maxx, ((maxy+1)/2)-1);
         size_ll = imagesize(0, (maxy+1)/2, maxx, maxy);

     buffer_ul = malloc(size_ul);
     buffer_ll = malloc(size_ll);

         if(buffer_ul == NULL || buffer_ll == NULL) {
                 p_message("Out of memory");
                 delay(DELAY_TIME);
                 free(buffer_ul);
                 free(buffer_ll);
                 if(gf) grid(ON);
                 return;
         }

         p_message("   ");
         getimage(0, 0, maxx, ((maxy+1)/2)-1, buffer_ul);
     p_message("Saving the screen to the file");
         getimage(0, (maxy+1)/2, maxx, maxy, buffer_ll);

         file_ptr = buffer_ul;
         wcomp(size_ul, file_ptr, fp);

         free(buffer_ul);

         file_ptr = buffer_ll;
         wcomp(size_ll, file_ptr, fp);

         free(buffer_ll);

         fputc(EOF, fp);
         fcloseall();
         unlink(fback);
         rename(fname, fback);
         rename(ftemp, fname);
         p_message("  ");
         if(gf) grid(ON);
 }
 /* read a picture file  */
 void load_pic()
 {
         char fname[STR_LENGTH], *fname_ptr;
         int ok_flag = TRUE;
         FILE *fp;
         char *buffer, *buf_ptr;
     unsigned size_buf, size_buf1;

         size_buf = imagesize(0, 0, maxx, ((maxy+1)/2)-1);
     buffer = malloc(size_buf);

         if(buffer == NULL) {
                 p_message("Out of memory");
                 delay(DELAY_TIME);
                 free(buffer);
                 return;
         }

         while(ok_flag) {
                 if(!get_string("Enter filename: ",fname)) {
                         free(buffer);
                         return; /* return if no keys were entered */
                 }
                 fname_ptr = fname;

                 while(*fname_ptr != '\0' && *fname_ptr != '.') fname_ptr++;
                 strcpy(fname_ptr, ".PIC");

                 if(!(fp = fopen(fname, "rb"))) {
                         if(header) gprintf(320, height+2, "cannot open file %
                         delay(DELAY_TIME);
                 }
                 else ok_flag = FALSE;
         }
         setcolor(bkcolor);
         setviewport(0,0,639,20,1);
         clearviewport();
         setviewport(0,0,639,349,1);
         setcolor(cc);

     p_message("Reading the file");

         size_buf1 = size_buf;
         rcomp(size_buf1, buffer, fp);
         putimage(0, 0, buffer, XOR_PUT);
         size_buf1 = size_buf;
         rcomp(size_buf1, buffer, fp);
         putimage(0, (maxy+1)/2, buffer, XOR_PUT);

         free(buffer);
         fclose(fp);
 }

 /* move one region to another   */


 /* be careful of start end points with this -- you can get a fold */


 void move(void)
 {
         register int i, j;
         int oldx, oldy, xx, yy, cx, cy, xdir, ydir, gf = FALSE;
         unsigned char c;

         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }
         check_flags();
     if(grid_flag) {
                 grid(OFF);
                 gf = TRUE;
         }

         oldx = x; oldy = y;

         xdir = x > max(startx, endx) ? 0 : 1;
         ydir = y > max(starty, endy) ? 0 : 1;

         cx = len(startx, endx) + 1;
         cy = len(starty, endy) + 1;


         for(i = 0, (xx = xdir ? min(startx,endx) : max(startx, endx));
                 i < cx;
                 i++, xdir ? xx++ : xx--, xdir ? x++ : x--) {

                 for(j = 0, y = oldy, (yy = ydir ? min(starty,endy) : max(star
                         j < cy;
                         j++, ydir ? yy++ : yy--, ydir ? y++ : y--) {

                         c = getpixel(xx, yy);
                         putpixel(xx, yy, 0);
                         if(c) putpixel(x, y, c);
                 }
         }
         x = oldx; y = oldy;
         if(gf) grid(ON);
 }

 /* copy one region to another - it's the same as move except it does not
         clear the original pixel */
 void copy(void)
 {
         register int i, j;
         int oldx, oldy, xx, yy, cx, cy, xdir, ydir, gf = FALSE;
         unsigned char c;

         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }
         check_flags();
     if(grid_flag) {
                 grid(OFF);
                 gf = TRUE;
         }

         oldx = x; oldy = y;

         xdir = x > max(startx, endx) ? 0 : 1;
         ydir = y > max(starty, endy) ? 0 : 1;

         cx = len(startx, endx) + 1;
         cy = len(starty, endy) + 1;

         for(i = 0, (xx = xdir ? min(startx,endx) : max(startx, endx));
                 i < cx;
                 i++, xdir ? xx++ : xx--, xdir ? x++ : x--) {

                 for(j = 0, y = oldy, (yy = ydir ? min(starty,endy) : max(star
                         j < cy;
                         j++, ydir ? yy++ : yy--, ydir ? y++ : y--) {

                         c = getpixel(xx, yy);
                         if(c) putpixel(x, y, c);
                 }
         }
         x = oldx; y = oldy;
         if(gf) grid(ON);
 }

 void delete_area(void)
 {
         register int i, j, cx, cy, xx, yy, gf = FALSE;

         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }
         check_flags();
     if(grid_flag) {
                 grid(OFF);
                 gf = TRUE;
         }

         for(i = 0, xx = min(startx, endx); i <= len(startx, endx); i++, xx++)
                 for(j = 0, yy = min(starty, endy); j <= len(starty, endy) ; j
                         putpixel(xx, yy, 0);
         if(gf) grid(ON);
 }

 /*
         GPRINTF: Used like PRINTF except the output is sent to the
         screen in graphics mode at the specified co-ordinate.
         NOTE: a string HAS to be defined as gprintf(x, y, "%s", "text")
 */

 void gprintf( int xx, int yy, char *fmt, ... )
 {
   va_list  argptr;                                /* Argument list pointer
   char str[140];                                /* Buffer to build sting into

   va_start( argptr, format );                /* Initialize va_ functions

   vsprintf( str, fmt, argptr );        /* prints string to buffer        */
   outtextxy( xx, yy, str );                /* Send string in graphics mode */
   va_end( argptr );                                /* Close va_ functions
 }

 /* print an informational message on the second line
    but only if HEADER is turned on
 */
 void p_message(char *str)
 {
         if(!header) return;

         setcolor(bkcolor);
         setviewport(0, height + 2, maxx, 19, 1);
         clearviewport();

         setcolor(msg_color);
         setviewport(0, 0, maxx, maxy, 1);
         gprintf(5, height + 2, "%s", str);
         setcolor(cc);
 }

 /* turn the first and second markers off.  Since the icon is XOR
    we have to first test if they are displayed
 */
 void check_flags(void)
 {
         if(first_flag) {
                 first_flag = FALSE;
                 putimage(startx-7, starty-7, first, XOR_PUT);
         }
         if(second_flag) {
                 second_flag = FALSE;
                 putimage(endx-3, endy-3, second, XOR_PUT);
         }
         first_point = TRUE;                /* reset to first point only */
 }

 /* save an area (icon) to memory */
 void capture(void)
 {
         register int i, j, c;
         int xx, yy, gf = FALSE;
         unsigned char *buf_ptr;
         unsigned long temp_size;
         union {
                 int i;
                 unsigned char c[2];
         } cx, cy;

         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }

         if(cap_flag) {
                 p_message("There is an icon in memory.  Do you wish to overwr
                 key.i = bioskey(0);
                 c = tolower(key.c[0]);
                 if(c != 'y') return;
         }
         check_flags();
     if(grid_flag) {
                 grid(OFF);
                 gf = TRUE;
         }

         p_message("  ");

         cx.i = len(startx, endx) + 1;
         cy.i = len(starty, endy) + 1;

         temp_size = (long)cx.i * (long)cy.i;
         if(temp_size > 64000L) {
                 p_message("Icon is too big");
                 delay(DELAY_TIME);
                 return;
         }
         c_size = cx.i * cy.i;
         if(cap_flag) free(c_buffer);
     c_buffer = malloc(c_size + 4);

         if(c_buffer == NULL) {
                 p_message("Out of memory");
                 delay(DELAY_TIME);
                 free(c_buffer);
                 return;
         }

         buf_ptr = c_buffer;
         *buf_ptr++ = cx.c[0];
         *buf_ptr++ = cx.c[1];
         *buf_ptr++ = cy.c[0];
         *buf_ptr++ = cy.c[1];

         for(i = 0, xx = min(startx, endx); i < cx.i; i++, xx++) {
                 for(j = 0, yy = min(starty, endy); j < cy.i; j++, yy++) {
                         c = getpixel(xx, yy);
                         *buf_ptr++ = c;
                 }
         }
         cap_flag = TRUE;
         if(gf) grid(ON);
 }

 /* display the saved icon */
 void uncapture(void)
 {
         register int i, j, c;
         int xx, yy;
         unsigned char *buf_ptr;
         union {
                 int i;
                 unsigned char c[2];
         } cx, cy;

         if(!cap_flag) {
                 p_message("There is NO captured picture - use the \"J\" comma
                 delay(DELAY_TIME);
         return;
         }
         buf_ptr = c_buffer;
         cx.c[0] = *buf_ptr++;
         cx.c[1] = *buf_ptr++;
         cy.c[0] = *buf_ptr++;
         cy.c[1] = *buf_ptr++;

         for(i = 0, xx = x; i < cx.i; i++, xx++) {
                 for(j = 0, yy=y; j < cy.i; j++, yy++) {
                         c = *buf_ptr++;
                         if(c != 0 && c != bkcolor) putpixel(xx, yy, c);
                 }
         }
 }

 /* why are you reading this comment */
 void help(void)
 {
         if(paint_help()) {
                 settextjustify(oldtext.horiz, oldtext.vert);
                 settextstyle(oldtext.font, oldtext.direction, oldtext.charsiz
                 p_message("Out of memory");
                 delay(DELAY_TIME);
                 return;
         }
 }

 /* change all occurences in a specified area to a new color  */
 void new_color(void)
 {
         unsigned char from, to, cx, cy;
         register int i, j, c, xx, yy;

         if(!(first_flag & second_flag)) {
                 p_message("Mark first AND second points");
                 delay(DELAY_TIME);
                 return;
         }
         check_flags();

         p_message("Enter the FROM color number");
         key.i = bioskey(0);
         from = key.c[0];
         switch(from) {
                 case '!': from = 11;
                               break;
                 case '@': from = 12;
                               break;
                 case '#': from = 13;
                               break;
                 case '$': from = 14;
                               break;
                 case '%': from = 15;
                               break;
                 case '0': from = 10;
                               break;
                 default:  from -= '0';
                               break;
         }
         p_message("Enter the TO color number");
         key.i = bioskey(0);
         to = key.c[0];
         switch(to) {
                 case '!': to = 11;
                               break;
                 case '@': to = 12;
                               break;
                 case '#': to = 13;
                               break;
                 case '$': to = 14;
                               break;
                 case '%': to = 15;
                               break;
                 case '0': to = 10;
                               break;
                 default:  to -= '0';
                               break;
         }
         if( to == bkcolor) to = 0;
         p_message("Changing colors");

         for(i = 0, xx = min(startx, endx); i <= len(startx, endx); i++, xx++)
                 for(j = 0, yy = min(starty, endy); j <= len(starty, endy) ; j
                         c = getpixel(xx, yy);
                         if( c == from) putpixel(xx, yy, to);
                 }
         }
 }

 /* jump to the nearest pixel of thesame color as the drawing color  */
 void vector(void)
 {
         register int i, xx, yy, z;
         int f0 = 0;

         xx = x;
         yy = y;

         p_message("Searching - please wait (Hit any key to abort)");
         if(x > 0 && x < maxx && y > miny && y < maxy)
                 if(getpixel(x, y) == cc) return;

         i = inc;

         while(f0 != 15) {
                 f0 = 0;
                 z = 2*i;
                 while(z--) {
                         x++;
                         if(x == maxx) f0 &= 1;
                         if(x < maxx) if(getpixel(x, y) == cc) return;
                 }
                 z = 2*i;
                 while(z--) {
                         y++;
                         if(y == maxy) f0 &= 2;
                         if(y < maxy) if(getpixel(x, y) == cc) return;
                 }
                 z = 2*i;
                 while(z--) {
                         x--;
                         if(x == 0) f0 &= 4;
                         if(x > minx) if(getpixel(x, y) == cc) return;
                 }
                 z = 2*i;
                 while(z--) {
                         y--;
                         if(y == miny) f0 &= 8;
                         if(y > miny) if(getpixel(x, y) == cc) return;
                 }
                 x -= inc; y -= inc; i += inc;
                 if(bioskey(1)) {
                         bioskey(0);                                /* get the
                         x = xx; y = yy;
                         return;
                 }
         }
         x = xx; y = yy;
 }

 /* change visual and active pages  */
 void swap_page(void)
 {
         check_flags();
         page ^= 1;
         setvisualpage(page);
         setactivepage(page);

 }

 /* turn cross hairs on, but only if they were off */
 /* turn cross hairs off, but only if they were on */
 void xhair(int state)
 {
         if((state && !xhair_flag) || (!state && xhair_flag)) {
             putimage(x-5, y-4, xhair_buf, XOR_PUT);
                 xhair_flag ^= 1;
         }
 }

 /* step through the 12 fill patterns   */
 void set_fill(void)
 {
         int length;
     static char *fill_text = "Current fill pattern: ";

         if(!header) return;                                                /*
         setlinestyle(0, 0, 0);
         key.i = 0;
         setviewport(0, 0, maxx, 2 * height, 1);
         do {
                 clearviewport();
         gprintf(0, (height/2)-1, "%s%s", fill_text, fill_num[fill_style]);
         length = textwidth(fill_text) + textwidth(fill_num[fill_style]);
                 setfillstyle(fill_style, cc);
                 rectangle(length, 0, length+50, height*2);
                 floodfill(length+1, 1, cc);
                 gprintf(length + 58, (height/2)-1,"%s", "Hit <CR> for next --
                 key.i = bioskey(0);
                 if(key.c[0] == 13) {
                         fill_style++;
                         if(fill_style == 12) fill_style = 0;
                 }
         } while(key.i != F11); /* 68 = F10 */
         setlinestyle(0, 0, width);
         setviewport(0, 0, maxx, maxy, 1);
         setcolor(cc);
         setbkcolor(bkcolor);
 }

 void line_style(void)
 {
         int length;
         static char *line_type = "Current line type: ";

         if(!header) return;
         setviewport(0, 0, maxx, 2 * height, 1);
         getlinesettings(&oldlinestyle);
         do {
                 clearviewport();
         gprintf(0, (height/2)-1, "%s%s", line_type, line_width[width]);
                 setlinestyle(oldlinestyle.linestyle, oldlinestyle.upattern, w
                 length = textwidth(line_type) + textwidth(line_width[width]);
                 line(length + 8, height, length+58, height);
                 gprintf(length + 66, (height/2)-1,"%s%s%s", "Hit <CR> for ",(
                 key.i = bioskey(0);
                 if(key.c[0] == 0x1b) break;                /* abort */
                 if(key.c[0] == 13) width ^= 3;
         } while (key.i != F12);
         setviewport(0, 0, maxx, maxy, 1);
         setcolor(cc);
         setbkcolor(bkcolor);

         if(key.c[0] != 0x1b) lstyle        ();


 }

 /* save the previously defined icon to a file  */
 void save_pik(void)
 {
         char fname[STR_LENGTH], *fname_ptr;
         FILE *fp;
         unsigned char *file_ptr;
         unsigned pik_size;
         int ok_flag = TRUE;

         if(!cap_flag) {
                 p_message("There is NO captured picture - use the \"J\" comma
                 delay(DELAY_TIME);
         return;
         }

         while(ok_flag) {
                 if(!get_string("Enter filename: ",fname)) return; /* return i
                 fname_ptr = fname;

                 while(*fname_ptr != '\0' && *fname_ptr != '.') fname_ptr++;
                 strcpy(fname_ptr, ".PIK");

                 if(!(fp = fopen(fname, "wb"))) printf("cannot open file %s\n"
                 else ok_flag = FALSE;
         }

         p_message("Saving the icon");

         file_ptr = c_buffer;
         pik_size = c_size + 4;        /* size of the saved image plus the x,y
         putw(pik_size, fp);                /* write the size of the picture f

         while(pik_size--) fputc(*file_ptr++, fp);

         putc(EOF, fp);                        /* just in case
         fclose(fp);
 }

 /* read the icon file that has been saved, use 'K' to display it  */
 void read_pik(void)
 {
         char fname[STR_LENGTH], *fname_ptr,c;
         FILE *fp;
         unsigned char *file_ptr;
         unsigned pik_size;
         int ok_flag = TRUE;

         if(cap_flag) {
                 p_message("There is an icon in memory.  Do you wish to overwr
                 key.i = bioskey(0);
                 c = tolower(key.c[0]);
                 if(c != 'y') return;
         }
     check_flags();
         p_message("  ");
         while(ok_flag) {
                 fname_ptr = fname;
                 if(!get_string("Enter filename: ",fname)) return; /* return i
                 while(*fname_ptr != '\0' && *fname_ptr != '.') fname_ptr++;
                 strcpy(fname_ptr, ".PIK");

                 if(!(fp = fopen(fname, "rb"))) printf("cannot open file %s\n"
                 else ok_flag = FALSE;
         }
         if(cap_flag) free(c_buffer);
         p_message("Reading icon");

         pik_size = getw(fp);        /* get the size of the picture first */

         c_size = pik_size-4;        /* global for 'what's there'
         c_buffer = malloc(pik_size);

         if(c_buffer == NULL) {
                 p_message("Out of memory");
                 delay(DELAY_TIME);
                 free(c_buffer);
                 return;
         }
         file_ptr = c_buffer;        /* preserve the pointer                */
         while(pik_size--) *file_ptr++ = fgetc(fp);
         cap_flag = TRUE;
         fclose(fp);
 }


 /* get a text string, displayed on line 2, return the character count
    or zero if <ESC> was hit
 */
 int get_string(char *text, char name[])
 {
         char *name_ptr;
         int j, count = 0;
         if(header) {
                 setcolor(msg_color);
                 gprintf(5, height+2, "%s", text);
     }
         name_ptr = name;
         j = textwidth(text);

         while(TRUE) {
                 if(header) gprintf(j, height+2, "%c", '_');
                 key.i = bioskey(0);
                 if(key.c[0] == 13) break;
                 if(key.c[0] == 27) {                /* provision for an abort
                         count = 0;
                         break;
                 }
                 if(key.c[0] == 0x08) {           /* backspace */
                         setcolor(bkcolor);
                         if(header) gprintf(j, height+2, "%c", 0xdb);
                         j -=textwidth("H");
                         if(header) {
                                 gprintf(j, height+2, "%c", 0xdb);
                                 setcolor(msg_color);
                         }
                         name_ptr--;
                         count--;
                         continue;
                 }
                 *name_ptr++ = key.c[0];
                 if(header) {
                         setcolor(bkcolor);
                         gprintf(j, height+2, "%c", 0xdb);
                         setcolor(msg_color);
                         gprintf(j, height+2, "%c", key.c[0]);
                 }
                 j += textwidth("H");
                 count++;
         }
         *name_ptr = '\0';
         setcolor(cc);
         return count;
 }

 void text_mode(void)
 {

         char *text_ptr;
         int j, count = 0, ok = 0;
         char *msg1 = "Enter text size(1-9) [";
         char *msg2 = "Enter text: ";
         char *msg3 = "Locate cursor and hit <F1> for horizontal or <F2> for v

         if(header) {
                 setcolor(msg_color);
                 gprintf(5, height+2, "%s%d] ", msg1, text_size);
     }
         while(!ok) {
                 if(header) {
                         setcolor(bkcolor);
                         gprintf(textwidth(msg1)+textwidth("5] "), height+2, "
                         setcolor(msg_color);
                         gprintf(textwidth(msg1)+textwidth("5] "), height+2, "
                 }
         key.i = bioskey(0);
                 if(key.c[0] == 13) break;
                 if(key.c[0] == 27) {
                         setcolor(cc);
                         return;
                 }
                 text_size = key.c[0] - '0';
                 if(text_size > 0 && text_size < 10) ok = 1;
         }
         if(header) {
                 setcolor(bkcolor);
                 gprintf(textwidth(msg1)+textwidth("5] "), height+2, "%c", 0xd
                 setcolor(msg_color);
                 gprintf(textwidth(msg1)+textwidth("5] "), height+2, "%d", tex
                 delay(200);
                 setcolor(bkcolor);
                 setviewport(0, height+2, maxx, 20, 1);
                 clearviewport();
                 setviewport(0, 0, maxx, maxy, 1);
                 setcolor(msg_color);
                 outtextxy(5, height+2, msg2);
         }
         text_ptr = text_line;
         j = textwidth(msg2);

         while(TRUE) {
                 if(header) gprintf(j, height+2, "%c", '_');
                 key.i = bioskey(0);
                 if(key.c[0] == 13) break;
                 if(key.c[0] == 27) {                /* provision for an abort
                         count = 0;
                         break;
                 }
                 if(key.c[0] == 0x08) {           /* backspace */
                         setcolor(bkcolor);
                         if(header) gprintf(j, height+2, "%c", 0xdb);
                         j -=textwidth("H");
                         if(header) {
                                 gprintf(j, height+2, "%c", 0xdb);
                                 setcolor(msg_color);
                         }
                         text_ptr--;
                         count--;
                         continue;
                 }
                 *text_ptr++ = key.c[0];
                 if(header) {
                         setcolor(bkcolor);
                         gprintf(j, height+2, "%c", 0xdb);
                         setcolor(msg_color);
                         gprintf(j, height+2, "%c", key.c[0]);
                 }
                 j += textwidth("H");
                 count++;
         }
         *text_ptr = '\0';
     setcolor(cc);

         if(!count) return;
         text_ok = TRUE;
         p_message(msg3);
 /*        delay(DELAY_TIME); */
         on_flag = FALSE;                                /* make sure pen is u
 }

 void print_text(void)
 {
         text_ok = 0;
         settextstyle(SMALL_FONT, HORIZ_DIR, text_size);
         gprintf(x, y - textheight("H"), text_line);
         settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
 }

 void v_print_text(void)
 {
         text_ok = 0;
         settextstyle(SMALL_FONT, VERT_DIR, text_size);
         gprintf(x, y - textwidth(text_line), text_line);
         settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
 }


 /********************************/
 /*                                                        */
 /*         MOUSE STUFF          */
 /*                                                        */
 /********************************/

 /* turn mouse on/off, but only if it is present. Mouse reset
    determined if installed. NO_MOUSE indicates not present
 */
 void swap_mouse(void)
 {
         if(mouse_flag != NO_MOUSE) mouse_flag ^= 1;
 }

 int mouse_reset(void)
 {
         function = 0;
         cmouses(&function, &arg2, &arg3, &arg4);

         if(function == 0) return TRUE;
         return FALSE;
 }

 /*return true if button is pressed, else zero  */
 int r_button_pressed(void)
 {
         function = 3;
         cmouses(&function, &arg2, &arg3, &arg4);
         return (arg2 & 2);
 }
 /*return true if button is pressed, else zero  */
 int l_button_pressed(void)
 {
         function = 3;
         cmouses(&function, &arg2, &arg3, &arg4);
         return (arg2 & 1);
 }


 /*return true if button is pressed, else zero  */
 int c_button_pressed(void)
 {
         function = 3;
         cmouses(&function, &arg2, &arg3, &arg4);
         return (arg2 & 4);
 }

 /* set mouse cursor coordinates, from global x,y (current pos)  */
 void set_mouse_position(void)
 {
         function = 4;
         cmouses(&function, &arg2, &x, &y);
 }

 /* return mouse cursor coordinates, from global x,y (current pos)  */
 void get_mouse_position(void)
 {
         function = 3;
         cmouses(&function, &arg2, &x, &y);
 }

 /* return direction of travel  */
 void mouse_motion(char *dx, char *dy)
 {
         int a3, a4;
         function = 11;
         cmouses(&function, &arg2, &a3, &a4);

         if(a3 > 0) *dy = DOWN;
         else if(a3 < 0) *dy = UP;
         else *dy = NOT_MOVED;

         if(a4 > 0) *dx = RIGHT;
         else if(a4 < 0) *dx = LEFT;
         else *dx = NOT_MOVED;
 }

 /* return TRUE when specified button is released  */
 void wait_on(int button)
 {
         switch(button) {
                 case LEFTB: while(l_button_pressed());
                                         break;
                 case RIGHTB: while(r_button_pressed());
                                         break;
                 default: while(c_button_pressed());
         }
 }

 void set_limits(void)
 {
         /* set X limit */

         function = 7;
         arg3 = 5;
         arg4 = 635;
         cmouses(&function, &arg2, &arg3, &arg4);

         /* set Y limit */

         function = 8;
         arg3 = header ? 20 : 5;
         arg4 = 345;
         cmouses(&function, &arg2, &arg3, &arg4);
 }

 #define INDICATE 0xd9

 void wcomp(unsigned size, char *ptr, FILE *fd)
 {
         unsigned char c, last, chr_cnt = 0;
         int flag = 0;

         c = *ptr++;
         fputc(c, fd);
         size--;

         while(size--) {
                 last = c;
                 c = *ptr++;

                 if(c == INDICATE) {
                         if(flag) fputc(chr_cnt, fd);
                         chr_cnt = 0;
                         flag = 0;
                         fputc(c, fd);
                         fputc(0, fd);
                         continue;
                 }

                 if(c == last) {
                         if(!flag) fputc(INDICATE, fd);
                         flag = 1;
                         chr_cnt++;
                         if(chr_cnt == 0xff) {
                                 fputc(chr_cnt, fd);
                                 fputc(c, fd);
                                 c = !c;
                                 chr_cnt = 0;
                                 flag = 0;
                         }
                         continue;
                 }
                 if(flag) {
                         fputc(chr_cnt, fd);
                         chr_cnt = 0;
                         flag = 0;
                 }
                 fputc(c, fd);
         }
         if(chr_cnt) fputc(chr_cnt, fd);

         return;

 }

 void rcomp(unsigned size, char *ptr, FILE *fs)
 {
         unsigned char c, count, last = 0, count1 = 0;

         c = fgetc(fs);
         *ptr++ = c;
         size--;

         while(size > 0) {

                 last = c;

                 c = fgetc(fs);

                 if(c == INDICATE) {
                         count = fgetc(fs);
                         count1 = count;
                         if(count == 0) {
                                 *ptr++ = last;
                                 size--;
                         }
                         else while(count--) {
                                 *ptr++ = last;
                                 size--;
                         }
                         if(count1 == 0xff) {
                                 c =fgetc(fs);
                                 if(c != last) {
                                         *ptr++ = c;
                                         size--;
                                 }
                         }
                 } else {
                         *ptr++ = c;
                         size--;
                 }
         }
         return;
 }

 void grid(int state)
 {
         int oldcolor;
         double lpos, hpos, inc, sc_factor;
         register int i;

         if(!(state ^ grid_flag)) return;

         oldcolor = getcolor();
         sc_factor = scale;
         while((sc_factor < 1.000) || (sc_factor >= 10.000)) {
                 if(sc_factor >= 10.000L) sc_factor /= 10.000L;
                 else if(sc_factor < 1.000L)  sc_factor *= 10.000L;
         }
     if(sc_factor > 5.000L) sc_factor /= 2.000L;

         inc = 66.000L/sc_factor;

         OUTINDEX(0, WHITE);
         OUTINDEX(1, ENABLE);
         OUTINDEX(3, 0x18);

         for(hpos = 5.0;  hpos <= 635.0; hpos += inc)
                 for(i = 20; i <= 345; i++) pointf((int)hpos, i);

         for(lpos = 20.0; lpos <= 345.0; lpos += (inc * xasp / yasp))
                 for(i = 5; i <= 635; i++) pointf(i, (int)lpos);

         OUTINDEX(0, 0);
         OUTINDEX(1, 0);
         OUTINDEX(3, 0);
         OUTINDEX(8, 0xff);

         setcolor(oldcolor);
         grid_flag ^= 1;
 }

 void pointf(int x, int y)
 {
         unsigned char mask = 0x80, exist_color;
         char far *base;

         base = (char *)(EGABASE + ((long)y * 80L + ((long)x/8L)));
         if(page) base += 0x8000L;
         mask >>= x % 8;
         exist_color = *base;
         OUTINDEX(8, mask);
         *base &= 0xff;
 }
 void xline(int startx, int starty, int endx, int endy, int state)
 {
         xline1(startx, starty, endx, endy, state);
         if(width == 3) {
         if(!(endy - starty)) {
                         xline1(startx, starty-1, endx, endy-1, 0);
                         xline1(startx, starty+1, endx, endy+1, 0);
                 } else if(!(endx - startx)) {
                         xline1(startx-1, starty, endx-1, endy, 0);
                         xline1(startx+1, starty, endx+1, endy, 0);
                 } else if((endy - starty) <= (endx-startx)) {
                         xline1(startx, starty-1, endx, endy-1, 0);
                         xline1(startx, starty+1, endx, endy+1, 0);
                 } else {
                         xline1(startx, starty-1, endx, endy-1, 0);
                         xline1(startx, starty+1, endx, endy+1, 0);
                 }
     }
 }
 /* draw a line after checking two endpoints were marked -- if state is 1 */
 void xline1(int startx, int starty, int endx, int endy, int state)
 {
         register int t, distance;
         int xerr = 0, yerr = 0, delta_x, delta_y;
         int incx, incy, ccc;

     if(state) {
                 if(!(first_flag & second_flag)) {
                         p_message("Mark first AND second points");
                         delay(DELAY_TIME);
                         return;
                 }
                 check_flags();
         }

         delta_x = endx - startx;
         delta_y = endy - starty;

         if(delta_x > 0) incx = 1;
         else if(delta_x == 0) incx = 0;
         else incx = -1;

         if(delta_y > 0) incy = 1;
         else if(delta_y == 0) incy = 0;
         else incy = -1;

         delta_x = abs(delta_x);
         delta_y = abs(delta_y);
         distance = delta_x > delta_y ? delta_x : delta_y;

         for(t = 0; t <= distance+1; t++) {

 /*        ccc = getpixel(startx, starty);
                 if(ccc != cc) putpixel(startx, starty,(ccc ^ cc));
 */
                 putpixel(startx, starty,cc);

                 xerr += delta_x;
                 yerr += delta_y;
                 if(xerr > distance) {
                         xerr -= distance;
                         startx += incx;
                 }
                 if(yerr > distance) {
                         yerr -= distance;
                         starty += incy;
                 }
         }
 }

 double xx[3], yy[3];



 /* undocumented "A" function -- I am still experimenting to get curve fitting
    to work.   Screen aspect ratio is a b**ch.  This routine will paint a circ
    given three points on the circumference.  I can't get the sizing very good
    From here one would arc from the angle of the first point to the angle of
    the third point.  The method used to get three points when we are used to
    inputting start,end stuff could be very useful for the ellipse and maybe
    some other things.
 */


 void xarc(int state)
 {
         double xc, yc, rad;
         int tempx1, tempy1;

     if(!state) {
                 if(header) p_message("Use <CR> to mark FIRST POINT");
                 arc_count = 1;
                 arc_mode = TRUE;
         } else {
                 switch(arc_count) {
                 case 1:
                         xx[0] = x;
                         yy[0] = y;

                         putimage(x-4, y-3, arc1, XOR_PUT);
                         if(header) p_message("Use <CR> to mark SECOND POINT")
                         break;
                 case 2:
                         xx[1] = x;
                         yy[1] = y;
                         putimage(x-3, y-3, second, XOR_PUT);
                         if(header) p_message("Use <CR> to mark END point");
                         break;
                 case 3:
                         xx[2] = x;
                         yy[2] = y;

                         arc_mode = FALSE;
                         putimage(xx[1]-3, yy[1]-3, second, XOR_PUT);
                         putimage(xx[0]-4, yy[0]-3, arc1, XOR_PUT);
 /*
 gprintf(10, 60, "xx = %d, %d, %d", xx[0], xx[1], xx[2]);
 gprintf(10, 80, "yy = %d, %d, %d", yy[0], yy[1], yy[2]);
 */
                         center(xx, yy, &xc, &yc, &rad);

                         startx = xc;
                         starty = yc;
                         endx = xc + rad;
                         endy = yc;
                         xcircle(FALSE);

 /*                        circle(round(xc), round(yc), round(rad));


 gprintf(10, 120, "xx = %d, %d, %d", xx[0], xx[1], xx[2]);
 gprintf(10, 140, "yy = %d, %d, %d", yy[0], yy[1], yy[2]);
 gprintf(10, 160, "xc = %d, yc = %d, rad = %d", round(xc), round(yc), round(ra

 */
                 }
                 key.i = 0;
                 arc_count += 1;
         }
 }

 void center(double x[], double y[], double *xc, double *yc, double *r)
 {
         double x2[2], xh[2], y2[2], yk[2];
         double x2y2[2], xnyn, ykn;

         x2[0] = sqr(x[1]) - sqr(x[0]);
         xh[0] = 2.0  * x[1] - 2.0  * x[0];
         y2[0] = sqr(y[1]) - sqr(y[0]);
         yk[0] = 2.0  * y[1] - 2.0  * y[0];

         x2[1] = sqr(x[2]) - sqr(x[1]);
         xh[1] = 2.0  * x[2] - 2.0  * x[1];
         y2[1] = sqr(y[2]) - sqr(y[1]);
         yk[1] = 2.0  * y[2] - 2.0  * y[1];

         x2y2[0] = x2[0] + y2[0];
         x2y2[1] = x2[1] + y2[1];

         xnyn = x2y2[0];
         ykn = yk[0];

         x2y2[0] *= xh[1];
         yk[0] *= xh[1];

         x2y2[1] *= xh[0];
         yk[1] *= xh[0];

         *yc = (x2y2[0] - x2y2[1]) / (yk[0] - yk[1]);
         *xc = (xnyn - (*yc * ykn)) / xh[0];

         x[0] -= *xc;
         y[0] -= *yc;

         *r = hypot(x[0], y[0]);
 }


 PARAM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\PARAM.C

 /*
  * STEVIE - ST Editor for VI Enthusiasts   ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 /*
  * Code to handle user-settable parameters. This is all pretty much table-
  * driven. To add a new parameter, put it in the params array, and add a
  * macro for it in param.h. If it's a numeric parameter, add any necessary
  * bounds checks to doset(). String parameters aren't currently supported.
  */

 #include "stevie.h"

 struct        param        params[] = {

         { "tabstop",        "ts",                8,        P_NUM },
         { "scroll",        "scroll",        12,        P_NUM },
         { "report",        "report",        5,        P_NUM },
         { "lines",        "lines",        25,        P_NUM },

         { "vbell",        "vb",                TRUE,        P_BOOL },
         { "showmatch",        "sm",                FALSE,        P_BOOL },
         { "wrapscan",        "ws",                TRUE,        P_BOOL },
         { "errorbells",        "eb",                FALSE,        P_BOOL },
         { "showmode",        "mo",                FALSE,        P_BOOL },
         { "backup",        "bk",                FALSE,        P_BOOL },
         { "return",        "cr",                TRUE,        P_BOOL },
         { "list",        "list",                FALSE,        P_BOOL },
 #if 0
         /* not yet implemented */
         { "autoindent",        "ai",                FALSE,        P_BOOL },
 #endif
         { "",                "",                0,        0, }

 };

 static        void        showparms();

 void
 doset(arg, inter)
 char        *arg;                /* parameter string */
 bool_t        inter;                /* TRUE if called interactively */
 {
         int        i;
         char        *s;
         bool_t        did_lines = FALSE;

         bool_t        state = TRUE;                /* new state of boolean pa

         if (arg == NULL) {
                 showparms(FALSE);
                 return;
         }
         if (strncmp(arg, "all", 3) == 0) {
                 showparms(TRUE);
                 return;
         }
         if (strncmp(arg, "no", 2) == 0) {
                 state = FALSE;
                 arg += 2;
         }

         for (i=0; params[i].fullname[0] != NUL ;i++) {
                 s = params[i].fullname;
                 if (strncmp(arg, s, strlen(s)) == 0)        /* matched full n
                         break;
                 s = params[i].shortname;
                 if (strncmp(arg, s, strlen(s)) == 0)        /* matched short
                         break;
         }

         if (params[i].fullname[0] != NUL) {        /* found a match */
                 if (params[i].flags & P_NUM) {
                         did_lines = (i == P_LI);
                         if (inter && (arg[strlen(s)] != '=' || state == FALSE
                                 emsg("Invalid set of numeric parameter");
                         else {
                                 params[i].value = atoi(arg+strlen(s)+1);
                                 params[i].flags |= P_CHANGED;
                         }
                 } else /* boolean */ {
                         if (inter && (arg[strlen(s)] == '='))
                                 emsg("Invalid set of boolean parameter");
                         else {
                                 params[i].value = state;
                                 params[i].flags |= P_CHANGED;
                         }
                 }
         } else {
                 if (inter)
                         emsg("Unrecognized 'set' option");
         }

         /*
          * Update the screen in case we changed something like "tabstop"
          * or "list" that will change its appearance.
          */
         if (inter)
                 updatescreen();

         if (did_lines) {
                 Rows = P(P_LI);
                 screenalloc();                /* allocate new screen buffers
                 screenclear();
                 updatescreen();
         }
         /*
          * Check the bounds for numeric parameters here
          */
         if (P(P_TS) <= 0 || P(P_TS) > 32) {
                 if (inter)
                         emsg("Invalid tab size specified");
                 P(P_TS) = 8;
                 return;
         }

         if (P(P_SS) <= 0 || P(P_SS) > Rows) {
                 if (inter)
                         emsg("Invalid scroll size specified");
                 P(P_SS) = 12;
                 return;
         }

         /*
          * Check for another argument, and call doset() recursively, if
          * found. If any argument results in an error, no further
          * parameters are processed.
          */
         while (*arg != ' ' && *arg != '\t') {        /* skip to next white sp
                 if (*arg == NUL)
                         return;                        /* end of parameter li
                 arg++;
         }
         while (*arg == ' ' || *arg == '\t')        /* skip to next non-white
                 arg++;

         if (*arg)
                 doset(arg);        /* recurse on next parameter, if present *
 }

 static        void
 showparms(all)
 bool_t        all;        /* show ALL parameters */
 {
         struct        param        *p;
         char        buf[64];

         gotocmd(TRUE, TRUE, 0);
         outstr("Parameters:\r\n");

         for (p = &params[0]; p->fullname[0] != NUL ;p++) {
                 if (!all && ((p->flags & P_CHANGED) == 0))
                         continue;
                 if (p->flags & P_BOOL)
                         sprintf(buf, "\t%s%s\r\n",
                                 (p->value ? "" : "no"), p->fullname);
                 else
                         sprintf(buf, "\t%s=%d\r\n", p->fullname, p->value);

                 outstr(buf);
         }
         wait_return();
 }


 PARK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\PARK.C

 #include <stdio.h>

 /*
 **  park fixed disk heads
 */

 main()
 {
     int cyl;
     struct {int ax,bx,cx,dx,si,di,ds,es;}srv;

     srv.ax = 0x0800;
     srv.dx = 0x0080;

     /* get fixed disk drive parameters */

     if ( sysint ( 0x13, &srv, &srv ) & 1 )
         abort ("park: Drive parms NOT returned\n");

     srv.ax = 0x0c00;            /* set 'seek' command */
     cyl = ((srv.cx & 0x00c0)<<2) | ((srv.cx & 0xff00)>>8);
     srv.dx = 0x0080;

     if ( sysint ( 0x13, &srv, &srv ) & 1 ) /* park the heads */
         abort ("park: Drive C: FAILED to park - error = %02xh\n",
               (srv.ax & 0xff00)>>8);
     else
         printf("park: Drive C: parked at cylinder %d\n", cyl);
 }


 PASSBACK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\PASSBACK.C

                                           /* Chapter 7 - Program 5 */
 main()
 {
 int index;
 int matrix[20];

    for (index = 0;index < 20;index++)              /* generate data */
       matrix[index] = index + 1;

    for (index = 0;index < 5;index++)         /* print original data */
       printf("Start  matrix[%d] = %d\n",index,matrix[index]);

    dosome(matrix);              /* go to a function & modify matrix */

    for (index = 0;index < 5;index++)       /* print modified matrix */
       printf("Back   matrix[%d] = %d\n",index,matrix[index]);
 }

 dosome(list)                 /* This will illustrate returning data */
 int list[];
 {
 int i;

    for (i = 0;i < 5;i++)                   /* print original matrix */
       printf("Before matrix[%d] = %d\n",i,list[i]);

    for (i = 0;i < 20;i++)                   /* add 10 to all values */
       list[i] += 10;

    for (i = 0;i < 5;i++)                   /* print modified matrix */
       printf("After  matrix[%d] = %d\n",i,list[i]);
 }


 PASSTWO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\PASSTWO.C

 /*PASSTWO.C - From page 298 of "Microsoft C Programming for the */
 /* IBM" by Robert Lafore. This program demonstrates that the    */
 /* value of a structure variable can be passed to a function as */
 /* a parameter. Also a continuation of simple database started  */
 /* on page 292.                                                 */
 /****************************************************************/

 #include <stdio.h>

 struct personnel {            /*define data structure*/
    char name [30];
    int agnumb;
 };

 main()
 {
 struct personnel agent1;      /*declare structure variable*/
 struct personnel agent2;      /*declare structure variable*/
 struct personnel newname();   /*declare function*/

    agent1 = newname();        /*get data for 1st agent*/
    agent2 = newname();        /*get data for 2nd agent*/
    list(agent1);              /*print data for 1st agent*/
    list(agent2);              /*print data for 2nd agent*/
 }

 /* newname() */
 /* puts a new agent in the database */
 struct personnel newname()
 {
 struct personnel agent;             /*new structure*/

    printf("\nNew agent\nEnter name: ");
    gets(agent.name);
    printf("Enter agent number (3 digits): ");
    scanf("%d",&agent.agnumb);
    fflush(stdin);
    return(agent);
 }

 /* list() */
 /* prints data on one agent */
 list(age)
 struct personnel age;               /*struct passed from main*/
 {
    printf("\n\nAgent: \n");
    printf("   Name: %s\n", age.name);
    printf("   Agent number: %03d\n", age.agnumb);
 }



 PCJUNK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\PCJUNK.C

 /*  PCJUNK.C     Misc. procedures */

 #include "stdio.h"
 #include "sdbio.h"
 #define ESC 27
 #define BS 8
 #define CR 13
 #define LF 10

 /*    Replaces JUNK.C for the IBM/PC version            dns */


 char *alloc(n)
 int n;
 {
    return (char*) malloc(n);
 }
 /* commented out because it doesn't work right replaced with the
    getcx from the original sdb
 */
 int getcx(fp)
   FILE *fp;
 {
     static char buf[LINEMAX] = {0};
     static int  bufptr = 0;
     static int  buflen = 0;
     int ch, i, j;

     if (fp!=stdin)
        if ((ch = fgetc(fp)) == '\n')
           return(fgetc(fp));
        else
           return(ch);

     if (buflen > 0 && bufptr < buflen)
       if (bufptr == buflen-1)
         {
         i = bufptr ;
         bufptr = 0 ;
         buflen = 0 ;
         return (buf[i]) ;
         }
       else
         {
         return (buf[bufptr++]);
         } ;

     bufptr = 0 ;
     buflen = 0 ;
     for (bufptr = 0; (ch = getch() ) != -1; )
         if (bufptr < LINEMAX)
           switch (ch)
             {
             case ESC:
               bufptr=0;
               buflen = 0 ;
               printf("\\\n     ");
               fflush(stdout);
               break ;
             case BS:
               if (bufptr>0)
                 {
                 bufptr-- ;
                 buflen-- ;
                 putch(ch) ;
                 putch(32) ;
                 putch(ch) ;
                 }
               break ;
             case CR:
               putch(13) ;
               putch(10) ;
               if (buflen == 0)
                 return(10) ;
               else
                 {
                 buf[bufptr] = 10 ;
                 buflen++ ;
                 bufptr = 1 ;
                 return(buf[0]) ;
                 }
               break ;
             default:
               buf[bufptr++] = ch;
               buflen++ ;
               putch(ch) ;
               break ;
             }
         else {
             printf("*** line too long ***\nRetype> ");
             fflush( stdout ) ;
             buflen = 0;
             bufptr = 0;
         };
  }
  int strncmp( str1, str2, len)
  char *str1, *str2 ;
  int  len ;
  {
    char  newstr1[255], newstr2[255] ;
    int  i ;

    for ( i = 0 ; i < len ; i++ )
      {
        newstr1[i] = str1[i] ;
        newstr2[i] = str2[i] ;
      }
    return (strcmp( newstr1, newstr2 )) ;
 }


 PEEK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\WNDWBOSS\PEEK.C

 /*
 ** Peek/Poke for Microsoft C
 **
 ** MSC /Ze peek
 **
 ** Copyright (c) 1986 - Philip A. Mongelluzzo
 ** All rights reserved.
 **
 ** Placed in public domain 5/8/86 by P.A. Mongelluzzo
 **
 */

 unsigned peek(ioff,iseg)
 unsigned iseg,ioff;
 {
 int far *adr;
 unsigned long seg,off;
   seg=iseg;
   off=ioff;
   adr = (seg << 16) | off;
   return (unsigned)(*adr);
 }

 void poke(ioff,iseg,val)
 unsigned iseg,ioff;
 unsigned char val;
 {
 int far *adr;
 unsigned long seg,off;
   seg=iseg;
   off=ioff;
   adr = (seg << 16) | off;
   *adr = val;
 }

 /* End */


 PEEPGEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\PEEPGEN.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 struct ocode    *peep_head = 0,
                 *peep_tail = 0;

 struct amode    *copy_addr(ap)
 /*
  *      copy an address mode structure (these things dont last).
  */
 struct amode    *ap;
 {       struct amode    *newap;
         if( ap == 0 )
                 return 0;
         newap = xalloc(sizeof(struct amode));
         newap->mode = ap->mode;
         newap->preg = ap->preg;
         newap->sreg = ap->sreg;
         newap->tempflag = ap->tempflag;
         newap->deep = ap->deep;
         newap->offset = ap->offset;
         return newap;
 }

 gen_code(op,len,ap1,ap2)
 /*
  *      generate a code sequence into the peep list.
  */
 int             op, len;
 struct amode    *ap1, *ap2;
 {       struct ocode    *new;
         new = xalloc(sizeof(struct ocode));
         new->opcode = op;
         new->length = len;
         new->oper1 = copy_addr(ap1);
         new->oper2 = copy_addr(ap2);
         add_peep(new);
 }

 add_peep(new)
 /*
  *      add the ocoderuction pointed to by new to the peep list.
  */
 struct ocode    *new;
 {       if( peep_head == 0 )
                 {
                 peep_head = peep_tail = new;
                 new->fwd = 0;
                 new->back = 0;
                 }
         else
                 {
                 new->fwd = 0;
                 new->back = peep_tail;
                 peep_tail->fwd = new;
                 peep_tail = new;
                 }
 }

 gen_label(labno)
 /*
  *      add a compiler generated label to the peep list.
  */
 int     labno;
 {       struct ocode    *new;
         new = xalloc(sizeof(struct ocode));
         new->opcode = op_label;
         new->oper1 = labno;
         add_peep(new);
 }

 flush_peep()
 /*
  *      output all code and labels in the peep list.
  */
 {       opt3();         /* do the peephole optimizations */
         while( peep_head != 0 )
                 {
                 if( peep_head->opcode == op_label )
                         put_label(peep_head->oper1);
                 else
                         put_ocode(peep_head);
                 peep_head = peep_head->fwd;
                 }
 }

 put_ocode(p)
 /*
  *      output the instruction passed.
  */
 struct ocode    *p;
 {       put_code(p->opcode,p->length,p->oper1,p->oper2);
 }

 peep_move(ip)
 /*
  *      peephole optimization for move instructions.
  *      makes quick immediates when possible.
  *      changes move #0,d to clr d.
  *      changes long moves to address registers to short when
  *              possible.
  *      changes move immediate to stack to pea.
  */
 struct ocode        *ip;
 {       struct enode    *ep;
         if( ip->oper1->mode != am_immed )
                 return;
         ep = ip->oper1->offset;
         if( ep->nodetype != en_icon )
                 return;
         if( ip->oper2->mode == am_areg )
                 {
                 if( -32768 <= ep->v.i && ep->v.i <= 32768 )
                         ip->length = 2;
                 }
         else if( ip->oper2->mode == am_dreg )
                 {
                 if( -128 <= ep->v.i && ep->v.i <= 127 )
                         {
                         ip->opcode = op_moveq;
                         ip->length = 0;
                         }
                 }
         else
                 {
                 if( ep->v.i == 0 )
                         {
                         ip->opcode = op_clr;
                         ip->oper1 = ip->oper2;
                         ip->oper2 = 0;
                         }
                 else if( ip->oper2->mode == am_adec && ip->oper2->preg == 7 )
                         {
                         ip->opcode = op_pea;
                         ip->length = 0;
                         ip->oper1->mode = am_direct;
                         ip->oper2 = 0;
                         }
                 }
 }

 int     equal_address(ap1,ap2)
 /*
  *      compare two address nodes and return true if they are
  *      equivalent.
  */
 struct amode    *ap1, *ap2;
 {       if( ap1 == 0 || ap2 == 0 )
                 return 0;
         if( ap1->mode != ap2->mode )
                 return 0;
         switch( ap1->mode )
                 {
                 case am_areg:   case am_dreg:
                 case am_ainc:   case am_adec:
                         return ap1->preg == ap2->preg;
                 }
         return 0;
 }

 peep_add(ip)
 /*
  *      peephole optimization for add instructions.
  *      makes quick immediates out of small constants.
  */
 struct ocode    *ip;
 {       struct enode    *ep;
         if( ip->oper1->mode != am_immed )
                 return;
         ep = ip->oper1->offset;
         if( ip->oper2->mode != am_areg )
                 ip->opcode = op_addi;
         else
                 {
                 if( isshort(ep) )
                         ip->length = 2;
                 }
         if( ep->nodetype != en_icon )
                 return;
         if( 1 <= ep->v.i && ep->v.i <= 8 )
                 ip->opcode = op_addq;
         else if( -8 <= ep->v.i && ep->v.i <= -1 )
                 {
                 ip->opcode = op_subq;
                 ep->v.i = -ep->v.i;
                 }
 }

 peep_sub(ip)
 /*
  *      peephole optimization for subtract instructions.
  *      makes quick immediates out of small constants.
  */
 struct ocode    *ip;
 {       struct enode    *ep;
         if( ip->oper1->mode != am_immed )
                 return;
         ep = ip->oper1->offset;
         if( ip->oper2->mode != am_areg )
                 ip->opcode = op_subi;
         else
                 {
                 if( isshort(ep) )
                         ip->length = 2;
                 }
         if( ep->nodetype != en_icon )
                 return;
         if( 1 <= ep->v.i && ep->v.i <= 8 )
                 ip->opcode = op_subq;
         else if( -8 <= ep->v.i && ep->v.i <= -1 )
                 {
                 ip->opcode = op_addq;
                 ep->v.i = -ep->v.i;
                 }
 }

 int     peep_cmp(ip)
 /*
  *      peephole optimization for compare instructions.
  *      changes compare #0 to tst and if previous instruction
  *      should have set the condition codes properly delete.
  *      return value is true if instruction was deleted.
  */
 struct ocode    *ip;
 {       struct ocode    *prev;
         struct enode    *ep;
         if( ip->oper1->mode != am_immed )
                 return;
         ep = ip->oper1->offset;
         if( ip->oper2->mode == am_areg )
                 {
                 if( isshort(ep) )
                         ip->length = 2;
                 return;
                 }
         ip->opcode = op_cmpi;
         if( ep->nodetype != en_icon || ep->v.i != 0 )
                 return;
         ip->oper1 = ip->oper2;
         ip->oper2 = 0;
         ip->opcode = op_tst;
         prev = ip->back;
         if( prev == 0 )
                 return;
         if( (((prev->opcode == op_move || prev->opcode == op_moveq) &&
                 equal_address(prev->oper1,ip->oper1)) &&
                 prev->oper2->mode != am_areg) ||
                 (prev->opcode != op_label &&
                 equal_address(prev->oper2,ip->oper1)) )
                 {
                 prev->fwd = ip->fwd;
                 if( prev->fwd != 0 )
                         prev->fwd->back = prev;
                 }
 }

 peep_muldiv(ip,op)
 /*
  *      changes multiplies and divides by convienient values
  *      to shift operations. op should be either op_asl or
  *      op_asr (for divide).
  */
 struct ocode    *ip;
 {       int     shcnt;
         if( ip->oper1->mode != am_immed )
                 return;
         if( ip->oper1->offset->nodetype != en_icon )
                 return;
         shcnt = ip->oper1->offset->v.i;
 /*      vax c doesn't do this type of switch well       */
         if( shcnt == 2) shcnt = 1;
         else if( shcnt == 4) shcnt = 2;
         else if( shcnt == 8) shcnt = 3;
         else if( shcnt == 16) shcnt = 4;
         else if( shcnt == 32) shcnt = 5;
         else if( shcnt == 64) shcnt = 6;
         else if( shcnt == 128) shcnt = 7;
         else if( shcnt == 256) shcnt = 8;
         else if( shcnt == 512) shcnt = 9;
         else if( shcnt == 1024) shcnt = 10;
         else if( shcnt == 2048) shcnt = 11;
         else if( shcnt == 4096) shcnt = 12;
         else if( shcnt == 8192) shcnt = 13;
         else if( shcnt == 16384) shcnt = 14;
         else return;
         ip->oper1->offset->v.i = shcnt;
         ip->opcode = op;
         ip->length = 4;
 }

 peep_uctran(ip)
 /*
  *      peephole optimization for unconditional transfers.
  *      deletes instructions which have no path.
  *      applies to bra, jmp, and rts instructions.
  */
 struct ocode    *ip;
 {       while( ip->fwd != 0 && ip->fwd->opcode != op_label )
                 {
                 ip->fwd = ip->fwd->fwd;
                 if( ip->fwd != 0 )
                         ip->fwd->back = ip;
                 }
 }

 opt3()
 /*
  *      peephole optimizer. This routine calls the instruction
  *      specific optimization routines above for each instruction
  *      in the peep list.
  */
 {       struct ocode    *ip;
         ip = peep_head;
         while( ip != 0 )
                 {
                 switch( ip->opcode )
                         {
                         case op_move:
                                 peep_move(ip);
                                 break;
                         case op_add:
                                 peep_add(ip);
                                 break;
                         case op_sub:
                                 peep_sub(ip);
                                 break;
                         case op_cmp:
                                 peep_cmp(ip);
                                 break;
                         case op_muls:
                                 peep_muldiv(ip,op_asl);
                                 break;
                         case op_bra:
                         case op_jmp:
                         case op_rts:
                                 peep_uctran(ip);
                         }
                 ip = ip->fwd;
                 }
 }



 PFINDFIL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\PFINDFIL.C

 #include <stdio.h>

 char *pfindfile(afn, ext)
 register char *afn;
 char *ext;
 /*
  *        Like findfile() but search all directories listed in the environmen
  *        variable "PATH", if no match is found in the current directory. If
  *        <afn> specifies a drive or directory, "PATH" is not used.
  */
 {
         static char tmp[PATHSIZE];
         register char *path, *p;
         char *findfile(), *strchr(), *getenv(), *strcpy();

         if((p = findfile(afn, ext)) ||                        /* search . fir
            strchr(afn, '\\') || strchr(afn, ':'))        /* path specified */
                 return(p);
         if(path = getenv("PATH")) {                        /* get PATH= */
                 while(*path) {
                         p = tmp;
                         while((*path != '\0') &&
                               (*path != ';') &&
                               (*path != ','))        /* copy directory */
                                 *p++ = *path++;
                         if(*path)                        /* move past delim *
                                 ++path;
                         if(p[-1] != '\\')                /* add \ if needed *
                                 *p++ = '\\';
                         strcpy(p, afn);                        /* copy filena
                         if(p = findfile(tmp, ext))        /* do search */
                                 return(p);
                 }
         }
         return(NULL);
 }


 PHELP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGAPAINT\PHELP.C

 /**************************************************************************
  *                                                                        *
  *                      P A I N T ---- H E L P                            *
  *                                                                        *
  *    To keep the main file alittle smaller, and for a little practice    *
  *     in external stuff, we'll keep this a separate file.  Someday I'll  *
  *     have sub levels of help.                                           *
  *                                                                        *
  **************************************************************************/

 #define FALSE 0
 #define TRUE  1

 #include <dos.h>
 #include <bios.h>
 #include <conio.h>
 #include <graphics.h>
 #include <alloc.h>
 #include <stdlib.h>

 extern int bkcolor, cc, maxx, maxy;
 extern int *first, *second;
 unsigned scr_size[2];
 void *scr_buffer[2];

 int paint_help(void)
 {
         union {
                 int i;
                 unsigned char c[2];
         } key;

         struct textsettingstype oldtext;

         register int i = 10;
         int title_x, title_y, title_color = YELLOW;
         int hite, wide, max_i;
         int ret_flag = 0;
     int timer = 999;
     void *text_buf;

         /* we are going to change the text style */


     gettextsettings(&oldtext);
         setusercharsize(1, 1, 7, 8);
         settextstyle(SMALL_FONT, HORIZ_DIR, USER_CHAR_SIZE);
         hite = textheight("H");
         wide = textwidth("H");

     text_buf = malloc(640 * (unsigned)hite);

         /* save the image  */

         scr_size[0] = imagesize(0, 0, maxx, ((maxy+1)/2)-1);
     scr_buffer[0] = malloc(scr_size[0]);
     if(scr_buffer[0] == NULL) {
                 free(scr_buffer[0]);
             return TRUE;
         }
         getimage(0, 0, maxx, ((maxy+1)/2)-1, scr_buffer[0]);

         scr_size[1] = imagesize(0, (maxy+1)/2, maxx, maxy);
     scr_buffer[1] = malloc(scr_size[1]);
     if(scr_buffer[1] == NULL) {
                 free(scr_buffer[0]);
                 free(scr_buffer[1]);
                 return TRUE;
         }
         getimage(0, (maxy+1)/2, maxx, maxy, scr_buffer[1]);

         setbkcolor(BLACK);
         setcolor(YELLOW);
         clearviewport();

         outtextxy((maxx/2)+30, 30+(1 *hite), "*******************************
         outtextxy((maxx/2)+30, 30+(2 *hite), "*                             *
         outtextxy((maxx/2)+30, 30+(3 *hite), "*                             *
         title_x = (maxx/2)+29+(7*wide);
         title_y = 30+(3*hite);
         outtextxy((maxx/2)+30, 30+(4 *hite), "*                             *
         outtextxy((maxx/2)+30, 30+(5 *hite), "*                             *
         outtextxy((maxx/2)+30, 30+(6 *hite), "*                             *
         outtextxy((maxx/2)+30, 30+(7 *hite), "*        by J. Hudson         *
         outtextxy((maxx/2)+30, 30+(8 *hite), "*                             *
         outtextxy((maxx/2)+30, 30+(9 *hite), "*            1988             *
         outtextxy((maxx/2)+30, 30+(10*hite), "*                             *
         outtextxy((maxx/2)+30, 30+(11*hite), "*******************************


         outtextxy(5, i, "F1, F2, F3, F4 - Set step increment to 1, 5, 10, 20"
         i += hite;
         outtextxy(5, i, "F5  - Change background color");
         i += hite;
         outtextxy(5, i, "F6  - Save the previously saved icon to a file");
         i += hite;
         outtextxy(5, i, "F7  - Read the icon file (use 'K' to display it)");
         i += hite;
         outtextxy(5, i, "F8  - Reset first and second markers");
         i += hite;
         outtextxy(5, i, "F9  - Turn header area on/off");
         i += hite;
         outtextxy(5, i, "F10 - Turn mouse ON/OFF");
         i += hite;
         outtextxy(5, i, "F11 - Change fill pattern");
         i += hite;
         outtextxy(5, i, "F12 - Change line width");
         i += hite;
         outtextxy(5, i, "1   - Set color number to 1  - ");
         setcolor(1);
         outtextxy((29 * wide) + 6, i, "BLUE");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "2   - Set color number to 2  - ");
         setcolor(2);
         outtextxy((29 * wide) + 6, i, "GREEN");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "3   - Set color number to 3  - ");
         setcolor(3);
         outtextxy((29 * wide) + 6, i, "CYAN");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "4   - Set color number to 4  - ");
         setcolor(4);
         outtextxy((29 * wide) + 6, i, "RED");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "5   - Set color number to 5  - ");
         setcolor(5);
         outtextxy((29 * wide) + 6, i, "MAGENTA");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "6   - Set color number to 6  - ");
         setcolor(6);
         outtextxy((29 * wide) + 6, i, "BROWN");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "7   - Set color number to 7  - ");
         setcolor(7);
         outtextxy((29 * wide) + 6, i, "LIGHT GRAY");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "8   - Set color number to 8  - ");
         setcolor(8);
         outtextxy((29 * wide) + 6, i, "DARK GRAY");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "9   - Set color number to 9  - ");
         setcolor(9);
         outtextxy((29 * wide) + 6, i, "LIGHT BLUE");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "0   - Set color number to 10 - ");
         setcolor(10);
         outtextxy((29 * wide) + 6, i, "LIGHT GREEN");
         setcolor(YELLOW);
         i += hite;
         outtextxy(8, i, "!   - Set color number to 11 - ");
         setcolor(11);
         outtextxy((29 * wide) + 6, i, "LIGHT CYAN");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "@   - Set color number to 12 - ");
         setcolor(12);
         outtextxy((29 * wide) + 6, i, "LIGHT RED");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "#   - Set color number to 13 - ");
         setcolor(13);
         outtextxy((29 * wide) + 6, i, "LIGHT MAGENTA");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "$   - Set color number to 14 - ");
         setcolor(14);
         outtextxy((29 * wide) + 6, i, "YELLOW");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "%   - Set color number to 15 - ");
         setcolor(15);
         outtextxy((29 * wide) + 6, i, "WHITE");
         setcolor(YELLOW);
         i += hite;
         outtextxy(5, i, "B   - Draw box around marked points");
         i += hite;
         outtextxy(5, i, "C   - Draw a circle, first point is the center, seco
         i += hite;
         outtextxy(5, i, "D   - Delete a marked area");
         i += hite;
         outtextxy(5, i, "E   - Draw ellipse");
         i += hite;
 /*        outtextxy(5, i, "F   - ");
         i += hite;
 */        outtextxy(5, i, "G   - Turn grid ON/OFF");
         i += hite;
 /*        outtextxy(5, i, "H   - ");
         i += hite;
 */        outtextxy(5, i, "J   - Save an image to memory");
         i += hite;
         outtextxy(5, i, "K   - Restore the saved image from memory");
         i += hite;
         outtextxy(5, i, "L   - Draw a line between points");
         i += hite;
         outtextxy(5, i, "M   - Move an area");
         i += hite;
         outtextxy(5, i, "N   - New color for an area");
         i += hite;
         outtextxy(5, i, "O   - Turn DRAW on/off (Pen up - Pen down)");
         i += hite;
         outtextxy(5, i, "P   - Swap pages");
         i += hite;
         outtextxy(0, i, "^P  - Print Screen");
         i += hite;
         outtextxy(5, i, "Q   - Quit");
         i += hite;
         outtextxy(5, i, "R   - Restore image from a file ");
         i += hite;
         outtextxy(5, i, "S   - Save image to a file");
         i += hite;
         outtextxy(0, i, "^S   - Change the screen scale");
         i += hite;
         outtextxy(5, i, "T   - Enter text");
         i += hite;
         outtextxy(5, i, "V   - Jump to the nearest pixel that matches the dra
         i += hite;
         outtextxy(5, i, "W   - Fill a bounded area (boundry must be same colo
         i += hite;
         outtextxy(5, i, "X   - Copy an area");
         i += hite;
         outtextxy(5, i, "Z   - Clear the screen");
         i += hite;
         outtextxy(5, i, "?   - Print this help screen");
         i += hite;
         outtextxy(0, i, "<CR> - Mark first   ,then second   points");
         putimage(5 + (17*wide), i-2, first, COPY_PUT);
         putimage(5 + (32*wide), i+2, second, COPY_PUT);

         max_i = (i/hite) - 1;

         outtextxy(400, 349-hite, "Hit <ESC> to return");

         settextstyle(TRIPLEX_FONT, HORIZ_DIR, 2);

         i = 0;
         getimage(0, (i*hite)+11, (wide*15)+7, ((i+1)*hite)+11, text_buf);
         putimage(0, (i*hite)+11, text_buf, NOT_PUT);

         while(!ret_flag) {
                 if(bioskey(1)) {
                         key.i = bioskey(0);
                         if(key.c[0] == 0x1b) ret_flag = 1;
                         else {

                 /* only use the keypad --- alais not the mouse  */


                                 if(!key.c[0]) {
                          if(key.c[1] == 72) {                /* up  */
                                                 if(i == 0) getimage(0, (i*hit
                                                 else getimage(0, (i*hite)+11,
                                                 putimage(0, (i*hite)+11, text
                                                 i -= 1;
                                                 if(i < 0) i = 0;
                                                 if(i == 0) getimage(0, (i*hit
                                                 else getimage(0, (i*hite)+11,
                                                 putimage(0, (i*hite)+11, text
                                         }
                          if(key.c[1] == 80) {                /* down  */
                                                 if(i == 0) getimage(0, (i*hit
                                                 else getimage(0, (i*hite)+11,
                                                 putimage(0, (i*hite)+11, text
                                                 i += 1;
                                                 if(i >= max_i) i = max_i;
                                                 getimage(0, (i*hite)+11, (wid
                                                 putimage(0, (i*hite)+11, text
                                         }

                                 }
                         }
                 } else {
                         if(timer != 12000) timer++;
                         else {
                                 if(title_color++ >= MAXCOLORS) title_color =
                                 setcolor(title_color);
                                 outtextxy(title_x, title_y, "P A I N T");
                                 timer = 0;
                         }
                 }
         }
         setbkcolor(bkcolor);
         clearviewport();
         setcolor(cc);
         settextjustify(oldtext.horiz, oldtext.vert);
         settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);

         putimage(0, 0, scr_buffer[0], COPY_PUT);
         putimage(0, (maxy+1)/2, scr_buffer[1], COPY_PUT);
          free(scr_buffer[0]);
         free(scr_buffer[1]);

         return FALSE;
 }



 PLCHECK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\PLCHECK.C

 /*  LCHECK by Richard Conn

 LCHECK displays to the user the nesting level number of each BEGIN/END ({/})
 group, thereby helping him to identify problem areas in his C programs.
 recognizes quoted material and comments and ignores { and } within these.

 08/01/84 - Fixed bug that caused program to treat an \' or \" as a "live"
            quote.  (Therefore, a statement such as "#define QUOTE '\''"
            would screw up the level counter in the program.  Changed version
            number to 1.2A.  (Don McCrady)

 05/16/87 - Conversion from BDS C to portable C.         (William C. Colley, I
 */

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * pair of #defines if you are running AZTEC C:
  */

 /*
 #define getc(f)                agetc(f)
 #define putc(c,f)        aputc(c,f)
 */

 VERS        "2.0"  /* Version Number */

 #include <stdio.h>

 #ifndef FALSE
 #define FALSE        0
 #endif

 #ifndef TRUE
 #define TRUE        (!0)
 #endif

 #ifndef EOF
 #define EOF        -1
 #endif

 TWIDTH        80        /* Terminal width = 80 chars */
 #define YES        'Y'
 #define NO        'N'
 ovfl        YES        /* Line Overflow */
 noovfl        NO        /* No Line Overflow */

 FILE *iobuf;
 int level = 0, chval, pos, nroutines = 0;

 int main(argc,argv)
 int argc;
 char **argv;
 {
     int done;
     void getit(), prlevel();

     if (argc == 1) {
         printf("LCHECK, Version %s\n",VERS);
         printf("Format of Command Line is --\n");
         printf("  LCHECK filename.typ");
         return TRUE;
         }
     if (!(iobuf = fopen(argv[1],"r"))) {
         printf("Cannot Find File %s\n",argv[1]);
         return TRUE;
         }
     printf("LCHECK, Version %s -- File:  %s\n",VERS,argv[1]);
     prlevel();        /* Print level number */
     do {
         getit();    /* Get next char */
         if (chval == '\'') do { /* If single quote, flush to end quote */
                 getit();
                 if (chval == '\\') {            /* check for \'  */
                     getit();
                     if (chval == '\'')            /* Ignore it and */
                         getit();            /* get next char */
                 }
             } while (chval != '\'');
         if (chval == '"') do {        /* If double quote, flush to end quote
                 getit();
                 if (chval == '\\') {            /* check for \" */
                     getit();
                     if (chval == '"')        /* Ignore it and */
                         getit();            /* get next char */
                 }
             } while (chval != '"');
         if (chval == '/') {            /* Possible comment */
             getit();
             if (chval == '*') {            /* Yes, it is a comment */
                 getit();
                 done = FALSE;
                 do {
                     if (chval == '*') {            /* End comment? */
                         getit();
                         if (chval == '/')   /* Yes */
                             done = TRUE;
                         }
                     else getit();
                 } while (!done);
                 }
             }
         if (chval == '{') level++;  /* BEGIN */
         if (chval == '}') {            /* END */
             level--;
             if (level == 0) {
                 nroutines++;
                 printf("\n** Routine %d **", nroutines);
                 }
             }
     } while (chval != EOF);

     printf("\nProgram Level Check is ");
     if (level == 0) printf("OK");
     else printf("NOT OK");
     printf("\nNumber of Routines Encountered: %d",--nroutines);
     fclose(iobuf);
     return level != 0;
 }

 void getit()  /* Get and Echo Character */
 {
     void echo(), prlevel();

     chval = getc(iobuf);
     if ((pos >= TWIDTH) & (chval != '\n')) prlevel(ovfl);
     if (chval != EOF) echo(chval);
 }

 void echo(chval)  /* Echo Char with tabulation */
 char chval;
 {
     void prlevel();

     switch (chval) {
     case '\t' : putchar(' '); pos++;
                 while (pos%9 != 0) {
                     putchar(' ');
                     pos++;
                     }
                 break;
     case '\b' : putchar('\b');
                 pos--;
                 break;
     case '\n' : prlevel(noovfl);
                 break;
     default  :        if (chval >= ' ') {
                 putchar(chval);
                 pos++;
         }
         break;
     }
 }

 void prlevel(ovfl_flag)         /* Print Level Number and Set Col Count */
 char ovfl_flag;
 {
     putchar('\n');
     if (level < 10) printf(" %d",level);
     else printf("%d",level);
     if (ovfl_flag == YES) putchar('-');
     else putchar(':');
     putchar(' ');  pos = 5;
 }


 PLOT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\PLOT.C

 /* plot.c */
 /* plots coordinates on screen */
 #define HEIGHT 5
 #define WIDTH 10

 main()
 {
 char matrix[HEIGHT][WIDTH];
 int x, y;

    for(y = 0; y < HEIGHT; y++)      /* fill matrix with periods */
       for(x = 0; x < WIDTH; x++)
          matrix[y][x] = '.';
    printf("Enter coordinates in form x,y (4,2).\n");
    printf("Use negative numbers to quit.\n");

    while(x >= 0)  {        /* until neg coordinates */
       for(y = 0; y < HEIGHT; y++) {    /*print matrix*/
          for(x = 0; x < WIDTH; x++)
             printf("%c ", matrix[y][x]);
          printf("\n\n");
       }
       printf("Coordinates: ");
       scanf("%d,%d", &x, &y);    /* get coordinates */
       if (x > 9 || y > 4) {
          printf("\n\nLimits: x = 9, y = 4");
          break;
       }
       matrix[y][x] = '\xb0';     /* put gray box there */
    }
 }



 PLOTXY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\PLOTXY.C

 /**********************************************************************
 PLOTXY
 Description - plotxy(x coordinate, y coordinate)
 **********************************************************************
 Function - plots a character at a given coordinate
 Input - integer plot routine
 Output - just to the screen
 #includes - none
 #defines  - none
 Routines Called - needs desmet c functions scr_rowcol and scr_co
 Notes - does error check--change as screen size changes; specify char
   to print
 **********************************************************************/

 plotxy(x,y)
 int x,y;
 {
   if(x<80 && x>-1 && y<24 && y>-1);  /* catch screen plot error */
     {
      scr_rowcol(y,x); /* desmet pc instruction - position cursor */
      scr_co('.');  /* desmet pc instruction - print on screen */
     }
   return;
 }

 /******************** end of function ********************************/


 POINTER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\POINTER.C

                                          /* Chapter 8 - Program 1 */
 main()                             /* illustration of pointer use */
 {
 int index,*pt1,*pt2;

    index = 39;                             /* any numerical value */
    pt1 = &index;                          /* the address of index */
    pt2 = pt1;
    printf("The value is %d %d %d\n",index,*pt1,*pt2);
    *pt1 = 13;                  /* this changes the value of index */
    printf("The value is %d %d %d\n",index,*pt1,*pt2);
 }


 POINTER2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\POINTER2.C

                                          /* Chapter 8 - Program 2 */
 main()
 {
 char strg[40],*there,one,two;
 int *pt,list[100],index;

    strcpy(strg,"This is a character string.");

    one = strg[0];                    /* one and two are identical */
    two = *strg;
    printf("The first output is %c %c\n",one,two);

    one = strg[8];                   /* one and two are indentical */
    two = *(strg+8);
    printf("the second output is %c %c\n",one,two);

    there = strg+10;           /* strg+10 is identical to strg[10] */
    printf("The third output is %c\n",strg[10]);
    printf("The fourth output is %c\n",*there);

    for (index = 0;index < 100;index++)
       list[index] = index + 100;
    pt = list + 27;
    printf("The fifth output is %d\n",list[27]);
    printf("The sixth output is %d\n",*pt);
 }


 PONG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\PONG.C

 /*              Pong Game Main Program
  */

 /* Copying modes for rect: */

 #define COPY 0
 #define XOR 1
 #define BITSET 2
 #define BITCLEAR 3
 #define blankPattern 0

 /* Gray pattern for the wall: */
 wallPattern[] = {
     0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555,
     0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555
 };

 /* Diamond pattern for the ball: */
 ballPattern[] = {
     0x0180, 0x03C0, 0x07E0, 0x0FF0, 0x1FF8, 0x3FFC, 0x7FFE, 0xFFFF,
     0xFFFF, 0x7FFE, 0x3FFC, 0x1FF8, 0x0FF0, 0x07E0, 0x03C0, 0x0180
 };

 #define FALSE 0
 #define TRUE 1

 /*      main()

         Function: Play pong. Simulate a ball moving around the display and
         bouncing off the walls and paddle. If the users hits the up or
         down arrow keys, move the paddle.

         Algorithm: Initialize the display and draw the walls, paddle, and
         ball. Then iterate checking the keyboard for up/down arrow hits,
         and simulating the moving ball.
 */

 main()

 {
         int ballX, ballY;       /* Current location of ball. */
         int newX, newY;         /* Next ball location. */
         int ballXV, ballYV;     /* Current velocity of ball. */
         int padHeight;          /* Paddle height. */
         int padY;               /* Current paddle location. */
         int ch;                 /* Input character from user. */
         int goodHits;           /* Number of successfull rebounds. */

         /* Set the display to graphics mode. */
         setMod(6);

         /* Set the initial positions and velocities of everything. */
         ballX = 431;
         ballY = 97;
         ballXV = ballYV = 1;
         padHeight = 60;
         padY = 10;
         goodHits = 0;

         /* Draw the wall, paddle, and ball. */
         rect(0,0,640,200,blankPattern,1,COPY);          /* Clear screen. */
         rect(0,0,640,10,wallPattern,1,COPY);            /* Top wall. */
         rect(0,190,640,200,wallPattern,1,COPY);         /* Bottom wall. */
         rect(630,10,640,190,wallPattern,1,COPY);        /* Right wall. */
         rect(10,padY,20,padY+padHeight,0,1,XOR);        /* Paddle. */
         rect(ballX,ballY,ballX+16,ballY+16,ballPattern,0,XOR); /* Ball. */

         /* Loop, simulating movement and waiting for commands from the user.
         while (TRUE) {
                 /* Check if there's a keypress waiting. */
                 if (keyChk(&ch)) {
                         /* If so, read it from the keystroke queue. */
                         keyRd();
                         /* If it was an ESC, exit the main loop. */
                         if ((ch & 0xFF) == 0x1B) break;
                         /* If it was an extended key, switch on that key. */
                         if ((ch & 0xFF) == 0)
                                 switch ((ch>>8) & 0xFF) {
                                         /* Up arrow: move paddle up. */
                                         case 72:
                                                 /* Check for at top. */
                                                 if (padY <= 20) break;
                                                 /* Draw new paddle. */
                                                 rect(10,padY-20,20,
                                                      padY+padHeight-20,0,1,1)
                                                 /* Erase old paddle. */
                                                 rect(10,padY,20,
                                                      padY+padHeight,0,1,1);
                                                 /* Update position. */
                                                 padY -= 20;
                                                 break;
                                         /* Down arrow: move paddle down. */
                                         case 80:
                                                 /* Check for at bottom. */
                                                 if ((padY+padHeight) >= 180)
                                                         break;
                                                 /* Draw new paddle. */
                                                 rect(10,padY+20,20,
                                                      padY+padHeight+20,0,1,1)
                                                 /* Erase old paddle. */
                                                 rect(10,padY,20,
                                                      padY+padHeight,0,1,1);
                                                 /* Update position. */
                                                 padY += 20;
                                                 break;
                                 };
                 };
                 /* If the ball is still on the display... */
                 if (ballX > -16) {
                         /* Compute where the ball will go next. */
                         newX = ballX+ballXV;
                         newY = ballY+ballYV;
                         /* Check and adjust for running into top or bottom. *
                         if ((newY < 10) || (newY > 174)) {
                                 ballYV = -ballYV;
                                 newY = ballY+ballYV;
                         };
                         /* Check and adjust for running into the right wall.
                         if (newX > 614) {
                                 ballXV = -ballXV;
                                 newX = ballX+ballXV;
                         /* Check and adjust for running into the paddle. */
                         } else if ((padY <= (ballY+15)) &&
                                    ((padY+padHeight) >= ballY) &&
                                    (ballX >= 20) &&
                                    (newX < 20)) {
                                 /* Reverse direction. */
                                 ballXV = -ballXV;
                                 newX = ballX+ballXV;
                                 /* Check for edge of paddle hit. */
                                 if (ballY < padY) {
                                         if (--ballYV == 0) ballYV--;
                                 } else if ((ballY+15) > (padY+padHeight)) {
                                         if (++ballYV == 0) ballYV++;
                                 };
                                 /* If he's gotten five, speed it up. */
                                 if (((++goodHits) % 5) == 0) {
                                         if (ballXV > 0) ballXV++;
                                         else ballXV--;
                                         if (ballYV > 0) ballYV++;
                                         else ballYV--;
                                 };
                         };
                         /* Draw the new ball. */
                         rect(newX,newY,newX+16,newY+16,ballPattern,0,XOR);
                         /* Erase the old ball. */
                         rect(ballX,ballY,ballX+16,ballY+16,ballPattern,0,XOR)
                         /* Update the ball position. */
                         ballX = newX; ballY = newY;
                 /* Otherwise, the ball is off the screen -- he missed. */
                 } else {
                         /* Put the ball ack on the screen, and reset hits. */
                         ballX = 431;
                         ballY = 97;
                         ballXV = ballYV = 1;
                         goodHits = 0;
                         /* Draw the ball. */
                         rect(ballX,ballY,ballX+16,ballY+16,ballPattern,0,1);
                 };
         };

         /* Reset the display mode to text. */
         setMod(2);
 }



 POPUP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\WNDWBOSS\POPUP.C

 /*
 ** POPUP - Popup Menu/Window Driver
 **
 ** Copyright (C) 1985 - Philip A. Mongelluzzo
 ** All rights reserved.
 **
 */

 "windows.h"                    /* window header */

 UARROW  0x48                    /* define scan codes */
 #define DARROW  0x50
 #define LARROW  0x4b
 #define RARROW  0x4d
 #define BS      0x0e
 #define DEL     0x53
 #define RET     0x1c
 #define ESC     0x01
 #define SPACE   0x39

 #define TRUE    1
 #define FALSE   0

 /*
 ** Popup structure templates
 */

   struct mitem {                        /* menu item template */
     int r;                              /* row */
     int c;                              /* col */
     char *t;                            /* text */
     int rv;                             /* return value */
   };

   struct pmenu {                        /* popup menu structure */
     int fm;                             /* first menu item index */
     int lm;                             /* last menu item index */
     struct mitem scrn[25];              /* a bunch of menu items */
   };

 /*
 *********
 * popup *
 *********
 */

 popup(page,row,col,width,height,atrib,batrib,mx,cflag)
 int page;                               /* video page */
 int row, col;                           /* window - upper row/col */
 int width, height;                      /* window - height & width */
 struct pmenu *mx;                       /* pointer to popup menu struct */
 int cflag;                              /* close on return strike flag */
 int atrib, batrib;                      /* attributes - window & border */
 {
 int i;                                  /* scratch integer */
 WINDOWPTR w;                            /* window pointer */
 static WINDOWPTR wpsave;                /* a place to remember it */
 int c;                                  /* key scan code,,char */
 static winopn = FALSE;                  /* window currently open flag */
 static lndx = 0;                        /* last open window item index */

   if(winopn) {                          /* window is still open */
     goto d0;                            /* enter processing loop */
   }
   lndx = -1;                            /* set index out of range */
   w = wn_open(page, row, col, width, height, atrib, batrib);
   wn_sync(w,TRUE);                      /* sync cursor */
   wpsave = w;                           /* save pointer */
   if (w == NULL) return(99);            /* out of mem or just fubar */
   winopn = TRUE;                        /* say window is open */

   i = 0;                                /* init index */
   while(mx->scrn[i].r) {                /* for as long as we have data */
     wn_puts(w, mx->scrn[i].r, mx->scrn[i].c, mx->scrn[i].t);
     i++;
   }

 d0:
   w = wpsave;                           /* restore pointer */
   i = lndx;                             /* BLINDLY assume that we're back */
   if(i < mx->fm) i = mx->fm;            /* and reset if "i" is now out of */
   if(i > mx->lm) i = mx->fm;            /* range - (dumb, but it works) */
   while(TRUE) {                         /* till we exit */
     wn_locate(w, mx->scrn[i].r, mx->scrn[i].c);
     c = v_getch() >> 8;                 /* see whats goin' on */
     if(c == ESC) break;                 /* ESC (user wants out) - swk */
     if(c == RET) {                      /* swk RETURN */
       if(cflag) {                       /* close window on return strike ? */
         wn_close(w);                    /* close the window */
         winopn = FALSE;                 /* say window is closed */
       }
       lndx = i;                         /* remember last indx */
       return(mx->scrn[i].rv);           /* return with rv */
     }
     if(c == DARROW) c = SPACE;          /* swk conversion */
     if(c == RARROW) c = SPACE;          /* swk conversion */
     if(c == LARROW) c = BS;             /* swk conversion */
     if(c == UARROW) c = BS;             /* swk conversion */
     if(c == SPACE || c == DEL || c == BS) {
       if(c == SPACE)                    /* foreward ?? */
         i++;                            /* bump index */
       else
         i--;                            /* decrement */
       if(i < mx->fm) i = mx->lm;        /* wrap on either */
       if(i > mx->lm) i = mx->fm;        /* end */
     }                                   /* endif */
   }                                     /* end while */
   wn_close(w);                          /* bye bye */
   winopn = FALSE;                       /* say window is closed */
   return(99);                           /* nothing selected */
 }

 #ifdef COMMENTS
 /*
 **********                              /* quick popup... */
 * qpopup *                              /* this is a hack of popup */
 **********                              /* but the code fragment */
 */                                      /* could be of value */
 #endif

 WINDOWPTR qpopup(page,row,col,width,height,atrib,batrib,mx)
 int page;                               /* video page */
 int row, col;                           /* window - upper row/col */
 int width, height;                      /* window - height & width */
 int atrib, batrib;                      /* atributes - window & border */
 struct pmenu *mx;                       /* pointer to text struct */
 {
 int i;                                  /* scratch integer */
 WINDOWPTR w;                            /* window pointer */

   w = wn_open(page, row, col, width, height, atrib, batrib);

   i = 0;                                /* init index */
   while(mx->scrn[i].r) {                /* for as long as we have data */
     wn_puts(w, mx->scrn[i].r, mx->scrn[i].c, mx->scrn[i].t);
     i++;
   }
   return(w);
 }

 /* End */


 POW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\POW.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/

 #include "math.h"
 #include "errno.h"

 double pow(a,b)
 double a,b;
 {
         double loga;
         extern int errno;

         if (a<=0.0) {
                 if (a<0.0 || a==0.0 && b<=0.0) {
                         errno = EDOM;
                         return -HUGE;
                 }
                 else return 0.0;
         }
         loga = log(a);
         loga *= b;
         if (loga > LOGHUGE) {
                 errno = ERANGE;
                 return HUGE;
         }
         if (loga < LOGTINY) {
                 errno = ERANGE;
                 return 0.0;
         }
         return exp(loga);
 }



 POW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\POW.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithm given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 84-124.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define reduce(v) ldexp(fint(ldexp(v,4)),-4)
 #define K          0.44269504088896340736

 #define P1        0.8333333333412136e-1
 #define P2        0.1249999796500608e-1
 #define P3        0.2233824352815418e-2
 #define P(a)        (((P3*a+P2)*a+P1)*a)

 #define Q1        0.693147180559937815e0
 #define Q2        0.240226506956777522e0
 #define Q3        0.555041084247568661e-1
 #define Q4        0.961811769138724104e-2
 #define Q5        0.133308101134082075e-2
 #define Q6        0.150774061788142382e-3
 #define Q(a)        ((((((Q6*a+Q5)*a+Q4)*a+Q3)*a+Q2)*a+Q1)*a)

 /*\p--------------------------------------------------------------------*/

 LOCAL double A1[17] =                /* Converted from octal tables        */
 {        1.0,                        /* in reference above by reading*/
         9.576032806985708e-01,        /* octal values to 45B, and        */
         9.170040432046704e-01,        /* converting to decimal to give*/
         8.781260801866466e-01,        /* A1.  Then this decimal string*/
         8.408964152537131e-01,        /* was converted back to octal.
         8.052451659746254e-01,        /* Error in this cycle was        */
         7.711054127039674e-01,        /* added into the converted        */
         7.384130729697489e-01,        /* octal value of the remaining
         7.071067811865461e-01,        /* digits, giving A2.                */
         6.771277734684453e-01,
         6.484197773255040e-01,
         6.209289060367418e-01,
         5.946035575013582e-01,
         5.693943173783431e-01,
         5.452538663326258e-01,
         5.221368912137052e-01,
         5.000000000000000e-01
 };
 LOCAL double A2[8] =
 {        2.847357921552306e-15,
         3.151180748043254e-15,
         1.760954860069324e-15,
         7.597361444532664e-16,
         1.065461039677172e-15,
         2.314569550762763e-16,
         2.736854898096527e-15,
         1.721971773273086e-15
 };
 /*\p*********************************************************************/
         double
 pow(x, y)                /* return power function x^y

 /*----------------------------------------------------------------------*/
 double x, y;
 {
         double c, g, r, xm, u1, u2, v, w, w1, w2, y1, y2, z;
         FAST int iw, p;
         int m;

         if (x <= 0.0)
         {        if (x < 0.0 OR x IS 0.0 AND y <= 0.0)
                 {        errno = EDOM;
                         return -INFINITY;
                 }
                 else return 0.0;
         }
         g = frexp(x, &m);
         xm = m;
         p = 0;        /* The Ai[] tables are indexed one less than in referen
         if (g <= A1[8])
                 p = 8;
         if (g <= A1[p + 4])
                 p = p + 4;
         if (g <= A1[p + 2])
                 p = p + 2;
         c = A1[++p];        /* p is now correct, index one less than ref.
         z = ((g - c) - A2[p / 2]) / (ldexp(g, -1) + ldexp(c, -1));
         v = z * z;
         r = P(v) * z;
         r += K * r;
         u2 = (r + z * K) + z;
         u1 = ldexp(ldexp(xm, 4) - p, -4);
         y2 = y - (y1 = reduce(y));
         w1 = reduce(w = u2 * y + u1 * y2);
         w2 = w - w1;
         w1 = reduce(w = w1 + u1 * y1);
         w2 += (w - w1);
         iw = (int) ldexp(w1 + (w = reduce(w2)), 4);
         w2 -= w;
         if (iw > BIGX)
         {        errno = ERANGE;
                 return INFINITY;
         }
         if (iw < SMALLX)
         {        errno = ERANGE;
                 return 0.0;
         }
         if (w2 > 0)
         {        iw++;
                 w2 -= 0.0625;
         }
         m = iw / 16 + (iw < 0 ? 0 : 1);
         p = 16 * m - iw;
         z = Q(w2);
         return ldexp(A1[p] + A1[p] * z, m); /* indices one less than ref. */
 }


 PREP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGAPAINT\PREP.C

 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <bios.h>
 #include <process.h>
 #include <io.h>

 #define LENGTH 80

 FILE *infile;
 FILE *outfile;

 void main(int argc, char *argv[])
 {

     register int i, count = 0;
     int flag = 1;

     char c;
     char tmp_file[LENGTH], *temptr;
     char src_file[LENGTH], *srcptr;
     char bak_file[LENGTH], *bakptr;

     if(argc != 2) {
         printf("\nUsage: prep <argv[1]>\n");
         exit(0);
     }
     strcpy(src_file, argv[1]);            /* copy the filename  */
     temptr = tmp_file;                    /* point to the files */
     srcptr = src_file;
     bakptr = bak_file;
     while(*srcptr) {                    /* copy the name til a . appears */
         if(*srcptr == '.') break;        /*   or we run out of stuff      */
         *bakptr++ = *srcptr;
         *temptr++ = *srcptr++;
     }
     strcpy(temptr, ".$$$");                /* fill in the file types        *
     strcpy(bakptr, ".BAK");
     if((infile = fopen(src_file, "r")) == NULL) {
         printf("\nCannot open file: %s\n", src_file);
         exit(0);
     }
     if((outfile = fopen(tmp_file, "w")) == NULL) {
         printf("\nCannot open file: %s\n", tmp_file);
         exit(0);
     }
     while(flag) {                        /* copy characters until End-Of-File
         c = fgetc(infile);
         if(c == EOF) flag = 0;
         if(c != '\t') {
                         fputc(c, outfile); /* expand the tab */
                         count++;
                 }
         else {
                         i = 4 - (count % 4);
                         while(i--) {
                                 fputc(' ', outfile);
                                 count++;
                         }
                 }
                 if(c == '\n')  count = 0;
     }
     fcloseall();
     unlink(bak_file);                    /* delete any previous .BAK files */
     rename(src_file, bak_file);            /* rename the files */
     rename(tmp_file, src_file);

 }


 PREPROC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\PREPROC.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 FILE            *inclfile[10];
 int             incldepth = 0;
 int             inclline[10];
 char            *lptr;

 preprocess()
 {       ++lptr;
         lastch = ' ';
         getsym();               /* get first word on line */
         if( lastst != id ) {
                 error(ERR_PREPROC);
                 return getline(incldepth == 0);
                 }
         if( strcmp(lastid,"include") == 0 )
                 return doinclude();
         else if( strcmp(lastid,"define") == 0 )
                 return dodefine();
         else    {
                 error(ERR_PREPROC);
                 return getline(incldepth == 0);
                 }
 }

 doinclude()
 {       int     rv;
         getsym();               /* get file to include */
         if( lastst != sconst ) {
                 error(ERR_INCLFILE);
                 return getline(incldepth == 0);
                 }
         inclline[incldepth] = lineno;
         inclfile[incldepth++] = input;  /* push current input file */
         input = fopen(laststr,"r");
         if( input == 0 ) {
                 input = inclfile[--incldepth];
                 error(ERR_CANTOPEN);
                 rv = getline(incldepth == 0);
                 }
         else    {
                 rv = getline(incldepth == 1);
                 lineno = -32768;        /* dont list include files */
                 }
         return rv;
 }

 dodefine()
 {       SYM     *sp;
         getsym();               /* get past #define */
         if( lastst != id ) {
                 error(ERR_DEFINE);
                 return getline(incldepth == 0);
                 }
         ++global_flag;          /* always do #define as globals */
         sp = xalloc(sizeof(SYM));
         sp->name = litlate(lastid);
         sp->value.s = litlate(lptr);
         insert(sp,&defsyms);
         --global_flag;
         return getline(incldepth == 0);
 }



 PRINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\PRINT.C

 /* ---------------------------------------------------        */
 /*        PRINT - Print a file with header to the printer */
 /*                M. Burton        04 July 1983                */
 /*        Written in Computer Innovations C86                */
 /* ---------------------------------------------------        */
 /*                Syntax:                                 */
 /*                                                        */
 /*        PRINT filename.typ - Print a file with line        */
 /*                                numbers.                */
 /*        PRINT filename.typ /N - Print a file without        */
 /*                                line numbers.                */
 /* ---------------------------------------------------        */

 #include "stdio.h"

 struct regval                /* Register structure for INT        */
 {
         int ax,bx,cx,dx,si,di,ds,es;
 }
 struct regval srv, rrv, trv, brv;
 int mo, dy, yr;
 int hr, mn, sc, hn;

 main(argc,argv)
         int argc;        /* Number of args in cmd line        */
         char *argv[];        /* Args in cmd line                */
 {
         int *fd;        /* File stream pointer                */
         int *cd;        /* Printer stream pointer        */
         char *sp;        /* filename.typ pointer         */
         int c;                /* Loop variable                */
         int lineno=1;        /* Line counter                 */
         int pline=1;        /* Line on page counter         */
         int page=1;        /* Page counter                 */
         char s[232];        /* Line buffer                        */

         srv.ax = (0x2c << 8);
         sysint(0x21,&srv,&brv); /* Get the time         */

         if (argc == 1)
         {
                 printf("Proper syntax: PRINT filename.typ </N>\007\n");
                 goto abort;
         }

         sp = argv[1];
         while ((*sp = toupper(*sp)) != EOS) sp++;
         fd = fopen(argv[1],"r");
         if (fd == 0)
         {
                 printf("%s not found\007\n",argv[1]);
                 goto abort;
         }

         cd = fopen("PRN:","w");
         if (cd == 0)
         {
                 printf("Printer offline\007\n");
                 goto abort;
         }

         c = 1;
         prthdr(page,cd,argv[1]);
         while (c != EOS)
         {
                 pline = 1;
                 while (pline < 57)
                 {
                         c = fgets(s,232,fd);
                         if (c == EOS) goto quit;
                         if (argc == 3)
                         {
                                 if (strncmp(argv[2],"/n",2) == 0 || strncmp(a
                                 {
                                         fprintf(cd,"%s",s);
                                 }
                         }
                         else
                         {
                                 fprintf(cd,"%7u  %s",lineno,s);
                         }
                         lineno++;
                         pline++;
                 }
                 page++;
                 fprintf(cd,"\n\014");
                 prthdr(page,cd,argv[1]);
         }
 quit:
         fprintf(cd,"  \n\014");
         srv.ax = (0x2c << 8);
         sysint(0x21,&srv,&trv);         /* Get end time */
         hr = (trv.cx >> 8) - (brv.cx >> 8);
         if((mn = (trv.cx & 0xff) - (brv.cx & 0xff)) < 0)
         {
                 hr--;
                 mn = mn + 60;
         }
         if((sc = (trv.dx >> 8) - (brv.dx >> 8)) < 0)
         {
                 mn--;
                 sc = sc + 60;
                 if (mn < 0)
                 {
                         hr--;
                         mn = mn + 60;
                 }
         }
         printf("Finished printing '%s';",argv[1]);
         printf("%5u lines,%5u pages.\n",--lineno,page);
         printf("Total print time %02u:%02u:%02u\n",hr,mn,sc);
         fclose(fd);
         fclose(cd);
 abort:        ;                /* Dummy line                        */
 }

 prthdr(p,cc,aa)         /* Print the page header        */
         int p, cc, *aa;
 {
         srv.ax = (0x2a << 8);
         sysint(0x21,&srv,&rrv);
         mo = (rrv.dx >> 8);
         dy = (rrv.dx & 0xff);
         yr = rrv.cx;
         srv.ax = (0x2c << 8);
         sysint(0x21,&srv,&trv);
         hr = (trv.cx >> 8);
         mn = (trv.cx & 0xff);
         sc = (trv.dx >> 8);
         hn = (trv.dx & 0xff);
         fprintf(cc,"Listing of %s     %02u-%02u-%4u     %02u:%02u:%02u.%02u
 }


 PRINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\PRINT.C


 /* ---------------------------------------------------        */
 /*        PRINT - Print a file with header to the printer        */
 /*                M. Burton        04 July 1983                */
 /*        Written in Computer Innovations C86                */
 /* ---------------------------------------------------        */
 /*                Syntax:                                        */
 /*                                                        */
 /*        PRINT filename.typ - Print a file with line        */
 /*                                numbers.                */
 /*        PRINT filename.typ /N - Print a file without        */
 /*                                line numbers.                */
 /* ---------------------------------------------------        */

 #include "stdio.h"

 struct regval                /* Register structure for INT        */
 {
         int ax,bx,cx,dx,si,di,ds,es;
 }
 struct regval srv, rrv, trv, brv;
 int mo, dy, yr;
 int hr, mn, sc, hn;

 main(argc,argv)
         int argc;        /* Number of args in cmd line        */
         char *argv[];        /* Args in cmd line                */
 {
         int *fd;        /* File stream pointer                */
         int *cd;        /* Printer stream pointer        */
         char *sp;        /* filename.typ pointer                */
         int c;                /* Loop variable                */
         int lineno=1;        /* Line counter                        */
         int pline=1;        /* Line on page counter                */
         int page=1;        /* Page counter                        */
         char s[232];        /* Line buffer                        */

         srv.ax = (0x2c << 8);
         sysint(0x21,&srv,&brv); /* Get the time                */

         if (argc == 1)
         {
                 printf("Proper syntax: PRINT filename.typ </N>\007\n");
                 goto abort;
         }

         sp = argv[1];
         while ((*sp = toupper(*sp)) != EOS) sp++;
         fd = fopen(argv[1],"r");
         if (fd == 0)
         {
                 printf("%s not found\007\n",argv[1]);
                 goto abort;
         }

         cd = fopen("PRN:","w");
         if (cd == 0)
         {
                 printf("Printer offline\007\n");
                 goto abort;
         }

         c = 1;
         prthdr(page,cd,argv[1]);
         while (c != EOS)
         {
                 pline = 1;
                 while (pline < 57)
                 {
                         c = fgets(s,232,fd);
                         if (c == EOS) goto quit;
                         if (argc == 3)
                         {
                                 if (strncmp(argv[2],"/n",2) == 0 || strncmp(a
                                 {
                                         fprintf(cd,"%s",s);
                                 }
                         }
                         else
                         {
                                 fprintf(cd,"%7u  %s",lineno,s);
                         }
                         lineno++;
                         pline++;
                 }
                 page++;
                 fprintf(cd,"\n\014");
                 prthdr(page,cd,argv[1]);
         }
 quit:
         fprintf(cd,"  \n\014");
         srv.ax = (0x2c << 8);
         sysint(0x21,&srv,&trv);                /* Get end time        */
         hr = (trv.cx >> 8) - (brv.cx >> 8);
         if((mn = (trv.cx & 0xff) - (brv.cx & 0xff)) < 0)
         {
                 hr--;
                 mn = mn + 60;
         }
         if((sc = (trv.dx >> 8) - (brv.dx >> 8)) < 0)
         {
                 mn--;
                 sc = sc + 60;
                 if (mn < 0)
                 {
                         hr--;
                         mn = mn + 60;
                 }
         }
         printf("Finished printing '%s';",argv[1]);
         printf("%5u lines,%5u pages.\n",--lineno,page);
         printf("Total print time %02u:%02u:%02u\n",hr,mn,sc);
         fclose(fd);
         fclose(cd);
 abort:        ;                /* Dummy line                        */
 }

 prthdr(p,cc,aa)                /* Print the page header        */
         int p, cc, *aa;
 {
         srv.ax = (0x2a << 8);
         sysint(0x21,&srv,&rrv);
         mo = (rrv.dx >> 8);
         dy = (rrv.dx & 0xff);
         yr = rrv.cx;
         srv.ax = (0x2c << 8);
         sysint(0x21,&srv,&trv);
         hr = (trv.cx >> 8);
         mn = (trv.cx & 0xff);
         sc = (trv.dx >> 8);
         hn = (trv.dx & 0xff);
         fprintf(cc,"Listing of %s     %02u-%02u-%4u     %02u:%02u:%02u.%02u
 }


 PRINTDAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\PRINTDAT.C

                                         /* Chapter 10 - Program 8 */
 #include "stdio.h"

 main()
 {
 FILE *funny,*printer;
 char c;

    funny = fopen("TENLINES.TXT","r"); /* open input file     */
    printer = fopen("PRN","w");        /* open printer file   */

    do {
       c = getc(funny);    /* get one character from the file */
       if (c != EOF) {
          putchar(c);      /* display it on the monitor       */
          putc(c,printer); /* print the character             */
       }
    } while (c != EOF);    /* repeat until EOF (end of file)  */

    fclose(funny);
    fclose(printer);
 }


 PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\PRINTF.C

 /* 1.2  01-08-86                                                (printf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/

 printf(fmt, args)        /* formatted print to stdout of args.

 /*----------------------------------------------------------------------*/
 STRING fmt;
 unsigned args;
 {
         int _putca();

         return format(_putca, fmt, &args);
 }

 /************************************************************************/
         LOCAL
 _putca(c)                /* Print c on stdout.

 /*----------------------------------------------------------------------*/
 {
         return putchar(c);
 }


 PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\PRINTF.C

 #include <stdio.h>
 #include <ctype.h>

 _printf(op, put, fmt, args)
 char *op;
 unsigned int (*put)();
 register unsigned char *fmt;
 register unsigned int *args;
 /*
  *        <fmt> points to a format control string.  <args> pointers to a
  *        list of arguments.  The format string is used to create and output
  *        stream with the arguments.  The <put> function is used to output
  *        each character.  The <op> parameter is given to the <put> function
  *        to specify the output stream.  Calls to <put> are of the form:
  *        "(*put)(c, op);" where <c> is the character to output.  The format
  *        string is composed of characters and format specifications.  The
  *        '%' character introduces a format specifier.  The general form of
  *        a format specifier is:
  *
  *            %[-][ |+][0][<width>|*][.[<precision>|*]][l]{d|i|u|o|x|b|c|s}
  *
  *        The '-' specifies left justification.  The ' ' or '+' specifies
  *        the character which preceeds positive numeric values.  The '0'
  *        specifies that numeric fields will be padded with '0' rather than
  *        ' '.  The <width> field is a numeric value specifying a minimum
  *        field width.  The <precision> field is a numeric value specifying
  *        the maximum number of data characters to display.  If '*' is
  *        specified for the width or the precision, an "int" value is taken
  *        from the argument list and used for that value.  If no width is
  *        specified, the field width varies according to the data width.  If
  *        no precision is specified, all data characters are included in the
  *        data width.  If the data width exceeds the field width, the field
  *        width will expand to allow all data characters to be printed.
  *        Including the 'l' or capitalizing the trailing character specifies
  *        that the associated value is a "long" type.  The trailing character
  *        specifies the format type, as follows:
  *
  *                d        Signed decimal integer
  *                i        same as 'd'
  *                u        Unsigned decimal integer
  *                o        Unsigned octal integer
  *                x        Unsigned hexadecimal integer
  *                b        Unsigned binary integer
  *                c        Character
  *                s        String
  *
  *        If the character following the '%' is not recognized, it is
  *        simply passed along to the output stream, thus "%%" is used to
  *        print a single '%' character.
  */
 {
         register int i, cnt = 0, ljustf, lval;
         int preci, dpoint, width;
         char pad, sign, radix;
         register char *ptmp;
         char tmp[64], *ltoa(), *ultoa();

         while(*fmt) {
                 if(*fmt == '%') {
                         ljustf = FALSE;        /* left justify flag */
                         sign = '\0';        /* sign char & status */
                         pad = ' ';        /* justification padding char */
                         width = -1;        /* min field width */
                         dpoint = FALSE;        /* found decimal point */
                         preci = -1;        /* max data width */
                         radix = 10;        /* number base */
                         ptmp = tmp;        /* pointer to area to print */
                         lval = FALSE;        /* long value flaged */
 fmtnxt:
                         i = 0;
                         while (isdigit(*++fmt))        {
                                 i = (i * 10) + (*fmt - '0');
                                 if (dpoint)
                                         preci = i;
                                 else if (!i && (pad == ' ')) {
                                         pad = '0';
                                         goto fmtnxt;
                                 }
                                 else
                                         width = i;
                         }

                         switch(*fmt) {
                                 case '\0':        /* early EOS */
                                         --fmt;
                                         goto charout;

                                 case '-':        /* left justification */
                                         ljustf = TRUE;
                                         goto fmtnxt;

                                 case ' ':
                                 case '+':        /* leading sign flag */
                                         sign = *fmt;
                                         goto fmtnxt;

                                 case '*':        /* parameter width value */
                                         i = *args++;
                                         if (dpoint)
                                                 preci = i;
                                         else
                                                 width = i;
                                         goto fmtnxt;

                                 case '.':        /* secondary width field */
                                         dpoint = TRUE;
                                         goto fmtnxt;

                                 case 'l':        /* long data */
                                         lval = TRUE;
                                         goto fmtnxt;

                                 case 'd':        /* Signed decimal */
                                 case 'i':
                                         ltoa((long)((lval)
                                                 ?(*((long *) args)++)
                                                 :(*((int  *) args)++)),
                                               ptmp, 10);
                                         goto printit;

                                 case 'b':        /* Unsigned binary */
                                         radix = 2;
                                         goto usproc;

                                 case 'o':        /* Unsigned octal */
                                         radix = 8;
                                         goto usproc;

                                 case 'x':        /* Unsigned hexadecimal */
                                 case 'X':
                                         radix = 16;
                                         /* fall thru */

                                 case 'u':        /* Unsigned decimal */
 usproc:
                                         ultoa((unsigned long)((lval)
                                                 ?(*((unsigned long *) args)++
                                                 :(*((unsigned int  *) args)++
                                               ptmp, radix);
                                         if (*fmt == 'x')
                                                 strlwr(ptmp, ptmp);
                                         goto printit;

                                 case 'c':        /* Character */
                                         ptmp[0] = *args++;
                                         ptmp[1] = '\0';
                                         goto nopad;

                                 case 's':        /* String */
                                         ptmp = *((char **) args)++;
 nopad:
                                         sign = '\0';
                                         pad  = ' ';
 printit:
                                         cnt += _prtfld(op, put, ptmp, ljustf,
                                                        sign, pad, width, prec
                                         break;

                                 default:        /* unknown character */
                                         goto charout;
                         }
                 }
                 else {
 charout:
                         (*put)(*fmt, op);                /* normal char out *
                         ++cnt;
                 }
                 ++fmt;
         }
         return(cnt);
 }


 PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\DISPIO\PRINTF.C

 /*
 **       name         printf -- formatted write to console.
 **
 **       Same as Lattice C printf() function, but much faster.
 */

 printf(cs, args)
 char *cs, *args;
 {
         int i, c, n;
         char *p, **na, *_pfmt();
         char work[256];

         na =  &args;           /* point to first arg */
         while (*cs)
         {
                 c = *cs++;
                 if (c == '%')
                         if (*cs == '%')
                         {
                                 c = *cs++;
                                 chrout(c);
                         }
                 else
                 {
                         p = _pfmt(cs, work, &na, &n);
                         if (p)
                         {
                                 cs = p;
                                 for (i=0; i<n; i++)
                                         chrout(work[i]);
                         }
                 }
                 else
                         chrout(c);
         }
         return;
 }

 chrout(c)
 char c;
 {
         if (c == '\n')
                 bdos(2,'\r');
         bdos(2,c);
 }



 PRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\PRINTF.C

 /*
 **       name         printf -- formatted write to console.
 **
 **       Same as Lattice C printf() function, but much faster.
 */

 printf(cs, args)
 char *cs, *args;
 {
         int i, c, n;
         char *p, **na, *_pfmt();
         char work[256];

         na =  &args;           /* point to first arg */
         while (*cs)
         {
                 c = *cs++;
                 if (c == '%')
                         if (*cs == '%')
                         {
                                 c = *cs++;
                                 chrout(c);
                         }
                 else
                 {
                         p = _pfmt(cs, work, &na, &n);
                         if (p)
                         {
                                 cs = p;
                                 for (i=0; i<n; i++)
                                         chrout(work[i]);
                         }
                 }
                 else
                         chrout(c);
         }
         return;
 }

 chrout(c)
 char c;
 {
         if (c == '\n')
                 bdos(2,'\r');
         bdos(2,c);
 }



 PRINTSCR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGAPAINT\PRINTSCR.C

 /***********************************************************
  *
  *               PRINT SCREEN UTILITY for Paint                    *
  *
  *  This was designed for an ALPS 218 seies printer        *
  *   using EPSON emulation.  I do not know how well        *
  *   it will work with other color printers, but it's      *
  *   good for guidelines.
  *
  ***********************************************************/


 #include <stdio.h>
 #include <dos.h>
 #include <conio.h>
 #include <graphics.h>

 #define WIDTH 80L
 #define XMAX 638
 #define YMAX 349
 #define XMIN 5
 #define YMIN 0
 #define CHARSOUT 800


 /* set up buffers for each of the colors.  The leading chars set up the
    color.  'C' just assigns memory for the rest of the array
 */

 static unsigned char black_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','0',0x1b,'K',0
 static unsigned char magenta_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','1',0x1b,'K'
 static unsigned char blue_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','2',0x1b,'K',0x
 static unsigned char violet_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','3',0x1b,'K',
 static unsigned char yellow_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','4',0x1b,'K',
 static unsigned char orange_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','5',0x1b,'K',
 static unsigned char green_buf[9+CHARSOUT] = {' ',' ',0x1b,'r','6',0x1b,'K',0

 /* I nuked off the last line of pins to improve symmetry.  I haven't
    seen any ill effects
 */


 /* char tank[] = {' ',' ',0x1b,'A',0x8,'\0'};  */
 char tank[] = {' ',' ',0x1b,'A',0x7,'\0'};

 char put_out(char character);

 void printscr(int reverse)
 {
         int x = XMAX, y, i;
         unsigned char mask;
         int c;

         /* set flags to see if any data is on the line for that color */

         char k_flag, m_flag, b_flag, v_flag, y_flag, o_flag, g_flag;

     fputs("\r", stdprn);
         fputs("\n", stdprn);

         fputs(tank,stdprn);

     fputs("\r", stdprn);
         fputs("\n", stdprn);

         while(x > 4) {
                 if(kbhit()) {
                         fputs("\0x1bA\0x9", stdprn);
                         getch();
                         break;
                 }

                 /* clear the buffers and flags */

                 for(i = 9; i < CHARSOUT + 9; i++) black_buf[i] = 0;
                 for(i = 9; i < CHARSOUT + 9; i++) magenta_buf[i] = 0;
                 for(i = 9; i < CHARSOUT + 9; i++) blue_buf[i] = 0;
                 for(i = 9; i < CHARSOUT + 9; i++) violet_buf[i] = 0;
                 for(i = 9; i < CHARSOUT + 9; i++) yellow_buf[i] = 0;
                 for(i = 9; i < CHARSOUT + 9; i++) orange_buf[i] = 0;
                 for(i = 9; i < CHARSOUT + 9; i++) green_buf[i] = 0;
                 k_flag = m_flag = b_flag = v_flag = y_flag = o_flag = g_flag

 /*                for(i = 0, mask = 0x80; i < 8; i++, mask >>= 1, x--) {  */
                 for(i = 0, mask = 0x80; i < 7; i++, mask >>= 1, x--) {
                         for(y = 0; y < YMAX; y++) {
                                 c = getpixel(x,y);     /* fill bit positions
                                 switch(c) {
                                          case DARKGRAY:         black_buf[y+9
                                                                         k_fla
                                                                            br
                                         case RED:                 magenta_buf
                                                                         m_fla
                                                                         break
                                         case LIGHTRED:  if(y & (x & 1) ? 0 :


                                                                         }
                                                                         break
                                         case BLUE:                  blue_buf[
                                                                         b_fla
                                                                         break
                                         case CYAN:                blue_buf[y+
                                                                         b_fla
                                                                         break
                                         case LIGHTBLUE:        if(y & (x & 1)


                                                                         }
                                                                         break
                                         case LIGHTCYAN:        if(y & (x & 1)


                                                                         }
                                                                         break
                                         case MAGENTA:        violet_buf[y+9]
                                                                         v_fla
                                                                         break
                                         case LIGHTMAGENTA: if(y & (x & 1) ? 0


                                                                            }
                                                                         break
                                         case YELLOW:        yellow_buf[y+9] |
                                                                         y_fla
                                                                         break
                                         case BROWN:                orange_buf
                                                                         o_fla
                                                                         break
                                         case GREEN:                green_buf[
                                                                         g_fla
                                                                         break
                                         case LIGHTGREEN: if(y & (x & 1) ? 0 :


                                                                          }
                                                                         break
                                 }
                         }
                         if(x < XMIN) break;   /* MIN X to keep vestiges from
                 }
                 if(k_flag) {           /* print the color only if sometimg is
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(black_buf[i]);
                 fputs("\r", stdprn);
                 }
         if(m_flag) {
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(magenta_buf[i]);
                 fputs("\r", stdprn);
                 }
                 if(b_flag) {
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(blue_buf[i]);
                 fputs("\r", stdprn);
                 }
         if(v_flag) {
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(violet_buf[i]);
                 fputs("\r", stdprn);
                 }
         if(y_flag) {
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(yellow_buf[i]);
                 fputs("\r", stdprn);
                 }
         if(o_flag) {
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(orange_buf[i]);
                 fputs("\r", stdprn);
                 }
         if(g_flag) {
                         for(i = 0; i < CHARSOUT+9; i++)
                                 put_out(green_buf[i]);
                 fputs("\r", stdprn);
                 }


                 fputs("\n", stdprn);

         }
         fputs("\x0c", stdprn);
         fflush(stdprn);                        /* print the last line */
 }

 /* not used - but someday ??? */

 char status(void)
 {
         union REGS regs;

         regs.h.ah = 2;
         regs.x.dx = 0;
         int86(0x17, &regs, &regs);
         return(regs.h.ah & 0x80);
 }

 /* out put to the printer */

 char put_out(char character)
 {
         union REGS regs;

         regs.h.ah = 0;
         regs.h.al = character;
         regs.x.dx = 0;
         int86(0x17, &regs, &regs);
         return(regs.h.ah);
 }






 PROGS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\PROGS.C

 /* EXAMPLE OF I/O STATEMENTS */
 #include "bc.h"
 main() {
 char *S = "STRING", *FLNAME = "TDAT.G";
 int A = 234, B = 678;
 if((fp1=fopen( "DATA.TST", "w"))==0){puts("can't open #1");exit(1);}
 fprintf(fp1, "%s %d %d", S, A, B);
 fclose(fp1);
 if((fp1=fopen( "DATA.TST", "r"))==0){puts("can't open #1");exit(1);}
 IEOF = fscanf(fp1, "%s %d %d", S, &A, &B);
 fclose(fp1);
 printf("%s %d %d \n", S, A, B);
 LIST(FLNAME);
 }/* IOEX*/

 LIST(FILENAME)
 char *FILENAME;
 {
 char C;
 if((fp4=fopen( FILENAME, "r"))==0){puts("can't open #4");exit(1);}
 while((C = getc(fp4)) != EOF) {
   putchar(C);
 }/*WH*/
 fclose(fp4);
 }/* LIST*/

 /* ERATOSTHENES SIEVE */
 #include "bc.h"
 #define SIZE 8190
 main() {
 int ITER, COUNT, I, K;
 int PRIME, FLAG[8191];
 printf("10 ITERATIONS \n");
 for(ITER = 1; ITER <= 10; ITER++) {
   COUNT = 0;
   for(I = 0; I <= SIZE; I++) {
     FLAG[I] = 1;
   }/*I*/
   for(I = 0; I <= SIZE; I++) {
     if(FLAG[I] != 0) {
       PRIME = I+I+3;
       K = I + PRIME;
       while(K <= SIZE) {
         FLAG[K] = 0;
         K = K + PRIME;
       }/*WH*/
       COUNT++;
     }/*IF*/
   }/*I*/
 }/*ITER*/
 printf(" %d PRIMES \n", COUNT);
 }/* SIEVE*/

 /* EIGHT QUEENS CHESS PROBLEM */
 #include "bc.h"
 int COLFREE[8], X[8];
 int UPFREE[15], DOWNFREE[15];
 int R, K;
 main() {
 /* INITIALIZE EMPTY BOARD */
 for(K = 0; K <= 7; K++) {
   COLFREE[K] = TRUE;
 }/*K*/
 for(K = 0; K <= 14; K++) {
   UPFREE[K] = DOWNFREE[K] = TRUE;
 }/*K*/
 R = -1;
 ADDQUEEN();
 }/* QUEEN8*/

 ADDQUEEN()
 {
 int C;
 R++;
 for(C = 0; C <= 7; C++) {
   /* IS SQUARE[R,C] FREE? */
   if(COLFREE[C] && UPFREE[R-C+7] && DOWNFREE[R+C]) {
     /* SET QUEEN ON SQUARE[R,C] */
     X[R] = C;
     COLFREE[C] = UPFREE[R-C+7] = DOWNFREE[R+C] = FALSE;
     if(R == 7) {
       printf("\n CONFIGURATION \n");
       for(K = 0; K <= 7; K++) {
         printf(" %d", X[K]);
       }/*K*/
       exit(1);
     ELSE ADDQUEEN();
     }/*IF*/
     /* REMOVE QUEEN FROM SQUARE[R,C)] */
     COLFREE[C] = UPFREE[R-C+7] = DOWNFREE[R+C] = TRUE;
   }/*IF*/
 }/*C*/
 R--;
 }/* ADDQUEEN*/

 /* PRODUCT OF TWO MATRICES OF VARIABLE DIMENSIONS */
 #include "bc.h"
 #define DLIM 21
 main() {
 double A[DLIM][DLIM], B[DLIM][DLIM], C[DLIM][DLIM];
 int I,J,K, N1,N2,N3;
 printf("DIMENSIONS = ");
 IEOF = scanf("%d %d %d", &N1, &N2, &N3);
 /* GENERATE MATRICES */
 for(J = 1; J <= N2; J++) {
   for(I = 1; I <= N1; I++) {
     A[I][J] = (double)(J-I);
   }/*I*/
   for(K = 1; K <= N3; K++) {
     B[J][K] = (double)(J+K);
   }/*K*/
 }/*J*/
 MATPRI(A,N1,N2);
 MATPRI(B,N2,N3);
 MULT(A,B,C,N1,N2,N3);
 MATPRI(C,N1,N3);
 }/* MAIN*/

 MULT(E,F,G, L1,L2,L3)
 double E[DLIM][DLIM], F[DLIM][DLIM], G[DLIM][DLIM];
 int L1, L2, L3;
 {
 int I,J,K;
 for(I = 1; I <= L1; I++) {
   for(K = 1; K <= L3; K++) {
     G[I][K] = 0;
     for(J = 1; J <= L2; J++) {
       G[I][K] = G[I][K]+E[I][J]*F[J][K];
     }/*J*/
   }/*K*/
 }/*I*/
 }/* MULT*/

 MATPRI(A, L1,L2)
 double A[DLIM][DLIM]; int L1, L2;
 {
 int I,J;
 printf("\n");
 for(I = 1; I <= L1; I++) {
   for(J = 1; J <= L2; J++) {
     printf("%8.3f", A[I][J]);
   }/*J*/
   printf("\n");
 }/*I*/
 }/* MATPRI*/

 /* EXAMPLE USING CONDITIONAL STATEMENTS */
 #include "bc.h"
 main() {
 char  *S = "@$^&*+";
 int I;
 for(I = 1; I <= 5; I++) {
   if(S[I] == '@') {
     printf("@");
   } else if {
     printf("$");
   } else if {
     printf("^");
   } else {
     printf("NO MATCH");
   }/*IF*/
 }/*I*/
 }/* CONDIT*/

 /* TOWERS OF HANOI */
 #include "bc.h"
 #define NDISK 64
 main() {
 MOVE(NDISK, 1, 3, 2);
 }/* HANOI*/

 MOVE(N, A, B, C)
 int N, A, B, C;
 {
 if(N > 0) {
   MOVE(N-1, A, C, B);
   printf("MOVE A DISK FROM %d TO %d \n", A, B);
   MOVE(N-1, C, B, A);
 }/*IF*/
 }/* MOVE*/

 /* INVERSE AND DETERMINANT OF SYMMETRIC MATRIX */
 #include "bc.h"
 #define DLIM 31
 main() {
 double A[DLIM][DLIM],R[DLIM][DLIM],DET,SINV();
 int I,J,ND;
 printf("ND = ");
 IEOF = scanf("%d", &ND);
 /* GENERATE ND X ND MATRIX */
 for(I = 1; I <= ND; I++) {
   for(J = 1; J <= ND; J++) {
     A[I][J]=1.;
   }/*J*/
   A[I][I]=2.;
 }/*I*/
 MATPRI(A,ND,ND);
 DET=SINV(A,R,ND);
 MATPRI(R,ND,ND);
 printf("%10.3f\n", DET);
 }/*MAIN*/

 double SINV(A,R,NN)
 double A[DLIM][DLIM], R[DLIM][DLIM];
 int NN;
 {
 double VEC[DLIM],DET,RL;
 int I,J,K,L;
 DET=A[1][1];
 R[1][1]=1./A[1][1];
 for(L = 2; L <= NN; L++) {
   K=L-1;
   RL=A[L][L];
   for(I = 1; I <= K; I++) {
     VEC[I]=0.;
     for(J = 1; J <= K; J++) {
       VEC[I]=VEC[I]+R[I][J]*A[L][J];
     }/*J*/
     RL=RL-A[L][I]*VEC[I];
   }/*I*/
   DET=DET*RL;
   for(I = 1; I <= K; I++) {
     R[L][I]=-VEC[I]/RL;
     R[I][L]=R[L][I];
   }/*I*/
   for(I = 1; I <= K; I++) {
     for(J = I; J <= K; J++) {
       R[I][J]=R[I][J]-VEC[I]*R[L][J];
       R[J][I]=R[I][J];
     }/*J*/
   }/*I*/
   R[L][L]=1./RL;
 }/*L*/
 return(DET);
 }/* SINV*/

 /* SHELL-METZNER SORT */
 #include "bc.h"
 #define DLIM 101
 #define NN 20
 main() {
 int X[DLIM];
 /* GENERATE VECTOR */
 for(I = 1; I <= N; I++) {
   X[I] = N-I+1;
 }/*I*/
 PRVEC(X,L);
 SZSORT(X,L);
 PRVEC(X,L);
 }/* SORT*/

 SZSORT(X,N)
 int X,N;
 {
 int KT,TP,I,J, K = 1;
 while(K < N) {
   K = 2*K;
 }/*WH*/
 K = K/2 - 1;
 while(K >= 1) {
   KT=1;
   while(KT > 0) {
     J = K;
     KT = 0;
     for(I = 1; I <= N; I++) {
       J++;
       if(J <= N && X[I] > X[J]) {
         TP=X[I];X[I]=X[J];X[J]=TP;
         KT++;
       }/*IF*/
     }/*I*/
   }/*WH*/
   K = K/2;
 }/*WH*/
 }/* SZSORT*/

 PRVEC(A,LL)
 int A[], LL;
 {
 int I;
 printf("\n");
 for(I = 1; I <= LL; I++) {
   printf(" %d ", A[I]);
 }/*I*/
 printf("\n");
 return;
 }/* PRVEC*/

 /* FIBONACCI NUMBERS */
 #include "bc.h"
 main() {
 int  N;
 printf("N = ");
 IEOF = scanf("%d", &N);
 printf("FIBON = %d\n", FIB(N));
 }/* FIBNUM*/

 int FIB(K)
 int K;
 {
 if(K <= 2) {
   return(1);
 } else {
   return(FIB(K-1) + FIB(K-2));
 }/*IF*/
 }/* FIB*/

 /* ZERO OF FUNCTION BY NEWTON'S METHOD */
 #include "bc.h"
 main() {
 int NMAX=20;
 double TOL=1.0E-6, X0, X, NEWT();
 X0 = 2;
 X = NEWT(X0,TOL,NMAX);
 printf("%f \n", X);
 }/* NEWTON*/

 double NEWT(X0,TOL,NMAX)
 double X0,TOL; int NMAX;
 {
 double FN(), DFN(), fabs(), X, INC;
 int I, N;
 X = X0;
 for(I = 1; I <= NMAX; I++) {
   INC = -FN(X)/DFN(X);
   X = X + INC;
   if(fabs(INC) < TOL) {
     return(X);
   }/*IF*/
 }/*I*/
 printf("NO CONVERGENCE");
 exit(1);
 }/* NEWT*/


 PRTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\PROBE\PRTEST.C

 /*                        PRTEST.C
         Test program for the program PROBE
                 Author: Colin Stearman [71036,256]
 */

 long i;
 main()

 {
 printf("test1\n");
 test1();
 printf("test2\n");
 test2();
 printf("test3\n");
 test3();
 printf("test4\n");
 test4();
 printf("test5\n");
 test5();
 }

 test1()

 {
 for (i=0; i<10000; i++);
 }

 test2()

 {
 for (i=0; i<20000; i++);
 }
 test3()

 {
 for (i=0; i<30000; i++);
 }
 test4()

 {
 for (i=0; i<40000; i++);
 }
 test5()

 {
 for (i=0; i<50000; i++);
 }
 test6()

 {
 for (i=0; i<100; i++);
 }


 PRTFLD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\PRTFLD.C

 _prtfld(op, put, buf, ljustf, sign, pad, width, preci)
 register char *op;
 register int (*put)();
 register unsigned char *buf;
 int ljustf;
 register char sign;
 char pad;
 register int width;
 int preci;
 /*
  *        Output the given field in the manner specified by the arguments.
  *        Return the number of characters output.
  */
 {
         register int cnt = 0, len;
         register unsigned char ch;

         len = strlen(buf);

         if (*buf == '-')
                 sign = *buf++;
         else if (sign)
                 len++;

         if ((preci != -1) && (len > preci))        /* limit max data width */
                 len = preci;

         if (width < len)        /* flexible field width or width overflow */
                 width = len;

 /* at this point:
  *        width = total field width
  *        len   = actual data width (including possible sign character)
  */
         cnt = width;
         width -= len;

         while (width || len)
                 {
                 if (!ljustf && width) {                /* left padding */
                         if (len && sign && (pad == '0'))
                                 goto showsign;
                         ch = pad;
                         --width;
                 }
                 else if (len) {
                         if (sign) {
 showsign:                        ch = sign;        /* sign */
                                 sign = '\0';
                         }
                         else
                                 ch = *buf++;        /* main field */
                         --len;
                 }
                 else {
                         ch = pad;                /* right padding */
                         --width;
                 }
                 (*put)(ch, op);
         }

         return(cnt);
 }


 PRTSCN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\PRTSCN.C

 #include <dos.h>
 prtscn()
 {
         struct HREG REG;
         int86(0x05,&REG,&REG);
 }



 PTRFUNC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\PTRFUNC.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 /*
  * The routines in this file attempt to imitate many of the operations
  * that used to be performed on simple character pointers and are now
  * performed on LPTR's. This makes it easier to modify other sections
  * of the code. Think of an LPTR as representing a position in the file.
  * Positions can be incremented, decremented, compared, etc. through
  * the functions implemented here.
  */

 /*
  * inc(p)
  *
  * Increment the line pointer 'p' crossing line boundaries as necessary.
  * Return 1 when crossing a line, -1 when at end of file, 0 otherwise.
  */
 int
 inc(lp)
 register LPTR        *lp;
 {
         register char *p = &(lp->linep->s[lp->index]);

         if (*p != NUL) {                        /* still within line */
                 lp->index++;
                 return ((p[1] != NUL) ? 0 : 1);
         }

         if (lp->linep->next != Fileend->linep) {  /* there is a next line */
                 lp->index = 0;
                 lp->linep = lp->linep->next;
                 return 1;
         }

         return -1;
 }

 /*
  * dec(p)
  *
  * Decrement the line pointer 'p' crossing line boundaries as necessary.
  * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
  */
 int
 dec(lp)
 register LPTR        *lp;
 {
         if (lp->index > 0) {                        /* still within line */
                 lp->index--;
                 return 0;
         }

         if (lp->linep->prev != NULL) {                /* there is a prior lin
                 lp->linep = lp->linep->prev;
                 lp->index = strlen(lp->linep->s);
                 return 1;
         }

         return -1;                                /* at start of file */
 }

 /*
  * gchar(lp) - get the character at position "lp"
  */
 int
 gchar(lp)
 register LPTR        *lp;
 {
         return (lp->linep->s[lp->index]);
 }

 /*
  * pchar(lp, c) - put character 'c' at position 'lp'
  */
 void
 pchar(lp, c)
 register LPTR        *lp;
 char        c;
 {
         lp->linep->s[lp->index] = c;
 }

 /*
  * pswap(a, b) - swap two position pointers
  */
 void
 pswap(a, b)
 register LPTR        *a, *b;
 {
         LPTR        tmp;

         tmp = *a;
         *a  = *b;
         *b  = tmp;
 }

 /*
  * Position comparisons
  */

 bool_t
 lt(a, b)
 register LPTR        *a, *b;
 {
         register int an, bn;

         an = LINEOF(a);
         bn = LINEOF(b);

         if (an != bn)
                 return (an < bn);
         else
                 return (a->index < b->index);
 }

 bool_t
 gt(a, b)
 LPTR        *a, *b;
 {
         register int an, bn;

         an = LINEOF(a);
         bn = LINEOF(b);

         if (an != bn)
                 return (an > bn);
         else
                 return (a->index > b->index);
 }

 bool_t
 equal(a, b)
 register LPTR        *a, *b;
 {
         return (a->linep == b->linep && a->index == b->index);
 }

 bool_t
 ltoreq(a, b)
 register LPTR        *a, *b;
 {
         return (lt(a, b) || equal(a, b));
 }

 bool_t
 gtoreq(a, b)
 LPTR        *a, *b;
 {
         return (gt(a, b) || equal(a, b));
 }


 PUTC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\PUTC.C

 /* 1.2  01-08-86                                                (putc.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 putc(c, fp)                /* Put character c on FILE fp.  Return c or EOF
                            on error condition.
 /*----------------------------------------------------------------------*/
 METACHAR c;
 FAST FILE *fp;
 {
         METACHAR flush();

         _rowcol(c, fp);
         if (fp->_bptr >= fp->_bend)
                 return flush(fp, c & 0xff);

         return (*fp->_bptr++ = c) & 0xff;
 }
 /*\p*********************************************************************/
         METACHAR
 flush(fp, c)                /* Write any already buffered characters onto
                            FILE fp.  If c is EOF, return NULL on success,
                            EOF on failure.  Otherwise, if i/o is buffered,
                            put c in the buffer, and return c.  If io isn't
                            buffered, write the char, return c if ok or EOF
                            if write error.                                 */
 /*----------------------------------------------------------------------*/
 METACHAR c;
 FAST FILE *fp;
 {
         FAST int siz;
         char cc;

         cc = c;
         if (fp->_flags & _IOERR)
                 return EOF;

         if (fp->_flags & _DIRTY)
         {        siz = fp->_bptr - fp->_buff;
                 if (write(fp->_unit, fp->_buff, siz) ISNT siz)
                 {        fp->_flags |= _IOERR;
                         fp->_bend = fp->_bptr = NULL;
                         return EOF;
                 }
         }
         if (c IS EOF)
         {        fp->_flags &= ~_DIRTY;
                 fp->_bend = fp->_bptr = NULL;
                 return NULL;
         }
         if (fp->_buff IS NULL)                /* if no buffer yet assigned.
                 getbuf(fp);
         if (fp->_buflen IS 1)                        /* unbuffered I/O
         {        if (write(fp->_unit, &cc, 1) ISNT 1)
                 {        fp->_flags |= _IOERR;
                         fp->_bend = fp->_bptr = NULL;
                         return EOF;
                 }
                 return c & 0xff;
         }
         fp->_bptr = fp->_buff;
         fp->_bend = fp->_buff + fp->_buflen;
         fp->_flags |= _DIRTY;
         return (*fp->_bptr++ = c) & 0xff;
 }
 /*\p*********************************************************************/
         VOID
 fclosall()                /* close all stream files                        */

 /*----------------------------------------------------------------------*/
 {
         FILE *fp;

         for (fp = IObuffs; fp < IObuffs + MAXSTREAM; fp++)
                 if (fp->_flags)
                         fclose(fp);
         return;

 }

 /*************************************************************************/
         METACHAR
 putca(c, fp)                /* Put ASCII character c on FILE fp.  Return c or
                            EOF on error condition.  Add a '\r' to the
                            output when c = '\n', as file fp is assumed
                            to be text.
 /*----------------------------------------------------------------------*/
 METACHAR c;
 FILE *fp;
 {
 #ifdef CROUTADD
         if (c IS '\n')
                 if (putc('\r', fp) IS EOF)
                         return EOF;
 #endif
         return putc(c, fp);
 }


 PUTENV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\PUTENV.C

 #include <stdio.h>

 extern char        *_envp;

 #define        ENVSIZ        2048

 static        int        envset = FALSE;                /* local env created?

 int putenv(entry)
 char *entry;
 /*
  *        Add <entry> to the environment.  <entry> can be any of the followin
  *        forms:
  *                <VARIABLE>
  *                <VARIABLE>=
  *                <VARIABLE>=<value>
  *        The first form removes <VARIABLE> from the environment.  getenv()
  *        will return NULL if looking for this variable.  The second form add
  *        <VARIABLE> to the environment, with a null value.  getenv() will
  *        return a pointer to a '\0' character if looking for this variable.
  *        Many environment handlers don't support such "tag variables", so
  *        their use is not recommended.  The final form is the most common,
  *        and safest to use.  <VARIABLE> is installed (or replaced) with the
  *        value <value>.  It should be noted that this function itself is not
  *        supported in many systems and should be used will care to prevent
  *        overflowing the space allocated for the environment.
  */
 {
         register char *p, *q, *t, c;
         register int len;
         char *malloc(), *getenv();

         if(!envset) {                                        /* no local env
                 if((p = malloc(ENVSIZ)) == NULL)
                         return(FALSE);
                 q = _envp;
                 _envp = p;
                 envset = TRUE;
                 if(q) {
                         while(*q)
                                 while(*p++ = *q++)
                                         ;
                 }
                 else
                         *p++ = '\0';
                 *p++ = '\0';
                 *p = 0xFF;
         }
         for(t=entry; (c = *t) && (c != '='); ++t)
                 ;
         *t = '\0';
         if(p = getenv(entry)) {                                /* remove old
                 q = p;
                 while(*q++)                        /* find end of old val */
                         ;
                 p -= (len = strlen(entry));
                 while(strncmp(--p, entry, len))        /* find start of old v
                         ;
                 while(*q)                        /* copy environment tail */
                         while(*p++ = *q++)
                                 ;
                 *p++ = '\0';                        /* tie off environment */
                 *p = 0xFF;
         }
         if(c == '=') {                                        /* install new
                 p = _envp;
                 while(*p)                        /* find end of env */
                         while(*p++)
                                 ;
                 *t = c;
                 q = entry;
                 while(*p++ = *q++)                /* copy new entry */
                         ;
                 *p++ = '\0';                        /* tie off environment */
                 *p = 0xFF;
         }
         return(TRUE);
 }


 PUTMENUS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\PUTMENUS.C

 /* PUTMENUS.C - Program to print menus on the screen. Typed     */
 /* from the book "Microsoft C Programming for the IBM" by Rob-  */
 /* ert Lafore, page 264.                                        */
 /****************************************************************/

 SIZE1 5               /* Items on menu1 */
 SIZE2 4               /* Items on menu2 */
 CLEAR "\x1B[2J"       /* Clears screen  */

 main()
 {
 static char *menu1[] =        /*first menu*/
             {  "Open",
                "Close",
                "Save",
                "Print",
                "Quit"   };
 static char *menu2[] =        /*second menu*/
             {  "Cut",
                "Copy",
                "Paste",
                "Reformat"  };
    printf(CLEAR);              /*Clear screen*/
    display(menu1, SIZE1, 20);    /*Display first menu*/
    display(menu2, SIZE2, 40);    /*Display second menu*/
    getch();
 }

 /* display() */
 /* Displays menu at given column number */
 display(arr, size, hpos)
 char *arr[];                  /*array to display*/
 int size;                     /*size of array*/
 int hpos;                     /*column number*/
 {
 int j;

    for(j = 0; j < size; j++) {         /*for each menu item*/
       printf("\x1B[%d;%df", j + 1, hpos);    /*position cursor*/
       printf("%s\n", *(arr + j));            /*print item*/
    }
 }


 PUTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\PUTS.C

 /* 1.0  12-10-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 puts(s)                        /* Put the string s, followed by newline, to t
                            stdout device. Return newline if ok, EOF if not*/
 /*----------------------------------------------------------------------*/
 FAST STRING s;
 {
         while (*s)
                 if (putchar(*s++) IS EOF)
                         return EOF;

         return putchar('\n');
 }


 PUTSTRIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\PUTSTRIN.C


 #include <stdio.h>
 #include <string.h>
 #include "expert.h"


 /*****************************************************************
 **
 **        PUT STRING
 **
 **        looks for string on rule line and
 **            either returns the offset into the
 **                string buffer if found or places
 **                it into the string buffer and returns
 **                the offset to it.
 **        strBuffOfst is the pointer to the offset to
 **                the last used location in the string buffer
 **
 **
 *****************************************************************/

 int        putString (infile,strBuff,strBuffOfst)

         FILE        *infile ;
         char        *strBuff ;
         int        *strBuffOfst ;

 {
 int        i,offSet,strLen,c,newline ;
 char        buff[MAX_STR_LEN] ;

 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING strBuffOfst= %d",*strBuffOfst) ;
 #endif

 /*
 **
 **        get file positioned to first non blank character (after keyword)
 **
 */

 while( ( c=getc(infile)) == BLANK )
         putchar(c) ;
 if( c == EOL )
         {
         putchar(c) ;
         return (LINE_ERROR) ;
         }
 if( c == EOF )
         return (KEY_EOF) ;
 ungetc(c,infile);

 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING c = %c", c) ;
 #endif
 /*
 **
 **         load the string on the line into the string buffer for
 **        later comparison to strings in the line buffer.
 **
 */
 newline = FALSE ;
 for( i = 0 ; i < (MAX_STR_LEN-1) ; i++ )
         {
         buff[i]=c=getc(infile) ;

 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING c =%c, i = %d -- ", c,i) ;
 #endif
         putchar(c) ;
         if(c == '\\')
                 {
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING newline is TRUE");
 #endif
                 newline = TRUE ;
                 continue ;
                 }
         if( newline == TRUE )
                 {
                 if( c == 'n' )
                         {
                         i -= 1 ;
                         buff[i] = '\n' ;
                         }
 #ifdef        DEBUG
                 fprintf(stdout,"\nDEBUG-PUTSTRING newline is FALSE");
 #endif
                 newline = FALSE ;
                 continue ;
                 }
         if(c == EOL)
                 {
                 buff[i]=0 ;
                 break ;
                 }
         if(c == EOF)
                 {
                 buff[i]=0 ;
                 ungetc(c,infile) ;
                 break ;
                 }
         }

 /*
 **        remove trailing blanks in the buffer
 **
 */
 for( --i ; i > -1 ; i-- )
         {
         if( buff[i] != BLANK )
                 break ;
         buff[i]=0 ;
         }
 if(i <= 0)
         return(STR_LEN_ERROR) ;
 strLen = i ;

 buff[MAX_STR_LEN-1] = 0 ;

 /*
 **        at this point strLen should be the offset to the last character
 **        in the string and is also, therefore, the length of the string -1
 **
 **        search for the string in the string buffer
 **        return offset to string if found else put the string
 **        in the string buffer and uptate buffer offset returning
 **        pointer to new string
 **
 */

 offSet = 0 ;
 while( offSet < *strBuffOfst )
         {
         if( strcmp(&strBuff[offSet], buff) == 0 )
                 return(offSet) ;
         while( strBuff[++offSet] ) ;           /* look for end of null trmntd
         ++offSet ;                        /* move past the null to next strin
         }
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING strBuffOfst= %d",*strBuffOfst) ;
         fprintf(stdout,"\nDEBUG-PUTSTRING offSet = %d",offSet) ;
         fprintf(stdout,"\nDEBUG-PUTSTRING strBuff= %s",&strBuff[offSet]);
         fprintf(stdout,"\nDEBUG-PUTSTRING buff   = %s",buff) ;
 #endif
 strcpy(&strBuff[*strBuffOfst],buff) ;
 if(*strBuffOfst == 0 )
         {
         *strBuffOfst += strLen + 2 ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING strBuffOfst= %d",*strBuffOfst) ;
 #endif
         return(0) ;
         }
 else
         {
         offSet = *strBuffOfst ;
         *strBuffOfst += strLen + 2 ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-PUTSTRING strBuffOfst= %d",*strBuffOfst) ;
 #endif
         return(offSet) ;
         }
 }


 QBENCH10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\WINDOW10\QBENCH10.C

 #include <stdio.h>
 #include <string.h>
 #include <dos.h>
 #include <conio.h>
 #include <w1.h>
 #include <windprot.h>

 /*===========================================================================
 /*  Qbench.c - produces a 'Screens/second' table for Q screen utilities
 /*
 /*  VERSION: 1.0
 /*  AUTHOR:  (C) 1987 Michael G. Mlachak  (TURBO-C) version
 /*           (C) 86,87 James H. leMay (Turbo Pascal) version
 /*
 /*  DATE: 6-2-1987
 /*  LIABILITY: Author assumes no reliabilty for misuse
 /*  COMMENTS:  Released under the teamware concept. (see other DOC FILES).
 /*  I'm not trying to support this program, so don't expect it to be perfect.
 /*  It will just give you a good feel for speed.  The time is adjusted for
 /*  an average 8 second test for each condition - total of 6 minutes.  For mo
 /*  accurate results, change TESTTIME = 16. I would appreciate anyone providi
 /*  me the results on their machine as a disk file including processor number
 /*  processor Mhz and Video card.
 /*===========================================================================

 typedef enum {  nowait,wait } WAITS;
 typedef enum {  attr,noattr } ATTRS;
 typedef enum {  start,stop } STARTSTOP;
 typedef char str80[80];

   #define PROCS        11
   #define TESTTIME     8  /*  TestTime in seconds for each case.  8 gives +/-
   #define HIDECURSOR   8192
   #define CAPS         83
   #define SMALLS       115
   #define CAPD         68
   #define SMALLD       100
   #define FALSE        0
   #define TRUE         1

   extern qinit(void);
   void timer(STARTSTOP);
   void checktime(void);
   void allprocs(int);
   void transproc(int);
   void exallproc(ATTRS,int,int);
   void extransproc(ATTRS,int,int);
   void readkb(int *);
   void getkey(void);
   int midword(void);
   int lobyte(void);

   int          attrib, count, screens, waitscreens, nowaitscreens, oldcursor;
   int          row, col, rows, cols, procnumber;
   double       scrpersec [PROCS][wait+1][noattr+1];
   double       t1, t2, elapsedtime;

   str80        strng;
   WAITS        w;
   ATTRS        a;
   char         scrarray[4000];
   FILE         *fcb;
   int          todisk;
   int          key;

    static str80 names[PROCS] = {
       " qwritelv    ",
       " qwritev     ",
       " qwrite      ",
       " qwritec     ",
       " qwritecv    ",
       " qfillc      ",
       " qfill       ",
       " qattr       ",
       " qattrc      ",
       " qstore      ",
       " qrestore    "};


 void main(void)
 {
   qinit();
   oldcursor = cursorchange(HIDECURSOR);
   gotorc(1,1);
   qfill(1, 1, 25, 80, 14, ' ');
   qwritec(1,1,80,14,"SCREENS / SECOND table for Q Screen Utilities (TURBO-C).
   qwritec(2,1,80,14,"(C) COPYRIGHT 1987 Michael G. Mlachak");
   qwritec(3,1,80,14,"(Original TEAMWARE concept (C) 86,87 James H. LeMay");
   qwritec(8, 1, 80, 14, "Data to Screen or Disk[S/D]?");
   gotorc(1, 29);
   getkey();
   qwritec(12, 1, 80, 14, "Don't worry about snow if you have CGA.");
   qwritec(13, 1, 80, 14, "It's testing as if you had an EGA.");
   sleep(3);

   for (procnumber = 0; procnumber <= PROCS-1; procnumber++)
      for (w = nowait; w <= wait; w++)
         for (a = attr; a <= noattr; a++)
             scrpersec[procnumber][w][a] = (double)0.0;
   qwait = FALSE;
   w = nowait;
   screens = 600; /*  First guess for screens  */
   checktime();

   nowaitscreens = screens;
   exallproc(attr, nowaitscreens, 14);
   extransproc(attr, nowaitscreens, 14);
   qattr(1, 1, 25, 80, 7);
   exallproc(noattr, nowaitscreens, -1);

   if ((unsigned)qseg !=0xB000) {
     qwait = TRUE;
     w = wait;
     screens = 90; /*  First guess for screens  */
     checktime();
     waitscreens = screens;
     exallproc(attr, waitscreens, 14);
     extransproc(attr, waitscreens, 14);
     qattr(1, 1, 25, 80, 7);
     exallproc(noattr, waitscreens, -1);
   }

   qfill(1, 1, 25, 80, 14, ' ');
   if (todisk) {
      fcb = fopen("QBENCH.DTA","w+");
   }
   else
      fcb = stdout;
   gotorc(1, 1);
   fprintf(fcb,"S C R E E N S / S E C O N D\n");
   fprintf(fcb,"             Chng\n");
   fprintf(fcb,"Function     Attr EGA    CGA\n");
   fprintf(fcb,"--------     ---- -----------\n");
   for (procnumber = 0; procnumber <= 6; procnumber++)
      for (a = attr; a <= noattr; a++) {
          if (a == attr)
             fprintf(fcb,"%s",names[procnumber]);
          else
             fprintf(fcb,"             ");
          if (a == attr)
             fprintf(fcb,"Yes  ");
          else
             fprintf(fcb,"No   ");
          fprintf(fcb,"%5.1f",scrpersec[procnumber][nowait][a]);
          fprintf(fcb,"%6.1f\n",scrpersec[procnumber][wait][a]);
      }
      for (procnumber = 7; procnumber <= 10; procnumber++)  {
         fprintf(fcb,"%s",names[procnumber]);
         if (procnumber < 9)
            fprintf(fcb,"Yes  ");
         else
            fprintf(fcb,"N/A  ");
         fprintf(fcb,"%5.1f",scrpersec[procnumber][nowait][attr]);
         fprintf(fcb,"%6.1f\n",scrpersec[procnumber][wait][attr]);
      }
      gotorc(24, 1);
      fprintf(fcb,"waitscreens= %d\n",waitscreens);
      fprintf(fcb,"nowaitscreens= %d\n",nowaitscreens);
      if (todisk) {
         fclose(fcb);
         qwritec(3,1,80,14,"(Data has been written to QBENCH.DTA)");
      }
      gotorc(24, 1);
      oldcursor = cursorchange(oldcursor);
 }  /* main */

 void         timer(ss)
 STARTSTOP    ss;
 {
    switch (ss) {

       case start:
                  t1 = (midword() * 256.0) + lobyte();
                  elapsedtime = 0.0;
       break;

       case stop:
                 t2 = (midword() * 256.0) + lobyte();
                 if (t2 < t1)
                    t2 = t2 + 1573040.0;           /*  max 1,573,040 tics/day
                 elapsedtime = (t2 - t1) / 18.206481934;  /* units of secs.. *
       break;
    } /* of switch */
 } /* of timer */

 void         checktime()
 {
   strcpy(strng, "TimerTest ");
   for (col = 1; col <= 3; col++)
      strcpy(strng, strcat(strng, strng));
   qfill(1, 1, 25, 80, 14, ' ');
   timer(start);

   for (count = 1; count <= screens; count++)
      for (row = 1; row <= 25; row++)
         qwritev(row, 1, 14, strng);
   timer(stop);
   screens = (int)((screens * TESTTIME) / elapsedtime);
 }  /* checktime */

 void         allprocs(procnumber)
 int          procnumber;
 {
     switch (procnumber) {

        case 0:
           timer(start);
           for (count = 1; count <= screens; count++)
              for (row = 1; row <= 25; row++)
                 qwritelv(row, 1, attrib, 80, strng);
           timer(stop);
        break;

        case 1:
           timer(start);
           for (count = 1; count <= screens; count++)
           for (row = 1; row <= 25; row++)
              qwritev(row, 1, attrib, strng);
           timer(stop);
        break;

        case 2:
            timer(start);
            for (count = 1; count <= screens; count++)
               for (row = 1; row <= 25; row++)
                  qwrite(row, 1, attrib, strng);
            timer(stop);
        break;

        case 3:
           timer(start);
           for (count = 1; count <= screens; count++)
              for (row = 1; row <= 25; row++)
                 qwritec(row, 1, 80, attrib, strng);
           timer(stop);
        break;

        case 4:
           timer(start);
           for (count = 1; count <= screens; count++)
              for (row = 1; row <= 25; row++)
                 qwritecv(row, 1, 80, attrib, strng);
           timer(stop);
        break;

        case 5:
           timer(start);
           for (count = 1; count <= screens; count++)
              qfillc(1, 1, 80, 25, 80, attrib, 'C');
           timer(stop);
        break;

        case 6:
           timer(start);
           for (count = 1; count <= screens; count++)
              qfill(1, 1, 25, 80, attrib, 'F');
           timer(stop);
        break;
     } /*  switch procnumber */
     if (attrib >= 0)  {
         switch (procnumber) {

            case 7:
               qfill(1, 1, 25, 80, attrib, 'a');
               timer(start);
               for (count = 1; count <= screens; count++)
                  qattr(1, 1, 25, 80, attrib);
               timer(stop);
            break;

            case 8:
               qfill(1, 1, 25, 80, attrib, 'c');
               timer(start);
               for (count = 1; count <= screens; count++)
               qattrc(1, 1, 80, 25, 80, attrib);
               timer(stop);
            break;
         } /*  switch procnumber  */
     } /* attrib >=0 */
     if (elapsedtime != (double)0.0) {
        scrpersec[procnumber][w][a] = (double)screens / elapsedtime;
     }
 }  /* allprocs */

 void         transproc(procnumber)
 int         procnumber;
 {
     for (row = 1; row <= 25; row++)
        qwritev(row, 1, attrib, strng);
     switch (procnumber) {

        case 9:
           timer(start);
           for (count = 1; count <= screens; count++)
              qstore(1, 1, 25, 80, scrarray);
           timer(stop);
        break;

        case 10:
           qstore(1, 1, 25, 80, scrarray);
           timer(start);
           for (count = 1; count <= screens; count++)
              qrestore(1, 1, 25, 80, scrarray);
           timer(stop);
        break;
     } /*  switch procnumber */
     if (elapsedtime != (double)0.0)  {
        scrpersec[procnumber][w][a] = (double)screens / elapsedtime;

     }
 }  /* transproc */

 void         exallproc(at, scrs, att)
 ATTRS        at;
 int          scrs;
 int          att;
 {
   static char temp_array[60];

   a = at;
   screens = scrs;
   attrib = att;
   for (procnumber = 0; procnumber <= 8; procnumber++) {
     strcpy(strng, names[procnumber]);
     if (w == wait)
        strcpy(strng, strcat(strng, " Wait    "));
     else
        strcpy(strng, strcat(strng, " No Wait "));
     if (a == attr)
        strcpy(strng, strcat(strng, " w/Attr  "));
     else
        strcpy(strng, strcat(strng, " No Attr "));
     memset(temp_array,(char)procnumber + 49,59);
     strncat(strng,temp_array,(80-strlen(strng)));
     allprocs(procnumber);
   }
 } /* exallproc */

 void         extransproc(at, scrs, att)
 ATTRS        at;
 int          scrs;
 int          att;
 {
   static char temp_array[60];

   a = at;
   screens = scrs;
   attrib = att;
   for (procnumber = 9; procnumber <= 10; procnumber++) {
     strcpy(strng, names[procnumber]);
     if (w == wait)
        strcpy(strng, strcat(strng, " Wait    "));
     else
        strcpy(strng, strcat(strng, " No Wait "));
     strcpy(strng, strcat(strng, " w/Attr  "));
     memset(temp_array,(char)procnumber + 49,59);
     strncat(strng,temp_array,(80-strlen(strng)));
     transproc(procnumber);
   }
 } /* extransproc */

 int midword(void)
 {
    return(peek(0x00,0x046D));
 }

 int lobyte(void)
 {
   return(peek(0x00,0x046C));
 }

 void        readkb(key)
 int         *key;
 {

   int t_key;

   t_key = getch();
   if (t_key ==0)     /* extended character hit */
      t_key = getch();
    *key = t_key;
 } /* readkb() */

 void         getkey(void)
 {
   do {
      readkb(&key);
   }  while (!((key == CAPS) || (key == CAPD) || (key == SMALLD)
               || (key == SMALLS)));
   todisk = ((key == CAPD) || (key == SMALLD));
 }  /* getkey() */



 QDEMO10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\WINDOW10\QDEMO10.C

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <dos.h>
 #include <conio.h>
 #include <w1.h>
 #include <windprot.h>
 #include <color.h>

 #define WAIT 15000
 /*===========================================================================
 /*  Qdemo.c - Demonstration program for Q screen utilities  ver 1.0, 6-1-87
 /*  Demo has been programmed for All Cards and any column mode.  If you want
 /*  try 40 column mode, set crtcolumns to 40 in main. This does not set your
 /*  machine to 40 column mode. This must be done by the DOS mode command.
 /*
 /* AUTHORS: Turbo Pascal version -- (C) 86,87 Jim H. Lemay
 /*          Turbo C version -- (C) 1987 Mike Mlachak
 /* DATE:    6-1-87
 /* VERSION: 1.0
 /* COMMENTS: Must be compiled in SMALL model and linked with WIND1x.lib
 /*===========================================================================

 typedef char str80[80];

     int          row, rows, col, cols, ctr, step, rstep, colmax, count,
                  attrib, i, j, crtcols;
     int          hidecursor, oldcursor, fgrnd, bgrnd;
     int          brdrattr, wndwattr;
     char         savedblock[4000], popupblock[4000];
     int          blkrow, blkcol;
     int          crtcolumns;               /*  number of CRT columns  */
     int          tattr;
     int          coll[3], colr[3];
     char         strng[75], numstr[75];
     double       rnum;

     extern void qinit(void);
     int random(int);

 /*  These are double lines for qbox  */


    static str80 data[9] = {
        "1",
        "22",
        "333",
        " Q Screen Utilities ",
        "Odd  Length",
        "Even  Length",
        "18 characters wide",
        "19 characters width",
        "Margin to Margin width"};

 /*  qbox is an application of Q screen utilities.  It can make fast pop up me
     Together with qstore/qrestore, you can do several windows at one time.



 void main(void)
 {
 /*  --- Set up data ---  */
   qinit(); /*  << <<  Required intializing statement !!  */
   crtcolumns = 80;
   crtcols = crtcolumns;
   hidecursor = 8192;

 /*  --- Initial screen ---  */
   oldcursor = cursorchange(hidecursor);
   qfill(1, 1, 25, crtcols, (BLUE << 4) + WHITE, ' '); /*   Clear Screen  */
   qwritecv(11, 1, crtcols, (BLUE << 4) + YELLOW, data[3]);
   qwritec(13, 1, crtcols, -1, "Your screen is about to explode.");
   qwritec(14, 1, crtcols, -1, "Hold on to your seat ...");
   sleep(4);

 /*  --- Explosion of Boxes ---  */
   qfill(11, 1, 4, crtcols, -1, ' '); /*   Clear Lines  */
   qattr(1, 1, 25, crtcols, LIGHTGRAY << 4); /*   Change screen attribute  */
   ctr = crtcols / 2;
   for (step = 2; step <= ctr - 2; step++) {
      if (step > 24)
         rstep = 12;
      else
         rstep = step >> 1;
      for (count = 1; count <= 20; count++) {
         row = 13 - rstep + random(rstep + 2);
         rows = rstep;
         cols = rstep + rstep + (rstep >> 2);
         if (step <= 24)
            col = ctr - cols + random(cols + 1);
         else
            col = ctr - 1 - step + random(step + step - 22);
       fgrnd = random(16);
       bgrnd = random(8);
       if (bgrnd == fgrnd)
          fgrnd = fgrnd + 1;
       attrib = (bgrnd << 4) + fgrnd;
       qfill(row,col,row,cols,attrib,'²');
     }  /* for count = 1*/
   } /* for step = 2,..etc */

   qfillc(10, 1, crtcols, 6, 34, RED << 4, ' ');
   qfillc(11, 1, crtcols, 4, 30, BROWN << 4, ' ');
   tattr = (RED << 4) + YELLOW;
   qwritecv(12, 1, crtcols, tattr, data[3]);
   qwritec(13, 1, crtcols, tattr, "Turbo-C  Version 1.0");

   /*  --- Save Screen for Page Demo ---  */
   if (maxpage > 0)
   {
     qstore(1, 1, 25, crtcols, savedblock);
     qwritepage(1);
     qrestore(1, 1, 25, crtcols, savedblock);
     qwritepage(0);
   }
   /*  --- End of Save Screen ---  */
   sleep(2);
   tattr = (BLUE << 4) + WHITE;
   qwritec(6, 1, crtcols, tattr, " qwrite will write with new attributes ");
   qwritec(7, 1, crtcols, tattr, " that you specify direct to the screen.");
   sleep(3);
   qwritec(18, 1, crtcols, -1, " qwrite will also use existing attributes ");
   qwritec(19, 1, crtcols, -1, "    when you do not even know or care.    ");
                         /*  highlight the word 'existing'  */
   qattrc(18, 6, crtcols + 5, 1, 10, (LIGHTRED << 4) + WHITE);
   sleep(4);
   qwritec(21, 1, crtcols, tattr, " Say Goodbye to this screen. ");
   sleep(2);
   /*  --- Disintigrate Screen ---  */

   for (i = 1; i <=7500; i++) {
     row = random(25) +1;
     col = random(crtcols) + 1;
     qfill(row,col,1,1,BLACK, ' ');
   }

 /*  --- Qwrite with Reals Demo ---  */
   qfill(1, 1, 25, crtcols, YELLOW, ' '); /*   Clear Screen  */
   qwritec(2, 1, crtcols, -1, "qwritev with TURBO-C's sprintf will write");
   qwritec(3, 1, crtcols, -1, "reals and integers faster:");
   sleep(4);
   rnum = 1.2345678901;
   for (col = 0; col <= (crtcols / 20) - 1; col++)  {
      for (row = 5; row <= 24; row++) {
         rnum = rnum + 1.0;
         sprintf(numstr,"%e",rnum);
         qwritev(row, col * 20 + 4, -1, numstr);
      }
   }
   sleep(5);

 /*  --- Centering Demo ---  */
   qfill(1, 1, 25, crtcols, LIGHTGRAY << 4, ' '); /*   Clear Screen  */
   qwritec(2, 1, crtcols, -1, "qwritec and qwritecv will automatically");
   qwritec(3, 1, crtcols, -1, "center your data ...");
   qwritec(4, 1, crtcols, -1, "(ODD breaks are shifted to the left.)");
   sleep(4);

   /*  - Set up columns for varying column modes -  */
   coll[1] = 1;
   colr[1] = crtcols;
   if (crtcols < 80) {
      coll[0] = coll[1];
      coll[2] = crtcols / 2;
      colr[0] = colr[1];
      colr[2] = crtcols / 2;
   }
   else {
      coll[0] = 3;
      colr[0] = 26;
      coll[2] = crtcols - 14;
      colr[2] = crtcols - 14;
   }

   qwritec(7, coll[0], colr[0], -1, "between margins ...");
   qbox(8, (coll[0] + (colr[0] >> 1)) - 14, 15, 26, WHITE, LIGHTGRAY, doublebr
   sleep(2);
   for (row = 11; row <= 19; row++)
      qwritecv(row, coll[0], colr[0], -1, data[row - 11]);
   sleep(2);

   qwritec(7, coll[1], colr[1], -1, "between two columns ...");
   qfillc(9, coll[1], colr[1], 13, 24, YELLOW, ' '); /*   Clear window  */
   for (row = 9; row <= 21; row++)
      qwritec(row, coll[1], colr[1], -1, "><"); /*   Show two columns   */
   sleep(2);
   for (row = 11; row <= 19; row++)
      qwritecv(row, coll[1], colr[1], LIGHTRED, data[row - 11]);
   sleep(2);

   qwritec(7, coll[2], colr[2], -1, "or on a center line ...");
   qfillc(8, coll[2], colr[2], 15, 27, LIGHTGRAY << 4, ' '); /*   Clear window
   for (row = 9; row <= 21; row++) /*   Show center line   */
      qwritec(row, coll[2], colr[2], (LIGHTGRAY << 4) + WHITE, "|");
   sleep(2);
   for (row = 11; row <= 19; row++)
      qwritecv(row, coll[2], colr[2], -1, data[row - 11]);
   sleep(5);

 /*  --- Qfill Demo ---  */
   qfill(1, 1, 25, crtcols, WHITE, ' '); /*   Clear Screen  */
   qwritec(2, 1, crtcols, -1, "qfill as well as qattr can fill");
   qwritec(3, 1, crtcols, -1, "your screen in several ways.");
   sleep(3);

   qwritec(7, 1, crtcols, -1, "by rows ...");
   sleep(2);
   for (row = 9; row <= 24; row++)
      qfill(row, 2, 1, crtcols - 2, 9 + row, (char)(row + 56));
   sleep(3);

   qfill(7, 1, 19, crtcols, WHITE, ' '); /*   Clear Lines  */
   qwritec(7, 1, crtcols, -1, "by columns ...");
   sleep(2);
   for (col = 2; col <= crtcols - 2; col++)
      qfill(9, col, 16, 1, 16 + col, (char)(col + 63));
   sleep(3);

   qfill(7, 1, 19, crtcols, WHITE, ' '); /*   Clear Lines  */
   qwritec(7, 1, crtcols, -1, "or by row-by-column blocks ...");
   sleep(2);
   qfill(9, 2, 16, crtcols - 2, (BLUE << 4) + YELLOW, '!');
   sleep(4);

 /*  --- Qbox demo ---  */
   qfill(1, 1, 25, crtcols, LIGHTGRAY << 4, ' '); /*   Clear Screen  */
   qwritec(2, 1, crtcols, -1, "qbox is an application procedure made");
   qwritec(3, 1, crtcols, -1, "from qwritev and qfill.  Together they");
   qwritec(4, 1, crtcols, -1, "can make windows with borders easy.");
   sleep(3);
   qwritec(14, 1, crtcols, -1, "How about 1000 of them? ... ");
   sleep(2);
   colmax = crtcols - 21;
   for (i = 1; i <= 1000; i++) {
      row = random(10) + 6;
      col = random(colmax) + 2;
      brdrattr = random(128);
      wndwattr = random(128);
      qbox(row, col, 10, 20, brdrattr, wndwattr, doublebrdr);
   }
   sleep(5);

 /*  --- Block Transfer and PopUp Demo ---  */
   qfill(1, 1, 25, crtcols, YELLOW, '?'); /*   Clear Screen  */
   qfillc(10, 1, crtcols, 6, 40, BROWN << 4, ' '); /*   Clear Block  */
   qwritec(11, 1, crtcols, -1, "qstore will save and restore");
   qwritec(12, 1, crtcols, -1, "Row-by-Column blocks on your display.");
   qwritec(13, 1, crtcols, -1, "It is so fast, I have to slow it down");
   qwritec(14, 1, crtcols, -1, "so you can see it.");
   sleep(4);
   blkrow = 8;
   blkcol = (crtcols / 2) - 9;
   qstore(blkrow, blkcol, 10, 20, savedblock);
   /*  --- Make a Pop Up Menu ---  */
   qbox(blkrow, blkcol, 10, 20, (BLUE << 4) + YELLOW, (BLUE << 4) + BROWN, dou
   qwritec(blkrow + 4, blkcol, blkcol + 20, -1, "Pop Up");
   qwritec(blkrow + 5, blkcol, blkcol + 20, -1, "Menu");
   /*  --- End of Pop Up Menu ---  */
   qstore(blkrow, blkcol, 10, 20, popupblock);
   sleep(3);
   colmax = crtcols - 20;
   for (i = 1; i <= 30; i++) {
     for (j = 0; j <=WAIT; j++);
      qrestore(blkrow, blkcol, 10, 20, savedblock);
      blkrow = random(15) + 1;
      blkcol = random(colmax) + 1;
      qstore(blkrow, blkcol, 10, 20, savedblock);
      qrestore(blkrow, blkcol, 10, 20, popupblock);
   }

 /*  --- Page Demo ---  */
   if (maxpage > 0) {
      qpage(1);
      qwritepage(1);
      tattr = (BLUE << 4) + YELLOW;
      qwritec(20, 1, crtcols, tattr, " Remember this page?  ");
      qwritec(21, 1, crtcols, tattr, " It wasn't destroyed, but saved using ")
      qwritec(22, 1, crtcols, tattr, " qstore/qrestore and placed on a new pag
      sleep(6);
      qwritepage(0);
      qpage(0);
   }

 /*  --- Attribute Demo ---  */
   qfill(1, 1, 25, crtcols, (GREEN << 4) + GREEN, ' '); /*   Clear Screen  */
   tattr = (GREEN << 4) + WHITE;
   qwritec(2, 1, crtcols, tattr, "Q Screen Utilities is hiding strings on");
   qwritec(3, 1, crtcols, tattr, "your screen ...");
   cols = crtcols / 20;
   if (qwait == 0)
      tattr = 0;
   else
      tattr = (GREEN << 4) + GREEN;
   for (col = 0; col <= cols - 1; col++)
      for (row = 5; row <= 20; row++)
         qwritev(row, 20 * col + 1, tattr, data[3]);
   sleep(3);

   qfill(2, 1, 2, crtcols, -1, ' '); /*   Clear Lines  */
   tattr = (GREEN << 4) + BLACK;
   qwritec(2, 1, crtcols, tattr, "qattr can show them -");
   qwritec(3, 1, crtcols, tattr, "by merely changing the attribute!");
   sleep(3);

   /*  --- Try using Turbo's color procedures this time ---  */
   qattr(5, 1, 16, crtcols, tattr); /*   Reveal Data  */
   sleep(3);

   qfill(2, 1, 2, crtcols, -1, ' '); /*   Clear Lines  */
   qwritec(2, 1, crtcols, tattr, "Or even just emphasize what's seen ...");
   for (i = 1; i <= 100; i++) {
     row = random(16) + 5;
     col = random(cols) * 20 + 1;
     qattr(row, col, 1, 20, 46);
     for (j=0; j<=WAIT-7500; j++);
     qattr(row, col, 1, 20, 32);
   }
   for (i = 1; i <= cols; i++) /*   Emphasize Data  */
     qattr(5 * i, (i - 1) * 20 + 1, 1, 20, (LIGHTGREEN << 4) + YELLOW);
   tattr = wiattr(YELLOW,GREEN);
   qwritec(24, 1, crtcols, tattr, " Original TEAMWARE concept (C) 86,87 James
   qwritec(23, 1, crtcols, tattr, " TURBO-C Version (C) 1987 Michael G. Mlacha
   gotorc(21, 1);
   oldcursor = cursorchange(oldcursor);
 }

 int random(seed)
 {
   int hold;

      hold= rand();
      if (hold > 127)
        hold = hold % 127;
      hold = hold % seed;
    return(hold);
 }



 QLIB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\TCLIB\QLIB.C


 /* Qlib.c
    Property of Borland International.
    Creates files readable by the Borland linker TLINK.
    Written by Roger Schlafly. (Compuserve: 76067,511)
    Compile in Turbo C with
      tcc -mc -w -p -O -Z -M -Id:\c -Ld:\c qlib
    (assuming Turbo C is in the directory d:\c.)

 This programs creates .LIB files that work with TLINK.
 It can be used as a primitive substitute for the librarians
 sold by Microsoft, Phoenix, Lattice.

 The Microsoft .LIB format is not documented and is not known
 to Borland at this time.  The Borland linker TLINK accepts
 files created with the Microsoft librarian, but it is actually
 quite simple minded in what it accepts to be a .LIB file.

 .LIB files created by QLIB work with TLINK, but not with the
 Microsoft linker.  QLIB does have any of the various options for
 modifying an existing .LIB file; it will only create one from
 scratch.  QLIB is, however, faster than the Microsoft librarian.

 Borland may someday have a librarian which supports the Microsoft
 format.  If and when that happens, TLINK may no longer support
 the format that QLIB uses.

 */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <io.h>
 #include <dos.h>
 #define Static static

 Static FILE *rspf = 0;
 Static FILE *libf = 0;
 Static FILE *fp = 0;
 Static char name[81];

 #define TAB \011

 char delimiters[] = " \n\011,;\r";
 #define iswhite(x)        (strchr(delimiters,(x)) != 0)

 int gettoken(void)
 /* return 1 on success
    put token in 'name'
 */
 {        int i, c;
         for (i=0; i<80; ++i)
         {        c = getc(rspf);
                 if (c == -1) if (i == 0) return 0; else break;
                 if (i == 0 && iswhite(c)) { i = -1; continue;}
                 name[i] = (char) c;
                 if (iswhite(c)) break;}
         name[i] = 0;
         return 1;}

 char *libname;

 void fatal(char *s)
 {
         puts(s);
         /* don't leave partially written .LIB file on disk */
         if (libf != NULL) fclose(libf);
         if (libname != NULL) unlink(libname);
         exit(1);
 }

 Static int cdecl handler(void)
 /* control-break handler
 */
 {
   fatal("Interrupted.");
   return 0;}

 void iofail(char *s)
 {
         printf("%s",s);
         fatal(": disk error");
 }

 char *append(char *s, char *t)
 {
         int n;
         char *p;
         n = strlen(s) + strlen(t) + 1;
         p = malloc(n);
         if (p == NULL) fatal("insufficient memory");
         strcpy(p,s);
         strcat(p,t);
         return p;
 }

 char *buf;
 #define MAX (unsigned) 30000

 unsigned char begin[] = { 0xA4, 1, 0, 0, };
 unsigned char end[]   = { 0xA6, 1, 0, 0, };

 int n;
 char *fname;
 int argi;

 cdecl main(argc,argv)
 char *argv[];
 {
         if (argc < 3)
         {
                 puts("Borland quick librarian, version 0.20.");
                 puts("Usage: QLIB  libname  objfiles");
                 puts("where objfiles is a series of OBJ file names,");
                 puts("or is @name, where name is an ascii file of OBJ file na
                 puts("where objfiles is an ascii file of OBJ file names.");
                 puts(".LIB and .OBJ extensions added automatically.");
                 puts("QLIB creates a .LIB consisting of those .OBJ files.");
                 exit(0);
         }

         ctrlbrk(handler);
         libname = append(argv[1],".LIB");
         libf = fopen(libname,"wb");
         if (libf == NULL) printf("%s",libname), fatal(": cannot open");
         printf("Creating %s\n",libname);
         if (argv[2][0] == '@')
         {
                 rspf = fopen(argv[2]+1,"r");
                 if (rspf == NULL)
                         printf("%s",argv[2]), fatal(": cannot open");
         }
         argi = rspf == NULL ? 2 : 0;

         buf = malloc(MAX);
         if (buf == NULL) fatal("insufficient memory");

         fwrite(begin,1,4,libf);

 while (1)
 {
         if (argi)
         {
                 if (argi >= argc) break;
                 strcpy(name,argv[argi++]);
         }
         else if (!gettoken()) break;

         fname = append(name,".OBJ");
         fp = fopen(fname,"rb");
         if (fp == NULL) iofail(fname);
 #ifdef        Portable
         if (fseek(fp,0L,2)) iofail(fname);
         n = ftell(fp);
         if (fseek(fp,0L,0)) iofail(fname);
         n = fread(buf,1,MAX,fp);
        /* TURBO C */
         /* manual says n = 0 if at EOF, but don't believe it. */
         n = _read(fileno(fp),buf,MAX);
 #endif
         if (n == MAX) fatal("OBJ file too large");
         if (fclose(fp)) iofail(fname);
         printf("Adding %s, %d bytes.\n",fname,n);
         fwrite(buf,1,n,libf);
 }
         fwrite(end,1,4,libf);
         if (fclose(libf)) iofail(libname);
         exit(0);
 }


 QSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\QSORT.C

 /* 1.0  11-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 LOCAL char *_base;
 LOCAL unsigned _width;
 LOCAL int (*_compare)();

 /************************************************************************/
         VOID
 qsort(b, n, w, comp)        /* Quicksort n elements beginning at base b, of
                            width w characters each, using comparison
                            function comp(p, q), which is greater than 0
                            if, and only if, elements *p and *q are
                            out of sort.
 /*----------------------------------------------------------------------*/
 char *b;
 unsigned n, w;
 int (*comp)();
 {
         VOID _swap();
         int _comp();

         _base = b;
         _width = w;
         _compare = comp;
         sortQ(n, _comp, _swap);
 }

 /************************************************************************/
         LOCAL VOID
 _swap(i, j)                /* exchange elements i and j of base array.

 /*----------------------------------------------------------------------*/
 unsigned i, j;
 {
         char *I, *J, c;
         unsigned k;

         I = _base + _width * i;
         J = _base + _width * j;
         for (k = 0; k < _width; k++)
         {        c = *I;
                 *I++ = *J;
                 *J++ = c;
         }
 }
 /*\p**********************************************************************/
         LOCAL
 _comp(i, j)        /* convert comparison access from index to pointer.

 /*----------------------------------------------------------------------*/
 unsigned i, j;
 {
         char *I, *J;

         I = _base + _width * i;
         J = _base + _width * j;
         return ((*_compare)(I, J));
 }


 QSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\QSORT.C

 #include <stdio.h>

 char        *_qbuf = NULL;                /* pointer to storage for qsort() *

 #define        PIVOT        ((i+j)>>1)

 static _wqsort(base, lo, hi, cmp)
 register int *base;
 register int lo;
 register int hi;
 register int (*cmp)();
 {
         int k;
         register int i, j, t;
         register int *p = &k;

         while(hi > lo) {
                 i = lo;
                 j = hi;
                 t = PIVOT;
                 *p = base[t];
                 base[t] = base[i];
                 while(i < j) {
                         while(((*cmp)((base+j), p)) > 0)
                                 --j;
                         base[i] = base[j];
                         while((i < j) && (((*cmp)((base+i), p)) <= 0))
                                 ++i;
                         base[j] = base[i];
                 }
                 base[i] = *p;
                 if((i - lo) < (hi - i)) {
                         _wqsort(base, lo, (i - 1), cmp);
                         lo = i + 1;
                 }
                 else {
                         _wqsort(base, (i + 1), hi, cmp);
                         hi = i - 1;
                 }
         }
 }

 static _lqsort(base, lo, hi, cmp)
 register long *base;
 register int lo;
 register int hi;
 register int (*cmp)();
 {
         long k;
         register int i, j, t;
         register long *p = &k;

         while(hi > lo) {
                 i = lo;
                 j = hi;
                 t = PIVOT;
                 *p = base[t];
                 base[t] = base[i];
                 while(i < j) {
                         while(((*cmp)((base+j), p)) > 0)
                                 --j;
                         base[i] = base[j];
                         while((i < j) && (((*cmp)((base+i), p)) <= 0))
                                 ++i;
                         base[j] = base[i];
                 }
                 base[i] = *p;
                 if((i - lo) < (hi - i)) {
                         _lqsort(base, lo, (i - 1), cmp);
                         lo = i + 1;
                 }
                 else {
                         _lqsort(base, (i + 1), hi, cmp);
                         hi = i - 1;
                 }
         }
 }

 static _nqsort(base, lo, hi, size, cmp)
 register char *base;
 register int lo;
 register int hi;
 register int size;
 register int (*cmp)();
 {
         register int i, j;
         register char *p = _qbuf;

         while(hi > lo) {
                 i = lo;
                 j = hi;
                 p = (base+size*PIVOT);
                 blkcpy(_qbuf, p, size);
                 blkcpy(p, (base+size*i), size);
                 p = _qbuf;
                 while(i < j) {
                         while(((*cmp)((base+size*j), p)) > 0)
                                 --j;
                         blkcpy((base+size*i), (base+size*j), size);
                         while((i < j) && (((*cmp)((base+size*i), p)) <= 0))
                                 ++i;
                         blkcpy((base+size*j), (base+size*i), size);
                 }
                 blkcpy((base+size*i), p, size);
                 if((i - lo) < (hi - i)) {
                         _nqsort(base, lo, (i - 1), size, cmp);
                         lo = i + 1;
                 }
                 else {
                         _nqsort(base, (i + 1), hi, size, cmp);
                         hi = i - 1;
                 }
         }
 }

 qsort(base, num, size, cmp)
 char *base;
 int num;
 int size;
 int (*cmp)();
 /*
  *        Perform a recursive quick-sort on an array starting at <base>
  *        containing <num> elements of <size> bytes each.  The function
  *        pointed to by <cmp> is used to compare elements.  Pointers to
  *        two items in the array are passed to the function, which must
  *        return a number representing their relationship as follows:
  *                negative        item1 < item2
  *                0                item1 == item2
  *                positive        item1 > item2
  *        The qsort() function requires the use of a temporary data area
  *        that is large enough to hold <size> bytes.  The default space
  *        provided is 128 bytes large.  If your record size is larger than
  *        128 bytes, YOU MUST provide an alternative storage area.  The
  *        global variable "_qbuf" points to the storage qsort() will use.
  *        Setting "_qbuf" to NULL restores use of the internal buffer.
  *        This routine is optimized to avoid N*N sort times for ordered data.
  */
 {
         char _qtemp[128];

         if(_qbuf == NULL)
                 _qbuf = _qtemp;
         if(size == 2)
                 _wqsort(base, 0, num-1, cmp);
         else if(size == 4)
                 _lqsort(base, 0, num-1, cmp);
         else
                 _nqsort(base, 0, num-1, size, cmp);
         if(_qbuf == _qtemp)
                 _qbuf = NULL;
 }


 QSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\QSORT.C

 /* qsort - quick sort
   qsort(n,comp,swap)
  unsigned n;
  int (*comp)();
  int (*swap)();
                   ***** see bsort for parameters
 */
 #define void int

 static int(*_comp)(), (*_swap)();

 void qsort(n,comp,swap)
 unsigned n;

 int (*comp)();
 int (*swap)();

 {
         _comp =comp;
             _swap=swap;
         _quick(0,n-1);
 }

 static void _quick(lb,ub)

 unsigned lb,ub;
 {
         unsigned j;
         unsigned _rearr();
         if(lb<ub) {
                 if(j=_rearr(lb,ub))
                 _quick(lb,j-1);
                 _quick(j+1,ub);
         }
 }

 static unsigned _rearr(lb,ub)
 unsigned lb,ub;

 {
         do {
                 while(ub > lb && (*_comp)(ub,lb) >=0)
                         ub--;
                 if(ub != lb) {
                         (*_swap)(ub,lb);
                         while(lb<ub && (*_comp)(lb,ub)<=0)
                         lb++;
                 if(lb != ub)
                         (*_swap)(lb,ub);
                 }
         } while(lb != ub);
         return(lb);
 }


 QSORTNET.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\QSORTNET.C

 Article 2718 (12 more) in net.sources:
 From: duane@anasazi.UUCP (Duane Morse)
 Subject: qsort source
 Message-ID: <276@anasazi.UUCP>
 Date: 29 Aug 85 14:04:07 GMT
 Date-Received: 2 Sep 85 06:12:20 GMT
 Distribution: net
 Organization: Anasazi, Phoenix Az.
 Lines: 182

 --MORE--(14%)
 Here is my own version of qsort for those of you interested in sorting
 algorithms.
 --------------------SUBROUTINE FOLLOWS, THEN MY SIGNATURE -------------
 /*TITLE pqsort.c - quicksort algorithm 1/10/85 10:04:32 */

 static char *version = "@(#)pqsort.c    1.1 1/10/85 10:04:32";

 /*
 ** void pqsort(vec, nel, esize, compptr)
 **
 **  Quick Sort routine.
 **  Based on Knuth's ART OF COMPUTER PROGRAMMING, VOL III, pp 114-117.
 **  For some unknown reason, this works faster than the library's qsort.
 **
 ** Parameters:
 **  vec = points to beginning of structure to sort.
 **  nel = number of elements.
 **  esize = size of an element.
 **  compptr = points to the routine for comparing two elements.
 **
 ** Returns:
 **  Nothing.
 */

 static int elsize;              /* Element size */
 static int (*comp)();           /* Address of comparison routing */

 static void memexch(), mysort();

 void pqsort(vec, nel, esize, compptr)

 unsigned char *vec;
 int nel;
 int esize;
 int (*compptr)();

 {
   /* If less than 2 items, done */
   if (nel < 2)
     return;

   elsize = esize;
   comp = compptr;

   /* Call the real worker */
   mysort(vec, nel);
 }
 /*PAGE*/
 /*
 ** void mysort(vec, nel)
 **
 **  The real quick sort routine.
 **
 ** Parameters:
 **  vec = points to beginning of structure to sort.
 **  nel = number of elements.
 **
 **  esize = size of an element.
 **  compptr = points to the routine for comparing two elements.
 **
 ** Returns:
 **  Nothing.
 */

 static void mysort(vec, nel)

 unsigned char *vec;
 int nel;

 {
   register short i, j;
   register unsigned char *iptr, *jptr, *kptr;

   /*
   ** If 2 items, check them by hand.
   */

 begin:
   if (nel == 2) {
     if ((*comp)(vec, vec + elsize) > 0)
       memexch(vec, vec + elsize, elsize);
     return;
   }

   /*
   ** Initialize for this round.
   */

   j = nel;
   i = 0;
   kptr = vec;
   iptr = vec;
   jptr = vec + elsize * nel;
 /*PAGE*/
   while (--j > i) {

     /*
     ** From the righthand side, find the first value that should be
     ** to the left of k.
     */

     jptr -= elsize;
     if ((*comp)(jptr, kptr) > 0)
       continue;

     /*
     ** Now from the lefthand side, find the first value that should be
     ** to the right of k.
     */

     iptr += elsize;
     while(++i < j && (*comp)(iptr, kptr) <= 0)
       iptr += elsize;

     if (i >= j)
       break;

     /*
     ** Exchange the two items.
     ** k will eventually end up between them.
     */

     memexch(jptr, iptr, elsize);
   }

   /*
   ** Move item 0 into position.
   */

   memexch(vec, iptr, elsize);

   /*
   ** Now sort the two partitions.
   */

   if ((nel -= (i + 1)) > 1)
     mysort(iptr + elsize, nel);

   /*
   ** To save a little time, just start the routine over by hand.
   */

   if (i > 1) {
     nel = i;
     goto begin;
   }
 }
 /*PAGE*/
 /*
 ** memexch(s1, s2, n)
 **
 **  Exchange the contents of two vectors.
 **
 ** Parameters:
 **  s1 = points to one vector.
 **  s2 = points to another vector.
 **  n = size of the vectors in bytes.
 **
 ** Returns:
 **  Nothing.
 */

 static void memexch(s1, s2, n)

 register unsigned char *s1;
 register unsigned char *s2;
 register int n;

 {
   register unsigned char c;

   while (n--) {
     c = *s1;
     *s1++ = *s2;
     *s2++ = c;
   }
 }
 ------------------------------------------------------
 --

 Duane Morse     ...!noao!terak!anasazi!duane
 (602) 275-0302


 RAND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\RAND.C

 #include <stdio.h>
 #include <osbind.h>

 rand()
 {
         return((Random() >> 3) & 0x7FFF);
 }


 RANDEXP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RANDEXP.C

 /* 1.0  01-22-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  * Computes a sample value from an exponential distribution characterized
  * by unit mean, i.e.,
  *
  *                p(x) = exp(-x)
  *
  * The method is by inversion of the cumulative probability function.  See
  * also
  *
  * Knuth, D. E., FUNDAMENTAL ALGORITHMS, Vol II, "Seminumerical Algorithms"
  * Addison-Wesley Pub. Co.,  page 128.
  *
  */

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         double
 randexp()                        /* Return an exponentially distributed rando
                            value with unit mean.                        */
 /*----------------------------------------------------------------------*/
 {
         double log(), random();

         return (-log(random()));
 }


 RANDNORM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RANDNORM.C

 /* 1.0  11-12-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Normal-Distribution Random Number Generator.
  *
  * Computes a sample value from a normal distribution characterized by
  * zero mean and unit standard deviation.  Uses "Box-Muller polar method"
  * for calculation of normal deviates,
  *
  * Box, G. E. P., and Muller, M. E., "A Note on the Generation of Normal
  * Deviates," ANNALS OF MATH. STAT., Vol. 29, pp. 610-611, 1958.
  *
  * Refined in
  *
  * Knuth, D. E., FUNDAMENTAL ALGORITHMS, Vol II, "Seminumerical Algorithms,"
  * Addison-Wesley Pub. Co., page 117.
  *
  */

 #include "defs.h"
 #include "stdtyp.h"
 #include "mathtyp.h"

 /************************************************************************/
         double
 randnorm()                /* Return a normally distributed random value
                            with zero mean and unit standard deviation.
 /*----------------------------------------------------------------------*/
 {
         LOCAL BOOL first = TRUE;
         double d, v1, v2;

         if (first--)
         {        do
                 {        v1 = 2.0 * random() - 1.0;
                         v2 = 2.0 * random() - 1.0;
                         /* v1 and v2 are each uniform on [-1, 1] */
                         d = v1 * v1 + v2 * v2;
                 } while ((d <= 0.0) OR (d >= 1.0));
                 /* now, the point (v1, v2) is uniform inside the unit circle,
                  * excluding the origin.
                  */
                 d = sqrt(-2.0 * log(d) / d);
                 v1 *= d;
                 v2 *= d;
                 return (v1);
         }
         else
         {        first = TRUE;
                 return (v2);
         }
 }


 RANDOM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RANDOM.C

 /* 1.1  10-16-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Uniform Random Number Generator, programmed using the algorithm
  *        given in:
  *
  *        Tausworthe, Robert C., STANDARDIZED DEVELOPMENT OF COMPUTER
  *        SOFTWARE, Part 2, Appendix L, Example 3, Prentice-Hall, Inc.,
  *        Englewood Cliffs, NJ, 1979, pp. 499-506.
  *
  *        The generator uses the primitive polynomial over GF(2^521),
  *        f(x) = x^521 + x^32 + 1, found in Zierler, N., and Brillhart, J.,
  *        "On Primitive Polynomials (Mod 2), II," INFORMATION AND CONTROL,
  *        Volume 14, No. 6, pp. 566-569, June, 1969.
  *
  *        Numbers output by the generator are unsigned, uniformly distributed
  *        over 0..65535.  Numbers have no serial statistical correlation,
  *        adjacent numbers are uniformly distributed over the 32-cube, and
  *        runs-up/down of length up to 13 require more than 10^11 samples to
  *        show deviation from theoretical.  The period of the generator is
  *        slightly larger than 1.3 * 10^154.
  *
  *        For more information on Tausworthe random number generators, see;
  *
  *        Tausworthe, Robert C., "Random Numbers Generated by Linear Recurren
  *        Modulo 2," MATH COMP., Vol. XIX, No. 90, pp. 201-208, April 1965.
  *
  *        Toothill, J. P. R., "An Asymptotically Random Tausworthe Sequence,"
  *        ACM J., Vol. 20, No. 3, pp. 469-481, July 1973.
  *
  *        Toothill, J. P. R., et al., "The Runs-Up and -Down Performance of
  *        Tausworthe Pseudorandom Number Generators," ACM J., Vol. 18, No. 3,
  *        pp. 381-399, July 1971.
  *
  *----------------------------------------------------------------------*
  *
  *        The shift register of 521 bits requires 65.125 bytes, or 65 bytes
  *        plus one bit.  One register load then provides 32 16-bit numbers
  *        before it must be refilled.  The 32-bit tap is at a 4-byte shift
  *        from the first byte, and at 521 - 32 = 489 = (61 bytes + 1 bit)
  *        inverse shift from the end.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"

 /*----------------------------------------------------------------------*/

 MULTIPLIER        18829        /* This is 5^15 (mod 65536)                */
 PRESEED                0xe5a1        /* a number picked out of the air!

 /*\p--------------------------------------------------------------------*/

 LOCAL utiny shiftreg[66];                /* 521-bit shift register        */
 LOCAL utiny *randptr = shiftreg - 1;        /* initialized for not accessed
 LOCAL utiny *endreg = shiftreg + 62;        /* always points at 32nd number

 /************************************************************************/
         VOID
 randize(seed)                        /* Randomize the generator using seed.
                                    See algorithm for seeding values.        *
 /*----------------------------------------------------------------------*/
 {
         int i, *rseed;

         if (seed IS 0)
                 seed = PRESEED;
         else if (seed < 0)
         {        rseed = (int *) &shiftreg[16];
                 while ((seed = *(++rseed)) IS 0)
                         ;        /* find something non-zero, whatever.
         }
         for (i = 0; i < 66; i++)
                 /* assume no adverse reaction on integer overflow        */
         {        shiftreg[i++] = ((seed *= MULTIPLIER) &0xff);
                 shiftreg[i] = ((seed >> 8) & 0xff);
         }
         shiftreg[65] &= 0x80;        /* mask out bits beyond 521st.
         refill();        /* refill and reset randptr                        *
 }

 /************************************************************************/
         unsigned
 urandom()        /* Return the next random number.  If shift register is
                    depleted, refill the entire register.                */
 /*----------------------------------------------------------------------*/
 {
         unsigned r;

         if (randptr < shiftreg)
                 randize(0);        /* in case randize wasn't called first
         else if (randptr > endreg)
                 refill();        /* and reset randptr & randx
         r = UTINY(*randptr++);
         r += (UTINY(*randptr++) << 8);
         return (r);
 }
 /*\p*********************************************************************/
         double
 random()                /* Return a uniform random value in [0, 1].        */

 /*----------------------------------------------------------------------*/
 {
         unsigned urandom();

         return (urandom() / 65535.0);
 }

 /************************************************************************/
         LOCAL VOID
 refill()                        /* refill the shift register                *

 /*----------------------------------------------------------------------*/
 {
         utiny *p, *q, cy0, cy1;
         FAST int i;

         p = shiftreg;                        /* point at 1st byte.
         q = &p[4];                        /* shift 4 * 8 = 32,
         for (i = 0; i < 62; i++)        /* and mod-2 add the register
                 *p++ ^= *q++;                /* to the 32-bit shift.
         p--;                                /* p should now be at byte 61:
         q = shiftreg;                        /* first 489 bits are ok.
         cy0 = 0;                        /* set carry bit to zero        */
         for (i = 0; i < 4; i++)                /* for the remaining 32 bits:
         {        cy1 = ((*q & 1) ? 0x80 : 0); /* save carry for nxt shift*/
                 *p++ ^= (((*q++ >> 1) & 0x7f) | cy0);
                                         /* mod-2 add the 489-shifts        */
                 cy0 = cy1;                /* set carry for next shift
         }
         *p ^= cy0;                        /* and mod-2 the final bit.
         randptr = shiftreg;                /* point at the first number
 }


 RANDOM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\RANDOM\RANDOM.C

 /*
     test deck for random.asm  - random number generator
 */
 extern unsigned xrand;
 main()
 {
      unsigned random();
      int   i,j;

  /*  xrand = 23965;  */

      for (i=1; i != 10; ++i) {
           for (j=1; j != 5; ++j)
                printf("  %d\t",random());
           printf("\n");
      }
 }


 RANDOM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\RANDOM.C

 /*
  * This file contains the command processing functions for a number of random
  * commands. There is no functional grouping here, for sure.
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 int     tabsize;                        /* Tab size (0: use real tabs)  */

 /*
  * Set fill column to n.
  */
 setfillcol(f, n)
 {
         fillcol = n;
         mlwrite("[Fill column is %d]",n);
         return(TRUE);
 }

 /*
  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  * the character that is under the cursor (in hex), and the fraction of the
  * text that is before the cursor. The displayed column is not the current
  * column, but the column that would be used on an infinite width display.
  * Normally this is bound to "C-X =".
  */
 showcpos(f, n)
 {
         register LINE   *lp;                /* current line */
         register long   numchars;        /* # of chars in file */
         register int        numlines;        /* # of lines in file */
         register long   predchars;        /* # chars preceding point */
         register int        predlines;        /* # lines preceding point */
         register int    curchar;        /* character under cursor */
         int ratio;
         int col;
         int savepos;                        /* temp save for current offset *
         int ecol;                        /* column pos/end of current line */

         /* starting at the beginning of the buffer */
         lp = lforw(curbp->b_linep);

         /* start counting chars and lines */
         numchars = 0;
         numlines = 0;
         while (lp != curbp->b_linep) {
                 /* if we are on the current line, record it */
                 if (lp == curwp->w_dotp) {
                         predlines = numlines;
                         predchars = numchars + curwp->w_doto;
                         if ((curwp->w_doto) == llength(lp))
                                 curchar = '\n';
                         else
                                 curchar = lgetc(lp, curwp->w_doto);
                 }
                 /* on to the next line */
                 ++numlines;
                 numchars += llength(lp) + 1;
                 lp = lforw(lp);
         }

         /* if at end of file, record it */
         if (curwp->w_dotp == curbp->b_linep) {
                 predlines = numlines;
                 predchars = numchars;
         }

         /* Get real column and end-of-line column. */
         col = getccol(FALSE);
         savepos = curwp->w_doto;
         curwp->w_doto = llength(curwp->w_dotp);
         ecol = getccol(FALSE);
         curwp->w_doto = savepos;

         ratio = 0;              /* Ratio before dot. */
         if (numchars != 0)
                 ratio = (100L*predchars) / numchars;

         /* summarize and report the info */
         mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x",
                 predlines+1, numlines+1, col, ecol,
                 predchars, numchars, ratio, curchar);
         return (TRUE);
 }

 getcline()        /* get the current line number */

 {
         register LINE   *lp;                /* current line */
         register int        numlines;        /* # of lines before point */

         /* starting at the beginning of the buffer */
         lp = lforw(curbp->b_linep);

         /* start counting lines */
         numlines = 0;
         while (lp != curbp->b_linep) {
                 /* if we are on the current line, record it */
                 if (lp == curwp->w_dotp)
                         break;
                 ++numlines;
                 lp = lforw(lp);
         }

         /* and return the resulting count */
         return(numlines + 1);
 }

 /*
  * Return current column.  Stop at first non-blank given TRUE argument.
  */
 getccol(bflg)
 int bflg;
 {
         register int c, i, col;
         col = 0;
         for (i=0; i<curwp->w_doto; ++i) {
                 c = lgetc(curwp->w_dotp, i);
                 if (c!=' ' && c!='\t' && bflg)
                         break;
                 if (c == '\t')
                         col |= 0x07;
                 else if (c<0x20 || c==0x7F)
                         ++col;
                 ++col;
         }
         return(col);
 }

 /*
  * Set current column.
  */
 setccol(pos)

 int pos;        /* position to set cursor */

 {
         register int c;                /* character being scanned */
         register int i;                /* index into current line */
         register int col;        /* current cursor column   */
         register int llen;        /* length of line in bytes */

         col = 0;
         llen = llength(curwp->w_dotp);

         /* scan the line until we are at or past the target column */
         for (i = 0; i < llen; ++i) {
                 /* upon reaching the target, drop out */
                 if (col >= pos)
                         break;

                 /* advance one character */
                 c = lgetc(curwp->w_dotp, i);
                 if (c == '\t')
                         col |= 0x07;
                 else if (c<0x20 || c==0x7F)
                         ++col;
                 ++col;
         }

         /* set us at the new position */
         curwp->w_doto = i;

         /* and tell weather we made it */
         return(col >= pos);
 }

 /*
  * Twiddle the two characters on either side of dot. If dot is at the end of
  * the line twiddle the two characters before it. Return with an error if dot
  * is at the beginning of line; it seems to be a bit pointless to make this
  * work. This fixes up a very common typo with a single stroke. Normally boun
  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  */
 twiddle(f, n)
 {
         register LINE   *dotp;
         register int    doto;
         register int    cl;
         register int    cr;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         dotp = curwp->w_dotp;
         doto = curwp->w_doto;
         if (doto==llength(dotp) && --doto<0)
                 return (FALSE);
         cr = lgetc(dotp, doto);
         if (--doto < 0)
                 return (FALSE);
         cl = lgetc(dotp, doto);
         lputc(dotp, doto+0, cr);
         lputc(dotp, doto+1, cl);
         lchange(WFEDIT);
         return (TRUE);
 }

 /*
  * Quote the next character, and insert it into the buffer. All the character
  * are taken literally, with the exception of the newline, which always has
  * its line splitting meaning. The character is always read, even if it is
  * inserted 0 times, for regularity. Bound to "C-Q"
  */
 quote(f, n)
 {
         register int    s;
         register int    c;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         c = tgetc();
         if (n < 0)
                 return (FALSE);
         if (n == 0)
                 return (TRUE);
         if (c == '\n') {
                 do {
                         s = lnewline();
                 } while (s==TRUE && --n);
                 return (s);
         }
         return (linsert(n, c));
 }

 /*
  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  * tab into file.  If given argument, n, of zero, change to true tabs.
  * If n > 1, simulate tab stop every n-characters using spaces. This has to b
  * done in this slightly funny way because the tab (in ASCII) has been turned
  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  */
 tab(f, n)
 {
         if (n < 0)
                 return (FALSE);
         if (n == 0 || n > 1) {
                 tabsize = n;
                 return(TRUE);
         }
         if (! tabsize)
                 return(linsert(1, '\t'));
         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
 }

 #if        AEDIT
 detab(f, n)                /* change tabs to spaces */

 int f,n;        /* default flag and numeric repeat count */

 {
         register int inc;        /* increment to next line [sgn(n)] */

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *

         if (f == FALSE)
                 n = 1;

         /* loop thru detabbing n lines */
         inc = ((n > 0) ? 1 : -1);
         while (n) {
                 curwp->w_doto = 0;        /* start at the beginning */

                 /* detab the entire current line */
                 while (curwp->w_doto < llength(curwp->w_dotp)) {
                         /* if we have a tab */
                         if (lgetc(curwp->w_dotp, curwp->w_doto) == '\t') {
                                 ldelete(1, FALSE);
                                 insspace(TRUE, 8 - (curwp->w_doto & 7));
                         }
                         forwchar(FALSE, 1);
                 }

                 /* advance/or back to the next line */
                 forwline(TRUE, inc);
                 n -= inc;
         }
         curwp->w_doto = 0;        /* to the begining of the line */
         thisflag &= ~CFCPCN;        /* flag that this resets the goal column
         lchange(WFEDIT);        /* yes, we have made at least an edit */
         return(TRUE);
 }

 entab(f, n)                /* change spaces to tabs where posible */

 int f,n;        /* default flag and numeric repeat count */

 {
         register int inc;        /* increment to next line [sgn(n)] */
         register int fspace;        /* pointer to first space if in a run */
         register int ccol;        /* current cursor column */
         register char cchar;        /* current character */

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *

         if (f == FALSE)
                 n = 1;

         /* loop thru entabbing n lines */
         inc = ((n > 0) ? 1 : -1);
         while (n) {
                 curwp->w_doto = 0;        /* start at the beginning */

                 /* entab the entire current line */
                 fspace = -1;
                 ccol = 0;
                 while (curwp->w_doto < llength(curwp->w_dotp)) {
                         /* see if it is time to compress */
                         if ((fspace >= 0) && (nextab(fspace) <= ccol))
                                 if (ccol - fspace < 2)
                                         fspace = -1;
                                 else {
                 /* there is a bug here dealing with mixed space/tabed
                    lines.......it will get fixed                */
                                         backchar(TRUE, ccol - fspace);
                                         ldelete(ccol - fspace, FALSE);
                                         linsert(1, '\t');
                                         fspace = -1;
                                 }

                         /* get the current character */
                         cchar = lgetc(curwp->w_dotp, curwp->w_doto);

                         switch (cchar) {
                                 case '\t': /* a tab...count em up */
                                         ccol = nextab(ccol);
                                         break;

                                 case ' ':  /* a space...compress? */
                                         if (fspace == -1)
                                                 fspace = ccol;
                                         ccol++;
                                         break;

                                 default:   /* any other char...just count */
                                         ccol++;
                                         fspace = -1;
                                         break;
                         }
                         forwchar(FALSE, 1);
                 }

                 /* advance/or back to the next line */
                 forwline(TRUE, inc);
                 n -= inc;
         }
         curwp->w_doto = 0;        /* to the begining of the line */
         thisflag &= ~CFCPCN;        /* flag that this resets the goal column
         lchange(WFEDIT);        /* yes, we have made at least an edit */
         return(TRUE);
 }

 trim(f, n)        /* trim trailing whitespace from the point to eol */

 int f,n;        /* default flag and numeric repeat count */

 {
         register LINE *lp;        /* current line pointer */
         register int offset;        /* original line offset position */
         register int length;        /* current length */
         register int inc;        /* increment to next line [sgn(n)] */

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *

         if (f == FALSE)
                 n = 1;

         /* loop thru trimming n lines */
         inc = ((n > 0) ? 1 : -1);
         while (n) {
                 lp = curwp->w_dotp;                /* find current line text
                 offset = curwp->w_doto;                /* save original offse
                 length = lp->l_used;                /* find current length */

                 /* trim the current line */
                 while (length > offset) {
                         if (lgetc(lp, length-1) != ' ' &&
                             lgetc(lp, length-1) != '\t')
                                     break;
                         length--;
                 }
                 lp->l_used = length;

                 /* advance/or back to the next line */
                 forwline(TRUE, inc);
                 n -= inc;
         }
         lchange(WFEDIT);
         thisflag &= ~CFCPCN;        /* flag that this resets the goal column
         return(TRUE);
 }
 #endif

 /*
  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  * and then back up over them. Everything is done by the subcommand
  * procerssors. They even handle the looping. Normally this is bound to "C-O"
  */
 openline(f, n)
 {
         register int    i;
         register int    s;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);
         if (n == 0)
                 return (TRUE);
         i = n;                                  /* Insert newlines.     */
         do {
                 s = lnewline();
         } while (s==TRUE && --i);
         if (s == TRUE)                          /* Then back up overtop */
                 s = backchar(f, n);             /* of them all.         */
         return (s);
 }

 /*
  * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
  * indentation as specified.
  */
 newline(f, n)
 {
         register int    s;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);

         /* if we are in C mode and this is a default <NL> */
         if (n == 1 && (curbp->b_mode & MDCMOD) &&
             curwp->w_dotp != curbp->b_linep)
                 return(cinsert());

         /*
          * If a newline was typed, fill column is defined, the argument is no
          * negative, wrap mode is enabled, and we are now past fill column,
          * and we are not read-only, perform word wrap.
          */
         if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
             getccol(FALSE) > fillcol &&
             (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
                 execute(META|SPEC|'W', FALSE, 1);

         /* insert some lines */
         while (n--) {
                 if ((s=lnewline()) != TRUE)
                         return (s);
         }
         return (TRUE);
 }

 cinsert()        /* insert a newline and indentation for C */

 {
         register char *cptr;        /* string pointer into text to copy */
         register int tptr;        /* index to scan into line */
         register int bracef;        /* was there a brace at the end of line?
         register int i;
         char ichar[NSTRING];        /* buffer to hold indent of last line */

         /* grab a pointer to text to copy indentation from */
         cptr = &curwp->w_dotp->l_text[0];

         /* check for a brace */
         tptr = curwp->w_doto - 1;
         bracef = (cptr[tptr] == '{');

         /* save the indent of the previous line */
         i = 0;
         while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
                 && (i < NSTRING - 1)) {
                 ichar[i] = cptr[i];
                 ++i;
         }
         ichar[i] = 0;                /* terminate it */

         /* put in the newline */
         if (lnewline() == FALSE)
                 return(FALSE);

         /* and the saved indentation */
         i = 0;
         while (ichar[i])
                 linsert(1, ichar[i++]);

         /* and one more tab for a brace */
         if (bracef)
                 tab(FALSE, 1);

         return(TRUE);
 }

 insbrace(n, c)        /* insert a brace into the text here...we are in CMODE

 int n;        /* repeat count */
 int c;        /* brace to insert (always { for now) */

 {
         register int ch;        /* last character before input */
         register int i;
         register int target;        /* column brace should go after */

         /* if we are at the beginning of the line, no go */
         if (curwp->w_doto == 0)
                 return(linsert(n,c));

         /* scan to see if all space before this is white space */
         for (i = curwp->w_doto - 1; i >= 0; --i) {
                 ch = lgetc(curwp->w_dotp, i);
                 if (ch != ' ' && ch != '\t')
                         return(linsert(n, c));
         }

         /* delete back first */
         target = getccol(FALSE);        /* calc where we will delete to */
         target -= 1;
         target -= target % (tabsize == 0 ? 8 : tabsize);
         while (getccol(FALSE) > target)
                 backdel(FALSE, 1);

         /* and insert the required brace(s) */
         return(linsert(n, c));
 }

 inspound()        /* insert a # into the text here...we are in CMODE */

 {
         register int ch;        /* last character before input */
         register int i;

         /* if we are at the beginning of the line, no go */
         if (curwp->w_doto == 0)
                 return(linsert(1,'#'));

         /* scan to see if all space before this is white space */
         for (i = curwp->w_doto - 1; i >= 0; --i) {
                 ch = lgetc(curwp->w_dotp, i);
                 if (ch != ' ' && ch != '\t')
                         return(linsert(1, '#'));
         }

         /* delete back first */
         while (getccol(FALSE) >= 1)
                 backdel(FALSE, 1);

         /* and insert the required pound */
         return(linsert(1, '#'));
 }

 /*
  * Delete blank lines around dot. What this command does depends if dot is
  * sitting on a blank line. If dot is sitting on a blank line, this command
  * deletes all the blank lines above and below the current line. If it is
  * sitting on a non blank line then it deletes all of the blank lines after
  * the line. Normally this command is bound to "C-X C-O". Any argument is
  * ignored.
  */
 deblank(f, n)
 {
         register LINE   *lp1;
         register LINE   *lp2;
         long nld;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         lp1 = curwp->w_dotp;
         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
                 lp1 = lp2;
         lp2 = lp1;
         nld = 0;
         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
                 ++nld;
         if (nld == 0)
                 return (TRUE);
         curwp->w_dotp = lforw(lp1);
         curwp->w_doto = 0;
         return (ldelete(nld, FALSE));
 }

 /*
  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  * of the previous line. Assumes tabs are every eight characters. Quite simpl
  * Figure out the indentation of the current line. Insert a newline by callin
  * the standard routine. Insert the indentation by inserting the right number
  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  * subcomands failed. Normally bound to "C-J".
  */
 indent(f, n)
 {
         register int    nicol;
         register int    c;
         register int    i;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);
         while (n--) {
                 nicol = 0;
                 for (i=0; i<llength(curwp->w_dotp); ++i) {
                         c = lgetc(curwp->w_dotp, i);
                         if (c!=' ' && c!='\t')
                                 break;
                         if (c == '\t')
                                 nicol |= 0x07;
                         ++nicol;
                 }
                 if (lnewline() == FALSE
                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
                         return (FALSE);
         }
         return (TRUE);
 }

 /*
  * Delete forward. This is real easy, because the basic delete routine does
  * all of the work. Watches for negative arguments, and does the right thing.
  * If any argument is present, it kills rather than deletes, to prevent loss
  * of text if typed with a big argument. Normally bound to "C-D".
  */
 forwdel(f, n)
 {
         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (backdel(f, -n));
         if (f != FALSE) {                       /* Really a kill.       */
                 if ((lastflag&CFKILL) == 0)
                         kdelete();
                 thisflag |= CFKILL;
         }
         return (ldelete((long)n, f));
 }

 /*
  * Delete backwards. This is quite easy too, because it's all done with other
  * functions. Just move the cursor back, and delete forwards. Like delete
  * forward, this actually does a kill if presented with an argument. Bound to
  * both "RUBOUT" and "C-H".
  */
 backdel(f, n)
 {
         register int    s;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (forwdel(f, -n));
         if (f != FALSE) {                       /* Really a kill.       */
                 if ((lastflag&CFKILL) == 0)
                         kdelete();
                 thisflag |= CFKILL;
         }
         if ((s=backchar(f, n)) == TRUE)
                 s = ldelete((long)n, f);
         return (s);
 }

 /*
  * Kill text. If called without an argument, it kills from dot to the end of
  * the line, unless it is at the end of the line, when it kills the newline.
  * If called with an argument of 0, it kills from the start of the line to do
  * If called with a positive argument, it kills from dot forward over that
  * number of newlines. If called with a negative argument it kills backwards
  * that number of newlines. Normally bound to "C-K".
  */
 killtext(f, n)
 {
         register LINE   *nextp;
         long chunk;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
                 kdelete();                      /* last wasn't a kill.  */
         thisflag |= CFKILL;
         if (f == FALSE) {
                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
                 if (chunk == 0)
                         chunk = 1;
         } else if (n == 0) {
                 chunk = curwp->w_doto;
                 curwp->w_doto = 0;
         } else if (n > 0) {
                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
                 nextp = lforw(curwp->w_dotp);
                 while (--n) {
                         if (nextp == curbp->b_linep)
                                 return (FALSE);
                         chunk += llength(nextp)+1;
                         nextp = lforw(nextp);
                 }
         } else {
                 mlwrite("neg kill");
                 return (FALSE);
         }
         return(ldelete(chunk, TRUE));
 }

 setmode(f, n)        /* prompt and set an editor mode */

 int f, n;        /* default and argument */

 {
         adjustmode(TRUE, FALSE);
 }

 delmode(f, n)        /* prompt and delete an editor mode */

 int f, n;        /* default and argument */

 {
         adjustmode(FALSE, FALSE);
 }

 setgmode(f, n)        /* prompt and set a global editor mode */

 int f, n;        /* default and argument */

 {
         adjustmode(TRUE, TRUE);
 }

 delgmode(f, n)        /* prompt and delete a global editor mode */

 int f, n;        /* default and argument */

 {
         adjustmode(FALSE, TRUE);
 }

 adjustmode(kind, global)        /* change the editor mode status */

 int kind;        /* true = set,                false = delete */
 int global;        /* true = global flag,        false = current buffer flag
 {
         register char *scan;                /* scanning pointer to convert pr
         register int i;                        /* loop index */
         register status;                /* error return on input */
 #if        COLOR
         register int uflag;                /* was modename uppercase?
 #endif
         char prompt[50];        /* string to prompt user with */
         char cbuf[NPAT];                /* buffer to recieve mode name into *

         /* build the proper prompt string */
         if (global)
                 strcpy(prompt,"Global mode to ");
         else
                 strcpy(prompt,"Mode to ");

         if (kind == TRUE)
                 strcat(prompt, "add: ");
         else
                 strcat(prompt, "delete: ");

         /* prompt the user and get an answer */

         status = mlreply(prompt, cbuf, NPAT - 1);
         if (status != TRUE)
                 return(status);

         /* make it uppercase */

         scan = cbuf;
 #if        COLOR
         uflag = (*scan >= 'A' && *scan <= 'Z');
 #endif
         while (*scan != 0) {
                 if (*scan >= 'a' && *scan <= 'z')
                         *scan = *scan - 32;
                 scan++;
         }

         /* test it first against the colors we know */
         for (i=0; i<NCOLORS; i++) {
                 if (strcmp(cbuf, cname[i]) == 0) {
                         /* finding the match, we set the color */
 #if        COLOR
                         if (uflag)
                                 if (global)
                                         gfcolor = i;
                                 else
                                         curwp->w_fcolor = i;
                         else
                                 if (global)
                                         gbcolor = i;
                                 else
                                         curwp->w_bcolor = i;

                         curwp->w_flag |= WFCOLR;
 #endif
                         mlerase();
                         return(TRUE);
                 }
         }

         /* test it against the modes we know */

         for (i=0; i < NUMMODES; i++) {
                 if (strcmp(cbuf, modename[i]) == 0) {
                         /* finding a match, we process it */
                         if (kind == TRUE)
                                 if (global)
                                         gmode |= (1 << i);
                                 else
                                         curbp->b_mode |= (1 << i);
                         else
                                 if (global)
                                         gmode &= ~(1 << i);
                                 else
                                         curbp->b_mode &= ~(1 << i);
                         /* display new mode line */
                         if (global == 0)
                                 upmode();
                         mlerase();        /* erase the junk */
                         return(TRUE);
                 }
         }

         mlwrite("No such mode!");
         return(FALSE);
 }

 /*        This function simply clears the message line,
                 mainly for macro usage                        */

 clrmes(f, n)

 int f, n;        /* arguments ignored */

 {
         mlforce("");
         return(TRUE);
 }

 /*        This function writes a string on the message line
                 mainly for macro usage                        */

 writemsg(f, n)

 int f, n;        /* arguments ignored */

 {
         register char *sp;        /* pointer into buf to expand %s */
         register char *np;        /* ptr into nbuf */
         register int status;
         char buf[NPAT];                /* buffer to recieve message into */
         char nbuf[NPAT*2];        /* buffer to expand string into */

         if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
                 return(status);

         /* expand all '%' to "%%" so mlwrite won't expect arguments */
         sp = buf;
         np = nbuf;
         while (*sp) {
                 *np++ = *sp;
                 if (*sp++ == '%')
                         *np++ = '%';
         }
         *np = '\0';

         /* write the message out */
         mlforce(nbuf);
         return(TRUE);
 }

 #if        CFENCE
 /*        the cursor is moved to a matching fence        */

 getfence(f, n)

 int f, n;        /* not used */

 {
         register LINE *oldlp;        /* original line pointer */
         register int oldoff;        /* and offset */
         register int sdir;        /* direction of search (1/-1) */
         register int count;        /* current fence level count */
         register char ch;        /* fence type to match against */
         register char ofence;        /* open fence */
         register char c;        /* current character in scan */

         /* save the original cursor position */
         oldlp = curwp->w_dotp;
         oldoff = curwp->w_doto;

         /* get the current character */
         if (oldoff == llength(oldlp))
                 ch = '\n';
         else
                 ch = lgetc(oldlp, oldoff);

         /* setup proper matching fence */
         switch (ch) {
                 case '(': ofence = ')'; sdir = FORWARD; break;
                 case '{': ofence = '}'; sdir = FORWARD; break;
                 case '[': ofence = ']'; sdir = FORWARD; break;
                 case ')': ofence = '('; sdir = REVERSE; break;
                 case '}': ofence = '{'; sdir = REVERSE; break;
                 case ']': ofence = '['; sdir = REVERSE; break;
                 default: TTbeep(); return(FALSE);
         }

         /* set up for scan */
         count = 1;
         if (sdir == REVERSE)
                 backchar(FALSE, 1);
         else
                 forwchar(FALSE, 1);

         /* scan until we find it, or reach the end of file */
         while (count > 0) {
                 if (curwp->w_doto == llength(curwp->w_dotp))
                         c = '\n';
                 else
                         c = lgetc(curwp->w_dotp, curwp->w_doto);
                 if (c == ch)
                         ++count;
                 if (c == ofence)
                         --count;
                 if (sdir == FORWARD)
                         forwchar(FALSE, 1);
                 else
                         backchar(FALSE, 1);
                 if (boundry(curwp->w_dotp, curwp->w_doto, sdir))
                         break;
         }

         /* if count is zero, we have a match, move the sucker */
         if (count == 0) {
                 if (sdir == FORWARD)
                         backchar(FALSE, 1);
                 else
                         forwchar(FALSE, 1);
                 curwp->w_flag |= WFMOVE;
                 return(TRUE);
         }

         /* restore the current position */
         curwp->w_dotp = oldlp;
         curwp->w_doto = oldoff;
         TTbeep();
         return(FALSE);
 }
 #endif

 /*        Close fences are matched against their partners, and if
         on screen the cursor briefly lights there                */

 fmatch(ch)

 char ch;        /* fence type to match against */

 {
         register LINE *oldlp;        /* original line pointer */
         register int oldoff;        /* and offset */
         register LINE *toplp;        /* top line in current window */
         register int count;        /* current fence level count */
         register char opench;        /* open fence */
         register char c;        /* current character in scan */
         register int i;

         /* first get the display update out there */
         update(FALSE);

         /* save the original cursor position */
         oldlp = curwp->w_dotp;
         oldoff = curwp->w_doto;

         /* setup proper open fence for passed close fence */
         if (ch == ')')
                 opench = '(';
         else if (ch == '}')
                 opench = '{';
         else
                 opench = '[';

         /* find the top line and set up for scan */
         toplp = curwp->w_linep->l_bp;
         count = 1;
         backchar(FALSE, 2);

         /* scan back until we find it, or reach past the top of the window */
         while (count > 0 && curwp->w_dotp != toplp) {
                 if (curwp->w_doto == llength(curwp->w_dotp))
                         c = '\n';
                 else
                         c = lgetc(curwp->w_dotp, curwp->w_doto);
                 if (c == ch)
                         ++count;
                 if (c == opench)
                         --count;
                 backchar(FALSE, 1);
                 if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
                     curwp->w_doto == 0)
                         break;
         }

         /* if count is zero, we have a match, display the sucker */
         /* there is a real machine dependant timing problem here we have
            yet to solve......... */
         if (count == 0) {
                 forwchar(FALSE, 1);
                 for (i = 0; i < term.t_pause; i++)
                         update(FALSE);
         }

         /* restore the current position */
         curwp->w_dotp = oldlp;
         curwp->w_doto = oldoff;
         return(TRUE);
 }

 istring(f, n)        /* ask for and insert a string into the current
                    buffer at the current point */

 int f, n;        /* ignored arguments */

 {
         register char *tp;        /* pointer into string to add */
         register int status;        /* status return code */
         char tstring[NPAT+1];        /* string to add */

         /* ask for string to insert */
         status = mlreplyt("String to insert<META>: ", tstring, NPAT, metac);
         if (status != TRUE)
                 return(status);

         if (f == FALSE)
                 n = 1;

         if (n < 0)
                 n = - n;

         /* insert it */
         while (n--) {
                 tp = &tstring[0];
                 while (*tp) {
                         if (*tp == 0x0a)
                                 status = lnewline();
                         else
                                 status = linsert(1, *tp);
                         ++tp;
                         if (status != TRUE)
                                 return(status);
                 }
         }

         return(TRUE);
 }


 RANDR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\RANDR.C

 /* RANDR.C - From page 456 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. Reads one agent's record, sel-    */
 /* ected by user, from database created by AGENTR.C             */
 /****************************************************************/

 #include "stdio.h"

 main()
 {
 struct {
    char name[40];
    int agnumb;
    float height;
 } agent;
 FILE *fptr;
 int recno;
 long int offset;

    if ((fptr = fopen("c:agents.rec", "r")) == NULL) {
       printf("\nCan't open file agents.rec");
       exit();
    }
    printf("\nEnter record number: ");
    scanf("%d", &recno);
    offset = --recno * sizeof(agent);        /*find offset*/
    if(fseek(fptr, offset, 0) != 0) {      /*go there*/
       printf("\nCan't move pointer there.");
       exit();
    }
    fread(&agent, sizeof(agent), 1, fptr);
    printf("\nName: %s", agent.name);
    printf("\nNumber: %03d", agent.agnumb);
    printf("\nHeight: %.2f", agent.height);
    fclose(fptr);
 }



 RATFUN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RATFUN.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathcons.h"

 /************************************************************************/
         double
 ratfun(x, P, Q, n, m)        /* return value of rational function P(x)/Q(x)
                            where n = deg(P), m = deg(Q)
 /*----------------------------------------------------------------------*/
 double x, P[], Q[];
 int n, m;
 {
         double num, den;
         int abs(), chrstc();

         if ( P[n] IS 1.0 AND n > 0)
                 num = x + P[--n];
         else
                 num = P[n];
         for (n--; n >= 0; n--)
                 num = num * x + P[n];
         if (Q[m] IS 1.0 AND m > 0)
                 den = x + Q[--m];
         else
                 den = Q[m];
         for (m--; m >= 0; m--)
                 den = den * x + Q[m];
         if (num IS 0.0 AND den ISNT 0.0)
                         return 0.0;

         if (den IS 0.0 OR abs(chrstc(num) - chrstc(den)) >= MAXEXP)
         {        errno = ERANGE;
                 return (num < 0.0 ? -INFINITY : INFINITY);
         }
         errno = 0;
         return (num/den);
 }


 READ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\READ.C


 /************************************************************
  *         IBM PC "C" Bulletin Board                        *
  *         Tulsa, OK 918-664-8737                           *
  *         SYSOP Lynn Long 300/1200 XMODEM                  *
  ***********************************************************/

 #include "io.h"
 #include "errno.h"
 #include "fcntl.h"

 int badfd(), filerd(), conin();

 static int (*readtab[])() = {
         badfd, filerd, conin,
 };
 extern int errno;

 read(fd, buff, len)
 char *buff;
 {
         register struct channel *chp;

         if (fd < 0 || fd > MAXCHAN) {
                 errno = EBADF;
                 return -1;
         }
         chp = &chantab[fd];
         return (*readtab[chp->c_read])(chp->c_arg, buff, len);
 }

 conin(x,buff,len)
 char *buff;
 {
         static char buffer[258] = { 0,0,0,0,0 };
         static int used = 0;
         register int l;

         if (buffer[1] == 0) {
                 buffer[0] = 255;
                 buffer[1] = buffer[2] = 0;
                 bdos(10,buffer);
                 bdos(2,'\n');
                 if (buffer[2] == 0x1a) {
                         buffer[1] = 0;
                         return 0;
                 }
                 buffer[++buffer[1] + 1] = '\r';
                 buffer[++buffer[1] + 1] = '\n';
                 used = 2;
         }
         if ((l = buffer[1]) > len)
                 l = len;
         blockmv(buff, buffer+used, l);
         used += l;
         buffer[1] -= l;
         return l;
 }



 READCHAR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\READCHAR.C

                                          /* Chapter 10 - Program 3 */
 #include "stdio.h"

 main()
 {
 FILE *funny;
 char c;

    funny = fopen("TENLINES.TXT","r");

    if (funny == NULL) printf("File doesn't exist\n");
    else {
       do {
          c = getc(funny);    /* get one character from the file */
          putchar(c);         /* display it on the monitor       */
       } while (c != EOF);    /* repeat until EOF (end of file)  */
    }
    fclose(funny);
 }


 READF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\READF.C

 /* READF.C - From page 441 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. This program reads a program      */
 /* created by a file that writes formatted data to a string,    */
 /* such as WRITEF.C which is on this disk.                      */
 /****************************************************************/

 #include <stdio.h>

 main()
 {
 FILE *fptr;
 char name[40];
 int code;
 float height;

    fptr = fopen("c:textfile.txt", "r");
    while(fscanf(fptr, "%s %d %f", name, &code, &height) != EOF)
       printf("%s %03d %.2f\n", name, code, height);
    fclose(fptr);
 }



 READGOOD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\READGOOD.C

                                         /* Chapter 10 - Program 5 */
 #include "stdio.h"

 main()
 {
 FILE *fp1;
 char oneword[100];
 char c;

    fp1 = fopen("TENLINES.TXT","r");

    do {
       c = fscanf(fp1,"%s",oneword); /* got one word from the file */
       if (c != EOF)
          printf("%s\n",oneword);    /* display it on the monitor  */
    } while (c != EOF);              /* repeat until EOF           */

    fclose(fp1);
 }


 READLINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\READLINE.C

                                         /* Chapter 10 - Program 6 */
 #include "stdio.h"

 main()
 {
 FILE *fp1;
 char oneword[100];
 char *c;

    fp1 = fopen("TENLINES.TXT","r");

    do {
       c = fgets(oneword,100,fp1); /* get one line from the file */
       if (c != NULL)
          printf("%s",oneword);    /* display it on the monitor  */
    } while (c != NULL);          /* repeat until NULL          */

    fclose(fp1);
 }


 READS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\READS.C

 /* READS.C - From page 437 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. Reads strings from a file,        */
 /* TEXTFILE.TXT, and displays them on screen.                   */
 /****************************************************************/

 #include <stdio.h>

 main()
 {
 FILE *fptr;
 char string[81];

    fptr = fopen("c:textfile.txt", "r");
    while(fgets(string, 80, fptr) != NULL)   /*read string*/
       printf("%s", string);
    fclose(fptr);
 }



 READTEXT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\READTEXT.C

                                          /* Chapter 10 - Program 4 */
 #include "stdio.h"

 main()
 {
 FILE *fp1;
 char oneword[100];
 char c;

    fp1 = fopen("TENLINES.TXT","r");

    do {
       c = fscanf(fp1,"%s",oneword); /* got one word from the file */
       printf("%s\n",oneword);       /* display it on the monitor  */
    } while (c != EOF);              /* repeat until EOF           */

    fclose(fp1);
 }


 REALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\REALLOC.C

 /* 1.1  07-10-85                                                (realloc.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         char *
 realloc(ptr, size)        /* Change the size of the block pointed to by ptr,
                            to size bytes.  Return pointer to (possibly
                            moved) block.  Return NULL if no memory
                            available.
 /*----------------------------------------------------------------------*/
 STRING ptr;
 unsigned size;
 {
         HEADER *p;
         STRING s, t, malloc();
         int n;

         p = (HEADER *) ptr - 1;        /* point to header        */
         n = MIN(p->s.size, size);
         free(ptr);
         if ((s = t = malloc(size)) ISNT NULL AND s ISNT ptr)
                 while (n-- > 0)
                         *s++ = *ptr++;                /* move the data over.
         return s;
 }


 REALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\REALLOC.C

 #include <stdio.h>
 #include <malloc.h>

 #define        MAXBLK                16
 #define        FREE                0x00
 #define        USED                0x80
 #define        NULLBLK                0x80000000L

 extern        char        *_mblk[];                /* memory heap pointers */
 extern        long        _msiz[];                /* memory heap sizes */

 static long *unlinkblk(addr)
 register long *addr;
 /*
  *        Unlink memory block at <addr> from free memory chain.
  */
 {
         register int i;
         register long *p, *q;

         for(i=0; i<MAXBLK; ++i) {
                 if((q = p = _mblk[i]) == NULL)
                         continue;                /* skip unavailable blocks *
                 if((addr < p) || (addr > ((char *) p)+_msiz[i]))
                         continue;                /* block range check */
                 while(p = *q) {
                         if(p == addr) {                /* found the right blo
                                 q[0] = p[1];        /* unlink it */
                                 return(p);
                         }
                         q = p + 1;
                 }
         }
         return(NULL);
 }

 char *realloc(addr, size)
 register long *addr;
 unsigned int size;
 /*
  *        Attempt to change the memory block at <addr> to the new <size>.
  *        Making a block smaller will always work, but making it larger
  *        may fail if there is not enough free memory.  If there is not
  *        enough memory, NULL is returned and the block will still reside
  *        at <addr>.  If realloc() succeeds, a pointer to the (possibly
  *        moved) new block will be returned.
  */
 {
         register long n, m, d, *p, *q;
         char *lalloc();

         p = addr - 1;
         n = p[0] & 0x00FFFFFFL;                        /* get actual block si
         m = (((long) size) + 5L) & ~1L;                /* calculate new block
         if(m <= n) {                        /* shrink... */
                 if((n -= m) >= 8L) {                /* big enough to shrink *
                         q = ((char *) p) + m;        /* calculate new break *
                         p[0] = m;
                         *((char *) p) = USED;
                         q[0] = n;
                         *((char *) q) = USED;
                         free(q + 1);                /* free remainder */
                 }
         }
         else {                                /* grow... */
                 d = *(q = ((char *) p) + n);
                 if((d > 0) &&                        /* next block is free */
                    (m <= (n + d)) &&                /* combination is big eno
                    (unlinkblk(q))) {                /* block can be unlinked
                         p[0] = (n + d);
                         *((char *) p) = USED;        /* extend in place */
                         return(realloc(addr, size));
                 }
                 if(p = lalloc(m - 4L)) {        /* allocate bigger block */
                         lblkcpy(p, addr, n-4L);        /* copy old data */
                         free(addr);                /* free old block */
                         addr = p;
                 }
                 else
                         addr = NULL;
         }
         return(addr);
 }


 RECTANGL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\RECTANGL.C

 /**********************************************************************
 RECTANGL.C
 Description -  draws a rectangle
 **********************************************************************
 Function - rectangle(x,y,horiz width,vertical height)
 Input - xy coord of upper left corner, width, height
 Output - to the screen
 #includes - none
 #defines  - none
 Routines Called - line, plotxy
 Notes - offsets vertical scale
 **********************************************************************/
 rectangle(x,y,sidex,sidey)
 int x,y,sidex,sidey;
 {
   int x1,y1;
   x1=x+sidex; /* horizontal width */
   y1=y+((sidey*2)/5); /* vertical height */
   line(x,y,x1,y); /* top horiz line */
   line(x,y1,x1,y1); /* bott horiz line */
   line(x,y,x,y1); /* left vertical line */
   line(x1,y,x1,y1); /* right vertical line */
   return;
 }
 /******************** end of function ********************************/


 RECURSON.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\RECURSON.C

                                          /* Chapter 5 - Program 5 */
 main()
 {
 int index;

    index = 8;
    count_dn(index);
 }

 count_dn(count)
 int count;
 {
    count--;
    printf("The value of the count is %d\n",count);
    if (count > 0)
       count_dn(count);
    printf("Now the count is %d\n",count);
 }


 REDIRBUF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\REDIRBUF.C

 /* 1.0  05-07-85                                                  (redirbuf.c
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         VOID
 redirbuf(fd)                /* Change the buffer allocation for stdin and
                            stdout for redirected i/o.
 /*----------------------------------------------------------------------*/
 {
         if (fd ISNT STDIN AND fd ISNT STDOUT)
                 return;

         IObuffs[fd]._buflen = BUFSIZ;
 }


 REGERROR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\REGERROR.C

 #include <stdio.h>

 void
 regerror(s)
 char *s;
 {
 #ifdef ERRAVAIL
         error("regexp: %s", s);
 #else
         fprintf(stderr, "regexp(3): %s\n", s);
         exit(1);
 /*
         note:        if the program using regexp(3) wants to handle the regex
                 errors, comment out the above and use this
 */
         return;          /* let using program handle errors */
 #endif
         /* NOTREACHED */
 }


 REGEXP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\REGEXP.C

 /*
  * regcomp and regexec -- regsub and regerror are elsewhere
  *
  *        Copyright (c) 1986 by University of Toronto.
  *        Written by Henry Spencer.  Not derived from licensed software.
  *
  *        Permission is granted to anyone to use this software for any
  *        purpose on any computer system, and to redistribute it freely,
  *        subject to the following restrictions:
  *
  *        1. The author is not responsible for the consequences of use of
  *                this software, no matter how awful, even if they arise
  *                from defects in it.
  *
  *        2. The origin of this software must not be misrepresented, either
  *                by explicit claim or by omission.
  *
  *        3. Altered versions must be plainly marked as such, and must not
  *                be misrepresented as being the original software.
  *
  * Beware that some of this code is subtly aware of the way operator
  * precedence is structured in regular expressions.  Serious changes in
  * regular-expression syntax might require a total rethink.
  */
 #include <stdio.h>
 #include <regexp.h>
 #include "regmagic.h"

 #if defined(__TURBOC__)
 #include <string.h>
 #endif TURBOC
 /*
  * The "internal use only" fields in regexp.h are present to pass info from
  * compile to execute that permits the execute phase to run lots faster on
  * simple cases.  They are:
  *
  * regstart        char that must begin a match; '\0' if none obvious
  * reganch        is the match anchored (at beginning-of-line only)?
  * regmust        string (pointer into program) that match must include, or N
  * regmlen        length of regmust string
  *
  * Regstart and reganch permit very fast decisions on suitable starting point
  * for a match, cutting down the work a lot.  Regmust permits fast rejection
  * of lines that cannot possibly match.  The regmust tests are costly enough
  * that regcomp() supplies a regmust only if the r.e. contains something
  * potentially expensive (at present, the only such thing detected is * or +
  * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  * supplied because the test in regexec() needs it and regcomp() is computing
  * it anyway.
  */

 /*
  * Structure for regexp "program".  This is essentially a linear encoding
  * of a nondeterministic finite-state machine (aka syntax charts or
  * "railroad normal form" in parsing technology).  Each node is an opcode
  * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  * all nodes except BRANCH implement concatenation; a "next" pointer with
  * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  * have one of the subtle syntax dependencies:  an individual BRANCH (as
  * opposed to a collection of them) is never concatenated with anything
  * because of operator precedence.)  The operand of some types of node is
  * a literal string; for others, it is a node leading into a sub-FSM.  In
  * particular, the operand of a BRANCH node is the first node of the branch.
  * (NB this is *not* a tree structure:  the tail of the branch connects
  * to the thing following the set of BRANCHes.)  The opcodes are:
  */

 /* definition        number        opnd?        meaning */
        END        0        /* no        End of program. */
        BOL        1        /* no        Match "" at beginning of line. */
        EOL        2        /* no        Match "" at end of line. */
        ANY        3        /* no        Match any one character. */
        ANYOF        4        /* str        Match any character in this string
        ANYBUT        5        /* str        Match any character not in this s
        BRANCH        6        /* node        Match this alternative, or the n
        BACK        7        /* no        Match "", "next" ptr points backward
        EXACTLY        8        /* str        Match this string. */
        NOTHING        9        /* no        Match empty string. */
        STAR        10        /* node        Match this (simple) thing 0 or mo
        PLUS        11        /* node        Match this (simple) thing 1 or mo
        OPEN        20        /* no        Mark this point in input as start o
                         /*        OPEN+1 is number 1, etc. */
        CLOSE        30        /* no        Analogous to OPEN. */

 /*
  * Opcode notes:
  *
  * BRANCH        The set of branches constituting a single choice are hooked
  *                together with their "next" pointers, since precedence preve
  *                anything being concatenated to any individual branch.  The
  *                "next" pointer of the last BRANCH in a choice points to the
  *                thing following the whole choice.  This is also where the
  *                final "next" pointer of each individual branch points; each
  *                branch starts with the operand node of a BRANCH node.
  *
  * BACK                Normal "next" pointers all implicitly point forward; B
  *                exists to make loop structures possible.
  *
  * STAR,PLUS        '?', and complex '*' and '+', are implemented as circular
  *                BRANCH structures using BACK.  Simple cases (one character
  *                per match) are implemented with STAR and PLUS for speed
  *                and to minimize recursive plunges.
  *
  * OPEN,CLOSE        ...are numbered at compile time.
  */

 /*
  * A node is one char of opcode followed by two chars of "next" pointer.
  * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  * value is a positive offset from the opcode of the node containing it.
  * An operand, if any, simply follows the node.  (Note that much of the
  * code generation knows about this implicit relationship.)
  *
  * Using two bytes for the "next" pointer is vast overkill for most things,
  * but allows patterns to get big without disasters.
  */
 #define        OP(p)        (*(p))
 #define        NEXT(p)        (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
 #define        OPERAND(p)        ((p) + 3)

 /*
  * See regmagic.h for one further detail of program structure.
  */


 /*
  * Utility definitions.
  */
 #ifndef CHARBITS
 #define        UCHARAT(p)        ((int)*(unsigned char *)(p))
 #else
 #define        UCHARAT(p)        ((int)*(p)&CHARBITS)
 #endif

 #define        FAIL(m)        { regerror(m); return(NULL); }
 #define        ISMULT(c)        ((c) == '*' || (c) == '+' || (c) == '?')
 #define        META        "^$.[()|?+*\\"

 /*
  * Flags to be passed up and down.
  */
        HASWIDTH        01        /* Known never to match null string. */
        SIMPLE                02        /* Simple enough to be STAR/PLUS opera
        SPSTART                04        /* Starts with * or +. */
        WORST                0        /* Worst case. */

 /*
  * Global work variables for regcomp().
  */
 static char *regparse;                /* Input-scan pointer. */
 static int regnpar;                /* () count. */
 static char regdummy;
 static char *regcode;                /* Code-emit pointer; &regdummy = don't.
 static long regsize;                /* Code size. */

 /*
  * Forward declarations for regcomp()'s friends.
  */
 #ifndef STATIC
 #define        STATIC        static
 #endif
 STATIC char *reg();
 STATIC char *regbranch();
 STATIC char *regpiece();
 STATIC char *regatom();
 STATIC char *regnode();
 STATIC char *regnext();
 STATIC void regc();
 STATIC void reginsert();
 STATIC void regtail();
 STATIC void regoptail();
 #ifdef STRCSPN
 STATIC int strcspn();
 #endif

 /*
  - regcomp - compile a regular expression into internal code
  *
  * We can't allocate space until we know how big the compiled form will be,
  * but we can't compile it (and thus know how big it is) until we've got a
  * place to put the code.  So we cheat:  we compile it twice, once with code
  * generation turned off and size counting turned on, and once "for real".
  * This also means that we don't allocate space until we are sure that the
  * thing really will compile successfully, and we never have to move the
  * code and thus invalidate pointers into it.  (Note that it has to be in
  * one piece because free() must be able to free it all.)
  *
  * Beware that the optimization-preparation code in here knows about some
  * of the structure of the compiled regexp.
  */
 regexp *
 regcomp(exp)
 char *exp;
 {
         register regexp *r;
         register char *scan;
         register char *longest;
         register int len;
         int flags;
         extern char *malloc();

         if (exp == NULL)
                 FAIL("NULL argument");

         /* First pass: determine size, legality. */
         regparse = exp;
         regnpar = 1;
         regsize = 0L;
         regcode = &regdummy;
         regc(MAGIC);
         if (reg(0, &flags) == NULL)
                 return(NULL);

         /* Small enough for pointer-storage convention? */
         if (regsize >= 32767L)                /* Probably could be 65535L. */
                 FAIL("regexp too big");

         /* Allocate space. */
         r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
         if (r == NULL)
                 FAIL("out of space");

         /* Second pass: emit code. */
         regparse = exp;
         regnpar = 1;
         regcode = r->program;
         regc(MAGIC);
         if (reg(0, &flags) == NULL)
                 return(NULL);

         /* Dig out information for optimizations. */
         r->regstart = '\0';        /* Worst-case defaults. */
         r->reganch = 0;
         r->regmust = NULL;
         r->regmlen = 0;
         scan = r->program+1;                        /* First BRANCH. */
         if (OP(regnext(scan)) == END) {                /* Only one top-level
                 scan = OPERAND(scan);

                 /* Starting-point info. */
                 if (OP(scan) == EXACTLY)
                         r->regstart = *OPERAND(scan);
                 else if (OP(scan) == BOL)
                         r->reganch++;

                 /*
                  * If there's something expensive in the r.e., find the
                  * longest literal string that must appear and make it the
                  * regmust.  Resolve ties in favor of later strings, since
                  * the regstart check works with the beginning of the r.e.
                  * and avoiding duplication strengthens checking.  Not a
                  * strong reason, but sufficient in the absence of others.
                  */
                 if (flags&SPSTART) {
                         longest = NULL;
                         len = 0;
                         for (; scan != NULL; scan = regnext(scan))
                                 if (OP(scan) == EXACTLY && strlen(OPERAND(sca
                                         longest = OPERAND(scan);
                                         len = strlen(OPERAND(scan));
                                 }
                         r->regmust = longest;
                         r->regmlen = len;
                 }
         }

         return(r);
 }

 /*
  - reg - regular expression, i.e. main body or parenthesized thing
  *
  * Caller must absorb opening parenthesis.
  *
  * Combining parenthesis handling with the base level of regular expression
  * is a trifle forced, but the need to tie the tails of the branches to what
  * follows makes it hard to avoid.
  */
 static char *
 reg(paren, flagp)
 int paren;                        /* Parenthesized? */
 int *flagp;
 {
         register char *ret;
         register char *br;
         register char *ender;
         register int parno;
         int flags;

         *flagp = HASWIDTH;        /* Tentatively. */

         /* Make an OPEN node, if parenthesized. */
         if (paren) {
                 if (regnpar >= NSUBEXP)
                         FAIL("too many ()");
                 parno = regnpar;
                 regnpar++;
                 ret = regnode(OPEN+parno);
         } else
                 ret = NULL;

         /* Pick up the branches, linking them together. */
         br = regbranch(&flags);
         if (br == NULL)
                 return(NULL);
         if (ret != NULL)
                 regtail(ret, br);        /* OPEN -> first. */
         else
                 ret = br;
         if (!(flags&HASWIDTH))
                 *flagp &= ~HASWIDTH;
         *flagp |= flags&SPSTART;
         while (*regparse == '|') {
                 regparse++;
                 br = regbranch(&flags);
                 if (br == NULL)
                         return(NULL);
                 regtail(ret, br);        /* BRANCH -> BRANCH. */
                 if (!(flags&HASWIDTH))
                         *flagp &= ~HASWIDTH;
                 *flagp |= flags&SPSTART;
         }

         /* Make a closing node, and hook it on the end. */
         ender = regnode((paren) ? CLOSE+parno : END);
         regtail(ret, ender);

         /* Hook the tails of the branches to the closing node. */
         for (br = ret; br != NULL; br = regnext(br))
                 regoptail(br, ender);

         /* Check for proper termination. */
         if (paren && *regparse++ != ')') {
                 FAIL("unmatched ()");
         } else if (!paren && *regparse != '\0') {
                 if (*regparse == ')') {
                         FAIL("unmatched ()");
                 } else
                         FAIL("junk on end");        /* "Can't happen". */
                 /* NOTREACHED */
         }

         return(ret);
 }

 /*
  - regbranch - one alternative of an | operator
  *
  * Implements the concatenation operator.
  */
 static char *
 regbranch(flagp)
 int *flagp;
 {
         register char *ret;
         register char *chain;
         register char *latest;
         int flags;

         *flagp = WORST;                /* Tentatively. */

         ret = regnode(BRANCH);
         chain = NULL;
         while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
                 latest = regpiece(&flags);
                 if (latest == NULL)
                         return(NULL);
                 *flagp |= flags&HASWIDTH;
                 if (chain == NULL)        /* First piece. */
                         *flagp |= flags&SPSTART;
                 else
                         regtail(chain, latest);
                 chain = latest;
         }
         if (chain == NULL)        /* Loop ran zero times. */
                 (void) regnode(NOTHING);

         return(ret);
 }

 /*
  - regpiece - something followed by possible [*+?]
  *
  * Note that the branching code sequences used for ? and the general cases
  * of * and + are somewhat optimized:  they use the same NOTHING node as
  * both the endmarker for their branch list and the body of the last branch.
  * It might seem that this node could be dispensed with entirely, but the
  * endmarker role is not redundant.
  */
 static char *
 regpiece(flagp)
 int *flagp;
 {
         register char *ret;
         register char op;
         register char *next;
         int flags;

         ret = regatom(&flags);
         if (ret == NULL)
                 return(NULL);

         op = *regparse;
         if (!ISMULT(op)) {
                 *flagp = flags;
                 return(ret);
         }

         if (!(flags&HASWIDTH) && op != '?')
                 FAIL("*+ operand could be empty");
         *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);

         if (op == '*' && (flags&SIMPLE))
                 reginsert(STAR, ret);
         else if (op == '*') {
                 /* Emit x* as (x&|), where & means "self". */
                 reginsert(BRANCH, ret);                        /* Either x */
                 regoptail(ret, regnode(BACK));                /* and loop */
                 regoptail(ret, ret);                        /* back */
                 regtail(ret, regnode(BRANCH));                /* or */
                 regtail(ret, regnode(NOTHING));                /* null. */
         } else if (op == '+' && (flags&SIMPLE))
                 reginsert(PLUS, ret);
         else if (op == '+') {
                 /* Emit x+ as x(&|), where & means "self". */
                 next = regnode(BRANCH);                        /* Either */
                 regtail(ret, next);
                 regtail(regnode(BACK), ret);                /* loop back */
                 regtail(next, regnode(BRANCH));                /* or */
                 regtail(ret, regnode(NOTHING));                /* null. */
         } else if (op == '?') {
                 /* Emit x? as (x|) */
                 reginsert(BRANCH, ret);                        /* Either x */
                 regtail(ret, regnode(BRANCH));                /* or */
                 next = regnode(NOTHING);                /* null. */
                 regtail(ret, next);
                 regoptail(ret, next);
         }
         regparse++;
         if (ISMULT(*regparse))
                 FAIL("nested *?+");

         return(ret);
 }

 /*
  - regatom - the lowest level
  *
  * Optimization:  gobbles an entire sequence of ordinary characters so that
  * it can turn them into a single node, which is smaller to store and
  * faster to run.  Backslashed characters are exceptions, each becoming a
  * separate node; the code is simpler that way and it's not worth fixing.
  */
 static char *
 regatom(flagp)
 int *flagp;
 {
         register char *ret;
         int flags;

         *flagp = WORST;                /* Tentatively. */

         switch (*regparse++) {
         case '^':
                 ret = regnode(BOL);
                 break;
         case '$':
                 ret = regnode(EOL);
                 break;
         case '.':
                 ret = regnode(ANY);
                 *flagp |= HASWIDTH|SIMPLE;
                 break;
         case '[': {
                         register int class;
                         register int classend;

                         if (*regparse == '^') {        /* Complement of range
                                 ret = regnode(ANYBUT);
                                 regparse++;
                         } else
                                 ret = regnode(ANYOF);
                         if (*regparse == ']' || *regparse == '-')
                                 regc(*regparse++);
                         while (*regparse != '\0' && *regparse != ']') {
                                 if (*regparse == '-') {
                                         regparse++;
                                         if (*regparse == ']' || *regparse ==
                                                 regc('-');
                                         else {
                                                 class = UCHARAT(regparse-2)+1
                                                 classend = UCHARAT(regparse);
                                                 if (class > classend+1)
                                                         FAIL("invalid [] rang
                                                 for (; class <= classend; cla
                                                         regc(class);
                                                 regparse++;
                                         }
                                 } else
                                         regc(*regparse++);
                         }
                         regc('\0');
                         if (*regparse != ']')
                                 FAIL("unmatched []");
                         regparse++;
                         *flagp |= HASWIDTH|SIMPLE;
                 }
                 break;
         case '(':
                 ret = reg(1, &flags);
                 if (ret == NULL)
                         return(NULL);
                 *flagp |= flags&(HASWIDTH|SPSTART);
                 break;
         case '\0':
         case '|':
         case ')':
                 FAIL("internal urp");        /* Supposed to be caught earlier
                 break;
         case '?':
         case '+':
         case '*':
                 FAIL("?+* follows nothing");
                 break;
         case '\\':
                 if (*regparse == '\0')
                         FAIL("trailing \\");
                 ret = regnode(EXACTLY);
                 regc(*regparse++);
                 regc('\0');
                 *flagp |= HASWIDTH|SIMPLE;
                 break;
         default: {
                         register int len;
                         register char ender;

                         regparse--;
                         len = strcspn(regparse, META);
                         if (len <= 0)
                                 FAIL("internal disaster");
                         ender = *(regparse+len);
                         if (len > 1 && ISMULT(ender))
                                 len--;                /* Back off clear of ?+
                         *flagp |= HASWIDTH;
                         if (len == 1)
                                 *flagp |= SIMPLE;
                         ret = regnode(EXACTLY);
                         while (len > 0) {
                                 regc(*regparse++);
                                 len--;
                         }
                         regc('\0');
                 }
                 break;
         }

         return(ret);
 }

 /*
  - regnode - emit a node
  */
 static char *                        /* Location. */
 regnode(op)
 char op;
 {
         register char *ret;
         register char *ptr;

         ret = regcode;
         if (ret == &regdummy) {
                 regsize += 3;
                 return(ret);
         }

         ptr = ret;
         *ptr++ = op;
         *ptr++ = '\0';                /* Null "next" pointer. */
         *ptr++ = '\0';
         regcode = ptr;

         return(ret);
 }

 /*
  - regc - emit (if appropriate) a byte of code
  */
 static void
 regc(b)
 char b;
 {
         if (regcode != &regdummy)
                 *regcode++ = b;
         else
                 regsize++;
 }

 /*
  - reginsert - insert an operator in front of already-emitted operand
  *
  * Means relocating the operand.
  */
 static void
 reginsert(op, opnd)
 char op;
 char *opnd;
 {
         register char *src;
         register char *dst;
         register char *place;

         if (regcode == &regdummy) {
                 regsize += 3;
                 return;
         }

         src = regcode;
         regcode += 3;
         dst = regcode;
         while (src > opnd)
                 *--dst = *--src;

         place = opnd;                /* Op node, where operand used to be. */
         *place++ = op;
         *place++ = '\0';
         *place++ = '\0';
 }

 /*
  - regtail - set the next-pointer at the end of a node chain
  */
 static void
 regtail(p, val)
 char *p;
 char *val;
 {
         register char *scan;
         register char *temp;
         register int offset;

         if (p == &regdummy)
                 return;

         /* Find last node. */
         scan = p;
         for (;;) {
                 temp = regnext(scan);
                 if (temp == NULL)
                         break;
                 scan = temp;
         }

         if (OP(scan) == BACK)
                 offset = scan - val;
         else
                 offset = val - scan;
         *(scan+1) = (offset>>8)&0377;
         *(scan+2) = offset&0377;
 }

 /*
  - regoptail - regtail on operand of first argument; nop if operandless
  */
 static void
 regoptail(p, val)
 char *p;
 char *val;
 {
         /* "Operandless" and "op != BRANCH" are synonymous in practice. */
         if (p == NULL || p == &regdummy || OP(p) != BRANCH)
                 return;
         regtail(OPERAND(p), val);
 }

 /*
  * regexec and friends
  */

 /*
  * Global work variables for regexec().
  */
 static char *reginput;                /* String-input pointer. */
 static char *regbol;                /* Beginning of input, for ^ check. */
 static char **regstartp;        /* Pointer to startp array. */
 static char **regendp;                /* Ditto for endp. */

 /*
  * Forwards.
  */
 STATIC int regtry();
 STATIC int regmatch();
 STATIC int regrepeat();

 #ifdef DEBUG
 int regnarrate = 0;
 void regdump();
 STATIC char *regprop();
 #endif

 /*
  - regexec - match a regexp against a string
  */
 int
 regexec(prog, string)
 register regexp *prog;
 register char *string;
 {
         register char *s;
         extern char *strchr();

         /* Be paranoid... */
         if (prog == NULL || string == NULL) {
                 regerror("NULL parameter");
                 return(0);
         }

         /* Check validity of program. */
         if (UCHARAT(prog->program) != MAGIC) {
                 regerror("corrupted program");
                 return(0);
         }

         /* If there is a "must appear" string, look for it. */
         if (prog->regmust != NULL) {
                 s = string;
                 while ((s = strchr(s, prog->regmust[0])) != NULL) {
                         if (strncmp(s, prog->regmust, prog->regmlen) == 0)
                                 break;        /* Found it. */
                         s++;
                 }
                 if (s == NULL)        /* Not present. */
                         return(0);
         }

         /* Mark beginning of line for ^ . */
         regbol = string;

         /* Simplest case:  anchored match need be tried only once. */
         if (prog->reganch)
                 return(regtry(prog, string));

         /* Messy cases:  unanchored match. */
         s = string;
         if (prog->regstart != '\0')
                 /* We know what char it must start with. */
                 while ((s = strchr(s, prog->regstart)) != NULL) {
                         if (regtry(prog, s))
                                 return(1);
                         s++;
                 }
         else
                 /* We don't -- general case. */
                 do {
                         if (regtry(prog, s))
                                 return(1);
                 } while (*s++ != '\0');

         /* Failure. */
         return(0);
 }

 /*
  - regtry - try match at specific point
  */
 static int                        /* 0 failure, 1 success */
 regtry(prog, string)
 regexp *prog;
 char *string;
 {
         register int i;
         register char **sp;
         register char **ep;

         reginput = string;
         regstartp = prog->startp;
         regendp = prog->endp;

         sp = prog->startp;
         ep = prog->endp;
         for (i = NSUBEXP; i > 0; i--) {
                 *sp++ = NULL;
                 *ep++ = NULL;
         }
         if (regmatch(prog->program + 1)) {
                 prog->startp[0] = string;
                 prog->endp[0] = reginput;
                 return(1);
         } else
                 return(0);
 }

 /*
  - regmatch - main matching routine
  *
  * Conceptually the strategy is simple:  check to see whether the current
  * node matches, call self recursively to see whether the rest matches,
  * and then act accordingly.  In practice we make some effort to avoid
  * recursion, in particular by going through "ordinary" nodes (that don't
  * need to know whether the rest of the match failed) by a loop instead of
  * by recursion.
  */
 static int                        /* 0 failure, 1 success */
 regmatch(prog)
 char *prog;
 {
         register char *scan;        /* Current node. */
         char *next;                /* Next node. */
         extern char *strchr();

         scan = prog;
 #ifdef DEBUG
         if (scan != NULL && regnarrate)
                 fprintf(stderr, "%s(\n", regprop(scan));
 #endif
         while (scan != NULL) {
 #ifdef DEBUG
                 if (regnarrate)
                         fprintf(stderr, "%s...\n", regprop(scan));
 #endif
                 next = regnext(scan);

                 switch (OP(scan)) {
                 case BOL:
                         if (reginput != regbol)
                                 return(0);
                         break;
                 case EOL:
                         if (*reginput != '\0')
                                 return(0);
                         break;
                 case ANY:
                         if (*reginput == '\0')
                                 return(0);
                         reginput++;
                         break;
                 case EXACTLY: {
                                 register int len;
                                 register char *opnd;

                                 opnd = OPERAND(scan);
                                 /* Inline the first character, for speed. */
                                 if (*opnd != *reginput)
                                         return(0);
                                 len = strlen(opnd);
                                 if (len > 1 && strncmp(opnd, reginput, len) !
                                         return(0);
                                 reginput += len;
                         }
                         break;
                 case ANYOF:
                          if (*reginput == '\0' || strchr(OPERAND(scan), *regi
                                 return(0);
                         reginput++;
                         break;
                 case ANYBUT:
                          if (*reginput == '\0' || strchr(OPERAND(scan), *regi
                                 return(0);
                         reginput++;
                         break;
                 case NOTHING:
                         break;
                 case BACK:
                         break;
                 case OPEN+1:
                 case OPEN+2:
                 case OPEN+3:
                 case OPEN+4:
                 case OPEN+5:
                 case OPEN+6:
                 case OPEN+7:
                 case OPEN+8:
                 case OPEN+9: {
                                 register int no;
                                 register char *save;

                                 no = OP(scan) - OPEN;
                                 save = reginput;

                                 if (regmatch(next)) {
                                         /*
                                          * Don't set startp if some later
                                          * invocation of the same parentheses
                                          * already has.
                                          */
                                         if (regstartp[no] == NULL)
                                                 regstartp[no] = save;
                                         return(1);
                                 } else
                                         return(0);
                         }
                         break;
                 case CLOSE+1:
                 case CLOSE+2:
                 case CLOSE+3:
                 case CLOSE+4:
                 case CLOSE+5:
                 case CLOSE+6:
                 case CLOSE+7:
                 case CLOSE+8:
                 case CLOSE+9: {
                                 register int no;
                                 register char *save;

                                 no = OP(scan) - CLOSE;
                                 save = reginput;

                                 if (regmatch(next)) {
                                         /*
                                          * Don't set endp if some later
                                          * invocation of the same parentheses
                                          * already has.
                                          */
                                         if (regendp[no] == NULL)
                                                 regendp[no] = save;
                                         return(1);
                                 } else
                                         return(0);
                         }
                         break;
                 case BRANCH: {
                                 register char *save;

                                 if (OP(next) != BRANCH)                /* No
                                         next = OPERAND(scan);        /* Avoid
                                 else {
                                         do {
                                                 save = reginput;
                                                 if (regmatch(OPERAND(scan)))
                                                         return(1);
                                                 reginput = save;
                                                 scan = regnext(scan);
                                         } while (scan != NULL && OP(scan) ==
                                         return(0);
                                         /* NOTREACHED */
                                 }
                         }
                         break;
                 case STAR:
                 case PLUS: {
                                 register char nextch;
                                 register int no;
                                 register char *save;
                                 register int min;

                                 /*
                                  * Lookahead to avoid useless match attempts
                                  * when we know what character comes next.
                                  */
                                 nextch = '\0';
                                 if (OP(next) == EXACTLY)
                                         nextch = *OPERAND(next);
                                 min = (OP(scan) == STAR) ? 0 : 1;
                                 save = reginput;
                                 no = regrepeat(OPERAND(scan));
                                 while (no >= min) {
                                         /* If it could work, try it. */
                                         if (nextch == '\0' || *reginput == ne
                                                 if (regmatch(next))
                                                         return(1);
                                         /* Couldn't or didn't -- back up. */
                                         no--;
                                         reginput = save + no;
                                 }
                                 return(0);
                         }
                         break;
                 case END:
                         return(1);        /* Success! */
                         break;
                 default:
                         regerror("memory corruption");
                         return(0);
                         break;
                 }

                 scan = next;
         }

         /*
          * We get here only if there's trouble -- normally "case END" is
          * the terminating point.
          */
         regerror("corrupted pointers");
         return(0);
 }

 /*
  - regrepeat - repeatedly match something simple, report how many
  */
 static int
 regrepeat(p)
 char *p;
 {
         register int count = 0;
         register char *scan;
         register char *opnd;

         scan = reginput;
         opnd = OPERAND(p);
         switch (OP(p)) {
         case ANY:
                 count = strlen(scan);
                 scan += count;
                 break;
         case EXACTLY:
                 while (*opnd == *scan) {
                         count++;
                         scan++;
                 }
                 break;
         case ANYOF:
                 while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
                         count++;
                         scan++;
                 }
                 break;
         case ANYBUT:
                 while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
                         count++;
                         scan++;
                 }
                 break;
         default:                /* Oh dear.  Called inappropriately. */
                 regerror("internal foulup");
                 count = 0;        /* Best compromise. */
                 break;
         }
         reginput = scan;

         return(count);
 }

 /*
  - regnext - dig the "next" pointer out of a node
  */
 static char *
 regnext(p)
 register char *p;
 {
         register int offset;

         if (p == &regdummy)
                 return(NULL);

         offset = NEXT(p);
         if (offset == 0)
                 return(NULL);

         if (OP(p) == BACK)
                 return(p-offset);
         else
                 return(p+offset);
 }

 #ifdef DEBUG

 STATIC char *regprop();

 /*
  - regdump - dump a regexp onto stdout in vaguely comprehensible form
  */
 void
 regdump(r)
 regexp *r;
 {
         register char *s;
         register char op = EXACTLY;        /* Arbitrary non-END op. */
         register char *next;
         extern char *strchr();


         s = r->program + 1;
         while (op != END) {        /* While that wasn't END last time... */
                 op = OP(s);
                 printf("%2d%s", s-r->program, regprop(s));        /* Where, w
                 next = regnext(s);
                 if (next == NULL)                /* Next ptr. */
                         printf("(0)");
                 else
                         printf("(%d)", (s-r->program)+(next-s));
                 s += 3;
                 if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
                         /* Literal string, where present. */
                         while (*s != '\0') {
                                 putchar(*s);
                                 s++;
                         }
                         s++;
                 }
                 putchar('\n');
         }

         /* Header fields of interest. */
         if (r->regstart != '\0')
                 printf("start `%c' ", r->regstart);
         if (r->reganch)
                 printf("anchored ");
         if (r->regmust != NULL)
                 printf("must have \"%s\"", r->regmust);
         printf("\n");
 }

 /*
  - regprop - printable representation of opcode
  */
 static char *
 regprop(op)
 char *op;
 {
         register char *p;
         static char buf[50];

         (void) strcpy(buf, ":");

         switch (OP(op)) {
         case BOL:
                 p = "BOL";
                 break;
         case EOL:
                 p = "EOL";
                 break;
         case ANY:
                 p = "ANY";
                 break;
         case ANYOF:
                 p = "ANYOF";
                 break;
         case ANYBUT:
                 p = "ANYBUT";
                 break;
         case BRANCH:
                 p = "BRANCH";
                 break;
         case EXACTLY:
                 p = "EXACTLY";
                 break;
         case NOTHING:
                 p = "NOTHING";
                 break;
         case BACK:
                 p = "BACK";
                 break;
         case END:
                 p = "END";
                 break;
         case OPEN+1:
         case OPEN+2:
         case OPEN+3:
         case OPEN+4:
         case OPEN+5:
         case OPEN+6:
         case OPEN+7:
         case OPEN+8:
         case OPEN+9:
                 sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
                 p = NULL;
                 break;
         case CLOSE+1:
         case CLOSE+2:
         case CLOSE+3:
         case CLOSE+4:
         case CLOSE+5:
         case CLOSE+6:
         case CLOSE+7:
         case CLOSE+8:
         case CLOSE+9:
                 sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
                 p = NULL;
                 break;
         case STAR:
                 p = "STAR";
                 break;
         case PLUS:
                 p = "PLUS";
                 break;
         default:
                 regerror("corrupted opcode");
                 break;
         }
         if (p != NULL)
                 (void) strcat(buf, p);
         return(buf);
 }
 #endif

 /*
  * The following is provided for those people who do not have strcspn() in
  * their C libraries.  They should get off their butts and do something
  * about it; at least one public-domain implementation of those (highly
  * useful) string routines has been published on Usenet.
  */
 #ifdef STRCSPN
 /*
  * strcspn - find length of initial segment of s1 consisting entirely
  * of characters not from s2
  */

 static int
 strcspn(s1, s2)
 char *s1;
 char *s2;
 {
         register char *scan1;
         register char *scan2;
         register int count;

         count = 0;
         for (scan1 = s1; *scan1 != '\0'; scan1++) {
                 for (scan2 = s2; *scan2 != '\0';)        /* ++ moved down. */
                         if (*scan1 == *scan2++)
                                 return(count);
                 count++;
         }
         return(count);
 }
 #endif


 REGION.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\REGION.C

 /*
  * The routines in this file
  * deal with the region, that magic space
  * between "." and mark. Some functions are
  * commands. Some functions are just for
  * internal use.
  */
 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if        MEGAMAX & ST520
 overlay        "region"
 #endif

 /*
  * Kill the region. Ask "getregion"
  * to figure out the bounds of the region.
  * Move "." to the start, and kill the characters.
  * Bound to "C-W".
  */
 killregion(f, n)
 {
         register int    s;
         REGION          region;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if ((s=getregion(&region)) != TRUE)
                 return (s);
         if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
                 kdelete();                      /* command, so do magic */
         thisflag |= CFKILL;                     /* kill buffer stuff.   */
         curwp->w_dotp = region.r_linep;
         curwp->w_doto = region.r_offset;
         return (ldelete(region.r_size, TRUE));
 }

 /*
  * Copy all of the characters in the
  * region to the kill buffer. Don't move dot
  * at all. This is a bit like a kill region followed
  * by a yank. Bound to "M-W".
  */
 copyregion(f, n)
 {
         register LINE   *linep;
         register int    loffs;
         register int    s;
         REGION          region;

         if ((s=getregion(&region)) != TRUE)
                 return (s);
         if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
                 kdelete();
         thisflag |= CFKILL;
         linep = region.r_linep;                 /* Current line.        */
         loffs = region.r_offset;                /* Current offset.      */
         while (region.r_size--) {
                 if (loffs == llength(linep)) {  /* End of line.         */
                         if ((s=kinsert('\n')) != TRUE)
                                 return (s);
                         linep = lforw(linep);
                         loffs = 0;
                 } else {                        /* Middle of line.      */
                         if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
                                 return (s);
                         ++loffs;
                 }
         }
         mlwrite("[region copied]");
         return (TRUE);
 }

 /*
  * Lower case region. Zap all of the upper
  * case characters in the region to lower case. Use
  * the region code to set the limits. Scan the buffer,
  * doing the changes. Call "lchange" to ensure that
  * redisplay is done in all buffers. Bound to
  * "C-X C-L".
  */
 lowerregion(f, n)
 {
         register LINE   *linep;
         register int    loffs;
         register int    c;
         register int    s;
         REGION          region;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if ((s=getregion(&region)) != TRUE)
                 return (s);
         lchange(WFHARD);
         linep = region.r_linep;
         loffs = region.r_offset;
         while (region.r_size--) {
                 if (loffs == llength(linep)) {
                         linep = lforw(linep);
                         loffs = 0;
                 } else {
                         c = lgetc(linep, loffs);
                         if (c>='A' && c<='Z')
                                 lputc(linep, loffs, c+'a'-'A');
                         ++loffs;
                 }
         }
         return (TRUE);
 }

 /*
  * Upper case region. Zap all of the lower
  * case characters in the region to upper case. Use
  * the region code to set the limits. Scan the buffer,
  * doing the changes. Call "lchange" to ensure that
  * redisplay is done in all buffers. Bound to
  * "C-X C-L".
  */
 upperregion(f, n)
 {
         register LINE   *linep;
         register int    loffs;
         register int    c;
         register int    s;
         REGION          region;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if ((s=getregion(&region)) != TRUE)
                 return (s);
         lchange(WFHARD);
         linep = region.r_linep;
         loffs = region.r_offset;
         while (region.r_size--) {
                 if (loffs == llength(linep)) {
                         linep = lforw(linep);
                         loffs = 0;
                 } else {
                         c = lgetc(linep, loffs);
                         if (c>='a' && c<='z')
                                 lputc(linep, loffs, c-'a'+'A');
                         ++loffs;
                 }
         }
         return (TRUE);
 }

 /*
  * This routine figures out the
  * bounds of the region in the current window, and
  * fills in the fields of the "REGION" structure pointed
  * to by "rp". Because the dot and mark are usually very
  * close together, we scan outward from dot looking for
  * mark. This should save time. Return a standard code.
  * Callers of this routine should be prepared to get
  * an "ABORT" status; we might make this have the
  * conform thing later.
  */
 getregion(rp)
 register REGION *rp;
 {
         register LINE   *flp;
         register LINE   *blp;
         long fsize;
         long bsize;

         if (curwp->w_markp == NULL) {
                 mlwrite("No mark set in this window");
                 return (FALSE);
         }
         if (curwp->w_dotp == curwp->w_markp) {
                 rp->r_linep = curwp->w_dotp;
                 if (curwp->w_doto < curwp->w_marko) {
                         rp->r_offset = curwp->w_doto;
                         rp->r_size = (long)(curwp->w_marko-curwp->w_doto);
                 } else {
                         rp->r_offset = curwp->w_marko;
                         rp->r_size = (long)(curwp->w_doto-curwp->w_marko);
                 }
                 return (TRUE);
         }
         blp = curwp->w_dotp;
         bsize = (long)curwp->w_doto;
         flp = curwp->w_dotp;
         fsize = (long)(llength(flp)-curwp->w_doto+1);
         while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
                 if (flp != curbp->b_linep) {
                         flp = lforw(flp);
                         if (flp == curwp->w_markp) {
                                 rp->r_linep = curwp->w_dotp;
                                 rp->r_offset = curwp->w_doto;
                                 rp->r_size = fsize+curwp->w_marko;
                                 return (TRUE);
                         }
                         fsize += llength(flp)+1;
                 }
                 if (lback(blp) != curbp->b_linep) {
                         blp = lback(blp);
                         bsize += llength(blp)+1;
                         if (blp == curwp->w_markp) {
                                 rp->r_linep = blp;
                                 rp->r_offset = curwp->w_marko;
                                 rp->r_size = bsize - curwp->w_marko;
                                 return (TRUE);
                         }
                 }
         }
         mlwrite("Bug: lost mark");
         return (FALSE);
 }



 REGISTER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\REGISTER.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 /*
  *      this module handles the allocation and de-allocation of
  *      temporary registers. when a temporary register is allocated
  *      the stack depth is saved in the field deep of the address
  *      mode structure. when validate is called on an address mode
  *      structure the stack is popped until the register is restored
  *      to it's pre-push value.
  */

 struct amode    push[] = { {am_adec,7} },
                 pop[] = { {am_ainc,7} };
 int             next_data,
                 next_addr;
 int             max_data,
                 max_addr;

 gen_push(reg,rmode)
 /*
  *      this routine generates code to push a register onto the stack
  */
 int     reg, rmode;
 {       struct amode    *ap1;
         ap1 = xalloc(sizeof(struct amode));
         ap1->preg = reg;
         ap1->mode = rmode;
         gen_code(op_move,4,ap1,push);
 }

 gen_pop(reg,rmode)
 /*
  *      generate code to pop the primary register in ap from the
  *      stack.
  */
 int     reg, rmode;
 {       struct amode    *ap1;
         ap1 = xalloc(sizeof(struct amode));
         ap1->preg = reg;
         ap1->mode = rmode;
         gen_code(op_move,4,pop,ap1);
 }

 initstack()
 /*
  *      this routine should be called before each expression is
  *      evaluated to make sure the stack is balanced and all of
  *      the registers are marked free.
  */
 {       next_data = 0;
         next_addr = 0;
         max_data = 2;
         max_addr = 1;
 }

 validate(ap)
 /*
  *      validate will make sure that if a register within an address
  *      mode has been pushed onto the stack that it is popped back
  *      at this time.
  */
 struct amode    *ap;
 {       switch( ap->mode )
                 {
                 case am_direct:
                 case am_immed:
                         return;         /* no registers used */
                 case am_dreg:
                         if( ap->preg > 2 )
                                 return; /* not a temporary */
                         if( max_data - ap->deep >= 3 )
                                 {
                                 gen_pop(ap->preg,am_dreg);
                                 --max_data;
                                 }
                         break;
                 default:
                         if( ap->preg > 1 )
                                 return; /* not a temp register */
                         if( max_addr - ap->deep >= 2 )
                                 {
                                 gen_pop(ap->preg,am_areg);
                                 --max_addr;
                                 }
                         break;
                 }
 }

 struct amode    *temp_data()
 /*
  *      allocate a temporary data register and return it's
  *      addressing mode.
  */
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_dreg;
         ap->preg = next_data % 3;
         ap->deep = next_data;
         if( next_data > max_data )
                 {
                 gen_push(next_data % 3,am_dreg);
                 max_data = next_data;
                 }
         ++next_data;
         return ap;
 }

 struct amode    *temp_addr()
 /*
  *      allocate a temporary address register and return it's
  *      addressing mode.
  */
 {       struct amode    *ap;
         ap = xalloc(sizeof(struct amode));
         ap->mode = am_areg;
         ap->preg = next_addr % 2;
         ap->deep = next_addr;
         if( next_addr > max_addr )
                 {
                 gen_push(next_addr % 2,am_areg);
                 max_addr = next_addr;
                 }
         ++next_addr;
         return ap;
 }

 freeop(ap)
 /*
  *      release any temporary registers used in an addressing mode.
  */
 struct amode    *ap;
 {       if( ap->mode == am_immed || ap->mode == am_direct )
                 return;         /* no registers used */
         if( ap->mode == am_dreg && ap->preg < 3 )
                 --next_data;
         else if( ap->preg < 2 )
                 --next_addr;
 }



 REGSUB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\REGSUB.C

 /*
  * regsub
  *
  *        Copyright (c) 1986 by University of Toronto.
  *        Written by Henry Spencer.  Not derived from licensed software.
  *
  *        Permission is granted to anyone to use this software for any
  *        purpose on any computer system, and to redistribute it freely,
  *        subject to the following restrictions:
  *
  *        1. The author is not responsible for the consequences of use of
  *                this software, no matter how awful, even if they arise
  *                from defects in it.
  *
  *        2. The origin of this software must not be misrepresented, either
  *                by explicit claim or by omission.
  *
  *        3. Altered versions must be plainly marked as such, and must not
  *                be misrepresented as being the original software.
  */
 #include <stdio.h>
 #include <regexp.h>
 #include "regmagic.h"

 #ifndef CHARBITS
 #define        UCHARAT(p)        ((int)*(unsigned char *)(p))
 #else
 #define        UCHARAT(p)        ((int)*(p)&CHARBITS)
 #endif

 /*
  - regsub - perform substitutions after a regexp match
  */
 void
 regsub(prog, source, dest)
 regexp *prog;
 char *source;
 char *dest;
 {
         register char *src;
         register char *dst;
         register char c;
         register int no;
         register int len;
         extern char *strncpy();

         if (prog == NULL || source == NULL || dest == NULL) {
                 regerror("NULL parm to regsub");
                 return;
         }
         if (UCHARAT(prog->program) != MAGIC) {
                 regerror("damaged regexp fed to regsub");
                 return;
         }

         src = source;
         dst = dest;
         while ((c = *src++) != '\0') {
                 if (c == '&')
                         no = 0;
                 else if (c == '\\' && '0' <= *src && *src <= '9')
                         no = *src++ - '0';
                 else
                         no = -1;
                  if (no < 0) {        /* Ordinary character. */
                          if (c == '\\' && (*src == '\\' || *src == '&'))
                                  c = *src++;
                          *dst++ = c;
                  } else if (prog->startp[no] != NULL && prog->endp[no] != NUL
                         len = prog->endp[no] - prog->startp[no];
                         (void) strncpy(dst, prog->startp[no], len);
                         dst += len;
                         if (len != 0 && *(dst-1) == '\0') {        /* strncpy
                                 regerror("damaged match string");
                                 return;
                         }
                 }
         }
         *dst++ = '\0';
 }


 REKEY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\REKEY\REKEY.C

 #include <stdio.h>
 #include <sgtty.h>
 instruct()
 {
         static char *instructions[] =
         {
                 "Rekey : Usage - rekey fname\n",
                 "Where fname is the name of the key redefinition file you\n",
                 "wish to create.\n\n",
                 "Hit the key you want to redefine, then type the string you\n
                 "want the key defined as, followed by a carriage return.\n",
                 "Use the following escapes to insert control chars in the str
                 "                \\n = crlf sequence\n",
                 "                \\t = tab\n",
                 "                \\b = backspace\n",
                 "                \\r = carriage return\n",
                 "                \\f = form feed\n",
                 "                \\\\  = backslash\n",
                 "Hit the escape key to end this program\n",
                 "to clear all keyboard definitions\n",
                 "To redefine the keyboard, use the command\n",
                 "               type fname<cr>\n",
                 "where fname is the name of the file you created with rekey\n
                 NULL
         };
         register char **instructor = instructions;
         while (*instructor)
         {
                 write(2,*instructor,strlen(*instructor));
                 instructor++;
         }
 }

 /*
 ** returns null if normal character, returns extended character otherwise.
 ** character read is stuffed into *c
 */
 ext_getc(c)
         register int *c;
 {
         register int returnval;
         struct sgttyb gtty;
         ioctl(stdin,TIOCGETP,&gtty);
         gtty.sg_flags |= RAW;
         ioctl(stdin,TIOCSETP,&gtty);
         if (*c = getc(stdin))
                 returnval = NULL;
         else
                 returnval = *c = getc(stdin);
         if (*c == 3 || *c == 26 || *c == 27)
         {
                 *c = EOF;
                 return EOF;
         }
         gtty.sg_flags &= (RAW ^ 0xFFFF);
         ioctl(stdin,TIOCSETP,&gtty);
         return returnval;
 }

 char keybuf[128];
 char tmpbuf[128];

 map_string(to,from)
         char* to;
         char* from;
 {
         while (*from)
         {
                 if (*from == '\\')
                 {
                         switch (*++from)
                         {
                         case 'n':
                                 *to++ = '\r';
                                 *to++ = '\n';
                                 break;
                         case 't':
                                 *to++ = 9;
                                 break;
                         case 'b':
                                 *to++ = 8;
                                 break;
                         case 'r':
                                 *to++ = '\r';
                                 break;
                         case 'f':
                                 *to++ = '\f';
                                 break;
                         default:
                                 *to++ = *from;
                         }
                 } else
                 {
                         *to++ = *from;
                 }
                 from++;
         }
 }

 define_key(op)
         FILE *op;
 {
         int c;
         char *string;
         register int is_extended;
         if (EOF == (is_extended = ext_getc(&c)))
                 return EOF;
         if (is_extended)
         {
                 if (c >= 59 && c <= 68)
                 {
                         printf("F%d =",c-58);
                 } else if (c >= 84 && c <= 93)
                 {
                         printf("Shift F%d =",c-83);
                 } else if (c >= 94 && c <= 103)
                 {
                         printf("Ctrl F%d =",c-103);
                 } else if (c >= 104 && c <= 113)
                 {
                         printf("Alt F%d =",c-103);
                 } else
                 {
                         switch (c)
                         {
                         case 71:
                                 printf("Home=");
                                 break;
                         case 72:
                                 printf("%c=",24);
                                 break;
                         case 73:
                                 printf("Pg Up=");
                                 break;
                         case 75:
                                 printf("Left Arrow="); /* cursor left */
                                 break;
                         case 77:
                                 printf("Right Arrow="); /* cursor right */
                                 break;
                         case 79:
                                 printf("End=");
                                 break;
                         case 80:
                                 printf("%c=",25); /* cursor down */
                                 break;
                         case 81:
                                 printf("Pg Dn=");
                                 break;
                         case 82:
                                 printf("Ins=");
                                 break;
                         case 83:
                                 printf("Del=");
                                 break;
                         case 119:
                                 printf("Ctrl Home=");
                                 break;
                         case 132:
                                 printf("Ctrl Pg Up=");
                                 break;
                         case 115:
                                 printf("Ctrl Left Arrow="); /* cursor left */
                                 break;
                         case 116:
                                 printf("Ctrl Right Arrow="); /* cursor right
                                 break;
                         case 117:
                                 printf("Ctrl End=");
                                 break;
                         case 118:
                                 printf("Ctrl Pg Dn=");
                                 break;
                         default:
                                 break;
                         }
                 }
                 if (NULL == gets(tmpbuf))
                         return EOF;
                 map_string(keybuf,tmpbuf);        /* map newlines to crlfs */
                 /* output the redefines string to file */
                 fprintf(op,"\033[0;%d",c);
                 string = keybuf;                        /* control string */
                 while (*string)
                 {
                         fprintf(op,";%d",*string);        /* spit each decima
                         ++string;
                 }
                 fprintf(op,"p");                                /* terminate

         }
 }

 main(argc,argv)
         int argc;
         char *argv[];
 {
         FILE *op;
         if (argc == 1)
                 instruct();
         if (!--argc)        /* if no args are left */
                 exit(0);
         if (NULL == (op = fopen(*(++argv),"w")))
         {
                 fprintf(stderr,"rekey : cant open %s\n",*argv);
                 exit(1);
         }
         while (EOF != define_key(op))
                 ;
         exit(0);
 }


 REMANTE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\REMANTE.C



 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /***********************************************
 **
 **        remAnte(antecedent)
 **
 **        returns the truth value of the fact to be remembered
 **        similar to verify except that the fact is a known antecedent
 **        and is not a consequent of any rule.  And therefore can be remember
 **        false as well as true.
 **
 ************************************************/

 #include <stdio.h>
 #include "expert.h"
 #include "inference.h"


 int        remAnte(antecedent)
         int        antecedent ;
 {
 int p_value ;

 switch(ruleBuff[antecedent].flag)
         {
         case STRING_TRUE :
         case STRING_TRUE_HYP:
                 knownTrue[numTrue++]=ruleBuff[antecedent].string ;
                 return(TRUE) ;
         case STRING_FALSE :
                 knownTrue[numTrue++]=ruleBuff[antecedent].string ;
                 return(FALSE) ;
         default:  /* routine to run */
                 if(weKnow(antecedent,&p_value) == TRUE)
                         return(p_value) ;
                 if( runRoutine(antecedent) == TRUE )
                         {
                         knownTrue[numTrue++]=ruleBuff[antecedent].string ;
                         if((ruleBuff[antecedent].flag == ROUTINE_TRUE) ||
                                 (ruleBuff[antecedent].flag == ROUTINE_TRUE_HY
                                 {
                                 return(TRUE) ;
                                 }
                         else
                                 {
                                 return(FALSE) ;
                                 }
                         }
                 else
                         {
                         knownFalse[numFalse++]=ruleBuff[antecedent].string ;
                         if(ruleBuff[antecedent].flag == ROUTINE_FALSE)
                                 {
                                 return(TRUE) ;
                                 }
                         else
                                 {
                                 return(FALSE) ;
                                 }
                         }
         }
 }


 RENAME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\RENAME.C

 /************************************************************
  *          IBM PC "C" Bulletin Board                       *
  *          Tulsa, OK  918-664-8737                         *
  ************************************************************/






 rename(old, new)
 char *old, *new;
 {
         char buff[60];

         fcbinit(new,buff);
         bdos(19,buff);
         fcbinit(old,buff);
         fcbinit(new,buff+16);
         bdos(23,buff);
 }


 RETAB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\RETAB.C

 /*
         HEADER:                CUG236;
         TITLE:                Entab/Detab/Strip Combo;
         DATE:                05/17/1987;
         DESCRIPTION:        "Strips upper-order bits, detabifies, then entabi
                         text file.  Old and new tab increments can differ.  I
                         new increment is 1, no entabification occurs.";
         VERSION:        0.0;
         KEYWORDS:        Tab, Tabs, Tab Expansion, Tab Utility, Tabify, Untab
                         Detab, Detab Utility;
         FILENAME:        RETAB.C;
         COMPILERS:        vanilla;
         AUTHORS:        W. C. Colley III;
 */

 /*
                          Tab Size Readjustment Program

                    Copyright (c) 1987 William C. Colley, III

 This program combines the functions of an ENTAB program and a DETAB program
 in the same program.  Combining the two allows a simple means of retabifying
 a program.  For example, let's say you edit a C program with your editor set
 for a tab increment of 4.  Now, you TYPE this file on the console and you fin
 that it laps over the right edge of the screen because your terminal expands
 tabs with a tab increment of 8.         What you really would like to do is d
 some of the tabs so that your program will TYPE just like it looked inside th
 editor.         The following command will do just that:

         RETAB -O4 -N8 oldfile newfile

 In the above command line, the two file names must be in order, but the -
 options can be spread around anywhere.        In fact, the - options are opti
 Their default values are set by a pair of #defines below.  The -O option
 specifies the tab increment that the old file was created with.         The -
 specifies the desired tab increment of the new file.

 Note that or -N1 causes no entabification.  Thus, the following command will
 detabify a file:

         RETAB -O8 -N1 oldfile newfile

 Also note that if the old file contains no tabs, there will be no
 detabification.         Thus, the following command will entabify a detabifie

         RETAB -N8 oldfile newfile

 Blanks and tabs in quoted strings are left alone.  The C conventions regardin
 character constants like '"' and character strings like "Here\'s a \"quote\".
 are supported.
 */

 #include <stdio.h>

 /*  Uncomment the following #defines if you are using an AZTEC C compiler:  *

 /*
 #define getc(x)            agetc(x)
 #define putc(x,y)   aputc(x,y)
 */

 /*  User-adjustable default values:

 OLDTABS            4            /*        Default old tab increment.
 NEWTABS            8            /*        Default new tab increment.

 NORMAL            0            /*        Normal state.
 QUOTE            1            /*        Quoted string skip state.
 BLANK            2            /*        Blank parsing state.

 int main(argc,argv)
 int argc;
 char **argv;
 {
     int del, i, j, atoi();
     FILE *old, *new;
     static char *oldfile = NULL, *newfile = NULL;
     static int err = 0, oldtabs = OLDTABS, newtabs = NEWTABS;
     static int blnks = 0, col = 0, lit = 0, state = NORMAL;

     while (--argc) {
         if (**++argv == '-') {
             switch (i = *(*argv + 1)) {
                 case 'n':
                 case 'N':   if ((i = atoi(*argv + 2)) < 1) {
                                 printf("ERROR:  New tab increment < 1\n\n");
                                 err = !0;
                             }
                             else newtabs = i;
                             break;

                 case 'o':
                 case 'O':   if ((i = atoi(*argv + 2)) < 1) {
                                 printf("ERROR:  Old tab increment < 1\n\n");
                                 err = !0;
                             }
                             else oldtabs = i;
                             break;

                 default:    printf("ERROR:  Illegal option %s\n\n",*argv);
                             err = !0;  break;
             }
         }
         else if (!oldfile) oldfile = *argv;
         else if (!newfile) newfile = *argv;
         else {
             printf("ERROR:  Extra filename %s\n\n",*argv);
             err = !0;
         }
     }
     if (!oldfile || !newfile) {
         printf("Usage:\tRETAB { -Onn } { -Nnn } oldfile newfile\n\n");
         err = !0;
     }
     else if (!(old = fopen(oldfile,"r"))) {
         printf("ERROR:  Cannot find file %s\n\n",oldfile);
         err = !0;
     }
     else {
         if (!(new = fopen(newfile,"w"))) {
             printf("ERROR:  Cannot create file %s\n\n",newfile);
             err = !0;
         }
         else {
             while ((i = getc(old)) != EOF) {
                 i &= 0177;
                 switch (state) {
                     case NORMAL:    switch (i) {
                                         case '\n':  col = 0;  putc('\n',new);
                                                     break;

                                         case '\t':  blnks = oldtabs -
                                                         col % oldtabs;
                                                     state = BLANK;  break;

                                         case ' ':   blnks = 1;        state =
                                                     break;

                                         case '\'':  del = '\'';         goto

                                         case '"':   del = '"';
 quote1:                                                    if (!lit) state =

                                         default:    ++col;  putc(i,new);
                                                     break;
                                     }
                                     break;

                     case QUOTE:            switch (i) {
                                         case '\n':  if (!lit) state = NORMAL;
                                                     col = 0;  break;

                                         case '\t':  col += newtabs -
                                                         col % newtabs;
                                                     break;

                                         case '\'':
                                         case '"':   if (!lit && i == del)
                                                         state = NORMAL;

                                         default:    ++col;  break;
                                     }
                                     putc(i,new);  break;

                     case BLANK:            switch (i) {
                                         case '\t':  blnks += oldtabs - (col +
                                                         blnks) % oldtabs;
                                                     break;

                                         case ' ':   ++blnks;  break;

                                         case '"':   del = '"';        goto qu

                                         case '\'':  del = '\'';
 quote2:                                                    state = QUOTE;  go

                                         default:    state = NORMAL;
 entab:                                                    if (blnks > 1 &&
                                                         newtabs > 1)
                                                         while ((j = newtabs -
                                                             col % newtabs)
                                                             <= blnks) {
                                                             col += j;
                                                             blnks -= j;
                                                             putc('\t',new);
                                                         }
                                                     for (; blnks; --blnks) {
                                                         ++col;        putc('
                                                     }
                                                     if (i == '\n') col = 0;
                                                     else ++col;
                                                     putc(i,new);  break;
                                     }
                                     break;
                 }
                 lit = !lit && i == '\\';
             }
             if (ferror(new) || fclose(new)) {
                 printf("ERROR:  Disk full\n\n");
                 err = !0;
             }
         }
         fclose(old);
     }
     return err;
 }


 RETABF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\RETABF.C

 /*
         HEADER:                CUG236;
         TITLE:                Entab/Detab/Strip Combo -- Filter Version;
         DATE:                05/25/1987;
         DESCRIPTION:        "Strips upper-order bits, detabifies, then entabi
                         text file.  Old and new tab increments can differ.  I
                         new increment is 1, no entabification occurs.";
         VERSION:        0.0;
         KEYWORDS:        Tab, Tabs, Tab Expansion, Tab Utility, Tabify, Untab
                         Detab, Detab Utility;
         FILENAME:        RETABF.C;
         COMPILERS:        vanilla;
         AUTHORS:        W. C. Colley III;
 */

 /*
                          Tab Size Readjustment Program

                    Copyright (c) 1987 William C. Colley, III

 This program combines the functions of an ENTAB program and a DETAB program
 in the same program.  Combining the two allows a simple means of retabifying
 a program.  For example, let's say you edit a C program with your editor set
 for a tab increment of 4.  Now, you TYPE this file on the console and you fin
 that it laps over the right edge of the screen because your terminal expands
 tabs with a tab increment of 8.         What you really would like to do is d
 some of the tabs so that your program will TYPE just like it looked inside th
 editor.         The following command will do just that:

         RETABF -O4 -N8 <oldfile >newfile

 In the above command line, the parameters can appear in any order.  The -
 options are optional.  Their default values are set by a pair of #defines
 below.        The -O option specifies the tab increment that the old file was
 created with.  The -N option specifies the desired tab increment of the new
 file.

 Note that or -N1 causes no entabification.  Thus, the following command will
 detabify a file:

         RETABF -O8 -N1 <oldfile >newfile

 Also note that if the old file contains no tabs, there will be no
 detabification.         Thus, the following command will entabify a detabifie

         RETAB -N8 <oldfile >newfile

 Blanks and tabs in quoted strings are left alone.  The C conventions regardin
 character constants like '"' and character strings like "Here\'s a \"quote\".
 are supported.
 */

 #include <stdio.h>

 /*  User-adjustable default values:

 OLDTABS            4            /*        Default old tab increment.
 NEWTABS            8            /*        Default new tab increment.

 NORMAL            0            /*        Normal state.
 QUOTE            1            /*        Quoted string skip state.
 BLANK            2            /*        Blank parsing state.

 int main(argc,argv)
 int argc;
 char **argv;
 {
     int del, i, j, atoi();
     static int err = 0, oldtabs = OLDTABS, newtabs = NEWTABS;
     static int blnks = 0, col = 0, lit = 0, state = NORMAL;

     while (--argc) {
         if (**++argv == '-') {
             switch (i = *(*argv + 1)) {
                 case 'n':
                 case 'N':   if ((i = atoi(*argv + 2)) < 1) {
                                 fprintf(stderr,
                                     "ERROR:  New tab increment < 1\n\n");
                                 err = !0;
                             }
                             else newtabs = i;
                             break;

                 case 'o':
                 case 'O':   if ((i = atoi(*argv + 2)) < 1) {
                                 fprintf(stderr,
                                     "ERROR:  Old tab increment < 1\n\n");
                                 err = !0;
                             }
                             else oldtabs = i;
                             break;

                 default:    fprintf(stderr,
                                 "ERROR:  Illegal option %s\n\n",*argv);
                             err = !0;  break;
             }
         }
         else {
             fprintf(stderr,"ERROR:  Illegal parameter %s\n\n",*argv);
             err = !0;
         }
     }
     if (err) {
         fprintf(stderr,"Usage:\tRETABF { -Onn } { -Nnn } oldfile newfile\n\n"
         err = !0;
     }
     else {
         while ((i = getchar()) != EOF) {
             i &= 0177;
             switch (state) {
                 case NORMAL:        switch (i) {
                                     case '\n':        col = 0;  putchar('\n')
                                                 break;

                                     case '\t':        blnks = oldtabs -
                                                     col % oldtabs;
                                                 state = BLANK;        break;

                                     case ' ':        blnks = 1;  state = BLAN
                                                 break;

                                     case '\'':        del = '\'';  goto quote

                                     case '"':        del = '"';
 quote1:                                                if (!lit) state = QUOT

                                     default:        ++col;        putchar(i);
                                 }
                                 break;

                 case QUOTE:        switch (i) {
                                     case '\n':        if (!lit) state = NORMA
                                                 col = 0;  break;

                                     case '\t':        col += newtabs -
                                                     col % newtabs;
                                                 break;

                                     case '\'':
                                     case '"':        if (!lit && i == del)
                                                     state = NORMAL;

                                     default:        ++col;        break;
                                 }
                                 putchar(i);  break;

                 case BLANK:        switch (i) {
                                     case '\t':        blnks += oldtabs - (col
                                                     blnks) % oldtabs;
                                                 break;

                                     case ' ':        ++blnks;  break;

                                     case '"':        del = '"';  goto quote2;

                                     case '\'':        del = '\'';
 quote2:                                                state = QUOTE;

                                     default:        state = NORMAL;
 entab:                                                if (blnks > 1 &&
                                                     newtabs > 1)
                                                     while ((j = newtabs -
                                                         col % newtabs)
                                                         <= blnks) {
                                                         col += j;
                                                         blnks -= j;
                                                         putchar('\t');
                                                     }
                                                 for (; blnks; --blnks) {
                                                     ++col;  putchar(' ');
                                                 }
                                                 if (i == '\n') col = 0;
                                                 else ++col;
                                                 putchar(i);  break;
                                 }
                                 break;
             }
             lit = !lit && i == '\\';
         }
     }
     return err;
 }


 REVVID.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MIKES30C\REVVID.C

 highlight(c)    /* Put character on screen in reverse video */
 int        c;
 {
     union REGS REG;

     REG.h.ah = 0x9;
     REG.h.al = c;
     REG.h.bl = 0x78;
     REG.h.bh = 00;
     REG.x.cx = 1;
     int86(0x10, &REG, &REG);

     return(REG.x.ax);

 }



 REWIND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\REWIND.C

 /* 1.0  12-17-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         METACHAR
 rewind(fp)                /* Set the FILE fp to the ORIGIN. Return EOF on
                            error.                                        */
 /*----------------------------------------------------------------------*/
 FILE *fp;
 {
         METACHAR fseek();

         return fseek(fp, 0L, ORIGIN);
 }


 RFILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\RFILE.C

 /*   This is a set of 3 general functions that will perform random
 *    file access.  `ropen()' opens a random file or creats it if it
 *    doesn't exist.  `hirec()' returns the high or last record in a
 *    file.  `rfile()' preforms the actual read/write operations.
 *    YOU MUST `close(port)' A FILE WHEN YOU ARE DONE.
 *    EACH RECORD is a STRUCTURE of size `sz', that is `sz=sizeof(*data);'.
 *    `data' is the pointer to the record structure that has been
 *    loaded prior to a read, or where data is written into.
 *    `rfiel()' returns the number of the record acted upon, should be
 *    the one you called UNLESS you called a recored number higher than
 *    the last record, then the actual record number is returned.
 *    See the comments in the text for more info.
 */

 /*   RFILE.C  Random file access functions  */

 "ALL.H"    /* #defines O_RDWR = 2, O_CREAT = 0x0100 (hex)  */

 int ropen(filspc)   /*  open file for random access  */

 char *filspc;

 { int port;

   port=open(filspc,O_RDWR | O_CREAT);
   return(port);  /*  port<0 = error  */
 }


 int rfile(port,rec,data,sz,mode)   /*  random file access         *
                                    *   assumes port assigned     */
 int port,rec;
 int sz;          /*  sizeof(structure)  */
 char *data;      /*  random record structure  */
 char mode;       /*  r = read, w = write  */

 { int stat,read(),write(),lrec,hirec();
   long pos,lseek();

   stat=0;
   lrec=hirec(port,sz);
   if(rec>lrec)   {  if(mode=='w')  rec=lrec+1;
                     else rec=lrec;
                  };
   rec-=1;
   pos=rec*sz;
   lseek(port,pos,0);
   switch(mode)   {  case'r':stat=read(port,data,sz);
                             break;
                     case'w':stat=write(port,data,sz);
                             break;
                  };
   if(stat<=0) return(stat-1);   /* -1=EOF, <(-1)=error */
   else return(rec+1);
 }


 int hirec(port,sz)   /*  random record count  */

 int port;
 int sz;    /*  sizeof(structure)  */

 { int ct;
   long ef,lseek();

   ef=lseek(port,0L,2);
   ct=ef/sz;
   return(ct);
 }


 RINDEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RINDEX.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 rindex(s, c)        /* return pointer to last occurrence of char c in string
                    s, or NULL otherwise.                                */
 /*----------------------------------------------------------------------*/
 STRING s;
 char c;
 {
         STRING p;

         for (p = s; *s ; s++)
                 ;
         while (c ISNT *s AND s >= p)
                 s--;
         return (s < p ? NULL : s);
 }


 RKNSTEP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RKNSTEP.C

 /* 1.0  11-19-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Integration step for N first-order ordinary differential equations
  *        using the 4th-order Runge-Kutta formulas, given in
  *
  *        HANDBOOK OF MATHEMATICAL FUNCTIONS, U. S. Dept. of Commerce,
  *        National Bureau of Standards Applied Mathematics Series No. 55,
  *        formula 25.5.10, page 896, June, 1964,
  *
  *        on each equation y'[i] = f(i, t, y[i]), i = 0, ... , N-1, as time
  *        progresses.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         VOID
 rknstep(N, f, h, t, y1, y2, dy, k, ys)
                 /* Store y2[i] = y1[i](t+h), for y1[i]' = f(i, t, y1),
                    using 4th-order Runge-Kutta method, i = 0, ... , N.
 /*----------------------------------------------------------------------*/
 double (*f)(), h, t, y1[], y2[], dy[], k[], ys[];
 /*
  *        Note: dy[] is a scratch array needed to hold intermediate
  *        calculations accumulating the dy value; k[] holds coefficients
  *        k1, k2, k3, and k4, successively; and the ys[] is for y approximant
  *        for each i.
  */
 {
         int i;
         double h2, ldexp();

         h2 = ldexp(h, -1);
         for (i = 0; i < N; i++)                /* i is equation index.
         {        dy[i] = h * (*f)(i, t, y1);                /* k1        */
                 ys[i] = y1[i] + dy[i] / 2;
         }
         for (i = 0; i < N; i++)
         {        k[i] = h * (*f)(i, t + h2, ys);                /* k2
                 dy[i] += 2 * k[i];
         }
         for (i = 0; i < N; i++)
                 ys[i] = y1[i] + k[i] / 2.0;
         for (i = 0; i < N; i++)
         {        k[i] = h * (*f)(i, t + h2, ys);                /* k3
                 dy[i] += 2 * k[i];
         }
         for (i = 0; i < N; i++)
                 ys[i] = y1[i] + k[i];
         for (i = 0; i < N; i++)
                 dy[i] += h * (*f)(i, t + h, ys);        /* k4        */
                                 /* dy is (k1 + 2 k2 + 2 k3 + k4) */
         for (i = 0; i < N; i++)
                 y2[i] = y1[i] + dy[i] / 6.0;
 }


 RKSTEP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\RKSTEP.C

 /* 1.0  01-22-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  *        Integration step of first-order ordinary differential equation
  *        using the 4th-order Runge-Kutta formulas, given in
  *
  *        HANDBOOK OF MATHEMATICAL FUNCTIONS, U. S. Dept. of Commerce,
  *        National Bureau of Standards Applied Mathematics Series No. 55,
  *        formula 25.5.10, page 896, June, 1964.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         VOID
 rkstep(f, h, t, yp)        /* Store approximate y(t+h), for y' = f(t, y),
                            where y = *yp, using 4th-order Runge-Kutta
                            method.                                        */
 /*----------------------------------------------------------------------*/
 double (*f)(), h, t, *yp;
 {
         double k1, k2, k3, k4, h2, y, ldexp();

         h2 = ldexp(h, -1);
         y = *yp;
         k1 = h * (*f)(t, y);
         k2 = h * (*f)(t + h2, y + ldexp(k1, -1));
         k3 = h * (*f)(t + h2, y + ldexp(k2, -1));
         k4 = h * (*f)(t + h, y + k3);
         *yp += (k1 + ldexp(k2 + k3, 1) + k4) / 6.0;
 }


 RM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\KWMV\RM.C

 #include <stdio.h>
 main(argc,argv)
         int argc;
         char *argv[];
 {
         static char cmdbuf[128] = "del ";
         while(--argc)
         {
                 ++argv;
                 if (-1 == unlink(*(argv)))
                 {
                         fprintf(stderr,"rm : %s not found\n",*argv);
                 }
         }
 }




 RM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TOOLS\RM.C

 /*
  * rm.c remove a file or files
  */

 <stdio.h>              /* Standard I/O definitions */
 <dos.h>                /* Msdos definitions */
 <errno.h>              /* error codes */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 #include <io.h>
 #include <conio.h>

 static char ID[]="## rm.c 1.0 K.van Houten 230987 ##";
 int isdir(char *);
 extern char **wild(char *);
 int rmfile(char *);
 int rmdirect(char *);

 int fflg=0;                     /* FORCE flag (no errors) */
 int rflg=0;                     /* RECURSIVE flag */
 int iflg=0;                     /* Interactive flag */
 int tmp;                        /* for return values */
 struct stat statbuf;            /* for file status structure */
 char ibuf[10];

 main (argc, argv)
 int     argc;                   /* Number of command line arguments */
 char   *argv[];                 /* Array of pointers to arguments */
 {
     for (argc--,argv++; argc>0; argc--,argv++) {
         if (**argv == '-') {
             while (*++(*argv)) {
                 switch (**argv) {
                 case 'f':
                     fflg++;
                     break;
                 case 'r':
                     rflg++;
                     break;
                 case 'i':
                     iflg++;
                     break;
                 default:
 usage:              printf("Usage: rm [-fir] <pathname> [<pathname> ..]\n");
                     exit(1);
                 }
             }
         }

         else
             break;
     }
     /*
      * NOW THE ARGV[0] CONTAINS THE FIRST NON-OPTION ARGUMENT,
      * WHILE ARGC CONTAINS THE NUMBER OF ARGUMENTS LEFT.
      * SO WE HAVE AVAILABLE ARGV[0] -- ARGV[ARGC-1].
      */

     *ibuf = (char)7;

     if (argc < 1)
         goto usage;

     if (rflg && !fflg) {
         printf("rm: Are you sure you want recursive remove?");
         cgets(ibuf);
         putch('\n');
         if (!((ibuf[2] == 'y') || (ibuf[2] == 'Y'))) {
             exit(0);
         }

     }

     while (argc > 0) {
         /* check arg is dir ? */
         if (stat(*argv,&statbuf) == -1) {
             if (fflg == 0) {
                 printf("rm: %s no such file or directory\n",*argv);
             }
             argc--;
             argv++;
             continue;
         }
         if (statbuf.st_mode & S_IFDIR) {
             if (rflg) {
                 (void)rmdirect(*argv);
             }
             else {
                 if (fflg == 0) {
                     printf("rm: %s is directory\n",*argv);
                 }
             }
         }
         else {
             (void)rmfile(*argv);
         }

         /* Next argument */
         argc--;
         argv++;
     }
     return(0);
 }

 int
 rmfile(p)
 char *p;
 {
     if (iflg) {
         printf("rm: remove %s ?",p);
         cgets(ibuf);
         putch('\n');
         if ((ibuf[2] == 'q') || (ibuf[2] == 'Q'))
             exit(2);
         if (!((ibuf[2] == 'y') || (ibuf[2] == 'Y'))) {
             return(0);
         }
     }
     if (fflg) {
 #ifdef DEBUG
         tmp = 0;
         printf("Changing mode %s\n",p);
 #else
         tmp = chmod(p, S_IREAD | S_IWRITE);
 #endif
         if (tmp == -1)
             perror("chmod");
     }
 #ifdef DEBUG
     tmp = 0;
     printf("Unlinking %s\n",p);
 #else
     tmp = unlink(p);
 #endif
     if (tmp == -1) {
         perror("unlink");
         return(0);
     }
     return(1);
 }

 int
 rmdirect(p)
 char *p;
 {
     char buf[100];
     char base[100];
     char **w;
     int i;
     int error = 0; /* counts errors */

     strcpy(base,p);
     strcpy(buf,p);
     if (buf[strlen(buf)-1] != '\\')
        strcat(buf,"\\");
     strcat(buf,"*.*\0");
     w = wild(buf);
     if (w != NULL) {
         for (i=0;(w[i] != NULL);i++) {
             strcpy(buf,base);
             if (buf[strlen(buf)-1] != '\\')
                 strcat(buf,"\\");
             strcat(buf,w[i]);
             if (isdir(buf) == 1) {
                 if (rflg == 1) {
                     if (rmdirect(buf) == 0) {
                         error++;
                     }
                 }
                 else {
                     if (fflg == 0) {
                         printf("rm: %s is directory\n",buf);
                     }
                     error++;
                 }
             }
             else {
                 if (rmfile(buf) == 0)
                     error++;
             }
         }
     }
     /* all entrys done , now we can rmdir */
     if (error == 0) {
 #ifdef DEBUG
         tmp = 0;
         printf("Removing Directory %s\n",base);
 #else
         tmp = rmdir(base);
 #endif
         if (tmp == -1) {
             perror("rmdir");
             return(0);
         }
         return(1);
     }
     return(0);
 }

 int
 isdir(p)
 char *p;
 {
     struct stat st;
     if (stat(p,&st) == -1) {
         if (fflg == 0) {
             printf("rm: %s no such file or directory\n",p);
         }
     }
     return((st.st_mode & S_IFDIR) ? 1 : 0);
 }


 RMAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\WILDCARD\RMAIN.C

 #define MSDOS2

 #include "dos.h"
 #include "stdio.h"
 #include "ctype.h"
 #include "ios1.h"

 MAXARG 100              /* maximum command line arguments */

 extern int _stack,_fmode,_iomode;
 extern char _iname[],_oname[],_dos;
 extern struct UFB _ufbs[];

 static int argc;                        /* arg count */
 static char *argv[MAXARG];                /* arg pointers */


 /**
  *
  * name         _main - process command line, open files, and call "main"
  *
  * synopsis     _main(line);
  *              char *line;     ptr to command line that caused execution
  *
  * description        This function performs the standard pre-processing for
  *                the main module of a C program.  It accepts a command
  *                line of the form
  *
  *                        pgmname arg1 arg2 ...
  *
  *                and builds a list of pointers to each argument.  The first
  *                pointer is to the program name.  For some environments, the
  *                standard I/O files are also opened, using file names that
  *                were set up by the OS interface module XCMAIN.
  *
  ********
  *                Modified: 11 April 1984
  *                          Ross Nelson
  *
  *                This routine now treats quoted strings in the command line
  *                as a single token, and allows the expansion of wildcard
  *                characters (see WILDCARD.C).  A quoted string begins with
  *                one of the characters ' or " and continues until that
  *                character is found again (unless escaped by a \).  Any
  *                command argument containing the MSDOS wildcard characters
  *                (* and ?) must be quoted or this routine will attempt to
  *                perform filename expansion on them.  The program will
  *                exit if any wildcard expansion fails to match.        If wi
  *                expansion fills available memory or overflows MAXARG, a
  *                messaage will be printed, but processing will continue.
  ********
  *
  *                Further mods: Oct-11-84 Chuck Forsberg V2.12, Unix pathname
  *
  */
 _main(line)
 char *line;
 {
         char c;
         char quoted;
         int x;
 #ifdef MSDOS2
         char buf[135], *wild, *malloc();
 #endif
 #if UNIX == 0
         FILE *fp0, *fp1, *fp2;
         extern int _bufsiz;
         char *getmem();
 #endif

 /*
  *
  * Build argument pointer list
  *
  */
         for(argc = 0; argc < MAXARG; )
         {
                 while(isspace(*line))
                         line++;
                 if(*line == '\0')
                         break;
                 argv[argc++] = line;
                 quoted = 0;
                 if (((*line == '\'') || (*line == '"')) && (*(line-1) != '\\'
                 {
                         quoted++;
                         c = *line;
                         argv[argc-1]++;
                         while (*++line)
                                 if ((*line == c) && (*(line-1) != '\\'))
                                         break;
                 }
                 else
                         while((*line != '\0') && (isspace(*line) == 0))
                                 line++;
                 c = *line;
                 *line++ = '\0';
 #ifdef MSDOS2
                 if (!quoted && stpbrk(argv[argc-1], "*?")) {
                         wild = argv[--argc];
                         if (!wildcard(wild, 0x10, buf)) {
                                 bdos (9, "No match.\r\n$");
                                 exit (1);
                         }
                         else
                                 do {
                                         if (strcmp(buf, ".") && strcmp(buf, "
                                         {
                                                 if ((argc == MAXARG) ||
                                                 !(argv[argc] = malloc(strlen(
                                                 {
                                                         bdos (9, "Wildcard ex
                                                         break;
                                                 }
                                                 strcpy(argv[argc++], buf);
                                         }
                                 }
                                         while (wildcard(wild, 0x10, buf));
                 }
 #endif
                 if(c == '\0')
                         break;
         }
 /*
  *
  * Open standard files
  *
  */
 #if UNIX == 0
         if(_dos < 2)
         {
                 fp0 = freopen(_iname,"r",stdin);
                 if(_oname[0] != '>')
                         fp1 = freopen(_oname,"w",stdout);
                 else
                         fp1 = freopen(&_oname[1],"a",stdout);
                 fp2 = freopen("","a",stderr);
                 if (fp2 == NULL)
                         _exit(1);
                 if (fp0 == NULL) {
                         fputs("Can't open stdin file\n", fp2);
                         exit(1);
                 }
                 setbuf(fp0, getmem(_bufsiz));        /* set stdin buffered */
                 fp0->_flag &= ~_IOMYBUF;        /* allow rlsmem if later set
                 if (fp1 == NULL) {
                         fputs("Can't open stdout file\n", fp2);
                         exit(1);
                 }
         }
         else {
                 stdin->_file = 0;
                 stdin->_flag = _IOREAD;
                 stdout->_file = 1;
                 stdout->_flag = _IOWRT;
                 stderr->_file = 2;
                 stderr->_flag = _IOWRT | _IONBF;

                 x = ((_fmode ^ _iomode) & 0x8000) ? UFB_NT : 0;
                 _ufbs[0].ufbflg = UFB_OP | UFB_RA | x;
                 _ufbs[1].ufbfh = 1;
                 _ufbs[1].ufbflg = UFB_OP | UFB_WA | x;
                 _ufbs[2].ufbfh = 2;
                 _ufbs[2].ufbflg = UFB_OP | UFB_WA | x;
                 if (_fgdi(1) & 0x80)
                         stdout->_flag |= _IONBF;
         }
 #endif


 /*
  *
  * Call the program already.
  *
  */
         main(argc,argv);              /* Call main function */
         exit(0);
 }


 RMAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\RMAIN.C

 #define MSDOS2

 #include "dos.h"
 #include "stdio.h"
 #include "ctype.h"
 #include "ios1.h"

 MAXARG 100              /* maximum command line arguments */

 extern int _stack,_fmode,_iomode;
 extern char _iname[],_oname[],_dos;
 extern struct UFB _ufbs[];

 static int argc;                        /* arg count */
 static char *argv[MAXARG];                /* arg pointers */


 /**
  *
  * name         _main - process command line, open files, and call "main"
  *
  * synopsis     _main(line);
  *              char *line;     ptr to command line that caused execution
  *
  * description        This function performs the standard pre-processing for
  *                the main module of a C program.  It accepts a command
  *                line of the form
  *
  *                        pgmname arg1 arg2 ...
  *
  *                and builds a list of pointers to each argument.  The first
  *                pointer is to the program name.  For some environments, the
  *                standard I/O files are also opened, using file names that
  *                were set up by the OS interface module XCMAIN.
  *
  ********
  *                Modified: 11 April 1984
  *                          Ross Nelson
  *
  *                This routine now treats quoted strings in the command line
  *                as a single token, and allows the expansion of wildcard
  *                characters (see WILDCARD.C).  A quoted string begins with
  *                one of the characters ' or " and continues until that
  *                character is found again (unless escaped by a \).  Any
  *                command argument containing the MSDOS wildcard characters
  *                (* and ?) must be quoted or this routine will attempt to
  *                perform filename expansion on them.  The program will
  *                exit if any wildcard expansion fails to match.        If wi
  *                expansion fills available memory or overflows MAXARG, a
  *                messaage will be printed, but processing will continue.
  ********
  *
  *                Further mods: Oct-11-84 Chuck Forsberg V2.12, Unix pathname
  *
  */
 _main(line)
 char *line;
 {
         char c;
         char quoted;
         int x;
 #ifdef MSDOS2
         char buf[135], *wild, *malloc();
 #endif
 #if UNIX == 0
         FILE *fp0, *fp1, *fp2;
         extern int _bufsiz;
         char *getmem();
 #endif

 /*
  *
  * Build argument pointer list
  *
  */
         for(argc = 0; argc < MAXARG; )
         {
                 while(isspace(*line))
                         line++;
                 if(*line == '\0')
                         break;
                 argv[argc++] = line;
                 quoted = 0;
                 if (((*line == '\'') || (*line == '"')) && (*(line-1) != '\\'
                 {
                         quoted++;
                         c = *line;
                         argv[argc-1]++;
                         while (*++line)
                                 if ((*line == c) && (*(line-1) != '\\'))
                                         break;
                 }
                 else
                         while((*line != '\0') && (isspace(*line) == 0))
                                 line++;
                 c = *line;
                 *line++ = '\0';
 #ifdef MSDOS2
                 if (!quoted && stpbrk(argv[argc-1], "*?")) {
                         wild = argv[--argc];
                         if (!wildcard(wild, 0x10, buf)) {
                                 bdos (9, "No match.\r\n$");
                                 exit (1);
                         }
                         else
                                 do {
                                         if (strcmp(buf, ".") && strcmp(buf, "
                                         {
                                                 if ((argc == MAXARG) ||
                                                 !(argv[argc] = malloc(strlen(
                                                 {
                                                         bdos (9, "Wildcard ex
                                                         break;
                                                 }
                                                 strcpy(argv[argc++], buf);
                                         }
                                 }
                                         while (wildcard(wild, 0x10, buf));
                 }
 #endif
                 if(c == '\0')
                         break;
         }
 /*
  *
  * Open standard files
  *
  */
 #if UNIX == 0
         if(_dos < 2)
         {
                 fp0 = freopen(_iname,"r",stdin);
                 if(_oname[0] != '>')
                         fp1 = freopen(_oname,"w",stdout);
                 else
                         fp1 = freopen(&_oname[1],"a",stdout);
                 fp2 = freopen("","a",stderr);
                 if (fp2 == NULL)
                         _exit(1);
                 if (fp0 == NULL) {
                         fputs("Can't open stdin file\n", fp2);
                         exit(1);
                 }
                 setbuf(fp0, getmem(_bufsiz));        /* set stdin buffered */
                 fp0->_flag &= ~_IOMYBUF;        /* allow rlsmem if later set
                 if (fp1 == NULL) {
                         fputs("Can't open stdout file\n", fp2);
                         exit(1);
                 }
         }
         else {
                 stdin->_file = 0;
                 stdin->_flag = _IOREAD;
                 stdout->_file = 1;
                 stdout->_flag = _IOWRT;
                 stderr->_file = 2;
                 stderr->_flag = _IOWRT | _IONBF;

                 x = ((_fmode ^ _iomode) & 0x8000) ? UFB_NT : 0;
                 _ufbs[0].ufbflg = UFB_OP | UFB_RA | x;
                 _ufbs[1].ufbfh = 1;
                 _ufbs[1].ufbflg = UFB_OP | UFB_WA | x;
                 _ufbs[2].ufbfh = 2;
                 _ufbs[2].ufbflg = UFB_OP | UFB_WA | x;
                 if (_fgdi(1) & 0x80)
                         stdout->_flag |= _IONBF;
         }
 #endif


 /*
  *
  * Call the program already.
  *
  */
         main(argc,argv);              /* Call main function */
         exit(0);
 }


 ROCKET.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\ROCKET.C

 /****************************************************************/
 /* ROCKET.C - A revised program typed from the book "Microsoft C*/
 /* Programming for the IBM" by Robert Lafore. The program is on */
 /* page 241. ANSI.SYS must be set up to use. This program is a  */
 /* slightly changed version of MOVE.C (page 241).               */
 /****************************************************************/

 #define ROWS 25
 #define COLS 5
 #define HOMECLR "\x1B[2J"
 #define CUR_BOTT "\x1B[%d;%df"
 #define CUR_TOP "\x1B[%d;%df"

 main()
 {
 int count, j, k, m;
 char *ptr[ROWS];           /*pointers to rows*/
 char *temp;                /*pointer storage*/
 static char pict[ROWS][COLS] = {       /* rocketship */
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       0,       0,       0          },
       { 0,        0,       '\x1E',  0,       0          },
       { 0,        '\x1E',  '\x1E',  '\x1E',  0          }  };

 static char gnd[] =        /* ground line */
             { '\xCD', '\xCD', '\xCD', '\xCD', '\xCD' };

    for(count = 0; count < ROWS; count++)     /*set up pointers*/
       *(ptr + count) = *(pict + count);

    for(count = 0; count < ROWS - 1; count++) {  /*do ROWS-1 # of times*/
       printf(HOMECLR);
       printf(CUR_BOTT, 25,0);
       printf("%s", gnd);                   /*print ground*/
       printf(CUR_TOP, 0,0);
       for(j = 0; j < ROWS-1; j++) {   /*print screen*/
          for(k = 0; k < COLS; k++) {
             if(*(*(ptr + j) + k) != 0) {     /*is rocket on line?*/
                for(m = 0; m < COLS; m++)     /*Yes, print line*/
                   printf("%c", *(*(ptr + j) + m));
                break;
             }
          }
          printf("%c", '\n');
       }
       temp = *ptr;               /*rotate pointers to move rocket*/
       for(j = 0; j < ROWS - 1; j++)
          *(ptr + j) = *(ptr + j + 1);
       *(ptr + ROWS - 1) = temp;
    }
 }



 ROMAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\ROMAN.C


 /*
 ** Print numbers fron 1 to 25 as Roman numerals.
 */
 main()
         {
         int x = 1;
         printf("This program prints out Roman Numerals\n");
         while (x <= 25)  {
                 roman (x);
                 x = x + 1 ;
                 }
         printf("\n\nI hope you liked it!\n");
         }

 /*
 ** Print an Arabic number in Roman numerals.
 */
 roman(arabic)
 int arabic;
         {
         arabic = romanize(arabic,1000,'m');
         arabic = romanize(arabic,500,'d');
         arabic = romanize(arabic,100,'c');
         arabic = romanize(arabic,50,'l');
         arabic = romanize(arabic,10,'x');
         arabic = romanize(arabic,5,'v');
         arabic = romanize(arabic,1,'i');
         romanize(arabic,1,'i');
         printf("\n");
         }

 /*
 ** Print the character c as many times as there are
 ** j's in the number i, then return i minus the j's
 */
 romanize (i,j,c)
 char c;
 int i,j;
         {
         while (i>=j)
                 {
                 putch(c);
                 i = i - j;
                 }
         return i;
         }




 ROMAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\ROMAN.C


 /*
 ** Print numbers fron 1 to 25 as Roman numerals.
 */
 main()
         {
         int x = 1;
         printf("This program prints out Roman Numerals\n");
         while (x <= 25)  {
                 roman (x);
                 x = x + 1 ;
                 }
         printf("\n\nI hope you liked it!\n");
         }

 /*
 ** Print an Arabic number in Roman numerals.
 */
 roman(arabic)
 int arabic;
         {
         arabic = romanize(arabic,1000,'m');
         arabic = romanize(arabic,500,'d');
         arabic = romanize(arabic,100,'c');
         arabic = romanize(arabic,50,'l');
         arabic = romanize(arabic,10,'x');
         arabic = romanize(arabic,5,'v');
         arabic = romanize(arabic,1,'i');
         romanize(arabic,1,'i');
         printf("\n");
         }

 /*
 ** Print the character c as many times as there are
 ** j's in the number i, then return i minus the j's
 */
 romanize (i,j,c)
 char c;
 int i,j;
         {
         while (i>=j)
                 {
                 putch(c);
                 i = i - j;
                 }
         return i;
         }




 ROUND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ROUND.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/
         double
 round(x)                /* return x rounded to nearest integer in
                            magnitude                                        *
 /*----------------------------------------------------------------------*/
 double x;
 {
         double fint();

         if (x < 0.0)
                 x -= 0.5;
         else        x += 0.5;
         return (fint(x));
 }



 ROWCOL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\ROWCOL.C

 /* 1.0  01-08-86                                                (_rowcol.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /*----------------------------------------------------------------------*/

 /*                        EXTERNAL REFERENCES

 GLOBAL int outrow[], outcol[];

 /************************************************************************/
         VOID
 _rowcol(c, fp)                /* update outrow and outcol for character c.

 /*----------------------------------------------------------------------*/
 FILE *fp;
 {
         switch (c)
         {   case '\n':
                 ++outrow[fp->_unit];
             case '\r':
                 outcol[fp->_unit] = 0;
                 break;
             case '\t':
                 while (++outcol[fp->_unit] % TABSTOP)
                         ;
                 break;
             case '\f':
                 outrow[fp->_unit] = 0;
                 break;
             default:
                 ++outcol[fp->_unit];
         }
 }


 RPD_FALL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\RPD_FALL.C




 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[1]==FALL_FAST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 RPD_RISE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\RPD_RISE.C



 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[1]==RISE_FAST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 RS232EXP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\RS232EXP.C

 /*
         HEADER:                CUG236;
         TITLE:                RS232 Diagnostic Helper (Kila86);
         DATE:                05/17/1987;
         DESCRIPTION:        "Helps diagnose problems with the RS232 serial po
         VERSION:        1.1;
         KEYWORDS:        Serial port, RS-232;
         FILENAME:        RS232EXP.C;
         SEE-ALSO:        RS232EXP.DOC;
         COMPILERS:        vanilla;
         AUTHORS:        J. Kilar, W. C. Colley III;
 */

 /*  Portability Note:  This program was originally written for the DeSmet C
     compiler.  That compiler supplies a number of quirky functions that
     operate the screen on the IBM PC.  This program uses two of them:

         void scr_rowcol(r,c)                Set the cursor to row r (1-24),
         int r, c;                        column c (1-80).

         void scr_clr()                        Clear the screen.

     Users on other systems will have to use equivalents from their C compiler
     libraries or write equivalents.

     The Eco-C88 compiler has equivalent routines (that require ANSI.SYS to be
     installed) as follows:

 void clrscr(), scr_pos();
 #define scr_rowcol(r,c)                scr_pos((r)-1,(c)-1)
 #define scr_clr                        clrscr

     Folks using serial terminals (like my Z-19) can write routines like these

 void scr_rowcol(r,c)
 int r, c;
 {
     fprintf(stderr,"\033Y%c%c",r + (' '-1),c + (' '-1));
 }

 void scr_clr()
 {
     fprintf(stderr,"\033Y  \033E");
 }

     You can also work directly into the ANSI.SYS driver or work into an ANSI
     serial terminal like this:

 void scr_rowcol(r,c)
 int r, c;
 {
     fprintf(stderr,"\033[%d;%dH",r,c);
 }

 void scr_clr()
 {
     fprintf(stderr,"\033[2J");
 }

 */
 #include <stdio.h>

 /*  Portability Note:  A few compilers don't know the additional type
     void.  If yours is one of these, uncomment the following #define.

 /* #define        void                int

 int baudrate(), bothpc(), bothterm(), chkcable(), databits(), dcedte();
 int decterm(), deviceoff(), fullcable(), parity(), pc(), pcmale();
 int pcmodem(), pcport(), pcprint(), pcterm(), resp(), respny(), term();
 void blank(), clear(), devincomp(), heading(), nullmodem(), wait();

 void main()
 {
     while (1) {
         heading();                        /* display heading */
         if (deviceoff()) break;                /* check that devices are on *
         if (chkcable()) break;                /* check cable connected */
         if (baudrate()) break;                /* check baud rate */
         if (parity()) break;                /* parity */
         if (databits()) break;                /* check data bits */
         if (pc()) {                        /* handle PC involved case */
             if (pcmale()) break;        /* on serial not parallel port? */
             if (pcport()) break;        /* COM1 or COM2 */
             if (bothpc()) break;        /* two PCs case */
             if (pcterm()) break;        /* PC to a terminal case */
             if (pcmodem()) break;        /* PC to a modem case */
             if (pcprint()) break;        /* PC to a printer */
             if (fullcable()) break;        /* try full straight thru cable */
             devincomp();  break;
         }
         else if (term()) {                /* no PC, terminal case */
             if (pcmodem()) break;
             if (decterm()) break;        /* DEC terminal */
             if (bothterm()) break;        /* both terminals */
             if (fullcable()) break;        /* try 25 lead straight thru cable
             if (dcedte()) break;
             devincomp();  break;
         }
         else {
             if (dcedte()) break;
             devincomp();  break;
         }
     }
     blank();  blank();
     printf("Glad I could be of service to you.\n");
 }

 /* heading - displays header for program */
 void heading()
 {
     clear();
     printf("RS-232 MINI EXPERT SYSTEM.\n");
     printf("Version 1.1   by   Joe Kilar\n");
     blank();
     printf("This program will help you solve RS-232 serial communications ");
     printf("problems.\n");
     printf("Examples are connecting PCs to serial printers, modems, or");
     printf(" terminals.\n");
     blank();
     printf("If you're not sure about an answer you may try skipping it by\n")
     printf("answering no to whether the devices are communicating.  ");
     printf("Jot down\n");
     printf("the question in case further aids don't result in success.\n");
     wait();
     return;
 }


 int deviceoff()
 {
     clear();
     printf("Check that power to both devices is on.  If power is not \n");
     printf("on, turn it on. \n");
     return respny();
 }


 int chkcable()
 {
     clear();
     printf("Check that the serial cable is firmly connected to both ");
     printf("devices.\nIf not, ensure a good connection. \n");
     return respny();
 }

 int baudrate()
 {
     clear();
     printf("Check that the baud rates selected or required for both devices")
     printf("\nare the same.   Baud rate reflects the speed at which data is")
     printf("\ncommunicated.  Typical baud rates are 300,1200,2400,9600, and "
     printf("19.2K\n");
     blank();
     printf("Some devices have auto-baud.  They lock onto the baud rate of\n")
     printf("the other device sending successive RETURNs (sometimes SPACEs). "
     printf("At times\nnoise ");
     printf("may make it lock onto the wrong baud rate.  Try turning it\n");
     printf("off and then back on to reset it.\n");
     blank();
     printf("Ensure that the baud rates are identical and/or reset any\n");
     printf("device using auto-baud.\n");
     return respny();
 }

 int parity()
 {
     clear();
     printf("Check that the parity's selected or required for both devices\n")
     printf("are the same.   Parity has to do with an extra bit sent that can"
     printf("\nhelp detect transmission errors.  It is usually set to even, ")
     printf("odd\nor none.\n");
     blank();
     printf("Ensure that the parity's are identical.\n");
     return respny();
 }

 int databits()
 {
     clear();
     printf("Check that each device is set for the same number of data bits.")
     printf("\nUsual values are  7  or  8.\n");
     blank();
     printf("Ensure that the data bits selected are identical. \n");
     return respny();
 }

 int pc()
 {
     clear();
     printf("Is one or both devices an IBM or compatible PC? \n");
     return resp("No", "Yes");
 }

 int pcmale()
 {
     clear();
     printf("Check that the cable is connected to the PC's serial and\n");
     printf("not parallel port.\n");
     printf("The serial port has male pins protruding from it, the parallel\n"
     printf("port is female. \n");
     blank();
     printf("Make sure the cable is connected to the serial port.\n");
     return respny();
 }

 int pcport()
 {
     clear();
     printf("If you have more than one serial port or have a PCjr, make sure")
     printf("\nyou are connected to the correct serial port.\n");
     blank();
     printf("The port that comes on an XT, usually closest to the side with\n"
     printf("the power switch, is COM1.  The serial port on back of a PCjr\n")
     printf("may look like COM1 or COM2 depending on the way the software\n");
     printf("accesses it.  Try switching to the other port if you\n");
     printf("are in doubt.\n");
     blank();
     printf("Double check which port is used, switch the cable, or tell the\n"
     printf("program to use the other if there is another or you have a PCjr."
     printf("\n");
     return respny();
 }

 int bothpc()
 {
     int r;

     clear();
     printf("Are both devices IBM or compatible PCs?\n");
     if (r = resp("No","Yes")) nullmodem();
     return r;
 }

 int pcterm()
 {
     int r;

     clear();
     printf("Is the other device a terminal?\n");
     if (r = resp("No","Yes")) nullmodem();
     return r;
 }

 int pcmodem()
 {
     int r;

     clear();
     printf("Is the other device a modem?\n");
     if (r = resp("No","Yes")) (void)fullcable();
     return r;
 }

 int pcprint()
 {
     int r;

     clear();
     printf("Is the other device a printer?\n");
     if (r = resp("No","Yes")) {
         clear();
         blank();
         printf("Make sure the printer is an RS-232 device and not a ");
         printf("Centronics\nparallel device.  If it is Centronics, you need "
         printf("to attach it\nto the parallel port of the PC.\n");
         wait();
     }
     return r;
 }

 int fullcable()
 {
     clear();  blank();
     printf("Try a straight thru cable that uses all 25 pins.  Make sure the")
     printf("\ncable is not a null modem cable.\n");
     return respny();
 }

 void nullmodem()
 {
     clear();
     printf("You need a null modem cable.  You can purchase one from a\n");
     printf("computer store.  You can also make one yourself by wiring\n");
     printf("up a cable as shown below.\n");
     blank();
     printf("     2 ------------------------------------------------ 3\n");
     printf("     3 ------------------------------------------------ 2\n");
     printf("     4 ------------------------------------------------ 5\n");
     printf("     5 ------------------------------------------------ 4\n");
     printf("     6 ------------------------------------------------ 20\n");
     printf("     7 ------------------------------------------------ 7\n");
     printf("    20 ------------------------------------------------ 6\n");
     blank();
     printf("If the null modem cable doesn't work, see someone in Digital\n");
     printf("Electronics for help.\n");
     wait();
     return;
 }

 int term()
 {
     clear();
     printf("Is one or both devices a terminal?\n");
     return resp("No","Yes");
 }

 int decterm()
 {
     clear();
     printf("If the terminal is a DEC model such as VT100 or VT220\n");
     printf("and other device is not a DEC computer or modem to a DEC\n");
     printf("computer (e.g. VAX), turn off the XON/XOFF feature.\n");
     return respny();
 }

 int bothterm()
 {
     int r;

     clear();
     printf("Are both devices terminals?\n");
     if (r = resp("No","Yes")) nullmodem();
     return r;
 }

 int dcedte()
 {
     clear();
     printf("RS-232 devices fall into two classes - DTE (Data Terminal ");
     printf("Equip.)\nand DCE (Data Communications Equip.).  Try a full 25 ");
     printf("pin straight\nthrough cable if one device is DTE and the other ")
     printf("DCE.  If both\ndevices are DTEs or DCEs, you need a null modem ")
     printf("cable. The device\nmanual may indicate the device's type.\n");
     blank();
     printf("Devices that are usually DTEs: terminals and IBM compatible PCs."
     printf("\nDevices that are usually DCEs: modems, ports to minicomputers,"
     printf("\n   printers, VME bus serial ports, and devices designed to ");
     printf("talk\n   with terminals such as serial ports on micro ");
     printf("development\n   systems.\n");
     blank();
     printf("Does it seem that you need a null modem cable as the devices are"
     printf("\nboth DTEs or DCEs?\n");
     if (resp("No","Yes")) nullmodem();
     clear();
     return respny();
 }

 void devincomp()
 {
     clear();
     printf("The devices are probably not supplying all the signals required")
     printf("\nby the other.  See someone in Digital Electronics for help.\n")
     wait();
     return;
 }


 int respny()
 {
     blank();
     printf("    Are the devices communicating properly now?\n");
     return resp("No","Yes");
 }


 int resp(zero,one)
 char *zero,*one;
 {
     char buf[256], *gets();

     blank();  blank();
     printf("            0  - %s \n",zero);
     blank();
     printf("            1 -  %s \n",one);

     do {
         scr_rowcol(22,10);
         printf("Enter either 0 or 1, then hit <return>: ");
     } while (*gets(buf) != '0' && *buf != '1');
     return *buf == '1';
 }

 void wait()
 {
     char buf[256], *gets();

     scr_rowcol(22,10);
     printf("Hit <return> to continue.....");
     (void)gets(buf);
     return;
 }


 void clear()
 {
     scr_clr();        scr_rowcol(1,1);
     return;
 }

 void blank()
 {
     printf("\n");
     return;
 }



 RSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\RSORT.C

 /*             RAM Sort Main Program

         This program reads the standard input into RAM, sorts
         it by line, and writes it back out again.
 */

 #include <stdio.h>
 #include <string.h>
 #include "rsort.h"

 /*      main(argc,argv)

         Function: Read the standard input into memory, sort it, and
         write it to the standard output. If there's a switch "/+<n>",
         then sort starting at column <n>.

         Algorithm: Call readLines to read it in, offLines to adjust
         the sort column if the appropriate switch is present, sortLines
         to sort it, and writeLines to write it out. If CALIBRATE is
         defined, skip the reading and writing and fill the buffer up
         with hard-to-sort stuff; this is used to check the timing.
 */

 main(argc,argv)

 int argc;
 char *argv[];

 {
         int i;

         /* Read in the lines, or fill up the buffer with test data. */
 #ifdef CALIBRATE
         fillLines();
         puts("Starting sort...");
 #ifdef HIST
         startH();
 #endif HIST
 #else CALIBRATE
         readLines();
 #endif CALIBRATE

         /* Check for a starting column parameter. */
         for (i = 1; i < argc; i++)
                 if ((argv[i][0] == '/') && (argv[i][1] == '+'))
                         /* Column sort switch found, so set the
                            columns to sort from. */
                         offLines(atoi(&argv[i][2])-1);

         /* Sort the lines. */
         sortLines();

         /* Write the lines back out again. */
 #ifdef CALIBRATE
 #ifdef HIST
         endH();
 #endif HIST
         puts("done.\n");
 #else CALIBRATE
         writeLines();
 #endif CALIBRATE
 }

 /*      fillLines()

         Function: Fill the buffer with fake (and hard-to-sort) data.

         Algorithm: Fill up ten-character lines until out of buffer space.

         Comments: Remember, this is intended to calibrate the speed
         of the sort, not to test it. This isn't necessarily the worst
         case for the program, just a case that takes time.
 */

 fillLines()

 {
         char *bPtr;             /* Pointer into buffer. */
         char fakeIn[10];        /* Current fill string. */
         char *fPtr;             /* Pointer into fakeIn. */

         /* Start with "ZZZZZZZZZZ". */
         for (fPtr = fakeIn; fPtr < &fakeIn[9]; *fPtr++ = 'Z');
         fakeIn[9] = 0;

         /* Fill in the buffer. */
         for (bPtr = buffer, nextLPtr = lPtr;
              (bPtr < &buffer[BUFSIZE-10]) &&
               (nextLPtr < &lPtr[LPTRSIZE]);
              nextLPtr++) {
                 /* Set the line pointer entry for this line. */
                 nextLPtr->start = nextLPtr->sortAt = bPtr;
                 /* Get the next string ("Z...ZZ" -> "Z...ZY", etc.). */
                 for (fPtr = &fakeIn[8]; fPtr >= fakeIn; fPtr--)
                         if ((*fPtr)-- == 'A') *fPtr = 'Z';
                         else break;
                 /* Copy it into the buffer. */
                 strcpy(bPtr,fakeIn);
                 bPtr += 10;
         };
 }

 /*      readLines()

         Function: Read all the lines on the standard input into
         the buffer array, and set the lPtr array to point to each
         line in the buffer.

         Algorithm: Repeatedly call gets() until we've read the
         whole thing in. But make sure we don't overflow any of
         the arrays in the process.

         Comments: Note that there is no way with gets() to ensure
         that it doesn't overflow the buffer. For example, suppose
         we've almost filled up the buffer, and then get a very long
         line. Whatever is in memory after the buffer will get
         overwritten. This is a flaw in the standard I/O library,
         but not one we'll take the time to fix here. We will simply
         exit ASAP so it can't do very much damage.
 */

 readLines()

 {
         char *bPtr;   /* Pointer into buffer. */

         /* Fill in the buffer from standard input. */
         for (bPtr = buffer, nextLPtr = lPtr;
              (bPtr < &buffer[BUFSIZE]) &&
               (nextLPtr < &lPtr[LPTRSIZE]) &&
               (gets(bPtr) != NULL);
              nextLPtr->start = nextLPtr->sortAt = bPtr, nextLPtr++,
               bPtr += strlen(bPtr)+1);
         /* Check for errors. */
         if (bPtr >= &buffer[BUFSIZE])
                 fatal("Input too large for RAM sort");
         if (nextLPtr >= &lPtr[LPTRSIZE])
                 fatal("Input has too many lines");
 }

 /*      writeLines()

         Function: Write all the lines pointed to by the lPtr array
         (presumably they're in the buffer) to the standard output.

         Algorithm: Cycle thru the lines and call puts() for each one.

         Comments: This routine does not depend on the lines being in
         the buffer; they could be anywhere in the data segment. We
         don't use this feature - or rather lack of restriction - here,
         but it could be useful at some future date.
 */

 writeLines()

 {
         struct linePtr *lPPtr;  /* Line pointer pointer. */

         /* Write out each line. */
         for (lPPtr = lPtr; lPPtr < nextLPtr; puts((lPPtr++)->start));
 }

 /*      offLines(offset)

         Function: Start search from offset characters after the
         start of the line.

         Algorithm: Go thru the line pointer table and bump the
         sortAt field to point offset bytes past the start field;
         make sure, however, that it doesn't end up pointing past
         the end of the line.
 */

 offLines(offset)

 int offset;

 {
         struct linePtr *lPPtr;  /* Line pointer pointer. */
         int i;                  /* Byte count. */
         char *cp;               /* Pointer into line. */

         /* If there's nothing to do, don't do it. */
         if (offset <= 0) return;

         /* Update each line in the array. */
         for (lPPtr = lPtr; lPPtr < nextLPtr; lPPtr++) {
                 /* Find the byte, correcting for end-of-line. */
                 for (i = offset, cp = lPPtr->start;
                      (i > 0) && (*cp != 0); i--, cp++);
                 /* Set the sortAt pointer. */
                 lPPtr->sortAt = cp;
         };
 }

 /*      fatal(s)

         Function: Report fatal errors and then exit to the system.
         s is a pointer to a string that describes the error.

         Algorithm: Calls fputs() to write the error message to the
         standard error output stream. Then call exit() to abort
         execution.

         Comments: The C library has perror() and abort() routines,
         but this is slightly more portable.
 */

 fatal(s)

 char *s;

 {
         fputs("Fatal error: ",stderr);
         fputs(s,stderr);
         fputs(".\n",stderr);
         exit(1);
 }



 RULECOMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\RULECOMP.C


 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /*****************************************************************
 **        Expert system rule compiler
 **
 **        This compiler produces a file of the form:
 **
 **        Number_of_bytes_in_hypstack_section
 **        Hypstack_section
 **        Number_of_bytes_in_rule_section
 **        Rule base section
 **        Number_of_bytes_in_string_section
 **        String section
 **        EOF
 **
 **        The rule section consits of integer flags and long-integer
 **        pointers to strings in the string section.
 **
 **        All strings in the string section will be unique nomatter how
 **        many times they are repeated in the rules which are compiled
 **        into the rule base by this compiler.
 **
 **
 **        Usage:
 **
 **        rulecomp rule.file object.file
 **
 *****************************************************************/

 /*****************************************************************
 **
 **        rule compiler main routine
 **
 *******************************************************************/

 #include <stdio.h>
 #include <string.h>

 #include "expert.h"
 #include "keywords.h"

 int        main(argc,argv)
 int argc ;
 char **argv ;

 {
 char        strBuff[MAX_STRING_BUFF] ;
 int        i ;
 int        state ;
 int        strAddr;
 int        numHypot, hypStack[MAX_HYPS],strBuffOfst ;
 int        c ;
 int        ruleBuffOfst ;
 int        keyWrdNum ;
 int        getKewWord() ;
 int        putString() ;
 int        lineNum ;

 struct  rule_statement_r ruleBuff[MAX_RULE_STATEMENTS] ;

 int        done ;
 FILE        *infile, *outfile ;

 for( done = 0; done < MAX_STRING_BUFF; done ++ )
         strBuff[done] = 0 ;
 for( done = 0; done < MAX_HYPS ; done++ )
         hypStack[done]=0 ;
 done = FALSE ;

 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP argc=%d ",argc) ;
 #endif

 if(argc != 3 )
         {
         fprintf(stdout, "\n\n Usage: rulecomp in.file out.file\n\n" ) ;
         exit() ;
         }
 infile = fopen( argv[1], "r" );
 if(infile == NULL)
         {
         fprintf(stdout,"\n\n Cannot open input file %s ", argv[1]);
         exit() ;
         }
 outfile = fopen(argv[2], "wb" ) ;
 if(outfile == NULL)
         {
         fprintf(stdout,"\n\n Cannot open output file %s ",argv[2]);
         exit() ;
         }
 done = FALSE ;

 numHypot = 0 ;                                /* number of hypothesis is zero
 strBuffOfst = 0 ;                        /* pointer in buffer is zero */
 ruleBuffOfst = 0 ;                        /* rule buffer offset is zero */


 state = ANTECEDENT ;

 /* Compilation states:
 **
 **        Antecedent group in progress -- 1
 **        Consequent group in progress -- 2
 **
 **        If state 1 and you get a consequent then output group barrier.
 **                change state to 2.
 **        If state 2 and you get an antecedent then output group barrier.
 **                change state to 1.
 */
 lineNum = 1 ;
 printf("\n") ;
 while( !done )
         {

 /*
 **           get the key word number from the
 **        input file
 */
         printf("%04d  ",lineNum++) ;
         keyWrdNum = getKeyWord(infile,keyWords,&lineNum);
 /*
 **        error occured on line clear the line and
 **        start over.
 */
         if(keyWrdNum == KEY_EOF)
                 {
                 done = TRUE ;
                 continue ;
                 }
         if(keyWrdNum == KEY_WORD_ERROR)
                 {
                 while( ( (c = getc(infile))) != EOL && (c != EOF) )
                         putchar(c) ;
                 fprintf(stdout," **** KEY WORD not found on line " );
                 if(c == EOF)
                         {
                         done = TRUE ;
                         break ;
                         }
                 putchar(c) ;
                 continue;
                 }
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP keyWrdNum = %d",keyWrdNum ) ;
 #endif
 /*
 **        based on the key Word build the
 **        rule files
 */

         switch(keyWrdNum)
                 {
                 case AND_N :
                 case ANDIF_N :
                 case IF_N :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case AND_N, ANDIF_N, IF_N ") ;
 #endif
                         if(state == CONSEQUENT)
                                 {
                                 state = ANTECEDENT ;
                                 ruleBuff[ruleBuffOfst].flag = NULL ;
                                 ruleBuff[ruleBuffOfst++].string = NULL ;
                                 }
                         ruleBuff[ruleBuffOfst].flag = STRING_TRUE ;
                         strAddr=putString(infile,strBuff,&strBuffOfst) ;
                         ruleBuff[ruleBuffOfst++].string = strAddr ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP strAddr= %d",strAddr ) ;
 #endif
                         break ;
                 case ANDRUN_N :
                 case ANDIFRUN_N :
                 case IFRUN_N :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case AND_N, ANDIF_N, IF_N ") ;
 #endif
                         if(state == CONSEQUENT)
                                 {
                                 state = ANTECEDENT ;
                                 ruleBuff[ruleBuffOfst].flag = NULL ;
                                 ruleBuff[ruleBuffOfst++].string = NULL ;
                                 }
                         ruleBuff[ruleBuffOfst].flag = ROUTINE_TRUE ;
                         strAddr=putString(infile,strBuff,&strBuffOfst) ;
                         ruleBuff[ruleBuffOfst++].string = strAddr ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP strAddr= %d",strAddr ) ;
 #endif
                         break ;
                 case ANDNOT_N :
                 case IFNOT_N  :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case ANDNOT_N, IFNOT_N    ") ;
 #endif
                         if(state == CONSEQUENT)
                                 {
                                 state = ANTECEDENT ;
                                 ruleBuff[ruleBuffOfst].flag = NULL ;
                                 ruleBuff[ruleBuffOfst++].string = NULL ;
                                 }
                         ruleBuff[ruleBuffOfst].flag = STRING_FALSE ;
                         strAddr=putString(infile,strBuff,&strBuffOfst) ;
                         ruleBuff[ruleBuffOfst++].string = strAddr ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP strAddr=%d",strAddr) ;
 #endif
                         break ;
                 case ANDNOTRUN_N :
                 case IFNOTRUN_N  :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case ANDNOT_N, IFNOT_N    ") ;
 #endif
                         if(state == CONSEQUENT)
                                 {
                                 state = ANTECEDENT ;
                                 ruleBuff[ruleBuffOfst].flag = NULL ;
                                 ruleBuff[ruleBuffOfst++].string = NULL ;
                                 }
                         ruleBuff[ruleBuffOfst].flag = ROUTINE_FALSE ;
                         strAddr=putString(infile,strBuff,&strBuffOfst) ;
                         ruleBuff[ruleBuffOfst++].string = strAddr ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP strAddr=%d",strAddr) ;
 #endif
                         break ;
                 case ANDTHEN_N :
                 case THEN_N :
                 case THENHYP_N :
                 case ANDTHENHYP :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case ANDTHEN_N,THEN_N,THENHYP_N");
 #endif
                         if(state == ANTECEDENT)
                                 {
                                 state = CONSEQUENT ;
                                 ruleBuff[ruleBuffOfst].flag = NULL ;
                                 ruleBuff[ruleBuffOfst++].string = NULL ;
                                 }

                         if( (keyWrdNum == THENHYP_N) || (keyWrdNum == ANDTHEN
                                 ruleBuff[ruleBuffOfst].flag = STRING_TRUE_HYP
                         else
                                 ruleBuff[ruleBuffOfst].flag = STRING_TRUE ;

                         strAddr=putString(infile,strBuff,&strBuffOfst) ;
                         hypStack[numHypot++] = ruleBuffOfst ;
                         ruleBuff[ruleBuffOfst++].string = strAddr ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP strAddr=%d",strAddr) ;
 #endif
                         break ;
                 case ANDTHENRUN_N :
                 case THENRUN_N :
                 case THENRUNHYP_N :
                 case ANDTHENRUNHYP_N :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case ANDTHEN_N,THEN_N,THENHYP_N");
 #endif
                         if(state == ANTECEDENT)
                                 {
                                 state = CONSEQUENT ;
                                 ruleBuff[ruleBuffOfst].flag = NULL ;
                                 ruleBuff[ruleBuffOfst++].string = NULL ;
                                 }

                         if( (keyWrdNum == THENRUNHYP_N ) || (keyWrdNum == AND
                                 ruleBuff[ruleBuffOfst].flag = ROUTINE_TRUE_HY
                         else
                                 ruleBuff[ruleBuffOfst].flag = ROUTINE_TRUE ;

                         strAddr=putString(infile,strBuff,&strBuffOfst) ;
                         hypStack[numHypot++] = ruleBuffOfst ;
                         ruleBuff[ruleBuffOfst++].string = strAddr ;
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP strAddr=%d",strAddr) ;
 #endif
                         break ;
                 case KEY_EOF :
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case KEY_EOF ") ;
 #endif
                         done = TRUE ;
                         break ;
                 default:
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP case DEFAULT "  ) ;
 #endif
                         fprintf(stdout, " \n\n illegal keyword number found "
                 }
         }

 /*
 **        set up some blank space at the end of the rule file
 */

 ruleBuff[ruleBuffOfst].flag = NULL ;
 ruleBuff[ruleBuffOfst++].string = NULL ;
 ruleBuff[ruleBuffOfst].flag = NULL ;
 ruleBuff[ruleBuffOfst++].string = NULL ;
 ruleBuff[ruleBuffOfst].flag = NULL ;
 ruleBuff[ruleBuffOfst++].string = NULL ;
 if(ruleBuffOfst%2 == 0 )
         {
         ruleBuff[ruleBuffOfst].flag = NULL ;
         ruleBuff[ruleBuffOfst++].string = NULL ;
         }
 #ifdef        DEBUG
         fprintf(stdout,"\nDEBUG-RULECOMP ruleBoffOfst=%d", ruleBuffOfst ) ;
 #endif
 /*
 **        ruleBuffOfst -3 is the number of rule statements processed
 */

 /*
 **
 **        Write out all of the compiled information as follows:
 **
 **                numHypot*2        Number_of_bytes_in_hypstack_section
 **                hypStack        Hypstack_section
 **                ruleBuffOfst        Number_of_bytes_in_rule_section
 **                ruleBuff        Rule base section
 **                strBuffOfst        Number_of_bytes_in_string_section
 **                strBuff                String section
 **                EOF
 **
 */
 #ifdef DEBUG

         fprintf(stdout,"\nDEBUG numHypot=%d",numHypot ) ;

         for(i=0;i<numHypot;i++)
                 fprintf(stdout,"\nDEBUG     hypStack=%d",hypStack[i] ) ;

         fprintf(stdout,"\nDEBUG ruleBuffOfst=%d  ",ruleBuffOfst ) ;

         for(i=0;i<ruleBuffOfst;i++)
                 {
                 fprintf(stdout,"\nDEBUG ruleBuff[%d].flag=%d ",i,ruleBuff[i].
                 fprintf(stdout,"\nDEBUG ruleBuff[%d].string=%d ",i,ruleBuff[i
                 }

         fprintf(stdout,"\nDEBUG strBuffOfst=%d",strBuffOfst ) ;

         for(i=0;i<strBuffOfst;i++)
                 fprintf(stdout,"\nDEBUG strBuff[%d]=%d(d),%c(c)",i,strBuff[i]
 #endif
 fwrite(&numHypot,sizeof(int),1,outfile) ;
 fwrite(hypStack,sizeof(int),numHypot,outfile) ;
 fwrite(&ruleBuffOfst,sizeof(int),1,outfile) ;
 fwrite(ruleBuff,2*sizeof(int),ruleBuffOfst,outfile) ;
 fwrite(&strBuffOfst,sizeof(int),1,outfile) ;
 fwrite(strBuff,1,strBuffOfst,outfile) ;
 fclose(infile);
 fclose(outfile);
 #ifdef DEBUG
         fclose(stdout) ;
 #endif
 printf("\n\n") ;
 exit(0) ;
 }



 RUNROUTI.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\RUNROUTI.C



 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /*****************************************************************
 **
 **        runRoutine(antecedent)
 **
 **        spawns the process with the path name specified in
 **
 **        ruleBuff[antecedent].string
 **
 **        and returns the value as TRUE or FALSE  depending on
 **        the value returned from the exit() command from the spawnd routine.
 **
 **        the routine returns TRUE if there is any problem with spawning
 **        the specified executable.
 **
 ******************************************************************/
 #define        MAX_ARGS        20

 #include <stdio.h>

 #ifdef MSDOS
 #include <process.h>
 #endif

 #include <errno.h>

 #include "expert.h"
 #include "inference.h"
 #include "routine.h"

 int        runRoutine(cnsquent)
         int        cnsquent ;
 {
 extern int errno ;

 #ifdef UNIXSV
 int        pnid ;
 #endif

 int        i,argc,p_value,numChars ;
 char        buffer[MAX_STR_LEN], *string_p;
 char        *argv[MAX_ARGS] ;

 /*
 ** copy string to buffer to get parameters
 */

 string_p = &strBuff[ruleBuff[cnsquent].string] ;

 for (numChars = 0 ; numChars < MAX_STR_LEN ; numChars++)
         {
         buffer[numChars]= *( string_p + numChars ) ;
         if(buffer[numChars] == NULL)
                 break ;
         }

 #ifdef DEBUG
 printf("\nDEBUG -- runroutine -- copied string is %s\n",buffer) ;
 #endif

 /*
 ** set the argv(alues) to the proper location within the buffer
 */

 argc = 1 ;
 argv[0] = buffer ;

 for(i=0;i<numChars;i++)
         {
 #ifdef DEBUG
 printf("\n DEBUG -- runroutine parameters i = %d, char = %c \n",i,buffer[i])
 #endif
         if(buffer[i] == NULL)
                 {
                 break ;
                 }
         if(buffer[i] == BLANK)
                 {
                 buffer[i] = NULL ;
                 while( buffer[++i] == BLANK ) ;
                 if(buffer[i] == NULL)
                         {
                         break ;
                         }
                 argv[argc++] = &buffer[i] ;
                 if(argc == MAX_ARGS)
                         {
                         printf("\n maximum arguments exceeded for %s\n",strin
                         argc -= 1 ;
                         break ;
                         }
                 }
         }
 argv[argc]=NULL ;
 #ifdef DEBUG
 for( i = 0 ; i < argc ; i++)
         {
         printf("\n argv[%d] = %s\n",i,argv[i]) ;
         }

 printf("\nRunning Routine %s ",argv[0] ) ;
 #endif

 #ifdef MSDOS
 p_value=spawnv(P_WAIT,argv[0],argv ) ;
 #endif


 #ifdef UNIXSV
 pnid = fork() ;
 if(pnid == -1)
         {
         printf("\nFork failure! Running %s -- returning TRUE \n",argv[0]) ;
         return(TRUE) ;
         }
 if(pnid != 0 )                 /* parent */
         {
         wait(&p_value) ;
         if(p_value != -1)
                 p_value = (p_value >> 8 ) & 0x0ff ;
         }
 else                        /* child */
         {
         execv(argv[0],argv) ;
         }
 #endif

 /*
 **        The return value is set by the routine having an exit(X)  where
 **        X is the value to be returned...
 **        There is a problem since the return value can also provide an
 **        indication that there was some problem with the attempt as follows:
 */

 if(p_value == RETURN_ROUTINE_TRUE)
         {
 #ifdef DEBUG
         printf(" -- TRUE\n") ;
 #endif
         return(TRUE) ;
         }
 if(p_value == RETURN_ROUTINE_FALSE)
         {
 #ifdef DEBUG
         printf(" -- FALSE \n") ;
 #endif
         return(FALSE) ;
         }
 if(p_value)
         switch(errno)
                 {
                 case ENOENT :
                         printf("\n Executable file %s not found assumed TRUE\
                         return(TRUE) ;
                 case ENOEXEC :
                         printf("\n File %s is not executable assumed TRUE\n",
                         return(TRUE) ;
                 case ENOMEM :
                         printf("\ Not enough memory to run -- assumed TRUE\n"
                         return(TRUE) ;
                 }
 printf("\n Routine did not return either ROUTINE_TRUE or ROUTINE_FALSE assume
 return(TRUE) ;
 }



 SAVEIMAG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\SAVEIMAG.C

 /* SAVEIMAG.C - From page 582 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. Writes a screen image to a file.  */
 /* Usage:   A>saveimag filename.ext   where filename.ext is     */
 /* the file of the screen image you want to create. This pro-   */
 /* gram doesn't work exactly right. It skips the first line of  */
 /* the screen and puts in the command line that is used to      */
 /* invoke this program in the file. The screen is moved up one  */
 /* line when this program is invoked and that's whats on the    */
 /* screen when this program takes over, not the exact original  */
 /* screen. I'm unable to figure out how to fix it. Try your     */
 /* luck.                                                        */
 /****************************************************************/

 #include <stdio.h>
 #define SPACE '\x20'

 main(argc, argv)
 int argc;
 char *argv[];
 {
 FILE *fptr;
 int col, row, lastchar, whatchar();
 char ch, buff[80];               /*buffer to hold one row*/

    if (argc != 2)  {
       printf("\nType \"saveimag filename\".");
       exit();
    }
    if((fptr = fopen(argv[1], "w")) == NULL)  {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    for(row = 1; row < 25; row++)  {
       lastchar = 0;              /*last nonspace char*/
       for(col = 1; col < 80; col++)  {
          ch = whatchar(col, row);
          buff[col - 1] = ch;
          if(ch != SPACE)         /*remember col # of last*/
             lastchar = col;      /* nonspace character*/
       }
       buff[++lastchar - 1] = '\n';     /*insert \n and \0 after*/
       buff[++lastchar - 1] = '\0';     /*last nonspace char    */
       fputs(buff, fptr);               /*write row to file*/
    }
    fclose(fptr);
 }

 /* wharchar() */  /* returns char at screen location col, row */
                   /* cols from 1 to 80, rows from 1 to 25 */
 int whatchar(col, row)
 int col, row;
 {
 int far *farptr;
 char ch;

    farptr = (int far *) 0xB0000000;
    ch = *(farptr + (row - 1)*80 + col - 1);
    return(ch);
 }



 SCANF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SCANF.C

 #include <stdio.h>
 #include <ctype.h>

 extern        char        _numstr[];

 /* #define        skip()        do{c=(*get)(ip); if (c<1) goto done;}while(is

 #define        skip()        while(isspace(c)) { if ((c=(*get)(ip))<1) goto d

 _scanf(ip, get, unget, fmt, args)
 register unsigned char *ip;
 int (*get)();
 int (*unget)();
 register unsigned char *fmt;
 char **args;

 /*
  *        <fmt> points to a format control string.  <args> pointers to a
  *        list of arguments, each of which is the address of a variable in
  *        which input data may be stored.  The format string is used to
  *        control reading of characters from the <get> function.  As each
  *        character is needed <get> is called in the form "c = (*get)(ip);"
  *        where <c> is the character read (negative for errors) and <ip> is
  *        the auxiliary pointer specified by the <ip> parameter.  If a
  *        character needs to be un-gotten, a call to <unget> of the form
  *        "(*unget)(c, ip);" is made.  The format string is composed of
  *        characters and format specifications.  Any characters in <fmt>,
  *        except whitespace characters, which are not part of a format
  *        specifier are expected to be matched one-to-one by characters in
  *        the input stream.  Scanning terminates if a mismatch occurs or if
  *        any call to <get> results in an error.  Whitespace characters
  *        match 0 or more whitespace characters in the input stream.  The
  *        '%' character introduces a format specifier.  The general form of
  *        a format specifier is:
  *
  *                 %[*][<width>][l|h]{d|u|o|x|b|i|c|s}
  *
  *        The '*' specifies that a field is to be scanned by not stored.
  *        No variable pointer should be provided for non-stored format
  *        specs.  The <width> field specifies that maximum number of
  *        characters to be process to fill the given format type.  Less
  *        than <width> characters will be processed if the field ends
  *        before <width> characters have been processed.  A field ends when
  *        either a whitespace character, or a character which does not fit
  *        the specified format, is read.  The preceding 'l' (or
  *        capitalizing the conversion character) specifies that the
  *        associated variable is a "long" type.  The trailing character
  *        specifies the format type, as follows:
  *
  *                d Signed decimal integer
  *                u Unsigned decimal integer
  *                o Unsigned octal integer
  *                x Unsigned hexadecimal integer
  *                b Unsigned binary integer
  *                i Unsigned decimal/octal/hexadecimal/binary integer
  *                c Character
  *                s String
  *
  *        If a <width> is specified with the 'c' format, exactly <width>
  *        characters (including whitespace) are read from the input stream,
  *        and written to a string.  No '\0' character is added If the
  *        character following the '%' is not recognized, it is expected to
  *        match the input stream as a non-format character, thus "%%" is
  *        used to match a single '%' character.
  *
  *        One additional conversion is the brace-format.  Shown as "%[...]",
  *        the '...' represent a list of characters.  If the first character
  *        in the list is a '^', the field contains any characters -not- in
  *        the list (starting with the 1st character after the '^').  If the
  *        first character of the list is not a '^', then the field will
  *        only contain those characters found in the list.  The field will
  *        be stored as a null terminated string.  Unlike most of the other
  *        formats, this conversion does allow the programmer to specify
  *        that whitespace characters will be included in the resulting
  *        string.
  */

 {
         register long n;
         register int c, width, lval, cnt = 0;
         int store, neg, base, wide1, endnull;
         register unsigned char *p;
         char unsigned delim[128], digits[17], *q;
         char *strchr(), *strcpy();

         if (!*fmt)
                 return(0);

         c = (*get)(ip);
         while(c > 0)
                 {
                 store = FALSE;
                 if (*fmt == '%')
                         {
                         n        = 0;
                         width        = -1;
                         wide1        = 1;
                         base        = 10;
                         lval        = FALSE;
                         store        = TRUE;
                         endnull        = TRUE;
                         neg        = -1;

                         strcpy(delim,  "\011\012\013\014\015 ");
                         strcpy(digits, _numstr); /* "01234567890ABCDEF" */

                         if (fmt[1] == '*')
                                 {
                                 store = FALSE;
                                 ++fmt;
                                 }

                         while (isdigit(*++fmt))                /* width digit
                                 {
                                 if (width == -1)
                                         width = 0;
                                 wide1 = width = (width * 10) + (*fmt - '0');
                                 }
                         --fmt;
 fmtnxt:
                         ++fmt;
                         switch(tolower(*fmt))        /* tolower() is a MACRO!
                                 {
                                 case '*':
                                         store = FALSE;
                                         goto fmtnxt;

                                 case 'l':        /* long data */
                                         lval = TRUE;
 /* for compatability --> */        case 'h':        /* short data */
                                         goto fmtnxt;

                                 case 'i':        /* any-base numeric */
                                         base = 0;
                                         goto numfmt;

                                 case 'b':        /* unsigned binary */
                                         base = 2;
                                         goto numfmt;

                                 case 'o':        /* unsigned octal */
                                         base = 8;
                                         goto numfmt;

                                 case 'x':        /* unsigned hexadecimal */
                                         base = 16;
                                         goto numfmt;

                                 case 'd':        /* SIGNED decimal */
                                         neg = FALSE;
                                         /* FALL-THRU */

                                 case 'u':        /* unsigned decimal */
 numfmt:                                        skip();

                                         if (isupper(*fmt))
                                                 lval = TRUE;

                                         if (!base)
                                                 {
                                                 base = 10;
                                                 neg = FALSE;
                                                 if (c == '%')
                                                         {
                                                         base = 2;
                                                         goto skip1;
                                                         }
                                                 else if (c == '0')
                                                         {
                                                         c = (*get)(ip);
                                                         if (c < 1)
                                                                 goto savnum;
                                                         if ((c != 'x')
                                                          && (c != 'X'))
                                                                 {
                                                                 base = 8;
                                                                 digits[8]= '\
                                                                 goto zeroin;
                                                                 }
                                                         base = 16;
                                                         goto skip1;
                                                         }
                                                 }

                                         if ((neg == FALSE) && (base == 10)
                                          && ((neg = (c == '-')) || (c == '+')
                                                 {
 skip1:
                                                 c = (*get)(ip);
                                                 if (c < 1)
                                                         goto done;
                                                 }

                                         digits[base] = '\0';
                                         p = strchr(digits,toupper(c));

                                         if (!p && width)
                                                 goto done;

                                         while (p && width-- && c)
                                                 {
                                                 n = (n * base) + (p - digits)
                                                 c = (*get)(ip);
 zeroin:
                                                 p = strchr(digits,toupper(c))
                                                 }
 savnum:
                                         if (store)
                                                 {
                                                 p = *args;
                                                 if (neg == TRUE)
                                                         n = -n;
                                                 if (lval)
                                                         *((long*) p) = n;
                                                 else
                                                         *((int *) p) = n;
                                                 ++cnt;
                                                 }
                                         break;

                                 case 'c':        /* character data */
                                         width = wide1;
                                         endnull        = FALSE;
                                         delim[0] = '\0';
                                         goto strproc;

                                 case '[':        /* string w/ delimiter set *

                                         /* get delimiters */
                                         p = delim;
                                         if (*++fmt == '^')
                                                 fmt++;
                                         else
                                                 lval = TRUE;

                                         while ((*p++ = *fmt) != ']')
                                                 if (*fmt++ == '\0')
                                                         goto done;
                                         *--p = '\0';
                                         goto strproc;

                                 case 's':        /* string data */
                                         skip();
 strproc:
                                         /* process string */
                                         p = *args;

                                         while (width--)
                                                 {
                                                 q = strchr(delim, c);
                                                 if (lval ? !q : q)
                                                         break;
                                                 if (store)
                                                         *p++ = c;
                                                 c = (*get)(ip);
                                                 if (width && (c < 1))
                                                         {
                                                         if (endnull)
                                                                 *p = '\0';
                                                         goto done;
                                                         }
                                                 }

                                         if (store)
                                                 {
                                                 if (endnull)
                                                         *p = '\0';
                                                 ++cnt;
                                                 }
                                         break;

                                 case '\0':        /* early EOS */
                                         --fmt;
                                         /* FALL THRU */

                                 default:
                                         goto cmatch;
                                 }
                         }
                 else if (isspace(*fmt))                /* skip whitespace */
                         {
                         skip();
                         }
                 else
                         {                        /* normal match char */
 cmatch:
                         if (c != *fmt)
                                 break;
                         c = (*get)(ip);
                         }

                 if (store)
                         args++;

                 if (!*++fmt)
                         break;
                 }

 done:                                                /* end of scan */
         if ((c < 1) && (cnt == 0))
                 return(EOF);
         (*unget)(c, ip);
         return(cnt);
 }



 SCANF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SCANF.C

 /* 1.1  01-08-86                                                (scanf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /*----------------------------------------------------------------------*/

 LOCAL int lastchar;

 /************************************************************************/

 scanf(fmt, arg)                /* Read stdin using format fmt, and deposit
                            information into arguments in arg list. Return
                            count of items read, or EOF on error.        */
 /*----------------------------------------------------------------------*/
 STRING fmt;
 unsigned *arg;
 {
         int _getc(), unformat();

         lastchar = EOF;
         return unformat(_getc, fmt, &arg);
 }

 /************************************************************************/
         LOCAL
 _getc(forward)                /* Return a character from the stdin.
                            If forward is TRUE, get next character and
                            advance; else, unget the character unless the
                            end has been reached. Return EOF if so.        */
 /*----------------------------------------------------------------------*/
 BOOL forward;
 {
         LOCAL int lastch = EOF;

         return (lastch = (forward ? (feof(stdin) ? EOF : getchar())
                 : ungetc(lastch, stdin)));
 }


 SCBIGRD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCBIGRD.C

 /*
 ** BYTE Large File Read Benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** Feb. 17, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Routine times reading of a 1000000 byte file.
 **
 */

 #include stdio.h

 BUFSIZ 10000        /* Size of read buffer */
 LOOPS  100        /* Number of times to read BUFSIZ characters
                            to get 1000000 bytes read. */
 char *rbuff;                /* Pointer to read buffer */
 int tblock[4];                /* Timer block */

 main()
 {
         int i;
         int fd;

         /* Announce program */
         printf("BYTE Large File Read Benchmark\n\n");

         /* Now allocate (if you can) space for the read */
         rbuff=malloc(BUFSIZ);
         if(rbuff==NULL) {
                 printf("Not enough memory for rbuff\n");
                 exit(0);
         }

         /* Open the file */
         fd=fopen("BIGFILE.DAT","r");

         /* Turn on the timer */
         gtime(tblock);

         /* Loop and read the file */
         for(i=0;i<LOOPS;++i)
                 read(fd,rbuff,BUFSIZ);

         /* Turn off timer and close file */
         calctim(tblock);
         fclose(fd);

         /* Report results */
         printf("Results: (HH:MM:SS:1/100ths)\n");
         printf("Time to read file: %d:%d:%d:%d\n",tblock[0],tblock[1],
          tblock[2],tblock[3]);

         exit(0);
 }



 SCBIGWT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCBIGWT.C

 /*
 ** BYTE Small-C  Disk I/O benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** Feb. 17, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Test times the writing of a 1 million byte file
 ** Requires support routines gtime and calctim.
 */

 #include stdio.h

 BUFSIZ 10000        /* Size of write buffer */
 LOOPS  100        /* number of times to write BUFSIZ characters to get
                            1000000 byte file. */
 char *wbuff;                /* Pointer to write buffer */
 int tblock[4];                /* Timer block */

 main()
 {
         int i;
         int fd;                /* File handle */

         /* Announce program */
         printf("BYTE Large File Write Benchmark\n\n");

         /* Allocate space for the write if possible*/
         wbuff=malloc(BUFSIZ);
         if(wbuff==NULL) {
                 printf("Not enough memory for wbuff\n");
                 exit(0);
         }

         /* Fill up the buffer */
         for(i=0;i<BUFSIZ;++i)
                 wbuff[i]='A';

         /* Open the file */
         fd=fopen("BIGFILE.DAT","w");

         /* Turn on the timer */
         gtime(tblock);

         /* Loop and write the file */
         for(i=0;i<LOOPS;++i)
                 write(fd,wbuff,BUFSIZ);

         /* Turn off timer and close file */
         calctim(tblock);
         fclose(fd);

         /* Report results */
         printf("Results: (HH:MM:SS:1/100ths)\n");
         printf("Time to write file: %d:%d:%d:%d\n",tblock[0],tblock[1],
          tblock[2],tblock[3]);

         exit(0);

 }


 SCDSSK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCDSSK.C


 /*
 ** BYTE DOS-level disk seek and read benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** March 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Operation:
 ** 1. Prompt operator for which disk device to test.
 ** 2. Determine maximum number of DOS sectors on device
 ** 3. Seek across DOS partition in tenths, reading 1 sector.
 ** 4. Report time for (3)
 ** 5. Seek across DOS partition in tenths, reading 8 sectors.
 ** 6. Report time for (5)
 ** 7. Exit
 */
 COUNT 50        /* # of iterations */
 stdin 0                /* Standard in */
 stdout 1        /* Standard out */

 char *buff;                /* Buffer for sectors */
 int tblock[4];                /* Timer block */
 int ddblock[4];                /* DOS disk information block */
 int drive;                /* Drive designation */
 int sect;                /* Sector size */
 int accum;                /* Time accumulator */
 int tsects;                /* Total # of sectors */
 int ssize;                /* Step size */
 int i,j;                /* For loops */

 main()
 {

 /* Announce program and determine drive to use */
         printf("BYTE DOS Disk Seek-And-Read Benchmark\n");
         printf("(Times reported are in 1/100ths of a second\n");
         printf("Which drive (1=A, 2=B ...)?");
         fscanf(stdin,"%d",&drive);

 /* Get information on selected drive */
         ddblock[0]=drive;         /*Load drive info to send to gddinfo*/
         gddinfo(ddblock);
         tsects=ddblock[3]*ddblock[0];        /* Total Clusters * Clusters/Sec
         printf("Total sectors for this disk:%u\n",tsects);

 /* Allocate memory for up to 8 sectors */
         buff=malloc(ddblock[2]*8);

 /* First test...read across the disk in tenths reading 1 sector */
 /* Assembler routine does an unsigned divide (tsects/10) to determine*/
 /* step size (ssize)  */
 #asm
         MOV        AX,_tsects
         XOR        DX,DX
         MOV        BX,10
         DIV        BX
         MOV        _ssize,AX
 #endasm
         accum=0;                /* Initialize time counter */
         for(i=0;i<COUNT;++i)        /* Perform test COUNT times*/
         {
                 ddseek(drive,0,1,buff);        /* Start at 0 */
                 sect=0;
                 for(j=0;j<10;++j)        /*Step through 10 steps */
                 {
                         sect+=ssize;
                         gtime(tblock);        /* Start timer */
                         ddseek(drive,sect,1,buff);
                         calctim(tblock);        /* Stop timer */
                         accum+=tblock[3]+100*(tblock[2]+
                                 60*tblock[1]);        /*Increment time counte
                 }
         }
         printf("Step 10th of total/ Read 1 sector\n");
         printf("# of Seeks Timed:%d\n",COUNT*10);
         printf("Total time:%d\n",accum);

 /* Second test... Same as first test except data is read in eight sector
 ** blocks */
         accum=0;
         for(i=0;i<COUNT;++i)
         {
                 ddseek(drive,0,1,buff);        /* Start at 0 */
                 sect=0;
                 for(j=0;j<10;++j)
                 {
                         sect+=ssize;
                         /* Don't fall off the end */
                         if(sect>(tsects-8)) sect=tsects-8;
                         gtime(tblock);
                         ddseek(drive,sect,8,buff);  /* Read eight sectors */
                         calctim(tblock);
                         accum+=tblock[3]+100*(tblock[2]+
                                 60*tblock[1]);
                 }
         }
         printf("Step 10th of total/ Read 8 sectors\n");
         printf("# of Seeks Timed:%d\n",COUNT*10);
         printf("Total time:%d\n",accum);



 /* Exit */
         exit(0);
 }

 /*
 **
 ** gddinfo(ddblock) - Get DOS disk info
 ** ddblock is a 4-element array
 ** Entry: ddblock[0] holds drive # (0=A, 1=B...)
 ** Exit: ddblock[0] = sectors/cluster
 **       ddblock[1] = available clusters
 **       ddblock[2] = bytes per sector
 **       ddblock[3] = total clusters
 */
 gddinfo(ddblock) int ddblock[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Pointer to ddblock[0]
         MOV        DL,[SI]                ;Drive #
         MOV        AH,36H                ;Function #
         PUSH        SI                ;Save just in case
         INT        21H                ;Get disk info
         POP        SI                ;Recover ddblock pointer
         MOV        [SI],AX                ;Sectors/cluster
         MOV        2[SI],BX        ;Avail clusters
         MOV        4[SI],CX        ;Bytes/sector
         MOV        6[SI],DX        ;Total clusters
         XOR        CX,CX                ;For Small-C
 #endasm
 }

 /*
 **
 ** ddseek(drive,sector,num,buff) int drive,sector,num; char *buff;
 ** DOS disk seek to sector on drive.  Read in num sectors into buff.
 ** NOTE: This routine decrements drive so that 0=A, 1=B..etc.
 **
 */
 ddseek(drive,sector,num,buff) int drive,sector,num;
 char *buff;
 {
 #asm
         MOV        BP,SP
         MOV        AL,8[BP]        ;Get drive
         DEC        AL                ;Decrement so in interrupt format
         MOV        DX,6[BP]        ;Get sector #
         MOV        CX,4[BP]        ;Number of sectors
         MOV        BX,2[BP]        ;Buffer address
         INT        25H                ;Read
         POP        DX                ;Dump the extra word
         XOR        CX,CX                ;For Small-C
 #endasm
 }


 SCFILEIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCFILEIO.C

 /*
 ** BYTE File I/O Benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** March 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Operation:
 ** 1. Create N files of predetermined size
 ** 2. Extend those N files a set amount
 ** 3. Enter a loop, executing:
 **    (a) 3 reads
 **    (b) 1 write
 **    Each read/write operation is performed on a random
 **    number of bytes.
 ** 4. Report:
 **    (a) Accumulated seek time
 **    (b) Accumulated read time and total bytes read
 **    (c) Accumulated write time and total bytes written.
 ** 5. Exit
 **
 */

 #include stdio.h

 int tblock[4];                /* Timer block */
 int rtblock[4];                /* Timer block for read time */
 int wtblock[4];                /* Timer block for write time */
 int stblock[4];                /* Timer block for seek time */

 int twbytes[2];                /* Total bytes written */
 int trbytes[2];                /* Total bytes read */

 int seed;                /* Seed for random number generator */

 #define BUFSIZ 8000
 char *tstring;                /* Pointer to string to write */
 char *rbuff;                /* Buffer for reading */

 /*
 ** COUNT defines the number of times the read-read-read-write
 ** loop is performed.
 */

 #define COUNT 120

 main()

 {
         int i;

         /* Init the seed */
         seed=0;

         /* Announce yourself */
         printf("BYTE File I/O Benchmark\n\n");

         /* First build tstring */

         tstring=malloc(BUFSIZ);                /* Get memory */
         if(tstring==NULL) {
           printf("No memory for tstring\n");
           exit(0);
         }
         for(i=0;i<BUFSIZ;++i)
                 tstring[i]='A';                /* Load it up */

         rbuff=malloc(BUFSIZ);                /* Get memory */
         if(rbuff==NULL) {
           printf("No memory for rbuff\n");
           exit(0);
         }

         /* Make sure all accumulators are empty */

         for(i=0;i<4;++i)
                 rtblock[i]=stblock[i]=wtblock[i]=0;

         twbytes[0]=twbytes[1]=0;
         trbytes[0]=trbytes[1]=0;

         /* Create the files */
         printf("...Creating files\n");
         for(i=0;i<10;++i)
                 kreate(i);

         /* Extend them */
         printf("...Extending files\n");
         for(i=0;i<10;++i)
                 appnd(i);

         /* Do the random I/O stuff */
         printf("...Performing random reads/writes\n");
         dorands();

         /* Tell user what happened */
         report();

         exit(0);
 }

 /*
 ** kreate(n)
 ** Create file n.  Write the assigned number of bytes.
 ** Close the file.
 ** This routine accumulates the number of bytes written
 ** and the time to write them.
 */
 kreate(n) int n;
 {
         int fd;                /* File handle */
         int nb;                /* Number of bytes to write */

         switch(n) {

           case 0:
                   nb=4000;
                    break;
           case 1:
                   nb=10000;
                   break;
           case 2:
                   nb=500;
                   break;
           case 3:
                   nb=2800;
                   break;
           case 4:
                   nb=25000;
                   break;
           case 5:
                   nb=14000;
                   break;
           case 6:
                   nb=8000;
                   break;
           case 7:
                   nb=8800;
                   break;
           case 8:
                   nb=300;
                   break;
           case 9:
                   nb=21111;
                   break;
         }

         fd=fopen(gfname(n),"w");        /* Open the file */
         accwbytes(nb);                /* Accumulate total bytes written */
         while(nb!=0) {
           if(nb>4000) n=4000; else n=nb;
           gtime(tblock);                /* Turn on timer */
           write(fd,tstring,n);
           calctim(tblock);        /* Turn off the timer */
               accwtime();                /* Accumulate total write time */
           nb-=n;
         }
         fclose(fd);                /* Close the file */
         return;
 }
 /*
 ** appnd(n)
 ** Open nth file.  Append the appropriate number of bytes
 */
 appnd(n)
 int n;
 {

         int fd;                /* File handle */
         int nb;                /* Number of bytes */

         switch(n) {

           case 0:  nb=12000;
                    break;
           case 1:  nb=20300;
                    break;
           case 2:  nb=31111;
                    break;
           case 3:  nb=3400;
                    break;
           case 4:  nb=9099;
                    break;
           case 5:  nb=20755;
                    break;
           case 6:  nb=7000;
                    break;
           case 7:  nb=400;
                    break;
           case 8:  nb=22000;
                    break;
           case 9:  nb=27000;
                    break;
         }

         fd=fopen(gfname(n),"a");        /* Open in append mode */
         accwbytes(nb);                /* Accumulate total bytes written */
         while(nb!=0) {
           if(nb>4000) n=4000; else n=nb;
           gtime(tblock);                /* Turn on timer */
           write(fd,tstring,n);
           calctim(tblock);        /* Turn off the timer */
               accwtime();                /* Accumulate total write time */
           nb-=n;
         }
         fclose(fd);
         return;
 }

 /*
 ** dorands()
 ** Do the random reads and writes.  Accumulating as you go.
 **
 */
 dorands()
 {
         int i,j,nb;
         int fd,offsetl,offseth;

 /* Do the whole thing COUNT times */

         for(i=0;i<COUNT;++i)
         {

           /* For each COUNT, do 3 reads, 1 write */
           for(j=0;j<3;++j)
           {
                 fd=fopen(gfname(randwc(10)),"r");
                 seek(fd,0,0,2);
                 tell(fd,&offsetl,&offseth);        /* Get file len */
                 if(offseth!=0) offseth=randwc(offseth);
                 if(offsetl<0)
                         offsetl=seed=rand(seed);
                 else
                         offsetl=randwc(offsetl);
                 gtime(tblock);
                 seek(fd,offsetl,offseth,0);
                 calctim(tblock);
                 accstime();                /* Accumulate seek time */
                 nb=randwc(8000);        /* Bytes to read */
                 gtime(tblock);
                 nb=read(fd,rbuff,nb);
                 calctim(tblock);
                 if(nb==ERR) {
                   printf("Error reading\n");
                   exit(0);
                 }
                 accrbytes(nb);                /* Accumulate bytes read */
                 accrtime();
                 fclose(fd);
         }
                 fd=fopen(gfname(randwc(10)),"u");
                 seek(fd,0,0,2);
                 tell(fd,&offsetl,&offseth);        /* Get file len */
                 if(offseth!=0) offseth=randwc(offseth);
                 if(offsetl<0)
                         offsetl=seed=rand(seed);
                 else
                         offsetl=randwc(offsetl);
                 gtime(tblock);
                 seek(fd,offsetl,offseth,0);
                 calctim(tblock);
                 accstime();                /* Accumulate seek time */
                 nb=randwc(8000);        /* Bytes to write */
                 gtime(tblock);
                 nb=write(fd,tstring,nb);
                 calctim(tblock);
                 if(nb==ERR) {
                   printf("Error writing\n");
                   exit(0);
                 }
                 accwbytes(nb);                /* Accumulate bytes written */
                 accwtime();
                 fclose(fd);
         }
         return;
 }

 /*
 ** report()
 ** Report results
 */
 report()
 {

         printf("***Results:  (All times are HH:MM:SS:1/100)\n\n");

         printf(" Total seek time: %d:%d:%d:%d\n\n",stblock[0],
                  stblock[1],stblock[2],stblock[3]);

         printf(" Total read time: %d:%d:%d:%d\n\n",rtblock[0],
                  rtblock[1],rtblock[2],rtblock[3]);
         printf("            bytes:");

         writebig(trbytes);
         printf("\n\n");

         printf(" Total write time: %d:%d:%d:%d\n\n",wtblock[0],
                  wtblock[1],wtblock[2],wtblock[3]);
         printf("             bytes:");

         writebig(twbytes);
         printf("\n\n");

         printf("P.S. Don't forget to delete the files.\n");

 }


 /*
 ** Take the time interval stored in tblock[] and add that to
 ** the array holding total accumulated write time (wtblock[]).
 */
 accwtime()
 {
         wtblock[3]+=tblock[3];        /* Hundredths */
         if(wtblock[3]>=100) {
                 wtblock[2]+=1;
                 wtblock[3]-=100;
         }
         wtblock[2]+=tblock[2]; /* Seconds */
         if(wtblock[2]>=60) {
                 wtblock[1]+=1;
                 wtblock[2]-=60;
         }
         wtblock[1]+=tblock[1]; /* Minutes */
         if(wtblock[1]>=60) {
                 wtblock[0]+=1;
                 wtblock[1]-=60;
         }
         wtblock[0]+=tblock[0];        /* Hours */
         return;
 }

 /*
 ** Take the time interval stored in tblock[] and add that to
 ** the array holding total accumulated read time (rtblock[]).
 */
 accrtime()
 {
         rtblock[3]+=tblock[3];        /* Hundredths */
         if(rtblock[3]>=100) {
                 rtblock[2]+=1;
                 rtblock[3]-=100;
         }
         rtblock[2]+=tblock[2]; /* Seconds */
         if(rtblock[2]>=60) {
                 rtblock[1]+=1;
                 rtblock[2]-=60;
         }
         rtblock[1]+=tblock[1]; /* Minutes */
         if(rtblock[1]>=60) {
                 rtblock[0]+=1;
                 rtblock[1]-=60;
         }
         rtblock[0]+=tblock[0];        /* Hours */
         return;
 }

 /*
 ** Take the time interval stored in tblock[] and add that to
 ** the array holding total accumulated seek time (rtblock[]).
 */
 accstime()
 {
         stblock[3]+=tblock[3];        /* Hundredths */
         if(stblock[3]>=100) {
                 stblock[2]+=1;
                 stblock[3]-=100;
         }
         stblock[2]+=tblock[2]; /* Seconds */
         if(stblock[2]>=60) {
                 stblock[1]+=1;
                 stblock[2]-=60;
         }
         stblock[1]+=tblock[1]; /* Minutes */
         if(stblock[1]>=60) {
                 stblock[0]+=1;
                 stblock[1]-=60;
         }
         stblock[0]+=tblock[0];        /* Hours */
         return;
 }

 /*
 ** accwbytes(n)
 ** Add n to total accumulated bytes written array.
 */
 accwbytes(n)
 int n;
 {
         while(n>10000) {
                 twbytes[0]+=1;
                 n-=10000;
         }
         twbytes[1]+=n;
         if(twbytes[1]>=10000) {
                 twbytes[0]+=1;
                 twbytes[1]-=10000;
         }
         return;
 }

 /*
 ** accrbytes(n)
 ** Add n to total accumulated bytes read array.
 */
 accrbytes(n)
 int n;
 {
         while(n>10000) {
                 trbytes[0]+=1;
                 n-=10000;
         }
         trbytes[1]+=n;
         if(trbytes[1]>=10000) {
                 trbytes[0]+=1;
                 trbytes[1]-=10000;
         }
         return;
 }

 /*
 ** gfname(n)
 ** Get the nth file's filename (returned as pointer).
 ** Note that n is 0-based.
 */
 gfname(n)
 int n;
 {
         switch(n) {
           case 0: return("FILE01.DAT");
           case 1: return("FILE02.DAT");
           case 2: return("FILE03.DAT");
           case 3: return("FILE04.DAT");
           case 4: return("FILE05.DAT");
           case 5: return("FILE06.DAT");
           case 6: return("FILE07.DAT");
           case 7: return("FILE08.DAT");
           case 8: return("FILE09.DAT");
           case 9: return("FILE10.DAT");
         }
 }

 /*
 ** randwc(x)
 ** Get a random number (positive) with ceiling x.
 */
 randwc(x)
 int x;
 {

         if(x==0) return(0);
         seed=rand(seed);        /* Get a random number */
         return(abs(seed)%x);
 }

 /*
 ** writebig(block)
 ** Write a big number.  number=10000*block[0]+block[1]
 */
 writebig(block) int block[];
 {
         printf("%d",block[0]);
         if(block[1]>999) printf("%u",block[1]);
         else {
          printf("0");
          if(block[1]>99) printf("%u",block[1]);
          else {
           printf("0");
           if(block[1]>9) printf("%u",block[1]);
           else {
            printf("0%u",block[1]);
           }
          }
         }
   return;
 }


 SCFM87.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCFM87.C

 /*
 ** BYTE Small C Floating Point Coprocessor Library
 ** BYTE Small C based on Small C by J.E. Hendrix
 ** 8087 version for 8088/8086
 ** Version 1, Feb. 17, 1988
 **
 ** Conventions:
 ** All variables are manipulated OUTSIDE the coprocessor in
 ** 8-byte form.
 */

 int        fsword;                /* Storage for status word */
 int        fsword1;        /* Extra storage for same */
 /*
 ** Initialize coprocessor
 ** Call this at the beginning and end of the program
 */
 finit() {
 #asm
         FINIT
 #endasm
 }

 /*
 ** fint2float(ptr)
 ** Converts integer pointed to by (ptr) into 8-byte floating point
 ** form and stores it back into (ptr);
 */
 fint2float(ptr) int ptr[]; {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Get pointer to 8-byte block
         FILD        QWORD PTR [SI]        ;Load the block in
         FSTP        QWORD PTR [SI]        ;Put it back out
 #endasm
 }

 /*
 ** ffloat2int(ptr)
 ** Converts 8-byte floating point number at ptr back to an integer.
 */
 ffloat2int(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Get pointer to 8-byte block
         FLD        QWORD PTR [SI]        ;Load it in
         FISTP        QWORD PTR [SI]        ;Save it back
 #endasm
 }

 /*
 ** f2add(fac1,fac2,dest)
 ** Add fac1 to fac2, store the result in dest
 */
 f2add(fac1,fac2,dest) int fac1[],fac2[],dest[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,6[BP]        ;Get first factor
         FLD        QWORD PTR [SI]        ;Push it
         MOV        SI,4[BP]        ;Get second factor
         FADD        QWORD PTR [SI]        ;Add it
         MOV        SI,2[BP]        ;Get destination
         FSTP        QWORD PTR [SI]        ;Store
 #endasm
 }

 /*
 ** f2sub(fac1,fac2,dest)
 ** Subtract fac2 from fac1, store result in dest
 */
 f2sub(fac1,fac2,dest) int fac1[],fac2[],dest[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,6[BP]        ;Get fac1
         FLD        QWORD PTR [SI]        ;Push it
         MOV        SI,4[BP]        ;Get fac2
         FSUB        QWORD PTR [SI]        ;Subtract
         MOV        SI,2[BP]        ;Destination
         FSTP        QWORD PTR [SI]        ;Store
 #endasm
 }

 /*
 ** f2mult(fac1,fac2,dest)
 ** Multiply fac1 by fac2, result in dest
 */
 f2mult(fac1,fac2,dest) int fac1[],fac2[],dest[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,6[BP]        ;get fac1
         FLD        QWORD PTR [SI]        ;Push it
         MOV        SI,4[BP]        ;Get fac2
         FLD        QWORD PTR [SI]
         FMUL
         MOV        SI,2[BP]        ;Destination pointer
         FSTP        QWORD PTR [SI]        ;Store
 #endasm
 }

 /*
 ** f2div(fac1,fac2,dest)
 ** Divide fac1 by fac2, result in dest
 */
 f2div(fac1,fac2,dest) int fac1[],fac2[],dest[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,6[BP]        ;Get fac1
         FLD        QWORD PTR [SI]        ;Push it
         MOV        SI,4[BP]        ;Get fac2
         FDIV        QWORD PTR [SI]        ;Divide
         MOV        SI,2[BP]        ;Destination
         FSTP        QWORD PTR [SI]        ;Store it
 #endasm
 }

 /*
 ** fload(ptr)
 ** Load floating point number given by ptr
 */
 fload(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]
         FLD        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fstore(ptr)
 ** Store floating point number given by ptr - pops floating point stack
 */
 fstore(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]
         FSTP        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fadd(ptr)
 ** Add contents of ptr to top of floating point stack -- result on stack
 */
 fadd(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]
         FADD        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fsub(ptr)
 ** Subtract contents of ptr from top of stack -- result on top of stack
 */
 fsub(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]
         FSUB        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fmult(ptr)
 ** Multiply contents of ptr by top of stack -- result on top of stack
 */
 fmult(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]
         FMUL        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fdiv(ptr)
 ** Divide top of stack by contents of ptr -- result on top of stack
 */
 fdiv(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]
         FDIV        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fabs()
 ** Set top of stack to its absolute value
 */
 fabs()
 {
 #asm
         FABS
 #endasm
 }

 /*
 ** fsqrt()
 ** Take square root of top of floating point stack
 */
 fsqrt()
 {
 #asm
                 FSQRT
 #endasm
 }

 /*
 ** fcompz(ptr)
 ** Compares number at ptr with zero
 ** Returns: -1 if less, 0 if equal, 1 if greater
 */
 fcompz(ptr) int ptr[];
 {
 #asm
         FLDZ                        ;get zero on stack
         MOV        BP,SP
         MOV        SI,2[BP]
         FLD        QWORD PTR [SI]        ;Get the number
         FCOMPP                        ;Compare
         FSTSW        _fsword                ;Store the control word
         FWAIT                        ;Make sure the coprocessor is done
         MOV        AX,_fsword        ;Get the control word
         XOR        BX,BX
         SAHF                        ;Move into flags
         JZ        FCZX
         JNC        FCZ1
         DEC        BX
         JMP        FCZX
 FCZ1:        INC        BX
 FCZX:

 #endasm
 }
 /*
 ** fcomp(ptr1,ptr2)
 ** ptr1 and ptr2 point to floating-point numbers.
 ** This function returns:
 ** 1 if ptr1>ptr2; 0 if ptr1=ptr2; -1 if ptr1<ptr2
 */
 fcomp(ptr1,ptr2) int ptr1[],ptr2[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Get ptr2
         FLD        QWORD PTR [SI]        ;Load it in

         MOV        SI,4[BP]
         FLD        QWORD PTR [SI]        ;Get ptr1
         FCOMPP                        ;Compare
         FSTSW        _fsword                ;Store the control word
         FWAIT                        ;Make sure the coprocessor is done
         MOV        AX,_fsword        ;Get the control word
         XOR        BX,BX
         SAHF                        ;Move into flags
         JZ        FCMX
         JNC        FCM1
         DEC        BX
         JMP        FCMX
 FCM1:        INC        BX
 FCMX:
 #endasm
 }

 /*
 ** ffact(n) int n;
 ** Calculate n!.  n! is left on top of stack.
 */
 ffact(n) int n;
 {
 #asm
         MOV        BP,SP                ;get value
         MOV        AX,2[BP]
         FLD1
         FLD1
 FFCT0:        DEC        AX                ;done?
         JZ        FFCT1
         FLD1
         FADD        ST,ST(2)        ;bump
         FST        ST(2)
         FMUL                        ;Multiply
         JMP        SHORT FFCT0
 FFCT1:        FFREE        ST(1)                ;Clear n
 #endasm
 }

 /*
 ** fsin(ptr,ptr1)
 ** Calculate sine of quantity at ptr...returns sine in ptr1
 */
 fsin(ptr,ptr1) int ptr[],ptr1[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,4[BP]        ;Get pointer
         FLD        QWORD PTR [SI]        ;Get argument
 ;See if arg is 0 -- if so, we can skip a lot
         FTST
         FSTSW        _fsword
         FWAIT
         MOV        AX,_fsword
         SAHF
         JZ        FSIN1
         FFREE        ST(0)
         FLD1                        ;Get a 1
         FLD        ST(0)                ;Dup it
         FADD                        ;2 now at stack top
         FLD        ST(0)                ;Dup it
         FLD        QWORD PTR [SI]        ;Get argument
         FDIVR                        ;arg/2
         FPTAN                        ;Get partial tangent
         FDIVR                        ;Calc y/x
         FST        ST(2)
         FMUL                        ;2*(y/x) on top
         FXCH
         FMUL        ST(0),ST        ;(y/x)^2
         FLD1                        ;Get 1 again
         FADD                        ;(1+(y/x)^2)
         FDIV
 FSIN1:        MOV        SI,2[BP]
         FSTP        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fxtoy(x,y,z)
 ** Given x and y are pointers to floating point numbers,
 ** calculates x^y and returns the result in z.
 ** Not that this routine is only good for returning roots
 ** of things.
 */
 fxtoy(x,y,z) int x[],y[],z[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,4[BP]        ;Get y
         FLD        QWORD PTR [SI]        ;y in st(0)
         MOV        SI,6[BP]
         FLD        QWORD PTR [SI]        ;x on top
         FYL2X                        ;y*log2(x)
         CALL        _ftwo2x                ;2^(y*log2(x))
         MOV        SI,2[BP]        ;Get z address
         FSTP        QWORD PTR [SI]        ;Store
 #endasm
 }

 /*
 ** fex(ptr,ptr1)
 ** Raises e^x, where x is in ptr.  Places result in ptr1.
 **/
 fex(ptr,ptr1) int ptr[],ptr1[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,4[BP]
         FLD        QWORD PTR [SI]        ;x in st(0)
         FLDL2E                        ;log2(e)
         FMUL                        ;x*log2(e)
         CALL        _ftwo2x                ;2^(x*log2(e))
         MOV        SI,2[BP]        ;Get destination
         FSTP        QWORD PTR [SI]        ;Store
 #endasm
 }

 /*
 ** fround(ptr)
 ** Assume ptr points to quadword floating point.
 ** Rounds contents of ptr to integer and stores result in ptr
 */
 fround(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Pointer to si
         FLD        QWORD PTR [SI]
         FRNDINT
         FSTP        QWORD PTR [SI]
 #endasm
 }

 /*
 ** fstoreb(ptr)
 ** Store top of stack as BCD into ptr
 */
 fstoreb(ptr) int ptr[];
 {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Get pointer
         FBSTP        [SI]                ;Store it
         FWAIT
 #endasm
 }

 /*
 ** ftwo2x()
 ** Raises two to the power of x.
 ** x is on top of the stack.
 ** Leaves result on top of stack.
 */
 ftwo2x()
 {
 #asm
 ;First save existing control word
         FNSTCW        _fsword
         MOV        AX,_fsword
         AND        AX,0F3FFH        ;Round toward nearest even
         MOV        _fsword1,AX
         FLDCW        _fsword1        ;New control word
 ;Now break exponent into integer and fractional part
         FLD        ST(0)                ;Dup x
         FRNDINT                        ;Int part in ST(0)
         FSUB        ST(1),ST        ;Fractional part in ST(1)
         FXCH                        ;Switch - int in st(1),
                                 ;frac. in st(0)
         FTST                        ;frac. < 0 ?
         FSTSW        _fsword1
         FWAIT
         F2XM1                        ;2^(f)-1
 ;See if fractional part is negative
         MOV        AX,_fsword1
         SAHF
         JNC        T2X1
 ;Fractional part is neg.
         FCHS                        ;Make it positive
         FLD        ST(0)                ;dup
         FLD1                        ;1 on top
         FADD                        ;2^(-f) on top
         FDIV                        ;(2^(-f)-1)/2^(-f)
         FCHS                        ;2^f-1
 T2X1:        FLD1
         FADD                        ;2^f
         FSCALE                        ;2^x
         FFREE        ST(1)                ;Clear out i
 ;Restore control word
         FLDCW        _fsword
 #endasm
 }

 /*
 ** fconst(val) int val;
 ** Load top of FPU stack with constant based on val:
 ** val     constant
 ** 0        0.0
 ** 1        1.0
 ** 2        pi
 ** 3        log2(e)
 ** 4        log2(10)
 ** 5        log10(2)
 ** 6        loge(2)
 */
 fconst(val) int val;
 {
         switch(val) {
          default:
          case 0:
 #asm
           FLDZ
 #endasm
            break;

          case 1:
 #asm
           FLD1
 #endasm
            break;

          case 2:
 #asm
           FLDPI
 #endasm
            break;

          case 3:
 #asm
           FLDL2E
 #endasm
            break;

          case 4:
 #asm
           FLDL2T
 #endasm
            break;

          case 5:
 #asm
           FLDLG2
 #endasm
            break;

          case 6:
 #asm
           FLDLN2
 #endasm
           break;
         }
         return;
 }

 /*
 ** fltprint(n,num)
 ** Entry:
 **  num points to an 8-byte floating-point number
 **  n is the number of characters to print
 ** This function prints the floating-point number in scientific
 ** notation: -x.xxxxxx E-xx
 */
 fltprint(n,num) int n,num[];
 {
         int ten[4];                /* Holder for ten */
         char tmp[10];                /* Holder for one */
         int msign;                /* Mantissa sign */
         int powcnt;                /* Counter for power */
         int i;                        /* Loop count */
         int j;                        /* Counter */
         int hld[4];                /* Holding val */

 /*
 ** Copy the number we want to print out into a holding area,
 ** since we'll be altering it to print it out.
 */

         for(i=0;i<4;++i)
                 hld[i]=num[i];

 /* First see what sign the number is.  Save in msign.
 ** If less than zero...change the sign of the number.
 ** If equal to zero, print it out and we can go home.
 */
         msign=fcompz(hld);
         if(msign==0) {
           printf("0.0 E0");
           return;
         }
         if(msign<0) {
                 fload(hld);
                 fabs();
                 fstore(hld);
         }

 /*
 ** Now see if the number is less than ten.  If so, multiply the number
 ** by ten repeatedly until it's not.  For each multiply, decrement a
 ** counter so we can keep track of the exponent.
 */
         powcnt=0;
         ten[0]=10;
         ten[1]=ten[2]=ten[3]=0;
         fint2float(ten);        /* Get floating-point 10 */
         while(fcomp(hld,ten)==-1) {
                 --powcnt;
                 f2mult(hld,ten,hld);
         }

 /*
 ** Do the reverse of the above.  As long as the number is greater than or
 ** equal to 10, divide it by 10.  Increment the exponent counter for
 ** each multiply.
 */

         while(fcomp(hld,ten)!=-1) {
                 ++powcnt;
                 f2div(hld,ten,hld);
         }

 /*
 ** We now know the number is in the range 10 > n >= 1, and its
 ** exponent is in powcnt.  Print the number out as follows:
 ** Print out a minus sign if the number was less than 0.
 ** Multiply by 10 as needed to get the number of digits the
 ** caller wants printed to the left of the decimal point.
 ** Store the result in packed BCD format.
 ** Extract the BCD digits and print them out.
 */

         if(msign<0) printf("-");
         fload(hld);
         for(i=0;i<n-1;++i)
                 fmult(ten);
         fstoreb(tmp);
         for(i=0;i<n;++i) {
                 j=tmp[(n-i-1)/2];
                 if(((n-i)&1)==0) j=j>>4;
                 j=j&15;
                 printf("%d",j);
                 if(i==0) printf(".");
         }

 /* Now print out exponent */

         printf("E%d",powcnt);
         return;
 }



 SCHDSEEK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCHDSEEK.C

 /*
 ** BYTE Hard disk seek benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** March 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Operation:
 **  1. Determine geometry of disk drive (how many cylinders)
 **  2. Perform COUNT iterations of the following (reporting
 **     times for each):
 **     (a) Adjacent track seeks for innermost cylinder
 **     (b) Adjacent track seeks for outermost cylinder
 **     (c) Half-platter seeks
 **     (d) Full-platter seeks
 **  3. Exit
 **
 */

 COUNT 100        /* Repititions */

 int tblock[4];                /* Timer block */
 int dblock[4];                /* Disk block */
 int sourc;                /* Source cylinder */
 int destc;                /* Destination cylinder */
 int accum;                /* Time accumulator */
 int i;                        /* index */
 char dbuff[516];        /* Buffer needed for disk read */

 extern gtime();                /* Get time */
 extern calctim();        /* Calc. elapsed time */

 main()
 {

         printf("BYTE Hard Disk Seek Benchmark\n");
         printf("All times given are in 1/100ths of a second\n");
 /* Get the hard disk parameters */
         dblock[0]=128;        /* First hard disk */
         gdinfo(dblock);

         printf("Max cylinder %d\n\n",dblock[2]);

         printf("All tests done for %d iterations\n\n",COUNT*2);

 /* Do outer track-track seek */
         sourc = 0;
         destc = 1;
         doseek();
         printf("***Outer track-track time***\n");
         printf("Total time:%d\n\n",accum);

 /* Do inner track-track seek */
         sourc = dblock[2]-2;
         destc = dblock[2]-1;
         doseek();
         printf("***Inner track-track time***\n");
         printf("Total time:%d\n\n",accum);

 /* Do half-platter seek */
         sourc = 0;
         destc = dblock[2]/2;
         doseek();
         printf("***Half-platter time***\n");
         printf("Total time:%d\n\n",accum);

 /* Do full-platter seek */
         sourc = 0;
         destc = dblock[2] - 1;
         doseek();
         printf("***Full-platter time***\n");
         printf("Total time:%d\n\n",accum);

 /* Exit */
         exit(0);
 }

 /*
 ** doseek()
 ** Uses global variables:
 ** sourc = starting cylinder
 ** destc = destination cylinder
 ** accum = accumulated time
 */
 doseek()
 {
         accum=0;
         hdseek(dbuff,sourc);        /* Init. track to source */
         for(i=0;i<COUNT;++i)
         {
                 gtime(tblock);
                 hdseek(dbuff,destc);
                 hdseek(dbuff,sourc);
                 calctim(tblock);        /* Get elapsed time */
                 accum+=tblock[3]+100*(tblock[2]+60*tblock[1]);
         }
         return;
 }

 /*
 ** hdseek(buff,cyl) char *buff; int cyl;
 ** Hard disk seek to cylinder cyl
 ** Buff is a pointer to a buffer to read the sector in.
 ** NOTE: We assume ES=DS
 **
 */
 hdseek(buff,cyl) char *buff; int cyl;
 {
 #asm
         MOV        BP,SP
         MOV        BX,4[BP]                ;Pointer to buffer
         MOV        CX,2[BP]                ;Get cylinder
         XCHG        CH,CL                        ;Swap parts
         ROR        CL,1                        ;Set up low part
         ROR        CL,1
         INC        CL                        ;Set to sector 1
         MOV        DX,80H                        ;Set hard disk no.
         MOV        AH,02H                        ;Function
         MOV        AL,1                        ;Read 1 sector
         INT        13H                        ;do the int
         XOR        CX,CX                        ;Just in case
 #endasm
 }
 /*
 ** 8088/8086 version
 ** gdinfo(dblock) int dblock[]; {
 ** Get disk information.
 ** dblock[] is assumed to be a 4-element array.  Upon entry,
 ** dblock[0] should have the disk number in it
 ** (0=A, 1=B...80H=First hard disk...etc.)
 ** Upon return, dblock holds:
 ** dblock[0] = # of hard disks on first controller
 ** dblock[1] = Number of heads
 ** dblock[2] = Number of cylinders
 ** dblcok[3] = Sectors per track
 */
 gdinfo(dblock) int dblock[]; {
 #asm
         MOV        BP,SP
         MOV        SI,2[BP]        ;Pointer to dblock
         MOV        DL,[SI]                ;Get drive number
         MOV        AH,08H                ;Get params
         INT        13H
         XOR        AX,AX                ;Clear high byte
         MOV        AL,DL
         MOV        [SI],AX                ;# Hard disks on 1st controller
         MOV        AL,DH
         INC        AL                ;Starts at zero
         MOV        2[SI],AX        ;Number of heads
         MOV        AL,CL
         AND        AL,3FH                ;Sectors/track
         MOV        6[SI],AX
         MOV        AL,CL
         SHL        AX,1
         SHL        AX,1
         MOV        AL,CH
         INC        AX                ;Starts at zero
         MOV        4[SI],AX        ;Max cylinders
         XOR        CX,CX                ;clear CX
 #endasm
 }




 SCN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\SCN.C

 /* SDB - token scanning routines */

 #include "stdio.h"
 #include "sdbio.h"
 #include "ctype.h"

 int dbv_token;                          /* current token */
 int dbv_tvalue;                         /* integer token value */
 char dbv_tstring[STRINGMAX+1];          /* string token value */
 struct ifile *dbv_ifp;                  /* indirect file context */
 struct macro *dbv_macros;               /* macro definitions */
 int dbv_fold;                           /* case fold alpha comparisons */

 static char *iprompt,*cprompt;          /* input prompts */
 static char cmdline[LINEMAX+2],*lptr;   /* current line and pointer */
 static int atbol;                       /* flag indicating at bol */
 static int savech;                      /* lookahead character */
 static int savetkn;                     /* lookahead token */
 static char *keywords[] = {             /* keyword table */
     "ascending",
     "by",
     "char",
     "compress",
     "create",
     "define",
     "delete",
     "descending",
     "exit",
     "export",
     "extract",
     "from",
     "help",
     "insert",
     "import",
     "into",
     "num",
     "print",
     "select",
     "set",
     "show",
     "sort",
     "update",
     "using",
     "where",
     NULL
 };
 static int keytokens[] = {              /* token values for each keyword */
     ASCENDING,
     BY,
     CHAR,
     COMPRESS,
     CREATE,
     DEFINE,
     DELETE,
     DESCENDING,
     EXIT,
     EXPORT,
     EXTRACT,
     FROM,
     HELP,
     INSERT,
     IMPORT,
     INTO,
     NUM,
     PRINT,
     SELECT,
     SET,
     SHOW,
     SORT,
     UPDATE,
     USING,
     WHERE,
     NULL
 };

 /* db_sinit - initialize the scanner */
 db_sinit()
 {
     /* at beginning of line */
     atbol = TRUE;

     /* make the command line null */
     lptr = NULL;

     /* no lookahead yet */
     savech = EOS;
     savetkn = NULL;

     /* no indirect command files */
     dbv_ifp = NULL;

     /* no macros defined */
     dbv_macros = NULL;

     /* fold alpha comparisons */
     dbv_fold = TRUE;
 }

 /* db_prompt(ip,cp) - initialize prompt strings */
 db_prompt(ip,cp)
   char *ip,*cp;
 {
     /* save initial and continuation prompt strings */
     iprompt = ip;
     cprompt = cp;
 }

 /* db_scan(fmt,args) - initiate line scan command parsing */
 db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
 {
     /* convert the command line and arguments */
     sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);

     /* start at the beginning of the command line */
     lptr = cmdline;
     iprompt = NULL;
     dbv_ifp = NULL;

     /* no lookahead yet */
     savech = EOS;
     savetkn = NULL;

     /* fold alpha comparisons */
     dbv_fold = TRUE;
 }

 /* db_flush - flush the current input line */
 int db_flush()
 {
     while (savech != '\n')
         if (savech > ' ')
             return (db_ferror(SYNTAX));
         else
             savech = getchx();

     savech = EOS;
     atbol = TRUE;
     return (TRUE);
 }

 /* db_gline - get a line from the current input */
 char *db_gline(buf)
   char *buf;
 {
     int ch,i;

     for (i = 0; (ch = getch()) != '\n' && ch != -1; )
         if (i < LINEMAX)
             buf[i++] = ch;
         else {
             printf("*** line too long ***\nRetype> ");
             fflush(stdout) ;
             i = 0;
         }
     buf[i] = EOS;

     return (buf);
 }

 /* db_ifile - setup an indirect command file */
 int db_ifile(fname)
   char *fname;
 {
     struct ifile *new_ifp;

     if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
         return (db_ferror(INSMEM));
     else if ((new_ifp->if_fp = fopen(fname,"r")) == NULL) {
         free(new_ifp);
         return (db_ferror(INDFNF));
     }
     new_ifp->if_mtext = NULL;
     new_ifp->if_savech = savech;
     new_ifp->if_lptr = lptr;
     new_ifp->if_next = dbv_ifp;
     dbv_ifp = new_ifp;

     /* return successfully */
     return (TRUE);
 }

 /* db_kill - kill indirect command file input */
 db_kill()
 {
     struct ifile *old_ifp;

     while ((old_ifp = dbv_ifp) != NULL) {
         dbv_ifp = old_ifp->if_next;
         if (old_ifp->if_fp != NULL)
             fclose(old_ifp->if_fp);
         savech = old_ifp->if_savech;
         lptr = old_ifp->if_lptr;
         free(old_ifp);
     }

     while (savech != '\n')
         savech = getchx();

     savech = EOS;
     savetkn = NULL;
     atbol = TRUE;
 }

 /* db_token - return the current input token */
 int db_token()
 {
     struct macro *mptr;
     struct ifile *new_ifp;

     /* find a token that's not a macro call */
     while (db_xtoken() == ID) {

         /* check for a macro call */
         for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
             if (db_scmp(dbv_tstring,mptr->mc_name) == 0) {
                 if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
                     printf("*** error expanding macro: %s ***\n",dbv_tstring)
                 else {
                     new_ifp->if_fp = NULL;
                     new_ifp->if_mtext = mptr->mc_mtext->mt_next;
                     new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text;
                     new_ifp->if_savech = savech; savech = EOS;
                     new_ifp->if_next = dbv_ifp;
                     dbv_ifp = new_ifp;
                 }
                 savetkn = NULL;
                 break;
             }

         if (mptr == NULL)
             break;
     }

     return (dbv_token);
 }

 /* db_xtoken - return the current input token */
 int db_xtoken()
 {
     int ch;

     /* check for a saved token */
     if ((dbv_token = savetkn) != NULL)
         return (dbv_token);

     /* get the next non-blank character */
     ch = nextch();

     /* check type of character */
     if (isalpha(ch))                    /* identifier or keyword */
         get_id();
     else if (isdigit(ch))               /* number */
         get_number();
     else if (ch == '"')                 /* string */
         get_string();
     else if (get_rel())                 /* relational operator */
         ;
     else                                /* single character token */
         dbv_token = getch();

     /* save the lookahead token */
     savetkn = dbv_token;

     /* return the token */
     return (dbv_token);
 }

 /* db_ntoken - get next token (after skipping the current one) */
 int db_ntoken()
 {
     /* get the current token */
     db_token();

     /* make sure another is read on next call */
     savetkn = NULL;

     /* return the current token */
     return (dbv_token);
 }

 /* db_xntoken - get next token (after skipping the current one) */
 int db_xntoken()
 {
     /* get the current token */
     db_xtoken();

     /* make sure another is read on next call */
     savetkn = NULL;

     /* return the current token */
     return (dbv_token);
 }

 /* db_scmp - compare two strings */
 int db_scmp(str1,str2)
   char *str1,*str2;
 {
     if (dbv_fold)
         return (scmp(str1,str2));
     else
         return (strcmp(str1,str2));
 }

 /* db_sncmp - compare two strings with a maximum length */
 int db_sncmp(str1,str2,len)
   char *str1,*str2; int len;
 {
     if (dbv_fold)
         return (sncmp(str1,str2,len));
     else
         return (strncmp(str1,str2,len));
 }

 /* scmp - compare two strings with alpha case folding */
 static int scmp(str1,str2)
   char *str1,*str2;
 {
     int ch1,ch2;

     /* compare each character */
     while (*str1 && *str2) {

         /* fold the character from the first string */
         if (isupper(*str1))
             ch1 = tolower(*str1++);
         else
             ch1 = *str1++;

         /* fold the character from the second string */
         if (isupper(*str2))
             ch2 = tolower(*str2++);
         else
             ch2 = *str2++;

         /* compare the characters */
         if (ch1 != ch2)
             if (ch1 < ch2)
                 return (-1);
             else
                 return (1);
     }

     /* check for strings of different lengths */
     if (*str1 == *str2)
         return (0);
     else if (*str1 == 0)
         return (-1);
     else
         return (1);
 }

 /* sncmp - compare two strings with alpha case folding and a maximum length *
 static int sncmp(str1,str2,len)
   char *str1,*str2; int len;
 {
     int ch1,ch2;

     /* compare each character */
     while (*str1 && *str2 && len > 0) {

         /* fold the character from the first string */
         if (isupper(*str1))
             ch1 = tolower(*str1++);
         else
             ch1 = *str1++;

         /* fold the character from the second string */
         if (isupper(*str2))
             ch2 = tolower(*str2++);
         else
             ch2 = *str2++;

         /* compare the characters */
         if (ch1 != ch2)
             if (ch1 < ch2)
                 return (-1);
             else
                 return (1);

         /* decrement the string length */
         len--;
     }

     /* check for strings of different lengths */
     if (len == 0 || *str1 == *str2)
         return (0);
     else if (*str1 == 0)
         return (-1);
     else
         return (1);
 }

 /* get_id - get a keyword or a user identifier */
 static get_id()
 {
     int ch,nchars,i;

     /* input letters and digits */
     ch = nextch();
     nchars = 0;
     while (isalpha(ch) || isdigit(ch)) {
         if (nchars < KEYWORDMAX)
             dbv_tstring[nchars++] = ch;
         getch(); ch = thisch();
     }

     /* terminate the keyword */
     dbv_tstring[nchars] = EOS;

     /* assume its an identifier */
     dbv_token = ID;

     /* check for keywords */
     for (i = 0; keywords[i] != NULL; i++)
         if (db_scmp(dbv_tstring,keywords[i]) == 0)
             dbv_token = keytokens[i];
 }

 /* get_number - get a number */
 static get_number()
 {
     int ch,ndigits,nodot;

     /* read digits and at most one decimal point */
     ch = nextch();
     ndigits = 0; nodot = TRUE;
     while (isdigit(ch) || (nodot && ch == '.')) {
         if (ch == '.')
             nodot = FALSE;
         if (ndigits < NUMBERMAX)
             dbv_tstring[ndigits++] = ch;
         getch(); ch = thisch();
     }

     /* terminate the number */
     dbv_tstring[ndigits] = EOS;

     /* get the value of the number */
     sscanf(dbv_tstring,"%d",&dbv_tvalue);

     /* token is a number */
     dbv_token = NUMBER;
 }

 /* get_string - get a string */
 static get_string()
 {
     int ch,nchars;

     /* skip the opening quote */
     getch();

     /* read characters until a closing quote is found */
     ch = thisch();
     nchars = 0;
     while (ch && ch != '"') {
         if (nchars < STRINGMAX)
             dbv_tstring[nchars++] = ch;
         getch(); ch = thisch();
     }

     /* terminate the string */
     dbv_tstring[nchars] = EOS;

     /* skip the closing quote */
     getch();

     /* token is a string */
     dbv_token = STRING;
 }

 /* get_rel - get a relational operator */
 static int get_rel()
 {
     int ch;

     switch (ch = nextch()) {
     case '=':
             getch();
             dbv_token = EQL;
             return (TRUE);;
     case '<':
             getch(); ch = nextch();
             if (ch == '>') {
                 getch();
                 dbv_token = NEQ;
             }
             else if (ch == '=') {
                 getch();
                 dbv_token = LEQ;
             }
             else
                 dbv_token = LSS;
             return (TRUE);;
     case '>':
             getch(); ch = nextch();
             if (ch == '=') {
                 getch();
                 dbv_token = GEQ;
             }
             else
                 dbv_token = GTR;
             return (TRUE);;
     default:
             return (FALSE);
     }
 }

 /* getch - get the next character */
 static int getch()
 {
     char fname[STRINGMAX+1];
     int ch,i;

     /* return the lookahead character if there is one */
     if (savech != EOS) {
         ch = savech;
         savech = EOS;
         return (ch);
     }

     /* get a character */
     ch = getchx();

     /* skip spaces at the beginning of a command */
     if (atbol && iprompt != NULL)
         while (ch <= ' ')
             ch = getchx();

     /* use continuation prompt next time */
     iprompt = NULL;

     /* check for indirect command file */
     while (ch == '@') {
         for (i = 0; (savech = getchx()) > ' '; )
             if (i < STRINGMAX)
                 fname[i++] = savech;
         fname[i] = 0;
         if (db_ifile(fname) != TRUE)
             printf("*** error opening command file: %s ***\n",fname);
         ch = getchx();
     }

     /* return the character */
     return (ch);
 }

 /* getchx - get the next character */
 static int getchx()
 {
     struct ifile *old_ifp;
     int ch;

     /* check for input from buffer */
     if (lptr != NULL) {
         while (*lptr == EOS)
             if (dbv_ifp != NULL)
                 if (dbv_ifp->if_mtext == NULL) {
                     old_ifp = dbv_ifp;
                     ch = dbv_ifp->if_savech; savech = EOS;
                     lptr = dbv_ifp->if_lptr;
                     dbv_ifp = dbv_ifp->if_next;
                     free(old_ifp);
                     if (ch != EOS)
                         return (ch);
                     if (lptr == NULL)
                         break;
                 }
                 else {
                     lptr = dbv_ifp->if_mtext->mt_text;
                     dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next;
                 }
             else
                 return (EOS);

         if (lptr != NULL)
             return (*lptr++);
     }

     /* print prompt if necessary */
     if (atbol && dbv_ifp == NULL)  {  /*dns*/
         if (iprompt != NULL)
             printf("%s",iprompt);
         else if (cprompt != NULL)
             printf("%s",cprompt);
 #ifdef Lattice
         fflush(stdout); /*dns*/
 #endif
         } /*dns*/

     if (dbv_ifp == NULL)
         if ((ch = getcx(stdin)) == '\n')
             atbol = TRUE;
         else
             atbol = FALSE;
     else {
         if ((ch = getcx(dbv_ifp->if_fp)) == -1) {
             old_ifp = dbv_ifp;
             ch = dbv_ifp->if_savech; savech = EOS;
             lptr = dbv_ifp->if_lptr;
             dbv_ifp = dbv_ifp->if_next;
             fclose(old_ifp->if_fp);
             free(old_ifp);
         }
     }

     /* return the character */
     return (ch);
 }

 /* thisch - get the current character */
 static int thisch()
 {
     /* get a lookahead character */
     if (savech == EOS)
         savech = getch();

     /* return lookahead character */
     return (savech);
 }

 /* nextch - get the next non-blank character */
 static int nextch()
 {
     int ch;

     /* skip blank characters */
     while ((ch = thisch()) <= ' ' && ch != EOS)
         getch();

     /* return the first non-blank */
     return (ch);
 }



 SCOPE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SCOPE.C

                                           /* Chapter 5 - Program 4 */
 "stdio.h"      /* Prototypes for Input/Output             */
 void head1(void);       /* Prototype for head1                     */
 void head2(void);       /* Prototype for head2                     */
 void head3(void);       /* Prototype for head3                     */

 int count;              /* This is a global variable               */

 main()
 {
 register int index; /* This variable is available only in main */

    head1();
    head2();
    head3();
                       /* main "for" loop of this program */
    for (index = 8;index > 0;index--) {
       int stuff;  /* This variable is only available in these braces*/
       for (stuff = 0;stuff <= 6;stuff++)
          printf("%d ",stuff);
       printf(" index is now %d\n",index);
     }
 }

 int counter;      /* This is available from this point on */
 void head1(void)
 {
 int index;        /* This variable is available only in head1 */

    index = 23;
    printf("The header1 value is %d\n",index);
 }

 void head2(void)
 {
 int count;  /* This variable is available only in head2 */
             /* and it displaces the global of the same name */

    count = 53;
    printf("The header2 value is %d\n",count);
    counter = 77;
 }

 void head3(void)
 {
    printf("The header3 value is %d\n",counter);
 }


 SCRAND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCRAND.C

 /*
 ** 8088/8086 version
 ** rand(seed) - Generate a random number using a linear
 ** congruence generator.  Seed is the initial seed for
 ** the generator.  On subsequent calls to rand() seed should
 ** be set to the value of the previeous random number. i.e.:
 ** newrand = rand(oldrand);
 */
 rand(seed) int seed; {
 #asm
         MOV        BP,SP
         MOV        AX,2[BP]        ;Get seed
         MOV        BX,58653
         MUL        BX
         ADD        AX,13849
         MOV        BX,AX
         XOR        CX,CX                ;For Small-C
 #endasm
 }



 SCREEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\SCREEN.C

 /*
  * Routines to manipulate the screen representations.
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 /*
  * The following variable is set (in filetonext) to the number of physical
  * lines taken by the line the cursor is on. We use this to avoid extra
  * calls to plines(). The optimized routines lfiletonext() and lnexttoscreen(
  * make sure that the size of the cursor line hasn't changed. If so, lines
  * below the cursor will move up or down and we need to call the routines
  * filetonext() and nexttoscreen() to examine the entire screen.
  */
 static        int        Cline_size;        /* size (in rows) of the cursor l
 static        int        Cline_row;        /* starting row of the cursor line

 /*
  * filetonext()
  *
  * Based on the current value of Topchar, transfer a screenfull of
  * stuff from Filemem to Nextscreen, and update Botchar.
  */

 static void
 filetonext()
 {
         register int row, col;
         register char *screenp = Nextscreen;
         LPTR memp;
         LPTR save;                        /* save pos. in case line won't fit
         register char *endscreen;
         register char *nextrow;
         char extra[16];
         int nextra = 0;
         register int c;
         int n;
         int done;
         int srow;                /* starting row of the current line */

         save = memp = *Topchar;

         /* The number of rows shown is Rows-1. */
         /* The last line is the status/command line. */
         endscreen = &screenp[(Rows-1)*Columns];

         srow = done = row = col = 0;
         while ( screenp < endscreen && !done) {

                 /* Get the next character to put on the screen. */

                 /* The 'extra' array contains the extra stuff that is */
                 /* inserted to represent special characters (tabs, and */
                 /* other non-printable stuff.  The order in the 'extra' */
                 /* array is reversed. */

                 if ( nextra > 0 )
                         c = extra[--nextra];
                 else {
                         c = (unsigned)(0xff & gchar(&memp));
                         if (inc(&memp) == -1)
                                 done = 1;
                         /* when getting a character from the file, we */
                         /* may have to turn it into something else on */
                         /* the way to putting it into 'Nextscreen'. */
                         if ( c == TAB && !P(P_LS) ) {
                                 strcpy(extra,"        ");
                                 /* tab amount depends on current column */
                                 nextra = ((P(P_TS)-1) - col%P(P_TS));
                                 c = ' ';
                         }
                         else if ( c == NUL && P(P_LS) ) {
                                 extra[0] = NUL;
                                 nextra = 1;
                                 c = '$';
                         } else if ( (n = chars[c].ch_size) > 1 ) {
                                 char *p;
                                 nextra = 0;
                                 p = chars[c].ch_str;
                                 /* copy 'ch-str'ing into 'extra' in reverse *
                                 while ( n > 1 )
                                         extra[nextra++] = p[--n];
                                 c = p[0];
                         }
                 }

                 if ( c == NUL ) {
                         srow = ++row;
                         /*
                          * Save this position in case the next line won't
                          * fit on the screen completely.
                          */
                         save = memp;
                         /* get pointer to start of next row */
                         nextrow = &Nextscreen[row*Columns];
                         /* blank out the rest of this row */
                         while ( screenp != nextrow )
                                 *screenp++ = ' ';
                         col = 0;
                         continue;
                 }
                 if ( col >= Columns ) {
                         row++;
                         col = 0;
                 }
                 /* store the character in Nextscreen */
                 *screenp++ = c;
                 col++;
         }
         /*
          * If we didn't hit the end of the file, and we didn't finish
          * the last line we were working on, then the line didn't fit.
          */
         if (!done && c != NUL) {
                 /*
                  * Clear the rest of the screen and mark the unused lines.
                  */
                 screenp = &Nextscreen[srow * Columns];
                 while (screenp < endscreen)
                         *screenp++ = ' ';
                 for (; srow < (Rows-1) ;srow++)
                         Nextscreen[srow * Columns] = '@';
                 *Botchar = save;
                 return;
         }
         /* make sure the rest of the screen is blank */
         while ( screenp < endscreen )
                 *screenp++ = ' ';
         /* put '~'s on rows that aren't part of the file. */
         if ( col != 0 )
                 row++;
         while ( row < Rows ) {
                 Nextscreen[row*Columns] = '~';
                 row++;
         }
         if (done)        /* we hit the end of the file */
                 *Botchar = *Fileend;
         else
                 *Botchar = memp;
 }

 /*
  * nexttoscreen
  *
  * Transfer the contents of Nextscreen to the screen, using Realscreen
  * to avoid unnecessary output.
  */
 static void
 nexttoscreen()
 {
         register char *np = Nextscreen;
         register char *rp = Realscreen;
         register char *endscreen;
         register int row = 0, col = 0;
         int gorow = -1, gocol = -1;

         endscreen = &np[(Rows-1)*Columns];

         outstr(T_CI);                /* disable cursor */

         for ( ; np < endscreen ; np++,rp++ ) {
                 /* If desired screen (contents of Nextscreen) does not */
                 /* match what's really there, put it there. */
                 if ( *np != *rp ) {
                         /* if we are positioned at the right place, */
                         /* we don't have to use windgoto(). */
                         if (gocol != col || gorow != row) {
                                 /*
                                  * If we're just off by one, don't send
                                  * an entire esc. seq. (this happens a lot!)
                                  */
                                 if (gorow == row && gocol+1 == col) {
                                         outchar(*(np-1));
                                         gocol++;
                                 } else
                                         windgoto(gorow=row,gocol=col);
                         }
                         outchar(*rp = *np);
                         gocol++;
                 }
                 if ( ++col >= Columns ) {
                         col = 0;
                         row++;
                 }
         }
         outstr(T_CV);                /* enable cursor again */
 }

 /*
  * lfiletonext() - like filetonext() but only for cursor line
  *
  * Returns true if the size of the cursor line (in rows) hasn't changed.
  * This determines whether or not we need to call filetonext() to examine
  * the entire screen for changes.
  */
 static bool_t
 lfiletonext()
 {
         register int row, col;
         register char *screenp;
         LPTR memp;
         register char *nextrow;
         char extra[16];
         int nextra = 0;
         register int c;
         int n;
         bool_t eof;

         screenp = Nextscreen + (Cline_row * Columns);

         memp = *Curschar;
         memp.index = 0;

         eof = FALSE;
         col = 0;
         row = Cline_row;

         while (!eof) {

                 /* Get the next character to put on the screen. */

                 /* The 'extra' array contains the extra stuff that is */
                 /* inserted to represent special characters (tabs, and */
                 /* other non-printable stuff.  The order in the 'extra' */
                 /* array is reversed. */

                 if ( nextra > 0 )
                         c = extra[--nextra];
                 else {
                         c = (unsigned)(0xff & gchar(&memp));
                         if (inc(&memp) == -1)
                                 eof = TRUE;
                         /* when getting a character from the file, we */
                         /* may have to turn it into something else on */
                         /* the way to putting it into 'Nextscreen'. */
                         if ( c == TAB && !P(P_LS) ) {
                                 strcpy(extra,"        ");
                                 /* tab amount depends on current column */
                                 nextra = ((P(P_TS)-1) - col%P(P_TS));
                                 c = ' ';
                         } else if ( c == NUL && P(P_LS) ) {
                                 extra[0] = NUL;
                                 nextra = 1;
                                 c = '$';
                         } else if ( c != NUL && (n=chars[c].ch_size) > 1 ) {
                                 char *p;
                                 nextra = 0;
                                 p = chars[c].ch_str;
                                 /* copy 'ch-str'ing into 'extra' in reverse *
                                 while ( n > 1 )
                                         extra[nextra++] = p[--n];
                                 c = p[0];
                         }
                 }

                 if ( c == NUL ) {
                         row++;
                         /* get pointer to start of next row */
                         nextrow = &Nextscreen[row*Columns];
                         /* blank out the rest of this row */
                         while ( screenp != nextrow )
                                 *screenp++ = ' ';
                         col = 0;
                         break;
                 }

                 if ( col >= Columns ) {
                         row++;
                         col = 0;
                 }
                 /* store the character in Nextscreen */
                 *screenp++ = c;
                 col++;
         }
         return ((row - Cline_row) == Cline_size);
 }

 /*
  * lnexttoscreen
  *
  * Like nexttoscreen() but only for the cursor line.
  */
 static void
 lnexttoscreen()
 {
         register char *np = Nextscreen + (Cline_row * Columns);
         register char *rp = Realscreen + (Cline_row * Columns);
         register char *endline;
         register int row, col;
         int gorow = -1, gocol = -1;

         endline = np + (Cline_size * Columns);

         row = Cline_row;
         col = 0;

         outstr(T_CI);                /* disable cursor */

         for ( ; np < endline ; np++,rp++ ) {
                 /* If desired screen (contents of Nextscreen) does not */
                 /* match what's really there, put it there. */
                 if ( *np != *rp ) {
                         /* if we are positioned at the right place, */
                         /* we don't have to use windgoto(). */
                         if (gocol != col || gorow != row) {
                                 /*
                                  * If we're just off by one, don't send
                                  * an entire esc. seq. (this happens a lot!)
                                  */
                                 if (gorow == row && gocol+1 == col) {
                                         outchar(*(np-1));
                                         gocol++;
                                 } else
                                         windgoto(gorow=row,gocol=col);
                         }
                         outchar(*rp = *np);
                         gocol++;
                 }
                 if ( ++col >= Columns ) {
                         col = 0;
                         row++;
                 }
         }
         outstr(T_CV);                /* enable cursor again */
 }

 /*
  * updateline() - update the line the cursor is on
  *
  * Updateline() is called after changes that only affect the line that
  * the cursor is on. This improves performance tremendously for normal
  * insert mode operation. The only thing we have to watch for is when
  * the cursor line grows or shrinks around a row boundary. This means
  * we have to repaint other parts of the screen appropriately. If
  * lfiletonext() returns FALSE, the size of the cursor line (in rows)
  * has changed and we have to call updatescreen() to do a complete job.
  */
 void
 updateline()
 {
         if (!lfiletonext())
                 updatescreen();                /* bag it, do the whole screen
         else
                 lnexttoscreen();
 }

 void
 updatescreen()
 {
         filetonext();
         nexttoscreen();
 }

 void
 screenclear()
 {
         register char        *rp, *np;
         register char        *end;

         outstr(T_ED);                /* clear the display */

         rp  = Realscreen;
         end = Realscreen + Rows * Columns;
         np  = Nextscreen;

         /* blank out the stored screens */
         while (rp != end)
                 *rp++ = *np++ = ' ';
 }

 void
 cursupdate()
 {
         LPTR *p;
         int inc, c, nlines;
         int i;
         int didinc;

         if (bufempty()) {                /* special case - file is empty */
                 *Topchar  = *Filemem;
                 *Curschar = *Filemem;
         } else if ( LINEOF(Curschar) < LINEOF(Topchar) ) {
                 nlines = cntllines(Curschar,Topchar);
                 /* if the cursor is above the top of */
                 /* the screen, put it at the top of the screen.. */
                 *Topchar = *Curschar;
                 Topchar->index = 0;
                 /* ... and, if we weren't very close to begin with, */
                 /* we scroll so that the line is close to the middle. */
                 if ( nlines > Rows/3 ) {
                         for (i=0, p = Topchar; i < Rows/3 ;i++, *Topchar = *p
                                 if ((p = prevline(p)) == NULL)
                                         break;
                 } else
                         s_ins(0, nlines-1);
                 updatescreen();
         }
         else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
                 nlines = cntllines(Botchar,Curschar);
                 /* If the cursor is off the bottom of the screen, */
                 /* put it at the top of the screen.. */
                 /* ... and back up */
                 if ( nlines > Rows/3 ) {
                         p = Curschar;
                         for (i=0; i < (2*Rows)/3 ;i++)
                                 if ((p = prevline(p)) == NULL)
                                         break;
                         *Topchar = *p;
                 } else {
                         scrollup(nlines);
                 }
                 updatescreen();
         }

         Cursrow = Curscol = Cursvcol = 0;
         for ( p=Topchar; p->linep != Curschar->linep ;p = nextline(p) )
                 Cursrow += plines(p);

         Cline_row = Cursrow;
         Cline_size = plines(p);

         for (i=0; i <= Curschar->index ;i++) {
                 c = Curschar->linep->s[i];
                 /* A tab gets expanded, depending on the current column */
                 if ( c == TAB && !P(P_LS) )
                         inc = P(P_TS) - (Curscol % P(P_TS));
                 else
                         inc = chars[(unsigned)(c & 0xff)].ch_size;
                 Curscol += inc;
                 Cursvcol += inc;
                 if ( Curscol >= Columns ) {
                         Curscol -= Columns;
                         Cursrow++;
                         didinc = TRUE;
                 }
                 else
                         didinc = FALSE;
         }
         if (didinc)
                 Cursrow--;

         if (c == TAB && State == NORMAL && !P(P_LS)) {
                 Curscol--;
                 Cursvcol--;
         } else {
                 Curscol -= inc;
                 Cursvcol -= inc;
         }
         if (Curscol < 0)
                 Curscol += Columns;

         if (set_want_col) {
                 Curswant = Cursvcol;
                 set_want_col = FALSE;
         }
 }

 /*
  * The rest of the routines in this file perform screen manipulations.
  * The given operation is performed physically on the screen. The
  * corresponding change is also made to the internal screen image.
  * In this way, the editor anticipates the effect of editing changes
  * on the appearance of the screen. That way, when we call screenupdate
  * a complete redraw isn't usually necessary. Another advantage is that
  * we can keep adding code to anticipate screen changes, and in the
  * meantime, everything still works.
  */

 /*
  * s_ins(row, nlines) - insert 'nlines' lines at 'row'
  */
 void
 s_ins(row, nlines)
 int        row;
 int        nlines;
 {
         register char        *s, *d;                /* src & dest for block c
         register char        *e;                /* end point for copy */
         register int        i;

         if (T_IL[0] == NUL)                /* can't do it */
                 return;

         /*
          * It "looks" better if we do all the inserts at once
          */
         outstr(T_SC);                        /* save position */

         for (i=0; i < nlines ;i++) {
                 windgoto(row, 0);
                 outstr(T_IL);
         }

         windgoto(Rows-1, 0);        /* delete any garbage that may have */
         outstr(T_EL);                /* been shifted to the bottom line */
         outstr(T_RC);                /* restore the cursor position */

         /*
          * Now do a block move to update the internal screen image
          */
         d = Realscreen + (Columns * (Rows - 1)) - 1;
         s = d - (Columns * nlines);
         e = Realscreen + (Columns * row);

         while (s >= e)
                 *d-- = *s--;

         /*
          * Clear the inserted lines
          */
         s = Realscreen + (row * Columns);
         e = s + (nlines * Columns);
         while (s < e)
                 *s++ = ' ';
 }

 /*
  * s_del(row, nlines) - delete 'nlines' lines at 'row'
  */
 void
 s_del(row, nlines)
 int        row;
 int        nlines;
 {
         register char        *s, *d, *e;
         register int        i;

         if (T_DL[0] == NUL)                        /* can't do it */
                 return;

         /* delete the lines */
         outstr(T_SC);                                /* save position */
         for (i=0; i < nlines ;i++) {
                 windgoto(row, 0);
                 outstr(T_DL);                        /* delete a line */
                 if (i == 0) {
                         windgoto(Rows-2, 0);        /* delete any garbage tha
                         outstr(T_EL);                /* was on the status lin
                 }
         }
         outstr(T_RC);                                /* restore position */

         /*
          * do a block move to update the internal image
          */
         d = Realscreen + (row * Columns);
         s = d + (nlines * Columns);
         e = Realscreen + ((Rows - 1) * Columns);

         while (s < e)
                 *d++ = *s++;

         while (d < e)                /* clear the lines at the bottom */
                 *d++ = ' ';
 }


 SCRNIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SCRNIO.C

 /* 1.2  10-08-85                                                (scrnio.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /*----------------------------------------------------------------------*/

 GLOBAL int outrow[], outcol[];
 GLOBAL tiny HEIGHT, WIDTH;        /* See scrnio.h for definitions.        */
 GLOBAL TEXT LEADIN[], RCSEPARATOR[], RCENDER[], CLEARSCREEN[], EREOPG[],
         HOMER[], EREOLN[], NORM_SCRN[], ALT_SCRN[], SCRNINI[], SCRNUNI[];
 GLOBAL TBOOL CB4L;
 GLOBAL tiny ROFFSET, COFFSET;
 GLOBAL TBOOL XLT2ASCII, SCRNWRAP, USELAST;

 /*----------------------------------------------------------------------*/

 toscrn(a, b)        write(STDOUT, a, b) /* write bchars of string a */
 TABSTOP                8                /* standard tab stops.

 /************************************************************************/
         VOID
 iniscrn()                /* Send initialization sequence to terminal        *

 /*----------------------------------------------------------------------*/
 {
         if (*SCRNINI)
                 scrsend(SCRNINI);
 }

 /************************************************************************/
         VOID
 uniscrn()                /* Send un-initialization sequence to terminal.

 /*----------------------------------------------------------------------*/
 {
         if (*SCRNUNI)
                 scrsend(SCRNUNI);
 }

 /*\p********************************************************************/
         VOID
 clrscrn()        /* Clear the terminal screen and home the cursor.        */

 /*----------------------------------------------------------------------*/
 {
 int i;
         if (*CLEARSCREEN)
                 scrsend(CLEARSCREEN);
         else
                 eraeop(0, 0);
         outrow[STDOUT] = outcol[STDOUT] = 0;
 }

 /************************************************************************/
         VOID
 home()                        /* Move cursor to row 0, column 0 of terminal.

 /*----------------------------------------------------------------------*/
 {
         if (*HOMER)
         {        scrsend(HOMER);
                 outrow[STDOUT] = outcol[STDOUT] = 0;
         }
         else
                 cursor(0, 0);
 }

 /************************************************************************/
         BOOL
 normscrn()                /* Begin normal-intensity mode.  Return TRUE if
                            supported, FALSE if not.                        */
 /*----------------------------------------------------------------------*/
 {
         scrsend(NORM_SCRN);
         return (*NORM_SCRN ISNT NULL);
 }

 /************************************************************************/
         BOOL
 altscrn()                /* Begin alternate-intensity mode.  Return TRUE
                            if supported, FALSE if not.
 /*----------------------------------------------------------------------*/
 {
         scrsend(ALT_SCRN);
         return (*ALT_SCRN ISNT NULL);
 }
 /*\p*********************************************************************/
         BOOL
 eraeop(r, c)                /* Erase from row r, col c to end of page. Return
                            TRUE, or FALSE if improper r, c.                */
 /*----------------------------------------------------------------------*/
 {
         int i;

         if (NOT cursor(r, c))
                 return (FALSE);

         if (*EREOPG)
                 scrsend(EREOPG);
         else
         {        i = r;
                 eraeol(r, c);
                 while (++i <= HEIGHT - 1)
                         eraeol(i, 0);
         }
         return (cursor(r, c));
 }

 /************************************************************************/
         BOOL
 eraeol(r, c)                /* Erase row r from column c to end of line. Retu
                            TRUE, or FALSE on improper r, c.                */
 /*----------------------------------------------------------------------*/
 {
         int i;

         if (NOT cursor(r, c))
                 return (FALSE);

         if (*EREOLN)
                 scrsend(EREOLN);
         else
         {        i = WIDTH - 1 - c;
                 while (i--)
                         toscrn(" ", 1);
                 if ((r ISNT HEIGHT - 1) OR USELAST)
                         toscrn(" ", 1);
                 cursor(r, c);
         }
         return (TRUE);
 }
 /*\p*********************************************************************/
         BOOL
 cursor(r, c)                /* Position the cursor at row r, column c.  Retur
                            TRUE if successful, or FALSE if coordinate
                            addressing error is sensed.
 /*----------------------------------------------------------------------*/
 {
         if ((r > HEIGHT - 1) OR (c > WIDTH - 1) OR (r < 0 AND c < 0))
                 return (FALSE);

         scrsend(LEADIN);
         CB4L ? coord(c + COFFSET) : coord(r + ROFFSET);
         scrsend(RCSEPARATOR);
         CB4L ? coord(r + ROFFSET) : coord(c + COFFSET);
         scrsend(RCENDER);
         outrow[STDOUT] = r;
         outcol[STDOUT] = c;
         return (TRUE);
 }

 /************************************************************************/
         LOCAL VOID
 scrsend(s)                /* Send the string s to the terminal

 /*----------------------------------------------------------------------*/
 STRING s;
 {
         if (*s)
                 toscrn(s, strlen(s));
 }

 /************************************************************************/
         LOCAL VOID
 coord(x)                /* Output the coordinate x to the screen.        */

 /*----------------------------------------------------------------------*/
 {
         BUFFER buf[10];

         if (XLT2ASCII)
         {        itoa(buf, x, 0);
                 if (*buf)
                         scrsend(buf);
         }
         else
                 toscrn(&x, 1);

 }
 /*\p*********************************************************************/
         METACHAR
 putscrn(c)                /* put character c to the screen and update row
                            and column values appropriately.                */
 /*----------------------------------------------------------------------*/
 {
         int i;
         char ch;

 #ifdef CROUTADD
         if (c IS '\n')
                 toscrn("\r", 1);
 #endif
         if (NOT USELAST AND outrow[STDOUT] IS (HEIGHT -1)
             AND outcol[STDOUT] IS (WIDTH -1))
                 return EOF;

         ch = c;
         switch(c)
         {   case '\n':
                 outrow[STDOUT]++;
             case '\r':
                 outcol[STDOUT] = 0;
                 break;
             case '\b':
                 if (outcol[STDOUT] > 0)
                         --outcol[STDOUT];
                         toscrn(&ch, 1);
                         return c;
             case '\t':
                 i = TABSTOP - (outcol[STDOUT] % TABSTOP);
                 while ((SCRNWRAP OR outcol[STDOUT] < WIDTH) AND i--)
                 {        toscrn(" ", 1);
                         ++outcol[STDOUT];
                 }
                 break;
             default :
                 outcol[STDOUT]++;
         }
         if (SCRNWRAP AND outcol[STDOUT] >= WIDTH)
         {        outrow[STDOUT]++;
                 outcol[STDOUT] -= WIDTH;
         }
         if (c ISNT '\t')
                 toscrn(&ch, 1);
         return c;
 }


 SCRNPUT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MIKES30C\SCRNPUT.C

 /**************************************************************************
   This program demonstrates the program NOSNOW.ASM which significantly
   increases the speed of full screen displays and updates as opposed to
   using printf.  This program and NOSNOW was written for Microsoft 3.0
   C and displays a screen without the usual snow assosiated with movedata.
   The following command and switches where used to compile:

      cl -Ox -Ze scrnput.c nosnow

         Enjoy!!   Mike Elkins    Sysop Mike's "C" Board
 ***************************************************************************/

 #include <stdio.h>
 #include <dos.h>

 void flash(unsigned int, unsigned int);
 void scrnsave(unsigned int, unsigned int);
 char *malloc();

 main()
 {
    char far *hold;
    unsigned  i;

    hold = (char far * ) malloc(4001);       /* Allocate memory for save */
    scrnsave(FP_SEG(hold), FP_OFF(hold));    /* Save current screen */
    screen0();                               /* Display new screen */
    for(i=0; i<60000; i++);                  /* Stall */
    for(i=0; i<60000; i++);
    for(i=0; i<60000; i++);
    flash(FP_SEG(hold), FP_OFF(hold));       /* Put orig. screen back */
    free(hold);                              /* Free space */
 }

 screen0() /* This screen was created with SG3 and the C code edited in */
 {
     char        *scrn0;

     scrn0 = malloc(2001);
     strcpy(scrn0, "ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
     strcat(scrn0, "Û²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
     strcat(scrn0, "Û²±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
     strcat(scrn0, "Û²±°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°                             W E L C O M E
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°                                  T O
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°                           MIKE'S  'C'  BOARD
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°              ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
     strcat(scrn0, "Û²±°              ³           FIDO  NODE  102/201
     strcat(scrn0, "Û²±°              ³            619 - 722 - 8724
     strcat(scrn0, "Û²±°              ³               24 HRS DAY
     strcat(scrn0, "Û²±°              ³             300/1200 BAUD
     strcat(scrn0, "Û²±°              ³           SYSOP  MIKE ELKINS
     strcat(scrn0, "Û²±°              ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°
     strcat(scrn0, "Û²±°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
     strcat(scrn0, "Û²±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
     strcat(scrn0, "Û²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
     strcat(scrn0, "ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

     quik_scrn(scrn0);
     free(scrn0);
 }

 /*********************************************************************
   These routines take an array containing a screen layout and injects
   attribute bytes preparing it for direct move to screen memory.
 *********************************************************************/
 quik_scrn(strng)
 char        *strng;
 {
     char        far *scrn;
     int        i, j;

     scrn = (char far * ) malloc(4001);
     build_scrn(scrn,strng);             /* Insert attribute bytes */
     flash(FP_SEG(scrn), FP_OFF(scrn));  /* Display new screen */
     free(scrn);

 }

 build_scrn(hld, scrn) /* Convert scrn to screen memory format and store in hl
 char        far *hld;
 char        *scrn;
 {
     int        i, j;

     for (i = 1; i < 4001; i += 2) /* Fill every other byte with std. screen *
         hld[i] = 0x07;            /* attribute starting with second */
     for (i = 0, j = 0; hld[i] = scrn[j]; i += 2, j++) /* Put above screen in*
         ;                         /* in every other byte */
 }



 SCSW88.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SCSW88.C

 /*
 ** 8088/8086 version
 ** Routine to get the time of day -- BYTE Small C
 ** MS-DOS version for 8088.
 ** tblock[] is assumed to be a 4-element int array.
 ** tblock[0]=hours
 ** tblock[1]=minutes
 ** tblock[2]=seconds
 ** tblcok[3]=hundredths of seconds
 */
 gtime(tblock) int tblock[];
 {
 #asm
         MOV        AH,2CH        ;Function to get time
         INT        21H        ;Do it
         XOR        AX,AX        ;Clear high part
         MOV        BP,SP
         MOV        SI,2[BP] ;Get pointer to array
         MOV        AL,CH
         MOV        [SI],AX        ;Hours
         MOV        AL,CL
         MOV        2[SI],AX ;Minutes
         MOV        AL,DH
         MOV        4[SI],AX ;Seconds
         MOV        AL,DL
         MOV        6[SI],AX ;Hundredths
         XOR        CX,CX        ;Clear CX
 #endasm
 }

 /*
 ** 8088/8086 version
 ** calctim() - calculate time difference between time stored in
 ** tblock[] and current time.
 ** tblock[] is a 4-element array:
 ** tblock[0] = hours
 ** tblock[1] = minutes
 ** tblock[2] = seconds
 ** tblcok[3] = 100/ths of a second
 ** calctim() returns its results in tblock[]
 */
 calctim(tblock) int tblock[]; {
 #asm
         MOV        AH,2CH        ;Get time
         INT        21H
         MOV        BP,SP
         MOV        SI,2[BP] ;Pointer to tblock[]
         MOV        AX,6[SI] ;Get 100/ths of a second
         SUB        DL,AL
         JNS        CAL1
         ADD        DL,100
         DEC        DH
 CAL1:        MOV        6[SI],DL
         MOV        AX,4[SI] ;Get seconds
         SUB        DH,AL
         JNS        CAL2
         ADD        DH,60
         DEC        CL
 CAL2:        MOV        4[SI],DH
         MOV        AX,2[SI] ;Get minutes
         SUB        CL,AL
         JNS        CAL3
         ADD        CL,60
         DEC        CH
 CAL3:        MOV        2[SI],CL
         MOV        AX,[SI]  ;Get hours
         SUB        CH,AL
         MOV        [SI],CH
         XOR        CX,CX
 #endasm
 }


 SDB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\SDB.C

 /* SDB - main routine */

 #include "stdio.h"
 #include "sdbio.h"

 extern int dbv_errcode;

 main()
 {
     printf("SDB - version 2.0\n");
     db_sinit();
     db_ifile("sdb.ini");

     while (TRUE) {
         db_prompt("SDB> ","\t> ");
         if (!db_parse(NULL)) {
             printf("** error: %s ***\n",db_ertxt(dbv_errcode));
             db_kill();
         }
     }
 }



 SDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\SDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==SOUTH)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 SEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\SEARCH.C

 /*
  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  *
  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  * Turbo C 1.5 port by: Denny Muscatelli 061988
  */

 #include "stevie.h"

 <regexp.h>        /* Henry Spencer's regular expression routines */

 #ifdef        MEGAMAX
 overlay "search"
 #endif

 /*
  * This file contains various searching-related routines. These fall into
  * three groups: string searches (for /, ?, n, and N), character searches
  * within a single line (for f, F, t, T, etc), and "other" kinds of searches
  * like the '%' command, and 'word' searches.
  */

 /*
  * String searches
  *
  * The actual searches are done using Henry Spencer's regular expression
  * library.
  */

        BEGWORD        "([^a-zA-Z0-9_]|^)"        /* replaces "\<" in search s
        ENDWORD        "([^a-zA-Z0-9_]|$)"        /* likewise replaces "\>" */

 bool_t        begword;        /* does the search include a 'begin word' match

 /*
  * mapstring(s) - map special backslash sequences
  */
 static char *
 mapstring(s)
 register char        *s;
 {
         static        char        ns[80];
         char        *p;

         begword = FALSE;

         for (p = ns; *s ;s++) {
                 if (*s != '\\') {        /* not an escape */
                         *p++ = *s;
                         continue;
                 }
                 switch (*++s) {
                 case '/':
                         *p++ = '/';
                         break;

                 case '<':
                         strcpy(p, BEGWORD);
                         p += strlen(BEGWORD);
                         begword = TRUE;
                         break;

                 case '>':
                         strcpy(p, ENDWORD);
                         p += strlen(ENDWORD);
                         break;

                 default:
                         *p++ = '\\';
                         *p++ = *s;
                         break;
                 }
         }
         *p++ = NUL;

         return ns;
 }

 static char *laststr = NULL;
 static int lastsdir;

 static LPTR *
 ssearch(dir,str)
 int        dir;        /* FORWARD or BACKWARD */
 char        *str;
 {
         static LPTR *bcksearch(), *fwdsearch();
         LPTR        *pos;

         if ( laststr != NULL )
                 free(laststr);
         laststr = strsave(str);
         lastsdir = dir;
         if ( dir == BACKWARD )
                 pos = bcksearch(mapstring(str));
         else
                 pos = fwdsearch(mapstring(str));

         /*
          * This is kind of a kludge, but its needed to make
          * 'beginning of word' searches land on the right place.
          */
         if (begword) {
                 if (pos->index != 0)
                         pos->index += 1;
         }
         return pos;
 }

 void
 dosearch(dir,str)
 int dir;
 char *str;
 {
         LPTR *p;

         if ((p = ssearch(dir,str)) == NULL)
                 msg("Pattern not found");
         else {
                 LPTR savep;

                 cursupdate();
                 /* if we're backing up, we make sure the line we're on */
                 /* is on the screen. */
                 setpcmark();
                 *Curschar = savep = *p;
                 cursupdate();
         }
 }

 #define        OTHERDIR(x)        (((x) == FORWARD) ? BACKWARD : FORWARD)

 void
 repsearch(flag)
 int        flag;
 {
         int        dir = lastsdir;

         if ( laststr == NULL )
                 beep();
         else
                 dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);

         lastsdir = dir;
 }

 /*
  * regerror - called by regexp routines when errors are detected.
  */
 void
 regerror(s)
 char        *s;
 {
         emsg(s);
 }

 static LPTR *
 fwdsearch(str)
 register char *str;
 {
         static LPTR infile;
         register LPTR *p;
         regexp *prog;
         bool_t        want_start = (*str == '^');        /* looking for start

         register char *s;
         register int i;

         if ((prog = regcomp(str)) == NULL) {
                 emsg("Invalid search string");
                 return NULL;
         }

         p = Curschar;
         i = Curschar->index + 1;
         do {
                 s = p->linep->s + i;
                 i = 0;

                 if (regexec(prog, s)) {                /* got a match */
                         /*
                          * If we wanted the start of a line and we aren't
                          * really there, then a match doesn't count.
                          */
                         if (want_start && (s != p->linep->s))
                                 continue;

                         infile.linep = p->linep;
                         infile.index = (int) (prog->startp[0] - p->linep->s);
                         free(prog);
                         return (&infile);
                 }
         } while ((p = nextline(p)) != NULL);

         /*
          * If wrapscan isn't set, then don't scan from the beginning
          * of the file. Just return failure here.
          */
         if (!P(P_WS)) {
                 free(prog);
                 return NULL;
         }

         /* search from the beginning of the file to Curschar */
         for (p = Filemem; p != NULL ;p = nextline(p)) {
                 s = p->linep->s;

                 if (regexec(prog, s)) {                /* got a match */
                         infile.linep = p->linep;
                         infile.index = (int) (prog->startp[0] - s);
                         free(prog);
                         return (&infile);
                 }

                 if (p->linep == Curschar->linep)
                         break;
         }

         free(prog);
         return(NULL);
 }

 static LPTR *
 bcksearch(str)
 char *str;
 {
         static LPTR infile;
         register LPTR *p;
         regexp        *prog;
         register char *s;
         register int i;
         bool_t        want_start = (*str == '^');        /* looking for start
         register char        *match;

         /* make sure str isn't empty */
         if (str == NULL || *str == NUL)
                 return NULL;

         if ((prog = regcomp(str)) == NULL) {
                 emsg("Invalid search string");
                 return NULL;
         }

         p = Curschar;
         dec(p);

         if (begword)                /* so we don't get stuck on one match */
                 dec(p);

         i = (want_start) ? 0 : p->index;

         do {
                 s = p->linep->s;

                 if (regexec(prog, s)) {                /* match somewhere on

                         if (want_start) {        /* could only have been one
                                 infile.linep = p->linep;
                                 infile.index = (int) (prog->startp[0] - s);
                                 free(prog);
                                 return (&infile);
                         }

                         /*
                          * Now, if there are multiple matches on this line,
                          * we have to get the last one. Or the last one
                          * before the cursor, if we're on that line.
                          */

                         match = prog->startp[0];

                         while (regexec(prog, prog->endp[0])) {
                                 if ((i >= 0) && ((prog->startp[0] - s) > i))
                                         break;
                                 match = prog->startp[0];
                         }

                         if ((i >= 0) && ((match - s) > i)) {
                                 i = -1;
                                 continue;
                         }

                         infile.linep = p->linep;
                         infile.index = (int) (match - s);
                         free(prog);
                         return (&infile);
                 }
                 i = -1;

         } while ((p = prevline(p)) != NULL);

         /*
          * If wrapscan isn't set, bag the search now
          */
         if (!P(P_WS)) {
                 free(prog);
                 return NULL;
         }

         /* search backward from the end of the file */
         p = prevline(Fileend);
         do {
                 s = p->linep->s;

                 if (regexec(prog, s)) {                /* match somewhere on

                         if (want_start) {        /* could only have been one
                                 infile.linep = p->linep;
                                 infile.index = (int) (prog->startp[0] - s);
                                 free(prog);
                                 return (&infile);
                         }

                         /*
                          * Now, if there are multiple matches on this line,
                          * we have to get the last one.
                          */

                         match = prog->startp[0];

                         while (regexec(prog, prog->endp[0]))
                                 match = prog->startp[0];

                         infile.linep = p->linep;
                         infile.index = (int) (match - s);
                         free(prog);
                         return (&infile);
                 }

                 if (p->linep == Curschar->linep)
                         break;

         } while ((p = prevline(p)) != NULL);

         free(prog);
         return NULL;
 }

 /*
  * Character Searches
  */

 static char lastc = NUL;        /* last character searched for */
 static int  lastcdir;                /* last direction of character search */
 static int  lastctype;                /* last type of search ("find" or "to")

 /*
  * searchc(c, dir, type)
  *
  * Search for character 'c', in direction 'dir'. If type is 0, move to
  * the position of the character, otherwise move to just before the char.
  */
 bool_t
 searchc(c, dir, type)
 char        c;
 int        dir;
 int        type;
 {
         LPTR        save;

         save = *Curschar;        /* save position in case we fail */
         lastc = c;
         lastcdir = dir;
         lastctype = type;

         /*
          * On 'to' searches, skip one to start with so we can repeat
          * searches in the same direction and have it work right.
          */
         if (type)
                 (dir == FORWARD) ? oneright() : oneleft();

         while ( (dir == FORWARD) ? oneright() : oneleft() ) {
                 if (gchar(Curschar) == c) {
                         if (type)
                                 (dir == FORWARD) ? oneleft() : oneright();
                         return TRUE;
                 }
         }
         *Curschar = save;
         return FALSE;
 }

 bool_t
 crepsearch(flag)
 int        flag;
 {
         int        dir = lastcdir;
         int        rval;

         if (lastc == NUL)
                 return FALSE;

         rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype

         lastcdir = dir;                /* restore dir., since it may have cha

         return rval;
 }

 /*
  * "Other" Searches
  */

 /*
  * showmatch - move the cursor to the matching paren or brace
  */
 LPTR *
 showmatch()
 {
         static        LPTR        pos;
         int        (*move)(), inc(), dec();
         char        initc = gchar(Curschar);        /* initial char */
         char        findc;                                /* terminating char
         char        c;
         int        count = 0;

         pos = *Curschar;                /* set starting point */

         switch (initc) {

         case '(':
                 findc = ')';
                 move = inc;
                 break;
         case ')':
                 findc = '(';
                 move = dec;
                 break;
         case '{':
                 findc = '}';
                 move = inc;
                 break;
         case '}':
                 findc = '{';
                 move = dec;
                 break;
         case '[':
                 findc = ']';
                 move = inc;
                 break;
         case ']':
                 findc = '[';
                 move = dec;
                 break;
         default:
                 return (LPTR *) NULL;
         }

         while ((*move)(&pos) != -1) {                /* until end of file */
                 c = gchar(&pos);
                 if (c == initc)
                         count++;
                 else if (c == findc) {
                         if (count == 0)
                                 return &pos;
                         count--;
                 }
         }
         return (LPTR *) NULL;                        /* never found it */
 }

 /*
  * findfunc(dir) - Find the next function in direction 'dir'
  *
  * Return TRUE if a function was found.
  */
 bool_t
 findfunc(dir)
 int        dir;
 {
         LPTR        *curr;

         curr = Curschar;

         do {
                 curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);

                 if (curr != NULL && curr->linep->s[0] == '{') {
                         setpcmark();
                         *Curschar = *curr;
                         return TRUE;
                 }
         } while (curr != NULL);

         return FALSE;
 }

 /*
  * The following routines do the word searches performed by the
  * 'w', 'W', 'b', 'B', 'e', and 'E' commands.
  */

 /*
  * To perform these searches, characters are placed into one of three
  * classes, and transitions between classes determine word boundaries.
  *
  * The classes are:
  *
  * 0 - white space
  * 1 - letters, digits, and underscore
  * 2 - everything else
  */

 static        int        stype;                /* type of the word motion bei

 #define        C0(c)        (((c) == ' ') || ((c) == '\t') || ((c) == NUL))
 #define        C1(c)        (isalpha(c) || isdigit(c) || ((c) == '_'))

 /*
  * cls(c) - returns the class of character 'c'
  *
  * The 'type' of the current search modifies the classes of characters
  * if a 'W', 'B', or 'E' motion is being done. In this case, chars. from
  * class 2 are reported as class 1 since only white space boundaries are
  * of interest.
  */
 static        int
 cls(c)
 char        c;
 {
         if (C0(c))
                 return 0;

         if (C1(c))
                 return 1;

         /*
          * If stype is non-zero, report these as class 1.
          */
         return (stype == 0) ? 2 : 1;
 }


 /*
  * fwd_word(pos, type) - move forward one word
  *
  * Returns the resulting position, or NULL if EOF was reached.
  */
 LPTR *
 fwd_word(p, type)
 LPTR        *p;
 int        type;
 {
         static        LPTR        pos;
         int        sclass = cls(gchar(p));                /* starting class *

         pos = *p;

         stype = type;

         /*
          * We always move at least one character.
          */
         if (inc(&pos) == -1)
                 return NULL;

         if (sclass != 0) {
                 while (cls(gchar(&pos)) == sclass) {
                         if (inc(&pos) == -1)
                                 return NULL;
                 }
                 /*
                  * If we went from 1 -> 2 or 2 -> 1, return here.
                  */
                 if (cls(gchar(&pos)) != 0)
                         return &pos;
         }

         /* We're in white space; go to next non-white */

         while (cls(gchar(&pos)) == 0) {
                 /*
                  * We'll stop if we land on a blank line
                  */
                 if (pos.index == 0 && pos.linep->s[0] == NUL)
                         break;

                 if (inc(&pos) == -1)
                         return NULL;
         }

         return &pos;
 }

 /*
  * bck_word(pos, type) - move backward one word
  *
  * Returns the resulting position, or NULL if EOF was reached.
  */
 LPTR *
 bck_word(p, type)
 LPTR        *p;
 int        type;
 {
         static        LPTR        pos;
         int        sclass = cls(gchar(p));                /* starting class *

         pos = *p;

         stype = type;

         if (dec(&pos) == -1)
                 return NULL;

         /*
          * If we're in the middle of a word, we just have to
          * back up to the start of it.
          */
         if (cls(gchar(&pos)) == sclass && sclass != 0) {
                 /*
                  * Move backward to start of the current word
                  */
                 while (cls(gchar(&pos)) == sclass) {
                         if (dec(&pos) == -1)
                                 return NULL;
                 }
                 inc(&pos);                        /* overshot - forward one *
                 return &pos;
         }

         /*
          * We were at the start of a word. Go back to the start
          * of the prior word.
          */

         while (cls(gchar(&pos)) == 0) {                /* skip any white spac
                 /*
                  * We'll stop if we land on a blank line
                  */
                 if (pos.index == 0 && pos.linep->s[0] == NUL)
                         return &pos;

                 if (dec(&pos) == -1)
                         return NULL;
         }

         sclass = cls(gchar(&pos));

         /*
          * Move backward to start of this word.
          */
         while (cls(gchar(&pos)) == sclass) {
                 if (dec(&pos) == -1)
                         return NULL;
         }
         inc(&pos);                        /* overshot - forward one */

         return &pos;
 }

 /*
  * end_word(pos, type) - move to the end of the word
  *
  * There is an apparent bug in the 'e' motion of the real vi. At least
  * on the System V Release 3 version for the 80386. Unlike 'b' and 'w',
  * the 'e' motion crosses blank lines. When the real vi crosses a blank
  * line in an 'e' motion, the cursor is placed on the FIRST character
  * of the next non-blank line. The 'E' command, however, works correctly.
  * Since this appears to be a bug, I have not duplicated it here.
  *
  * Returns the resulting position, or NULL if EOF was reached.
  */
 LPTR *
 end_word(p, type)
 LPTR        *p;
 int        type;
 {
         static        LPTR        pos;
         int        sclass = cls(gchar(p));                /* starting class *

         pos = *p;

         stype = type;

         if (inc(&pos) == -1)
                 return NULL;

         /*
          * If we're in the middle of a word, we just have to
          * move to the end of it.
          */
         if (cls(gchar(&pos)) == sclass && sclass != 0) {
                 /*
                  * Move forward to end of the current word
                  */
                 while (cls(gchar(&pos)) == sclass) {
                         if (inc(&pos) == -1)
                                 return NULL;
                 }
                 dec(&pos);                        /* overshot - forward one *
                 return &pos;
         }

         /*
          * We were at the end of a word. Go to the end
          * of the next word.
          */

         while (cls(gchar(&pos)) == 0) {                /* skip any white spac
                 if (inc(&pos) == -1)
                         return NULL;
         }

         sclass = cls(gchar(&pos));

         /*
          * Move forward to end of this word.
          */
         while (cls(gchar(&pos)) == sclass) {
                 if (inc(&pos) == -1)
                         return NULL;
         }
         dec(&pos);                        /* overshot - forward one */

         return &pos;
 }


 SEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\SEARCH.C

 /*
  * The functions in this file implement commands that search in the forward
  * and backward directions.  There are no special characters in the search
  * strings.  Probably should have a regular expression search, or something
  * like that.
  *
  * Aug. 1986 John M. Gamble:
  *        Made forward and reverse search use the same scan routine.
  *
  *        Added a limited number of regular expressions - 'any',
  *        'character class', 'closure', 'beginning of line', and
  *        'end of line'.
  *
  *        Replacement metacharacters will have to wait for a re-write of
  *        the replaces function, and a new variation of ldelete().
  *
  *        For those curious as to my references, i made use of
  *        Kernighan & Plauger's "Software Tools."
  *        I deliberately did not look at any published grep or editor
  *        source (aside from this one) for inspiration.  I did make use of
  *        Allen Hollub's bitmap routines as published in Doctor Dobb's Journa
  *        June, 1985 and modified them for the limited needs of character cla
  *        matching.  Any inefficiences, bugs, stupid coding examples, etc.,
  *        are therefore my own responsibility.
  *
  * April 1987: John M. Gamble
  *        Deleted the "if (n == 0) n = 1;" statements in front of the
  *        search/hunt routines.  Since we now use a do loop, these
  *        checks are unnecessary.  Consolidated common code into the
  *        function delins().  Renamed global mclen matchlen,
  *        and added the globals matchline, matchoff, patmatch, and
  *        mlenold.
  *        This gave us the ability to unreplace regular expression searches,
  *        and to put the matched string into an evironment variable.
  *        SOON TO COME: Meta-replacement characters!
  *
  *        25-apr-87        DML
  *        - cleaned up an unneccessary if/else in forwsearch() and
  *          backsearch()
  *        - savematch() failed to malloc room for the terminating byte
  *          of the match string (stomp...stomp...). It does now. Also
  *          it now returns gracefully if malloc fails
  *
  *        July 1987: John M. Gamble
  *        Set the variables matchlen and matchoff in the 'unreplace'
  *        section of replaces().  It would confuse the function
  *        savematch() if you replaced, unreplaced, then replaced
  *        again (serves you right for being so wishy-washy...)
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if        LATTICE
 #define        void        int
 #endif

 static int    amatch();
 static int    readpattern();
 static int    replaces();
 static int    nextch();
 static int    mcstr();
 static int    mceq();
 static int    cclmake();
 static int    biteq();
 static BITMAP   clearbits();
 static void     setbit();

 /*
  * forwsearch -- Search forward.  Get a search string from the user, and
  *        search for the string.  If found, reset the "." to be just after
  *        the match string, and (perhaps) repaint the display.
  */

 forwsearch(f, n)
 int f, n;        /* default flag / numeric argument */
 {
         register int status = TRUE;

         /* If n is negative, search backwards.
          * Otherwise proceed by asking for the search string.
          */
         if (n < 0)
                 return(backsearch(f, -n));

         /* Ask the user for the text of a pattern.  If the
          * response is TRUE (responses other than FALSE are
          * possible), search for the pattern for as long as
          * n is positive (n == 0 will go through once, which
          * is just fine).
          */
         if ((status = readpattern("Search", &pat[0], TRUE)) == TRUE) {
                 do {
 #if        MAGIC
                         if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0
                                 status = mcscanner(&mcpat[0], FORWARD, PTEND)
                         else
 #endif
                                 status = scanner(&pat[0], FORWARD, PTEND);
                 } while ((--n > 0) && status);

                 /* Save away the match, or complain
                  * if not there.
                  */
                 if (status == TRUE)
                         savematch();
                 else
                         mlwrite("Not found");
         }
         return(status);
 }

 /*
  * forwhunt -- Search forward for a previously acquired search string.
  *        If found, reset the "." to be just after the match string,
  *        and (perhaps) repaint the display.
  */

 forwhunt(f, n)
 int f, n;        /* default flag / numeric argument */
 {
         register int status = TRUE;

         if (n < 0)                /* search backwards */
                 return(backhunt(f, -n));

         /* Make sure a pattern exists, or that we didn't switch
          * into MAGIC mode until after we entered the pattern.
          */
         if (pat[0] == '\0')
         {
                 mlwrite("No pattern set");
                 return FALSE;
         }
 #if        MAGIC
         if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 &&
                  mcpat[0].mc_type == MCNIL)
         {
                 if (!mcstr())
                         return FALSE;
         }
 #endif

         /* Search for the pattern for as long as
          * n is positive (n == 0 will go through once, which
          * is just fine).
          */
         do
         {
 #if        MAGIC
                 if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0)
                         status = mcscanner(&mcpat[0], FORWARD, PTEND);
                 else
 #endif
                         status = scanner(&pat[0], FORWARD, PTEND);
         } while ((--n > 0) && status);

         /* Save away the match, or complain
          * if not there.
          */
         if (status == TRUE)
                 savematch();
         else
                 mlwrite("Not found");

         return(status);
 }

 /*
  * backsearch -- Reverse search.  Get a search string from the user, and
  *        search, starting at "." and proceeding toward the front of the buff
  *        If found "." is left pointing at the first character of the pattern
  *        (the last character that was matched).
  */
 backsearch(f, n)
 int f, n;        /* default flag / numeric argument */
 {
         register int status = TRUE;

         /* If n is negative, search forwards.
          * Otherwise proceed by asking for the search string.
          */
         if (n < 0)
                 return(forwsearch(f, -n));

         /* Ask the user for the text of a pattern.  If the
          * response is TRUE (responses other than FALSE are
          * possible), search for the pattern for as long as
          * n is positive (n == 0 will go through once, which
          * is just fine).
          */
         if ((status = readpattern("Reverse search", &pat[0], TRUE)) == TRUE)
                 do {
 #if        MAGIC
                         if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0
                                 status = mcscanner(&tapcm[0], REVERSE, PTBEG)
                         else
 #endif
                                 status = scanner(&tap[0], REVERSE, PTBEG);
                 } while ((--n > 0) && status);

                 /* Save away the match, or complain
                  * if not there.
                  */
                 if (status == TRUE)
                         savematch();
                 else
                         mlwrite("Not found");
         }
         return(status);
 }

 /*
  * backhunt -- Reverse search for a previously acquired search string,
  *        starting at "." and proceeding toward the front of the buffer.
  *        If found "." is left pointing at the first character of the pattern
  *        (the last character that was matched).
  */
 backhunt(f, n)

 int f, n;        /* default flag / numeric argument */

 {
         register int        status = TRUE;

         if (n < 0)
                 return(forwhunt(f, -n));

         /* Make sure a pattern exists, or that we didn't switch
          * into MAGIC mode until after we entered the pattern.
          */
         if (tap[0] == '\0')
         {
                 mlwrite("No pattern set");
                 return FALSE;
         }
 #if        MAGIC
         if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 &&
                  tapcm[0].mc_type == MCNIL)
         {
                 if (!mcstr())
                         return FALSE;
         }
 #endif

         /* Go search for it for as long as
          * n is positive (n == 0 will go through once, which
          * is just fine).
          */
         do
         {
 #if        MAGIC
                 if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0)
                         status = mcscanner(&tapcm[0], REVERSE, PTBEG);
                 else
 #endif
                         status = scanner(&tap[0], REVERSE, PTBEG);
         } while ((--n > 0) && status);

         /* Save away the match, or complain
          * if not there.
          */
         if (status == TRUE)
                 savematch();
         else
                 mlwrite("Not found");

         return(status);
 }

 #if        MAGIC
 /*
  * mcscanner -- Search for a meta-pattern in either direction.  If found,
  *        reset the "." to be at the start or just after the match string,
  *        and (perhaps) repaint the display.
  */
 int        mcscanner(mcpatrn, direct, beg_or_end)
 MC        *mcpatrn;                /* pointer into pattern */
 int        direct;                /* which way to go.*/
 int        beg_or_end;        /* put point at beginning or end of pattern.*/
 {
         LINE *curline;                        /* current line during scan */
         int curoff;                        /* position within current line */

         /* If we are going in reverse, then the 'end' is actually
          * the beginning of the pattern.  Toggle it.
          */
         beg_or_end ^= direct;

         /*
          * Save the old matchlen length, in case it is
          * horribly different (closure) from the old length.
          * This is terribly important for query-replace undo
          * command.
          */
         mlenold = matchlen;

         /* Setup local scan pointers to global ".".
          */
         curline = curwp->w_dotp;
         curoff  = curwp->w_doto;

         /* Scan each character until we hit the head link record.
          */
         while (!boundry(curline, curoff, direct))
         {
                 /* Save the current position in case we need to
                  * restore it on a match, and initialize matchlen to
                  * zero in case we are doing a search for replacement.
                  */
                 matchline = curline;
                 matchoff = curoff;
                 matchlen = 0;

                 if (amatch(mcpatrn, direct, &curline, &curoff))
                 {
                         /* A SUCCESSFULL MATCH!!!
                          * reset the global "." pointers.
                          */
                         if (beg_or_end == PTEND)        /* at end of string *
                         {
                                 curwp->w_dotp = curline;
                                 curwp->w_doto = curoff;
                         }
                         else                /* at beginning of string */
                         {
                                 curwp->w_dotp = matchline;
                                 curwp->w_doto = matchoff;
                         }

                         curwp->w_flag |= WFMOVE; /* flag that we have moved *
                         return TRUE;
                 }

                 /* Advance the cursor.
                  */
                 nextch(&curline, &curoff, direct);
         }

         return FALSE;        /* We could not find a match.*/
 }

 /*
  * amatch -- Search for a meta-pattern in either direction.  Based on the
  *        recursive routine amatch() (for "anchored match") in
  *        Kernighan & Plauger's "Software Tools".
  */
 static int        amatch(mcptr, direct, pcwline, pcwoff)
 register MC        *mcptr;        /* string to scan for */
 int                direct;                /* which way to go.*/
 LINE                **pcwline;        /* current line during scan */
 int                *pcwoff;        /* position within current line */
 {
         register int c;                        /* character at current positi
         LINE *curline;                        /* current line during scan */
         int curoff;                        /* position within current line */
         int nchars;

         /* Set up local scan pointers to ".", and get
          * the current character.  Then loop around
          * the pattern pointer until success or failure.
          */
         curline = *pcwline;
         curoff = *pcwoff;

         /* The beginning-of-line and end-of-line metacharacters
          * do not compare against characters, they compare
          * against positions.
          * BOL is guaranteed to be at the start of the pattern
          * for forward searches, and at the end of the pattern
          * for reverse searches.  The reverse is true for EOL.
          * So, for a start, we check for them on entry.
          */
         if (mcptr->mc_type == BOL)
         {
                 if (curoff != 0)
                         return FALSE;
                 mcptr++;
         }

         if (mcptr->mc_type == EOL)
         {
                 if (curoff != llength(curline))
                         return FALSE;
                 mcptr++;
         }

         while (mcptr->mc_type != MCNIL)
         {
                 c = nextch(&curline, &curoff, direct);

                 if (mcptr->mc_type & CLOSURE)
                 {
                         /* Try to match as many characters as possible
                          * against the current meta-character.  A
                          * newline never matches a closure.
                          */
                         nchars = 0;
                         while (c != '\n' && mceq(c, mcptr))
                         {
                                 c = nextch(&curline, &curoff, direct);
                                 nchars++;
                         }

                         /* We are now at the character that made us
                          * fail.  Try to match the rest of the pattern.
                          * Shrink the closure by one for each failure.
                          * Since closure matches *zero* or more occurences
                          * of a pattern, a match may start even if the
                          * previous loop matched no characters.
                          */
                         mcptr++;

                         for (;;)
                         {
                                 c = nextch(&curline, &curoff, direct ^ REVERS

                                 if (amatch(mcptr, direct, &curline, &curoff))
                                 {
                                         matchlen += nchars;
                                         goto success;
                                 }

                                 if (nchars-- == 0)
                                         return FALSE;
                         }
                 }
                 else                        /* Not closure.*/
                 {
                         /* The only way we'd get a BOL metacharacter
                          * at this point is at the end of the reversed patter
                          * The only way we'd get an EOL metacharacter
                          * here is at the end of a regular pattern.
                          * So if we match one or the other, and are at
                          * the appropriate position, we are guaranteed succes
                          * (since the next pattern character has to be MCNIL)
                          * Before we report success, however, we back up by
                          * one character, so as to leave the cursor in the
                          * correct position.  For example, a search for ")$"
                          * will leave the cursor at the end of the line, whil
                          * a search for ")<NL>" will leave the cursor at the
                          * beginning of the next line.  This follows the
                          * notion that the meta-character '$' (and likewise
                          * '^') match positions, not characters.
                          */
                         if (mcptr->mc_type == BOL)
                                 if (curoff == llength(curline))
                                 {
                                         c = nextch(&curline, &curoff,
                                                    direct ^ REVERSE);
                                         goto success;
                                 }
                                 else
                                         return FALSE;

                         if (mcptr->mc_type == EOL)
                                 if (curoff == 0)
                                 {
                                         c = nextch(&curline, &curoff,
                                                    direct ^ REVERSE);
                                         goto success;
                                 }
                                 else
                                         return FALSE;

                         /* Neither BOL nor EOL, so go through
                          * the meta-character equal function.
                          */
                         if (!mceq(c, mcptr))
                                 return FALSE;
                 }

                 /* Increment the length counter and
                  * advance the pattern pointer.
                  */
                 matchlen++;
                 mcptr++;
         }                        /* End of mcptr loop.*/

         /* A SUCCESSFULL MATCH!!!
          * Reset the "." pointers.
          */
 success:
         *pcwline = curline;
         *pcwoff  = curoff;

         return TRUE;
 }
 #endif

 /*
  * scanner -- Search for a pattern in either direction.  If found,
  *        reset the "." to be at the start or just after the match string,
  *        and (perhaps) repaint the display.
  */
 int        scanner(patrn, direct, beg_or_end)
 unsigned char *patrn;        /* string to scan for */
 int        direct;                /* which way to go.*/
 int        beg_or_end;        /* put point at beginning or end of pattern.*/
 {
         register int        c;                /* character at current positio
         register unsigned char *patptr;        /* pointer into pattern */
         LINE        *curline;                /* current line during scan */
         int        curoff;                        /* position within current
         LINE        *scanline;                /* current line during scanning
         int        scanoff;                /* position in scanned line */

         /* If we are going in reverse, then the 'end' is actually
          * the beginning of the pattern.  Toggle it.
          */
         beg_or_end ^= direct;

         /* Set up local pointers to global ".".
          */
         curline = curwp->w_dotp;
         curoff = curwp->w_doto;

         /* Scan each character until we hit the head link record.
          */
         while (!boundry(curline, curoff, direct))
         {
                 /* Save the current position in case we match
                  * the search string at this point.
                  */
                 matchline = curline;
                 matchoff = curoff;

                 /* Get the character resolving newlines, and
                  * test it against first char in pattern.
                  */
                 c = nextch(&curline, &curoff, direct);

                 if (eq(c, patrn[0]))        /* if we find it..*/
                 {
                         /* Setup scanning pointers.
                          */
                         scanline = curline;
                         scanoff = curoff;
                         patptr = &patrn[0];

                         /* Scan through the pattern for a match.
                          */
                         while (*++patptr != '\0')
                         {
                                 c = nextch(&scanline, &scanoff, direct);

                                 if (!eq(c, *patptr))
                                         goto fail;
                         }

                         /* A SUCCESSFULL MATCH!!!
                          * reset the global "." pointers
                          */
                         if (beg_or_end == PTEND)        /* at end of string *
                         {
                                 curwp->w_dotp = scanline;
                                 curwp->w_doto = scanoff;
                         }
                         else                /* at beginning of string */
                         {
                                 curwp->w_dotp = matchline;
                                 curwp->w_doto = matchoff;
                         }

                         curwp->w_flag |= WFMOVE; /* Flag that we have moved.*
                         return TRUE;

                 }
 fail:;                        /* continue to search */
         }

         return FALSE;        /* We could not find a match */
 }

 /*
  * eq -- Compare two characters.  The "bc" comes from the buffer, "pc"
  *        from the pattern.  If we are not in EXACT mode, fold out the case.
  */
 int        eq(bc, pc)
 register int        bc;
 register int        pc;
 {
         if ((curwp->w_bufp->b_mode & MDEXACT) == 0)
         {
                 if (islower(bc))
                         bc ^= DIFCASE;

                 if (islower(pc))
                         pc ^= DIFCASE;
         }

         return (bc == pc);
 }

 /*
  * readpattern -- Read a pattern.  Stash it in apat.  If it is the
  *        search string, create the reverse pattern and the magic
  *        pattern, assuming we are in MAGIC mode (and defined that way).
  *        Apat is not updated if the user types in an empty line.  If
  *        the user typed an empty line, and there is no old pattern, it is
  *        an error.  Display the old pattern, in the style of Jeff Lomicka.
  *        There is some do-it-yourself control expansion.  Change to using
  *        <META> to delimit the end-of-pattern to allow <NL>s in the search
  *        string.
  */
 static int        readpattern(prompt, apat, srch)
 char        *prompt;
 char        apat[];
 int        srch;
 {
         int status;
         char tpat[NPAT+20];

         strcpy(tpat, prompt);        /* copy prompt to output string */
         strcat(tpat, " [");        /* build new prompt string */
         expandp(&apat[0], &tpat[strlen(tpat)], NPAT/2);        /* add old pat
         strcat(tpat, "]<META>: ");

         /* Read a pattern.  Either we get one,
          * or we just get the META charater, and use the previous pattern.
          * Then, if it's the search string, make a reversed pattern.
          * *Then*, make the meta-pattern, if we are defined that way.
          */
         if ((status = mlreplyt(tpat, tpat, NPAT, metac)) == TRUE)
         {
                 strcpy(apat, tpat);
                 if (srch)        /* If we are doing the search string.*/
                 {
                         mlenold = matchlen = strlen(apat);
                         /* Reverse string copy.
                          */
                         rvstrcpy(tap, apat);
 #if        MAGIC
                         /* Only make the meta-pattern if in magic mode,
                          * since the pattern in question might have an
                          * invalid meta combination.
                          */
                         if ((curwp->w_bufp->b_mode & MDMAGIC) == 0)
                                 mcclear();
                         else
                                 status = mcstr();
 #endif
                 }
         }
         else if (status == FALSE && apat[0] != 0)        /* Old one */
                 status = TRUE;

         return(status);
 }

 /*
  * savematch -- We found the pattern?  Let's save it away.
  */

 savematch()
 {
         register char *ptr;        /* ptr into malloced last match string */
         register int j;                /* index */
         LINE *curline;                /* line of last match */
         int curoff;                /* offset "      "    */

         /* free any existing match string */
         if (patmatch != NULL)
                 free(patmatch);

         /* attempt to allocate a new one */
         ptr = patmatch = malloc(matchlen + 1);
         if (ptr == NULL)
                 return;

         /* save the match! */
         curoff = matchoff;
         curline = matchline;

         for (j = 0; j < matchlen; j++)
                 *ptr++ = nextch(&curline, &curoff, FORWARD);

         /* null terminate the match string */
         *ptr = '\0';
 }

 /*
  * rvstrcpy -- Reverse string copy.
  */
 rvstrcpy(rvstr, str)
 register char        *rvstr, *str;
 {
         register int i;

         str += (i = strlen(str));

         while (i-- > 0)
                 *rvstr++ = *--str;

         *rvstr = '\0';
 }

 /*
  * sreplace -- Search and replace.
  */
 sreplace(f, n)

 int f;                /* default flag */
 int n;                /* # of repetitions wanted */

 {
         return(replaces(FALSE, f, n));
 }

 /*
  * qreplace -- search and replace with query.
  */
 qreplace(f, n)
 int f;                /* default flag */
 int n;                /* # of repetitions wanted */
 {
         return(replaces(TRUE, f, n));
 }

 /*
  * replaces -- Search for a string and replace it with another
  *        string.  Query might be enabled (according to kind).
  */
 static int        replaces(kind, f, n)
 int        kind;        /* Query enabled flag */
 int        f;        /* default flag */
 int        n;        /* # of repetitions wanted */
 {
         register int status;        /* success flag on pattern inputs */
         register int rlength;        /* length of replacement string */
         register int numsub;        /* number of substitutions */
         register int nummatch;        /* number of found matches */
         int nlflag;                /* last char of search string a <NL>? */
         int nlrepl;                /* was a replace done on the last line? */
         char c;                        /* input char for query */
         char tpat[NPAT];        /* temporary to hold search pattern */
         LINE *origline;                /* original "." position */
         int origoff;                /* and offset (for . query option) */
         LINE *lastline;                /* position of last replace and */
         int lastoff;                /* offset (for 'u' query option) */

         if (curbp->b_mode & MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *

         /* Check for negative repetitions.
          */
         if (f && n < 0)
                 return(FALSE);

         /* Ask the user for the text of a pattern.
          */
         if ((status = readpattern(
             (kind == FALSE ? "Replace" : "Query replace"), &pat[0], TRUE))
                                                                 != TRUE)
                 return(status);

         /* Ask for the replacement string.
          */
         if ((status = readpattern("with", &rpat[0], FALSE)) == ABORT)
                 return(status);

         /* Find the length of the replacement string.
          */
         rlength = strlen(&rpat[0]);

         /* Set up flags so we can make sure not to do a recursive
          * replace on the last line.
          */
         nlflag = (pat[matchlen - 1] == '\n');
         nlrepl = FALSE;

         if (kind)
         {
                 /* Build query replace question string.
                  */
                 strcpy(tpat, "Replace '");
                 expandp(&pat[0], &tpat[strlen(tpat)], NPAT/3);
                 strcat(tpat, "' with '");
                 expandp(&rpat[0], &tpat[strlen(tpat)], NPAT/3);
                 strcat(tpat, "'? ");

                 /* Initialize last replaced pointers.
                  */
                 lastline = NULL;
                 lastoff = 0;
         }

         /* Save original . position, init the number of matches and
          * substitutions, and scan through the file.
          */
         origline = curwp->w_dotp;
         origoff = curwp->w_doto;
         numsub = 0;
         nummatch = 0;

         while ( (f == FALSE || n > nummatch) &&
                 (nlflag == FALSE || nlrepl == FALSE) )
         {
                 /* Search for the pattern.
                  * If we search with a regular expression,
                  * matchlen is reset to the true length of
                  * the matched string.
                  */
 #if        MAGIC
                 if ((magical && curwp->w_bufp->b_mode & MDMAGIC) != 0)
                 {
                         if (!mcscanner(&mcpat[0], FORWARD, PTBEG))
                                 break;
                 }
                 else
 #endif
                         if (!scanner(&pat[0], FORWARD, PTBEG))
                                 break;                /* all done */

                 ++nummatch;        /* Increment # of matches */

                 /* Check if we are on the last line.
                  */
                 nlrepl = (lforw(curwp->w_dotp) == curwp->w_bufp->b_linep);

                 /* Check for query.
                  */
                 if (kind)
                 {
                         /* Get the query.
                          */
 pprompt:                mlwrite(&tpat[0], &pat[0], &rpat[0]);
 qprompt:
                         update(TRUE);  /* show the proposed place to change *
                         c = tgetc();                        /* and input */
                         mlwrite("");                        /* and clear it *

                         /* And respond appropriately.
                          */
                         switch (c)
                         {
                                 case 'y':        /* yes, substitute */
                                 case ' ':
                                         savematch();
                                         break;

                                 case 'n':        /* no, onword */
                                         forwchar(FALSE, 1);
                                         continue;

                                 case '!':        /* yes/stop asking */
                                         kind = FALSE;
                                         break;

                                 case 'u':        /* undo last and re-prompt *

                                         /* Restore old position.
                                          */
                                         if (lastline == NULL)
                                         {
                                                 /* There is nothing to undo.
                                                  */
                                                 TTbeep();
                                                 goto pprompt;
                                         }
                                         curwp->w_dotp = lastline;
                                         curwp->w_doto = lastoff;
                                         lastline = NULL;
                                         lastoff = 0;

                                         /* Delete the new string.
                                          */
                                         backchar(FALSE, rlength);
                                         status = delins(rlength, patmatch);
                                         if (status != TRUE)
                                                 return (status);

                                         /* Record one less substitution,
                                          * backup, and reprompt.
                                          */
                                         --numsub;
                                         backchar(FALSE, mlenold);
                                         matchline = curwp->w_dotp;
                                         matchoff  = curwp->w_doto;
                                         goto pprompt;

                                 case '.':        /* abort! and return */
                                         /* restore old position */
                                         curwp->w_dotp = origline;
                                         curwp->w_doto = origoff;
                                         curwp->w_flag |= WFMOVE;

                                 case BELL:        /* abort! and stay */
                                         mlwrite("Aborted!");
                                         return(FALSE);

                                 default:        /* bitch and beep */
                                         TTbeep();

                                 case '?':        /* help me */
                                         mlwrite(
 "(Y)es, (N)o, (!)Do rest, (U)ndo last, (^G)Abort, (.)Abort back, (?)Help: ");
                                         goto qprompt;

                         }        /* end of switch */
                 }        /* end of "if kind" */

                 /*
                  * Delete the sucker, and insert its
                  * replacement.
                  */
                 status = delins(matchlen, &rpat[0]);
                 if (status != TRUE)
                         return (status);

                 /* Save where we are if we might undo this....
                  */
                 if (kind)
                 {
                         lastline = curwp->w_dotp;
                         lastoff = curwp->w_doto;
                 }

                 numsub++;        /* increment # of substitutions */
         }

         /* And report the results.
          */
         mlwrite("%d substitutions", numsub);
         return(TRUE);
 }

 /*
  * delins -- Delete a specified length from the current
  *        point, then insert the string.
  */
 delins(dlength, instr)
 int        dlength;
 char        *instr;
 {
         int        status;
         char        tmpc;

         /* Zap what we gotta,
          * and insert its replacement.
          */
         if (!(status = ldelete((long) dlength, FALSE)))
         {
                 mlwrite("%%ERROR while deleting");
                 return(FALSE);
         }
         else
                 while (tmpc = *instr)
                 {
                         status = (tmpc == '\n'? lnewline(): linsert(1, tmpc))

                         /* Insertion error?
                          */
                         if (!status)
                         {
                                 mlwrite("%%Out of memory while inserting");
                                 break;
                         }
                         instr++;
                 }
         return (status);
 }

 /*
  * expandp -- Expand control key sequences for output.
  */
 expandp(srcstr, deststr, maxlength)
 char *srcstr;        /* string to expand */
 char *deststr;        /* destination of expanded string */
 int maxlength;        /* maximum chars in destination */
 {
         unsigned char c;        /* current char to translate */

         /* Scan through the string.
          */
         while ((c = *srcstr++) != 0)
         {
                 if (c == '\n')                /* it's a newline */
                 {
                         *deststr++ = '<';
                         *deststr++ = 'N';
                         *deststr++ = 'L';
                         *deststr++ = '>';
                         maxlength -= 4;
                 }
                 else if (c < 0x20 || c == 0x7f)        /* control character *
                 {
                         *deststr++ = '^';
                         *deststr++ = c ^ 0x40;
                         maxlength -= 2;
                 }
                 else if (c == '%')
                 {
                         *deststr++ = '%';
                         *deststr++ = '%';
                         maxlength -= 2;
                 }
                 else                        /* any other character */
                 {
                         *deststr++ = c;
                         maxlength--;
                 }

                 /* check for maxlength */
                 if (maxlength < 4)
                 {
                         *deststr++ = '$';
                         *deststr = '\0';
                         return(FALSE);
                 }
         }
         *deststr = '\0';
         return(TRUE);
 }

 /*
  * boundry -- Return information depending on whether we may search no
  *        further.  Beginning of file and end of file are the obvious
  *        cases, but we may want to add further optional boundry restrictions
  *        in future, a' la VMS EDT.  At the moment, just return TRUE or
  *        FALSE depending on if a boundry is hit (ouch).
  */
 int        boundry(curline, curoff, dir)
 LINE        *curline;
 int        curoff, dir;
 {
         register int        border;

         if (dir == FORWARD)
         {
                 border = (curoff == llength(curline)) &&
                          (lforw(curline) == curbp->b_linep);
         }
         else
         {
                 border = (curoff == 0) &&
                          (lback(curline) == curbp->b_linep);
         }
         return (border);
 }

 /*
  * nextch -- retrieve the next/previous character in the buffer,
  *        and advance/retreat the point.
  *        The order in which this is done is significant, and depends
  *        upon the direction of the search.  Forward searches look at
  *        the current character and move, reverse searches move and
  *        look at the character.
  */
 static int nextch(pcurline, pcuroff, dir)
 LINE        **pcurline;
 int        *pcuroff;
 int        dir;
 {
         register LINE        *curline;
         register int        curoff;
         register int        c;

         curline = *pcurline;
         curoff = *pcuroff;

         if (dir == FORWARD)
         {
                 if (curoff == llength(curline))                /* if at EOL *
                 {
                         curline = lforw(curline);        /* skip to next line
                         curoff = 0;
                         c = '\n';                        /* and return a <NL>
                 }
                 else
                         c = lgetc(curline, curoff++);        /* get the char
         }
         else                        /* Reverse.*/
         {
                 if (curoff == 0)
                 {
                         curline = lback(curline);
                         curoff = llength(curline);
                         c = '\n';
                 }
                 else
                         c = lgetc(curline, --curoff);

         }
         *pcurline = curline;
         *pcuroff = curoff;

         return (c);
 }

 #if        MAGIC
 /*
  * mcstr -- Set up the 'magic' array.  The closure symbol is taken as
  *        a literal character when (1) it is the first character in the
  *        pattern, and (2) when preceded by a symbol that does not allow
  *        closure, such as a newline, beginning of line symbol, or another
  *        closure symbol.
  *
  *        Coding comment (jmg):  yes, i know i have gotos that are, strictly
  *        speaking, unnecessary.  But right now we are so cramped for
  *        code space that i will grab what i can in order to remain
  *        within the 64K limit.  C compilers actually do very little
  *        in the way of optimizing - they expect you to do that.
  */
 static int mcstr()
 {
         MC        *mcptr, *rtpcm;
         char        *patptr;
          int        mj;
          int        pchr;
          int        status = TRUE;
          int        does_closure = FALSE;

         /* If we had metacharacters in the MC array previously,
          * free up any bitmaps that may have been allocated.
          */
         if (magical)
                 mcclear();

         magical = FALSE;
         mj = 0;
         mcptr = &mcpat[0];
         patptr = &pat[0];

         while ((pchr = *patptr) && status)
         {
                 switch (pchr)
                 {
                         case MC_CCL:
                                 status = cclmake(&patptr, mcptr);
                                 magical = TRUE;
                                 does_closure = TRUE;
                                 break;
                         case MC_BOL:
                                 if (mj != 0)
                                         goto litcase;

                                 mcptr->mc_type = BOL;
                                 magical = TRUE;
                                 does_closure = FALSE;
                                 break;
                         case MC_EOL:
                                 if (*(patptr + 1) != '\0')
                                         goto litcase;

                                 mcptr->mc_type = EOL;
                                 magical = TRUE;
                                 does_closure = FALSE;
                                 break;
                         case MC_ANY:
                                 mcptr->mc_type = ANY;
                                 magical = TRUE;
                                 does_closure = TRUE;
                                 break;
                         case MC_CLOSURE:
                                 /* Does the closure symbol mean closure here?
                                  * If so, back up to the previous element
                                  * and indicate it is enclosed.
                                  */
                                 if (!does_closure)
                                         goto litcase;
                                 mj--;
                                 mcptr--;
                                 mcptr->mc_type |= CLOSURE;
                                 magical = TRUE;
                                 does_closure = FALSE;
                                 break;

                         /* Note: no break between MC_ESC case and the default
                          */
                         case MC_ESC:
                                 if (*(patptr + 1) != '\0')
                                 {
                                         pchr = *++patptr;
                                         magical = TRUE;
                                 }
                         default:
 litcase:                        mcptr->mc_type = LITCHAR;
                                 mcptr->u.lchar = pchr;
                                 does_closure = (pchr != '\n');
                                 break;
                 }                /* End of switch.*/
                 mcptr++;
                 patptr++;
                 mj++;
         }                /* End of while.*/

         /* Close off the meta-string.
          */
         mcptr->mc_type = MCNIL;

         /* Set up the reverse array, if the status is good.  Please note the
          * structure assignment - your compiler may not like that.
          * If the status is not good, nil out the meta-pattern.
          * The only way the status would be bad is from the cclmake()
          * routine, and the bitmap for that member is guarenteed to be
          * freed.  So we stomp a MCNIL value there, and call mcclear()
          * to free any other bitmaps.
          */
         if (status)
         {
                 rtpcm = &tapcm[0];
                 while (--mj >= 0)
                 {
 #if        LATTICE
                         movmem(--mcptr, rtpcm++, sizeof (MC));
 #endif

 #if        MWC86 | AZTEC | MSC | TURBO | VMS | USG | BSD | V7
                         *rtpcm++ = *--mcptr;
 #endif
                 }
                 rtpcm->mc_type = MCNIL;
         }
         else
         {
                 (--mcptr)->mc_type = MCNIL;
                 mcclear();
         }

         return(status);
 }

 /*
  * mcclear -- Free up any CCL bitmaps, and MCNIL the MC arrays.
  */
 mcclear()
 {
         register MC        *mcptr;

         mcptr = &mcpat[0];

         while (mcptr->mc_type != MCNIL)
         {
                 if ((mcptr->mc_type & MASKCL) == CCL ||
                     (mcptr->mc_type & MASKCL) == NCCL)
                         free(mcptr->u.cclmap);
                 mcptr++;
         }
         mcpat[0].mc_type = tapcm[0].mc_type = MCNIL;
 }

 /*
  * mceq -- meta-character equality with a character.  In Kernighan & Plauger'
  *        Software Tools, this is the function omatch(), but i felt there
  *        were too many functions with the 'match' name already.
  */
 static int        mceq(bc, mt)
 int        bc;
 MC        *mt;
 {
         register int result;

         switch (mt->mc_type & MASKCL)
         {
                 case LITCHAR:
                         result = eq(bc, mt->u.lchar);
                         break;

                 case ANY:
                         result = (bc != '\n');
                         break;

                 case CCL:
                         if (!(result = biteq(bc, mt->u.cclmap)))
                         {
                                 if ((curwp->w_bufp->b_mode & MDEXACT) == 0 &&
                                     (isletter(bc)))
                                 {
                                         result = biteq(CHCASE(bc), mt->u.cclm
                                 }
                         }
                         break;

                 case NCCL:
                         result = !biteq(bc, mt->u.cclmap);

                         if ((curwp->w_bufp->b_mode & MDEXACT) == 0 &&
                             (isletter(bc)))
                         {
                                 result &= !biteq(CHCASE(bc), mt->u.cclmap);
                         }
                         break;

                 default:
                         mlwrite("mceq: what is %d?", mt->mc_type);
                         result = FALSE;
                         break;

         }        /* End of switch.*/

         return (result);
 }

 /*
  * cclmake -- create the bitmap for the character class.
  *        ppatptr is left pointing to the end-of-character-class character,
  *        so that a loop may automatically increment with safety.
  */
 static int        cclmake(ppatptr, mcptr)
 char        **ppatptr;
 MC        *mcptr;
 {
         BITMAP                clearbits();
         BITMAP                bmap;
         register char        *patptr;
         register int        pchr, ochr;

         if ((bmap = clearbits()) == NULL)
         {
                 mlwrite("%%Out of memory");
                 return FALSE;
         }

         mcptr->u.cclmap = bmap;
         patptr = *ppatptr;

         /*
          * Test the initial character(s) in ccl for
          * special cases - negate ccl, or an end ccl
          * character as a first character.  Anything
          * else gets set in the bitmap.
          */
         if (*++patptr == MC_NCCL)
         {
                 patptr++;
                 mcptr->mc_type = NCCL;
         }
         else
                 mcptr->mc_type = CCL;

         if ((ochr = *patptr) == MC_ECCL)
         {
                 mlwrite("%%No characters in character class");
                 return (FALSE);
         }
         else
         {
                 if (ochr == MC_ESC)
                         ochr = *++patptr;

                 setbit(ochr, bmap);
                 patptr++;
         }

         while (ochr != '\0' && (pchr = *patptr) != MC_ECCL)
         {
                 switch (pchr)
                 {
                         /* Range character loses its meaning
                          * if it is the last character in
                          * the class.
                          */
                         case MC_RCCL:
                                 if (*(patptr + 1) == MC_ECCL)
                                         setbit(pchr, bmap);
                                 else
                                 {
                                         pchr = *++patptr;
                                         while (++ochr <= pchr)
                                                 setbit(ochr, bmap);
                                 }
                                 break;

                         /* Note: no break between case MC_ESC and the default
                          */
                         case MC_ESC:
                                 pchr = *++patptr;
                         default:
                                 setbit(pchr, bmap);
                                 break;
                 }
                 patptr++;
                 ochr = pchr;
         }

         *ppatptr = patptr;

         if (ochr == '\0')
         {
                 mlwrite("%%Character class not ended");
                 free(bmap);
                 return FALSE;
         }
         return TRUE;
 }

 /*
  * biteq -- is the character in the bitmap?
  */
 static int        biteq(bc, cclmap)
 int        bc;
 BITMAP        cclmap;
 {
         if (bc >= HICHAR)
                 return FALSE;

         return( (*(cclmap + (bc >> 3)) & BIT(bc & 7))? TRUE: FALSE );
 }

 /*
  * clearbits -- Allocate and zero out a CCL bitmap.
  */
 static        BITMAP clearbits()
 {
         char                *malloc();

         BITMAP                cclstart, cclmap;
         register int        j;

         if ((cclmap = cclstart = (BITMAP) malloc(HIBYTE)) != NULL)
                 for (j = 0; j < HIBYTE; j++)
                         *cclmap++ = 0;

         return (cclstart);
 }

 /*
  * setbit -- Set a bit (ON only) in the bitmap.
  */
 static void setbit(bc, cclmap)
 int        bc;
 BITMAP        cclmap;
 {
         if (bc < HICHAR)
                 *(cclmap + (bc >> 3)) |= BIT(bc & 7);
 }
 #endif


 SEARCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SEARCH.C

 /*         int search(int (*dir_procedure)(),int (*file_procedure)(),char *ma
 **
 **                                this procedure will visit every subdirector
 **                                directory where this procedure was called.
 **                                a directory is entered or exited, the proce
 **                                dir_procedure is called.  each directory is
 **                                matching        the mask argument.  everyti
 **                                the mask, the file_procedure pointer is cal
 **
 **                                int (*dir_procedure)(int pass,
 **
 **
 **                                the dir_procedure is called each time a dir
 **                                entered (pass == 1) and after a directory i
 **                                (pass == 2).  dir_procedure is passed two a
 **
 **                                        ARGUMENTS:
 **                                        pass = 1 on first entry to director
 **                                        dir point to directory string.  on
 **                                        current working directory.  on pass
 **                                        directory of the exited string;
 **
 **                                        RETURN:
 **                                        returns of anything other than 0 te
 **                                 return value is returned by search.
 **
 **                                int (*file_procedure)(struct *ffblk);
 **
 **                                the file_procedure pointer argument is exec
 **                                a new file name is encountered in the direc
 **                                files trigger this call (HIDDEN and SYSTEM
 **                                The ffblk structure pointer is passed to th
 **                                so file name and attributes may be tested.
 **
 **                                calls to argument pointers are checked for
 */

 #include <stdio.h>
 #include <alloc.h>
 #include <dir.h>
 #include <dos.h>

 int search(int (*dir_procedure)(),int (*file_procedure)(),char *mask)
 {
         struct ffblk *item;        /* see page 88 of turboc reference guide
         int errcode=0;                        /* error code returned by direc
         int returncode=0;                /* return code from called procedure
         char *dir;                                /* current directory string

         /* item and dir are allocated storage with malloc to minimize
         /* stack ussage durring recusive calls
         if (((item=(struct ffblk *)malloc(sizeof(struct ffblk))) == NULL) ||
                 ((dir=malloc(MAXDRIVE+MAXPATH+MAXFILE))==NULL))
                 perror("Search Procedure");

         getcwd(dir,MAXDRIVE+MAXPATH);

         if(dir_procedure!=NULL)                /* only call procedure if not
                 if((returncode=(*dir_procedure)(1,dir))!=0)
                         return(returncode);

         /*
         /* file loop
         /*

         errcode=findfirst(mask,item,FA_SYSTEM+FA_HIDDEN);
         while(errcode==0  && returncode==0)
                 {
                 if (!(item->ff_attrib & FA_DIREC))
                         if(file_procedure!=NULL)
                                 returncode=(*file_procedure)(item);
                 if (!returncode)
                         {
                         errcode=findnext(item);
                         }
                 }

         /*
         /* directory loop
         /*

         if (!returncode)
                 errcode=findfirst("*.*",item,FA_DIREC+FA_SYSTEM+FA_HIDDEN);
         while(errcode==0 && returncode==0)
                 {
                 if((item->ff_attrib & FA_DIREC) && (item->ff_name[0]!='.'))
                         {
                           chdir(item->ff_name);

                         /* recursive call */
                         returncode=search(dir_procedure,file_procedure,mask);

                         getcwd(dir,MAXDRIVE+MAXPATH);

                           chdir("..");

                         if(dir_procedure!=NULL)
                                 if((returncode=(*dir_procedure)(2,dir))!=0)
                                         return(returncode);

                           }

                 if (!returncode)
                         errcode=findnext(item);
                 }
         free(item);
         free(dir);
         return(returncode);
 }

 /*
 **                to see how this procedure works, add line:         #define
 **                at top of file and compile/link with:
 */

 #ifdef DEBUG

 int dir_print(int *pass, char *dir)
 {
         printf("Directory: %s, pass %1d\n",dir,pass);
         return(0);
 }

 int file_print(struct ffblk *item)
 {
         printf("File: %s\n",item->ff_name);
         return(0);
 }

 main(argc,argv)
 int argc;
 char **argv;
 {
         if (argc==2)
                 search(dir_print,file_print,argv[1]);
         else
                  search(dir_print,file_print,"*.*");
 }
 #endif


 SEARCHKW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\SEARCHKW.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 struct kwblk {
         char            *word;
         int                      stype;
         }       keywords[] = {

         {"int", kw_int}, {"char", kw_char}, {"long", kw_long},
         {"float", kw_float}, {"double", kw_double}, {"return", kw_return},
         {"struct", kw_struct}, {"union", kw_union}, {"typedef", kw_typedef},
         {"enum", kw_enum}, {"static", kw_static}, {"auto", kw_auto},
         {"sizeof", kw_sizeof}, {"do", kw_do}, {"if", kw_if},
         {"else", kw_else}, {"for", kw_for},{"switch", kw_switch},
         {"while", kw_while},{"short", kw_short}, {"extern", kw_extern},
         {"case", kw_case}, {"goto", kw_goto}, {"default", kw_default},
         {"register", kw_register}, {"unsigned", kw_unsigned},
         {"break", kw_break}, {"continue", kw_continue}, {"void", kw_void},
         {0, 0} };

 searchkw()
 {       struct kwblk    *kwbp;
         kwbp = keywords;
         while(kwbp->word != 0) {
                 if(strcmp(lastid,kwbp->word) == 0)
                         return lastst = kwbp->stype;
                 else
                         ++kwbp;
                 }
 }



 SEDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\SEDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==SOUTH_EAST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 SEL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\SEL.C

 /* SDB - select data from the database */

 #include "sdbio.h"

 extern int dbv_token;
 extern char dbv_tstring[];
 extern int dbv_tvalue;

 /* db_select - select a set of tuples from a set of relations */
 struct sel *db_select(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct sel *slptr;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* allocate a sel structure */
     if ((slptr = malloc(sizeof(struct sel))) == NULL)
         return (db_nerror(INSMEM));

     /* initialize the structure */
     slptr->sl_rels = NULL;
     slptr->sl_attrs = NULL;
     slptr->sl_where = NULL;
     slptr->sl_bindings = NULL;

     /* parse the list of selected attributes */
     if (!get_sattrs(slptr)) {
         db_done(slptr);
         return (NULL);
     }

     /* check for "from" clause */
     if (db_token() == FROM) {
         db_ntoken();
         if (!get_srels(slptr)) {
             db_done(slptr);
             return (NULL);
         }
     }
     else {
         if (!srelation(slptr,"sdbcur",NULL)) {
             db_done(slptr);
             return (NULL);
         }
     }

     /* check the list of selected attributes */
     if (!check_attrs(slptr)) {
         db_done(slptr);
         return (NULL);
     }

     /* check for the existance of a "where" clause */
     if (db_token() == WHERE) {
         db_ntoken();

         /* parse the boolean expression */
         if (!db_compile(slptr)) {
             db_done(slptr);
             return (FALSE);
         }
     }

     /* return the new selection structure */
     return (slptr);
 }

 /* db_retrieve - retrieve a set of tuples from a set of relations */
 struct sel *db_retrieve(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct sel *slptr;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* allocate a sel structure */
     if ((slptr = malloc(sizeof(struct sel))) == NULL)
         return (db_nerror(INSMEM));

     /* initialize the structure */
     slptr->sl_rels = NULL;
     slptr->sl_attrs = NULL;
     slptr->sl_where = NULL;
     slptr->sl_bindings = NULL;

     /* check for selected relations clause */
     if (db_token() == ID) {
         if (!get_srels(slptr)) {
             db_done(slptr);
             return (NULL);
         }
     }
     else {
         if (!srelation(slptr,"sdbcur",NULL)) {
             db_done(slptr);
             return (NULL);
         }
     }

     /* check the list of selected attributes */
     if (!check_attrs(slptr)) {
         db_done(slptr);
         return (NULL);
     }

     /* check for the existance of a "where" clause */
     if (db_token() == WHERE) {
         db_ntoken();

         /* parse the boolean expression */
         if (!db_compile(slptr)) {
             db_done(slptr);
             return (FALSE);
         }
     }

     /* return the new selection structure */
     return (slptr);
 }

 /* db_done(slptr) - finish a selection */
 db_done(slptr)
   struct sel *slptr;
 {
     struct sattr *saptr,*nxtsa;
     struct srel *srptr,*nxtsr;
     struct binding *bdptr,*nxtbd;

     /* free the selected attribute blocks */
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = nxtsa) {
         nxtsa = saptr->sa_next;
         if (saptr->sa_rname != NULL)
             free(saptr->sa_rname);
         free(saptr->sa_aname);
         if (saptr->sa_name != NULL)
             free(saptr->sa_name);
         free(saptr);
     }

     /* close the scans and free the selected relation blocks */
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = nxtsr) {
         nxtsr = srptr->sr_next;
         if (srptr->sr_name != NULL)
             free(srptr->sr_name);
         db_rclose(srptr->sr_scan);
         free(srptr);
     }

     /* free the where clause */
     db_fcode(slptr);

     /* free the user bindings */
     for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = nxtbd) {
         nxtbd = bdptr->bd_next;
         free(bdptr);
     }

     /* free the selection structure */
     free(slptr);
 }

 /* db_fetch(slptr) - fetch the next tuple from a selection */
 int db_fetch(slptr)
   struct sel *slptr;
 {
     struct srel *srptr;
     struct binding *bdptr;

     /* clear the update flags */
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
         srptr->sr_update = FALSE;

     /* find a matching tuple */
     while (process(slptr->sl_rels))
         if (db_interpret(slptr)) {
             for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = bdptr->bd
                 db_aget(bdptr->bd_attr,bdptr->bd_vtuple,bdptr->bd_vuser);
             return (TRUE);
         }

     /* no matches, failure return */
     return (FALSE);
 }

 /* db_update - update modified tuples */
 int db_update(slptr)
   struct sel *slptr;
 {
     struct srel *srptr;

     /* check each selected relation for updates */
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
         if (srptr->sr_update)
             if (!db_rupdate(srptr->sr_scan))
                 return (FALSE);

     /* return successfully */
     return (TRUE);
 }

 /* db_store - store tuples */
 int db_store(slptr)
   struct sel *slptr;
 {
     struct srel *srptr;

     /* check each selected relation for stores */
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
         if (srptr->sr_update)
             if (!db_rstore(srptr->sr_scan))
                 return (FALSE);

     /* return successfully */
     return (TRUE);
 }

 /* db_bind - bind a user buffer to the value of an attribute */
 int db_bind(slptr,rname,aname,avalue)
   struct sel *slptr; char *rname,*aname,*avalue;
 {
     struct binding *newbd;
     struct srel *srptr;

     /* allocate and initialize a binding structure */
     if ((newbd = malloc(sizeof(struct binding))) == NULL)
         return (db_ferror(INSMEM));
     newbd->bd_vuser = avalue;

     /* find the attribute */
     if (!find_attr(slptr,rname,aname,&newbd->bd_vtuple,&srptr,&newbd->bd_attr
         return (FALSE);

     /* link the new binding into the binding list */
     newbd->bd_next = slptr->sl_bindings;
     slptr->sl_bindings = newbd;

     /* return successfully */
     return (TRUE);
 }

 /* db_get - get the value of an attribute */
 int db_get(slptr,rname,aname,avalue)
   struct sel *slptr; char *rname,*aname,*avalue;
 {
     struct srel *srptr;
     struct attribute *aptr;
     char *vptr;

     /* find the attribute */
     if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
         return (FALSE);

     /* get the attribute value */
     db_aget(aptr,vptr,avalue);

     /* return successfully */
     return (TRUE);
 }

 /* db_put - put the value of an attribute */
 int db_put(slptr,rname,aname,avalue)
   struct sel *slptr; char *rname,*aname,*avalue;
 {
     struct srel *srptr;
     struct attribute *aptr;
     char *vptr;

     /* find the attribute */
     if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
         return (FALSE);

     /* put the attribute value */
     db_aput(aptr,vptr,avalue);

     /* mark the tuple as updated */
     srptr->sr_update = TRUE;

     /* return successfully */
     return (TRUE);
 }

 /* db_sattr - get selected attribute type, pointer, and length */
 int db_sattr(slptr,rname,aname,ptype,pptr,plen)
   struct sel *slptr; char *rname,*aname;
   int *ptype; char **pptr; int *plen;
 {
     struct srel *srptr;
     struct attribute *aptr;

     if (!find_attr(slptr,rname,aname,pptr,&srptr,&aptr))
         return (FALSE);
     *ptype = aptr->at_type;
     *plen = aptr->at_size;
     return (TRUE);
 }

 /* get_sattrs(slptr) - get selected attributes */
 static get_sattrs(slptr)
   struct sel *slptr;
 {
     struct sattr *newsattr,*lastsattr;

     /* check for "*" or blank field meaning all attributes are selected */
     if (db_token() == '*') {
         db_ntoken();
         return (TRUE);
     }
     else if (db_token() != ID)
         return (TRUE);

     /* parse a list of attribute names */
     lastsattr = NULL;
     while (TRUE) {

         /* get attribute name */
         if (db_ntoken() != ID)
             return (db_ferror(SYNTAX));

         /* allocate a selected attribute structure */
         if ((newsattr = malloc(sizeof(struct sattr))) == NULL)
             return (db_ferror(INSMEM));

         /* initialize the selected attribute structure */
         newsattr->sa_next = NULL;

         /* save the attribute name */
         if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) {
             free(newsattr);
             return (db_ferror(INSMEM));
         }
         strcpy(newsattr->sa_aname,dbv_tstring);

         /* check for "." meaning "<rel-name>.<att-name>" */
         if (db_token() == '.') {
             db_ntoken();

             /* the previous ID was really the relation name */
             newsattr->sa_rname = newsattr->sa_aname;

             /* check for attribute name */
             if (db_ntoken() != ID) {
                 free(newsattr->sa_aname); free(newsattr);
                 return (db_ferror(SYNTAX));
             }

             /* save the attribute name */
             if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL)
                 free(newsattr->sa_aname); free(newsattr);
                 return (db_ferror(INSMEM));
             }
             strcpy(newsattr->sa_aname,dbv_tstring);
         }
         else
             newsattr->sa_rname = NULL;

         /* check for alternate attribute name */
         if (db_token() == ID) {
             db_ntoken();

             /* allocate space for the alternate name */
             if ((newsattr->sa_name = malloc(strlen(dbv_tstring)+1)) == NULL)
                 if (newsattr->sa_rname != NULL)
                     free(newsattr->sa_rname);
                 free(newsattr->sa_aname);
                 free(newsattr);
                 return (db_ferror(INSMEM));
             }
             strcpy(newsattr->sa_name,dbv_tstring);
         }
         else
             newsattr->sa_name = NULL;

         /* link the selected attribute structure into the list */
         if (lastsattr == NULL)
             slptr->sl_attrs = newsattr;
         else
             lastsattr->sa_next = newsattr;
         lastsattr = newsattr;

         /* check for more attributes */
         if (db_token() != ',')
             break;
         db_ntoken();
     }

     /* return successfully */
     return (TRUE);
 }

 /* get_srels(slptr) - get selected relations */
 static get_srels(slptr)
   struct sel *slptr;
 {
     char rname[KEYWORDMAX+1],*aname;

     /* get the list of selected relations */
     while (TRUE) {

         /* check for relation name */
         if (db_ntoken() != ID)
             return (db_ferror(SYNTAX));
         strcpy(rname,dbv_tstring);

         /* check for alternate relation name */
         if (db_token() == ID) {
             db_ntoken();
             aname = dbv_tstring;
         }
         else
             aname = NULL;

         /* add the relation name to the list */
         if (!srelation(slptr,rname,aname))
             return (FALSE);

         /* check for more selected relations */
         if (db_token() != ',')
             break;
         db_ntoken();
     }

     /* return successfully */
     return (TRUE);
 }

 /* srelation - select a relation */
 static srelation(slptr,rname,aname)
   struct sel *slptr; char *rname,*aname;
 {
     struct srel *srptr,*newsrel;

     /* allocate a new selected relation structure */
     if ((newsrel = malloc(sizeof(struct srel))) == NULL)
         return (db_ferror(INSMEM));

     /* initialize the new selected relation structure */
     newsrel->sr_ctuple = FALSE;
     newsrel->sr_update = FALSE;
     newsrel->sr_next = NULL;

     /* open the relation */
     if ((newsrel->sr_scan = db_ropen(rname)) == NULL) {
         free(newsrel);
         return (FALSE);
     }

     /* check for alternate relation name */
     if (aname != NULL) {

         /* allocate space for the alternate name */
         if ((newsrel->sr_name = malloc(strlen(aname)+1)) == NULL) {
             free(newsrel);
             return (db_ferror(INSMEM));
         }
         strcpy(newsrel->sr_name,aname);
     }
     else
         newsrel->sr_name = NULL;

     /* find the end of the list of relation names */
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
         if (srptr->sr_next == NULL)
             break;

     /* link the new selected relation structure into the list */
     if (srptr == NULL)
         slptr->sl_rels = newsrel;
     else
         srptr->sr_next = newsrel;

     /* return successfully */
     return (TRUE);
 }

 /* check_attrs(slptr) - check the list of selected attributes */
 static int check_attrs(slptr)
   struct sel *slptr;
 {
     struct sattr *saptr;

     /* check for all attributes selected */
     if (slptr->sl_attrs == NULL)
         return (all_attrs(slptr));

     /* check each selected attribute */
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
         if (!find_attr(slptr,saptr->sa_rname,saptr->sa_aname,
                         &saptr->sa_aptr,&saptr->sa_srel,&saptr->sa_attr))
             return (FALSE);

     /* return successfully */
     return (TRUE);
 }

 /* all_attrs(slptr) - create a list of all attributes */
 static int all_attrs(slptr)
   struct sel *slptr;
 {
     struct sattr *newsattr,*lastsattr;
     struct srel *srptr;
     struct attribute *aptr;
     int i,astart;

     /* loop through each selected relation */
     lastsattr = NULL;
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {

         /* loop through each attribute within the relation */
         astart = 1;
         for (i = 0; i < NATTRS; i++) {

             /* get a pointer to the current attribute */
             aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];

             /* check for last attribute */
             if (aptr->at_name[0] == 0)
                 break;

             /* allocate a new selected attribute structure */
             if ((newsattr = malloc(sizeof(struct sattr))) == NULL)
                 return (db_ferror(INSMEM));

             /* initialize the new selected attribute structure */
             newsattr->sa_name = NULL;
             newsattr->sa_srel = srptr;
             newsattr->sa_aptr = srptr->sr_scan->sc_tuple + astart;
             newsattr->sa_attr = aptr;
             newsattr->sa_next = NULL;

             /* save the relation name */
             if ((newsattr->sa_rname = malloc(RNSIZE+1)) == NULL) {
                 free(newsattr);
                 return (db_ferror(INSMEM));
             }
             stccpy(newsattr->sa_rname,
                     srptr->sr_scan->sc_relation->rl_name,
                     RNSIZE);
             newsattr->sa_rname[RNSIZE] = 0;

             /* save the attribute name */
             if ((newsattr->sa_aname = malloc(ANSIZE+1)) == NULL) {
                 free(newsattr->sa_rname);
                 free(newsattr);
                 return (db_ferror(INSMEM));
             }
             stccpy(newsattr->sa_aname,
                     srptr->sr_scan->sc_relation->rl_header.hd_attrs[i].at_nam
                     ANSIZE);
             newsattr->sa_aname[ANSIZE] = 0;

             /* link the selected attribute into the list */
             if (lastsattr == NULL)
                 slptr->sl_attrs = newsattr;
             else
                 lastsattr->sa_next = newsattr;
             lastsattr = newsattr;

             /* update the attribute start */
             astart += aptr->at_size;
         }
     }

     /* return successfully */
     return (TRUE);
 }

 /* find_attr - find a named attribute */
 static int find_attr(slptr,rname,aname,paptr,psrel,pattr)
   struct sel *slptr; char *rname,*aname;
   char **paptr; struct attribute **pattr;
 {
     /* check for unqualified or qualified attribute names */
     if (rname == NULL)
         return (uattr(slptr,aname,paptr,psrel,pattr));
     else
         return (qattr(slptr,rname,aname,paptr,psrel,pattr));
 }

 /* uattr - find an unqualified attribute name */
 static int uattr(slptr,aname,paptr,psrel,pattr)
   struct sel *slptr; char *aname;
   char **paptr; struct srel **psrel; struct attribute **pattr;
 {
     struct srel *srptr;
     struct attribute *aptr;
     int i,astart;

     /* loop through each selected relation */
     *pattr = NULL;
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {

         /* loop through each attribute within the relation */
         astart = 1;
         for (i = 0; i < NATTRS; i++) {

             /* get a pointer to the current attribute */
             aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];

             /* check for last attribute */
             if (aptr->at_name[0] == 0)
                 break;

             /* check for attribute name match */
             if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
                 if (*pattr != NULL)
                     return (db_ferror(ATAMBG));
                 *paptr = srptr->sr_scan->sc_tuple + astart;
                 *psrel = srptr;
                 *pattr = aptr;
             }

             /* update the attribute start */
             astart += aptr->at_size;
         }
     }

     /* check whether attribute was found */
     if (*pattr == NULL)
         return (db_ferror(ATUNDF));

     /* return successfully */
     return (TRUE);
 }

 /* qattr - find a qualified attribute name */
 static int qattr(slptr,rname,aname,paptr,psrel,pattr)
   struct sel *slptr; char *rname,*aname;
   char **paptr; struct srel **psrel; struct attribute **pattr;
 {
     struct srel *srptr;
     struct attribute *aptr;
     char *crname;
     int i,astart;

     /* loop through each selected relation */
     for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {

         /* get relation name */
         if ((crname = srptr->sr_name) == NULL)
             crname = srptr->sr_scan->sc_relation->rl_name;

         /* check for relation name match */
         if (db_sncmp(rname,crname,RNSIZE) == 0) {

             /* loop through each attribute within the relation */
             astart = 1;
             for (i = 0; i < NATTRS; i++) {

                 /* get a pointer to the current attribute */
                 aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];

                 /* check for last attribute */
                 if (aptr->at_name[0] == 0)
                     break;

                 /* check for attribute name match */
                 if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
                     *paptr = srptr->sr_scan->sc_tuple + astart;
                     *psrel = srptr;
                     *pattr = aptr;
                     return (TRUE);
                 }

                 /* update the attribute start */
                 astart += aptr->at_size;
             }

             /* attribute name not found */
             return (db_ferror(ATUNDF));
         }
     }

     /* relation name not found */
     return (db_ferror(RLUNDF));
 }

 /* process(srptr) - process each tuple in a relation cross-product */
 static int process(srptr)
   struct srel *srptr;
 {
     /* always get a new tuple if this is the last relation in the list */
     if (srptr->sr_next == NULL) {

         /* check for beginning of new scan */
         if (!srptr->sr_ctuple)
             db_rbegin(srptr->sr_scan);

         /* return the next tuple in the relation */
         return (srptr->sr_ctuple = db_rfetch(srptr->sr_scan));
     }

     /* check for beginning of new scan */
     if (!srptr->sr_ctuple) {
         db_rbegin(srptr->sr_scan);

         /* get the first tuple */
         if (!db_rfetch(srptr->sr_scan))
             return (FALSE);
     }

     /* look for a match with the remaining relations in list */
     while (!process(srptr->sr_next))

         /* get the next tuple in the scan */
         if (!db_rfetch(srptr->sr_scan))
             return (srptr->sr_ctuple = FALSE);

     /* found a match at this level */
     return (srptr->sr_ctuple = TRUE);
 }

 /* db_aget - get the value of an attribute */
 db_aget(aptr,vptr,avalue)
   struct attribute *aptr; char *vptr,*avalue;
 {
     int i;

     /* get the attribute value */
     for (i = 0; i < aptr->at_size; i++)
         *avalue++ = vptr[i];
     *avalue = EOS;
 }

 /* db_aput - put the value of an attribute */
 db_aput(aptr,vptr,avalue)
   struct attribute *aptr; char *vptr,*avalue;
 {
     int i;

     /* initialize counter */
     i = 0;

     /* right justify numbers */
     if (aptr->at_type == TNUM)
         for (; i < aptr->at_size - strlen(avalue); i++)
             vptr[i] = ' ';

     /* put the attribute value */
     for (; i < aptr->at_size; i++)
         if (*avalue == 0)
             vptr[i] = 0;
         else
             vptr[i] = *avalue++;
 }



 SER1200.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\SER1200.C

 /* SER1200.C - From page 495 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. This program modifies the pro-    */
 /* gram SER300.C to communicate with the serial port at 1200 b. */
 /****************************************************************/

 "dos.h"           /*for union REGS*/
 COM 1              /*serial port no. 0 = COM1, 1 = COM2*/
 CONF 0x83          /*1200bpi, no par, 1 stop, 8 bits*/
 RS232 0x14         /*RS-232 serial port int number*/
 DATAR 0x100        /*data ready bit in status word*/
 #define TRUE 1
 #define FALSE 0
 VIDEO 0x10         /*ROM BIOS video int number*/
 union REGS inregs, outregs;   /*for ROM BIOS calls*/
 int far *fptr;
 int row, col;

 main()
 {
 char ch, receive();
 int j;
 init();
 clscr();                /*clear screen for putscr()*/

    while(TRUE)  {
       if(kbhit())  {    /*if key pressed*/
          ch = getch();
          send(ch);            /*send char to serial port*/
       }
       if(ready())  {          /*if serial port ready*/
          ch = receive();      /*get char*/
          putscr(ch);
       }
    }
 }

 /* clscr() */     /*clear the screen*/
 clscr()
 {
 int addr;

    fptr = (int far *) 0xB0000000;
    for(addr = 0; addr < 2000; addr++)
       *(fptr + addr) = 0x0700;
    row = 0; col = 0;          /*initialize for putscr()*/
    inregs.h.ah = 2;           /*'set cursor position' service*/
    inregs.h.dh = row;
    inregs.h.dl = col;
    inregs.h.bh = 0;           /*page number*/
    int86(VIDEO, &inregs, &outregs);
 }

 /* putscr() */    /* puts char on screen at row, col */
 putscr(ch)
 char ch;
 {
 int j;

    switch(ch)  {
       case(0x0A):             /*if return*/
          col = 0;             /*start at beginning of line*/
          break;
       case(0x0D):             /*if linefeed*/
          ++row;               /*go to next row*/
          break;
       case(0x08):             /*if backspace*/
          if(col > 0)
             --col;            /*backspace cursor*/
          *(fptr + col + row*80) = 0x0700;  /*print space*/
          break;
       default:
          *(fptr + col + row*80) = (int)ch | 0x0700;
          ++col;               /*display & go to next col*/
    }
    if(col >= 80)  {           /*if past end of row*/
       col = 0;                /*do carriage return and*/
       ++row;                  /*linefeed*/
    }
    if(row >= 25)              /*if below bottom row*/
       row = 0;                /*start at top*/
    if(col == 0)               /*if at beginning of line*/
       for(j = 0; j < 80; j++)    /*clear line*/
          *(fptr + j + row*80) = 0x0700;
    inregs.h.ah = 2;           /* 'set cursor position' service*/
    inregs.h.dh = row;
    inregs.h.dl = col;
    inregs.h.bh = 0;           /*page number*/
    int86(VIDEO, &inregs, &outregs);
 }

 /* init() */      /* initialize serial port */
 init(conf)
 char conf;        /*addr of configuration code*/
 {
    inregs.h.ah = 0;        /* 'initialize port' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = CONF;     /*configuration*/
    int86(RS232, &inregs, &outregs);
 }

 /* send() */      /* send char to serial port */
 send(c)
 char c;
 {
    inregs.h.ah = 1;        /* 'send char' service */
    inregs.x.dx = COM;      /*port number*/
    inregs.h.al = c;        /*character*/
    int86(RS232, &inregs, &outregs);
 }

 /* ready */    /* get serial port ready status */
 ready()
 {
    inregs.h.ah = 3;        /* 'get status' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.x.ax & DATAR);    /*return 'data ready' status*/
 }

 /* receive */     /* get character from serial port */
 char receive()
 {
    inregs.h.ah = 2;        /* 'receive char' service */
    inregs.x.dx = COM;      /*port number*/
    int86(RS232, &inregs, &outregs);
    return(outregs.h.al & 0x7F);     /*return character*/
                                     /* (AND off 8th bit*/
 }



 SER300.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\SER300.C

 /* SER300.C - From page 485 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. This program is a simple prog-    */
 /* ram that communicates with a serial port and needs a Hayes   */
 /* compatible modem as the program is written.                  */
 /****************************************************************/

 "dos.h"              /*For ROM BIOS calls*/
 COM 1                 /*Serial port (0 = COM1, 1 = COM2)*/
 CONF 0x43             /*300 baud, no par, 1 stop, 8 bits*/
 DATAR 0x100           /*data-ready bit in status word*/
 #define TRUE 1

 main()
 {
 union REGS inregs, outregs;
 char ch;

    inregs.h.ah = 0;           /*initialize port service*/
    inregs.x.dx = COM;         /*port number*/
    inregs.h.al = CONF;        /*configuration*/
    int86(0x14, &inregs, &outregs);  /*serial port interrupt*/
    printf("\n\nPort status after initialization: 0x%x.\n\n", outregs.x.ax);
    while(TRUE)  {
       if(kbhit())  {          /*if key pressed*/
          ch = getch();        /*get char from keyboard*/
          inregs.h.ah = 1;     /*'sent char' service*/
          inregs.x.dx = COM;   /*port number*/
          inregs.h.al = ch;    /*character*/
          int86(0x14, &inregs, &outregs);
       }
       inregs.h.ah = 3;        /*'get port status' service*/
       inregs.x.dx = COM;      /* port number*/
       int86(0x14, &inregs, &outregs);
       if(outregs.x.ax & DATAR)  {      /*data ready ? */
          inregs.h.ah = 2;     /*'receive char' service*/
          inregs.x.dx = COM;   /*port number*/
          int86(0x14, &inregs, &outregs);
          ch = outregs.h.al & 0x7F;     /*get char*/
          putch(ch);                    /*display char*/
       }                    /*end if*/
    }                       /*end while*/
 }



 SETBUF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SETBUF.C

 /* 1.2  05-08-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /************************************************************************/
         VOID
 setbuf(fp, buffer)        /* If a buffer is assigned to FILE fp, liberate
                            it.  Assign buffer (assumed BUFSIZ bytes) if
                            not NULL; otherwise, assign the 1-byte buffer. */
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 BUFFER buffer;
 {
         if (fp->_buff AND fp->_flags & _ALLBUF)
                 liberate(fp->_buff, fp->_buflen);
         if (buffer)
         {        fp->_buff = buffer;
                 fp->_buflen = BUFSIZ;
         }
         else
         {        fp->_buff = &fp->_bytbuf;
                 fp->_buflen = 1;
         }
 }


 SETBUF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SETBUF.C

 #include <stdio.h>
 #include <io.h>

 void setbuf(fp, buf)
 register FILE *fp;
 char *buf;
 /*
  *        If <buf> is NULL, make <fp> unbuffered, else <buf> points to a buff
  *        of BUFSIZ characters to be used as the stream buffer for <fp>.
  */
 {
         fp->F_cnt = 0;
         fp->F_unc1 = '\0';
         fp->F_unc2 = '\0';
         fp->F_bp = buf;
         if(fp->F_buf = buf) {
                 fp->F_stat |= F_BUFFER;
                 fp->F_bsiz = BUFSIZ;
         }
         else {
                 fp->F_stat &= ~F_BUFFER;
                 fp->F_bsiz = 0;
         }
 }


 SETCUR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\SETCUR.C

 /* SETCUR.C - From page 326 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. This program will set the cursor  */
 /* size from smaller than normal to a size filling the entire   */
 /* character block using ROM BIOS call 0x10 function 01. To     */
 /* use:  A>setcur xx yy where xx and yy are each numbers from   */
 /* 0 - 13. To get a normal cursor use: A>setcur 12 13           */
 /* By making the first number larger than the second you will   */
 /* get a two part cursor.                                       */
 /****************************************************************/

 "dos.h"        /*declares REGS*/
 CURSIZE 1       /* "set cursor size service" of int 0x10*/
 VIDEO 0x10      /*video BIOS interrupt number*/

 main(argc, argv)
 int argc;
 char *argv[];
 {
 union REGS regs;
 int start, end;

    if (argc != 3) {
       printf("\nExample usage: A>setcur 12 13   (gives normal cursor)");
       exit();
    }
    start = atoi(argv[1]);
    end = atoi(argv[2]);
    regs.h.ch = (char)start;      /*starting scan line number*/
    regs.h.cl = (char)end;        /*ending scan line number*/
    regs.h.ah = CURSIZE;          /*service number of int 0x10*/
    int86(VIDEO, &regs, &regs);   /*call video interrupt*/
 }




 SETHAYES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\SETHAYES.C

 /***********************************************************************
  *  This is to serve as an example of how to initialize a Hayes Smart- *
  *  modem out of Lattice C.  It initialize the baud  rate divisors  at *
  *  baud, sets the parametes at 8 data bits, no parity, and 1 stop bit *
  *  You can replace the pointer *mdmstg to the command values that you *
  *  want to set the Hayes to.                                          *
  *               Program By:                                               *
  *                           Lynn Long                                 *
  *                           Tulsa IBBS C-SIG                          *
  *                           300/450/1200, XMODEM, 24 hours            *
  *                           Registration Required                     *
  ***********************************************************************/
  /*    for comm port # 1.  i will make this into a function as soon as  *
   *    i have time and pass the comm port, baud rate and setup string   *
   *    to it.         Lynn Long   */


 main()
 {


         unsigned byte=0x00;
         char *mdmstg =        "ATE0X1V1Q0M0ST=45S2=255S0=1\r";

         outp(0x3fb,0x80);         /* to access baud rate divisors */
         outp(0x3f8,0x60);         /* set baud        rate divisor lsb for 120
         outp(0x3f9,0x00);         /* set baud        rate divisor msb for 120
         outp(0x3fb,0x23);         /* set line        control        reg for
         outp(0x3fc,0x03);         /* force dtr and cs        signals        o
         outp(0x3f9,0x00);         /* disable interrupts */

         while(*mdmstg != '\0'){
                 byte = inp(0x3fd);                    /* input line        st
                 byte &= 0x20;                   /* look at transmit        ho
                 if(byte == 0x20){
                         outp(0x3f8,*mdmstg);        /* if transmit hold reg
                         *mdmstg++;                /* output a byte        and
                 }
         }

 }




 SETPRTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\SETPRTR.C

 /* --------------------------------------------------------------------- */
 /*        SETPRTR - Send printer setup codes to the IBM (MX-80) printer
 /*           Written for public domain distribution in
 /*           Caprock Systems Small-c:pc
 /*           by        Michael Burton
 /*                320 Highland Dr. Apt 203                                 */
 /*                Glen Burnie, MD  21061
 /*                (301)768-8358
 /*                                                                         */
 /*        Version 1.0        09 May 1983
 /* --------------------------------------------------------------------- */

 CMPRSON         15        /* Compress code                         */
 CMPRSOFF        146        /* Uncompress code                         */
 DSOFF                200        /* Double strike off code                 */
 ESC                27        /* Escape code                                 *
 CR                13        /* Carriage return                         */
 LF                10        /* Linefeed                                 */
 BS                08        /* Backspace                                 */
 #define TRUE                01

 int cmd;

 /* Beginning of SETPRTR main program        */

 main()
 {
         clrscreen();
         putline("     IBM/EPSON MX-80 Printer Setup");
         putline("            by Michael Burton ");
         putline(" ");
         putline("A] Double width on  L] Double width off");
         putline("B] Compressed on    M] Compressed off");
         putline("C] Underlining on   N] Underlining off");
         putline("D] Emphasized on    P] Emphasized off");
         putline("E] Doublestrike on  Q] Doublestrike off");
         putline("F] Superscript on   R] Superscript off");
         putline("G] Subscript on     S] Subscript off");
         putline("H] Italics on       T] Italics off");
         putline("I] Perf skip set    U] Perf skip off");
         putline("J] Column width set V] Page length set");
         putline("K] Printer reset    W] Return to DOS");

         while (TRUE)
         {
                 putcurs(16,0);
                 puts("Selection?  ");
                 putchar(BS);
                 cmd = getchar() | 32;

                 if (cmd == 'a')
                 {
                         prt3chr(ESC,'W',1);
                         finmes("Double Width Print on");
                 }
                 if (cmd == 'b')
                 {
                         prtchr(CMPRSON);
                         finmes("Compressed Print on");
                 }
                 if (cmd == 'c')
                 {
                         prt3chr(ESC,'-',1);
                         finmes("Underline on");
                 }
                 if (cmd == 'd')
                 {
                         prt2chr(ESC,'E');
                         finmes("Emphasized Print on");
                 }
                 if (cmd == 'e')
                 {
                         prt2chr(ESC,'G');
                         finmes("Double Strike Print on");
                 }
                 if (cmd == 'f')
                 {
                         prt3chr(ESC,'S',0);
                         finmes("Superscript on");
                 }
                 if (cmd == 'g')
                 {
                         prt3chr(ESC,'S',1);
                         finmes("Subscript on");
                 }
                 if (cmd == 'h')
                 {
                         prt2chr(ESC,'4');
                         finmes("Italics on");
                 }
                 if (cmd == 'i')
                 {
         getinall("Perf skip how many lines? ",0,128,'N',"Perf skip set");
                 }
                 if (cmd == 'j')
                 {
         getinall("No. of columns? ",0,232,'Q',"Column width set");
                 }
                 if (cmd == 'k')
                 {
                         prt2chr(ESC,'@');
                         finmes("Printer Reset");
                 }
                 if (cmd == 'l')
                 {
                         prt3chr(ESC,'W',0);
                         finmes("Double Width Print off");
                 }
                 if (cmd == 'm')
                 {
                         prtchr(CMPRSOFF);
                         finmes("Compressed Print off");
                 }
                 if (cmd == 'n')
                 {
                         prt3chr(ESC,'-',0);
                         finmes("Underline off");
                 }
                 if (cmd == 'p')
                 {
                         prt2chr(ESC,'F');
                         finmes("Emphasized Print off");
                 }
                 if (cmd == 'q')
                 {
                         prt2chr(ESC,DSOFF);
                         finmes("Double Strike Print off");
                 }
                 if (cmd == 'r')
                 {
                         prt2chr(ESC,DSOFF);
                         finmes("Superscript off");
                 }
                 if (cmd == 's')
                 {
                         prt2chr(ESC,DSOFF);
                         finmes("Subscript off");
                 }
                 if (cmd == 't')
                 {
                         prt2chr(ESC,'5');
                         finmes("Italics off");
                 }
                 if (cmd == 'u')
                 {
                         prt2chr(ESC,'O');
                         finmes("Perf skip off");
                 }
                 if (cmd == 'v')
                 {
         getinall("How many lines? ",0,128,'C',"Page length set");
                 }
                 if (cmd == 'w') exit();
                 if (cmd == 'x') prtline();
                 if (cmd < 'a' | cmd > 'x')
                         bell();
                 else
                         delay(6000);
         }
 }

 /*  End of SETPRTR main program         */
 /*  Beginning of support functions        */

 delay(n)        /* Wait a while */
         int n;
 {
         int i;

         i = 0;
         while (i++ < n) {
         }
         while (i-- > 0) {
         }
         clearline(20);
 }

 prtline()        /* Diagnostic. Print a line on the printer. */
 {
         char buff[41];
         int i;

         i = 0;
         clearline(16);
         putcurs(16,0);
         gets(buff);
         while (buff[i] >0)
         {
                 pcdos(5,buff[i++]);
         }
         pcdos(5,CR);
         pcdos(5,LF);
         clearline(16);
 }

 /*  Printer functions                */

 getinall(s,l,u,c,t)
         int *s,l,u,c,*t;
 {
         int buff[41], n;

         while (TRUE)
         {
                 clearline(16);
                 putcurs(16,0);
                 puts(s);
                 gets(buff);
                 n = atoi(buff);
                 clearline(16);
                 if (n <= l | n >= u)
                         bell();
                 else
                         break;
         }
         prt3chr(ESC,c,n);
         finmes(t);
 }
 prt3chr(s,t,u)        /* Output 3 chars to the printer */
         char s,t,u;
 {
         prt2chr(s,t);
         prtchr(u);
 }

 prt2chr(s,t)        /* Output 2 chars to the printer */
         char s,t;
 {
         prtchr(s);
         prtchr(t);
 }

 prtchr(s)        /* Output a char to the printer */
         char s;
 {
         finmes("Ready Printer");
         pcdos(5,s);
         clearline(20);
 }

 /* Display functions                */

 putline(s)        /* Send a line to display with cr/lf */
         char *s;
 {
         puts(s);
         putchar(CR);
 }

 finmes(s)        /* Send a finish message to line 20 */
         char *s;
 {
         putcurs(20,0);
         puts(s);
 }

 clearline(n)        /* Clear 40 columns of line n */
         int n;
 {
         putcurs(n,0);
         puts("                                       ");
 }

 putcurs(r,c)        /* Put cursor at a specified row and column */
         int r,c;
 {
         int a,b,d;

         a = 2;
         b = 0;
         d = 0;
         int10(a,d,b,d,d,d,r,c);
 }

 atoi(s)         /* Convert a string to integer */
         char *s;
 {
         int n;
         n = 0;
         while (*s >= '0' && *s <= '9')
         {
                 n = 10 * n + *s - '0';
                 s++;
         }
         return(n);
 }


 SETSCRN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\WINDOW\SETSCRN.C


 #include <stdio.h>

 main(argc, argv)        /* set a display mode */
 int                argc;
 char        *argv[];
 {
         int                m;

         if (argc != 2) /* only one arg allowed on command line */
                 help();
         m = atoi(argv[1]);
         if ((m < 0) || (m > 6)) /* arg out of range */
                 help();
         set_mode(m);
 }


 help()
 {
         puts("\nSetScrn -- ver 1.0 by Ray McVay\n");
         puts("\nUsage: setscrn n\n");
         puts(  "where: n = 0 = 40x25 BW\n");
         puts(  "     : n = 1 = 40x25 COLOR\n");
         puts(  "     : n = 2 = 80x25 BW\n");
         puts(  "     : n = 3 = 80x25 COLOR\n");
         puts(  "     : n = 4 = 320x200 COLOR\n");
         puts(  "     : n = 5 = 320x200 BW\n");
         puts(  "     : n = 6 = 640x200 BW\n");
         exit(1);
 }


 SETSCRN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\WINDKW\SETSCRN.C


 #include <stdio.h>

 main(argc, argv)        /* set a display mode */
 int                argc;
 char        *argv[];
 {
         int                m;

         if (argc != 2) /* only one arg allowed on command line */
                 help();
         m = atoi(argv[1]);
         if ((m < 0) || (m > 6)) /* arg out of range */
                 help();
         set_mode(m);
 }


 help()
 {
         puts("\nSetScrn -- ver 1.0 by Ray McVay\n");
         puts("\nUsage: setscrn n\n");
         puts(  "where: n = 0 = 40x25 BW\n");
         puts(  "     : n = 1 = 40x25 COLOR\n");
         puts(  "     : n = 2 = 80x25 BW\n");
         puts(  "     : n = 3 = 80x25 COLOR\n");
         puts(  "     : n = 4 = 320x200 COLOR\n");
         puts(  "     : n = 5 = 320x200 BW\n");
         puts(  "     : n = 6 = 640x200 BW\n");
         exit(1);
 }


 SETVBUF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SETVBUF.C

 #include <stdio.h>
 #include <io.h>

 int setvbuf(fp, bp, bmode, size)
 register FILE *fp;
 char *bp;
 int bmode;
 unsigned int size;
 {
         fp->F_cnt = 0;
         fp->F_unc1 = '\0';
         fp->F_unc2 = '\0';
         if((bmode == _SVBn) || (bp == NULL)) {                /* unbuffered *
                 fp->F_stat &= ~F_BUFFER;
                 fp->F_buf = NULL;
                 fp->F_bsiz = 0;
         }
         else {
                 fp->F_stat |= F_BUFFER;
                 fp->F_buf = bp;
                 fp->F_bsiz = size;
         }
         fp->F_bp = fp->F_buf;
         return(0);
 }


 SGN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SGN.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"

 /************************************************************************/
         double
 sgn(x)                        /* return double sgn function of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         return SGN(x);
 }


 SGREP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\SGREP.C

 /*
         HEADER:                CUG236;
         TITLE:                SGREP Text Pattern Replacer (McKe86);
         DATE:                05/17/1987;
         DESCRIPTION:        "Is a modified version of the CUG 152 grep progra
                         with the added features of string substitution,
                         multiple pattern search, case sensitivity, and scanni
                         option.";
         VERSION:        1.0;
         KEYWORDS:        Text filter;
         FILENAME:        SGREP.C;
         SEE-ALSO:        SGREP.DOC;
         COMPILERS:        vanilla;
         AUTHORS:        J. McKeon;
 */

 /*
  *
  * The        information  in         this  document         is  subject  to
  * without  notice  and         should not be construed as a commitment
  * by Digital Equipment Corporation or by DECUS.
  *
  * Neither Digital Equipment Corporation, DECUS, nor the authors
  * assume any responsibility for the use or reliability of  this
  * document or the described software.
  *
  *        Copyright (C) 1980, DECUS
  *
  * General permission to copy or modify, but not for profit,  is
  * hereby  granted,  provided that the above copyright notice is
  * included and reference made to  the        fact  that  reproduction
  * privileges were granted by DECUS.
  *
  */

 #include "stdio.h"

 /*
  * grep.
  *
  * Runs on the Decus compiler or on vms.
  * Converted for BDS compiler (under CP/M-80), 20-Jan-83, by Chris Kern.
  * Converted to IBM PC with CI-C86 C Compiler June 1983 by David N. Smith
  * On vms, define as:
  *        grep :== "$disk:[account]grep"           (native)
  *        grep :== "$disk:[account]grep grep"        (Decus)
  *
  * sgrep.
  *
  * Addition of string substitution capability,
  * multiple pattern search, upper-lower case option, scanning options,
  * and name changed to sgrep, April 1986 by James J. McKeon.
  * Runs on IBM PC or compatibles using ECO C88 compiler.
  *
  * For help type "sgrep ?".  See below for more information.
  *
  * May 1987, William C. Colley, III -- Fixed bug in usage of function fgets()
  * in function compat().  Added several notes about portability to various
  * compilers.  Fixed a glitch in case STAR of function pmatch() that crashed
  * the program when compiled under MSDOS large model.  The glitch occurred
  * when a pointer was (deliberately) run backward past the beginning of an
  * array of char.  The array was exactly on a paragraph boundary, so the
  * pointer decremented from 0x0e5d0000 to 0x0e5dffff instead of to 0x0e5cffff
  * as expected.  A pointer comparison then turned out bogus data and the
  * program went into an infinite loop.  The moral of this story is:  Don't
  * play fast and loose with pointers if you want portability.
  */

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * pair of #defines if you are running AZTEC C:
  */

 /*
 #define getc(f)                agetc(f)
 #define putc(c,f)        aputc(c,f)
 */

 /*
  * Portability Note:  8-bit systems often don't have header file ctype.h.
  * If your system doesn't have it, uncomment the #define NO_CTYPE_H.
  */

 /*
 #define NO_CTYPE_H
 */

 #ifdef        NO_CTYPE_H
 int isalpha(), isalnum(), isdigit(), tolower();
 #else
 #include <ctype.h>
 #endif

 char        *documentation[] = {
 "Sgrep searches a file for a given pattern and substitutes a pattern.",
 "If no substitution is required, the command sgrep -myn corresponds",
 "to grep -n and will match only. Output is to the screen and may be",
 "re-directed using \">\" at the DOS level. Execute by",
 "  sgrep [flags] pattern-file input-file",
 "",
 "Flags are single characters preceeded by '-':",
 "   -c      Only a count of matching lines is printed",
 "   -m      Match patterns only, no substitutions.",
 "   -n      Each line is preceeded by its line number",
 "   -v      Only print non-matching lines",
 "   -y      Upper and lower case match.",
 "",
 0 };

 char        *patdoc[] = {
 "Each match pattern is on a separate line followed by its substitute",
 "pattern, if any, also on a separate line.",

 " MATCH PATTERNS",
 "The regular_expression defines the pattern to search for.  Upper and",
 "lower-case are regarded as different unless -y option is used.",
 "x      An ordinary character (not mentioned below) matches that character.",
 "'\\'    The backslash quotes any character.  \"\\$\" matches a dollar-sign."
 "'$'    Matches beginning or end of line.",
 "'.'    A period matches any character except \"new-line\".",
 "':a'   A colon matches a class of characters described by the following",
 "':d'     character.  \":a\" matches any alphabetic, \":d\" matches digits,",
 "':n'     \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
 "': '     other control characters except new-line.",
 "'*'    An expression followed by an asterisk matches zero or more",
 "       occurrances of that expression: \"fo*\" matches \"f\", \"fo\"",
 "       \"foo\", etc.",
 "'+'    An expression followed by a plus sign matches one or more",
 "       occurrances of that expression: \"fo+\" matches \"fo\", etc.",
 "'-'    An expression followed by a minus sign optionally matches",
 "       the expression.",
 "'[]'   A string enclosed in square brackets matches any character in",
 "       that string, but no others.  If the first character in the",
 "       string is a circumflex, the expression matches any character",
 "       except \"new-line\" and the characters in the string.  For",
 "       example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
 "       matches \"abc\" but not \"axb\".  A range of characters may be",
 "       specified by two characters separated by \"-\".  Note that,",
 "       [a-z] matches alphabetics, while [z-a] never matches.",
 "The concatenation of regular expressions is a regular expression.",

 " Scanning options:",
 "The default scanning option is match all occurences of the pattern.",
 "'@'    at the beginning of the pattern, is equivalent to",
 "       \"$: *\", meaning match first non-whitespace pattern.",
 "'@e'   at the end of a pattern means that if a match is",
 "       found (and a substitution made), end all pattern search",
 "       on current line.",
 "'@r'   at the end of a pattern means that after a match",
 "       (and substitution), rescan line until no match occurs.",

 " SUBSTITUTE PATTERNS ",
 "The only control character for substitute patterns is \"?\".",
 "Any other character represents itself. Only the characters ? and",
 " \\ itself need to be quoted.",

 "'?n'   where n is a non-zero digit, indicates the position where",
 "       the nth wildcard string is to be placed.",
 "A wildcard string is any string which is not completely fixed,",
 "both as to the characters and number of characters in the string.",
 0};

 #define LMAX        100
 #define PMAX        2000
 #define NPATMAX 100

 #define CHR        1
 #define SCOP        2
 #define BEOL        3
 #define ANY        4
 #define CLASS        5
 #define NCLASS        6
 #define STAR        7
 #define PLUS        8
 #define MINUS        9
 #define ALPHA        10
 #define DIGIT        11
 #define NALPHA        12
 #define PUNCT        13
 #define RANGE        14
 #define ENDPAT        15
 #define lowopt(x) yflag?tolower(x):x

 int        cflag;
 int        mflag;
 int        nflag;
 int        vflag;
 int        yflag;

 int        debug        =        0;           /* Set for debug code      */

 char        *pp, *psp;

 #ifndef vms
 char        file_name[81];
 #endif

 char        lbuf[LMAX], slbuf[LMAX];
 char        pbuf[PMAX], spbuf[PMAX];
 char        * wldstr[19][2];  /* Location of wildcard strings */
 int        nws, npat, rescan, nxtln;
 char   *mpp[NPATMAX], *mpsp[NPATMAX];  /* Location of patterns */

 void exit();
 /*******************************************************/

 int main(argc, argv)
 int argc;
 char *argv[];
 {
    register char   *p;
    register int           c;
    FILE                   *f;
    void cant(), compat(), grep(), help(), usage();

    if (argc <= 1)
       usage("No arguments");
    if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
       help(documentation);
       help(patdoc);
       return !0;
       }
       p=argv[argc-1];
       if ((f=fopen(p, "r")) == NULL) cant(p);
       p = argv[1];
       if (*p == '-') {
          ++p;
          while (c = *p++) {
             switch(tolower(c)) {

             case 'c':
                ++cflag;
                break;

             case 'd':
                ++debug;
                break;

             case 'm':
                ++mflag;
                break;

             case 'n':
                ++nflag;
                break;

             case 'v':
                ++vflag;
                break;

             case 'y':
                ++yflag;
                break;

             default:
                usage("Unknown flag");
             }
          }
         p=argv[2];
       }
       compat(p);
       grep(f);
       fclose(f);
       return 0;
 }

 /*******************************************************/

 void cant(s)
 char *s;
 {
    fprintf(stderr, "%s: cannot open\n", s);
 }


 /*******************************************************/

 void help(hp)
 char **hp;  /* dns added extra '*'  */
 /*
  * Give good help
  */
 {
    register char   **dp;

    for (dp = hp; *dp; dp++)
       printf("%s\n", *dp);
 }

 /*******************************************************/

 void usage(s)
 char *s;
 {
    fprintf(stderr, "?SGREP-%s\n", s);
    fprintf(stderr,
   "Usage: sgrep [-mycnv] pattern-file input-file. sgrep ? for help\n");
    exit(1);
 }

 /*******************************************************/


 void compile(source)
 char *source;                /* Pattern to compile              */
 /*
  * Compile the pattern into global pbuf[]
  */
 {
    register char  *s;              /* Source string pointer           */
    register char  *lp;              /* Last pattern pointer           */
    register int          c;              /* Current character           */
    int                  o;              /* Temp                           */
    char                  *spp;              /* Save beginning of pattern */
    char                  *cclass();  /* Compile class routine           */
    void badpat(), store();

    s = source;
    if (debug)
       printf("Pattern = %s\n", s);
    while (c = *s++) {
       /*
        * STAR, PLUS and MINUS are special.
        */
       if (c == '*' || c == '+' || c == '-') {
          if (pp == pbuf ||
               (o=pp[-1]) == SCOP || o == '\0' ||
               o == BEOL ||
               o == STAR ||
               o == PLUS ||
               o == MINUS)
             badpat("Illegal occurrance op.", source, s);
          store(ENDPAT);
          store(ENDPAT);
          spp = pp;                 /* Save pattern end         */
          while (--pp > lp)         /* Move pattern down         */
             *pp = pp[-1];         /* one byte                 */
          *pp =         (c == '*') ? STAR :
             (c == '-') ? MINUS : PLUS;
          pp = spp;                 /* Restore pattern end         */
          continue;
       }
       /*
        * All the rest.
        */
       lp = pp;               /* Remember start       */
       switch(c) {

       case '@':
          if(s-1 == source) {
            store(BEOL);
            store(STAR);
            store(PUNCT);
            store(ENDPAT);
            break;
          } else {
          store(SCOP);
          store(*s++);
          break;
          }
       case '$':
          store(BEOL);
          break;

       case '.':
          store(ANY);
          break;

       case '[':
          s = cclass(source, s);
          break;

       case ':':
          if (*s) {
             switch(c = *s++) {

             case 'a':
             case 'A':
                store(ALPHA);
                break;

             case 'd':
             case 'D':
                store(DIGIT);
                break;

             case 'n':
             case 'N':
                store(NALPHA);
                break;

             case ' ':
                store(PUNCT);
                break;

             default:
                badpat("Unknown : type", source, s);

             }
             break;
          }
          else         badpat("No : type", source, s);

       case '\\':
          if (*s)
             c = *s++;

       default:
          store(CHR);
          store(lowopt(c));
       }
    }
    pp -= 2;                   /* delete linefeed */
    store(ENDPAT);
    store(0);                    /* Terminate string            */
    mpp[npat+1] = pp;
    if (debug) {
       for (lp = mpp[npat]; lp < pp;) {
          if ((c = (*lp++ & 0377)) < ' ')
             printf("\\%x ", c);
          else         printf("%c ", c);
         }
         printf("\n");
    }
 }

 /*******************************************************/

 char *cclass(source, src)
 char *source;             /* Pattern start -- for error msg.             */
 char *src;             /* Class start              */
 /*
  * Compile a class (within [])
  */
 {
    register char   *s;              /* Source pointer           */
    register char   *cp;              /* Pattern start           */
    register int           c;              /* Current character */
    int                   o;              /* Temp                   */
    void badpat(), store();

    s = src;
    o = CLASS;
    if (*s == '^') {
       ++s;
       o = NCLASS;
    }
    store(o);
    cp = pp;
    store(0);                              /* Byte count         */
    while ((c = *s++) && c!=']') {
       if (c == '\\') {                      /* Store quoted char    */
          if ((c = *s++) == '\0')      /* Gotta get something  */
             badpat("Class terminates badly", source, s);
          else store(lowopt(c));
       }
       else if (c == '-' &&
             (pp - cp) > 1 && *s != ']' && *s != '\0') {
          c = pp[-1];                 /* Range start            */
          pp[-1] = RANGE;         /* Range signal    */
          store(c);                 /* Re-store start  */
          c = *s++;                 /* Get end char and*/
          store(lowopt(c));        /* Store it           */
       }
       else {
          store(lowopt(c));        /* Store normal char */
       }
    }
    if (c != ']')
       badpat("Unterminated class", source, s);
    if ((c = (pp - cp)) >= 256)
       badpat("Class too large", source, s);
    if (c == 0)
       badpat("Empty class", source, s);
    *cp = c;
    return(s);
 }

 /*******************************************************/

 void store(op)
 int op;
 {
    void error();

    if (pp >= &pbuf[PMAX])
       error("Pattern too complex\n");
    *pp++ = op;
 }

 /*******************************************************/

 void badpat(message, source, stop)
 char  *message;              /* Error message */
 char  *source;              /* Pattern start */
 char  *stop;              /* Pattern end   */
 {
    void error();

    fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
    fprintf(stderr, "-GREP-E-Stopped at byte %d, '%c'\n",
          stop-source, stop[-1]);
    error("?GREP-E-Bad pattern\n");
 }

 /*******************************************************/

 void grep(fp)
 FILE           *fp;              /* File to process            */
 /*
  * Scan the file for the pattern in pbuf[]
  */
 {
    register int lno, count, m;
    int        jpat, mm, match();

    lno = 0;
    count = 0;
    while (fgets(lbuf, LMAX, fp)) {
     ++lno;
     mm = 0;
     for(jpat=1;jpat<=npat;jpat++){
      m = nxtln = 0;
      do {
        rescan = 0;
        if(match(jpat)) m = 1;
      } while(rescan == 1);
      if(m) mm = 1;
       if(nxtln)
         break;
     }/*jpat*/
     if (!mflag)
       printf("%s", lbuf);
     else if(mm && !vflag || !mm && vflag) {
       if(cflag)
         count++;
       else {
         if(nflag)
           printf("%d\t", lno);
         printf("%s\n", lbuf);
       }
     }
    }/*wh*/
    if (cflag)
       printf("%d\n", count);
 }

 /*******************************************************/

 int match(jp)
 /*
  * Match the current line (in lbuf[]), return 1 if it does.
  */
   int  jp;
 {
    register char   *l;              /* Line pointer            */
    char         *s, *pat, *lst;
    int km;
    char *pmatch(), *movs();
    void substit();

    km=0;
    pat = mpp[jp];
    l = lst = lbuf;
    while(*l) {
       nws = 0;
       s=pmatch(l,pat);
       if (s){
         if(s < l) break;    /* BOL impossible */
         km = 1;
         if(mflag) break;
         wldstr[0][0]=l;
         wldstr[0][1]=s;
         substit(lst, jp);
         lst = s;
         l = s - 1;
       }
       if(nxtln) break;
       l++;
    }
    if(km && !mflag) {
      substit(lst, 0);
      l = movs(slbuf,slbuf+LMAX,lbuf);
      *l = 0;
    }
    return(km);
 }

 /*******************************************************/

 char *pmatch(line, pattern)
 char                   *line;     /* (partial) line to match      */
 char                   *pattern;  /* (partial) pattern to match   */
 {
    register char   *l;              /* Current line pointer              */
    register char   *p;              /* Current pattern pointer      */
    register char   c;              /* Current character              */
    char                   *e;              /* End for STAR and PLUS match  */
    int                   op;              /* Pattern operation              *
    int                   n;              /* Class counter
    char                   *are;      /* Start of STAR match              */
    int        ows;
    static int wss;              /* Wild string switch */
    void error();

    l = line;
    if (debug > 1)
       printf("pmatch(\"%s\")\n", line);
    p = pattern;
    while ((op = *p++) != ENDPAT) {
       if (debug > 1)
          printf("byte[%d] = 0%o, '%c', op = 0%o\n",
                l-line, *l, *l, op);
       switch(op) {

       case CHR:
          c = *l++;
          if ((yflag ? tolower(c) : c) != *p++)
             return NULL;
          break;

       case SCOP:
          if(*p++ == 'r')
            rescan = 1;
          else
            nxtln = 1;
          break;

       case BEOL:
          if((p-1) == pattern && l != lbuf) return(line-1);
          if((p-1) != pattern && *l != '\n') return NULL;
          break;

       case ANY:
          if (*l++ == '\n')
             return NULL;
          break;

       case DIGIT:
          c = *l++;
          if(!isdigit(c)) return NULL;
          break;

       case ALPHA:
          c = *l++;
          if (!isalpha(c)) return NULL;
          break;

       case NALPHA:
          c = *l++;
          if (!isalnum(c)) return NULL;
          break;

       case PUNCT:
          if ((c = *l++) == '\n' || c > ' ')
             return NULL;
          break;

       case CLASS:
       case NCLASS:
          c = *l++;
          if (yflag) c = tolower(c);
          n = *p++ & 0377;
          do {
             if (*p == RANGE) {
                p += 3;
                n -= 2;
                if (c >= p[-2] && c <= p[-1])
                   break;
             }
             else {
               if(c == '\n')
                 return NULL;
               if (c == *p++) break;
             }
          } while (--n > 1);
           if(op == CLASS && n <= 1) return NULL;
           if(op != CLASS && n > 1) return NULL;
          if (op == CLASS)
             p += n - 2;
          break;

       case MINUS:
          e = pmatch(l, p);         /* Look for a match        */
          while (*p++ != ENDPAT); /* Skip over pattern        */
          if (e)                         /* Got a match?        */
             l = e;                 /* Yes, update string        */
          break;                         /* Always succeeds        */

       case PLUS:                 /* One or more ...        */
          wss=1;                         /* wldstr switch on */
          if (!(l = pmatch(l, p))){
             wss=0;
             return NULL;         /* Gotta have a match        */
          }
       case STAR:                 /* Zero or more ...        */
          wss = 1;                 /* wldstr switch on */
          for (are = l; *l && (e = pmatch(l, p)); l = e);
                                  /* Get longest match        */
          wss = 0;
          ows = ++nws;                 /* Save wildstring number */
          while (*p++ != ENDPAT); /* Skip over pattern        */
          do {                         /* Try to match rest        */
             if (e = pmatch(l, p)){
              wldstr[ows][0]=are - op + 7; /* Subtract 1 if plus */
              wldstr[ows][1]=l;
               return(e);
              }
             nws = ows;
          } while (l-- > are);
          return NULL;                 /* Nothing else worked */

       default:
          printf("Bad op code %d\n", op);
          error("Cannot happen -- match\n");
       }
       if((wss == 0) && (op >= 4) && (op <= 13)){
         ++nws;
         wldstr[nws][0] = l-1;  /* single character */
         wldstr[nws][1] = l;
         if(op == 9 && e == 0)
           wldstr[nws][0] = l;  /* null string */
       }
   }
    return(l);
 }

 /*******************************************************/

 void error(s)
 char *s;
 {
    fprintf(stderr, "%s", s);
    exit(1);
 }

 void compat(patfile)        /* Read in pattern file and compile patterns */
 char  *patfile;
 {
     FILE  *fp;
     char  *l;
     void cant(), compile(), compsub(), error();

     if((fp=fopen(patfile,"r")) == NULL) cant(patfile);
     npat = 0;  mpp[1] = pp = pbuf;  mpsp[1] = psp = spbuf;
     while((l = fgets(slbuf,LMAX,fp)) && *l){
         npat += 1;  compile(slbuf);
         if(!mflag) {
             if (l = fgets(slbuf,PMAX,fp)) compsub();
             else
                 error("?GREP-E-Odd number of lines in substitution pattern\n"
         }
     }
     if(debug) printf(" npat = %d \n",npat);
     fclose(fp);
 }

 void compsub()
 /* Compile substitute pattern into spbuf */
 {
 char *l, *p, c;
   if(debug) printf(" Subspat = %s \n",slbuf);
   p = psp;
   for(l=slbuf;*l;l++){
     c = *l;
     switch(c){
     case '?':
       *p++ = 7;
       l++;
       *p++ = (*l - 48);
       break;
     case '\\':
       c = *(++l);
     default:
       *p++ = c;
     }
   }
     p--;         /* delete linefeed */
     *p = 0;
     psp = ++p;
    mpsp[npat+1] = psp;
    if(debug){
     for(l=mpsp[npat];*l;l++){
       if((c = (*l & 0377)) < ' ') printf("\\%x ",c);
       else printf("%c ",c);
     }
     printf("\n");
    }
 }

 char  *movs(l1,l2,p)
 /* Move string from l1 to p */
 char  *l1, *l2, *p;
 {
 char  *l;
   for(l = l1; l < l2 && *l; l++)
     *p++ = *l;
   return(p);
 }

 void substit(lb, jpat)        /* construct output record */
 char  *lb;
 int  jpat;
 {
 char  *movs(), *p;
 static char *sl = slbuf;
 int k;
  if(jpat == 0){
   sl =        movs(wldstr[0][1],lbuf+LMAX,sl);
   *sl = 0;
   sl = slbuf;
   return;
  }
   psp = mpsp[jpat];
   sl = movs(lb,wldstr[0][0],sl);
   for(p=psp; *p; p++){
     switch(*p) {
     case 7:
       p++;
       k = *p;
       sl =   movs(wldstr[k][0],wldstr[k][1],sl);
       break;
     default:
       *sl++ = *p;
     }/*sw*/
   }
 }


 SHELL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SHELL.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 extern char        *_base;

 shell()
 /*
  *        Invoke a command line interface shell.  If the "SHELL" environment
  *        variable is not defined, a prompt showing the current working
  *        directory will be given.  Each line entered will then be passed
  *        to the system() function for execution until the command "exit"
  *        is entered to terminate the shell.  If "SHELL" is defined, and
  *        the "_shell_p" variable is valid, the value of "SHELL" will be
  *        passed to the program pointed to by "_shell_p" in order to allow
  *        the shell to invoke a command line interaction of its own.  If
  *        the "_shell_p" variable is not valid, the program defined by
  *        "SHELL" will be searched for along the "PATH", and executed with
  *        no arguments.  If the "SHELL" can't be found, the internal command
  *        line described above will be used.
  */
 {
         register char *p, *q;
         register int rv = 0;
         register int (*shell)();
         char command[128];
         char *getenv(), *strtok(), *pfindfile(), *fullpath();
         int getch(), putch();

         /* SHELL= variable? */
         if((p = getenv("SHELL")) && (*p)) {        /* SHELL is valid? */
                 q = Super(0L);
                 shell = *((long *) 0x4F6L);        /* get _shell_p value */
                 Super(q);
                 if((shell) &&                                /* shell availab
                    (((long) shell) < ((long) _base)) &&        /* reasonable
                    (strncmp(shell, "PATH", 4))) {        /* not corrupted */
                         rv = (*shell)(p);                /* call shell */
                         return;
                 }
                 if(p = pfindfile(p, "prg\0ttp\0tos\0")) {
                         spawn(p, "");                        /* execute shell
                         return;
                 }
         }
         /* internal command line interface */
         for(;;) {
                 cprintf("%s> ", fullpath(NULL, ""));        /* cwd as prompt
                 getln(NULL, getch, putch, command, 128);/* editable field */
                 cputs("\r\n");
                 if(command[0] == '\0')                        /* ignore blank
                         continue;
                 if(!stricmp(command, "exit"))                /* leave the she
                         return;
                 system(command);                        /* execute a command
         }
 }


 SHIFTER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SHIFTER.C

                                          /* Chapter 13 - Program 4 */
 main()
 {
 int small, big, index, count;

    printf("       shift left      shift right\n\n");
    small = 1;
    big = 0x4000;
    for(index = 0;index < 17;index++) {
       printf("%8d %8x %8d %8x\n",small,small,big,big);
       small = small << 1;
       big = big >> 1;
    }

    printf("\n");
    count = 2;
    small = 1;
    big = 0x4000;
    for(index = 0;index < 9;index++) {
       printf("%8d %8x %8d %8x\n",small,small,big,big);
       small = small << count;
       big = big >> count;
    }
 }


 SHIFTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\SHIFTEST.C

 /* SHIFTEST.C - From page 340 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. This program demonstrates the     */
 /* bitwise right shift operator.                                */
 /****************************************************************/

 #define TRUE 1

 main()
 {
 unsigned char x1, x2;

    while(TRUE) {
       printf("\n\nEnter hex number (ff or less) and number of bits ");
       printf("\nto shift (8 or less; example 'cc 3'): ");
       scanf("%x %d", &x1, &x2);
       printf("\n%02x >> %d = %02x\n", x1, x2, x1 >> x2);
    }
 }



 SHOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\SHOW.C

 /*                      Show Text File Utility

         This program displays a text file on the screen and redisplays
         it according to the user's use of the page-up, page-down,
         up-arrow, down-arrow, 'u', and 'd' keys. It exits when the user
         types either 'q' or ESC.
 */

 #include <stdio.h>

 CALIBRATE       /* If defined, display pages 21 times for timing. */

 /*#define VANILLA*/     /* Define for vanilla, TTY style output. */
 /*#define ANSI*/        /* Define for ANSI.SYS style output. */
 ROMBIOS         /* Define for ROM BIOS style output. */

 MAXLINES 10000  /* Maximum number of lines in file. */

 LINESIZE 200    /* Maximum number of characters in a line. */

 FILE *inFile;           /* File identifier for file to be displayed. */

 int curLine;            /* Where to start displaying from. */

 struct cmdType {        /* Command table entry form. */
  char cmdKey;           /* The key code or ASCII value. */
  int (*cmdFunc)();      /* The function to call. */
  int cmdParm;           /* The parameter to pass to it. */
 };

 int upLines(), quitIt();

 struct cmdType keyTab[] = {     /* Normal key table. */
         'u', upLines, 20,       /* 'u' key: scroll backward 20 lines. */
         'U', upLines, 20,       /* 'U' key: scroll backward 20 lines. */
         'd', upLines, -20,      /* 'd' key: scroll forward 20 lines. */
         'D', upLines, -20,      /* 'D' key: scroll forward 20 lines. */
         'q', quitIt, 0,         /* 'q' key: quit. */
         'Q', quitIt, 0,         /* 'Q' key: quit. */
         033, quitIt, 0,         /* ESC key: quit. */
         0, quitIt, 0            /* End-of-table. */
 };

 struct cmdType zKeyTab[] = {    /* Zero-prefix key table. */
         72, upLines, 1,         /* Up-arrow key: scroll backward 1 line. */
         73, upLines, 20,        /* Up-page key: scroll backward 20 lines. */
         80, upLines, -1,        /* Down-arrow key: scroll forward 1 line. */
         81, upLines, -20,       /* Down-page key: scroll forward 20 lines. */
         0, quitIt, 0            /* End-of-table. */
 };

 long lineStart[MAXLINES];       /* Offsets from start of file to lines. */
 long *nextStart;                /* Pointer to next available line start. */

 #define TRUE 1
 #define FALSE 0

 /*      main(argc,argv)

         Function: Display a text file on the screen.

         Algorithm: Start at the beginning of the file. Display a page,
         reading the file as needed. Then repeatedly wait for keyboard
         input, and take the appropriate action based on it.
 */

 main(argc,argv)

 int argc;
 char *argv[];

 {
         int i;

         /* Check that the user gave us the right number of command
            line parameters. */
         if (argc != 2) {
                 /* If not, tell him what's wrong and exit. */
                 puts("Usage: show <filename>\n");
                 exit(1);
         };

         /* Open the input file, if possible. */
         if ((inFile = fopen(argv[1],"r")) == NULL) {
                 /* If it wouldn't open, let the user know and exit. */
                 puts("Couldn't open input file.\n");
                 exit(1);
         };

         /* Start at the first line in the file. */
         curLine = 0;
         /* Set the file offset for that line in the line start array. */
         lineStart[0] = 0L;
         /* Set nextStart to indicate that this is the only entry we've
            filled in in lineStart so far. */
         nextStart = &lineStart[1];

         /* Repeatedly display a page, and then get and execute commands. */
         do {

 #ifdef CALIBRATE
                 /* If we're going to calibrate, repeat the following page
                    display 20 times. */
                 for (i = 20; i > 0; i--)
 #endif CALIBRATE

                         showPage();
         } while (!nextCommand());
 }

 /*      nextCommand()

         Function: Get and execute the next keyboard command. Return
         TRUE if it's time to quit.

         Algorithm: Get the keyboard input using getch. It then looks
         the character up in the keyTab or zKeyTab tables and executes
         the function found there (if any). Finally, it returns the value
         returned by the executed function.
 */

 nextCommand()

 {
         char c;                 /* The input from the user. */
         struct cmdType *cPtr;   /* A pointer into the command table. */

         /* Get the command from the user. */
         c = getch();
         /* If it isn't an extended code, use the ASCII command table. */
         if (c != 0) cPtr = keyTab;
         /* Otherwise, get the second character (the scan code), and use
            the scan code command table. */
         else {
                 c = getch();
                cPtr = zKeyTab;
         };

         /* Search thru the command table for the user input value. */
         for (; cPtr->cmdKey != 0; cPtr++)
                 if (cPtr->cmdKey == c)
                         /* If we found it, execute it. */
                         return((*cPtr->cmdFunc)(cPtr->cmdParm));

         /* If we didn't find it in the table, don't do anything at all. */
         return(FALSE);
 }

 /*      quitIt(dummy)

         Function: Quit command.

         Algorithm: Just return TRUE.
 */

 quitIt(dummy)

 int dummy;

 {
          return(TRUE);
 }

 /*      upLines(num)

         Function: Move the window up by num lines (may be negative).

         Algorithm: Just adjust curLine.

         Comments: The actual change in the display will be done by
         the showPage function.
 */

 upLines(num)

 int num;

 {
         /* Adjust the curLine global. */
         curLine -= num;
         /* But make sure we don't move back past the beginning of the file. *
         if (curLine < 0) curLine = 0;
         /* Return FALSE -- i.e., don't quit. */
         return(FALSE);
 }

 /*      showPage()

         Function: Display the page starting at curLine.

         Algorithm: First, clear the screen. Second, make sure that
         the line start array has the first line to be displayed.
         Then, starting at the first line on the screen, read and
         display each visible line.
 */

 showPage()

 {
         int i,j;
         long *lineStPtr;        /* Pointer into the line start array. */
         char line[LINESIZE];    /* Buffer into which to read lines. */

         /* Clear the screen. */
         clrScreen();

         /* Make sure the first line offset is in the line start array. */
         while (&lineStart[curLine] >= nextStart)
                 readLine(nextStart,line);

         /* For each line to be displayed... */
         for (lineStPtr = &lineStart[curLine], i = 24; i; i--, lineStPtr++) {
                 /* Read the line in. */
                 readLine(lineStPtr,line);
                 /* And display it. */
                 dispLine(line);
         };
 }

 /*      readLine(lStPtr,lBuf)

         Function: Read the line whose line start array entry is pointed
         to by lStPtr into the buffer pointed to by lBuf.

         Algorithm: Use fseek to position the file to the line requested,
         then read it in with fgets. Finally, set the next entry in the
         line start array to the file position after the read.

         Comments: The line start array entry pointed to by lStPtr must
         have been filled in already or the results of calling this
         function are undefined.
 */

 readLine(lStPtr,lBuf)

 long *lStPtr;
 char *lBuf;

 {
         /* Position the file to the line requested. */
         fseek(inFile,*lStPtr,0);
         /* Read in the line. */
         fgets(lBuf,LINESIZE,inFile);
         /* Record the offset to the next line in the file. */
         if (lStPtr == (nextStart-1)) *nextStart++ = ftell(inFile);
 }

 /*      clrScreen(), dispLine(lBuf)

         Function: Clear the screen (clrScreen()) or display a line (dispLine(

         Algorithm: The algorithm depends on which of VANILLA, ANSI, and
         ROMBIOS are defined. See the main text of the chapter for more
         details.
 */

 clrScreen()

 {
 #ifdef VANILLA
         int i;

         /* Write blank lines to scroll everything off the screen. */
         for (i = 0; i < 25; i++) dispLine("\n");
 #endif VANILLA

 #ifdef ANSI
         /* Send the ANSI clear screen sequence. */
         fputs("\033[2J",stdout);
 #endif ANSI

 #ifdef ROMBIOS
         /* Call the ROM BIOS to clear the screen for us. */
         scrClr();
 #endif ROMBIOS
 }

 dispLine(lBuf)

 char *lBuf;

 {
 #ifdef VANILLA
         /* Use the regular standard output routines. */
         fputs(lBuf,stdout);
 #endif VANILLA

 #ifdef ANSI
         /* Use the regular standard output routine. */
         fputs(lBuf,stdout);
 #endif ANSI

 #ifdef ROMBIOS
         /* Call the ROM BIOS. */
         scrPuts(lBuf); scrPuts("\r");
 #endif ROMBIOS
 }



 SHOWEQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\SHOWEQ.C

 #include "eqlib.h"

 /*      main()

         Function: Get and display the system memory size and the
         equipment configuration.

         Algorithm: Call the ROM BIOS interface routines memSz and
         getEq. Then interpret their replies and display the results.
 */

 main()

 {
         int theEq;      /* The equipment configuration. */
         int i;

         /* Display the memory size. */
         printf("Memory size is %dK.\n\n Equipment present:\n   ",memSz());

         /* Get the equipment configuration. */
         theEq = getEq();
         /* Get the number of printers. */
         i = (theEq & prtnMask) >> prtnShft;
         /* If there are any at all, show how many. */
         if (i != 0) printf("%d printer(s).\n   ",i);
         /* If there's a game I/O interface present, say so. */
         if (theEq & gioMask) printf("1 game I/O.\n   ");
         /* Get the number of serial ports. */
         i = (theEq & RS232Mask) >> RS232Shft;
         /* If there are any, show how many. */
         if (i != 0) printf("%d serial port(s).\n   ",i);
         /* If there are any diskette drives present, show how many. */
         if (theEq & diskMask) printf("%d diskette drive(s).\n   ",
                                      ((theEq & dsknMask) >> dsknShft)+1);
         /* Show the initial video mode. */
         printf("Initial video mode: ");
         i = theEq & vmodeMask;
         if (i == CO40) printf("40x25 color");
         else if (i == CO80) printf("80x25 color");
         else if (i == MONO) printf("80x25 monochrome");
         /* Show the system board RAM size. */
         printf(".\n   System board RAM size: %dK bytes.\n",
                16*(((theEq & sbramMask) >> sbramShft)+1));
 }



 SHOWEQ2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\SHOWEQ2.C

 #include "eqlib.h"

 /*      main()

         Function: Get and display the system memory size and the
         equipment configuration.

         Algorithm: Call the ROM BIOS interface routines memSz and
         getEq. Then interpret their replies and display the results.
 */

 main()

 {
         int theEq;      /* The equipment configuration. */
         int i;

         /* Clear the display. */
         scrUp(0,0,0,24,79,0);

         /* Display the memory size at the bottom of the screen. */
         setPos(0,15,30);
         printf("Memory size is %dK.",memSz());

         /* Display the equipment configuration at the top of the screen. */
         setPos(0,0,0);
         printf("Equipment present:\n   ");
         /* Get the equipment configuration. */
         theEq = getEq();
         /* Get the number of printers. */
         i = (theEq & prtnMask) >> prtnShft;
         /* If there are any at all, show how many. */
         if (i != 0) printf("%d printer(s).\n   ",i);
         /* If there's a game I/O interface present, say so. */
         if (theEq & gioMask) printf("1 game I/O.\n   ");
         /* Get the number of serial ports. */
         i = (theEq & RS232Mask) >> RS232Shft;
         /* If there are any, show how many. */
         if (i != 0) printf("%d serial port(s).\n   ",i);
         /* If there are any diskette drives present, show how many. */
         if (theEq & diskMask) printf("%d diskette drive(s).\n   ",
                                      ((theEq & dsknMask) >> dsknShft)+1);
         /* Show the initial video mode. */
         printf("Initial video mode: ");
         i = theEq & vmodeMask;
         if (i == CO40) printf("40x25 color");
         else if (i == CO80) printf("80x25 color");
         else if (i == MONO) printf("80x25 monochrome");
         /* Show the system board RAM size. */
         printf(".\n   System board RAM size: %dK bytes.\n",
                16*(((theEq & sbramMask) >> sbramShft)+1));

         /* Return the cursor to the bottom of the page. */
         setPos(0,23,0);
 }



 SIEVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\SIEVE.C


 #define true 1
 #define false 0
 #define size 8190
 #define sizepl 8191

 char        flags[sizepl];

 main() {
         int i,prime,k,count,iter;
         printf("10 iterations\n");
         for(iter=1;iter<= 10;iter++){
                 count=0;
                 for(i = 0; i<=size;i++)
                         flags[i]=true;
                 for(i=0;i <= size; i++){
                         if(flags[i]){
                                 prime = i+i+3;
                                 k=i+prime;
                                         while(k<=size){
                                                 flags[k] = false;
                                                 k += prime;
                                                 }
                                         count = count+1;
                                 }
                         }
                 }
         printf("\n%d primes\n",count);
         }


 SIEVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SIEVE.C


 /*
 ** BYTE Sieve Benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** March 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** This program executes the infamous Eratosthenes Sieve Prime
 ** Number Program from BYTE, Jan. 1983.
 **
 ** Operation:
 ** 1. Turn on stopwatch
 ** 2. Execute SIEVE for LOOP iterations
 ** 3. Turn off stopwatch
 ** 4. Report time and number of primes found
 ** 5. Exit
 **
 */

 #include stdio.h

 #define size  8190
 #define LOOP  100
 #define TRUE  YES
 #define FALSE NO

 int tblock[4];                /* Timer holding array */
 char flags [size + 1];

 main()

 {
     int i, prime, k, count, iter;

 /* Announce yourself */
     printf("BYTE Sieve Benchmark\n");

     printf("%d iterations\n",LOOP);

 /* Start timer and execute loop */
     gtime(tblock);
     for (iter = 1; iter <= LOOP; iter++)
           {
           count = 0;                              /* prime counter */
           for (i = 0; i <= size; i++)             /* set all flags true */
                 flags [i] = TRUE;
           for (i = 0; i <= size; i++)
                {
                     if (flags [i])                /* found a prime */
                     {
                     prime = i + i + 3;            /* twice index + 3 */
 /*                  printf ("\n%d", prime);  */
                     for (k = i + prime; k <= size; k+= prime)
                                  flags [k] = FALSE;  /* kill all multiple */
                     count++;                         /* primes found */
                     }
                 }
       }
       calctim(tblock);

 /* Report results */
      printf("Results:  (HH:MM:SS:1/100ths)\n");
      printf("Elapsed time: %d:%d:%d:%d\n\n",tblock[0],tblock[1],
              tblock[2],tblock[3]);

      printf ("%d primes.\n\n", count);     /* primes found on 100th pass */

 /* Exit */
      printf("Press RETURN to exit:");
      fgetc(stdin);
      exit(0);
  }


 SIEVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\SIEVE.C



 #define true 1
 #define false 0
 #define size 8190
 #define sizepl 8191

 main() {
         int i,prime,k,count,iter;
         char flags[sizepl];
         printf("10 iterations\n");
         for(iter=1;iter<= 10;iter++){
                 count=0;
                 for(i = 0; i<=size;i++)
                         flags[i]=true;
                 for(i=0;i <= size; i++){
                         if(flags[i]){
                                 prime = i+i+3;
                                 k=i+prime;
                                         while(k<=size){
                                                 flags[k] = false;
                                                 k += prime;
                                                 }
                                         count = count+1;
                                 }
                         }
                 }
         printf("\n%d primes\n",count);
         }



 SIMPLEIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SIMPLEIO.C

                                        /* Chapter 9 - Program 1 */
 "stdio.h"          /* standard header for input/output */

 main()
 {
 char c;

    printf("Enter any characters, X = halt program.\n");

    do {
       c = getchar();    /* get a single character from the kb   */
       putchar(c);       /* display the character on the monitor */
    } while (c != 'X');  /* until an X is hit                    */

    printf("\nEnd of program.\n");
 }


 SIMPSON.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SIMPSON.C

 /* 1.0  03-05-85 */
 /************************************************************************
  *                      Robert C. Tausworthe                                *
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, California 91009        1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"

 /*----------------------------------------------------------------------*
         This algorithm utilizes Simpson's extended rule, as published in
 HANDBOOK OF MATHEMATICAL FUNCTIONS, U. S. Department of Commerce,
 National Bureau of Standards, Applied Mathematics Series 55, June 1964,
 formula 25.4.6 on page 886.  The error is (n*h**5/90)*f''''(x) for some
 x in (lowlim, uplim), where h = (uplim - lowlim)/2n.                        *

 /************************************************************************/
         double
 simpson(func, lowlim, uplim, n)        /* return the integral of func from
                                    lowlim to uplim using Simpson's rule
                                    on 2n + 1 points.                        *
 /*----------------------------------------------------------------------*/

 double (*func)(), lowlim, uplim;
 {
         double x, y, odds, evens, h, h2, ends;
         int i;

         if (n <= 0)
         {        errno = EDOM;
                 return 0.0;
         }
         odds = evens = 0.0;
         ends = (*func)(lowlim) + (*func)(uplim);
         h2 = (uplim - lowlim) / n;
         h = h2 / 2.0;
         x = lowlim + h;                /* sum upward on odd points, downward
         y = uplim - h2;                /* on the even points.
         for (i = 1; i < n; i++, x += h2, y -= h2)
         {        odds += (*func)(x);
                 evens += (*func)(y);
         }
         odds += (*func)(x);
         return (h * (ends + 4.0 * odds + 2.0 * evens) / 3);
 }



 SIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SIN.C

 /* 1.1  07-08-85                                                (sin.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 125-149.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define R0        1.0
 #define R1        0.16666666666666665052e+00
 #define R2        0.83333333333331650314e-02
 #define R3        0.19841269841201840457e-03
 #define R4        0.27557319210152756119e-05
 #define R5        0.25052106798274584544e-07
 #define R6        0.16058936490371589114e-09
 #define R7        0.76429178068910467734e-12
 #define R8        0.27204790957888846175e-14

 C1        3.1416015625                        /* C1 - C2 = PI
 #define C2        8.9089102067615373566e-6;

 LOCAL double sincos();

 /*\p*********************************************************************/
         double
 sin(x)                                /* return trigonometric sine of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         if (x < 0.0)
                 return sincos(x, -x, 1);
         else
                 return sincos(x, x, 0);
 }

 /************************************************************************/
         double
 cos(x)                                /* return trigonometric cosine of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         return sincos(x, ABS(x) + PIover2, 0);
 }

 /************************************************************************/
         LOCAL double
 sincos(x, y, sgnflag)                /* compute both sine and cosine

 /*----------------------------------------------------------------------*/
 double x, y;
 {
         double f, xn, r, g;

         if (y >= MAXANGLE)
         {        errno = ERANGE;
                 return 0.0;
         }
         if (modf(y * INVPI, &xn) >= 0.5)
                 ++xn;
         if ((int)xn & 1)
                 sgnflag = !sgnflag;
         if (y ISNT ABS(x))
                 xn -= 0.5;
         g = modf(ABS(x), &x);
         f = ((x - xn * C1) + g) + xn * C2;
         if (ABS(f) > FADEOUT)
         {        g = f * f;
                 r = (((((((R8*g-R7)*g+R6)*g-R5)*g
                         +R4)*g-R3)*g+R2)*g-R1)*g;
                 f += f * r;
         }
         return (sgnflag ? -f : f);
 }


 SINE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\SINE.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/


 #include "math.h"
 #include "errno.h"

 double cos(x)
 double x;
 {
         double sincos();

         return sincos(x, fabs(x) + 1.57079632679489661923, 0);
 }

 double sin(x)
 double x;
 {
         double sincos();

         if (x < 0.0)
                 return sincos(x,-x,1);
         else
                 return sincos(x,x,0);
 }

 #define R1 -0.16666666666666665052e+00
 #define R2 +0.83333333333331650314e-02
 #define R3 -0.19841269841201840457e-03
 #define R4 +0.27557319210152756119e-05
 #define R5 -0.25052106798274584544e-07
 #define R6 +0.16058936490371589114e-09
 #define R7 -0.76429178068910467734e-12
 #define R8 +0.27204790957888846175e-14

 #define YMAX 6.7465e09

 static double sincos(x,y,sgn)
 double x,y;
 {
         double f, xn, r, g;
         extern int errno;

         if (y >= YMAX) {
                 errno = ERANGE;
                 return 0.0;
         }
         if (modf(y * 0.31830988618379067154, &xn) >= 0.5)
                 ++xn;
         if ((int)xn & 1)
                 sgn = !sgn;
         if (fabs(x) != y)
                 xn -= 0.5;
         g = modf(fabs(x), &x);          /* break into fraction and integer pa
         f = ((x - xn*3.1416015625) + g) + xn*8.9089102067615373566e-6;
         if (fabs(f) > 2.3283e-10) {
                 g = f*f;
                 r = (((((((R8*g R7)*g R6)*g R5)*g
                                 R4)*g R3)*g R2)*g R1)*g;
                 f += f*r;
         }
         if (sgn)
                 f = -f;
         return f;
 }



 SINGLEIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SINGLEIO.C

                                          /* Chapter 9 - Program 2 */
 #include <stdio.h>

 main()
 {
 char c;

    printf("Enter any characters, terminate program with X\n");

    do {
       c = getch();                     /* get a character */
       putchar(c);                  /* display the hit key */
    } while (c != 'X');

    printf("\nEnd of program.\n");
 }


 SINH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SINH.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 217-238.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define P0         -0.35181283430177117881e+6
 #define P1         -0.11563521196851768270e+5
 #define P2         -0.16375798202630751372e+3
 #define P3         -0.78966127417357099479e+0
 #define P(z)         (((P3*z P2)*z P1)*z P0)

 #define Q0         -0.21108770058106271242e+7
 #define Q1         +0.36162723109421836460e+5
 #define Q2         -0.27773523119650701667e+3
 #define Q3        +1.0
 #define Q(z)         (((z Q2)*z Q1)*z Q0)

 #define LNv        0.69316101074218750000
 #define Vm2        0.24999308500451499336
 #define Vov2m1        0.13830277879601902638e-4

 /*\p*********************************************************************/
         double
 sinh(x)                        /* return hyperbolic sine of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double y, w, z;
         FAST int sgn;

         if (x < 0.0)
         {        y = -x;
                 sgn = 1;
         }
         else
         {        y = x;
                 sgn = 0;
         }
         if (y > 1.0)
         {        w = y - LNv;
                 if (w > LOGINFINITY)
                 {        errno = ERANGE;
                         z = INFINITY;
                 }
                 else
                 {        z = exp(w);
                         if (w < PRECISION)
                                 z -= Vm2 / z;
                         z += Vov2m1 * z;
                 }
                 if (sgn)
                         z = -z;
         }
         else if (y < FADEOUT)
                 z = x;
         else
         {        z = x * x;
                 z = x + x * z *
                         P(z)
                         /Q(z);
         }
         return z;
 }


 SLO_FALL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\SLO_FALL.C



 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[1]==FALL_SLOW)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 SLO_RISE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\SLO_RISE.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[1]==RISE_SLOW)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 SNAP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\SNAP\SNAP.C



 /*  Memory snapshot routine written in DeSmet 'C'.
                 by Stan Peters, 813 Clara, Palo Alto, 94303.

         A debugging tool, useful for examining structures and file data.
         It is also a valuable learning aid for 'C' but requires that
         you have (or gain) dump reading ability.
         It should have good portability, as it was first written in BDS 'C'
         for a CP/M system.                           */


                         /* test of snap   */

 struct stype        {
         char line1[16];
         char line2[16];
         char line3[16];
         char *p1;
         char *p2;
         char *p3;
         char *p4;
 } s;

          char ss1[9];
          char ss2[9];
          int  s1;
          char ss3[9];
          int  s2;
          int  s3;
          char *ss;

 main()
 {
         for(s1 = 0; s1 <64 ;s1++)
                 s.line1[s1] = 1;                /* initialize snap target  */
         strcpy(s.line2,"line2 string");
         snap(s,32,"snap 1");
         strcpy(s.line1,"too long line1 string");
         snap(s,64,"snap 2");
         strcpy (s.line3,s.line1);
         s.p1 = s.line1;
         s.p2 = &s.line1;
         s.p3 = &s.p1;                        /* pointer  to string pointer */
         s.p4 = *s.p1;                        /* illogical, char to ptr
         snap(s,72,"snap 3");

         strcpy(ss1,"1 string");
         strcpy(ss2,"2 string");
         strcpy(ss3,"3 string");
         s1 = 1;   s2 = 2;  s3 = 3;
         ss = &ss1;
         snap(s,64,"snap 4");
 }

         /* routine displays memory as hex and characters  */

 char stst[80];                /* build space for snap line */

 snap(ptr,len,label)
         char  *ptr;                        /* start of area to be snapped */
         int    len;                        /* length */
         char  *label;
 {
         char        c;
         int                g,        h,        i,        j,        k,
         pl = ptr + len -1;
         printf("\n%s", label);
   for ( l = 0; l < len; l += 16)
   {
         for (g = 4; g < 80; g++)
                 stst[g] = ' ';                                        /* clea
         sprintf(stst,"\n%04x    ",ptr);                /* address of data  */
         i = 0;        j = 7;        k = 51;
         for ( g=0; g<4; g++)
         {
                 for ( h=0; h < 4 && pl >= ptr; h++)
                 {
                         c = *ptr++;
                         stst[j++] = makeasci(( c >> 4) & 0xf); /* left nibble
                         stst[j++] = makeasci( c & 0xf);       /* right nibble
                         if (( c < ' ') || (c > 0x7e))        /* now character
                                 c = '.';
                         stst[k++] = c;
                  }
                  j += 2;
                 /*        k++;                insert this to space rt side ch
         }
         stst[78] = 0;
         puts(stst);
   }
 }

 int         makeasci(c)
                 short        c;
                  {
                 return (( c > 9 ) ? c + 'A' - 10 : c + '0');
                 }


 SND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MIKES30C\SND.C

 /************************************************************************
   Demo of the sound.asm routine for Microsoft C 3.0.  Some very low
   freqs may cause divide error.

         void sound(duration, frequency);

      Enjoy!!   Mike's "C" Board 619-722-8724
 ************************************************************************/

 main()
 {
    int i, j;

    for(j = 0; j < 3; j++) {
       for(i = 100; i < 650; i += 25)
          sound(25, i);
       for(i = 650; i > 99; i -= 25)
          sound(25, i);
       }

 }


 SONGS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CTOOLBX1\SONGS.C

 extern j[250], jb[250], s[250], sb[250], w[250], wb[250], d[250], db[250];

 int melody[250];
 int beat[250];


 main()
 {

    int choice = 0, jx, i = 0;

       printf("\n\nThe following is a demonstration of the background\n");
       printf("music capability of the C Tool Box Library version 1.00\n");
       printf("It is simply written with no safeguards but does\n");
       printf("illustrate a method of obtaining more than one song\n");
       printf("played with the current command structure.  The \n");
       printf("background sound capability will be improved and \n");
       printf("restructured somewhat for the next major release.\n\n");

       printf("You may make a selection of songs to play\n");
       printf("but once a song starts to play do NOT attempt\n");
       printf("to rerun the program and start a new one.  Let\n");
       printf("the first song finish before starting a new one\n");
       printf("\n\nChoose\n\n   1.  Jingle Bells\n");
       printf("   2.  Sugar Plum Fairy\n");
       printf("   3.  We Wish You a Merry Xmas\n");
       printf("   4.  Deck the Halls\n");
       printf("   5.  End the Program\n");

       scanf("%d", &choice);

       if (choice == 1)
       {
          jx = 1;
          while (jx != 255)
          {
            melody[i] =  jx = j[i];
            beat[i]   = jb[i];
            i++;
          }
          jingle();
       }

       if (choice == 2)
       {
          jx = 1;
          while (jx != 255)
          {
            melody[i] = jx = s[i];
            beat[i]   = sb[i];
            i++;
          }
          spf();
       }

       if (choice == 3)
       {
          jx = 1;
          while (jx != 255)
          {
            melody[i] = jx = w[i];
            beat[i]   = wb[i];
            i++;
          }
          wwxmas();
       }

       if (choice == 4)
       {
          jx = 1;
          while (jx != 255)
          {
            melody[i] = jx = d[i];
            beat[i]   = db[i];
            i++;
          }
          deck();
       }
       printf("\n\n\We at Unicorn Software wish you and yours the\n");
       printf("very best of holiday seasons.\n\n");
 }


 SORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\SORT.C

 #include          <stdio.h>
 #include          <ctype.h>

  MAXWORD  80                           /* maximum word length */
  NEWLINE  putc('\n',fp)     /* put carraige return in file fp */

 struct text {               /* global declaration of tree node 'text' */
              char word[MAXWORD];
              struct text *lptr;
              struct text *rptr;
 };

 struct text *root;         /* global declaration of root of text tree */

 main(argc, argv)
   /*-----------------------------------------------------------------*/
   /* driver for sort procedure.  Srt will sort lines of a specified  */
   /* input file and place the result in either the stdout or a       */
   /* specified output file.  Program is written for Lattice C but    */
   /* functions provided in its library are documented so that srt    */
   /* might be modified to suit your compiler.  If you have any       */
   /* trouble or questions give me a call (if you can find me)        */
   /*-----------------------------------------------------------------*/
   /* Joe R Wyatt    2311 49th Lubbock, Tx 79412                      */
   /* Home #: 806/793-5689    Office #: 806/763-8011 ext: 239         */
   /*-----------------------------------------------------------------*/
   /* Variables :        fp --     pointer to input file              */
   /*                   fp2 --     ptr to output file                 */
   /*                     c --     integer returned from getw.        */
   /*                     i --     processed line count               */
   /*                     j --     empty line count                   */
   /*                  word --     temporary input line storage       */
   /* Procedures:      getw --     included                           */
   /*                 putwt --     included                           */
   /*                 ptree --     included                           */
   /* Functions :    printf --     string compare                     */
   /*                 fopen --     open file and return file pointer  */
   /*                  exit --     premature exit from program        */
   /*                fclose --     close file                         */
   /*-----------------------------------------------------------------*/
 int argc;
 char *argv[];
 {
      FILE *fp, *fp2, *fopen();
      int c, i, j;
      char word[MAXWORD];

      root = NULL;                                /* root of text tree */
      if (argc == 1)  {                  /* no file specified for sort */
           printf("usage: srt infile.ext <outfile.exe>\n");
           exit(0);
      }
      else{                                         /* open input file */
           if ((fp = fopen(*(argv+1), "r")) == NULL) {
                printf("cannot read %s\n",*(argv+1));
                exit(1);
           }
           if (argc == 3) {                        /* open output file */
                if ((fp2 = fopen(*(argv+2), "w")) == NULL) {
                     printf("cannot open %s \n",*argv[3]);
                     exit(1);
                }
           }
           else
                fp2 = stdout;                   /* no output specified */
      }
      i = 0;
      j = 0;
      while((c = getw(fp,word)) != EOF) {     /* get next line of file */
           if (strlen(word) != 0) {
                putwt(word);           /* if not null then put in tree */
                i++;            /* increment number of lines processed */
           }
           else
                j++;                 /* else inc number of empty lines */
      }
      fclose(fp);
      ptree(fp2, root);                           /* print sorted tree */
      printf("\nprocedure concluded.\n%d lines processed\n",i);
      printf("%d empty lines ignored.\n",j);
      fclose(fp2);
 }

 putwt(w)
   /*-----------------------------------------------------------------*/
   /* procedure places 'w' in tree named 'text'.                      */
   /* Parameters:         w --     null ended string                  */
   /* Variables :      temp --     temporary pointer                  */
   /*                   ptr --     ptr to node to place 'w' in.       */
   /*                 value --     result of strcmp used for placement*/
   /*                              in text tree.                      */
   /* Procedures:    search --     included                           */
   /* Functions :    strcmp --     string compare                     */
   /*                getmem --     allocate memory for tree           */
   /*                sizeof --     return size of structure           */
   /*                printf --     print string to stdout             */
   /*                strcpy --     string copy                        */
   /*                  exit --     leave prgram prematurly            */
   /*-----------------------------------------------------------------*/
 char *w;
 {
      struct text *search(), *temp, *ptr;
      int value = 1;

      temp = search(w);  /* locate position to place new node in tree */

      if (temp != NULL) /* if NULL then tree is empty. else compare keys */
           value = strcmp(w, temp -> word);
      if (value == 0)                    /* duplicate entry.  ignore. */
           return;

      ptr = (struct text *)getmem(sizeof(struct text));
      if (ptr == NULL) {                   /* memory allocation error */
           printf("out of memory\n");
           exit(1);
      }
        strcpy(ptr -> word, w);                     /* store new node */
        ptr -> lptr = NULL;
        ptr -> rptr = NULL;

      if (temp != NULL) {                   /* place new node in tree */
           if (value > 0)
                temp -> rptr = ptr;
           else
                temp -> lptr = ptr;
           }
      else
           root = ptr;
      return;
 }

 struct text *search(w)
   /*-----------------------------------------------------------------*/
   /* procedure locates where 'w' is to be placed in text tree and    */
   /* returns pointer to prior node.                                  */
   /* procedure places 'w' in tree named 'text'.                      */
   /* Parameters:         w --     null ended string                  */
   /* Variables :      ptr1 --     temporary pointer                  */
   /*                  ptr2 --     lags ptr1 by one node              */
   /*                 value --     result of strcmp used for placement*/
   /*                              in text tree.                      */
   /* Functions :    strcmp --     string compare                     */
   /*-----------------------------------------------------------------*/
 char *w;
 {
      struct text *ptr1;
      struct text *ptr2;
      int value;

      ptr1 = root;                             /* initialize pointers */
      ptr2 = root;
      while(ptr1 != NULL) {
           ptr2 = ptr1;
           value = strcmp(w, ptr1 -> word);
           if (value > 0)
                ptr1 = ptr1 -> rptr;
           else if (value < 0)
                ptr1 = ptr1 -> lptr;
           else
                ptr1 = NULL;
      }
      return(ptr2);
 }

 ptree(fp, ptr)
   /*-----------------------------------------------------------------*/
   /* recursive procedure to print contents of text tree.             */
   /* Parameters:        fp --     pointer to output file.            */
   /*                   ptr --     pointer to root of current subtree */
   /* Procedures:      putw --     included                           */
   /*-----------------------------------------------------------------*/
 FILE *fp;
 struct text *ptr;
 {
      if (ptr != NULL) {
           ptree(fp, ptr -> lptr);   /* find leftmost node of subtree */
           putw(fp, ptr -> word);                       /* print data */
           ptree(fp, ptr -> rptr);             /* print right subtree */
      }
 }

 EOW -2    /* end of word */
 getw(fp,w)
   /*-----------------------------------------------------------------*/
   /* gets next line in input file.                                   */
   /* Parameters:        fp --     pointer to input file              */
   /*                     w --     pointer to string for input        */
   /* Variables :         c --     input character                    */
   /*                     f --     end of word flag                   */
   /*                 count --     number of characters               */
   /* Functions :      getc --     get byte from input file           */
   /*-----------------------------------------------------------------*/
 FILE *fp;
 char *w;
 {
      int c,f,count;

      f = 0;                                 /* initialize local vars */
      count = 0;
      while (f != EOW && count < MAXWORD) {
           c = getc(fp);
           if (c != EOF && c != '\n') {       /* input to end of line */
                count++;                    /* increment byte counter */
                *w++ = c;
           }
           else
                f = EOW; /* end of line reached or max chars exceded. */
      }
      *w = '\0';                  /* place null byte on end of string */
      return(c);                         /* return last byte of input */
 }

 putw(fp,w)
   /*-----------------------------------------------------------------*/
   /* prints string to output file.                                   */
   /* Parameters:        fp --     pointer to input file              */
   /*                     w --     pointer to string for input        */
   /* Variables :         c --     output character                   */
   /* Functions :      putc --     put byte to output file            */
   /*-----------------------------------------------------------------*/
 FILE *fp;
 char *w;
 {
      int c;

      while (*w != '\0')
           putc(*w++, fp);
      NEWLINE;
 }


 SORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\SORT.C


 /*
 ** BYTE Sort Benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** Feb. 17, 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** Sorts integer array of random numbers using 3 methods:
 ** QUICKSORT
 ** SHELLSORT
 ** HEAPSORT
 **
 ** The QUICKSORT and HEAPSORT algorithms used were adapted from
 ** examples given by G.H. Gonnet in his excellent HANDBOOK OF
 ** ALGORITHMS AND DATA STRUCTURES -- Addison Wesley
 ** ISBN 0-201-14218-X.
 ** The SHELLSORT algorithms was adapted from a version presented
 ** in Neill Graham's MICROPROCESSOR PROGRAMMING FOR COMPUTER
 ** HOBBYISTS, Tab Books, ISBN 0-8306-6952-3.
 **
 ** The benchmark operates as follows:
 ** 1. Build an array of random integers.
 ** 2. Turn on the stopwatch.
 ** 3. Perform QUICKSORT
 ** 4. Turn off the stopwatch.
 ** 5. Accumulate total time.
 ** 6. Re-build array of random integers.
 ** 7. Turn on the stopwatch.
 ** 8. Perform SHELLSORT.
 ** 9. Turn off the stopwatch.
 ** 10. Add elapsed time to total.
 ** 11. Re-build array of random integers.
 ** 12. Turn on the stopwatch.
 ** 13. Perform HEAPSORT.
 ** 14. Turn off the stopwatch.
 ** 15. Add elapsed time to total.
 ** 16. Print out results.
 **
 */

 stdio.h                /* Standard I/O */
 ASIZE 8000                /* Array size */

 int tblock[4];                        /* Timer block */
 int tacc[4];                        /* Timer accumulator */
 int seed;                        /* Random number seed */

 main()
 {
         int sarray[ASIZE];        /* Array to sort */

         /* Announce yourself */
         printf("BYTE Sort Benchmark\n\n");

         /* Build random array */
         seed=0;
         getrand(sarray);

         printf("--QUICKSORT\n");
         /* Turn on timer */
         gtime(tblock);

         /* QUICKSORT */
         qsort(sarray,0,ASIZE-1);

         /* Turn off timer and accumulate time */
         calctim(tblock);
         acctime();

         /* Build another random array */
         seed=0;
         getrand(sarray);

         printf("--SHELLSORT\n");
         /* Turn on timer */
         gtime(tblock);

         /* SHELLSORT */
         shsort(sarray,0,ASIZE-1);

         /* Turn off timer and accumulate time */
         calctim(tblock);
         acctime();

         /* Build another random array */
         seed=0;
         getrand(sarray);

         /* Turn on timer */
         gtime(tblock);

         printf("--HEAPSORT\n");
         /* HEAPSORT */
         hsort(sarray,0,ASIZE-1);

         /* Turn off timer and accumulate time */
         calctim(tblock);
         acctime();

         /* Report */

         printf("Total sorting time: (HH:MM:SS:1/100)\n");
         printf("%d:%d:%d:%d\n\n",tacc[0],tacc[1],tacc[2],tacc[3]);

         printf("Press RETURN for operating system:");
         fgetc(stdin);
         exit(0);

 }

 /* QUICKSORT
 ** qsort(array,bot,top)
 ** int array[] - array to sort
 ** bot - Index to first element in array[]
 ** top - Index to last element in array[]
 */
 qsort(aray,bot,top) int aray[],bot,top;
 {
         int i,j,temp;

   while(bot<top) {

         /* Set ranges and choose partitioning element */
         i=bot;
         j=top;
         temp=aray[bot];

         /* Partition array */
         while(i<j) {
           while(aray[j]>temp) j-=1;
           aray[i]=aray[j];
           while((i<j)&&(aray[i]<=temp)) i+=1;
           aray[j]=aray[i];
         }
         aray[i]=temp;

         /* Call qsort recursively */
         qsort(aray,bot,i-1);
         bot=i+1;
   }
 }

 /*
 ** SHELLSHORT
 ** shsort(array,bot,top)
 ** int array[] - array to sort
 ** bot - Index to first element in array[]
 ** top - Index to last element in array[]
 */
 shsort(aray,bot,top) int aray[],bot,top;
 {
         int i,gap,nex,temp;


         gap=(top-bot)/2;        /* Set gap width */
         do {
           do {
                 nex=1;                /* No exchanges yet */
                 for(i=0;i<=top-gap;++i )
                 {  if(aray[i]>aray[i+gap])
                    {  temp=aray[i];
                       aray[i]=aray[i+gap];
                       aray[i+gap]=temp;
                       nex=0;        /* An exchange happened */
                    }
                 }
           } while(nex==0);
           gap=gap/2;
         } while(gap!=0);

 }

 /*
 ** HEAPSORT
 ** hsort(aray,bot,top)
 ** int array[] - array to sort
 ** bot - Index to first element in array[]
 ** top - Index to last element in array[]
 */
 hsort(aray,bot,top) int aray[],bot,top;
 {
         int i,temp;

         /* First...make a heap */
         for(i=(top/2);i>1;--i)
                 sift(aray,i,top);
         /* Extract maximum */
         for(i=top;i>1;--i) {
           sift(aray,0,i);
           temp=aray[0];
           aray[0]=aray[i];
           aray[i]=temp;
         }
 }

 sift(aray,i,j) int aray[],i,j;
 {
         int k,temp;

         while((2*i)<=j) {
           k=2*i;
           if(k<j)
             if(aray[k]<aray[k+1]) ++k;

           if(aray[i]<aray[k]) {
             temp=aray[k];
             aray[k]=aray[i];
             aray[i]=temp;
             i=k;
           }
           else i=j+1;
         }
         return;
 }

 /*
 ** Getrand()
 ** Builds an array of random numbers.
 */
 getrand(array) int array[];
 {
         int i;

         for(i=0;i<ASIZE;++i) {
                 seed=rand(seed);
                 array[i]=seed;
         }
 }

 /*
 ** acctime()
 ** Accumulate time stored in tblock[] into tacc[]
 */
 acctime()
 {
         tacc[3]+=tblock[3];        /* Hundredths */
         if(tacc[3]>=100) {
                 tacc[2]+=1;
                 tacc[3]-=100;
         }
         tacc[2]+=tblock[2]; /* Seconds */
         if(tacc[2]>=60) {
                 tacc[1]+=1;
                 tacc[2]-=60;
         }
         tacc[1]+=tblock[1]; /* Minutes */
         if(tacc[1]>=60) {
                 tacc[0]+=1;
                 tacc[1]-=60;
         }
         tacc[0]+=tblock[0];        /* Hours */
         return;
 }



 SORTB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SORTB.C

 /* 1.0  11-12-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Bubble-sort subroutine, using the usual shuttle algorithm,
  *        such as found in JPL's MBASIC(tm) user's manual.  It also appears
  *        in
  *
  *        Tausworthe, Robert, STANDARDIZED DEVELOPMENT OF COMPUTER SOFTWARE,
  *        Part I, Methods, Prentice-Hall, Inc., Englewood Cliffs, NJ, 1976.
  *
  *        It is written so the array type is unknown to the algorithm, but is
  *        known to comp() and exch().  The comparison function comp(i, j)
  *        must be positive if, and only if, the array elements indexed by
  *        i and j are out of sort.  The function exch(i, j) must exchange
  *        elements indexed by i and j.
  *
  */

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         VOID
 sortB(n, comp, exch)        /* Bubble sort array[0..(n-1)] compared by index
                            function comp(i, j), and exchanged by
                            index function exch(i, j).
 /*----------------------------------------------------------------------*/
 unsigned n;
 int (*comp)();
 VOID (*exch)();
 {
         FAST unsigned i, j, k, m;

         for (i = 0, j = 1; i < n - 1; i++, j++)
                 if ((*comp)(i, j) > 0)
                 {        (*exch)(i, j);
                         for (k = i; k > 0 AND (*comp)(m=k-1, k) > 0; k--)
                                 (*exch)(m, k);
                 }
 }


 SORTDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\SORTDIR.C

 /***********************************************************************
         SORTDIR.C
         (c) Rex Conn 12/10/84

 SORTDIR does a physical sort of your disk directory.  It will perform
 either a disk-based sort (for the root directory) or a file sort (for
 subdirectories).  It requires DOS 2.0/2.1 to run, and should handle non-
 standard media ok.  (I've tested it on a Bernoulli Box and on quad
 density diskettes, but if you have strange media, test SORTDIR before
 extensive use.)  SORTDIR was created using Computer Innovations C86.

 SORTDIR will sort system files first, then hidden files, then the volume
 name, then any subdirectory names, and finally the normal files, all in
 straight ASCII sequence order.

 To run, just type SORTDIR at the DOS prompt.  There are no options;
 SORTDIR will only sort your current directory.

 Good luck, and use at your own risk!

 p.s.:  SORTDIR will NOT work with DOS 3.0 and DOS 3.1

 ************************************************************************/

 #include "stdio.h"

 /* structure for directory entries */
 struct dnode {
         unsigned char att;
         unsigned char direntry[32];
 } *dir[1024];

 /* FCB structure */
 struct filecontrol {
         unsigned char extended[7];
         unsigned char drive[1];
         unsigned char filename[11];
         int blocknum;
         int lrecsize;
         long filesize;
         int fdate;
         unsigned char reserved[10];
         unsigned char lrecnum;
         long recnum;
 } fcb;

 struct regval srv,rrv;
 struct segments segregs;

 unsigned char buf[80],*ptr,buffer[512],bdos(),*strrchr(),*malloc();

 int        i,j,n,nextfree;
 int        dirsector,numsectors,disk;

 /* comparison routine for QSORT */
 comp(a,b)
 unsigned char **a,**b;
 {
         return strcmp(*a,*b);
 }

 main()
 {
         bdos(9,"Sortdir ver. 1.1\r\n$");
         buf[0] = '\\';
         segread(&segregs);
         srv.ds = segregs.sds;
         /* get current directory */
         srv.ah = 0x47;
         srv.dx = 0;
         srv.si = buf+1;
         sysint21(&srv,&rrv);
         /* if in root, sort disk */
         if (buf[1] == '\0') {
                 /* determine type of disk to get directory */
                 disk = bdos(0x19);
                 srv.ah = 0x32;
                 srv.dx = 0;
                 sysint21(&srv,&rrv);
                 dirsector = peek(rrv.bx+16,rrv.ds);
                 i = peek(rrv.bx+9,rrv.ds);
                 numsectors = (i % 32) ? (i / 32) + 1 : i / 32;
                 /* read directory block from disk */
                 nextfree = 0;
                 for (i=dirsector;i<dirsector + numsectors;i++) {
                         getsect(disk,buffer,0,i,1);
                         for (n=0;n<512;n+=32) {
                                 if (buffer[n] == '\0') {
                                         i = dirsector + numsectors;
                                         break;
                                 }
                                 dir[nextfree] = malloc(sizeof(struct dnode));
                                 movmem(buffer+n,dir[nextfree]->direntry,32);
                                 subsort(nextfree);
                                 nextfree++;
                         }
                 }
                 /* sort the block */
                 qsort(dir,nextfree,PTRSIZE,comp);
                 /* write it back to the disk */
                 for (j=0,i=dirsector;i<dirsector + numsectors;i++) {
                         for (n=0;n<512;n++)
                                 buffer[n] = '\0';
                         for (n=0;n<512;n+=32) {
                                 movmem(dir[j]->direntry,buffer+n,32);
                                 if (++j >= nextfree)
                                         break;
                         }
                         getsect(disk,buffer,1,i,1);
                         if (j >= nextfree)
                                 break;
                 }
                 srv.ah = 0x32;                        /* force BPB read */
                 srv.dx = 0;                        /* default disk?? */
                 sysint21(&srv,&rrv);
                 pokeb(rrv.bx+23,rrv.ds,-1);
                 sysint21(&srv,&rrv);
         } else {                /* else sort subdirectory file */
                 srv.ah = 0x3B;                /* change directory */
                 srv.dx = "..";
                 sysint21(&srv,&rrv);
                 fcb.extended[0] = 0xFF;
                 fcb.extended[6] = 16;
                 ptr = strrchr(buf,'\\') + 1;
                 for (i=0;i<11;i++) {
                         if ((*ptr == '.') && (i == 8))
                                 ptr++;
                         if ((*ptr) && (*ptr != '.'))
                                 fcb.filename[i] = *ptr++;
                         else
                                 fcb.filename[i] = ' ';
                 }
                 srv.ah = 0x0F;                /* open the file */
                 srv.dx = &fcb;
                 sysint21(&srv,&rrv);
                 if (rrv.al == 0xFF)
                         error("Can't open subdirectory\n$");
                 fcb.lrecsize = 32;        /* directory entry size */
                 fcb.lrecnum = 0;

                 fcb.filesize = 32768;
                 bdos(0x1A,buffer);
                 nextfree = 0;
                 srv.ah = 0x14;                /* sequential read */
                 do {
                         sysint21(&srv,&rrv);
                         if (buffer[0] == '\0')        /* end of directory */
                                 break;
                         dir[nextfree] = malloc(sizeof(struct dnode));
                         movmem(buffer,dir[nextfree]->direntry,32);
                         subsort(nextfree);
                         nextfree++;
                 } while (rrv.al == 0);
                 qsort(dir,nextfree,PTRSIZE,comp);
                 fcb.blocknum = 0;                /* reset block number */
                 fcb.lrecnum = 0;
                 for (i=0;i<nextfree;i++) {
                         srv.ah = 0x15;                /* sequential write */
                         bdos(0x1A,dir[i]->direntry);
                         sysint21(&srv,&rrv);
                 }
                 srv.ah = 0x10;                        /* close the subdirecto
                 srv.dx = &fcb;
                 sysint21(&srv,&rrv);
                 srv.ah = 0x3B;                        /* change directory */
                 srv.dx = buf;
                 sysint21(&srv,&rrv);
         }
 }

 /* sort labels first, then hidden files, then subdirs, then everything else *
 subsort(a)
 int a;
 {
         if (dir[a]->direntry[0] == '.')                /* root directory entr
                 dir[a]->att = 1;
         else if (dir[a]->direntry[11] & 4)        /* system file */
                 dir[a]->att = 2;
         else if (dir[a]->direntry[11] & 2)        /* hidden file? */
                 dir[a]->att = 3;
         else if (dir[a]->direntry[11] & 8)        /* volume label? */
                 dir[a]->att = 4;
         else if (dir[a]->direntry[11] & 16)        /* subdirectory? */
                 dir[a]->att = 5;
         else
                 dir[a]->att = 6;
 }

 /* print error message and abort */
 error(s)
 unsigned char *s;
 {
         bdos(9,s);
         _exit(1);
 }



 SORTDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SORTDIR.C

 /***********************************************************************
         SORTDIR.C
         (c) Rex Conn 12/10/84

 SORTDIR does a physical sort of your disk directory.  It will perform
 either a disk-based sort (for the root directory) or a file sort (for
 subdirectories).  It requires DOS 2.0/2.1 to run, and should handle non-
 standard media ok.  (I've tested it on a Bernoulli Box and on quad
 density diskettes, but if you have strange media, test SORTDIR before
 extensive use.)  SORTDIR was created using Computer Innovations C86.

 SORTDIR will sort system files first, then hidden files, then the volume
 name, then any subdirectory names, and finally the normal files, all in
 straight ASCII sequence order.

 To run, just type SORTDIR at the DOS prompt.  There are no options;
 SORTDIR will only sort your current directory.

 Good luck, and use at your own risk!

 p.s.:  SORTDIR will NOT work with DOS 3.0 and DOS 3.1

 ************************************************************************/

 #include "stdio.h"

 /* structure for directory entries */
 struct dnode {
         unsigned char att;
         unsigned char direntry[32];
 } *dir[1024];

 /* FCB structure */
 struct filecontrol {
         unsigned char extended[7];
         unsigned char drive[1];
         unsigned char filename[11];
         int blocknum;
         int lrecsize;
         long filesize;
         int fdate;
         unsigned char reserved[10];
         unsigned char lrecnum;
         long recnum;
 } fcb;

 struct regval srv,rrv;
 struct segments segregs;

 unsigned char buf[80],*ptr,buffer[512],bdos(),*strrchr(),*malloc();

 int        i,j,n,nextfree;
 int        dirsector,numsectors,disk;

 /* comparison routine for QSORT */
 comp(a,b)
 unsigned char **a,**b;
 {
         return strcmp(*a,*b);
 }

 main()
 {
         bdos(9,"Sortdir ver. 1.1\r\n$");
         buf[0] = '\\';
         segread(&segregs);
         srv.ds = segregs.sds;
         /* get current directory */
         srv.ah = 0x47;
         srv.dx = 0;
         srv.si = buf+1;
         sysint21(&srv,&rrv);
         /* if in root, sort disk */
         if (buf[1] == '\0') {
                 /* determine type of disk to get directory */
                 disk = bdos(0x19);
                 srv.ah = 0x32;
                 srv.dx = 0;
                 sysint21(&srv,&rrv);
                 dirsector = peek(rrv.bx+16,rrv.ds);
                 i = peek(rrv.bx+9,rrv.ds);
                 numsectors = (i % 32) ? (i / 32) + 1 : i / 32;
                 /* read directory block from disk */
                 nextfree = 0;
                 for (i=dirsector;i<dirsector + numsectors;i++) {
                         getsect(disk,buffer,0,i,1);
                         for (n=0;n<512;n+=32) {
                                 if (buffer[n] == '\0') {
                                         i = dirsector + numsectors;
                                         break;
                                 }
                                 dir[nextfree] = malloc(sizeof(struct dnode));
                                 movmem(buffer+n,dir[nextfree]->direntry,32);
                                 subsort(nextfree);
                                 nextfree++;
                         }
                 }
                 /* sort the block */
                 qsort(dir,nextfree,PTRSIZE,comp);
                 /* write it back to the disk */
                 for (j=0,i=dirsector;i<dirsector + numsectors;i++) {
                         for (n=0;n<512;n++)
                                 buffer[n] = '\0';
                         for (n=0;n<512;n+=32) {
                                 movmem(dir[j]->direntry,buffer+n,32);
                                 if (++j >= nextfree)
                                         break;
                         }
                         getsect(disk,buffer,1,i,1);
                         if (j >= nextfree)
                                 break;
                 }
                 srv.ah = 0x32;                        /* force BPB read */
                 srv.dx = 0;                        /* default disk?? */
                 sysint21(&srv,&rrv);
                 pokeb(rrv.bx+23,rrv.ds,-1);
                 sysint21(&srv,&rrv);
         } else {                /* else sort subdirectory file */
                 srv.ah = 0x3B;                /* change directory */
                 srv.dx = "..";
                 sysint21(&srv,&rrv);
                 fcb.extended[0] = 0xFF;
                 fcb.extended[6] = 16;
                 ptr = strrchr(buf,'\\') + 1;
                 for (i=0;i<11;i++) {
                         if ((*ptr == '.') && (i == 8))
                                 ptr++;
                         if ((*ptr) && (*ptr != '.'))
                                 fcb.filename[i] = *ptr++;
                         else
                                 fcb.filename[i] = ' ';
                 }
                 srv.ah = 0x0F;                /* open the file */
                 srv.dx = &fcb;
                 sysint21(&srv,&rrv);
                 if (rrv.al == 0xFF)
                         error("Can't open subdirectory\n$");
                 fcb.lrecsize = 32;        /* directory entry size */
                 fcb.lrecnum = 0;

                 fcb.filesize = 32768;
                 bdos(0x1A,buffer);
                 nextfree = 0;
                 srv.ah = 0x14;                /* sequential read */
                 do {
                         sysint21(&srv,&rrv);
                         if (buffer[0] == '\0')        /* end of directory */
                                 break;
                         dir[nextfree] = malloc(sizeof(struct dnode));
                         movmem(buffer,dir[nextfree]->direntry,32);
                         subsort(nextfree);
                         nextfree++;
                 } while (rrv.al == 0);
                 qsort(dir,nextfree,PTRSIZE,comp);
                 fcb.blocknum = 0;                /* reset block number */
                 fcb.lrecnum = 0;
                 for (i=0;i<nextfree;i++) {
                         srv.ah = 0x15;                /* sequential write */
                         bdos(0x1A,dir[i]->direntry);
                         sysint21(&srv,&rrv);
                 }
                 srv.ah = 0x10;                        /* close the subdirecto
                 srv.dx = &fcb;
                 sysint21(&srv,&rrv);
                 srv.ah = 0x3B;                        /* change directory */
                 srv.dx = buf;
                 sysint21(&srv,&rrv);
         }
 }

 /* sort labels first, then hidden files, then subdirs, then everything else *
 subsort(a)
 int a;
 {
         if (dir[a]->direntry[0] == '.')                /* root directory entr
                 dir[a]->att = 1;
         else if (dir[a]->direntry[11] & 4)        /* system file */
                 dir[a]->att = 2;
         else if (dir[a]->direntry[11] & 2)        /* hidden file? */
                 dir[a]->att = 3;
         else if (dir[a]->direntry[11] & 8)        /* volume label? */
                 dir[a]->att = 4;
         else if (dir[a]->direntry[11] & 16)        /* subdirectory? */
                 dir[a]->att = 5;
         else
                 dir[a]->att = 6;
 }

 /* print error message and abort */
 error(s)
 unsigned char *s;
 {
         bdos(9,s);
         _exit(1);
 }



 SORTH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SORTH.C

 /* 1.0  11-12-84
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Heapsort subroutine, using an iterative form of the usual
  *        recursive algorithm, such as found in
  *
  *        Aho, A. V., Hopcroft, J. E., and Ullmann, J. D., THE DESIGN AND
  *        ANALYSIS OF ALGORITHMS, Addison-Wesley Pub. Co., pp. 87-92.
  *
  *        The function is written so the array type is unknown to the
  *        algorithm, but is known to comp() and exch().  The comparison
  *        function comp(i, j) must be positive if, and only if, the array
  *        elements indexed by i and j are out of sort.  The function
  *        exch(i, j) must exchange the elements at indices i and j.
  */

 #include "defs.h"
 #include "stdtyp.h"

 int         (*gcomp)();        /* global compare and exchange functions */
 VOID         (*gexch)();

 /************************************************************************/
         VOID
 sortH(n, comp, exch)        /* Heapsort array of 0..(n-1) items compared
                            by comp(i,j), exchanged by exch(i,j)         */
 /*----------------------------------------------------------------------*/
 unsigned n;
 int (*comp)();
 VOID (*exch)();
 {
         unsigned i;
         int j;

         gcomp = comp;                /* set functions global to this subrouti
         gexch = exch;

         for (j = n-- / 2 - 1; j >= 0; j--)        /* build heap. n is now
                 heap(j, n);                /* the index of the last element.
         for (i = n; i > 0; )
         {        (*gexch)(0, i--);
                 heap(0, i);
         }
 }

 /*\p*********************************************************************/
         LOCAL VOID
 heap(dad, rightmost)        /* build heap from (dad-1)-st to (rightmost-1)-st
                            elements of the array.                        */
 /*----------------------------------------------------------------------*/
 unsigned dad, rightmost;
 {                        /* Array to sort in heapsort algorithm is 1..n, */
                         /* but arrays in C go 0..(n-1). Thus the offset.*/

         unsigned son, r;

         FOREVER
         {        if ((son = 2 * dad + 1) > rightmost) /* if no sons remain, *
                         return;
                 if (son < rightmost)        /* if both right and left sons
                         if ((*gcomp)(r = son + 1, son) > 0)
                                 son = r;
                 /* son is now the index of the maximum son-element of dad */
                 if ((*gcomp)(son, dad) > 0)
                 {        (*gexch)(son, dad);
                         dad = son;
                 }
                 else
                         return;
         }
 }


 SORTL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\SORTL.C

 /*                  Sort Lines

         This file contains the function that sorts the lines that
         rsort.c read in.
 */

 #include <stdio.h>
 #include <string.h>
 #include "rsort.h"

 /*      sortLines()

         Function: Sort the lPtr array according to the lines pointed
         to by lPtr[].start; but sort from the column pointed to by
         lPtr[].sortAt.

         Algorithm: A selection sort. The smallest item is found and
         swaped with the first entry, then the smallest of the remaining
         items is found, then... Until the entire array is sorted.

         Comments: strcmp() is used to compare lines, which defines
         what we mean by "sorted." There are other definitions that
         could make sense here, from fairly simple ones like descending
         order to much more exotic ones.
 */

 sortLines()

 {
         struct linePtr *sortLPtr;       /* Start of unsorted lines. */
         struct linePtr *srchLPtr;       /* Line being checked now. */
         struct linePtr *lowLPtr;        /* Lowest line found so far. */
         struct linePtr newLPtr;         /* Temp for swapping sort/low. */

         /* For each line in the array... */
         for (sortLPtr = lPtr; sortLPtr < nextLPtr; sortLPtr++) {
                 /* Find the lowest remaining line. */
                 for (lowLPtr = srchLPtr = sortLPtr;
                      srchLPtr < nextLPtr; srchLPtr++)
                         if (strcmp(lowLPtr->sortAt,srchLPtr->sortAt) > 0)
                                 lowLPtr = srchLPtr;
                 /* Swap it with the first unsorted line. */
                 newLPtr = *sortLPtr;
                 *sortLPtr = *lowLPtr;
                 *lowLPtr = newLPtr;
         };
 }



 SORTQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SORTQ.C

 /* 1.0  11-12-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Quicksort subroutine, using the usual C. A. R. Hoare recursive
  *        algorithm, such as described in
  *
  *        Knuth, D. E., FUNDAMENTAL ALGORITHMS, Vol. III, "Sorting and
  *        Searching," Addison-Wesley, pp. 116.
  *
  *        It is written so the array type is unknown to the algorithm, but is
  *        known to comp() and exch().  The comparison function comp(i, j)
  *        must be positive if, and only if, the array elements indexed by
  *        i and j are out of sort.  The function exch(i, j) must exchange
  *        array elements indexed by i and j.
  */

 #include "defs.h"
 #include "stdtyp.h"

 int         (*gcomp)();        /* global compare and exchange functions */
 VOID         (*gexch)();

 /************************************************************************/
         VOID
 sortQ(n, comp, exch)                /* Quicksort array of n items compared by
                                    comp(i, j), exchanged by exch(i, j)
 /*----------------------------------------------------------------------*/
 unsigned n;
 int (*comp)();
 VOID (*exch)();
 {
         VOID quick();

         gcomp = comp;                /* set functions global to this subrouti
         gexch = exch;
         quick(0, n - 1);        /* quicksort from 0 to n-1 */
 }

 /*\p*********************************************************************/
         LOCAL VOID
 quick(low, high)                /* quicksort array from low to high.        *

 /*----------------------------------------------------------------------*/
 unsigned low, high;
 {
         unsigned j, partition();

         if (low < high)
         {        if ((j = partition(low, high)) IS low)
                         quick(low + 1, high);        /* lower segment empty
                 else if (j IS high)
                         quick(low, j-1);        /* upper segment empty
                 else if (j - low < high - j)
                 {        quick(low, j - 1);        /* smaller segment first *
                         quick(j + 1, high);        /* minimizes stack depth.*
                 }
                 else
                 {        quick(j + 1, high);
                         quick(low, j - 1);
                 }
         }
 }

 /************************************************************************/
         LOCAL unsigned
 partition(low, high)        /* partition into lower and upper sets and return
                            index of middle (sorted) element.                *
 /*----------------------------------------------------------------------*/
 unsigned low, high;
 {
         (*gexch)(low, (low+high)/2);        /* partition on middle element
         do
         {        while (low < high AND (*gcomp)(low, high) <= 0)
                         high--;        /* find unsorted higher element
                 if (high ISNT low)
                 {        (*gexch)(low, high);
                         while (low < high AND (*gcomp)(low, high) <= 0)
                                 low++;        /* find unsorted lower element
                         if(low ISNT high)
                                 (*gexch)(low, high);
                 }
         } while(low ISNT high);
         return low;
 }


 SORTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SORTS.C

 /* 1.0  11-12-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Shell sort subroutine, programmed using the algorithm in
  *
  *        Kernighan, B. W., and Ritchie, D. M., THE C PROGRAMMING LANGUAGE,
  *        Prentice-Hall Software Series, Englewood Cliffs, NJ, 1978,
  *        pages 58 and  117.
  *
  *        It is written so the array type is unknown to the algorithm, but
  *        known to comp() and exch().  The comparison function comp(i, j)
  *        must be positive if, and only if, the array elements at i and j
  *        are out of sort.  The function exch(i, j) must exchange array
  *        elements indexed by i and j.
  *
  */

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         VOID
 sortS(n, comp, exch)                /* Shell sort array of n items compared b
                                    comp(i, j), exchanged by exch(i, j).
 /*----------------------------------------------------------------------*/
 unsigned n;
 int (*comp)();
 VOID (*exch)();
 {
         FAST unsigned i, k, gap;
         FAST int j;

         for (gap = n / 2; gap > 0; gap /= 2)
                 for (i = gap; i < n; i++)
                 {        j = i - gap;
                         while (j >= 0 AND (*comp)(j, (k = j + gap)) > 0)
                         {        (*exch)(j, k);
                                 j -= gap;
                         }
                 }
 }


 SOUNDEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\SOUNDEX.C

 /****************************************************************
 *        SOUNDEX ALGORITHM in C                                        *
 *                                                                 *
 *        The basic Algorithm source is taken from EDN Nov.        *
 *        14, 1985 pg. 36.                                        *
 *                                                                *
 *        As a test Those in Illinois will find that the                *
 *        first group of numbers in their drivers license                *
 *        number is the soundex number for their last name.        *
 *                                                                *
 *        RHW  PC-IBBS ID. #1230                                        *
 *                                                                *
 ****************************************************************/

 #include <ctype.h>

 char (*soundex(out_pntr, in_pntr))
 char *in_pntr;
 char *out_pntr;
 {
 extern char get_scode();
 char ch,last_ch;
 int count = 0;

         strcpy(out_pntr,"0000");        /* Pre-fill output string for    */
                                         /* error and trailing zeros.     */
         *out_pntr = toupper(*in_pntr);         /* Copy first letter
         last_ch = get_scode(*in_pntr);        /* code of the first letter
                                         /* for the first 'double-letter  */
                                         /* check.                         */
                                         /* Loop on input letters until   */
                                         /* end of input (null) or output */
                                         /* letter code count = 3         */

         while( (ch = get_scode(*(++in_pntr)) ) && (count < 3) )
         {
         if( (ch != '0') && (ch != last_ch) ) /* if not skipped or double */
                 *(out_pntr+(++count)) = ch; /* letter, copy to output */
                 last_ch = ch;        /* save code of last input letter for */
                                 /* next double-letter check */
         }
         return(out_pntr);        /* pointer to input string */
 }

 char get_scode(ch)
 char ch;
 {
                             /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
                             /* :::::::::::::::::::::::::: */
 static char soundex_map[] =   "01230120022455012623010202";

         /* If alpha, map input letter to soundex code. If not, return 0 */

         if( !isalpha(ch) )        /*error if not alpha */
                 return(0);
         else
                 return(soundex_map[(toupper(ch) - 'A')] );
 }
 #include <ctype.h>

 main(argc, argv)
 int        argc;
 char        *argv[];
 {
 char        *code[10];

 int        i;

         if(argc == 1) /* No arguments, give usage */
         {
         printf("\nUsage: soundex (name) (...)\n");
         exit(1);
         }

         for(i = 1; i < argc; i++)
         {
         soundex(code, argv[i]) ;
         printf("The Soundex Code for \"%s\" is: %s\n", argv[i],code);
         }
         exit(0);
 }


 SPAWN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\SPAWN.C

 /*        Spawn:        various DOS access commands
                 for MicroEMACS
 */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     AMIGA
 #define  NEW   1006L
 #endif

 #if                ST520 & MEGAMAX
 #include <osbind.h>
 #include <string.h>
 LOAD_EXEC 0         /* load and execute the program */
 char        *STcmd,                /* the command filename & path  */
         *STargs,        /* command args (if any)        */
         *STenv,                /* environment                  */
         *STwork;        /* work area                        */
 #endif

 #if     VMS
 EFN     0                               /* Event flag.          */

        <ssdef.h>                       /* Random headers.      */
 #include        <stsdef.h>
 #include        <descrip.h>
 #include        <iodef.h>

 extern  int     oldmode[3];                     /* In "termio.c"        */
 extern  int     newmode[3];                     /* In "termio.c"        */
 extern  short   iochan;                         /* In "termio.c"        */
 #endif

 #if     V7 | USG | BSD
 #include        <signal.h>
 extern int vttidy();
 #endif

 #if        MSDOS & (MSC | TURBO)
 #include        <process.h>
 #endif

 /*
  * Create a subjob with a copy of the command intrepreter in it. When the
  * command interpreter exits, mark the screen as garbage so that you do a ful
  * repaint. Bound to "^X C". The message at the start in VMS puts out a newli
  * Under some (unknown) condition, you don't get one free when DCL starts up.
  */
 spawncli(f, n)
 {
 #if     AMIGA
         long newcli;

 #endif

 #if     V7 | USG | BSD
         register char *cp;
         char    *getenv();
 #endif

         /* don't allow this command if restricted */
         if (restflag)
                 return(resterr());

 #if        AMIGA
         mlwrite("[Starting new CLI]");
         sgarbf = TRUE;
         Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L);
         return(TRUE);
 #endif

 #if     VMS
         movecursor(term.t_nrow, 0);             /* In last line.        */
         mlputs("[Starting DCL]\r\n");
         TTflush();                              /* Ignore "ttcol".      */
         sgarbf = TRUE;
         return (sys(NULL));                     /* NULL => DCL.         */
 #endif
 #if     CPM
         mlwrite("Not in CP/M-86");
 #endif
 #if        ST520
         mlwrite("Not in TOS");
 #endif
 #if     MSDOS & (AZTEC | MSC | TURBO)
         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
         TTflush();
         TTkclose();
         system("command.com");
         TTkopen();
         sgarbf = TRUE;
         return(TRUE);
 #endif
 #if     MSDOS & LATTICE
         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
         TTflush();
         TTkclose();
         sys("\\command.com", "");               /* Run CLI.             */
         TTkopen();
         sgarbf = TRUE;
         return(TRUE);
 #endif
 #if     V7 | USG | BSD
         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
         TTflush();
         TTclose();                              /* stty to old settings */
         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
                 system(cp);
         else
 #if        BSD
                 system("exec /bin/csh");
 #else
                 system("exec /bin/sh");
 #endif
         sgarbf = TRUE;
         sleep(2);
         TTopen();
         return(TRUE);
 #endif
 }

 #if        BSD

 bktoshell()                /* suspend MicroEMACS and wait to wake up */
 {
         int pid;

         vttidy();
         pid = getpid();
         kill(pid,SIGTSTP);
 }

 rtfrmshell()
 {
         TTopen();
         curwp->w_flag = WFHARD;
         sgarbf = TRUE;
 }
 #endif

 /*
  * Run a one-liner in a subjob. When the command returns, wait for a single
  * character to be typed, then mark the screen as garbage so a full repaint i
  * done. Bound to "C-X !".
  */
 spawn(f, n)
 {
         register int    s;
         char            line[NLINE];

 #if        ST520 & MEGAMAX
         int i,j,k;
         char *sptr,*tptr;
 #endif

 #if     AMIGA
         long newcli;
 #endif

         /* don't allow this command if restricted */
         if (restflag)
                 return(resterr());

 #if        AMIGA
         if ((s=mlreply("!", line, NLINE)) != TRUE)
                 return (s);
         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
         Execute(line, 0L, newcli);
         Close(newcli);
         tgetc();     /* Pause.               */
         sgarbf = TRUE;
         return(TRUE);
 #endif
 #if     ST520 & MEGAMAX
         if ((s=mlreply("!", line, NLINE)) != TRUE)
                 return(s);
         movecursor(term.t_nrow - 1, 0);
         TTclose();
 /*
  * break the line into the command and its args
  * be cute about it, if there is no '.' in the filename, try
  * to find .prg, .tos or .ttp in that order
  * in any case check to see that the file exists before we run
  * amok
  */
         STenv = NULL;
         if((tptr = index(&line[0],' ')) == NULL) { /* no args */
                 STcmd = (char *)malloc(strlen(line) + 1);
                 strcpy(STcmd,line);
                 STargs = NULL;
         }
         else {  /* seperate out the args from the command */
                 /* resist the temptation to do ptr arithmetic */
                 STcmd = (char *)malloc(strlen(line) + 1);
                 for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++)
                         STcmd[i] = *sptr;
                 STcmd[i] = '\0';
                 for(; *tptr == ' ' || *tptr == '\t'; tptr++);
                 if(*tptr == '\0')
                         STargs = NULL;
                 else {
                         STargs = (char *)malloc(strlen(tptr) + 2);
 /* first byte of STargs is the length of the string */
                         STargs[0] = strlen(tptr);
                         STargs[1] = NULL; /* fake it for strcat */
                         strcat(STargs,tptr);
                 }
         }
 /*
  * before we issue the command look for the '.', if it's not there
  * try adding .prg, .tos and .ttp to see if they exist, if not
  * issue the command as is
  */
         if((tptr = index(STcmd,'.')) == NULL) {
                  STwork = (char *)malloc(strlen(STcmd) + 4);
                  strcpy(STwork,STcmd);
                  strcat(STwork,".prg");
                  tptr = index(STwork,'.');
                  if(Fsfirst(1,STwork) != 0) { /* try .tos */
                          strcpy(tptr,".tos");
                          if(Fsfirst(1,STwork) != 0) { /* try .ttp */
                                  strcpy(tptr,".ttp");
                                  if(Fsfirst(1,STwork) != 0) /* never mind */
                                          *STwork = NULL;
                                  }
                          }
          }
          if(*STwork != NULL)
                 Pexec(LOAD_EXEC,STwork,STargs,STenv);
         else
                 Pexec(LOAD_EXEC,STcmd,STargs,STenv);
         TTopen();
         mlputs("\r\n\n[End]");                  /* Pause.               */
         TTgetc();                             /* Pause.               */
         sgarbf = TRUE;
         return (TRUE);
 #endif
 #if     VMS
         if ((s=mlreply("!", line, NLINE)) != TRUE)
                 return (s);
         TTputc('\n');                /* Already have '\r'    */
         TTflush();
         s = sys(line);                          /* Run the command.     */
         mlputs("\r\n\n[End]");                  /* Pause.               */
         TTflush();
         tgetc();
         sgarbf = TRUE;
         return (s);
 #endif
 #if     CPM
         mlwrite("Not in CP/M-86");
         return (FALSE);
 #endif
 #if     MSDOS | (ST520 & LATTICE)
         if ((s=mlreply("!", line, NLINE)) != TRUE)
                 return(s);
         movecursor(term.t_nrow - 1, 0);
         TTkclose();
         system(line);
         TTkopen();
         /* if we are interactive, pause here */
         if (clexec == FALSE) {
                 mlputs("\r\n\n[End]");
                 tgetc();
         }
         sgarbf = TRUE;
         return (TRUE);
 #endif
 #if     V7 | USG | BSD
         if ((s=mlreply("!", line, NLINE)) != TRUE)
                 return (s);
         TTputc('\n');                /* Already have '\r'    */
         TTflush();
         TTclose();                              /* stty to old modes    */
         system(line);
         TTopen();
         mlputs("[End]");                        /* Pause.               */
         TTflush();
         while ((s = tgetc()) != '\r' && s != ' ')
                 ;
         sgarbf = TRUE;
         return (TRUE);
 #endif
 }

 /*
  * Pipe a one line command into a window
  * Bound to ^X @
  */
 pipecmd(f, n)
 {
         register int    s;        /* return status from CLI */
         register WINDOW *wp;        /* pointer to new window */
         register BUFFER *bp;        /* pointer to buffer to zot */
         char        line[NLINE];        /* command line send to shell */
         static char bname[] = "command";

 #if        AMIGA
         static char filnam[] = "ram:command";
         long newcli;
 #else
         static char filnam[NSTRING] = "command";
 #endif

 #if        MSDOS
         char *tmp;
         char *getenv();
         FILE *fp;
         FILE *fopen();
 #endif

         /* don't allow this command if restricted */
         if (restflag)
                 return(resterr());

 #if        MSDOS
         if ((tmp = getenv("TMP")) == NULL)
                 strcpy(filnam, "command");
         else {
                 strcpy(filnam, tmp);
                 strcat(filnam,"\\command");
         }
 #endif

 #if     VMS
         mlwrite("Not availible under VMS");
         return(FALSE);
 #endif
 #if     CPM
         mlwrite("Not availible under CP/M-86");
         return(FALSE);
 #endif

         /* get the command to pipe in */
         if ((s=mlreply("@", line, NLINE)) != TRUE)
                 return(s);

         /* get rid of the command output buffer if it exists */
         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
                 /* try to make sure we are off screen */
                 wp = wheadp;
                 while (wp != NULL) {
                         if (wp->w_bufp == bp) {
                                 onlywind(FALSE, 1);
                                 break;
                         }
                         wp = wp->w_wndp;
                 }
                 if (zotbuf(bp) != TRUE)

                         return(FALSE);
         }

 #if     AMIGA
         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
         strcat(line, " >");
         strcat(line, filnam);
         Execute(line, 0L, newcli);
         s = TRUE;
         Close(newcli);
         sgarbf = TRUE;
 #endif
 #if     MSDOS
         strcat(line," >>");
         strcat(line,filnam);
         movecursor(term.t_nrow - 1, 0);
         TTkclose();
         system(line);
         TTkopen();
         sgarbf = TRUE;
         if ((fp = fopen(filnam, "r")) == NULL) {
                 s = FALSE;
         } else {
                 fclose(fp);
                 s = TRUE;
         }
 #endif
 #if     V7 | USG | BSD
         TTputc('\n');                /* Already have '\r'    */
         TTflush();
         TTclose();                              /* stty to old modes    */
         strcat(line,">");
         strcat(line,filnam);
         system(line);
         TTopen();
         TTflush();
         sgarbf = TRUE;
         s = TRUE;
 #endif

         if (s != TRUE)
                 return(s);

         /* split the current window to make room for the command output */
         if (splitwind(FALSE, 1) == FALSE)
                         return(FALSE);

         /* and read the stuff in */
         if (getfile(filnam, FALSE) == FALSE)
                 return(FALSE);

         /* make this window in VIEW mode, update all mode lines */
         curwp->w_bufp->b_mode |= MDVIEW;
         wp = wheadp;
         while (wp != NULL) {
                 wp->w_flag |= WFMODE;
                 wp = wp->w_wndp;
         }

         /* and get rid of the temporary file */
         unlink(filnam);
         return(TRUE);
 }

 /*
  * filter a buffer through an external DOS program
  * Bound to ^X #
  */
 filter(f, n)

 {
         register int    s;        /* return status from CLI */
         register BUFFER *bp;        /* pointer to buffer to zot */
         char line[NLINE];        /* command line send to shell */
         char tmpnam[NFILEN];        /* place to store real file name */
         static char bname1[] = "fltinp";

 #if        AMIGA
         static char filnam1[] = "ram:fltinp";
         static char filnam2[] = "ram:fltout";
         long newcli;
 #else
         static char filnam1[] = "fltinp";
         static char filnam2[] = "fltout";
 #endif

         /* don't allow this command if restricted */
         if (restflag)
                 return(resterr());

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *

 #if     VMS
         mlwrite("Not availible under VMS");
         return(FALSE);
 #endif
 #if     CPM
         mlwrite("Not availible under CP/M-86");
         return(FALSE);
 #endif

         /* get the filter name and its args */
         if ((s=mlreply("#", line, NLINE)) != TRUE)
                 return(s);

         /* setup the proper file names */
         bp = curbp;
         strcpy(tmpnam, bp->b_fname);        /* save the original name */
         strcpy(bp->b_fname, bname1);        /* set it to our new one */

         /* write it out, checking for errors */
         if (writeout(filnam1) != TRUE) {
                 mlwrite("[Cannot write filter file]");
                 strcpy(bp->b_fname, tmpnam);
                 return(FALSE);
         }

 #if     AMIGA
         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
         strcat(line, " <ram:fltinp >ram:fltout");
         Execute(line,0L,newcli);
         s = TRUE;
         Close(newcli);
         sgarbf = TRUE;
 #endif
 #if     MSDOS
         strcat(line," <fltinp >fltout");
         movecursor(term.t_nrow - 1, 0);
         TTkclose();
         system(line);
         TTkopen();
         sgarbf = TRUE;
         s = TRUE;
 #endif
 #if     V7 | USG | BSD
         TTputc('\n');                /* Already have '\r'    */
         TTflush();
         TTclose();                              /* stty to old modes    */
         strcat(line," <fltinp >fltout");
         system(line);
         TTopen();
         TTflush();
         sgarbf = TRUE;
         s = TRUE;
 #endif

         /* on failure, escape gracefully */
         if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
                 mlwrite("[Execution failed]");
                 strcpy(bp->b_fname, tmpnam);
                 unlink(filnam1);
                 unlink(filnam2);
                 return(s);
         }

         /* reset file name */
         strcpy(bp->b_fname, tmpnam);        /* restore name */
         bp->b_flag |= BFCHG;                /* flag it as changed */

         /* and get rid of the temporary file */
         unlink(filnam1);
         unlink(filnam2);
         return(TRUE);
 }

 #if     VMS
 /*
  * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  * want to run a copy of DCL in the subjob (this is how the standard routine
  * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way i
  * and the way out, because DCL does not want the channel to be in raw mode.
  */
 sys(cmd)
 register char   *cmd;
 {
         struct  dsc$descriptor  cdsc;
         struct  dsc$descriptor  *cdscp;
         long    status;
         long    substatus;
         long    iosb[2];

         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                 return (FALSE);
         cdscp = NULL;                           /* Assume DCL.          */
         if (cmd != NULL) {                      /* Build descriptor.    */
                 cdsc.dsc$a_pointer = cmd;
                 cdsc.dsc$w_length  = strlen(cmd);
                 cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
                 cdsc.dsc$b_class   = DSC$K_CLASS_S;
                 cdscp = &cdsc;
         }
         status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
         if (status != SS$_NORMAL)
                 substatus = status;
         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                           newmode, sizeof(newmode), 0, 0, 0, 0);
         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                 return (FALSE);
         if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
                 return (FALSE);
         return (TRUE);
 }
 #endif

 #if        ~AZTEC & ~MSC & ~TURBO & MSDOS

 /*
  * This routine, once again by Bob McNamara, is a C translation of the "syste
  * routine in the MWC-86 run time library. It differs from the "system" routi
  * in that it does not unconditionally append the string ".exe" to the end of
  * the command name. We needed to do this because we want to be able to spawn
  * off "command.com". We really do not understand what it does, but if you do
  * do it exactly "malloc" starts doing very very strange things.
  */
 sys(cmd, tail)
 char    *cmd;
 char    *tail;
 {
 #if MWC86
         register unsigned n;
         extern   char     *__end;

         n = __end + 15;
         n >>= 4;
         n = ((n + dsreg() + 16) & 0xFFF0) + 16;
         return(execall(cmd, tail, n));
 #endif

 #if LATTICE
         return(forklp(cmd, tail, (char *)NULL));
 #endif
 }
 #endif

 #if        MSDOS & LATTICE
 /*        System: a modified version of lattice's system() function
                 that detects the proper switchar and uses it
                 written by Dana Hogget                                */

 system(cmd)

 char *cmd;        /*  Incoming command line to execute  */

 {
         char *getenv();
         static char *swchar = "/C";        /*  Execution switch  */
         union REGS inregs;        /*  parameters for dos call  */
         union REGS outregs;        /*  Return results from dos call  */
         char *shell;                /*  Name of system command processor  */
         char *p;                /*  Temporary pointer  */
         int ferr;                /*  Error condition if any  */

         /*  get name of system shell  */
         if ((shell = getenv("COMSPEC")) == NULL) {
                 return (-1);                /*  No shell located  */
         }

         p = cmd;
         while (isspace(*p)) {                /*  find out if null command */
                 p++;
         }

         /**  If the command line is not empty, bring up the shell  **/
         /**  and execute the command.  Otherwise, bring up the     **/
         /**  shell in interactive mode.   **/

         if (p && *p) {
                 /**  detect current switch character and us it  **/
                 inregs.h.ah = 0x37;        /*  get setting data  */
                 inregs.h.al = 0x00;        /*  get switch character  */
                 intdos(&inregs, &outregs);
                 *swchar = outregs.h.dl;
                 ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
         } else {
                 ferr = forkl(shell, "command", (char *)NULL);
         }

         return (ferr ? ferr : wait());
 }
 #endif


 SPAWNE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SPAWNE.C

 #include <osbind.h>
 #include <stdio.h>

 int spawne(program, cmdline, envp)
 char *program;
 char *cmdline;
 char *envp;
 /*
  *        Calls the OS "Pexec" trap with the parameters specified.  Since
  *        the OS uses a Pascal-like string for the command line, the
  *        <cmdline> parameter, which is a normal C-string, is used to
  *        create the actual command line which is passed to the OS trap.
  */
 {
         char execbuf[128];                /* buffer for exec command line */
         register int n;

         if(cmdline) {
                 if((n = strlen(cmdline)) > 126)
                         n = 126;
                 execbuf[0] = n;
                 strncpy(execbuf+1, cmdline, n);
                 execbuf[n+2] = '\0';
         }
         else
                 execbuf[0] = execbuf[1] = '\0';
         n = Pexec(0, program, execbuf, envp);
         return(n);
 }


 SPAWNPE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SPAWNPE.C

 #include <stdio.h>

 int spawnpe(program, cmdline, envp)
 char *program;
 char *cmdline;
 char *envp;
 /*
  *        Operates like spawne() except that the "PATH" environment variable,
  *        if it is valid, is used to locate the program to be executed.
  */
 {
         register char *p;
         char *pfindfile();

         if(p = pfindfile(program, "ttp\0tos\0prg\0app\0"))
                 return(spawne(p, cmdline, envp));
         return(ERROR);
 }


 SPECIAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SPECIAL.C

                                         /* Chapter 9 - Program 7 */
 #include "stdio.h"

 main()
 {
 int index;

    for (index = 0;index < 6;index++) {
       printf("This line goes to the standard output.\n");
       fprintf(stderr,"This line goes to the error device.\n");
    }

    exit(4);  /* This can be tested with the DOS errorlevel
                 command in a batch file. The number returned
                 is used as follows;

                 IF ERRORLEVEL 4 GOTO FOUR
                 (continue here if less than 4)
                 .
                 .
                 GOTO DONE
                 :FOUR
                 (continue here if 4 or greater)
                 .
                 .
                 :DONE
                                                                   */
 }


 SPEED.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\SPEED.C

 /*                      Display Processor Speed
  */

 /*      main()

         Function: Display the speed of the current processor, as a
         percentage of a standard IBM-PC.

         Algorithm: Just call calib and print out the result.
 */

 main()

 {
         printf("This processor is %u%% of a standard IBM-PC.\n",calib());
 }



 SPF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CTOOLBX1\SPF.C



 /*   The below defines the Sugar Plum Fairy  */

 int s[250] =      { 41, 38, 41, 40, 37, 38, 36, 36, 36,
                     35, 35, 35, 35, 34, 34, 33, 38, 34, 38, 33, 100,
                     29, 26, 29, 28, 34, 33, 41, 41, 41,

                     40, 40, 40, 38, 38, 38, 37, 40, 38, 40, 37,  97,
                     41, 38, 41, 40, 37, 38, 36, 36, 36,
                     35, 35, 35, 34, 34, 34, 33, 38, 34, 38, 33, 100,
                     38, 35, 38, 37, 100,36, 33, 36, 35,
                     100,34, 31, 34, 33, 100,33, 38,
                          0xff };

 int sb[250]   =   {  4,  4,  8,  8,  8,  8,  4,  4,  8,
                      4,  4,  8,  4,  4,  8,  4,  4,  4,  4,  8, 15,
                      4,  4,  8,  8,  8,  8,  4,  4,  8,
                      4,  4,  8,  4,  4,  8,  4,  4,  4,  4,  8,
                      4,  4,  8,  8,  8,  8,  4,  4,  8,
                      4,  4,  8,  4,  4,  8,  4,  4,  4,  4,  8,  15,
                      4,  4,  8,  8, 10,  4,  4,  8,  8,
                      10, 4,  4,  8,  8, 10,  8, 8,
                            10   };


 spf()
 {
    setsound();
 }


 SPOOL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\SPOOL.C

 /* add a file to the print spooler que by calling spool(filename,fcb)*/
 /* filename is a string containing the name of the file to print*/
 /* fcb points to 36 bytes where an fcb can be built */
 /* e.g.: main()
          {static char fnam[10]="a:spool.c";
           static char fcb[36];
           spool(fnam,fcb);
          }                    */

 spool() /* filename, fcb */
 {
 #asm
      push si
      push es
      push ds
      pop es
      mov si,[bp+4] ;filename string address
      mov di,[bp+6] ;fcb space
      mov ax,290fh  ;parse filename
      int 21h
      mov dx,di     ;fcb address
      mov ah,0fh    ;open
      int 21h
      mov ah,0      ;add print file to que
      int 2fh       ;spooler queue
      pop es
      pop si
 #
 }



 SPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SPRINTF.C

 /* 1.1  01-08-86                                                (sprintf.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 LOCAL STRING globstr;                /* global string for sputc() deposit

 /************************************************************************/

 sprintf(str, fmt, args)                /* formatted printf into str string.

 /*----------------------------------------------------------------------*/
 STRING str, fmt;
 unsigned args;
 {
         int sputc(), i;

         globstr = str;
         i = format(sputc, fmt, &args);
         *globstr = NULL;
         return i;
 }

 /************************************************************************/
         LOCAL
 sputc(c)                /* Put character c into global string globstr.

 /*----------------------------------------------------------------------*/
 {
         return (*globstr++ = c) & 0xff;
 }


 SPRINTF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SPRINTF.C

 static unsigned int sputc(c, s)
 char c, **s;
 /*
  *        Local function to put a character to a string
  */
 {
         return(*(*s)++ = c);
 }

 sprintf(buf, fmt, arg)
 char *buf;
 char *fmt;
 int arg;
 {
         register int n;
         register char *p = buf;

         n = _printf(&buf, sputc, fmt, &arg);
         p[n] = '\0';                /* always tie of the string */
         return(n);
 }


 SQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\SQ.C

 /* This program compresses a file without loosing information.
  * The "usq" program is required to unsqueeze the file
  * before it can be used.
  *
  * Typical compression rates are between 30 and 50 percent for text files.
  *
  * Squeezing a really big file takes a few minutes.
  *
  * Useage:
  *        sq [file1] [file2] ... [filen]
  *
  * where file1 through filen are the names of the files to be squeezed.
  * The file type (under CP/M or MS-DOS) is changed to ".SQ"; under UN*X,
  * ".SQ" is appended to the file name. The original file name is stored
  * in the squeezed file.
  *
  * If no file name is given on the command line you will be
  * prompted for commands (one at a time). An empty command
  * terminates the program.
  *
  * The transformations compress strings of identical bytes and
  * then encode each resulting byte value and EOF as bit strings
  * having lengths in inverse proportion to their frequency of
  * occurrance in the intermediate input stream. The latter uses
  * the Huffman algorithm. Decoding information is included in
  * the squeezed file, so squeezing short files or files with
  * uniformly distributed byte values will actually increase size.
  */

 /* CHANGE HISTORY:
  * 1.3        Close files properly in case of error exit.
  * 1.4        Break up long introductory lines.
  * 1.4        Send introduction only to console.
  * 1.4        Send errors only to console.
  * 1.5  Fix BUG that caused a rare few squeezed files
  *        to be incorrect and fail the USQ crc check.
  *        The problem was that some 17 bit codes were
  *        generated but are not supported by other code.
  *        THIS IS A MAJOR CHANGE affecting TR2.C and SQ.H and
  *        requires recompilation of all files which are part
  *        of SQ. Two basic changes were made: tree depth is now
  *        used as a tie breaker when weights are equal. This
  *        makes the tree shallower. Although that may always be
  *        sufficient, an error trap was added to cause rescaling
  *        of the counts if any code > 16 bits long is generated.
  * 1.5        Add debugging displays option '-'.
  * 1.6  Fixed to work correctly under MP/M II.  Also shortened
  *      signon message.
  * 2.0        New version for use with CI-C86 compiler (CP/M-86 and MS-DOS)
  * 2.1  Converted for use in MLINK
  * 2.2  Converted for use with optimizing CI-C86 compiler (MS-DOS)
  * 3.0  Generalized for UN*X use, changed output file naming convention
  */

 /* ejecteject */

 /*
  * The following define MUST be set to the maximum length of a file name
  * on the system "sq" is being compiled for.  If not, "sq" will not be
  * able to check for whether the output file name it creates is valid
  * or not.
  */

 #define FNM_LEN 14
 UNIX                                /* comment out for CP/M, MS-DOS versions
 #define SQMAIN

 #define VERSION "3.1   12/19/84"

 #include <stdio.h>
 #include "sqcom.h"
 #include "sq.h"
 #define FALSE 0

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int i,c;
         char inparg[128];        /* parameter from input */

         debug = FALSE;
         printf("File squeezer version %s (original author: R. Greenlaw)\n\n",

         /* Process the parameters in order */
         for(i = 1; i < argc; ++i)
                 obey(argv[i]);

         if(argc < 2) {
                 printf("Enter file names, one line at a time, or type <RETURN
                 do {
                         printf("\n*");
                         for(i = 0; i < 16; ++i) {
                                 if((c = getchar()) == EOF)
                                         c = '\n';        /* fake empty (exit)
                                 if((inparg[i] = c) == '\n') {
                                         inparg[i] = '\0';
                                         break;
                                 }
                         }
                         if(inparg[0] != '\0')
                                 obey(inparg);
                 } while(inparg[0] != '\0');
         }
 }

 /* ejecteject */

 obey(p)
 char *p;
 {
         char *q;
         char outfile[128];        /* output file spec. */

         if(*p == '-') {
                 /* toggle debug option */
                 debug = !debug;
                 return;
         }

         /* Check for ambiguous (wild-card) name */
         for(q = p; *q != '\0'; ++q)
                 if(*q == '*' || *q == '?') {
                         printf("\nAmbiguous name %s ignored", p);
                         return;
         }
         /* First build output file name */
         strcpy(outfile, p);                /* copy input name to output */

         /* Find and change output file suffix */

         if (strlen(outfile) + 3 > FNM_LEN) {        /* check for long file na
                 q = outfile + FNM_LEN - 3;
                 *q = '\0';                /* make room for suffix */
         }
         else {
                 q = outfile + strlen(outfile);
 #ifndef UNIX
                 for(; --q >= outfile;)
                         if (*q == '.') {
                                 *q = '\0';        /* delete file type */
                                 break;
                         }
 #else
                 --q;
 #endif
         }

         strcat(outfile, ".SQ");

         squeeze(p, outfile);
 }

 /* ejecteject */

 squeeze(infile, outfile)
 char *infile, *outfile;
 {
         int i, c,c2;
         FILE *inbuff, *outbuff;                /* file buffers */

         printf("%s -> %s: ", infile, outfile);

         if(!(inbuff=fopen(infile, "rb"))) {
                 printf("Can't open %s for input pass 1\n", infile);
                 return;
         }
         if(!(outbuff=fopen(outfile, "wb"))) {
                 printf("Can't create %s\n", outfile);
                 fclose(inbuff);
                 return;
         }

         /* First pass - get properties of file */
         crc = 0;        /* initialize checksum */
         printf("analyzing, ");
         init_ncr();
         init_huff(inbuff);
         fclose(inbuff);

         /* Write output file header with decoding info */
         wrt_head(outbuff, infile);

         /* Second pass - encode the file */
         printf("squeezing,");
         if(!(inbuff=fopen(infile, "rb"))) {
                 printf("Can't open %s for input pass 2\n", infile);
                 goto closeout;
         }
         init_ncr();        /* For second pass */

         /* Translate the input file into the output file */
         while((c = gethuff(inbuff)) != EOF)
                 putce(c, outbuff);
         oflush(outbuff);
         printf(" done.\n");
 closeall:
         fclose(inbuff);
 closeout:
         fclose(outbuff);
 }


 SQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQ.C

 static char *sccsid = "@(#)sq.c         1.7u (UCF) 82/12/15";
 /*
  *   sq.c - CP/M compatible file squeezer utility
  *
  *   compile as follows:
  *   cc [-DVAX] -O sq.c -o sq
  *       (define VAX only if running on VAX)
  */

 #include <stdio.h>
 #include <signal.h>

 #define TRUE 1
 #define FALSE 0
 #define ERROR (-1)
 PATHLEN312/* Number of characters allowed in pathname */
 #define ALTNAME "sq.out"

 /* Definitions and external declarations */

 RECOGNIZE 0xFF76/* unlikely pattern */

 /* *** Stuff for first translation module *** */

 #define DLE 0x90


 /* *** Stuff for second translation module *** */

 SPEOF 256/* special endfile token */
 NUMVALS 257/* 256 data values plus SPEOF*/


 VAX   /*  we only want 16 bit integers  */

 typedef short INT;
 typedef unsigned short UNSIGNED;

   /*  PDP-11 and other 16-bit machines  */

 typedef int INT;
 typedef unsigned UNSIGNED;

 #endif


 /* Definitions and external declarations */

 INT Usestd;/* Use stdout for squeezed output */
 UNSIGNED crc;/* error check code */

 /* *** Stuff for first translation module *** */

 INT likect;/*count of consecutive identical chars */
 INT lastchar, newchar;
 char state;

 /* states */

 NOHIST0 /*don't consider previous input*/
 SENTCHAR 1 /*lastchar set, no lookahead yet */
 SENDNEWC 2 /*newchar set, previous sequence done */
 SENDCNT 3 /*newchar set, DLE sent, send count next */

 /* *** Stuff for second translation module *** */

 NOCHILD -1/* indicates end of path through tree */
 NUMNODES (NUMVALS + NUMVALS - 1)/* nbr of nodes */

 MAXCOUNT (UNSIGNED) 65535/* biggest UNSIGNED integer */

 /* The following array of structures are the nodes of the
  * binary trees. The first NUMVALS nodes becomethe leaves of the
  * final tree and represent the values of the data bytes being
  * encoded and the special endfile, SPEOF.
  * The remaining nodes become the internal nodes of the final tree.
  */

 structnd {
 UNSIGNED weight;/* number of appearances */
 INT tdepth;/* length on longest path in tre*/
 INT lchild, rchild;/* indexes to next level */
 } node[NUMNODES];

 INT dctreehd;/*index to head node of final tree */

 /* This is the encoding table:
  * The bit strings have first bit in  low bit.
  * Note that counts were scaled so code fits UNSIGNED integer
  */

 INT codelen[NUMVALS];/* number of bits in code */
 UNSIGNED code[NUMVALS];/* code itself, right adjusted */
 UNSIGNED tcode;/* temporary code value */


 /* Variables used by encoding process */

 INT curin;/* Value currently being encoded */
 INT cbitsrem;/* Number of code string bits remaining */
 UNSIGNED ccode;/* Current code shifted so next code bit is at right */

 /* This program compresses a file without losing information.
  * The usq.com program is required to unsqueeze the file
  * before it can be used.
  *
  * Typical compression rates are:
  *.COM6%(Don't bother)
  *.ASM33%(using full ASCII set)
  *.DIC46%(using only uppercase and a few others)
  * Squeezing a really big file takes a few minutes.
  *
  * Useage:
  *sq file ...
  *
  *
  * The squeezed file name is formed by changing the second from last
  * letter of the file type to Q. If there is no file type,
  * the squeezed file type is QQQ. If the name exists it is
  * overwritten!
  *
  * The transformations compress strings of identical bytes and
  * then encode each resulting byte value and EOF as bit strings
  * having lengths in inverse proportion to their frequency of
  * occurrence in the intermediate input stream. The latter uses
  * the Huffman algorithm. Decoding information is included in
  * the squeezed file, so squeezing short files or files with
  * uniformly distributed byte values will actually increase size.
  */

 /* CHANGE HISTORY:
  * 1.5u **nix version - means output to stdout.
  *  (stdin not allowed becuase sq needs to rewind input, which
  *  won't work with pipes.)
  * Filename generation changed to suit **nix and stdio.
  * 1.6u machine independent output for file compatibility with
  *original CP/M version SQ, when running on machine with
  *IBM byte ordering such as Z8000 and 68000.
  * 1.7u machine independence was still lacking for 32-bit machines
  *      like the VAX-11/780, so a typedef was added.  No action
  *      need be taken if running on a 16-bit machine, but if
  *      running on a VAX, define VAX either on the cc line or
  *      in the program preamble.   Ben Goldfarb 12/13/82
  */


 #define VERSION "1.7u   12-13-82"

 INT inbackground = 0;

 INT buildenc(), gethuff(), getc_crc();

 main(argc, argv)
 INT argc;
 char *argv[];
 {
 register INT i,c;


 if (signal(SIGINT, SIG_IGN)==SIG_IGN)
 inbackground++;
 else
 signal(SIGINT, SIG_DFL);
 signal(SIGHUP, SIG_IGN);

 /* Process the parameters in order */
 for(i = 1; i < argc; ++i) {
 if(strcmp(argv[i], "-")==0)
 Usestd = TRUE;
 }
 for(i = 1; i < argc; ++i) {
 if(strcmp(argv[i], "-")!=0)
 obey(argv[i]);
 }

 if(argc < 2) {
 fprintf(stderr,"File squeezer version %s by\n\tRichard Greenlaw\n\t251 Colony
 fprintf(stderr, "Usage: sq [-] pathname ...\n");
 fprintf(stderr, "\t- squeezed output to stdout\n");
 exit(1);
 }
 exit(0);
 }

 obey(p)
 char *p;
 {
 char *w,*q;
 char outfile[PATHLEN+2];/* output file spec. */

 /* First build output file name */

 strcpy(outfile, p);
 /* Find and change output file type */
 for(w=q = outfile; *q != '\0'; ++q)/* skip leading /'s */
 if( *q == '/')
 w = q+1;
 for(q = w; *q != '\0'; ++q)
 if(*q == '.')
 if(*(q + 1) == '\0')
 *q = '\0';/* kill trailing dot */
 else
 switch(*(q+2)) {
 case 'q':
 case 'Q':
 fprintf(stderr, "sq: %s ignored ( already squeezed?)", p);
 return;
 case '\0':
 *(q+3) = '\0';
 /* fall thru */
 default:
 *(q + 2) = 'Q';
 goto named;
 }
 /* No file type */
 strcat(outfile, ".QQQ");
 named:
 if(strlen(w)>14)
 strcpy(outfile, ALTNAME);/* check for too long name */
 squeeze(p, outfile);
 }

 squeeze(infile, outfile)
 char *infile, *outfile;
 {
 register INT i, c;
 FILE *inbuff, *outbuff;/* file buffers */

 if (!inbackground)
 fprintf(stderr, "\n%s -> %s: ", infile, outfile);

 if((inbuff=fopen(infile, "r")) == NULL) {
 fprintf(stderr, "sq: can't open %s\n", infile);
 return;
 }
 if(Usestd)
 outbuff=stdout;
 else if((outbuff=fopen(outfile, "w")) == NULL) {
 fprintf(stderr, "sq: can't create %s\n", outfile);
 fclose(inbuff);
 return;
 }

 /* First pass - get properties of file */
 crc = 0;/* initialize checksum */
 if (!inbackground)
 fprintf(stderr, "analyzing, ");
 init_ncr();
 init_huff(inbuff);
 rewind(inbuff);

 /* Write output file header with decoding info */
 wrt_head(outbuff, infile);

 /* Second pass - encode the file */
 if (!inbackground)
 fprintf(stderr, "squeezing, ");

 init_ncr();/* For second pass */

 /* Translate the input file into the output file */
 while((c = gethuff(inbuff)) != EOF)
 if(putc(c, outbuff) == ERROR && ferror(outbuff)) {
 fprintf(stderr, "sq: write error\n");
 goto closeall;
 }
 if (!inbackground)
 fprintf(stderr, " done.\n");
 closeall:
 fclose(inbuff);
 closeout:
 fflush(outbuff);
 fclose(outbuff);
 }


 /* First translation - encoding of repeated characters
  * The code is byte for byte pass through except that
  * DLE is encoded as DLE, zero and repeated byte values
  * are encoded as value, DLE, count for count >= 3.
  */

 init_ncr()/*initialize getcnr() */
 {
 state = NOHIST;
 }

 INT
 getcnr(iob)
 FILE *iob;
 {
 switch(state) {
 case NOHIST:
 /* No relevant history */
 state = SENTCHAR;
 return lastchar = getc_crc(iob);
 case SENTCHAR:
 /* Lastchar is set, need lookahead */
 switch(lastchar) {
 case DLE:
 state = NOHIST;
 return 0;/* indicates DLE was the data */
 case EOF:
 return EOF;
 default:
 for(likect = 1; (newchar = getc_crc(iob)) == lastchar && likect < 255; ++like
 ;
 switch(likect) {
 case 1:
 return lastchar = newchar;
 case 2:
 /* just pass through */
 state = SENDNEWC;
 return lastchar;
 default:
 state = SENDCNT;
 return DLE;
 }
 }
 case SENDNEWC:
 /* Previous sequence complete, newchar set */
 state = SENTCHAR;
 return lastchar = newchar;
 case SENDCNT:
 /* Sent DLE for repeat sequence, send count */
 state = SENDNEWC;
 return likect;
 default:
 fprintf(stderr,"sq: Bug - bad state\n");
 exit(1);
 /* NOTREACHED */
 }
 }


 /******** Second translation - bytes to variable length bit strings *********


 /* This translation uses the Huffman algorithm to develop a
  * binary tree representing the decoding information for
  * a variable length bit string code for each input value.
  * Each string's length is in inverse proportion to its
  * frequency of appearance in the incoming data stream.
  * The encoding table is derived from the decoding table.
  *
  * The range of valid values into the Huffman algorithm are
  * the values of a byte stored in an integer plus the special
  * endfile value chosen to be an adjacent value. Overall, 0-SPEOF.
  *
  * The "node" array of structures contains the nodes of the
  * binary tree. The first NUMVALS nodes are the leaves of the
  * tree and represent the values of the data bytes being
  * encoded and the special endfile, SPEOF.
  * The remaining nodes become the internal nodes of the tree.
  *
  * In the original design it was believed that
  * a Huffman code would fit in the same number of
  * bits that will hold the sum of all the counts.
  * That was disproven by a user's file and was a rare but
  * infamous bug. This version attempts to choose among equally
  * weighted subtrees according to their maximum depths to avoid
  * unnecessarily long codes. In case that is not sufficient
  * to guarantee codes <= 16 bits long, we initially scale
  * the counts so the total fits in an unsigned integer, but
  * if codes longer than 16 bits are generated the counts are
  * rescaled to a lower ceiling and code generation is retried.
  */

 /* Initialize the Huffman translation. This requires reading
  * the input file through any preceding translation functions
  * to get the frequency distribution of the various values.
  */

 init_huff(ib)
 FILE *ib;
 {
 register INT c, i;
 INT btlist[NUMVALS];/* list of intermediate binary trees */
 INT listlen;/* length of btlist */
 UNSIGNED *wp;/* simplifies weight counting */
 UNSIGNED ceiling;/* limit for scaling */

 /* Initialize tree nodes to no weight, no children */
 init_tree();

 /* Build frequency info in tree */
 do {
 c = getcnr(ib);
 if(c == EOF)
 c = SPEOF;
 if(*(wp = &node[c].weight) !=  MAXCOUNT)
 ++(*wp);
 }
 while(c != SPEOF);

 ceiling = MAXCOUNT;

 do {/* Keep trying to scale and encode */
 if(ceiling != MAXCOUNT)
 fprintf(stderr, "sq: *** rescaling ***, ");
 scale(ceiling);
 ceiling /= 2;/* in case we rescale */

 /* Build list of single node binary trees having
  * leaves for the input values with non-zero counts
  */
 for(i = listlen = 0; i < NUMVALS; ++i)
 if(node[i].weight != 0) {
 node[i].tdepth = 0;
 btlist[listlen++] = i;
 }

 /* Arrange list of trees into a heap with the entry
  * indexing the node with the least weight at the top.
  */
 heap(btlist, listlen);

 /* Convert the list of trees to a single decoding tree */
 bld_tree(btlist, listlen);

 /* Initialize the encoding table */
 init_enc();

 /* Try to build encoding table.
  * Fail if any code is > 16 bits long.
  */
 }
 while(buildenc(0, dctreehd) == ERROR);

 /* Initialize encoding variables */
 cbitsrem = 0;/*force initial read */
 curin = 0;/*anything but endfile*/
 }

 /* The count of number of occurrances of each input value
  * have already been prevented from exceeding MAXCOUNT.
  * Now we must scale them so that their sum doesn't exceed
  * ceiling and yet no non-zero count can become zero.
  * This scaling prevents errors in the weights of the
  * interior nodes of the Huffman tree and also ensures that
  * the codes will fit in an unsigned integer. Rescaling is
  * used if necessary to limit the code length.
  */

 scale(ceil)
 UNSIGNED ceil;/* upper limit on total weight */
 {
 register INT i,c;
 INT ovflw, divisor;
 UNSIGNED w, sum;
 char increased;/* flag */

 do {
 for(i = sum = ovflw = 0; i < NUMVALS; ++i) {
 if(node[i].weight > (ceil - sum))
 ++ovflw;
 sum += node[i].weight;
 }

 divisor = ovflw + 1;

 /* Ensure no non-zero values are lost */
 increased = FALSE;
 for(i = 0; i < NUMVALS; ++i) {
 w = node[i].weight;
 if (w < divisor && w != 0) {
 /* Don't fail to provide a code if it's used at all */
 node[i].weight = divisor;
 increased = TRUE;
 }
 }
 }
 while(increased);

 /* Scaling factor choosen, now scale */
 if(divisor > 1)
 for(i = 0; i < NUMVALS; ++i)
 node[i].weight /= divisor;
 }

 /* heap() and adjust() maintain a list of binary trees as a
  * heap with the top indexing the binary tree on the list
  * which has the least weight or, in case of equal weights,
  * least depth in its longest path. The depth part is not
  * strictly necessary, but tends to avoid long codes which
  * might provoke rescaling.
  */

 heap(list, length)
 INT list[], length;
 {
 register INT i;

 for(i = (length - 2) / 2; i >= 0; --i)
 adjust(list, i, length - 1);
 }

 /* Make a heap from a heap with a new top */

 adjust(list, top, bottom)
 INT list[], top, bottom;
 {
 register INT k, temp;

 k = 2 * top + 1;/* left child of top */
 temp = list[top];/* remember root node of top tree */
 if( k <= bottom) {
 if( k < bottom && cmptrees(list[k], list[k + 1]))
 ++k;

 /* k indexes "smaller" child (in heap of trees) of top */
 /* now make top index "smaller" of old top and smallest child */
 if(cmptrees(temp, list[k])) {
 list[top] = list[k];
 list[k] = temp;
 /* Make the changed list a heap */
 adjust(list, k, bottom); /*recursive*/
 }
 }
 }

 /* Compare two trees, if a > b return true, else return false
  * note comparison rules in previous comments.
  */

 cmptrees(a, b)
 INT a, b;/* root nodes of trees */
 {
 if(node[a].weight > node[b].weight)
 return TRUE;
 if(node[a].weight == node[b].weight)
 if(node[a].tdepth > node[b].tdepth)
 return TRUE;
 return FALSE;
 }

 /* HUFFMAN ALGORITHM: develops the single element trees
  * into a single binary tree by forming subtrees rooted in
  * interior nodes having weights equal to the sum of weights of all
  * their descendents and having depth counts indicating the
  * depth of their longest paths.
  *
  * When all trees have been formed into a single tree satisfying
  * the heap property (on weight, with depth as a tie breaker)
  * then the binary code assigned to a leaf (value to be encoded)
  * is then the series of left (0) and right (1)
  * paths leading from the root to the leaf.
  * Note that trees are removed from the heaped list by
  * moving the last element over the top element and
  * reheaping the shorter list.
  */

 bld_tree(list, len)
 INT list[];
 INT len;
 {
 register INT freenode;/* next free node in tree */
 register struct nd *frnp;/* free node pointer */
 INT lch, rch;/* temporaries for left, right children */
 INT i;

 /* Initialize index to next available (non-leaf) node.
  * Lower numbered nodes correspond to leaves (data values).
  */
 freenode = NUMVALS;

 while(len > 1) {
 /* Take from list two btrees with least weight
  * and build an interior node pointing to them.
  * This forms a new tree.
  */
 lch = list[0];/* This one will be left child */

 /* delete top (least) tree from the list of trees */
 list[0] = list[--len];
 adjust(list, 0, len - 1);

 /* Take new top (least) tree. Reuse list slot later */
 rch = list[0];/* This one will be right child */

 /* Form new tree from the two least trees using
  * a free node as root. Put the new tree in the list.
  */
 frnp = &node[freenode];/* address of next free node */
 list[0] = freenode++;/* put at top for now */
 frnp->lchild = lch;
 frnp->rchild = rch;
 frnp->weight = node[lch].weight + node[rch].weight;
 frnp->tdepth = 1 + maxchar(node[lch].tdepth, node[rch].tdepth);
 /* reheap list  to get least tree at top*/
 adjust(list, 0, len - 1);
 }
 dctreehd = list[0];/*head of final tree */
 }

 /* ???????????? */
 maxchar(a, b)
 {
 return a > b ? a : b;
 }
 /* Initialize all nodes to single element binary trees
  * with zero weight and depth.
  */

 init_tree()
 {
 register INT i;

 for(i = 0; i < NUMNODES; ++i) {
 node[i].weight = 0;
 node[i].tdepth = 0;
 node[i].lchild = NOCHILD;
 node[i].rchild = NOCHILD;
 }
 }

 init_enc()
 {
 register INT i;

 /* Initialize encoding table */
 for(i = 0; i < NUMVALS; ++i) {
 codelen[i] = 0;
 }
 }

 /* Recursive routine to walk the indicated subtree and level
  * and maintain the current path code in bstree. When a leaf
  * is found the entire code string and length are put into
  * the encoding table entry for the leaf's data value .
  *
  * Returns ERROR if codes are too long.
  */

 INT/* returns ERROR or NULL */
 buildenc(level, root)
 INT level;/* level of tree being examined, from zero */
 INT root; /* root of subtree is also data value if leaf */
 {
 register INT l, r;

 l = node[root].lchild;
 r = node[root].rchild;

 if( l == NOCHILD && r == NOCHILD) {
 /* Leaf. Previous path determines bit string
  * code of length level (bits 0 to level - 1).
  * Ensures unused code bits are zero.
  */
 codelen[root] = level;
 code[root] = tcode & (((UNSIGNED)~0) >> (16 - level));
 return (level > 16) ? ERROR : NULL;
 }
 else {
 if( l != NOCHILD) {
 /* Clear path bit and continue deeper */
 tcode &= ~(1 << level);
 /* NOTE RECURSION */
 if(buildenc(level + 1, l) == ERROR)
 return ERROR;
 }
 if(r != NOCHILD) {
 /* Set path bit and continue deeper */
 tcode |= 1 << level;
 /* NOTE RECURSION */
 if(buildenc(level + 1, r) == ERROR)
 return ERROR;
 }
 }
 return NULL;/* if we got here we're ok so far */
 }

 /* Write out the header of the compressed file */

 wrt_head(ob, infile)
 FILE *ob;
 char *infile;/* input file name (w/ or w/o drive) */
 {
 register INT l,r;
 INT i, k;
 INT numnodes;/* nbr of nodes in simplified tree */

 putwe(RECOGNIZE, ob);/* identifies as compressed */
 putwe(crc, ob);/* unsigned sum of original data */

 /* Record the original file name w/o drive */
 if(*(infile + 1) == ':')
 infile += 2;/* skip drive */

 do {
 putce(*infile, ob);
 }
 while(*(infile++) != '\0');


 /* Write out a simplified decoding tree. Only the interior
  * nodes are written. When a child is a leaf index
  * (representing a data value) it is recoded as
  * -(index + 1) to distinguish it from interior indexes
  * which are recoded as positive indexes in the new tree.
  * Note that this tree will be empty for an empty file.
  */

 numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS -1);
 putwe(numnodes, ob);

 for(k = 0, i = dctreehd; k < numnodes; ++k, --i) {
 l = node[i].lchild;
 r = node[i].rchild;
 l = l < NUMVALS ? -(l + 1) : dctreehd - l;
 r = r < NUMVALS ? -(r + 1) : dctreehd - r;
 putwe(l, ob);/* left child */
 putwe(r, ob);/* right child */
 }
 }

 /* Get an encoded byte or EOF. Reads from specified stream AS NEEDED.
  *
  * There are two unsynchronized bit-byte relationships here.
  * The input stream bytes are converted to bit strings of
  * various lengths via the static variables named c...
  * These bit strings are concatenated without padding to
  * become the stream of encoded result bytes, which this
  * function returns one at a time. The EOF (end of file) is
  * converted to SPEOF for convenience and encoded like any
  * other input value. True EOF is returned after that.
  *
  * The original gethuff() called a seperate function,
  * getbit(), but that more readable version was too slow.
  */

 INT/*  Returns byte values except for EOF */
 gethuff(ib)
 FILE *ib;
 {
 INT rbyte;/* Result byte value */
 INT need, take;/* numbers of bits */

 rbyte = 0;
 need = 8;/* build one byte per call */

 /* Loop to build a byte of encoded data
  * Initialization forces read the first time
  */

 loop:
 if(cbitsrem >= need) {
 /* Current code fullfills our needs */
 if(need == 0)
 return rbyte;
 /* Take what we need */
 rbyte |= ccode << (8 - need);
 /* And leave the rest */
 ccode >>= need;
 cbitsrem -= need;
 return rbyte;
 }

 /* We need more than current code */
 if(cbitsrem > 0) {
 /* Take what there is */
 rbyte |= ccode << (8 - need);
 need -= cbitsrem;
 }
 /* No more bits in current code string */
 if(curin == SPEOF) {
 /* The end of file token has been encoded. If
  * result byte has data return it and do EOF next time
  */
 cbitsrem = 0;

 /*NOTE: +0 is to fight compiler bug? */
 return (need == 8) ? EOF : rbyte + 0;
 }

 /* Get an input byte */
 if((curin = getcnr(ib)) == EOF)
 curin = SPEOF;/* convenient for encoding */

 /* Get the new byte's code */
 ccode = code[curin];
 cbitsrem = codelen[curin];

 goto loop;
 }


 /* Get next byte from file and update checksum */

 INT
 getc_crc(ib)
 FILE *ib;
 {
 register INT c;

 c = getc(ib);
 if(c != EOF)
 crc += c;/* checksum */
 return c;
 }

 /* Output functions with error reporting */

 putce(c, iob)
 INT c;
 FILE *iob;
 {
 if(putc(c, iob) == ERROR && ferror(iob)) {
 fprintf(stderr, "sq: write error\n");
 exit(1);
 }
 }

 /*
  * machine independent put-word that writes low order byte first
  *  (compatible with CP/M original) regardless of host cpu.
  */
 putwe(w, iob)
 INT w;
 FILE *iob;
 {
 putc(w, iob);
 putc(w>>8, iob);
 if (ferror(iob)) {
 fprintf(stderr, "sq: write error\n");
 exit(1);
 }
 }



 SQ18U.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQ_USQ\SQ18U.C

 static char *sccsid = "@(#)sq.c         1.8u (UCF) 83/09/02";
 /*
  *   sq.c - CP/M compatible file squeezer utility
  *
  *   compile as follows:
  *   cc [-DVAX] -O sq.c -o sq
  *         (define VAX only if running on VAX)
  */

 #include <stdio.h>
 /* #include <signal.h> */

 #define TRUE 1
 #define FALSE 0
 #define ERROR (-1)
 PATHLEN 312        /* Number of characters allowed in pathname */
 #define ALTNAME "sq.out"

 /* Definitions and external declarations */

 RECOGNIZE 0xFF76        /* unlikely pattern */

 /* *** Stuff for first translation module *** */

 #define DLE 0x90


 /* *** Stuff for second translation module *** */

 SPEOF 256        /* special endfile token */
 NUMVALS 257        /* 256 data values plus SPEOF*/


 VAX   /*  we only want 16 bit integers  */

 typedef short INT;
 typedef unsigned short UNSIGNED;

        /*  PDP-11 and other 16-bit machines  */

 typedef int INT;
 typedef unsigned UNSIGNED;

 #endif


 /* Definitions and external declarations */

 INT Usestd;        /* Use stdout for squeezed output */
 UNSIGNED crc;        /* error check code */

 /* *** Stuff for first translation module *** */

 INT likect;        /*count of consecutive identical chars */
 INT lastchar, newchar;
 unsigned char state;

 /* states */

 NOHIST        0        /*don't consider previous input*/
 SENTCHAR 1        /*lastchar set, no lookahead yet */
 SENDNEWC 2        /*newchar set, previous sequence done */
 SENDCNT 3        /*newchar set, DLE sent, send count next */

 /* *** Stuff for second translation module *** */

 NOCHILD -1        /* indicates end of path through tree */
 NUMNODES (NUMVALS + NUMVALS - 1)        /* nbr of nodes */

 MAXCOUNT (UNSIGNED) 65535        /* biggest UNSIGNED integer */

 /* The following array of structures are the nodes of the
  * binary trees. The first NUMVALS nodes becomethe leaves of the
  * final tree and represent the values of the data bytes being
  * encoded and the special endfile, SPEOF.
  * The remaining nodes become the internal nodes of the final tree.
  */

 struct        nd {
         UNSIGNED weight;        /* number of appearances */
         INT tdepth;                /* length on longest path in tre*/
         INT lchild, rchild;        /* indexes to next level */
 } node[NUMNODES];

 INT dctreehd;        /*index to head node of final tree */

 /* This is the encoding table:
  * The bit strings have first bit in  low bit.
  * Note that counts were scaled so code fits UNSIGNED integer
  */

 INT codelen[NUMVALS];                /* number of bits in code */
 UNSIGNED code[NUMVALS];         /* code itself, right adjusted */
 UNSIGNED tcode;                 /* temporary code value */


 /* Variables used by encoding process */

 INT curin;        /* Value currently being encoded */
 INT cbitsrem;        /* Number of code string bits remaining */
 UNSIGNED ccode; /* Current code shifted so next code bit is at right */

 /* This program compresses a file without losing information.
  * The usq.com program is required to unsqueeze the file
  * before it can be used.
  *
  * Typical compression rates are:
  *        .COM        6%        (Don't bother)
  *        .ASM        33%        (using full ASCII set)
  *        .DIC        46%        (using only uppercase and a few others)
  * Squeezing a really big file takes a few minutes.
  *
  * Useage:
  *        sq file ...
  *
  *
  * The squeezed file name is formed by changing the second from last
  * letter of the file type to Q. If there is no file type,
  * the squeezed file type is QQQ. If the name exists it is
  * overwritten!
  *
  * The transformations compress strings of identical bytes and
  * then encode each resulting byte value and EOF as bit strings
  * having lengths in inverse proportion to their frequency of
  * occurrence in the intermediate input stream. The latter uses
  * the Huffman algorithm. Decoding information is included in
  * the squeezed file, so squeezing short files or files with
  * uniformly distributed byte values will actually increase size.
  */

 /* CHANGE HISTORY:
  * 1.5u *unix version - means output to stdout.
  *  (stdin not allowed becuase sq needs to rewind input, which
  *  won't work with pipes.)
  * Filename generation changed to suit **nix and stdio.
  * 1.6u machine independent output for file compatibility with
  *        original CP/M version SQ, when running on machine with
  *        IBM byte ordering such as Z8000 and 68000.
  * 1.7u machine independence was still lacking for 32-bit machines
  *        like the VAX-11/780, so a typedef was added.  No action
  *        need be taken if running on a 16-bit machine, but if
  *        running on a VAX, define VAX either on the cc line or
  *        in the program preamble.   Ben Goldfarb 12/13/82
  * 1.8u Modified to run under CI-86 compiler for the IBM PC
  *        Robert J. Beilstein 09/02/83
  */

 #define VERSION "1.8u   12-13-82"

 INT inbackground = 0;  /* change to 1 to suppress informative messages */

 INT buildenc(), gethuff(), getc_crc();

 main(argc, argv)
 INT argc;
 char *argv[];
 {
         register INT i,c;
 /*

         if (signal(SIGINT, SIG_IGN)==SIG_IGN)
                 inbackground++;
         else
                 signal(SIGINT, SIG_DFL);
         signal(SIGHUP, SIG_IGN);           */

         /* Process the parameters in order */
         for(i = 1; i < argc; ++i) {
                 if(strcmp(argv[i], "-")==0)
                         Usestd = TRUE;
         }
         for(i = 1; i < argc; ++i) {
                 if(strcmp(argv[i], "-")!=0)
                         obey(argv[i]);
         }

         if(argc < 2) {
                 fprintf(stderr,"File squeezer version %s by\n\tRichard Greenl
                 fprintf(stderr, "Usage: sq [-] pathname ...\n");
                 fprintf(stderr, "\t- squeezed output to stdout\n");
                 exit(1);
         }
         exit(0);
 }
 obey(p)
 unsigned char *p;
 {
         unsigned char *w,*q;
         unsigned char outfile[PATHLEN+2];         /* output file spec. */

         /* First build output file name */

         strcpy(outfile, p);
         /* Find and change output file type */
         for(w=q = outfile; *q != '\0'; ++q)     /* skip leading /'s */
                 if( *q == '/')
                         w = q+1;
         for(q = w; *q != '\0'; ++q)
                 if(*q == '.')
                         if(*(q + 1) == '\0')
                                 *q = '\0';      /* kill trailing dot */
                         else
                                 switch(*(q+2)) {
                                 case 'q':
                                 case 'Q':
                                         fprintf(stderr, "sq: %s ignored ( alr
                                         return;
                                 case '\0':
                                         *(q+3) = '\0';
                                         /* fall thru */
                                 default:
                                         *(q + 2) = 'Q';
                                         goto named;
                                 }
         /* No file type */
         strcat(outfile, ".QQQ");
 named:
         if(strlen(w)>14)
                 strcpy(outfile, ALTNAME);        /* check for too long name *
         squeeze(p, outfile);
 }

 squeeze(infile, outfile)
 unsigned char *infile, *outfile;
 {
         register INT i, c;
         FILE *inbuff, *outbuff; /* file buffers */

         if (!inbackground)
                 fprintf(stderr, "\n%s -> %s: ", infile, outfile);

         if((inbuff=fopen(infile, "rb")) == NULL) {
                 fprintf(stderr, "sq: can't open %s\n", infile);
                 return;
         }
         if(Usestd)
                 outbuff=stdout;
         else if((outbuff=fopen(outfile, "wb")) == NULL) {
                 fprintf(stderr, "sq: can't create %s\n", outfile);
                 fclose(inbuff);
                 return;
         }

         /* First pass - get properties of file */
         crc = 0;        /* initialize checksum */
         if (!inbackground)
                 fprintf(stderr, "analyzing, ");
         init_ncr();
         init_huff(inbuff);
         /* rewind(inbuff); */ fseek(inbuff,0L,0);

         /* Write output file header with decoding info */
         wrt_head(outbuff, infile);

         /* Second pass - encode the file */
         if (!inbackground)
                 fprintf(stderr, "squeezing, ");

         init_ncr();        /* For second pass */

         /* Translate the input file into the output file */
         while((c = gethuff(inbuff)) != EOF)
                 if(putc(c, outbuff) == ERROR && ferror(outbuff)) {
                         fprintf(stderr, "sq: write error\n");
                         goto closeall;
                 }
         if (!inbackground)
                 fprintf(stderr, " done.\n");
 closeall:
         fclose(inbuff);
 closeout:
         fflush(outbuff);
         fclose(outbuff);
 }


 /* First translation - encoding of repeated characters
  * The code is byte for byte pass through except that
  * DLE is encoded as DLE, zero and repeated byte values
  * are encoded as value, DLE, count for count >= 3.
  */

 init_ncr()        /*initialize getcnr() */
 {
         state = NOHIST;
 }

 INT
 getcnr(iob)
 FILE *iob;
 {
         switch(state) {
         case NOHIST:
                 /* No relevant history */
                 state = SENTCHAR;
                 return lastchar = getc_crc(iob);
         case SENTCHAR:
                 /* Lastchar is set, need lookahead */
                 switch(lastchar) {
                 case DLE:
                         state = NOHIST;
                         return 0;        /* indicates DLE was the data */
                 case EOF:
                         return EOF;
                 default:
                         for(likect = 1; (newchar = getc_crc(iob)) == lastchar
                                 ;
                         switch(likect) {
                         case 1:
                                 return lastchar = newchar;
                         case 2:
                                 /* just pass through */
                                 state = SENDNEWC;
                                 return lastchar;
                         default:
                                 state = SENDCNT;
                                 return DLE;
                         }
                 }
         case SENDNEWC:
                 /* Previous sequence complete, newchar set */
                 state = SENTCHAR;
                 return lastchar = newchar;
         case SENDCNT:
                 /* Sent DLE for repeat sequence, send count */
                 state = SENDNEWC;
                 return likect;
         default:
                 fprintf(stderr,"sq: Bug - bad state\n");
                 exit(1);
                 /* NOTREACHED */
         }
 }


 /******** Second translation - bytes to variable length bit strings *********


 /* This translation uses the Huffman algorithm to develop a
  * binary tree representing the decoding information for
  * a variable length bit string code for each input value.
  * Each string's length is in inverse proportion to its
  * frequency of appearance in the incoming data stream.
  * The encoding table is derived from the decoding table.
  *
  * The range of valid values into the Huffman algorithm are
  * the values of a byte stored in an integer plus the special
  * endfile value chosen to be an adjacent value. Overall, 0-SPEOF.
  *
  * The "node" array of structures contains the nodes of the
  * binary tree. The first NUMVALS nodes are the leaves of the
  * tree and represent the values of the data bytes being
  * encoded and the special endfile, SPEOF.
  * The remaining nodes become the internal nodes of the tree.
  *
  * In the original design it was believed that
  * a Huffman code would fit in the same number of
  * bits that will hold the sum of all the counts.
  * That was disproven by a user's file and was a rare but
  * infamous bug. This version attempts to choose among equally
  * weighted subtrees according to their maximum depths to avoid
  * unnecessarily long codes. In case that is not sufficient
  * to guarantee codes <= 16 bits long, we initially scale
  * the counts so the total fits in an unsigned integer, but
  * if codes longer than 16 bits are generated the counts are
  * rescaled to a lower ceiling and code generation is retried.
  */

 /* Initialize the Huffman translation. This requires reading
  * the input file through any preceding translation functions
  * to get the frequency distribution of the various values.
  */

 init_huff(ib)
 FILE *ib;
 {
         register INT c, i;
         INT btlist[NUMVALS];        /* list of intermediate binary trees */
         INT listlen;                /* length of btlist */
         UNSIGNED *wp;                /* simplifies weight counting */
         UNSIGNED ceiling;        /* limit for scaling */

         /* Initialize tree nodes to no weight, no children */
         init_tree();

         /* Build frequency info in tree */
         do {
                 c = getcnr(ib);
                 if(c == EOF)
                         c = SPEOF;
                 if(*(wp = &node[c].weight) !=  MAXCOUNT)
                         ++(*wp);
         }
         while(c != SPEOF);

         ceiling = MAXCOUNT;

         do {        /* Keep trying to scale and encode */
                 if(ceiling != MAXCOUNT)
                         fprintf(stderr, "sq: *** rescaling ***, ");
                 scale(ceiling);
                 ceiling /= 2;        /* in case we rescale */

                 /* Build list of single node binary trees having
                                  * leaves for the input values with non-zero
                                  */
                 for(i = listlen = 0; i < NUMVALS; ++i)
                         if(node[i].weight != 0) {
                                 node[i].tdepth = 0;
                                 btlist[listlen++] = i;
                         }

                 /* Arrange list of trees into a heap with the entry
                                  * indexing the node with the least weight at
                                  */
                 heap(btlist, listlen);

                 /* Convert the list of trees to a single decoding tree */
                 bld_tree(btlist, listlen);

                 /* Initialize the encoding table */
                 init_enc();

                 /* Try to build encoding table.
                                  * Fail if any code is > 16 bits long.
                                  */
         }
         while(buildenc(0, dctreehd) == ERROR);

         /* Initialize encoding variables */
         cbitsrem = 0;        /*force initial read */
         curin = 0;        /*anything but endfile*/
 }

 /* The count of number of occurrances of each input value
  * have already been prevented from exceeding MAXCOUNT.
  * Now we must scale them so that their sum doesn't exceed
  * ceiling and yet no non-zero count can become zero.
  * This scaling prevents errors in the weights of the
  * interior nodes of the Huffman tree and also ensures that
  * the codes will fit in an unsigned integer. Rescaling is
  * used if necessary to limit the code length.
  */

 scale(ceil)
 UNSIGNED ceil;        /* upper limit on total weight */
 {
         register INT i,c;
         INT ovflw, divisor;
         UNSIGNED w, sum;
         unsigned char increased;         /* flag */

         do {
                 for(i = sum = ovflw = 0; i < NUMVALS; ++i) {
                         if(node[i].weight > (ceil - sum))
                                 ++ovflw;
                         sum += node[i].weight;
                 }

                 divisor = ovflw + 1;

                 /* Ensure no non-zero values are lost */
                 increased = FALSE;
                 for(i = 0; i < NUMVALS; ++i) {
                         w = node[i].weight;
                         if (w < divisor && w != 0) {
                                 /* Don't fail to provide a code if it's used
                                 node[i].weight = divisor;
                                 increased = TRUE;
                         }
                 }
         }
         while(increased);

         /* Scaling factor choosen, now scale */
         if(divisor > 1)
                 for(i = 0; i < NUMVALS; ++i)
                         node[i].weight /= divisor;
 }

 /* heap() and adjust() maintain a list of binary trees as a
  * heap with the top indexing the binary tree on the list
  * which has the least weight or, in case of equal weights,
  * least depth in its longest path. The depth part is not
  * strictly necessary, but tends to avoid long codes which
  * might provoke rescaling.
  */

 heap(list, length)
 INT list[], length;
 {
         register INT i;

         for(i = (length - 2) / 2; i >= 0; --i)
                 adjust(list, i, length - 1);
 }

 /* Make a heap from a heap with a new top */

 adjust(list, top, bottom)
 INT list[], top, bottom;
 {
         register INT k, temp;

         k = 2 * top + 1;        /* left child of top */
         temp = list[top];        /* remember root node of top tree */
         if( k <= bottom) {
                 if( k < bottom && cmptrees(list[k], list[k + 1]))
                         ++k;

                 /* k indexes "smaller" child (in heap of trees) of top */
                 /* now make top index "smaller" of old top and smallest child
                 if(cmptrees(temp, list[k])) {
                         list[top] = list[k];
                         list[k] = temp;
                         /* Make the changed list a heap */
                         adjust(list, k, bottom); /*recursive*/
                 }
         }
 }

 /* Compare two trees, if a > b return true, else return false
  * note comparison rules in previous comments.
  */

 cmptrees(a, b)
 INT a, b;        /* root nodes of trees */
 {
         if(node[a].weight > node[b].weight)
                 return TRUE;
         if(node[a].weight == node[b].weight)
                 if(node[a].tdepth > node[b].tdepth)
                         return TRUE;
         return FALSE;
 }

 /* HUFFMAN ALGORITHM: develops the single element trees
  * into a single binary tree by forming subtrees rooted in
  * interior nodes having weights equal to the sum of weights of all
  * their descendents and having depth counts indicating the
  * depth of their longest paths.
  *
  * When all trees have been formed into a single tree satisfying
  * the heap property (on weight, with depth as a tie breaker)
  * then the binary code assigned to a leaf (value to be encoded)
  * is then the series of left (0) and right (1)
  * paths leading from the root to the leaf.
  * Note that trees are removed from the heaped list by
  * moving the last element over the top element and
  * reheaping the shorter list.
  */

 bld_tree(list, len)
 INT list[];
 INT len;
 {
         register INT freenode;                /* next free node in tree */
         register struct nd *frnp;        /* free node pointer */
         INT lch, rch;                /* temporaries for left, right children
         INT i;

         /* Initialize index to next available (non-leaf) node.
                  * Lower numbered nodes correspond to leaves (data values).
                  */
         freenode = NUMVALS;

         while(len > 1) {
                 /* Take from list two btrees with least weight
                                  * and build an interior node pointing to the
                                  * This forms a new tree.
                                  */
                 lch = list[0];        /* This one will be left child */

                 /* delete top (least) tree from the list of trees */
                 list[0] = list[--len];
                 adjust(list, 0, len - 1);

                 /* Take new top (least) tree. Reuse list slot later */
                 rch = list[0];        /* This one will be right child */

                 /* Form new tree from the two least trees using
                                  * a free node as root. Put the new tree in t
                                  */
                 frnp = &node[freenode]; /* address of next free node */
                 list[0] = freenode++;        /* put at top for now */
                 frnp->lchild = lch;
                 frnp->rchild = rch;
                 frnp->weight = node[lch].weight + node[rch].weight;
                 frnp->tdepth = 1 + maxchar(node[lch].tdepth, node[rch].tdepth
                 /* reheap list        to get least tree at top*/
                 adjust(list, 0, len - 1);
         }
         dctreehd = list[0];        /*head of final tree */
 }

 /* ???????????? */
 maxchar(a, b)
 {
         return a > b ? a : b;
 }
 /* Initialize all nodes to single element binary trees
  * with zero weight and depth.
  */

 init_tree()
 {
         register INT i;

         for(i = 0; i < NUMNODES; ++i) {
                 node[i].weight = 0;
                 node[i].tdepth = 0;
                 node[i].lchild = NOCHILD;
                 node[i].rchild = NOCHILD;
         }
 }

 init_enc()
 {
         register INT i;

         /* Initialize encoding table */
         for(i = 0; i < NUMVALS; ++i) {
                 codelen[i] = 0;
         }
 }

 /* Recursive routine to walk the indicated subtree and level
  * and maintain the current path code in bstree. When a leaf
  * is found the entire code string and length are put into
  * the encoding table entry for the leaf's data value .
  *
  * Returns ERROR if codes are too long.
  */

 INT                /* returns ERROR or NULL */
 buildenc(level, root)
 INT level;/* level of tree being examined, from zero */
 INT root; /* root of subtree is also data value if leaf */
 {
         register INT l, r;

         l = node[root].lchild;
         r = node[root].rchild;

         if( l == NOCHILD && r == NOCHILD) {
                 /* Leaf. Previous path determines bit string
                                  * code of length level (bits 0 to level - 1)
                                  * Ensures unused code bits are zero.
                                  */
                 codelen[root] = level;
                 code[root] = tcode & (((UNSIGNED)~0) >> (16 - level));
                 return (level > 16) ? ERROR : NULL;
         }
         else {
                 if( l != NOCHILD) {
                         /* Clear path bit and continue deeper */
                         tcode &= ~(1 << level);
                         /* NOTE RECURSION */
                         if(buildenc(level + 1, l) == ERROR)
                                 return ERROR;
                 }
                 if(r != NOCHILD) {
                         /* Set path bit and continue deeper */
                         tcode |= 1 << level;
                         /* NOTE RECURSION */
                         if(buildenc(level + 1, r) == ERROR)
                                 return ERROR;
                 }
         }
         return NULL;        /* if we got here we're ok so far */
 }

 /* Write out the header of the compressed file */

 wrt_head(ob, infile)
 FILE *ob;
 unsigned char *infile;         /* input file name (w/ or w/o drive) */
 {
         register INT l,r;
         INT i, k;
         INT numnodes;                /* nbr of nodes in simplified tree */

         putwe(RECOGNIZE, ob);        /* identifies as compressed */
         putwe(crc, ob);         /* unsigned sum of original data */

         /* Record the original file name w/o drive */
         if(*(infile + 1) == ':')
                 infile += 2;        /* skip drive */

         do {
                 putce(*infile, ob);
         }
         while(*(infile++) != '\0');


         /* Write out a simplified decoding tree. Only the interior
                  * nodes are written. When a child is a leaf index
                  * (representing a data value) it is recoded as
                  * -(index + 1) to distinguish it from interior indexes
                  * which are recoded as positive indexes in the new tree.
                  * Note that this tree will be empty for an empty file.
                  */

         numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS -1);
         putwe(numnodes, ob);

         for(k = 0, i = dctreehd; k < numnodes; ++k, --i) {
                 l = node[i].lchild;
                 r = node[i].rchild;
                 l = l < NUMVALS ? -(l + 1) : dctreehd - l;
                 r = r < NUMVALS ? -(r + 1) : dctreehd - r;
                 putwe(l, ob);        /* left child */
                 putwe(r, ob);        /* right child */
         }
 }

 /* Get an encoded byte or EOF. Reads from specified stream AS NEEDED.
  *
  * There are two unsynchronized bit-byte relationships here.
  * The input stream bytes are converted to bit strings of
  * various lengths via the static variables named c...
  * These bit strings are concatenated without padding to
  * become the stream of encoded result bytes, which this
  * function returns one at a time. The EOF (end of file) is
  * converted to SPEOF for convenience and encoded like any
  * other input value. True EOF is returned after that.
  *
  * The original gethuff() called a seperate function,
  * getbit(), but that more readable version was too slow.
  */

 INT                /*  Returns byte values except for EOF */
 gethuff(ib)
 FILE *ib;
 {
         INT rbyte;        /* Result byte value */
         INT need, take; /* numbers of bits */

         rbyte = 0;
         need = 8;        /* build one byte per call */

         /* Loop to build a byte of encoded data
                  * Initialization forces read the first time
                  */

 loop:
         if(cbitsrem >= need) {
                 /* Current code fullfills our needs */
                 if(need == 0)
                         return rbyte;
                 /* Take what we need */
                 rbyte |= ccode << (8 - need);
                 /* And leave the rest */
                 ccode >>= need;
                 cbitsrem -= need;
                 return rbyte & 0xff;
         }

         /* We need more than current code */
         if(cbitsrem > 0) {
                 /* Take what there is */
                 rbyte |= ccode << (8 - need);
                 need -= cbitsrem;
         }
         /* No more bits in current code string */
         if(curin == SPEOF) {
                 /* The end of file token has been encoded. If
                                  * result byte has data return it and do EOF
                                  */
                 cbitsrem = 0;

                 /*NOTE: +0 is to fight compiler bug? */
                 return (need == 8) ? EOF : rbyte + 0;
         }

         /* Get an input byte */
         if((curin = getcnr(ib)) == EOF)
                 curin = SPEOF;        /* convenient for encoding */

         /* Get the new byte's code */
         ccode = code[curin];
         cbitsrem = codelen[curin];

         goto loop;
 }


 /* Get next byte from file and update checksum */

 INT
 getc_crc(ib)
 FILE *ib;
 {
         register INT c;

         c = getc(ib);
         if(c != EOF)
                 crc += c;        /* checksum */
         return c;
 }

 /* Output functions with error reporting */

 putce(c, iob)
 INT c;
 FILE *iob;
 {
         if(putc(c, iob) == ERROR && ferror(iob)) {
                 fprintf(stderr, "sq: write error\n");
                 exit(1);
         }
 }

 /*
  * machine independent put-word that writes low order byte first
  *  (compatible with CP/M original) regardless of host cpu.
  */
 putwe(w, iob)
 INT w;
 FILE *iob;
 {
         putc(w, iob);
         putc(w>>8, iob);
         if (ferror(iob)) {
                 fprintf(stderr, "sq: write error\n");
                 exit(1);
         }
 }


 SQDEBUG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\SQDEBUG.C

 /* Debugging aids for SQ and related modules */

 #include <stdio.h>
 #include "sqcom.h"
 #include "sq.h"

 pcounts()
 {
         int i;

         if(debug) {
                 printf("\nCounts after 1st algorithm and maybe scaling");
                 for(i = 0; i < NUMVALS; ++i) {
                         if(i%8 == 0)
                                 printf("\n%4x  ", i);
                         printf("%5u  ", node[i].weight);
                 }
         printf("\n\n");
         }
 }

 phuff()
 {
         int i;

         if(debug) {
                 printf("\nEncoding tree - root=%3d\n", dctreehd);
                 for(i = 0; i < NUMNODES; ++i)
                         if(node[i].weight != 0)
                                 printf("%3d  w=%5u d=%3d l=%3d r=%3d\n", i, n

                 printf("\nHuffman codes\n");
                 for(i = 0; i < NUMVALS; ++i) {
                         if(codelen[i] > 0)
                                 printf("%3d  %4x l=%2d c=%4x\n", i, i, codele
                 }
         }
 }


 SQIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\SQIO.C

 #include <stdio.h>
 #include "sqcom.h"
 #include "sq.h"
 #define ERROR -1

 /* Get next byte from file and update checksum */

 int
 getc_crc(ib)
 FILE *ib;
 {
         int c;

         c = getc(ib);
         if (c != EOF)
                 crc += c;                /* checksum */
         return c;
 }

 /* Output functions with error reporting */

 static char obuf[128];
 static int oblen = 0;

 putce(c,  iob)
 int c;
 FILE *iob;
 {
         obuf[oblen++] = c;
         if (oblen >= sizeof(obuf)) oflush(iob);
 }

 putwe(w,  iob)
 int w;
 FILE *iob;
 {
         obuf[oblen++] = w;
         if (oblen >= sizeof(obuf)) oflush(iob);
         obuf[oblen++] = w >> 8;
         if (oblen >= sizeof(obuf)) oflush(iob);
 }

 oflush(iob)                                /* flush output buffer */
 FILE *iob;
 {
         if (oblen && !fwrite(obuf, oblen, 1, iob)) {
                 printf("Error writing output file\n");
                 exit(1);
         }
         oblen = 0;
 }


 SQRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\SQRT.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/


 #include "math.h"
 #include "errno.h"

 double sqrt(x)
 double x;
 {
         double f, y;
         int n;
         extern int errno;

         if (x == 0.0)
                 return x;
         if (x < 0.0) {
                 errno = EDOM;
                 return 0.0;
         }
         f = frexp(x, &n);
         y = 0.41731 + 0.59016 * f;
         y = (y + f/y);
         y = ldexp(y,-2) + f/y;  /* fast calculation of y2 */
         y = ldexp(y + f/y, -1);
         y = ldexp(y + f/y, -1);

         if (n&1) {
                 y *= 0.70710678118654752440;
                 ++n;
         }
         return ldexp(y,n/2);
 }



 SQUARE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\GRAPHICS\SQUARE.C

 /**********************************************************************
 SQUARE
 Description - draws a square
 **********************************************************************
 Function - square(x,y,side)
 Input - xy coord of upper left corner, length of one side
 Output - to the screen
 #includes - none
 #defines  - none
 Routines Called - rectangle, line, plotxy
 Notes -
 **********************************************************************/
 square(x,y,side)
 int x,y,side;
 {
   rectangle(x,y,side,side);
   return;
 }
 /******************** end of function ********************************/


 SQUARES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SQUARES.C

                                           /* Chapter 5 - Program 2 */
 main()  /* This is the main program */
 {
 int x,y;

    for(x = 0;x <= 7;x++) {
       y = squ(x);  /* go get the value of x*x */
       printf("The square of %d is %d\n",x,y);
    }

    for (x = 0;x <= 7;++x)
       printf("The value of %d is %d\n",x,squ(x));
 }

 squ(in)  /* function to get the value of in squared */
 int in;
 {
 int square;

    square = in * in;
    return(square);  /* This sets squ() = square */
 }


 SQUIG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\SQUIG.C

 /*                      Fractal Generation Program
 */

 #include <stdio.h>
 #include <math.h>

 #define FALSE 0
 #define TRUE 1

 /* Movement directions: */

 #define UP 0
 #define DOWN 1
 #define LEFT 2
 #define RIGHT 3

 /* Table to convert from the direction of a segment being drawn (first
    index) and the direction of a subsegment (second index) to absolute
    screen up/down/left/right: */

 int dirDir[4][4] = {
         LEFT, RIGHT, DOWN, UP,  /* Line up. */
         RIGHT, LEFT, UP, DOWN,  /* Line down. */
         DOWN, UP, RIGHT, LEFT,  /* Line left. */
         UP, DOWN, LEFT, RIGHT   /* Line right. */
 };

 /* X-axis multiplier for up/down/left/right movement: */

 int xDir[4] = {
         0, 0, -1, 1     /* Line right. */
 };

 /* Y-axis multiplier for up/down/left/right movement: */

 int yDir[4] = {
         -1, 1, 0, 0     /* Line right. */
 };

 int boxPatt[100];       /* The box pattern. */
 int boxPSz;             /* It's size. */

 int linePatt[100];      /* The line pattern. */
 int linePSz;            /* It's size. */
 int lineLen;            /* Width of line pattern in line segments. */

 int level;              /* The level of detail to go to. */

 float x, y;             /* The current pen position. */

 int color;              /* The current pen color. */

 /*      main()

         Function: Get box and line patterns, the line size, and the
         level to draw to from the user. Then draw the fractal. When
         done, ask if another one should be drawn. Repeat the sequence
         as long as the user wants.

         Algorithm: Use getPatt to read in the patterns for the box and
         the line pattern. Use gets/atoi for the other, numeric input.
         Then call doPatt to actually draw the fractal.
 */

 main()

 {
         char str[100];  /* Input buffer for user responses. */
         int side;       /* Size of line in screen dots. */

         /* Repeat while the user wants more. */
         do {
                 /* Set the display mode; use 6 for CGA, 14 for EGA with
                    color display, or 16 for EGA with enhanced color disp. */
                 setMod(6);
                 /* Get the box pattern. */
                 getPatt("box",boxPatt,&boxPSz,TRUE,TRUE);
                 /* Get the size of the box line. */
                 printf("Side size: ");
                 gets(str);
                 side = atoi(str);
                 /* Get the line pattern. */
                 lineLen = getPatt("line",linePatt,&linePSz,TRUE,FALSE);
                 /* Get the level to display to. */
                 printf("Level: ");
                 gets(str);
                 level = atoi(str);
                 /* Set the pen position and color to start with. */
                 x = 270; y = 50; color = 7;
                 /* Draw the fractal. */
                 doPatt(boxPatt,boxPSz,RIGHT,(float) side,0);
                 /* Ask if the user wants to do another one. */
                 printf("Do another one? ");
                 gets(str);
         } while ((str[0] == 'y') || (str[0] == 'Y'));
 }

 /*      getPatt(prmpt,patt,size,noUp,noLeft)

         Function: Get a pattern from the user. Issue the prompt
         string pointed to by prmpt. Then read the pattern into
         the pattern array pointed to by patt, and set the size
         pointed to by size. If noUp is TRUE, don't allow patterns
         that end at a different up/down level than they began.
         If noLeft is TRUE, don't allow patterns that end at a
         different left/right level than they started. getPatt
         returns the number of segments to the right the pattern
         ends at from its starting position.

         Algorithm: Prompt the user and then read in the pattern
         string. Scan through it, converting from 'u'/'d'/'l'/'r'
         to UP/DOWN/LEFT/RIGHT. When done, check it for validity.
         If it fails, tell the user and do it all over again.
 */

 getPatt(prmpt,patt,size,noUp,noLeft)

 char *prmpt;
 int *patt;
 int *size;
 int noUp;
 int noLeft;

 {
         char str[100];          /* Input buffer for user input. */
         char *cp;               /* Char pointer to scan buffer with. */
         int *pPtr;              /* Pattern array pointer. */
         int upCnt, rightCnt;    /* Up/down and left/right offsets. */
         int badPatt;            /* TRUE if pattern is bad. */

         /* Repeat until he gets it right. */
         do {
                 /* Prompt him for a pattern string. */
                 printf("Enter %s pattern: ",prmpt); gets(str);
                 /* Assume the pattern's OK. */
                 badPatt = FALSE;
                 /* Scan through the pattern string. */
                 for (cp = str, pPtr = patt, upCnt = rightCnt = 0, *size = 0;
                      *cp != 0; cp++, pPtr++, (*size)++) {
                         switch (*cp) {
                                 case 'u':
                                 case 'U':
                                         /* Up one. */
                                         *pPtr = UP;
                                         upCnt++;
                                         break;
                                 case 'd':
                                 case 'D':
                                         /* Down one. */
                                         *pPtr = DOWN;
                                         upCnt--;
                                         break;
                                 case 'l':
                                 case 'L':
                                         /* Left one. */
                                         *pPtr = LEFT;
                                         rightCnt--;
                                         break;
                                 case 'r':
                                 case 'R':
                                         *pPtr = RIGHT;
                                         rightCnt++;
                                         break;
                                 default:
                                         badPatt = TRUE;
                                         break;
                         };
                         if (badPatt) {
                                 printf("Only U, D, L, or R allowed!\n");
                                 break;
                         };
                 };
                 if (noUp && (upCnt != 0)) {
                         printf("Pattern must end at the same up/down level ")
                         printf("it began at.\n");
                         badPatt = TRUE;
                 };
                 if (noLeft && (rightCnt != 0)) {
                         printf("Pattern must end at the same right/left ");
                         printf("level it began at.\n");
                         badPatt = TRUE;
                 };
         } while (badPatt);
         return(rightCnt);
 }

 /*      doPatt(patt,pattSize,dir,size,lev)

         Function: Draw the pattern pointed to by patt, of size pattSize,
         in the direction dir (UP, DOWN, LEFT, or RIGHT), with each line
         segment of size size; this will be level lev. If lev doesn't yet
         match the global variable level, then recursively call doPatt to
         draw each segment as a series of segments from the line pattern.

         Algorithm: For each segment in the pattern, if we're at the drawing
         level (lev == level), then figure out the proper direction to
         draw and draw the segment; otherwise, call doPatt to draw the
         sub-pattern.
 */

 doPatt(patt,pattSize,dir,size,lev)

 int *patt;
 int pattSize;
 int dir;
 float size;
 int lev;

 {
         int *pPtr;                      /* A pointer into the pattern. */
         int pCnt;                       /* Count of pattern segments left. */
         int xPlusMinus, yPlusMinus;     /* The x and y drawing increments. */
         register int i, j;              /* Row and column drawing indices. */
         int iEnd, jEnd;                 /* Where to stop drawing. */
         int temp;
         int subDir;                     /* The absolute up/down/left/right. *
         int dotVal;                     /* Color to draw. */

         /* For each segment in the pattern... */
         for (pPtr = patt, pCnt = 0; pCnt++ < pattSize; pPtr++) {
                 /* If we're at drawing level... */
                 if (lev == level) {
                         /* Find the absolute direction. */
                         subDir = dirDir[dir][*pPtr];
                         /* Convert the pen position to row/column ints. */
                         i = x; j = y;
                         /* Get the pen increment for drawing. */
                         xPlusMinus = xDir[subDir];
                         yPlusMinus = yDir[subDir];
                         /* Compute the new pen position after drawing. */
                         x += xPlusMinus*size; y += yPlusMinus*size;
                         /* Convert the end point to row/column ints. */
                         iEnd = x; jEnd = y;
                         /* We always want to draw in ascending coordinates.
                            Therefore, we must swap i/iEnd and j/jEnd if
                            we'd be drawing descending. */
                         if (iEnd < i) {
                                 temp = i; i = iEnd; iEnd = temp;
                         };
                         if (jEnd < j) {
                                 temp = j; j = jEnd; jEnd = temp;
                         };
                         /* Similarly, we need the abs of the increments. */
                         xPlusMinus = abs(xPlusMinus);
                         yPlusMinus = abs(yPlusMinus);
                         /* Set the color to draw. For the EGA, this should
                            be the global variable color; for CGA, it should
                            be 1. */
                         dotVal = 1 /*color*/;
                         /* Decide whether we're drawing a vertical or
                            horizontal line. */
                         if (xPlusMinus == 0) {
                                 /* If vertical, draw it. */
                                 do putDot(0,j++,i,dotVal); while (j < jEnd);
                         } else {
                                 /* If horizontal, draw it. */
                                 do putDot(0,j,i++,dotVal); while (i < iEnd);
                         };

                 /* If we're not down to drawing level yet, call doPatt to
                    draw the next level down. */
                 } else doPatt(linePatt,linePSz,dirDir[dir][*pPtr],
                               size/((float) lineLen),lev+1);

                 /* If this is the top level, switch to the next color for
                    drawing the next segment. */
                 if (lev == 0) {
                         color--;
                         if (color == 0) color = 15;
                 };
         };
 }



 SRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\SRT.C

 /* SDB - sort routines */

 #include "stdio.h"
 #include "sdbio.h"

 extern int dbv_token;
 extern char dbv_tstring[];
 extern int dbv_tvalue;

 /* get_skeys - get sort key list */
 static struct skey *get_skeys(sptr)
   struct scan *sptr;
 {
     struct skey *skeys,*newskey,*lastskey;

     /* parse a list of attribute names */
     skeys = lastskey = NULL;
     while (TRUE) {

         /* get attribute name */
         if (db_ntoken() != ID)
             return (db_nerror(SYNTAX));

         /* allocate a sort key structure */
         if ((newskey = malloc(sizeof(struct skey))) == NULL)
             return (db_nerror(INSMEM));

         /* initialize the sort key structure */
         newskey->sk_next = NULL;

         /* lookup the attribute name */
         if (!find_attr(sptr,newskey,dbv_tstring)) {
             free(newskey);
             return (NULL);
         }

         /* check for ascending or descending */
         if (db_token() == ASCENDING || dbv_token == DESCENDING) {
             newskey->sk_type = dbv_token;
             db_ntoken();
         }
         else
             newskey->sk_type = ASCENDING;

         /* link the sort key structure into the list */
         if (lastskey == NULL)
             skeys = newskey;
         else
             lastskey->sk_next = newskey;
         lastskey = newskey;

         /* check for more attributes */
         if (db_token() != ',')
             break;
         db_ntoken();
     }

     /* return successfully */
     return (skeys);
 }

 /* db_sort - sort tuples in a relation */
 int *db_sort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
   char *fmt;
 {
     struct scan *sptr1,*sptr2,*sptr3;   /*dns*/
     struct skey *skeys;
     int result;

     /* check for a command line */
     if (fmt != NULL)
         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

     /* checks for relation name */
     if (db_token() == ID)
         db_ntoken();
     else
         strcpy(dbv_tstring,"sdbcur");

     /* open the relation */
     if ((sptr1 = db_ropen(dbv_tstring)) == NULL)
         return (FALSE);
     if ((sptr2 = db_ropen(dbv_tstring)) == NULL) {
         db_rclose(sptr1);
         return (FALSE);
         }
     if ((sptr3 = db_ropen(dbv_tstring)) == NULL) {   /*dns*/
         db_rclose(sptr1);                            /*dns*/
         db_rclose(sptr2);                            /*dns*/
         return (FALSE);                              /*dns*/
         }

     /* checks for "<relation-name> by <sort-list>" */
     if (db_ntoken() != BY)
         return (db_ferror(SYNTAX));
     if ((skeys = get_skeys(sptr1)) == NULL) {
         db_rclose(sptr1);
         db_rclose(sptr2);
         db_rclose(sptr3);  /*dns*/
         return (FALSE);
        }

     /* do the sort */
     result = sort(skeys,sptr1,sptr2,sptr3);  /*dns*/

     /* close the relation */
     db_rclose(sptr1);
     db_rclose(sptr2);
     db_rclose(sptr3);     /*dns*/

     /* free the sort keys */
     free_skeys(skeys);

     return (result);
 }

 /* free_skeys - free a list of sort keys */
 static free_skeys(skeys)
   struct skey *skeys;
 {
     struct skey *thisskey;

     for (thisskey = skeys; skeys != NULL; thisskey = skeys) {
         skeys = skeys->sk_next;
         free(thisskey);
     }
 }

 /* find_attr - find an attribute */
 static int find_attr(sptr,newskey,aname)
   struct scan *sptr; struct skey *newskey; char *aname;
 {
     struct attribute *aptr;
     int i,astart;

     /* loop through each attribute within the relation */
     astart = 1;
     for (i = 0; i < NATTRS; i++) {

         /* get a pointer to the current attribute */
         aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

         /* check for last attribute */
         if (aptr->at_name[0] == 0)
             break;

         /* check for attribute name match */
         if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
             newskey->sk_start = astart;
             newskey->sk_aptr = aptr;
             return (TRUE);
         }

         /* update the attribute start */
         astart += aptr->at_size;
     }

     /* attribute name not found */
     return (db_ferror(ATUNDF));
 }

 /* sort - sort the relation */
 static int sort(skeys,sptr1,sptr2,sptr3)
   struct skey *skeys; struct scan *sptr1,*sptr2,*sptr3;
 {
 /*  unsigned int j,k,l,r;          dns */
     long int passes,swaps;           /*dns*/
     int i, j, m, n;         /*dns*/
     int rec1 = 0;           /*dns*/
     int rec2 = 0;           /*dns*/
     int rec3 = 0;           /*dns*/
     int dns = 0;            /*dns*/
     FILE *test;             /*dns*/

     passes = 0L;
     swaps = 0L;

     /*dns --->   */
     test = fopen("sort.dat", "w");
     n = sptr1->sc_relation->rl_tcnt;
     m = n;

     while( m>1 )   {
        passes++;
        if ((m/=3.14159) < 1)  m = 1;
        for ( j=1; j<=n-m; j++ )  {
           if( rec1 != j+m )  {
              if(dns) fprintf(test,"Read1: %d\n", j+m);
              if (!db_rget(sptr1, rec1=j+m))  return (FALSE);
              }
           for ( i=j; i>=1; i-=m ) {
              if( rec2 != i )   {
                 if(dns) fprintf(test,"Read2: %d\n", i);
                 if (!db_rget(sptr2, rec2=i))  return (FALSE);
                 }
              if (compare(skeys,sptr1,sptr2) > 0)
                 break;
              if(rec3 != i+m)  {
                 if(dns) fprintf(test,"Read3: %d\n", i+m);
                 if (!db_rget(sptr3, rec3=i+m))  return (FALSE);
                 }
              if(dns) fprintf(test,"Write 3,2: %d from %d\n", i+m, i);
              assign( sptr3, sptr2 );
              swaps++;
              }
           if(rec1 != i+m)  {
              if(rec3 != i+m)  {
                 if(dns) fprintf(test,"Read 3: %d\n", i+m);
                 if (!db_rget(sptr3, rec3=i+m))  return (FALSE);
                 }
              if(dns) fprintf(test,"Write 3,1: %d from %d\n", i+m, j+m);
              assign( sptr3, sptr1 );
              swaps++;
              }
           }
        }
        fclose(test);

 /*
     l = 2;
     r = sptr1->sc_relation->rl_tcnt;
     k = r;

     do {
         for (j = r; j >= l; j--) {
             if (!db_rget(sptr1,j-1))
                 return (FALSE);
             if (!db_rget(sptr2,j))
                 return (FALSE);
             if (compare(skeys,sptr1,sptr2) > 0) {
                 swap(sptr1,sptr2);
                 k = j;
                 swaps++;
             }
         }
         l = k + 1;
         for (j = l; j <= r; j++) {
             if (!db_rget(sptr1,j-1))
                 return (FALSE);
             if (!db_rget(sptr2,j))
                 return (FALSE);
             if (compare(skeys,sptr1,sptr2) > 0) {
                 swap(sptr1,sptr2);
                 k = j;
                 swaps++;
             }
         }
         r = k - 1;
         passes++;
     } while (l <= r);
 */

     printf("[ Passes: %ld  Swaps: %ld ]\n",passes,swaps);

     return (TRUE);
 }

 /* compare - compare two tuples */
 static int compare(skeys,sptr1,sptr2)
   struct skey *skeys; struct scan *sptr1,*sptr2;
 {
     struct skey *cskey;
     int result;

     for (cskey = skeys; cskey != NULL; cskey = cskey->sk_next)
         if ((result = cattr(cskey,sptr1,sptr2)) != 0)
             break;

     return (result);
 }

 /* cattr - compare two attributes */
 static int cattr(cskey,sptr1,sptr2)
   struct skey *cskey; struct scan *sptr1,*sptr2;
 {
     int astart,aend,i;

     astart = cskey->sk_start;
     aend = astart + cskey->sk_aptr->at_size;

     for (i = astart; i < aend; i++)
         if (sptr1->sc_tuple[i] != sptr2->sc_tuple[i])
             break;

     if (i == aend)
         return (0);

     if (sptr1->sc_tuple[i] < sptr2->sc_tuple[i])
         if (cskey->sk_type == ASCENDING)
             return (-1);
         else
             return (1);
     else
         if (cskey->sk_type == ASCENDING)
             return (1);
         else
             return (-1);
 }

 /* swap - swap two tuples */
 /* dns
 static int swap(sptr1,sptr2)
   struct scan *sptr1,*sptr2;
 {
     unsigned int tnum1,tnum2;

     tnum1 = sptr1->sc_atnum;
     tnum2 = sptr2->sc_atnum;

     if (!db_rput(sptr1,tnum2))
         return (FALSE);
     if (!db_rput(sptr2,tnum1))
         return (FALSE);

     return (TRUE);
 }
   dns  */


 /* assign - assign one tupple to another */
 static int assign(sptr1,sptr2)
   struct scan *sptr1,*sptr2;
 {
     unsigned int tnum1,tnum2;

     tnum1 = sptr1->sc_atnum;

     if (!db_rput(sptr2,tnum1))
         return (FALSE);

     return (TRUE);
 }



 SRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SRT.C

 #include          <stdio.h>
 #include          <ctype.h>

  MAXWORD  80                           /* maximum word length */
  NEWLINE  putc('\n',fp)     /* put carraige return in file fp */

 struct text {               /* global declaration of tree node 'text' */
              char word[MAXWORD];
              struct text *lptr;
              struct text *rptr;
 };

 struct text *root;         /* global declaration of root of text tree */

 main(argc, argv)
   /*-----------------------------------------------------------------*/
   /* driver for sort procedure.  Srt will sort lines of a specified  */
   /* input file and place the result in either the stdout or a       */
   /* specified output file.  Program is written for Lattice C but    */
   /* functions provided in its library are documented so that srt    */
   /* might be modified to suit your compiler.  If you have any       */
   /* trouble or questions give me a call (if you can find me)        */
   /*-----------------------------------------------------------------*/
   /* Joe R Wyatt    2311 Lubbock, Tx  79412                          */
   /* Home #: 806/793-5689    Office #: 806/763-8011 ext: 239         */
   /*-----------------------------------------------------------------*/
   /* Variables :        fp --     pointer to input file              */
   /*                   fp2 --     ptr to output file                 */
   /*                     c --     integer returned from getw.        */
   /*                     i --     processed line count               */
   /*                     j --     empty line count                   */
   /*                  word --     temporary input line storage       */
   /* Procedures:      getw --     included                           */
   /*                 putwt --     included                           */
   /*                 ptree --     included                           */
   /* Functions :    printf --     string compare                     */
   /*                 fopen --     open file and return file pointer  */
   /*                  exit --     premature exit from program        */
   /*                fclose --     close file                         */
   /*-----------------------------------------------------------------*/
 int argc;
 char *argv[];
 {
      FILE *fp, *fp2, *fopen();
      int c, i, j;
      char word[MAXWORD];

      root = NULL;                                /* root of text tree */
      if (argc == 1)  {                  /* no file specified for sort */
           printf("usage: srt infile.ext <outfile.exe>\n");
           exit(0);
      }
      else{                                         /* open input file */
           if ((fp = fopen(*(argv+1), "r")) == NULL) {
                printf("cannot read %s\n",*(argv+1));
                exit(1);
           }
           if (argc == 3) {                        /* open output file */
                if ((fp2 = fopen(*(argv+2), "w")) == NULL) {
                     printf("cannot open %s \n",*argv[3]);
                     exit(1);
                }
           }
           else
                fp2 = stdout;                   /* no output specified */
      }
      i = 0;
      j = 0;
      while((c = getw(fp,word)) != EOF) {     /* get next line of file */
           if (strlen(word) != 0) {
                putwt(word);           /* if not null then put in tree */
                i++;            /* increment number of lines processed */
           }
           else
                j++;                 /* else inc number of empty lines */
      }
      fclose(fp);
      ptree(fp2, root);                           /* print sorted tree */
      printf("\nprocedure concluded.\n%d lines processed\n",i);
      printf("%d empty lines ignored.\n",j);
      fclose(fp2);
 }

 putwt(w)
   /*-----------------------------------------------------------------*/
   /* procedure places 'w' in tree named 'text'.                      */
   /* Parameters:         w --     null ended string                  */
   /* Variables :


 SSCANF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\SSCANF.C

 /* 1.1  01-08-86                                                (sscanf.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

 /*----------------------------------------------------------------------*/

 LOCAL STRING         scanstr;
 LOCAL BOOL         NOT_EOL;

 /************************************************************************/

 sscanf(s, fmt, arg)        /* Read string s using format fmt, and deposit
                            information into arguments in arg list. Return
                            count of items read.
 /*----------------------------------------------------------------------*/
 STRING s, fmt;
 int *arg;
 {
         int sgetc(), unformat();

         scanstr = s;
         NOT_EOL = TRUE;
         return unformat(sgetc, fmt, &arg);
 }

 /************************************************************************/
         LOCAL
 sgetc(forward)                /* Return a character from the LOCAL scanstr.
                            If forward is TRUE, get next character and
                            advance; else, back up and get one unless the
                            end has been reached. Return EOF if so.        */
 /*----------------------------------------------------------------------*/
 BOOL forward;
 {
         if (forward)
         {        if (*scanstr)
                         return *scanstr++ & 0xff;

                 else
                         NOT_EOL = FALSE;
         }
         else if (NOT_EOL)
                 return *--scanstr & 0xff;

         return EOF;
 }


 SSCANF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SSCANF.C

 static int sgetc(s)
 unsigned char **s;
 /*
  *        Local function to get a character from a string
  */
 {
         return(*(*s)++);
 }

 static int sungetc(c, s)
 unsigned char c, **s;
 /*
  *        Local function to unget a character from a string
  */
 {
         return(*--(*s) = c);
 }

 sscanf(buf, fmt, arg)
 unsigned char *buf;
 unsigned char *fmt;
 int arg;
 {
         return(_scanf(&buf, sgetc, sungetc, fmt, &arg));
 }


 SSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\SSORT.C

 /* ssort - shell sort (see Knuth p. 85
    ssort(n,comp,swap)
 unsigned n;
 int (*comp)();
 int (*swap)();
             see bsort for full description of parms
 */
 #define void int

 void ssort(n,comp,swap)
 unsigned n;
 int (*comp)();
 int (*swap)();
 {
         int m;
         int h,i,j,k;

         m=n;

         while(m /= 2) {
                 k = n - m;
                 j = 1;
                 do {
                         i = j;
                         do {
                                 h = i + m;
                                 if((*comp)(i-1,h=1) > 0) {
                                         (*swap)(i - 1, h - 1);
                                         i -= m;
                                  }else
                                         break;
                         } while(i>= 1);
                 j+=1;
                 } while(j <= k);
         }
 }


 ST520.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\ST520.C

 /*

 The routines in this file provide support for the Atari 520 or 1040ST
 using VT52 emulation.  The I/O services are provided here as well.  It
 compiles into nothing if not a 520ST style device.

 */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     ATARI & ST520 & MEGAMAX
 #include        <osbind.h>
 #include        <ctype.h>

 #define LINEA_INIT 0xA000
 #define V_CEL_WR   -0x28

 #define V_CEL_MY   -0x2a
 #define V_CEL_HT   -0x2e
 #define V_FNT_AD   -0x16
 #define V_OFF_AD   -0x0a
 #define V_DISAB    -346

 NROW    25                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
        NPAUSE        25                        /* # times thru update to paus
 BIAS    0x20                    /* Origin 0 coordinate bias.    */
 ESC     0x1B                    /* ESC character.               */
 BEL     0x07                    /* ascii bell character         */

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     st520move();
 extern  int     st520eeol();
 extern  int     st520eeop();
 extern  int     st520beep();
 extern  int     st520open();
 extern        int        st520close();
 extern        int        st520rev();
 extern  int st520kopen();
 extern  int st520kclose();
 extern        int st520chgrez();

 #if        COLOR
 extern        int        st520fcol();
 extern        int        st520bcol();

 int                cfcolor = -1;                /* current fg (character) col
 int                cbcolor = -1;                /* current bg color */
 int                oldpal[8];                /* pallette when emacs was invok
 int                newpal[8] = {                /* default emacs pallette */
         0x000, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0x777};
 #endif

 int STncolors = 0;                /* number of colors  */
 int STrez;                        /* physical screen resolution */

 /*
  * Dispatch table. All the
  * hard fields just point into the
  * terminal I/O code.
  */
 TERM    term    = {
         NROW-1,
         NCOL,
         MARGIN,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         &st520open,
         &st520close,
         &st520kopen,
         &st520kclose,
         &ttgetc,
         &ttputc,
         &ttflush,
         &st520move,
         &st520eeol,
         &st520eeop,
         &st520beep,
         &st520rev
 #if        MULTREZ
         , &st520chgrez
 #endif
 #if        COLOR
         , &st520fcol,
         &st520bcol
 #endif
 };
         struct KBDvecs {
                 int (*midivec) ();
                 int (*vkbderr) ();
                 int (*vmiderr) ();
                 int (*statvec) ();
                 int (*mousevec) ();
                 int (*clockvec) ();
                 int (*joyvec) ();
                 int (*midisys) ();
                 int (*ikbdsys) ();
         };
         struct Param {
                 char topmode;
                 char buttons;
                 char xparam;
                 char yparam;
                 int xmax,ymax;
                 int xinitial,yinitial;
         };
         struct KBDvecs *kbdvecs;
         struct Param *paramp;
         char kbdcmds[25];

 st520move(row, col)
 {
         ttputc(ESC);
         ttputc('Y');
         ttputc(row+BIAS);
         ttputc(col+BIAS);
 }

 st520eeol()
 {
         ttputc(ESC);
         ttputc('K');
 }

 st520eeop()
 {

 #if        COLOR
                 st520fcol(gfcolor);
                 st520bcol(gbcolor);
 #endif
         ttputc(ESC);
         ttputc('J');
 }

 st520rev(status)        /* set the reverse video state */

 int status;        /* TRUE = reverse video, FALSE = normal video */

 {

         if(status) {
                 ttputc(ESC);
                 ttputc('p');
         }
         else {
                 ttputc(ESC);
                 ttputc('q');
         }
 }

 #if        COLOR
 st520fcol(color)
 int color;
 {
                 if(color == cfcolor || !STncolors)
                         return;
                 else {

                         ttputc(ESC);
                         ttputc('b');
                         ttputc(color & 0x0f);
                         cfcolor = color;
                 }
 }

 st520bcol(color)
 int color;
 {
                 if(color == cbcolor || !STncolors)
                         return;
                 else {
                         ttputc(ESC);
                         ttputc('c');
                         ttputc(color & 0x0f);
                         cbcolor = color;
                 }

 }
 #endif

 st520beep()
 {
 #ifdef        BEL
         ttputc(BEL);
         ttflush();
 #endif
 }

 st520open()
 {
         int i,j,k;
         long phys, log;        /* screen bases */

 /* IMPORTANT: it is ABSOLUTELY necessary that the default resolution be the
  *        largest possible so that display will allocate (malloc) the maximum
  *        size for the VIDEO arrray
  */
         STrez = Getrez();
         switch(STrez) {
                 case 0: /* low res 25x40 16 colors */
                         phys = Physbase();
                         log  = Logbase();
                         Setscreen(log, phys, 1);
                         STrez = 1;
                         /* fall thru to med res */

                 case 1: /* med res 25x80 4 colors */
                         term.t_nrow = 25 - 1;
                         term.t_ncol  = 80;
                         grez = 1;
 #if        COLOR
                         STncolors = 4;
                         for(i=0;i<8;i++) {
                                 oldpal[i] = Setcolor(i,newpal[i]);
                         }
 #endif
                         break;
                 case 2: /* high res 25x80 no colors */
                         term.t_nrow  = 40 - 1;
                         term.t_ncol  = 80;
                         grez = 2;
                         make_8x10(); /* create a smaller font */
                         set_40();    /* and go to 40 line mode */
 #if        COLOR
                         STncolors = 0;
 #endif
                         break;
         }

         revexist = TRUE;
         eolexist = TRUE;
         paramp = (struct Param *)malloc(sizeof(struct Param));
         kbdvecs = (struct KBDvecs *)Kbdvbase();
         paramp -> topmode = 0;
         paramp -> buttons = 4;
         paramp -> xparam = 8;
         paramp -> yparam = 10;
         paramp -> xmax = 79;
         paramp -> ymax = 23;
         paramp -> xinitial = 0;
         paramp -> yinitial = 0;
         Initmous(1,paramp,kbdvecs -> mousevec);

         i = 0;
         kbdcmds[i++] = 0x0a;        /*set mouse keycode mode */
         kbdcmds[i++] = 0x08;
         kbdcmds[i++] = 0x0a;
         Ikbdws(i-1,&kbdcmds[0]);
         Cursconf(1,0);
         Cursconf(3,0);
         Cconout(27);Cconout('E');
         ttopen();
 }

 st520close()

 {
         int i,j,k;

         i = 0;
         kbdcmds[i++] = 0x80;        /*reset mouse keycode mode */
         kbdcmds[i++] = 0x01;
         Ikbdws(i-1,&kbdcmds[0]);
         if(grez == 2 && STrez == 2) /* b/w monitor in 40 row mode */
                 restore();

 #if                COLOR
         for(i=0;i<STncolors;i++)
                 Setcolor(i,oldpal[i]);
 #endif
         Cconout(27);Cconout('E');
         paramp -> buttons = 0;
         Initmous(2,paramp,kbdvecs -> mousevec);
         i = 0;
         kbdcmds[i++] = 0x80;        /*reset the keyboard*/
         kbdcmds[i++] = 0x01;
         Ikbdws(i-1,&kbdcmds[0]);
         Cursconf(1,0);
         ttclose();
 }
 st520kopen()
 {

 }
 st520kclose()
 {

 }

 st520chgrez(nurez)
 int nurez;
 {
         int ierr, i, j ,k;
         long phys, log;        /* screen bases */
         char dum[80]; /* for debugging only */

         if(grez == nurez)
                 return(TRUE);

         if(STrez == 2) { /* b/w monitor-only allow hi | med rez */
                 switch(nurez) {
                         case 2: /* high res */
                                 term.t_nrow  = 40 - 1;
                                 term.t_ncol  = 80;
                                 make_8x10(); /* create a smaller font */
                                 set_40();    /* and go to 40 line mode */
                                 grez = 2;
                                 sgarbf = TRUE;
                                 onlywind(1,1);
                                 break;
                         case 1: /* med res */
                                 term.t_nrow  = 25 - 1;
                                 term.t_ncol  = 80;
                                 restore();
                                 grez = 1;
                                 sgarbf = TRUE;
                                 onlywind(1,1);
                                 break;
                         default:
                                 mlwrite("Invalid resolution");
                                 return(FALSE);
                                 break;
                 }
         }
         else { /* color monitor-only allow low | medium resolution */
                 phys = Physbase();
                 log  = Logbase();
                 switch(nurez) {
                         case 1:
                                 term.t_nrow  = 25 - 1;
                                 term.t_ncol  = 80;
                                 Setscreen(log, phys, 1);
                                 STncolors = 4;
                                 grez = 1;
                                 sgarbf = TRUE;
                                 onlywind(1,1);
                                 break;
                         case 0:
                                 term.t_nrow  = 25 - 1;
                                 term.t_ncol  = 40;
                                 Setscreen(log, phys, 0);
                                 STncolors = 8;
                                 grez = 0;
                                 sgarbf = TRUE;
                                 onlywind(1,1);
                                 break;
                         default:
                                 mlwrite("%Invalid resolution");
                                 return(FALSE);
                                 break;
                 }
         }
 }

 STcurblink(onoff)
 int onoff;
 {
         if(onoff)
                 Cursconf(2,0);
         else
                 Cursconf(3,0);
 }


 char parm_save[28];
 long fnt_8x10[640];

 make_8x10()
 {
         int i,j,k;
         long savea23[2];

         for(i=0;i<640;i++)
                 fnt_8x10[i] = 0;

         asm {
         movem.l        A2-A3,savea23(A6)

         dc.w        LINEA_INIT                ;A1 -> array of font headers

         lea        parm_save(A4),A2        ;A2 -> parameters savearea
         move.l        V_OFF_AD(A0),(A2)+
         move.l        V_FNT_AD(A0),(A2)+
         move.w        V_CEL_HT(A0),(A2)+
         move.w        V_CEL_MY(A0),(A2)+
         move.w        V_CEL_WR(A0),(A2)+


         move.l        04(A1),A1                ; A1 -> 8x8 font header
         move.l        76(A1),A2                ; A2 -> 8x8 font data
         lea        fnt_8x10+0x100(A4),A3        ; A3 -> 2nd line of font buff
         move.w        #0x200-1,D0                ; D0 <- longword counter for

 fnt_loop:

         move.l        (A2)+,(A3)+
         dbf        D0,fnt_loop

         movem.l        savea23(A6),A2-A3
         }

 }

 set_40()
 {
         long        savea23[2];

         asm {

 ;
 ;  use the 8x10 character set: 40 line mode
 ;

         movem.l        A2-A3,savea23(A6)

         dc.w        LINEA_INIT

         move.l        04(A1),A1                ; A1 -> 8x8 font header
         move.l        72(A1),V_OFF_AD(A0)        ; v_off_ad <- 8x8  offset ta
         lea        fnt_8x10(A4),A2
         move.l        A2,V_FNT_AD(A0)                ; v_fnt_ad <- 8x10 font

         move.w        #10,V_CEL_HT(A0)        ; v_cel_ht <- 10   8x10 cell he
         move.w        #39,V_CEL_MY(A0)        ; v_cel_my <- 39   maximum cell
         move.w        #800,V_CEL_WR(A0)        ; v_cel_wr <- 800  offset to c

         movem.l savea23,A2-A3
         }
 }

 set_20()
 {
         long        savea23[2];

         asm {

 ;
 ;  use the 8x10 character set: 20 line mode
 ;

         movem.l        A2-A3,savea23(A6)

         dc.w        LINEA_INIT                ; A0 -> line A variables

         move.l        04(A1),A1                ; A1 -> 8x8 font header
         move.l        72(A1),V_OFF_AD(A0)        ; v_off_ad <- 8x8  offset ta
         lea        fnt_8x10(A4),A2
         move.l        A2,V_FNT_AD(A0)                ; v_fnt_ad <- 8x10 font

         move.w        #10,V_CEL_HT(A0)        ; v_cel_ht <- 10   8x10 cell he
         move.w        #19,V_CEL_MY(A0)        ; v_cel_my <- 19   maximum cell
         move.w        #1600,V_CEL_WR(A0)        ; v_cel_wr <- 800  offset to

         movem.l        savea23,A2-A3
         }
 }


 restore()
 {
         long savea23[2];

         asm {

 ;  return what was saved in parameter save zone

         movem.l        A2-A3,savea23(A6)

         dc.w        LINEA_INIT                ; a0 -> line A variables

         lea        parm_save(A4),A2        ; a2 -> parameter save area
         move.l        (A2)+,V_OFF_AD(A0)
         move.l        (A2)+,V_FNT_AD(A0)
         move.w        (A2)+,V_CEL_HT(A0)
         move.w        (A2)+,V_CEL_MY(A0)
         move.w        (A2)+,V_CEL_WR(A0)

         movem.l        savea23(A6),A2-A3
         }
 }
 GetCurStat(onoff)
 int        onoff;
 {
         long savea23[2];

         asm {
         movem.l        A2-A3,savea23(A6)

         dc.w        LINEA_INIT                ; a0 -> line A variables
         move.w        V_DISAB(A0),onoff(A6)        ; 0 = cursor visible
         moveq        #0,D0
         move.w        V_DISAB(A0),D0
         movem.l        savea23(A6),A2-A3
         }
 }
 #else
 #if        ATARI & ST520 & LATTICE

 /*
         These routines provide support for the ATARI 1040ST using
 the LATTICE compiler using the virtual VT52 Emulator

 */

 NROW    40                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
        NPAUSE        300                        /* # times thru update to pau
 BIAS    0x20                    /* Origin 0 coordinate bias.    */
 ESC     0x1B                    /* ESC character.               */
 BEL     0x07                    /* ASCII bell character         */

 /****        ST Internals definitions                *****/

 /*        BIOS calls */

        BCONSTAT        1        /* return input device status */
        CONIN                2        /* read character from device */
        BCONOUT                3        /* write character to device */

 /*        XBIOS calls */

        INITMOUS        0        /* initialize the mouse */
        GETREZ                4        /* get current resolution */
        SETSCREEN        5        /* set screen resolution */
        SETPALETTE        6        /* set the color pallette */
        SETCOLOR        7        /* set or read a color */
        CURSCONF        21        /* set cursor configuration */
        IKBDWS                25        /* intelligent keyboard send command *
        KBDVBASE        34        /* get keyboard table base */

 /*        GEMDOS calls */

        EXEC                0x4b        /* Exec off a process */

        CON                2        /* CON: Keyboard and screen device */

 /*        LINE A variables        */

 #define LINEA_INIT 0xA000
 #define V_CEL_WR   -0x28
 #define V_CEL_MY   -0x2a
 #define V_CEL_HT   -0x2e
 #define V_FNT_AD   -0x16
 #define V_OFF_AD   -0x0a
 #define V_DISAB    -346

 /*        Palette color definitions        */

 #define        LOWPAL        "000700070770007707077777"
 #define        MEDPAL        "000700007777"
 #define        HIGHPAL        "000111"

 /*        ST Global definitions                */

 /* keyboard vector table */
 struct KVT {
         long midivec;                /* midi input */
         long vkbderr;                /* keyboard error */
         long vmiderr;                /* MIDI error */
         long statvec;                /* IKBD status */
         int (*mousevec)();        /* mouse vector */
         long clockvec;                /* clock vector */
         long joyvec;                /* joystict vector */
 } *ktable;

 int (*sysmint)();                        /* system mouse interupt handler */

 /* mouse parameter table */
 struct Param {
         char topmode;
         char buttons;
         char xparam;
         char yparam;
         int xmax,ymax;
         int xinitial,yinitial;
 } mparam;

 int initrez;                        /* initial screen resolution */
 int currez;                        /* current screen resolution */
 char resname[][8] = {                /* screen resolution names */
         "LOW", "MEDIUM", "HIGH", "DENSE"
 };
 short spalette[16];                        /* original color palette settings
 short palette[16];                        /* current palette settings */

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     stmove();
 extern  int     steeol();
 extern  int     steeop();
 extern  int     stbeep();
 extern  int     stopen();
 extern        int        stclose();
 extern        int        stgetc();
 extern        int        stputc();
 extern        int        strev();
 extern        int        strez();
 extern        int        stkopen();
 extern        int        stkclose();

 #if        COLOR
 extern        int        stfcol();
 extern        int        stbcol();
 #endif

 /*
  * Dispatch table. All the
  * hard fields just point into the
  * terminal I/O code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         &stopen,
         &stclose,
         &stkopen,
         &stkclose,
         &stgetc,
         &stputc,
         &ttflush,
         &stmove,
         &steeol,
         &steeop,
         &stbeep,
         &strev,
         &strez
 #if        COLOR
         , &stfcol,
         &stbcol
 #endif
 };

 stmove(row, col)
 {
         stputc(ESC);
         stputc('Y');
         stputc(row+BIAS);
         stputc(col+BIAS);
 }

 steeol()
 {
         stputc(ESC);
         stputc('K');
 }

 steeop()
 {
 #if        COLOR
         stfcol(gfcolor);
         stbcol(gbcolor);
 #endif
         stputc(ESC);
         stputc('J');
 }

 strev(status)        /* set the reverse video state */

 int status;        /* TRUE = reverse video, FALSE = normal video */

 {
         if (currez > 1) {
                 stputc(ESC);
                 stputc(status ? 'p' : 'q');
         }
 }

 #if        COLOR
 mapcol(clr)        /* medium rez color translation */

 int clr;        /* emacs color number to translate */

 {
         static int mctable[] = {0, 1, 2, 3, 2, 1, 2, 3};

         if (currez != 1)
                 return(clr);
         else
                 return(mctable[clr]);
 }

 stfcol(color)        /* set the forground color */

 int color;        /* color to set forground to */

 {
         if (currez < 2) {
                 stputc(ESC);
                 stputc('b');
                 stputc(mapcol(color));
         }
 }

 stbcol(color)        /* set the background color */

 int color;        /* color to set background to */


 {
         if (currez < 2) {
                 stputc(ESC);
                 stputc('c');
                 stputc(mapcol(color));
         }
 }
 #endif

 stbeep()
 {
         stputc(BEL);
         ttflush();
 }

 domouse()        /* mouse interupt handler */

 {
         return((*sysmint)());
 }

 stkopen()        /* open the keyboard (and mouse) */

 {
         /* grab the keyboard vector table */
         ktable = (struct KVT *)xbios(KBDVBASE);
         sysmint = ktable->mousevec;        /* save mouse vector */

         /* initialize the mouse */
         mparam.topmode = 0;
         mparam.buttons = 4;
         mparam.xparam = 8;
         mparam.yparam = 10;
         mparam.xmax = 79;
         mparam.ymax = 23;
         mparam.xinitial = 0;
         mparam.yinitial = 0;
         xbios(INITMOUS, 4, &mparam, &domouse);
 }

 stopen()        /* open the screen */

 {
         int i;

         ttopen();
         eolexist = TRUE;

         /* switch to a steady cursor */
         xbios(CURSCONF, 3);

         /* save the current color palette */
         for (i=0; i<16; i++)
                 spalette[i] = xbios(SETCOLOR, i, -1);

         /* and find the current resolution */
         initrez = currez = xbios(GETREZ);
         strcpy(sres, resname[currez]);

         /* set up the screen size and palette */
         switch (currez) {
                 case 0:        term.t_mrow = 25 - 1;
                         term.t_nrow = 25 - 1;
                         term.t_ncol = 40;
                         strcpy(palstr, LOWPAL);
                         break;

                 case 1: term.t_mrow = 25 - 1;
                         term.t_nrow = 25 - 1;
                         strcpy(palstr, MEDPAL);
                         break;

                 case 2: term.t_mrow = 40 - 1;
                         term.t_nrow = 25 - 1;
                         strcpy(palstr, HIGHPAL);
         }

         /* and set up the default palette */
         spal(palstr);

         stputc(ESC);        /* automatic overflow off */
         stputc('w');
         stputc(ESC);        /* turn cursor on */
         stputc('e');
 }

 stkclose()        /* close the keyboard (and mouse) */

 {
         static char resetcmd[] = {0x80, 0x01};        /* keyboard reset comma

         /* restore the mouse interupt routines */
         xbios(INITMOUS, 2, &mparam, (long)sysmint);

         /* and reset the keyboard controller */
         xbios(IKBDWS, 1, &resetcmd[0]);
 }

 stclose()

 {
         stputc(ESC);        /* auto overflow on */
         stputc('v');

         /* switch to a flashing cursor */
         xbios(CURSCONF, 2);

         /* restore the original screen resolution */
         strez(resname[initrez]);

         /* restore the original palette settings */
         xbios(SETPALETTE, spalette);

         ttclose();
 }

 /*         spal(pstr):        reset the current palette according to a
                         "palette string" of the form

         000111222333444555666777

         which contains the octal values for the palette registers
 */

 spal(pstr)

 char *pstr;        /* palette string */

 {
         int pal;        /* current palette position */
         int clr;        /* current color value */
         int i;

         for (pal = 0; pal < 16; pal++) {
                 if (*pstr== 0)
                         break;

                 /* parse off a color */
                 clr = 0;
                 for (i = 0; i < 3; i++)
                         if (*pstr)
                                 clr = clr * 16 + (*pstr++ - '0');
                 palette[pal] = clr;
         };

         /* and now set it */
         xbios(SETPALETTE, palette);
 }

 stgetc()        /* get a char from the keyboard */

 {
         int rval;                /* return value from BIOS call */
         static int funkey = 0;        /* held fuction key scan code */

         /* if there is a pending function key, return it */
         if (funkey) {
                 rval = funkey;
                 funkey = 0;
         } else {

                 /* waiting... flash the cursor */
                 xbios(CURSCONF, 2);

                 /* get the character */
                 rval = bios(CONIN, CON);
                 if ((rval & 255) == 0) {
                         funkey = (rval >> 16) & 255;
                         rval = 0;
                 }

                 /* and switch to a steady cursor */
                 xbios(CURSCONF, 3);
         }

         return(rval & 255);
 }

 stputc(c)        /* output char c to the screen */

 char c;                /* character to print out */

 {
         bios(BCONOUT, CON, c);
 }

 strez(newrez)        /* change screen resolution */

 char *newrez;        /* requested resolution */

 {
         int nrez;        /* requested new resolution */

         /* first, decode the resolution name */
         for (nrez = 0; nrez < 4; nrez++)
                 if (strcmp(newrez, resname[nrez]) == 0)
                         break;
         if (nrez == 4) {
                 mlwrite("%%No such resolution");
                 return(FALSE);
         }

         /* next, make sure this resolution is legal for this monitor */
         if ((currez < 2 && nrez > 1) || (currez > 1 && nrez < 2)) {
                 mlwrite("%%Resolution illegal for this monitor");
                 return(FALSE);
         }

         /* eliminate non-changes */
         if (currez == nrez)
                 return(TRUE);

         /* finally, make the change */
         switch (nrez) {
                 case 0:        /* low resolution - 16 colors */
                         newwidth(TRUE, 40);
                         strcpy(palstr, LOWPAL);
                         xbios(SETSCREEN, -1, -1, 0);
                         break;

                 case 1:        /* medium resolution - 4 colors */
                         newwidth(TRUE, 80);
                         strcpy(palstr, MEDPAL);
                         xbios(SETSCREEN, -1, -1, 1);
                         break;

                 case 2:        /* High resolution - 2 colors - 25 lines */
                         newsize(TRUE, 25);
                         strcpy(palstr, HIGHPAL);
                         /* change char set back to normal */
                         break;

                 case 3:        /* Dense resolution - 2 colors - 40 lines */
                         /* newsize(TRUE, 40); */
                         strcpy(palstr, HIGHPAL);
                         /*change char set size */
                         break;
         }

         /* and set up the default palette */
         spal(palstr);
         currez = nrez;
         strcpy(sres, resname[currez]);

         stputc(ESC);        /* automatic overflow off */
         stputc('w');
         stputc(ESC);        /* turn cursor on */
         stputc('e');

         return(TRUE);
 }

 system(cmd)        /* call the system to execute a new program */

 char *cmd;        /* command to execute */

 {
         char *pptr;                        /* pointer into program name */
         char pname[NSTRING];                /* name of program to execute */
         char tail[NSTRING];                /* command tail */

         /* scan off program name.... */
         pptr = pname;
         while (*cmd && (*cmd != ' ' && *cmd != '\t'))
                 *pptr++ = *cmd++;
         *pptr = 0;

         /* create program name length/string */
         tail[0] = strlen(cmd);
         strcpy(&tail[1], cmd);

         /* go do it! */
         return(gemdos(                (int)EXEC,
                                 (int)0,
                                 (char *)pname,
                                 (char *)tail,
                                 (char *)NULL));
 }

 #if        TYPEAH
 typahead()

 {
         int rval;        /* return value from BIOS call */

         /* get the status of the console */
         rval = bios(BCONSTAT, CON);

         /* end return the results */
         if (rval == 0)
                 return(FALSE);
         else
                 return(TRUE);
 }
 #endif

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else
 sthello()
 {
 }
 #endif
 #endif


 STAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STAT.C

 #include <osbind.h>
 #include <stdio.h>
 #include <io.h>

 static        STAT        _dta;                /* local DTA buffer */

 int access(name, amode)
 char *name;
 int amode;
 /*
  *        Return non-zero if a file with the given <name> can be accessed
  *        in the given <amode>.  Possible <amode> values are:
  *                _ACCe                file/directory exists
  *                _ACCr                file can be read
  *                _ACCw                file can be written
  *                _ACCrw                file can be read and written
  */
 {
         register STAT *_pdta;                /* pointer to old DTA */
         register int rv;

         _pdta = Fgetdta();
         Fsetdta(&_dta);
         rv = (Fsfirst(name, amode) == 0);
         Fsetdta(_pdta);
         return(rv);
 }

 int stat(name, statbuf)
 char *name;
 STAT *statbuf;
 /*
  *        Search for file <name> and load <statbuf> with information
  *        about that file, if it is found.  Return 0 if found, or
  *        ERROR (-1) if no file/directory matched <name>.  Volume
  *        labels are not included in the search.
  */
 {
         if(access(name, 0x17)) {
                 *statbuf = _dta;
                 return(0);
         }
         return(ERROR);
 }

 long fsize(name)
 char *name;
 /*
  *        Return the size of the file <name> in bytes.  Note that this
  *        is a long value.  Return -1L if the file is not found.
  */
 {
         if(access(name, 0x07))
                 return(_dta.S_size);
         return(-1L);
 }


 STAYRES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\STAYRESC\STAYRES.C


 /****************************************************************************
 /*
 /*     STAYRES.C   Version 1.1        10/26/85               Brian Irvine
 /*
 /****************************************************************************
 /*
 /* stayres.c - Code which can be used in a general way to create programs   *
 /*               in C which will terminate and stay resident.  This code
 /*               will allow the use of DOS I/O without having the stack and
 /*               registers clobbered.  This code is written in DeSmet C and
 /*               uses library functions which may not be available in other
 /*               C compilers.  It also makes heavy use of the #asm compiler
 /*               directive to allow in-line assembly language within the C
 /*               code.  This code provides a general outline for a main()
 /*               function which can be modified to suit the users needs. All
 /*               the code necessary to terminate and stay resident is
 /*               contained in this module; the user's program can be contain-
 /*               ed entirely externally.        The program does not have to
 /*               COM file, and the amount of memory reserved is not limited
 /*               to 64K. The code has not been tested on program files with
 /*               greater than 64K of code.
 /*
 /*               This code is based on a set of routines written in Turbo
 /*               Pascal by Lane H. Ferris which are available on the Borland
 /*               SIG on Compuserve.
 /*
 /*               Brian Irvine
 /*               3379 St Marys Place
 /*               Santa Clara, CA 95051
 /*               [71016,544]
 /*
 /****************************************************************************


 /****************************************************************************
 /*
 /* Modification Log:
 /*     Version 1.10 - 10/26/85
 /*     Corrected error in restoring stack which caused major problems.
 /*     Tested now with Personal Editor, Volkswriter Deluxe, Crosstalk.
 /*     Removed redundant code which restored registers twice, once from     *
 /*     memory and again from the stack.                                     *
 /*
 /****************************************************************************

 #include   "stdio.h"

 /*----- Global variables ---------------------------------------------------*

 unsigned   dos_regs [10];               /* save DOS registers here */
 unsigned   dos_dseg;                       /* save the DS and SS regs */
 unsigned   dos_sseg;                       /* for later convenience */
 unsigned   dos_sp;                       /* storage for DOS stack pointer */
 unsigned   c_sseg;                       /* save our stack segment here */
 unsigned   c_sp;                       /* and our stack pointer here */
 unsigned   stacksize;                       /* size of DOS/local stack */
 int           _rax, _rbx, _rcx, _rdx,     /* variables hold register values *
            _rsi, _rdi, _rds, _res;

 /*--------------------------------------------------------------------------*
 /* note: storage to save the DOS/C data segments must be allocated in the   *
 /*         code segment, so variable must be defined inside "#asm - #" area.
 /*--------------------------------------------------------------------------*

 /*----- Constants ----------------------------------------------------------*

    KB_INT      0x16    /* BIOS software int keyboard service routine */
    DOS_INT     0x21    /* DOS kitchen sink interrupt */
    USER_INT    0x67    /* INT 16H vector is moved to here */

    WAKEUP      0x71    /* scan code for Alt-F10 */
    PARAGRAPHS  0x1000  /* # of paragraphs of memory to keep */

 /*----- Externals ----------------------------------------------------------*

 extern unsigned _PCB;        /* DeSmet C stores original sp value at _PCB + 2
 extern void    program();               /* user's program module entry point

 /*--------------------------------------------------------------------------*
 /*     Initial program startup code
 /*--------------------------------------------------------------------------*

 main ()
 {

 /* Save the C data segment and reserve storage in code segment for later use

 #asm

            jmp           get_ds

 active_:   db           0
 c_ds_:           dw           0
 dos_ds_:   dw           0

 get_ds:    push    ax
            mov           ax,ds
            mov           cs:c_ds_,ax
            pop           ax

 #
    /* initialize program stack segment variable */

    c_sseg = _showds();

    /* get the current address of INT 16H and save it */

    _res = 0;                       /* just for DOS 3.0 */
    _rax = 0x3500 + USER_INT;
    _doint (DOS_INT);

    if ( _res != 0 )
        puts ("\nInterrupt 67H in use.  Can't install program.\n");
    else
        {

 /*--------------------------------------------------------------------------*
 /*     Do your program initialization here because you won't get hold of    *
 /*     it again until it is entered with the wakeup key sequence.
 /*--------------------------------------------------------------------------*

        /* get address of current INT 16H routine */

        _rax = 0x3500 + KB_INT;
        _doint (DOS_INT);

        /* set the old INT 16H code up as INT 67H for later use */

        _rax = 0x2500 + USER_INT;
        _rds = _res;
        _rdx = _rbx;
        _doint (DOS_INT);

        /*  now set the INT 16H vector to point to our new service routine */

        _rax = 0x2500 + KB_INT;
        _rds = _showcs();

 #asm
            push    bx
            lea           bx, back_door_
            mov           word _rdx_,bx
            pop           bx
 #
        _doint (DOS_INT);


        puts ("Resident program installed.\n");

        /* now terminate while staying resident */

        _rax = 0x3100;
        _rdx = PARAGRAPHS;
        _doint (DOS_INT);

        }

 }


 /*----- Interrupt 16H service routine --------------------------------------*
 /*
 /*     This function replaces the standard BIOS INT 16H service routine.    *
 /*     It is called by DOS and our application program to get the next
 /*     character from the queue, check the shift status, or just see if     *
 /*     there is a character in the queue.  All type 1 and 2 requests are    *
 /*     passed through to the original service routine, through a long
 /*     jump to that address.  Type 0 requests (get the next character)
 /*     are handled through an INT 67H call to the original service rou-     *
 /*     tine.  The character obtained is checked to see if it is the
 /*     designated wakeup key.  If not, it is passed on to DOS.        If it i
 /*     then part of the DOS stack is saved on the local stack, all the
 /*     processor registers are saved in memory and the program is
 /*     started up.  The C program environment and registers are estab-
 /*     lished and the DOS environment is saved for later restoration.
 /*     Upon return from the user's program, the DOS stack is restored       *
 /*     from the data saved on the local stack, bringing DOS back to
 /*     where it was before the user program was turned on.
 /*     These operations allow programs to be written in C without having    *
 /*     to worry about the resident routines destroying the DOS registers    *
 /*     when file I/O is used.  It also allows the use of printf().
 /*
 /*--------------------------------------------------------------------------*



 void   back_door()
 {
 /*
    Current stack contents:
                sp -> DOS ip
            sp + 2 -> DOS cs
            sp + 4 -> DOS flags

    C function prologue:
            push    bp
            mov           bp,sp
 */

 #asm
            pop           bp                       ;toss out the bp from the p
            cmp           cs:active_,1        ;if the program is currently act
            jne           not_on               ;go service the request
 ;
 ; long jump to F000:E82E
 ;
            db           0EAH
            dw           0E82EH
            dw           0F000H
 ;
 not_on:    cmp           ah,0                ;if this is a character request
            jz           chr_rqst               ;check a little further
 ;
 ; long jump to F000:E82E
 ;
            db           0EAH
            dw           0E82EH
            dw           0F000H
 ;
 chr_rqst:
            int           67H                       ;get the next character fr
            cmp           ah,71H               ;if it's not the wakeup charact
            jne           skipall               ;then take it back to the call
            mov           cs:active_,1        ;else set the 'program active' f
 ;
 ;  now we enter the program
 ;
            cli                               ;no interrupts for now
            mov           cs:dos_ds_,ds       ;save the DOS data segment
            mov           ds,cs:c_ds_               ;establish our data segmen
            push    bp                       ;save bp
            mov           bp,offset dos_regs_ ;point to dos_regs
            mov           ds:[bp+0], ax       ;copy the current registers into
            mov           ds:[bp+2], bx       ;array in the local data segment
            mov           ds:[bp+4], cx
            mov           ds:[bp+6], dx
            pop           ds:[bp+8]               ;get the bp and save it
            mov           ds:[bp+10], si
            mov           ds:[bp+12], di
            push    ax
            mov           ax, cs:dos_ds_      ;save the DOS ds reg
            mov           ds:[bp+14], ax
            pop           ax
            mov           ds:[bp+16], es      ;save es
            pushf                       ;save the flags too
            pop           ds:[bp+18]
            mov           word dos_sseg_,ss   ;save DOS stack segment
            mov           si,ss               ;if DOS stack segment and C stac
            mov           es,si               ;segment are the same, then use
            mov           ss,word c_sseg_     ;current stack pointer for savin
            cmp           si,word c_sseg_     ;the registers. If not the same,
            mov           si,sp               ;we are entering the program so
            je           keep_sp               ;the starting stack pointer
            mov           si,ss:_PCB_ + 2
 keep_sp:   xchg    sp,si               ;save the registers on the stack
                                        ;now using local stack (ds = ss)
            push    [bp+0]               ;save ax
            push    [bp+2]               ;save bx
            push    [bp+4]               ;save cx
            push    [bp+6]               ;save dx
                                        ;don't save bp
            push    [bp+10]               ;save si
            push    [bp+12]               ;save di
            push    [bp+14]               ;save ds
            push    [bp+16]               ;save es
                                        ;don't save flags
            sub           cx,cx               ;now save 40 words or less from
            sub           cx,si               ;DOS stack onto the current stac
            shr           cx,1                ;If the stack size is less than
            cmp           cx,40               ;save 'stacksize' words, else sa
            jle           under40
            mov           cx,40
 under40:   mov           word stacksize_,cx
 restack:   push    es:[si]
            inc           si
            inc           si
            loop    restack
            push    si                       ;save the count of words pushed o
            mov           word c_sp_,sp       ;save current stack pointer
            sti
            push    bp                       ;do the C function prologue here
            mov           bp,sp

 #

 /*----- Call your program from here ----------------------------------------*

            program();

 /*----- Restore everything -------------------------------------------------*

 #asm
 restore:
            pop           bp
            cli                               ;no interrupts
            mov           sp,word c_sp_       ;get the stack pointer back
            pop           si                       ;get pointer to top of word
            mov           cx,word stacksize_  ;get count of words to move
            mov           es,word dos_sseg_   ;point es to caller's stack
 unstack:   dec           si                       ;back up one word
            dec           si
            pop           es:[si]               ;restore the caller's stack fr
            loop    unstack
            mov           bp,si               ;save pointer to top of caller's
            pop           es                       ;pop registers off the stac
            pop           di                       ;don't restore ds just yet
            pop           di
            pop           si
            pop           dx
            pop           cx
            pop           bx
            pop           ax
            mov           sp,bp               ;restore the caller's stack poin
            mov           ax,0                ;tell caller there was no charac
            mov           ss,word dos_sseg_   ;switch back to the caller's sta
            mov           bp,offset dos_regs_
            push    ds:[bp+18]               ;restore the flags from memory
            popf
            mov           bp,ds:[bp+8]        ;restore the caller's bp reg
            mov           cs:active_,0        ;reset the 'program active' flag
            mov           ds,cs:dos_ds_       ;finally restore caller's data s
 skipall:   iret                        ;head on back

 #

 }




 STEADY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\STEADY.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[1]==STEADY)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 STIME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STIME.C

 #include <time.h>

 extern        long        gemdos();

 long cnvtime(rawtime, time)
 long *rawtime;
 register struct tm *time;
 /*
  *        Convert <time> structure value to raw time format.  In addition to
  *        returning the raw time value, if the <rawtime> pointer in not NULL,
  *        the value is stored in the long <rawtime> points to. (cf: time)
  */
 {
         register long t;

         t = (time->tm_year - 80) & 0x7F;
         t <<= 4;
         t |= (time->tm_mon - 1) & 0x0F;
         t <<= 5;
         t |= (time->tm_mday) & 0x1F;
         t <<= 5;
         t |= (time->tm_hour) & 0x1F;
         t <<= 6;
         t |= (time->tm_min) & 0x3F;
         t <<= 5;
         t |= (time->tm_sec >> 1) & 0x1F;
         if(rawtime)
                 *rawtime = t;
         return(t);
 }

 void stime(rawtime)
 long *rawtime;
 /*
  *        Set the system clock to <rawtime>.
  */
 {
         register int *ip = rawtime;

         gemdos(0x2B, ip[0]);                /* set date from high word */
         gemdos(0x2D, ip[1]);                /* set time from low word */
 }

 int utime(pathname, rawtime)
 char *pathname;
 long *rawtime;
 /*
  *        Set the modification date of <pathname> to <rawtime>.  Returns zero
  *        for success, or a negative error code.
  */
 {
         register int h, *ip = rawtime;
         int d_and_t[2];
         long raw;

         if(!ip) {
                 ip = &raw;                                        /* current
                 time(ip);                                        /*  time   *
         }
         if((h = ((int) gemdos(0x3D, pathname, 2))) < 0)                /* ope
                 return(h);                                        /* FAILURE
         d_and_t[0] = ip[1];                                        /* time */
         d_and_t[1] = ip[0];                                        /* date */
         gemdos(0x57, d_and_t, h, 1);                                /* timest
         gemdos(0x3E, h);                                        /* close */
         return(0);                                                /* SUCCESS
 }


 STKSIZ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STKSIZ.C

 /*
  *        Default _STKSIZ variable declaration
  */

 unsigned long _STKSIZ = 4096;                /* 4K stack+heap */


 STMT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\STMT.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 /*
  *      the statement module handles all of the possible c statements
  *      and builds a parse tree of the statements.
  *
  *      each routine returns a pointer to a statement parse node which
  *      reflects the statement just parsed.
  */

 struct snode    *statement();   /* forward declaration */

 struct snode    *whilestmt()
 /*
  *      whilestmt parses the c while statement.
  */
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_while;
         getsym();
         if( lastst != openpa )
                 error(ERR_EXPREXPECT);
         else    {
                 getsym();
                 if( expression(&(snp->exp)) == 0 )
                         error(ERR_EXPREXPECT);
                 needpunc( closepa );
                 snp->s1 = statement();
                 }
         return snp;
 }

 struct snode    *dostmt()
 /*
  *      dostmt parses the c do-while construct.
  */
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_do;
         getsym();
         snp->s1 = statement();
         if( lastst != kw_while )
                 error(ERR_WHILEXPECT);
         else    {
                 getsym();
                 if( lastst != openpa )
                         error(ERR_EXPREXPECT);
                 else    {
                         getsym();
                         if( expression(&(snp->exp)) == 0 )
                                 error(ERR_EXPREXPECT);
                         needpunc(closepa);
                         }
                 if( lastst != end )
                         needpunc( semicolon );
                 }
         return snp;
 }

 struct snode    *forstmt()
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         getsym();
         needpunc(openpa);
         if( expression(&(snp->label)) == 0 )
                 snp->label = 0;
         needpunc(semicolon);
         snp->stype = st_for;
         if( expression(&(snp->exp)) == 0 )
                 snp->exp = 0;
         needpunc(semicolon);
         if( expression(&(snp->s2)) == 0 )
                 snp->s2 = 0;
         needpunc(closepa);
         snp->s1 = statement();
         return snp;
 }

 struct snode    *ifstmt()
 /*
  *      ifstmt parses the c if statement and an else clause if
  *      one is present.
  */
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_if;
         getsym();
         if( lastst != openpa )
                 error(ERR_EXPREXPECT);
         else    {
                 getsym();
                 if( expression(&(snp->exp)) == 0 )
                         error(ERR_EXPREXPECT);
                 needpunc( closepa );
                 snp->s1 = statement();
                 if( lastst == kw_else ) {
                         getsym();
                         snp->s2 = statement();
                         }
                 else
                         snp->s2 = 0;
                 }
         return snp;
 }

 struct snode    *casestmt()
 /*
  *      cases are returned as seperate statements. for normal
  *      cases label is the case value and s2 is zero. for the
  *      default case s2 is nonzero.
  */
 {       struct snode    *snp;
         struct snode    *head, *tail;
         snp = xalloc(sizeof(struct snode));
         if( lastst == kw_case ) {
                 getsym();
                 snp->s2 = 0;
                 snp->stype = st_case;
                 snp->label = intexpr();
                 }
         else if( lastst == kw_default) {
                 getsym();
                 snp->s2 = 1;
                 }
         else    {
                 error(ERR_NOCASE);
                 return 0;
                 }
         needpunc(colon);
         head = 0;
         while( lastst != end &&
                 lastst != kw_case &&
                 lastst != kw_default ) {
                 if( head == 0 )
                         head = tail = statement();
                 else    {
                         tail->next = statement();
                         if( tail->next != 0 )
                                 tail = tail->next;
                         }
                 tail->next = 0;
                 }
         snp->s1 = head;
         return snp;
 }

 int     checkcases(head)
 /*
  *      checkcases will check to see if any duplicate cases
  *      exist in the case list pointed to by head.
  */
 struct snode    *head;
 {
         struct snode        *top, *cur;
         cur = top = head;
         while( top != 0 )
         {
                 cur = top->next;
                 while( cur != 0 )
                 {
                         if( (!(cur->s1 || cur->s2) && cur->label == top->labe
                                 || (cur->s2 && top->s2) )
                         {
                                 printf(" duplicate case label %d\n",cur->labe
                                 return 1;
                         }
                         cur = cur->next;
                 }
                 top = top->next;
         }
         return 0;
 }

 struct snode    *switchstmt()
 {       struct snode    *snp;
         struct snode    *head, *tail;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_switch;
         getsym();
         needpunc(openpa);
         if( expression(&(snp->exp)) == 0 )
                 error(ERR_EXPREXPECT);
         needpunc(closepa);
         needpunc(begin);
         head = 0;
         while( lastst != end ) {
                 if( head == 0 )
                         head = tail = casestmt();
                 else    {
                         tail->next = casestmt();
                         if( tail->next != 0 )
                                 tail = tail->next;
                         }
                 tail->next = 0;
                 }
         snp->s1 = head;
         getsym();
         if( checkcases(head) )
                 error(ERR_DUPCASE);
         return snp;
 }

 struct snode    *retstmt()
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_return;
         getsym();
         expression(&(snp->exp));
         if( lastst != end )
                 needpunc( semicolon );
         return snp;
 }

 struct snode    *breakstmt()
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_break;
         getsym();
         if( lastst != end )
                 needpunc( semicolon );
         return snp;
 }

 struct snode    *contstmt()
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_continue;
         getsym();
         if( lastst != end )
                 needpunc( semicolon );
         return snp;
 }

 struct snode    *exprstmt()
 /*
  *      exprstmt is called whenever a statement does not begin
  *      with a keyword. the statement should be an expression.
  */
 {       struct snode    *snp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_expr;
         if( expression(&(snp->exp)) == 0 ) {
                 error(ERR_EXPREXPECT);
                 getsym();
                 }
         if( lastst != end )
                 needpunc( semicolon );
         return snp;
 }

 struct snode    *compound()
 /*
  *      compound processes a block of statements and forms a linked
  *      list of the statements within the block.
  *
  *      compound expects the input pointer to already be past the
  *      begin symbol of the block.
  */
 {       struct snode    *head, *tail;
         head = 0;
         while( lastst != end ) {
                 if( head == 0 )
                         head = tail = statement();
                 else    {
                         tail->next = statement();
                         if( tail->next != 0 )
                                 tail = tail->next;
                         }
                 }
         getsym();
         return head;
 }

 struct snode    *labelstmt()
 /*
  *      labelstmt processes a label that appears before a
  *      statement as a seperate statement.
  */
 {       struct snode    *snp;
         SYM             *sp;
         snp = xalloc(sizeof(struct snode));
         snp->stype = st_label;
         if( (sp = search(lastid,lsyms.head)) == 0 ) {
                 sp = xalloc(sizeof(SYM));
                 sp->name = litlate(lastid);
                 sp->storage_class = sc_label;
                 sp->tp = 0;
                 sp->value.i = nextlabel++;
                 insert(sp,&lsyms);
                 }
         else    {
                 if( sp->storage_class != sc_ulabel )
                         error(ERR_LABEL);
                 else
                         sp->storage_class = sc_label;
                 }
         getsym();       /* get past id */
         needpunc(colon);
         if( sp->storage_class == sc_label ) {
                 snp->label = sp->value.i;
                 snp->next = 0;
                 return snp;
                 }
         return 0;
 }

 struct snode    *gotostmt()
 /*
  *      gotostmt processes the goto statement and puts undefined
  *      labels into the symbol table.
  */
 {       struct snode    *snp;
         SYM             *sp;
         getsym();
         if( lastst != id ) {
                 error(ERR_IDEXPECT);
                 return 0;
                 }
         snp = xalloc(sizeof(struct snode));
         if( (sp = search(lastid,lsyms.head)) == 0 ) {
                 sp = xalloc(sizeof(SYM));
                 sp->name = litlate(lastid);
                 sp->value.i = nextlabel++;
                 sp->storage_class = sc_ulabel;
                 sp->tp = 0;
                 insert(sp,&lsyms);
                 }
         getsym();       /* get past label name */
         if( lastst != end )
                 needpunc( semicolon );
         if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel)
                 error( ERR_LABEL );
         else    {
                 snp->stype = st_goto;
                 snp->label = sp->value.i;
                 snp->next = 0;
                 return snp;
                 }
         return 0;
 }

 struct snode    *statement()
 /*
  *      statement figures out which of the statement processors
  *      should be called and transfers control to the proper
  *      routine.
  */
 {       struct snode    *snp;
         switch( lastst ) {
                 case semicolon:
                         getsym();
                         snp = 0;
                         break;
                 case begin:
                         getsym();
                         snp = compound();
                         return snp;
                 case kw_if:
                         snp = ifstmt();
                         break;
                 case kw_while:
                         snp = whilestmt();
                         break;
                 case kw_for:
                         snp = forstmt();
                         break;
                 case kw_return:
                         snp = retstmt();
                         break;
                 case kw_break:
                         snp = breakstmt();
                         break;
                 case kw_goto:
                         snp = gotostmt();
                         break;
                 case kw_continue:
                         snp = contstmt();
                         break;
                 case kw_do:
                         snp = dostmt();
                         break;
                 case kw_switch:
                         snp = switchstmt();
                         break;
                 case id:
                         while( isspace(lastch) )
                                 getch();
                         if( lastch == ':' )
                                 return labelstmt();
                         /* else fall through to process expression */
                 default:
                         snp = exprstmt();
                         break;
                 }
         if( snp != 0 )
                 snp->next = 0;
         return snp;
 }



 STRADD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRADD.C

 /* 1.0  05-13-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 stradd(n, s, args) /* concatenate n strings args to s. return pointer s

 /*----------------------------------------------------------------------*/
 STRING s, args;
 {
         STRING p, t, *q;

         p = s;
         while (*s)
                 s++;
         for (q = &args; n-- > 0; q++)
         {        t = *q;
                 while (*t)
                         *s++ = *t++;
         }
         *s = NULL;
         return p;
 }


 STRADJ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRADJ.C

 char *stradj(string, dir)
 register char *string;
 register int dir;
 /*
  *        Adjust <string> by adding space if <dir> is positive, or removing
  *        space if <dir> is negative.  The magnitude of <dir> is the number
  *        of character positions to add or remove.  Characters are added or
  *        removed at the beginning of <string>.  A pointer to the modified
  *        <string> is returned.
  */
 {
         register char *p = string, *q;

         if(dir == 0)
                 return(string);
         if(dir > 0) {                        /* add space */
                 while(*p)                        /* find end */
                         ++p;
                 q = p + dir;                        /* set gap */
                 while(p >= string)                /* copy data */
                         *q-- = *p--;
                 while(q >= string) {                /* replace <nul>s */
                         if(*q == '\0')
                                 *q = ' ';
                         --q;
                 }
         }
         else {                                /* remove space */
                 dir = -dir;
                 q = p + dir;                        /* set gap */
                 while(*p++ = *q++)                /* copy data */
                         ;
         }
         return(string);
 }


 STRCAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRCAT.C

 char *strcat(dest, source)
 register char *dest;
 register char *source;
 /*
  *        Concatenate <source> on the end of <dest>.  The terminator of
  *        <dest> will be overwritten by the first character of <source>.
  *        The termintor from <source> will be copied.  A pointer to
  *        the modified <dest> is returned.
  */
 {
         register char *p = dest;

         while(*dest)
                 ++dest;
         while(*dest++ = *source++)
                 ;
         return(p);
 }


 STRCAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRCAT.C

 /* 1.0  05-13-85                                                 (strcat.c)
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 strcat(s1, s2)        /* concatenate strings s1 and s2, return pointer s1

 /*----------------------------------------------------------------------*/
 STRING s1, s2;
 {
         STRING t;

         for (t = s1; *s1; s1++)
                 ;
         while (*s1++ = *s2++)
                 ;
         return t;
 }


 STRCMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRCMP.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/

 strcmp(s, t)        /* return 0 if strings s and t are the same, a neg no. if
                    s < t, and a pos. no. if s > t.                        */
 /*----------------------------------------------------------------------*/
 STRING s, t;
 {
         for ( ; *s IS *t; s++, t++)
                 if (*s IS NULL)
                         return (NULL);
         return (*s - *t);
 }


 STRCMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRCMP.C

 int strcmp(str1, str2)
 register char *str1;
 register char *str2;
 /*
  *        Lexicographically compare the two strings.  Return a value
  *        indicating the relationship between the strings.  Possible
  *        return values are:
  *                negative        str1 < str2
  *                0                str1 == str2
  *                positive        str1 > str2
  */
 {
         for(; *str1 == *str2; ++str1, ++str2)
                 if(*str1 == '\0')
                         return(0);
         return(*str1 - *str2);
 }


 STRCPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRCPY.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 strcpy(s, t)        /* copy string t into s, return pointer s

 /*----------------------------------------------------------------------*/
 STRING s, t;
 {
         STRING p;

         p = s;
         while (*s++ = *t++)
                 ;
         return p;
 }


 STRCPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRCPY.C

 char *strcpy(dest, source)
 register char *dest;
 register char *source;
 /*
  *        Copies the <source> string to the <dest> including the '\0'.  A
  *        pointer to the start of <dest> is returned.
  */
 {
         register char *p = dest;

         while(*dest++ = *source++)
                 ;
         return(p);
 }


 STRCSPN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRCSPN.C

 int strcspn(string, set)
 register char *string;
 register char *set;
 /*
  *        Return the length of the sub-string of <string> that consists
  *        entirely of characters not found in <set>.  The terminating '\0'
  *        in <set> is not considered part of the match set.  If the first
  *        character if <string> is in <set>, 0 is returned.
  */
 {
         register int n = 0;
         char *strchr();

         while(*string && !strchr(set, *string++))
                 ++n;
         return(n);
 }


 STRDUP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRDUP.C

 char *strdup(string)
 register char *string;
 /*
  *        Create a copy of <string> and return a pointer to the copy.
  */
 {
         register char *p;
         char *malloc();

         if(p = malloc(strlen(string) + 1))
                 strcpy(p, string);
         return(p);
 }


 STREQL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STREQL.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         BOOL
 streql(s, t)                /* Return true if strings s and t are same.

 /*----------------------------------------------------------------------*/
 STRING s, t;
 {
         return (strcmp(s, t) IS NULL);
 }


 STRICMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRICMP.C

 int stricmp(str1, str2)
 register char *str1;
 register char *str2;
 /*
  *        Compare strings as with strcmp(), but ignore the case of any
  *        alphabetic characters.
  */
 {
         register char c1, c2;

         while((c1 = tolower(*str1++)) == (c2 = tolower(*str2++)))
                 if(c1 == '\0')
                         return(0);
         return(c1 - c2);
 }


 STRICMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CXREF\STRICMP.C

 int stricmp(a, b)
 char *a, *b;
 {
    int Result;

    while (((Result = toupper(*a++) - toupper(*b++)) == 0) && (*(a - 1) != 0))
    if (Result < 0)
       Result = -1;
    if (Result > 0)
       Result = 1;
    return (Result);
 }


 STRINDEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRINDEX.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/

 strindex(s, t)                /* return the index of t in s, -1 if none.

 /*----------------------------------------------------------------------*/
 STRING s, t;
 {
         int i, j, k;

         for (i = 0; s[i] ISNT NULL; i++)
         {        for (j = i, k = 0; t[k] ISNT NULL AND s[j] IS t[k]; j++, k++
                         ;
                 if (t[k] IS NULL)
                         return (i);
         }
         return (EOF);
 }

 /*        This is the index(s,t) function given in Kernighan and Ritchie,
  *        page 67.
  */


 STRING.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\ADVC\STRING.C

 #include <ctype.h>

 int any2dec(str,radix)                /* convert string to integer */
    char *str;
    unsigned int radix;
 {
    unsigned int digit, number = 0;
    while (*str) {
       if (isdigit(*str)) digit = *str - '0';
       else if (islower(digit)) digit = *str - 'a' + 10;
       else digit = *str - 'A' + 10;
       number = number * radix + digit;
       str++; }
    return(number);
 }



 unsigned char *bsqueeze(line)         /* squeeze blanks from a string */
    unsigned char *line;
 {
    static unsigned char sqbuf[126];
    unsigned char *sqptr = sqbuf;
    int repcnt = 0;

    while (*line) {
       while(*line == ' ') {
          line++;
          repcnt++; }
       if (repcnt == 2)
          *sqptr++ = ' ' | 128;
       else if (repcnt > 2) {
          *sqptr++ = 128;
          *sqptr++ = repcnt | 128; }
       else if (repcnt) {
          if (sqptr == &sqbuf[0])
             *sqptr++ = ' ';
          else *(sqptr - 1) += 128; }
       repcnt = 0;
       *sqptr++ = *line++; }
    *sqptr = '\0';
    return(&sqbuf[0]);
 }



 unsigned char *bunsqueeze(line)       /* unsqueeze a blank-squeezed string */
    unsigned char *line;
 {
    static unsigned char usqbuf[126];
    unsigned char *usqptr = usqbuf;
    int repcnt = 0;

    while (*line) {
       if (*line < 128)
          *usqptr++ = *line;
       else if (*line == 128) {
          repcnt = *++line - 128;
          while (repcnt--)
              *usqptr++ = ' '; }
       else {
          *usqptr++ = *line - 128;
          *usqptr++ = ' '; }
       line++; }
    *usqptr = '\0';
    return(&usqbuf[0]);
 }



 char *dec2any(number,radix)           /* convert integer to string */
    unsigned int number, radix;
 {
    static char buffer[64];      /* allow for up to 64-bit integers */
    char *bufptr = buffer + 64;  /* point to end of buffer */
    int digit;
    *bufptr-- = '\0';
    do {
       digit = number % radix;
       number /= radix;
       *bufptr-- = (digit < 10) ? (digit + '0') : (digit + 'A' - 10); }
    while (number);
    return(++bufptr);
 }



 char *extract(str,delim,element)    /* extract element from delimited string
    char *str, delim;
    int element;
 {
    static char elembuf[80];
    char *elem = elembuf, *temp;

    temp = str;
    while (*str && element)
       if (*str++ == delim)
          if (--element) temp = str;
    if ((element == 1) && (*str == '\0') || (element == 0))
       while (*temp && (*temp != delim))
          *elem++ = *temp++;
    *elem = '\0';
    return(&elembuf[0]);
 }



 char *locase(str)                     /* convert string to lowercase */
    char *str;
 {
    char *start;
    start = str;
    while (*str) {
       if (isupper(*str))
          *str = tolower(*str);
       str++; }
    return(start);
 }



 char *multiand(str,c)                 /* AND string with a given value */
    char *str, c;
 {
    char *start;

    start = str;
    while (*str)
       *str++ &= c;
    return(start);
 }



 char *multior(str,c)                  /* OR string with a given value */
    char *str, c;
 {
    char *start;

    start = str;
    while (*str)
       *str++ |= c;
    return(start);
 }



 char *multixor(str,c)                 /* XOR string with a given value */
    char *str, c;
 {
    char *start;

    start = str;
    while (*str)
       *str++ ^= c;
    return(start);
 }



 char *reverse(str)                    /* reverse order of chrs in a string */
    char *str;
 {
    char *start, *end, tmp;
    int length;

    end = str + (length = strlen(start = str)) -1;
    length >>= 1;

    while (length--) {
       tmp = *str;
       *str++ = *end;
       *end-- = tmp; }
    return(start);
 }



 char *soundex(str)                    /* get soundex code for a string */
    char *str;
 {
    static char soundexbuf[81];
    char *table = "01230120022455012623010202";
    char *sdx = soundexbuf, lastchr = ' ';

    while (*str) {
       if (isalpha(*str) && (*str != lastchr)) {
          *sdx = *(table + toupper(*str) - 'A');
          if ((*sdx != '0') && (*sdx != lastchr))
             lastchr = *sdx++; }
       str++; }
    *sdx = '\0';
    return(&soundexbuf[0]);
 }



 char *strip(str,c)                    /* strip a given chr from a string */
    char *str, c;
 {
    char *start, *newstr;

    start = newstr = str;
    while (*str) {
       if (*str != c)
          *newstr++ = *str;
       str++; }
    *newstr = '\0';
    return(start);
 }



 char *striprange(str,clo,chi)         /* strip a range of chrs from a string
    char *str, clo, chi;
 {
    char *start, *newstr;

    start = newstr = str;
    while (*str) {
       if ((*str > chi) | (*str < clo))
          *newstr++ = *str;
       str++; }
    *newstr = '\0';
    return(start);
 }



 char *upcase(str)                     /* convert a string to uppercase */
    char *str;
 {
    char *start;
    start = str;
    while (*str) {
       if (islower(*str))
          *str = toupper(*str);
       str++; }
    return(start);
 }


 STRINGIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\STRINGIN.C

                                           /* Chapter 9 - Program 5 */
 #include "stdio.h"

 main()
 {
 char big[25];

     printf("Input a character string, up to 25 characters.\n");
     printf("An X in column 1 causes the program to stop.\n");

     do {
        scanf("%s",big);
        printf("The string is -> %s\n",big);
     } while (big[0] != 'X');

     printf("End of program.\n");
 }


 STRINGS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\STRINGS.C

                                          /* Chapter 7 - Program 2 */
 main()
 {
 char name1[12],name2[12],mixed[25];
 char title[20];

    strcpy(name1,"Rosalinda");
    strcpy(name2,"Zeke");
    strcpy(title,"This is the title.");

    printf("     %s\n\n",title);
    printf("Name 1 is %s\n",name1);
    printf("Name 2 is %s\n",name2);

    if(strcmp(name1,name2)>0)  /* returns 1 if name1 > name2 */
       strcpy(mixed,name1);
    else
       strcpy(mixed,name2);

    printf("The biggest name alpabetically is %s\n",mixed);

    strcpy(mixed,name1);
    strcat(mixed,"  ");
    strcat(mixed,name2);
    printf("Both names are %s\n",mixed);
 }


 STRIRPL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRIRPL.C

 int strirpl(string, ptrn, rpl, n)
 char *string;
 char *ptrn;
 register char *rpl;
 register int n;
 /*
  *        Same as strrpl() except ignores case of alphabetic characters.
  */
 {
         register char *p, *q = string;
         register int d, rlen, nn = 0;
         char *stristr();

         rlen = strlen(rpl);
         d = rlen - strlen(ptrn);
         while(n && (p = stristr(q, ptrn))) {
                 ++nn;
                 stradj(p, d);
                 strncpy(p, rpl, rlen);
                 q = p + rlen;
                 if(n > 0)
                         --n;
         }
         return(nn);
 }


 STRISTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRISTR.C

 #include <d:\usr\stdlib\stdio.h>

 char *stristr(string, pattern)
 register char *string;
 register char *pattern;
 /*
  *        Same as strstr(), but ignore the case of any alphabetic characters.
  */
 {
         register int plen;

         plen = strlen(pattern);
         while(*string) {
                 if(strnicmp(string, pattern, plen) == 0)
                         return(string);
                 ++string;
         }
         return(NULL);
 }


 STRLEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRLEN.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         int
 strlen(s)        /* return length of string s

 /*----------------------------------------------------------------------*/
 STRING s;
 {
         STRING p;

         p = s;
         while (*p)
                 p++;
         return (p - s);
 }


 STRLEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRLEN.C

 int strlen(string)
 register char *string;
 /*
  *        Returns the number of characters in a string, not including the
  *        terminating '\0'.
  */
 {
         register int n = 0;

         while(*string++)
                 ++n;
         return(n);
 }


 STRLWR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRLWR.C

 #include <d:\usr\stdlib\stdio.h>

 char *strlwr(string)
 register char *string;
 /*
  *        Convert all alphabetic characters in <string> to lower case.
  */
 {
         register char *p = string;

         while(*string) {
                 if(isupper(*string))
                         *string ^= 0x20;
                 ++string;
         }
         return(p);
 }


 STRMATH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\STRMATH.C

 /*
  *    Program name:  strmath.c
  *
  *    Program author:  Robert E. Sawyer
  *                     Torrance, California
  *
  *    Released for personal, non-commercial use only, 1 August 1984.
  *
  *    Specifications to which the main functions were written:
  *        They must do decimal arithmetic on numbers stored in strings.
  *        The numbers must be in the form:
  *
  *        Snnnnnnn.nnnn
  *
  *        where "S" is an optional sign (+ or -), "n" is any
  *        decimal digit (0 through 9) and "." is an optional
  *        decimal point.  The four routines should be called
  *        "decadd", "decsub", "decmul", and "decdiv", and they
  *        each must be called as follows:
  *
  *                char n1[21],n2[21],result[21];
  *                strcpy (n1,"123.45");
  *                strcpy (n2,"-3.0)";
  *
  *                if (!decadd(result,n1,n2))
  *                    printf ("Error adding %s to %s\n", n1, n2);
  *                else
  *                    printf ("Result is %s\n", result);
  *
  *        In this example, the program should print
  *
  *                Result is 120.45
  *
  *        "decsub", "decmul", and "decdiv" should work the same
  *        way.
  *
  *        These routines should return a 1 (true) if the arguments
  *        are valid and the result can be calculated, and a 0
  *        (false) if anything is wrong.  In the case of an error,
  *        the "result" argument should contain a null value.
  *
  *        The strings may have from 1 to 18 significant digits.
  *        Since there can be a leading sign and a decimal point,
  *        the strings must be able to hold at least 20 characters.
  *        They are dimensioned with 21 above to handle the 20
  *        character limit plus the trailing zero needed in C
  *        strings.
  *
  *        If the result will be too long (i.e. more than 18
  *        significant digits) treat that case as an error
  *        (i.e., return a 0 and set "result" to be a null).
  *        The same holds true for an attempted division by zero.
  *
  *        Math must be EXACT (!!) -- that means no rounding!
  *        These routines must run on an IBM PC without an
  *        8087 chip, and they must be written using only
  *        C functions (i.e., no "C Tools", "C Food", or
  *        other enhancement packages).
  *
  *    Sources:  The lowest level string-math functions are modelled
  *        on corresponding algorithms in D.E.Knuth's, 'The Art of
  *        Computer Programming', Vol.2, and on C.E.Burton's algorithms
  *        in DDJ, #89, 'RSA: A Public Key Cryptosystem, Part 1'.
  */

 N    18     /*chosen maximum number of significant digits */
 #define MIN(x, y)  ((x) > (y) ? (y) : (x))
 #define MAX(x, y)  ((x) > (y) ? (x) : (y))

 /*-----------------driver to test the functions-------------------*/
 main()
     {
     char n1[N+3], n2[N+3], nn1[N+3], nn2[N+3], res1[N+3], res2[N+3];
     int l1, l2, lr1, lr2, ok;
     char msg[N+3];

     printf("Arithmetic to %.0d significant digits\n\n", N);
     while (1)
         {
         printf("Enter 1st number:  ");
         scanf("%s", nn1);

          printf("Enter 2nd number:  ");
         scanf("%s", nn2);

         l1 = strlen(nn1);
         l2 = strlen(nn2);

         strcpy(n1, nn1);
         strcpy(n2, nn2);

         ok = decadd(res1, n1, n2);
         if (!ok)
             strcpy(msg, "*ERROR*");
         else
             msg[0] = '\0';
         printf("\n ADD -> %s  %s\n", res1, msg);

         ok = decsub(res1, n1, n2);
         if (!ok)
             strcpy(msg, "*ERROR*");
         else
             msg[0] = '\0';
         printf("\n SUB -> %s  %s\n", res1, msg);

         ok = decmul(res1, n1, n2);
         if (!ok)
             strcpy(msg, "*ERROR*");
         else
             msg[0] = '\0';
         printf("\n MUL -> %s  %s\n", res1, msg);

         ok = decdiv(res1, n1, n2);
         if (!ok)
             strcpy(msg, "*ERROR*");
         else
             msg[0] = '\0';
         printf("\n DIV -> %s  %s\n", res1, msg);

         printf("-------------\n");
         }
     }

 /*---------------------main functions--------------------------*/

 decadd(sum, n1, n2)
     char sum[], n1[], n2[];
     {
     char num[N+3], num1[N+3], num2[N+3];
     int sign1, digl1, digr1, sign2, digl2, digr2;
     int sign, digr;
     int len, len1, len2;
     int del;

     if (parse(n1, num1, &sign1, &digl1, &digr1) &&
         parse(n2, num2, &sign2, &digl2, &digr2))
         {
         len1 = strlen(num1);
         len2 = strlen(num2);
         len  = MAX(digl1, digl2) + MAX(digr1, digr2);
         if (len > N)    /* allow for sign, decimal point, and '\0' */
             {
             sum[0] = '\0';
             return (0);
             }
         if (digr1 < digr2)
             {
             del = digr2 - digr1;
             pad(num1, del);
             len1 += del;
             digr = digr2;
             }
         else
             {
             del = digr1 - digr2;
             pad(num2, del);
             len2 += del;
             digr = digr1;
             }
         if (!add(num1, len1, sign1, num2, len2, sign2, num, &sign))
             {
             sum[0] = '\0';
                 return (0);
             }
         if ((len = strlen(num)) > N)
             {
             sum[0] = '\0';
             return (0);
             }
         fix(num, len, sign, digr);
         strcpy(sum, num);
         return (1);
         }
     else
         {
         sum[0] = '\0';
         return (0);
         }
     }

 decsub(dif, n1, n2)
     char dif[], n1[], n2[];
     {
     char num[N+3], num1[N+3], num2[N+3];
     int sign1, digl1, digr1, sign2, digl2, digr2;
     int sign, digr;
     int len, len1, len2;
     int del;

     if (parse(n1, num1, &sign1, &digl1, &digr1) &&
         parse(n2, num2, &sign2, &digl2, &digr2))
         {
         len1 = strlen(num1);
         len2 = strlen(num2);
         len  = MAX(digl1, digl2) + MAX(digr1, digr2);
         if (len > N)    /* allow for sign, decimal point, and '\0' */
             {
             dif[0] = '\0';
             return (0);
             }
         if (digr1 < digr2)
             {
             del = digr2 - digr1;
             pad(num1, del);
             len1 += del;
             digr = digr2;
             }
         else
             {
             del = digr1 - digr2;
             pad(num2, del);
             len2 += del;
             digr = digr1;
             }
         if (!sub(num1, len1, sign1, num2, len2, sign2, num, &sign))
             {
             dif[0] = '\0';
             return (0);
             }
         if ((len = strlen(num)) > N)
             {
             dif[0] = '\0';
             return (0);
             }
         fix(num, len, sign, digr);
         strcpy(dif, num);
         return (1);
         }
     else
         {
         dif[0] = '\0';
         return (0);
         }
     }

 decmul(prod, n1, n2)
     char prod[], n1[], n2[];
     {
     char num[N+3], num1[N+3], num2[N+3];
     int sign1, digl1, digr1, sign2, digl2, digr2;
     int sign, digr;
     int len, len1, len2;

     if (parse(n1, num1, &sign1, &digl1, &digr1) &&
         parse(n2, num2, &sign2, &digl2, &digr2))
         {
         len1 = strlen(num1);
         len2 = strlen(num2);
         if (len1+len2-1 > N)    /* allow for sign, decimal point, and '\0' */
             {
             prod[0] = '\0';
             return (0);
             }
         digr = digr1 + digr2;
         if (!mul(num1, len1, sign1, num2, len2, sign2, num, &sign))
             {
             prod[0] = '\0';
             return (0);
             }
         if ((len = strlen(num)) > N)
             {
             prod[0] = '\0';
             return (0);
             }
         fix(num, len, sign, digr);
         strcpy(prod, num);
         return (1);
         }
     else
         {
         prod[0] = '\0';
         return (0);
         }
     }

 decdiv(quot, n1, n2)
     char quot[], n1[], n2[];
     {
     char num[N+N+1], num1[N+N+1], num2[N+3];
     int sign1, digl1, digr1, sign2, digl2, digr2;
     int sign, digr, digl, inum;
     int len, len1, len2;

     if (parse(n1, num1, &sign1, &digl1, &digr1) &&
         parse(n2, num2, &sign2, &digl2, &digr2))
         {
         len1 = strlen(num1);
         len2 = strlen(num2);
         pad(num1, N+N-len1);
         if (!div(num1, N+N, sign1, num2, len2, sign2, num, &sign))
             {
             quot[0] = '\0';
             return (0);
             }
         if ((len=strlen(num))==N+N-len2)
             digl = len1 - len2;
         else
             digl = len1 - len2 + 1;
         for (inum=len-1; (num[inum]=='0') && (inum>0); --inum)
             ;
         num[++inum] = '\0';
         len = inum;
         digr = len - digl + digr1 - digr2;
         if ((len > N) || (digr > N) || (digl > N))
             {
             quot[0] = '\0';
             return (0);
             }
         fix(num, len, sign, digr);
         strcpy(quot, num);
         return (1);
         }
     else
         {
         quot[0] = '\0';
         return (0);
         }
     }

 /*-----------intermediate level string-math functions----------*/

 /*    add()
  *    performs the appropriate string math
  */
 add(num1, len1, sign1, num2, len2, sign2, num, sign)
     char num1[], num2[], num[];
     int sign1, sign2, *sign;
     int len1, len2;
     {
     if ((sign1>0) && (sign2>0))
         {
         *sign = 1;
         if (!sadd(num1, len1, num2, len2, num))
             return (0);
         }
     else if ((sign1<0) && (sign2<0))
         {
         *sign = -1;
         if (!sadd(num1, len1, num2, len2, num))
             return (0);
         }
     else if ((sign1<0) && (sign2>0))
         {
         if ((len2>len1) || ((len2==len1) && (strcmp(num2,num1) > 0)))
             {
             *sign = 1;
             if (!ssub(num2, len2, num1, len1, num))
                 return (0);
             }
         else
             {
             *sign = -1;
             if (!ssub(num1, len1, num2, len2, num))
                 return (0);
             }
         }
     else
         {
         if ((len2>len1) || ((len2==len1) && (strcmp(num2,num1) > 0)))
             {
             *sign = -1;
             if (!ssub(num2, len2, num1, len1, num))
                 return (0);
             }
         else
             {
             *sign = 1;
             if (!ssub(num1, len1, num2, len2, num))
                 return (0);
             }
         }
     return (1);
     }

 /*    sub()
  *    performs the appropriate string math
  */
 sub(num1, len1, sign1, num2, len2, sign2, num, sign)
     char num1[], num2[], num[];
     int sign1, sign2, *sign;
     int len1, len2;
     {
     if ((sign1>0) && (sign2>0))
         {
         if ((len2>len1) || ((len2==len1) && (strcmp(num2,num1) > 0)))
             {
             *sign = -1;
             if (!ssub(num2, len2, num1, len1, num))
                 return (0);
             }
         else
             {
             *sign = 1;
             if (!ssub(num1, len1, num2, len2, num))
                 return (0);
             }
         }
     else if ((sign1<0) && (sign2<0))
         {
         if ((len2>len1) || ((len2==len1) && (strcmp(num2,num1) > 0)))
             {
             *sign = 1;
              if (!ssub(num2, len2, num1, len1, num))
                 return (0);
             }
         else
             {
             *sign = -1;
             if (!ssub(num1, len1, num2, len2, num))
                 return (0);
             }
         }
     else if ((sign1<0) && (sign2>0))
         {
         *sign = -1;
         if (!sadd(num2, len2, num1, len1, num))
             return (0);
         }
     else
         {
         *sign = 1;
         if (!sadd(num1, len1, num2, len2, num))
             return (0);
         }
     return (1);
     }

 /*    mul()
  *    performs the appropriate string math
  */
 mul(num1, len1, sign1, num2, len2, sign2, num, sign)
     char num1[], num2[], num[];
     int sign1, sign2, *sign;
     int len1, len2;
     {
     if (sign1*sign2 > 0)
         {
         *sign = 1;
         if (!smul(num1, len1, num2, len2, num))
             return (0);
         }
     else
         {
         *sign = -1;
         if (!smul(num1, len1, num2, len2, num))
             return (0);
         }
     return (1);
     }

 /*    div()
  *    performs the appropriate string math
  */
 div(num1, len1, sign1, num2, len2, sign2, num, sign)
     char num1[], num2[], num[];
     int sign1, sign2, *sign;
     int len1, len2;
     {
     char rem[N+3];

     if (sign1*sign2 > 0)
         {
         *sign = 1;
         if (!sdiv(num1, len1, num2, len2, num, rem))
             return (0);
         if (rem[0] > '0')
             return (0);
         }
     else
         {
         *sign = -1;
         if (!sdiv(num1, len1, num2, len2, num, rem))
             return (0);
         if (rem[0] > '0')
             return (0);
         }
     return (1);
     }

 /*-----------lowest level string-math functions------------*/

 /*  sadd(), ssub(), smul(), sdiv() perform the lowest level
  *  manipulations on strings interpreted as nonnegative integers.
  *    leading '0's are removed from num1, num2, and from the result
  *  substrings, to which a terminal null is appended;
  *    each function returns 0 on error.
  */

 /* sadd() yields sum[],
  * lens <= max(len1, len2) + 1
  */
 sadd(num1, len1, num2, len2, sum)
     char num1[], num2[], sum[];
     int len1, len2;
     {
     int lens, add, carry, index1, index2, indexs, temp1, temp2;

     lens = MAX(len1, len2) + 1;
     indexs = lens - 1;
     index1 = len1 - 1;
     index2 = len2 - 1;
     carry = 0;
     while ( MIN(index1, index2) >= 0)
         {
         temp1 = num1[index1] - '0';
         temp2 = num2[index2] - '0';
         add = carry + temp1 + temp2;
         sum[indexs] = add % 10 + '0';
         carry = add / 10;
         --index1;
         --index2;
         --indexs;
         }
     if (index2 < 0)
         {
         while (index1 >= 0)
             {
             temp1 = num1[index1] - '0';
             add = carry + temp1;
             sum[indexs] = add % 10 + '0';
             carry = add / 10;
             --index1;
             --indexs;
             }
         }
     else
         {
         while (index2 >= 0)
             {
             temp1 = num2[index2] - '0';
             add = carry + temp1;
             sum[indexs] = add % 10 + '0';
             carry = add / 10;
             --index2;
             --indexs;
             }
         }
     sum[indexs] = carry + '0';
     --indexs;
     while (indexs >= 0)
         {
         sum[indexs] = '0';
         --indexs;
         }
     while ((sum[0]=='0') && (lens>1))
         {
         for (indexs=1; indexs<lens; ++indexs)
             sum[indexs-1] = sum[indexs];
         --lens;
         }
     sum[lens] = '\0';
     return lens;
     }

 /* ssub() yields dif[],
  * lend <= len1
  */
 ssub(num1, len1, num2, len2, dif)
     char num1[], num2[], dif[];
     int len1, len2;
     {
     int lend, sub, borrow, index1, index2, indexd, temp1, temp2;

     lend = len1;
     if (len1>=len2)
         {
         indexd = lend - 1;
         index1 = len1 - 1;
         index2 = len2 - 1;
         borrow = 0;

         while (index2 >= 0)
             {
             temp1 = num1[index1] - '0';
             temp2 = num2[index2] - '0';
             sub = borrow + temp1 - temp2;
             if (sub < 0)
                 {
                 sub += 10;
                 borrow = -1;
                 }
             else
                 borrow = 0;
             dif[indexd] = sub + '0';
             --index1;
             --index2;
             --indexd;
             }
         while (index1 >= 0)
             {
             temp1 = num1[index1] - '0';
             sub = borrow + temp1;
             if (sub < 0)
                 {
                 sub += 10;
                 borrow = -1;
                 }
             else
                 borrow = 0;
             dif[indexd] = sub + '0';
             --index1;
             --indexd;
             }
         if (borrow==0)
             while (indexd >= 0)
                 {
                 dif[indexd] = '0';
                 --indexd;
                 }
         else
             {
             dif[0] = '\0';
             return 0;
             }
         while ((dif[0]=='0') && (lend>1))
             {
             for (indexd=1; indexd<lend; ++indexd)
                 dif[indexd-1] = dif[indexd];
             --lend;
             }
         dif[lend] = '\0';
         }
     else
         {
         dif[0] = '\0';
         return 0;
         }
     return lend;
     }

 /* smul() yields prod[],
  * lenp <= len1 + len2
  */
 smul(num1, len1, num2, len2, prod)
     char num1[], num2[], prod[];
     int len1, len2;
     {
     int lenp, mult, carry, index1, index2, indexp, temp1, temp2, tempp;

     lenp = len1 + len2;
     index2 = len2 - 1;
     for (indexp=0; indexp<lenp; ++indexp)
         prod[indexp] = '0';
     while (index2 >= 0)
         {
         indexp = lenp + index2 - len2;
         if (num2[index2] == '0')
             {
             carry = 0;
             indexp -= len1;
             }
         else
             {
             index1 = len1 - 1;
             carry = 0;
             while (index1 >= 0)
                 {
                 temp1 = num1[index1] - '0';
                 temp2 = num2[index2] - '0';
                 tempp = prod[indexp] - '0';
                 mult = carry + temp1*temp2 + tempp;
                 prod[indexp] = mult % 10 + '0';
                 carry = mult / 10;
                 --index1;
                 --indexp;
                 }
             }
         prod[indexp] = carry + '0';
         --index2;
         }
     while ((prod[0]=='0') && (lenp>1))
         {
         for (indexp=1; indexp<lenp; ++indexp)
             prod[indexp-1] = prod[indexp];
         --lenp;
         }
     prod[lenp] = '\0';
     return lenp;
     }

 /* sdiv() yields quot[] and rem[],
  * lenq <= max(len1-len2, 1)
  * lenr <= len2
  */
 sdiv(num1, len1, num2, len2, quot, rem)
     char num1[], num2[], quot[], rem[];
     int len1, len2;
     {
     int lenq, lenr, div, flag, scale,
         index, index1, index2, indexq, indexr,
         temp1, temp2, temp3, temp4, temp5, qtest;

     if (num1[0] != '0')
         {
         for (index1=len1; index1>0; --index1)
             num1[index1] = num1[index1-1];
         num1[0] = '0';
         ++len1;
         }
     while ((num2[0]=='0') && (len2>1))
         {
         for (index2=1; index2<len2; ++index2)
             num2[index2-1] = num2[index2];
         --len2;
         }
     lenq = MAX(len1-len2, 1);
     lenr = len2;
     if ((len1<len2) || ((len1==len2) && (num1[0]<num2[0])))
         {
         quot[0] = '0';
         lenq = 1;
         strcpy(rem, num1);
         lenr = len1;
         }
     if(num2[0] != '0')
         {
         for (indexq=0; indexq<lenq; ++indexq)
             quot[indexq] = '0';
         for (indexr=0; indexr<lenr; ++indexr)
             rem[indexr] = '0';
         flag = 0;
         for (index1=1; index1<len1; ++index1)
             if (num1[index1] != '0')
                 {
                 flag = 1;
                 break;
                 }
         if (flag != 0)
             {
             temp1 = num2[0] - '0';
             scale = 10 / (temp1 + 1);
             if (scale > 1)
                 {
                 flag = 0;
                 index1 = len1 -1;
                 while (index1 >= 0)
                     {
                     temp1 = num1[index1] - '0';
                     div = flag + scale*temp1;
                     num1[index1] = div % 10 + '0';
                     flag = div /10;
                     --index1;
                     }
                 flag = 0;
                 index2 = len2 -1;
                 while (index2 >= 0)
                     {
                     temp1 = num2[index2] - '0';
                     div = flag + scale*temp1;
                     num2[index2] = div % 10 + '0';
                     flag = div / 10;
                     --index2;
                     }
                 }
             index1 = 0;
             while (index1 < (len1-len2))
                 {
                 if (num2[0] == num1[index1])
                     qtest = 9;
                 else
                     {
                     temp1 = num1[index1] - '0';
                     temp3 = num2[0] - '0';
                     if ((index1+1) < len1)
                         temp2 = num1[index1+1] - '0';
                     else
                         temp2 = 0;
                     qtest = (10*temp1 + temp2) / temp3;
                     }
                 temp2 = num1[index1] - '0';
                 temp4 = num2[0] - '0';
                 if (len2 >= 2)
                     temp1 = num2[1] - '0';
                 else
                     temp1 = 0;
                 if ((index1+1) < len1)
                     {
                     temp3 = num1[index1+1] - '0';
                     if ((index1+2) < len1)
                         temp5 = num1[index1+2] - '0';
                     else
                         temp5 = 0;
                     }
                 else
                     {
                     temp3 = 0;
                     temp5 = 0;
                     }
                 while (qtest*temp1 > (10*(10*temp2 + temp3
                                     - qtest*temp4) + temp5))
                     --qtest;
                 index2 = len2 - 1;
                 index = index1 + len2;
                 flag = 0;
                 while (index >= index1)
                     {
                     if (index2 >= 0)
                         {
                         temp1 = num2[index2] - '0';
                         flag -= qtest*temp1;
                         }
                     temp1 = num1[index] - '0';
                     div = flag + temp1;
                     if (div < 0)
                         {
                         flag = div / 10;
                         div %= 10;
                         if (div < 0)
                             {
                             div += 10;
                             --flag;
                             }
                         }
                     else
                         flag = 0;
                     num1[index] = div + '0';
                     --index2;
                     --index;
                     }
                 indexq = lenq - (len1 - len2) + index1;
                 if (flag != 0)
                     {
                     quot[indexq] = qtest - 1 + '0';
                     index2 = len2 - 1;
                     index = index1 + len2;
                     flag = 0;
                     while (index >= index1)
                         {
                         if (index2 >= 0)
                             {
                             temp1 = num2[index2] - '0';
                             flag += temp1;
                             }
                         temp1 = num1[index] - '0';
                         div = flag + temp1;
                         if (div > 9)
                             {
                             div -= 10;
                             flag = 1;
                             }
                         else
                             flag = 0;
                         num1[index] = div + '0';
                         --index2;
                         --index;
                         }
                     }
                 else
                     quot[indexq] = qtest + '0';
                 ++index1;
                 }
             index1 = len1 - len2;
             indexr = lenr - len2;
             flag = 0;
             while (index1 < len1)
                 {
                 temp1 = num1[index1] - '0';
                 div = temp1 + 10*flag;
                 rem[indexr] = div / scale + '0';
                 flag = div % scale;
                 ++index1;
                 ++indexr;
                 }
             index2 = 0;
             flag = 0;
             while (index2 < len2)
                 {
                 temp1 = num2[index2] - '0';
                 div = temp1 + 10*flag;
                 num2[index2] = div / scale + '0';
                 flag = div % scale;
                 ++index2;
                 }
             }
         while ((quot[0]=='0') && (lenq>1))
             {
             for (indexq=1; indexq<lenq; ++indexq)
                 quot[indexq-1] = quot[indexq];
             --lenq;
             }
         while ((rem[0]=='0') && (lenr>1))
             {
             for (indexr=1; indexr<lenr; ++indexr)
                 rem[indexr-1] = rem[indexr];
             --lenr;
             }
         quot[lenq] = '\0';
         rem[lenr] = '\0';
         }
     else
         {
         quot[0] = '\0';
         rem[0] = '\0';
         return 0;
         }
     return (lenq+lenr) * (lenq>0) * (lenr>0);
     }

 /*    parse() returns 0 on error.
  *    input:    str[] a string of digits with optional decimal point
  *            and leading sign.
  *    output:    num[] is a string containing the significant digits
  *            of str[], and digl/digr is the number of digits to the
  *          left/right of the decimal point.
  */
 parse(str, num, sign, digl, digr)
     char str[], num[];
     int *sign, *digl, *digr;
     {
     char c;
     int dflag, istr, inum, len;

     dflag = 0;
     inum = 0;
     *digl = 0;
     *digr = 0;
     c = str[0];
     if (c=='+')
         *sign = 1;
     else if (c=='-')
         *sign = -1;
     else if (c=='.')
         {
         *sign = 1;
         dflag = 1;
         }
     else if ((c>='0') && (c<='9'))
         {
         *sign = 1;
         if (c != '0')
             {
             *digl = 1;
             num[0] = c;
             ++inum;
             }
         }
     else
         return (0);
     istr = 1;
     while ((c=str[istr++]) != '\0')
         {
         if ((c=='.') && (dflag==0))
             dflag = 1;
         else if ((c>='0') && (c<='9'))
             {
             if ((c!='0') || (*digl>0) || (dflag==1))
                 {
                 if (dflag==0)
                     ++(*digl);
                 else
                     ++(*digr);
                 num[inum] = c;
                 ++inum;
                 }
             }
         else
             return (0);
         }
     --inum;
       while ((num[inum]=='0') && (inum>= *digl))
         {
         --(*digr);
         --inum;
         }
     num[++inum] = '\0';
     len = inum;
     while ((num[0]=='0') && (len>1))
         {
         for (inum=1; inum<len; ++inum)
             num[inum-1] = num[inum];
         --len;
         if (*digl>0)
             --(*digl);
         }
     num[len] = '\0';
     return (1);
     }

 /*    fix()
  *    inserts sign and decimal point in digit string num[]
  */
 fix(num, len, sign, digr)
     char num[];
     int len, sign, digr;
     {
     int inum;
     char nnum[N+3];

     if (digr >= 0)
         {
         if (len >= digr)
             {
             for (inum=len; inum>len-digr; --inum)
                 num[inum] = num[inum-1];
             num[inum] = '.';
             ++len;
             num[len] = '\0';
             }
         else
             {
             nnum[0] = '.';
             for (inum=1; inum<=digr; ++inum)
                 {
                 if (inum<=digr-len)
                     nnum[inum] = '0';
                 else
                     nnum[inum] = num[inum-digr+len-1];
                 }
             nnum[inum] = '\0';
             strcpy(num, nnum);
             len = digr+1;
             }
         }
     else
         {
         len -= digr - 1;
         pad(num, -digr);
         num[len-1] = '.';
         num[len] = '\0';

         }
     if (sign==-1)
         {
         for (inum=len; inum>0; --inum)
             num[inum] = num[inum-1];
         num[0] = '-';
         ++len;
         num[len] = '\0';
         }

     }

 /*     pad()
  *  input:    num[] a string .
  *            dig a number of '0's to be appended to num[].
  *    output: num[] with dig '0's appended.
  */
  pad(num, dig)
      char num[];
      int dig;
      {
      int inum, len;

     len = strlen(num);
     for (inum=len; inum < len+dig; ++inum)
         num[inum] = '0';
     num[inum] = '\0';
     }

 /*------------------end of file----------------------*/



 STRNCAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRNCAT.C

 /* 1.0  07-06-84
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 strncat(s1, s2, n)        /* concatenate string s2 onto s1, but at most
                            n characters. Return pointer s1.                */
 /*----------------------------------------------------------------------*/
 STRING s1, s2;
 int n;
 {
         STRING p;

         p = s1;
         while (*s1 AND n > 0)
         {        s1++;
                 n--;
         }
         strncpy(s1, s2, n);
         return p;
 }


 STRNCAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRNCAT.C

 char *strncat(dest, source, limit)
 register char *dest;
 register char *source;
 register int limit;
 /*
  *        Concatenate <limit> characters from <source> onto <dest>.  If
  *        <source> contains less than <limit> characters, the length of
  *        source is used for <limit>.  The terminating '\0' is always
  *        added.  A pointer to <dest> is returned.
  */
 {
         register char *p = dest;

         while(*dest)
                 ++dest;
         while((limit--) && (*dest++ = *source++))
                 ;
         *dest = '\0';
         return(p);
 }


 STRNCMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRNCMP.C

 int strncmp(str1, str2, limit)
 register char *str1;
 register char *str2;
 register int limit;
 /*
  *        Compare strings as with strcmp(), but limit comparison to the
  *        <limit> characters.
  */
 {
         for(; ((--limit) && (*str1 == *str2)); ++str1, ++str2)
                 if(*str1 == '\0')
                         return(0);
         return(*str1 - *str2);
 }


 STRNCMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRNCMP.C

 /* 1.1  02-10-86                                                (strncmp.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984, 86        *
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/

 strncmp(s, t, n)        /* compares s and t for max of n chars. Returns
                            0 if equal, a neg. no. if s<t, pos. if s>t
 /*----------------------------------------------------------------------*/
 STRING s, t;
 int n;
 {
         for ( ; --n > 0 AND *s IS *t; s++, t++)
                 if (*s IS NULL)
                         return (0);
         return (*s - *t);
 }


 STRNCPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRNCPY.C

 char *strncpy(dest, source, limit)
 register char *dest;
 register char *source;
 register int limit;
 /*
  *        Copies the <source> string to the <dest>.  At most, <limit>
  *        characters are copied.  If <source> ends before <limit> characters
  *        have been copied, the '\0' is copied, otherwise <dest> is not
  *        terminated by the copy.
  */
 {
         register char *p = dest;

         while((limit--) && (*dest++ = *source++))
                 ;
         return(p);
 }


 STRNCPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRNCPY.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 strncpy(s1, s2, n)        /* copy leftmost n chars of s2 into s1,
                            return s1                                        *
 /*----------------------------------------------------------------------*/
 STRING s1, s2;
 int n;
 {
         STRING s;

         for (s = s1; n-- > 0 AND (*s1 = *s2); s1++ , s2++)
                 ;
         *s1 = NULL;
         return s;
 }



 STRNICMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRNICMP.C

 int strnicmp(str1, str2, limit)
 register char *str1;
 register char *str2;
 register int limit;
 /*
  *        Compare strings as with strncmp(), but ignore the case of any
  *        alphabetic characters.
  */
 {
         register char c1, c2;

         while(((c1 = tolower(*str1++)) == (c2 = tolower(*str2++))) && --limit
                 if(c1 == '\0')
                         return(0);
         return(c1 - c2);
 }


 STRPBRK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRPBRK.C

 #include <d:\usr\stdlib\stdio.h>

 char *strpbrk(string, set)
 register char *string;
 register char *set;
 /*
  *        Return a pointer to the first occurance in <string> of any
  *        character in <set>.
  */
 {
         char *strchr();

         while(*string) {
                 if(strchr(set, *string))
                         return(string);
                 ++string;
         }
         return(NULL);
 }


 STRPOS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRPOS.C

 int strpos(string, symbol)
 register char *string;
 register char symbol;
 /*
  *        Return the index of the first occurance of <symbol> in <string>.
  *        -1 is returned if <symbol> is not found.
  */
 {
         register int i = 0;

         do {
                 if(*string == symbol)
                         return(i);
                 ++i;
         } while(*string++);
         return(-1);
 }


 STRREV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRREV.C

 char *strrev(string)
 char *string;
 /*
  *        Reverse the order of the characters in <string> in place.
  */
 {
         register char *p = string, *q, c;

         if(*(q = p)) {                /* non-empty string? */
                 while(*++q)
                         ;
                 while(--q > p) {
                         c = *q;
                         *q = *p;
                         *p++ = c;
                 }
         }
         return(string);
 }


 STRRPBRK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRRPBRK.C

 #include <d:\usr\stdlib\stdio.h>

 char *strrpbrk(string, set)
 register char *string;
 register char *set;
 /*
  *        Return a pointer to the last occurance in <string> of any
  *        character in <set>.
  */
 {
         register char *p;
         char *strrchr(), *strchr();

         p = strrchr(string, '\0');                /* start at EOS */
         while(string != p) {
                 if(strchr(set, *--p))
                         return(p);
         }
         return(NULL);
 }


 STRRPL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRRPL.C

 int strrpl(string, ptrn, rpl, n)
 char *string;
 char *ptrn;
 register char *rpl;
 register int n;
 /*
  *        Replace at most <n> occurances of <ptrn> in <string> with <rpl>.
  *        If <n> is -1, replace all.  Return the number of replacments.
  */
 {
         register char *p, *q = string;
         register int d, rlen, nn = 0;
         char *strstr();

         rlen = strlen(rpl);
         d = rlen - strlen(ptrn);
         while(n && (p = strstr(q, ptrn))) {
                 ++nn;
                 stradj(p, d);
                 strncpy(p, rpl, rlen);
                 q = p + rlen;
                 if(n > 0)
                         --n;
         }
         return(nn);
 }


 STRRPOS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRRPOS.C

 int strrpos(string, symbol)
 register char *string;
 register char symbol;
 /*
  *        Return the index of the last occurance of <symbol> in <string>.
  *        -1 is returned if <symbol> is not found.
  */
 {
         register int i = 0;
         register char *p = string;

         while(*string++)
                 ++i;
         do {
                 if(*--string == symbol)
                         return(i);
                 --i;
         } while(string != p);
         return(-1);
 }


 STRSAVE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\STRSAVE.C

 /* 1.0  07-10-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  *
  *        This is from Kernighan and Ritchie, page 103.
  *
  *---------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"

 /************************************************************************/
         STRING
 strsave(s)                /* get enough storage for s and put s there,
                            return pointer to the string, or NULL if no
                            string space                                 */
 /*----------------------------------------------------------------------*/
 STRING s;
 {
         STRING p, malloc();

         if ((p = malloc(strlen(s) + 1)) ISNT NULL)
                 strcpy(p, s);
         return p;
 }


 STRSET.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRSET.C

 char *strset(string, c)
 char *string;
 register char c;
 /*
  *        Fill <string> with <c> up the the terminating '\0' of <string>.
  */
 {
         register char *p = string;

         while(*p)
                 *p++ = c;
         return(string);
 }

 char *strnset(string, c, n)
 char *string;
 register char c;
 register int n;
 /*
  *        Fill at most <n> characters of <string> with <c>, up the the
  *        terminating '\0' of <string>.
  */
 {
         register char *p = string;

         while(n-- && *p)
                 *p++ = c;
         return(string);
 }


 STRSPN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRSPN.C

 int strspn(string, set)
 register char *string;
 register char *set;
 /*
  *        Return the length of the sub-string of <string> that consists
  *        entirely of characters found in <set>.  The terminating '\0'
  *        in <set> is not considered part of the match set.  If the first
  *        character if <string> is not in <set>, 0 is returned.
  */
 {
         register int n = 0;
         char *strchr();

         while(*string && strchr(set, *string++))
                 ++n;
         return(n);
 }


 STRSTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRSTR.C

 #include <d:\usr\stdlib\stdio.h>

 char *strstr(string, pattern)
 register char *string;
 register char *pattern;
 /*
  *        Return a pointer to the first occurance of <pattern> in <string>.
  *        NULL is returned if <pattern> is not found.
  */
 {
         register int plen;
         char *strchr();

         plen = strlen(pattern);
         while(string = strchr(string, *pattern)) {
                 if(strncmp(string, pattern, plen) == 0)
                         return(string);
                 ++string;
         }
         return(NULL);
 }


 STRTOK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRTOK.C

 #include <d:\usr\stdlib\stdio.h>

 static        char        *_strtok = NULL;        /* local token pointer */

 char *strtok(string, delim)
 register char *string;
 register char *delim;
 /*
  *        Return a token from <string>.  If <string> in not NULL, it is
  *        the beginning of a string from which tokens are to be extracted.
  *        Characters found in <delim> are skipped over to find the start
  *        of a token, characters are then accumulated until a character in
  *        <delim> is found, or the terminator of <string> is reached.
  *        A pointer to the '\0' terminated token is then returned.  Note
  *        that this function modifies <string> (by inserting '\0's) in
  *        the process.  Subsequent calls to strtok() may specify NULL as
  *        the <string> argument, in which case subsequent tokens are
  *        returned, or NULL if there are no more tokens.
  */
 {
         register char *p;
         char *strchr();

         if(string == NULL)
                 string = _strtok;
         while(*string && strchr(delim, *string))
                 ++string;
         if(*string == '\0')                /* no more tokens */
                 return(NULL);
         p = string;
         while(*string && !strchr(delim, *string))
                 ++string;
         if(*string != '\0')
                 *string++ = '\0';
         _strtok = string;
         return(p);
 }


 STRTRIM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRTRIM.C

 char *strtrim(string, junk)
 register char *string;
 register char *junk;
 /*
  *        Remove leading and trailing characters found in <junk>
  *        from <string>.  Return a pointer to the modified <string>.
  */
 {
         register char *p = string, *q = string;
         char *strchr();

         while(*string && strchr(junk, *string))
                 ++string;
         while(*string && !strchr(junk, *string))
                 *p++ = *string++;
         *p = '\0';
         return(q);
 }


 STRUCT1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\STRUCT1.C

                                          /* Chapter 11 - Program 1 */
 main()
 {

 struct {
    char initial;    /* last name initial      */
    int age;         /* childs age             */
    int grade;       /* childs grade in school */
    } boy,girl;

    boy.initial = 'R';
    boy.age = 15;
    boy.grade = 75;

    girl.age = boy.age - 1;  /* she is one year younger */
    girl.grade = 82;
    girl.initial = 'H';

    printf("%c is %d years old and got a grade of %d\n",
            girl.initial, girl.age, girl.grade);

    printf("%c is %d years old and got a grade of %d\n",
            boy.initial, boy.age, boy.grade);
 }


 STRUCT2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\STRUCT2.C

                                         /* Chapter 11 - Program 2 */
 main()
 {
 struct {
    char initial;
    int age;
    int grade;
    } kids[12];

 int index;

    for (index = 0;index < 12;index++) {
       kids[index].initial = 'A' + index;
       kids[index].age = 16;
       kids[index].grade = 84;
    }

    kids[3].age = kids[5].age = 17;
    kids[2].grade = kids[6].grade = 92;
    kids[4].grade = 57;

    kids[10] = kids[4];               /* Structure assignment  */

    for (index = 0;index < 12;index++)
       printf("%c is %d years old and got a grade of %d\n",
              kids[index].initial, kids[index].age,
              kids[index].grade);
 }


 STRUCT3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\STRUCT3.C

                                          /* Chapter 11 - Program 3 */
 main()
 {
 struct {
    char initial;
    int age;
    int grade;
    } kids[12],*point,extra;

 int index;

    for (index = 0;index < 12;index++) {
       point = kids + index;
       point->initial = 'A' + index;
       point->age = 16;
       point->grade = 84;
    }

    kids[3].age = kids[5].age = 17;
    kids[2].grade = kids[6].grade = 92;
    kids[4].grade = 57;

    for (index = 0;index < 12;index++) {
       point = kids + index;
       printf("%c is %d years old and got a grade of %d\n",
              (*point).initial, kids[index].age,
              point->grade);
    }
    extra = kids[2];               /* Structure assignment */
    extra = *point;                /* Structure assignment */
 }


 STRUPR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\STRUPR.C

 #include <d:\usr\stdlib\stdio.h>

 char *strupr(string)
 register char *string;
 /*
  *        Convert all alphabetic characters in <string> to upper case.
  */
 {
         register char *p = string;

         while(*string) {
                 if(islower(*string))
                         *string ^= 0x20;
                 ++string;
         }
         return(p);
 }


 SUBSTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SUBSTR.C

 char *substr(dest, source, start, end)
 register char *dest;
 register char *source;
 register int start;
 register int end;
 /*
  *        Copy characters from <source> to <dest> starting with character
  *        <start> and ending with <end>.  A pointer to <dest>, which will
  *        be '\0' terminated, is returned.
  */
 {
         register char *p = dest;
         register int n;

         n = strlen(source);
         if(start > n)
                 start = n - 1;
         if(end > n)
                 end = n - 1;
         source += start;
         while(start++ <= end)
                 *p++ = *source++;
         *p = '\0';
         return(dest);
 }

 char *subnstr(dest, source, start, length)
 register char *dest;
 register char *source;
 register int start;
 register int length;
 /*
  *        Copy <length> characters from <source> to <dest> starting with
  *        character <start>.  A pointer to <dest>, which will be '\0'
  *        terminated, is returned.
  */
 {
         register char *p = dest;
         register int n;

         n = strlen(source);
         if(start > n)
                 start = n - 1;
         source += start;
         while(*source && (length--))
                 *p++ = *source++;
         *p = '\0';
         return(dest);
 }


 SUMSQRES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SUMSQRES.C

                                           /* Chapter 5 - Program 1 */
 int sum; /* This is a global variable */

 main()
 {
 int index;

    header();        /* This calls the function named header */
    for (index = 1;index <= 7;index++)
      square(index); /* This calls the square function */
    ending();        /* This calls the ending function */
 }

 header()        /* This is the function named header */
 {
    sum = 0;     /* Initialize the variable "sum" */
    printf("This is the header for the square program\n\n");
 }

 square(number)   /* This is the square function */
 int number;
 {
 int numsq;

    numsq = number * number;  /* This produces the square */
    sum += numsq;
    printf("The square of %d is %d\n",number,numsq);
 }

 ending()   /* This is the ending function */
 {
    printf("\nThe sum of the squares is %d\n",sum);
 }


 SVSCREEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\EGASAVE\SVSCREEN.C

 #include <graph.h>
 #include <stdio.h>
 #include <memory.h>
 #include <dos.h>
 #include <malloc.h>


 /*        Program for saving the EGA screen FAST       */
 /*        This version for MSC 5.0 C, small model      */
 /*        Uses 28K buffer in data segment, you may     */
 /*        need change the program to use a smaller     */
 /*        buffer if data space is at a premium.  This  */
 /*        version works well for a fast "slide show"   */
 /*        type of effect where there is not much       */
 /*        program data.                                */
 /*                                                     */
 /*        If using a model with a large data segment   */
 /*        so that all data calls are far, then the     */
 /*        buffer is not needed, you can fwrite         */
 /*        directly from video memory.                  */
 /*                                                     */
 /*        usage:    error = save_screen(filename);     */
 /*                  error is type int                  */
 /*                  filename is char array of size 13  */
 /*                  error returned as stated below     */










 unsigned char buffer[28000];   /* buffer for one plane of video mem */




 save_screen (filename)

 char *filename;   /*  file name passed from calling program */

 {

       unsigned char plane;    /* variable to hold current video plane */
       int flag;          /* Error Flag */
                          /* 0 = success */
                          /* 1 = open file error */
                          /* 2 = write file error */

       FILE *screen_save;
       struct SREGS segregs;    /* structure for segread call */


       segread(&segregs);

       if ((screen_save = fopen(filename, "wb")) == NULL)
             return(1);


       for (plane = 0; plane < 4; plane++)
          {
              outp(0x3CE, 4);
              outp(0x3CF, plane);

              movedata(0xA000, 0x0000, segregs.ds, (unsigned int)buffer, 28000

                /* 0xA000 = segment for EGA video memory */
                /* 0x0000 = offset  for EGA video memory */
                /* segregs.ds = segment for variable "buffer" */
                /* (unsigned int)buffer = offset for variable "buffer" */
                /* 28000 is the byte size of one video plane */

              fwrite(buffer,1,28000,screen_save);
              if (ferror(screen_save))
                   return(2);

           }


     fclose(screen_save);


 }






 SWDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\SWDIR.C



 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==SOUTH_WEST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 SWITCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\SWITCH.C

                                          /* Chapter 3 - Program 6 */
 main()
 {
 int truck;

    for (truck = 3;truck < 13;truck = truck + 1) {

       switch (truck) {
          case 3  : printf("The value is three\n");
                    break;
          case 4  : printf("The value is four\n");
                    break;
          case 5  :
          case 6  :
          case 7  :
          case 8  : printf("The value is between 5 and 8\n");
                    break;
          case 11 : printf("The value is eleven\n");
                    break;
          default : printf("It is one of the undefined values\n");
                    break;
       } /* end of switch */

    } /* end of for loop */
 }


 SWITCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\SWITCH.C


 /****************************************************************************
 *****************************************************************************


                      THIS UTILITY SELECTS THE ACTIVE DISPLAY
              USAGE:  switch [MONITOR] [MODE]

                      [MONITOR] = monochrome or color.
                         type in either mono or monochrome,
                                 or col or color for color display.

                      [MODE] = (FOR COLOR ONLY)
                         0     40 * 25 BLACK AND WHITE
                         1     40 * 25 COLOR
                         2     80 * 25 BLACK AND WHITE
                         3     80 * 25 COLOR
                         4     320 * 200 COLOR  (MED. RES.)
                         5     320 * 200 BLACK AND WHITE  (MED. RES.)
                         6     640 * 200 BLACK AND WHITE  (HIGH RES.)

 *****************************************************************************
 *****************************************************************************


 #include "stdio.h"
 #include "conio.h"
 #include "utility.h"
 #include "screen.h"
 #include "string.h"
 #include "ctype.h"
 main(argc, argv)
 int argc;
 char **argv;
 {
         ADS equip_flag, new_equip_flag;
         int comlinptr, ax, bx, cx, dx, mode, columns, page, x;
         unsigned flag;
         char c, *comlin1, *calloc();
         comlin1 = calloc(40, 1);/*allocate 40 bytes for comlin1*/
         x = 0;

         if(argc < 2)/*check for command line argument*/
                 utabort("NO COMMAND LINE ARGUMENT  switch [MONITOR] [MODE]");

         equip_flag.s = 0x0040;/*rom bios data segment*/
         equip_flag.r = 0x0010;/*offset*/
         new_equip_flag.s = _defds;/*default data segment*/
         new_equip_flag.r = &flag;

         strcpy(comlin1, argv[1]);/*move argv1 to comlin1 for convert to LC*/
         while((c = comlin1[x]) != '\0'){/*convert if upper case to lower*/
                 comlin1[x++] = tolower(c);
         }

         strcpy(argv[1], comlin1);/*return changed string to  argv[1]*/
         free(comlin1);/*free allocated space of comlin1*/

         if((stsindex("mono", argv[1])) == 0){/*switch to monochrome*/
                 if(!scmode(&mode, &columns, &page))/*check not on monochrome*
                         utabort("ALREADY ON MONOCHROME ADAPTER");
                 outp(0x3d8, 00);/*deselect video enable on 6845*/
                 bios(17, &ax, &bx, &cx, &dx);/*get current flag into ax*/
                 flag = ax | 0x0030;/*set equipment flag to monochrome*/
                 utslmove(&new_equip_flag, &equip_flag, 4);/*return flag*/
                 screset(0);/*bios set mode call*/
                 exit();
         }

         if((stsindex("col", argv[1])) == 0){/*switch to color display*/
              if(argc != 3 || argc > 3)/*correct number of arguments*/
                 utabort("NO COMMAND LINE ARGUMENT  switch [MONITOR] [MODE]");
              if(scmode(&mode, &columns, &page))/*check not on color already*/
                       utabort("ALREADY ON COLOR ADAPTER");
              clear_screen();/*clear mono screen*/
              utslmove(&equip_flag, &new_equip_flag, 4);
              flag = flag ^ 0x0030;/*erase old display info*/
              flag = flag | 0x0020;/*set as 80 * 25 color card*/
              utslmove(&new_equip_flag, &equip_flag, 4);/*return flag*/
              stcd_i(argv[2], &comlinptr);/*set com line arg to integer*/
              screset(comlinptr);/*set mode from command line*/
              exit();
         }
         utabort("NO COMMAND LINE ARGUMENT  switch [MONITOR] [MODE]");
 }


 clear_screen()/*clears monochrome screen*/
 {

         int ax, bx, cx, dx;
         ax = 0x0600;/*set ah = 6  scroll screen*/
         bx = 0x0700;/*attribute 7*/
         cx = 0x0000;
         dx = 0x184f;/*set 24, 79 for scroll*/

         bios(16, &ax, &bx, &cx, &dx);

 }




 SWITCH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\SWITCH.C

 /* switch.c              switch display monitors
                       by Earl C. Terwilliger Jr.
                       05-04-1983
 */
 main()
 {
   struct regval { int ax,bx,cx,dx,si,di,ds,es; };
   struct regval srv,rrv;

   srv.cx = 0X0F00;                               /* remove the cursor */
   srv.ax = 0X0100;                               /* set cursor type   */
   sysint(16,&srv,&rrv);

   srv.ax = 0X0600;                               /* scroll & blank    */
   srv.cx = 0X0000;                               /* top left            */
   srv.dx = 0X184F;                               /* bottom right            *
   srv.bx = 0X0700;                               /* fill attribute    */
   sysint(16,&srv,&rrv);

   sysint(17,&srv,&rrv);                        /* equipment flag    */
   rrv.bx = rrv.ax;                               /* copy it            */
   rrv.bx &= 0X0030;                               /* Mask for video    */
   rrv.ax ^= rrv.bx;
   if (rrv.bx == 0X0030) {
    rrv.ax |= 0X0020;
    srv.ax = 0X0002;
   }
   else { rrv.ax |= 0X0030;
          srv.ax = 0X0007;
   }
   pokeb(0X0410,0,rrv.ax);                       /* save new equip    */
   sysint(16,&srv,&rrv);                        /* Screen back on    */
 }


 SYMBOL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CC68\SYMBOL.C

 #include        <stdio.h>
 #include        "c.h"
 #include        "expr.h"
 #include        "gen.h"
 #include        "cglbdec.h"

 /*
  *        68000 C compiler
  *
  *        Copyright 1984, 1985, 1986 Matthew Brandt.
  *  all commercial rights reserved.
  *
  *        This compiler is intended as an instructive tool for personal use.
  *        use for profit without the written consent of the author is prohibi
  *
  *        This compiler may be distributed freely for non-commercial use as l
  *        as this notice stays intact. Please forward any enhancements or que
  *        to:
  *
  *                Matthew Brandt
  *                Box 920337
  *                Norcross, Ga 30092
  */

 SYM     *search(na,thead)
 char    *na;
 SYM     *thead;
 {       while( thead != 0) {
                 if(strcmp(thead->name,na) == 0)
                         return thead;
                 thead = thead->next;
                 }
         return 0;
 }

 SYM     *gsearch(na)
 char    *na;
 {       SYM     *sp;
         if( (sp = search(na,lsyms.head)) == 0)
                 sp = search(na,gsyms.head);
         return sp;
 }

 insert(sp,table)
 SYM     *sp;
 TABLE   *table;
 {       if( search(sp->name,table->head) == 0) {
                 if( table->head == 0)
                         table->head = table->tail = sp;
                 else    {
                         table->tail->next = sp;
                         table->tail = sp;
                         }
                 sp->next = 0;
                 }
         else
                 error(ERR_DUPSYM);
 }


 SYSREAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\SYSREAD.C

 /* SYSREAD.C - From page 461 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. This program reads and displays   */
 /* a file using system I/O.  Usage: A>sysread filename.ext      */
 /****************************************************************/

 #include "fcntl.h"
 #define BUFFSIZE 512
 char buff[BUFFSIZE];

 main(argc, argv)
 int argc;
 char *argv[];
 {
 int inhandle, bytes, j;

    if(argc != 2) {
       printf("\nFormat: A>sysread filename.ext");
       exit();
    }
    if((inhandle = open(argv[1], O_RDONLY | O_BINARY)) < 0) {
       printf("\nCan't open file %s.", argv[1]);
       exit();
    }
    while((bytes = read(inhandle, buff, BUFFSIZE)) > 0)
       for(j = 0; j < bytes; j++)
          putch(buff[j]);
    close(inhandle);
 }



 SYSREAD2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\SYSREAD2.C

 /* SYSREAD2.C - From page 463 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. This program reads and displays   */
 /* a file using system I/O.  Usage: A>sysread2 filename.ext     */
 /* This program differs from SYSREAD.C only in that it uses     */
 /* the perror() function.                                       */
 /****************************************************************/

 #include "fcntl.h"
 #define BUFFSIZE 512
 char buff[BUFFSIZE];

 main(argc, argv)
 int argc;
 char *argv[];
 {
 int inhandle, bytes, j;

    if(argc != 2) {
       printf("\nFormat: A>sysread2 filename.ext");
       exit();
    }
    if((inhandle = open(argv[1], O_RDONLY | O_BINARY)) < 0)
       perror("\nCan't open input file");
    while((bytes = read(inhandle, buff, BUFFSIZE)) > 0)
       for(j = 0; j < bytes; j++)
          putch(buff[j]);
    close(inhandle);
 }



 SYSTEM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\SYSTEM.C

 #include <osbind.h>
 #include <stdio.h>

 extern char        *_base;

 int system(command)
 char *command;
 /*
  *        Attempts to pass <command> to the shell program pointed to by
  *        the system variable "_shell_p".  If a valid shell can't be found
  *        there, the "SHELL" environment variable is searched for.  If it
  *        exists and is not empty, it will be the name of the shell program
  *        to execute the given command.  If "SHELL" is not valid, the
  *        "PATH" variable is searched for.  This would specify the paths
  *        to search for the program name which is the first token of the
  *        command.  If "PATH" is not valid, the current directory is
  *        searched as for the given command.  The extensions tried (if none
  *        is specified) are ".TTP", ".TOS", ".PRG" and ".APP".
  */
 {
         register char *p, *q;
         register int rv = 0;
         register int (*shell)();
         char *getenv(), *strtok();

         if(!command)
                 return(ERROR);

         /* get _shell_p value */
         p = Super(0L);
         shell = *((long *) 0x4F6L);
         Super(p);

         /* validate _shell_p */
         if((shell) &&                                /* Shell available. */
            (((long) shell) < ((long) _base)) &&        /* Reasonable shell po
            (strncmp(shell, "PATH", 4))) {        /* Not corrupted */

                 /* execute the command */
                 rv = (*shell)(command);
                 return(rv);
         }

         /* SHELL= variable? */
         if((p = getenv("SHELL")) && (*p))
                 return(spawnp(p, command));

         /* parse for spawnp() attempt */
         p = strtok(command, " \t\r\n");
         q = strtok(NULL, "\r\n");
         return(spawnp(p, (q ? q : "")));
 }


 TAIL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TAIL.C

 /* Subject: Aztec C source - tail.c */
 /* tail - print last part of file */

 #include "stdio.h"
 #define TRUE 1
 #define FALSE 0
 #define BLANK ' '
 #define NL 0x0a
 #define TAB 0x09

 int lines, chars ;

 main(argc, argv)
 int argc ;
 char *argv[] ;
 {
     char *s ;
     FILE *input ;
     int count ;


     argc-- ; argv++ ;
     lines = TRUE ;
     chars = FALSE ;
     count = -10 ;

     if( argc == 0 ) {
         tail( stdin, count ) ;
         exit(0) ;
     }

     s = *argv ;
     if( *s == '-' || *s == '+' ) {
         s++ ;
         if( *s >= '0' && *s <= '9' ) {
             count = stoi( *argv ) ;
             s++ ;
             while( *s >= '0' && *s <= '9' )
                 s++ ;
         }
         if( *s == 'c' ) {
             chars = TRUE ;
             lines = FALSE ;
         }
         else if( *s != 'l' && *s != EOS ) {
             fprintf(stderr, "tail: unknown option %c\n", *s ) ;
             argc = 0 ;
         }
         argc-- ; argv++ ;
     }

     if( argc < 0 ) {
         fprintf(stderr, "usage: tail [+/-[number][lc]] [files]\n");
         exit(1) ;
     }

     if( argc == 0 )
         tail( stdin, count ) ;

     else if( (input=fopen(*argv,"r")) == NULL ) {
         fprintf(stderr, "tail: can't open %s\n", *argv) ;
         exit(1) ;
     }
     else {
         tail( input, count ) ;
         fclose( input ) ;
     }

     exit(0) ;

 } /* end main */

 /* stoi - convert string to integer */

 stoi(s)
 char *s ;
 {
     int n, sign ;

     while( *s == BLANK || *s == NL || *s == TAB )
         s++ ;

     sign = 1 ;
     if( *s == '+' )
         s++ ;
     else if( *s == '-' ) {
         sign = -1 ;
         s++ ;
     }
     for( n=0 ; *s >= '0' && *s <= '9' ; s++ )
         n = 10 * n + *s - '0' ;
     return( sign * n ) ;
 }

 /* tail - print 'count' lines/chars */

 #define INCR(p)  if(p >= end) p=cbuf ; else p++
 #define BUFSIZE 4098

 char cbuf[ BUFSIZE ] ;

 tail( in, goal )
 FILE *in ;
 int goal ;
 {
     int c, count ;
     char *start, *finish, *end ;

     count = 0 ;

     if( goal > 0 ) {    /* skip */

         if( lines )     /* lines */
             while( (c=getc(in)) != EOF ) {
                 if( c == NL )
                     count++ ;
                 if( count >= goal )
                     break ;
             }
         else            /* chars */
             while( getc(in) != EOF ) {
                 count++ ;
                 if( count >= goal )
                     break ;
             }
         if( count >= goal )
             while( (c=getc(in)) != EOF )
                 putc(c, stdout ) ;
     }

     else {              /* tail */

         goal = -goal ;
         start = finish = cbuf ;
         end = &cbuf[ BUFSIZE - 1 ] ;

         while( (c=getc(in)) != EOF ) {
             *finish = c ;
             INCR( finish ) ;

             if( start == finish )
                 INCR( start ) ;
             if( !lines || c == NL )
                 count++ ;

             if( count > goal ) {
                 count = goal ;
                 if( lines )
                     while( *start != NL )
                         INCR( start ) ;
                 INCR( start ) ;
             }

         } /* end while */

         while( start != finish ) {
             putc( *start, stdout ) ;
             INCR( start ) ;
         }

     } /* end else */

 } /* end tail */



 TAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\TAN.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/



 #include "math.h"
 #include "errno.h"

 extern int errno;

 static double tansub();

 double cotan(x)
 double x;
 {
         double y;

         y = fabs(x);
         if (y < 1.91e-152) {
                 errno = ERANGE;
                 if (x < 0.0)
                         return -HUGE;
                 else
                         return HUGE;
         }
         return tansub(x,y,2);
 }

 double tan(x)
 double x;
 {
         return tansub(x, fabs(x), 0);
 }

 #define P1 -0.13338350006421960681e+0
 #define P2 +0.34248878235890589960e-2
 #define P3 -0.17861707342254426711e-4
 #define Q0 +1.0
 #define Q1 -0.46671683339755294240e+0
 #define Q2 +0.25663832289440112864e-1
 #define Q3 -0.31181531907010027307e-3
 #define Q4 +0.49819433993786512270e-6

 #define P(f,g) (((P3*g P2)*g P1)*g*f + f)
 #define Q(g) ((((Q4*g Q3)*g Q2)*g Q1)*g Q0)

 #define YMAX 6.74652e09

 static double tansub(x, y, flag)
 double x,y;
 {
         double f, g, xn;
         double xnum, xden;

         if (y > YMAX) {
                 errno = ERANGE;
                 return 0.0;
         }
         if (modf(x*0.63661977236758134308, &xn) >= 0.5)
                 xn += (x < 0.0) ? -1.0 : 1.0;
         f = (x - xn*1.57080078125) + xn*4.454455103380768678308e-6;
         if (fabs(f) < 2.33e-10) {
                 xnum = f;
                 xden = 1.0;
         } else {
                 g = f*f;
                 xnum = P(f,g);
                 xden = Q(g);
         }
         flag |= ((int)xn & 1);
         switch (flag) {
         case 1:         /* A: tan, xn odd */
                 xnum = -xnum;
         case 2:         /* B: cotan, xn even */
                 return xden/xnum;

         case 3:         /* C: cotan, xn odd */
                 xnum = -xnum;
         case 0:         /* D: tan, xn even */
                 return xnum/xden;
         }
         return 0.0;
 }



 TAN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\TAN.C

 /* 1.1  07-08-85 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1985
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 150-173.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 C1        1.57080078125                        /* C1 - C2 = PIover2        */
 #define C2        4.454455103380768678308e-6

 #define P0         1.0
 #define P1         0.13338350006421960681e+0
 #define P2         0.34248878235890589960e-2
 #define P3         0.17861707342254426711e-4
 #define P(g)        (((-P3*g+P2)*g-P1)*g)

 #define Q0         1.0
 #define Q1         0.46671683339755294240e+0
 #define Q2         0.25663832289440112864e-1
 #define Q3         0.31181531907010027307e-3
 #define Q4         0.49819433993786512270e-6
 #define Q(g)        (((((Q4*g-Q3)*g+Q2)*g-Q1)*g+0.5)+0.5)

 LOCAL double tancot();

 /*\p*********************************************************************/
         double
 tan(x)                        /* return trigonometric tangent of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         return tancot(x, ABS(x), 0);
 }

 /************************************************************************/
         double
 cotan(x)                /* returns trigonometric cotangent of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double y;

         y = ABS(x);
         if (y < SYMLEAST)
         {        errno = ERANGE;
                 if (x < 0.0)
                         return -INFINITY;
                 else
                         return INFINITY;
         }
         return tancot(x, y, 1);
 }

 /*\p*********************************************************************/
         LOCAL double
 tancot(x, y, flag)                /* process both tan and cot functions

 /*----------------------------------------------------------------------*/
 double x,y;
 BOOL flag;
 {
         double f, g, x1, x2, xn;
         double xnum, xden;

         if (y > MAXANGLE)
         {        errno = ERANGE;
                 return 0.0;
         }
         xn = round(TWOoverPI * x);
         x1 = fint(x);
         f = ((x1 - xn * C1) + (x - x1)) + xn * C2;
         if (ABS(f) < FADEOUT)
         {        xnum = f;
                 xden = 1.0;
         }
         else
         {        g = f * f;
                 xnum = P(g) * f + f;
                 xden = Q(g);
         }
         if ((int) xn & 1)
         {        flag = !flag;        /* invert tan-cotan logic        */
                 xnum = -xnum;        /* Cases A and C, xn odd        */
         }
         if (flag)
                 return (xden / xnum);        /* inverted function        */
         else
                 return (xnum / xden);        /* normal function        */
 }


 TANH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC2\TANH.C

 /* 1.0  04-27-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *        Programmmed using the algorithms given in:
  *
  *        Coty, William J., Jr., and Waite, William, SOFTWARE MANUAL FOR
  *        THE ELEMENTARY FUNCTIONS, Prentice-Hall Series in Computational
  *        Mathematics, Prentice-Hall, Inc., Inglewood Cliffs, NJ, 1980,
  *        pp. 239-255.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"
 #include "mathtyp.h"
 #include "mathcons.h"

 /*----------------------------------------------------------------------*/

 #define LN3ov2        0.54930614433405484570

 #define P0         -0.16134119023996228053e+4
 #define P1         -0.99225929672236083313e+2
 #define P2         -0.96437492777225469787e+0
 #define gP(g)         (((P2*g P1)*g P0)*g)

 #define Q0         +0.48402357071988688686e+4
 #define Q1         +0.22337720718962312926e+4
 #define Q2         +0.11274474380534949335e+3
 #define Q3        +1.0
 #define Q(g)         (((g Q2)*g Q1)*g Q0)

 /*\p*********************************************************************/
         double
 tanh(x)                        /* return hyperbolic tangent of x

 /*----------------------------------------------------------------------*/
 double x;
 {
         double f,g,r;

         if ((f = ABS(x)) > TANHXBIG)
                 r = 1.0;
         else if (f > LN3ov2)
                 r = ldexp(0.5 - 1.0 / (exp(ldexp(f, 1)) + 1.0), 1);
         else if (f < FADEOUT)
                 r = f;
         else
         {        g = f * f;
                 r = f + f*
                         (gP(g)
                         /Q(g));
         }
         return (x < 0.0 ? -r : r);
 }


 TANH.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\TANH.C


 /***********************************************************
  *               The TULSA IBM C BOARD                     *
  *                   918-664-8737                          *
  *             300/1200 XMODEM, 24 Hours                   *
  **********************************************************/

 #include "math.h"

 #define P0 -0.16134119023996228053e+4
 #define P1 -0.99225929672236083313e+2
 #define P2 -0.96437492777225469787e+0
 #define Q0 +0.48402357071988688686e+4
 #define Q1 +0.22337720718962312926e+4
 #define Q2 +0.11274474380534949335e+3

 #define gP(g) (((P2*g P1)*g P0)*g)
 #define Q(g) (((g Q2)*g Q1)*g Q0)

 double tanh(x)
 double x;
 {
         double f,g,r;

         f = fabs(x);
         if (f > 25.3)
                 r = 1.0;
         else if (f > 0.54930614433405484570) {
                 r = 0.5 - 1.0/(exp(f+f)+1.0);
                 r += r;
         } else if (f < 2.3e-10)
                 r = f;
         else {
                 g = f*f;
                 r = f + f*
                         (gP(g)
                         /Q(g));
         }
         if (x < 0.0)
                 r = -r;
         return r;
 }



 TBL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\SDB\TBL.C

 /* SDB - table output routines */

 #include "stdio.h"
 #include "sdbio.h"

 static char buffer[TABLEMAX+1];
 int bndx;

 /* db_thead - print a table header */
 db_thead(fp,slptr)
   FILE *fp; struct sel *slptr;
 {
     struct sattr *saptr;
     int twidth,fwidth,i;
     char *aname;

     /* compute the table width */
     twidth = 1;
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
         twidth += saptr->sa_attr->at_size + 3;

     /* print the top line of the table */
     bstart();
     for (i = 0; i < twidth; i++)
         binsert('-');
     bprint(fp);

     /* print the label line of the table */
     bstart();
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
         fwidth = saptr->sa_attr->at_size;
         binsert('|'); binsert(' ');
         if ((aname = saptr->sa_name) == NULL)
             aname = saptr->sa_aname;
         for (i = 0; i < fwidth; i++)
             if (*aname != 0)
                 binsert(*aname++);
             else
                 binsert(' ');
         binsert(' ');
     }
     binsert('|');
     bprint(fp);

     /* print the line under the labels */
     bstart();
     for (i = 0; i < twidth; i++)
         binsert('-');
     bprint(fp);
 }

 /* db_tfoot - print a table foot */
 db_tfoot(fp,slptr)
   FILE *fp; struct sel *slptr;
 {
     struct sattr *saptr;
     int twidth,i;

     /* compute the table width */
     twidth = 1;
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
         twidth += saptr->sa_attr->at_size + 3;

     /* print the line at the foot of the table */
     bstart();
     for (i = 0; i < twidth; i++)
         binsert('-');
     bprint(fp);
 }

 /* db_tentry - print a table entry */
 db_tentry(fp,slptr)
   FILE *fp; struct sel *slptr;
 {
     struct sattr *saptr;
     int fwidth,i;

     /* print a table entry */
     bstart();
     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
         fwidth = saptr->sa_attr->at_size;
         binsert('|'); binsert(' ');
         for (i = 0; i < fwidth; i++)
             if (saptr->sa_aptr[i] != 0)
                 binsert(saptr->sa_aptr[i]);
             else
                 binsert(' ');
         binsert(' ');
     }
     binsert('|');
     bprint(fp);
 }

 /* bstart - start building a line */
 static bstart()
 {
     bndx = 0;
 }

 /* binsert - insert a character into the buffer */
 static binsert(ch)
   int ch;
 {
     if (bndx < TABLEMAX)
         buffer[bndx++] = ch;
 }

 /* bprint - print the current line */
 static bprint(fp)
   FILE *fp;
 {
     buffer[bndx] = EOS;
     fprintf(fp,"%s\n",buffer);
 }



 TC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\TC.C

 /*
 **                TEXT COMPARE UTILITY
 **
 **   Copyright 1987, S.E. Margison
 **
 **   This short utility compares two text files and shows
 **   any line differences.
 **
 **   As distributed, this program requires (for compilation):
 **     "Steve's Datalight Library" version 1.10 or later
 **   which may be obtained without registration from many Bulletin
 **   Board Systems including:
 **      Compuserve IBMSW
 **      Cul-De-Sac (Holliston, MA.)
 **      HAL-PC BBS (Houston, TX.)
 **   and software library houses including:
 **      Public (Software) Library (Houston, TX.)
 **
 **   or by registration:
 **      $10 for Docs, Small Model Library
 **      $25 for Docs, S, D, L, P libraries, and complete library source
 **              in C and Assembler
 **     Steven E. Margison
 **     124 Sixth Street
 **     Downers Grove, IL, 60515
 **
 **
 */

 #include <stdio.h>
 #include <smdefs.h>

 main(argc, argv)
 int argc;
 char *argv[];
 {
    FILE *fp1, *fp2;
    char buf1[MAXLINE], buf2[MAXLINE];
    int lc, end1, end2;
    lc = 0;
    end1 = end2 = NO;

    if(argc isnot 3) error("usage: TC file1 file2");

    if((fp1 = fopen(argv[1], "r")) is NULL) cant(argv[1]);

    if((fp2 = fopen(argv[2], "r")) is NULL) {
       fclose(fp1);
       cant(argv[1]);
       }

    for(;;) {
       ++lc;
       if(fgets(buf1, MAXLINE, fp1) is NULL) end1 = YES;
       if(fgets(buf2, MAXLINE, fp2) is NULL) end2 = YES;
       if((end1 is YES) or (end2 is YES)) break;

       if(strcmp(buf1, buf2)) {
          printf("Line %d in %s\n", lc, argv[1]);
          printf("%s", buf1);
          printf("Line %d in %s\n", lc, argv[2]);
          printf("%s", buf2);
          }
       }
    if((end1 is YES) and (end2 is NO))
       printf("EOF on %s occured first\n", argv[1]);
    if((end2 is YES) and (end1 is NO))
       printf("EOF on %s occured first\n", argv[2]);
    fclose(fp1);
    fclose(fp2);
    }



 TCAP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\TCAP.C

 /*        tcap:        Unix V5, V7 and BS4.2 Termcap video driver
                 for MicroEMACS
 */

        termdef        1                        /* don't define "term" externa

 #include <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if TERMCAP

 #define        MARGIN        8
 #define        SCRSIZ        64
        NPAUSE        10                        /* # times thru update to paus
 #define BEL     0x07
 #define ESC     0x1B

 extern int      ttopen();
 extern int      ttgetc();
 extern int      ttputc();
 extern int        tgetnum();
 extern int      ttflush();
 extern int      ttclose();
 extern int        tcapkopen();
 extern int        tcapkclose();
 extern int      tcapmove();
 extern int      tcapeeol();
 extern int      tcapeeop();
 extern int      tcapbeep();
 extern int        tcaprev();
 extern int        tcapcres();
 extern int      tcapopen();
 extern int      tput();
 extern char     *tgoto();
 #if        COLOR
 extern        int        tcapfcol();
 extern        int        tcapbcol();
 #endif

 #define TCAPSLEN 315
 char tcapbuf[TCAPSLEN];
 char *UP, PC, *CM, *CE, *CL, *SO, *SE;

 TERM term = {
         NULL,        /* these four values are set dynamically at open time */
         NULL,
         NULL,
         NULL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         tcapopen,
         ttclose,
         tcapkopen,
         tcapkclose,
         ttgetc,
         ttputc,
         ttflush,
         tcapmove,
         tcapeeol,
         tcapeeop,
         tcapbeep,
         tcaprev,
         tcapcres
 #if        COLOR
         , tcapfcol,
         tcapbcol
 #endif
 };

 tcapopen()

 {
         char *getenv();
         char *t, *p, *tgetstr();
         char tcbuf[1024];
         char *tv_stype;
         char err_str[72];

         if ((tv_stype = getenv("TERM")) == NULL)
         {
                 puts("Environment variable TERM not defined!");
                 exit(1);
         }

         if ((tgetent(tcbuf, tv_stype)) != 1)
         {
                 sprintf(err_str, "Unknown terminal type %s!", tv_stype);
                 puts(err_str);
                 exit(1);
         }


        if ((term.t_nrow=(short)tgetnum("li")-1) == -1){
                puts("termcap entry incomplete (lines)");
                exit(1);
        }
         term.t_mrow =  term.t_nrow;

        if ((term.t_ncol=(short)tgetnum("co")) == -1){
                puts("Termcap entry incomplete (columns)");
                exit(1);
        }
         term.t_mcol = term.t_ncol;

         p = tcapbuf;
         t = tgetstr("pc", &p);
         if(t)
                 PC = *t;

         CL = tgetstr("cl", &p);
         CM = tgetstr("cm", &p);
         CE = tgetstr("ce", &p);
         UP = tgetstr("up", &p);
         SE = tgetstr("se", &p);
         SO = tgetstr("so", &p);
         if (SO != NULL)
                 revexist = TRUE;

         if(CL == NULL || CM == NULL || UP == NULL)
         {
                 puts("Incomplete termcap entry\n");
                 exit(1);
         }

         if (CE == NULL)                /* will we be able to use clear to EOL
                 eolexist = FALSE;

         if (p >= &tcapbuf[TCAPSLEN])
         {
                 puts("Terminal description too big!\n");
                 exit(1);
         }
         ttopen();
 }

 tcapkopen()

 {
         strcpy(sres, "NORMAL");
 }

 tcapkclose()

 {
 }

 tcapmove(row, col)
 register int row, col;
 {
         putpad(tgoto(CM, col, row));
 }

 tcapeeol()
 {
         putpad(CE);
 }

 tcapeeop()
 {
         putpad(CL);
 }

 tcaprev(state)                /* change reverse video status */

 int state;                /* FALSE = normal video, TRUE = reverse video */

 {
         static int revstate = FALSE;
         if (state) {
                 if (SO != NULL)
                         putpad(SO);
         } else
                 if (SE != NULL)
                         putpad(SE);
 }

 tcapcres()        /* change screen resolution */

 {
         return(TRUE);
 }

 spal(dummy)        /* change palette string */

 {
         /*        Does nothing here        */
 }

 #if        COLOR
 tcapfcol()        /* no colors here, ignore this */
 {
 }

 tcapbcol()        /* no colors here, ignore this */
 {
 }
 #endif

 tcapbeep()
 {
         ttputc(BEL);
 }

 putpad(str)
 char    *str;
 {
         tputs(str, 1, ttputc);
 }

 putnpad(str, n)
 char    *str;
 {
         tputs(str, n, ttputc);
 }


 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else

 hello()
 {
 }

 #endif


 TCXLDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\TCXL\TCXLDEMO.C

 /*

         TCXLDEMO.C  - A demonstration program of the TCXL function library.

                         (c) 1987, 1988  by Mike Smedley

         To compile:

             from the command line type:  tcc tcxldemo tcxl.lib
                                               or:
                                          make -ftcxldemo

                                     or:

             from the environment, specify 'TCXLDEMO.PRJ' as the Project Name

 */

 #include <conio.h>
 #include <dos.h>
 #include <process.h>
 #include <stdio.h>
 #include "tcxldef.h"
 #include "tcxlkey.h"
 #include "tcxlvid.h"
 #include "tcxlwin.h"

 void interrupt exit_prog(void);
 void error_exit(void);
 void pulldown_demo(void);

 int row,col,*sbuf1;                                    /*  global variables

 main()
 {
     register int i,j;
     int ch;
     int whandle[10];
     int *sbuf2;
     char *fname="        ";
     char *mi=" ";
     char *lname="              ";
     char *phone="          ";
     char *pressakey="Press a key";
     char *spaces=  "           ";


     videoinit();                    /*  initialize video  */
     sbuf1=ssave();                  /*  save current screen contents  */
     if(!sbuf1) error_exit();
     readcur(&row,&col);             /*  save current cursor position  */
     setcursz(32,0);                 /*  turn off cursor  */
     setvect(0x23,exit_prog);        /*  redirect Ctrl-Break interrupt  */
     setcbrk(ON);                    /*  set Ctrl-Break checking on  */
     for(;;) {

         /*  open up opening screen windows  */

         for(i=0;i<6;i++) {
             whandle[i]=wopen(i,i+10,i+13,i+47,3,LCYAN|_BLUE);
             if(!whandle[i]) error_exit();

             /*  sound tones of increasing pitch  */

             sound_(15000-((i+2)*1500),1);
             sound_(12000-((i+1)*1500),1);
         }

         wprints(0,16,LRED,"TCXL");
         wprints(1,2,LGREEN,"An Extended Library of Functions");
         wprints(2,12,LGREEN,"for Turbo C");
         wprints(4,10,YELLOW,"by Mike Smedley");
         wprints(6,0,LMAGENTA,"(c) 1987, 1988 - All Rights Reserved");
         wprints(8,7,WHITE,"Demonstration Program");
         wprints(10,7,LCYAN|_BLUE,"Press any key to begin");

         /*  change colors of prompt until a key is pressed  */

         i=LBLUE;
         for(;;) {
             gotoxy_(16,22);
             setattr(i|_BLUE,23);
             delay_(2);
             if(kbhit()) {
                 ch=getch();
                 break;
             }
             i++;
             if(i>WHITE) i=LBLUE;
         }
         if(ch==ESC) exit_prog();             /*  see if Esc key was pressed
         wprints(10,7,_BLUE,"                       ");

         /*  scroll the window's text up and out of the window  */

         for(i=0;i<10;i++) {
             wscroll(1,UP);
             delay_(2);
         }

         /*  close all open windows */

         for(i=5;i>=0;i--) {
             wclose();
             delay_(2);
         }


         /*  open demo window 0 and demonstrate text wraparound and
             scrolling from within a window                          */

         whandle[0]=wopen(1,1,11,41,0,LMAGENTA|_RED);
         if(!whandle[0]) error_exit();
         wtextattr(LCYAN|_RED);
         wprintf("\n TCXL's window display functions like"
                 "\n wprintf() & wputs() allow wrap-around"
                 "\n and scrolling from within windows.");
         wprints(7,14,YELLOW|BLINK|_RED,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(7,14,_RED,spaces);
         wgotoxy(8,0);
           for(i=0;i<15;i++) {
             if(kbhit()) {
                 if(getch()==ESC) exit_prog();
                 break;
             }
             for(j=DGREY;j<=WHITE;j++) {
                 wtextattr(j|_RED);
                 wputs("TCXL   ");
                 delay_(1);
             }
         }


         /*  open demo window 1 and demonstrate changing of window attribute

         whandle[1]=wopen(14,35,23,65,2,YELLOW|_BLUE);
         if(!whandle[1]) error_exit();
         wtextattr(LCYAN|_BLUE);
         wputs("\n  The wchgattr() function"
               "\n  allows you to change the"
               "\n  attribute of the active"
               "\n  window.");
         wprints(6,9,YELLOW|BLINK|_BLUE,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(6,9,_BLUE,spaces);
         wchgattr(WHITE|_GREEN);
         delay_(12);
         wchgattr(LMAGENTA|_RED);
         delay_(12);
         wchgattr(LCYAN|_BLUE);
         if(kbhit()) {                               /*  check for keypress  *
             if(getch()==ESC) exit_prog();
         }
         delay_(12);
         wchgattr(YELLOW|_MAGENTA);
         delay_(12);
         wchgattr(WHITE|_LGREY);
         delay_(12);

         /*  open demo window 2 and demonstrate window titles
             and resizing of windows                           */

         whandle[2]=wopen(5,20,19,45,3,LCYAN|_GREEN);
         if(!whandle[2]) error_exit();
         wtextattr(WHITE|_GREEN);
         wputs("\n  The wtitle() function"
               "\n  allows you to give a"
               "\n  window a title.");
         wprints(5,6,YELLOW|BLINK|_GREEN,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(5,6,_GREEN,spaces);
         wtitle("[ My Title ]",TLEFT);
         delay_(18);
         wtitle("[ My Title ]",TRIGHT);
         delay_(18);
         wtitle("[ My Title ]",TCENTER);
         wtextattr(LGREEN|_GREEN);
         wputs("\n\n\n  The wsize() function"
                   "\n  allows you to resize"
                   "\n  the active window.");
         wprints(10,6,YELLOW|BLINK|_GREEN,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(10,6,_GREEN,spaces);
         wsize(19,60);
         delay_(12);;
         wsize(19,75);
         delay_(12);;
         wsize(24,75);
         delay_(12);;
         wsize(24,60);
         delay_(12);;
         wsize(24,45);
         delay_(12);;
         wsize(19,45);
         delay_(12);;


         /*  open demo window 3 and demonstrate multi-field keyboard input  */

         whandle[3]=wopen(12,10,23,50,1,LCYAN|_BLUE);
         if(!whandle[3]) error_exit();
         wtextattr(LMAGENTA|_BLUE);
         wputs("\n    The winpdef() and winpread()"
               "\n    functions allow multi-field"
               "\n    keyboard input.");
         wprints(3,21,YELLOW|BLINK|_BLUE,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(3,21,_BLUE,spaces);
         wprints(5,2,LCYAN|_BLUE,"First name?");
         if(winpdef(5,15,fname,'M',BLACK|_LGREY)) error_exit();
         wprints(5,26,LCYAN|_BLUE,"MI?");
         if(winpdef(5,31,mi,'U',BLACK|_LGREY)) error_exit();
         wprints(7,2,LCYAN|_BLUE,"Last name?");
         if(winpdef(7,15,lname,'M',BLACK|_LGREY)) error_exit();
         wtextattr(LGREEN|_BLUE);
         setcursz(6,7);                          /*  turn cursor on  */
         i=winpread();
         setcursz(32,0);                         /*  turn cursor back off  */
         if(i) exit_prog();                      /*  check for Esc press  */


         /*  open demo window 4 and demonstrate controlled keyboard input  */

         whandle[4]=wopen(8,41,16,78,3,WHITE|_MAGENTA);
         if(!whandle[4]) error_exit();
         wtextattr(LGREEN|_MAGENTA);
         wputs("\n  For complete control of keyboard"
               "\n  input, there is the winputsf()"
               "\n  function.  ");
         wprints(3,13,YELLOW|BLINK|_MAGENTA,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(3,13,_MAGENTA,spaces);
         wtextattr(WHITE|_MAGENTA);
         setcursz(6,7);                                   /*  turn cursor on
         i=winputsf(phone," '\n\n  Phone number?  ' !R-! "
             " !-! '(' !+! ### !-! ') ' !+! ### !-! '-' !+! #### ");
         setcursz(32,0);                            /*  turn cursor back off
         if(i) exit_prog();                      /*  check for Esc press  */

         /*  clear window 4 and demonstrate text line drawing  */

         wclear();
         wsize(22,78);
         wtextattr(LGREEN|_MAGENTA);
         wputs("\n The whline() & wvline() functions"
               "\n are used for drawing 'smart' text"
               "\n lines inside the active window.");
         wprints(5,12,YELLOW|BLINK|_MAGENTA,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(5,12,_MAGENTA,spaces);
         wtextattr(LCYAN|_MAGENTA);
         whline(6,2,23,3);
         delay_(18);
         wvline(5,5,7,3);
         delay_(18);
         whline(10,1,25,3);
         delay_(18);
         wtextattr(LBLUE|_MAGENTA);
         if(kbhit()) {                               /*  check for keypress  *
             if(getch()==ESC) exit_prog();
         }
         wvline(6,25,5,3);
         delay_(18);
         whline(8,5,21,3);
         delay_(18);
         wvline(5,16,6,3);
         delay_(18);
         wtextattr(LGREEN|_MAGENTA);
         whline(7,2,15,3);
         delay_(18);
         whline(5,9,15,3);
         if(waitkeyt(108)==ESC) exit_prog();

         /*  clear window 4 and demonstrate pull-down & bar-selection menus  *

         wclear();
         wtextattr(LGREEN|_MAGENTA);
         wputs("\n  With the wmbardef() & wmbarget()"
               "\n  functions, you can make pull-down"
               "\n  and bar-select menus.");
         wprints(5,12,YELLOW|BLINK|_MAGENTA,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         pulldown_demo();
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(5,12,_MAGENTA,spaces);
         wprints(3,24,YELLOW|_MAGENTA,"Select one:");
         wmbardef(5,3,LCYAN|_MAGENTA,"Add record",'A');
         wmbardef(5,18,LCYAN|_MAGENTA,"Show record",'S');
         wmbardef(7,3,LCYAN|_MAGENTA,"Delete record",'D');
         wmbardef(7,18,LCYAN|_MAGENTA,"Update record",'U');
         wmbardef(9,3,LCYAN|_MAGENTA,"Print record",'P');
         wmbardef(9,18,LCYAN|_MAGENTA,"Quit program",'Q');
         i=wmbarget(LCYAN|_LGREY,'A',NO);
         wprints(3,24,_MAGENTA,spaces);
         if(!i) exit_prog();
         wgotoxy(11,10);
         wtextattr(WHITE|_MAGENTA);
         wprintf("You selected %c!",i);
         delay_(12);

         /*  open demo window 5 and demonstrate screen swapping  */

         whandle[5]=wopen(3,3,12,33,0,YELLOW|_BLACK);
         if(!whandle[5]) error_exit();
         wtextattr(LCYAN|_BLACK);
         wputs("\n  The ssave() and srestore()"
               "\n  functions allow screen"
               "\n  swapping to/from memory.");
         wprints(5,8,LRED|BLINK|_BLACK,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(5,8,_BLACK,spaces);
         sbuf2=ssave();
         if(!sbuf2) error_exit();
         gotoxy_(24,79);
         clrscrn();
         prints(10,27,LMAGENTA,"Press a key to return");
         if(waitkeyt(273)==ESC) exit_prog();
         srestore(sbuf2);


         /*  open demo window 6 and demonstrate activating of windows  */

         whandle[6]=wopen(11,48,21,77,1,LCYAN|_CYAN);
         wtextattr(WHITE|_CYAN);
         wputs("\n TCXL's wactiv() is used to"
               "\n activate a window, making"
               "\n it available for windowing"
               "\n operations.");
         wprints(4,14,YELLOW|BLINK|_CYAN,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(4,14,_CYAN,spaces);
         for(i=0;i<=6;i++) {
             if(kbhit()) {                            /*  check for keypress
                 if(getch()==ESC) exit_prog();
             }
             if(wactiv(whandle[i])) error_exit();
             delay_(15);
         }


         /*  open demo window 7 and demonstrate moving of active window  */

         whandle[7]=wopen(4,2,16,35,2,LGREEN|_BROWN);
         if(!whandle[7]) error_exit();
         wtextattr(WHITE|_BROWN);
         wputs("\n To move the active window,"
               "\n the wmove() function is"
               "\n used.");
         wprints(3,8,YELLOW|BLINK|_BROWN,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(3,8,_BROWN,spaces);
         if(wmove(0,0)) error_exit();
         delay_(12);
         if(wmove(10,4)) error_exit();
         delay_(12);
         if(wmove(6,19)) error_exit();
         delay_(12);
         if(kbhit()) {                               /*  check for keypress  *
             if(getch()==ESC) exit_prog();
         }
         if(wmove(1,13)) error_exit();
         delay_(12);
         if(wmove(2,35)) error_exit();
         delay_(12);
         if(wmove(11,35)) error_exit();
         delay_(12);


         /*  demonstrate making copies of the same window  */

         wtextattr(LRED|_BROWN);
         wputs("\n\n The wcopy() function will"
                 "\n create a duplicate of the"
                 "\n active window.");
         wprints(7,17,YELLOW|BLINK|_BROWN,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(7,17,_BROWN,spaces);
         whandle[8]=wcopy(0,0);
         if(!whandle[8]) error_exit();
         delay_(12);
         whandle[9]=wcopy(1,37);
         if(!whandle[9]) error_exit();
         if(kbhit()) {                               /*  check for keypress  *
             if(getch()==ESC) exit_prog();
         }
         delay_(18);
         wclose();                                      /*  close copies  */
         delay_(12);
         wclose();
         delay_(12);


         /*  close all windows except window 0  */

         while(wnopen()>1) {
             if(kbhit()) {
                 if(getch()==ESC) exit_prog();
             }
             wclose();
             delay_(6);
         }


         /*  list other features of TCXL  */

         wclear();
         wputs("  Other features of TCXL include:\n");
         wtextattr(LGREEN|_RED);
         wputs("\n  - EGA 43 & VGA 50 line modes"
               "\n  - expanded memory usage"
               "\n  - screen/window swapping to disk"
               "\n  - advanced string manipulation"
               "\n  - equipment detection"
               "\n  - mouse functions"
               "\n  - printer functions");
         wprints(8,26,YELLOW|BLINK|_RED,pressakey);
         if(waitkeyt(273)==ESC) exit_prog();
         wprints(8,26,_RED,spaces);


         /*  get response from the keyboard, controlling input  */

         wclear();
         if(wmove(7,19)) error_exit();
         wgotoxy(3,11);
         wtextattr(WHITE|_RED);
         wputs("View demo again?  ");
         setcursz(7,1);                           /*  turn cursor on  */
         clearkeys();                             /*  clear keyboard buffer  *
         ch=wgetchf("YyNn");                      /*  get keyboard response  *
         setcursz(32,0);                          /*  turn cursor back off  */
         if(ch==ESC) exit_prog();                 /*  see if Esc was pressed
         wclose();
         if(ch=='Y'||ch=='y') {
         }
         else {
             exit_prog();
         }
     }
 }

 /*  This function is the demonstration of pull-down windows   */

 void pulldown_demo(void)
 {
     char m1,m2;

     if(!wopen(0,0,24,79,2,CYAN)) error_exit();
     wprints(0,0,_BLUE,"                                        "
                       "                                      ");
     wprints(1,0,CYAN,"ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"
                       "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
     wgotoxy(2,0);
     wtextattr(YELLOW);
     wputs("This is a sample editor interface to demonstrate how TCXL's "
           "wmbardef()\n"
           "and wmbarget() functions can be used for pull-down menus.  "
           "Use arrow keys\n"
           "to move selection bar around and use the Esc key to exit the "
           "menu you are\n"
           "currently in.  Any selection from a pull-down menu will return "
           "you to demo.");
     m1='F';                         /* initialize selection bar position  */
     m2=PDMAIN;
     top:
     wmbardef(0,2,YELLOW|_BLUE,"File",'F');      /* define main menu */
     wmbardef(0,15,YELLOW|_BLUE,"Editing",'E');
     wmbardef(0,31,YELLOW|_BLUE,"Defaults",'D');
     wmbardef(0,47,YELLOW|_BLUE,"Help",'H');
     wmbardef(0,59,YELLOW|_BLUE,"Options",'O');
     if(wmbardef(0,73,YELLOW|_BLUE,"Quit",'Q')) error_exit();
     m1=wmbarget(YELLOW|_MAGENTA,m1,m2);
     switch(m1) {          /*  test return value from main (horizontal) menu
         case 'F':                    /* define pull-down menu for option 'F'
             if(!wopen(2,1,11,14,0,LGREY)) error_exit();
             wmbardef(0,0,YELLOW|_BLUE," Load       ",'L');
             wmbardef(1,0,YELLOW|_BLUE," Save       ",'S');
             wmbardef(2,0,YELLOW|_BLUE," Rename     ",'R');
             wmbardef(3,0,YELLOW|_BLUE," New        ",'N');
             wmbardef(4,0,YELLOW|_BLUE," Directory  ",'D');
             wmbardef(5,0,YELLOW|_BLUE," Change dir ",'C');
             wmbardef(6,0,YELLOW|_BLUE," OS Shell   ",'O');
             if(wmbardef(7,0,YELLOW|_BLUE," Quit       ",'Q')) error_exit();
             m2=wmbarget(YELLOW|_MAGENTA,'L',PDMENU);
             wclose();
             if(m2<=PDMENU) goto top;        /* test for Esc or Lt/Rt Arrow

 /*          This is where you would test the
             return value from the pull-down menu        */

             break;
         case 'E':                    /* define pull-down menu for option 'E'
             if(!wopen(2,14,10,28,0,LGREY)) error_exit();
             wmbardef(0,0,YELLOW|_BLUE," Cut         ",'C');
             wmbardef(1,0,YELLOW|_BLUE," Paste       ",'P');
             wmbardef(2,0,YELLOW|_BLUE," cOpy        ",'O');
             wmbardef(3,0,YELLOW|_BLUE," block Begin ",'B');
             wmbardef(4,0,YELLOW|_BLUE," block End   ",'E');
             wmbardef(5,0,YELLOW|_BLUE," Insert line ",'I');
             if(wmbardef(6,0,YELLOW|_BLUE," Delete line ",'D')) error_exit();
             m2=wmbarget(YELLOW|_MAGENTA,'C',PDMENU);
             wclose();
             if(m2<=PDMENU) goto top;        /* test for Esc or Lt/Rt Arrow

 /*          This is where you would test the
             return value from the pull-down menu        */

             break;
         case 'D':                    /* define pull-down menu for option 'D'
             if(!wopen(2,30,11,52,0,LGREY)) error_exit();
             wmbardef(0,0,YELLOW|_BLUE," Left margin       0 ",'L');
             wmbardef(1,0,YELLOW|_BLUE," Right margin     72 ",'R');
             wmbardef(2,0,YELLOW|_BLUE," Tab width         4 ",'T');
             wmbardef(3,0,YELLOW|_BLUE," tab eXpansion   yes ",'X');
             wmbardef(4,0,YELLOW|_BLUE," Insert mode     yes ",'I');
             wmbardef(5,0,YELLOW|_BLUE," iNdent mode     yes ",'N');
             wmbardef(6,0,YELLOW|_BLUE," Word wrap mode   no ",'W');
             if(wmbardef(7,0,YELLOW|_BLUE," Save defaults       ",'S')) {
                 error_exit();
             }
             m2=wmbarget(YELLOW|_MAGENTA,'L',PDMENU);
             wclose();
             if(m2<=PDMENU) goto top;        /* test for Esc or Lt/Rt Arrow

 /*          This is where you would test the
             return value from the pull-down menu        */

             break;
         case 'H':                    /* define pull-down menu for option 'H'
             if(!wopen(2,46,7,65,0,LGREY)) error_exit();
             wmbardef(0,0,YELLOW|_BLUE," help on Help     ",'H');
             wmbardef(1,0,YELLOW|_BLUE," help on Editing  ",'E');
             wmbardef(2,0,YELLOW|_BLUE," help on Defaults ",'D');
             if(wmbardef(3,0,YELLOW|_BLUE," help on Options  ",'O')) {
                 error_exit();
             }
             m2=wmbarget(YELLOW|_MAGENTA,'H',PDMENU);
             wclose();
             if(m2<=PDMENU) goto top;        /* test for Esc or Lt/Rt Arrow

 /*          This is where you would test the
             return value from the pull-down menu        */

             break;
         case 'O':                    /* define pull-down menu for option 'O'
             if(!wopen(2,56,8,77,0,LGREY)) error_exit();
             wmbardef(0,0,YELLOW|_BLUE," screen siZe     43 ",'Z');
             wmbardef(1,0,YELLOW|_BLUE," Backup files   yes ",'B');
             wmbardef(2,0,YELLOW|_BLUE," bOxed display   no ",'O');
             wmbardef(3,0,YELLOW|_BLUE," Load options       ",'L');
             if(wmbardef(4,0,YELLOW|_BLUE," Save options       ",'S')) {
                 error_exit();
             }
             m2=wmbarget(YELLOW|_MAGENTA,'Z',PDMENU);
             wclose();
             if(m2<=PDMENU) goto top;        /* test for Esc or Lt/Rt Arrow

 /*          This is where you would test the
             return value from the pull-down menu        */

             break;
         case 'Q':                    /* define pull-down menu for option 'Q'
             if(!wopen(2,60,7,78,0,LGREY)) error_exit();
             wcclear(BLUE|_BLUE);
             wprints(0,2,WHITE|_BLUE,"Are you sure?");
             wmbardef(2,0,YELLOW|_BLUE,"       No        ",'N');
             if(wmbardef(3,0,YELLOW|_BLUE,"       Yes       ",'Y')) {
                 error_exit();
             }
             m2=wmbarget(YELLOW|_MAGENTA,'N',PDMENU);
             wclose();
             if(m2<=PDMENU) goto top;        /* test for Esc or Lt/Rt Arrow

 /*          This is where you would test the
             return value from the pull-down menu        */

             break;
         default:
     }
     wclose();
 }


 /*  if the Esc key or Ctrl-Break is pressed, this function will be called  */

 void interrupt exit_prog(void)
 {
     clearkeys();                       /*  clear keyboard buffer  */
     setcursz(6,7);                     /*  set cursor size back to normal  */
     srestore(sbuf1);                   /*  restore original screen  */
     gotoxy_(row,col);                  /*  restore original cursor position
     exit(0);
 }

 /*  if an error occurs, this function will be called  */

 void error_exit(void)
 {
     setcursz(6,7);                       /*  set cursor size back to normal
     if(_werrno) {
         printf("\nError:  %s      ",werrmsg());    /*  display error message
     }
     else {
         abort();
     }
     exit(1);
 }


 TDISPIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\CASM1\TDISPIO.C


 /*                        Listing 4
                     C to Assembly Interface
       Computer Language, Vol. 2, No. 2 (February, 1985), pp. 49-59
         Modified to remove duplicate leading part, L.P., 5/29/85
    Split into DSPIO.H for #define's and macros and TDSPIO.C, L.P., 5/29/85
 */

 #include "DISPIO.H"

 main()
 {
  int retvals [4] ;
  int index ;
   SET_MODE ;
   hline(0,0,219,80) ;   /* draw box around screen */
   hline(24,0,219,80) ;   /* i.e., manual window using nonwindow characters */
   verline(0,0,219,24) ;
   verline(0,79,219,24) ;
   window(3,3,6,5) ;
   window(10,10,5,6) ;
   window(7,17,10,11) ;
   window(15,40,10,6) ;
   window(5,50,20,16) ;
       /* read cursor position */
   for (index=0; index <4; index++ ) {
     curpos(index,index+1) ;
     dispio(read_position,PAGE,0,0,retvals) ;
     printf("For page PAGE, Row:%u, Col:%u, cursor mode=%o,%o \n",
       retvals[3]>>8, (retvals[3]<<8)>>8, retvals[2]>>8,(retvals[2]<<8)>>8) ;
   }
      /* get current video state */
   dispio(get_state,PAGE,0,0,retvals) ;
   printf("Mode: %u, Columns: %u, Active Page: %u \n",
      (retvals[0]<<8)>>8, retvals[0]>>8, retvals[1]>>8 ) ;
 }
 window(row,col,width,depth) /* start at row,col, i.e. left upper corner */
 char row,col ;
 {
      /* first do 4 corners */
   curpos(row,col) ;
   wrtchar(214) ;
   curpos(row+depth,col) ;
   wrtchar(211) ;
   curpos(row,col+width-1) ;
   wrtchar(183) ;
   curpos(row+depth,col+width-1) ;
   wrtchar(189) ;
      /* then connect corners with horizontal and vertical lines */
   hline(row,col+1,196,width-2) ;
   hline(row+depth,col+1,196,width-2) ;
   verline(row+1,col,186,depth-1) ;
   verline(row+1,col+width-1,186,depth-1) ;
 }
 verline(row,col,ch,len)
 char row, col, ch, len ;
 {
   char cnt ;
      for (cnt=len; cnt > 0; cnt--) {
         curpos(row++,col) ;
         wrtchar(ch) ;
      }
 }


 TDSPIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\CASM1\TDSPIO.C


 /*                        Listing 2
                     C to Assembly Interface
       Computer Language, Vol. 2, No. 2 (February, 1985), pp. 49-59
         Modified to remove duplicate leading part, L.P., 5/29/85
    Split into DSPIO.H for #define's and macros and TDSPIO.C, L.P., 5/29/85
 */

 #include "DSPIO.H"

 main()
 {
  int retvals [4] ;
  int index ;
   SET_MODE ;
   hline(0,0,219,80) ;   /* draw box around screen */
   hline(24,0,219,80) ;   /* i.e., manual window using nonwindow characters */
   verline(0,0,219,24) ;
   verline(0,79,219,24) ;
   window(3,3,6,5) ;
   window(10,10,5,6) ;
   window(7,17,10,11) ;
   window(15,40,10,6) ;
   window(5,50,20,16) ;
       /* read cursor position */
   for (index=0; index <4; index++ ) {
     curpos(index,index+1) ;
     dspio(read_position,PAGE,0,0,retvals) ;
     printf("For page PAGE, Row:%u, Col:%u, cursor mode=%o,%o \n",
       retvals[3]>>8, (retvals[3]<<8)>>8, retvals[2]>>8,(retvals[2]<<8)>>8) ;
   }
      /* get current video state */
   dspio(get_state,PAGE,0,0,retvals) ;
   printf("Mode: %u, Columns: %u, Active Page: %u \n",
      (retvals[0]<<8)>>8, retvals[0]>>8, retvals[1]>>8 ) ;
 }
 window(row,col,width,depth) /* start at row,col, i.e. left upper corner */
 char row,col ;
 {
      /* first do 4 corners */
   curpos(row,col) ;
   wrtchar(214) ;
   curpos(row+depth,col) ;
   wrtchar(211) ;
   curpos(row,col+width-1) ;
   wrtchar(183) ;
   curpos(row+depth,col+width-1) ;
   wrtchar(189) ;
      /* then connect corners with horizontal and vertical lines */
   hline(row,col+1,196,width-2) ;
   hline(row+depth,col+1,196,width-2) ;
   verline(row+1,col,186,depth-1) ;
   verline(row+1,col+width-1,186,depth-1) ;
 }
 verline(row,col,ch,len)
 char row, col, ch, len ;
 {
   char cnt ;
      for (cnt=len; cnt > 0; cnt--) {
         curpos(row++,col) ;
         wrtchar(ch) ;
      }
 }


 TEAM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\TEAM.C

 /****************************************************************/
 /* TEAM.C - From page 297 of the book "Microsoft C Program-     */
 /* ming for the IBM by Robert Lafore. This is a continuation of */
 /* a simple database program developed from page 292 to         */
 /* the end of the chapter (9).                                  */
 /****************************************************************/

 struct personnel {
    char name [30];
    int agnumb;
 };

 struct team {
    struct personnel chief;      /*structure within structure*/
    struct personnel indian;
 };

 struct team team1 = {                     /*declares and initializes*/
    { "Harrison Tweedbury", 102 },         /*struct variable team1   */
    { "James Bond", 007         }
 };

 main()
 {

    printf("\nChief:\n");
    printf("   Name: %s\n", team1.chief.name);
    printf("   Agent number: %03d\n", team1.chief.agnumb);
    printf("\n\nIndian:\n");
    printf("   Name: %s\n", team1.indian.name);
    printf("   Agent number: %03d\n", team1.indian.agnumb);
 }





 TEE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\TEE.C

 /*
         HEADER:                CUG236;
         TITLE:                Portable TEE;
         DATE:                05/23/87;
         DESCRIPTION:        "Copies stdin to the specified file without chang
                         stdout.";
         KEYWORDS:        Software tools, Text filters,tee, pipes;
         FILENAME:        TEE.C;
         WARNINGS:        "The author claims copyrights and authorizes
                         non-commercial use only.";
         AUTHORS:        Michael M. Yokoyama;
         COMPILERS:        vanilla;
 */

 #include <stdio.h>

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * #define if you are running AZTEC C:
  */

 /*
 #define putc(c,f)        aputc(c,f)
 */

 #ifndef TRUE
 #define TRUE  1
 #endif

 #ifndef FALSE
 #define FALSE 0
 #endif

 int main(argc, argv)
 int argc;
 char *argv[];
 {
     int cin, correct;
     FILE *fout;

     correct = FALSE;
     if (argc == 2) {
         if ((fout = fopen(argv[1], "w")) == NULL) {
             fprintf(stderr,"TEE:  cannot create %s\n", argv[1]);
             return !0;
         }
         correct = TRUE;
     }
     else fprintf(stderr,"TEE Usage:  tee out_file\n");

     while ((cin = getchar()) != EOF) {
         putchar(cin);
         if (correct) putc(cin, fout);
     }
     if (correct) fclose(fout);
     return !correct;
 }


 TEMPCONV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\TEMPCONV.C

                                        /* Chapter 3 - Program 8 */
 /****************************************************************/
 /*                                                              */
 /*     This is a temperature conversion program written in      */
 /*      the C programming language. This program generates      */
 /*      and displays a table of farenheit and centigrade        */
 /*      temperatures, and lists the freezing and boiling        */
 /*      of water.                                               */
 /*                                                              */
 /****************************************************************/

 main()
 {
 int count;        /* a loop control variable               */
 int farenheit;    /* the temperature in farenheit degrees  */
 int centigrade;   /* the temperature in centigrade degrees */

    printf("Centigrade to Farenheit temperature table\n\n");

    for(count = -2;count <= 12;count = count + 1){
       centigrade = 10 * count;
       farenheit = 32 + (centigrade * 9)/5;
       printf("  C =%4d   F =%4d  ",centigrade,farenheit);
       if (centigrade == 0)
          printf(" Freezing point of water");
       if (centigrade == 100)
          printf(" Boiling point of water");
       printf("\n");
    } /* end of for loop */
 }


 TEMPL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TEMPL\TEMPL.C


 /********************************************************************

     TEMPLATE GENERATOR for custom keyboard templates.  Helps learning
         curve for common functions.

 */



 #include <stdio.h>
 #include <dos.h>
 #include <conio.h>
 #include <ctype.h>
 #include <graphics.h>
 #include <string.h>
 #include <stdlib.h>
 #include <mem.h>

 #define TRUE      1
 #define FALSE     0
 #define NUM_LINES 4
 #define NUM_KEYS  12
 #define NUM_CHARS 11
 #define DC2       0x12
 #define SI        0x0f
 #define ESC                  0x1b

 void fprnt(char *text, int auto_lf);
 char put_out(char character);
 void stretch( char *src, char *dst);

 char vert_spacing[] = {ESC,'A',0x8,0};

 char title[80];

 struct {                        /* structure for the top half lines */
     char            s1[2];
     char            esc;
     char            mode;
     int             len;
     unsigned char   v1[90];
     unsigned char   v2[90];
     unsigned char   v3[90];
     unsigned char   v4[90];
     unsigned char   v5[130];
     unsigned char   v6[90];
     unsigned char   v7[90];
     unsigned char   v8[50];
 } top = {' ',' ',ESC,'L',720};

 struct {                        /* stucture for the bottom half lines */
     char            s1[2];
     char            esc;
     char            mode;
     int             len;
     unsigned char   v1[8];
     unsigned char   v2[90];
     unsigned char   v3[90];
     unsigned char   v4[130];
     unsigned char   v5[90];
     unsigned char   v6[90];
     unsigned char   v7[90];
     unsigned char   v8[90];
     unsigned char   v9[40];
     unsigned char   v10[2];
 } bottom = {' ',' ',ESC,'L',720};

 char func[NUM_LINES][NUM_KEYS][NUM_CHARS+2];    /* array to hold function key
 char *fptr;
 char buffer[128];
 char t0[200];
 char t1[200];
 char t2[200];
 char t3[200];

 int f, l, j, flag;
 char c_cnt[3] = {0,0,0};
 char f_cnt[12] = {0,0,0, 0,0,0, 0,0,0, 0,0,0};

 char col[3][15][40];
 char lines[15][120];

 int len, col_line;
 char fname[40], mode, mode_num, ans;
 char buffer[128];
 FILE *fs;


 void main()
 {
     register         int i;
     int                 pr_flag, ok_flag = TRUE, tlen;

         fptr = &func[0][0][0];      /* fill function array with spaces */
     for(i = 0; i < sizeof(func); i++) *fptr++ = ' ';

         fptr = &col[0][0][0];
         for(i = 0; i < sizeof(col); i++) *fptr++ = ' ';

         while(ok_flag) {
                 printf("\n\nDo you want the input from the KEYBOARD or a FILE
                 printf("\nNote: keyboard input onlys allows function key data
                 ans = tolower(getch());
                 if(ans == 'f' || ans == 'k')
                         ok_flag = FALSE;
         }

         if(ans == 'f') {

             printf("\n");
                 ok_flag = TRUE;
             while(ok_flag) {
                 printf("Enter filename: ");
                 gets(fname);
                    if((fs = fopen(fname, "r")) != NULL)
                     ok_flag = 0;
             }

             mode = 0;
             while((fgets(buffer, 128, fs)) != NULL) {
                 if(buffer[0] == ';') continue;
                 if(buffer[0] == '*') continue;
                 if(buffer[0] == '\n') continue;

                 if(buffer[0] == '.') {
                     mode = tolower(buffer[1]);
                     if(mode == 'f' || mode == 'c')
                         mode_num = atoi(&buffer[2]) - 1;
                     continue;
                 }
                 len = strlen(buffer) - 1;             /* eleminate the LF */
                 if(!(mode == 0 || mode == 'c' || mode == 'f' || mode == 't'))
                     printf("\n******* ERROR in input file (mode) *******");
                     continue;
                 }

                 if(mode == 't') {
                     if(len > 50) {
                         printf("\n******* ERROR in input file (title length)
                     }
                                 tlen = min(len,50);
                     strncpy(title, buffer, tlen);
                     mode = 0;
                     continue;
                 }
                 if(mode == 'c') {
                     if(mode_num > 3) {
                         printf("\n******* ERROR in input file (column > 3) **
                         continue;
                     }
                     if(c_cnt[0] > 15 || c_cnt[1] > 15 || c_cnt[2] > 15) {
                         printf("\n******* ERROR in input file (column line co
                         continue;
                     }
                     if(len > 35) {
                         printf("\n******* ERROR in input file (column text le
                     }
                     if(buffer[0] == '/' && buffer[1] == '/')
                         c_cnt[mode_num]++;
                     else
                         strncpy(&col[mode_num][c_cnt[mode_num]++][0], buffer,
                     continue;
                 }
                 if(mode == 'f') {
                     if(mode_num > 11) {
                         printf("\n******* ERROR in input file (function key n
                         continue;
                     }
                     for(i = 0; i < 12; i++) {
                         if(f_cnt[i] > 4 ) {
                             printf("\n******* ERROR in input file (line count
                             continue;
                         }
                     }
                     if(len > 11) {
                         printf("\n******* ERROR in input file (function key t
                     }
                     if(buffer[0] == '/' && buffer[1] == '/')
                         f_cnt[mode_num]++;
                     else
                         strncpy(&func[f_cnt[mode_num]++][mode_num][0], buffer
                     continue;
                 }

             }
             col_line = max(c_cnt[0], max(c_cnt[1], c_cnt[2]));

         } else {
                 ok_flag = TRUE;
             printf("\n");               /* request the optional title */
             while(ok_flag) {
                 printf("\nEnter title (50 chars max): ");
                 gets(title);
                 tlen = strlen(title);
                 if(tlen <= 50) ok_flag = 0;
                 else printf("%c%c", 0x07, 0x07);
             }

             for(f = 0; f < NUM_KEYS;) {     /* get the data for all 12 functi
                 printf("\n\n");
                 for(l = 0; l < NUM_LINES;) {
                     for(i = 0; i < NUM_CHARS; i++)
                         func[l][f][i] = ' ';
                     flag = TRUE;
                     printf("\Enter F%d line %d ( 11 chars max): ", f+1, l+1);
                     gets(buffer);
                     if(buffer[0] == '\0') break;
                     if(strlen(buffer) > NUM_CHARS) {
                         printf("..... Too many characters .....\n");
                         flag = FALSE;
                         break;
                     }
                     strncpy(&func[l][f][0], buffer, strlen(buffer));
                     l++;
                 }
                 if(flag) {
                     printf("\nIs this correct? ");
                     if(tolower(getche()) == 'y') f++;
                 }
             }
     }

     printf("\n\nPrepare printer, hit any key ");
     getch();

     for(i = 0; i < 29; i++) putch(0x08);
     printf(".......... Printing ..........");

     for(i = 0; i < 2; i++) put_out('\n');   /* skip some top of form      */


         for(i = 0; i < 15; i++)
                 for(j = 0; j < 3; j++)
                         movmem(&col[j][i][0], &lines[i][40*j], 40);

         put_out(ESC); put_out('E');                /* emphasized */
         put_out(ESC); put_out('M');                /* pica       */
         put_out(ESC); put_out('2');     /* 6 LPI      */

         for(i = 0; i < col_line; i++) {
                 for(j = 0; j < 11; j++) put_out(' ');
                 for(j = 0; j < 63; j++) put_out(lines[i][j]);
                 put_out('\r'); put_out('\n');
         }

         put_out(ESC); put_out('P');                        /* go to 10 CPI */
         put_out(DC2);

     for(i = 0; i < 1; i++) put_out('\n');   /* skip some space      */
     put_out('\r');

     stretch(&func[0][0][0], t0);            /* fill in the extra spaces   */
     stretch(&func[1][0][0], t1);            /*  for the gaps at F4 and F8 */
     stretch(&func[2][0][0], t2);
     stretch(&func[3][0][0], t3);


     put_out(ESC); put_out('E');            /* emphasized characters      */

     fputs(vert_spacing, stdprn);            /* set line spacing           */

     for(i = 0; i < 720; i++) top.v1[i] = 0xc0;
     top.v1[0] = top.v1[1] = 0xff;
     fprnt(&top.s1[0], 1);                           /* print upper line   */

     for(i = 2; i < 720; i++) top.v1[i] = 0;
     fprnt(&top.s1[0], 1);                           /* print blank line   */

     top.v2[0] = top.v2[1] = top.v3[0] = top.v3[1] =
     top.v4[0] = top.v4[1] = top.v5[0] = top.v5[1] =
     top.v6[0] = top.v6[1] = top.v7[0] = top.v7[1] =
     top.v8[0] = top.v8[1] = 0xff;

     fprnt(&top.s1[0], 0);                           /* vertical serriations

     put_out(SI);                                    /* print full top line */
     for(i = 0; i < 17; i++) put_out(' ');           /* function key text   */
     for(i = 0; i < 89; i++) put_out(t0[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     fprnt(&top.s1[0], 0);                           /* vertical serriations

     put_out(SI);
     for(i = 0; i < 17; i++) put_out(' ');
     for(i = 0; i < 89; i++) put_out(t1[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     fprnt(&top.s1[0], 0);                           /* vertical serriations

     put_out(SI);
     for(i = 0; i < 17; i++) put_out(' ');
     for(i = 0; i < 89; i++) put_out(t2[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     fprnt(&top.s1[0], 0);                           /* vertical serriations

     put_out(SI);
     for(i = 0; i < 17; i++) put_out(' ');
     for(i = 0; i < 89; i++) put_out(t3[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     for(i = 92; i < 720; i++) top.v1[i] = 0xc0;
     fprnt(&top.s1[0], 1);                           /* top horizontal inside


     for(i = 92; i < 720; i++) top.v1[i] = 0;

     for(i = 0; i < 5; i++) fprnt(&top.s1[0], 1);    /* left side  --- 5 times

     for(i = 92; i < 720; i++) top.v1[i] = 3;
     fprnt(&top.s1[0], 1);                           /* bottom horizontal insi

     for(i = 2; i < 720; i++) top.v1[i] = 0;
     for(i = 0; i < 2; i++) fprnt(&top.s1[0], 1);    /* left edge and blank li
     fprnt(&top.s1[0], 0);

     if(tlen > 0) {
         put_out(0x0e);
         for(i = 0; i < 28 - (tlen/2); i++) put_out(' ');
         for(i = 0; i < (tlen/2) + 3; i++) {
             if(title[i] == '\0') break;
             put_out(title[i]);
         }
     }
     put_out('\r');
     put_out('\n');


     for(i = 0; i < 3; i++) fprnt(&top.s1[0], 1);    /* left edge and blank li

     for(i = 0; i < 720; i++) top.v1[i] = 0xc0;
     fprnt(&top.s1[0], 1);                           /* bottom line  */


     /* print the bottom half   */

     for(i = 0; i < 4; i++) put_out('\n');          /* skip some form */
     put_out('\r');

         put_out(ESC); put_out('M');                /* elite pitch */
         put_out(ESC); put_out('2');        /* 6 LPI */
         for(i = 0; i < col_line; i++) {
                 for(j = 0; j < 3; j++) put_out(' ');
                 for(j = 49; j < 120; j++) put_out(lines[i][j]);
                 put_out('\r'); put_out('\n');
         }

         put_out(ESC); put_out('P');                        /* go to 10 CPI */
     for(i = 0; i < 1; i++) put_out('\n');   /* skip some space      */
     put_out('\r');

     fputs(vert_spacing, stdprn);

     for(i = 0; i < 718; i++) bottom.v1[i] = 0xc0;
     bottom.v10[0] = bottom.v10[1] = 0xff;
     fprnt(&bottom.s1[0], 1);                        /* top line  */

     for(i = 0; i < 718; i++) bottom.v1[i] = 0;
     fprnt(&bottom.s1[0], 1);                        /* blank line  */

     bottom.v2[0] = bottom.v2[1] = bottom.v3[0] = bottom.v3[1] =
     bottom.v4[0] = bottom.v4[1] = bottom.v5[0] = bottom.v5[1] =
     bottom.v6[0] = bottom.v6[1] = bottom.v7[0] = bottom.v7[1] =
     bottom.v8[0] = bottom.v8[1] = 0xff;

     fprnt(&bottom.s1[0], 0);                        /* vertical serriations *

     put_out(SI);
     for(i = 0; i < 5; i++) put_out(' ');
     for(i = 70; i < 186; i++) put_out(t0[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     fprnt(&bottom.s1[0], 0);                        /* vertical serriations *

     put_out(SI);
     for(i = 0; i < 5; i++) put_out(' ');
     for(i = 70; i < 186; i++) put_out(t1[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     fprnt(&bottom.s1[0], 0);                        /* vertical serriations *

     put_out(SI);
     for(i = 0; i < 5; i++) put_out(' ');
     for(i = 70; i < 186; i++) put_out(t2[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     fprnt(&bottom.s1[0], 0);                        /* vertical serriations *

     put_out(SI);
     for(i = 0; i < 5; i++) put_out(' ');
     for(i = 70; i < 186; i++) put_out(t3[i]);
     put_out(DC2);
     put_out('\r');
     put_out('\n');

     for(i = 0; i < 678; i++) bottom.v1[i] = 0xc0;
     bottom.v9[0] = bottom.v9[1] = 0xff;
     fprnt(&bottom.s1[0], 1);                        /* top inside line  */


     for(i = 0; i < 678; i++) bottom.v1[i] = 0;
     for(i = 0; i < 5; i++) fprnt(&bottom.s1[0], 1); /* right side  */

     for(i = 0; i < 678; i++) bottom.v1[i] = 3;
     fprnt(&bottom.s1[0], 1);                        /* bottom inside line  */

     for(i = 0; i < 718; i++) bottom.v1[i] = 0;
     for(i = 0; i < 2; i++) fprnt(&bottom.s1[0], 1); /* right side  */
     fprnt(&bottom.s1[0], 0);


     if(tlen > 0) {
         put_out(0x0e);
         put_out(' ');
         for( i = (tlen/2) -3; title[i] != '\0'; i++)
             put_out(title[i]);
     }
     put_out('\r');
     put_out('\n');


     for(i = 0; i < 3; i++) fprnt(&bottom.s1[0], 1); /* right side  */

     for(i = 0; i < 720; i++) bottom.v1[i] = 0xc0;
     fprnt(&bottom.s1[0], 1);                        /* bottom line  */

     printf("\n\n");

     put_out(0xc);
     fflush(stdprn);

 }

 /* not used - but someday ??? */

 char status(void)
 {
     union REGS regs;

     regs.h.ah = 2;
     regs.x.dx = 0;
     int86(0x17, &regs, &regs);
     return(regs.h.ah & 0x80);
 }

 /* out put to the printer */

 char put_out(char character)
 {
     union REGS regs;

     regs.h.ah = 0;
     regs.h.al = character;
     regs.x.dx = 0;
     int86(0x17, &regs, &regs);
     return(regs.h.ah);
 }

 void fprnt(char *text, int auto_lf) /* print a line with optional CR */
 {
     int i;

     for( i = 0; i < 726; i++)
         put_out(*text++);
     if(auto_lf) {
         put_out('\r');
         put_out('\n');
     } else put_out('\r');
 }

 /* take data from thefunction key array and put it in the Tx array */
 void stretch( char *src, char *dst)
 {
     register int i;

     for(i = 0; i < 4*13; i++)
         *dst++ = *src++;
     for(i = 0; i < 6; i++)      /* 6 extra spaces for F4 */
         *dst++ = ' ';

     for(i = 0; i < 4*13; i++)
         *dst++ = *src++;
     for(i = 0; i < 5; i++)      /* 5 extra spaces for F8 */
         *dst++ = ' ';           /* I think my printer is non-linear or ??? */
     for(i = 0; i < 4*13; i++)
         *dst++ = *src++;
 }



 TERM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\TERM.C

 /*                      Terminal Emulator Program
 */

 SERCONFIG 0x83  /* 1200 baud, 8 bits, 1 stop bit, no parity. */

 SERDRDY 0x100   /* Serial receiver data ready bit mask. */

 #define TRUE 1
 #define FALSE 0

 /*      main()

         Function: Display data coming from COM1 on the screen, and send
         keystrokes from the keyboard out to COM1.

         Algorithm: Loop, waiting for data from either side to appear.
         Use keyChk to see if there's anything from the keyboard; if
         there is, send it using serSend. Use serRecv to check if
         there's anything from the serial port; if there is, display
         it using putTty.
 */

 main()

 {
         int ch; /* Character to transfer. */

         /* Initialize the port. */
         serInit(0,SERCONFIG);

         /* Main loop. */
         while (TRUE) {
                 /* Check for keyboard input. */
                 if (keyChk(&ch)) {
                         /* If yes, clear the character from the queue. */
                         keyRd();
                         /* Check for non-ASCII. */
                         if ((ch & 0xFF) == 0) {
                                 break;
                         };
                         /* Send the character out the serial port. */
                         serSend(0,ch);
                 };
                 /* Anything available from the serial port? */
                 if (serStat(0) & SERDRDY) {
                         /* If so, read it in. */
                         ch = serRecv(0);
                         /* And put it on the screen. */
                         putTty(0,ch,3);
                 };
         };
 }



 TERM2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\TERM2.C

 /*                      Terminal Emulator Program (Version 2)
 */

 SERCONFIG 0x83  /* 1200 baud, 8 bits, 1 stop bit, no parity. */

 SERDRDY 0x100   /* Serial receiver data ready bit mask. */

 #define TRUE 1
 #define FALSE 0

 /*      main()

         Function: Display data coming from COM1 on the screen, and send
         keystrokes from the keyboard out to COM1.

         Algorithm: Loop, waiting for data from either side to appear.
         Use keyChk to see if there's anything from the keyboard; if
         there is, send it using serSend. Use serRecv to check if
         there's anything from the serial port; if there is, display
         it using putTty.
 */

 main()

 {
         int ch; /* Character to transfer. */

         /* Initialize the port. */
         serInit(0,SERCONFIG);

         /* Main loop. */
         while (TRUE) {
                 /* Check for keyboard input. */
                 if (keyChk(&ch)) {
                         /* If yes, clear the character from the queue. */
                         keyRd();
                         /* Check for non-ASCII. */
                         if ((ch & 0xFF) == 0) {
                                 break;
                         };
                         /* Send the character out the serial port. */
                         serSend(0,ch);
                 };
                 /* Anything available from the serial port? */
                 if ((ch = serRecv(0)) != -1)
                         /* If so, display it. */
                         putTty(0,ch,3);
         };

         /* Close the serial port. */
         serClose(0);
 }



 TERMIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\TERMIO.C

 /*
  * The functions in this file negotiate with the operating system for
  * characters, and write characters in a barely buffered fashion on the displ
  * All operating systems.
  */
 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if   MSDOS & TURBO
 #include <conio.h>
 #endif

 #if     AMIGA
 #define NEW 1006L
 #define AMG_MAXBUF      1024L
 static long terminal;
 static char     scrn_tmp[AMG_MAXBUF+1];
 static long     scrn_tmp_p = 0;
 #endif

 #if ST520 & MEGAMAX
 #include <osbind.h>
         int STscancode = 0;
 #endif

 #if     VMS
 #include        <stsdef.h>
 #include        <ssdef.h>
 #include        <descrip.h>
 #include        <iodef.h>
 #include        <ttdef.h>
 #include        <tt2def.h>

 NIBUF   128                     /* Input buffer size            */
 NOBUF   1024                    /* MM says bug buffers win!     */
 EFN     0                       /* Event flag                   */

 char    obuf[NOBUF];                    /* Output buffer                */
 int     nobuf;                  /* # of bytes in above    */
 char    ibuf[NIBUF];                    /* Input buffer          */
 int     nibuf;                  /* # of bytes in above  */
 int     ibufi;                  /* Read index                   */
 int     oldmode[3];                     /* Old TTY mode bits            */
 int     newmode[3];                     /* New TTY mode bits            */
 short   iochan;                  /* TTY I/O channel             */
 #endif

 #if     CPM
 #include        <bdos.h>
 #endif

 #if     MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86)
 union REGS rg;                /* cpu register for use of DOS calls */
 int nxtchar = -1;        /* character held from type ahead    */
 #endif

 #if RAINBOW
 #include "rainbow.h"
 #endif

        USG                        /* System V */
 #include        <signal.h>
 #include        <termio.h>
 #include        <fcntl.h>
 int kbdflgs;                        /* saved keyboard fd flags        */
 int kbdpoll;                        /* in O_NDELAY mode
 int kbdqp;                        /* there is a char in kbdq        */
 char kbdq;                        /* char we've already read        */
 struct        termio        otermio;        /* original terminal characterist
 struct        termio        ntermio;        /* charactoristics to use inside
 #endif

 #if V7 | BSD
 #undef        CTRL
        <sgtty.h>        /* for stty/gtty functions */
 #include        <signal.h>
 struct  sgttyb  ostate;          /* saved tty state */
 struct  sgttyb  nstate;          /* values for editor mode */
 struct tchars        otchars;        /* Saved terminal special character set
 struct tchars        ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
                                 /* A lot of nothing */
 #if BSD
 <sys/ioctl.h>                /* to get at the typeahead */
 extern        int rtfrmshell();        /* return from suspended shell */
 #define        TBUFSIZ        128
 char tobuf[TBUFSIZ];                /* terminal output buffer */
 #endif
 #endif

 /*
  * This function is called once to set up the terminal device streams.
  * On VMS, it translates TT until it finds the terminal, then assigns
  * a channel to it and sets it raw. On CPM it is a no-op.
  */
 ttopen()
 {
 #if     AMIGA
         char oline[NSTRING];
 #if        AZTEC
         extern        Enable_Abort;        /* Turn off ctrl-C interrupt */

         Enable_Abort = 0;        /* for the Manx compiler */
 #endif
         strcpy(oline, "RAW:0/0/640/200/");
         strcat(oline, PROGNAME);
         strcat(oline, " ");
         strcat(oline, VERSION);
         strcat(oline, "/Amiga");
         terminal = Open(oline, NEW);
 #endif
 #if     VMS
         struct  dsc$descriptor  idsc;
         struct  dsc$descriptor  odsc;
         char    oname[40];
         int     iosb[2];
         int     status;

         odsc.dsc$a_pointer = "TT";
         odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
         odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
         odsc.dsc$b_class        = DSC$K_CLASS_S;
         idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
         idsc.dsc$b_class        = DSC$K_CLASS_S;
         do {
                 idsc.dsc$a_pointer = odsc.dsc$a_pointer;
                 idsc.dsc$w_length  = odsc.dsc$w_length;
                 odsc.dsc$a_pointer = &oname[0];
                 odsc.dsc$w_length  = sizeof(oname);
                 status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
                 if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
                         exit(status);
                 if (oname[0] == 0x1B) {
                         odsc.dsc$a_pointer += 4;
                         odsc.dsc$w_length  -= 4;
                 }
         } while (status == SS$_NORMAL);
         status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
         if (status != SS$_NORMAL)
                 exit(status);
         status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                 exit(status);
         newmode[0] = oldmode[0];
         newmode[1] = oldmode[1] | TT$M_NOECHO;
         newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
         newmode[2] = oldmode[2] | TT2$M_PASTHRU;
         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                           newmode, sizeof(newmode), 0, 0, 0, 0);
         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                 exit(status);
         term.t_nrow = (newmode[1]>>24) - 1;
         term.t_ncol = newmode[0]>>16;

 #endif
 #if     CPM
 #endif

 #if     MSDOS & (HP150 == 0) & LATTICE
         /* kill the ctrl-break interupt */
         rg.h.ah = 0x33;                /* control-break check dos call */
         rg.h.al = 1;                /* set the current state */
         rg.h.dl = 0;                /* set it OFF */
         intdos(&rg, &rg);        /* go for it! */
 #endif

 #if        USG
         ioctl(0, TCGETA, &otermio);        /* save old settings */
         ntermio.c_iflag = 0;                /* setup new settings */
         ntermio.c_oflag = 0;
         ntermio.c_cflag = otermio.c_cflag;
         ntermio.c_lflag = 0;
         ntermio.c_line = otermio.c_line;
         ntermio.c_cc[VMIN] = 1;
         ntermio.c_cc[VTIME] = 0;
         ioctl(0, TCSETA, &ntermio);        /* and activate them */
         kbdflgs = fcntl( 0, F_GETFL, 0 );
         kbdpoll = FALSE;
 #endif

 #if     V7 | BSD
         gtty(0, &ostate);                       /* save old state */
         gtty(0, &nstate);                       /* get base of new state */
         nstate.sg_flags |= RAW;
         nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
         stty(0, &nstate);                       /* set mode */
         ioctl(0, TIOCGETC, &otchars);                /* Save old characters *
         ioctl(0, TIOCSETC, &ntchars);                /* Place new character i
 #if        BSD
         /* provide a smaller terminal output buffer so that
            the type ahead detection works better (more often) */
         setbuffer(stdout, &tobuf[0], TBUFSIZ);
         signal(SIGTSTP,SIG_DFL);        /* set signals so that we can */
         signal(SIGCONT,rtfrmshell);        /* suspend & restart emacs */
 #endif
 #endif
         /* on all screens we are not sure of the initial position
            of the cursor                                        */
         ttrow = 999;
         ttcol = 999;
 }

 /*
  * This function gets called just before we go back home to the command
  * interpreter. On VMS it puts the terminal back in a reasonable state.
  * Another no-operation on CPM.
  */
 ttclose()
 {
 #if     AMIGA
 #if        LATTICE
         amg_flush();
         Close(terminal);
 #endif
 #if        AZTEC
         amg_flush();
         Enable_Abort = 1;        /* Fix for Manx */
         Close(terminal);
 #endif
 #endif

 #if     VMS
         int     status;
         int     iosb[1];

         ttflush();
         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                  oldmode, sizeof(oldmode), 0, 0, 0, 0);
         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                 exit(status);
         status = SYS$DASSGN(iochan);
         if (status != SS$_NORMAL)
                 exit(status);
 #endif
 #if     CPM
 #endif
 #if     MSDOS & (HP150 == 0) & LATTICE
         /* restore the ctrl-break interupt */
         rg.h.ah = 0x33;                /* control-break check dos call */
         rg.h.al = 1;                /* set the current state */
         rg.h.dl = 1;                /* set it ON */
         intdos(&rg, &rg);        /* go for it! */
 #endif

 #if        USG
         ioctl(0, TCSETA, &otermio);        /* restore terminal settings */
         fcntl(0, F_SETFL, kbdflgs);
 #endif

 #if     V7 | BSD
         stty(0, &ostate);
         ioctl(0, TIOCSETC, &otchars);        /* Place old character into K */
 #endif
 }

 /*
  * Write a character to the display. On VMS, terminal output is buffered, and
  * we just put the characters in the big array, after checking for overflow.
  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  * MS-DOS (use the very very raw console output routine).
  */
 ttputc(c)
 #if     AMIGA | (ST520 & MEGAMAX)
         char c;
 #endif
 {
 #if     AMIGA
         scrn_tmp[scrn_tmp_p++] = c;
         if(scrn_tmp_p>=AMG_MAXBUF)
                 amg_flush();
 #endif
 #if        ST520 & MEGAMAX
         Bconout(2,c);
 #endif
 #if     VMS
         if (nobuf >= NOBUF)
                 ttflush();
         obuf[nobuf++] = c;
 #endif

 #if     CPM
         bios(BCONOUT, c, 0);
 #endif

 #if     MSDOS & MWC86
         putcnb(c);
 #endif

 #if        MSDOS & (LATTICE | AZTEC) & ~IBMPC
         bdos(6, c, 0);
 #endif

 #if RAINBOW
         Put_Char(c);                    /* fast video */
 #endif


 #if     V7 | USG | BSD
         fputc(c, stdout);
 #endif
 }

 #if        AMIGA
 amg_flush()
 {
         if(scrn_tmp_p)
                 Write(terminal,scrn_tmp,scrn_tmp_p);
         scrn_tmp_p = 0;
 }
 #endif

 /*
  * Flush terminal buffer. Does real work where the terminal output is buffere
  * up. A no-operation on systems where byte at a time terminal I/O is done.
  */
 ttflush()
 {
 #if     AMIGA
         amg_flush();
 #endif
 #if     VMS
         int     status;
         int     iosb[2];

         status = SS$_NORMAL;
         if (nobuf != 0) {
                 status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
                          iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
                 if (status == SS$_NORMAL)
                         status = iosb[0] & 0xFFFF;
                 nobuf = 0;
         }
         return (status);
 #endif

 #if     CPM
 #endif

 #if     MSDOS
 #endif

 #if     V7 | USG | BSD
         fflush(stdout);
 #endif
 }

 /*
  * Read a character from the terminal, performing no editing and doing no ech
  * at all. More complex in VMS that almost anyplace else, which figures. Very
  * simple on CPM, because the system can do exactly what you want.
  */
 ttgetc()
 {
 #if     AMIGA
         char ch;
         amg_flush();
         Read(terminal, &ch, 1L);
         return(255 & (int)ch);
 #endif
 #if        ST520 & MEGAMAX
         long ch;
 /*
  * blink the cursor only if nothing is happening, this keeps the
  * cursor on steadily during movement making it easier to track
  */
         STcurblink(TRUE);  /* the cursor blinks while we wait */
         ch = Bconin(2);
         STcurblink(FALSE); /* the cursor is steady while we work */
         STscancode = (ch >> 16) & 0xff;
                return(255 & (int)ch);
 #endif
 #if     VMS
         int     status;
         int     iosb[2];
         int     term[2];

         while (ibufi >= nibuf) {
                 ibufi = 0;
                 term[0] = 0;
                 term[1] = 0;
                 status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
                          iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
                 if (status != SS$_NORMAL)
                         exit(status);
                 status = iosb[0] & 0xFFFF;
                 if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
                         exit(status);
                 nibuf = (iosb[0]>>16) + (iosb[1]>>16);
                 if (nibuf == 0) {
                         status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
                                  iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
                         if (status != SS$_NORMAL
                         || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
                                 exit(status);
                         nibuf = (iosb[0]>>16) + (iosb[1]>>16);
                 }
         }
         return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
 #endif

 #if     CPM
         return (biosb(BCONIN, 0, 0));
 #endif

 #if RAINBOW
         int Ch;

         while ((Ch = Read_Keyboard()) < 0);

         if ((Ch & Function_Key) == 0)
                 if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
                         Ch &= 0xFF;

         return Ch;
 #endif

 #if     MSDOS & MWC86
         return (getcnb());
 #endif

 #if        MSDOS & (LATTICE | MSC | TURBO | AZTEC)
         int c;                /* character read */

         /* if a char already is ready, return it */
         if (nxtchar >= 0) {
                 c = nxtchar;
                 nxtchar = -1;
                 return(c);
         }

         /* call the dos to get a char */
         rg.h.ah = 7;                /* dos Direct Console Input call */
         intdos(&rg, &rg);
         c = rg.h.al;                /* grab the char */
         return(c & 255);
 #endif

 #if     V7 | BSD
         return(127 & fgetc(stdin));
 #endif

 #if        USG
         if( kbdqp )
                 kbdqp = FALSE;
         else
         {
                 if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
                         return FALSE;
                 kbdpoll = FALSE;
                 while (read(0, &kbdq, 1) != 1)
                         ;
         }
         return ( kbdq & 127 );
 #endif
 }

 #if        TYPEAH & (~ST520 | ~LATTICE)
 /* typahead:        Check to see if any characters are already in the
                 keyboard buffer
 */

 typahead()

 {
 #if        MSDOS & (MSC | TURBO)
         if (kbhit() != 0)
                 return(TRUE);
         else
                 return(FALSE);
 #endif

 #if        MSDOS & (LATTICE | AZTEC | MWC86)
         int c;                /* character read */
         int flags;        /* cpu flags from dos call */

         if (nxtchar >= 0)
                 return(TRUE);

         rg.h.ah = 6;        /* Direct Console I/O call */
         rg.h.dl = 255;        /*         does console input */
 #if        LATTICE | AZTEC
         flags = intdos(&rg, &rg);
 #else
         intcall(&rg, &rg, 0x21);
         flags = rg.x.flags;
 #endif
         c = rg.h.al;        /* grab the character */

         /* no character pending */
         if ((flags & 64) != 0)
                 return(FALSE);

         /* save the character and return true */
         nxtchar = c;
         return(TRUE);
 #endif

 #if        BSD
         int x;        /* holds # of pending chars */

         return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
 #endif

 #if        USG
         if( !kbdqp )
         {
                 if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
                         return(FALSE);
                 kbdqp = (1 == read( 0, &kbdq, 1 ));
         }
         return ( kbdqp );
 #endif
         return(FALSE);
 }
 #endif



 TERMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\TERMP.C

 /*                      Terminal Emulator Program with Printing
 */

 #include "slib.h"

 #define TRUE 1
 #define FALSE 0

 /*      main()

         Function: Display data coming from COM1 on the screen, and send
         keystrokes from the keyboard out to COM1. If F1 is pressed,
         toggle into print-also mode, where each input is also sent to
         the printer port.

         Algorithm: Loop, waiting for data from either side to appear.
         Use keyChk to see if there's anything from the keyboard; if
         there is, send it using serSend. Use serRecv to check if
         there's anything from the serial port; if there is, display
         it using putTty, and if we're in print mode, also print it
         using prtPrint.
 */

 main()

 {
         int ch;         /* Character to transfer. */
         int printOn;    /* TRUE if printing is toggled on. */

         /* Initialize the printer. */
         prtInit(0);
         printOn = FALSE;

         /* Initialize the serial port. */
         serInit(0,B1200+DB8+SB1+PNONE);

         /* Main loop. */
         while (TRUE) {
                 /* Check for keyboard input. */
                 if (keyChk(&ch)) {
                         /* If yes, clear the character from the queue. */
                         keyRd();
                         /* Check for non-ASCII. */
                         if ((ch & 0xFF) == 0) {
                                 /* Check for F1 key. */
                                 if (((ch>>8) & 0xFF) == 59)
                                         /* If F1, toggle print mode. */
                                         printOn = !printOn;
                                 else break;
                         };
                         /* Send the character out the serial port. */
                         serSend(0,ch);
                 };
                 /* Anything available from the serial port? */
                 if (serStat(0) & RCVDRDY) {
                         /* If so, read it in. */
                         ch = serRecv(0);
                         /* And put it on the screen. */
                         putTty(0,ch,3);
                         /* If we're in print mode, print it as well. */
                         if (printOn) prtPrint(0,ch);
                 };
         };
 }



 TEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\BEYONDC\TEST.C

 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 #include <malloc.h>
 #include <memory.h>

 /* Boolean type and values. */
 typedef int     BOOLEAN;
 #define TRUE    1
 #define FALSE   0

 /* Exit values. */
 #define SUCCESS   0
 #define FAILURE   1

 /* Structure for option values. */
 typedef struct options
 {
     int   lngval;
 } OPTIONS;

 /* Default option values. */
 #define DEF_LNGVAL   25

 /* Function declarations. */
 void    cmpfiles (char *, char *, OPTIONS *);
 BOOLEAN readin   (FILE *, char ***, int *);
 void    compare  (char **, int, char **, int, int);

 /* Program name. */
 static char   Progname[] = "test";
 
 main (argc, argv)

 int    argc;
 char   **argv;
 {
     OPTIONS   opt;        /* Structure for option values. */
     char      *thisopt;   /* Current option. */
     char      *thisval;   /* Current option value. */

     /* Move past program name in arg list. */
     argv++;
     argc--;

     /* Initialize options. */
     opt.lngval = DEF_LNGVAL;

     /* Process options. */
     for ( ; argc > 0 && **argv == '-'; argc--, argv++)
     {
         /* Get option flag. */
         thisopt = *argv + 1;

         /* Look for 'l' option. */
         if (tolower (*thisopt) == 'l')
         {
             /* Get option value. */
             thisval = thisopt + 1;

             /* Option value must be a positive integer. */
             if (isdigit (*thisval) && (opt.lngval = atoi (thisval)))
             {
                 ;
             }
             else
             {
                 fprintf (stderr,
                         "%s:  invalid value, \"%s\", for option \"%c\"\n",
                         Progname, thisval, *thisopt);
                 exit (FAILURE);
             }
         }
         else
         {
             fprintf (stderr, "%s:  invalid option, \"%c\"\n",
                     Progname, *thisopt);
             exit (FAILURE);
         }
     }

     /* Must be exactly two arguments left. */
     if (argc == 2)
     {
         cmpfiles (*argv, *(argv + 1), &opt);
         exit (SUCCESS);
     }
     else
     {
         fprintf (stderr, "usage:  %s [-ln] file1 file2\n", Progname);
         exit (FAILURE);
     }
 }
 
 static void cmpfiles (file1, file2, opt)

 char      *file1;   /* (I) File name #1. */
 char      *file2;   /* (I) File name #2. */
 OPTIONS   *opt;     /* (O) Options. */
 {
     FILE   *fp1;   /* File pointer #1. */
     FILE   *fp2;   /* File pointer #2. */
     char   **a1;   /* Array of lines #1. */
     int    n1;     /* Number of lines in a1 (not including 0th element). */
     char   **a2;   /* Array of lines #2. */
     int    n2;     /* Number of lines in a2 (not including 0th element). */

     /* Open the files. */
     if ((fp1 = fopen (file1, "rt")) && (fp2 = fopen (file2, "rt")))
     {
         /* Read each file and place the lines of text into an array. */
         if (readin (fp1, &a1, &n1) && readin (fp2, &a2, &n2))
         {
             compare (a1, n1, a2, n2, opt->lngval);
         }
         else
         {
             fprintf (stderr,
                     "%s:  could not read files into memory\n", Progname);
         }
     }
     else
     {
         fprintf (stderr, "%s:  could not open files\n", Progname);
     }
 }
 
 static BOOLEAN readin (fp, a, n)

 FILE   *fp;    /* (I) File pointer. */
 char   ***a;   /* (O) Array of lines. */
 int    *n;     /* (O) Number of lines in a (not including 0th element). */
 {
     #define NLINES   1000   /* Maximum number of lines that will be handled.
     #define NBUF     512    /* Maximum line length that will be handled. */

     char      **array;         /* Array of lines. */
     int       i;               /* Counter. */
     int       len;             /* Length of line. */
     char      buf[NBUF + 1];   /* Text buffer. */

     /* Allocate an array for a maximum number of lines of text. */
     if (array = (char **) malloc ((NLINES + 1) * sizeof (char *)))
     {
         ;
     }
     else
     {
         return (FALSE);
     }

     /* Read the lines of text. */
     for (i = 1; fgets (buf, NBUF + 1, fp) && i < NLINES; i++)
     {
         /* Allocate an array. */
         len = strlen (buf);
         if (array[i] = malloc ((len + 1) * sizeof (char)))
         {
             /* Copy the text. */
             memcpy (array[i], buf, len + 1);
         }
         else
         {
             return (FALSE);
         }
     }

     /* Return the array and the number of lines. */
     *a = array;
     *n = i - 1;

     return (TRUE);
 }


 TEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TEST.C


 /*
    Test program for checking basic CTask functions.

    Note that strange effects, like duplicated or incomplete output,
    may be due to the concurrent usage of "printf". This is not trapped
    here, since the effects are not fatal, but in real applications,
    resources should be used to channel console output access.
 */

 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #include <ctype.h>

 #include "tsk.h"

 #if (TSK_NAMED)
 extern void snapshot (FILE *f);
 #endif

 #define STACKSIZE 2048

 word _stklen = 5 * STACKSIZE;  /* For Turbo C: Four tasks + main Task Stack *

 typedef struct {
                farptr xx;
                char str [20];
                } message;

 tcb tcb1, tcb2, tcb3, tcb4;
 mailbox box;
 message msg;
 flag halt;
 pipe pip;
 buffer buf;

 byte pipbuf [10];
 word bufbuf [40];

 int endrun;


 /*
    Task1 sends a mail to Task3, and waits for a response in the buffer.
    The response is then displayed.
    Task1 will stop while the halt flag is set.
 */

 void far task1 (void)
 {
    char str [20];

    printf ("Task 1 started\n");
    while (!endrun)
       {
       wait_flag_clear (&halt, 0L);

       t_delay (5);
       putch ('1');
       strcpy (msg.str, "From T1");
       send_mail (&box, &msg);

       read_buffer (&buf, str, 20, 0L);
       printf ("Task 1 read buf: <%s>\n", str);
       }
 }

 /*
    Task2 reads the keyboard. If a character has been read, it is passed
    to Task4 via a pipe. Entering 'h' will set the halt flag (stopping Task1),
    entering 'c' will clear the halt flag.
    'e' stops the program.
 */

 void far task2 (void)
 {
    int ch;

    printf ("Task 2 started\n");
    while (!endrun)
       {
       ch = t_read_key () & 0xff;
       switch (tolower (ch))
          {
          case 'h':   set_flag (&halt);
                      break;
          case 'c':   clear_flag (&halt);
                      break;
          case 'e':   wake_task (NULL);
                      break;
 #if (TSK_NAMED)
          case 'd':   snapshot (stdout);
                      break;
 #endif
          }

       if (!endrun)
          write_pipe (&pip, ch, 0L);
       putch ('2');
       }
 }


 /*
    Task3 waits for mail, then sends it back through a buffer.
 */

 void far task3 (void)
 {
    message far *m;

    printf ("Task 3 started\n");
    while (!endrun)
       {
       m = wait_mail (&box, 0L);
       printf ("Task 3 received <%Fs>\n", m->str);

       m->str [6] = '3';
       write_buffer (&buf, m->str, 7, 0L);
       }
 }


 /*
    Task4 waits for a character in the pipe and displays it. To make
    things livelier, it uses a timeout while waiting, and will display
    faces when the timeout occurred before the character.
 */

 void far task4 (void)
 {
    int ch;

    printf ("Task 4 started\n");
    while (!endrun)
       {
       ch = read_pipe (&pip, 10L);
       if (ch < 0)
          putch (0x02);
       else
          printf ("Task 4 got <%c>\n", ch);
       }
 }


 main ()
 {
    char stack1 [STACKSIZE];
    char stack2 [STACKSIZE];
    char stack3 [STACKSIZE];
    char stack4 [STACKSIZE];

    endrun = 0;
    install_tasker (0, 0);
    create_task (&tcb1, task1, stack1, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK1"
 #endif
                 );
    create_task (&tcb2, task2, stack2, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK2"
 #endif
                 );
    create_task (&tcb3, task3, stack3, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK3"
 #endif
                 );
    create_task (&tcb4, task4, stack4, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK4"
 #endif
                 );
    create_mailbox (&box
 #if (TSK_NAMEPAR)
                 ,"Mailbox"
 #endif
                 );
    create_flag (&halt
 #if (TSK_NAMEPAR)
                 ,"Halt"
 #endif
                 );
    create_pipe (&pip, pipbuf, sizeof (pipbuf)
 #if (TSK_NAMEPAR)
                 ,"Pipe"
 #endif
                 );
    create_buffer (&buf, bufbuf, sizeof (bufbuf)
 #if (TSK_NAMEPAR)
                 ,"Buffer"
 #endif
                 );

    start_task (&tcb1);
    start_task (&tcb2);
    start_task (&tcb3);
    start_task (&tcb4);
    preempt_on ();

    t_delay (0L);

    endrun = 1;
    puts ("******** Main Task *********");

    set_priority (NULL, 10);
    delete_mailbox (&box);
    delete_pipe (&pip);
    delete_buffer (&buf);
    delete_flag (&halt);

    schedule ();

    preempt_off ();
 /*   remove_tasker (); */
    puts ("******** End Run *********");
 }


 TEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\TCRES2\TEST.C

 #include <resident.h>

 int window_one_buff [ (37 + 2) * (4 + 2) ];
 int run_once = 0, low_color = MONOCHROME, hi_color;
 int pass_buffer [ 35 * 2 + 1 ];

 struct WINDOW window_one;

 void test_box ()
    {
       int key;

       if (run_once)
          exch_window (&window_one);
       else {
          make_window (&window_one);
          dis_str (11, 21, "Test of Memory Resident Library V2.01", low_color)
          dis_str (12, 21, "Press the arrow & paging keys to move", low_color)
          dis_str (13, 21, "Press ESC to uninstall the test Prog.", low_color)
          dis_str (14, 25,     "Press any other key to exit.", low_color);
          run_once = 1;
       }
       hidecur ();
       while (!(key = getch ()))
          key_window (getch (), &window_one);
       keystrokes ("Test Passed!", pass_buffer);
       exch_window (&window_one);
       normalcur ();
       if (key == 27)
          drop_tsr ();
    }

 main ()
    {
       if (loaded ())
          printf ("The test program has already been loaded");
       else {
          if (iscolor ())
             low_color = color (GREEN, BLACK);
          hi_color = 10;
          STACK_SIZE = 200;
          window_one.row = 10;
          window_one.col = 20;
          window_one.hlen = 37;
          window_one.vlen = 4;
          window_one.color = hi_color;
          window_one.buffer = window_one_buff;
          window_one.vtype = DOUBLE_LINE;
          window_one.htype = DOUBLE_LINE;
          printf ("\n");
          printf ("Memory Resident Library V2.01 Test Program\n");
          printf ("Press Ctrl - Alt - T to call up.\n");
          go_resident (test_box, KEY_T, KEY_ALT, KEY_CTRL);
       }
    }



 TEST2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\MULTITSK\TEST2.C

 int conlock;
 int *comanch;
 struct INPUT
    { struct INPUT *next;
      char text[2];
    };
 struct INPUT *diskqueue;
 char *getmem();

 /*  This program tests the multi-tasking functions.
 *   Three functions are attached:
 *       1.  keytask, which just echoes characters from the keyboard
 *           to the console until a tilde (~) is encountered.
 *       2.  diskin, which copies the file "taskfunc.asm" to an internal
 *           queue, one full line at a time.
 *       3.  diskout, which dumps the internal queue, at most 10 chars
 *           at a time, to the file "test2.out"
 *
 *   The main task just waits until all subtasks have completed.
 *
 */
 #include "stdio.h"

 main()
 {
   int j;
   int i;


   inittask("main");
   if (attach(getmem(100),getmem(1024),1024)) keytask();
   if (attach(getmem(100),getmem(1024),1024)) diskin();
   if (attach(getmem(100),getmem(1024),1024)) diskout();
   while (taskcnt() > 1) { yield(); }
 }

 keytask()
 {
   char c;


 printf("\nKeyboard task activated");
 for (;;)

    {
      if (iskbhit())
        {
         c = getch();
         if (c == '\r') putch('\n');
         putch(c);
         if (c == '~')
           {
              printf("\nKeyboard task terminating");
              stop();
           }
        }
      yield();
    }
 }

 diskin()
 {
   FILE *fp;
   char buffer[256], *sp;
   struct INPUT *nq, *wp;

   printf("\nRead task now active");

   fp = fopen("taskfunc.asm","r");
   if (!fp)  {printf("\nUnable to open taskfunc.asm - terminating"); exit(3);}
   while ((sp = fgets(buffer,256,fp)))
     {
       nq = (struct INPUT *) getmem( 8+sizeof(char *) + strlen(sp));
       nq->next = NULL;
       strcpy(nq->text, sp);
       wp = (struct INPUT *) &diskqueue;
       while (wp->next) { wp = wp->next; }
       wp->next = nq;
       yield();
     }
   fclose(fp);
   printf("\n\nRead subtask terminated.");
   stop();
 }
 diskout()
 {
   FILE *fp;
   char *sp;
   int j;
   struct INPUT *nq, *wp;
   char c;

   fp = fopen("test2.out","w");
   printf("\nWritetask now active");
   while ((nq=diskqueue) || (taskcnt() > 3))
     {
       diskqueue = nq->next;
       sp = nq->text;
       j=0;
       while (*sp)
         { fputc(*sp++, fp);
           if (j++>10) {yield(); j=0;}
         }
       rlsmem(nq,8+sizeof(char *) + strlen(nq->text));

       yield();
     }
   printf("\n\nWrite task terminating");
   fclose(fp);
   stop();
 }


 TESTDX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\TESTDX.C

 main()
 {
    lprintf("The following is a test of the Unicorn #1 Library with a\n");
    lprintf("daisy wheel printer.  The library was designed using an\n");
    lprintf("Epson DX-10 printer.  This printer is designed to be\n");
    lprintf("Diablo 630 compatible therefore the commands in the\n");
    lprintf("library should be applicable to many Daisy wheels.\n\n\n");

    lputch('A');
    lputch('B');
    lputch('C');
    lputch('D');
    lputch('E');
    lputch('F');
    lputch('G');
    lputch('H');
    lputch('I');

    dxlf();

    lputch('a');
    lputch('b');
    lputch('c');
    lputch('d');
    lputch('e');
    lputch('f');
    lputch('g');
    lputch('h');
    lputch('i');

    dxrlf();

    lputch('A');
    lputch('B');
    lputch('C');
    lputch('D');
    lputch('E');
    lputch('F');
    lputch('G');
    lputch('H');
    lputch('I');

    dxcr();
    dxlf();
    dxcr();
    dxlf();
    dxcr();
    dxlf();
    dxcr();
    dxlf();

    lprintf("\nNotice that in the above a LF was sent to the printer. This\n")
    lprintf("did advance the paper one line but did NOT do a carriage return.\
    lprintf("The reverse line feed performed in a similar manner.");

    lprintf("\n\nNow lets do some ");
    dxhlf();
    lprintf("sub");
    dxrhlf();
    lprintf(" and ");
    dxrhlf();
    lprintf("super");
    dxhlf();
    lprintf("Scripting with the printer.\n\n");
    dxshast();
    lprintf("Now we will do shadow printing\n");
    lprintf("Now let's ");
    dxundlst();
    lprintf("underline");
    dxundend();
    lprintf(" a bit of print\n");
    dxboldst();
    lprintf("This line is printed using bold print\n");
    dxbsend();
    dxchwide(15);
    lprintf("\nNow let's use 8 pitch print\n");
    dxchwide(12);
    lprintf("\nNow let's use 10 pitch print\n");
    dxchwide(10);
    lprintf("\nNow let's use 12 pitch print\n");
    lprintf("\n\n\nThis is the end of the daisy wheel print test\n");
    dxff();
 }


 TESTEQP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\TESTEQP.C

 main()
 {
   cls();
   beepsp();
   printf("\n\n\nThis program will read various information concerning your\n"
   printf("computer and display it on the screen using functions from\n");
   printf("the Unicorn #1 library.\n\n\n\n\n");

   printf("The equipment status is %d decimal or %x hex\n\n", equip(), equip()
   printf("There are %d Kilobytes of memory installed\n", memsize());
   printf("The model code number is %d decimal or %x hex\n",getctype(),getctyp
 }


 TESTGRPR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\TESTGRPR.C

 main()
 {
   printf("The following program acesses the IBM Graphics printer");

   lprintf("\nThis is a test program to check the IBM Graphics printer\n");
   lprintf("and the Unicorn1 Library\n\n\n");

   prtwidon();
   lprintf("This is the wide print\n");
   lprintf("A simple carriage return has turned it off\n");
   prtwidof();
   prtdubon();
   lprintf("This is double strike printing\n");
   lprintf("A carriage return did NOT turn it off\n");
   prtdubof();
   prtempon();
   lprintf("This is emphasized print\n");
   prtdubon();
   lprintf("This is both emphasized and double strike\n");
   prtdubof();
   prtempof();
   lprintf("Following this line the printer buzzer should sound\n");
   prtbuzz();
   prtcomon();
   lprintf("This is compressed print\n");
   lprintf("A carriage return does NOT turn it off\n");
   prtcomof();
   lprintf("There should be a backspace character");
   prtbs();
   lprintf("right after the word character\n");
   lprintf("There should be a tab");
   prttab();
   lprintf("right after the word tab\n");
   lprintf("The line feed character here");
   prtlf();
   lprintf("moves the line up one and moves the carriage back\n");
   lprintf("\n\nThis ");
   prtwidon();
   prtdubon();
   prtempon();
   lprintf("is a");
   prtwidof();
   prtdubof();
   prtempof();
   lprintf("simple test line ");
   prtcomon();
   lprintf("With different type styles\n");
   prtcomof();
   lprintf("Next is a Form Feed character to eject the page\n");
   prtff();







   printf("\nAll done now!");

 }



 TESTINTS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\TESTINTS.C

 /*
 **          TEST PROGRAM FOR INTERRUPT HANDLER FUNCTIONS
 **  This program demonstrates the installable interrupt
 **  service routines contained in the functions ticker, ctlbrk(),
 **  and in SMDLx.LIB.
 **  The ticker routine installs on
 **  interrupt 1CH, and chains after completion to whatever
 **  routine may have already been hung on that interrupt.
 **  Ticker is not a C function as such, but a stand-alone assembly
 **  language routine which is installed by installtick() and removed
 **  by removetick().
 **  The ctlbrk() routine is used to exit the program and cleanup
 **  the interrupt vector table upon exit.  It installs upon int 23H.
 **
 **  Copyright 1986, S.E. Margison
 **
 */

 #include <stdio.h>
 #include <dos.h>
 #include <smdefs.h>

 /* first, we must declare our control-break handler routine.
 ** this routine could do almost anything, but we will just
 ** set a flag that the main program can test, and print a message.
 ** Note that this should be declared BEFORE main() routine!
 */

 int killit;

 handler() {    /* handler cannot return a value, so declare void */
    killit = YES;
    puts("Control-C received; exiting program");
    return(0);       /* return 0 to continue program */
    }

 int count;       /* this is the variable which ticker will manipulate */
 extern void installtick(), removetick();

 main() {
    int i;

 /* BEFORE we change the interrupt vector table, we MUST
 ** install our control-C trap.  If not, it would be possible
 ** for a fast typist to control-C out of the program after
 ** we mess up the vector table and before we grab the control-C
 ** handler vector.   Result:  Well, just turn off the power switch
 ** and start all over again!!!
 */

    ctlbrk(&handler);       /* install our trap */
    killit = NO;            /* and clear our trap flag */



 /* Use installtick() to pass the desired variable address to the ticker
 ** process and install it upon the interrupt.
 */

    installtick(&count);



 /* this loop demonstrates the use of the ticker function.  As long as
 ** the count variable is not 0, it will be decremented 18.21 times
 ** per second.  ticker tests the value for zero and if it is,
 ** does not decrement it again.  This makes it unnecessary to try to
 ** "trap" count exactly at zero before the next interrupt occurs.
 ** To use ticker, place a value in count (18 = 1 second more or less).
 ** Then, check it every so often to see if it is zero (or whatever
 ** your heart desires).
 */

    i = 0;
    while(!killit) {          /* abort when control-C trap sets this flag */
       count = 18;            /* set a value of 1 second */
       while(count != 0);     /* loop until timed out */
       printf("This is loop #%d\n", i++);  /* do something useful here */
       }                      /* and go again */

 /* if we are here, then our control-C trap worked! */

 /* now, we have to clean up after ourselves.  It is necessary
 ** to restore the original vector table contents.  Alternate
 ** option is to turn off the power!!
 */

 /* first, remove the ticker from the interrupt table.
 ** WARNING:  FAILURE TO REMOVE TICKER BEFORE EXITING PROGRAM
 **           WILL DEFINITELY (as in positively!) CRASH THE
 **           SYSTEM ALMOST IMMEDIATELY!!!!!!
 */
         removetick();

 /* finally, let's restore the original control-C handler by uninstalling
 ** our own.  A NULL parameter does the job!
 ** Yes, DOS restores the original vector upon exit from our program, but
 ** this shows that we can also do that ourselves.
 */
    ctlbrk(0);

    }

 /* If using ticker, the following ctlbrk handler would be sufficient
 ** if it was desired to abort the program cleanly when a control-break
 ** was pressed:
    handler {
       removetick();
       return(1);
       }
 */



 TESTPIX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\GRAPH\HERCBIOS\TESTPIX.C


 /*  MAIN tests PIXEL by drawing lines on the screen  */

 #include        "stdio.h"

 main ()
 {
         int i,j;
         char        line [90];

         /* first clear screen */
         grafix (0);

         /* now draw a couple of lines */
         for (i=0; i<696; i++)
         {
                 pixel (i, i/2, 1);
                 pixel (i, 348 - i/2, 1);
         }

         waitkey();                /* wait for CR */

         /* a different pattern on page 1 */
         swpage (1);
         for (i=0; i<720; i++)
         for (j=0; j<348; j=j+50)
                 pixel (i,j,1);
         for (i=0; i<720; i=i+90)
         for (j=0; j<348; j++)
                 pixel (i,j,1);

         /* switch back and forth a couple of times */
         waitkey();
         swpage (0);
         waitkey();
         swpage (1);
         waitkey();
         swpage (0);
         waitkey();
         swpage (1);
         waitkey();

 #ifndef NOTONE
         /* add some writing */
         dline (10, 4, "Hello, there!");
         dline (10, 5, "Second LINE of text.");
         dline (10, 6, "all on display page 1.");

         waitkey();
         for (i=0; i<8; i++)
                 for (j=0; j<32; j++)
                         dchar (j+5, i+13, (char) (32*i+j));

         waitkey();
 #endif
         /* repeat for page 0 */
         swpage (0);

 #ifndef NOTZERO
         /* add some writing */
         dline (10, 4, "Hello, there!");
         dline (10, 5, "Second LINE of text.");
         dline (10, 6, "this time on display page 0.");

         waitkey();
         for (i=0; i<8; i++)
                 for (j=0; j<32; j++)
                         dchar (j+5, i+13, (char) (32*i+j));
 #endif

         waitkey();

         /* back to alpha mode */
         waitkey();
         alfa();
 }

 dline (x, y, chstr)        /* write character-string at x,y */
         int         x,y;
         char        chstr [90];
 {
         int        i;
         char        *p;

         i=0;
         for ( p=chstr; *p != '\0'; p++ )
         {
                 dchar ( x+i, y, *p );
                 i++;
         }
 }


 TESTSND.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\TESTSND.C

 main()
 {
    cls();
    printf("\n\nSound testing program!\n\n\n");

    printf("Sound a tone\n");
    ctone(1000, 500);
    printf("Sound another tone\n");
    ctone(500, 1000);

    printf("Here is a red alert \n");
    redalert();

    printf("Here is a broad spectrum white noise\n");
    wnoise(100,3000, 9500);
    printf("burble using 200, 300\n");
    burble(200,300);
    printf("burble using 400, 500\n");
    burble(400, 500);
    printf("high frequency white noise\n");
    wnoise(1000, 1500, 9500);
    printf("low frequency white noise\n");
    wnoise(100, 400, 9500);
    printf("Machine gun sound\n");
    mgun();

    printf("An ascending glissando\n");
    gliss(100,1000,300);
    printf("A descending glissando\n");
    gliss(3000, 200, 100);
    printf("\n\nEnd of the sound test program!");
 }







 TESTTASK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\MULTITSK\TESTTASK.C

 int lock[5];
 int *comanch;

 #include "stdio.h"
 char *getmem();

 /*          Test multi-tasking function library
  *
  *   In this test, a main task and three subtasks are created.
  *   Initally, each task identifies itself, then issues yield to
  *   allow the next task to execute.
  *
  *   main then obtains all of the locks, and enters a loop, issuing an
  *   identifying message on each pass.  At cycle 5, 10, 15 and 20,
  *   a lock is released via deq.
  *
  *   Each of the subtasks performs a limited number of iterations of the
  *   following:  enq lock, issue message, then deq lock.
  *
  *   The sequence of displays shows each of the tasks being dispatched
  *   in turn, but only when any needed lock is available.
  *
  *   Note that although parameters may not be passed to the subtasks
  *   as normal arguments, the task-id is given through the
  *   task-related data area passed via attach.
  *
  */

 main()
 {
   static int ids[4] = {1,2,3,4};
   int j;
   int i;

   comanch = &ids[0];
   inittask(&ids[0]);
   for (i=1;i<4; i++)
     {   /* get subtask going with 1k stack */
         if (attach(&ids[i],getmem(1024),1024)) subtask();
     }
   printf("\tMain");
   yield();                        /* give other tasks 1 shot each */
   for (i=1;i<5; i++)  enq(&lock[i]);  /* block other tasks */
   for (j=1;j<26;j++)
      {
         if (j==5)  deq(&lock[1]);
         if (j==10) deq(&lock[2]);
         if (j==15) deq(&lock[3]);
         if (j==20) deq(&lock[4]);
         printf("\tMain ");
         yield();
      }
   while (taskcnt() > 1) yield();    /* wait for completion of subtasks */
 }

 subtask()
 {
   int i;
   int j;

   i = *comanch;
   j = i*10;
   while (j--)
     {
        enq(&lock[i]);
        printf("\t %d",i);
        deq(&lock[i]);
        yield();
     }
   stop();
 }


 TEXT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\TEXT.C

 /*
 ** BYTE Text Display Benchmark
 ** Version 1 for 8088/8086/80286/80386
 ** March 1988
 ** Written in BYTE Small-C
 ** Based on Small-C by J.E. Hendrix
 **
 ** This program executes the following steps:
 **  1. Saves the current video mode
 **  2. Prompts the user for which text mode he wishes to
 **     run the benchmark.
 **  3. Calculates the screen width for the mode the user has
 **     selected and constructs a string of the appropriate width.
 **  4. Begins timing.
 **  5. Switches to the new mode.
 **  6. Writes COUNT strings to the screen.
 **  7. Stops timing.
 **  8. Switches to the original video mode.
 **  9. Reports its results.
 ** 10. Exits.
 **
 ** This program writes to the screen using Small-C's
 ** Umsdos call directed to stdout. (Int 21h function 40H)
 */

 /*
 ** Note: COUNT should have 40 and 80 as common denominator.
 */

 COUNT 8000        /* Number of chars */

 stdin 0                /* Standard input */
 stdout 1        /* Standard output */
 WRITE 16384        /* MSDOS write function */

 int tblock[4];        /* Timer block */
 int vblock[3]; /* Array for video mode stuff */
 char buffer[82];  /* Char array for string */
 int lines;        /* Number of lines */

 extern gtime();                /* Start stopwatch */
 extern calctim();        /* Stop stopwatch */
 extern gvmode();        /* Get video mode */
 extern svmode();        /* Set video mode */

 main() {
         int mode;        /* video mode */
         int len;        /* string length */
         int i;                /* For loop */
         int row,col,rowinc,colinc;  /* Row and column vars */
         char c;                /* Temporary holding char */

 /* First get current video mode */
         gvmode(vblock);

 /* Now prompt for mode to test */
         printf(" BYTE Text Video Benchmark\n");
         printf(" What video mode?");
         fscanf(stdin,"%d",&mode);

 /* Select length */
         switch(mode) {
                 case 0:
                 case 1: len=40;
                          break;
                 case 2:
                 case 3:
                 case 7: len=80;
                         break;
                 default:
                    printf("Illegal mode\n");
                    exit(0);
         }

 /* Build string */
         c='A';
         for (i=0;i<len;++i) {
                 buffer[i]=c++;
                 if(c>'Z') c='A';
         }

 /* Set # of lines to print */
         lines = COUNT / len;

 /* Initialize row/col outside of timing loop */
         row = col = 1;
         rowinc=1; colinc=1;

 /* Begin timing */
         gtime(tblock);
 /* Switch modes */
         svmode(mode);
 /* Do the loop for writing stuff */
         for (i=0; i<lines; ++i)
                 Umsdos(buffer,len,stdout,WRITE);
 /* Do cursor positioning loop */
         for (i=0; i<COUNT; ++i)
         {
                 curpos(row,col);
                 Umsdos(&c,1,stdout,WRITE);
                 if(row==25) rowinc=-1;
                 if(row==0) rowinc=1;
                 if(col==len) colinc=-1;
                 if(col==0) colinc=1;
                 row+=rowinc;
                 col+=colinc;
                 if(++c>'Z') c='A';
         }
 /* Stop timing */
         calctim(tblock);
 /* Switch mode back */
         mode=vblock[0];
         svmode(mode);
 /* Display results */
         printf(" Elapsed time (HH:MM:SS:1/100ths):\n");
         printf(" %d:%d:%d:%d\n",tblock[0],tblock[1],tblock[2],
                 tblock[3]);
         exit(0);
 }

 /*
 ** curpos(row,col) int row,col;
 ** position cursor to row/col using BIOS int 10h function
 */
 curpos(row,col) int row,col;
 {
 #asm
         MOV        BP,SP
         MOV        DL,2[BP]        ;column
         MOV        DH,4[BP]        ;row
         MOV        AH,2                ;Function
         INT        10H
         XOR        CX,CX
 #endasm
 }


 TIC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\TIC.C

 /*                      TicTac

         This program plays a perfect game of tic-tac-toe.
 */

 #define FALSE 0
 #define TRUE 1

 char board[9];   /* The playing board; for each space, 0 is not used,
                    1 is X, -1 is O. */

 /*      main()

         Function: Ask the user which side(s) he wants to play. Then
         make or ask for moves one each side until one side wins.

         Algorithm: First, set humanX and humanO to indicate which
         side(s) the human is playing. Then init the board and print
         it out. Then iterate making or asking for a move, printing
         it out, and testing for a win. Each pass thru the main loop,
         the program switches sides.
 */

 main()

 {
         register int side;               /* Which side is playing (1 or -1).
         int move;               /* Next move. */
         int val;                /* Value of move. */
         int humanX, humanO;     /* TRUE if human is playing X/O. */
         char str[20];           /* Input are for yes/no. */

         /* Ask the user if the computer should play the Xs. */
         printf("Should the computer play Xs? ");
         gets(str);
         if ((str[0] == 'y') || (str[0] == 'Y')) humanX = FALSE;
         else humanX = TRUE;
         /* Ask about playing the Os. */
         printf("Should the computer play Os? ");
         gets(str);
         if ((str[0] == 'y') || (str[0] == 'Y')) humanO = FALSE;
         else humanO = TRUE;

         /* Initialize the board. */
         initBd();

         /* Show the empty board. */
         printBd();

         /* X goes first. */
         side = 1;

         /* Loop until a win or the player quits. */
         while (TRUE) {
                 /* If this side is played by the human... */
                 if ((humanX && (side == 1)) || (humanO && (side == -1))) {
                         /* Query for move; repeat until legal. */
                         do {
                             if (side == 1)
                                 printf("X's move (enter 1-9, or 0 to quit): "
                             else printf("O's move (enter 1-9, or 0 to quit):
                             scanf("%d",&move);
                         } while ((move != 0) && (board[move-1] != 0));
                         /* Check for quit. */
                         if (move == 0) break;
                 /* Otherwise, decide on the best move to make. */
                 } else move = bestMove(side,&val)+1;
                 /* Make the move. */
                 board[move-1] = side;
                 /* Show the new board to the user. */
                 printBd();
                 /* If that one won it, say so and exit. */
                 if (hasWon(side)) {
                         printf("That move won!\n");
                         break;
                 };
                 /* If it was a tie, say so and exit. */
                 if (isTie()) {
                         printf("Tie game!\n");
                         break;
                 };
                 /* Switch sides for the next move. */
                 side = -side;
         };
 }

 /*      initBd()

         Function: Initialize the board to all empty.

         Algorithm: Set each board entry to zero.
 */

 initBd()

 {
         register int i;

         /* Zero (empty) each square in the board. */
         for (i = 0; i < 9; i++) board[i] = 0;
 }

 /*      isTie()

         Function: Return TRUE if the current board position is a tie.

         Algorithm: See if we can find an untaken board position. If not,
         it's a tie. Otherwise, there's still hope.
 */

 isTie()

 {
         register int i;

         /* Check each space on the board. */
         for (i = 0; i < 9; i++) if (board[i] == 0) return(FALSE);
         /* If none found, return tie. */
         return(TRUE);
 }

 /*      hasWon(p)

         Function: Return true if player p has won, where p is 1 for X
         and -1 for O.

         Algorithm: Check for every possible three in a row. If any are
         found, it's a win, so we return TRUE; otherwise, we return FALSE.
 */
 #ifdef NEVER
 hasWon(p)

 int p;

 {
         register int i;
         register int w;

         /* Calculate the sum of three in a row. */
         w = 3*p;

         /* Check for three in a row horizontally. */
         for (i = 0; i < 9; i += 3)
                 if ((board[i]+board[i+1]+board[i+2]) == w) return(TRUE);

         /* Check for three in a row vertically. */
         for (i = 0; i < 3; i++)
                 if ((board[i]+board[i+3]+board[i+6]) == w) return(TRUE);

         /* Check the diagonols. */
         if ((board[0]+board[4]+board[8]) == w) return(TRUE);
         if ((board[2]+board[4]+board[6]) == w) return(TRUE);

         /* If nothing, then return a non-win. */
         return(FALSE);
 }
 #endif NEVER
 /*      bestMove(p,v)

         Function: Return the best possible move for player p. p is 1
         for X or -1 for O. Also return the value of that move (1 for
         a win, 0 for a tie, and -1 for a loss) in v.
 */

 bestMove(p,v)

 int p;
 int *v;

 {
         register int i;
         int lastTie;
         register int lastMove;
         int subV;

         /* First, check for a tie. */
         if (isTie()) {
                 *v = 0;
                 return(0);
         };

         /* If not a tie, try each potential move. */
         for (*v = -1, lastTie = lastMove = -1, i = 0; i < 9; i++) {
                 /* If this isn't a possible move, skip it. */
                 if (board[i] != 0) continue;
                 /* Make the move. */
                 lastMove = i;
                 board[i] = p;
                 /* Did it win? */
                 if (hasWon(p)) *v = 1;
                 else {
                         /* If not, find out how good the other side can do. *
                         bestMove(-p,&subV);
                         /* If they can only lose, this is still a win. */
                         if (subV == -1) *v = 1;
                         /* Or, if it's a tie, remember it. */
                         else if (subV == 0) {
                                 *v = 0;
                                 lastTie = i;
                         };
                 };
                 /* Take back the move. */
                 board[i] = 0;
                 /* If we found a win, return immediately (can't do any
                    better than that). */
                 if (*v == 1) return(i);
         };
         /* If we didn't find any wins, return a tie move. */
         if (*v == 0) return(lastTie);
         /* If there weren't even any ties, return a loosing move. */
         else return(lastMove);
 }

 /*      printBd()

         Function: Display the board for the user.

         Algorithm: Iterate thru each square and print it out.
 */

 printBd()

 {
         register int i;

         /* For each square... */
         for (i = 0; i < 9; i++) {
                 /* Print X, O, or space. */
                 if (board[i] == 0) printf(" ");
                 else if (board[i] == 1) printf("X");
                 else printf("O");
                 /* If this is the last square in the line... */
                 if ((i % 3) == 2) {
                         /* Print the adjacent numbered board. */
                         printf("    %1d|%1d|%1d\n",i-1,i,i+1);
                         if (i != 8) printf("-+-+-    -+-+-\n");
                 } else printf("|");
         };
         printf("\n");
 }



 TIC2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\TIC2.C

 #define FALSE 0
 #define TRUE 1

 char board[9];     /* The playing board; for each space, 0 is not used, 1 is
                      -1 is O. */

 hasWon(p)

 int p;

 {
  register int i;
  register int w;

  w = 3*p;
  for (i = 0; i < 9; i += 3)
      if ((board[i]+board[i+1]+board[i+2]) == w) return(TRUE);
  for (i = 0; i < 3; i++)
      if ((board[i]+board[i+3]+board[i+6]) == w) return(TRUE);
  if ((board[0]+board[4]+board[8]) == w) return(TRUE);
  if ((board[2]+board[4]+board[6]) == w) return(TRUE);
  return(FALSE);
 }



 TIME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\TIME.C

 /*
  * DATE/TIME FUNCTIONS:
  *
  *        To use the functions in this section, you must include "TIME.H"
  *        in your source file.
  */

 #include <d:\usr\stdlib\stdio.h>
 #include <d:\usr\stdlib\time.h>

 static struct tm the_time;
 static struct tm jan_1;
 static char timebuf[26] = "Day Mon dd hh:mm:ss yyyy\n";
 static char *day[]   = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
 static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

 long julian_date(time)
 register struct tm *time;
 {
         register long c, y, m, d;

         y = time->tm_year + 1900;        /* year - 1900 */
         m = time->tm_mon + 1;                /* month, 0..11 */
         d = time->tm_mday;                /* day, 1..31 */
         if(m > 2)
                 m -= 3L;
         else {
                 m += 9L;
                 y -= 1L;
         }
         c = y / 100L;
         y %= 100L;
         return(        ((146097L * c) >> 2) +
                 ((1461L * y) >> 2) +
                 (((153L * m) + 2) / 5) +
                 d +
                 1721119L );
 }

 long time(rawtime)
 register long *rawtime;
 /*
  *        Get the current system clock date/time value.  Under many systems,
  *        this function returns the number of seconds since 00:00:00 GMT on
  *        Jan 1, 1970.  This implementation returns an encoded date/time
  *        value instead.  Therefore any programs which depend on this value
  *        being a number of seconds will not work properly.  However, other
  *        functions in this section which make use of the raw time value
  *        returned by time() are implemented to be compatible with this
  *        encoding, and will work properly.  In addition to returning the
  *        raw time value, if the <rawtime> pointer in not NULL, the value
  *        is stored in the long <rawtime> points to.
  */
 {
         register long t;

         t = (gemdos(0x2A) << 16) | (gemdos(0x2C) & 0xFFFFL);
         if(rawtime)
                 *rawtime = t;
         return(t);
 }

 char *ctime(rawtime)
 long *rawtime;
 /*
  *        Convert <rawtime> to a string.  A 26 character fixed field string
  *        is created from the raw time value.  The following is an example
  *        of what this string might look like:
  *                "Wed Jul 08 18:43:07 1987\n\0"
  *        A 24-hour clock is used, and due to a limitation in the ST system
  *        clock value, only a resolution of 2 seconds is possible.  A pointer
  *        to the formatted string, which is held in an internal buffer, is
  *        returned.
  */
 {
         char *asctime();
         struct tm *gmtime();

         return(asctime(gmtime(rawtime)));
 }

 struct tm *gmtime(rawtime)
 long *rawtime;
 /*
  *        Convert <rawtime> to fill time structure fields.  A pointer to an
  *        internal structure is returned.  Refer to "TIME.H" for the values
  *        of the various structure fields.
  */
 {
         register long time, jdate, jjan1;
         register struct tm *t, *j;

         time = *rawtime;
         t = &the_time;
         j = &jan_1;
         t->tm_sec = (time & 0x1F) << 1;
         time >>= 5;
         t->tm_min = (time & 0x3F);
         time >>= 6;
         t->tm_hour = (time & 0x1F);
         time >>= 5;
         t->tm_mday = (time & 0x1F);
         time >>= 5;
         t->tm_mon = (time & 0x0F) - 1;
         time >>= 4;
         t->tm_year = (time & 0x7F) + 80;
         jdate = julian_date(t);
         *j = *t;
         j->tm_mon = 0;                /* set up Jan 1 */
         j->tm_mday = 1;
         jjan1 = julian_date(j);
         t->tm_wday = (jdate + 1) % 7;
         t->tm_yday = jdate - jjan1;
         t->tm_isdst = FALSE;
         return(t);
 }

 char *asctime(time)
 register struct tm *time;
 /*
  *        Convert <time> structure value to a string.  The same format, and
  *        the same internal buffer, as for ctime() is used for this function.
  */
 {
         sprintf(timebuf, "%3s %3s %02d %02d:%02d:%02d %04d\n",
                 day[time->tm_wday], month[time->tm_mon], time->tm_mday,
                 time->tm_hour, time->tm_min, time->tm_sec, time->tm_year+1900
         return(timebuf);
 }


 TIMER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\TIMER.C

 /* TIMER.C - From page 511 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. Checks the initime() and timeout()*/
 /* functions from the same page.                                */
 /****************************************************************/

 main()
 {
 long intval;

    while(1)  {
       printf("\n\nEnter interval (hundreds of a second): ");
       scanf("%D", &intval);
       initime(intval);              /*initialize timer*/
       printf("\n\nStart.\n");
       while(!timeout())
          ;
       printf("\n\nEnd.\n");
    }
 }

 /* initime() */   /* initializes time delay for timeout() function */
 /* delays number of hundredths of a second in argument */
 /* increments every 5 or 6 hundredths sec */

 <types.h>      /*defines time_b type in timeb*/
 <timeb.h>      /*defines time_b structure*/
 struct timeb xtime;     /*structure for time info*/
 long time1, time2;      /*start & running times*/
 long intval;            /*interval in hundredths*/

 initime(hsecs)
 long hsecs;
 {

    intval = (hsecs < 12) ? 12 : hsecs;    /*minimum is 12*/
    ftime(&xtime);
    time1 = (long)xtime.millitm/10 + xtime.time*100;
 }

 /* timeout() */   /* Returns 1 to function timer() */
 /* if time interval exceeded, 0 otherwise. */
 timeout()
 {

    ftime(&xtime);
    time2 = (long)xtime.millitm/10 + xtime.time*100;
    return((time2-time1 > intval) ? 1 : 0);
 }




 TIMER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLIBSSRC\TIMER.C

 #include <d:\usr\stdlib\time.h>

 long start_timer(t)
 TIMER *t;
 /*
  *        Start a 200Hz timer.  This timer value can later be checked with
  *        time_since() to determine elapsed time.  These functions provide
  *        a very low-overhead way of timing events.
  */
 {
         asm("        clr.l        -(sp)                ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* enter superv
         asm("        addq.l        #6,sp                ");
         asm("        move.l        $4BA,-(sp)        ");        /* save syste
         asm("        move.l        d0,-(sp)        ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* exit supervi
         asm("        addq.l        #6,sp                ");
         asm("        move.l        (sp)+,d0        ");
         asm("        move.l        $8(a6),a0        ");        /* grab pointe
         asm("        move.l        d0,(a0)                ");        /* retur
 }

 long time_since(t)
 TIMER *t;
 /*
  *        Returns the number of 200Hz ticks since start_timer() was called
  *        for timer <t>.
  */
 {
         asm("        clr.l        -(sp)                ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* enter superv
         asm("        addq.l        #6,sp                ");
         asm("        move.l        $4BA,-(sp)        ");        /* save syste
         asm("        move.l        d0,-(sp)        ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* exit supervi
         asm("        addq.l        #6,sp                ");
         asm("        move.l        (sp)+,d0        ");
         asm("        move.l        $8(a6),a0        ");        /* grab pointe
         asm("        sub.l        (a0),d0                ");        /* return
 }

 sleep(dt)
 int dt;
 /*
  *        Suspend operation for <dt> seconds.  This is implemented as a
  *        start_timer()/time_since() tight loop waiting for the specified
  *        amount of time to pass.  In a multi-tasking environment, this
  *        function should be replaced by a call which will de-activate
  *        this task for a period of time, allowing other tasks to run.
  */
 {
         long t, start_timer(), time_since();
         register long tt;

         tt = ((long) dt) * 200L;
         start_timer(&t);
         while(time_since(&t) < tt)
                 ;
 }


 TIMERS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\CSR20A\TIMERS.C

 /* timers.c
  *
  *        Return elapsed time (in tenths of seconds)
  *        since kick-off of timer.
  *
  *        D. Perras        03 Jan 1987
  *  Datalight C
  *
  *      B. Pritchett        05 Jan 1987
  *  Microsoft C Modifications
  *
   *        Routines included:
  *
  *                void        init_tmr()                Initialize the timer
  *                void        start_tmr()                Start the timer coun
  *        unsigned        stop_tmr()                Stop the timer, return re
  *        unsigned        read_tmr()                Read the elapsed time sin
  *                void        reset_tmr()                Reset the timer does
  *                void        zero_tmr()                Zero the timer (relat
  *
  *                 long         get_timer()                Return the PC's cu
  */

 <dos.h>  /* This is to include the REGS structure. */
                           /* It can be changed as needed for the compiler */


        MSC        1                /* references union: regs.x.cx vs. regs.cx

 long        timers[10], t_dvsr;
 int        timer_flag[10];

 #define         INIT_FLG        1
 #define         STRT_FLG        2
 #define         TMR_ON(j)                (timer_flag[(j)] & STRT_FLG)
 #define         TMR_INIT(j)        (timer_flag[(j)] & INIT_FLG)
 #define  TIMER_INT        0x1A

 #define         ERRVAL                0

 unsigned init_tmr()
 {
 /*        This routine does two timer calls and compares the return values
  *  just to be sure the timer is working.
  *        Return ERRVAL if error found, otherwise returns (unsigned) tm1
  */

         int i;
         unsigned tm1;
         long tmv, get_timer();

         for (i=0; i<10; i++)
                 timer_flag[i] = timers[i] = 0;
         tmv = get_timer();

         for (i=0; i<16000; i++)
                 ;                                        /* Null 'for' loop t
         tm1 = get_timer() - tmv;

 /* Currently, we test the result value for non-zero.  However, if the
  * system environment demands it, a value range could be tested and the
  * t_dvsr variable assigned accordingly.  The 182 value is for IBM PC's
  * and compatibles.
  */

         if (tm1 != 0)
                 for (i=0; i<10; i++)
                         timer_flag[i] |= INIT_FLG;
         else tm1 = ERRVAL;
         t_dvsr = 182;
         return tm1;
 }

 void start_tmr(x)
 int x;
 {
 /*        This routine picks up the current time stored by the timer
  *        and puts it in timers[x].
  *        It also set the 'timer started indicator'
  *        It returns nothing.
  */

         long get_timer();

         x = abs(x)%10;

         if (TMR_INIT(x) && !TMR_ON(x)) {
                 timers[x] = get_timer();
                 timer_flag[x] |= STRT_FLG;
         }
 }

 unsigned stop_tmr(x)
 int x;
 {
 /*        This routine stops the timer and returns the difference
  *        between the count stored by the start_tmr and the timer
  *        count at the point of stopping.
  *  The difference is made significant to the tenths-of-seconds.
  */

         unsigned tmp;
         long        tmp1, get_timer();

         x = abs(x)%10;

         if (TMR_ON(x)) {
                 tmp1 = get_timer()-timers[x];
                 timer_flag[x] &= ~STRT_FLG;
                 tmp1 *= 100;
                 tmp1 /=  t_dvsr;
                 timers[x] = 0;
                 tmp = tmp1;
                 return tmp;
         } else return ERRVAL;
 }

 unsigned read_tmr(x)
 int x;
 {
 /*        This routine works line stop_tmr except that the timer is
  *        is not stopped.  The elapsed time is returned and the timer
  *        is continued.
  *  Successive calls to read_tmr will return successivelly greater values.
  */

         unsigned tmp;
         long        tmp3, get_timer();

         x = abs(x)%10;

         if (TMR_ON(x)) {
                 tmp3 = get_timer()-timers[x];
                 tmp3 *= 100;
                 tmp3 /= t_dvsr;
                 tmp = tmp3;
                 return tmp;
         } else return ERRVAL;
 }

 void reset_tmr(x)
 int x;
 {
 /* This function resets the specified timer to 0
  * and clears the TMR_ON flag.  It does not return
  * a value.
  */

         x = abs(x)%10;

         if (TMR_ON(x)) {
                 timers[x] = 0;
                 timer_flag[x] &= ~STRT_FLG;
         }
 }

 void zero_tmr(x)
 int x;
 {
 /*  This function zeros the specified timer relative to the time it
  *  is called.  The timer operation is continued.
  *  It does not return a timer value.
  */

         long get_timer();


         x = abs(x)%10;

         if (TMR_ON(x)) {
                 timers[x] = get_timer();
         }
 }


 long get_timer()
 {
 /*        This routine returns the value in the PC's timer
  *        It is placed here so that the int86 call can be
  *  changed, if needed, without effecting the code above.
  */


         static long        tmp1;
 #ifdef MSC
         static union REGS regs;
 #else
         static REGS regs;
 #endif
         static int flags;

 #ifdef MSC
                 regs.x.ax = 0;
                 flags = int86(TIMER_INT,&regs,&regs);
                 tmp1 = regs.x.cx * 65536 + regs.x.dx;
 #else
                 regs.ax = 0;
                 flags = int86(TIMER_INT,&regs,&regs);
                 tmp1 = regs.cx  * 65536 + regs.dx;
 #endif
                 return(tmp1);
 }

 /* end of timers.c        */


 TIMEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TIMEX\TIMEX.C

 /*
                 Time a DOS command and display its exit code.
                         Portability of this program  approaches zero.
                         Note that the program contains functions which
                         are peculiar to the Lattice C library, and
                         that it references locations peculiar to the
                         IBM PC's memory map . Portability to workalikes is
                         unknown.  Invoking the program with no arguments
                         on the commandline produces a help screen.
                         Noncommercial distribution of source and object
                         code is permitted and encouraged provided that
                         this notice is left intact.


                                                                         Ken R
                                                                         Rt #2
                                                                         Watki
                                                                         July
 */

 #include <stdio.h>
 char *malloc();

 main(argc,argv)
     int argc;
     char **argv;
     {
         float ticki, tickf;                        /* initial and final clock
         int code;                                        /* dos return code *
         unsigned i = 0,buf[2];                /* holds 32-bit clock tick coun
         char *nargv[32];                        /* new commandline argument v
         extern char *helptxt[];                /* the help screen */

         if (argc == 1)
                 help(helptxt);

         while (--argc > 0) {
                 if ((nargv[i] = malloc(strlen(argv[i+1]))) == NULL) {
                         fprintf(stderr,"timex: out of memory timing %s\n",arg
                         exit(1);
                 }
                 strcpy(nargv[i],argv[i+1]);
                 i++;
         }
         nargv[i] = NULL;

         peek(0x0040,0x006c,buf,4);
         ticki = (0x1000 * (float)buf[1]) + (float)buf[0];

         if (forkvp(argv[1],nargv)) {
                 fprintf(stderr,"timex: cannot find %s for timing\n",nargv[0])
                 exit(1);
                 }

         code = wait();
         peek(0x0040,0x006c,buf,4);
         tickf = (0x1000 * (float)buf[1]) + (float)buf[0];
         printf("\n%9.1fs   (%d)\n",(tickf-ticki) * 0.0549254,code);
         }

 /*
         help module:  function and text
 */

 help(mesg)
 char **mesg;
 {
         while (*mesg != NULL)
                 puts(*mesg++);
                 exit(0);
 }

 char *helptxt[] = {
 "\nDisplays the running time and exit code of a program.\n",
 "              Usage: timex <commandline>\n",
 "Where <commandline>  is any COM or EXE program in the current",
 "directory or command search path and its associated arguments",
 "and parameters.     The timex command won't time BAT files or",
 "resident DOS commands (COPY, e.g.).  Run time is displayed in",
 "seconds to the nearest tenth,  and the exit code is displayed",
 "as an eight-bit integer set off by parentheses.      Internal",
 "resolution of the timer is ca. 0.055 seconds.   Noncommercial",
 "distribution  of this  program  is  permitted  and encouraged",
 "provided that this notice is left intact.\n",
 "          Ken Rice  Rt #2  Watkinsville GA 30677",
 NULL };


 TIPC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\TIPC.C

 /*
  * The routines in this file provide support for the TI-PC and other
  * compatible terminals. It goes directly to the graphics RAM to do
  * screen output. It compiles into nothing if not a TI-PC driver
  */

 termdef 1                       /* don't define "term" external */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     TIPC

 NROW    25                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
 MARGIN  8                       /* size of minimim margin and   */
 SCRSIZ  64                      /* scroll size for extended lines */
 NPAUSE  200                     /* # times thru update to pause */
 BEL     0x07                    /* BEL character.               */
 ESC     0x1B                    /* ESC character.               */
 SPACE   32                      /* space character              */
 SCADD   0xDE000L                /* address of screen RAM        */

 CHAR_ENABLE     0x08            /* TI attribute to show char    */
 TI_REVERSE      0x10            /* TI attribute to reverse char */
 BLACK   0+CHAR_ENABLE           /* TI attribute for Black       */
 BLUE    1+CHAR_ENABLE           /* TI attribute for Blue        */
 RED     2+CHAR_ENABLE           /* TI attribute for Red         */
 MAGENTA 3+CHAR_ENABLE           /* TI attribute for Magenta     */
 GREEN   4+CHAR_ENABLE           /* TI attribute for Green       */
 CYAN    5+CHAR_ENABLE           /* TI attribute for Cyan        */
 YELLOW  6+CHAR_ENABLE           /* TI attribute for Yellow      */
 WHITE   7+CHAR_ENABLE           /* TI attribute for White       */


 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     timove();
 extern  int     tieeol();
 extern  int     tieeop();
 extern  int     tibeep();
 extern  int     tiopen();
 extern  int     tirev();
 extern        int        ticres();
 extern  int     ticlose();
 extern  int     tiputc();

 #if     COLOR
 extern  int     tifcol();
 extern  int     tibcol();

 int     cfcolor = -1;           /* current forground color */
 int     cbcolor = -1;           /* current background color */
 int     ctrans[] =              /* ansi to ti color translation table */
         {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE};
 #endif

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         tiopen,
         ticlose,
         ttgetc,
         tiputc,
         ttflush,
         timove,
         tieeol,
         tieeop,
         tibeep,
         tirev,
         ticres
 #if     COLOR
         , tifcol,
         tibcol
 #endif
 };

 extern union REGS rg;

 #if     COLOR
 setatt( attr )
 int attr;
 {
         rg.h.ah = 0x16;         /* set the forground character attribute */
         rg.h.bl = attr;
         int86( 0x49, &rg, &rg );
 }

 tifcol(color)           /* set the current output color */

 int color;      /* color to set */

 {
         cfcolor = ctrans[color];
         setatt ( cfcolor );
 }

 tibcol(color)           /* set the current background color */

 int color;      /* color to set */

 {
         cbcolor = ctrans[color];
 }
 #endif

 timove(row, col)
 {
         rg.h.ah = 2;            /* set cursor position function code */
         rg.h.dh = col;
         rg.h.dl = row;
         int86(0x49, &rg, &rg);
 }

 tieeol()        /* erase to the end of the line */

 {
         int ccol;       /* current column cursor lives */
         int crow;       /*         row  */

         /* find the current cursor position */
         rg.h.ah = 3;            /* read cursor position function code */
         int86(0x49, &rg, &rg);
         ccol = rg.h.dh;         /* record current column */
         crow = rg.h.dl;         /* and row */

         rg.h.ah = 0x09;         /* Write character at cursor position */
         rg.h.al = ' ';          /* Space */
         rg.h.bl = cfcolor;
         rg.x.cx = NCOL-ccol;    /* Number of characters to write */
         int86(0x49, &rg, &rg);

 }

 tiputc(ch)      /* put a character at the current position in the
                    current colors */

 int ch;

 {
         rg.h.ah = 0x0E;         /* write char to screen with current attrs */
         rg.h.al = ch;
         int86(0x49, &rg, &rg);
 }

 tieeop()                        /* Actually a clear screen */
 {

         rg.h.ah = 0x13;         /* Clear Text Screen and Home Cursor */
         int86(0x49, &rg, &rg);
 }

 tirev(state)            /* change reverse video state */

 int state;      /* TRUE = reverse, FALSE = normal */

 {
         setatt( state ? cbcolor : cfcolor  );
 }

 ticres()        /* change screen resolution */

 {
         return(TRUE);
 }

 spal()                /* change palette string */

 {
         /*        Does nothing here        */
 }

 tibeep()
 {
         bdos(6, BEL, 0);
 }

 tiopen()
 {
         strcpy(sres, "NORMAL");
         revexist = TRUE;
         ttopen();
 }

 ticlose()

 {
 #if     COLOR
         tifcol(7);
         tibcol(0);
 #endif
         ttclose();
 }
 #else
 tihello()
 {
 }
 #endif



 TM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\CSR20A\TM.C

 #include <color.h>

 main()
  {
   int c = 0;
   int w;
   int w2;
   save_cursor();
   color(WHT_F+BLU_B);
   w = wopen(2,3,10,10,1);
   color(BLU_F+WHT_B);
   w2 = wopen(7,7,20,30,3);
   for ( c = 0; c < 5; ++c )
    {
     wactivate(w);
     delay(25);
     wactivate(w2);
     delay(25);
    }
   for ( c = 0; c < 50; ++c )
       wprintf(w2,"wprintf() - %02d\n",c);
   wprintf(w2,"wprintf() - %02d",c);
   getch();
   wblank(w2,3);
   getch();
   wprint(w2,"\f  Header, Static.\n");
   whline(w2,1);
   wputat(w2,wrow(w2)-1,0,"  Footer, Static.");
   whline(w2,wrow(w2)-2);
   wfreeze(w2,2,wrow(w2)-3);
   wgotoxy(w2,2,0);
   getch();
   for ( c = 0; c < 50; ++c )
       wprintf(w2,"wprintf() - %02d\n",c);
   wprintf(w2,"wprintf() - %02d",c);
   getch();
   wcloseall();
   restore_cursor();
  }

 delay(x)
  int x;
  {
   int i = 0;
   while ( i < x )
         ++x;
  }


 TOKEN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\TOKEN.C

 /*
  * Bob Denny         28-Aug-82  Remove reference to stdio.h
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 #include <lex.h>

 extern char *llend, llbuf[];

 char *token(cpp)
 char **cpp;
 {
         if (cpp)
                 *cpp = llend;
         return(llbuf);
 }


 TOLOWER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC1\TOLOWER.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         int
 tolower(c)                /* returns lower case of c, if a letter.        */

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (TOLOWER(c));
 }


 TONE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\TONE.C

 /* Program: tone.c */
 /* #include <tone.c> */
 /* Usage: tone(freq,time); */

 TIMERMODE 182                /* Code to put timer in right mode */
 FREQSCALE 1190000L        /* basic time frequency in Hz */
 TIMESCALE 1230L                /* number of counts in .1 second */
 T_MODEPORT 67                /* port controls timer mode */
 FREQPORT 66                        /* port controls tone frequency */
 BEEPPORT 97                        /* port controls speaker */
 ON 79                                /* signal to turn speaker on */

 tone(freq,time)
 int freq, time;
 {
         int hibyt, lobyt, port;
         long i, count, divisor;

         divisor=FREQSCALE/freq;                /* scale frequency to timer un
         lobyt=divisor % 256;                /* break integer into */
         hibyt=divisor / 256;                /* two bytes */
         count=TIMESCALE*time;                /* convert time to TIMER unites
         outp(T_MODEPORT,TIMERMODE);        /* prepare timer for input */
         outp(FREQPORT,lobyt);                /* set low byte of timer registe
         outp(FREQPORT,hibyt);                /* set high byte of timer regist
         port=inp(BEEPPORT);                /* save port setting */
         outp(BEEPPORT,ON);                /* turn speaker on */
         for(i=0; i<count; i++)
         ;
         outp(BEEPPORT,port);                /* turn speaker off, restore sett
 }


 TONE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\TONE.C

 /* Program: tone.c */
 /* #include <tone.c> */
 /* Usage: tone(freq,time); */

 TIMERMODE 182                /* Code to put timer in right mode */
 FREQSCALE 1190000L        /* basic time frequency in Hz */
 TIMESCALE 1230L                /* number of counts in .1 second */
 T_MODEPORT 67                /* port controls timer mode */
 FREQPORT 66                        /* port controls tone frequency */
 BEEPPORT 97                        /* port controls speaker */
 ON 79                                /* signal to turn speaker on */

 tone(freq,time)
 int freq, time;
 {
         int hibyt, lobyt, port;
         long i, count, divisor;

         divisor=FREQSCALE/freq;                /* scale frequency to timer un
         lobyt=divisor % 256;                /* break integer into */
         hibyt=divisor / 256;                /* two bytes */
         count=TIMESCALE*time;                /* convert time to TIMER unites
         outp(T_MODEPORT,TIMERMODE);        /* prepare timer for input */
         outp(FREQPORT,lobyt);                /* set low byte of timer registe
         outp(FREQPORT,hibyt);                /* set high byte of timer regist
         port=inp(BEEPPORT);                /* save port setting */
         outp(BEEPPORT,ON);                /* turn speaker on */
         for(i=0; i<count; i++)
         ;
         outp(BEEPPORT,port);                /* turn speaker off, restore sett
 }


 TONE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\TONE.C

 /* Program: tone.c */
 /* #include <tone.c> */
 /* Usage: tone(freq,time); */

 TIMERMODE 182        /* Code to put timer in right mode */
 FREQSCALE 1190000L   /* basic time frequency in Hz */
 TIMESCALE 1230L      /* number of counts in .1 second */
 T_MODEPORT 67        /* port controls timer mode */
 FREQPORT 66               /* port controls tone frequency */
 BEEPPORT 97               /* port controls speaker */
 ON 79                /* signal to turn speaker on */

 tone(freq,time)
 int freq, time;
 {
     int hibyt, lobyt, port;
     long i, count, divisor;

     divisor=FREQSCALE/freq;       /* scale frequency to timer units */
     lobyt=divisor % 256;          /* break integer into */
     hibyt=divisor / 256;          /* two bytes */
     count=TIMESCALE*time;         /* convert time to TIMER unites */
     outp(T_MODEPORT,TIMERMODE);   /* prepare timer for input */
     outp(FREQPORT,lobyt);         /* set low byte of timer register */
     outp(FREQPORT,hibyt);         /* set high byte of timer register */
     port=inp(BEEPPORT);      /* save port setting */
     outp(BEEPPORT,ON);       /* turn speaker on */
     for(i=0; i<count; i++)
     ;
     outp(BEEPPORT,port);          /* turn speaker off, restore setting */
 }


 TOS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\TOS.C

 /*
  * System-dependent routines for the Atari ST.
  */

 #include "stevie.h"

 #include <osbind.h>

 /*
  * The following buffer is used to work around a bug in TOS. It appears that
  * unread console input can cause a crash, but only if console output is
  * going on. The solution is to always grab any unread input before putting
  * out a character. The following buffer holds any characters read in this
  * fashion. The problem can be easily produced because STEVIE can't yet keep
  * up with the normal auto-repeat rate in insert mode.
  */
 #define        IBUFSZ        128

 static long inbuf[IBUFSZ];        /* buffer for unread input */
 static long *inptr = inbuf;        /* where to put next character */

 /*
  * inchar() - get a character from the keyboard
  *
  * Certain special keys are mapped to values above 0x80. These
  * mappings are defined in keymap.h. If the key has a non-zero
  * ascii value, it is simply returned. Otherwise it may be a
  * special key we want to map.
  *
  * The ST has a bug involving keyboard input that seems to occur
  * when typing quickly, especially typing capital letters. Sometimes
  * a value of 0x02540000 is read. This doesn't correspond to anything
  * on the keyboard, according to my documentation. My solution is to
  * loop when any unknown key is seen. Normally, the bell is rung to
  * indicate the error. If the "bug" value is seen, we ignore it completely.
  */
 int
 inchar()
 {
         for (;;) {
                 long c, *p;

                 /*
                  * Get the next input character, either from the input
                  * buffer or directly from TOS.
                  */
                 if (inptr != inbuf) {        /* input in the buffer, use it *
                         c = inbuf[0];
                         /*
                          * Shift everything else in the buffer down. This
                          * would be cleaner if we used a circular buffer,
                          * but it really isn't worth it.
                          */
                         inptr--;
                         for (p = inbuf; p < inptr ;p++)
                                 *p = *(p+1);
                 } else
                         c = Crawcin();

                 if ((c & 0xff) != 0)
                         return ((int) c);

                 switch ((int) (c >> 16) & 0xff) {

                 case 0x62: return K_HELP;
                 case 0x61: return K_UNDO;
                 case 0x52: return K_INSERT;
                 case 0x47: return K_HOME;
                 case 0x48: return K_UARROW;
                 case 0x50: return K_DARROW;
                 case 0x4b: return K_LARROW;
                 case 0x4d: return K_RARROW;
                 case 0x29: return K_CGRAVE;        /* control grave accent */

                 /*
                  * Occurs due to a bug in TOS.
                  */
                 case 0x54:
                         break;
                 /*
                  * Add the function keys here later if we put in support
                  * for macros.
                  */

                 default:
                         beep();
                         break;

                 }
         }
 }

 /*
  * get_inchars - snarf away any pending console input
  *
  * If the buffer overflows, we discard what's left and ring the bell.
  */
 static void
 get_inchars()
 {
         while (Cconis()) {
                 if (inptr >= &inbuf[IBUFSZ]) {        /* no room in buffer? *
                         Crawcin();                /* discard the input */
                         beep();                        /* and sound the alarm
                 } else
                         *inptr++ = Crawcin();
         }
 }

 void
 outchar(c)
 char        c;
 {
         get_inchars();
         Cconout(c);
 }

 void
 outstr(s)
 register char        *s;
 {
         get_inchars();
         Cconws(s);
 }

 #define        BGND        0
 #define        TEXT        3

 /*
  * vbeep() - visual bell
  */
 static void
 vbeep()
 {
         int        text, bgnd;                /* text and background colors *
         long        l;

         text = Setcolor(TEXT, -1);
         bgnd = Setcolor(BGND, -1);

         Setcolor(TEXT, bgnd);                /* swap colors */
         Setcolor(BGND, text);

         for (l=0; l < 5000 ;l++)        /* short pause */
                 ;

         Setcolor(TEXT, text);                /* restore colors */
         Setcolor(BGND, bgnd);
 }

 void
 beep()
 {
         if (P(P_VB))
                 vbeep();
         else
                 outchar('\007');
 }

 /*
  * remove(file) - remove a file
  */
 void
 remove(file)
 char *file;
 {
         Fdelete(file);
 }

 /*
  * rename(of, nf) - rename existing file 'of' to 'nf'
  */
 void
 rename(of, nf)
 char        *of, *nf;
 {
         Fdelete(nf);                /* if 'nf' exists, remove it */
         Frename(0, of, nf);
 }

 void
 windinit()
 {
         if (Getrez() == 0)
                 Columns = 40;                /* low resolution */
         else
                 Columns = 80;                /* medium or high */

         P(P_LI) = Rows = 25;

         Cursconf(1,NULL);
 }

 void
 windexit(r)
 int r;
 {
         exit(r);
 }

 void
 windgoto(r, c)
 int        r, c;
 {
         outstr("\033Y");
         outchar(r + 040);
         outchar(c + 040);
 }

 /*
  * System calls or library routines missing in TOS.
  */

 void
 sleep(n)
 int n;
 {
         int k;

         k = Tgettime();
         while ( Tgettime() <= k+n )
                 ;
 }

 void
 delay()
 {
         long        n;

         for (n = 0; n < 8000 ;n++)
                 ;
 }

 int
 system(cmd)
 char        *cmd;
 {
         char        arg[1];

         arg[0] = (char) 0;        /* no arguments passed to the shell */

         if (Pexec(0, cmd, arg, 0L) < 0)
                 return -1;
         else
                 return 0;
 }

 #ifdef        MEGAMAX
 char *
 strchr(s, c)
 char        *s;
 int        c;
 {
         do {
                 if ( *s == c )
                         return(s);
         } while (*s++);
         return(NULL);
 }
 #endif

 #ifdef        MEGAMAX

 FILE *
 fopenb(fname, mode)
 char        *fname;
 char        *mode;
 {
         char        modestr[10];

         sprintf(modestr, "b%s", mode);

         return fopen(fname, modestr);
 }

 #endif

 /*
  * getenv() - get a string from the environment
  *
  * Both Alcyon and Megamax are missing getenv(). This routine works for
  * both compilers and with the Beckemeyer and Gulam shells. With gulam,
  * the env_style variable should be set to either "mw" or "gu".
  */
 char *
 getenv(name)
 char *name;
 {
         extern long _base;
         char *envp, *p;

         envp = *((char **) (_base + 0x2c));

         for (; *envp ;envp += strlen(envp)+1) {
                 if (strncmp(envp, name, strlen(name)) == 0) {
                         p = envp + strlen(name);
                         if (*p++ == '=')
                                 return p;
                 }
         }
         return (char *) 0;
 }


 TOUPPER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC1\TOUPPER.C

 /* 1.0  07-06-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "ctype.h"

 /************************************************************************/
         int
 toupper(c)                /* returns upper case of c, if a letter.        */

 /*----------------------------------------------------------------------*/
 int c;
 {
         return (TOUPPER(c));
 }


 TOWERS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\TOWERS.C

 #include <stdio.h>

 /*
  *                 IBM RBBS-PC Tulsa, OK
  *                 Switching totally to the "C" Language
  *                 24 Hour operation 300/1200 baud XMODEM
  *                 918-664-8737
  *                 SYSOP LYNN LONG
  *
  *                  Towers of Hanoi
  *
  * The object of the game is to transfer the disks from
  * the leftmost tower to the rightmost tower obeying the
  * following set of rules:
  *
  * 1) Only the top disk of any tower may be moved at a time
  * 2) At no time must a larger disk be placed on a smaller disk
  *
  */

 #define FORMFEED                0x0c
 #define ESC                                0x1b

 #define POST                        0xba
 #define POST_BASE                0xca
 #define BASE                        0xcd
 #define RING                        0xdc

 #define SCREEN_WIDTH        80
 #define SCREEN_HEIGHT        25

 #define RING_WIDTH                ((((SCREEN_WIDTH - 2)/3) & 0xfe)-1)
 #define LEFT_POST                (RING_WIDTH/2+1)
 #define CENTER_POST                (LEFT_POST+RING_WIDTH)
 #define RIGHT_POST                (LEFT_POST+2*RING_WIDTH)

 #define MOVING_ROW                2
 #define BASE_ROW                15
 #define POST_HEIGHT                11

 char top[3]={ BASE_ROW-1, BASE_ROW-1, BASE_ROW-1 };
 int pause=0;


 main(argc, argv)
 int argc;
 char *argv[];
         {
         int nrings;

         if(argc < 1  ||  argc > 3)
                 abort("Use: hanoi [rings [delay]]\n");

         nrings = argc > 1 ? atoi(argv[1]) : 7;
         pause = argc > 2 ? atoi(argv[2]) : 1;

         setup(nrings);
         hanoi(nrings, 0, 2, 1);

         curse(0, SCREEN_HEIGHT-1);
         }


 hanoi(n, a, b, c)
 char n, a, b, c;
         {
         if(n == 0)
                 return;

         hanoi(n-1, a, c, b);
         movering(n, a, b);
         hanoi(n-1, c, b, a);
         }


 setup(n)
 char n;
         {
         char i;

         putchar(FORMFEED);

         for(i = MOVING_ROW+2; i < BASE_ROW; ++i) {
                 cput(LEFT_POST, i, POST);
                 cput(CENTER_POST, i, POST);
                 cput(RIGHT_POST, i, POST);
                 }

         curse(0, BASE_ROW);

         for(i = 1; i < SCREEN_WIDTH; ++i)
                 putchar(BASE);

         cput(LEFT_POST, BASE_ROW, POST_BASE);
         cput(CENTER_POST, BASE_ROW, POST_BASE);
         cput(RIGHT_POST, BASE_ROW, POST_BASE);

         for(i = n; i > 0; --i)
                 draw(i, LEFT_POST, top[0]--, RING);
         }


 curse(x, y)
 char x, y;
         {

         wait();

         putchar(ESC);
         putchar('=');
         putchar(y + ' ');
         putchar(x + ' ');
         }


 cput(x, y, ch)
 char ch;
 int x,y;
         {
         putchar(ESC);
         putchar('=');
         putchar(y + ' ');
         putchar(x + ' ');
         putchar(ch);
         wait();
         }


 draw(ring, centre, y, ch)
 char ring, centre, y, ch;
         {
         char i;

         curse(centre-ring, y);

         for(i=0; i<ring; ++i)
                 putchar(ch);

         curse(centre+1, y);

         for(i=0; i<ring; ++i)
                 putchar(ch);
         }


 movering(ring, from, to)
 char ring, from, to;
         {
         char fromc, toc;
         char fromy, toy;

         fromc = LEFT_POST + from * RING_WIDTH;
         toc = LEFT_POST + to * RING_WIDTH;
         fromy = ++top[from];
         toy = top[to]--;

         while(fromy != MOVING_ROW) {
                 draw(ring, fromc, fromy, ' ');
                 draw(ring, fromc, --fromy, RING);
                 }

         if(fromc < toc)
                 while(fromc != toc) {
                         cput(fromc-ring, fromy, ' ');
                         cput(fromc, fromy, RING);
                         cput(fromc+1, fromy, ' ');
                         cput(fromc+ring+1, fromy, RING);
                         ++fromc;
                         }
         else if (fromc > toc)
                 while(fromc != toc) {
                         cput(fromc+ring, fromy, ' ');
                         cput(fromc, fromy, RING);
                         cput(fromc-1, fromy, ' ');
                         cput(fromc-ring-1, fromy, RING);
                         --fromc;
                         }

         while(fromy != toy) {
                 draw(ring, fromc, fromy, ' ');
                 draw(ring, fromc, ++fromy, RING);
                 }
         }


 wait() {
         int i;

         i = 1 << pause;

         while(--i)
                 i = i;
         }




 TPRINT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\TPRINT\TPRINT.C


 /****************************************************************
 *                                                                *
 *                        P R I N T                                *
 *                                                                *
 *                ASCII file transfer to PRN device.                 *
 *                                                                *
 *        T. Jennings 6 Nov. 82                                        *
 *          created 23 Sept. 82                                        *
 *                                                                *
 ****************************************************************/

 #include <stdio.h>
 #include <ctype.h>

 #define        NUL        0x00
 #define        CR        0x0d
 #define        LF        0x0a
 #define        HT        0x09
 #define        FF        0x0c
 #define        DEL        0x7f

 #define        PAGELEN        66
 #define        BOTTOM        58
 FILE *printfile, *fopen();
 FILE *printer;
 char c;
 int line,column;
 int tabwidth;
 int formfeed;
 int number,lineno;
 int brackets,brkt_level;
 int pageno;
 int printable;
 int titles;
 int margin;
 int i;
 char filename[12];

 main(argc,argv)
 int argc;
 char **argv;
 {
         fprintf(stderr,"\nFile Print Utility 6 Nov. 82\n");
         number =0;                /* dont number lines */
         titles= 0;                /* no top of page title */
         margin= 0;                /* no left margin tab */
         brackets =0;                /* dont count brackets */
         brkt_level =0;
         column =0;
         line =0;
         tabwidth =8;
         formfeed =1;
         lineno =0;                /* current line number, */
         pageno =1;
         printable =0;

         if (--argc) {
                 if ((printfile=fopen(*++argv,"r")) ==NULL) {
                         fprintf(stderr,"PRINT: Can't find file '%s'.\n",*argv
                         exit();
                 }
                 strcpy(filename,*argv);                /* save filename for t

                 if ((printer= fopen("PRN","w")) ==NULL) {
                         fprintf(stderr,"PRINT: Can't open LST device\n");
                         exit();
                 }
                 while (--argc) {                /* look for options */
                         c= **++argv;
                         switch(tolower(c)) {
                         case 't':
                                 fprintf(stderr,"\t-Page headers\n");
                                 titles= 1;
                                 break;
                         case 'n':                /* line numbers */
                                 fprintf(stderr,"\t-Line numbers\n");
                                 number =1;
                                 break;
                         case 'c':                /* C source */
                                 fprintf(stderr,"\t-'C' source\n");
                                 brackets =1;
                                 break;
                         case 'm':
                                 fprintf(stderr,"\t-Left margin\n");
                                 margin= 1;
                                 break;
                         default:
                                 fprintf(stderr,"Illegal option: '%s'\n",*argv
                                 break;
                         }
                 }
                 title();
                 printchar(LF);
                 while ((i=fgetc(printfile)) !=EOF) {
                         c=i;                        /* type conversion, */
                         printchar(c);                /* print character, */
                         if (c =='{')                /* count bracket levels,
                                 ++brkt_level;
                         if (c == '}') {                /* if closing bracket,
                                 if ((--brkt_level ==0) && brackets) {
                                         printchar(FF); /* top level, formfeed
                                 }
                         }
                 }
                 fputc(LF,printer);
                 fputc(FF,printer);                /* do a formfeed, */
                 exit();
         }
         fprintf(stderr,"\nYou must specify a file, followed by any options");
         fprintf(stderr,"\n\tT\tTop of page headers");
         fprintf(stderr,"\n\tN\tLine numbers");
         fprintf(stderr,"\n\tC\tC source");
         fprintf(stderr,"\n\tM\tLeft margin");
         fprintf(stderr,"\nExample:  PRINT <filename> N C T M");
         exit();
 }
 /* Print character <C> to the printer. */

 printchar(c)
 char c;
 {
         switch (c) {
         case LF:
                 ++lineno;
                 fputc(CR,printer);
                 fputc(c,printer);                /* then line feed, */
                 if (++line >= BOTTOM)                 /* if bottom margin, */
                         printchar(FF);                /* formfeed, */
                 if (number)
                         fprintf(printer,"%3d: \t",lineno);
                 if (margin)
                         printchar(HT);                /* left margins */
                 break;
         case FF:
                 fputc(LF,printer);
                 fputc(c,printer);
                 line =0; ++pageno;
                 title();
                 break;
         default:
                 fputc(c,printer);
                 break;
         }
         return;
 }
 /* If the title flag is set, type the title across the top of the page. */

 title() {
         if (titles) {
                 fprintf(printer,"File: %-12s%58sPage %d\n",filename," ",pagen
                 ++line;
         }
         return;
 }


 TPRINT1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\PRNT\TPRINT1\TPRINT1.C


 /****************************************************************
 *                                                                *
 *                        P R I N T                               *
 *                                                                *
 *                ASCII file transfer to PRN device.              *
 *                                                                *
 *        T. Jennings 6 Nov. 82                                   *
 *          created 23 Sept. 82                                   *
 *                                                                *
 *          revised 14 Nov.  85    Steve Ripley                   *
 *                                                                *
 ****************************************************************/

 #include <stdio.h>
 #include <ctype.h>

 #define  NUL     0x00
 #define  CR      0x0d
 #define  LF      0x0a
 #define  HT      0x09
 #define  FF      0x0c
 #define  DEL     0x7f

 #define  PAGELEN 66
 #define  BOTTOM  58

 struct srv {int ax,bx,cx,dx,si,di,ds,es;};

 struct srv reg;

 char *months[] = {
                "Januaary ",
                "February ",
                "March ",
                "April ",
                "May ",
                "June ",
                "July ",
                "August ",
                "September ",
                "October ",
                "November ",
                "December "
                };

 FILE *printfile, *fopen();
 FILE *printer;
 char cin, temp[5];
 int line,column;
 int tabwidth;
 int formfeed;
 int number,lineno;
 int brackets,brkt_level;
 int pageno;
 int printable;
 int titles;
 int margin;
 int i;
 char filename[12];
 char  *date,
       hour,minute,second;

 main(argc,argv)
 int argc;
 char **argv;
 {
       getdate();
       gettime();
         fprintf(stderr,"\nFile Print Utility 6 Nov. 82\n");
         number =0;               /* dont number lines */
         titles= 0;               /* no top of page title */
         margin= 0;               /* no left margin tab */
         brackets =0;             /* dont count brackets */
         brkt_level =0;
         column =0;
         line =0;
         tabwidth =8;
         formfeed =1;
         lineno =0;               /* current line number, */
         pageno =1;
         printable =0;

         if (--argc) {
                 if ((printfile=fopen(*++argv,"r")) ==NULL) {
                         fprintf(stderr,"PRINT: Can't find file '%s'.\n",*argv
                         exit();
                 }
                 strcpy(filename,*argv);          /* save filename for title *
                 upper(filename);

                 if ((printer= fopen("PRN","w")) ==NULL) {
                         fprintf(stderr,"PRINT: Can't open LST device\n");
                         exit();
                 }
                 while (--argc) {         /* look for options */
                         cin= **++argv;
                         switch(tolower(cin)) {
                         case 't':
                                 fprintf(stderr,"\t-Page headers\n");
                                 titles= 1;
                                 break;
                         case 'n':                /* line numbers */
                                 fprintf(stderr,"\t-Line numbers\n");
                                 number =1;
                                 break;
                         case 'c':                /* C source */
                                 fprintf(stderr,"\t-'C' source\n");
                                 brackets =1;
                                 break;
                         case 'm':
                                 fprintf(stderr,"\t-Left margin\n");
                                 margin= 1;
                                 break;
                         default:
                                 fprintf(stderr,"Illegal option: '%s'\n",*argv
                                 break;
                         }
                 }
                 title();
                 printchar(LF);
                 while ((i=fgetc(printfile)) !=EOF) {
                         cin=i;                     /* type conversion, */
                         printchar(cin);            /* print character, */
                         if (cin =='{')             /* count bracket levels, *
                                 ++brkt_level;
                         if (cin == '}') {          /* if closing bracket, and
                                 if ((--brkt_level ==0) && brackets) {
                                         printchar(FF); /* top level, formfeed
                                 }
                         }
                 }
                 fputc(LF,printer);
                 fputc(FF,printer);               /* do a formfeed, */
                 fprintf(printer,"\033J");        /* motor off, */
                 exit();
         }
         fprintf(stderr,"\nYou must specify a file, followed by any options");
         fprintf(stderr,"\n\tT\tTop of page headers");
         fprintf(stderr,"\n\tN\tLine numbers");
         fprintf(stderr,"\n\tC\tC source");
         fprintf(stderr,"\n\tM\tLeft margin");
         fprintf(stderr,"\nExample:  PRINT <filename> N C T M");
         exit();
 }
 /* Print character <C> to the printer. */

 printchar(c)
 char c;
 {
         switch (c) {
         case LF:
                 ++lineno;
                 fputc(CR,printer);
                 fputc(c,printer);                /* then line feed, */
                 if (++line >= BOTTOM)            /* if bottom margin, */
                         printchar(FF);           /* formfeed, */
                 if (number)
                         fprintf(printer,"%3d: \t",lineno);
                 if (margin)
                         printchar(HT);           /* left margins */
                 break;
         case FF:
                 fputc(LF,printer);
                 fputc(c,printer);
                 line =0; ++pageno;
                 title();
                 break;
         default:
                 fputc(c,printer);
                 break;
         }
         return;
 }
 /* If the title flag is set, type the title across the top of the page. */

 title() {
    if (titles) {
        fprintf(printer,
            "\015Date: %s   Time: %02d:%02d:%02d   File: %-12s   %sPage %d",
            date,hour,minute,second,filename," ",pageno);
        fprintf(printer,
            "\015Date: %s   Time: %02d:%02d:%02d   File: %-12s   %sPage %d\n",
            date,hour,minute,second,filename," ",pageno);
       ++line;
    }
    else
       if (pageno == 1) {
        fprintf(printer,"\015Date: %s   Time: %02d:%02d:%02d   File: %-12s",
            date,hour,minute,second,filename);
        fprintf(printer,"\015Date: %s   Time: %02d:%02d:%02d   File: %-12s\n",
            date,hour,minute,second,filename);
        ++line;
       }
    return;
 }

 getdate()
 {
    date = calloc(1,25);
    reg.ax = 0x2a << 8;
    sysint21(&reg,&reg);
    strcpy(date,months[(reg.dx >> 8) - 1]);
    itoa(reg.dx & 0xff,temp);
    strcat(date,temp);
    strcat(date,", ");
    itoa(reg.cx,temp);
    strcat(date,temp);
    return;
 }
 gettime()
 {
    reg.ax = 0x2c << 8;
    sysint21(&reg,&reg);
    hour = reg.cx >> 8;
    minute = reg.cx & 0xff;
    second = reg.dx >> 8;
    return;
 }


 TPRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TPRT.C


 /*
    Test program for checking CTask printer buffering.
 */

 #include <stdio.h>
 #include <conio.h>
 #include <process.h>
 #include <ctype.h>

 #include "tsk.h"
 #include "prt.h"

 PORT 0    /* LPT1 (mono card) */
 POLL 0    /* Set to 1 to use polling */

 #if (TSK_NAMED)
 extern void snapshot (FILE *f);
 #endif

 #define STACKSIZE 2048

 word _stklen = 3 * STACKSIZE;  /* For Turbo C: Two tasks + main Task Stack */

 tcb tcb1, tcb2;
 flag halt, ready;

 byte xmtbuf [1024];
 int endrun;

 FILE *pfile;


 void far task1 (void)
 {
    int i;

    printf ("Task 1 started\n");

    /* Copy file into printer pipe. Using a larger file buffer would be more
       efficient, but this is only a demo.
    */

    while (!endrun && ((i = getc (pfile)) != EOF))
       prt_write (PORT, (byte)i, 0L);

    if (endrun)
       return;

    /* Wait for printer to complete output. */

    if (!prt_complete (PORT))
       puts ("Waiting for Printer");
    prt_wait_complete (PORT, 0L);

    /* Stop program */

    set_flag (&halt);
    set_flag (&ready);
 }


 /*
    Second task just for fun. Echoes keyboard characters, aborts printing
    when 'e' is entered. Also outputs snapshot dump on 'd'.
 */

 void far task2 (void)
 {
    int ch;

    printf ("Task 2 started\n");
    while (!endrun)
       {
       ch = t_read_key () & 0xff;
       putch (ch);
       ch = tolower (ch);
       endrun = (ch == 'e');
 #if (TSK_NAMED)
       if (ch == 'd')
          snapshot (stdout);
 #endif
       }

    set_flag (&halt);
 }



 void main (int argc, char **argv)
 {
    char stack1 [STACKSIZE];
    char stack2 [STACKSIZE];

    if ((pfile = fopen (argv [1], "rb")) == NULL)
       {
       printf ("Error opening file '%s'\n", argv [1]);
       exit (1);
       }

    endrun = 0;
    install_tasker (0, 0);

    prt_install (PORT, POLL, PRI_STD, xmtbuf, sizeof (xmtbuf));

    create_task (&tcb1, task1, stack1, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK1"
 #endif
                 );
    create_task (&tcb2, task2, stack2, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK2"
 #endif
                 );
    create_flag (&halt
 #if (TSK_NAMEPAR)
                 ,"Halt"
 #endif
                 );
    create_flag (&ready
 #if (TSK_NAMEPAR)
                 ,"Ready"
 #endif
                 );

    start_task (&tcb1);
    start_task (&tcb2);

    preempt_on ();
    wait_flag_set (&halt, 0L);

    endrun = 1;
    puts ("******** Main Task *********");
    wait_flag_set (&ready, 0L);

    puts ("******** End Run *********");
    preempt_off ();
    prt_remove (PORT);
    remove_tasker ();

    fclose (pfile);
 }




 TR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TR.C

 /* filter to transliterate characters */

 /*        The program tr implements character transliteration and behaves the
  *        as the program in Software Tools by the same name.  It is a pure fi
  */


 #include <stdio.h>

 #define ESCAPE '@'
 #define MAXSET 400
 #define NOT '!'

 xindex(c, s, allbut, lastto) /* reverse sense of index if allbut = YES */
 register int c;
 char *s;
 int allbut, lastto;
 {
     int cindex();

     if(c == EOF)                                return -1;
     else if(allbut == NO)                return cindex(c, s);        /* tell
     else if(cindex(c, s) >= 0)        return -1;
     else                                                return lastto + 1;
 }

 cindex(c, s) /* Find index of character c in string s; return -1 if not found
 char c, s[];
 {
     register int i;

     for(i = 0; s[i] != '\0'; ++i)
         if(c == s[i]) return(i);
     return(-1);
 }

 char *esc(str) /* handle escape sequence; return pointer to "fixed" character
 register char *str;
 {

     if(*str != ESCAPE) return(str);     /* nothing to do */
     if(*(str + 1) == '\0') return(str); /* not special at end */
     if(*++str == 'b')    *str = '\b';
     else if(*str == 'f') *str = '\f';
     else if(*str == 'n') *str = '\n';
     else if(*str == 'q') *str = '"';
     else if(*str == 'r') *str = '\r';
     else if(*str == 's') *str = ' ';
     else if(*str == 't') *str = '\t';
     else if(*str == '0')
     {
     char buf[3];
     int atoh();

         buf[0] = *++str;
         buf[1] = *++str;
         buf[2] = '\0';
         *str = (char) atoh(buf);
     }
     return(str);
 }

 char *dodash(valid, s, start) /* expand *psetDASH*s into pset ... from valid
 char valid[];
 char *s;
 int start;
 {
     int cindex(), addchar();
     register int i, limit;

     if( (limit = cindex(*(s + 1), valid) ) < 0) /* not valid; literal dash */
     {
         addchar('-');
         return s;
     }
     ++s;
     for(i = start; i <= limit; i++)
             addchar(valid[];
     reun s;
 }

 static int count_set;
 static char *pset;

 main(arg,rgv)
 int ar;hr*rgv[];
 {
     int fill(), addchar(), strln) index(), getchar(), putchar()  char from[MA
     char *caller;
     int allbut, collapse;
     register int i, lastto, c;

     caller = *argv;
     if(argc = 1)
     {
         tfprintf(stder"sage: %s from [to]\n", caller);
       ext1);
     }
     pset = from;
     count_set = MAXSET;
     i = 0;
     if((++arv[i] == NOT)
     {            allbut = YES;
       i++;
     }    else
             allbut = NO

     if((*argv)[i] = '-')

        addchar'');
         i++;
    }
     if(fill(*argv + i) =NO
    {
         tfprint(tderr, "%s: romstis too large\n", caller);
      eit(2);
     }
     if(argc > 2)
     {
             count_set = MAXSET;
             pset = to;
           i = 0;
             if(*++ag)[i] == '-')
             {
                addchar('-');               i+;            }
         if(fill(*arv + i = NO)
         {
             tfprintf(stderr, "%s: to set is too large\n, caller)
            exit(2);
         }
         lastto = strlen(to) - 1;
     }
     else lastto = -1;

    if(strlen(from) > lastto || allbut == YES) collapse = YES;
   le                                      collapse = NO;

     for(;;)
     {
         i = xindex((c = getchar()), from, allbut, lastto);
       if(collapse == YES && i >= lastto && lastto >= 0)                /* col
         {
             putchar(to[lastto]);
             do i = xindex((c = getchar()), from, allbut, lastto);
                                 while(i >= lastto);
         }
         if(c == EOF) break;                         /* done */

         if( i >= 0 && lastto >= 0) putchar(to[i]);        /* transliterate */

         else if(i == -1) putchar(c);                                /* copy *


     }
 }

 addchar(c) /* add input character to end of set if there is room*
 char c;
 {
     if(--count_set >= 0)
     {
         *pset++ = c;
         retur YES;
     }
     else return NO
 }

 static char dgts[] = "0123456789"
 tatcchar lower[] = "abcdefghknprtuvwxyz";
 static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

 fill(str) /* expand input character set into pset */
 register char *str;
 {
     char *esc(), *dodash();
     int addchar(), cindex();
     register int i;

     for(; *str != '\0'; ++str)
         if(*str != '-' || *(str +1 = '\0') /* not dash or dash at end */
                     addchar( *( str = esc(str) ) );
         else if( (i = cindex(*(pset - 1), digits) ) >= 0)
                 str = dodash(digits, str, ++i);
         else if( (i = cindex(*(pset - 1), lower) ) >= 0)
                 str = dodash(lower, str, ++i);
         else if( (i = cindex(*(pset - 1), upper) ) >= 0)
             str = dodash(upper, str, ++i);
         else
                 addchar('-');          /* dash is literal with "other" before

     return addchar('\0');
 }


 TR1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\TR1.C

 #include <stdio.h>
 #include "sqcom.h"
 #include "sq.h"
 #define ERROR -1
 #define TRUE 1
 #define FALSE 0

 /* First translation - encoding of repeated characters
  * The code is byte for byte pass through except that
  * DLE is encoded as DLE, zero and repeated byte values
  * are encoded as value, DLE, count for count >= 3.
  */

 init_ncr()        /*initialize getcnr() */
 {
         state = NOHIST;
 }

 int
 getcnr(iob)
 FILE *iob;
 {
         switch(state) {
         case NOHIST:
                 /* No relevant history */
                 state = SENTCHAR;
                 return lastchar = getc_crc(iob);
         case SENTCHAR:
                 /* Lastchar is set, need lookahead */
                 switch(lastchar) {
                 case DLE:
                         state = NOHIST;
                         return 0;        /* indicates DLE was the data */
                 case EOF:
                         return EOF;
                 default:
                         for(likect = 1; (newchar = getc_crc(iob)) == lastchar
                                 ;
                         switch(likect) {
                         case 1:
                                 return lastchar = newchar;
                         case 2:
                                 /* just pass through */
                                 state = SENDNEWC;
                                 return lastchar;
                         default:
                                 state = SENDCNT;
                                 return DLE;
                         }
                 }
         case SENDNEWC:
                 /* Previous sequence complete, newchar set */
                 state = SENTCHAR;
                 return lastchar = newchar;
         case SENDCNT:
                 /* Sent DLE for repeat sequence, send count */
                 state = SENDNEWC;
                 return likect;
         default:
                 puts("Bug - bad state\n");
                 exit(1);
         }
 }


 TR2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\TR2.C

 /* #define DEBUG */
 #include <stdio.h>
 #include "sqcom.h"
 #include "sq.h"
 #define ERROR -1
 #define TRUE 1
 #define FALSE 0

 /******** Second translation - bytes to variable length bit strings *********


 /* This translation uses the Huffman algorithm to develop a
  * binary tree representing the decoding information for
  * a variable length bit string code for each input value.
  * Each string's length is in inverse proportion to its
  * frequency of appearance in the incoming data stream.
  * The encoding table is derived from the decoding table.
  *
  * The range of valid values into the Huffman algorithm are
  * the values of a byte stored in an integer plus the special
  * endfile value chosen to be an adjacent value. Overall, 0-SPEOF.
  *
  * The "node" array of structures contains the nodes of the
  * binary tree. The first NUMVALS nodes are the leaves of the
  * tree and represent the values of the data bytes being
  * encoded and the special endfile, SPEOF.
  * The remaining nodes become the internal nodes of the tree.
  *
  * In the original design it was believed that
  * a Huffman code would fit in the same number of
  * bits that will hold the sum of all the counts.
  * That was disproven by a user's file and was a rare but
  * infamous bug. This version attempts to choose among equally
  * weighted subtrees according to their maximum depths to avoid
  * unnecessarily long codes. In case that is not sufficient
  * to guarantee codes <= 16 bits long, we initially scale
  * the counts so the total fits in an unsigned integer, but
  * if codes longer than 16 bits are generated the counts are
  * rescaled to a lower ceiling and code generation is retried.
  */

 /* Initialize the Huffman translation. This requires reading
  * the input file through any preceding translation functions
  * to get the frequency distribution of the various values.
  */

 init_huff(ib)
 FILE *ib;
 {
         int c, i;
         int btlist[NUMVALS];        /* list of intermediate binary trees */
         int listlen;                /* length of btlist */
         unsigned int *wp;        /* simplifies weight counting */
         unsigned int ceiling;        /* limit for scaling */

         /* Initialize tree nodes to no weight, no children */
         init_tree();

         /* Build frequency info in tree */
         do {
                 c = getcnr(ib);
                 if(c == EOF)
                         c = SPEOF;
                 if(*(wp = &node[c].weight) !=  MAXCOUNT)
                         ++(*wp);
         } while(c != SPEOF);
 #ifdef DEBUG
         pcounts();        /* debugging aid */
 #endif
         ceiling = MAXCOUNT;

         do {        /* Keep trying to scale and encode */
                 if(ceiling != MAXCOUNT)
                         printf("*** rescaling ***, ");
                 scale(ceiling);
                 ceiling /= 2;        /* in case we rescale */
 #ifdef DEBUG
                 pcounts();        /* debugging aid */
 #endif

                 /* Build list of single node binary trees having
                  * leaves for the input values with non-zero counts
                  */
                 for(i = listlen = 0; i < NUMVALS; ++i)
                         if(node[i].weight != 0) {
                                 node[i].tdepth = 0;
                                 btlist[listlen++] = i;
                         }

                 /* Arrange list of trees into a heap with the entry
                  * indexing the node with the least weight at the top.
                  */
                 heap(btlist, listlen);

                 /* Convert the list of trees to a single decoding tree */
                 bld_tree(btlist, listlen);

                 /* Initialize the encoding table */
                 init_enc();

                 /* Try to build encoding table.
                  * Fail if any code is > 16 bits long.
                  */
         } while(buildenc(0, dctreehd) == ERROR);
 #ifdef DEBUG
         phuff();        /* debugging aid */
 #endif
         /* Initialize encoding variables */
         cbitsrem = 0;        /*force initial read */
         curin = 0;        /*anything but endfile*/
 }
 /*  */
 /* The count of number of occurrances of each input value
  * have already been prevented from exceeding MAXCOUNT.
  * Now we must scale them so that their sum doesn't exceed
  * ceiling and yet no non-zero count can become zero.
  * This scaling prevents errors in the weights of the
  * interior nodes of the Huffman tree and also ensures that
  * the codes will fit in an unsigned integer. Rescaling is
  * used if necessary to limit the code length.
  */

 scale(ceil)
 unsigned int ceil;        /* upper limit on total weight */
 {
         int c, ovflw, divisor, i;
         unsigned int w, sum;
         char increased;                /* flag */

         do {
                 for(i = sum = ovflw = 0; i < NUMVALS; ++i) {
                         if(node[i].weight > (ceil - sum))
                                 ++ovflw;
                         sum += node[i].weight;
                 }

                 divisor = ovflw + 1;

                 /* Ensure no non-zero values are lost */
                 increased = FALSE;
                 for(i = 0; i < NUMVALS; ++i) {
                         w = node[i].weight;
                         if (w < divisor && w > 0) {
                                 /* Don't fail to provide a code if it's used
                                 node[i].weight = divisor;
                                 increased = TRUE;
                         }
                 }
         } while(increased);

         /* Scaling factor choosen, now scale */
         if(divisor > 1)
                 for(i = 0; i < NUMVALS; ++i)
                         node[i].weight /= divisor;
 }
 /*  */
 /* heap() and adjust() maintain a list of binary trees as a
  * heap with the top indexing the binary tree on the list
  * which has the least weight or, in case of equal weights,
  * least depth in its longest path. The depth part is not
  * strictly necessary, but tends to avoid long codes which
  * might provoke rescaling.
  */

 heap(list, length)
 int list[], length;
 {
         int i;

         for(i = (length - 2) / 2; i >= 0; --i)
                 adjust(list, i, length - 1);
 }

 /* Make a heap from a heap with a new top */

 adjust(list, top, bottom)
 int list[], top, bottom;
 {
         int k, temp;
         char cmptrees();

         k = 2 * top + 1;        /* left child of top */
         temp = list[top];        /* remember root node of top tree */
         if( k <= bottom) {
                 if( k < bottom && cmptrees(list[k], list[k + 1]))
                         ++k;

                 /* k indexes "smaller" child (in heap of trees) of top */
                 /* now make top index "smaller" of old top and smallest child
                 if(cmptrees(temp, list[k])) {
                         list[top] = list[k];
                         list[k] = temp;
                         /* Make the changed list a heap */
                         adjust(list, k, bottom); /*recursive*/
                 }
         }
 }

 /* Compare two trees, if a > b return true, else return false
  * note comparison rules in previous comments.
  */

 char        /* Boolean */
 cmptrees(a, b)
 int a, b;        /* root nodes of trees */
 {
         if(node[a].weight > node[b].weight)
                 return TRUE;
         if(node[a].weight == node[b].weight)
                 if(node[a].tdepth > node[b].tdepth)
                         return TRUE;
         return FALSE;
 }
 /*  */
 /* HUFFMAN ALGORITHM: develops the single element trees
  * into a single binary tree by forming subtrees rooted in
  * interior nodes having weights equal to the sum of weights of all
  * their descendents and having depth counts indicating the
  * depth of their longest paths.
  *
  * When all trees have been formed into a single tree satisfying
  * the heap property (on weight, with depth as a tie breaker)
  * then the binary code assigned to a leaf (value to be encoded)
  * is then the series of left (0) and right (1)
  * paths leading from the root to the leaf.
  * Note that trees are removed from the heaped list by
  * moving the last element over the top element and
  * reheaping the shorter list.
  */

 bld_tree(list, len)
 int list[];
 int len;
 {
         int freenode;                /* next free node in tree */
         int lch, rch;                /* temporaries for left, right children
         struct nd *frnp;        /* free node pointer */
         int i;
         char maxchar();

         /* Initialize index to next available (non-leaf) node.
          * Lower numbered nodes correspond to leaves (data values).
          */
         freenode = NUMVALS;

         while(len > 1) {
                 /* Take from list two btrees with least weight
                  * and build an interior node pointing to them.
                  * This forms a new tree.
                  */
                 lch = list[0];        /* This one will be left child */

                 /* delete top (least) tree from the list of trees */
                 list[0] = list[--len];
                 adjust(list, 0, len - 1);

                 /* Take new top (least) tree. Reuse list slot later */
                 rch = list[0];        /* This one will be right child */

                 /* Form new tree from the two least trees using
                  * a free node as root. Put the new tree in the list.
                  */
                 frnp = &node[freenode];        /* address of next free node *
                 list[0] = freenode++;        /* put at top for now */
                 frnp->lchild = lch;
                 frnp->rchild = rch;
                 frnp->weight = node[lch].weight + node[rch].weight;
                 frnp->tdepth = 1 + maxchar(node[lch].tdepth, node[rch].tdepth
                 /* reheap list  to get least tree at top*/
                 adjust(list, 0, len - 1);
         }
         dctreehd = list[0];        /*head of final tree */
 }
 /*  */
 char
 maxchar(a, b)
 char a, b;
 {
         return a > b ? a : b;
 }
 /* Initialize all nodes to single element binary trees
  * with zero weight and depth.
  */

 init_tree()
 {
         int i;

         for(i = 0; i < NUMNODES; ++i) {
                 node[i].weight = 0;
                 node[i].tdepth = 0;
                 node[i].lchild = NOCHILD;
                 node[i].rchild = NOCHILD;
         }
 }

 init_enc()
 {
         int i;

         /* Initialize encoding table */
         for(i = 0; i < NUMVALS; ++i) {
                 codelen[i] = 0;
         }
 }
 /*  */
 /* Recursive routine to walk the indicated subtree and level
  * and maintain the current path code in bstree. When a leaf
  * is found the entire code string and length are put into
  * the encoding table entry for the leaf's data value.
  *
  * Returns ERROR if codes are too long.
  */

 int                /* returns ERROR or NULL */
 buildenc(level, root)
 int level;/* level of tree being examined, from zero */
 int root; /* root of subtree is also data value if leaf */
 {
         int l, r;

         l = node[root].lchild;
         r = node[root].rchild;
 #ifdef DEBUG
         if (debug) printf("level=%d,root=%d,l=%d,r=%d,tcode=%04x\n",level,roo
 #endif
         if( l == NOCHILD && r == NOCHILD) {
                 /* Leaf. Previous path determines bit string
                  * code of length level (bits 0 to level - 1).
                  * Ensures unused code bits are zero.
                  */
                 codelen[root] = level;
                 code[root] = tcode & ((unsigned int)(~0) >> ((sizeof(int) * 8
 #ifdef DEBUG
                 if (debug) printf("  codelen[%d]=%d,code[%d]=%02x\n",root,cod
 #endif
                 return (level > 16) ? ERROR : NULL;
         } else {
                 if( l != NOCHILD) {
                         /* Clear path bit and continue deeper */
                         tcode &= ~(1 << level);
                         /* NOTE RECURSION */
                         if(buildenc(level + 1, l) == ERROR)
                                 return ERROR;
                 }
                 if(r != NOCHILD) {
                         /* Set path bit and continue deeper */
                         tcode |= 1 << level;
                         /* NOTE RECURSION */
                         if(buildenc(level + 1, r) == ERROR)
                                 return ERROR;
                 }
         }
         return NULL;        /* if we got here we're ok so far */
 }
 /*  */
 /* Write out the header of the compressed file */

 wrt_head(ob, infile)
 FILE *ob;
 char *infile;        /* input file name (w/ or w/o drive) */
 {
         int i, k, l, r;
         int numnodes;                /* nbr of nodes in simplified tree */

         putwe(RECOGNIZE, ob);        /* identifies as compressed */
         putwe(crc, ob);                /* unsigned sum of original data */

         /* Record the original file name w/o drive */
         if(*(infile + 1) == ':')
                 infile += 2;        /* skip drive */

         do {
                 putce(*infile, ob);
         } while(*(infile++) != '\0');


         /* Write out a simplified decoding tree. Only the interior
          * nodes are written. When a child is a leaf index
          * (representing a data value) it is recoded as
          * -(index + 1) to distinguish it from interior indexes
          * which are recoded as positive indexes in the new tree.
          * Note that this tree will be empty for an empty file.
          */

         numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS -1);
         putwe(numnodes, ob);

         for(k = 0, i = dctreehd; k < numnodes; ++k, --i) {
                 l = node[i].lchild;
                 r = node[i].rchild;
                 l = l < NUMVALS ? -(l + 1) : dctreehd - l;
                 r = r < NUMVALS ? -(r + 1) : dctreehd - r;
                 putwe(l, ob);        /* left child */
                 putwe(r, ob);        /* right child */
         }
 }
 /*  */
 /* Get an encoded byte or EOF. Reads from specified stream AS NEEDED.
  *
  * There are two unsynchronized bit-byte relationships here.
  * The input stream bytes are converted to bit strings of
  * various lengths via the static variables named c...
  * These bit strings are concatenated without padding to
  * become the stream of encoded result bytes, which this
  * function returns one at a time. The EOF (end of file) is
  * converted to SPEOF for convenience and encoded like any
  * other input value. True EOF is returned after that.
  *
  * The original gethuff() called a seperate function,
  * getbit(), but that more readable version was too slow.
  */

 int                                /*  Returns byte values except for EOF */
 gethuff(ib)
 FILE *ib;
 {
         unsigned int rbyte;        /* Result byte value */
         char need, take;        /* numbers of bits */

         rbyte = 0;
         need = 8;                /* build one byte per call */

         /* Loop to build a byte of encoded data
          * Initialization forces read the first time
          */

 loop:
         if(cbitsrem >= need) {
                 /* Current code fullfills our needs */
                 if(need == 0)
                         return rbyte & 0xff;
                 /* Take what we need */
                  rbyte |= ccode << (8 - need);
                 /* And leave the rest */
                 ccode >>= need;
                 cbitsrem -= need;
                 return rbyte & 0xff;
         }

         /* We need more than current code */
         if(cbitsrem > 0) {
                 /* Take what there is */
                 rbyte |= ccode << (8 - need);
                 need -= cbitsrem;
         }
         /* No more bits in current code string */
         if(curin == SPEOF) {
                 /* The end of file token has been encoded. If
                  * result byte has data return it and do EOF next time
                  */
                 cbitsrem = 0;

                 return (need == 8) ? EOF : rbyte & 0xff;
         }

         /* Get an input byte */
         if((curin = getcnr(ib)) == EOF)
                 curin = SPEOF;        /* convenient for encoding */

         /* Get the new byte's code */
         ccode = code[curin];
         cbitsrem = codelen[curin];

         goto loop;
 }


 TRIVIAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\TRIVIAL.C

 main()
 {
 }


 TRY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\TRY.C

 /*
  * Simple test program for regexp(3) stuff.  Knows about debugging hooks.
  *
  *        Copyright (c) 1986 by University of Toronto.
  *        Written by Henry Spencer.  Not derived from licensed software.
  *
  *        Permission is granted to anyone to use this software for any
  *        purpose on any computer system, and to redistribute it freely,
  *        subject to the following restrictions:
  *
  *        1. The author is not responsible for the consequences of use of
  *                this software, no matter how awful, even if they arise
  *                from defects in it.
  *
  *        2. The origin of this software must not be misrepresented, either
  *                by explicit claim or by omission.
  *
  *        3. Altered versions must be plainly marked as such, and must not
  *                be misrepresented as being the original software.
  *
  * Usage: try re [string [output [-]]]
  * The re is compiled and dumped, regexeced against the string, the result
  * is applied to output using regsub().  The - triggers a running narrative
  * from regexec().  Dumping and narrative don't happen unless DEBUG.
  *
  * If there are no arguments, stdin is assumed to be a stream of lines with
  * five fields:  a r.e., a string to match it against, a result code, a
  * source string for regsub, and the proper result.  Result codes are 'c'
  * for compile failure, 'y' for match success, 'n' for match failure.
  * Field separator is tab.
  */
 #include <stdio.h>
 #include <regexp.h>

 #ifdef ERRAVAIL
 char *progname;
 extern char *mkprogname();
 #endif

 #ifdef DEBUG
 extern int regnarrate;
 #endif

 char buf[BUFSIZ];

 int errreport = 0;                /* Report errors via errseen? */
 char *errseen = NULL;                /* Error message. */
 int status = 0;                        /* Exit status. */

 /* ARGSUSED */
 main(argc, argv)
 int argc;
 char *argv[];
 {
         regexp *r;
         int i;

 #ifdef ERRAVAIL
         progname = mkprogname(argv[0]);
 #endif

         if (argc == 1) {
                 multiple();
                 exit(status);
         }

         r = regcomp(argv[1]);
         if (r == NULL)
                 error("regcomp failure", "");
 #ifdef DEBUG
         regdump(r);
         if (argc > 4)
                 regnarrate++;
 #endif
         if (argc > 2) {
                 i = regexec(r, argv[2]);
                 printf("%d", i);
                 for (i = 1; i < NSUBEXP; i++)
                         if (r->startp[i] != NULL && r->endp[i] != NULL)
                                 printf(" \\%d", i);
                 printf("\n");
         }
         if (argc > 3) {
                 regsub(r, argv[3], buf);
                 printf("%s\n", buf);
         }
         exit(status);
 }

 void
 regerror(s)
 char *s;
 {
         if (errreport)
                 errseen = s;
         else
                 error(s, "");
 }

 #ifndef ERRAVAIL
 error(s1, s2)
 char *s1;
 char *s2;
 {
         fprintf(stderr, "regexp: ");
         fprintf(stderr, s1, s2);
         fprintf(stderr, "\n");
         exit(1);
 }
 #endif

 int lineno;

 regexp badregexp;                /* Implicit init to 0. */

 multiple()
 {
         char rbuf[BUFSIZ];
         char *field[5];
         char *scan;
         int i;
         regexp *r;
         extern char *strchr();

         errreport = 1;
         lineno = 0;
         while (fgets(rbuf, sizeof(rbuf), stdin) != NULL) {
                 rbuf[strlen(rbuf)-1] = '\0';        /* Dispense with \n. */
                 lineno++;
                 scan = rbuf;
                 for (i = 0; i < 5; i++) {
                         field[i] = scan;
                         if (field[i] == NULL) {
                                 complain("bad testfile format", "");
                                 exit(1);
                         }
                         scan = strchr(scan, '\t');
                         if (scan != NULL)
                                 *scan++ = '\0';
                 }
                 try(field);
         }

         /* And finish up with some internal testing... */
         lineno = 9990;
         errseen = NULL;
         if (regcomp((char *)NULL) != NULL || errseen == NULL)
                 complain("regcomp(NULL) doesn't complain", "");
         lineno = 9991;
         errseen = NULL;
         if (regexec((regexp *)NULL, "foo") || errseen == NULL)
                 complain("regexec(NULL, ...) doesn't complain", "");
         lineno = 9992;
         r = regcomp("foo");
         if (r == NULL) {
                 complain("regcomp(\"foo\") fails", "");
                 return;
         }
         lineno = 9993;
         errseen = NULL;
         if (regexec(r, (char *)NULL) || errseen == NULL)
                 complain("regexec(..., NULL) doesn't complain", "");
         lineno = 9994;
         errseen = NULL;
         regsub((regexp *)NULL, "foo", rbuf);
         if (errseen == NULL)
                 complain("regsub(NULL, ..., ...) doesn't complain", "");
         lineno = 9995;
         errseen = NULL;
         regsub(r, (char *)NULL, rbuf);
         if (errseen == NULL)
                 complain("regsub(..., NULL, ...) doesn't complain", "");
         lineno = 9996;
         errseen = NULL;
         regsub(r, "foo", (char *)NULL);
         if (errseen == NULL)
                 complain("regsub(..., ..., NULL) doesn't complain", "");
         lineno = 9997;
         errseen = NULL;
         if (regexec(&badregexp, "foo") || errseen == NULL)
                 complain("regexec(nonsense, ...) doesn't complain", "");
         lineno = 9998;
         errseen = NULL;
         regsub(&badregexp, "foo", rbuf);
         if (errseen == NULL)
                 complain("regsub(nonsense, ..., ...) doesn't complain", "");
 }

 try(fields)
 char **fields;
 {
         regexp *r;
         char dbuf[BUFSIZ];

         errseen = NULL;
         r = regcomp(fields[0]);
         if (r == NULL) {
                 if (*fields[2] != 'c')
                         complain("regcomp failure in `%s'", fields[0]);
                 return;
         }
         if (*fields[2] == 'c') {
                 complain("unexpected regcomp success in `%s'", fields[0]);
                 free((char *)r);
                 return;
         }
         if (!regexec(r, fields[1])) {
                 if (*fields[2] != 'n')
                         complain("regexec failure in `%s'", "");
                 free((char *)r);
                 return;
         }
         if (*fields[2] == 'n') {
                 complain("unexpected regexec success", "");
                 free((char *)r);
                 return;
         }
         errseen = NULL;
         regsub(r, fields[3], dbuf);
         if (errseen != NULL) {
                 complain("regsub complaint", "");
                 free((char *)r);
                 return;
         }
         if (strcmp(dbuf, fields[4]) != 0)
                 complain("regsub result `%s' wrong", dbuf);
         free((char *)r);
 }

 complain(s1, s2)
 char *s1;
 char *s2;
 {
         fprintf(stderr, "try: %d: ", lineno);
         fprintf(stderr, s1, s2);
         fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : "");
         status = 1;
 }


 TSIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSIO.C


 /*
    Test program for checking the CTask serial I/O interface.
 */

 #include <stdio.h>
 #include <conio.h>
 #include <ctype.h>
 #include <process.h>

 #include "tsk.h"
 #include "sio.h"

 #if (TSK_NAMED)
 extern void snapshot (FILE *f);
 #endif

 PORT   0x80     /* COM1, relative */
 BAUD   9600L    /* Baudrate */


 #define STACKSIZE 2048

 word _stklen = 4 * STACKSIZE;  /* For Turbo C: Two tasks + main Task Stack */

 tcb tcb1, tcb2, tcb3;
 flag halt;
 sioptr siop;

 word rcvbuf [10000];
 byte xmtbuf [100];

 int endrun, err;

 /*
    Task 1 reads characters from the serial line and displays them on
    the screen. While the halt flag is set, characters are not read,
    so the XON/XOFF and RTS/CTS protocol can be tested for the receiving
    side.
 */

 void far task1 (void)
 {
    word ch;

    printf ("Task 1 started\n");
    while (!endrun)
       {
       wait_flag_clear (&halt, 0L);
       if (endrun)
          return;
       ch = v24_receive (siop, 0L);
       putch (ch);
       if (ch & 0xff00)
          {
          err = 1;
          printf ("\n%c*%02x*", ch, ch >> 8);
          }
       }
 }


 /*
    Task 2 reads characters from the keyboard and sends them to the
    serial port. If 'h' is entered, the halt flag is set, so task1
    stops reading. If 'c' is entered, the halt flag is cleared.
    Entering 'e' stops the program.
    'd' outputs snapshot dump.
 */

 void far task2 (void)
 {
    int ch;

    printf ("Task 2 started\n");
    while (!endrun)
       {
       ch = t_read_key () & 0xff;
       switch (tolower (ch))
          {
          case 'h':   set_flag (&halt);
                      puts ("-halt-");
                      break;

          case 'c':   clear_flag (&halt);
                      err = 0;
                      puts ("-continue-");
                      break;

          case 'e':   puts ("-end-");
                      endrun = 1;
                      clear_flag (&halt);
                      wake_task (NULL);
                      break;

 #if (TSK_NAMED)
          case 'd':   snapshot (stdout);
                      break;
 #endif

          default:    /* putch (ch); */
                      v24_send (siop, ch, 0L);
                      break;
          }
       }
 }


 main ()
 {
    char stack1 [STACKSIZE];
    char stack2 [STACKSIZE];

    endrun = 0;

    install_tasker (0, 0);
    siop = v24_install (PORT, 1, rcvbuf, sizeof (rcvbuf), xmtbuf, sizeof (xmtb

    if (siop == NULL)
       {
       remove_tasker ();
       printf ("Couldn't install COM-Port\n");
       exit (1);
       }
    v24_change_baud (siop, BAUD);
    v24_protocol (siop, XONXOFF | RTSCTS, 40, 60);

    create_task (&tcb1, task1, stack1, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK1"
 #endif
                 );
    create_task (&tcb2, task2, stack2, STACKSIZE, PRI_STD, NULL
 #if (TSK_NAMEPAR)
                 ,"TASK2"
 #endif
                 );

    create_flag (&halt
 #if (TSK_NAMEPAR)
                 ,"Halt"
 #endif
                 );

    start_task (&tcb1);
    start_task (&tcb2);

    preempt_on ();
    t_delay (0L);

    endrun = 1;
    puts ("******** Main Task *********");

    set_priority (NULL, 10);
    schedule ();
    delete_flag (&halt);

    preempt_off ();
 /*   v24_remove (siop, 1); */
    remove_tasker ();

    puts ("******** End Run *********");
 }



 TSKALLOC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKALLOC.C

 /*
    TSKALLOC.C - CTask - Dynamic memory allocation interface

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany

    This file is new with Version 1.1

    This module contains the memory allocation functions that are needed
    if TSK_DYNAMIC is defined.

 */

 #include "tsk.h"

 #if (TURBO)
 #include <alloc.h>
 #else
 #include <malloc.h>
 #endif

 #define xalloc(size) malloc (size)
 #define xfree(item)  free (item)

 resource alloc_resource;

 farptr tsk_alloc (word size)
 {
    farptr ptr;

    request_resource (&alloc_resource, 0L);
    ptr = xalloc (size);
    release_resource (&alloc_resource);

    return ptr;
 }


 void tsk_free (farptr item)
 {
    request_resource (&alloc_resource, 0L);
    xfree (item);
    release_resource (&alloc_resource);
 }



 TSKBUF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKBUF.C

 /*
    TSKBUF.C - CTask - Buffered Message handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany

    NOTE: None of the Buffer routines my be used from inside an interrupt
          handler. The routines are relatively slow, since they use
          the normal word pipe and resource calls. Optimization would be
          possible by using block moves and internally handling resources.
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"


 bufferptr far create_buffer (bufferptr buf, farptr pbuf, word bufsize
 #if (TSK_NAMEPAR)
                         ,byteptr name
 #endif
                         )
 {
 #if (TSK_DYNAMIC)
    if (buf == NULL)
       {
       if ((buf = tsk_alloc (sizeof (buffer))) == NULL)
          return NULL;
       buf->flags = F_TEMP;
       }
    else
       buf->flags = 0;
    if (pbuf == NULL)
       {
       if ((pbuf = tsk_alloc (bufsize)) == NULL)
          {
          if (buf->flags & F_TEMP)
             tsk_free (buf);
          return NULL;
          }
       buf->flags |= F_STTEMP;
       }
 #endif

    create_wpipe (&buf->pip, pbuf, bufsize
 #if (TSK_NAMEPAR)
                  ,name
 #endif
                  );
    create_resource (&buf->buf_read
 #if (TSK_NAMEPAR)
                  ,name
 #endif
                  );
    create_resource (&buf->buf_write
 #if (TSK_NAMEPAR)
                  ,name
 #endif
                  );
    buf->msgcnt = 0;

 #if (TSK_NAMED)
    tsk_add_name (&buf->name, name, TYP_BUFFER, buf);
 #endif

    return buf;
 }


 void far delete_buffer (bufferptr buf)
 {
    delete_wpipe (&buf->pip);
    delete_resource (&buf->buf_read);
    delete_resource (&buf->buf_write);
    buf->msgcnt = 0;

 #if (TSK_NAMED)
    tsk_del_name (&buf->name);
 #endif

 #if (TSK_DYNAMIC)
    if (buf->flags & F_STTEMP)
       tsk_free (buf->pip.wcontents);
    if (buf->flags & F_TEMP)
       tsk_free (buf);
 #endif
 }


 int far read_buffer (bufferptr buf, farptr msg, int size, dword timeout)
 {
    int i, len, l1, l2;
    word w;

    if ((i = request_resource (&buf->buf_read, timeout)) < 0)
       return i;

    if ((len = read_wpipe (&buf->pip, timeout)) < 0)
       {
       release_resource (&buf->buf_read);
       return len;
       }

    l1 = (len < size) ? len : size;

    for (i = 0; i < l1; i++)
       {
       if (!(i & 1))
          w = read_wpipe (&buf->pip, 0L);
       else
          w = w >> 8;
       ((byteptr)msg) [i] = (byte)w;
       }

    l2 = (len + 1) >> 1;
    for (i = (l1 + 1) >> 1; i < l2; i++)
       read_wpipe (&buf->pip, 0L);
    if (l1 < size)
       ((byteptr)msg) [l1] = 0;

    buf->msgcnt--;

    release_resource (&buf->buf_read);
    return len;
 }


 int far c_read_buffer (bufferptr buf, farptr msg, int size)
 {
    int res;
    CRITICAL;

    res = -1;
    C_ENTER;

    if (buf->pip.filled && buf->buf_read.state)
       {
       request_resource (&buf->buf_read, 0L);
       C_LEAVE;
       res = read_buffer (buf, msg, size, 0L);
       }
    else
       C_LEAVE;

    return res;
 }


 local int near tsk_wrbuf (bufferptr buf, word w, dword timeout)
 {
    int i;

    if ((i = write_wpipe (&buf->pip, w, timeout)) < 0)
       release_resource (&buf->buf_write);
    return i;
 }


 int far write_buffer (bufferptr buf, farptr msg, int size, dword timeout)
 {
    int i, res, l2;

    if (size < 0 || (word)((size + 3) >> 1) > buf->pip.bufsize)
       return -3;

    if ((i = request_resource (&buf->buf_write, timeout)) < 0)
       return i;

    if ((i = tsk_wrbuf (buf, (word)size, timeout)) < 0)
       return i;

    l2 = (size + 1) >> 1;

    for (i = 0; i < l2; i++)
       if ((res = tsk_wrbuf (buf, ((wordptr)msg) [i], timeout)) < 0)
          return res;

    buf->msgcnt++;

    release_resource (&buf->buf_write);
    return size;
 }


 int far c_write_buffer (bufferptr buf, farptr msg, int size)
 {
    int res;
    CRITICAL;

    if (size < 0 || (word)((size + 3) >> 1) > buf->pip.bufsize)
       return -3;

    C_ENTER;
    res = -1;

    if (wpipe_free (&buf->pip) >= ((size + 3) >> 1) && buf->buf_write.state)
       {
       request_resource (&buf->buf_write, 0L);
       C_LEAVE;
       res = write_buffer (buf, msg, size, 0L);
       }
    else
       C_LEAVE;

    return res;
 }


 word far check_buffer (bufferptr buf)
 {
    return buf->msgcnt;
 }



 TSKCNT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKCNT.C

 /*
    TSKCNT.C - CTask - Counter handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"

 /*
    create_counter - initialises counter.
 */

 counterptr far create_counter (counterptr cnt
 #if (TSK_NAMEPAR)
                               ,byteptr name
 #endif
                               )
 {
 #if (TSK_DYNAMIC)
    if (cnt == NULL)
       {
       if ((cnt = tsk_alloc (sizeof (counter))) == NULL)
          return NULL;
       cnt->flags = F_TEMP;
       }
    else
       cnt->flags = 0;
 #endif

    cnt->wait_set = cnt->wait_clear = NULL;
    cnt->state = 0;

 #if (TSK_NAMED)
    tsk_add_name (&cnt->name, name, TYP_COUNTER, cnt);
 #endif

    return cnt;
 }


 /*
    delete_counter - kills all processes waiting for counter
 */

 void far delete_counter (counterptr cnt)
 {
    CRITICAL;

    C_ENTER;
    tsk_kill_queue (&(cnt->wait_set));
    tsk_kill_queue (&(cnt->wait_clear));
    cnt->state = 0L;
    C_LEAVE;

 #if (TSK_NAMED)
    tsk_del_name (&cnt->name);
 #endif

 #if (TSK_DYNAMIC)
    if (cnt->flags & F_TEMP)
       tsk_free (cnt);
 #endif
 }


 /*
    clear_counter  - Sets counter to zero. All tasks waiting for
                     Counter zero are made eligible.
 */

 void far clear_counter (counterptr cnt)
 {
    CRITICAL;

    C_ENTER;
    cnt->state = 0L;
    while (cnt->wait_clear != NULL)
       cnt->wait_clear = tsk_runable (cnt->wait_clear);
    C_LEAVE;
 }

 /*
    wait_counter_set  - Wait until counter is != 0. If counter is != 0 on
                        entry, the counter is decremented and the task
                        continues to run. If the counter is decremented to
                        zero, tasks waiting for zero are made eligible.
 */

 int far wait_counter_set (counterptr cnt, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (cnt->state)
       {
       if (!--cnt->state)
          while (cnt->wait_clear != NULL)
             cnt->wait_clear = tsk_runable (cnt->wait_clear);
       C_LEAVE;
       return 0;
       }

    tsk_current->retptr = NULL;
    tsk_wait (&cnt->wait_set, timeout);
    return (int)tsk_current->retptr;
 }

 /*
    wait_counter_clear - Wait until counter is == 0. If counter is == 0 on
                        entry, the task continues to run.
 */

 int far wait_counter_clear (counterptr cnt, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (!cnt->state)
       {
       C_LEAVE;
       return 0;
       }

    tsk_current->retptr = NULL;
    tsk_wait (&cnt->wait_clear, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    inc_counter - Increment counter. If there are tasks waiting for the
                  set state, the first task in the queue is made eligible.
 */

 void far inc_counter (counterptr cnt)
 {
    tcbptr curr;

    CRITICAL;

    C_ENTER;
    if ((curr = cnt->wait_set) == NULL)
       {
       cnt->state++;
       C_LEAVE;
       return;
       }
    cnt->wait_set = tsk_runable (curr);
    C_LEAVE;
 }


 /*
    check_counter - return current counter state.
 */

 dword far check_counter (counterptr cnt)
 {
    return cnt->state;
 }





 TSKFLG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKFLG.C

 /*
    TSKFLG.C - CTask - Flag handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"


 /*
    create_flag - initialises flag.
 */

 flagptr far create_flag (flagptr flg
 #if (TSK_NAMEPAR)
                         ,byteptr name
 #endif
                         )
 {
 #if (TSK_DYNAMIC)
    if (flg == NULL)
       {
       if ((flg = tsk_alloc (sizeof (flag))) == NULL)
          return NULL;
       flg->flags = F_TEMP;
       }
    else
       flg->flags = 0;
 #endif

    flg->wait_set = flg->wait_clear = NULL;
    flg->state = 0;

 #if (TSK_NAMED)
    tsk_add_name (&flg->name, name, TYP_FLAG, flg);
 #endif

    return flg;
 }

 /*
    delete_flag - kills all processes waiting for flag
 */

 void far delete_flag (flagptr flg)
 {
    CRITICAL;

    C_ENTER;

    tsk_kill_queue (&(flg->wait_set));
    tsk_kill_queue (&(flg->wait_clear));
    flg->state = 0;
    C_LEAVE;

 #if (TSK_NAMED)
    tsk_del_name (&flg->name);
 #endif

 #if (TSK_DYNAMIC)
    if (flg->flags & F_TEMP)
       tsk_free (flg);
 #endif
 }


 /*
    wait_flag_set  - Wait until flag is != 0. If flag is != 0 on
                     entry, the task continues to run.
 */

 int far wait_flag_set (flagptr flg, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (flg->state)
       {
       C_LEAVE;
       return 0;
       }
    tsk_current->retptr = NULL;
    tsk_wait (&flg->wait_set, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    wait_flag_clear - Wait until flag is == 0. If flag is == 0 on
                      entry, the task continues to run.
 */

 int far wait_flag_clear (flagptr flg, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (!flg->state)
       {
       C_LEAVE;
       return 0;
       }

    tsk_current->retptr = NULL;
    tsk_wait (&flg->wait_clear, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    set_flag - Set flag to 1. If there are tasks waiting for the
               set state, all tasks in the queue are made eligible.
 */

 void far set_flag (flagptr flg)
 {
    CRITICAL;

    C_ENTER;
    flg->state = 1;

    while (flg->wait_set != NULL)
       flg->wait_set = tsk_runable (flg->wait_set);
    C_LEAVE;
 }


 /*
    clear_flag - Set flag to 0. If there are tasks waiting for the
                 clear state, all tasks in the queue are made eligible.
 */

 void far clear_flag (flagptr flg)
 {
    CRITICAL;

    C_ENTER;
    flg->state = 0;

    while (flg->wait_clear != NULL)
       flg->wait_clear = tsk_runable (flg->wait_clear);

    C_LEAVE;
 }


 /*
    clear_flag_wait_set - Set flag to 0, then wait for set state.
 */

 int far clear_flag_wait_set (flagptr flg, dword timeout)
 {
    clear_flag (flg);
    return wait_flag_clear (flg, timeout);
 }


 /*
    check_flag - return current flag state.
 */

 int far check_flag (flagptr flg)
 {
    return flg->state;
 }





 TSKMAIN.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKMAIN.C

 /*
    TSKMAIN.C - CTask - Main routines for task handling.

    CTask - a Multitasking Kernel for C

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany

    No rights reserved.

    Version 1.1  88-07-01

       Changes from V0.1: - Separated timeout handling from INT9 chaining
                            for better control over TSR response.
                          - Handling of timeout queue rewritten.
                          - More features for timeouts (can handle
                            flags, counters, function calls, and repetititve
                            timeouts).
                          - Support for dynamically allocated control blocks.
                          - Idle task removed.

 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"

 #define STACKSIZE 512

 /*
    The task queues:
       All tasks using a timeout, either through "t_delay" or an event wait,
       are enqueued into the "tsk_timer" queue, using the "timerq" link.
       All tasks eligible for running are enqueued in "tsk_eligible".
       The tcb-address of the current running task is stored in "tsk_current".
 */

 tlinkptr _Near tsk_timer;
 tcbptr   _Near tsk_eligible;
 tcbptr   _Near tsk_current;

 /*
    System flags:
       tsk_preempt is zero if preemption is allowed.
                   Bit 0 is set if preemption has been disabled globally.
                   Bit 1 is set for temporary disabling preemption.
                   Temporary preemption is automatically removed by the
                   scheduler.

       tsk_pretick is nonzero if a schedule request from an interrupt handler
                   was rejected due to tsk_preempt nonzero. This allows
                   an immediate scheduling whenever tsk_preempt is set to 0.

       tsk_var_prior Can be set nonzero to enable variable priority.
                     Variable priority will increase the priority of
                     eligible tasks on each scheduler call while they
                     are waiting to be executed, so that low priority
                     tasks will slowly get to the head of the eligible
                     queue, getting a chance to be run. With variable
                     priority off, lower priority tasks will never be
                     executed while higher priority tasks are eligible.

 */

 byte _Near tsk_preempt;
 byte _Near tsk_pretick;
 byte _Near tsk_var_prior;

 /* --------------------------------------------------------------------- */

 /*
    The tcb's of the standard tasks.

       timer_tcb   is the tcb for the timer task.
                   This task waits for the tsk_timer_counter, which is
                   increased on every timer tick. It processes the entries
                   in the timeout queue.

       int9_tcb    is the tcb for the int9 chain task.
                   This task waits for the tsk_int9_counter, which is
                   increased on every system timer tick. It then chains to
                   the previous timer interrupt entry.

       main_tcb    is the "main" task which called "install_tasker". This
                   task has no separate stack, rather the stack on entry
                   to the scheduler is used.

 */

 counter  _Near tsk_timer_counter;

 local tcb timer_tcb;
 local tcb main_tcb;

 local char timer_stack [STACKSIZE];

 #if (IBM)
 counter  _Near tsk_int9_counter;
 local tcb int9_tcb;
 local char int9_stack [STACKSIZE];
 #endif

 #if (CLOCK_MSEC)
 double tick_factor;
 #endif

 word _Near ticks_per_sec;

 #if (TSK_NAMED)
 namerec tsk_name_list;
 #endif


 /*
    Un-Install-Function pointers for the optional serial and printer
    drivers. If ports are installed, the driver inserts the address
    of a remove-function here, to be called on removal of the main
    tasker.
 */

 funcptr v24_remove_func = NULL;
 funcptr prt_remove_func = NULL;


 /* --------------------------------------------------------------------- */

 #pragma check_stack(off)

 /*
    Killretn kills the current active task. It is used internally, but
    can also be called from outside.
 */

 void far killretn (void)
 {
    tsk_cli ();
    tsk_kill (tsk_current);
    tsk_current = NULL;
    schedule ();
 }

 /*
    tsk_timer_action performs the necessary action when a timeout occurred.
 */

 local void tsk_timer_action (tlinkptr elem)
 {
    tcbptr task;
    byte st;

    switch (elem->tkind & 0x7f)
       {
       case TKIND_WAKE:
       case TKIND_TASK:  task = (tcbptr) elem->strucp;
                         st = task->state;

                         if (st == ST_WAITING || st == ST_DELAYED)
                            {
                            task->retptr = TTIMEOUT;
                            tsk_wakeup (task);
                            }
                         break;

       case TKIND_FLAG:  set_flag ((flagptr) elem->strucp);
                         break;

       case TKIND_COUNTER: inc_counter ((counterptr) elem->strucp);
                         break;

       case TKIND_PROC:  ((funcptr) elem->strucp)();
                         break;

       default:          break;
       }
 }


 /*
    The timer task handles all timeouts.
    It maintains a single timer queue, which contains elements of the
    "tlink" structure. No other task is allowed to manipulate this queue,
    except for the insertion of new elements at the queue head. This allows
    stepping through the queue with interrupts enabled.
    CAUTION: This assumes that the operation of loading a far pointer
             is indivisible!
 */

 local void far timer (void)
 {
    tlinkptr curr;
    tlinkptr last;
    byte state;
    CRITICAL;

    while (1)
       {
       wait_counter_set (&tsk_timer_counter, 0L);

       last = (tlinkptr) &tsk_timer;

       while ((curr = last->next) != NULL)
          {
          /* Enter critical section for access to state and timeout
             variables. The timer action is also critical.
          */
          C_ENTER;
          if ((state = curr->tstate) >= TSTAT_COUNTDOWN)
             if (!--curr->timeout)
                {
                if (state == TSTAT_COUNTDOWN)
                   state = (byte) TSTAT_REMOVE;
                else
                   curr->timeout = curr->reload;

                tsk_timer_action (curr);
                }
          if (state == (byte) TSTAT_REMOVE)
             {
             last->next = curr->next;
             curr->tstate = TSTAT_IDLE;

 #if (TSK_DYNAMIC)
             if (curr->tkind & TKIND_TEMP)
                {
                if ((curr->tkind & 0x7f) == TKIND_TASK)
                   tsk_kill ((tcbptr) curr->strucp);
                else
                   tsk_free (curr);
                }
 #endif
             curr = last;
             }
          C_LEAVE;
          last = curr;
          }
       }
 }

 /*
    int9 is the timer interrupt chain task.
 */

 #if (IBM)

 local void far int9 (void)
 {
    while (1)
       {
       wait_counter_set (&tsk_int9_counter, 0L);
       tsk_chain_timer ();
       }
 }

 #endif

 /* ---------------------------------------------------------------------- */

 /*
    create_task
       Initialises a tcb. The task is in stopped state initially.
 */

 tcbptr far create_task (tcbptr task,
                         funcptr func,
                         byteptr stack,
                         word stksz,
                         word prior,
                         farptr arg
 #if (TSK_NAMEPAR)
                         ,byteptr name
 #endif
                         )

 {
    struct task_stack far *stk;

 #if (TSK_DYNAMIC)
    if (task == NULL)
       {
       if ((task = (tcbptr) tsk_alloc (sizeof(tcb))) == NULL)
          return NULL;
       task->flags = F_TEMP;
       }
    else
       task->flags = 0;

    if (stack == NULL)
       {
       if ((stack = (byteptr) tsk_alloc (stksz)) == NULL)
          {
          if (task->flags & F_TEMP)
             tsk_free (task);
          return NULL;
          }
       task->flags |= F_STTEMP;
       }
 #else
    task->flags = 0;
 #endif

    stk = (struct task_stack far *)(stack + stksz - sizeof (struct task_stack)
    stk->r_ds = stk->r_es = tsk_dseg ();
    stk->r_bp = 0;
    stk->r_flags = tsk_flags ();
    stk->retn = func;
    stk->dummyret = killretn;
    stk->arg = arg;

    task->stkbot = stack;
    task->stack = (byteptr) stk;
    task->next = NULL;
    task->queue = NULL;
    task->state = ST_STOPPED;
    task->prior = task->initprior = prior;
    task->timerq.timeout = task->timerq.reload = 0;
    task->timerq.strucp = (farptr) task;
    task->timerq.tkind = TKIND_TASK;
    task->timerq.tstate = TSTAT_IDLE;

 #if (TSK_NAMED)
    tsk_add_name (&task->name, name, TYP_TCB, task);
 #endif

    return task;
 }


 /*
    kill_task
       Removes a task from the system.
       CAUTION: The task control block may *not* be immediately re-used
                if it was enqueued in the timer queue. Check for
                task->timerq.tstate == TSTAT_IDLE before modifying
                the tcb.
 */

 void far kill_task (tcbptr task)
 {
    byte st;
    CRITICAL;

    C_ENTER;
    if ((st = task->state) != ST_RUNNING)
       tsk_unqueue (task);

    task->queue = NULL;
    tsk_kill (task);
    if (st == ST_RUNNING)
       {
       tsk_current = NULL;
       schedule ();
       }
    C_LEAVE;
 }


 /*
    start_task
       Starts a stopped task. Returns -1 if the task was not stopped.
 */

 int far start_task (tcbptr task)
 {
    CRITICAL;

    if (task == NULL)
       task = &main_tcb;

    if (task->state == ST_STOPPED)
       {
       task->state = ST_ELIGIBLE;
       C_ENTER;
       tsk_enqueue (task, &tsk_eligible);
       C_LEAVE;
       return 0;
       }
    return -1;
 }


 /*
    wake_task
       Restarts a task waiting for an event or timeout.
       Returns -1 if the task was not waiting or stopped.
 */

 int far wake_task (tcbptr task)
 {
    CRITICAL;

    if (task == NULL)
       task = &main_tcb;

    C_ENTER;
    if (task->state >= ST_ELIGIBLE)
       {
       C_LEAVE;
       return -1;
       }

    task->retptr = TWAKE;
    tsk_wakeup (task);
    C_LEAVE;
    return 0;
 }



 /*
    get_priority
       Returns the priority of a task.
 */

 word far get_priority (tcbptr task)
 {
    if (task == NULL)
       task = &main_tcb;

    return task->prior;
 }


 /*
    set_priority
       Changes the priority of a task. If the task is enqueued in a
       queue, its position in the queue is affected.
 */

 void far set_priority (tcbptr task, word prior)
 {
    tqueptr que;
    CRITICAL;

    if (task == NULL)
       task = &main_tcb;

    C_ENTER;
    task->prior = task->initprior = prior;

    if ((task->state != ST_RUNNING) && ((que = task->queue) != NULL))
       {
       tsk_unqueue (task);
       tsk_enqueue (task, que);
       }
    C_LEAVE;
 }

 /*
    set_task_flags
       Changes the user modifiable flags of the task.
 */

 void far set_task_flags (tcbptr task, byte flags)
 {
    CRITICAL;

    if (task == NULL)
       task = &main_tcb;

    C_ENTER;
    task->flags = (task->flags & FL_SYSM) | (flags & FL_USRM);
    C_LEAVE;
 }


 /* --------------------------------------------------------------------- */


 /*
    t_delay
       delay the current task by "ticks" clock ticks.
       If ticks is zero, the task is stopped.
 */

 int far t_delay (dword ticks)
 {
    tsk_cli ();
    tsk_current->queue = NULL;
    if (ticks)
       {
       tsk_current->state = ST_DELAYED;
       tsk_enqtimer (tsk_current, ticks);
       }
    else
       tsk_current->state = ST_STOPPED;

    schedule ();
    return (int)tsk_current->retptr;
 }


 /* --------------------------------------------------------------------- */


 /*
    install_tasker
       Installs the Ctask system. The internal tasks are created,
       the queues are initialised, and the interrupt handler installation
       routines are called. Task preemption is initially off.

       Handling of the speedup parameter is system dependent.
 */

 void far install_tasker (byte varpri, int speedup)
 {
    word divisor, sys_ticks;

    tsk_current = &main_tcb;
    tsk_eligible = NULL;
    tsk_timer = NULL;
    tsk_preempt = 1;
    tsk_pretick = 0;
    tsk_var_prior = varpri;

 #if (TSK_NAMED)
    tsk_name_list.follow = tsk_name_list.prev = &tsk_name_list;
    tsk_name_list.nkind = 0;
    tsk_name_list.name [0] = 0;
 #endif

    create_task (&timer_tcb, timer, timer_stack, STACKSIZE, PRI_TIMER, NULL
 #if (TSK_NAMEPAR)
                 , "-TIMER-"
 #endif
                 );
    create_counter (&tsk_timer_counter
 #if (TSK_NAMEPAR)
                 , "TIMCOUNT"
 #endif
                 );

 #if (TSK_DYNAMIC)
    create_resource (&alloc_resource
 #if (TSK_NAMEPAR)
                 , "ALLOCRSC"
 #endif
                 );
 #endif

    main_tcb.prior = main_tcb.initprior = PRI_TIMER - 1;
    main_tcb.queue = &tsk_eligible;
    main_tcb.flags = F_CRIT;
    main_tcb.state = ST_RUNNING;
    start_task (&timer_tcb);

 #if (IBM)
    create_task (&int9_tcb, int9, int9_stack, STACKSIZE, PRI_INT9, NULL
 #if (TSK_NAMEPAR)
                 , "-INT9-"
 #endif
                 );
    create_counter (&tsk_int9_counter
 #if (TSK_NAMEPAR)
                 , "INT9CNT"
 #endif
                 );
    start_task (&int9_tcb);

    if (speedup <= 0 || speedup > 8)
       {
       divisor = 0;
       sys_ticks = 1;
       }
    else
       {
       divisor = 0x8000 >> (speedup - 1);
       sys_ticks = 1 << speedup;
       }

    ticks_per_sec = 18 * sys_ticks;  /* rough number only */

 #if (CLOCK_MSEC)
    tick_factor = (65536.0 / (double)sys_ticks) / 1193.18;
 #endif

    tsk_install_timer (divisor, sys_ticks);
    tsk_install_kbd ();
 #endif
 #if (AT_BIOS)
    tsk_install_bios ();
 #endif

 #if (DOS)
    tsk_install_dos ();
 #endif
 }


 /*
    preempt_off
       Turns off task preemption (will stay off until explicitly enabled).
 */

 void far preempt_off (void)
 {
    tsk_preempt = 1;
 }


 /*
    preempt_on
       Resets permanent and temporary task preemption flag. If
       preemption is pending, the scheduler is called.
 */

 void far preempt_on (void)
 {
    tsk_preempt = 0;
    tsk_cli ();
    if (tsk_pretick)
       schedule ();
    tsk_sti ();
 }


 /*
    remove_tasker
       Calls the interrupt handler un-install routines.
 */

 void far remove_tasker (void)
 {
    tsk_preempt = 0;

 #if (AT_BIOS)
    tsk_remove_bios ();
 #endif
 #if (IBM)

    if (v24_remove_func != NULL)
       v24_remove_func ();
    if (prt_remove_func != NULL)
       prt_remove_func ();

    /* Allow all stored clock ticks to be processed */
    set_priority (&int9_tcb, 0xffff);
    while (check_counter (&tsk_int9_counter))
       schedule();

    tsk_remove_timer ();
    tsk_remove_kbd ();
 #endif

 #if (DOS)
    tsk_remove_dos ();
 #endif
 }


 /*
    tsk_ena_preempt
       Resets temporary task preemption flag. If preemption is pending,
       the scheduler is called.
 */

 void far tsk_ena_preempt (void)
 {
    tsk_cli ();
    if (!(tsk_preempt &= ~2))
       if (tsk_pretick)
          schedule ();
    tsk_sti ();
 }


 /* --------------------------------------------------------------------- */

 /*
    create_timer
       Creates a timer queue element. The element is inserted into
       the timeout queue.
 */

 tlinkptr far create_timer (tlinkptr elem, dword tout, farptr strucp,
                            byte kind, byte rept)
 {
    CRITICAL;

    if (kind <= TKIND_TASK || kind > TKIND_COUNTER)
       return NULL;

 #if (TSK_DYNAMIC)

    if (elem == NULL)
       {
       if ((elem = tsk_alloc (sizeof (tlink))) == NULL)
          return NULL;
       kind |= TKIND_TEMP;
       }

 #endif

    elem->tkind = kind;
    elem->strucp = strucp;
    elem->tstate = (byte)((rept) ? TSTAT_REPEAT : TSTAT_COUNTDOWN);
    elem->timeout = elem->reload = tsk_timeout(tout);

    C_ENTER;
    elem->next = tsk_timer;
    tsk_timer = elem;
    C_LEAVE;

    return elem;
 }


 /*
    delete_timer
       Deletes a timeout element.
 */

 void far delete_timer (tlinkptr elem)
 {
    CRITICAL;

    C_ENTER;
    if (elem->tstate != TSTAT_IDLE)
       {
       elem->tstate = (byte)TSTAT_REMOVE;
       C_LEAVE;
       return;
       }
    C_LEAVE;

 #if (TSK_DYNAMIC)
    if (elem->tkind & TKIND_TEMP)
       tsk_free (elem);
 #endif
 }


 /*
    change_timer
       Changes the timeout and/or repeat-flag in a timer element.
       If the timer was idle, it is inserted into the timeout queue.

       If 0 is passed as timeout, the element is removed from the
       timeout queue (same as delete_timer).

       This routine should *not* be used for dynamically allocated
       timer elements.
 */

 void far change_timer (tlinkptr elem, dword tout, byte rept)
 {
    byte st;
    CRITICAL;

    if (!tout)
       {
       delete_timer (elem);
       return;
       }

    C_ENTER;
    elem->timeout = elem->reload = tsk_timeout(tout);
    st = elem->tstate;
    elem->tstate = (byte)((rept) ? TSTAT_REPEAT : TSTAT_COUNTDOWN);

    if (st == TSTAT_IDLE)
       {
       elem->next = tsk_timer;
       tsk_timer = elem;
       }
    C_LEAVE;
 }



 TSKMSG.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKMSG.C

 /*
    TSKMSG.C - CTask - Message handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"


 /*
    create_mailbox - initialises mailbox.
 */

 mailboxptr far create_mailbox (mailboxptr box
 #if (TSK_NAMEPAR)
                               ,byteptr name
 #endif
                               )
 {
 #if (TSK_DYNAMIC)
    if (box == NULL)
       {
       if ((box = tsk_alloc (sizeof (mailbox))) == NULL)
          return NULL;
       box->flags = F_TEMP;
       }
    else
       box->flags = 0;
 #endif

    box->waiting = NULL;
    box->mail_first = box->mail_last = NULL;

 #if (TSK_NAMED)
    tsk_add_name (&box->name, name, TYP_MAILBOX, box);
 #endif

    return box;
 }


 /*
    delete_mailbox - kills all processes waiting for mail
 */

 void far delete_mailbox (mailboxptr box)
 {
    CRITICAL;

    C_ENTER;
    tsk_kill_queue (&(box->waiting));
    box->mail_first = box->mail_last = NULL;
    C_LEAVE;

 #if (TSK_NAMED)
    tsk_del_name (&box->name);
 #endif

 #if (TSK_DYNAMIC)
    if (box->flags & F_TEMP)
       tsk_free (box);
 #endif
 }


 /*
    wait_mail - Wait until mail arrives. If there is mail in the box on
                entry, the first mail block is assigned to the caller,
                and the task continues to run.
 */

 farptr far wait_mail (mailboxptr box, dword timeout)
 {
    msgptr msg;
    CRITICAL;

    C_ENTER;
    if ((msg = box->mail_first) != NULL)
       {
       if ((box->mail_first = msg->next) == NULL)
          box->mail_last = NULL;
       C_LEAVE;
       return msg;
       }

    tsk_wait (&box->waiting, timeout);
    return tsk_current->retptr;
 }

 /*
    c_wait_mail - If there is mail in the box on entry, the first mail
                  block is assigned to the caller, else an error is returned.
 */

 farptr far c_wait_mail (mailboxptr box)
 {
    msgptr msg;
    CRITICAL;

    C_ENTER;
    if ((msg = box->mail_first) != NULL)
       if ((box->mail_first = msg->next) == NULL)
          box->mail_last = NULL;
    C_LEAVE;
    return msg;
 }


 /*
    send_mail - Send a mail block to a mailbox. If there are tasks waiting
                for mail, the first waiting task is assigned the block and
                is made eligible.
 */

 void far send_mail (mailboxptr box, farptr msg)
 {
    tcbptr curr;
    CRITICAL;

    C_ENTER;
    if ((curr = box->waiting) == NULL)
       {
       if (box->mail_first == NULL)
          box->mail_first = (msgptr)msg;
       else
          box->mail_last->next = (msgptr)msg;
       ((msgptr)msg)->next = NULL;
       box->mail_last = (msgptr)msg;
       C_LEAVE;
       return;
       }
    box->waiting = tsk_runable (curr);
    curr->retptr = msg;
    C_LEAVE;
 }


 /*
    check_mailbox - returns TRUE if there is mail in the box.
 */

 int far check_mailbox (mailboxptr box)
 {
    return box->mail_first != NULL;
 }




 TSKPIP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKPIP.C

 /*
    TSKPIP.C - CTask - Pipe handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"

 /*
    tsk_getcpipe - get a byte from a pipe. For internal use only.
                   Critical section assumed entered.
 */

 local byte near tsk_getcpipe (pipeptr pip)
 {
    byte c;

    c = pip->contents [pip->outptr++];
    if (pip->outptr >= pip->bufsize)
       pip->outptr = 0;
    pip->filled--;
    return c;
 }


 /*
    tsk_putcpipe - put a byte to a pipe. For internal use only.
                   Critical section assumed entered.
 */

 local void near tsk_putcpipe (pipeptr pip, byte c)
 {
    pip->contents [pip->inptr++] = c;
    if (pip->inptr >= pip->bufsize)
       pip->inptr = 0;
    pip->filled++;
 }


 /* -------------------------------------------------------------------- */


 /*
    create_pipe - initialises pipe.
 */

 pipeptr far create_pipe (pipeptr pip, farptr buf, word bufsize
 #if (TSK_NAMEPAR)
                         ,byteptr name
 #endif
                         )
 {
 #if (TSK_DYNAMIC)
    if (pip == NULL)
       {
       if ((pip = tsk_alloc (sizeof (pipe))) == NULL)
          return NULL;
       pip->flags = F_TEMP;
       }
    else
       pip->flags = 0;
    if (buf == NULL)
       {
       if ((buf = tsk_alloc (bufsize)) == NULL)
          {
          if (pip->flags & F_TEMP)
             tsk_free (pip);
          return NULL;
          }
       pip->flags |= F_STTEMP;
       }
 #endif

    pip->wait_read = pip->wait_write = pip->wait_clear = NULL;
    pip->outptr = pip->inptr = pip->filled = 0;
    pip->bufsize = bufsize;
    pip->contents = (byteptr)buf;

 #if (TSK_NAMED)
    tsk_add_name (&pip->name, name, TYP_PIPE, pip);
 #endif

    return pip;
 }


 /*
    delete_pipe - kills all processes waiting for reading from or writing
                  to the pipe.
 */

 void far delete_pipe (pipeptr pip)
 {
    CRITICAL;

    C_ENTER;
    tsk_kill_queue (&(pip->wait_read));
    tsk_kill_queue (&(pip->wait_write));
    tsk_kill_queue (&(pip->wait_clear));
    pip->outptr = pip->inptr = pip->filled = 0;
    C_LEAVE;

 #if (TSK_NAMED)
    tsk_del_name (&pip->name);
 #endif

 #if (TSK_DYNAMIC)
    if (pip->flags & F_STTEMP)
       tsk_free (pip->contents);
    if (pip->flags & F_TEMP)
       tsk_free (pip);
 #endif
 }


 /*
    read_pipe - Wait until a character is written to the pipe. If there
                is a character in the pipe on entry, it is assigned to
                the caller, and the task continues to run. If there are
                tasks waiting to write, the first task is made eligible,
                and the character is inserted into the pipe.
 */

 int far read_pipe (pipeptr pip, dword timeout)
 {
    tcbptr curr;
    int res;
    CRITICAL;

    C_ENTER;

    if (pip->filled)
       {
       res = tsk_getcpipe (pip);

       if ((curr = pip->wait_write) != NULL)
          {
          tsk_putcpipe (pip, (byte)curr->retsize);
          pip->wait_write = tsk_runable (curr);
          curr->retptr = NULL;
          }
       else if (!pip->filled)
          while (pip->wait_clear != NULL)
             pip->wait_clear = tsk_runable (pip->wait_clear);

       C_LEAVE;
       return res;
       }

    tsk_wait (&pip->wait_read, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    c_read_pipe - If there is a character in the pipe on entry,
                  read_pipe is called, otherwise en error status is returned.
 */

 int far c_read_pipe (pipeptr pip)
 {
    CRITICAL, res;

    C_ENTER;
    res = (pip->filled) ? read_pipe (pip, 0L) : -1;
    C_LEAVE;
    return res;
 }



 /*
    write_pipe - Wait until space for the character to be written to the
                 pipe is available. If there is enough space in the pipe
                 on entry, the character is inserted into the pipe, and
                 the task continues to run. If there are tasks waiting
                 to read, the first task is made eligible, and the character
                 is passed to the waiting task.
 */

 int far write_pipe (pipeptr pip, byte ch, dword timeout)
 {
    tcbptr curr;
    CRITICAL;

    C_ENTER;

    if (pip->filled < pip->bufsize)
       {
       if ((curr = pip->wait_read) != NULL)
          {
          pip->wait_read = tsk_runable (curr);
          curr->retptr = (farptr)ch;
          C_LEAVE;
          return 0;
          }

       tsk_putcpipe (pip, ch);
       C_LEAVE;
       return 0;
       }

    tsk_current->retsize = ch;
    tsk_wait (&pip->wait_write, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    c_write_pipe - If there is space for the character in the pipe on entry,
                   write_pipe is called, otherwise en error status is returned
 */

 int far c_write_pipe (pipeptr pip, byte ch)
 {
    int res;
    CRITICAL;

    C_ENTER;
    res = (pip->filled < pip->bufsize) ? write_pipe (pip, ch, 0L) : -1;
    C_LEAVE;
    return res;
 }


 /*
    wait_pipe_empty - Wait until the pipe is empty. If the pipe is
                      empty on entry, the task continues to run.
 */

 int far wait_pipe_empty (pipeptr pip, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (!pip->filled)
       {
       C_LEAVE;
       return 0;
       }

    tsk_current->retptr = NULL;
    tsk_wait (&pip->wait_clear, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    check_pipe - returns -1 if there are no characters in the pipe, else
                 the first available character.
 */

 int far check_pipe (pipeptr pip)
 {
    return (pip->filled) ? (int)pip->contents [pip->outptr] : -1;
 }


 /*
    pipe_free - returns the number of free characters in the pipe.
 */

 word far pipe_free (pipeptr pip)
 {
    return pip->bufsize - pip->filled;
 }




 TSKPRT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKPRT.C

 /*
    TSKPRT.C - CTask - Printer interface routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */


 #include "tsk.h"
 #include "prt.h"

 STKSZ     256   /* Printer Task stack size */

 /*
    The following values may need some tuning for optimum performance.
 */
 /*
    MAX_WAIT_xx: Maximum number of times through the loop when waiting
                 for the printer to get ready.
 */

 MAX_WAIT_INT    30 /* For interrupt output */
 MAX_WAIT_POLL   30 /* For polling output */

 /*
    xx_DELAY: Ticks to wait before trying again when printer was not ready.
 */

 INT_DELAY    5L  /* For interrupt output */
 POLL_DELAY   5L  /* For polling output */

 INT_TIMEOUT  2L  /* Timeout for ACK interrupt wait */


 typedef void (interrupt far * intprocptr)(void);

 inta00    0x20   /* 8259 interrupt controller control-port */
 inta01    0x21   /* 8259 interrupt controller mask-port */

 rdserv    0x0b   /* read service register control value */
 eoi       0x20   /* end of interrupt signal for 8259 */

 #define data      0x00
 #define status    0x01
 #define control   0x02

 #define STROBE    0x01
 #define IRQENA    0x10

 #define dflt_control    (INIT | SELECT)


 /*
    To add support for other LPT-Ports, define
       - Port base
       - IRQ-Bit (optional)
       - Interrupt vector (optional)
    here, add the necessary data to the pr_port_descr array, and, if irq
    was specified, define the corresponding interrupt function by
    duplicating prtint0, replacing the index into the prt_data array.
 */

 PORTS  3              /* Number of defined ports */

 lpt1_base    0x3bc    /* LPT1 port base (mono card) */
 lpt2_base    0x378    /* LPT2 port base (IBM printer adapter) */
 lpt3_base    0x278    /* LPT3 port base (secondary parallel) */

 lpt1_irq     0x80     /* IRQ-Bit for LPT1 */
 lpt2_irq     0x80     /* IRQ-Bit for LPT2 */
 lpt3_irq     0x20     /* IRQ-Bit for LPT3 */

 lpt1_vect    0x0f     /* Interrupt vector for LPT1 */
 lpt2_vect    0x0f     /* Interrupt vector for LPT2 */
 lpt3_vect    0x0d     /* Interrupt vector for LPT3 */

 typedef struct {
                intprocptr  proc;
                int         base;
                byte        irq;
                byte        vector;
                } port_data;

 local void interrupt far prtint0 (void);
 local void interrupt far prtint1 (void);
 local void interrupt far prtint2 (void);

 port_data pr_port_descr [PORTS] = {
                                  { prtint0, lpt1_base, lpt1_irq, lpt1_vect },
                                  { prtint1, lpt2_base, lpt2_irq, lpt2_vect },
                                  { prtint2, lpt3_base, lpt3_irq, lpt3_vect }
                                   };

 /*-------------------------------------------------------------------------*/

 typedef struct {
                farptr   savvect;       /* Interrupt vector save location */
                int      port_base;     /* Port base I/O address */
                byte     irqbit;        /* IRQ-Bit for this port */
                byte     civect;        /* Interrupt Vector for this port */
                byte     wait_xmit;     /* Transmit delayed */
                byte     xmit_pending;  /* Transmit in progress */
                byte     polling;       /* Use polling if on */
                                         byte                ccontrol;
                pipe     xmit_pipe;     /* Transmit pipe */
                flag     pready;        /* Printer ready flag */
                tcb      pr_task;       /* Printer task */
                byte     pr_stack [STKSZ]; /* Printer task stack */
                } prt_datarec;

 typedef prt_datarec *prtptr;

 local prt_datarec prt_data [PORTS];
 local int prt_installed [PORTS] = { 0 };

 extern funcptr prt_remove_func;

 /*-------------------------------------------------------------------------*/


 local void near prtint (prtptr prt)
 {
    /* Turn off int */
    prt->ccontrol &= ~IRQENA;
    tsk_outp (prt->port_base + control, prt->ccontrol);

    /* Signal print char complete */
    set_flag (&prt->pready);
    tsk_outp (inta00, eoi);
 }


 local void interrupt far prtint0 (void)
 {
    prtint (&prt_data [0]);
 }

 local void interrupt far prtint1 (void)
 {
    prtint (&prt_data [1]);
 }

 local void interrupt far prtint2 (void)
 {
    prtint (&prt_data [2]);
 }

 /*-------------------------------------------------------------------------*/


 local void near pr_toggle_strobe (int port_base, byte ctl)
 {
    tsk_outp (port_base + control, ctl | STROBE);
    tsk_nop ();
    tsk_outp (port_base + control, ctl);
 }

 local int near pr_ready (int port_base)
 {
    return (tsk_inp (port_base + status) & (BUSY | ACK | PEND | SELIN | ERROR)
           == (BUSY | ACK | SELIN | ERROR);
 }


 local void near pr_output_poll (prtptr prt, byte ch)
 {
    int wait_count;
    int port_base;

    port_base = prt->port_base;
    while (!pr_ready (port_base))
       {
       for (wait_count = 0; wait_count < MAX_WAIT_POLL; wait_count++)
          if (pr_ready (port_base))
             break;
       if (!pr_ready (port_base))
          t_delay (POLL_DELAY);
       }
    tsk_outp (port_base + data, ch);
    pr_toggle_strobe (port_base, prt->ccontrol);
 }


 local void near pr_output_int (prtptr prt, byte ch)
 {
    int wait_count;
    int port_base;

    port_base = prt->port_base;
    while (!pr_ready (port_base))
       {
       for (wait_count = 0; wait_count < MAX_WAIT_INT; wait_count++)
          if (pr_ready (port_base))
             break;
       if (!pr_ready (port_base))
          t_delay (INT_DELAY);
       }

    clear_flag (&prt->pready);

    tsk_outp (port_base + data, ch);
    pr_toggle_strobe (port_base, prt->ccontrol | IRQENA);

    for (wait_count = 0; wait_count < MAX_WAIT_INT; wait_count++)
       if (check_flag (&prt->pready))
          return;

    if (wait_flag_set (&prt->pready, INT_TIMEOUT) < 0)
       tsk_outp (prt->port_base + control, prt->ccontrol &= ~IRQENA);
 }


 local void far pr_task (prtptr prt)
 {
    int ch;

    while (1)
       {
       ch = read_pipe (&prt->xmit_pipe, 0L);
       if (prt->polling)
          pr_output_poll (prt, (byte)ch);
       else
          pr_output_int (prt, (byte)ch);
       }
 }

 /*-------------------------------------------------------------------------*/

 int far prt_install (int port, byte polling, word prior,
                      farptr xmitbuf, word xmitsize)
 {
    prtptr prt;
    int pbase;
    intprocptr far *intptr;
 #if (TSK_NAMEPAR)
    static char name [] = "PRTn";

    name [3] = (char)(port & 0x7f) + '0';
 #endif

    if (port & 0x80)
       {
       port &= 0x7f;
       if (port > 4)
          return -1;
       pbase = *((wordptr)(MK_FP (0x40, port * 2 + 8)));
       if (!pbase)
          return -1;

       for (port = 0; port < PORTS; port++)
          if (pr_port_descr [port].base == pbase)
             break;
       }

    if (port < 0 || port >= PORTS || !xmitsize || prt_installed [port])
       return -1;

    prt = &prt_data [port];

    if (create_pipe (&prt->xmit_pipe, xmitbuf, xmitsize
 #if (TSK_NAMEPAR)
                    , name
 #endif
                    ) == NULL)
       return -1;

    create_flag (&prt->pready
 #if (TSK_NAMEPAR)
                 , name
 #endif
                 );

    create_task (&prt->pr_task, pr_task, prt->pr_stack, STKSZ, prior, prt
 #if (TSK_NAMEPAR)
                 , name
 #endif
                 );

    pbase = prt->port_base = pr_port_descr [port].base;
    prt->civect = pr_port_descr [port].vector;
    prt->irqbit = pr_port_descr [port].irq;
    prt->ccontrol = dflt_control;
    prt->wait_xmit = prt->xmit_pending = 0;

    if (!prt->irqbit)
       polling = 1;

    prt->polling = polling;

    tsk_outp (pbase + control, dflt_control);
    if (!polling)
       {
       intptr = (intprocptr far *)MK_FP (0, prt->civect * 4);
       tsk_cli ();
       prt->savvect = *intptr;
       *intptr = pr_port_descr [port].proc;
       tsk_sti ();
       tsk_outp (inta01, tsk_inp (inta01) & ~prt->irqbit);
       }

    prt_installed [port] = 1;
    prt_remove_func = prt_remove_all;
    start_task (&prt->pr_task);

         return port;
    }


 void far prt_remove (int port)
    {
    prtptr prt;
    intprocptr far *intptr;

    prt = &prt_data [port];
    tsk_outp (prt->port_base + control, prt->ccontrol & ~IRQENA);

    if (!prt->polling)
       {
       tsk_outp (inta01, tsk_inp (inta01) | prt->irqbit);
       intptr = (intprocptr far *)MK_FP (0, prt->civect * 4);
       tsk_cli ();
       *intptr = prt->savvect;
       tsk_sti ();
       }
    kill_task (&prt->pr_task);
    delete_pipe (&prt->xmit_pipe);
    delete_flag (&prt->pready);

    prt_installed [port] = 0;
    }


 void far prt_remove_all (void)
 {
    int i;

    for (i = 0; i < PORTS; i++)
       if (prt_installed [i])
          prt_remove (i);
 }


 /*-------------------------------------------------------------------------*/


 void far prt_change_control (int port, byte ctl)
 {
    prtptr prt;
    CRITICAL;

    prt = &prt_data [port];
    C_ENTER;
    prt->ccontrol = (prt->ccontrol & ~(AUTOFEED | INIT | SELECT))
                    | (ctl & (AUTOFEED | INIT | SELECT));
    C_LEAVE;
    tsk_outp (prt->port_base + control, prt->ccontrol);
 }


 int far prt_write (int port, byte ch, dword timeout)
 {
    return write_pipe (&prt_data [port].xmit_pipe, ch, timeout);
 }


 int far prt_status (int port)
 {
    return tsk_inp (prt_data [port].port_base + status);
 }


 int far prt_complete (int port)
 {
    return (check_pipe (&prt_data [port].xmit_pipe) == -1);
 }


 int far prt_wait_complete (int port, dword timeout)
 {
    return wait_pipe_empty (&prt_data [port].xmit_pipe, timeout);
 }



 TSKRSC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKRSC.C

 /*
    TSKRSC.C - CTask - Resource handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"

 /*
    create resource - initialise resource.
 */

 resourceptr far create_resource (resourceptr rsc
 #if (TSK_NAMEPAR)
                                  ,byteptr name
 #endif
                                  )
 {
 #if (TSK_DYNAMIC)
    if (rsc == NULL)
       {
       if ((rsc = tsk_alloc (sizeof (resource))) == NULL)
          return NULL;
       rsc->flags = F_TEMP;
       }
    else
       rsc->flags = 0;
 #endif

    rsc->waiting = NULL;
    rsc->state = 1;
    rsc->owner = NULL;

 #if (TSK_NAMED)
    tsk_add_name (&rsc->name, name, TYP_RESOURCE, rsc);
 #endif

    return rsc;
 }

 /*
    delete_resource - Kill all tasks waiting for the resource.
 */

 void far delete_resource (resourceptr rsc)
 {
    CRITICAL;

    C_ENTER;
    tsk_kill_queue (&(rsc->waiting));
    rsc->owner = NULL;
    rsc->state = 0;
    C_LEAVE;

 #if (TSK_NAMED)
    tsk_del_name (&rsc->name);
 #endif

 #if (TSK_DYNAMIC)
    if (rsc->flags & F_TEMP)
       tsk_free (rsc);
 #endif
 }


 /*
    request_resource - Wait until resource is available. If the resource
                       is free on entry, it is assigned to the task, and
                       the task continues to run.
                       If the task requesting the resource already owns it,
                       this routine returns 0.
 */

 int far request_resource (resourceptr rsc, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (rsc->state || rsc->owner == tsk_current)
       {
       rsc->state = 0;
       rsc->owner = tsk_current;
       C_LEAVE;
       return 0;
       }
    tsk_current->retptr = NULL;
    tsk_wait (&rsc->waiting, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    c_request_resource - If the resource is free on entry, it is assigned
                         to the task, otherwise an error status is returned.
 */

 int far c_request_resource (resourceptr rsc)
 {
    int rv;
    CRITICAL;

    C_ENTER;
    if (rv = rsc->state)
       {
       rsc->state = 0;
       rsc->owner = tsk_current;
       }
    C_LEAVE;
    return (rv) ? 0 : -1;
 }


 /*
    release_resource - Release the resource. If there are tasks waiting for
                       the resource, it is assigned to the first waiting
                       task, and the task is made eligible.
 */

 void far release_resource (resourceptr rsc)
 {
    tcbptr curr;
    CRITICAL;

    if (rsc->owner != tsk_current)
       return;

    C_ENTER;
    if ((curr = rsc->waiting) == NULL)
       {
       rsc->state = 1;
       rsc->owner = NULL;
       C_LEAVE;
       return;
       }

    rsc->waiting = tsk_runable (curr);
    rsc->owner = curr;
    C_LEAVE;
 }


 /*
    check_resource - returns 1 if the resource is available.
 */

 int far check_resource (resourceptr rsc)
 {
    return rsc->state;
 }



 TSKSIO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKSIO.C

 /*
    TSKSIO.C - CTask - Serial I/O interface routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany

    With version 1.1, support for shared IRQ lines and dynamically
    defined ports was added. The tables used are

       port_list   The pointer to the list of defined ports. Newly
                   defined ports are added to the end of the list.
                   Ports can never be deleted. Each port descriptor
                   contains the hardware info for the port, plus a
                   pointer to the associated sio-control-block if the
                   port was initialized.

       port_last   The pointer to the last element in port_list.

       irq_array   Is an array of pointers to sio-control-blocks. For
                   each possible IRQ-line the entry in this table points
                   to the first block active for this line. If the IRQ
                   is shared, sio-blocks are chained into this list via
                   their "next" pointer.

       irq_procs   Contains the pointer to the interrupt handler function
                   for the corresponding IRQ-line.

       sio_data    Contains the statically defined sio control blocks.
       port_descr  Contains the statically defined port descriptor blocks.

    NOTE:    You can not dynamically define ports for IRQ-lines that
             have no interrupt handler function defined. To be completely
             flexible, you would have to define sioint-handlers for all
             possible IRQs and enter the addresses into the irq_procs array.

    CAUTION: Please restrict the installation and removal of v24-
             ports to *one* task. The manipulation of the lists is
             not protected, so simultaneous install/remove calls
             may cause trouble. Since ports are normally installed and
             removed in the main task, the protection of critical regions
             seemed unnecessary.

    CAUTION: Shared interrupt logic and IRQ-lines above 4 were not
             tested due to the lack of suitable hardware. Changes may
             be necessary in the handling of the modem control register
             OUT2 line that normally controls interrupt enable, depending
             on the multiport-hardware installed in the target system.
 */

 #include "tsk.h"
 #include "sio.h"

 MAX_IRQ   16    /* Maximum number of interrupt lines,
                            16 for AT, 8 for XT. Can be left at 16 */

 CHAIN_IRQBIT    0x04  /* Chained int controller IRQ bit */

 RESTORE_DEFAULT 1     /* Restore parameter for remove_all */

 typedef void (interrupt far * intprocptr)(void);

 #define RTS       0x02
 #define DTR       0x01
 #define OUT2      0x08

 #define ERR_MASK  0x1e

 inta00    0x20   /* 8259 interrupt controller control-port */
 inta01    0x21   /* 8259 interrupt controller mask-port */

 inta10    0xa0   /* secondary 8259 control-port for IRQ 8-15 */
 inta11    0xa1   /* secondary 8259 mask-port for IRQ 8-15 */

 rdserv    0x0b   /* read service register control value */
 eoi       0x20   /* end of interrupt signal for 8259 */

 intdata   0x0b   /* Enable Interrupts except Line status */

 #define rxreadybit 0x01
 #define txemptybit 0x40
 #define txreadybit 0x20
 #define framingbit 0x08
 #define breakbit   0x10

 /* Note: In version 1.1, port offsets start at 0, not 8 */

 #define linecontrol  0x03
 #define linestatus   0x05
 #define intid        0x02
 #define intenable    0x01
 #define modemcontrol 0x04
 #define modemstatus  0x06
 #define receivedata  0x00
 #define transmitdata 0x00

 baudreg_dll  0x00     /* baud rate least significant byte */
 baudreg_dlm  0x01     /* baud rate most significant byte */

 /*
    Default values for initialising the ports.
    Change to your liking (but remember that OUT2 must be set in the
    modem control register to allow interrupts to come through with
    normal controllers).
 */

 dflt_modcon 0x0b   /* Modem Control: Activate DTR, RTS, OUT2 */
 dflt_baud   96     /* Baud Rate Divisor: 1200 Baud */
 dflt_lcon   0x03   /* Line Control: No Parity, 1 Stop, 8 Data */

 /*
    Defined baud rates. You may expand this table with non-standard
    rates if desired.
 */

 local long baud_table [] = {
                                50L, 2304L,
                                75L, 1536L,
                               110L, 1047L,
                               134L,  857L,
                               150L,  768L,
                               300L,  384L,
                               600L,  192L,
                              1200L,   96L,
                              1800L,   64L,
                              2000L,   58L,
                              2400L,   48L,
                              3600L,   32L,
                              4800L,   24L,
                              7200L,   16L,
                              9600L,   12L,
                             19200L,    6L,
                             38400L,    3L,
                                 0L,    0L };

 /*-------------------------------------------------------------------------*/

 /*
    To add static support for other COM-Ports, define
       - Port base
       - IRQ-Line
       - Interrupt vector
    here, and add the necessary data to the port_descr array.
    If the port does *not* share an IRQ with the predefined ports,
    define the corresponding interrupt function by duplicating siointx,
    and place the entry for this function into the irq_procs array.

    Note that ports may also be defined on-line if TSK_DYNAMIC is enabled.
 */

 STATIC_PORTS  2       /* Number of statically defined ports */

 /* Note: In version 1.1, port offsets start at 0, not 8 */

 com1_base    0x3f8    /* COM1 port base */
 com2_base    0x2f8    /* COM2 port base */

 com1_irq     4        /* IRQ-Line for COM1 */
 com2_irq     3        /* IRQ-Line for COM2 */

 com1_vect    0x0c     /* Interrupt vector for COM1 */
 com2_vect    0x0b     /* Interrupt vector for COM2 */

 /*-------------------------------------------------------------------------*/


 local void interrupt far sioint3 (void);
 local void interrupt far sioint4 (void);

 /*
    Table of Interrupt handler functions for each IRQ line.
 */

 local intprocptr irq_procs [MAX_IRQ] = {  NULL,    /* IRQ 0 */
                                           NULL,    /* IRQ 1 */
                                           NULL,    /* IRQ 2 */
                                           sioint3, /* IRQ 3 */
                                           sioint4, /* IRQ 4 */
                                           NULL,    /* IRQ 5 */
                                           NULL,    /* IRQ 6 */
                                           NULL,    /* IRQ 7 */
                                           NULL,    /* IRQ 8 */
                                           NULL,    /* IRQ 9 */
                                           NULL,    /* IRQ 10 */
                                           NULL,    /* IRQ 11 */
                                           NULL,    /* IRQ 12 */
                                           NULL,    /* IRQ 13 */
                                           NULL,    /* IRQ 14 */
                                           NULL };  /* IRQ 15 */


 local sio_datarec sio_data [STATIC_PORTS];

 /* When adding entries to port_descr, be sure to chain the
    elements in ascending order via the first field, and to
    increase the internal port number in the second field. */

 local port_data port_descr [STATIC_PORTS] = {
      { &port_descr[1], 0, NULL, com1_base, com1_irq, com1_vect },
      { NULL,           1, NULL, com2_base, com2_irq, com2_vect }
                                             };

 local sioptr  irq_array [MAX_IRQ] = { NULL };

 local portptr port_list = &port_descr [0];
 local portptr port_last = &port_descr [1];

 local int ports = STATIC_PORTS;

 extern funcptr v24_remove_func;

 /*-------------------------------------------------------------------------*/


 local void near change_rts (sioptr data, int on)
 {
    data->rtsoff = (byte)(!on);
    data->cmodcontrol = (data->cmodcontrol & ~RTS) | ((on) ? RTS : 0);
    tsk_outp (data->port_base + modemcontrol, data->cmodcontrol);
 }


 local void near transmit_ready (sioptr data)
 {
    int i;
 #if (MSC)
    int temp;
 #endif

    if ((i = data->r_xoff) < 0)
       {
 #if (MSC)
       temp = (i == -1) ? XOFF : XON;
       tsk_outp (data->port_base + transmitdata, temp);
 #else
       /* NOTE: Microsoft C 5.0 generates an "Internal Compiler Error"
                when compiling the following statement.
       */
       tsk_outp (data->port_base + transmitdata, (i == -1) ? XOFF : XON);
 #endif
       data->r_xoff = (i == -1) ? 1 : 0;
       data->xmit_pending = 1;
       return;
       }

    data->xmit_pending = 0;

    if (!(data->wait_xmit = (byte)(check_pipe (&data->xmit_pipe) != -1)))
       return;

    if ((data->modem_flags & data->modstat) ^ data->modem_flags)
       return;

    if (data->flags & XONXOFF && data->t_xoff)
       return;

    data->wait_xmit = 0;

    if ((i = c_read_pipe (&data->xmit_pipe)) < 0)
       return;

    tsk_outp (data->port_base + transmitdata, (byte)i);
    data->xmit_pending = 1;
 }


 local void near modem_status_int (sioptr data)
 {
    data->modstat = tsk_inp (data->port_base + modemstatus);

    if (data->wait_xmit)
       transmit_ready (data);
 }


 local void near receive_ready (sioptr data)
 {
    word status;
    word ch;

    while ((status = tsk_inp (data->port_base + linestatus)) & rxreadybit)
       {
       tsk_nop ();
       ch = tsk_inp (data->port_base + receivedata);

       if (data->flags & XONXOFF)
          {
          if (ch == XON)
             {
             data->t_xoff = 0;
             if (data->wait_xmit)
                transmit_ready (data);
             continue;
             }
          else if (ch == XOFF)
             {
             data->t_xoff = 1;
             continue;
             }
          if (!data->r_xoff &&
              wpipe_free (&data->rcv_pipe) < data->xoff_threshold)
             {
             data->r_xoff = -1;
             if (!data->xmit_pending)
                transmit_ready (data);
             }
          }

       if (data->flags & RTSCTS && !data->rtsoff)
          if (wpipe_free (&data->rcv_pipe) < data->xoff_threshold)
             change_rts (data, 0);

       status = (status & ERR_MASK) << 8;
       if (c_write_wpipe (&data->rcv_pipe, ch | status) < 0)
          data->overrun = 1;
       }
 }


 /*-------------------------------------------------------------------------*/


 local void near sioint (sioptr data)
 {
    int id;

    while (!((id = tsk_inp (data->port_base + intid)) & 1))
       switch (id & 0x07)
          {
          case 0x00:  modem_status_int (data);
                      break;

          case 0x02:  transmit_ready (data);
                      break;

          case 0x04:  receive_ready (data);
                      break;

 /*       case 0x06:  line_status_int (data); (currently not used)
                      break;
 */
          }
 }


 local void interrupt far sioint3 (void)
 {
    sioptr curr;

    tsk_sti ();
    for (curr = irq_array [3]; curr != NULL; curr = curr->next)
       sioint (curr);

    tsk_cli ();
    /* NOTE: for IRQ's 8-15, add the following here:
       tsk_outp (inta10, eoi);
    */
    tsk_outp (inta00, eoi);
 }


 local void interrupt far sioint4 (void)
 {
    sioptr curr;

    tsk_sti ();
    for (curr = irq_array [4]; curr != NULL; curr = curr->next)
       sioint (curr);

    tsk_cli ();
    /* NOTE: for IRQ's 8-15, add the following here:
       tsk_outp (inta10, eoi);
    */
    tsk_outp (inta00, eoi);
 }

 /*-------------------------------------------------------------------------*/

 int far v24_define_port (int base, byte irq, byte vector)
 {
 #if (TSK_DYNAMIC)
    portptr portp;

    if (irq >= MAX_IRQ)
       return -1;
    if (irq_procs [irq] == NULL)
       return -1;

    if ((portp = tsk_alloc (sizeof (port_data))) == NULL)
       return -1;
    portp->pnum = ports;
    portp->base = base;
    portp->irq = irq;
    portp->vector = vector;
    portp->next = NULL;
    portp->sio = NULL;

    if (port_list == NULL)
       port_list = portp;
    else
       port_last->next = portp;

    port_last = portp;
    ports++;

    return portp->pnum;

 #else
    return -1;
 #endif
 }


 local sioptr ret_error (sioptr sio)
 {
    sio->port->sio = NULL;
 #if (TSK_DYNAMIC)
    if (sio->port->pnum >= STATIC_PORTS)
       tsk_free (sio);
 #endif
    return NULL;
 }

 sioptr far v24_install (int port, int init,
                         farptr rcvbuf, word rcvsize,
                         farptr xmitbuf, word xmitsize)
 {
    sioptr sio;
    portptr portp;
    int pbase;
    intprocptr far *intptr;
    int i, inta;

 #if (TSK_NAMEPAR)
    static char xname [] = "SIOnXMIT", rname [] = "SIOnRCV";

    xname [3] = rname [3] = (char)(port & 0x7f) + '0';
 #endif

    if (port < 0 || !rcvsize || !xmitsize)
       return NULL;

    portp = port_list;

    if (port & 0x80)     /* Relative port number */
       {
       port &= 0x7f;
       if (port > 4)
          return NULL;
       pbase = *((wordptr)(MK_FP (0x40, port * 2)));
       if (!pbase)
          return NULL;

       for (port = 0; port < ports; port++, portp = portp->next)
          if (portp->base == pbase)
             break;

       if (port >= ports)
          return NULL;
       }
    else
       {
       if (port > ports)
          return NULL;
       for (port = 0; port < ports; port++)
          portp = portp->next;
       }

    if (portp->sio != NULL) /* Port already in use ? */
       return NULL;

    if (port < STATIC_PORTS)
       portp->sio = sio = &sio_data [port];
    else
 #if (TSK_DYNAMIC)
       if ((portp->sio = sio = tsk_alloc (sizeof (sio_datarec))) == NULL)
          return NULL;
 #else
       return NULL;
 #endif

    pbase = sio->port_base = portp->base;
    sio->port = portp;

    /* Check if port accessible by modifying the modem control register */

    i = sio->cmodcontrol = sio->save_mcon = tsk_inp (pbase + modemcontrol);
    if (i & 0xe0)
       return ret_error (sio);
    tsk_nop ();
    tsk_outp (pbase + modemcontrol, 0xe0 | i);
    tsk_nop ();
    if (tsk_inp (pbase + modemcontrol) != (byte) i)
       return ret_error (sio);

    /* Port seems OK */

    if (create_pipe (&sio->xmit_pipe, xmitbuf, xmitsize
 #if (TSK_NAMEPAR)
                 , xname
 #endif
                 ) == NULL)
       return ret_error (sio);

    if (create_wpipe (&sio->rcv_pipe, rcvbuf, rcvsize
 #if (TSK_NAMEPAR)
                 , rname
 #endif
                 ) == NULL)
       {
       delete_pipe (&sio->xmit_pipe);
       return ret_error (sio);
       }

    sio->civect = portp->vector;
    sio->irqbit = (byte)(1 << (portp->irq & 0x07));

    sio->wait_xmit = sio->xmit_pending = 0;
    sio->overrun = 0;
    sio->flags = 0;
    sio->modem_flags = 0;
    sio->r_xoff = sio->t_xoff = 0;
    sio->rtsoff = 0;

    sio->clcontrol = sio->save_lcon = tsk_inp (pbase + linecontrol);
    tsk_nop ();
    sio->save_inten = tsk_inp (pbase + intenable);
    tsk_nop ();

    if (init)
       {
       sio->clcontrol = dflt_lcon;
       sio->cmodcontrol = dflt_modcon;
       }

    tsk_outp (pbase + linecontrol, sio->clcontrol | 0x80);
    tsk_nop ();
    sio->save_bd1 = tsk_inp (pbase + baudreg_dll);
    tsk_nop ();
    sio->save_bd2 = tsk_inp (pbase + baudreg_dlm);
    tsk_nop ();
    tsk_outp (pbase + linecontrol, sio->clcontrol);
    tsk_nop ();

    tsk_outp (pbase + intenable, 0);

    if (irq_array [portp->irq] == NULL)
       {
       intptr = (intprocptr far *)MK_FP (0, sio->civect * 4);
       tsk_cli ();
       sio->savvect = *intptr;
       *intptr = irq_procs [portp->irq];
       tsk_sti ();
       }

    if (init)
       {
       tsk_outp (pbase + linecontrol, dflt_lcon | 0x80);
       tsk_nop ();
       tsk_outp (pbase + baudreg_dll, dflt_baud);
       tsk_nop ();
       tsk_outp (pbase + baudreg_dlm, dflt_baud >> 8);
       tsk_nop ();
       tsk_outp (pbase + linecontrol, dflt_lcon);
       tsk_nop ();
       tsk_outp (pbase + modemcontrol, dflt_modcon);
       tsk_nop ();
       }
    else
       {
       i = tsk_inp (pbase + modemcontrol) | OUT2;
       tsk_nop ();
       tsk_outp (pbase + modemcontrol, i);
       tsk_nop ();
       }

    while (tsk_inp (pbase + linestatus) & rxreadybit)
       {
       tsk_nop ();
       tsk_inp (pbase + receivedata);
       tsk_nop ();
       }
    tsk_nop ();

    tsk_inp (pbase + linestatus);
    tsk_nop ();
    sio->modstat = tsk_inp (pbase + modemstatus);
    tsk_nop ();
    tsk_inp (pbase + intid);
    tsk_nop ();

    inta = (portp->irq > 7) ? inta11 : inta01;

    if (irq_array [portp->irq] == NULL)
       {
       if (portp->irq > 7)
          {
          i = tsk_inp (inta01) & ~CHAIN_IRQBIT;
          tsk_nop ();
          tsk_outp (inta01, i);
          }

       sio->save_irq = (byte)((i = tsk_inp (inta)) & sio->irqbit);
       tsk_nop ();
       tsk_outp (inta, i & ~sio->irqbit);
       }
    else
       sio->save_irq = (irq_array [portp->irq])->save_irq;

    tsk_cli ();
    sio->next = irq_array [portp->irq];
    irq_array [portp->irq] = sio;
    tsk_sti ();

    v24_remove_func = v24_remove_all;

    tsk_outp (pbase + intenable, intdata);

         return sio;
    }


 void far v24_remove (sioptr sio, int restore)
    {
    intprocptr far *intptr;
    int pbase, i, inta;
    portptr portp;
    sioptr curr, last;

    pbase = sio->port_base;
    portp = sio->port;

    last = NULL;
    curr = irq_array [portp->irq];
    while (curr != sio && curr != NULL)
       {
       last = curr;
       curr = curr->next;
       }
    if (curr == NULL)
       return;

    tsk_outp (pbase + intenable, 0);
    tsk_cli ();
    if (last == NULL)
       irq_array [portp->irq] = sio->next;
    else
       last->next = sio->next;
    tsk_sti ();

    inta = (portp->irq > 7) ? inta11 : inta01;

    if (restore)
       {
       tsk_outp (pbase + modemcontrol, sio->save_mcon);
       tsk_nop ();
       tsk_outp (pbase + linecontrol, sio->save_lcon | 0x80);
       tsk_nop ();
       tsk_outp (pbase + baudreg_dll, sio->save_bd1);
       tsk_nop ();
       tsk_outp (pbase + baudreg_dlm, sio->save_bd2);
       tsk_nop ();
       tsk_outp (pbase + linecontrol, sio->save_lcon);
       tsk_nop ();
       if (irq_array [portp->irq] == NULL)
          {
          tsk_cli ();
          tsk_outp (pbase + intenable, sio->save_inten);
          i = tsk_inp (inta) & ~sio->irqbit;
          tsk_nop ();
          tsk_outp (inta, i | sio->save_irq);
          }
       }
    else if (irq_array [portp->irq] == NULL)
       {
       tsk_cli ();
       i = tsk_inp (inta) | sio->irqbit;
       tsk_nop ();
       tsk_outp (inta, i);
       }

    if (irq_array [portp->irq] == NULL)
       {
       tsk_cli ();
       intptr = (intprocptr far *)MK_FP (0, sio->civect * 4);
       *intptr = sio->savvect;
       }
    tsk_sti ();

    portp->sio = NULL;
    delete_pipe (&sio->xmit_pipe);
    delete_wpipe (&sio->rcv_pipe);

 #if (TSK_DYNAMIC)
    if (portp->pnum >= STATIC_PORTS)
       tsk_free (sio);
 #endif
    }


 void far v24_remove_all (void)
 {
    int i;
    sioptr sio;

    for (i = 0; i < MAX_IRQ; i++)
       {
       while ((sio = irq_array [i]) != NULL)
          v24_remove (sio, RESTORE_DEFAULT);
       }
 }

 /*-------------------------------------------------------------------------*/

 /*
    void v24_change_rts (sioptr sio, int on)
 */

 void far v24_change_rts (sioptr sio, int on)
 {
    sio->cmodcontrol = (sio->cmodcontrol & ~RTS) | ((on) ? RTS : 0);
    tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
 }

 /*
    void v24_change_dtr (sioptr sio, int on)
 */

 void far v24_change_dtr (sioptr sio, int on)
 {
    sio->cmodcontrol = (sio->cmodcontrol & ~DTR) | ((on) ? DTR : 0);
    tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
 }


 /*
    void far v24_change_baud (sioptr sio, int rate)
 */

 void far v24_change_baud (sioptr sio, long rate)
 {
    int i;

    for (i = 0; baud_table [i]; i += 2)
       if (baud_table [i] == rate)
          break;
    if (!(i = (int)baud_table [i + 1]))
       return;

    tsk_outp (sio->port_base + linecontrol, sio->clcontrol | (byte)0x80);
    tsk_nop ();
    tsk_outp (sio->port_base + baudreg_dll, (byte)i);
    tsk_nop ();
    tsk_outp (sio->port_base + baudreg_dlm, (byte)(i >> 8));
    tsk_nop ();
    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
 }


 void far v24_change_parity (sioptr sio, int par)
 {
    sio->clcontrol = (sio->clcontrol & 0xc7) | par;
    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
 }


 void far v24_change_wordlength (sioptr sio, int len)
 {
    int i;

    switch (len)
       {
       case 5:  i = 0x00; break;
       case 6:  i = 0x01; break;
       case 7:  i = 0x02; break;
       case 8:  i = 0x03; break;
       default: return;
       }
    sio->clcontrol = (sio->clcontrol & 0xfc) | i;
    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
 }


 void far v24_change_stopbits (sioptr sio, int n)
 {
    int i;

    switch (n)
       {
       case 1:  i = 0x00; break;
       case 2:  i = 0x04; break;
       default: return;
       }
    sio->clcontrol = (sio->clcontrol & 0xfb) | i;
    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
 }


 void far v24_watch_modem (sioptr sio, byte flags)
 {
    sio->modem_flags = flags & (CTS | DSR | RI | CD);
 }


 void far v24_protocol (sioptr sio, int prot, word offthresh, word onthresh)
 {
    byte old;

    old = sio->flags;
    sio->flags = (byte)prot;
    if (prot)
       {
       if (!offthresh)
          offthresh = 10;
       sio->xoff_threshold = offthresh;
       if (onthresh <= offthresh)
          onthresh = offthresh + 10;
       sio->xon_threshold = onthresh;
       }

    if ((old & RTSCTS) != ((byte)prot & RTSCTS))
       {
       change_rts (sio, 1);
       sio->modem_flags = (sio->modem_flags & ~CTS) |
                          ((prot & RTSCTS) ? CTS : 0);
       }

    if (!(prot & XONXOFF))
       {
       if (sio->r_xoff)
          sio->r_xoff = -2;
       sio->t_xoff = 0;
       }

    if (!sio->xmit_pending)
       transmit_ready (sio);
 }


 /*-------------------------------------------------------------------------*/


 int far v24_send (sioptr sio, byte ch, dword timeout)
 {
    int res;

    if ((res = write_pipe (&sio->xmit_pipe, ch, timeout)) < 0)
       return res;
    tsk_cli ();
    if (!sio->xmit_pending)
       transmit_ready (sio);
    tsk_sti ();
    return 0;
 }


 int far v24_receive (sioptr sio, dword timeout)
 {
    int res;

    if ((res = (int)read_wpipe (&sio->rcv_pipe, timeout)) < 0)
       return res;

    if (!sio->flags)
       return res;

    if (wpipe_free (&sio->rcv_pipe) > sio->xon_threshold)
       {
       tsk_cli ();
       if (sio->r_xoff)
          {
          sio->r_xoff = -2;
          if (!sio->xmit_pending)
             transmit_ready (sio);
          }
       tsk_sti ();

       if (sio->rtsoff)
          change_rts (sio, 1);
       }
    return res;
 }


 int far v24_overrun (sioptr sio)
 {
    int res;

    res = sio->overrun;
    sio->overrun = 0;
    return res;
 }


 int far v24_check (sioptr sio)
 {
    return check_wpipe (&sio->rcv_pipe);
 }


 int far v24_modem_status (sioptr sio)
 {
    return sio->modstat;
 }


 int far v24_complete (sioptr sio)
 {
    return (check_pipe (&sio->xmit_pipe) == -1);
 }


 int far v24_wait_complete (sioptr sio, dword timeout)
 {
    return wait_pipe_empty (&sio->xmit_pipe, timeout);
 }




 TSKSNAP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKSNAP.C

 /*
    TSKSNAP.C - CTask State Snaphot

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany

    This file is new with Version 1.1
 */

 #include "tsk.h"
 #include "tsklocal.h"

 #if (TSK_NAMED)

 local char *sn_state [] = { "*???*", "Stop", "Delay", "Wait", "Elig", "Run" }
 local char *sn_kind [] = { "*Undef*", "Task", "Flag", "Resource", "Counter",
                            "Mailbox", "Pipe", "Wpipe", "Buffer" };

 local int sn_wlist (FILE *f, char *str, tqueptr list, int col)
 {
    tcbptr curr;

    if ((curr = *list) == NULL)
       return col;
    if (col)
       fprintf (f, "\n%51c", ' ');
    col = 52;
    fprintf (f, "%6s(%Fp):  ", str, list);
    while (curr != NULL)
       {
       if (col >= 60)
          {
          fprintf (f, "\n51c", ' ');
          col = 52;
          }
       fprintf (f, "%-8s(%Fp) ", curr->name.name, curr);
       col += 20;
       curr = curr->next;
       }
    return col;
 }

 local void dump_events (FILE *f)
 {
    nameptr curr;
    int col;
    flagptr fl;
    counterptr ct;
    resourceptr rs;
    mailboxptr mb;
    pipeptr pp;
    wpipeptr wp;
    bufferptr bp;

    fprintf (f, "List of Events:\n");
    /*           1234567890123456789012345678901234567890123456789012345
                 12345678   12345678  12345678  123456(123456789):        */
    fprintf (f, "Name       Type         State     Waitfor(Queue)   Tasks\n");

    for (curr = tsk_name_list.follow; curr->nkind; curr = curr->follow)
       if (curr->nkind != TYP_TCB)
          {
          fprintf (f, "%-8s   %-8s  ", curr->name, sn_kind [curr->nkind]);
          switch (curr->nkind)
             {
             case TYP_FLAG: fl = (flagptr) curr->strucp;
                            fprintf (f, "%8s  ", (fl->state) ? "Set" : "Clear"
                            col = sn_wlist (f, "Set", &fl->wait_set, 0);
                            sn_wlist (f, "Clear", &fl->wait_clear, col);
                            break;

             case TYP_COUNTER: ct = (counterptr) curr->strucp;
                            fprintf (f, "%8ld  ", ct->state);
                            col = sn_wlist (f, "Set", &ct->wait_set, 0);
                            sn_wlist (f, "Clear", &ct->wait_clear, col);
                            break;

             case TYP_RESOURCE: rs = (resourceptr) curr->strucp;
                            fprintf (f, "%8s  ", (rs->state) ? "Free" : "Busy"
                            col = sn_wlist (f, "Owner", &rs->owner, 0);
                            sn_wlist (f, "Wait", &rs->waiting, col);
                            break;

             case TYP_MAILBOX: mb = (mailboxptr) curr->strucp;
                            fprintf (f, "%8s  ", (mb->mail_first == NULL)
                                     ? "Empty" : "Mail");
                            sn_wlist (f, "Mail", &mb->waiting, 0);
                            break;

             case TYP_PIPE: pp = (pipeptr) curr->strucp;
                            fprintf (f, "%8u  ", pp->filled);
                            col = sn_wlist (f, "Read", &pp->wait_read, 0);
                            col = sn_wlist (f, "Write", &pp->wait_write, col);
                            sn_wlist (f, "Clear", &pp->wait_clear, col);
                            break;

             case TYP_WPIPE: wp = (wpipeptr) curr->strucp;
                            fprintf (f, "%8u  ", wp->filled);
                            col = sn_wlist (f, "Read", &wp->wait_read, 0);
                            col = sn_wlist (f, "Write", &wp->wait_write, col);
                            sn_wlist (f, "Clear", &wp->wait_clear, col);
                            break;

             case TYP_BUFFER: bp = (bufferptr) curr->strucp;
                            fprintf (f, "%8u  ", bp->msgcnt);
                            col = sn_wlist (f, "Read", &bp->buf_read.waiting,
                            sn_wlist (f, "Write", &bp->buf_write.waiting, col)
                            break;

             default:       fprintf (f, "*Invalid Type %02x", curr->nkind);
                            break;
             }
          fprintf (f, "\n");
          }
    fprintf (f, "\n");
 }


 local void dump_tasks (FILE *f)
 {
    nameptr curr;
    tcbptr task;
    fprintf (f, "\nTask List:\n");
    fprintf (f, "Name     State Queue      Timeout TCB-addr  Stackptr  Stackbo

    for (curr = tsk_name_list.follow; curr->nkind; curr = curr->follow)
       if (curr->nkind == TYP_TCB)
          {
          task = (tcbptr) curr->strucp;

          fprintf (f, "%-8s %-5s %Fp %8ld %Fp %Fp %Fp %Fp %5u\n",
                  curr->name,
                  sn_state [(task->state <= 5)
                            ? task->state : 0],
                  task->queue,
                  task->timerq.timeout,
                  task,
                  task->stack,
                  task->stkbot,
                  ((struct task_stack *)task->stack)->retn,
                  task->prior);
          }
    fprintf (f, "\n");
 }


 void snapshot (FILE *f)
 {
    word oldpri;

    oldpri = get_priority (tsk_current);
    set_priority (tsk_current, 0xffff);

    dump_tasks (f);
    dump_events (f);

    set_priority (tsk_current, oldpri);
 }

 #endif



 TSKSUB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKSUB.C

 /*
    CTask Subroutines

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany

    Version 1.1  88-07-01

       Changes from V0.1: - Handling of timeout queue rewritten
                          - Timeouts in milliseconds (optional)
                          - Support for dynamically allocated control blocks.
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"

 /*
    tsk_enqueue  inserts a task into a queue based on priority.
 */

 void far tsk_enqueue (tcbptr task, tqueptr que)
 {
    tcbptr last, curr;

    last = NULL;
    curr = *que;

    while (curr != NULL && curr->prior >= task->prior)
       {
       last = curr;
       curr = curr->next;
       }
    task->next = curr;
    if (last == NULL)
       *que = task;
    else
       last->next = task;
    task->queue = que;
 }


 /*
    tsk_unqueue
       Removes a task from somewhere in the middle of a queue. It is only
       used when stopping or prematurely waking a task, since in all other
       circumstances a task is only removed from the head of a queue.
 */

 void far tsk_unqueue (tcbptr task)
 {
    tcbptr last, curr;

    if (task->state == ST_RUNNING || task->queue == NULL)
       return;

    last = NULL;
    curr = *task->queue;

    while (curr != task)
       {
       if (curr == NULL)
          return;
       last = curr;
       curr = curr->next;
       }
    if (last == NULL)
       *task->queue = curr->next;
    else
       last->next = curr->next;
    task->queue = NULL;
 }


 /*
    tsk_enqtimer inserts a task into the timer queue.
 */

 void far tsk_enqtimer (tcbptr task, dword tout)
 {
    tlinkptr curr;

    if (tout == 0)
       return;

    /*
       Tasks are not sorted in the timer queue, so the task is inserted
       at the queue head. The timer task has to step through all tasks
       in the queue to cont down the timeout, so sorting would not bring
       any advantages.
    */

    curr = &task->timerq;
    curr->timeout = tsk_timeout(tout);
    if (curr->tstate == TSTAT_IDLE)
       {
       curr->next = tsk_timer;
       tsk_timer = curr;
       }
    curr->tstate = TSTAT_COUNTDOWN;
 }


 /*
    tsk_runable
       make a task eligible for running. The task is removed from the
       timer queue and enqueued in the eligible queue. The old "next"
       pointer of the tcb is returned. This assumes that the task
       is removed from the head of a queue.
 */

 tcbptr far tsk_runable (tcbptr task)
 {
    tcbptr nxt;

    nxt = task->next;
    task->state = ST_ELIGIBLE;
    tsk_unqtimer (task);
    tsk_enqueue (task, &tsk_eligible);
    return nxt;
 }


 /*
    tsk_wakeup
       make a task eligible for running. The task is removed from the
       timer queue and enqueued in the eligible queue.
       This routine assumes that the task is removed from the middle of
       a queue.
 */

 void far tsk_wakeup (tcbptr task)
 {
    task->state = ST_ELIGIBLE;
    tsk_unqueue (task);
    tsk_unqtimer (task);
    tsk_enqueue (task, &tsk_eligible);
 }


 /*
    tsk_wait - put current running task in wait state.
               Note that the task is NOT enqueued in the respective queue
               here, this is done by the scheduler based on the queue head
               pointer. Only the timeout queue is affected directly.
 */

 void far tsk_wait (tqueptr que, dword timeout)
 {
    tsk_current->state = ST_WAITING;
    tsk_current->queue = que;
    tsk_enqtimer (tsk_current, timeout);
    schedule ();
 }


 /*
    tsk_kill - mark task as killed.
 */

 void far tsk_kill (tcbptr task)
 {
 #if (TSK_NAMED)
    tsk_del_name (&task->name);
 #endif

    task->state = ST_KILLED;
    if (task->timerq.tstate != TSTAT_IDLE)
       {
       task->timerq.tstate = (byte) TSTAT_REMOVE;
 #if (TSK_DYNAMIC)
       if (task->flags & F_TEMP)
          task->timerq.tkind |= TKIND_TEMP;
       }
    else
       {
       if (task->flags & F_STTEMP)
          tsk_free (task->stack);
       if (task->flags & F_TEMP)
          tsk_free (task);
       }
 #else
       }
 #endif
 }

 /*
    tsk_kill_queue
       Removes all tasks from a queue. For internal use only, critical
       section assumed entered.
 */

 void far tsk_kill_queue (tqueptr que)
 {
    tcbptr curr;

    for (curr = *que; curr != NULL; curr = curr->next)
       {
       tsk_unqtimer (curr);
       tsk_kill (curr);
       }
    *que = NULL;
 }


 #if (CLOCK_MSEC)

 dword tsk_timeout (dword tout)
 {
    dword t;

    t = (dword) (((double)tout / tick_factor) + 0.5);
    return (t) ? t : 1;
 }

 #endif

 #if (TSK_NAMED)

 /*
    tsk_add_name
       Initialise name-list element and insert it at the end of the list.
       NOTE: no check is made for duplicate names; names are not sorted.
 */

 void far tsk_add_name (nameptr elem, byteptr name, byte kind, farptr strucp)
 {
    byteptr n;
    int i;
    CRITICAL;

    elem->nkind = kind;
    elem->strucp = strucp;
    n = elem->name;
    if (name != NULL)
       for (i = 0; i < 8; i++)
          if (!(*n++ = *name++))
             break;
    *n = 0;

    C_ENTER;
    elem->prev = tsk_name_list.prev;
    tsk_name_list.prev = elem;
    elem->follow = &tsk_name_list;
    elem->prev->follow = elem;
    C_LEAVE;
 }


 /*
    tsk_del_name
       delete name-element from the name-list.
 */

 void far tsk_del_name (nameptr elem)
 {
    CRITICAL;

    C_ENTER;
    elem->follow->prev = elem->prev;
    elem->prev->follow = elem->follow;
    C_LEAVE;
 }


 /*
    find_name
       find structure, given name and type.
       If type is zero, the first name-element matching the name is returned.
       If type is nonzero, the first structure matching the name and type is
       returned.
 */

 local int tsk_streq (byteptr n1, byteptr n2)
 {
    while (*n1 && *n1 == *n2)
       {
       n1++;
       n2++;
       }
    return *n1 == *n2;
 }

 farptr far find_name (byteptr name, byte kind)
 {
    nameptr curr;

    for (curr = tsk_name_list.follow; curr->nkind; curr = curr->follow)
       if (!kind || curr->nkind == kind)
          if (tsk_streq (name, curr->name))
             return (kind) ? curr->strucp : curr;

    return NULL;
 }
 #endif



 TSKWPIP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\CTASK11\TSKWPIP.C

 /*
    TSKWPIP.C - CTask - Word Pipe handling routines.

    Public Domain Software written by
       Thomas Wagner
       Patschkauer Weg 31
       D-1000 Berlin 33
       West Germany
 */

 #include <stdio.h>

 #include "tsk.h"
 #include "tsklocal.h"

 /*
    tsk_getwpipe - get a word from a pipe. For internal use only.
                   Critical section assumed entered.
 */

 local word near tsk_getwpipe (wpipeptr pip)
 {
    word c;

    c = pip->wcontents [pip->outptr++];
    if (pip->outptr >= pip->bufsize)
       pip->outptr = 0;
    pip->filled--;
    return c;
 }


 /*
    tsk_putwpipe - put a word to a pipe. For internal use only.
                   Critical section assumed entered.
 */

 local void near tsk_putwpipe (wpipeptr pip, word c)
 {
    pip->wcontents [pip->inptr++] = c;
    if (pip->inptr >= pip->bufsize)
       pip->inptr = 0;
    pip->filled++;
 }


 /* -------------------------------------------------------------------- */


 /*
    create_wpipe - initialises wpipe.
 */

 wpipeptr far create_wpipe (wpipeptr pip, farptr buf, word bufsize
 #if (TSK_NAMEPAR)
                            ,byteptr name
 #endif
                            )
 {
 #if (TSK_DYNAMIC)
    if (pip == NULL)
       {
       if ((pip = tsk_alloc (sizeof (wpipe))) == NULL)
          return NULL;
       pip->flags = F_TEMP;
       }
    else
       pip->flags = 0;
    if (buf == NULL)
       {
       if ((buf = tsk_alloc (bufsize)) == NULL)
          {
          if (pip->flags & F_TEMP)
             tsk_free (pip);
          return NULL;
          }
       pip->flags |= F_STTEMP;
       }
 #endif

    pip->wait_read = pip->wait_write = pip->wait_clear = NULL;
    pip->outptr = pip->inptr = pip->filled = 0;
    pip->bufsize = bufsize >> 1;
    pip->wcontents = (wordptr)buf;

 #if (TSK_NAMED)
    tsk_add_name (&pip->name, name, TYP_WPIPE, pip);
 #endif

    return pip;
 }


 /*
    delete_wpipe - kills all processes waiting for reading from or writing
                   to the wpipe.
 */

 void far delete_wpipe (wpipeptr pip)
 {
    CRITICAL;

    C_ENTER;
    tsk_kill_queue (&(pip->wait_read));
    tsk_kill_queue (&(pip->wait_write));
    tsk_kill_queue (&(pip->wait_clear));
    pip->outptr = pip->inptr = pip->filled = 0;
    C_LEAVE;

 #if (TSK_NAMED)
    tsk_del_name (&pip->name);
 #endif

 #if (TSK_DYNAMIC)
    if (pip->flags & F_STTEMP)
       tsk_free (pip->wcontents);
    if (pip->flags & F_TEMP)
       tsk_free (pip);
 #endif
 }


 /*
    read_wpipe - Wait until a word is written to the wpipe. If there
                 is a word in the wpipe on entry, it is assigned to
                 the caller, and the task continues to run. If there are
                 tasks waiting to write, the first task is made eligible,
                 and the word is inserted into the wpipe.
 */

 word far read_wpipe (wpipeptr pip, dword timeout)
 {
    tcbptr curr;
    word res;
    CRITICAL;

    C_ENTER;

    if (pip->filled)
       {
       res = tsk_getwpipe (pip);

       if ((curr = pip->wait_write) != NULL)
          {
          tsk_putwpipe (pip, curr->retsize);
          pip->wait_write = tsk_runable (curr);
          curr->retptr = NULL;
          }
       else if (!pip->filled)
          while (pip->wait_clear != NULL)
             pip->wait_clear = tsk_runable (pip->wait_clear);

       C_LEAVE;
       return res;
       }

    tsk_wait (&pip->wait_read, timeout);
    return (word)tsk_current->retptr;
 }


 /*
    c_read_wpipe - If there is a word in the wpipe on entry,
                   read_wpipe is called, otherwise an error status is returned
 */

 word far c_read_wpipe (wpipeptr pip)
 {
    CRITICAL, res;

    C_ENTER;
    res = (pip->filled) ? read_wpipe (pip, 0L) : (word)-1;
    C_LEAVE;
    return res;
 }



 /*
    write_wpipe - Wait until space for the word to be written to the
                  wpipe is available. If there is enough space in the wpipe
                  on entry, the word is inserted into the wpipe, and
                  the task continues to run. If there are tasks waiting
                  to read, the first task is made eligible, and the word
                  is passed to the waiting task.
 */

 int far write_wpipe (wpipeptr pip, word ch, dword timeout)
 {
    tcbptr curr;
    CRITICAL;

    C_ENTER;

    if (pip->filled < pip->bufsize)
       {
       if ((curr = pip->wait_read) != NULL)
          {
          pip->wait_read = tsk_runable (curr);
          curr->retptr = (farptr)ch;
          C_LEAVE;
          return 0;
          }

       tsk_putwpipe (pip, ch);
       C_LEAVE;
       return 0;
       }

    tsk_current->retsize = ch;
    tsk_wait (&pip->wait_write, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    c_write_wpipe - If there is space for the word in the wpipe on entry,
                    write_wpipe is called, otherwise an error status is return
 */

 int far c_write_wpipe (wpipeptr pip, word ch)
 {
    int res;
    CRITICAL;

    C_ENTER;
    res = (pip->filled < pip->bufsize) ? write_wpipe (pip, ch, 0L) : -1;
    C_LEAVE;
    return res;
 }


 /*
    wait_wpipe_empty - Wait until the pipe is empty. If the pipe is
                       empty on entry, the task continues to run.
 */

 int far wait_wpipe_empty (wpipeptr pip, dword timeout)
 {
    CRITICAL;

    C_ENTER;
    if (!pip->filled)
       {
       C_LEAVE;
       return 0;
       }

    tsk_current->retptr = NULL;
    tsk_wait (&pip->wait_clear, timeout);
    return (int)tsk_current->retptr;
 }


 /*
    check_wpipe - returns -1 if there are no words in the wpipe, else
                  the first available word.
 */

 word far check_wpipe (wpipeptr pip)
 {
    return (pip->filled) ? pip->wcontents [pip->outptr] : (word)-1;
 }


 /*
    wpipe_free - returns the number of free words in the pipe.
 */

 word far wpipe_free (wpipeptr pip)
 {
    return pip->bufsize - pip->filled;
 }




 TSORT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TSORT.C

   /* TSORT.C - A text file sort program */
   /* Slightly rewritten to run under DRC and UNIX VER 7 C */
   /* Usage:  TSORT <infile >outfile */

 #include          <stdio.h>
 #include          <ctype.h>

  MAXWORD  80                           /* maximum word length */
  NEWLINE  putc('\n',fp)     /* put carraige return in file fp */

 struct text {               /* global declaration of tree node 'text' */
              char word[MAXWORD];
              struct text *lptr;
              struct text *rptr;
 };

 struct text *root;         /* global declaration of root of text tree */

 main(argc, argv)
   /*-----------------------------------------------------------------*/
   /* driver for sort procedure.  Srt will sort lines of a specified  */
   /* input file and place the result in either the stdout or a       */
   /* specified output file.  Program is written for Lattice C but    */
   /* functions provided in its library are documented so that srt    */
   /* might be modified to suit your compiler.  If you have any       */
   /* trouble or questions give me a call (if you can find me)        */
   /*-----------------------------------------------------------------*/
   /* Joe R Wyatt    2311 49th Lubbock, Tx 79412                      */
   /* Home #: 806/793-5689    Office #: 806/763-8011 ext: 239         */
   /*-----------------------------------------------------------------*/
   /* Variables :        fp --     pointer to input file              */
   /*                   fp2 --     ptr to output file                 */
   /*                     c --     integer returned from getw.        */
   /*                     i --     processed line count               */
   /*                     j --     empty line count                   */
   /*                  word --     temporary input line storage       */
   /* Procedures:      getw --     included                           */
   /*                 putwt --     included                           */
   /*                 ptree --     included                           */
   /* Functions :    printf --     string compare                     */
   /*                 fopen --     open file and return file pointer  */
   /*                  exit --     premature exit from program        */
   /*                fclose --     close file                         */
   /*-----------------------------------------------------------------*/
 int argc;
 char *argv[];
 {
      FILE *fp, *fp2, *fopen();
      int c, i, j;
      char word[MAXWORD];

      root = NULL;                                /* root of text tree */
      fp  = stdin;
      fp2 = stdout;
      i = 0;
      j = 0;
      while((c = getw(fp,word)) != EOF) {     /* get next line of file */
           if (strlen(word) != 0) {
                putwt(word);           /* if not null then put in tree */
                i++;            /* increment number of lines processed */
           }
           else
                j++;                 /* else inc number of empty lines */
      }
      fclose(fp);
      ptree(fp2, root);                           /* print sorted tree */
      printf("\nprocedure concluded.\n%d lines processed\n",i);
      printf("%d empty lines ignored.\n",j);
      fclose(fp2);
 }

 putwt(w)
   /*-----------------------------------------------------------------*/
   /* procedure places 'w' in tree named 'text'.                      */
   /* Parameters:         w --     null ended string                  */
   /* Variables :      temp --     temporary pointer                  */
   /*                   ptr --     ptr to node to place 'w' in.       */
   /*                 value --     result of strcmp used for placement*/
   /*                              in text tree.                      */
   /* Procedures:    search --     included                           */
   /* Functions :    strcmp --     string compare                     */
   /*                getmem --     allocate memory for tree           */
   /*                sizeof --     return size of structure           */
   /*                printf --     print string to stdout             */
   /*                strcpy --     string copy                        */
   /*                  exit --     leave prgram prematurly            */
   /*-----------------------------------------------------------------*/
 char *w;
 {
      struct text *search(), *temp, *ptr;
      int value = 1;

      temp = search(w);  /* locate position to place new node in tree */

      if (temp != NULL) /* if NULL then tree is empty. else compare keys */
           value = strcmp(w, temp -> word);
      if (value == 0)                    /* duplicate entry.  ignore. */
           return;

      ptr = (struct text *)malloc(sizeof(struct text));
      if (ptr == NULL) {                   /* memory allocation error */
           printf("out of memory\n");
           exit(1);
      }
        strcpy(ptr -> word, w);                     /* store new node */
        ptr -> lptr = NULL;
        ptr -> rptr = NULL;

      if (temp != NULL) {                   /* place new node in tree */
           if (value > 0)
                temp -> rptr = ptr;
           else
                temp -> lptr = ptr;
           }
      else
           root = ptr;
      return;
 }

 struct text *search(w)
   /*-----------------------------------------------------------------*/
   /* procedure locates where 'w' is to be placed in text tree and    */
   /* returns pointer to prior node.                                  */
   /* procedure places 'w' in tree named 'text'.                      */
   /* Parameters:         w --     null ended string                  */
   /* Variables :      ptr1 --     temporary pointer                  */
   /*                  ptr2 --     lags ptr1 by one node              */
   /*                 value --     result of strcmp used for placement*/
   /*                              in text tree.                      */
   /* Functions :    strcmp --     string compare                     */
   /*-----------------------------------------------------------------*/
 char *w;
 {
      struct text *ptr1;
      struct text *ptr2;
      int value;

      ptr1 = root;                             /* initialize pointers */
      ptr2 = root;
      while(ptr1 != NULL) {
           ptr2 = ptr1;
           value = strcmp(w, ptr1 -> word);
           if (value > 0)
                ptr1 = ptr1 -> rptr;
           else if (value < 0)
                ptr1 = ptr1 -> lptr;
           else
                ptr1 = NULL;
      }
      return(ptr2);
 }

 ptree(fp, ptr)
   /*-----------------------------------------------------------------*/
   /* recursive procedure to print contents of text tree.             */
   /* Parameters:        fp --     pointer to output file.            */
   /*                   ptr --     pointer to root of current subtree */
   /* Procedures:      putw --     included                           */
   /*-----------------------------------------------------------------*/
 FILE *fp;
 struct text *ptr;
 {
      if (ptr != NULL) {
           ptree(fp, ptr -> lptr);   /* find leftmost node of subtree */
           putw(fp, ptr -> word);                       /* print data */
           ptree(fp, ptr -> rptr);             /* print right subtree */
      }
 }

 EOW -2    /* end of word */
 getw(fp,w)
   /*-----------------------------------------------------------------*/
   /* gets next line in input file.                                   */
   /* Parameters:        fp --     pointer to input file              */
   /*                     w --     pointer to string for input        */
   /* Variables :         c --     input character                    */
   /*                     f --     end of word flag                   */
   /*                 count --     number of characters               */
   /* Functions :      getc --     get byte from input file           */
   /*-----------------------------------------------------------------*/
 FILE *fp;
 char *w;
 {
      int c,f,count;

      f = 0;                                 /* initialize local vars */
      count = 0;
      while (f != EOW && count < MAXWORD) {
           c = getc(fp);
           if (c != EOF && c != '\n') {       /* input to end of line */
                count++;                    /* increment byte counter */
                *w++ = c;
           }
           else
                f = EOW; /* end of line reached or max chars exceded. */
      }
      *w = '\0';                  /* place null byte on end of string */
      return(c);                         /* return last byte of input */
 }

 putw(fp,w)
   /*-----------------------------------------------------------------*/
   /* prints string to output file.                                   */
   /* Parameters:        fp --     pointer to input file              */
   /*                     w --     pointer to string for input        */
   /* Variables :         c --     output character                   */
   /* Functions :      putc --     put byte to output file            */
   /*-----------------------------------------------------------------*/
 FILE *fp;
 char *w;
 {
      int c;

      while (*w != '\0')
           putc(*w++, fp);
      NEWLINE;
 }


 TSR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLC_TSR\TSR.C

 /*
 In December of 1986 Roy Sherrill, President of Datalight, asked me if I
 could produce a Terminate and Stay Resident (TSR) library function for
 Datalight C.  He explained that a consultant programmer known by him to
 be capable of producing such a library function estimated 4 to 6 months
 effort.  I scoffed at that and produced my first version of a fully
 operational TSR library function over the following weekend.  A
 demonstration copy was forwarded to Datalight and Roy Sherrill
 encouraged me to enhance that version with a screen saver function, all
 the while strongly implying that Datalight wished to use the resultant
 library function as a product.

 Roy Sherrill was either not serious or is in the progress of reverse
 engineering the .OBJ files he received from me.  In either case, his
 time is up.  I offer the enclosed files to any C programmer who finds
 them useful with no strings or encumberances of any kind.  In other
 words, the enclosed files are offered free and clear to the public
 domain to whomever desires to use them.

 Anyone desiring the source code for TSR.OBJ should contact me
 personally.

 John J. Newlin
 4060-288 Rosenda Ct.
 San Diego, CA 92122
 (619) 455-6225

 A note to Roy Sherrill:  It won't be Microsoft that treads on
 Datalight's grave - it will be Borland!!!
 */


 /* minimum configuration is _stack = 2048 - 470h paragraphs
    with no screen save */
 #include <stdio.h>
 int _stack = 6048;
 main()
 {
   if (check_tsr() == 112)  /* 112 = Alt-F9 */
   /* check_tsr returns an integer equal to the hot key value of any
      Datalight TSR routines currently in memory.  It is used to determine
      if your TSR has already been installed */
   {
      puts("TSR installed in memory\07");
      exit(1);
   }
   puts("DATALIGHT C memory resident demo installed");
   tsr_init(112,0x0500);
   /* tsr_init is called with two integer values.  The first is the
   extended scan code of the activation ("hot") key.  The second is the
   amount of memory (in 16 byte paragraphs) needed to support the TSR.
   Memory calculation must be accomplished by the programmer prior to
   final compilation and linking. */

 }
 tsr_main()
 /* tsr_main is the function called by the TSR when the "hot" key is
 sensed.  It MUST have this name.  It may call any other functions and
 acts as the primary gateway between the resident handler and the main
 program code.  Place your desired code here. */

 { int key,attr;
   char vmode,*msg;
   static char *buffer[4000];
   /* This buffer is used to save the entire screen but it is possible to
      use savescrn and restscrn to save and selected portions of the screen.
      For example, savescrn(10,10,20,8,buffer) would save a rectangular
      portion of the screen with the upper left hand corner at 10,10, a
      width of 20 columns, and a depth of 8 rows.  A buffer on the heap just
      large enough to contain the portion of the screen desired to be saved
      may be employed by using the intrinsic call calloc.  The amount of
      memory required is computed as width * depth * 2.
   */

   savecurs();
   /* Saves the position and the type of the current cursor */

   savescrn(1,1,80,25,buffer);
   /* This function saves a selected rectangular portion of the screen.  In
      this case the entire screen is saved.  The function declaration
      (restscrn is the same) is:

                void savescrn(col,row,width,depth,buffer);
                int col,row,width,depth;
                char *buffer;

      where col is the column coordinate of the upper left hand corner of the
      rectangle, row is the row coordinate of the upper left hand corner of
      the rectangle, width is the width of the rectangle in columns, and depth
      is the height of the rectangle in rows (normalized so that the top left
      corner of the full screen is column 1, row 1)
   */

   cls(14); /* clears the entire screen with an attribute of 0Eh.  Declared
               as :
                    void cls(attribute);
                    int attribute;
            */

   /*
       The type of video monitor is detected and adjusted for automatically
       upon each call to savescrn.
   */

   msg = "TERMINATE & STAY RESIDENT DEMONSTRATION";

   gotoxy(21,6);  /* position the cursor - normalized to (1,1) for upper left
                     corner of the full screen.  Declared as :

                            void gotoxy(col,row);
                            int col,row;
                   */

   puts(msg);
   msg = "DATALIGHT C";
   gotoxy(35,8);
   puts(msg);
   msg = "by John Newlin";
   gotoxy(33,10);
   puts(msg);
   msg = "Copyright (C) 1987";
   gotoxy(31,12);
   puts(msg);
   msg = "Any key continues";
   gotoxy(32,14);
   puts(msg);
   msg = "End key deinstalls";
   gotoxy(31,16);
   puts(msg);
   key = getkey(); /* my personal keyboard interrogator */
   if (key == 335)
     {
       restscrn(1,1,80,25,buffer);  /* restore the saved screen */
       restcurs();  /* restore the saved cursor type and position */
       remove();                   /* remove this TSR */
     }
   restscrn(1,1,80,25,buffer);      /* restore the saved screen */
   restcurs();                     /* restore the cursor type and position */
 }



 TTY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\TTY.C

 /*
  *        TTY.C                A quick general purpose terminal program.
  */

 #include <stdio.h>
 #include <osbind.h>
 #ifdef dLibs
 #include <time.h>
 #endif

 #define        ident        "TTY v0.71\033v\r\n"

 #define        ABORT        (-3)
 #define        CANCEL        (-2)

 #define        AUX        1
 #define        CON        2

 #define        SOH        0x01
 #define        STX        0x02
 #define        EOT        0x04
 #define        ACK        0x06
 #define        NAK        0x15
 #define        CAN        0x18
 #define        CEE        0x43

        KEY_UNDO        0x6100                /* [undo]        */
        KEY_HELP        0x6200                /* [help]        */
        KEY_INS                0x5200                /* [insert]        */
        KEY_CLR                0x4700                /* [clr/home]        */
        KEY_CR                0x1C0D                /* [return]        */
        KEY_LF                0x720D                /* [enter]        */
        KEY_BS                0x0E08                /* [backspace]        */
        KEY_DEL                0x537F                /* [delete]        */
        KEY_BRK                0x2E03                /* [control][C]        */
        KEY_F1                0x3B00                /* [f1]                */
        KEY_F2                0x3C00                /* [f2]                */
        KEY_F3                0x3D00                /* [f3]                */
        KEY_F4                0x3E00                /* [f4]                */
        KEY_F5                0x3F00                /* [f5]                */
        KEY_F6                0x4000                /* [f6]                */
        KEY_F7                0x4100                /* [f7]                */
        KEY_F8                0x4200                /* [f8]                */
        KEY_F9                0x4300                /* [f9]                */
        KEY_F10                0x4400                /* [f10]        */
        ALT_C                0x2E00                /* [alt][C]        */
        ALT_A                0x1E00                /* [alt][A]        */
        ALT_DASH        0x8200                /* [alt][-]        */
        ALT_V                0x2F00                /* [alt][V]        */
        ALT_T                0x1400                /* [alt][T]        */
        ALT_E                0x1200                /* [alt][E]        */
        ALT_F                0x2100                /* [alt][F]        */
        ALT_R                0x1300                /* [alt][R]        */
        ALT_S                0x1F00                /* [alt][S]        */
        ALT_B                0x3000                /* [alt][B]        */
        ALT_0                0x8100                /* [alt][0]        */
        ALT_H                0x2300                /* [alt][H]        */
        ALT_X                0x2D00                /* [alt][X]        */
        ALT_G                0x2200                /* [alt][G]        */

        ECODES        3                /* line echo settings (aka duplex) */
        FULLDUP        0                /*        no echo
        HALFDUP        1                /*        local echo                */
        HOSTMOD        2                /*        local & remote echo        *

        XCODES        4                /* # of file xfer modes */
 #define        ASCII        0
 #define        XMODEM        1
 #define        XMODEMC        2
 #define        YMODEM        3

        BCODES        5                /* # of baud rate settings */
 #define        B300        0
 #define        B1200        1
 #define        B2400        2
 #define        B4800        3
 #define        B9600        4

        HSIZ        (1<<11)                /* history size (2K) */
 #define        HMASK        (HSIZ-1)

 int        cd;                        /* current state of carrier */
 BYTE        hist[HSIZ];                /* history buffer */
 int        hp = 0;                        /* history position index */
 BYTE        data[1200];                /* general purpose data buffer */
 int        crcmode, kmode, ybatch;        /* file transfer mode settings */
 int        pktnum;                        /* file transfer packet counter */
 int        noise;                        /* line noise analysis value */
 handle        capture = 0;                /* ascii capture file handle */
 int        crtocrlf = FALSE;        /* convert <cr> --> <cr>+<lf> */
 int        echo = FULLDUP;                /* echo mode (duplex) */
 char        *ename[ECODES] =        /* echo mode names */
         {"full duplex", "half duplex", "host mode"};
 int        xfer = XMODEMC;                /* file xfer mode */
 char        *xname[XCODES] =        /* xfer mode names */
         {"ascii", "xmodem", "xmodem-crc", "ymodem"};
 int        bcode = B300;                /* baud code (not set on entry) */
 int        brate[BCODES] =                /* baud rate values */
         {9, 7, 4, 2, 1};
 char        *bname[BCODES] =        /* baud code names */
         {"300", "1200", "2400", "4800", "9600"};
 int        literal = FALSE;        /* literal mode flag */
 int        debug = FALSE;                /* debugging mode flag */

 struct iorec {
         char        *iobuf;                        /* pointer to buffer */
         int        iobufsiz;                /* size of buffer */
         int        iobufhd;                /* head pointer */
         int        iobuftl;                /* tail pointer */
         int        iobuflo;                /* low water mark */
         int        iobufhi;                /* high water mark */
 };

 typedef struct {
     struct iorec in;                        /*  0 Input buffer
     struct iorec out;                        /* 14 Output buffer
     char        rsr_status;                /* 28 MFP(0x1C) Receiver status
     char        tsr_status;                /* 29 MFP(0x1D) Transmit status
     char        xoff_sent;                /* 30 TRUE if we sent XOFF        *
     char        xoff_received;                /* 31 TRUE if we got XOFF
     char        mode;                        /* 32 Bit 0 XON, Bit 1 RTS mode
     char        filler;                        /* 33 Unused
 } IOREC;

 #define        IBUFSIZ        1200
 #define        OBUFSIZ        2

 char        st_ibuf[IBUFSIZ];        /* our own input buffer                *
 char        st_obuf[OBUFSIZ];        /* and our own output buffer        */

 IOREC        *st_sysr;                /* ptr to system rs232 record        */
 IOREC        st_savr;                /* to save system rs232 record        */

 IOREC        st_myiorec = {                /* my own i/o record */
      st_ibuf, IBUFSIZ, 0, 0, (IBUFSIZ/4), (3*(IBUFSIZ/4)),
      st_obuf, OBUFSIZ, 0, 0, 0, 1,
      0, 0, 0, 0
 };

 #ifndef dLibs
 int strncmp(str1, str2, limit)
 register char *str1;
 register char *str2;
 register int limit;
 /*
  *        Compare strings as with strcmp(), but limit comparison to the
  *        first <limit> characters.
  */
 {
         for(; ((--limit) && (*str1 == *str2)); ++str1, ++str2)
                 if(*str1 == '\0')
                         return(0);
         return(*str1 - *str2);
 }

 /*
  * start_timer & time_since
  *
  * Use 200Hz system clock for an elapsed time function. -Dal
  */
 long start_timer(timer)
 long *timer;
 {
         asm("        clr.l        -(sp)                ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* enter superv
         asm("        addq.l        #6,sp                ");
         asm("        move.l        $4BA,-(sp)        ");        /* save syste
         asm("        move.l        d0,-(sp)        ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* exit supervi
         asm("        addq.l        #6,sp                ");
         asm("        move.l        (sp)+,d0        ");
         asm("        move.l        $8(a6),a0        ");        /* grab pointe
         asm("        move.l        d0,(a0)                ");        /* retur
 }

 long time_since(timer)
 long *timer;
 {
         asm("        clr.l        -(sp)                ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* enter superv
         asm("        addq.l        #6,sp                ");
         asm("        move.l        $4BA,-(sp)        ");        /* save syste
         asm("        move.l        d0,-(sp)        ");
         asm("        move.w        #$20,-(sp)        ");
         asm("        trap        #1                ");        /* exit supervi
         asm("        addq.l        #6,sp                ");
         asm("        move.l        (sp)+,d0        ");
         asm("        move.l        $8(a6),a0        ");        /* grab pointe
         asm("        sub.l        (a0),d0                ");        /* return
 }
 #endif

 msleep(n)                        /* do nothing for n-100ths of a second */
 register int n;
 {
         long t;

         n <<= 1;                /* multiply by 2 to get 200Hz ticks */
         start_timer(&t);
         while(time_since(&t) < n)
                 ;
 }

 rs232cd()                        /* state of rs232 carrier detect line */
 {
         register long ssp;
         register int *mfp, status;

         mfp = ((int *) 0xFFFFFA00L);                /* base address of MFP */
         ssp = Super(0L);                        /* enter supervisor mode */
         status = *mfp;                                /* get MFP status */
         Super(ssp);                                /* return to user mode */
         return(!(status & 0x0002));                /* check for carrier */
 }

 snd_brk()                        /* send a BREAK to the rs232 port */
 {
         register long ssp;
         register char *tsr;

         tsr = ((char *) 0xFFFFFA2DL);                /* address of tsr */
         ssp = Super(0L);                        /* enter supervisor mode */
         *tsr = 0x09;                                /* turn break on */
         Super(ssp);                                /* return to user mode */
         msleep(30);                                /* 0.3 second BREAK */
         ssp = Super(0L);                        /* enter supervisor mode */
         *tsr = 0x01;                                /* turn break off */
         Super(ssp);                                /* return to user mode */
 }

 hangup()                        /* drop carrier by droppping DTR to modem */
 {
         Ongibit(0x10);                                /* kill DTR */
         msleep(50);                                /* wait 1/2 a second */
         Offgibit(0xEF);                                /* restore DTR */
 }

 /*
  * Buffered file input functions
  */
        Bsiz        1024                /* block read size */
        Fsiz        (2*Bsiz)+256        /* buffer size */
 BYTE        Fbuf[Fsiz];                /* file character buffer */
 BYTE        *Fp = &Fbuf[Fsiz];        /* next character to output from Fbuf[]
 int        Fcnt = 0;                /* number of characters in Fbuf[] */
 handle        Fh;                        /* file handle for buffered file */

 Finit(fname)
 char *fname;
 {
         Fp = &Fbuf[Fsiz];
         Fcnt = 0;
         return(Fh = Fopen(fname, 0));
 }

 Fgetc()                        /* get a character from file */
 {
         register int n;

         if(Fcnt <= 0) {
                 Fp -= Bsiz;
                 if((n = Fread(Fh, ((long) Bsiz), Fp)) < 0)
                         Bconws(CON, "<read error>\r\n");
                 if(n <= 0)
                         return(EOF);
                 Fcnt += n;
         }
         --Fcnt;
         return(*Fp++);                /* MUST & with 0xFF if not UNSIGNED */
 }

 Fgetn(buf, n)                /* get 'n' characters from file */
 register char *buf;
 register int n;
 {
         register int c, m;

         m = n;
         while(n--) {
                 if((c = Fgetc()) == EOF) {
                         m -= (++n);
                         while(n--)
                                 *buf++ = '\0';
                         break;
                 }
                 *buf++ = c;
         }
         return(m);
 }

 Fungetn(buf, n)
 register char *buf;
 register int n;
 {
         register char *p;

         Fcnt += n;
         Fp -= n;
         for(p=Fp; n--; *p++ = *buf++)
                 ;
 }

 /*
  * Extra i/o functions including AUX: input with timeout
  */
 openaux()                /* set up our own rs232 input and output buffers */
 {
         while(Bconstat(AUX))                /* flush existing buffer */
                 Bconin(AUX);
         st_sysr = (IOREC *)Iorec(0);
         st_savr = *st_sysr;                /* Save system buffer        */
         *st_sysr = st_myiorec;                /* Set my io buffer        */
 }

 closeaux()                /* restore system i/o buffer */
 {
         *st_sysr = st_savr;
 }

 int un_kb = '\0';                /* ungotten keyboard character */

 #define        ungetkb(c)        un_kb=(c)

 kbready()
 {
         return(un_kb || Bconstat(CON));
 }

 getkb()
 {
         register long n;
         register int c;

         if(un_kb) {
                 c = un_kb;
                 un_kb = '\0';
                 return(c);
         }
         n = Bconin(CON);
         return((0x00FF & n) | (0xFF00 & (n>>8)));
 }

 checkabort()                        /* check for abort conditions */
 {
         return(!rs232cd() || (Bconstat(CON) && (getkb() == KEY_UNDO)));
 }

 #define        RDLNMAX        128

 char *getln()                        /* Get input line from console thru OS *
 {
         static char rdlnbuf[RDLNMAX+4];
         register char *cp=rdlnbuf;
         register int c, i=0;

         for(;;) {
                 c = getkb();
                 if(c == KEY_UNDO) {
                         *(cp = rdlnbuf) = '\0';
                         i=0;
                         break;
                 }
                 else if((c == KEY_CR) || (c == KEY_LF)) {
                         *cp = '\0';
                         break;
                 }
                 else if((c == KEY_BS) || (c == KEY_DEL)) {
                         if(cp != rdlnbuf) {
                                 --cp;
                                 Bconws(CON, "\b \b");
                                 --i;
                         }
                         else
                                 Bconout(CON, 0x07);
                 }
                 else if((c >= ' ') && (i < RDLNMAX)) {
                         Bconout(CON, (*cp++ = c));
                         ++i;
                 }
                 else
                         Bconout(CON, 0x07);
         }
         return(rdlnbuf);
 }

 char *prompt(p)                        /* prompt for console input */
 char *p;
 {
         Bconws(CON, p);
         p = getln();
         Bconws(CON, "\r\n");
         return(p);
 }

 int un_aux = '\0';                /* ungotten AUX: character */
 int can_flg = FALSE;                /* CAN character received */

 #define        ungetaux(c)        un_aux=(c)

 auxready()
 {
         return(un_aux || Bconstat(AUX));
 }

 getaux(limit)                        /* get a character from AUX: w/ timeout
 int limit;
 {
         long t;
         register long tt;
         register int c;

         tt = ((long) (limit * 200));
         if(un_aux) {
                 c = un_aux;
                 un_aux = '\0';
                 return(c);
         }
         start_timer(&t);
         while(!Bconstat(AUX)) {
                 if(checkabort()) {
                         cancel();
                         return(ABORT);
                 }
                 if(time_since(&t) > tt)
                         return(ERROR);
         }
         c = (0xFF & Bconin(AUX));
         if(c == CAN) {
                 if((can_flg = !can_flg) == FALSE)
                         return(CANCEL);
         }
         else
                 can_flg = FALSE;
         return(c);
 }

 int getsnaux(s, n)                /* get 'n' characters from AUX: */
 register char *s;
 register int n;
 {
         register int c;

         while(n--) {
                 switch(c = getaux(1)) {
                         case ERROR:
                         case ABORT:
                                 return(c);
                         case CANCEL:
                                 c = CAN;        /* FALL THRU! */
                         default:
                                 *s++ = c;
                 }
         }
         *s = '\0';
         return(TRUE);
 }

 putaux(c)
 int c;
 {
         Bconout(AUX, (c & 0xFF));
 }

 putsnaux(s, n)                        /* send 'n' characters to AUX: */
 register char *s;
 register int n;
 {
         register int c;

         while(n--) {
                 if(auxready()) {
                         c = getaux(0);
                         if((c < 0) || (c == NAK))
                                 return(ungetaux(c));
                 }
                 putaux(*s++);
         }
 }

 purge()
 {
         register int c;

         while((c = getaux(1)) >= 0)        /* wait for timeout or cancel */
                 ;
         return(c);
 }

 cancel()
 {
         register int i;

         purge();
         for(i=0;i<3;++i)
                 putaux(CAN);
         for(i=0;i<3;++i)
                 putaux('\b');
         if(debug) Bconws(CON, "<cancel>\r\n");
         return(CANCEL);
 }

 /*
  * This function calculates the CRC used by the XMODEM/CRC Protocol
  * The first argument is a pointer to the message block.
  * The second argument is the number of bytes in the message block.
  * The function returns an integer which contains the CRC.
  * The low order 16 bits are the coefficients of the CRC.
  */
 int calcrc(ptr, count)
 register char *ptr;
 register int count;
 {
         register int crc = 0, i;

         while(--count >= 0) {
                 crc = crc ^ (int)*ptr++ << 8;
                 for(i=0; i<8; ++i)
                         if(crc & 0x8000)
                                 crc = crc << 1 ^ 0x1021;
                         else
                                 crc = crc << 1;
                 }
         return(crc & 0xFFFF);
 }

 int calchk(ptr, count)
 register char *ptr;
 register int count;
 {
         register int sum = 0;

         while(--count >= 0)
                 sum += *ptr++;
         return(sum & 0x00FF);
 }

 mode_init()                        /* initialize xfer mode settings from conf
 {
         crcmode = (xfer >= XMODEMC);
         kmode = (xfer >= YMODEM);
         ybatch = (xfer == YMODEM) && (FALSE);        /* <-- check for wildcar
 }

 pkt_sync(limit)
 int limit;
 {
         register int c;

          kmode = FALSE;
         while(rs232cd()) {
                 switch(c = getaux(limit)) {
                         case ERROR:
                         case CANCEL:
                         case ABORT:
                                 return(c);
                         case STX:
                                 kmode = TRUE;                /* FALL THRU...
                         case SOH:
                                 return(TRUE);
                         case EOT:
                                 return(FALSE);
                 }
         }
         return(ERROR);
 }

 rcv_init()
 {
         register int i, j;

         pktnum = 1;
         mode_init();
         if(crcmode) {
                 i = 3;
                 while(i--) {
                         putaux(CEE);
                         Bconout(CON, 'c');
                         j = pkt_sync(5);
                         if(j != ERROR)
                                 return(j);
                 }
                 crcmode = FALSE;
         }
         i = 9;
         while(i--) {
                 putaux(NAK);
                 Bconout(CON, '.');
                 j = pkt_sync(5);
                 if(j != ERROR)
                         return(j);
         }
         if(debug) Bconws(CON, "<init failed>\r\n");
         return(ERROR);
 }

 rcv_pkt()
 {
         register int i, j, k = 0;

         while(++k < 6) {
                 if((j = pkt_sync(10)) != TRUE)
                         return(j);
                 i = (kmode ? 1024 : 128);
                 j = getsnaux(data, (i+3+crcmode));
                 if(j == ERROR) {                /* receiver timeout */
                         if(debug) Bconws(CON, "[timeout]");
                         goto RETRY;
                 }
                 if((pktnum==1) && (data[0]==0) && (data[1]==0xFF)) {
                         /* Ymodem-batch header */
                         crcmode = TRUE;
                         ybatch = TRUE;
                         Bconout(CON, '*');
                         putaux(ACK);
                         putaux(CEE);
                         return(rcv_pkt());        /* recurse... */
                 }
                 if(data[0] != ~data[1]) {        /* parity error */
                         if(debug) Bconws(CON, "[parity error]");
                         goto RETRY;
                 }
                 if(data[0] == (pktnum - 1)) {        /* duplicate packet */
                         if(debug) Bconws(CON, "[duplicate packet]");
                         putaux(ACK);
                         return(rcv_pkt());        /* recurse... */
                 }
                 if(data[0] != pktnum) {                /* sequence error, CAN
                         if(debug) Bconws(CON, "[sequence error]");
                         return(cancel());
                 }
                 if(crcmode) {
                         j = calcrc(data+2, i);
                         i = *((int *) (data+i+2));
                 }
                 else {
                         j = calchk(data+2, i);
                         i = ((int) (0xFF & data[i+2]));
                 }
                 if(i == j) {
                         if(++pktnum > 255)
                                 pktnum = 0;
                         Bconout(CON, '+');
                         putaux(ACK);
                         return(TRUE);
                 }
                 if(debug) Bconws(CON, crcmode?"[crc error]":"[chksum error]")
 RETRY:                purge();
                 Bconout(CON, '-');
                 putaux(NAK);
         }
         if(debug) Bconws(CON, "[retry error]");
         return(cancel());
 }

 rcv_file()
 {
         register int f, j;
         register char *p;

         if(!rs232cd()) {
                 Bconws(CON, "You're not on-line.\r\n");
                 return(FALSE);
         }
         if(xfer == ASCII) {
                 Bconws(CON, "Use text capture for ASCII receive.\r\n");
                 return(TRUE);
         }
         p = prompt("\r\nReceive file: ");        /* prompt for file name */
         if(!(*p))
                 return(FALSE);
         if((f = Fcreate(p, 0)) < 0) {
                 Bconws(CON, "\007<file error>\r\n");
                 return(ERROR);
         }
         if((j = rcv_init()) != TRUE)
                 return(j);
         ungetaux(kmode ? STX : SOH);
         if(debug) Bconws(CON, (crcmode?"<crc mode>":"<chksum mode>"));
         while((j = rcv_pkt()) == TRUE) {
                 if(Fwrite(f, (kmode ? 1024L : 128L), data+2) < 0)
                         return(cancel());
         }
         Fclose(f);
         if(ybatch) {                /* clean up after ymodem batch xfer */
                 msleep(50);
                 cancel();
         }
         if(j == FALSE) {
                 putaux(ACK);
                 if(debug) Bconws(CON, "<file rcvd>");
                 Bconws(CON, "\r\n");
                 return(TRUE);
         }
         else
                 return(j);
 }

 snd_init()
 {
         register int c;

         if(xfer == ASCII)
                 return(TRUE);
         pktnum = 1;
         noise = 7;
         mode_init();
         while(Bconstat(AUX))
                 Bconin(AUX);
         for(;;) {
                 switch(c = getaux(30)) {
                         case ERROR:
                         case CANCEL:
                         case ABORT:
                                 return(c);
                         case CEE:
                         case NAK:
                                 Bconout(CON, ((c == CEE) ? 'c' : '.'));
                                 if(!(crcmode = (c == CEE)))
                                         kmode = FALSE;
                                 if(debug) Bconws(CON,
                                                 (crcmode?"<crc mode>":
                                                          "<chksum mode>"));
                                 return(TRUE);
                 }
         }
 }

 snd_pkt()
 {
         register int n, i, j, k = 0;
         register char *p;

         if(xfer == ASCII) {
                 switch(i = Fgetc()) {
                         case EOF:
                                 return(FALSE);
                         case '\r':
                                 putaux('\r');
                                 if(crtocrlf)
                                         putaux('\n');
                                 msleep(10);                /* FALL THRU.. */
                         case '\n':
                                 break;
                         default:
                                 putaux(i);
                 }
                 while((i = getaux(0)) >= 0)
                         Bconout(CON, (i & 0x7F));
                 return((i == ERROR) ? TRUE : i);
         }
         while(++k < 6) {
                 data[0] = (pktnum & 0xFF);
                 data[1] = ((~pktnum) & 0xFF);
                 i = (kmode ? 1024 : 128);
                 p = data+2;
                 if((n = Fgetn(p, i)) == 0)        /* empty packet == EOF */
                         return(FALSE);
                 if(kmode && (n < 1024)) {        /* send last packets as 128
                         Fungetn(p, n);
                         kmode = FALSE;
                         n = Fgetn(p, (i = 128));
                 }
                 if(crcmode) {
                         j = calcrc(p, i);
                         *((int *) (p+i)) = j;
                 }
                 else
                         *(p+i) = calchk(p, i);
                 putaux(kmode ? STX : SOH);
                 putsnaux(data, i+3+crcmode);
                 do {
                         switch(j = getaux(15)) {
                                 case CANCEL:
                                 case ABORT:
                                         return(j);
                                 case ACK:
                                         ++noise;
                                         if(++pktnum > 255)
                                                 pktnum = 0;
                                         Bconout(CON, '+');
                                         return(n == i);        /* short pkt =
                                 case ERROR:
                                         j = NAK;
                                         break;
                         }
                 } while(j != NAK);
                 Fungetn(p, n);
                 Bconout(CON, '-');
                 if(kmode && ((noise -= 8) < 0)) {        /* if too noisy.. */
                         if(debug) Bconws(CON, "<downshift>");
                         kmode = FALSE;
                 }
         }
         return(cancel());
 }

 snd_file()
 {
         register int i, j;
         register char *p;

         if(!rs232cd()) {
                 Bconws(CON, "You're not on-line.\r\n");
                 return(FALSE);
         }
         p = prompt("\r\nSend file: ");                /* prompt for file name
         if(!(*p))
                 return(FALSE);
         if(Finit(p) < 0) {
                 Bconws(CON, "\007<file error>\r\n");
                 return(ERROR);
         }
         if((j = snd_init()) != TRUE)
                 return(j);
         while((j = snd_pkt()) == TRUE)
                 ;
         Fclose(Fh);
         if(xfer == ASCII)
                 return(j == FALSE);
         if(j == FALSE) {
                 i = NAK;
                 do {
                         if(i == NAK)
                                 putaux(EOT);
                         i = getaux(10);
                         if(i < 0)
                                 return(i);
                 } while(i != ACK);
                 if(debug) Bconws(CON, "<file sent>");
                 Bconws(CON, "\r\n");
                 return(TRUE);
         }
         else
                 return(j);
 }

 start_capture()
 {
         register char *p;

         if(*(p = prompt("\r\nCapture file: ")) == '\0')
                 return(FALSE);
         if((capture = Fcreate(p, 0)) < 0) {
                 capture = 0;
                 Bconws(CON, "\007<file error>\r\n");
                 return(FALSE);
         }
 }

 putcap(c)
 char c;
 {
         if(Fwrite(capture, 1L, &c) != 1L) {
                 capture = 0;
                 Bconws(CON, "\007<write error>\r\n");
                 return(FALSE);
         }
 }

 do_grab()
 {
         register int h, i, j;

         if((h = Fopen("GRAB.TXT", 2)) < 0) {
                 if((h = Fcreate("GRAB.TXT", 0)) < 0) {
                         Bconws(CON, "\007<can't create grab file>\r\n");
                         return(FALSE);
                 }
         }
         else
                 Fseek(h, 0L, 2);
         if(Fwrite(h, 8L, "\r\n----\r\n") != 8L) {
                 Bconws(CON, "\007<write error>\r\n");
                 return(FALSE);
         }
         i = HSIZ - hp;
         j = hp;
         if(i > 0)
                 if(Fwrite(h, ((long) i), &hist[j]) <= 0) {
                         Bconws(CON, "\007<write error>\r\n");
                         return(FALSE);
                 }
         if(j > 0)
                 if(Fwrite(h, ((long) j), hist) <= 0) {
                         Bconws(CON, "\007<write error>\r\n");
                         return(FALSE);
                 }
         Fclose(h);
         return(TRUE);
 }

 do_help()
 {
         Bconws(CON, "\r\n");
         Bconws(CON, "[Alt][C]        Shell Command        [F1]\r\n");
         Bconws(CON, "[Alt][A]        Ascii Capture        [F2]\r\n");
         Bconws(CON, "[Alt][-]        Debug mode        [F3]\r\n");
         Bconws(CON, "[Alt][V]        Literal mode        [F4]\r\n");
         Bconws(CON, "[Alt][T]        CR -> CR+LF        [F5]\r\n");
         Bconws(CON, "[Alt][E]        Echo mode        [F6]\r\n");
         Bconws(CON, "[Alt][F]        File Xfer Mode        [F7]\r\n");
         Bconws(CON, "[Alt][R]        Receive File        [F8]\r\n");
         Bconws(CON, "[Alt][S]        Send File        [F9]\r\n");
         Bconws(CON, "[Alt][B]        Baud Rate        [F10]\r\n");
         Bconws(CON, "[Alt][0]        Send BREAK        [INS]\r\n");
         Bconws(CON, "[Alt][H]        Drop Carrier        [CLR]\r\n");
         Bconws(CON, "[Alt][X]        Exit TTY        [UNDO]\r\n");
         Bconws(CON, "[Alt][G]        Grab history        \r\n");
 }

 char *hexchr(c)
 {
         static char hexout[5];
         static char hexdigit[] = "0123456789ABCDEF";

         hexout[4] = '\0';
         hexout[3] = hexdigit[c&0xF];
         c >>= 4;
         hexout[2] = hexdigit[c&0xF];
         hexout[1] = 'x';
         hexout[0] = '\\';
         return(hexout);
 }

 extern        long        _base;                /* our base-page pointer */

 do_shell()
 {
         register char *p, *ssp, (*shell)();
         register long rv = 0L;

         /* get _shell_p value */
         ssp = Super(0L);
         shell = *((long *) 0x4F6L);
         Super(ssp);

         /* validate _shell_p */
         if(shell == 0L) {
                 Bconws(CON, "\r\nNo shell available.\r\n");
                 return(ERROR);
         }
         if((((long) shell) > ((long) _base)) || !(strncmp(shell, "PATH", 4)))
                 Bconws(CON, "\r\nBad shell pointer.\r\n");
                 return(ERROR);
         }

         /* execute the command */
         if(*(p = prompt("\r\nShell Command: ")))
                 rv = (*shell)(p);
         return((int) rv);
 }

 main()
 {
         register int c;

         Bconws(CON, ident);
         openaux();
         for(c = 0; c < HSIZ; hist[c++] = '\0')                /* zero history
                 ;
 #ifdef NEVER
         cd = !rs232cd();
 #endif
         for(;;) {
                 if(kbready()) {
                         switch(c = getkb()) {
                                 case KEY_UNDO:                /* exit */
                                 case ALT_X:
                                         Bconws(CON, "\r\nExit TTY? ");
                                         c = (getkb() & 0xFF);
                                         Bconout(CON, c);
                                         Bconws(CON, "\r\n");
                                         if((c == 'y') || (c == 'Y'))
                                                 punt(0);
                                         break;
                                 case KEY_INS:                /* break */
                                 case ALT_0:
                                         snd_brk();
                                         break;
                                 case KEY_CLR:                /* hangup */
                                 case ALT_H:
                                         hangup();
                                         break;
                                 case KEY_F1:                /* shell escape *
                                 case ALT_C:
                                         do_shell();
                                         break;
                                 case KEY_F2:                /* ascii capture
                                 case ALT_A:
                                         if(capture) {
                                                 Fclose(capture);
                                                 capture = 0;
                                                 Bconws(CON,
                                                         "[capture off]\r\n");
                                         }
                                         else if(start_capture()) {
                                                 Bconws(CON,
                                                         "[capture on]\r\n");
                                         }
                                         break;
                                 case KEY_F3:                /* debug toggle *
                                 case ALT_DASH:
                                         Bconws(CON, ((debug = !debug) ?
                                                 "\r\n[DEBUG ON]\r\n" :
                                                 "\r\n[DEBUG OFF]\r\n"));
                                         break;
                                 case KEY_F4:                /* literal toggle
                                 case ALT_V:
                                         Bconws(CON, ((literal = !literal) ?
                                                 "\r\n[literal on]\r\n" :
                                                 "\r\n[literal off]\r\n"));
                                         break;
                                 case KEY_F5:                /* cr -> cr+lf */
                                 case ALT_T:
                                         crtocrlf = !crtocrlf;
                                         Bconws(CON, crtocrlf?
                                                 "[cr->cr+lf]" : "[cr->cr]");
                                         Bconws(CON, "\r\n");
                                         break;
                                 case KEY_F6:                /* duplex/echo mo
                                 case ALT_E:
                                         echo = ((echo + 1) % ECODES);
                                         Bconout(CON, '[');
                                         Bconws(CON, ename[echo]);
                                         Bconws(CON, "]\r\n");
                                         break;
                                 case KEY_F7:                /* file xfer mode
                                 case ALT_F:
                                         xfer = ((xfer + 1) % XCODES);
                                         Bconout(CON, '[');
                                         Bconws(CON, xname[xfer]);
                                         Bconws(CON, "]\r\n");
                                         break;
                                 case KEY_F8:                /* receive file *
                                 case ALT_R:
                                         if(rcv_file() != TRUE)
                                          Bconws(CON, "\r\n<rcv failed>\r\n");
                                         break;
                                 case KEY_F9:                /* send file */
                                 case ALT_S:
                                         if(snd_file() != TRUE)
                                          Bconws(CON, "\r\n<send failed>\r\n")
                                         break;
                                 case KEY_F10:                /* change baud r
                                 case ALT_B:
                                         bcode = ((bcode + 1) % BCODES);
                                         Rsconf(brate[bcode],0,-1,-1,-1,-1);
                                         Bconout(CON, '[');
                                         Bconws(CON, bname[bcode]);
                                         Bconws(CON, "]\r\n");
                                         break;
                                 case ALT_G:                /* grab history */
                                         if(do_grab())
                                                 Bconws(CON, "<grabbed>\r\n");
                                         break;
                                 case KEY_HELP:                /* help info */
                                         do_help();
                                         break;
                                 default:
                                         c &= 0xFF;
                                         putaux(c);
                                         if(echo >= HALFDUP) {
                                                 Bconout(CON, c);
                                                 hist[hp++] = c;
                                                 hp &= HMASK;
                                                 if(capture)
                                                         putcap(c);
                                         }
                                         if(crtocrlf && (c == '\r'))
                                                 ungetkb('\n');
                                         break;
                         }
                 }
                 if(auxready()) {
                         if(un_aux) {
                                 c = (un_aux & 0xFF);
                                 un_aux = '\0';
                         }
                         else
                                 c = (Bconin(AUX) & 0x7F);
                         if(literal && (c < ' '))
                                 Bconws(CON, hexchr(c));
                         else
                                 Bconout(CON, c);
                         hist[hp++] = c;
                         hp &= HMASK;
                         if(capture)
                                 putcap(c);
                         if(echo == HOSTMOD)
                                 putaux(c);
                         if(crtocrlf && (c == '\r'))
                                 ungetaux('\n');
                 }
 #ifdef NEVER
                 if (cd != rs232cd())
                         Bconws(CON, ((cd = rs232cd()) ?
                                 "\r\n[CARRIER]\r\n" :
                                 "\r\n[NO CARRIER]\r\n"));
 #endif
         }
 }

 Bconws(dev, s)
 register int dev;
 register char *s;
 {
         while(*s)
                 Bconout(dev, *s++);
 }

 punt(errcode)
 int errcode;
 {
         closeaux();
         exit(errcode);
 }

 #ifdef dLibs
 _initargs()                /* dummy function to avoid command line processing
 {
 }
 #endif


 TWINS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\TWINS.C

 /****************************************************************/
 /* TWINS.C - From page 296 of the book "Microsoft C Program-    */
 /* ming for the IBM by Robert Lafore. This is a continuation of */
 /* a simple database program developed from page 292 to         */
 /* the end of the chapter (9).                                  */
 /****************************************************************/

 main()
 {
 struct personnel {
    char name [30];
    int agnumb;
 };

 struct personnel agent1;
 struct personnel agent2;

    printf("\nAgent 1.\nEnter name: ");
    gets(agent1.name);
    printf("Enter agent number (3 digits): ");
    scanf("%d", &agent1.agnumb);

    agent2 = agent1;           /*assigns one structure to another*/

    printf("\nList of agents:\n\n");
    printf("   Name: %s\n", agent1.name);
    printf("   Agent number: %03d\n", agent1.agnumb);
    printf("   Name: %s\n", agent2.name);
    printf("   Agent number: %03d\n", agent2.agnumb);
 }




 TWOAGENT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\TWOAGENT.C

 /****************************************************************/
 /* TWOAGENT.C - From page 292 of the book "Microsoft C Program- */
 /* ming for the IBM by Robert Lafore. This is the beginning of  */
 /* a simple database program developed from the above page to   */
 /* the end of the chapter (9).                                  */
 /****************************************************************/

 #include "stdio.h"

 main()
 {
 struct personnel {
    char name [30];
    int agnumb;
 };
 struct personnel agent1;
 struct personnel agent2;

    printf("\nAgent 1:\nEnter name: ");
    gets(agent1.name);
    printf("Enter agent number (3 digits): ");
    scanf("%d", &agent1.agnumb);
    fflush(stdin);                   /*clear buffer*/
    printf("\nAgent 2:\nEnter name: ");
    gets(agent2.name);
    printf("Enter agent number (3 digits); ");
    scanf("%d", &agent2.agnumb);

    printf("\nList of agents:\n\n");
    printf("   Name: %s\n", agent1.name);
    printf("   Agent number: %03d\n", agent1.agnumb);
    printf("   Name: %s\n", agent2.name);
    printf("   Agent number: %03d\n", agent2.agnumb);
 }




 TWOWAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\TWOWAY.C

                                         /* Chapter 8 - Program 3 */
 main()
 {
 int pecans,apples;

    pecans = 100;
    apples = 101;
    printf("The starting values are %d %d\n",pecans,apples);

                            /* when we call "fixup"          */
    fixup(pecans,&apples);  /* we take the value of pecans   */
                            /* we take the address of apples */

    printf("The ending values are %d %d\n",pecans,apples);
 }

 fixup(nuts,fruit)             /* nuts is an integer value   */
 int nuts,*fruit;              /* fruit points to an integer */
 {
    printf("The values are %d %d\n",nuts,*fruit);
    nuts = 135;
    *fruit = 172;
    printf("The values are %d %d\n",nuts,*fruit);
 }


 TYPECONV.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\TYPECONV.C


 /*
 ** Demonstration of Type Conversion
 ** across assignments.
 */
 main()
         {
         char c1,c2,c3;
         int i1,i2,i3;
         float f1,f2,f3;

         c1 = 'x';       /* no conversion */
         c2 = 1000;      /* int constant demoted to char */
         c3 = 6.02e23;   /* float constant demoted to char */
         printf("%c  %c  %c\n",c1,c2,c3);

 /* Note that the character value is printed as is; the integer
 ** with a value of 1000 is converted to its binary equivalent
 ** of 1111101000 and truncated to the first 8 data bits which
 ** gives 11101000 or decimal 232 or the Greek symbol "phi"
 ** when the ASCII symbol is printed; and the conversion from
 ** float to char is meaningless and does not occur.  */

         i1 = 'x';       /* char constant promoted to int */
         i2 = 1000;      /* no conversion */
         i3 = 6.02e23;   /* float constant demoted to int */
         printf("%d  %d  %d\n",i1,i2,i3);

 /* Note that ASCII 'x' has an integer value of 120, and the
 ** character constant 'x' is promoted when we assign it to an
 ** integer.  The floating point constant is demoted to the
 ** largest integer 32767 that is possible in the Microsoft
 ** C compiler and that number is returned as an integer. */

         f1 = 'x';       /* x char constant promoted to float */
         f2 = 1000;      /* int constant promoted to float */
         f3 = 6.02e23;   /* no conversion */
         printf("%f %f %f\n",f1,f2,f3);

 /* There are no demoted values, everything is represented as
 ** its double precision floating point equivalent!   */

         }




 TYPESQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\TYPESQ.C

 /*% cc -O -s % -o type

 *        TYPE - uses typesq.c for 'sqed' files
   derived from cnode 'cat', typesq, and others. W. Earnest 5/28/82
   Credit to the following and others for parts of the software:
         Dick Greenlaw        (usq)
         Bob Mathias        (typesq)
         Steve Passe        (cnode)
         Joe Shannon        (cnode)
         Chuck Forsberg (Unix version)
 */
 char Version[] = {"type revised 7-16-82"};

 #include <stdio.h>
 /* #include <signal.h> */
 #define ERROR (-1)
 #define OK 0
 #define PATHLEN 128

 RECOGNIZE 0xFF76        /* unlikely pattern */
 DLE 0x90                /* repeat byte flag */
 SPEOF 256                /* special endfile token */
 NUMVALS 257                /* 256 data values plus SPEOF*/
 #define LARGE 30000

 struct _sqleaf {                /* Decoding tree */
         int _children[2];        /* left, right */
 };
 struct _sqleaf Dnode[NUMVALS - 1];

 int early_exit;
 FILE *infile;

 int Bpos;                /* last bit position read */
 int Curin;                /* last byte value read */
 int Repct;                /* Number of times to retirn value */
 int Value;                /* current byte value or EOF */

 sexit()
 {
         early_exit++;
 /*        signal(SIGINT, sexit); */
 }

 sequit()
 {
         putchar('\n');
         exit(1);
 }

 main(p_argc, p_argv)
 int p_argc;
 char **p_argv;
 {
         char file[PATHLEN];
         register char x;
 /*        static char stobuf[BUFSIZ];  */
         extern sexit();


 /*        signal(SIGINT, sexit);         */
 /*        signal(SIGQUIT, sequit); */
 /*        setbuf(stdout, stobuf);  */
         if (p_argc < 2) {
                 fprintf(stderr, "Usage: type name ...\n");
                 exit(1);
         }

         for (x = 1;x < p_argc;++x) {
                 fprintf(stderr, "\n\n======================== Listing %s ====
                 switch (catvalid(file, p_argv[x])) {
                 case 'q':
                         switch (qsend(file)) {
                         case ERROR:
                                 break;
                         case 'a':
                                 send_text(file);
                         }
                         break;
                 case 'a':
                         send_text(file); break;
                 case 'x':
                         break;
                 }
         }
         return (OK);
 }

 send_text(file)
 char *file;
 {
         register c;

         early_exit = 0;
         while( ((c = getc(infile)) != EOF) && (!early_exit) )
                 putchar(c);
         fclose(infile);
         fflush(stdout);
         return (OK);
 }

 catvalid(pname, name)
 char *pname;
 char *name;
 {
         if((infile=fopen(name, "rb"))==NULL) {
                 fprintf(stderr, "Can't open %s\n", name);
                 return ERROR;
         }
         strcpy(pname, name);
         return ('q');
 }

 /*
         The following code is primarily from typesq.c and utr.c.  Typesq
 is a modification of USQ by Dick Greenlaw.  Those modifications (usq
 to typesq) were made by Bob Mathias, I am responsible for the butchery
 done to make it work with cat.

 */

 qsend(fname)
 char *fname;
 {
         register i, c;
         register char *p;
         register int numnodes;                        /* size of decoding tre
         char origname[PATHLEN];         /* Original file name without drive *

         init_cr(); init_huff();

         if(portgetw(infile) != RECOGNIZE) {        /* Process header */
                 rewind(infile);
                 return 'a';                     /* not squeezed after all */
         }
         portgetw(infile);                        /* discard checksum */
         p = origname;                                /* Get original file nam
         do {                                        /* send it to array */
                 *p = getc(infile);
         } while(*p++ != '\0');

         numnodes = portgetw(infile);
         if(numnodes < 0 || numnodes >= NUMVALS) {
                 fprintf(stderr, "%s has invalid decode tree size\n", fname);
                 fclose(infile);
                 return ERROR;
         }
         /* Initialize for possible empty tree (SPEOF only) */
         Dnode[0]._children[0] = -(SPEOF + 1);
         Dnode[0]._children[1] = -(SPEOF + 1);

         for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
                 Dnode[i]._children[0] = portgetw(infile);
                 Dnode[i]._children[1] = portgetw(infile);
         }
         /* Get translated output bytes and write file */
         fprintf(stderr, "\n%s -> %s\n\n",fname,origname);
         early_exit = 0;
         while( ((c = getcr(infile)) != EOF) && (!early_exit) )
                 putchar(c);
         fclose(infile);
         fflush(stdout);
         return OK;
 }
 /*** from utr.c - */
 /* initialize decoding functions */

 init_cr()
 {
         Repct = 0;
 }

 init_huff()
 {
         Bpos = 99;        /* force initial read */
 }

 /* Get bytes with decoding - this decodes repetition,
  * calls getuhuff to decode file stream into byte
  * level code with only repetition encoding.
  *
  * The code is simple passing through of bytes except
  * that DLE is encoded as DLE-zero and other values
  * repeated more than twice are encoded as value-DLE-count.
  */

 int
 getcr()
 {
         register c;

         if(Repct > 0) {
                 /* Expanding a repeated char */
                 --Repct;
                 return Value;
         } else {
                 /* Nothing unusual */
                 if((c = getuhuff()) != DLE) {
                         /* It's not the special delimiter */
                         Value = c;
                         if(Value == EOF)
                                 Repct = LARGE;
                         return Value;
                 } else {
                         /* Special token */
                         if((Repct = getuhuff()) == 0)
                                 /* DLE, zero represents DLE */
                                 return DLE;
                         else {
                                 /* Begin expanding repetition */
                                 Repct -= 2;        /* 2nd time */
                                 return Value;
                         }
                 }
         }
 }
 /* Decode file stream into a byte level code with only
  * repetition encoding remaining.
  */

 int
 getuhuff()
 {
         register i;
         register bitval;

         /* Follow bit stream in tree to a leaf*/
         i = 0;        /* Start at root of tree */
         do {
                 if(++Bpos > 7) {
                         if((Curin = getc(infile)) == ERROR)
                                 return ERROR;
                         Bpos = 0;
                         /* move a level deeper in tree */
                         i = Dnode[i]._children[1 & Curin];
                 } else
                         i = Dnode[i]._children[1 & (Curin >>= 1)];
         } while(i >= 0);

         /* Decode fake node index to original data value */
         i = -(i + 1);
         /* Decode special endfile token to normal EOF */
         i = (i == SPEOF) ? EOF : i;
         return i;
 }
 /*
  * Machine independent getw which always gets bytes in the same order
  *  as the CP/M version of SQ wrote them
  */
 portgetw(f)
 FILE *f;
 {
         register c;

         c = getc(f)&0377;
         return c + (getc(f)<<8);
 }




 TYPEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SUPER_C\TYPEX.C

 /*              Examples of Types of Data & Code in C
 */

 int a,b;                        /* Uninitialized global data. */

 int x = {5};                    /* Initialized global data. */

 static int i;                   /* Uninitialized static data local
                                    to this module. */

 static int y = {9};             /* Initialized static data local to
                                    this module. */

 /* retNext(inc): returns the current value of a count maintained by
    the routine, and then adds inc to the count. */

 retNext(inc)

 int inc;        /* Parameter data. */

 {
  static int lastinc;            /* Uninitialized static data local
                                    to this function. */
  static int count = {0};        /* Initialized static data local to
                                    this function. */
  int retValue;                  /* Automatic data. */

  lastinc = inc;                 /* Code. */
  retValue = count;              /* Code. */
  count += inc;                  /* Code. */
  return(retValue);              /* Code. */
 }



 UGLYFORM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\UGLYFORM.C

 main()  /* Main program starts here */{printf("Good form ");printf
  ("can aid in ");printf("understanding a program.\n")
 ;printf("And bad form ");printf("can make a program ");
 printf("unreadable.\n");}


 UNFORMAT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC1\UNFORMAT.C

 /* 1.1  01-08-86                                             (unformat.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1986
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"

        NEXT                TRUE        /* Forward direction for getting chars
 BACK                FALSE        /* Reverse direction for getting chars.
 LONGTYP                TRUE        /* Value to signal long or double.
 NORMTYP                FALSE        /* Value to denote normal width number.
 SHORTTYP        -TRUE        /* Value to denote short rather than int*/

 /*----------------------------------------------------------------------*/

 LOCAL int         width;
 LOCAL int         (*xgetc)();
 STRING                index();

 /************************************************************************/

 unformat(getch, fmt, arglist)        /* Perform scanf() on getch input medium
                                    using format fmt and argument list
                                    pointed to by arglist. Returns number of
                                    matched and assigned input items, or
                                    EOF if input finished before fmt.        *
 /*----------------------------------------------------------------------*/
 int (*getch)();                        /* Note:  getch(NEXT) performs a
 FAST STRING fmt;                /* getc(medium), and getch(BACK) does
 int **arglist;                        /* an ungetc(c, medium).
 {
         FAST int c;
         double nxtfloat(), d;
         long nxtnumber(), val;
         int count, base;
         STRING s;
         BOOL suppress, numtyp;
         char wkbuf[MAXLINE];

         count = 0;
         xgetc = getch;
 /*\p*/
         while (c = *fmt++)
         {        if (c IS '%')
                 {        numtyp = NORMTYP;
                         suppress = FALSE;
                         width = MAXLINE;
                         if (*fmt IS '*')
                         {        ++fmt;
                                 suppress = TRUE;
                         }
                         if (isdigit(*fmt))
                         {        width = 0;
                                 do
                                 {        width *= 10;
                                         width += (*fmt - '0');
                                 } while (isdigit(*++fmt));
                         }
                         if (*fmt IS 'l')
                         {        numtyp = LONGTYP;
                                 ++fmt;
                         }
                         if (*fmt IS 'h')
                         {        numtyp = SHORTTYP;
                                 ++fmt;
                         }
                         if (index("DOXEF", c = *fmt++))
                                 numtyp = LONGTYP;
                         switch (c = tolower(c))
                         {   case ' ':
                                 fmt--;
                                 if (numtyp IS SHORTTYP)
                                         c = 'd';
                                 else
                                         break;
                             case 'd':
                             case 'o':
                             case 'x':
                                 base = (c IS 'd'? 10 : (c IS 'o' ? 8 : 16));
                                 if (eatblanks())
                                         return (count ? count : EOF);

                                 val = nxtnumber(base);
                                 if (NOT suppress)
                                 {        if (numtyp IS LONGTYP)
                                                 *(long *)(*arglist++) = val;
                                         else if (numtyp IS SHORTTYP)
                                                 *(short *)(*arglist++) = val;
                                         else
                                                 **arglist++ = val;
                                         ++count;
                                 }
                                 break;
 /*\p*/
                             case 'e':
                             case 'f':
                                 if (eatblanks())
                                         return (count ? count : EOF);

                                 d = nxtfloat(wkbuf);
                                 if (NOT suppress)
                                 {        if (numtyp IS LONGTYP)
                                                 *(double *)(*arglist++) = d;
                                         else
                                                 *(float *)(*arglist++) = d;
                                         ++count;
                                 }
                                 break;
                             case '[':
                             case 's':
                                 if (c IS '[')
                                 {        if (*fmt IS '^' OR *fmt IS '~')
                                         {        numtyp = NORMTYP;
                                                 ++fmt;
                                         }
                                         else
                                                 numtyp = LONGTYP;
                                         for (s = wkbuf;(c = *fmt++) ISNT ']';
                                                 *s++ = c;
                                         *s = NULL;
                                 }
                                 else
                                 {        numtyp = NORMTYP;
                                         strcpy(wkbuf, " \t\n");
                                 }
                                 if (eatblanks())
                                         return (count ? count : EOF);

                                 if (NOT suppress)
                                         s = (STRING) *arglist++;
                                 while (width--)
                                 {        if ((c = (*xgetc)(NEXT)) IS EOF)
                                                 break;
                                         if (numtyp IS NORMTYP ?
                                             (index(wkbuf, c) ISNT NULL) :
                                             (index(wkbuf, c)  IS  NULL))
                                         {        (*xgetc)(BACK);
                                                 break;
                                         }
                                         if (NOT suppress)
                                                 *s++ = c;
                                 }
                                 if (NOT suppress)
                                 {        *s = NULL;
                                         ++count;
                                 }
                                 break;
 /*\p*/
                             case 'c':
                                 if ((c = (*xgetc)(NEXT)) IS EOF)
                                         return (count ? count : EOF);

                                 if (NOT suppress)
                                 {        *(STRING)(*arglist++) = c;
                                         ++count;
                                 }
                                 break;
                             case '%':
                                 goto match;
                         }
                 }
                 else if (isspace(c))
                 {        if (eatblanks())
                                 return (count ? count : EOF);
                 }
                 else
                 {
 match:                        if (eatblanks())
                                 return (count ? count : EOF);

                         if ((*xgetc)(NEXT) ISNT c)
                                 return count;
                 }
         }
         return count;
 }

 /************************************************************************/
         LOCAL BOOL
 eatblanks()                /* Get characters from input medium until no longe
                            whitespace.  Return FALSE normally, or TRUE at
                            end of line.
 /*----------------------------------------------------------------------*/
 {
 char c;
         while (isspace(c = (*xgetc)(NEXT)))
                 ;
         if ((*xgetc)(BACK) IS EOF)
                 return TRUE;
         else
                 return FALSE;
 }
 /*\p*********************************************************************/
         LOCAL double
 nxtfloat(buffer)        /* Get the next ascii e-form or f-form from the
                            input medium, and return its value. Store
                            the ascii form in buffer.                        *
 /*----------------------------------------------------------------------*/
 STRING buffer;
 {
         FAST int c;
         FAST STRING s;
         TBOOL decmlpt, sign, exp;
         double atof();

         s = buffer;
         sign = exp = decmlpt = FALSE;
         while (width--)
         {        c = (*xgetc)(NEXT);
                 if (NOT sign AND (c IS '-' OR c IS '+'))
                         sign = TRUE;
                 else if (NOT decmlpt AND c IS '.')
                         sign = decmlpt = TRUE;
                 else if (NOT exp AND (c IS 'e' OR c IS 'E'))
                 {        sign = FALSE;
                         exp = decmlpt = TRUE;
                 }
                 else if (NOT isdigit(c))
                 {        (*xgetc)(BACK);
                         break;
                 }
                 *s++ = c;
         }
         *s = 0;
         return atof(buffer);
 }
 /*\p*********************************************************************/
         LOCAL long
 nxtnumber(base)                /* Get the ascii string of a number with given
                            base from input medium, return its value.        *
 /*----------------------------------------------------------------------*/
 {
         int c;
         long value;
         BOOL minus;
         LOCAL char digits[] = "0123456789abcdef";

         if (width <= 0)
                 return 0L;

         value = 0;
         minus = FALSE;
         if ((c = (*xgetc)(NEXT)) IS '-')
         {        minus = TRUE;
                 --width;
         }
         else if (c IS '+')
                 --width;
         else
                 (*xgetc)(BACK);
         while (width--)
         {        c = index(digits, tolower((*xgetc)(NEXT))) - digits;
                 if (c < 0 OR c >= base)
                 {        (*xgetc)(BACK);
                         break;
                 }
                 value *= base;
                 value += c;
         }
         return (minus ? -value : value);
 }


 UNGETC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC1\UNGETC.C

 /* 1.0  12-17-84 */
 /************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************/

 #include "defs.h"
 #include "stdtyp.h"
 #include "stdio.h"


 /************************************************************************/
         METACHAR
 ungetc(c, fp)                /* Push c back onto FILE fp stream, and return c
                            Return EOF if c is EOF.                        */
 /*----------------------------------------------------------------------*/
 FAST FILE *fp;
 {
         if ((c IS EOF) OR (fp->_bptr <= fp->_buff))
                 return EOF;

         return (*--fp->_bptr = c);
 }


 UNION.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\UNION.C

 /* UNION.C - From page 314 of "Microsoft C Programming for the  */
 /* IBM" by Robert Lafore. Demonstrates unions. This program     */
 /* gives an error: Fatal error:L1101 Invalid object module      */
 /* when linking. In Quick C Programmers Guide user is reques-   */
 /* ted to contact Microsoft.                                    */
 /****************************************************************/

 main()
 {
 union intflo {
    int intnum;
    float fltnum;
 } unex;

    printf("sizeof (union intflo) = %d\n", sizeof(union intflo));
    unex.intnum = 734;
    printf("unex.intnum = %d\n", unex.intnum);
    unex.fltnum = 867.43;
    printf("unex.fltnum = %f\n", unex.fltnum);
 }



 UNION1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\UNION1.C

                                          /* Chapter 11 - Program 5 */
 main()
 {
 union {
    int value;     /* This is the first part of the union */
    struct {
       char first;   /* These two values are the second     */
       char second;
    } half;
 } number;

 long index;

    for (index = 12;index < 300000;index += 35231) {
       number.value = index;
       printf("%8x %6x %6x\n",number.value, number.half.first,
               number.half.second);
    }
 }


 UNION2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\UNION2.C

                                          /* Chapter 11 - Program 6 */
 #define AUTO 1
 #define BOAT 2
 #define PLANE 3
 #define SHIP 4

 main()
 {
 struct automobile {  /* structure for an automobile         */
    int tires;
    int fenders;
    int doors;
 };

 typedef struct {     /* structure for a boat or ship        */
    int displacement;
    char length;
 } BOATDEF;

 struct {
    char vehicle;         /* what type of vehicle?           */
    int weight;           /* gross weight of vehicle         */
    union {               /* type-dependent data             */
       struct automobile car;      /* part 1 of the union    */
       BOATDEF boat;               /* part 2 of the union    */
       struct {
          char engines;
          int wingspan;
       } airplane;                 /* part 3 of the union    */
       BOATDEF ship;               /* part 4 of the union    */
    } vehicle_type;
    int value;            /* value of vehicle in dollars     */
    char owner[32];       /* owners name                     */
 } ford, sun_fish, piper_cub;   /* three variable structures */

        /* define a few of the fields as an illustration     */

    ford.vehicle = AUTO;
    ford.weight = 2742;              /* with a full gas tank */
    ford.vehicle_type.car.tires = 5;  /* including the spare */
    ford.vehicle_type.car.doors = 2;

    sun_fish.value = 3742;           /* trailer not included */
    sun_fish.vehicle_type.boat.length = 20;

    piper_cub.vehicle = PLANE;
    piper_cub.vehicle_type.airplane.wingspan = 27;

    if (ford.vehicle == AUTO) /* which it is in this case */
       printf("The ford has %d tires.\n",ford.vehicle_type.car.tires);

    if (piper_cub.vehicle == AUTO) /* which it is not in this case */
       printf("The plane has %d tires.\n",piper_cub.vehicle_type.
              car.tires);
 }


 UNISTRUC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\UNISTRUC.C

 /*UNISTRUC.C - From page 317 of "Microsoft C Programming for    */
 /* IBM" by Robert Lafore. It demonstrates union of structures.  */
 /* This file has same problem as UNION.C on this disk and is    */
 /* described in it's source file description located at the     */
 /* top of the source just like this description.                */
 /****************************************************************/

 main()
 {
 struct twoints {
    int intnum1;
    int intnum2;
 } stex;

 union intflo {
    struct twoints stex;
    float fltnum;
 } unex;

    printf("sizeof(union intflo) = %d\n", sizeof(union intflo));
    unex.stex.intnum1 = 734;
    unex.stex.intnum2 = -333;
    printf("unex.stex.intnum1 = %d\n", unex.stex.intnum1);
    printf("unex.stex.intnum2 = %d\n", unex.stex.intnum2);
    unex.fltnum = 867.43;
    printf("unex.fltnum = %f\n", unex.fltnum);
 }




 UNIX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\STEVIE\UNIX.C

 /*
  * System-dependent routines for UNIX System V Release 3.
  */

 #include "stevie.h"
 #include <termio.h>

 /*
  * inchar() - get a character from the keyboard
  */
 int
 inchar()
 {
         char        c;

         flushbuf();                /* flush any pending output */

         while (read(0, &c, 1) != 1)
                 ;

         return c;
 }

 #define        BSIZE        2048
 static        char        outbuf[BSIZE];
 static        int        bpos = 0;

 flushbuf()
 {
         if (bpos != 0)
                 write(1, outbuf, bpos);
         bpos = 0;
 }

 /*
  * Macro to output a character. Used within this file for speed.
  */
 #define        outone(c)        outbuf[bpos++] = c; if (bpos >= BSIZE) flushb

 /*
  * Function version for use outside this file.
  */
 void
 outchar(c)
 register char        c;
 {
         outbuf[bpos++] = c;
         if (bpos >= BSIZE)
                 flushbuf();
 }

 void
 outstr(s)
 register char        *s;
 {
         while (*s) {
                 outone(*s++);
         }
 }

 void
 beep()
 {
         outone('\007');
 }

 /*
  * remove(file) - remove a file
  */
 void
 remove(file)
 char *file;
 {
         unlink(file);
 }

 /*
  * rename(of, nf) - rename existing file 'of' to 'nf'
  */
 void
 rename(of, nf)
 char        *of, *nf;
 {
         unlink(nf);
         link(of, nf);
         unlink(of);
 }

 void
 delay()
 {
         /* not implemented */
 }

 static        struct        termio        ostate;

 void
 windinit()
 {
         char        *getenv();
         char        *term;
         struct        termio        nstate;

         if ((term = getenv("TERM")) == NULL || strcmp(term, "vt100") != 0) {
                 fprintf(stderr, "Invalid terminal type '%s'\n", term);
                 exit(1);
         }
         Columns = 80;
         P(P_LI) = Rows = 24;

         /*
          * Go into cbreak mode
          */
          ioctl(0, TCGETA, &ostate);
          nstate = ostate;
          nstate.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
          nstate.c_cc[VMIN] = 1;
          nstate.c_cc[VTIME] = 0;
          ioctl(0, TCSETAW, &nstate);
 }

 void
 windexit(r)
 int r;
 {
         /*
          * Restore terminal modes
          */
         ioctl(0, TCSETAW, &ostate);

         exit(r);
 }

 #define        outone(c)        outbuf[bpos++] = c; if (bpos >= BSIZE) flushb

 void
 windgoto(r, c)
 register int        r, c;
 {
         r += 1;
         c += 1;

         /*
          * Check for overflow once, to save time.
          */
         if (bpos + 8 >= BSIZE)
                 flushbuf();

         outbuf[bpos++] = '\033';
         outbuf[bpos++] = '[';
         if (r >= 10)
                 outbuf[bpos++] = r/10 + '0';
         outbuf[bpos++] = r%10 + '0';
         outbuf[bpos++] = ';';
         if (c >= 10)
                 outbuf[bpos++] = c/10 + '0';
         outbuf[bpos++] = c%10 + '0';
         outbuf[bpos++] = 'H';
 }

 FILE *
 fopenb(fname, mode)
 char        *fname;
 char        *mode;
 {
         return fopen(fname, mode);
 }


 UNLINK.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\UNLINK.C


 #include "io.h"

 unlink(name)
 char *name;
 {
         struct fcb delfcb;

         fcbinit(name,&delfcb);
         return bdos(DELFIL,&delfcb);
 }



 UNLUMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LUMPS\UNLUMP.C

 /* UNLUMP:  Break apart files lumped together by LUMP */

 #include "stdio.h"

 #define  BUFL  512

 FILE *infile, *outfile;

 main(argc,argv)
 int argc;
 char *argv[];
 {
    int c, i;
    char filename[61];
    char buf[BUFL];
    int opened = 0;

    if(argc<2)  { usage(); exit(0); }

    argc--;
    if( (infile=fopen(argv[1], "r")) == NULL )     inerr();
    while( fgets(buf, BUFL, infile) != NULL )  {
       filename[0] = '\0';
       sscanf( buf, "*FILE: %60s", filename );
       if( filename[0] != '\0' )  {
          if(opened)  fclose(outfile);
          printf( "*FILE: %s\n", filename );
          if( (outfile=fopen(filename,"w")) == NULL )    outerr();
          opened = 1;
          continue;
          }
       if( !opened )  fmterr();
       if( fputs(buf, outfile) == EOF )  outerr();
       }
    if( ferror(infile) )  inerr();
    fclose(infile);
 }


 usage()
 {
    printf("Usage:  unlump infile \n");
    printf("   UnLump the input file into output files named in it.\n");
    printf("   Files are separated by  a line with the format:\n");
    printf("      *FILE: filename.ext\n\n");
 }


 inerr()
 {
    printf("\nError opening or reading input file \n");
    fclose(infile);
    exit(1);
 }


 outerr()
 {
    printf("\nError opening or writing output file \n");
    fclose(outfile);
    exit(1);
 }


 fmterr()
 {
    printf("\nFile does not have proper LUMP format\n");
    exit(1);
 }


 UNTAB4.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\UNTAB4\UNTAB4.C

 /* Compile with DeSmet 2.2 or later */

 MAXSIZE 255     /* maximum line size */
 CR '\015'       /* code for carriage return (in octal) */

 main(argc,argv)         /* UNTAB4.C - Feb. 25, 1984 - V. T. Bly */
 int  argc;              /* Contact:     Vincent T. Bly          */
 char *argv[];           /*              P. O. Box 409           */
 {                       /*              Ft. Belvoir, VA  22060  */
 /*
 FUNCTION:   Take, as input, a file with tab stops expanded to 4 spaces.
             Create a new file with all tabs replaced by spaces.  The
             new file will have the original filename with the extension
             ".tab".  Example: input file - my.c, output file - my.tab.
             The original file is not altered.

 PURPOSE:    To allow files created by the DeSmet SEE editor (including
             all C source files from C-Ware) to by used with the IBM
             Personal Editor.  Files created with editors such as SEE or
             Vedit treat nonstandard tabs differently than other editors
             such as IBM's Personal Editor.  By processing these files
             (with tabs set to 4) with UNTAB4, the ".tab" file can be
             loaded and displayed by any editor.

 TO USE:     Type UNTAB4 followed by the filename (including extension)
             of the file you wish to untab.  The file you specify should
             have been created by SEE or a similar editor with tabs set
             to 4.  All C source files from C-ware are supplied this way.
             The new ".tab" file created will be larger than the original,
             since all tabs have been replaced by spaces.  You can shrink
             it back by loading it into the Personal Editor and resaving
             it.  This, again, will substitute tabs for spaces, but in a
             different way than that used by SEE.
 */
     int   s_file, d_file, e, i, j, k, l;
     int   tab = 4;
     char  *tabname, c, inbuff[256], outbuff[256];

     if (argc < 2) {
         puts("** Need a filename **\t");
         exit(1);
     }
     tabname = tabext(argv[1]);                  /* get destination file name
     s_file = fopen(argv[1], "r");               /* open source file */
     if (s_file == 0) {                          /* abort if can't open file *
         printf("* Cannot Open: %s *\n", argv[1]);
         exit(1);
     }
     d_file = fopen(tabname, "w");               /* open destination file */
     if (d_file == 0) {                          /* abort if can't open file *
         printf("* Cannot Open: %s *\n", tabname);
         exit(1);
     }
     do {
         e = fgets(inbuff, MAXSIZE, s_file);     /* get a line from the file *
         i = 0;  k = 0;
         while ((c = inbuff[i++]) != '\0') {     /* while not end of line */
             if (c == '\t') {                    /* if character is a tab */
                 l = k;
                 for (j = 0; j < (tab - (l % tab)); j++)
                     outbuff[k++] =' ';          /* expand tab to "tab" spaces
             } else if (c != CR) {               /* else, if not a CR, */
                 outbuff[k++] = c;               /* output character */
             }
         }
         outbuff[k] = '\0';                      /* output end of line char. *
         fputs(outbuff, d_file);                 /* write line to output file
         puts("* ");                             /* display "*" on screen */
     } while (e != 0);                           /* loop until end of file */
     close(s_file);                              /* close files */
     close(d_file);
 }

 tabext(oldname)             /* Create a new filename w/.tab extension */
 char  *oldname;
 {
     int   l;
     char  *index(), *p;
     static char tabname[13];

     l = strlen(oldname);            /* get length of oldname */
     p = index(oldname, '.');        /* get pointer to '.' in oldname */
     if (p > 0)
         l = p - oldname;            /* now l = # of chars up to extension */
     strncpy(tabname, oldname, 8);   /* copy name up to extension */
     strncpy(tabname + l, ".tab", 5);/* add ".tab" to form tabname */
     return(tabname);
 }


 UPLOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\UPLOW.C

                                         /* Chapter 13 - Program 1 */
 #include "STDIO.H"
 "ctype.h"      /* Note - your compiler may not need this */

 main()
 {
 FILE *fp;
 char line[80], filename[24];
 char *c;

    printf("Enter filename -> ");
    scanf("%s",filename);
    fp = fopen(filename,"r");

    do {
       c = fgets(line,80,fp);   /* get a line of text */
       if (c != NULL) {
          mix_up_the_chars(line);
       }
    } while (c != NULL);

    fclose(fp);
 }

 mix_up_the_chars(line)   /* this function turns all upper case
                             characters into lower case, and all
                             lower case to upper case. It ignores
                             all other characters.               */
 char line[];
 {
 int index;

    for (index = 0;line[index] != 0;index++) {
       if (isupper(line[index]))     /* 1 if upper case */
          line[index] = tolower(line[index]);
       else {
          if (islower(line[index]))  /* 1 if lower case */
             line[index] = toupper(line[index]);
       }
    }
    printf("%s",line);
 }


 USQ.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\USQ.C

 /* Program to unsqueeze files formed by sq.com
  *
  * Useage:
  *
  *        usq [-count] [-fcount] [file1] [file2] ... [filen]
  *
  * where file1 through filen represent one or more files to be compressed,
  * and the following options may be specified:
  *
  *        -count                Previewing feature: redirects output
  *                         files to standard output with parity stripped
  *                        and unprintables except CR, LF, TAB and  FF
  *                        converted to periods. Limits each file
  *                        to first count lines.
  *                        Defaults to console, but see below how
  *                        to capture all in one file for further
  *                        processing, such as by PIP.
  *                        Count defaults to a very high value.
  *                        No CRC check is performed when previewing.
  *                        Use drive: to cancel this.
  *
  *        -fcount                Same as -count except formfeed
  *                        appended to preview of each file.
  *                        Example: -f10.
  *
  * If no such items are given on the command line you will be
  * prompted for commands (one at a time). An empty command
  * terminates the program.
  *
  * The unsqueezed file name is recorded in the squeezed file.
  *
  */
 /* CHANGE HISTORY:
  * 1.3        Close inbuff to avoid exceeding maximum number of
  *        open files. Includes rearranging error exits.
  * 1.4        Add -count option to allow quick inspection of files.
  * 1.5  Break up long lines of introductory text
  * 1.5  -count no longer appends formfeed to preview of each file.
  *        -fcount (-f10, -F10) does append formfeed.
  * 1.6  Modified to work correctly under MP/M II (DIO.C change) and
  *      signon message shortened.
  * 2.0        Modified to work with CI-C86 compiler (CP/M-86 and MS-DOS)
  * 2.1  Modified for use in MLINK
  * 2.2  Modified for use with optimizing CI-C86 compiler (MS-DOS)
  * 3.0  Generalized for use under UNIX
  */

 /* ejecteject */

 #define SQMAIN

 #include <stdio.h>
 #include "sqcom.h"
 #include "usq.h"
 #define VERSION "3.1   12/19/84"

 /* This must follow all include files */
 unsigned int dispcnt;        /* How much of each file to preview */
 char        ffflag;                /* should formfeed separate preview from d

 main(argc, argv)
 int argc;
 char *argv[];
 {
         int i,c;
         char inparg[16];        /* parameter from input */

         dispcnt = 0;        /* Not in preview mode */

         printf("File unsqueezer version %s (original author: R. Greenlaw)\n\n

         /* Process the parameters in order */
         for(i = 1; i < argc; ++i)
                 obey(argv[i]);

         if(argc < 2) {
                 printf("Enter file names, one line at a time, or type <RETURN
                 do {
                         printf("\n*");
                         for(i = 0; i < 16; ++i) {
                                 if((c = getchar()) == EOF)
                                         c = '\n';        /* force empty (exit
                                 if((inparg[i] = c) == '\n') {
                                         inparg[i] = '\0';
                                         break;
                                 }
                         }
                         if(inparg[0] != '\0')
                                 obey(inparg);
                 } while(inparg[0] != '\0');
         }
 }

 /* ejecteject */

 obey(p)
 char *p;
 {
         char *q, cc;

         if(*p == '-') {
                 if(ffflag = ((*(p+1) == 'F') || (*(p+1) == 'f')))
                         ++p;
                 /* Set number of lines of each file to view */
                 dispcnt = 65535;        /* default */
                 if(*(p+1))
                         if((dispcnt = atoi(p + 1)) == 0)
                                 printf("\nBAD COUNT %s", p + 1);
                 return;
         }

         /* Check for ambiguous (wild-card) name */
         for(q = p; *q != '\0'; ++q)
                 if(*q == '*' || *q == '?') {
                         printf("\nCan't accept ambiguous name %s", p);
                         return;
                 }

         unsqueeze(p);
 }

 /* ejecteject */

 unsqueeze(infile)
 char *infile;
 {
         FILE *inbuff, *outbuff;        /* file buffers */
         int i, c;
         char cc;

         char *p;
         unsigned int filecrc;        /* checksum */
         int numnodes;                /* size of decoding tree */
         char outfile[128];        /* output file name */
         unsigned int linect;        /* count of number of lines previewed */
         char obuf[128];                /* output buffer */
         int oblen;                /* length of output buffer */
         static char errmsg[] = "ERROR - write failure in %s\n";

         if(!(inbuff=fopen(infile, "rb"))) {
                 printf("Can't open %s\n", infile);
                 return;
         }
         /* Initialization */
         linect = 0;
         crc = 0;
         init_cr();
         init_huff();

         /* Process header */
         if(getx16(inbuff) != RECOGNIZE) {
                 printf("%s is not a squeezed file\n", infile);
                 goto closein;
         }

         filecrc = getw16(inbuff);

         /* Get original file name */
         p = outfile;                        /* send it to array */
         do {
                 *p = getc(inbuff);
         } while(*p++ != '\0');

         printf("%s -> %s: ", infile, outfile);


         numnodes = getw16(inbuff);

         if(numnodes < 0 || numnodes >= NUMVALS) {
                 printf("%s has invalid decode tree size\n", infile);
                 goto closein;
         }

         /* Initialize for possible empty tree (SPEOF only) */
         dnode[0].children[0] = -(SPEOF + 1);
         dnode[0].children[1] = -(SPEOF + 1);

         /* Get decoding tree from file */
         for(i = 0; i < numnodes; ++i) {
                 dnode[i].children[0] = getw16(inbuff);
                 dnode[i].children[1] = getw16(inbuff);
         }

         if(dispcnt) {
                 /* Use standard output for previewing */
                 putchar('\n');
                 while(((c = getcr(inbuff)) != EOF) && (linect < dispcnt)) {
                         cc = 0x7f & c;        /* strip parity */
                         if((cc < ' ') || (cc > '~'))
                                 /* Unprintable */
                                 switch(cc) {
                                 case '\r':        /* return */
                                         /* newline will generate CR-LF */
                                         goto next;
                                 case '\n':        /* newline */
                                         ++linect;
                                 case '\f':        /* formfeed */
                                 case '\t':        /* tab */
                                         break;
                                 default:
                                         cc = '.';
                                 }
                         putchar(cc);
                 next: ;
                 }
                 if(ffflag)
                         putchar('\f');        /* formfeed */
         } else {
                 /* Create output file */
                 if(!(outbuff=fopen(outfile, "wb"))) {
                         printf("Can't create %s\n", outfile);
                         goto closeall;
                 }
                 printf("unsqueezing,");
                 /* Get translated output bytes and write file */
                 oblen = 0;
                 while((c = getcr(inbuff)) != EOF) {
                         crc += c;
                         obuf[oblen++] = c;
                         if (oblen >= sizeof(obuf)) {
                                 if(!fwrite(obuf, sizeof(obuf), 1, outbuff)) {
                                         printf(errmsg, outfile);
                                         goto closeall;
                                 }
                                 oblen = 0;
                         }
                 }
                 if (oblen && !fwrite(obuf, oblen, 1, outbuff)) {
                         printf(errmsg, outfile);
                         goto closeall;
                 }

                 if((filecrc && 0xFFFF) != (crc && 0xFFFF))
                         printf("ERROR - checksum error in %s\n", outfile);
                 else        printf(" done.\n");

         closeall:
                 fclose(outbuff);
         }

 closein:
         fclose(inbuff);
 }

 getw16(iob)                        /* get 16-bit word from file */
 FILE *iob;
 {
 int temp;

 temp = getc(iob);                /* get low order byte */
 temp |= getc(iob) << 8;
 if (temp & 0x8000) temp |= (~0) << 15;        /* propogate sign for big ints
 return temp;

 }


 getx16(iob)                        /* get 16-bit (unsigned) word from file */
 FILE *iob;
 {
 int temp;

 temp = getc(iob);                /* get low order byte */
 return temp | (getc(iob) << 8);

 }




 USQ18U.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQ_USQ\USQ18U.C

 static char *sccsid = "@(#)usq.c        1.8u (UCF) 83/09/02";
 /*
  *      usq.c - CP/M compatible file unsqueezer utility
  *
  *      compile as follows:
  *      cc [-DVAX] -O usq.c -o usq
  *         (define VAX only if running on VAX)
  */

 /*      modified by J. Chappell 02-02-84 to check if ferror occurred on write
                                 02-07-84 to accept wildcards in filenames
                                 09-05-84 to give message for disk full
         modified by M. Sehorne  09-10-84 to correct message output format
 */


 #include <stdio.h>
 /* #include <signal.h> */
 /* #include <ctype.h> */

 #define TRUE 1
 #define FALSE 0
 #define ERROR (-1)
 PATHLEN 312     /* Number of characters allowed in pathname */
 #define OK 0

 #define VERSION "1.8u   09-02-83"
 RECOGNIZE 0xFF76        /* unlikely pattern */
 DLE 0x90                /* repeat byte flag */
 SPEOF 256               /* special endfile token */
 NUMVALS 257             /* 256 data values plus SPEOF*/
 #define LARGE 30000

 VAX   /* then we don't want 32 bit integers */

 typedef short INT;
 typedef unsigned short UNSIGNED;

   /*  16 bit machines  */

 typedef int INT;
 typedef unsigned UNSIGNED;

 #endif

 struct _sqleaf {                /* Decoding tree */
         INT _children[2];       /* left, right */
 };
 struct _sqleaf Dnode[NUMVALS - 1];


 INT Bpos;               /* last bit position read */
 INT Curin;              /* last byte value read */
 INT Repct;              /* Number of times to return value */
 INT Value;              /* current byte value or EOF */

 INT MakeLCPathname=TRUE;        /* translate pathname to lc if all caps */
 INT Nlmode=FALSE;               /* zap cr's if true */
 INT Inbackground = FALSE;

 INT getcr(), getuhuff(), portgetw();

 extern int fflush(),ferror(),fclose();
 #define WILDCARD TRUE
 #define DOS TRUE

 main(argc, argv)
 unsigned char *argv[];
 {
         register unsigned char *cp;
         register INT npats=0;
         unsigned char **patts;
         INT n, errorstat;

 /*
         if (signal(SIGINT, SIG_IGN)==SIG_IGN)
                 Inbackground++;
         else
                 signal(SIGINT, SIG_DFL);
         signal(SIGHUP, SIG_IGN);
                                         */

         errorstat=0;
         if(argc<2)
                 goto usage;
         while (--argc) {
                 cp = *++argv;
                 if(*cp == '-') {
                         while( *++cp) {
                                 switch(*cp) {
                                 case 'n':
                                         Nlmode=TRUE; break;
                                 case 'u':
                                         MakeLCPathname=FALSE; break;
                                 default:
                                         goto usage;
                                 }
                         }
                 }
                 else if( !npats && argc>0) {
                         if(argv[0][0]) {
                                 npats=argc;
                                 patts=argv;
                         }
                 }
         }
         if(npats < 1) {
 usage:
                 fprintf(stderr,"File squeezer version %s by\n\tRichard Greenl
                 fprintf(stderr,"Usage: usq [-nu] file ...\n");
                 fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
                 fprintf(stderr,"\t-u preserve Uppercase pathnames\n");
 #ifdef WILDCARD
                 fprintf(stderr,"\n\tWildcards are acceptable in filenames.\n"
                 fprintf(stderr," \tThis means that you can USQ *.?Q?\n");
 #endif
                 fprintf(stderr,"\n\tUSQ will write the output file to the");
                 fprintf(stderr," \n\tcurrently logged drive/directory.\n");
                 exit(1);
         }

 #ifdef WILDCARD
         for(n=0; n<npats; ++n){
                 unsigned char *dir(), *cp, *s;
                 if(cp=dir(patts[n],1)){
                    for(s=cp;*s;s+=(strlen(s)+1)) errorstat |= squeeze(s);
                    free(cp);
                 }
                 else errorstat |= squeeze(patts[n]);
         }
 #else
         for(n=0; n<npats; ++n)
                 errorstat |= squeeze(patts[n]);
 #endif

         exit(errorstat != 0);
 }

 /*
         The following code is primarily from typesq.c and utr.c.  Typesq
 is a modification of USQ by Dick Greenlaw.  Those modifications (usq
 to typesq) were made by Bob Mathias, I am responsible for the butchery
 done to make it work with cat.

 */

 FILE *in, *out;
 squeeze(fname)
 unsigned char *fname;
 {
         register INT i, c;
         register unsigned char *p;
         register INT numnodes;                  /* size of decoding tree */
         register UNSIGNED crc;
         UNSIGNED filecrc;
         unsigned char origname[PATHLEN];        /* Original file name without
                                                   drive */
         long written;   /* number of bytes written */

         init_cr(); init_huff(); crc=0;

         if((in=fopen( fname, "rb"))==NULL) {
                 fprintf(stderr, "usq: can't open %s\n", fname);
                 return ERROR;
         }
         if(portgetw(in) != (INT) RECOGNIZE) {/* Process header */
                 fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
                 return(ERROR);
         }
         filecrc = (UNSIGNED) portgetw(in);      /* checksum */
         p = origname;                           /* Get original file name */
         do {                                    /* send it to array */
                 *p = getc(in);
         } while(*p++ != '\0');

         numnodes = portgetw(in);
         if(numnodes < 0 || numnodes >= NUMVALS) {
                 fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
                 fclose(in);
                 return(ERROR);
         }
         /* Initialize for possible empty tree (SPEOF only) */
         Dnode[0]._children[0] = -(SPEOF + 1);
         Dnode[0]._children[1] = -(SPEOF + 1);

         for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
                 Dnode[i]._children[0] = portgetw(in);
                 Dnode[i]._children[1] = portgetw(in);
         }
         /* Get translated output bytes and write file */
         if(MakeLCPathname && !IsAnyLower(origname))
                 uncaps(origname);
         for(p=origname; *p; ++p)                /* change / to _ */
                 if( *p == '/')
                         *p = '_';
         if (!Inbackground)
                 fprintf(stderr,"usq: unsqueezing %s to %s ",fname,origname);
         if((out=fopen(origname, "wb"))==NULL) {
                 fprintf(stderr, "usq: can't create %s\n", origname);
         }

         written=0;
         while ((c = getcr()) != EOF) {
                 crc += (UNSIGNED) c;
                 if ( c == '\r' && Nlmode)
                         continue;
                 if(fputc(c,out)!=c){
                         fclose(in);
                         crash(origname);
                 }
                 else ++written;
         }
         fclose(in);

         if(fflush(out)<0 || ferror(out)<0 || fclose(out)<0)
                 crash(origname);

         if( crc != filecrc ) {
                 fprintf(stderr, "usq: bad checksum in %s\n", fname);
                 fflush(stdout);
                 return(ERROR);
         }
         fprintf(stderr,"%8ld bytes written.\n",written);
         return(OK);
 }

 crash(fn) /* crash due to error writing file */
 char *fn;
 {

   fprintf(stderr,"\nusq: Error writing file: %s\n",fn);
   fprintf(stderr,"\nThe disk you are writing to is probably full.\n");
 #ifdef DOS
   fprintf(stderr,"\nTry running CHKDSK on your destination disk.\n");
 #else
   fprintf(stderr,"\nTry running STAT on your destination disk.\n");
 #endif
   exit(1);
 }

 /*** from utr.c - */
 /* initialize decoding functions */

 init_cr()
 {
         Repct = 0;
 }

 init_huff()
 {
         Bpos = 99;      /* force initial read */
 }

 /* Get bytes with decoding - this decodes repetition,
  * calls getuhuff to decode file stream into byte
  * level code with only repetition encoding.
  *
  * The code is simple passing through of bytes except
  * that DLE is encoded as DLE-zero and other values
  * repeated more than twice are encoded as value-DLE-count.
  */

 INT
 getcr()
 {
         register INT c;

         if(Repct > 0) {
                 /* Expanding a repeated char */
                 --Repct;
                 return(Value);
         } else {
                 /* Nothing unusual */
                 if((c = getuhuff()) != DLE) {
                         /* It's not the special delimiter */
                         Value = c;
                         if(Value == EOF)
                                 Repct = LARGE;
                         return(Value);
                 } else {
                         /* Special token */
                         if((Repct = getuhuff()) == 0)
                                 /* DLE, zero represents DLE */
                                 return(DLE);
                         else {
                                 /* Begin expanding repetition */
                                 Repct -= 2;     /* 2nd time */
                                 return(Value);
                         }
                 }
         }
 }
 /* Decode file stream into a byte level code with only
  * repetition encoding remaining.
  */

 INT
 getuhuff()
 {
         register INT i;

         /* Follow bit stream in tree to a leaf*/
         i = 0;  /* Start at root of tree */
         do {
                 if(++Bpos > 7) {
                         if((Curin = getc(in)) == ERROR)
                                 return(ERROR);
                         Bpos = 0;
                         /* move a level deeper in tree */
                         i = Dnode[i]._children[1 & Curin];
                 } else
                         i = Dnode[i]._children[1 & (Curin >>= 1)];
         } while(i >= 0);

         /* Decode fake node index to original data value */
         i = -(i + 1);
         /* Decode special endfile token to normal EOF */
         i = (i == SPEOF) ? EOF : i;
         return(i);
 }
 /*
  * Machine independent getw which always gets bytes in the same order
  *  as the CP/M version of SQ wrote them
  */
 INT
 portgetw(f)
 FILE *f;
 {
         register INT c;

         c = getc(f) & 0377;
         return(c | (getc(f) << 8));
 }


 /* make string s lower case */
 uncaps(s)
 unsigned char *s;
 {
         for( ; *s; ++s)
                 if(isupper(*s))
                         *s = tolower(*s);
 }


 /*
  * IsAnyLower returns TRUE if string s has lower case letters.
  */
 IsAnyLower(s)
 unsigned char *s;
 {
         for( ; *s; ++s)
                 if (islower(*s))
                         return(TRUE);
         return(FALSE);
 }


 #ifdef WILDCARD
 /*      dir: for DOS ALL

         Entry:
                 1. Filename possibly containing wildcards ? and *
                 2. Drive specifier flag

         Returns: Pointer to data area containing NULL terminated
                  list of filenames, or NULL if none found.

         Notes: User must free up data allocated by this function
                 with free() if memory is to be restored to heap
                 after use.

               Drive specifier: if non-zero will drive specifiers
                 will be put on file names

               Path names: not supported

 */

 unsigned char *dir(filespec,drflag)
 unsigned char *filespec;
 short drflag;
 {
 BLOCK 100               /* room for fcb,dta,etc.. */
 FIRST 0x1100            /* search first */
 NEXT 0x1200             /* search next */
 CURRENT 0x19            /* get current drive */
 PARSE 0x2900            /* parse file name */
 SETDTA 0x1a00           /* set disk transfer address */

 unsigned char *fcb,*rets,*cp,*tmp,*dta,*realloc();
 unsigned short mode,pos,i;
 struct regval { int ax,bx,cx,dx,si,di,ds,es;} r;

   tmp=realloc(0,BLOCK); fcb=realloc(0,BLOCK);
   dta=realloc(0,BLOCK); rets=realloc(0,BLOCK);

   segread(&r.si);                       /* parse file name */
   r.es=r.ds; r.si=filespec; r.di=fcb; r.ax=PARSE; sysint21(&r,&r);

   segread(&r.si);                       /* set dta */
   r.dx=dta; r.ax=SETDTA; sysint21(&r,&r);

   for(pos=0,mode=FIRST;;mode=NEXT){
         segread(&r.si); r.ax=mode; r.dx=fcb; sysint21(&r,&r);   /* search  */
         if(r.ax&0xff==0xff)break;                       /* not found */
         cp=tmp;
         if(drflag){                             /* put on drive specifier */
                 if(*dta==0)*dta=(bdos(CURRENT)&0xff)+1;
                 *cp++=*dta+'A'-1; *cp++=':';
         }
         for(i=1;i<9;i++)if(*(dta+i)!=' ')*cp++=*(dta+i); *cp++='.';
         for(;i<12;i++)if(*(dta+i)!=' ')*cp++=*(dta+i); *cp='\0';
         rets=realloc(rets,pos+strlen(tmp)+1);   /* store file name */
         strcpy(rets+pos,tmp);
         pos+=(strlen(tmp)+1);
   }

   if(pos)rets=realloc(rets,pos+strlen(tmp)+1);
   else free(rets);
   free(fcb); free(tmp); free(dta);
   return pos ? rets: 0;
 }

 #endif


 UTOA.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\JPLC1\UTOA.C

 /* 1.1  01-08-86                                                 (utoa.c)
  ************************************************************************
  *                        Robert C. Tausworthe
  *                        Jet Propulsion Laboratory                        *
  *                        Pasadena, CA 91009                1984
  ************************************************************************
  *
  *        These functions are modified versions of itoa() found in Kernighan
  *        and Ritchie, page 60, with modifications as suggested in exercises
  *        3-4 and 3-5, and with returned pointer to result string.
  *
  *----------------------------------------------------------------------*/

 #include "defs.h"
 #include "stdtyp.h"
 #include "errno.h"

 /************************************************************************/
         STRING
 utoa(s, n, w)                /* return pointer to string s, which contains as
                            value of unsigned n, base 10, min width w.
 /*----------------------------------------------------------------------*/
 STRING s;
 unsigned n;
 {
         STRING utoab();

         return utoab(s, n, w, 10);
 }

 /************************************************************************/
         STRING
 utoab(s, n, w, b)        /* convert n to a minimum of w ascii characters,
                            base b, and put  in s.  Return pointer to s.
 /*----------------------------------------------------------------------*/
 STRING s;
 unsigned n;
 {
         LOCAL char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
         int i, j;
         char c, fill;

         if (w < 0)
         {        fill = '0';
                 w = -w;
         }
         else
                 fill = ' ';
         i = 0;
         do                        /* generate digits in reverse order:
         {        s[i++] = digits[n % b];
         } while (n /= b);
         while (i < w)                        /* expand to proper width.
                 s[i++] = fill;        /* i is just beyond last filled postion
         s[i--] = NULL;                        /* add null terminator        *
         for (i, j = 0; j < i; j++, i--) /*  now reverse chars */
         {        c = s[j];
                 s[j] = s[i];
                 s[i] = c;
         }
         return s;
 }


 UTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SQUPORT\UTR.C

 #include <stdio.h>
 #include "sqcom.h"
 #include "usq.h"
 #define ERROR -1

 /* initialize decoding functions */

 init_cr()
 {
         repct = 0;
 }

 init_huff()
 {
         bpos = 99;        /* force initial read */
 }

 /* Get bytes with decoding - this decodes repetition,
  * calls getuhuff to decode file stream into byte
  * level code with only repetition encoding.
  *
  * The code is simple passing through of bytes except
  * that DLE is encoded as DLE-zero and other values
  * repeated more than twice are encoded as value-DLE-count.
  */

 int
 getcr(ib)
 FILE *ib;
 {
         int c;

         if(repct > 0) {
                 /* Expanding a repeated char */
                 --repct;
                 return value;
         } else {
                 /* Nothing unusual */
                 if((c = getuhuff(ib)) != DLE) {
                         /* It's not the special delimiter */
                         value = c;
                         if(value == EOF)
                                 repct = LARGE;
                         return value;
                 } else {
                         /* Special token */
                         if((repct = getuhuff(ib)) == 0)
                                 /* DLE, zero represents DLE */
                                 return DLE;
                         else {
                                 /* Begin expanding repetition */
                                 repct -= 2;        /* 2nd time */
                                 return value;
                         }
                 }
         }
 }

 /* ejecteject */

 /* Decode file stream into a byte level code with only
  * repetition encoding remaining.
  */

 int
 getuhuff(ib)
 FILE *ib;
 {
         int i;
         int bitval;

         /* Follow bit stream in tree to a leaf*/
         i = 0;        /* Start at root of tree */
         do {
                 if(++bpos > 7) {
                         if((curin = getc(ib)) == ERROR)
                                 return ERROR;
                         bpos = 0;
                         /* move a level deeper in tree */
                         i = dnode[i].children[1 & curin];
                 } else
                         i = dnode[i].children[1 & (curin >>= 1)];
         } while(i >= 0);

         /* Decode fake node index to original data value */
         i = -(i + 1);
         /* Decode special endfile token to normal EOF */
         i = (i == SPEOF) ? EOF : i;
         return i;
 }


 VC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\VC.C

 /*         VC.C    VC.C    VC.C    VC.C    VC.C    VC.C    VC.C

 VISUAL CALCULATOR                           X   X   XXX
   MAIN PROGRAM                              X   X  X   X
                                             X   X  X
 July 1, 1987                                 X X   X
                                              X X   X
                                               X    X   X
                                               X     XXX

      This program will evaluate single value expressions in a
      manner similar to those evaluated by a hand-held calculator,
      hence its name, the Visual Calculator. It was never intended
      to be programmable, so no loop constructs are included in
      its design. It is possible to write a series of statements,
      store them in a file, and recall them while using them to
      calculate with new values of input variables in the six
      variable storage registers. The input variables can be
      changed, and the entire series recalculated.

      Although this is a potentially useful program in its own
      right, it was originally written as an illustration of a
      rather large C program. It is especially useful because
      the student of C can run the program to determine its
      operating characteristics, then study the code needed to
      perform the various operations. For that reason, the entire
      program is heavily commented. An actual production program
      would probably not have as many comments as this example
      but it would not be bad practice to comment all of your
      programs to this extent.
 */
 #include "ctype.h"
 #include "stdio.h"
 #include "string.h"
 #include "conio.h"
 #include "process.h"
 #include "struct.def"
 #include "defin.h"

 struct vars allvars[12]; /* this is the main variable storage */
 int varinuse = 0;        /* which variable is being used now  */
 char inline[200];        /* input line area                   */
 int col;                 /* used for searching across the input */
 int errcode;             /* error code number                 */
 int colerr;              /* column where error occurred       */
 int printit = 0;         /* 1 = print a transcript            */
 int ignore;              /* 1 = ignore calculations for line  */
 extern char strngout[];  /* output message area               */
 extern int valattr;      /* value and variable attribute      */
 extern int helpattr;     /* help box attribute                */
 FILE *prtfile;           /* file pointers                     */

 struct lines *top, *bot, *q, *p, *arrow, *trnsend;

 /* *********************************************************** main */
 /* This is the main control loop for the program. It initializes    */
 /* everything and reads statements until no errors are found. It    */
 /* continues reading until an F10 is detected in a subordinate      */
 /* function where control is returned to DOS                        */
 main()
 {
    top = bot = q = p = arrow = trnsend = NULL;
    monitor();                 /* initialize video attributes */
    initdata(&allvars[0]);   /* initialize all data           */
    bkgndvid();   /* display video background - double lines  */
    valusvid();   /* display starting values of all variables */
    strtrans("Welcome to the Visual Calculator - Version 1.10",0);
    transout();
    do{
       poscurs(23,7);
       printf("  input >                                 ");
       printf("                              ");
       do {                     /* repeat input until no errors      */
          readline();           /* get an input line                 */
          errdis("                         ");  /* clear error msg   */
          parse();              /* parse the line                    */
          if (errcode) errout();/* output error message              */
       } while (errcode);
       if (ignore == 1)
          strtrans(inline,0);   /* store comment in transcript       */
       else
          strtrans(inline,1);   /* store "inline" in transcript      */
       transout();
    } while (1);                /* continuous loop                   */
 }
 /* ******************************************************* readline */
 /* This function reads a line by inputting one character at a time  */
 /* and deciding what to do with it if it is a special character, or */
 /* adding it to the input line if it is a special character. The    */
 /* routine takes care of such things as backspace, cursor movement  */
 /* and delete keys. The final result is a single line of text stored*/
 /* in the buffer "inline" and the line displayed on the monitor.    */
 void readline(void)
 {
 int index;
 int c,temp;
 int row = 23,col = 17;
 int attr;

    if (errcode) {                   /* error recovery allow reenter */
       index = colerr;
       errcode = 0;
    }
    else {                                   /* normal input routine */
       index = 0;
       for (temp = 0;temp < 80;temp++)
          inline[temp] = 0;                    /* clear input buffer */
    }

    poscurs(row,col+index);           /* starting location of cursor */

    do {                /* repeat this do loop until a return is hit */
       while ((c = getch()) == EOF);              /* get a keystroke */

       if (c == 0) {       /* a zero here says a special key was hit */
                              /* get the key and act on it as needed */
          int spec;
          spec = getch();          /* this is the special code found */
          switch (spec) {
             case 59 : helpm();                 /* F1 - Help math    */
                       transout();
                       break;
             case 60 : helps();                 /* F2 - Help system  */
                       transout();
                       break;
             case 61 : if (printit) {           /* F3 - Print on/off */
                          printit = 0;          /* print off */
                          fprintf(prtfile,"%s\n\n","Print off");
                          fclose(prtfile);
                          strcpy(strngout,"-----");
                          attr = helpattr;
                       } else {
                          prtfile = fopen("PRN","w");   /* print on */
                          if (prtprblm()) {
                             errcode = 12;   /* printer is not ready */
                             errout();
                             break;
                          }
                          printit = 1;
                          fprintf(prtfile,"%s\n","Print On");
                          strcpy(strngout,"Print");
                          attr = valattr;
                       }
                       strngdis(1,73,attr);
                       break;
             case 62 :                       /* F4 - Mark transcript */
                       arrow->marked = (arrow->marked?0:1);
                       transout();
                       break;
             case 63 : fileout();           /* F5 - Store transcript */
                       break;
             case 64 : filein();             /* F6 - Retrieve trans  */
                       errcode = 0;
                       break;
             case 65 :                       /* F7 -                 */
                       break;
             case 66 :                       /* F8 -                 */
                       break;
             case 67 :                       /* F9 - Edit a line     */
                       strcpy(inline,arrow->lineloc);
                       poscurs(23,17);
                       printf("%s",inline);
                       break;
             case 68 : poscurs(23,17);        /* F10 - Quit to DOS   */
                       printf("Quit? (Y/N) ");
                       c = getch();
                       if ((c == 'Y') || (c == 'y')){
                          clrscrn();
                          exit(0);
                       }
                       poscurs(23,17);
                       printf("              ");
                       break;
             case 75 : if (index) {                    /* left arrow */
                          index = index -1;        /* back up cursor */
                       }
                       break;

             case 77 : if (index < 65) {              /* right arrow */
                          if (inline[index] == 0)      /* zero found */
                             inline[index] = ' ';    /* blank over 0 */
                          index = index + 1;       /* cursor forward */
                       }
                       break;

             case 72 : movarrow(-1);                     /* up arrow */
                       break;

             case 80 : movarrow(1);                    /* down arrow */
                       break;

             case 73 : movarrow(-8);                      /* page up */
                       break;

             case 81 : movarrow(8);                     /* page down */
                       break;

             case 71 : movarrow(-1000);                      /* home */
                       break;

             case 79 : movarrow(1000);                        /* end */
                       break;

             case 83 : temp = index;                   /* delete key */
                               /* move all characters left one space */
                       while (inline[temp]) {
                          inline[temp] = inline[temp+1];
                          putchar(inline[temp++]);
                       }
                       putchar(0);             /* zero in last place */
                       break;

             default : poscurs(15,5);
                       printf(" S%3d",spec);
          }
          poscurs(row,col+index); /* actually put cursor in position */
       }

       else {                           /* normal letter or char hit */
          int curr,next;
          if (islower(c)) c = toupper(c);   /* convert to upper case */
          if ((c >= '\40') && (c <= '\176')) {     /* printable char */
             poscurs(row,col+index);
             putchar(c);
             next = inline[index];
             inline[index++] = c;
             curr = index;
             while((next != 0) && (curr <= 65)) {  /* move remainder */
                temp = next;                           /* line right */
                next = inline[curr];
                inline[curr++] = temp;
                putchar(temp);
             }
          }
          else {
             if ((c == 8) && index){                    /* backspace */
                index--;
                poscurs(row,col+index);            /* back up cursor */
                temp = index;
                while (inline[temp]) {
                   inline[temp] = inline[temp+1];
                   putchar(inline[temp++]);
                }
                putchar(0);
             }
          }
          poscurs(row,col+index);
       }
       if (c == 3) exit(0);                /* ctrl-break, out to DOS */
    } while (c != 13);      /* newline found, line input is complete */
 }

 /* ********************************************************** parse */
 /* This function does a lot of checking of the input line for       */
 /* logical errors in construction, then turns control over to the   */
 /* function "calcdata" for the actual calculations.                 */
 void parse(void)
 {
 int index,parcol;
 double newval;
 char name[7];

    varinuse = -1;
    errcode = 0;
    col = 0;
    ignore = 1;                             /* ignore this line      */

    if (inline[0] == '#') {            /* get list of variable names */
       getnames();
       return;
    }

    while (inline[col] == ' ') col++;       /* ignore leading blanks */
    if (inline[col] == '$') return;         /* ignore a comment line */
    if (inline[col] == 0) return;             /* ignore a blank line */
    ignore = 0;                            /* don't ignore this line */

    name[0] = inline[col++];                   /* find variable name */
    index = 1;
    while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
           ((inline[col] >= '0') && (inline[col] <= '9'))) &&
           (index <= 5)) {          /* continue var or function name */
       name[index++] = inline[col++];
    }
    name[index] = 0;                                   /* name found */

    for (index = 0;index < 12;index++) {
       if ((strcmp(name,allvars[index].varname)) == 0)
          varinuse = index;                   /* variable name found */
    }
    if (varinuse < 0) errchk(3);            /* unknown variable name */

    while (inline[col] == ' ') col++;       /* ignore leading blanks */
    if (inline[col] == '=') col++;
       else errchk(8);                         /* missing equal sign */

    parcol = 0;         /* now check for correct parenthesis matchup */
    index = col;
    do {
       if (inline[col] == '(') parcol++;
       if (inline[col++] == ')') parcol--;
       if (parcol < 0) errchk(1);       /* paren count went negative */
    } while (inline[col]);
    if (parcol) errchk(2);                  /* left over parentheses */
    col = index;

    calcdata(&newval);        /* now go evaluate the full expression */
    if (errcode == 0) {         /* don't update value if error found */
       allvars[varinuse].value = newval;
       disnew(varinuse);                /* display the changed value */
    }
 }

 /* ********************************************************* errout */
 /* This is the function that displays the blinking error message on */
 /* the monitor. Note the extra errors for expansion of the table.   */
 void errout(void)
 {
    switch (errcode) {
       case  1 : errdis("extra right parentheses  ");
                 break;
       case  2 : errdis("missing right parentheses");
                 break;
       case  3 : errdis("unknown variable name    ");
                 break;
       case  4 : errdis("invalid math operator    ");
                 break;
       case  5 : errdis("negative value for SQRT  ");
                 break;
       case  6 : errdis("function not found      ");
                 break;
       case  7 : errdis("negative value for LOG   ");
                 break;
       case  8 : errdis("equal sign missing       ");
                 break;
       case  9 : errdis("invalid data field       ");
                 break;
       case 10 : errdis("division by zero         ");
                 break;
       case 11 : errdis("File doesn't exist       ");
                 break;
       case 12 : errdis("Printer not ready        ");
                 break;
       case 13 : errdis("Out of memory            ");
                 break;
       case 14 : errdis("Dash expected            ");
                 break;
       case 15 : errdis("Invalid format code      ");
                 break;
       case 16 : errdis("Neg value for FACTORIAL  ");
                 break;
       case 17 : errdis("Err 17                   ");
                 break;

       default : errdis("unknown error            ");
                 poscurs(21,70);
                 printf("%d",errcode);
    }
    poscurs(23,12+colerr);
 }


 VERIFY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\VERIFY.C


 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /********************************************************
 **
 **        verify(consequent)
 **
 **        finds the truth about the consequent -- returns
 **        TRUE if consequent is proved (all antecedents are TRUE)
 **        FALSE if any of the antecedents are FALSE
 **
 ********************************************************/

 #include <stdio.h>
 #include "expert.h"
 #include "inference.h"

 int        verify(cnsquent)
         int        cnsquent ;

 {
 int         i,j,k,m,n ;
 int        antecedent[MAX_ANTECEDENTS] ;
 int        consequent[MAX_ANTECEDENTS] ;
 int        p_value ;                        /* predicate value */

 #ifdef DEBUG
         int di ;
         for(di=0;di<numTrue;di++)
                 printf("\nDEBUG-verify knownTrueFact = %d",knownTrue[di]) ;
         for(di=0;di<numFalse;di++)
                 printf("\nDEBUG-verify knownFalseFact = %d",knownFalse[di]) ;

 #endif

 /*
 **
 **        get all of the antecedents for the consequent
 **
 **        First locate the antecedents -- should be directly in front
 **        of the consequent, delimited by a consequent with a flag of zero
 */

 #ifdef DEBUG
         printf("\nDEBUG -- verify consequent = %d",cnsquent ) ;
 #endif

 j = 0 ;

 for(i=cnsquent; i>=0 ; i--)
         {
         if(ruleBuff[i].flag == 0 )
                 break ;
         }

 if(i == -1)
         {
         printf("\n Bad Consequent, has no antecedents! returning TRUE value \
         return(TRUE);
         }

 for(i = i-1 ;i>=0; i--)
         {
         if(ruleBuff[i].flag != 0)
                 antecedent[j++]=i ;
         else
                 break ;
         }

 if(j==0)
         {
         printf("\n Bad Consequent, has no antecedents! returning TRUE value \
         return(TRUE);
         }

 #ifdef DEBUG
         printf("\nDEBUG -- verify antecedents = ") ;
         for(di=0; di < j; di++)
                 printf("\n         %d -- %d",di,antecedent[di]) ;
 #endif

 /*
 **        at this point we should have some antecedents in the antecedent
 **        stack so now lets see if each can be proved, and if there are
 **        any consequents which will need verification.
 */

 /*
 **        main verificaiton loop:
 */

 for(i=j-1 ; i >= 0 ; i--) /* for all of the antecedents in our stack */
         {

 /*
 **        determine if the antecedent is itself a consequent
 **
 **        compare value of the string pointer of the antecedent needs to
 **        be compaired with the value of the string pointer of all of the
 **        consequents, if there is a match then the antecedent is a consequen
 **
 **        There may be more
 **        than one consequent and this is handled below since all of these
 **        must be false before we give up hope that one will be verified--
 **        REMEMBER -- consequents are not remembered FALSE they can only be
 **        remembered when they are true -- FALSEness for a consequent merely
 **        means that this particular rule did not verify it , some other one
 **        might.
 **
 */

         for(k=0; k< numHypot; k++ )
                 if(ruleBuff[hypStack[k]].string == ruleBuff[antecedent[i]].st
                         break ;

         if(k != numHypot)  /* we have an antecedent which is a consequent */
                 {

 #ifdef DEBUG
         printf("\nDEBUG -- verify antecedent %d is consequent %d",i, antecede
 #endif

 /*
 **        What we have is an antecedent which is a consequent of another
 **        rule or rules.  What is needed then is to place each of these conse
 **        into a stack and prove them one at a time.  We will return truth
 **        if any of these are proven true and return false only when all of
 **        them are false.   We can use veriry recursively in this case to
 **        verify each one.
 **
 **        get all consequents matching hypStack[k].string into a stack
 **        look for truth of any consequent.
 **        if consequent is true (according to flag) return true.
 **        if all consequents are false then return false.
 */
                 n = 0 ;
                 for( m = 0 ; m < numHypot ; m++)
                         {
                         if(ruleBuff[antecedent[i]].string == ruleBuff[hypStac
                                 {
 #ifdef DEBUG
                                 printf("\nDEBUG--consequent stack(%d) = %d",n
 #endif
                                 consequent[n++] = hypStack[m] ;
                                 }
                         }
 /*
 **        verify each consequent
 */

                 p_value = FALSE ;
                 for(m = 0 ; m < n ; m++)
                         {

 #ifdef DEBUG
         printf("\nDEBUG -- verify(2) consequent = %d",consequent[m] ) ;
 #endif
                         if( verify(consequent[m]) == TRUE )
                                 {
                                 p_value = TRUE ;
                                 if(known(consequent[m],knownTrue,numTrue) ==
                                         {
                                         printf("\nI infer that : %s\n",&strBu
                                         knownTrue[numTrue++]=ruleBuff[consequ
                                         }
                                 if(remAnte(antecedent[i]) == TRUE)
                                         {
                                         break ;
                                         }
                                 else
                                         {
                                         return(FALSE) ;
                                         }
                                 }
                         }
                 if(p_value == FALSE) /* all of the consequents were not prove
                         {
                         switch(ruleBuff[antecedent[i]].flag)
                                 {
                                 case STRING_FALSE :
                                 case ROUTINE_FALSE :
                                         continue ;
                                 case STRING_TRUE :
                                 case STRING_TRUE_HYP :
                                 case ROUTINE_TRUE :
                                 case ROUTINE_TRUE_HYP :
                                         return(FALSE) ;
                                 }
                         }
                 else                        /* at least one was known */
                         {
                         switch(ruleBuff[antecedent[i]].flag)
                                 {
                                 case STRING_TRUE :
                                 case STRING_TRUE_HYP :
                                 case ROUTINE_TRUE:
                                 case ROUTINE_TRUE_HYP:
                                         continue ;
                                 case STRING_FALSE :
                                 case ROUTINE_FALSE :
                                         return(FALSE) ;
                                 }
                         }
                 }

         else        /* we have a plane old string or routine antecedent */

                 {

                 if(weKnow(antecedent[i],&p_value) == TRUE)
                         {
                         if(p_value == TRUE)
                                 continue ;
                         else
                                 return(FALSE) ;
                         }
 /*
 **        Things arent known and are simple consequents so prove them
 **        either by asking the user or by running the routine
 */
                 if(verifyTruth(antecedent[i]) == TRUE)
                         continue ;
                 else
                         return(FALSE) ;
                 }
         }
 /*
 **        Everything was TRUE in the big and statement so return it
 */
 return(TRUE) ;
 }



 VERIFYTR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\VERIFYTR.C



 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /*****************************************************
 **
 **        verifyTruth(antecedent) ;
 **
 **        This routine verifies the truth of a string or routine which
 **        is not a consequnt of a rule (ie an antecedent)
 **
 **        The routine remembers the final state of the antecedent in
 **        the knownTrue, or knownFalse stacks
 **
 **        accomplishes task either by running the routine or by
 **        asking the user for the specific truth of a statement
 **
 **        returns --
 **                the "true" predicate value of the antecedent
 **                according to its .flag:
 **
 **                        TRUE if the antecedent phrase is TRUE and
 **                           the antecedent .flag indicates positive,
 **                        FALSE if the antecedent phrase is TRUE and
 **                           the antecedent .flag indicates negative.
 **                        etc.
 **
 *******************************************************/

 #include <stdio.h>
 #include "expert.h"
 #include "inference.h"

 int        verifyTruth(antecedent)
         int antecedent ;
 {
 switch(ruleBuff[antecedent].flag)
         {
         case STRING_TRUE :
         case STRING_TRUE_HYP:
                 if( getTruth(antecedent) == TRUE)
                         {
                         knownTrue[numTrue++] = ruleBuff[antecedent].string ;
                         return(TRUE) ;
                         }
                 else
                         {
                         knownFalse[numFalse++] = ruleBuff[antecedent].string
                         return(FALSE) ;
                         }
         case STRING_FALSE :
                 if( getTruth(antecedent) == TRUE)
                         {
                         knownTrue[numTrue++] = ruleBuff[antecedent].string ;
                         return(FALSE) ;
                         }
                 else
                         {
                         knownFalse[numFalse++] = ruleBuff[antecedent].string
                         return(TRUE) ;
                         }
         case ROUTINE_TRUE :
         case ROUTINE_TRUE_HYP:
                 if( runRoutine(antecedent) == TRUE)
                         {
                         knownTrue[numTrue++] = ruleBuff[antecedent].string ;
                         return(TRUE) ;
                         }
                 else
                         {
                         knownFalse[numFalse++] = ruleBuff[antecedent].string
                         return(FALSE) ;
                         }
         case ROUTINE_FALSE :
                 if (runRoutine(antecedent) == TRUE)
                         {
                         knownTrue[numTrue++] = ruleBuff[antecedent].string ;
                         return(FALSE) ;
                         }
                 else
                         {
                         knownFalse[numFalse++] = ruleBuff[antecedent].string
                         return(TRUE) ;
                         }
                 default:
                         printf("\major problem # 0001 -- llegal antecedent fl
                         return(TRUE) ;
                 }
 }



 VIDASM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\TCLIB\VIDASM.C

 /* These routines are for Turbo-C and provide some basic but
    valuable screen access to the IBM PC/AT and Compatibles.
    Unfortunately these cannot be used when in the Turbo-C
    development environment.

    by Mike Elkins - Mike's C Board (619)-722-8724 1200/2400
      */

 cls()         /* Clear the screen  */
 {

     asm  mov   ax,0600h
     asm  mov   bh,7
     asm  mov   cx,0
     asm  mov   dx,184fh
     asm  int   10h

 }

 del_cur()  /* Make cursor disappear */
 {

     asm  mov   ah,01
     asm  mov   ch,26h
     asm  mov   cl,7
     asm  int   10h
 }

 restor_cur()  /* Put cursor back on screen */
 {
     unsigned        st, en;

     if (get_mode() == 7)
         st = 12, en = 13;
     else
         st = 6, en = 7;

     asm  mov   ah,01
     asm  mov   bh,0
     asm  mov   ch,st
     asm  mov   cl,en
     asm  int   10h
 }

 get_mode()   /* Check for Monocrome or graphics  */
 {

     asm  mov   ah,15
     asm  mov   bh,0
     asm  mov   ch,0
     asm  mov   cl,0
     asm  int   10h
     asm  xor   ah,ah
 }

 gotoxy(x, y)
 int x, y;
 {

     asm  mov   ah,02
     asm  mov   bh,0
     asm  mov   dh,x
     asm  mov   dl,y
     asm  int   10h
 }

          Mike Johnson...........1-918-493-21372400 N81N         Met Chem.....


 VIDEO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\ADVC\VIDEO.C

 #include <dos.h>

 void bkscroll(lcol,trow,rcol,brow,lines)  /* scroll a screen area down */
    int lcol, trow, rcol, brow, lines;
 {
    union REGS inregs;
    union REGS outregs;

    inregs.h.ah = 15;                    /* get active display page */
    int86(0x10,&inregs,&outregs);
    inregs.h.bh = outregs.h.bh;
    inregs.h.dl = --lcol;
    inregs.h.dh = --trow;
    inregs.h.ah = 2;                     /* set cursor position */
    int86(0x10,&inregs,&outregs);
    inregs.h.ah = 8;                     /* get color/attribute */
    int86(0x10,&inregs,&outregs);
    inregs.h.bh = outregs.h.ah;
    inregs.h.cl = lcol;
    inregs.h.ch = trow;
    inregs.h.dl = --rcol;
    inregs.h.dh = --brow;
    inregs.h.al = lines;
    inregs.h.ah = 7;                     /* do the backscroll */
    int86(0x10,&inregs,&outregs);
 }





 void clreol()                         /* clear from cursor to end of line */
 {
    union REGS inregs;
    union REGS outregs;
    int attr, columns;

    inregs.h.ah = 15;                       /* get display page, columns */
    int86(0x10,&inregs,&outregs);
    inregs.h.bh = outregs.h.bh;
    columns = outregs.h.ah;
    inregs.h.ah = 8;                        /* get color/attribute */
    int86(0x10,&inregs,&outregs);
    attr = outregs.h.ah;
    inregs.h.ah = 3;                        /* get cursor position */
    int86(0x10,&inregs,&outregs);
    inregs.h.bl = attr;
    inregs.x.cx = columns - outregs.h.dl;
    inregs.x.ax = 0x0920;                   /* write spaces until EOLN */
    int86(0x10,&inregs,&outregs);
 }





 void scroll(lcol,trow,rcol,brow,lines)   /* scroll a screen area up */
    int lcol, trow, rcol, brow, lines;
 {
    union REGS inregs;
    union REGS outregs;

    inregs.h.ah = 15;                    /* get active display page */
    int86(0x10,&inregs,&outregs);
    inregs.h.bh = outregs.h.bh;
    inregs.h.dl = --lcol;
    inregs.h.dh = --trow;
    inregs.h.ah = 2;                     /* set cursor position */
    int86(0x10,&inregs,&outregs);
    inregs.h.ah = 8;                     /* get color/attribute */
    int86(0x10,&inregs,&outregs);
    inregs.h.bh = outregs.h.ah;
    inregs.h.cl = lcol;
    inregs.h.ch = trow;
    inregs.h.dl = --rcol;
    inregs.h.dh = --brow;
    inregs.h.al = lines;
    inregs.h.ah = 6;                     /* do the scroll */
    int86(0x10,&inregs,&outregs);
 }


 VIDEO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\SCBENCH\VIDEO.C

 /*
 **
 ** BYTE Small-C Video Support Routines
 ** NOTE: Many of these routines were adapted from code presented
 **       in Richard Wilton's PROGRAMMER'S GUIDE TO PC & PS/2
 **       VIDEO SYSTEMS (Microsoft Press, ISBN 1-55615-103-9)
 **       (A *fabulous* book, by the way.)
 **       Also, Robert Jourdain's PROGRAMMER'S PROBLEM SOLVER
 **       FOR THE IBM PC,XT & AT (Brady Books, ISBN 0-89303-787-7)
 **       (Another fine book.)
 **
 ** setp(x,y,color,mode)
 ** Set pixel at x,y to color. Mode is mode #.
 ** This function assumes that ES points to the video segment.
 */
 setp(x,y,color,mode)
 int x,y,color,mode;
 {
 #asm
         MOV        BP,SP                ;Get pointer to arguments
         MOV        AX,6[BP]        ;y coord
         MOV        BX,8[BP]        ;x coord
         MOV     CX,2[BP]        ;Mode
 ;Determine which routine to execute using mode
 ;First check for Hercules
         CMP        CL,255
         JNE        SETP10
 ;
 ; Hercules mode
         CALL CALCPH
 SETP01:
         MOV        AL,4[BP]        ;Get color
         SHL        AX,CL                ;Shift in
         NOT        AH
         AND        ES:[BX],AH        ;Zero the pixel
         OR        ES:[BX],AL        ;Set it
         XOR        CX,CX                ;For small c
         RET
 ;
 SETP10:
         CMP        CL,6
         JGE        SETP20
 ;
 ;Modes 4 and 5
 ;
         CALL CALCP4
         JMP        SHORT SETP01        ;Borrow code
 ;
 SETP20:
         CMP        CL,13
         JGE        SETP30
 ;
 ;Mode 6
 ;
         CALL CALCP6
         JMP        SHORT SETP01        ;Borrow code
 ;
 SETP30:
         CMP        CL,14
         JGE        SETP40
 ;
 ;Mode 13
 ;
         CALL CALCP13
 SETP31:
         SHL        AH,CL                ;Position mask
         MOV        DX,3CEH                ;Address register port
         MOV        AL,8                ;Mask register number
         OUT        DX,AX
         MOV        AX,205H                ;Mode register number 2, write mode
         OUT        DX,AX
         MOV        AH,0                ;Replace mode
         MOV        AL,3                ;Data rotate/function select register
         OUT        DX,AX
         MOV        AL,ES:[BX]        ;Load the latches
         MOV        AL,4[BP]        ;Get the color
         MOV        ES:[BX],AL        ;Store it
         MOV        AX,0FF08H        ;Restore defaults
         OUT        DX,AX
         MOV        AX,5
         OUT        DX,AX
         MOV        AX,3
         OUT        DX,AX
         XOR        CX,CX
         RET
 ;
 SETP40:
         CMP        CL,17
         JGE        SETP50
 ;
 ; Modes 14,15,16
 ;
 SETP41:
         CALL CALCP14
         JMP        SHORT SETP31        ;Borrow code
 ;
 SETP50:
         CMP        CL,18
         JGE        SETP60
 ;
 ; Mode 17
 ;
         CALL CALCP14
         JMP SHORT SETP01        ;Borrow code
 ;
 SETP60:
         CMP        CL,18
         JZ        SETP41                        ;18 same as EGA
 ;
 ; Mode 19
 ;
         CALL CALCP19
         MOV        AL,4[BP]        ;Get color
         MOV        ES:[BX],AL        ;set it
         XOR        CX,CX                ;For small c
         RET
 ;
 ; Calculate pixel address for modes 4 and 5
 ; Entry: AX = y coord
 ;        BX = x coord
 ; Exit:  AH = bit mask
 ;        BX = byte offset
 ;        CL = number of bits to shift
         PUBLIC CALCP4
 CALCP4:
         MOV CL,BL
         XCHG AH,AL
         SHR AX,1
         ADD BH,AL
         XOR AL,AL
         ADD BX,AX
         SHR AX,1
         SHR AX,1
         ADD BX,AX
         SHR BX,1
         SHR BX,1
         MOV AH,3
         AND CL,AH
         XOR CL,AH
         SHL CL,1
         RET
 ;
 ; Calculate address of pixel for mode 6
 ; Entry: See abov
 ; Exit: See above
 ;
         PUBLIC CALCP6
 CALCP6:
         MOV CL,BL
         XCHG AH,AL
         SHR BX,1
         SHR AX,1
         ADD BH,AL
         XOR AL,AL
         ADD BX,AX
         SHR AX,1
         SHR AX,1
         ADD BX,AX
         SHR BX,1
         SHR BX,1
         AND CL,7
         XOR CL,7
         MOV AH,1
         RET
 ;
 ; Calculate pixel address for mode 13
 ; Entry: See above
 ; Exit: See above
 ;
         PUBLIC CALCP13
 CALCP13:
         MOV CL,BL
         MOV DX,40
 CP13COM:
         MUL DX
         SHR BX,1
         SHR BX,1
         SHR BX,1
         ADD BX,AX
         AND CL,7
         XOR CL,7
         MOV AH,1
         RET
 ;
 ; Calculate pixel address for modes 14,15,16,17,18
 ; Entry: See above
 ; Exit: See above
 ;
         PUBLIC CALCP14
 CALCP14:
         MOV CL,BL
         MOV DX,80
         JMP SHORT CP13COM
 ;
 ; Calculate pixel address for mode 19
 ; Entry: See above
 ; Exit: See above
 ; Note: we don't need a bit mask in AH or a shift count in CL
 ;       for this mode.
 ;
         PUBLIC CALCP19
 CALCP19:
         XCHG AH,AL
         ADD BX,AX
         SHR AX,1
         SHR AX,1
         ADD BX,AX
         RET
 ;
 ; Calculate pixel address for Hercules graphics mode
 ;
         PUBLIC CALCPH
 CALCPH:
         MOV        CL,BL
         SHR AX,1
         RCR BX,1
         SHR AX,1
         RCR BX,1
         SHR BX,1
         MOV AH,90
         MUL AH
         ADD BX,AX
         AND CL,7
         XOR CL,7
         MOV AH,1
         RET
 #endasm
 }

 /*
 ** getp(x,y,mode)
 ** Returns value of pixel at x,y
 ** mode holds current graphics mode
 */
 getp(x,y,mode)
 int x,y,mode; {
 #asm
         MOV BP,SP        ;Get pointer to arguments
         MOV CX,2[BP]        ;Get mode
         MOV AX,4[BP]        ;Get y coord
         MOV BX,6[BP]        ;Get x coord
 ;
         CMP        CL,255                ;Hercules mode selected by 255
         JNE        GETP10
 ;
 ; Hercules monochrome mode
 ;
         CALL CALCPH
 GETP01:
         MOV        BL,ES:[BX]
         SHR BL,CL
         AND BL,AH
         XOR BH,BH
         XOR CX,CX
         RET
 ;
 GETP10:
         CMP CL,6
         JGE GETP20
 ;
 ; Modes 4 and 5
 ;
         CALL CALCP4
         JMP SHORT GETP01        ;Borrow code
 ;
 GETP20:
         CMP CL,7
         JGE        GETP30
 ;
 ; Mode 6
 ;
         CALL CALCP6
         JMP SHORT GETP01        ;Borrow code
 ;
 GETP30:
         CMP        CL,14
         JGE        GETP40
 ;
 ; Mode 13
 ;
         CALL CALCP13
 GETP31:
         MOV CH,AH
         SHL CH,CL
         MOV SI,BX
         MOV DX,3CEH
         MOV AX,304H
         XOR BL,BL
 GETP32:
         OUT DX,AX
         MOV BH,ES:[SI]
         AND BH,CH
         NEG BH
         ROL BX,1
         DEC AH
         JGE GETP32
         XOR BH,BH
         XOR CX,CX
         RET
 ;
 GETP40:
         CMP        CL,15
         JNE GETP50
 ;
 ; Special for mode 15
 ;
         CALL CALCP14
         MOV CH,AH
         SHL CH,CL
         MOV SI,BX
         MOV DX,3CEH
         MOV AX,204H
         XOR BL,BL
 GETP41:
         OUT DX,AX
         MOV BH,ES:[SI]
         AND BH,CH
         NEG BH
         ROL BX,1
         SUB AH,2
         JGE GETP41
         XOR BH,BH
         XOR CX,CX
         RET
 ;
 GETP50:
         CMP        CL,17
         JGE        GETP60
 ;
 ; Modes 14 and 16
 ;
 GETP51:
         CALL CALCP14
         JMP GETP31                ;Borrow code
 ;
 GETP60:
         CMP        CL,18
         JZ        GETP51                ;Mode 18 same as EGA 14 and 16
 ;
 ; Mode 19
 ;
         CALL CALCP19
         MOV BL,ES:[BX]
         XOR        BH,BH
         XOR CX,CX
 #endasm
 }

 /*
 ** 8088/8086 version
 ** svmode(mode) int mode; {
 ** Set video mode.
 ** Mode is:
 ** 0 - 40 x 25 chars b&w (cga,ega,mcga,vga)
 ** 1 - 40 x 25 chars color (cga,ega,mcga,vga)
 ** 2 - 80 x 25 chars b&w (cga,ega,mcga,vga)
 ** 3 - 80 x 25 chars color (cga,ega,mcga,vga)
 ** 4 - 320 x 200 4-color graph (cga,ega,mcga,vga)
 ** 5 - 320 x 200 b&w graph (cga,ega,mcga,vga)
 ** 6 - 640 x 200 b&w graph (cga,ega,mcga,vga)
 ** 7 - 80 x 25 chars b&w (mda,ega,vga)
 ** 8 - 160 x 200 16-color graph (jr)
 ** 9 - 320 x 200 16-color graph (jr)
 ** 10 - 640 x 200 4-color graph (jr)
 ** 11 - reserved by EGA video BIOS
 ** 12 - reserved by EGA video BIOS
 ** 13 - 320 x 200 16-color graph (ega,vga)
 ** 14 - 640 x 200 16-color graph (ega,vga)
 ** 15 - 640 x 350 2-color graph (ega,vga)
 ** 16 - 640 x 350 4- or 16-color (ega,vga)
 ** 17 - 640 x 480 2-color (mcga,vga)
 ** 18 - 640 x 480 16-color (vga)
 ** 19 - 320 x 200 256-color (mcga,vga)
 ** 255 - Heculese 720x348 monochrome graphics
 */
 svmode(mode) int mode; {
 #asm
         MOV        BP,SP
         MOV        AX,2[BP]
         CMP        AX,255                ;Hercules?
         JZ        HERC
         PUSH        DS
         MOV        BX,40H                ;Video display data area
         MOV        DS,BX
         MOV        BL,32                ;Presence of CGA
         MOV        AX,2[BP]
         MOV        DL,AL
         AND        DL,7
         CMP        DL,7
         JNE        SVM1
         MOV        BL,48                ;Presence of MDA
 SVM1:        AND        BYTE PTR DS:[10H],11001111B
         OR        BYTE PTR DS:[10H],BL
         INT        10H        ;Set the mode
         POP        DS                ;Restore DS
         XOR        CX,CX        ;Clear for Small-C
         RET
 HERC:
 ;Update video bios data area
         MOV        AX,40H
         MOV        ES,AX
         MOV        DI,49H        ;ES:DI is video bios data area
         MOV        SI,OFFSET BDATA
         MOV        CX,BDLEN
         REP        MOVSB                ;Update video bios data
 ;Set config. switch
         MOV        DX,3BFH                ;Config switch port
         MOV        AL,1                ;Exclude second 32K of video buffer
         OUT        DX,AL
 ;Blank the screen
         MOV        DX,3B8H
         XOR        AL,AL
         OUT        DX,AL
 ;Program the CRTC
         SUB        DL,4                ;3b4H is addres reg port of CRTC
         MOV        SI,OFFSET CRTCP
         MOV        CX,9                ;9 parameters to load
 HERC1:        LODSW                        ;Al=crtc register number/AH=VALUE
         OUT        DX,AX
         LOOP        HERC1
 ;Set graphics mode
         ADD        DL,4
         MOV        AL,CRTMD
         OUT         DX,AL
 ;Clear the video buffer
         MOV        AX,0B000H
         MOV        ES,AX
         XOR        AX,AX                ;Clear to zero
         XOR        DI,DI
         MOV        CX,4000H
         REP        STOSW
         XOR        CX,CX                ;Clear for small c
         RET                        ;Go home
 ;Configurations stuff for Hercules
 CRTCP        DB        00H,35H                ;54 chars horizontal
         DB        01,2DH                ;45 displayed
         DB        02,2EH                ;Sync at 46th char
         DB        03,07H                ;Sync width 7 char clocks
         DB        4,5BH                ;Vert total of 92 characters
         DB        05,02H                ;Vert adjust of 2 scan lines
         DB        06,57H                ;Vert displayed of 87 char rows
         DB        07,57H                ;Vert. sync after 87th char row
         DB        09,03H                ;Max scan line, 4 scan lines per char
 BDATA        DB        7                ;CRT_MODE
         DW        80                ;CRT_COLS
         DW        8000H                ;CRT_LEN
         DW        0                ;CRT_START
         DW        8 DUP (0)        ;CURSOR_POSN
         DW        0                ;CURSOR_MODE
         DB        0                ;ACTIVE_PAGE
         DW        3B4H                ;ADDR_6845
 CRTMD        DB        0AH                ;CRT_MODE_SET
         DB        0                ;PALLETTE
 BDLEN        EQU        $-BDATA
 #endasm
 }

 /*
 ** 8088/8086 version
 ** gvmode(vlock) int vblock[3] ; { - Get current video mode
 ** Returns current video mode info
 ** vblock[0] = current video mode #
 ** vblock[1] = character columns on screen
 ** vblock[2] = current display page #
 */
 gvmode() {
 #asm
         MOV        AH,0FH
         INT        10H
         MOV        BP,SP
         MOV        SI,2[BP]        ;Pointer to tblock
         XOR        CH,CH                ;Clear hi part
         MOV        CL,AL
         MOV        [SI],CX                ;Mode #
         MOV        CL,AH
         MOV        2[SI],CX        ;Char columns on screen
         MOV        CL,BH
         MOV        4[SI],CX        ;Current display page
         XOR        CX,CX                ;Clear
 #endasm
 }


 VMSVT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\VMSVT.C

 /*
  *  Advanced VMS terminal driver
  *
  *  Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT
  *  located in SYS$SYSTEM.
  *
  *  Author:  Curtis Smith
  *  Last Updated: 07/14/87
  */

        <stdio.h>                /* Standard I/O package                */
        "estruct.h"                /* Emacs' structures                */
        "edef.h"                /* Emacs' definitions                */

 #if        VMSVT

         <descrip.h>                /* Descriptor definitions        */

 /*  These would normally come from iodef.h and ttdef.h  */
 IO$_SENSEMODE        0x27                /* Sense mode of terminal        */
 TT$_UNKNOWN        0x00                /* Unknown terminal                */

 /** Forward references **/
 int vmsopen(), ttclose(), vmskopen(), vmskclose(), ttgetc(), ttputc();
 int ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev();
 int vmscres();
 extern int eolexist, revexist;
 extern char sres[];

 #if COLOR
 int vmsfcol(), vmsbcol();
 #endif

 /** SMG stuff **/
 static char * begin_reverse, * end_reverse, * erase_to_end_line;
 static char * erase_whole_display;
 static int termtype;

 #define SMG$K_BEGIN_REVERSE                0x1bf
 #define SMG$K_END_REVERSE                0x1d6
 #define SMG$K_SET_CURSOR_ABS                0x23a
 #define SMG$K_ERASE_WHOLE_DISPLAY        0x1da
 #define SMG$K_ERASE_TO_END_LINE                0x1d9


 /* Dispatch table. All hard fields just point into the terminal I/O code. */
 TERM        term        = {
         24 - 1,                                /* Max number of rows allowabl
         /* Filled in */ - 1,                /* Current number of rows used
         132,                                /* Max number of columns        *
         /* Filled in */ 0,                /* Current number of columns
         64,                                /* Min margin for extended lines*/
         8,                                /* Size of scroll region        */
         100,                                /* # times thru update to pause *
         vmsopen,                        /* Open terminal at the start
         ttclose,                        /* Close terminal at end        */
         vmskopen,                        /* Open keyboard                */
         vmskclose,                        /* Close keyboard                */
         ttgetc,                                /* Get character from keyboard
         ttputc,                                /* Put character to display
         ttflush,                        /* Flush output buffers
         vmsmove,                        /* Move cursor, origin 0        */
         vmseeol,                        /* Erase to end of line
         vmseeop,                        /* Erase to end of page
         vmsbeep,                        /* Beep
         vmsrev,                                /* Set reverse video state
         vmscres                                /* Change screen resolution
 #if        COLOR
         , vmsfcol,                        /* Set forground color
         vmsbcol                                /* Set background color
 #endif
 };

 /***
  *  ttputs  -  Send a string to ttputc
  *
  *  Nothing returned
  ***/
 ttputs(string)
 char * string;                                /* String to write
 {
         if (string)
                 while (*string != '\0')
                         ttputc(*string++);
 }


 /***
  *  vmsmove  -  Move the cursor (0 origin)
  *
  *  Nothing returned
  ***/
 vmsmove(row, col)
 int row;                                /* Row position
 int col;                                /* Column position                */
 {
         char buffer[32];
         int ret_length;
         static int request_code = SMG$K_SET_CURSOR_ABS;
         static int max_buffer_length = sizeof(buffer);
         static int arg_list[3] = { 2 };
         register char * cp;

         register int i;

         /* Set the arguments into the arg_list array
          * SMG assumes the row/column positions are 1 based (boo!)
          */
         arg_list[1] = row + 1;
         arg_list[2] = col + 1;

         if ((smg$get_term_data(                /* Get terminal data
                 &termtype,                /* Terminal table address        */
                 &request_code,                /* Request code
                 &max_buffer_length,        /* Maximum buffer length        */
                 &ret_length,                /* Return length                *
                 buffer,                        /* Capability data buffer
                 arg_list)                /* Argument list array

         /* We'll know soon enough if this doesn't work                */
                         & 1) == 0) {
                                 ttputs("OOPS");
                                 return;
                         }

         /* Send out resulting sequence                                */
         i = ret_length;
         cp = buffer;
         while (i-- > 0)
                 ttputc(*cp++);
 }


 /***
  *  vmsrev  -  Set the reverse video status
  *
  *  Nothing returned
  ***/
 vmsrev(status)
 int status;                                /* TRUE if setting reverse
 {
         if (status)
                 ttputs(begin_reverse);
         else
                 ttputs(end_reverse);
 }

 /***
  *  vmscres  -  Change screen resolution (which it doesn't)
  *
  *  Nothing returned
  ***/
 vmscres()
 {
         /* But it could.  For vt100/vt200s, one could switch from
         80 and 132 columns modes */
 }


 #if        COLOR
 /***
  *  vmsfcol  -  Set the forground color (not implimented)
  *
  *  Nothing returned
  ***/
 vmsfcol()
 {
 }

 /***
  *  vmsbcol  -  Set the background color (not implimented)
  *
  *  Nothing returned
  ***/
 vmsbcol()
 {
 }
 #endif

 /***
  *  vmseeol  -  Erase to end of line
  *
  *  Nothing returned
  ***/
 vmseeol()
 {
         ttputs(erase_to_end_line);
 }


 /***
  *  vmseeop  -  Erase to end of page (clear screen)
  *
  *  Nothing returned
  ***/
 vmseeop()
 {
         ttputs(erase_whole_display);
 }


 /***
  *  vmsbeep  -  Ring the bell
  *
  *  Nothing returned
  ***/
 vmsbeep()
 {
         ttputc('\007');
 }


 /***
  *  vmsgetstr  -  Get an SMG string capability by name
  *
  *  Returns:        Escape sequence
  *                NULL        No escape sequence available
  ***/
 char * vmsgetstr(request_code)
 int request_code;                        /* Request code
 {
         register char * result;
         static char seq_storage[1024];
         static char * buffer = seq_storage;
         static int arg_list[2] = { 1, 1 };
         int max_buffer_length, ret_length;

         /*  Precompute buffer length */

         max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer;

         /* Get terminal commands sequence from master table */

         if ((smg$get_term_data(        /* Get terminal data                */
                 &termtype,        /* Terminal table address        */
                 &request_code,        /* Request code
                 &max_buffer_length,/* Maximum buffer length        */
                 &ret_length,        /* Return length                */
                 buffer,                /* Capability data buffer        */
                 arg_list)        /* Argument list array                */

         /* If this doesn't work, try again with no arguments */

                 & 1) == 0 &&

                 (smg$get_term_data(        /* Get terminal data
                         &termtype,        /* Terminal table address        */
                         &request_code,        /* Request code
                         &max_buffer_length,/* Maximum buffer length        */
                         &ret_length,        /* Return length                *
                         buffer)                /* Capability data buffer

         /* Return NULL pointer if capability is not available */

                         & 1) == 0)
                                 return NULL;

         /* Check for empty result */
         if (ret_length == 0)
                 return NULL;

         /* Save current position so we can return it to caller */

         result = buffer;

         /* NIL terminate the sequence for return */

         buffer[ret_length] = 0;

         /* Advance buffer */

         buffer += ret_length + 1;

         /* Return capability to user */
         return result;
 }


 /** I/O information block definitions **/
 struct iosb {                        /* I/O status block
         short        i_cond;                /* Condition value
         short        i_xfer;                /* Transfer count
         long        i_info;                /* Device information
 };
 struct termchar {                /* Terminal characteristics                *
         char        t_class;        /* Terminal class
         char        t_type;                /* Terminal type
         short        t_width;        /* Terminal width in characters
         long        t_mandl;        /* Terminal's mode and length
         long        t_extend;        /* Extended terminal characteristics
 };
 static struct termchar tc;        /* Terminal characteristics

 /***
  *  vmsgtty - Get terminal type from system control block
  *
  *  Nothing returned
  ***/
 vmsgtty()
 {
         short fd;
         int status;
         struct iosb iostatus;
         $DESCRIPTOR(devnam, "SYS$INPUT");

         /* Assign input to a channel */
         status = sys$assign(&devnam, &fd, 0, 0);
         if ((status & 1) == 0)
                 exit (status);

         /* Get terminal characteristics */
         status = sys$qiow(                /* Queue and wait                */
                 0,                        /* Wait on event flag zero        *
                 fd,                        /* Channel to input terminal
                 IO$_SENSEMODE,                /* Get current characteristic
                 &iostatus,                /* Status after operation        */
                 0, 0,                        /* No AST service
                 &tc,                        /* Terminal characteristics buf *
                 sizeof(tc),                /* Size of the buffer
                 0, 0, 0, 0);                /* P3-P6 unused

         /* De-assign the input device */
         if ((sys$dassgn(fd) & 1) == 0)
                 exit(status);

         /* Jump out if bad status */
         if ((status & 1) == 0)
                 exit(status);
         if ((iostatus.i_cond & 1) == 0)
                 exit(iostatus.i_cond);
 }


 /***
  *  vmsopen  -  Get terminal type and open terminal
  *
  *  Nothing returned
  ***/
 vmsopen()
 {
         /* Get terminal type */
         vmsgtty();
         if (tc.t_type == TT$_UNKNOWN) {
                 printf("Terminal type is unknown!\n");
                 printf("Try set your terminal type with SET TERMINAL/INQUIRE\
                 printf("Or get help on SET TERMINAL/DEVICE_TYPE\n");
                 exit(3);
         }

         /* Access the system terminal definition table for the
         /* information of the terminal type returned by IO$_SENSEMODE
         if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0)
                 return -1;

         /* Set sizes */
         term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1;
         term.t_ncol = tc.t_width;

         /* Get some capabilities */
         begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE);
         end_reverse = vmsgetstr(SMG$K_END_REVERSE);
         revexist = begin_reverse != NULL && end_reverse != NULL;
         erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE);
         eolexist = erase_whole_display != NULL;
         erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY);

         /* Set resolution */
         strcpy(sres, "NORMAL");

         /* Open terminal I/O drivers */
         ttopen();
 }


 /***
  *  vmskopen  -  Open keyboard (not used)
  *
  *  Nothing returned
  ***/
 vmskopen()
 {
 }


 /***
  *  vmskclose  -  Close keyboard (not used)
  *
  *  Nothing returned
  ***/
 vmskclose()
 {
 }


 /***
  *  fnclabel  -  Label function keys (not used)
  *
  *  Nothing returned
  ***/
 #if        FLABEL
 fnclabel(f, n)                /* label a function key */
 int f,n;        /* default flag, numeric argument [unused] */
 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif


 /***
  *  spal  -  Set palette type  (Are you kidding?)
  *
  *  Nothing returned
  ***/
 spal()
 {
 }

 #else

 /***
  *  hellovms  -  Avoid error because of empty module
  *
  *  Nothing returned
  ***/
 hellovms()
 {
 }

 #endif


 VT100.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\VT100TST\VT100.C

 /*
 Having received many requests for my terminal emulator for the IBM PC,
 here it is. It is written in C for the DeSmet C compiler, with assembler
 for all the I/O routines. DeSmet's I/O library is big as a bus, and slow
 to boot, so I simply avoid it. This program does very little, reasonably
 well. New functions are easy to add. For folks with other compilers,
 the only part likely to fail to work is the assembler for I/O: I put it
 in-stream, using the "#asm" construct for in-stream assembler. You will
 need to edit all assembler into an external assembler file, and invent
 headers and trailers to implement the C calling convention for your compiler.
 This program hasn't been prettied up for public consumption, but I am
 painfully busy with other things, so in the hope that this is better
 than nothing, here it is:

 >From this to the next line of dashes is the document file for the program: *
 /*---------------------------------------------------------------------------



                  Comm: a communication program for the IBM-PC

 Comm is a minimal dumb terminal emulator for the IBM-PC under PC-DOS.  It  us
 BIOS  function calls for keyboard input,  allowing all control characters to
 sent with the conventional keyboard sequences. It uses an interrupt handler f
 the communication port,  functional up to 9600 baud.  It is written in  C  wi
 assembler routines to handle I/O. It only supports the first asynchronous por
 COM1:.  It doesn't support setting the communication parameters.  This  can
 done with the DOS "mode" command. The port IS NOT DISABLED (DTR is not droppe
 when the program is terminated; you must disconnect from the remote computer
 some other fashion.  As a result, however, you can exit to DOS, make use of a
 DOS commands which don't tinker with the communication  port,  and  resume  t
 terminal  session,  without any disruption visible at the other end (characte
 sent to the PC will be lost in the interim).  Best of  all,  it  is  small.
 supports very few commands, all of which are alt sequences:

 alt-e is a toggle:  it turns echoing on and off (default off). This can be us
       for half-duplex systems.

 alt-v is a toggle:  it turns verbose mode on and off (default off).  In verbo
       mode  characters  which  are  normally non-printable and aren't "carria
       control" characters print as "^x",  where "x" is the character you  wou
       hit to send the control character. Otherwise such chaff is ignored.

 alt-b sends a break (approx. 300 ms. of line high)

 alt-q quits the program, and returns to DOS
 -----------------------------------------------------------------------------
 The program follows:
 NOTE: this code is indented using tabs set every 4 columns, not 8.
 -----------------------------------------------------------------------------
 /*
  * Rudimentary communication program; written in C with I/O
  * routines in assembler, using "#asm" construct in DeSmet C.
  */

 #define TRUE 1
 #define FALSE 0
 #define NULL 0

 #define comm_stat head!=tail

 int head=0,
         tail=0;

 char comm_buffer[8192];

 main()
 {
         char commget();

         int c,
                 echo=FALSE,
                 verbose=FALSE;

         initcomm();

         goto inside;
         while((c=my_ci())<256) /* alt's and function keys are >=256 */
         {
                 commput(c);
                 if(echo)
                         my_co(c);
 inside:        while(my_stat()==0)
                         if(comm_stat)
                                 if(is_nice(c=commget()))
                                         my_co(c);
                                 else
                                         if(verbose)
                                         {
                                                 my_co('^');
                                                 my_co(127&(c+'@'));
                                         }
         }
         switch(c>>8) /* process function key */
         {
                 case '\060': /* b        send break        */
                         make_break();
                         my_puts("** break **\n");
                         break;
                 case '\022': /* e        echo toggle        */
                         echo = !echo;
                         if(echo)
                                 my_puts("** echo on **\n");
                         else
                                 my_puts("** echo off **\n");
                         break;
                 case '\020': /* q        quit                */
                         my_puts("** returning to DOS **\n");
                         goto byebye;
                 case '\057': /* v        verbose                */
                         verbose = !verbose;
                         if(verbose)
                                 my_puts("** verbose on **\n");
                         else
                                 my_puts("** verbose off **\n");
                         break;
         }
         goto inside;

 byebye:
         killcomm();
 }

 initcomm()
 {
 #asm

 ; initialize communication port,
 ; and install interrupt handler

 ; save dseg for interrupt handler
         mov                ax,ds
         mov                cs:dssave,ax

 ; set int vector to my handler
         push        ds
         xor                ax,ax
         mov                ds,ax
         mov                [30h],offset handler
         mov                ax,cs
         mov                [32h],ax
         pop                ds

 ; assert DTR, RTS, and OUT2
         mov                dx,3fch
         mov                al,11
         out                dx,al

 ; enable interrupts for data ready
         mov                dx,3f9h
         mov                al,1
         out                dx,al

 ; clear any outstanding int
         mov                dx,3f8h
         in                al,dx

 ; enable interrupts
         sti

 ; enable IRQ4 on 8259A
         in                al,21h
         and                al,0efh
         out                21h,al

 ; and return
         jmp                init_finis

 dssave:        dw 0

 handler:
         push        ds
         push        ax
         push        dx
         push        bx

 ; restore appropriate dseg
         mov                ax,cs:dssave
         mov                ds,ax

 ; grab the byte from comm port
         mov                dx,3f8h
         in                al,dx

 ; put it in the buffer
         mov                bx,tail_
         mov                comm_buffer_[bx],al

 ; tail=tail+1 (mod 8192)
         inc                bx
         cmp                bx,8192
         jl                handler_around
         xor                bx,bx

 handler_around:
         mov                tail_,bx

 ; tell the 8259A EOI
         mov                dx,20h
         mov                al,32
         out                dx,al

         pop                bx
         pop                dx
         pop                ax
         pop                ds

 ; reenable interrupts
         sti

         iret

 init_finis:
 #
 }

 commput(c)
 int c;
 {
 #asm
 ; put the character out the port
         mov                dx,3f8h
         mov                ax,[bp+4]
         out                dx,al
 #
 }

 char commget()
 {
         char temp;

                 temp=comm_buffer[head++];
                 head%=8192;
                 return(temp);
 }

 killcomm()
 {
 #asm
 ; disconnect the interrupt handler
         in                al,21h
         or                al,10h
         out                21h,al
 #
 }

 make_break()
 {
 #asm
 ; set bit on LCR
         mov                dx,3fbh
         in                al,dx
         push        ax
         or                al,40h
         out                dx,al

 ; wait a wee bit (~200 ms)
         mov                bx,8
 outer:
         mov                cx,7000
 tight:
         loop        tight
         dec                bx
         jnz                outer

 ; and turn break back off
         pop                ax
         out                dx,al
 #
 }

 is_nice(c) /* true for those characters that "should" be received */
 char c;
 {
         c&=127;
         if(c>=' ' && c<='~')        /* printable */
                 return(TRUE);
         if(c>6 && c<11)                        /* BEL, BS, HT, LF */
                 return(TRUE);
         if(c==13 || c==27)                /* CR, ESC */
                 return(TRUE);
         return(FALSE);
 }

 my_puts(s) /* puts, using my_co() */
 char *s;
 {
         while(*s)
         {
                 if(*s=='\n')
                         my_co('\r');
                 my_co(*(s++));
         }
 }

 my_co(c) /* character output, smaller and faster than DeSmet's,
                         using DOS function call 2.00 */
 char c;
 {
 #asm
         mov                ah,2
         mov                dx,[bp+4]
         int                21h
 #
 }

 my_stat() /* true if character is ready from keyboard */
 {
 #asm
         mov                ah,1
         int                16h
         jz                stat_no_char
         mov                ax,1
         jmp                stat_finis

 stat_no_char:
         xor                ax,ax

 stat_finis:
 #
 }

 my_ci() /* get character from keyboard, using BIOS function call */
 {
 #asm
         xor                ah,ah
         int                16h
         or                al,al
         jz                my_ci_finis
         xor                ah,ah

 my_ci_finis:
 #
 }
 -----------------------------------------------------------------------------
 The termcap for DOS 2.00 with ansi device driver follows:
 -----------------------------------------------------------------------------
 pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\
         :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
         :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
         :pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt:
 pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\
         :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
         :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
         :pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt:
 -----------------------------------------------------------------------------
 and that's it! Enjoy. I place this in the public domain, and would appreciate
 feedback. Improvements and bug reports especially desired. If the code is too
 cryptic or uncommented, feel free to send questions to:
                                         Bennett Todd
                                         ...{decvax,ihnp4,akgua}!mcnc!ecsvax!b




 VT100TST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\VT100TST\VT100TST.C

 /*
 This program is supposed to test the compatibility of VT100-compatible
 terminals. However: it's also a nice demo of the capabilities of a VT100.
 The author is not on the net but I will forward comments and ideas of
 enhancements to him. What other VT100 functions should be tested?

 The program was written under TOPS-10 so the author is probably not very
 interested in enhancements pertaining to UN*X.
 The responsibility for distributing this program is mine, the author has
 only given his consent.

     {decvax,philabs}!mcvax!enea!ttds!johanw

 Cut at this line
 =========================================================================*/
 /*
                                VTTEST.C

                 Written nov-dec 1983 by Per Lindberg,
           Stockholm University Computer Center (QZ), Sweden.

                   THE MAD PROGRAMMER STRIKES AGAIN!

 This is a program to test the compatibility (or to demonstrate the
 non-compatibility) of so-called "VT100-compatible" terminals. In
 conformance of the good old hacker traditions, the only documentation
 of this program is the source code itself. To understand it, you also
 need a copy of the original VT100 manual from DEC.

 This program is not nearly finished yet, it only tests about half
 of what it should. And there is neither any support for all the
 different variations of VT100, like VT125, VT131 or the new VT200
 series. I might fix that someday, but in the meantime, feel free to
 snarf my program and hack it up.

 The original version of this program was (and is still) written in a
 losing implementation of C, the John Hopkins University portable JHU
 C, as installed on the DECsystem-10 under TOPS-10. It is not a full
 implementation of C (as defined in "the C programming language" by
 Kernighan & Ritchie). One of its worst cretinisms is that identifiers
 are only significant to the first five characters. I hope to get a
 better C compiler for the DEC-10 soon.

 */

 #include <stdio.h>


 char *getlin(str)
 char *str;
 {
         static char buf[100];
         printf("%s", str);
         return(gets(buf));
 }

 main () {


 #define vt100 1
 #define vt102 2

     int     vttype;

     vttype = inittype ();
     tst_movements ();
     tst_screen ();
     tst_characters ();
     tst_doublesize ();
     tst_reports ();
     tst_vt52 ();
     bye ();
 }

 tst_movements () {

  /* Test of: CUF (Cursor Forward) CUB (Cursor Backward) CUD (Cursor Down)
     Up)        RI  (Reverse Index) CUP (Cursor Position)  HVP (Horizontal and
     EL  (Erase in Line) PCALN (Screen Alignment Display) <CR> <BS> */

     int     row, col;

 /*  pcaln();  */
     ed (2);
     pcaln ();
     cup (9, 10);
     ed (1);
     cup (18, 60);
     ed (0);
     el (1);
     cup (9, 71);
     el (0);
     for (row = 10; row <= 16; row++) {
         cup (row, 10);
         el (1);
         cup (row, 71);
         el (0);
     }
     cup (17, 30);
     el (2);
     for (col = 1; col <= 80; col++) {
         hvp (24, col);
         printf ("*");
         hvp (1, col);
         printf ("*");
     }
     cup (2, 2);
     for (row = 2; row <= 23; row++) {
         printf ("+");
         cub (1);
         ind ();
     }
     cup (23, 79);
     for (row = 23; row >= 2; row--) {
         printf ("+");
         cub (1);
         ri ();
     }
     cup (2, 1);
     for (row = 2; row <= 23; row++) {
         printf ("*");
         cup (row, 80);
         printf ("*");
         cub (10);
         if (row < 10)
             nel ();
         else
             printf ("\n");
     }
     cup (2, 10);
     cub (42);
     cuf (2);
     for (col = 3; col <= 78; col++) {
         printf ("+");
         cuf (0);
         cub (2);
         cuf (1);
     }
     cup (23, 70);
     cuf (42);
     cub (2);
     for (col = 78; col >= 3; col--) {
         printf ("+");
         cub (1);
         cuf (1);
         cub (0);
         printf ("%c", 8);
     }
     cup (1, 1);
     cuu (10);
     cuu (1);
     cuu (0);
     cup (24, 80);
     cud (10);
     cud (1);
     cud (0);

     cup (10, 12);
     for (row = 10; row <= 15; row++) {
         for (col = 12; col <= 69; col++)
             printf (" ");
         cud (1);
         cub (58);
     }
     cuu (5);
     cuf (1);
     printf ("The screen should be cleared, and have a unbroken border");
     cup (12, 13);
     printf ("of *'s and +'s around the edge, and exactly in the");
     cup (13, 13);
     printf ("middle there should be a frame of E's around this text");
     cup (14, 13);
     printf ("with one (1) free position around it. Now, push <RETURN>");
     getlin ("");
 }

 tst_screen () {

  /* Test of: - PCSTBM (Set Top and Bottom Margins) - TBC    (Tabulation Clear
     SM RM  (Set/Reset mode): - 80/132 chars - Origin: Realtive/absolute - Scr

     int     i, row, col, down, soft;

     ed (2);
     sm ("?7");                                                /* Wrap Around
     cup (1, 1);
     for (col = 1; col <= 160; col++)
         printf ("*");
     rm ("?7");                                                /* Wrap Around
     cup (3, 1);
     for (col = 1; col <= 160; col++)
         printf ("*");
     sm ("?7");                                                /* Wrap Around
     cup (5, 1);
     printf ("This should be three identical lines of *'s completely filling\n
     printf ("the top of the screen without any empty lines between.\n");
     getlin ("Push <RETURN>");

     ed (2);
     cup (1, 1);
     for (col = 1; col <= 79; col++)
         printf ("+");
     for (row = 1; row <= 24; row++) {
         hvp (row, 80);
         printf ("*");
     }
     cup (10, 10);
     printf ("This illustrates the \"wrap around bug\" which exists on a");
     cup (11, 10);
     printf ("standard VT100. On the top of the screen there should be");
     cup (12, 10);
     printf ("a row of +'s, and the rightmost column should be filled");
     cup (13, 10);
     printf ("with *'s. But if the bug is present, some of the *'s may");
     cup (14, 10);
     printf ("be placed in other places, e.g. in the leftmost column,");
     cup (15, 10);
     printf ("and the top line of +'s may be scrolled away.");
     cup (17, 10);
     printf ("Of course, a good VT100-compatible terminal should have");
     cup (18, 10);
     printf ("means of shutting this bug off (if it has it at all!)");
     cup (20, 10);
     getlin ("Push <RETURN>");

     ed (2);
     tbc (3);
     cup (1, 1);
     for (col = 1; col <= 78; col + = 3) {
         cuf (3);
         hts ();
     }
     cup (1, 4);
     for (col = 4; col <= 78; col + = 6) {
         tbc (0);
         cuf (6);
     }
     cup (1, 7);
     tbc (1);
     tbc (2);                                                /* no-op */
     cup (1, 1);
     for (col = 1; col <= 78; col + = 6)
         printf ("\t*");
     cup (2, 2);
     for (col = 2; col <= 78; col + = 6)
         printf ("     *");
     cup (4, 1);
     getlin ("These two lines should look the same. Push <RETURN>");
     sm ("?3");                                                /* 132 cols */
     ed (2);                                                /* VT100 clears sc
     cup (1, 1);
     tbc (3);
     for (col = 1; col <= 132; col + = 8) {
         cuf (8);
         hts ();
     }
     cup (1, 1);
     for (col = 1; col <= 130; col + = 10)
         printf ("1234567890");
     printf ("12");
     cup (3, 1);
     getlin ("This is 132 column mode. Push <RETURN>");
     rm ("?3");                                                /* 80 cols */
     ed (2);                                                /* VT100 clears sc
     cup (1, 1);
     for (col = 1; col <= 80; col + = 10)
         printf ("1234567890");
     cup (3, 1);
     getlin ("This is 80 column mode. Push <RETURN>");
     ed (2);
     sm ("?6");                                                /* Origin mode
     for (soft = -1; soft <= 0; soft++) {
         if (soft)
             sm ("?4");
         else
             rm ("?4");
         for (row = 12; row >= 1; row - = 11) {
             pcstbm (row, 24 - row + 1);
             ed (2);
             for (down = 0; down >= -1; down--) {
                 if (down)
                     cuu (24);
                 else
                     cud (24);
                 for (i = 1; i <= 30; i++) {
                     printf ("%s scroll %s region %d Line %d\n",
                             soft ? "Soft" : "Jump",
                             down ? "down" : "up",
                             2 * (13 - row), i);
                     if (down) {
                         ri ();
                         ri ();
                     }
                 }
             }
             getlin ("Push <RETURN>");
         }
     }
     ed (2);
     pcstbm (23, 24);
     printf ("\nThis line should be at the bottom of the screen.");
     cup (1, 1);
     printf ("This line should be the one above the bottom of the screeen.");
     getlin (" Push <RETURN>");
     ed (2);
     rm ("?6");                                                /* Origin mode
     cup (24, 1);
     printf ("This line should be at the bottom of the screen.");
     cup (1, 1);
     printf ("This line should be at the top of the screen.");
     getlin (" Push <RETURN>");
     pcstbm (1, 24);
 }

 tst_characters () {
                                                         /* Test of: PCLL   (L
                                                            SGR    (Select Gra
                                                            Inverse PCSC   (Sa

     int     i, j, g, cset;
     char   *tststr, chcode[5], *setmsg[5], *ledmsg[6], *ledseq[6], *attr[5];

     tststr = "*qx`";

     chcode[0] = 'A';
     chcode[1] = 'B';
     chcode[2] = '0';
     chcode[3] = '1';
     chcode[4] = '2';
     setmsg[0] = "UK / national (character set A)";
     setmsg[1] = "US ASCII (B)";
     setmsg[2] = "Special graphics and line drawing (0)";
     setmsg[3] = "Alternate character ROM standard characters (1)";
     setmsg[4] = "Alternate character ROM special graphics (2)";

     ledmsg[0] = "L1 L2 L3 L4";
     ledseq[0] = "1;2;3;4";
     ledmsg[1] = "   L2 L3 L4";
     ledseq[1] = "1;0;4;3;2";
     ledmsg[2] = "   L2 L3";
     ledseq[2] = "1;4;;2;3";
     ledmsg[3] = "L1 L2";
     ledseq[3] = ";;2;1";
     ledmsg[4] = "L1";
     ledseq[4] = "1";
     ledmsg[5] = "";
     ledseq[5] = "";

     attr[0] = ";0";
     attr[1] = ";1";
     attr[2] = ";4";
     attr[3] = ";5";
     attr[4] = ";7";

     ed (2);
     cup (10, 1);
     printf ("These LEDs (\"lamps\") on the keyboard should be on:");
     for (i = 0; i <= 5; i++) {
         cup (10, 52);
         el (0);
         printf (ledmsg[i]);
         pcll ("0");
         pcll (ledseq[i]);
         cup (12, 1);
         getlin ("Push <RETURN>");
     }
     ed (2);
     cup (1, 10);
     printf ("Selected as G0 (with SI)");
     cup (1, 48);
     printf ("Selected as G1 (with SO)");
     for (cset = 0; cset <= 4; cset++) {
         scs (1, 'B');
         cup (3 + 4 * cset);
         sgr ("1");
         printf (setmsg[cset]);
         sgr ("0");
         for (g = 0; g <= 1; g++) {
             scs (g, chcode[cset]);
             for (i = 1; i <= 3; i++) {
                 cup (3 + 4 * cset + i, 10 + 38 * g);
                 for (j = 0; j <= 31; j++) {
                     printf ("%c", i * 32 + j);
                 }
             }
         }
     }
     scs (1, 'B');
     cup (24, 1);
     getlin ("These are the installed character sets. Push <RETURN>");

     ed (2);
     cup (1, 20);
     printf ("Graphic rendition test pattern:");
     cup (4, 1);
     sgr ("0");
     printf ("vanilla");
     cup (4, 40);
     sgr ("0;1");
     printf ("bold");
     cup (6, 6);
     sgr (";4");
     printf ("underline");
     cup (6, 45);
     sgr (";1");
     sgr ("4");
     printf ("bold underline");
     cup (8, 1);
     sgr ("0;5");
     printf ("blink");
     cup (8, 40);
     sgr ("0;5;1");
     printf ("bold blink");
     cup (10, 6);
     sgr ("0;4;5");
     printf ("underline blink");
     cup (10, 45);
     sgr ("0;1;4;5");
     printf ("bold underline blink");
     cup (12, 1);
     sgr ("1;4;5;0;7");
     printf ("negative");
     cup (12, 40);
     sgr ("0;1;7");
     printf ("bold negative");
     cup (14, 6);
     sgr ("0;4;7");
     printf ("underline negative");
     cup (14, 45);
     sgr ("0;1;4;7");
     printf ("bold underline negative");
     cup (16, 1);
     sgr ("1;4;;5;7");
     printf ("blink negative");
     cup (16, 40);
     sgr ("0;1;5;7");
     printf ("bold blink negative");
     cup (18, 6);
     sgr ("0;4;5;7");
     printf ("underline blink negative");
     cup (18, 45);
     sgr ("0;1;4;5;7");
     printf ("bold underline blink negative");
     sgr ("");

     rm ("?5");                                                /* Inverse vide
     cup (23, 1);
     el (0);
     getlin ("Black background. Push <RETURN>");
     sm ("?5");                                                /* Inverse vide
     cup (23, 1);
     el (0);
     getlin ("Inverse video. Push <RETURN>");
     rm ("?5");
     ed (2);
     cup (8, 12);
     printf ("normal");
     cup (8, 24);
     printf ("bold");
     cup (8, 36);
     printf ("underscored");
     cup (8, 48);
     printf ("blinking");
     cup (8, 60);
     printf ("reversed");
     cup (10, 1);
     printf ("stars:");
     cup (12, 1);
     printf ("line:");
     cup (14, 1);
     printf ("x'es:");
     cup (16, 1);
     printf ("diamonds:");
     for (cset = 0; cset <= 3; cset++) {
         for (i = 0; i <= 4; i++) {
             cup (10 + 2 * cset, 12 + 12 * i);
             sgr (attr[i]);
             if (cset == 0 || cset == 2)
                 scs (0, 'B');
             else
                 scs (0, '0');
             for (j = 0; j <= 4; j++) {
                 printf ("%c", tststr[cset]);
             }
             pcsc ();
             cup (cset + 1, i + 1);
             sgr ("");
             scs (0, 'B');
             printf ("A");
             pcrc ();
             for (j = 0; j <= 4; j++) {
                 printf ("%c", tststr[cset]);
             }
         }
     }
     sgr ("0");
     scs (0, 'B');
     cup (22, 1);
     printf ("There should be 10 characters of each flavour, and a rectangle\n
     getlin ("of 5 x 4 A's filling the top left of the screen. Push <RETURN>")
 }

 tst_doublesize () {
                                                         /* Test of: PCSWL  (S
                                                            Line) PCDHL  (Doub
                                                            width) */

     int     i, w, w1;

  /* Print the test pattern in both 80 and 132 character width  */

     for (w = 0; w <= 1; w++) {
         w1 = 13 * w;

         ed (2);
         cup (1, 1);
         if (w) {
             sm ("?3");
             printf ("132 column mode");
         }
         else {
             rm ("?3");
             printf (" 80 column mode");
         }

         cup (5, 3 + 2 * w1);
         printf ("v------- left margin");

         cup (7, 3 + 2 * w1);
         printf ("This is a normal-sized line");
         pcdhl (0);
         pcdhl (1);
         pcdwl ();
         pcswl ();

         cup (9, 2 + w1);
         printf ("This is a Double-width line");
         pcswl ();
         pcdhl (0);
         pcdhl (1);
         pcdwl ();

         cup (11, 2 + w1);
         pcdwl ();
         pcswl ();
         pcdhl (1);
         pcdhl (0);
         printf ("This is a Double-width-and-height line");
         cup (12, 2 + w1);
         pcdwl ();
         pcswl ();
         pcdhl (0);
         pcdhl (1);
         printf ("This is a Double-width-and-height line");

         cup (14, 2 + w1);
         pcdwl ();
         pcswl ();
         pcdhl (1);
         pcdhl (0);
         el (2);
         printf ("This is another such line");
         cup (15, 2 + w1);
         pcdwl ();
         pcswl ();
         pcdhl (0);
         pcdhl (1);
         printf ("This is another such line");

         cup (17, 3 + 2 * w1);
         printf ("^------- left margin");

         cup (21, 1);
         printf ("This is not a double-width line");
         for (i = 0; i <= 1; i++) {
             cup (21, 6);
             if (i) {
                 printf ("**is**");
                 pcdwl ();
             }
             else {
                 printf ("is not");
                 pcswl ();
             }
             cup (23, 1);
             getlin ("Push <RETURN>");
         }
     }

     rm ("?3");
     ed (2);

     scs (0, '0');
     cup (8, 1);
     pcdhl (0);
     printf ("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
     cup (9, 1);
     pcdhl (1);
     printf ("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
     cup (10, 1);
     pcdhl (0);
     printf ("x                                   x");
     cup (11, 1);
     pcdhl (1);
     printf ("x                                   x");
     cup (12, 1);
     pcdhl (0);
     printf ("x                                   x");
     cup (13, 1);
     pcdhl (1);
     printf ("x                                   x");
     cup (14, 1);
     pcdhl (0);
     printf ("x                                   x");
     cup (15, 1);
     pcdhl (1);
     printf ("x                                   x");
     cup (16, 1);
     pcdhl (0);
     printf ("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
     cup (17, 1);
     pcdhl (1);
     printf ("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
     scs (0, 'B');
     sgr ("1;5");
     cup (12, 3);
     printf ("The mad programmer strikes again!");
     cup (13, 3);
     printf ("The mad programmer strikes again!");
     sgr ("0");
     cup (22, 1);
     printf ("Another test pattern...  a frame with blinking bold text,\n");
     getlin ("all in double-height double-width size.  Push <RETURN>");

  /* the FACIT 4431 has a bug when you scroll    */
                                                         /* down doublesized t

     pcstbm (8, 24);
     cup (8, 1);                                                /* We are in a
     for (i = 1; i <= 12; i++)
         ri ();
     cup (1, 1);
     getlin ("Exactly half of the box should remain. Push <RETURN>");
 }

 tst_reports () {
                                                         /* Test of: <ENQ> (An
                                                            - LineFeed / Newli
     ;
 }

 tst_vt52 () {
                                                         /* Test of: SM RM  (S
     ;
 }

 esc (s) char   *s; {
     printf ("%c%s", 27, s);
 }

 esc2 (s1, s2) char  s1, s2; {
     printf ("%c%s%s", 27, s1, s2);
 }

 brcstr (ps, c) char *ps, c; {
     printf ("%c[%s%c", 27, ps, c);
 }

 brc (pn, c) int pn;
 char    c; {
     char   *str, *ptr;
     ptr = str = "[    ";
     ptr++;
     if (pn > 99) {
         *ptr++ = (pn / 100) + 48;
         pn % = 100;
     }
     if (pn > 9) {
         *ptr++ = (pn / 10) + 48;
         pn % = 10;
     }
     *ptr++ = pn + 48;
     *ptr++ = c;
     *ptr = '\0';
     printf ("%c%s", 27, str);
 }

 brc2 (pn1, pn2, c) int  pn1, pn2;
 char    c; {
     char   *str, *ptr;
     ptr = str = "[        ";
     ptr++;
     if (pn1 > 99) {
         *ptr++ = (pn1 / 100) + 48;
         pn1 % = 100;
     }
     if (pn1 > 9) {
         *ptr++ = (pn1 / 10) + 48;
         pn1 % = 10;
     }
     *ptr++ = pn1 + 48;
     *ptr++ = ';';
     if (pn2 > 99) {
         *ptr++ = (pn2 / 100) + 48;
         pn2 % = 100;
     }
     if (pn2 > 9) {
         *ptr++ = (pn2 / 10) + 48;
         pn2 % = 10;
     }
     *ptr++ = pn2 + 48;
     *ptr++ = c;
     *ptr = '\0';
     printf ("%c%s", 27, str);
 }

 char   *readto (c) char c; {

  /* read characters one-by-one without echo until c is read. */

  /* NOT YET IMPLEMENTED! */

     return ("Not Yet Implemented!!");
 }

 cub (pn) int    pn; {                                        /* Cursor Backwa
     brc (pn, 'D');
 }
 cud (pn) int    pn; {                                        /* Cursor Down *
     brc (pn, 'B');
 }
 cuf (pn) int    pn; {                                        /* Cursor Forwar
     brc (pn, 'C');
 }
 cup (pn1, pn2) int  pn1, pn2; {                                /* Cursor Posi
     brc2 (pn1, pn2, 'H');
 }
 cuu (pn) int    pn; {                                        /* Cursor Up */
     brc (pn, 'A');
 }
 da (pn) {                                                /* Device Attributes
     char   *str;
     brc (pn, 'c');
     str = readto ('c');
 }
 pcaln () {                                                /* Screen Alignment
     esc ("#8");
 }
 pcdhl (lower) int   lower; {                                /* Double Height
     if (lower)
         esc ("#4");
     else
         esc ("#3");
 }
 pcdwl () {                                                /* Double Wide Line
     esc ("#6");;
 }
 pcid () {                                                /* Identify Terminal
     esc ("Z");
 }
 pckpam () {                                                /* Keypad Applicat
     esc ("=");;
 }
 pcpnm () {                                                /* Keypad Numeric M
     esc (">");
 }
 pcll (ps) char *ps; {                                        /* Load LEDs */
     brcstr (ps, 'q');
 }
 pcrc () {                                                /* Restore Cursor */
     esc ("8");
 }
 pcreqtparm (pn) {                                        /* Request Terminal
     char   *str;
     brc (pn, 'x');
     str = readto ('x');
 }
 pcsc () {                                                /* Save Cursor */
     esc ("7");;
 }
 pcstbm (pn1, pn2) int   pn1, pn2; {                        /* Set Top and Bot
     brc2 (pn1, pn2, 'r');
 }
 pcswl () {                                                /* Single With Line
     esc ("#5");
 }
 pctst (pn) int  pn; {                                        /* Invoke Confid
     brc2 (2, pn, 'y');
 }
 dsr (pn) {                                                /* Device Status Re
     char   *str;
     brc (pn, 'n');
     str = readto ('n');
 }
 ed (pn) int pn; {                                        /* Erase in Display
     brc (pn, 'J');
 }
 el (pn) int pn; {                                        /* Erase in Line */
     brc (pn, 'K');
 }
 hts () {                                                /* Horizontal Tabulat
     esc ("H");
 }
 hvp (pn1, pn2) int  pn1, pn2; {                                /* Horizontal
     brc2 (pn1, pn2, 'f');
 }
 ind () {                                                /* Index */
     esc ("D");
 }
 mc (pn) int pn; {                                        /* Media Copy (Not V
     brc (pn, 'i');
 }
 nel () {                                                /* Next Line */
     esc ("E");
 }
 ri () {                                                        /* Reverse Ind
     esc ("M");
 }
 ris () {                                                /* Reset to Initial S
     esc ("c");
 }
 rm (ps) char   *ps; {                                        /* Reset Mode */
     brcstr (ps, 'l');
 }
 scs (g, c) int  g;
 char    c; {                                                /* Select charact
     printf ("%c%c%c%c%c%c%c", 27, g ? ')' : '(', c,
             27, g ? '(' : ')', 'B',
             g ? 14 : 15);
 }
 sgr (ps) char  *ps; {                                        /* Select Graphi
     brcstr (ps, 'm');
 }
 sm (ps) char   *ps; {                                        /* Set Mode */
     brcstr (ps, 'h');
 }
 tbc (pn) int    pn; {                                        /* Tabulation Cl
     brc (pn, 'g');
 }

 inittype () {

     int     ok;
     char   *answer;

     answer = "vt102";
     goto frotz;                                                /* Bypass this

     printf ("Compatibility test of terminal with respect to VT100\n\n\n");
     do {
         answer = (getlin ("What is your terminal type (vt100, vt102)? "));
         ok = (strcmp (answer, "vt100") == 0) ||
              (strcmp (answer, "vt102") == 0);
         if (!ok)
             printf ("Type 'vt100' or 'vt102'!\n");
     }
     while (!ok);

 frotz:                                                         /* bypass hack

  /* Set up my personal prejudices         */

     esc ("<");                                                /* Enter ANSI m
     rm ("?3");                                                /* 80 col mode
     rm ("?5");                                                /* Black backgr
     sm ("?7");                                                /* Wrap around

     return ((strcmp (answer, "vt100") == 0) ? vt100 : vt102);
 }

 bye () {
                                                         /* Force my personal

     rm ("?3");                                                /* 80 col mode
     rm ("?5");                                                /* Black backgr
     rm ("?6");                                                /* Absolute ori
     sm ("?7");                                                /* Wrap around
     pcstbm (0, 0);                                        /* No scroll region

  /* Say goodbye */

     ed (2);
     cup (12, 30);
     printf ("That's all, folks!\n\n");
     exit (3);
 }




 VT52.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\VT52.C

 /*
  * The routines in this file
  * provide support for VT52 style terminals
  * over a serial line. The serial I/O services are
  * provided by routines in "termio.c". It compiles
  * into nothing if not a VT52 style device. The
  * bell on the VT52 is terrible, so the "beep"
  * routine is conditionalized on defining BEL.
  */
        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     VT52

 NROW    24                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
        NPAUSE        100                        /* # times thru update to pau
 BIAS    0x20                    /* Origin 0 coordinate bias.    */
 ESC     0x1B                    /* ESC character.               */
 BEL     0x07                    /* ascii bell character         */

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     vt52move();
 extern  int     vt52eeol();
 extern  int     vt52eeop();
 extern  int     vt52beep();
 extern  int     vt52open();
 extern        int        vt52rev();
 extern        int        vt52cres();
 extern        int        vt52kopen();
 extern        int        vt52kclose();

 #if        COLOR
 extern        int        vt52fcol();
 extern        int        vt52bcol();
 #endif

 /*
  * Dispatch table. All the
  * hard fields just point into the
  * terminal I/O code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         &vt52open,
         &ttclose,
         &vt52kopen,
         &vt52kclose,
         &ttgetc,
         &ttputc,
         &ttflush,
         &vt52move,
         &vt52eeol,
         &vt52eeop,
         &vt52beep,
         &vt52rev,
         &vt52cres
 #if        COLOR
         , &vt52fcol,
         &vt52bcol
 #endif
 };

 vt52move(row, col)
 {
         ttputc(ESC);
         ttputc('Y');
         ttputc(row+BIAS);
         ttputc(col+BIAS);
 }

 vt52eeol()
 {
         ttputc(ESC);
         ttputc('K');
 }

 vt52eeop()
 {
         ttputc(ESC);
         ttputc('J');
 }

 vt52rev(status)        /* set the reverse video state */

 int status;        /* TRUE = reverse video, FALSE = normal video */

 {
         /* can't do this here, so we won't */
 }

 vt52cres()        /* change screen resolution - (not here though) */

 {
         return(TRUE);
 }

 spal()                /* change palette string */

 {
         /*        Does nothing here        */
 }

 #if        COLOR
 vt52fcol()        /* set the forground color [NOT IMPLIMENTED] */
 {
 }

 vt52bcol()        /* set the background color [NOT IMPLIMENTED] */
 {
 }
 #endif

 vt52beep()
 {
 #ifdef  BEL
         ttputc(BEL);
         ttflush();
 #endif
 }

 vt52open()
 {
 #if     V7 | BSD
         register char *cp;
         char *getenv();

         if ((cp = getenv("TERM")) == NULL) {
                 puts("Shell variable TERM not defined!");
                 exit(1);
         }
         if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
                 puts("Terminal type not 'vt52'or 'z19' !");
                 exit(1);
         }
 #endif
         ttopen();
 }

 vt52kopen()

 {
 }

 vt52kclose()

 {
 }


 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else

 vt52hello()

 {
 }

 #endif


 VTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\BPLUS11\VTEST.C

 /*                     VTEST.C test program.                        */
 /*  This is a simple test program which creates two index files.    */
 /*  100 keys are added to each file, some keys are deleted and      */
 /*  then the keys are added back to the file.  The keys are listed  */
 /*  in ascending and decending order.                               */

 #include "bplus.h"
 #include <stdio.h>
 #include <time.h>
 #include <conio.h>

 IX_DESC name1, name2;        /* index file variables */

 void uplist(name)            /* list keys in ascending order */
   IX_DESC *name;
   {
     ENTRY ee;
     first_key(name);
     while (next_key(&ee, name) == IX_OK) printf("%s   ",ee.key);
     printf("\nPress any key to continue \n");
     getch();
   }

 void downlist(name)           /* list keys in decending order  */
   IX_DESC *name;
   {
     ENTRY ee;
     last_key(name);
     while (prev_key(&ee, name) == IX_OK) printf("%s   ",ee.key);
     printf("\nPress any key to continue \n");
     getch();
   }

 main()
   {
     long i;
     long ltime;
     ENTRY e;
     printf("Make two index files\n");
     make_index("test1.idx",&name1, 0);
     make_index("test2.idx",&name2, 1);
     printf("Indexing 100 items in two index files:\n");

     /* note the time to index */
     time(&ltime);
     printf("%s",ctime(&ltime));

     /* add 100 keys to each index file */
     for (i = 0L; i < 100L; i++)
       {
         e.recptr = i;
         sprintf(e.key, "VALUE1-%2d",i);
         add_key(&e, &name1);
         sprintf(e.key, "VALUE2-%2d",i);
         add_key(&e, &name2);
       }

     /* print the time required for indexing the two files */
     time(&ltime);
     printf("%s",ctime(&ltime));
     printf("Indexing is complete\n\n");
     printf("List the keys in each index file in ascending order:\n\n");
     uplist(&name1);
     uplist(&name2);

     /* delete some keys and list again */
     printf("\nNow delete all keys from 20 to 90 in each file\n\n");
     for (i = 20L; i < 90L; i++)
       {
         e.recptr = i;
         sprintf(e.key, "VALUE1-%2d",i);
         delete_key(&e, &name1);
         sprintf(e.key, "VALUE2-%2d",i);
         delete_key(&e, &name2);
       }
     printf("List the keys now for each index file in ascending order:\n\n");
     uplist(&name1);
     uplist(&name2);

     /* add the keys back and list again */
     printf("Now add back all items from 20 to 90 to each index\n\n");
     for (i = 20L; i < 90L; i++)
       {
         e.recptr = i;
         sprintf(e.key, "VALUE1-%d",i);
         add_key(&e, &name1);
         sprintf(e.key, "VALUE2-%d",i);
         add_key(&e, &name2);
       }
     printf("List the keys for each index file again in ascending order:\n\n")
     uplist(&name1);
     uplist(&name2);

     /* list both files in decending order */
     printf("List the keys for each index file in decending order\n\n");
     downlist(&name1);
     downlist(&name2);

     /* always close all files */
     close_index(&name1);
     close_index(&name2);
   }


 V_SYNC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\V_SYNC.C

 v_sync()/*** wait till vertical blanking (CG card) ***/
 {
 #asm
      push dx
      mov dx,3DAh
 try: in al,dx    ; video status
      test al,8   ; blanking?
      jz try      ; not set yeti
      pop dx
 #
 }



 WARRAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\WARRAY.C

 /* WARRAY.C - From page 450 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. Writes an array to a file using   */
 /* binary mode.                                                 */
 /****************************************************************/

 #include "stdio.h"
 int table[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 main()
 {
 FILE *fptr;

    if((fptr = fopen("c:table.rec", "wb")) == NULL) {
       printf("\nCan't open file agents.rec");
       exit();
    }
    fwrite(table, sizeof(table), 1, fptr);
    fclose(fptr);
 }



 WC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\DLLIB\WC.C

 /*
 **                WORD COUNT UTILITY
 **
 ** syntax:
 ** wc [-cwlsv] file
 ** -c count only characters
 ** -w count only words
 ** -l count only lines
 ** -s gives only a hex checksum
 ** -q silences reporting of filenames
 ** file is input file (Do NOT use stdin redirection!)
 ** options must be first argument only
 ** wildcard filenames are allowed, as well as multiple filenames
 **
 ** ========== COPYRIGHT 1986 BY STEVEN E. MARGISON ==============
 ** 9-18-86 A  Datalight C
 **
 **   As distributed, this program requires (for compilation):
 **     "Steve's Datalight Library" version 1.10 or later
 **   which may be obtained without registration from many Bulletin
 **   Board Systems including:
 **      Compuserve IBMSW
 **      Cul-De-Sac (Holliston, MA.)
 **      HAL-PC BBS (Houston, TX.)
 **   and software library houses including:
 **      Public (Software) Library (Houston, TX.)
 **
 **   or by registration:
 **      $10 for Docs, Small Model Library
 **      $25 for Docs, S, D, L, P libraries, and complete library source
 **              in C and Assembler
 **     Steven E. Margison
 **     124 Sixth Street
 **     Downers Grove, IL, 60515
 **
 **
 */

 #include <stdio.h>
 #include <smdefs.h>

 int binflg, copt, wopt, lopt, sopt, allopt, verbose;
 char path[64], fname[MAXFN], dest[64 + MAXFN + 1];
 FILE *fd;

 main(argc, argv)
 int argc;
 char *argv[];
 {
    char *cksum, *nc, *nl, *nw;
    int index, c, inword, argci;

    if(argc < 2) usage();
    verbose = YES;
    sopt = lopt = wopt = copt = FALSE;
    allopt=TRUE;
    argci = 1;

    if(argv[argci][0] is '-') {
       index = 0;
       while(argv[argci][++index] isnot NULL) {
          switch(tolower(argv[argci][index])) {
             case 'q':
                verbose = NO;
                break;
             case 'c':
                copt = TRUE;
                allopt = FALSE;
                break;
             case 'w':
                wopt = TRUE;
                allopt = FALSE;
                break;
             case 'l':
                lopt = TRUE;
                allopt = FALSE;
                break;
             case 's':
                sopt = TRUE;
                allopt = FALSE;
                break;
             default:
                usage();
          } /* end of switch */
       } /* end of while */
    argci++;    /* get around options */
    } /* end of option "if" */

    while(argci < argc) {
       cksum = nc = nl = nw = 0;
       inword = NO;
       if(argv[argci][0] is '-') usage();

       do_open(argv[argci++]);

       while((c = fgetc(fd)) isnot EOF) {
          cksum += c;
          if(binflg) continue;
          if(c is '\n') {
             ++nl;
             ++nc;
             ++nc;     /* because a newline is actually two characters */
             inword = NO;
          }
          else ++nc;
          if(isspace(c)) inword = NO;
          else if(inword is NO) {
             inword = YES;
             ++nw;
             }
          }  /* end of inner while */
       if(allopt and !binflg)
          printf("%6d characters  %d words  %d lines  %6x checksum\n",
             nc, nw, nl, cksum);
       if(binflg) printf("%x checksum\n", cksum);

       if(copt) printf("%d\n", nc);
       if(wopt) printf("%d\n", nw);
       if(lopt) printf("%d\n", nl);
       if(sopt) printf("%x\n", cksum);
       fclose(fd);
    } /* end of file loop */
 }

 usage() {
 fputs("WC Version 1.42 9-18-86  Copyright 1986 S.E. Margison\n", stderr);
 error("usage: wc [-cwlsq] <file1, file2, filen>");
 }

 do_open(string) char *string; {
    binflg = NO;
    if(exttyp(string, "OBJ") is YES) { binflg = YES; goto AA; }
    if(exttyp(string, "EXE") is YES) { binflg = YES; goto AA; }
    if(exttyp(string, "COM") is YES) { binflg = YES; goto AA; }
    if(exttyp(string, "ARC") is YES) { binflg = YES; goto AA; }
    if(exttyp(string, "LIB") is YES) binflg = YES;
    AA:
    if(!binflg) {
       if((fd = fopen(string, "r")) is NULL) cant(string);
       }
    else {
       if((fd = fopen(string, "rb")) is NULL) cant(string);
       }
    if(verbose) printf("File: %s\n", string);
    }



 WDIR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\WDIR.C


 #include <stdio.h>
 #include "routine.h"
 #include "weather.h"

 main()
 {
 FILE *dataFile ;
 int        value[20] ;

 dataFile = fopen("WEATHER.DAT","rb") ;
 fread(value,2,20,dataFile) ;
 fclose(dataFile) ;
 if(value[2]==WEST)
         return(RETURN_ROUTINE_TRUE) ;
 else
         return(RETURN_ROUTINE_FALSE) ;
 }



 WEEKDAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\DATE\WEEKDAY.C

 /*                     *** weekday.c ***                             */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* function to determine the day of the week a given gregorian date  */
 /* falls on.  Returns a 0 if successful or a -1 if not.              */
 /*                                                                   */
 /* WARNING - day must be declared to be at least 10 characters or a  */
 /*           memory overwrite will occure.                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1983                             */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 int weekday(indate,day)
 char indate[],day[];
 {
         static char days [7][10] = {'S','u','n','d','a','y','\0',' ',' ',' ',
                                     'M','o','n','d','a','y','\0',' ',' ',' ',
                                     'T','u','e','s','d','a','y','\0',' ',' ',
                                     'W','e','d','n','e','s','d','a','y','\0',
                                     'T','h','u','r','s','d','a','y','\0',' ',
                                     'F','r','i','d','a','y','\0',' ',' ',' ',
                                     'S','a','t','u','r','d','a','y','\0',' '}
         int iday;
         long julian,gtoj();

         /* get julian date */
         if ((julian = gtoj(indate)) == (-1)) return(-1);

         /* calculate day of week */
         iday = (julian-1) % 7;

         /* move weekday into character string */
         strcpy(day,days[iday]);

         /* done */
         return(0);
 }


 WEEKDAY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB1\WEEKDAY.C

 /*                     *** weekday.c ***                             */
 /*                                                                   */
 /* IBM - PC microsoft "C"                                            */
 /*                                                                   */
 /* function to determine the day of the week a given gregorian date  */
 /* falls on.  Returns a 0 if successful or a -1 if not.              */
 /*                                                                   */
 /* WARNING - day must be declared to be at least 10 characters or a  */
 /*           memory overwrite will occure.                           */
 /*                                                                   */
 /* Written by L. Cuthbertson, March 1983                             */
 /*                                                                   */
 /*********************************************************************/
 /*                                                                   */

 int weekday(indate,day)
 char indate[],day[];
 {
         static char days [7][10] = {'S','u','n','d','a','y','\0',' ',' ',' ',
                                     'M','o','n','d','a','y','\0',' ',' ',' ',
                                     'T','u','e','s','d','a','y','\0',' ',' ',
                                     'W','e','d','n','e','s','d','a','y','\0',
                                     'T','h','u','r','s','d','a','y','\0',' ',
                                     'F','r','i','d','a','y','\0',' ',' ',' ',
                                     'S','a','t','u','r','d','a','y','\0',' '}
         int iday;
         long julian,gtoj();

         /* get julian date */
         if ((julian = gtoj(indate)) == (-1)) return(-1);

         /* calculate day of week */
         iday = (julian-1) % 7;

         /* move weekday into character string */
         strcpy(day,days[iday]);

         /* done */
         return(0);
 }


 WEKNOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\INFERNG\WEKNOW.C



 /*****************************************************************
 **                                                                **
 **          Inference -- (C) Copyright 1985 George Hageman        **
 **                                                                **
 **            user-supported software:                                **
 **                                                                **
 **                    George Hageman                                **
 **                    P.O. Box 11234                                **
 **                    Boulder, Colorado 80302                        **
 **                                                                **
 *****************************************************************/

 /*****************************************************************
 **
 **        weKnow(antecedent,&predicate)
 **
 **        routines searches both knownTrue and knownFalse
 **        stacks to determine whether the antecedent is known.
 **
 **        the return value of the routine is TRUE if known and FALSE otherwis
 **
 **        the predicate is set to the "true" value of the antecedent accordin
 **        to whether its phase is TRUE or FALSE and its .flag indicator.
 **
 *****************************************************************/

 #include "expert.h"
 #include "inference.h"

 int        weKnow(antecedent,p_value)
         int antecedent,*p_value ;
 {
 if(known(antecedent,knownTrue,numTrue) == TRUE )
         switch(ruleBuff[antecedent].flag)
                 {
                 case STRING_TRUE:
                 case STRING_TRUE_HYP:
                 case ROUTINE_TRUE:
                 case ROUTINE_TRUE_HYP:
                         *p_value = TRUE ;
                         return(TRUE)  ;
                 case STRING_FALSE:
                 case ROUTINE_FALSE :
                         *p_value = FALSE ;
                         return(TRUE) ;
                 }
 if(known(antecedent,knownFalse,numFalse) == TRUE )
         switch(ruleBuff[antecedent].flag)
                 {
                 case STRING_TRUE:
                 case STRING_TRUE_HYP:
                 case ROUTINE_TRUE:
                 case ROUTINE_TRUE_HYP :
                         *p_value = FALSE ;
                         return(TRUE) ;
                 case STRING_FALSE:
                 case ROUTINE_FALSE:
                         *p_value = TRUE ;
                         return(TRUE)  ;
                 }
 return(FALSE) ;
 }



 WHATNEXT.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\WHATNEXT.C

 /* *************************************************************** */
 /* This program reads a series of words from the command line,     */
 /* and displays all but the last on the monitor. The last is a     */
 /* series of characters which are used as input comparisons. One   */
 /* character is read from the keyboard. If it is one of the        */
 /* characters in the comparison list, its number is returned to    */
 /* DOS as the errorlevel command. If the character does not exist  */
 /* in the list, a zero is returned. Example follows;               */
 /*                                                                 */
 /* WHATNEXT What model do you want? ALR%3T                         */
 /*                                                                 */
 /* What model do you want?      <---- displayed on monitor         */
 /*    If key a or A is hit, errorlevel 1 is returned.              */
 /*    If key l or L is hit, errorlevel 2 is returned.              */
 /*    If key r or R is hit, errorlevel 3 is returned.              */
 /*    If key % is hit, errorlevel 4 is returned.                   */
 /*    If key 3 is hit, errorlevel 5 is returned.                   */
 /*    If key t or T is hit, errorlevel 6 is returned.              */
 /*    If any other key is hit, errorlevel 0 is returned.           */
 /*                                                                 */
 /*  The question must be on one line.                              */
 /*  Up to nine different keys can be used.                         */
 /*  The errorlevel can be interpreted in a batchfile.              */
 /* *************************************************************** */

 #include "stdio.h"
 #include "ctype.h"
 #include "conio.h"
 #include "process.h"

 main(int number,char *name[])
 {
 int index;                  /* a counter and incrementing variable */
 int c;                     /* the character read in for comparison */
 int code;                  /* the resulting errorlevel returned to */
 char next_char;                    /* used for the comparison loop */
 char *point;               /* a dummy pointer used for convenience */

                      /* At least one group must be used for this   */
                      /* filename, and one group used for the       */
                      /* required fields, so less than three allows */
                      /* for no question.                           */
    if (number < 3) {
       printf("No question given on command line\n");
       exit(0);
    }

                          /* print out words 2 to n-1, the question */
    number--;
    for(index = 1;index < number;index++) {
       printf("%s ",name[index]);
    }

                    /* get the users response and make it uppercase */
    c = getch();
    printf("%c\n",c);
    if (islower(c))
       c = toupper(c);
    point = name[number];/* point to the last pointer on the inputs */

    code = 0;
    index = 0;
    do {            /* search across allowed responses in last word */
       next_char = *(point + index);
       if (islower(next_char))
          next_char = toupper(next_char);      /* make it uppercase */
       if(next_char == c)                    /* if a match is found */
          code = index + 1;         /* save the number of the match */
       index++;
    } while (*(point + index));      /* until NULL terminator found */

    exit(code);               /* return the errorcode to the system */
 }


 WHEREY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CXREF\WHEREY.C

 #include <stdio.h>

 int WhereY()
 {
    struct
    {
       int AX, BX, CX, DX, SI, DI;
    } Regs;

    Regs.AX = 0x0300;
    Regs.BX = 0;
    int86(0x10, &Regs, &Regs);
    return (Regs.DX >> 8);
 }


 WHILE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\WHILE.C

                                          /* Chapter 3 - Program 1 */
 /* This is an example of a "while" loop */

 main()
 {
 int count;

    count = 0;
    while (count < 6) {
       printf("The value of count is %d\n",count);
       count = count + 1;
    }
 }


 WILD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\TOOLS\WILD.C

 /*
  * Wildcard expansion for within C programs
  */

 <stdio.h>              /* Standard I/O definitions */
 <ctype.h>              /* Character type macros */
 <dos.h>                /* Msdos definitions */
 <errno.h>              /* error codes */
 #include <string.h>
 #include <stdlib.h>
 #include <search.h>
 #include <malloc.h>

 #define SIZE(x)         (sizeof(x)/sizeof(x[0]))
 A_RONLY         0x01    /* Read only file */
 A_HIDDEN        0x02    /* Hidden file */
 A_SYSTEM        0x04    /* System file */
 A_DIRECTORY     0x10    /* Directory file */
 A_ARCHIVE       0x20    /* Archive bit */
 FNLEN           80      /* Maximum filename length */
 MAXFILES        512     /* Max number of files/directory */

 static char ID[]="## wild.c 1.0 K.van Houten 230987 ##";
 struct date {
 unsigned    d_sec:      5;      /* Time, 2 second intervals */
 unsigned    d_min:      6;      /* Time, minutes */
 unsigned    d_hour:     5;      /* Time, hours */
 unsigned    d_day:      5;      /* Date, day of month */
 unsigned    d_month:    4;      /* Date, month of year */
 unsigned    d_year:     7;      /* Date, year since 1980 */
 };
 struct find {
     char    fnd_dosinfo[21];    /* Reserved for dos */
     char    fnd_attr;           /* File attribute */
     struct date fnd_date;       /* Date structure */
     long    fnd_size;           /* File size */
     char    fnd_name[13];       /* File name less path */
 };
 char   *strrchr ();
 int     qscmp ();
 void findf();
 void findn();
 char **wild();

 static int tmp;
 static struct find f;              /* Used to return data from msdos */
 static union REGS r, o;            /* Contains register values for intcall()

 char **
 wild(file)
 char *file;
 {
     int i,j,count;
     char **fnd;

     fnd = (char **)malloc(MAXFILES * sizeof(char *));
     if (fnd == NULL) {
         printf("wildcard expansion out of mem\n");
         exit(2);
     }

     r.h.ah = 0x1a;              /* SET DISK TRANSFER ADDRESS FUNCTION */
     r.x.dx = (int) & f;
     tmp = intdos (&r, &o);
     count = 0;

     findf (file);
     if (o.x.cflag) {
         return(NULL);
     }
     for (;;) {
         if (o.x.cflag) {
             break;
         }
         if (f.fnd_attr & A_DIRECTORY) {
             if (f.fnd_name[0] == '.')
                goto next;
         }
         if ((fnd[count] = malloc(15)) == NULL) {
               printf("wildcard expansion out of memory\n");
               exit(2);
         }
         strcpy(fnd[count],strlwr(f.fnd_name));
         count++;
 next:   findn ();
      }
      if (count == 0) {
         return(NULL);
     }
     qsort ((char *)fnd, count, sizeof (char *), qscmp);

     fnd[count] = NULL;
     return(fnd);
 }


 /*
  * Find first entry, return info in find structure.
  */
 void
 findf (file)
 char *file;
 {
     r.h.ah = 0x4e;              /* FINDFIRST function */
     r.x.cx = A_HIDDEN | A_SYSTEM | A_DIRECTORY |
         A_RONLY | A_ARCHIVE;
     r.x.dx = (int) file;
     tmp = intdos (&r, &o);      /* Find first */
 }

 /*
  * Find next entry
  */
 void
 findn ()
 {
     r.h.ah = 0x4f;              /* Now use FINDNEXT function */
     tmp = intdos (&r, &o);      /* Find next */
 }


 /*
  * Qsort compare routine
  * files sort alphabetically.
  * This routine is called by qsort and passed two pointers to
  * find structure pointers.
  */
 qscmp (p1, p2)
 char **p1;
 char **p2;
 {
     register char   *f1 = *p1;
     register char   *f2 = *p2;
     register int    cmp;

     return (strcmp (f1, f2));
 }


 WILDCARD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CLIB2\WILDCARD.C

 /*
 *        Wildcard matching routine for MSDOS V2.0, Lattice C V2.0.
 *            Ross Nelson
 *            10 November 1983
 *
 *        Requires "find1st" and "findnext" from FIND.ASM.  User passes
 *        in a legal MSDOS wildcard, an attribute bit mask, and a buffer.
 *        On the first call, the wildcard is passed to DOS, and the
 *        routine returns 0 if there was no match.  If a match occurs,
 *        the first matching file name in the directory is copied into
 *        the buffer.  Subsequent calls ignore the first two parameters
 *        and copy the next succeding files to the buffer at the third
 *        parameter.  When no further matches exist the function returns
 *        FALSE (0).  Typical usage is:
 *
 *                if (!wildcard(pattern, 0x10, filename))
 *                        /* error, no match */
 *                else
 *                        do {
 *                                /* process filename */
 *                        } while (wildcard(0, 0, filename));
 *
 *
 */

 #include <ctype.h>

 struct dta {
         char reserve[21];
         char attrib;
         unsigned time;
         unsigned date;
         long size;
         char name[13];
         };

 static struct dta info;
 static int repeat = 0;
 static char dir[64];

 int wildcard (wc, attr, file)
 char *wc, attr, *file;
 {
         if (!repeat) {
                 get_header (wc, dir);        /* save directory prefix */
                 repeat = find1st (wc, attr, &info);
                 }
         else
                 repeat = findnext (&info);
         if (repeat) {
                 strcpy (file, dir);        /* directory prefix */
                 strcat (file, info.name);  /* file name */
                 while (*file) {
                         *file = tolower (*file);
                         file++;
                         }
                 }
         return (int) repeat;
 }

 static get_header (s, head)
 char *s, *head;
 {
 char *ptr;

         /* Strip device or directory header e.g. a: or \etc\ */
         ptr = s + strlen (s);
         while (s < ptr--)
                 if ((*ptr == '\\') || (*ptr == '/') || (*ptr == ':'))
                         break;
         while (s <= ptr)
                 *head++ = *s++;
         *head = '\0';
 }


 WILDCARD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\LATTICE\WILDCARD\WILDCARD.C

 /*
 *        Wildcard matching routine for MSDOS V2.0, Lattice C V2.0.
 *            Ross Nelson
 *            10 November 1983
 *
 *        Requires "find1st" and "findnext" from FIND.ASM.  User passes
 *        in a legal MSDOS wildcard, an attribute bit mask, and a buffer.
 *        On the first call, the wildcard is passed to DOS, and the
 *        routine returns 0 if there was no match.  If a match occurs,
 *        the first matching file name in the directory is copied into
 *        the buffer.  Subsequent calls ignore the first two parameters
 *        and copy the next succeding files to the buffer at the third
 *        parameter.  When no further matches exist the function returns
 *        FALSE (0).  Typical usage is:
 *
 *                if (!wildcard(pattern, 0x10, filename))
 *                        /* error, no match */
 *                else
 *                        do {
 *                                /* process filename */
 *                        } while (wildcard(0, 0, filename));
 *
 *
 */

 #include <ctype.h>

 struct dta {
         char reserve[21];
         char attrib;
         unsigned time;
         unsigned date;
         long size;
         char name[13];
         };

 static struct dta info;
 static int repeat = 0;
 static char dir[64];

 int wildcard (wc, attr, file)
 char *wc, attr, *file;
 {
         if (!repeat) {
                 get_header (wc, dir);        /* save directory prefix */
                 repeat = find1st (wc, attr, &info);
                 }
         else
                 repeat = findnext (&info);
         if (repeat) {
                 strcpy (file, dir);        /* directory prefix */
                 strcat (file, info.name);  /* file name */
                 while (*file) {
                         *file = tolower (*file);
                         file++;
                         }
                 }
         return (int) repeat;
 }

 static get_header (s, head)
 char *s, *head;
 {
 char *ptr;

         /* Strip device or directory header e.g. a: or \etc\ */
         ptr = s + strlen (s);
         while (s < ptr--)
                 if ((*ptr == '\\') || (*ptr == '/') || (*ptr == ':'))
                         break;
         while (s <= ptr)
                 *head++ = *s++;
         *head = '\0';
 }


 WINDOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\WINDOW.C

 /*
  * Window management. Some of the functions are internal, and some are
  * attached to keys that the user actually types.
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if        MEGAMAX & ST520
 overlay        "window"
 #endif

 /*
  * Reposition dot in the current window to line "n". If the argument is
  * positive, it is that line. If it is negative it is that line from the
  * bottom. If it is 0 the window is centered (this is what the standard
  * redisplay code does). With no argument it defaults to 0. Bound to M-!.
  */
 reposition(f, n)
     {
     if (f == FALSE)        /* default to 0 to center screen */
         n = 0;
     curwp->w_force = n;
     curwp->w_flag |= WFFORCE;
     return (TRUE);
     }

 /*
  * Refresh the screen. With no argument, it just does the refresh. With an
  * argument it recenters "." in the current window. Bound to "C-L".
  */
 refresh(f, n)
     {
     if (f == FALSE)
         sgarbf = TRUE;
     else
         {
         curwp->w_force = 0;             /* Center dot. */
         curwp->w_flag |= WFFORCE;
         }

     return (TRUE);
     }

 /*
  * The command make the next window (next => down the screen) the current
  * window. There are no real errors, although the command does nothing if
  * there is only 1 window on the screen. Bound to "C-X C-N".
  *
  * with an argument this command finds the <n>th window from the top
  *
  */
 nextwind(f, n)

 int f, n;        /* default flag and numeric argument */

 {
         register WINDOW *wp;
         register int nwindows;                /* total number of windows */

         if (f) {

                 /* first count the # of windows */
                 wp = wheadp;
                 nwindows = 1;
                 while (wp->w_wndp != NULL) {
                         nwindows++;
                         wp = wp->w_wndp;
                 }

                 /* if the argument is negative, it is the nth window
                    from the bottom of the screen                        */
                 if (n < 0)
                         n = nwindows + n + 1;

                 /* if an argument, give them that window from the top */
                 if (n > 0 && n <= nwindows) {
                         wp = wheadp;
                         while (--n)
                                 wp = wp->w_wndp;
                 } else {
                         mlwrite("Window number out of range");
                         return(FALSE);
                 }
         } else
                 if ((wp = curwp->w_wndp) == NULL)
                         wp = wheadp;
         curwp = wp;
         curbp = wp->w_bufp;
         upmode();
         return (TRUE);
 }

 /*
  * This command makes the previous window (previous => up the screen) the
  * current window. There arn't any errors, although the command does not do a
  * lot if there is 1 window.
  */
 prevwind(f, n)
 {
         register WINDOW *wp1;
         register WINDOW *wp2;

         /* if we have an argument, we mean the nth window from the bottom */
         if (f)
                 return(nextwind(f, -n));

         wp1 = wheadp;
         wp2 = curwp;

         if (wp1 == wp2)
                 wp2 = NULL;

         while (wp1->w_wndp != wp2)
                 wp1 = wp1->w_wndp;

         curwp = wp1;
         curbp = wp1->w_bufp;
         upmode();
         return (TRUE);
 }

 /*
  * This command moves the current window down by "arg" lines. Recompute the
  * top line in the window. The move up and move down code is almost completel
  * the same; most of the work has to do with reframing the window, and pickin
  * a new dot. We share the code by having "move down" just be an interface to
  * "move up". Magic. Bound to "C-X C-N".
  */
 mvdnwind(f, n)

 int n;

 {
         return (mvupwind(f, -n));
 }

 /*
  * Move the current window up by "arg" lines. Recompute the new top line of
  * the window. Look to see if "." is still on the screen. If it is, you win.
  * If it isn't, then move "." to center it in the new framing of the window
  * (this command does not really move "."; it moves the frame). Bound to
  * "C-X C-P".
  */
 mvupwind(f, n)
     int n;

     {
     register LINE *lp;
     register int i;

     lp = curwp->w_linep;

     if (n < 0)
         {
         while (n++ && lp!=curbp->b_linep)
             lp = lforw(lp);
         }
     else
         {
         while (n-- && lback(lp)!=curbp->b_linep)
             lp = lback(lp);
         }

     curwp->w_linep = lp;
     curwp->w_flag |= WFHARD;            /* Mode line is OK. */

     for (i = 0; i < curwp->w_ntrows; ++i)
         {
         if (lp == curwp->w_dotp)
             return (TRUE);
         if (lp == curbp->b_linep)
             break;
         lp = lforw(lp);
         }

     lp = curwp->w_linep;
     i  = curwp->w_ntrows/2;

     while (i-- && lp != curbp->b_linep)
         lp = lforw(lp);

     curwp->w_dotp  = lp;
     curwp->w_doto  = 0;
     return (TRUE);
     }

 /*
  * This command makes the current window the only window on the screen. Bound
  * to "C-X 1". Try to set the framing so that "." does not have to move on th
  * display. Some care has to be taken to keep the values of dot and mark in
  * the buffer structures right if the distruction of a window makes a buffer
  * become undisplayed.
  */
 onlywind(f, n)
 {
         register WINDOW *wp;
         register LINE   *lp;
         register int    i;

         while (wheadp != curwp) {
                 wp = wheadp;
                 wheadp = wp->w_wndp;
                 if (--wp->w_bufp->b_nwnd == 0) {
                         wp->w_bufp->b_dotp  = wp->w_dotp;
                         wp->w_bufp->b_doto  = wp->w_doto;
                         wp->w_bufp->b_markp = wp->w_markp;
                         wp->w_bufp->b_marko = wp->w_marko;
                 }
                 free((char *) wp);
         }
         while (curwp->w_wndp != NULL) {
                 wp = curwp->w_wndp;
                 curwp->w_wndp = wp->w_wndp;
                 if (--wp->w_bufp->b_nwnd == 0) {
                         wp->w_bufp->b_dotp  = wp->w_dotp;
                         wp->w_bufp->b_doto  = wp->w_doto;
                         wp->w_bufp->b_markp = wp->w_markp;
                         wp->w_bufp->b_marko = wp->w_marko;
                 }
                 free((char *) wp);
         }
         lp = curwp->w_linep;
         i  = curwp->w_toprow;
         while (i!=0 && lback(lp)!=curbp->b_linep) {
                 --i;
                 lp = lback(lp);
         }
         curwp->w_toprow = 0;
         curwp->w_ntrows = term.t_nrow-1;
         curwp->w_linep  = lp;
         curwp->w_flag  |= WFMODE|WFHARD;
         return (TRUE);
 }

 /*
  * Delete the current window, placing its space in the window above,
  * or, if it is the top window, the window below. Bound to C-X 0.
  */

 delwind(f,n)

 int f, n;        /* arguments are ignored for this command */

 {
         register WINDOW *wp;        /* window to recieve deleted space */
         register WINDOW *lwp;        /* ptr window before curwp */
         register int target;        /* target line to search for */

         /* if there is only one window, don't delete it */
         if (wheadp->w_wndp == NULL) {
                 mlwrite("Can not delete this window");
                 return(FALSE);
         }

         /* find window before curwp in linked list */
         wp = wheadp;
         lwp = NULL;
         while (wp != NULL) {
                 if (wp == curwp)
                         break;
                 lwp = wp;
                 wp = wp->w_wndp;
         }

         /* find recieving window and give up our space */
         wp = wheadp;
         if (curwp->w_toprow == 0) {
                 /* find the next window down */
                 target = curwp->w_ntrows + 1;
                 while (wp != NULL) {
                         if (wp->w_toprow == target)
                                 break;
                         wp = wp->w_wndp;
                 }
                 if (wp == NULL)
                         return(FALSE);
                 wp->w_toprow = 0;
                 wp->w_ntrows += target;
         } else {
                 /* find the next window up */
                 target = curwp->w_toprow - 1;
                 while (wp != NULL) {
                         if ((wp->w_toprow + wp->w_ntrows) == target)
                                 break;
                         wp = wp->w_wndp;
                 }
                 if (wp == NULL)
                         return(FALSE);
                 wp->w_ntrows += 1 + curwp->w_ntrows;
         }

         /* get rid of the current window */
         if (--curwp->w_bufp->b_nwnd == 0) {
                 curwp->w_bufp->b_dotp = curwp->w_dotp;
                 curwp->w_bufp->b_doto = curwp->w_doto;
                 curwp->w_bufp->b_markp = curwp->w_markp;
                 curwp->w_bufp->b_marko = curwp->w_marko;
         }
         if (lwp == NULL)
                 wheadp = curwp->w_wndp;
         else
                 lwp->w_wndp = curwp->w_wndp;
         free((char *)curwp);
         curwp = wp;
         wp->w_flag |= WFHARD;
         curbp = wp->w_bufp;
         upmode();
         return(TRUE);
 }

 /*

 Split the current window.  A window smaller than 3 lines cannot be
 split.  An argument of 1 forces the cursor into the upper window, an
 argument of two forces the cursor to the lower window.  The only other
 error that is possible is a "malloc" failure allocating the structure
 for the new window.  Bound to "C-X 2".

  */
 splitwind(f, n)

 int f, n;        /* default flag and numeric argument */

 {
         register WINDOW *wp;
         register LINE   *lp;
         register int    ntru;
         register int    ntrl;
         register int    ntrd;
         register WINDOW *wp1;
         register WINDOW *wp2;
         char *malloc();

         if (curwp->w_ntrows < 3) {
                 mlwrite("Cannot split a %d line window", curwp->w_ntrows);
                 return (FALSE);
         }
         if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
                 mlwrite("[OUT OF MEMORY]");
                 return (FALSE);
         }
         ++curbp->b_nwnd;                        /* Displayed twice.     */
         wp->w_bufp  = curbp;
         wp->w_dotp  = curwp->w_dotp;
         wp->w_doto  = curwp->w_doto;
         wp->w_markp = curwp->w_markp;
         wp->w_marko = curwp->w_marko;
         wp->w_flag  = 0;
         wp->w_force = 0;
 #if        COLOR
         /* set the colors of the new window */
         wp->w_fcolor = gfcolor;
         wp->w_bcolor = gbcolor;
 #endif
         ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
         ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
         lp = curwp->w_linep;
         ntrd = 0;
         while (lp != curwp->w_dotp) {
                 ++ntrd;
                 lp = lforw(lp);
         }
         lp = curwp->w_linep;
         if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
                 /* Old is upper window. */
                 if (ntrd == ntru)               /* Hit mode line.       */
                         lp = lforw(lp);
                 curwp->w_ntrows = ntru;
                 wp->w_wndp = curwp->w_wndp;
                 curwp->w_wndp = wp;
                 wp->w_toprow = curwp->w_toprow+ntru+1;
                 wp->w_ntrows = ntrl;
         } else {                                /* Old is lower window  */
                 wp1 = NULL;
                 wp2 = wheadp;
                 while (wp2 != curwp) {
                         wp1 = wp2;
                         wp2 = wp2->w_wndp;
                 }
                 if (wp1 == NULL)
                         wheadp = wp;
                 else
                         wp1->w_wndp = wp;
                 wp->w_wndp   = curwp;
                 wp->w_toprow = curwp->w_toprow;
                 wp->w_ntrows = ntru;
                 ++ntru;                         /* Mode line.           */
                 curwp->w_toprow += ntru;
                 curwp->w_ntrows  = ntrl;
                 while (ntru--)
                         lp = lforw(lp);
         }
         curwp->w_linep = lp;                    /* Adjust the top lines */
         wp->w_linep = lp;                       /* if necessary.        */
         curwp->w_flag |= WFMODE|WFHARD;
         wp->w_flag |= WFMODE|WFHARD;
         return (TRUE);
 }

 /*
  * Enlarge the current window. Find the window that loses space. Make sure it
  * is big enough. If so, hack the window descriptions, and ask redisplay to d
  * all the hard work. You don't just set "force reframe" because dot would
  * move. Bound to "C-X Z".
  */
 enlargewind(f, n)
 {
         register WINDOW *adjwp;
         register LINE   *lp;
         register int    i;

         if (n < 0)
                 return (shrinkwind(f, -n));
         if (wheadp->w_wndp == NULL) {
                 mlwrite("Only one window");
                 return (FALSE);
         }
         if ((adjwp=curwp->w_wndp) == NULL) {
                 adjwp = wheadp;
                 while (adjwp->w_wndp != curwp)
                         adjwp = adjwp->w_wndp;
         }
         if (adjwp->w_ntrows <= n) {
                 mlwrite("Impossible change");
                 return (FALSE);
         }
         if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
                 lp = adjwp->w_linep;
                 for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
                         lp = lforw(lp);
                 adjwp->w_linep  = lp;
                 adjwp->w_toprow += n;
         } else {                                /* Shrink above.        */
                 lp = curwp->w_linep;
                 for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
                         lp = lback(lp);
                 curwp->w_linep  = lp;
                 curwp->w_toprow -= n;
         }
         curwp->w_ntrows += n;
         adjwp->w_ntrows -= n;
         curwp->w_flag |= WFMODE|WFHARD;
         adjwp->w_flag |= WFMODE|WFHARD;
         return (TRUE);
 }

 /*
  * Shrink the current window. Find the window that gains space. Hack at the
  * window descriptions. Ask the redisplay to do all the hard work. Bound to
  * "C-X C-Z".
  */
 shrinkwind(f, n)
 {
         register WINDOW *adjwp;
         register LINE   *lp;
         register int    i;

         if (n < 0)
                 return (enlargewind(f, -n));
         if (wheadp->w_wndp == NULL) {
                 mlwrite("Only one window");
                 return (FALSE);
         }
         if ((adjwp=curwp->w_wndp) == NULL) {
                 adjwp = wheadp;
                 while (adjwp->w_wndp != curwp)
                         adjwp = adjwp->w_wndp;
         }
         if (curwp->w_ntrows <= n) {
                 mlwrite("Impossible change");
                 return (FALSE);
         }
         if (curwp->w_wndp == adjwp) {           /* Grow below.          */
                 lp = adjwp->w_linep;
                 for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
                         lp = lback(lp);
                 adjwp->w_linep  = lp;
                 adjwp->w_toprow -= n;
         } else {                                /* Grow above.          */
                 lp = curwp->w_linep;
                 for (i=0; i<n && lp!=curbp->b_linep; ++i)
                         lp = lforw(lp);
                 curwp->w_linep  = lp;
                 curwp->w_toprow += n;
         }
         curwp->w_ntrows -= n;
         adjwp->w_ntrows += n;
         curwp->w_flag |= WFMODE|WFHARD;
         adjwp->w_flag |= WFMODE|WFHARD;
         return (TRUE);
 }

 /*        Resize the current window to the requested size        */

 resize(f, n)

 int f, n;        /* default flag and numeric argument */

 {
         int clines;        /* current # of lines in window */

         /* must have a non-default argument, else ignore call */
         if (f == FALSE)
                 return(TRUE);

         /* find out what to do */
         clines = curwp->w_ntrows;

         /* already the right size? */
         if (clines == n)
                 return(TRUE);

         return(enlargewind(TRUE, n - clines));
 }

 /*
  * Pick a window for a pop-up. Split the screen if there is only one window.
  * Pick the uppermost window that isn't the current window. An LRU algorithm
  * might be better. Return a pointer, or NULL on error.
  */
 WINDOW  *
 wpopup()
 {
         register WINDOW *wp;

         if (wheadp->w_wndp == NULL              /* Only 1 window        */
         && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
                 return (NULL);
         wp = wheadp;                            /* Find window to use   */
         while (wp!=NULL && wp==curwp)
                 wp = wp->w_wndp;
         return (wp);
 }

 scrnextup(f, n)                /* scroll the next window up (back) a page */

 {
         nextwind(FALSE, 1);
         backpage(f, n);
         prevwind(FALSE, 1);
 }

 scrnextdw(f, n)                /* scroll the next window down (forward) a pag

 {
         nextwind(FALSE, 1);
         forwpage(f, n);
         prevwind(FALSE, 1);
 }

 savewnd(f, n)                /* save ptr to current window */

 {
         swindow = curwp;
         return(TRUE);
 }

 restwnd(f, n)                /* restore the saved screen */

 {
         register WINDOW *wp;

         /* find the window */
         wp = wheadp;
         while (wp != NULL) {
                 if (wp == swindow) {
                         curwp = wp;
                         curbp = wp->w_bufp;
                         upmode();
                         return (TRUE);
                 }
                 wp = wp->w_wndp;
         }

         mlwrite("[No such window exists]");
         return(FALSE);
 }

 newsize(f, n)        /* resize the screen, re-writing the screen */

 int f;        /* default flag */
 int n;        /* numeric argument */

 {
         WINDOW *wp;        /* current window being examined */
         WINDOW *nextwp;        /* next window to scan */
         WINDOW *lastwp;        /* last window scanned */
         int lastline;        /* screen line of last line of current window */

         /* if the command defaults, assume the largest */
         if (f == FALSE)
                 n = term.t_mrow + 1;

         /* make sure it's in range */
         if (n < 3 || n > term.t_mrow + 1) {
                 mlwrite("%%Screen size out of range");
                 return(FALSE);
         }

         if (term.t_nrow == n - 1)
                 return(TRUE);
         else if (term.t_nrow < n - 1) {

                 /* go to the last window */
                 wp = wheadp;
                 while (wp->w_wndp != NULL)
                         wp = wp->w_wndp;

                 /* and enlarge it as needed */
                 wp->w_ntrows = n - wp->w_toprow - 2;
                 wp->w_flag |= WFHARD|WFMODE;

         } else {

                 /* rebuild the window structure */
                 nextwp = wheadp;
                 wp = NULL;
                 lastwp = NULL;
                 while (nextwp != NULL) {
                         wp = nextwp;
                         nextwp = wp->w_wndp;

                         /* get rid of it if it is too low */
                         if (wp->w_toprow > n - 2) {

                                 /* save the point/mark if needed */
                                 if (--wp->w_bufp->b_nwnd == 0) {
                                         wp->w_bufp->b_dotp = wp->w_dotp;
                                         wp->w_bufp->b_doto = wp->w_doto;
                                         wp->w_bufp->b_markp = wp->w_markp;
                                         wp->w_bufp->b_marko = wp->w_marko;
                                 }

                                 /* update curwp and lastwp if needed */
                                 if (wp == curwp)
                                         curwp = wheadp;
                                         curbp = curwp->w_bufp;
                                 if (lastwp != NULL)
                                         lastwp->w_wndp = NULL;

                                 /* free the structure */
                                 free((char *)wp);
                                 wp = NULL;

                         } else {
                                 /* need to change this window size? */
                                 lastline = wp->w_toprow + wp->w_ntrows - 1;
                                 if (lastline >= n - 2) {
                                         wp->w_ntrows = n - wp->w_toprow - 2;
                                         wp->w_flag |= WFHARD|WFMODE;
                                 }
                         }

                         lastwp = wp;
                 }
         }

         /* screen is garbage */
         term.t_nrow = n - 1;
         sgarbf = TRUE;
         return(TRUE);
 }

 newwidth(f, n)        /* resize the screen, re-writing the screen */

 int f;        /* default flag */
 int n;        /* numeric argument */

 {
         register WINDOW *wp;

         /* if the command defaults, assume the largest */
         if (f == FALSE)
                 n = term.t_mcol;

         /* make sure it's in range */
         if (n < 10 || n > term.t_mcol) {
                 mlwrite("%%Screen width out of range");
                 return(FALSE);
         }

         /* otherwise, just re-width it (no big deal) */
         term.t_ncol = n;
         term.t_margin = n / 10;
         term.t_scrsiz = n - (term.t_margin * 2);

         /* florce all windows to redraw */
         wp = wheadp;
         while (wp) {
                 wp->w_flag |= WFHARD | WFMOVE | WFMODE;
                 wp = wp->w_wndp;
         }
         sgarbf = TRUE;

         return(TRUE);
 }

 int getwpos()        /* get screen offset of current line in current window *

 {
         register int sline;        /* screen line from top of window */
         register LINE *lp;        /* scannile line pointer */

         /* search down the line we want */
         lp = curwp->w_linep;
         sline = 1;
         while (lp != curwp->w_dotp) {
                 ++sline;
                 lp = lforw(lp);
         }

         /* and return the value */
         return(sline);
 }


 WINDOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\WINDOW\WINDOW.C

 /*        module:                window.c
  *        programmer:        Ray L. McVay
  *        started:        1 Aug 84
  *        version:        1.2, 23 Aug 84
  *
  *        A simple window package based on the article and programs
  *        by Edward Mitchell in the Jan 84 Dr. Dobb's Journal.  This
  *        implementation uses dynamically allocated buffers for the
  *        window control blocks and screen save buffers.
  *
  *        An assembly language support library called VLIB is used to
  *        interface the DeSmet C compiler with the IBM ROM BIOS video
  *        routines.  VLIB will undoubtedly have to be rewritten if the
  *        window package is to be used with other compilers.
  *
  *        History -
  *
  *        1.1        -        Added style member to wcb structure, clr_window
  *                        use of wn->cx for horizontal scrolling in write_tex
  *
  *        1.2 -        Added oldx, oldy members to wcb structure and use them
  *                        in draw_window() and remove_window().
  *
  */

 #include        <stdio.h>

 typedef struct wcb        /* --- window control block        ---
 {
         int                ulx,        /* upper left corner x coordinate
                         uly,        /* ditto y coordinate
                         xsize,        /* line width of inside of window
                         ysize,        /* number of lines inside of window
                         cx,                /* current cursor offset in window
                         cy,
                         style,        /* attribute to be used in window
                         *scrnsave,        /* pointer to screen save buffer */
                         oldx,        /* cursor position when window was
                         oldy;        /* opened (used for screen restore)
 } WINDOW, *WINDOWPTR;


 /************************************************************************
 * putch(), write a character and attribute to a specific XY location on *
 *                   the screen. The attribute is the high byte of the charact
 ************************************************************************/

 putch(x, y, c)
 int                x, y, c;
 {
         gotoxy(x, y, 0);
         vputca(c, 0, 1);
 }


 /************************************************************************
 * getch(), return the character and attribute at screen XY
 ************************************************************************/

 getch(x, y)
 int                x, y;
 {
         gotoxy(x, y, 0);
         return(vgetc(0));
 }


 /************************************************************************
 * draw_row(), output a row of one character/attribute at XY
 ************************************************************************/

 draw_row(x, y, count, c)
 int                x, y, count,c;
 {
         gotoxy(x, y, 0);
         vputca(c, 0, count);
 }


 /************************************************************************
 * draw_window(), open a window of given size with upper left corner at
 *                                 XY. Allocates buffers for the window contro
 *                                 screen save buffers. Copies overwritten scr
 *                                 buffer. Draws the blank window. Returns the
 *                                 the window control block or NULL if no buff
 ************************************************************************/

 WINDOWPTR draw_window(x, y, width, height, attrib)
 int                x, y, width, height, attrib;
 {
         WINDOWPTR wn;
         int                tx, ty,
                         xend, yend;
         int                *tptr;
         char        *calloc();

         if ((wn = (WINDOWPTR)calloc(1, sizeof(WINDOW))) == NULL)
                 return(NULL);
         else if ((wn->scrnsave = (int *)calloc((width+2) * (height+2), sizeof
         {
                 free(wn);
                 return(NULL);
         }
         else
         {
                 /* store parameters in window control block */

                 wn->ulx = x;
                 wn->uly = y;
                 wn->xsize = width;
                 wn->ysize = height;
                 wn->cx = 1;
                 wn->cy = 1;
                 wn->style = attrib;
                 attrib <<= 8;        /* will make things below go quicker */
                 wn->oldx = getxy(0) & 255;
                 wn->oldy = getxy(0) >> 8;

                 /* Copy existing text where the window will be placed */
                 /* to the scrnsave buffer. Obviously, a less portable */
                 /* routine could be much faster.

                 tptr = wn->scrnsave;
                 xend = x + width + 2;
                 yend = y + height + 2;

                 for (ty = y; ty < yend; ty++)
                 {
                         for (tx = x; tx < xend; tx++)
                                 *tptr++ = getch(tx, ty);
                 }

                 /* draw the window border and clear the text area */

                 putch(x, y, 0xda + attrib);
                 draw_row(x + 1, y, width, 0xc4 + attrib);        /* horiz bar
                 putch(x + width + 1, y, 0xbf + attrib);                /* ur

                 yend = y + height;

                 for (ty = y+1; ty <= yend; ty++)
                 {
                         putch(x, ty, 0xb3 + attrib);                        /
                         putch(x+width+1, ty, 0xb3 + attrib);
                 }

                 putch(x, y + height + 1, 0xc0 + attrib);
                 draw_row(x + 1, y + height + 1, width, 0xc4 + attrib);
                 putch(x + width + 1, y + height + 1, 0xd9 + attrib);        /

                 clr_window(wn);

                 return(wn);
         }
 }


 /************************************************************************
 * remove_window(), erase the window at the window control block.
 *                                   Must be the "top" window if overlapping w
 *                                   used. "Tiled" windows could be removed ra
 ************************************************************************/

 remove_window(wn)
 WINDOWPTR wn;
 {
         int                tx, ty,
                         xend, yend;
         int                *tptr;

         /* just repaint the saved text at the appropriate location */

         tptr = wn->scrnsave;
         xend = wn->ulx + wn->xsize + 2;
         yend = wn->uly + wn->ysize + 2;

         for (ty = wn->uly; ty < yend; ty++)
         {
                 for (tx = wn->ulx; tx < xend; tx++)
                         putch(tx, ty, *tptr++);
         }

         /* put cursor back where it was before this rude interruption */

         gotoxy(wn->oldx, wn->oldy, 0);

         /* then release the dynamic storage used */

         free(wn->scrnsave);
         free(wn);
 }


 /************************************************************************
 * write_text(), print a string inside a window using cx, cy in WCB
 ************************************************************************/

 write_text(wn, string)
 WINDOWPTR wn;
 char        *string;
 {
         int                tx, ty, xend;

         /* first check to see if we're at the bottom of the window
         /* if we are then scroll the contents of the window up

         if (wn->cy > wn->ysize)
         {
                 delete_row(wn, 1);
                 --wn->cy;
         }

         /* Print as much of the string as will fit in the window.
          * cx is used for relative left margin. If cx is negative then
          * the first cx characters will be removed from the string to
          * allow horizontal scrolling in the window.
          * NOTE: This obviously simple-minded technique is usable for
          *                  displaying predetermined messages but a more gene
          *                 console output intercept should be used for Star-l
          *                 environments.

         if (wn->cx > 0)
                 tx = wn->ulx + wn->cx;
         else
         {
                 if (-wn->cx < strlen(string))
                         string -= wn->cx;
                 else
                         *string = '\0';
                 tx = wn->ulx + 1;
         }
         xend = wn->ulx + wn->xsize + 1;
         ty = wn->uly + wn->cy;
         while ((tx < xend) && *string)
         {
                 gotoxy(tx++, ty, 0);
                 vputc(*string++, 0, 1);
         }
         ++wn->cy;                /* move the internal cursor to the next line
 }


 /************************************************************************
 * insert_row(), insert a row of blanks by scrolling the lower portion
 *                                of a window down
 ************************************************************************/

 insert_row(wn, row)
 WINDOWPTR wn;
 int                row;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + row;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrldn(scrlwn, 1, wn->style);
 }


 /************************************************************************
 * delete_row(), delete a row by scrolling the lower portion of a window *
 *                                up and inserting a row of blanks at the bott
 ************************************************************************/

 delete_row(wn, row)
 WINDOWPTR wn;
 int                row;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + row;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrlup(scrlwn, 1, wn->style);
 }


 /************************************************************************
 * clr_window(), clear the "active" part of a window        and "home" interna
 *                                text cursor
 ************************************************************************/

 clr_window(wn)
 WINDOWPTR wn;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + 1;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrlup(scrlwn, 0, wn->style);
         wn->cx = 1;
         wn->cy = 1;
 }


 WINDOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\WINDKW\WINDOW.C

 /*        module:                window.c
  *        programmer:        Ray L. McVay
  *        started:        1 Aug 84
  *        version:        1.2, 23 Aug 84
  *
  *        A simple window package based on the article and programs
  *        by Edward Mitchell in the Jan 84 Dr. Dobb's Journal.  This
  *        implementation uses dynamically allocated buffers for the
  *        window control blocks and screen save buffers.
  *
  *        An assembly language support library called VLIB is used to
  *        interface the DeSmet C compiler with the IBM ROM BIOS video
  *        routines.  VLIB will undoubtedly have to be rewritten if the
  *        window package is to be used with other compilers.
  *
  *        History -
  *
  *        1.1 -  Added style member to wcb structure, wcls and
  *                use of wn->cx for horizontal scrolling in wrt_txt().
  *
  *        1.2 -        Added oldx, oldy members to wcb structure and use them
  *                 in wopen() and wclose().
  *
  */

 #include        <stdio.h>
 #include        "window.h"

 int        page;                /* Active page number.        */

 /************************************************************************
 * vwrtch(), write a character and attribute to a specific XY location
 *        on the screen. The attribute is the high byte of the character.
 ************************************************************************/

 vwrtch(x, y, c)
 int                x, y, c;
 {
         gotoxy(x, y, page);
         vputca(c, page, 1);
 }


 /************************************************************************
 * vrdch(), return the character and attribute at screen XY                *
 ************************************************************************/
 vrdch(x, y)
 int                x, y;
 {
         gotoxy(x, y, page);
         return(vgetc(page));
 }


 /************************************************************************
 * draw_row(), output a row of one character/attribute at XY                *
 ************************************************************************/

 draw_row(x, y, count, c)
 int                x, y, count,c;
 {
         gotoxy(x, y, page);
         vputca(c, page, count);
 }

 /************************************************************************
 * wopen(),         open a window of given size with upper left corner at
 *                XY. Allocates buffers for the window control block and
 *                screen save buffers. Copies overwritten screen to the
 *                buffer. Draws the blank window. Returns the address of
 *                the window control block or NULL if no buffer space.
 *        NOTE:        The border attributes are given in the structure
 *                pointer bord and can be different than the window's        *
 *                contents attribute.                                        *
 ************************************************************************/

 WINDOW *wopen(wbd, x, y, width, height, attrib)
 BORDER *wbd;
 int        x, y, width, height, attrib;
 {
         WINDOW *wn;
         register int tx, ty, xend, yend;
         int        *tptr, c;
         char        *calloc();

         if ((wn = (WINDOW *)calloc(1, sizeof(WINDOW))) == NULL)
                 return(NULL);
         else if ((wn->scrnsave = (int *)calloc((width+2) * (height+2),
                          sizeof(int))) == NULL)
         {
                 free(wn);
                 return(NULL);
         }
         else
         {
                 /* store parameters in window control block */

                 wn->xmargin = wn->ymargin = 0;
                 wn->ulx = x;
                 wn->uly = y;
                 wn->xsize = width;
                 wn->ysize = height;
                 wn->cx = 1;
                 wn->cy = 1;
                 wn->atrib = attrib;
                 wn->oldx = getxy(page) & 255;
                 wn->oldy = getxy(page) >> 8;

                 /* Copy existing text where the window will be placed
                 /* to the scrnsave buffer. Obviously, a less portable
                 /* routine could be much faster.                        */

                 tptr = wn->scrnsave;
                 xend = x + width + 2;
                 yend = y + height + 2;
                 for (ty = y; ty < yend; ty++)
                 {
                         for (tx = x; tx < xend; tx++)
                                 *tptr++ = vrdch(tx, ty);
                 }
                 /* draw the window border and clear the text area        */

                 vwrtch(x, y, wbd->ul);             /* ul corner*/
                 draw_row(x + 1, y, width, wbd->h); /* horiz bar*/
                 vwrtch(x + width + 1, y, wbd->ur); /* ur corner*/

                 yend = y + height;

                 for (c=wbd->v,ty = y+1; ty <= yend; ty++)
                 {
                         vwrtch(x, ty, c);   /* draw the sides*/
                         vwrtch(x+width+1, ty, c);
                 }

                 vwrtch(x, y + height + 1, wbd->ll);  /* ll corner*/
         /* horiz bar */
                 draw_row(x + 1, y + height + 1, width, wbd->h);
         /* lr corner */
                 vwrtch(x + width + 1, y + height + 1, wbd->lr);

                 wcls(wn);
                 return(wn);
         }
 }


 /************************************************************************
 * wclose(), erase the window at the window control block.                *
 *        Must be the "top" window if overlapping windows are                *
 *        used. "Tiled" windows could be removed randomly.                *
 ************************************************************************/

 wclose(wn)
 WINDOW *wn;
 {
         register
         int                tx, ty,
                         xend, yend;
         int                *tptr;

         /* just repaint the saved text at the appropriate location */

         tptr = wn->scrnsave;
         xend = wn->ulx + wn->xsize + 2;
         yend = wn->uly + wn->ysize + 2;

         for (ty = wn->uly; ty < yend; ty++)
         {
                 for (tx = wn->ulx; tx < xend; tx++)
                         vwrtch(tx, ty, *tptr++);
         }

         /* put cursor back where it was before this rude interruption */

         gotoxy(wn->oldx, wn->oldy, page);

         /* then release the dynamic storage used */

         free(wn->scrnsave);
         free(wn);
 }


 /************************************************************************
 * wputstr(), print a string inside a window using cx, cy in WCB
 ************************************************************************/

 wputstr(wn, string)
 register WINDOW *wn;
 register char        *string;
 {
         int                tcx;

         /* Print as much of the string as will fit in the window.        *
          * cx is used for relative left margin. If cx is negative then
          * the first cx characters will be removed from the string to
          * allow horizontal scrolling in the window.                        *

         while(*string)
                 wputchar(wn, *string++);
         return set_wcxy(wn,0,0);
 }


 /************************************************************************
 * wputs(), print a string inside a window using cx, cy in WCB.
 *        Note that the CR, LF, BS, TAB, and DEL keys are processed.        *
 ************************************************************************/

 wputs(wn, string)
 register WINDOW *wn;
 register char        *string;
 {
         while(*string)
                 wputch(wn, *string++);
         return wbound(wn);
 }

 /************************************************************************
 * wputch(), print a character inside a window using cx, cy in WCB        *
 *        while processing for CR, LF, BS, TAB, and DEL.
 ************************************************************************/

 wputch(wn, c)
 register WINDOW *wn;
 char        c;
 {
         int rcode;

         rcode = 0;
         switch (c) {
                 case '\r':        /* Carriage return */
                         wn->cx = -wn->xmargin+1;
                         break;
                 case '\n':        /* Linefeed */
                         ++wn->cy;
                         break;
                 case '\b':        /* Backspace */
                         --wn->cx;
                         break;
                 case 0x7f:        /* Delete */
                         if(wn->cx < 1) {        /* If we are left of the */
                                 ++wn->cx;        /* window account for the */
                                 return;                /* delete. */
                         }
                         wputch(wn, 0x08);
                         wputchar(wn, ' ');
                         wputch(wn, 0x08);
                         break;
                 case 0x09:        /* Tab */
                         do
                                 wputchar(wn,' ');
                         while(wn->cx & 0x07);
                         break;
                 case 0x0c:        /* Formfeed */
                         wcls(wn);
                         break;
                 default:
                         wputchar(wn, c);
                         break;
         }
         return set_wcxy(wn,0,0);
 }

 /************************************************************************
 * wputchar(), print a character as is where ever the cursor might be
 *         inside a window using cx, cy in WCB.
 *        Note that the negitive value of cx is handled and that the        *
 *           window is not scrolled.                                        *
 ************************************************************************/

 wputchar(wn, c)
 register WINDOW *wn;
 char        c;
 {
         int rcode;

         if((rcode = wbound(wn))) {
                 ++wn->cx;
                 return (rcode);
         }
         gotoxy(wn->ulx + wn->cx++, wn->uly + wn->cy, page);
         vputca(wn->atrib<<8|c, page, 1);
         return(0);
 }


 /************************************************************************
 * wins_row(), insert a row of blanks by scrolling the lower portion        *
 *        of a window down.                                                *
 *        The current (cy) row is inserted.                                *
 ************************************************************************/

 wins_row(wn)
 register WINDOW *wn;
 {
         int        rcode, scrlwn[4];

         /* Don't if we are not in the window. */
         if((rcode = wbound(wn)))
                 return(rcode);

         /* If it is the last line in the window just delete it. */
         if(wn->cy == wn->ysize)
                 draw_row(wn->ulx+1, wn->uly + wn->cy,
                          wn->xsize, (wn->atrib <<8) |' ');
         else {
         /* calculate corners of the scrolling window */
                 scrlwn[0] = wn->ulx +1;                        /* ulx */
                 scrlwn[1] = wn->uly + wn->cy;                /* uly */
                 scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
                 scrlwn[3] = wn->uly + wn->ysize;        /* lry */

                 scrldn(scrlwn, 1, wn->atrib);
         }
         return(0);
 }


 /************************************************************************
 * wdel_row(), delete a row by scrolling the lower portion of a window
 *        up and inserting a row of blanks at the bottom row                *
 *        The current (cy) row is deleted.                                *
 ************************************************************************/

 wdel_row(wn)
 register WINDOW *wn;
 {
         int        rcode, scrlwn[4];

         /* Don't if we are not in the window. */
         if((rcode = wbound(wn)))
                 return(rcode);

         if(wn->cy == wn->ysize)
                 draw_row(wn->ulx+1, wn->uly + wn->cy,
                          wn->xsize, (wn->atrib <<8) |' ');
         else {
         /* calculate corners of the scrolling window */
                 scrlwn[0] = wn->ulx + 1;                /* ulx */
                 scrlwn[1] = wn->uly + wn->cy;                /* uly */
                 scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
                 scrlwn[3] = wn->uly + wn->ysize;        /* lry */

                 scrlup(scrlwn, 1, wn->atrib);
         }
         return(0);
 }


 /************************************************************************
 * wcls(), clear the "active" part of a window
 *        and "home" internal text cursor
 ************************************************************************/

 wcls(wn)
 register WINDOW *wn;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + 1;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrlup(scrlwn, 0, wn->atrib);
         wn->cx = 1;
         wn->cy = 1;
 }

 /************************************************************************
 * wceol(), clear to end of the line of the window.                        *
 ************************************************************************/

 wceol(wn)
 register WINDOW *wn;
 {
         register int tx, ty;

         if((tx=wbound(wn)))
                 return(tx);
         tx = wn->ulx + wn->cx;
         ty = wn->uly + wn->cy;
         draw_row(tx, ty, wn->xsize-wn->cx+1, (wn->atrib <<8) |' ');
         gotoxy(tx, ty, page);
         return(0);
 }

 /************************************************************************
 * wcursor(), cursor controls for a window.                                *
 ************************************************************************/

 wcursor(wn,c)
 register WINDOW *wn;
 {
         register int tcx, n, tx, ty;

         switch (c) {
                 case CUR_UP:        /* Cursor up */
                         --wn->cy;
                         break;
                 case CUR_DWN:        /* Cursor down */
                         ++wn->cy;
                         break;
                 case CUR_LEFT:        /* Cursor left */
                         --wn->cx;
                         break;
                 case CUR_RIGHT:        /* Cursor right */
                         ++wn->cx;
                         break;
                 case HOME:        /* Home cursor */
                         return set_wcxy(wn,1,1);
                 case END:        /* End cursor */
                         return set_wcxy(wn,1, wn->ysize);
                 default:
                         return(-1);
         }
         if(wn->cx <1) {
                 wn->cx = wn->xsize;
         } else if(wn->cx > wn->xsize)
                 wn->cx = 1;
         if(wn->cy <1)
                 wn->cy = wn->ysize;
         else if(wn->cy > wn->ysize)
                 wn->cy = 1;
         return set_wcxy(wn, wn->cx, wn->cy);
 }


 /************************************************************************
 * wdelch(), Deletes a character at the current window cursor position.
 ************************************************************************/

 wdelch(wn)
 register WINDOW *wn;
 {
         register int tx, ty, xend, rcode;

         /* Don't if we are not in the window. */
         if((rcode = wbound(wn))) {
                 --wn->cx;
                 return(rcode);
         }

         tx = wn->cx + wn->ulx;
         ty = wn->cy + wn->uly;
         xend = wn->ulx + wn->xsize;

         for(; tx < xend; ++tx)
                 vwrtch(tx, ty, vrdch(tx+1,ty));
         vwrtch(tx, ty, wn->atrib<<8 | ' ');

         return set_wcxy(wn, 0, 0);
 }


 /************************************************************************
 * winsch(), Inserts a character at the current window cursor position.
 ************************************************************************/

 winsch(wn,c)
 register WINDOW *wn;
 int c;
 {
         int tcx, tcy;
         register int tx, ty, n, rcode, xend;

         /* Don't if we are not in the window. */
         if((rcode = wbound(wn))) {
                 ++wn->cx;
                 return(rcode);
         }
         tcx = wn->cx;
         tcy = wn->cy;
         tx = wn->cx + wn->ulx;
         ty = wn->cy + wn->uly;
         switch (c) {
                 case '\n':
                         if(wn->cy == wn->ysize) {
                                 wscroll(wn);
                                 if(wn->cy >1)
                                         --ty;
                         } else {
                                 ++wn->cy;
                                 ++tcy;
                                 wins_row(wn);
                         }
                         for( ; wn->cx <= wn->xsize;) {
                                 wputchar(wn, (n=vrdch(tx,ty)));
                                 vwrtch(tx++, ty, (n&0xff00)|' ');
                         }
                         break;
                 case '\b':
                         --tcx;
                         if(wn->cy == 1 && wn->cx ==1)
                                 break;
                         n=vrdch(tx,ty);
                         wputch(wn,c);
                         wputchar(wn,n);
                         wdelch(wn);
                         return set_wcxy(wn,-1,0);
                 case '\r':
                          return wputch(wn, c);
                 case 0x09:        /* Tab */
                         do
                                 winsch(wn,' ');
                         while(wn->cx & 0x07);
                         break;
                 default:
                         c |= (wn->atrib<<8);
                         if(wn->cx == wn->xsize) {
                                 vwrtch(tx,ty,c);
                                 ++tcx;
                                 break;
                         }
                         xend = wn->ulx + wn->xsize;
                         for( ; tx < xend; c=n) {
                                 n=vrdch(tx++,ty);
                                 vputca(c, page, 1);
                         }
                         ++tcx;
                         break;
         }
         return set_wcxy(wn, tcx, tcy);
 }

 /************************************************************************
 * wgets(), Gets a string of characters at the current  window cursor        *
 *        position.  The number of characters to obtain cnt or reaching
 *        the end of the window terminates the function.  The number of
 *        charaters retrived is returned.
 ************************************************************************/

 wgets(wn,s,cnt)
 register WINDOW *wn;
 char *s;                /* Where to place the null terminated string.
 int cnt;                /* Number of character to retrive.                 */
 {
         int xend; register int tx, ty, n;

         if(wbound(wn))
                 return(0);
         tx = wn->ulx + wn->cx;
         ty = wn->uly + wn->cy;
         xend = wn->ulx + wn->xsize +1;
         for(n=0; cnt-- && tx < xend; ++n)
                 *s++ = vrdch(tx++, ty);
         *s = 0;
         return(n);
 }

 /************************************************************************
 * wscroll(), Scrolls the window up one line.                                *
 ************************************************************************/

 wscroll(wn)
 register WINDOW *wn;
 {
         int tcy;

         tcy = wn->cy;
         wn->cy =1;
         wdel_row(wn);
         wn->cy = tcy;
 }

 /************************************************************************
 * wbound(), Check to see if cursor is within the window.                *
 *        Returns a code indicating whether the cursor is in the window.  *
 ************************************************************************/

 wbound(wn)
 register WINDOW *wn;
 {
         register int rcode;

         rcode =0;
         if(wn->cx <1)
                 rcode = LEFT_OF;
         else if(wn->cx > wn->xsize)
                 rcode = RIGHT_OF;
         if(wn->cy <1)
                 rcode |= TOP_OF;
         else if(wn->cy > wn->ysize)
                 rcode |= BOTTOM_OF;
         return(rcode);
 }


 /************************************************************************
 * wgetch(), Returns the character at window cursor location or the        *
 *        boundry code if the location is not within the window.
 ************************************************************************/

 wgetch(wn)
 register WINDOW *wn;
 {
         int rcode;

         if((rcode=wbound(wn)))
                 return (rcode);
         return (vrdch(wn->ulx + wn->cx, wn->uly + wn->cy) &0xff);
 }

 /************************************************************************
 * set_wcxy(), Sets the relative window cursor to the give x,y location. *
 *        If either x or y is zero the cursor is moved in the given axis  *
 *         the number of spaces given, where positive x is to the right
 *        and positive y is down.
 *        Note that the home position for a window is 1,1.                *
 ************************************************************************/

 set_wcxy(wn,x,y)
 register WINDOW *wn;
 int x,y;
 {
         if(x && y) {
                 wn->cx = x;
                 wn->cy = y;
         } else {
                 if(!x && y)
                         wn->cy += y;
                 if(!y && x)
                         wn->cx += x;
         }
         gotoxy(wn->ulx + wn->cx, wn->uly + wn->cy, page);
         return wbound(wn);
 }


 /************************************************************************
 * get_wcxy(), Gets the relative window cursor.
 *        x = get_wcur() & 0xff, and y = get_wcur() >> 8
 *        Note that the home position for a window is 1,1.                *
 ************************************************************************/

 get_wcxy(wn)
 register WINDOW *wn;
 {
         return((wn->cy << 8) | wn->cx);
 }

 /************************************************************************
 * set_cxy(), Sets the screen cursor to the give x,y location.
 *        Note that the home position is 0,0.                                *
 ************************************************************************/

 set_cxy(x,y)
 register int x,y;
 {
         if(!x || !y) {
                 if(!x && y)
                         y += (getxy(page)>>8);
                 if(!y && x)
                         x += (getxy(page) & 0xff);
         }
         gotoxy(x,y,page);
 }


 /************************************************************************
 * get_cxy(), Gets the screen cursor location of page 0.
 *        x = get_wcur() & 0xff, and y = get_wcur() >> 8
 *        Note that the home position is 0,0.                                *
 ************************************************************************/

 get_cxy()
 {
         return(getxy(page));
 }

 /************************************************************************
 * get_page(), Gets the current video page being used.
 ************************************************************************/

 get_page()
 {
         return (page);
 }

 /************************************************************************
 * set_page(), Sets the active video page and udates page.                *
 ************************************************************************/

 set_page(n)
 char n;
 {
         switch (get_mode()) {
                 case 0:
                 case 1:
                         if(n > 7)
                                 return(-1);
                         break;
                 case 2:
                 case 3:
                         if(n > 3)
                                 return(-1);
                         break;
                 case 7:
                         if(n > 1)
                                 return(-1);
                         break;
                 default:
                         return(-1);
         }
         vsetpage(n);
         page = n;
         return(n);
 }

 /************************************************************************
 * wprintf(), Works like printf for a window.                                *
 ************************************************************************/

 wprintf(wn,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
 WINDOW *wn;
 char *cs;
 {
         static buf[256];

         sprintf(buf,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
         return wputs(wn,buf);
 }


 /************************************************************************
 * wprinta(), Works like wprintf with the addtion of the x,y                *
 *        position.                                                        *
 ************************************************************************/

 wprinta(x,y,wn,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
 int x,y;
 WINDOW *wn;
 char *cs;
 {
         set_wcxy(wn,x,y);
         return wprintf(wn,cs,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
 }


 WINDOW.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\WIND_C86\WINDOW.C

 /*        module:                window.c
  *        programmer:        Ray L. McVay
  *        started:        1 Aug 84
  *        version:        1.2, 23 Aug 84
  *
  *        A simple window package based on the article and programs
  *        by Edward Mitchell in the Jan 84 Dr. Dobb's Journal.  This
  *        implementation uses dynamically allocated buffers for the
  *        window control blocks and screen save buffers.
  *
  *        An assembly language support library called VLIB is used to
  *        interface the DeSmet C compiler with the IBM ROM BIOS video
  *        routines.  VLIB will undoubtedly have to be rewritten if the
  *        window package is to be used with other compilers.
  *
  *        History -
  *
  *        1.1        -        Added style member to wcb structure, clr_window
  *                        use of wn->cx for horizontal scrolling in write_tex
  *
  *        1.2 -        Added oldx, oldy members to wcb structure and use them
  *                        in draw_window() and remove_window().
  *
  *  Dec 84 - vlib.asm rewriten to assemble using MASM creating vlib.obj
  *           making it compatable with Computer Inovations C86 Compiler
  *           by Mike Elkins (619) 722-4363.
  */



 /************************************************************************
 * putch(), write a character and attribute to a specific XY location on *
 *                   the screen. The attribute is the high byte of the charact
 ************************************************************************/

 putch(x, y, c)
 int                x, y, c;
 {
         gotoxy_(x, y, 0);
         vputca_(c, 0, 1);
 }


 /************************************************************************
 * getch(), return the character and attribute at screen XY
 ************************************************************************/

 getch(x, y)
 int                x, y;
 {
         gotoxy_(x, y, 0);
         return(vgetc_(0));
 }


 /************************************************************************
 * draw_row(), output a row of one character/attribute at XY
 ************************************************************************/

 draw_row(x, y, count, c)
 int                x, y, count,c;
 {
         gotoxy_(x, y, 0);
         vputca_(c, 0, count);
 }


 /************************************************************************
 * draw_window(), open a window of given size with upper left corner at
 *                                 XY. Allocates buffers for the window contro
 *                                 screen save buffers. Copies overwritten scr
 *                                 buffer. Draws the blank window. Returns the
 *                                 the window control block or NULL if no buff
 ************************************************************************/

 WINDOWPTR draw_window(x, y, width, height, attrib)
 int                x, y, width, height, attrib;
 {
         WINDOWPTR wn;
         int                tx, ty,
                         xend, yend;
         int                *tptr;
         char        *calloc();

         if ((wn = (WINDOWPTR)calloc(1, sizeof(WINDOW))) == NULL)
                 return(NULL);
         else if ((wn->scrnsave = (int *)calloc((width+2) * (height+2), sizeof
         {
                 free(wn);
                 return(NULL);
         }
         else
         {
                 /* store parameters in window control block */

                 wn->ulx = x;
                 wn->uly = y;
                 wn->xsize = width;
                 wn->ysize = height;
                 wn->cx = 1;
                 wn->cy = 1;
                 wn->style = attrib;
                 attrib <<= 8;        /* will make things below go quicker */
                 wn->oldx = getxy_(0) & 255;
                 wn->oldy = getxy_(0) >> 8;

                 /* Copy existing text where the window will be placed */
                 /* to the scrnsave buffer. Obviously, a less portable */
                 /* routine could be much faster.

                 tptr = wn->scrnsave;
                 xend = x + width + 2;
                 yend = y + height + 2;

                 for (ty = y; ty < yend; ty++)
                 {
                         for (tx = x; tx < xend; tx++)
                                 *tptr++ = getch(tx, ty);
                 }

                 /* draw the window border and clear the text area */

                 putch(x, y, 0xda + attrib);
                 draw_row(x + 1, y, width, 0xc4 + attrib);        /* horiz bar
                 putch(x + width + 1, y, 0xbf + attrib);                /* ur

                 yend = y + height;

                 for (ty = y+1; ty <= yend; ty++)
                 {
                         putch(x, ty, 0xb3 + attrib);                        /
                         putch(x+width+1, ty, 0xb3 + attrib);
                 }

                 putch(x, y + height + 1, 0xc0 + attrib);
                 draw_row(x + 1, y + height + 1, width, 0xc4 + attrib);
                 putch(x + width + 1, y + height + 1, 0xd9 + attrib);        /

                 clr_window(wn);

                 return(wn);
         }
 }


 /************************************************************************
 * remove_window(), erase the window at the window control block.
 *                                   Must be the "top" window if overlapping w
 *                                   used. "Tiled" windows could be removed ra
 ************************************************************************/

 remove_window(wn)
 WINDOWPTR wn;
 {
         int                tx, ty,
                         xend, yend;
         int                *tptr;

         /* just repaint the saved text at the appropriate location */

         tptr = wn->scrnsave;
         xend = wn->ulx + wn->xsize + 2;
         yend = wn->uly + wn->ysize + 2;

         for (ty = wn->uly; ty < yend; ty++)
         {
                 for (tx = wn->ulx; tx < xend; tx++)
                         putch(tx, ty, *tptr++);
         }

         /* put cursor back where it was before this rude interruption */

         gotoxy_(wn->oldx, wn->oldy, 0);

         /* then release the dynamic storage used */

         free(wn->scrnsave);
         free(wn);
 }


 /************************************************************************
 * write_text(), print a string inside a window using cx, cy in WCB
 ************************************************************************/

 write_text(wn, string)
 WINDOWPTR wn;
 char        *string;
 {
         int                tx, ty, xend;

         /* first check to see if we're at the bottom of the window
         /* if we are then scroll the contents of the window up

         if (wn->cy > wn->ysize)
         {
                 delete_row(wn, 1);
                 --wn->cy;
         }

         /* Print as much of the string as will fit in the window.
          * cx is used for relative left margin. If cx is negative then
          * the first cx characters will be removed from the string to
          * allow horizontal scrolling in the window.
          * NOTE: This obviously simple-minded technique is usable for
          *                  displaying predetermined messages but a more gene
          *                 console output intercept should be used for Star-l
          *                 environments.

         if (wn->cx > 0)
                 tx = wn->ulx + wn->cx;
         else
         {
                 if (-wn->cx < strlen(string))
                         string -= wn->cx;
                 else
                         *string = '\0';
                 tx = wn->ulx + 1;
         }
         xend = wn->ulx + wn->xsize + 1;
         ty = wn->uly + wn->cy;
         while ((tx < xend) && *string)
         {
                 gotoxy_(tx++, ty, 0);
                 vputc_(*string++, 0, 1);
         }
         ++wn->cy;                /* move the internal cursor to the next line
 }


 /************************************************************************
 * insert_row(), insert a row of blanks by scrolling the lower portion
 *                                of a window down
 ************************************************************************/

 insert_row(wn, row)
 WINDOWPTR wn;
 int                row;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + row;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrldn_(scrlwn, 1, wn->style);
 }


 /************************************************************************
 * delete_row(), delete a row by scrolling the lower portion of a window *
 *                                up and inserting a row of blanks at the bott
 ************************************************************************/

 delete_row(wn, row)
 WINDOWPTR wn;
 int                row;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + row;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrlup_(scrlwn, 1, wn->style);
 }


 /************************************************************************
 * clr_window(), clear the "active" part of a window        and "home" interna
 *                                text cursor
 ************************************************************************/

 clr_window(wn)
 WINDOWPTR wn;
 {
         int                scrlwn[4];

         /* calculate corners of the scrolling window */

         scrlwn[0] = wn->ulx + 1;                        /* ulx */
         scrlwn[1] = wn->uly + 1;                        /* uly */
         scrlwn[2] = wn->ulx + wn->xsize;        /* lrx */
         scrlwn[3] = wn->uly + wn->ysize;        /* lry */

         scrlup_(scrlwn, 0, wn->style);
         wn->cx = 1;
         wn->cy = 1;
 }


 WINDOWS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MSC\MSC_WIND\WINDOWS.C

 #include <graph.h>
 #include <windows.h>


 void set_text_mode()
   {
   if (_setvideomode(_TEXTC80))
     {
     video_mode_set = _TEXTC80;
     video_base = 0xb800;
     }
   else
     if (_setvideomode(_TEXTBW80))
       {
       video_mode_set = _TEXTBW80;
       video_base = 0xb000;
       }
     else
       if (_setvideomode(_TEXTC40))
         {
         video_mode_set = _TEXTC40;
         video_base = 0xb800;
         }
       else
         if (_setvideomode(_TEXTBW40))
           {
           video_mode_set = _TEXTBW40;
           video_base = 0xb000;
           }
         else
           if (_setvideomode(_TEXTMONO))
             {
             video_mode_set = (_TEXTMONO);
             video_base = 0xb000;
             }
   }

 int makebxwindow(up_row, up_col, down_row, down_col, fore_color, back_color,
   border_fore, border_back)
   short up_row;
   short up_col;
   short down_row;
   short down_col;
   short fore_color;
   short back_color;
   short border_fore;
   short border_back;
   {
   int window_made = 1;
   int count;
   int max_count;
   short old_wrap;
   char hold_char[2];

   if (((down_row - up_row) < 3) || ((down_col - up_col) < 5))
     return(0);
   old_wrap = _wrapon(_GWRAPOFF);
   window_made = makewindow(up_row,up_col,down_row,down_col,
   border_fore,border_back);
   if (!window_made)
     {
     _wrapon(old_wrap);
     return(0);
     }
   hold_char[0] = UP_LEFT_CORNER;
   hold_char[1] = '\00';
   _outtext(hold_char);
   hold_char[0] = HORZ_LINE;
   max_count = (down_col - up_col) - 1;
   for (count = 0; count < max_count; count++)
     _outtext(hold_char);
   hold_char[0] = UP_RIGHT_CORNER;
   _outtext(hold_char);
   hold_char[0] = VERT_LINE;
   max_count = (down_row - up_row) + 1;
   for (count = 2; count < max_count; count++)
     {
     _settextposition(count, down_col);
     _outtext(hold_char);
     }
   _settextposition(down_row,1);
   hold_char[0] = DOWN_LEFT_CORNER;
   _outtext(hold_char);
   hold_char[0] = HORZ_LINE;
   max_count = (down_col - up_col) - 1;
   for (count = 0; count < max_count; count++)
     _outtext(hold_char);
   hold_char[0] = DOWN_RIGHT_CORNER;
   _outtext(hold_char);
   hold_char[0] = VERT_LINE;
   max_count = (down_row - up_row) + 1;
   for (count = 2; count < max_count; count++)
     {
     _settextposition(count, 1);
     _outtext(hold_char);
     }
   hold_char[0] = VERT_LINE;
   up_row += 1;
   up_col += 2;
   down_row -= 1;
   down_col -= 2;
   window_made = makewindow(up_row,up_col,down_row,down_col,
     fore_color,back_color);
   _wrapon(old_wrap);
   if (!window_made)
     return(0);
   else
     return(1);
   }


 int makewindow(up_row, up_col, down_row, down_col, fore_color, back_color)
   short up_row;
   short up_col;
   short down_row;
   short down_col;
   short fore_color;
   short back_color;
   {
   int num_bytes;
   int bytes_per_line;
   int loop;
   int start_pos;
   unsigned int vid_offset = 0;
   struct rccoord cp;
   struct videoconfig vc;

   if (window.current_window > (MAX_WINDOW_NUMBER - 1))
     return(0);
   _getvideoconfig(&vc);
   if ((down_row <= up_row) || (down_col <= up_col))
     return(0);
   if ((up_row < 1) || (up_row > vc.numtextrows))
     return(0);
   if ((up_col < 1) || (up_col > vc.numtextcols))
     return(0);
   if ((down_row < 1) || (down_row > vc.numtextrows))
     return(0);
   if ((down_col < 1) || (down_col > vc.numtextcols))
     return(0);
   if ((video_mode_set == _TEXTBW40) || (video_mode_set == _TEXTBW80) ||
     (video_mode_set == _TEXTMONO))
     {
     fore_color = WHITE;
     back_color = BLACK;
     }
   if (window.current_window == 0)
     {
     window.up_row[0] = 1;
     window.up_col[0] = 1;
     window.down_row[0] = vc.numtextrows;
     window.down_col[0] = vc.numtextcols;
     num_bytes = ((vc.numtextrows * vc.numtextcols) * 2);
     window.hold_address[0] = _fmalloc(num_bytes);
     movedata(video_base, 0x0000, FP_SEG(window.hold_address[0]),
       FP_OFF(window.hold_address[0]), num_bytes);
     }
   cp = _gettextposition();
   window.cursor_row[window.current_window] = cp.row;
   window.cursor_col[window.current_window] = cp.col;
   window.fore_color[window.current_window] = _gettextcolor();
   window.back_color[window.current_window] = _getbkcolor();
   window.current_window += 1;
   _settextcolor(fore_color);
   _setbkcolor(back_color);
   num_bytes = (((down_row - up_row) + 1) * ((down_col - up_col) + 1)) * 2;
   window.hold_address[window.current_window] = _fmalloc(num_bytes);
   bytes_per_line = ((down_col - up_col) + 1) * 2;
   for (loop = up_row; loop < (down_row + 1); loop++)
     {
     start_pos = (((loop - 1) * (vc.numtextcols * 2)) + ((up_col - 1) * 2));
     movedata(video_base, start_pos,
       FP_SEG(window.hold_address[window.current_window]),
       (FP_OFF(window.hold_address[window.current_window]) + vid_offset),
       bytes_per_line);
     vid_offset += bytes_per_line;
     }
   _settextwindow(up_row, up_col, down_row, down_col);
   _clearscreen(_GWINDOW);
   window.up_row[window.current_window] = up_row;
   window.up_col[window.current_window] = up_col;
   window.down_row[window.current_window] = down_row;
   window.down_col[window.current_window] = down_col;
   return(1);
   }

 int unmakebxwindow()
   {
   unmakewindow();
   unmakewindow();
   }

 int unmakewindow()
   {
   int loop;
   unsigned int vid_offset = 0;
   int start_pos;
   int bytes_per_line;
   struct rccoord cp;
   struct videoconfig vc;

   if (window.current_window == 0)
     return(0);
   _getvideoconfig(&vc);
   bytes_per_line = ((window.down_col[window.current_window] -
     window.up_col[window.current_window]) + 1) * 2;
   for (loop = window.up_row[window.current_window];
     loop < (window.down_row[window.current_window] + 1); loop++)
     {
     start_pos = (((loop - 1) * (vc.numtextcols * 2)) +
       ((window.up_col[window.current_window] - 1) * 2));
     movedata(FP_SEG(window.hold_address[window.current_window]),
     (FP_OFF(window.hold_address[window.current_window]) + vid_offset),
     video_base, start_pos, bytes_per_line);
     vid_offset += bytes_per_line;
     }
   window.current_window -= 1;
   _settextcolor(window.fore_color[window.current_window]);
   _setbkcolor(window.back_color[window.current_window]);
   _settextwindow(window.up_row[window.current_window],
     window.up_col[window.current_window],
     window.down_row[window.current_window],
     window.down_col[window.current_window]);
   _settextposition(window.cursor_row[window.current_window],
     window.cursor_col[window.current_window]);
   return(1);
   }



 WNDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\WINDKW\WNDEMO.C


 #include <stdio.h>
 #include "window.h"


 int        insert;                /* Global flag to indicate if in insert mod
 main()                        /* demonstration */
 {
         BORDER wborder;
         WINDOW *wn, *wn1, *wopen();
         char c;
         int i;

         insert =0;
         wborder.ul = 0x02da;
         wborder.ur = 0x02bf;
         wborder.ll = 0x02c0;
         wborder.lr = 0x02d9;
         wborder.v  = 0x02b3;
         wborder.h  = 0x02c4;

 /*
         for (i = 1; i < 25; i++)
           printf("The quick brown fox jumped over the lazy dog's back.\n");
 */
         set_page(0);
         if ((wn = wopen(&wborder,2, 2, 64, 18, (get_mode() < 4) ? 14 : 120))
                 == NULL)
         {
                 printf("\n--- Error opening first window\n");
                 exit(1);
         }
         show_mail(wn);

         if ((wn1 = wopen(&wborder, 15, 5, 30, 1, (get_mode() < 4) ? 14 :10))
                 == NULL)
         {
                 printf("\n--- Error opening second window\n");
                 exit(1);
         }
         wputstr(wn1, " Read your mail more often!");
         getch();
         wcursor(wn1, HOME);
         wins_row(wn1);

         getch();
         wclose(wn1);

         for (i = -4; i < 5; ++i)
         {
                 wcls(wn);
                 wn->xmargin = i;
                 show_mail(wn);
                 getch();
         }
         for(;;) {
                 switch ( (c = getch()) ) {
                         case 0:
                                 switch ( (c = getch()) ) {
                                         case INSERT:
                                                 insert = ~insert;
                                                 showcur(wn);
                                                 break;
                                         case DELETE:
                                                 hidecur();
                                                 wdelch(wn);
                                                 showcur(wn);
                                                 break;
                                         default:
                                                 if(wcursor(wn,c) <0) {
                                                         putch(7);
                                                         break;
                                                 }
                                                 showcur(wn);
                                                 break;
                                 }
                                 break;
                         case 0x17:                /* ^W */
                                 wclose(wn);
                                 if(get_page())
                                         set_page(0);
                                 else
                                         set_page(1);
                                 if ((wn = wopen(&wborder,0, 0, 78, 23,
                                  (get_mode() < 4) ? 14 : 120)) == NULL) {
                                   printf("\n--- Error opening first window\n"
                                  exit(1);
                                 }
                                 show_mail(wn);
                                 wprinta(10,0,wn,"\n\nPage %u", get_page());
                                 wcursor(wn, HOME);
                                 showcur(wn);

                                 break;
                         case 0x1b:                /* Esc */
                                 goto bye;
                         case 0x14:                /* ^T */
                                 hidecur();
                                 wceol(wn);
                                 showcur(wn);
                                 break;
                         case 0x19:                /* ^Y */
                                 hidecur();
                                 wdel_row(wn);
                                 showcur(wn);
                                 break;
                         default:
                                 hidecur();
                                 if(insert)
                                         winsch(wn, c);
                                 else
                                         wputch(wn, c);
                                 showcur(wn);
                                 break;
                 }
         }
 bye:        wclose(wn);
         exit(0);
 }

 hidecur()
 {
         curtype(15,14);
 }

 showcur(wn)
 WINDOW *wn;
 {
         if(wbound(wn)) {
                 hidecur();
         } else {
                 if(insert)
                         curtype(0,11);
                 else
                         curtype(10,11);
         }
 }

 show_mail(wn)                /* display the MAIL message */
 {
         hidecur();
         wputs(wn, "123456789-123456789-123456789-123456789-\r\n");
         wputs(wn, "\nMail System\r\n");
         wputs(wn, "-----------\r\n");
         wputs(wn, "Messages Received:  3\r\n");
         wputs(wn, "From          Date      Time\r\n");
         wputs(wn, "----         ------     ----\r\n");
         wputs(wn, "John         1/24/83    0935\r\n");
         wputs(wn, "Kim          1/23/83    1547\r\n");
         wputs(wn, "Sam          1/23/83    1117\r\n");
         wputs(wn, "\r\nEnter characters and use the cursor keys.\r\n");
         wputs(wn, "Also try ^T, ^Y and ^W.\r\n");
         wputs(wn,
         "\r\nAfter a while, the ESC character returns you back to DOS.\r\n");
         wputs(wn, "\r\n\n\t\t    Have fun!    ");
         showcur(wn);
 }


 WNDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\CI_C86\WIND_C86\WNDEMO.C

 /***************************************************************
 **      Dec 84  Converted to compile using CI C86 compiler    **
 **      Use   link wndemo+vlib,,,c86s2s  to link.             **
 **      by Mike Elkins (619) 722-4363                         **
 ***************************************************************/

 #include <stdio.h>
 #include <window.h>
 #include <window.c>

 main()        /* demonstration */
 {
     WINDOWPTR wn, wn1;
     int        i;

     /*
         for (i = 1; i < 25; i++)
                 printf("The quick brown fox jumped over the lazy dog's back.\
 */
 /*  Draw bottom window and fill with text from show_mail() below */
     if ((wn = draw_window(10, 3, 60, 10, 0x70)) == NULL) {
         printf("\n--- Error opening first window\n");
         exit(1);
     }
     show_mail(wn);

 /* Draw second window on top of first with reversed fore/background */
     if ((wn1 = draw_window(15, 5, 30, 3, 7 )) == NULL) {
         printf("\n--- Error opening second window\n");
         exit(1);
     }
     write_text(wn1, " Read your mail more often!");

     getchar();                        /* Wait for any key to be pressed */
     remove_window(wn1); /* Get rid of top window */


 /* This technique will cause the window to scroll from right to left */
     for (i = 5; i > -10; i -= 2) {
         clr_window(wn);
         wn->cx = i;
         show_mail(wn);
         getchar();
     }
     insert_row(wn, 4);   /* Insert an empty row  */
     getchar();
     wn->cy = 10;         /* Place cursor on tenth row */
     write_text(wn, "******************************");
     show_mail(wn);       /* scroll everything up */
     getchar();

     remove_window(wn);
     exit(0);
 }


 show_mail(wn)                /* display the MAIL message */
 {
     write_text(wn, "Mail System");
     write_text(wn, "-----------");
     write_text(wn, "Messages Received:  3");
     write_text(wn, "From          Date      Time");
     write_text(wn, "----         ------     ----");
     write_text(wn, "John         1/24/83    0935");
     write_text(wn, "Kim          1/23/83    1547");
     write_text(wn, "Sam          1/23/83    1117");
     write_text(wn, "This line of text should be truncated before here.");
 }




 WNDEMO.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\DESMET_C\WINDOW\WNDEMO.C


 #include <stdio.h>
 #include <window.h>

 main()        /* demonstration */
 {
         WINDOWPTR wn, wn1;
         int                i;

 /*
         for (i = 1; i < 25; i++)
                 printf("The quick brown fox jumped over the lazy dog's back.\
 */
         if ((wn = draw_window(10, 3, 30, 10, (get_mode() < 4) ? 7 : 0)) == NU
         {
                 printf("\n--- Error opening first window\n");
                 exit(1);
         }
         show_mail(wn);

         if ((wn1 = draw_window(15, 5, 30, 1, (get_mode() < 4) ? 0x70 : 255))
         {
                 printf("\n--- Error opening second window\n");
                 exit(1);
         }
         write_text(wn1, " Read your mail more often!");

         ci();
         remove_window(wn1);

         for (i = 5; i > -10; i -= 2)
         {
                 clr_window(wn);
                 wn->cx = i;
                 show_mail(wn);
                 ci();
         }

         remove_window(wn);
         exit(0);
 }


 show_mail(wn)                /* display the MAIL message */
 {
         write_text(wn, "Mail System");
         write_text(wn, "-----------");
         write_text(wn, "Messages Received:  3");
         write_text(wn, "From          Date      Time");
         write_text(wn, "----         ------     ----");
         write_text(wn, "John         1/24/83    0935");
         write_text(wn, "Kim          1/23/83    1547");
         write_text(wn, "Sam          1/23/83    1117");
         write_text(wn, "This line of text should be truncated before here.");
 }


 WORD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC1\WORD.C

 /*
  * The routines in this file implement commands that work word or a
  * paragraph at a time.  There are all sorts of word mode commands.  If I
  * do any sentence mode commands, they are likely to be put in this file.
  */

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 /* Word wrap on n-spaces. Back-over whatever precedes the point on the curren
  * line and stop on the first word-break or the beginning of the line. If we
  * reach the beginning of the line, jump back to the end of the word and star
  * a new line.        Otherwise, break the line at the word-break, eat it, an
  * back to the end of the word.
  * Returns TRUE on success, FALSE on errors.
  */
 wrapword(f, n)

 int f;                /* default flag */
 int n;                /* numeric argument */

 {
         register int cnt;        /* size of word wrapped to next line */
         register int c;                /* charector temporary */

         /* backup from the <NL> 1 char */
         if (!backchar(0, 1))
                 return(FALSE);

         /* back up until we aren't in a word,
            make sure there is a break in the line */
         cnt = 0;
         while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
                                 && (c != '\t')) {
                 cnt++;
                 if (!backchar(0, 1))
                         return(FALSE);
                 /* if we make it to the beginning, start a new line */
                 if (curwp->w_doto == 0) {
                         gotoeol(FALSE, 0);
                         return(lnewline());
                 }
         }

         /* delete the forward white space */
         if (!forwdel(0, 1))
                 return(FALSE);

         /* put in a end of line */
         if (!lnewline())
                 return(FALSE);

         /* and past the first word */
         while (cnt-- > 0) {
                 if (forwchar(FALSE, 1) == FALSE)
                         return(FALSE);
         }
         return(TRUE);
 }

 /*
  * Move the cursor backward by "n" words. All of the details of motion are
  * performed by the "backchar" and "forwchar" routines. Error if you try to
  * move beyond the buffers.
  */
 backword(f, n)
 {
         if (n < 0)
                 return (forwword(f, -n));
         if (backchar(FALSE, 1) == FALSE)
                 return (FALSE);
         while (n--) {
                 while (inword() == FALSE) {
                         if (backchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
                 while (inword() != FALSE) {
                         if (backchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
         }
         return (forwchar(FALSE, 1));
 }

 /*
  * Move the cursor forward by the specified number of words. All of the motio
  * is done by "forwchar". Error if you try and move beyond the buffer's end.
  */
 forwword(f, n)
 {
         if (n < 0)
                 return (backword(f, -n));
         while (n--) {
                 while (inword() == TRUE) {
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }

                 while (inword() == FALSE) {
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
         }
         return(TRUE);
 }

 /*
  * Move the cursor forward by the specified number of words. As you move,
  * convert any characters to upper case. Error if you try and move beyond the
  * end of the buffer. Bound to "M-U".
  */
 upperword(f, n)
 {
         register int        c;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);
         while (n--) {
                 while (inword() == FALSE) {
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
                 while (inword() != FALSE) {
                         c = lgetc(curwp->w_dotp, curwp->w_doto);
                         if (c>='a' && c<='z') {
                                 c -= 'a'-'A';
                                 lputc(curwp->w_dotp, curwp->w_doto, c);
                                 lchange(WFHARD);
                         }
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
         }
         return (TRUE);
 }

 /*
  * Move the cursor forward by the specified number of words. As you move
  * convert characters to lower case. Error if you try and move over the end o
  * the buffer. Bound to "M-L".
  */
 lowerword(f, n)
 {
         register int        c;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);
         while (n--) {
                 while (inword() == FALSE) {
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
                 while (inword() != FALSE) {
                         c = lgetc(curwp->w_dotp, curwp->w_doto);
                         if (c>='A' && c<='Z') {
                                 c += 'a'-'A';
                                 lputc(curwp->w_dotp, curwp->w_doto, c);
                                 lchange(WFHARD);
                         }
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
         }
         return (TRUE);
 }

 /*
  * Move the cursor forward by the specified number of words. As you move
  * convert the first character of the word to upper case, and subsequent
  * characters to lower case. Error if you try and move past the end of the
  * buffer. Bound to "M-C".
  */
 capword(f, n)
 {
         register int        c;

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (n < 0)
                 return (FALSE);
         while (n--) {
                 while (inword() == FALSE) {
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                 }
                 if (inword() != FALSE) {
                         c = lgetc(curwp->w_dotp, curwp->w_doto);
                         if (c>='a' && c<='z') {
                                 c -= 'a'-'A';
                                 lputc(curwp->w_dotp, curwp->w_doto, c);
                                 lchange(WFHARD);
                         }
                         if (forwchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                         while (inword() != FALSE) {
                                 c = lgetc(curwp->w_dotp, curwp->w_doto);
                                 if (c>='A' && c<='Z') {
                                         c += 'a'-'A';
                                         lputc(curwp->w_dotp, curwp->w_doto, c
                                         lchange(WFHARD);
                                 }
                                 if (forwchar(FALSE, 1) == FALSE)
                                         return (FALSE);
                         }
                 }
         }
         return (TRUE);
 }

 /*
  * Kill forward by "n" words. Remember the location of dot. Move forward by
  * the right number of words. Put dot back where it was and issue the kill
  * command for the right number of characters. With a zero argument, just
  * kill one word and no whitespace. Bound to "M-D".
  */
 delfword(f, n)
 {
         register LINE        *dotp;        /* original cursor line */
         register int        doto;        /*        and row */
         register int c;                /* temp char */
         long size;                /* # of chars to delete */

         /* don't allow this command if we are in read only mode */
         if (curbp->b_mode&MDVIEW)
                 return(rdonly());

         /* ignore the command if there is a negative argument */
         if (n < 0)
                 return (FALSE);

         /* Clear the kill buffer if last command wasn't a kill */
         if ((lastflag&CFKILL) == 0)
                 kdelete();
         thisflag |= CFKILL;        /* this command is a kill */

         /* save the current cursor position */
         dotp = curwp->w_dotp;
         doto = curwp->w_doto;

         /* figure out how many characters to give the axe */
         size = 0;

         /* get us into a word.... */
         while (inword() == FALSE) {
                 if (forwchar(FALSE, 1) == FALSE)
                         return(FALSE);
                 ++size;
         }

         if (n == 0) {
                 /* skip one word, no whitespace! */
                 while (inword() == TRUE) {
                         if (forwchar(FALSE, 1) == FALSE)
                                 return(FALSE);
                         ++size;
                 }
         } else {
                 /* skip n words.... */
                 while (n--) {

                         /* if we are at EOL; skip to the beginning of the nex
                         while (curwp->w_doto == llength(curwp->w_dotp)) {
                                 if (forwchar(FALSE, 1) == FALSE)
                                         return(FALSE);
                                 ++size;
                         }

                         /* move forward till we are at the end of the word */
                         while (inword() == TRUE) {
                                 if (forwchar(FALSE, 1) == FALSE)
                                         return(FALSE);
                                 ++size;
                         }

                         /* if there are more words, skip the interword stuff
                         if (n != 0)
                                 while (inword() == FALSE) {
                                         if (forwchar(FALSE, 1) == FALSE)
                                                 return(FALSE);
                                         ++size;
                                 }
                 }

                 /* skip whitespace and newlines */
                 while ((curwp->w_doto == llength(curwp->w_dotp)) ||
                         ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') ||
                         (c == '\t')) {
                                 if (forwchar(FALSE, 1) == FALSE)
                                         break;
                                 ++size;
                 }
         }

         /* restore the original position and delete the words */
         curwp->w_dotp = dotp;
         curwp->w_doto = doto;
         return (ldelete(size, TRUE));
 }

 /*
  * Kill backwards by "n" words. Move backwards by the desired number of words
  * counting the characters. When dot is finally moved to its resting place,
  * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  */
 delbword(f, n)
 {
         long size;

         /* don't allow this command if we are in read only mode */
         if (curbp->b_mode&MDVIEW)
                 return(rdonly());

         /* ignore the command if there is a nonpositive argument */
         if (n <= 0)
                 return (FALSE);

         /* Clear the kill buffer if last command wasn't a kill */
         if ((lastflag&CFKILL) == 0)
                 kdelete();
         thisflag |= CFKILL;        /* this command is a kill */

         if (backchar(FALSE, 1) == FALSE)
                 return (FALSE);
         size = 0;
         while (n--) {
                 while (inword() == FALSE) {
                         if (backchar(FALSE, 1) == FALSE)
                                 return (FALSE);
                         ++size;
                 }
                 while (inword() != FALSE) {
                         ++size;
                         if (backchar(FALSE, 1) == FALSE)
                                 goto bckdel;
                 }
         }
         if (forwchar(FALSE, 1) == FALSE)
                 return (FALSE);
 bckdel:        return (ldelete(size, TRUE));
 }

 /*
  * Return TRUE if the character at dot is a character that is considered to b
  * part of a word. The word character list is hard coded. Should be setable.
  */
 inword()
 {
         register int        c;

         if (curwp->w_doto == llength(curwp->w_dotp))
                 return (FALSE);
         c = lgetc(curwp->w_dotp, curwp->w_doto);
         if (c>='a' && c<='z')
                 return (TRUE);
         if (c>='A' && c<='Z')
                 return (TRUE);
         if (c>='0' && c<='9')
                 return (TRUE);
         return (FALSE);
 }

 #if        WORDPRO
 fillpara(f, n)        /* Fill the current paragraph according to the current
                    fill column

 int f, n;        /* deFault flag and Numeric argument */

 {
         register int c;                        /* current char durring scan
         register int wordlen;                /* length of current word
         register int clength;                /* position on line during fill
         register int i;                        /* index during word copy
         register int newlength;                /* tentative new line length
         register int eopflag;                /* Are we at the End-Of-Paragrap
         register int firstflag;                /* first word? (needs no space
         register LINE *eopline;                /* pointer to line just past E
         register int dotflag;                /* was the last char a period?
         char wbuf[NSTRING];                /* buffer for current word

         if (curbp->b_mode&MDVIEW)        /* don't allow this command if
                 return(rdonly());        /* we are in read only mode        *
         if (fillcol == 0) {        /* no fill column set */
                 mlwrite("No fill column set");
                 return(FALSE);
         }

         /* record the pointer to the line just past the EOP */
         gotoeop(FALSE, 1);
         eopline = lforw(curwp->w_dotp);

         /* and back top the beginning of the paragraph */
         gotobop(FALSE, 1);

         /* initialize various info */
         clength = curwp->w_doto;
         if (clength && curwp->w_dotp->l_text[0] == TAB)
                 clength = 8;
         wordlen = 0;
         dotflag = FALSE;

         /* scan through lines, filling words */
         firstflag = TRUE;
         eopflag = FALSE;
         while (!eopflag) {
                 /* get the next character in the paragraph */
                 if (curwp->w_doto == llength(curwp->w_dotp)) {
                         c = ' ';
                         if (lforw(curwp->w_dotp) == eopline)
                                 eopflag = TRUE;
                 } else
                         c = lgetc(curwp->w_dotp, curwp->w_doto);

                 /* and then delete it */
                 ldelete(1L, FALSE);

                 /* if not a separator, just add it in */
                 if (c != ' ' && c != '\t') {
                         dotflag = (c == '.');                /* was it a dot
                         if (wordlen < NSTRING - 1)
                                 wbuf[wordlen++] = c;
                 } else if (wordlen) {
                         /* at a word break with a word waiting */
                         /* calculate tantitive new length with word added */
                         newlength = clength + 1 + wordlen;
                         if (newlength <= fillcol) {
                                 /* add word to current line */
                                 if (!firstflag) {
                                         linsert(1, ' '); /* the space */
                                         ++clength;
                                 }
                                 firstflag = FALSE;
                         } else {
                                 /* start a new line */
                                 lnewline();
                                 clength = 0;
                         }

                         /* and add the word in in either case */
                         for (i=0; i<wordlen; i++) {
                                 linsert(1, wbuf[i]);
                                 ++clength;
                         }
                         if (dotflag) {
                                 linsert(1, ' ');
                                 ++clength;
                         }
                         wordlen = 0;
                 }
         }
         /* and add a last newline for the end of our new paragraph */
         lnewline();
         return(TRUE);
 }

 killpara(f, n)        /* delete n paragraphs starting with the current one */

 int f;        /* default flag */
 int n;        /* # of paras to delete */

 {
         register int status;        /* returned status of functions */

         while (n--) {                /* for each paragraph to delete */

                 /* mark out the end and beginning of the para to delete */
                 gotoeop(FALSE, 1);

                 /* set the mark here */
                 curwp->w_markp = curwp->w_dotp;
                 curwp->w_marko = curwp->w_doto;

                 /* go to the beginning of the paragraph */
                 gotobop(FALSE, 1);
                 curwp->w_doto = 0;        /* force us to the beginning of lin

                 /* and delete it */
                 if ((status = killregion(FALSE, 1)) != TRUE)
                         return(status);

                 /* and clean up the 2 extra lines */
                 ldelete(2L, TRUE);
         }
         return(TRUE);
 }


 /*        wordcount:        count the # of words in the marked region,
                         along with average word sizes, # of chars, etc,
                         and report on them.                        */

 wordcount(f, n)

 int f, n;        /* ignored numeric arguments */

 {
         register LINE *lp;        /* current line to scan */
         register int offset;        /* current char to scan */
         long size;                /* size of region left to count */
         register int ch;        /* current character to scan */
         register int wordflag;        /* are we in a word now? */
         register int lastword;        /* were we just in a word? */
         long nwords;                /* total # of words */
         long nchars;                /* total number of chars */
         int nlines;                /* total number of lines in region */
         int avgch;                /* average number of chars/word */
         int status;                /* status return code */
         REGION region;                /* region to look at */

         /* make sure we have a region to count */
         if ((status = getregion(&region)) != TRUE)
                 return(status);
         lp = region.r_linep;
         offset = region.r_offset;
         size = region.r_size;

         /* count up things */
         lastword = FALSE;
         nchars = 0L;
         nwords = 0L;
         nlines = 0;
         while (size--) {

                 /* get the current character */
                 if (offset == llength(lp)) {        /* end of line */
                         ch = '\n';
                         lp = lforw(lp);
                         offset = 0;
                         ++nlines;
                 } else {
                         ch = lgetc(lp, offset);
                         ++offset;
                 }

                 /* and tabulate it */
                 wordflag = ((ch >= 'a' && ch <= 'z') ||
                             (ch >= 'A' && ch <= 'Z') ||
                             (ch >= '0' && ch <= '9'));
                 if (wordflag == TRUE && lastword == FALSE)
                         ++nwords;
                 lastword = wordflag;
                 ++nchars;
         }

         /* and report on the info */
         if (nwords > 0L)
                 avgch = (int)((100L * nchars) / nwords);
         else
                 avgch = 0;

         mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
                 nwords, nchars, nlines + 1, avgch);
         return(TRUE);
 }
 #endif


 WPRO1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\WPRO1.C

 /* WPRO1.C - From page 355 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. This is a rudimentary one line    */
 /* word processor.                                              */
 /****************************************************************/

 "dos.h"           /*for REGS definition*/
 #define TRUE 1
 COMAX 80           /*max num of cols*/
 #define R_ARRO 77
 #define L_ARRO 75
 VIDEO 0x10         /*video ROM BIOS service*/
 int col = 0;               /*cursor position*/
 int far *farptr;
 union REGS regs;           /*for ROM BIOS calls*/

 main()
 {
 char ch;

    farptr = (int far *) 0xB0000000;    /*start of screen memory*/
    clear();
    cursor();                           /*position cursor*/
    while(TRUE) {
       if ((ch = getch()) == 0) {
          ch = getch();                 /*read extended code*/
          switch(ch) {
             case R_ARRO:
                if (col < COMAX)
                   ++col;
                break;
             case L_ARRO:
                if (col > 0)
                   --col;
                break;
          }
       }
       else                             /*not extended code*/
          if (col < COMAX)
             insert(ch);                /*print char at col*/
       cursor();                        /*reset cursor*/
    }
 }

 /* cursor */  /*move cursor to row = 0, col */
 cursor()
 {

    regs.h.ah = 2;                /* 'set cursor position service */
    regs.h.dl = col;              /*column varies*/
    regs.h.dh = 0;                /*always top row*/
    regs.h.bh = 0;                /*page zero*/
    int86(VIDEO, &regs, &regs);   /*call video int*/
 }

 /* insert() */  /*inserts char at cursor position*/
 insert(ch)
 char ch;
 {
 int j;

    *(farptr + col) = ch | 0x700;       /*insert char*/
    ++col;                              /*move cursor right*/
 }

 /* clear */      /*clears screen using direct memory access*/
 clear()
 {
 int j;

    for(j = 0; j < 2000; j++)           /*fill screen mem with*/
       *(farptr + j) = 0x0700;          /*zeros   (attrib=07) */
 }



 WPRO2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_01\WPRO2.C

 /* WPRO2.C - From page 362 of "Microsoft C Programming for      */
 /* the IBM" by Robert Lafore. This adds some more features to   */
 /* the WPRO1.C simple word processor on this disk. Hit Alt-     */
 /* u to toggle underline on and off. I changed the switch       */
 /* statement to enable the right arrow key when cursor is       */
 /* at the last column.                                          */
 /****************************************************************/

 "dos.h"           /* for REGS definition */
 #define TRUE 1
 COMAX 80           /* max number of columns */
 #define R_ARRO 77
 #define L_ARRO 75
 #define BK_SPC 8
 ALT_U 22           /* [Alt] and [u] keys */
 VIDEO 0x10         /* video ROM BIOS service */
 NORM 0x07          /* normal attribute */
 UNDR 0x01          /* underline attribute */
 int col = 0;               /* cursor position */
 int length = 0;            /* length of phrase */
 int far *farptr;           /* pointer to screen memory */
 union REGS regs;           /* for ROM BIOS calls */

 main()
 {
 char ch, attr = NORM;

    farptr = (int far *) 0xB0000000;    /*start of screen mem*/
    clear();
    cursor();
    while(TRUE) {
       if ((ch = getch()) == 0) {       /*if extended code key*/
          ch = getch();                 /*read extended code*/
          switch(ch) {
             case R_ARRO: {
                if (col < length) {
                   ++col;
                   break;
                }
                else if (col >= length) {
                   ++col;
                   ++length;
                   break;
                }
             }
             case L_ARRO:
                if (col > 0)
                   --col;
                break;
             case ALT_U:
                attr = (attr == NORM) ? UNDR : NORM;
          }
       }
       else
          switch(ch) {
             case BK_SPC:
                if (length > 0)
                   delete();
                break;
             default:
                if (length < COMAX)
                   insert(ch, attr);
          }
       cursor();
    }                    /* end while */
 }                       /* end main */

 /* cursor() */    /* move cursor to row = 0, col */
 cursor()
 {
 regs.h.ah = 2;       /* 'set cursor pos' service */
 regs.h.dl = col;     /* column varies */
 regs.h.dh = 0;       /* always top row */
 regs.h.bh = 0;       /* page zero */

    int86(VIDEO, &regs, &regs);     /* call video interrupt */
 }

 /* insert() */    /*inserts cursor at cursor position */
 insert(ch, attr)
 char ch, attr;
 {
 int j;

    for (j = length; j > col; j--)         /* shift chars right */
       *(farptr + j) = *(farptr + j -1);   /*     to make room */
    *(farptr + col) = ch | attr << 8;      /* insert char */
    ++length;                              /* increment count */
    ++col;                                 /* move cursor right */
 }

 /* delete() */    /* deletes char at pos 1 left of cursor */
 delete()
 {
 int j;

    for(j = col; j <= length; j++)         /* shift chars left */
       *(farptr + j - 1) = *(farptr + j);
    --length;                              /* decrement count */
    --col;                                 /* move cursor left */
 }

 /* clear() */  /*clears screen by inserting 0 at every location */
 clear()
 {
 int j;

    for(j = 0; j < 2000; j++)
       *(farptr + j) = 0x0700;    /* zeros with attr = 07 */
 }



 WRITE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\FUNC\MATH\WRITE.C


 /***********************************************************
  *     IBM PC "C" Bulletin Board                           *
  *     Tulsa, OK  918-664-8737                             *
  *     SYSOP Lynn Long   300/1200 XMODEM                   *
  ***********************************************************/


 #include "io.h"
 #include "errno.h"

 int filewr(), badfd(), conwr();

 static int (*wrt_tab[])() = {
         badfd, filewr, conwr,
 };

 write(fd, buff, len)
 char *buff;
 {
         register struct channel *chp;

         if (fd < 0 || fd > MAXCHAN) {
                 errno = EBADF;
                 return -1;
         }
         chp = &chantab[fd];
         return (*wrt_tab[chp->c_write])(chp->c_arg, buff, len);
 }

 conwr(kind, buff, len)
 register char *buff;
 {
         register int count;

         for (count = 0 ; count < len ; ++count)
                 bdos(kind, *buff++);
         return count;
 }




 WRITEF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\WRITEF.C

 /* WRITEF.C - From page 441 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. This program writes formatted     */
 /* data to a file. To use, enter data at prompt as follows:     */
 /*   Bond 007 74.5 <return>.   To exit after entering desired   */
 /* number of lines, enter at prompt:   x 0 0 <return>.          */
 /* This program will not work correctly if the DOS type comm-   */
 /* and is used to read it. To read the file, use READF.C, also  */
 /* on this disk. The file WRITEF_A.C on this disk can be read   */
 /* with the DOS type command.                                   */
 /****************************************************************/

 #include <stdio.h>

 main()
 {
 FILE *fptr;
 char name[40];
 int code;
 float height;

    fptr = fopen("c:textfile.txt", "w");
    do {
       printf("Type name, code number, and height: ");
       scanf("%s %d %f", name, &code, &height);
       fprintf(fptr, "%s %d %f", name, code, height);
    } while(strlen(name) > 1);              /* no name given ? */
    fclose(fptr);
 }



 WRITEF2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\WRITEF2.C

 /* WRITEF2.C - From page 459 of "Microsoft C Programming for    */
 /* the IBM" by Robert Lafore. This program writes formatted     */
 /* data to a file. To use, enter data at prompt as follows:     */
 /*   Bond 007 74.5 <return>.   To exit after entering desired   */
 /* number of lines, enter at prompt:   x 0 0 <return>.          */
 /* This program will not work correctly if the DOS type comm-   */
 /* and is used to read it. To read the file, use READF.C, also  */
 /* on this disk. The file WRITEF_A.C on this disk can be read   */
 /* with the DOS type command.                                   */
 /****************************************************************/

 #include <stdio.h>

 main()
 {
 FILE *fptr;
 char name[40];
 int code;
 float height;

    if((fptr = fopen("c:textfile.txt", "w")) == NULL) {
       printf("\nCan't open textfile.txt");
       exit();
    }
    do {
       printf("Type name, code number, and height: ");
       scanf("%s %d %f", name, &code, &height);
       fprintf(fptr, "%s %d %f", name, code, height);
       if (ferror(fptr)) {
          perror("Write error");
          fclose(fptr);
          exit();
       }
    } while(strlen(name) > 1);              /* no name given ? */
    fclose(fptr);
 }



 WRITEF_A.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\WRITEF_A.C

 /* WRITEF_A.C - From page 441 of "Microsoft C Programming for   */
 /* the IBM" by Robert Lafore. This program writes formatted     */
 /* data to a file. To use, enter data at prompt as follows:     */
 /*   Bond 007 74.5 <return>.   To exit after entering desired   */
 /* number of lines, enter at prompt:   x 0 0 <return>.          */
 /* This program has been changed from what's in the book to     */
 /* make it work correctly. The book version, WRITEF.C is also   */
 /* on this disk to use in conjunction with READF.C              */
 /****************************************************************/

 #include <stdio.h>

 main()
 {
 FILE *fptr;
 char name[40];
 int code;
 float height;
 int count = 0;

    fptr = fopen("c:textfile.txt", "w");
    while((strlen(name) > 1) || count == 0) { /* no name given ? */
       count++;
       printf("Type name, code number, and height: ");
       scanf("%s %d %f", name, &code, &height);
       if(strlen(name) > 1) {
          fprintf(fptr, "%-10s %03d %f", name, code, height);
          fprintf(fptr, "\n");
       }
    }
    fclose(fptr);
 }



 WRITER.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\WRITER.C

 /* WRITER.C - From page 448 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. Writes structures to a file us-   */
 /* ing the record I/O method of performing standard I/O. Ano-   */
 /* ther name for record I/O is block I/O. Record I/O writes to  */
 /* files in binary. NOTE!!!! This program will not link cor-    */
 /* rectly with Quick C. It gives Fatal error L1101 & manual     */
 /* recommends contacting Microsoft.                             */
 /****************************************************************/

 #include "stdio.h"

 main()
 {
 struct {
    char name[40];
    int agnumb;
    float height;
 } agent;
 float dummy = 0.0;
 FILE *fptr;

    if((fptr = fopen("agents.rec", "wb")) == NULL) {
       printf("\nCan't open file agents.rec");
       exit();
    }
    do {
       printf("\nEnter name: ");
       gets(agent.name);
       printf("Enter number: ");
       scanf("%d", &agent.agnumb);
       printf("Enter height: ");
       scanf("%f", &agent.height);
       fflush(stdin);                   /*flush keyboard buffer*/
       fwrite(&agent, sizeof(agent), 1, fptr);
       printf("Add another agent (y/n) ? ");
    } while(getche() == 'y');
    fclose(fptr);
 }



 WRITES.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\R_LA4_02\WRITES.C

 /* WRITES.C - From page 437 of "Microsoft C Programming for     */
 /* the IBM" by Robert Lafore. Writes the file C:TEXTFILE.TXT,   */
 /* typed at keyboard, to disk.                                  */
 /****************************************************************/

 #include <stdio.h>

 main()
 {
 FILE *fptr;
 char string[81];

    fptr = fopen("c:textfile.txt", "w");
    while(strlen(gets(string)) > 0) {
       fputs(string, fptr);             /*write string to file*/
       fputs("\n", fptr);
    }
    fclose(fptr);
 }



 WRTMORE.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\WRTMORE.C

 main()
 {
    printf("This is a line of text to output.\n");
    printf("And this is another ");
    printf("line of text.\n\n");
    printf("This is a third line.\n");
 }


 WRTSOME.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CSOURCE\WRTSOME.C

 main()
 {
    printf("This is a line of text to output.");
 }


 WTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\AZTEC_C\WINDKW\WTEST.C

 #include <stdio.h>
 #include "window.h"
 #include <signal.h>
 void (*signal())();
 char color[] =
 {
         14,13,12,11,10
 };

 main()
 {
         int i,j,k;
         WINDOW *wopen(), *windows[5];
         BORDER wborder;
         (void)signal(SIGINT,SIG_IGN);
         set_page(1);

         wborder.ul = 0x3BDA;
         wborder.ur = 0x3BBF;
         wborder.ll = 0x3BC0;
         wborder.lr = 0x3BD9;
         wborder.v  = 0x3BB3;
         wborder.h  = 0x3BC4;
         for (i = 0; i < 5; i++)
         {
                 if (NULL ==
                         (windows[i] =
                         wopen(&wborder,(i * 10),        /* x */
                                                    (i * 4),                /*
                                                    30,10,
                                                    color[i]
                    )))
                 {
                         set_page(0);
                         printf("Error opening window #%d\n",i);
                         goto bye;
                 }
                 wcls(windows[i]);
                 for (j = 0; j < 9; j++)
                         wprintf(windows[i],"Hello everybody from window %d!!!
                                 i);
         }
         for (i = 4 ; i >= 0; i--)
         {
                 bdos(7);
                 wclose(windows[i]);
         }
 bye:
         set_page(0);
         exit(0);
 }


 WTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\UCTURBO\WTEST.C

 #include <stdio.h>
 #include <window.h>
 #include <border.h>

 int insert;

 main()
 {
    WINDOW *wn, *wn1, *wn2, *wopen();
    char a[80];
    char b[80];


    bdr21.att = 0x014;

 insert = 0;

 if ((wn = wnopen(&bdr21, 10,2,60,10, 0x01e)) == NULL)
 {
    printf("\n--- Error opening window wn\n");
    exit(1);
 }
 hidecur();
 wnputs(wn, "\r\n                Unicorn Software                   \r\n");
 wnputs(wn, "                  is proud to present\r\n");
 wnputs(wn, "  The Unicorn Window functions.  Many functions are \r\n");
 wnputs(wn, "  available for your pleasure.  Type your name please\r\n");
 wnputs(wn, "\r\n\Press any key to continue.\r\n");
 showcur();
 wnputs(wn, "Your name is - ");
 gets(a);
 wngets(wn, b, 8);

 if ((wn2 = wnopen(&bdr12, 15,13,30,5, 0x05f)) == NULL)
 {
    printf("\n--- Error opening window wn2\n");
 }
 hidecur();
 wnputs(wn2, "This is window wn2\r\n");
 wnputs(wn2, "Hello there  ");
 wnputs(wn2, b);
 wnputs(wn2, ", How\r\nare you today?");
 wnputs(wn2, "\r\n\r\nPress any key to continue.\r\n");
 gets(a);


 if ((wn1 = wnopen(&bdr1r, 5,5,70,9, 0x04c)) == (WINDOW *) NULL)
 {
    printf("\n--- Error opening window wn1\n");
 }

 hidecur();
 wnputs(wn1, "This is window wn1\r\n");
 wnputs(wn1, "Press any key to continue.\r\n");
 gets(a);
 wnclose(wn1);
 gets(a);
 wnclose(wn2);


 wnputs(wn, "\r\nBack in  window wn now press any key to\r\n");
 wnputs(wn, "Return to dos\r\n");
 gets(a);
 wnclose(wn);
 showcur();

 }


 hidecur()
 {
   wsetcurt(10,9);
 }


 showcur()
 {
   wsetcurt(6,7);
 }





 WTUTOR10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\WINDOW10\WTUTOR10.C

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <dos.h>
 #include <conio.h>
 #include <w1.h>
 #include <windprot.h>
 #include <color.h>

 #define RETKEY       13
 #define ESCKEY       27
 #define TRUE         1
 #define FALSE        0

 typedef char str80[80];
 extern wndwstattype wndwstat[MAXWNDW];/*  window stats  */
 extern byteptr      wndwptr[MAXWNDW];/*  pointer to window on heap  */
 extern byte         li, licurrent;/*  level index, level index for swapping w

 void         show30windows(void);
 void         showinitialscreen(void);
 void         showgeneral(void);
 void         showlist(void);
 void         showinitwindow(void);
 void         showborders(void);
 void         showremovewindow(void);
 void         showmakewindow(void);
 void         showflicker(void);
 void         showscrollwindow(void);
 void         showtitlewindow(void);
 void         showspecialeffects(void);
 void         showmaxwndw(void);
 void         showqwik21(void);
 void         showprogramming(void);
 void         showeditor(void);
 void         readkb(int *);
 void         getkey(void);
 void         findnextstep(void);
 void         showwindows(void);
 int          random(int);


     int          i, j, k, m;
     int          oldcursor, battr, step ;
     int          key;

     static str80        stra[16] = {
       "",
       "The windowing functions in  the file  WINDOW10.LIB",
       "are  a  set of public domain routines  that  allow",
       "Turbo C  to  create  incredibly fast multi - level",
       "windows.   Created  under  the  Teamware  concept,",
       "WINDOW10.LIB makes use of the quick screen writing",
       "utilities  of Jim H. LeMay -- which were converted",
       "from Turbo Pascal inline to external assembly. The",
       "windows may  be  of any  size  (from 2x2 to screen",
       "limits)  and  color  and  may  have one of several",
       "different  border  styles and colors including  no",
       "border.  They  also   work   in any   column  mode",
       "40/80/etc.  These routines automatically configure",
       "to your video card and  video  mode. All of  these",
       "routines were converted from Turbo Pascal to Turbo",
       "C, (SMALL MODEL) with the authors permission.     "};

     static str80        strb[11] = {
       "The window function package",
       "consists of five functions;",
       "",
       "      initwindow()",
       "      makewindow()",
       "      scrollwindow()",
       "      removewindow()",
       "      titlewindow()",
       "",
       "The functions are described",
       "in the following windows:"};

     static str80        strc[8] = {
       "initwindow",
       "",
       "FORMAT:   void initwindow (int windowattribute);",
       "",
       "Initwindow initializes  several variables required  by  the",
       "windowing package,  as well as selecting the foreground and",
       "background colors of the initial screen display. Initwindow",
       "must be called before using any of the other functions.    "};

     static str80        strd[17] = {
       "makewindow",
       "",
       "FORMAT:  void makewindow (int row,col,rows,cols,wattr,battr;",
       "                                            BORDERS brdrsel);",
       "",
       "Makewindow puts a new blank window on the display.  The window starts"
       "at the upper left corner (row,col)  and extends for a number of  rows"
       "and columns (rows,cols).   If a border exists, the actual  dimensions"
       "of the Turbo C window will be 2 less than indicated in the makewindow"
       "statement.  The border can be one of the following: (SEE w1.h)",
       "",
       "   nobrdr     - just window       evensolidbrdr - evenly solid",
       "   blankbrdr  - blank spaces      thinsolidbrdr - thin solid line",
       "   singlebrdr - single line       lhatchbrdr - light hatch",
       "   doublebrdr - double line       mhatchbrdr - medium hatch",
       "   mixedbrdr  - single/double     hhatchbrdr - heavy hatch",
       "   solidbrdr  - solid             userbrdr   - user defined border"};

     static str80        stre[6] = {
       "removewindow",
       "FORMAT:   void removewindow(void);",
       "",
       "Removewindow removes the last window",
       "remaining  on  the screen  from  the",
       "makewindow function."};

     static str80        strf[2] = {
       "See if your BIOS gives you flicker",
       "when your screen rolls down next ..."};

     static str80        strg[19] = {
       "",
       "    scrollwindow",
       "",
       "",
       "FORMAT:  void scrollwindow (byte rowbegin,rowend byte; DIRTYPE dir);",
       "",
       "The BIOS scroll that was used for this call may have worked just fine"
       "for this window.  However, if  your screen just had some bad flicker "
       "as it was scrolling down, your BIOS is not flicker-free.  To keep the"
       "display flicker-free,  to work on other  video pages  or an EGA, then"
       "you will need this function.  The upward  scroll, used scrollwindow, "
       "so no flicker was seen then.  It also scrolls partial windows.",
       "",
       "The direction of the scroll can be any of the following:(SEE w1.h)",
       "",
       "    'up'   - to scroll up",
       "    'down' - to scroll down",
       "",
       ""};

     static str80        strh[6] = {
       "titlewindow",
       "FORMAT:   void titlewindow (justify;title);",
       "                   int justify; title str80",
       "Titlewindow places a title in the top border",
       "of the current window.  Justify permits left,",
       "center or right justification of the title."};

     static str80        stri[18] = {
       "There are now two special effects that can",
       "enhance the window display:",
       "   zoomeffect   - emulates the MACINTOSH.",
       "   shadoweffect - places a left or right",
       "              shadow underneath the menu.",
       "These global variables can be placed anywhere",
       "in your program.  zoomEffect is INT while",
       "shadoweffect is of DIRtYPE.",
       "                             press RETURN ...",
       "CGA:",
       "The CGA is self-regulating and controls the",
       "zoom rate.",
       "MDA and EGA:",
       "These video cards are quite fast and need a",
       "delay for the effect.  A default value of 11",
       "milliseconds is used in a global INT",
       "named 'zoomdelay' and shouldn't need any",
       "adjustment."};

     static str80        strj[5] = {
       " The maximum  number  of windows that",
       " may be on the screen at any one time",
       " is   specified   by   the   constant",
       " \"MAXWNDW\".The compiled library uses",
       " this value so do NOT change it......"};

     static str80        strk[9] = {
       " In addition to windows, there are 15 powerful",
       " Q screen write functions  you can use:",
       "      qwritelv   qfillc     qstore",
       "      qwritev    qfill      qrestore",
       "      qwrite     qattr      qpage",
       "      qwritec    qattrc     qwritepage",
       "      qwritecv   gotorc     cursorchange ",
       " In WINDOW10.ARC, compile and run QDEMO.C to see",
       " all of these features."};

     static str80        strl[20] = {
       " The functions are used as follows:",
       "",
       "  ....Your include files....",
       "  #include <w1.h> ",
       "  #include <windprot.h> ",
       "  #include <color.h> ",
       "  ...Your variables and functions...",
       "  main(argc,argv)",
       "    {",
       "    initwindow (windowattribute);",
       "    makewindow (row,col,rows,cols,wattr,battr,",
       "                                     brdrsel);",
       "    titlewindow (justify,'the window title');",
       "    removewindow();",
       "    }",
       "  end.",
       "",
       " { Use one removewindow for each makewindow. }",
       " { IMPORTANT: Remember to link in the proper }",
       " {            WINDOW1x.lib library .         }"};

     static str80        strm[7] = {
       "If you have any questions or comments,",
       "please write to, or drop a note (CIS:)",
       "",
       "        Michael G. Mlachak",
       "        4318 Stewart Court.",
       "        East Chicago, IN 46312",
       "        CIS - 76327,1410"};

     static str160       title = " TURBO-C WINDOWS (Continued) ";
     static int          hidecursor = 0x2020; /*  Value to hide cursor  */


 void main(void)
 {
    int dummy_li;

    initwindow(wiattr(BLUE, CYAN));
    oldcursor = cursorchange(hidecursor);
    gotorc(1, 1);
    show30windows();
    showinitialscreen();
    showwindows();
    /*  -- Use the following statment to return to the original screen.--  */
    dummy_li = li;
    for (i = 1; i <= dummy_li; i++)
       removewindow();
    qfill(1, 1, 25, 80, 112, ' ');
    qwritec(12, 1, 80, 112, "This concludes the windows tutorial...");
    sleep(2);
    oldcursor = cursorchange(oldcursor);
 }  /* of main */

 void         show30windows()
 {
    /*  -- Throw out 30 windows 4 times --  */
    int hold_li;

    for (m = 1; m <= 4; m++) {
      for (i = 1; i <= 28; i++) {
        j = random(70);
        k = random(21);
        makewindow(k + 1, j + 1, 5, 11, wiattr(YELLOW, RED), wiattr(YELLOW, RE
        qwrite(k + 3, j + 3, -1, "WINDOWS");
      }
      hold_li = li;
      if (m == 4)
         sleep(3);
      else
        sleep(1);
      for (i = 1; i <= hold_li; i++) {
        removewindow();
      }
    } /* for m= 1; */
 } /* of show30windows */

 void         showinitialscreen()
 {
    /*  -- Create initial screen --  */
    qwritec(1, 1, 80, -1, "TURBO C - Windows Tutorial");
    qwritec(2, 1, 80, -1, "Version 1.0 -- (C) COPYRIGHT 1987 Michael G. Mlacha
    qwritec(3, 1, 80, -1, "Original TEAMWARE concept (C) COPYRIGHT Jim H. LeMa
    qwritec(5, 1, 80, 112, "For each of the following displays:");
    qwrite(6, 26, 112, "1. Press RETURN to continue.");
    qwrite(7, 26, 112, "2. Press ESC to back up.");
    qwritec(12, 1, 80, 112, "This is the original screen without windows.");
    step = 0;
 }  /* of showinitialscreen() */

 void         showgeneral()
 {
    /*  -- General description --  */
    shadoweffect = right;
    makewindow(4, 15, 19, 52, wiattr(BLACK, GREEN), wiattr(BLACK, GREEN), mixe
    titlewindow(center, " TURBO-C WINDOWS ");
    for (j = 1; j <= 16; j++)
      qwritev(wndwstat[li].wsrow + j, wndwstat[li].wscol + 1, -1, stra[j-1]);
    shadoweffect = nodir;
 }  /* showgeneral */

 void         showlist()
 {
    /*  -- List of Procedures --  */
    makewindow(5, 2, 15, 33, wiattr(BLACK, CYAN), wiattr(WHITE, BLUE), mhatchb
    titlewindow(center, " Five Functions ");
    for (j = 1; j <= 2; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, -1, strb[j-
    for (j = 3; j <= 9; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, wiattr(WHIT
    for (j = 10; j <= 11; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, -1, strb[j-
 }   /* showlist() */

 void         showinitwindow()
 {
    /*  -- InitWindow description --  */
    makewindow(11, 17, 12, 63, wiattr(YELLOW, RED), wiattr(YELLOW, RED), singl
    titlewindow(left, title);
    qwritev(wndwstat[li].wsrow + 2, wndwstat[li].wscol + 2, wiattr(WHITE, BLUE
    for (j = 2; j <= 4; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, wiattr(CYAN
    for (j = 5; j <= 8; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, wiattr(WHIT
 } /* showinitwindow() */

 void         showmakewindow()
 {
    /*  -- MakeWindow description --  */
    makewindow(4, 7, 21, 71, wiattr(LIGHTMAGENTA, BLUE), wiattr(LIGHTMAGENTA,
    titlewindow(left, title);
    qwritev(wndwstat[li].wsrow + 2, wndwstat[li].wscol + 5, wiattr(YELLOW, RED
    for (j = 2; j <= 4; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 1, wiattr(LIGH
    for (j = 5; j <= 17; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 1, wiattr(YELL
 } /* showmakewindow () */

 void         showborders()
 {
    /*  -- Show different borders --  */
    for (i = 0; i <= 5; i++)  {
      if (i == 1)
         battr = wiattr(YELLOW, YELLOW);
      else
         battr = wiattr(YELLOW, GREEN);
      makewindow(2 + 2 * i, 13 + 3 * i, 5, 10, wiattr(YELLOW, GREEN), battr, i
    }
    /* with Brdr[UserBrdr] DO  { **/
 /*   {
      TL = '\017';
      TH = '\017';
      TR = '\017';
      LV = 'Þ';
      RV = 'Ý';
      BL = '\017';
      BH = '\017';
      BR = '\017';
    }
     }  END WITH */
    for (i = 6; i <= 11; i++) {
      makewindow(24 - 2 * i, 24 + 3 * i, 5, 10, wiattr(YELLOW, GREEN), battr,
    }
 }  /* showborders () */

 void         showremovewindow()
 {
    /*  -- RemoveWindow description --  */
    makewindow(11, 20, 11, 40, wiattr(BLACK, BROWN), wiattr(BLACK, BROWN), dou
    titlewindow(left, title);
    qwritev(wndwstat[li].wsrow + 2, wndwstat[li].wscol + 5, wiattr(WHITE, MAGE
    qwritev(wndwstat[li].wsrow + 4, wndwstat[li].wscol + 2, wiattr(YELLOW, BRO
    for (j = 3; j <= 6; j++)
       qwritev(wndwstat[li].wsrow + 2 + j, wndwstat[li].wscol + 2, wiattr(WHIT
 } /* showremoveeindow() */

 void         showflicker()
 {
    /*  -- Flicker Note --  */
    makewindow(11, 22, 4, 40, wiattr(BLACK, BROWN), wiattr(BLACK, BROWN), mixe
    for (j = 1; j <= 2; j++)
      qwritev(wndwstat[li].wsrow + j, wndwstat[li].wscol + 2, -1, strf[j-1]);
 }  /* showflicker() */

 void         showscrollwindow()
 {
    /*  -- ScrollWindow description --  */
      gotorc(wndwstat[li].wsrow + 1, wndwstat[li].wscol + 1);
      for (j = 1; j <= 19; j++)
         window(8,5,76,22,wiattr(LIGHTMAGENTA, BLUE));
      for (j = 1; j <= 19; j++) {
         scrollwindow(1, 19, up);
         qwritev(wndwstat[li].wsrow + 19, wndwstat[li].wscol + 1, -1, strg[j-1
      }
 }  /* showscrollwindow() */

 void         showtitlewindow()
 {
    /*  -- TitleWindow description --  */
    makewindow(12, 16, 11, 49, wiattr(RED, LIGHTGRAY), wiattr(RED, LIGHTGRAY),
    titlewindow(left, title);
    qwritev(wndwstat[li].wsrow + 2, wndwstat[li].wscol + 5, wiattr(LIGHTGREEN,
    qwritev(wndwstat[li].wsrow + 4, wndwstat[li].wscol + 2, wiattr(BLACK, LIGH
    for (j = 3; j <= 6; j++)
       qwritev(wndwstat[li].wsrow + 2 + j, wndwstat[li].wscol + 2, wiattr(GREE
 } /* showtitlewindow() */

 void         showspecialeffects()
 {
    /*  -- Special effects description --  */
    if (qwait)
       shadoweffect = right;
    makewindow(6, 25, 14, 49, wiattr(BLACK, GREEN), wiattr(WHITE, GREEN), doub
    titlewindow(center, " Special Effects ");
    for (j = 1; j <= 2; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, -1, stri[j-
    for (j = 3; j <= 5; j++)
       qwritev(wndwstat[li].wsrow + 2 + j, wndwstat[li].wscol + 2, wiattr(WHIT
    for (j = 6; j <= 9; j++)
       qwritev(wndwstat[li].wsrow + 3 + j, wndwstat[li].wscol + 2, -1, stri[j-
    /**scanf("\n");  **/
    qfill(wndwstat[li].wsrow + 2, wndwstat[li].wscol + 2, 11, 45, wiattr(BLACK
    qwritev(wndwstat[li].wsrow + 2, wndwstat[li].wscol + 2, wiattr(WHITE, GREE
    for (j = 11; j <= 12; j++)
       qwritev(wndwstat[li].wsrow + j - 8, wndwstat[li].wscol + 2, -1, stri[j-
    qwritev(wndwstat[li].wsrow + 6, wndwstat[li].wscol + 2, wiattr(WHITE, GREE
    for (j = 14; j <= 18; j++)
       qwritev(wndwstat[li].wsrow + j - 7, wndwstat[li].wscol + 2, -1, stri[j-
    shadoweffect = nodir;
 } /* showspecialeffects() */

 void         showmaxwndw()
 {
    /*  -- MaxWndw constant --  */
    makewindow(17, 9, 7, 38, wiattr(BLACK, BROWN), wiattr(BLACK, BROWN), nobrd
    titlewindow(center, "- WINDOW LIMITS -");
    for (j = 1; j <= 5; j++)
       qwritev(wndwstat[li].wsrow + j, wndwstat[li].wscol, -1, strj[j-1]);
 } /* showmaxwndw() */

 void         showqwik21()
 {
    /*  -- QWIK21.INC procedures --  */
    makewindow(8, 20, 15, 51, wiattr(YELLOW, RED), wiattr(YELLOW, RED), evenso
    titlewindow(center, " Utility Functions ");
    for (j = 1; j <= 2; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 1, -1, strk[j-
    for (j = 3; j <= 7; j++)
       qwritev(wndwstat[li].wsrow + 2 + j, wndwstat[li].wscol + 1, wiattr(WHIT
    for (j = 8; j <= 9; j++)
       qwritev(wndwstat[li].wsrow + 3 + j, wndwstat[li].wscol + 1, -1, strk[j-
 } /* showqwik21() */

 void         showprogramming()
 {
    /*  -- Programming for WINDOW33.INC --  */
    makewindow(2, 25, 23, 50, wiattr(YELLOW, MAGENTA), wiattr(YELLOW, MAGENTA)
    for (j = 1; j <= 20; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 1, -1, strl[j-
 } /* showprogramming() */

 void         showeditor()
 {
    /*  -- Editor for WINDOW33.INC --  */
    if (qwait)
       shadoweffect = right;
    makewindow(8, 20, 11, 42, wiattr(BLACK, BROWN), wiattr(BLACK, BROWN), hhat
    titlewindow(center, " Teamware Editor: ");
    for (j = 1; j <= 7; j++)
       qwritev(wndwstat[li].wsrow + 1 + j, wndwstat[li].wscol + 2, wiattr(WHIT
    shadoweffect = nodir;
 }  /* showeditor */

 void        readkb(key)
 int         *key;
 {

   int t_key;

   t_key = getch();
   if (t_key ==0)     /* extended character hit */
      t_key = getch();
    *key = t_key;
 } /* readkb() */

 void         getkey()
 {
   do {
      readkb(&key);
   }  while (!((key == RETKEY) || (key == ESCKEY)));
 }  /* getkey() */

 void         findnextstep()
 {
   switch (key) {
       case ESCKEY:
          if (step > 0) {
              removewindow();
              switch (step) {
                 case 5:
                         for (j = 1; j <= 11; j++)
                            removewindow();
                 break;
                 case 7:
                        showborders();
                        showremovewindow();
                 break;
                 case 8:
                        step = 4;
                 break;
              } /*  switch step  */
             step = step - 1;
          } /* if step > 0 */
       break;

       case RETKEY:
          step = step + 1;
          if ((step >=9) && (step <=13))
             zoomeffect = TRUE;
          else
             zoomeffect = FALSE;
          switch (step) {
             case 7:
                    for (i = 0; i <= 12; i++)
                       removewindow();
             break;
             case 8:
                    removewindow();
             break;
          } /* switch step */
       break;
   } /*  switch key  */
 }  /* findnextstep() */

 void         showwindows(void)
 {
   do {
     getkey();
     findnextstep();
     if (key == RETKEY) {
        switch (step) {
           case 1:
                  showgeneral();
           break;
           case 2:
                  showlist();
           break;
           case 3:
                  showinitwindow();
           break;
           case 4:
                  showmakewindow();
           break;
           case 5:
                  showborders();
           break;
           case 6:
                  showremovewindow();
           break;
           case 7:
                  showflicker();
           break;
           case 8:
                  showscrollwindow();
           break;
           case 9:
                  showtitlewindow();
           break;
           case 10:
                  showspecialeffects();
           break;
           case 11:
                  showmaxwndw();
           break;
           case 12:
                  showqwik21();
           break;
           case 13:
                   showprogramming();
           break;
           case 14:
                   showeditor();
           break;
       } /* switch step */
     } /* if key ==RETKEY */
    }  while (step != 15) ;
 }  /* showindows */

 int random(seed)
 {
   int hold;

      hold= rand();
      if (hold > 127)
        hold = hold % 127;
      hold = hold % seed;
    return(hold);
 }


 WWXMAS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\CTOOLBX1\WWXMAS.C

 /*  We Wish You a Merry Christmas */

 int w[250] =      { 31, 36,100, 36, 38, 36, 35, 33,100, 33,100, 33,
                     38,100, 38, 40, 38, 36, 35, 31,100, 31,
                     40,100, 40, 41, 40, 38, 36, 33, 31,100, 31,
                     33, 38, 35, 36, 31, 36,100, 36,100, 36,
                     35,100, 35, 36, 35, 33, 31, 38,
                     40, 38,100, 38, 36,100, 36,
                     43, 31,100, 31,100, 31, 33, 38, 35, 36,

                            0xff };

 int wb[250]   =   {  5,  5,  1,  3,  3,  3,  3,  5,  1,  5,  1,  5,
                      5,  1,  3,  3,  3,  3,  5,  5,  1,  5,
                      5,  1,  3,  3,  3,  3,  5,  5,  3,  1,  3,
                      5,  5,  5, 14,  5,  5,  1,  5,  1,  5,
                     12,  1,  5,  5,  5,  5, 12,  5,
                      5,  3,  1,  3,  3,  1,  3,
                      5,  5,  1,  3,  1,  3,  5,  5,  5, 12,

                            1 };


 wwxmas()
 {
    setsound();
 }



 XC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\CUG236\XC.C

 /*
         HEADER:                CUG236;
         TITLE:                Cross Reference Generator;
         DATE:                04/05/1987;
         DESCRIPTION:        "Generic version of programmer's cross-reference
                         generator originally for BDS.";
         VERSION:        2.2;
         KEYWORDS:        Cross Reference;
         FILENAME:        XC.C;
         SEE-ALSO:        CUG126, CUG171;
         COMPILERS:        vanilla;
         AUTHORS:        Phillip N. Hisley, W. H. Rauser, W. C. Colley III;
 */

 /************************************************************************/
 /*   5 APR 1987          Portable C Conversion            WCC
 /*     -  Epson init string changed from hex (\x00) to octal (\000).        *
 /*     -  Use () with A?(c=B):(c=C) for portability.  If it's an error, */
 /*                it seems to be a very common one.                        */
 /*     -  Made use of host compiler's strcmp() and strcpy() as they are */
 /*                usually written in assembly and run faster.
 /*     -  Globally replaced "alpha_" with "alp_", "alloc_" with
 /*                "allo_", and "tmpchr" with "tmpch" to avoid multiply
 /*                defined symbol errors on compilers that only support
 /*                @$%&*&?>}\~~@# 6-character names.                        */
 /*     -  Added abs() macro for compilers that don't have one.          */
 /*     -  Used some data initialization to kill off some code.
 /*     -  Made miscellaneous small tweaks for portability.                */
 /*     -  Cleaned out old BDS C stuff to improve readability.
 /*     -  Cleaned up abortion with use of rf_blk.rf_cnt as a pointer        *
 /*                link to the next rf_blk.  This construct will NOT work
 /*                in environments like the MSDOS large model where ints
 /*                are smaller than pointers!                                *
 /*                                                                        */
 /*   9-26-83   Microsoft C 1.04         Conversion    WHR
 /*     -  \t between line numbers and text to fix indenting problem.        *
 /*     -  added option -e for output to Epson in condensed print.        */
 /*     -  toupper() and isupper() are macros, not functions.                *
 /*     -  eliminate side effect in toupper(*++arg) in main().
 /*     -  change alloc() to malloc().
 /*     -  add #define NAMES that are not in stdio.h                        */
 /*     -  MS-C requires () in statement A?(c=B):(c=C)        error or not??
 /*                                                                        */
 /*   4-30-83   Computer Innovations C-86 1.31 Conversion    WHR
 /*     -  #include filename changed to allow a disk drive prefix, D:        *
 /*     -  convert if(fprintf(...) == ERROR) lst_err(); to fprintf(..);
 /*     -  convert if(fopen(...) == ERROR) statements to == NULL.        */
 /*     -  C86 requires () in statement A?(c=B):(c=C)        error or not??
 /*     -  remove getc() == ERROR check in fil_chr().                        *
 /*     -  convert file conventions from BDS C to C-86.
 /*     -  comment out BDS unique statements, mark revised statements.
 /*          keep all BDS statements to document conversion effort.        */
 /*                                                                        */
 /**  4-19-83   BDS C Version file XC.CQ copied from Laurel RCPM           WHR
 /************************************************************************/
 /*                                                           */
 /*    XC  -  A 'C' Concordance Utility                           */
 /*                                                           */
 /*    Version 1.0   January, 1982                           */
 /*                                                           */
 /*    Copyright (c) 1982 by Philip N. Hisley                   */
 /*                                                           */
 /*    Released for non-commercial distribution only           */
 /*                                                           */
 /*    Abstract:                                                   */
 /*                                                           */
 /*    'XC' is a cross-reference utility for 'C' programs.  */
 /*    Its has the ability to handle nested include files   */
 /*    to a depth of 8 levels and properly processes nested */
 /*    comments as supported by BDS C. Option flags support */
 /*    the following features:                                   */
 /*                                                           */
 /*    - Routing of list output to disk                           */
 /*    - Cross-referencing of reserved words                   */
 /*    - Processing of nested include files                   */
 /*    - Generation of listing only                           */
 /*                                                           */
 /*    Usage: xc <filename> <flag(s)>                           */
 /*                                                           */
 /*    Flags: -i                   = Enable file inclusion           */
 /*             -l                   = Generate listing only           */
 /*             -r                   = Cross-ref reserved words           */
 /*             -o <filename> = Write output to named file           */
 /*                                                           */
 /*    Please report bugs/fixes/enhancements to:                   */
 /*                                                           */
 /*              Philip N. Hisley                                   */
 /*              548H Jamestown Court                           */
 /*              Edgewood, Maryland 21040                           */
 /*              (301) 679-4606                                   */
 /*              Net Addr: PNH@MIT-AI                           */
 /*                                                           */
 /***********************************************************/

 #include <stdio.h>

 /*
  * Portability Note:  The AZTEC C compilers handle the binary/text file
  * dichotomy differently from most other compilers.  Uncomment the following
  * pair of #defines if you are running AZTEC C:
  */

 /*
 #define getc(f)                agetc(f)
 #define putc(c,f)        aputc(c,f)
 */

 /*  Portability Note:  8-bit systems often don't have header files
     ctype.h and string.h.  If your system doesn't have these,
     uncomment the #defines NO_STRING_H and NO_CTYPE_H.                   WCC

 /*
 #define         NO_STRING_H
 #define         NO_CTYPE_H
 */

 /*  Portability Note:  Some older compilers call the function malloc()
     by its older name alloc().        If you have one of these older
     compilers, uncomment the following #define.                        WCC

 /*
 #define         malloc(x)        alloc(x)
 */

 /*  Portability Note:  A few compilers don't know the additional type
     void.  If yours is one of these, uncomment the following #define.

 /* #define        void                int

         NO_CTYPE_H                                                /* WCC */
 int isalpha(), isdigit(), isupper(), toupper();
 #else
 <ctype.h>                                                /* WHR */
 #endif

         NO_STRING_H                                                /* WCC */
 int strcmp();  char *strcpy();
 #else
 #include <string.h>
 #endif

         abs                                                        /* WCC */
 #define         abs(x)                ((x < 0) ? (-x) : (x))
 #endif

 /*  Portability Note:  Some stdio.h files define various of these
     constants.        Some don't.  Therefore, each definition is
     compiled only if needed.                                           WCC */

         NULL                                                        /* WCC */
 #define         NULL            0
 #endif

         FALSE                                                        /* WCC *
         FALSE            0                                                /*
 #endif

         TRUE                                                        /* WCC */
         TRUE            1                                                /* W
 #endif

         MAX_REF    5                /* maximum refs per ref-block */
         MAX_LEN    20                /* maximum identifier length  */
         MAX_WRD   749                /* maximum number of identifiers */
         MAX_ALPHA  53                /* maximum alpha chain heads */
         REFS_PER_LINE        8        /* maximum refs per line */
 #define         LINES_PER_PAGE 60
         FF 0x0C                 /* formfeed */

 /*  Order of the next two structure declarations reversed to avoid
     a forward reference that chokes some compilers.                        WC

 struct rf_blk {
                  int ref_item[MAX_REF];
                  int ref_cnt;
                  struct rf_blk *ref_lnk;
                } onerf;

 struct id_blk {
                  char id_name[MAX_LEN];
                  struct id_blk *alp_lnk;
                  struct rf_blk *top_lnk;
                  struct rf_blk *lst_lnk;
                } oneid, *id_vector[MAX_WRD];

 struct alp_hdr { struct id_blk *alp_top;
                    struct id_blk *alp_lst;
                  } alp_vector[MAX_ALPHA];

 int        linum;                /* line number */
 int        edtnum;                /* edit line number */
 int        fil_cnt;        /* active file index */
 int        wrd_cnt;        /* token count */
 int        pagno;                /* page number */
 int        id_cnt;                /* number of unique identifiers */
 int        rhsh_cnt;        /* number of conflict hits */
 int        filevl;                /* file level  */
 int        paglin;                /* page line counter */
 int        prt_ref = FALSE;
 char        act_fil[MAX_LEN];
 char        lst_fil[MAX_LEN];
 char        gbl_fil[MAX_LEN];
 FILE   *l_buffer;                                             /* WHR */
 int        e_flg = FALSE, i_flg = FALSE, o_flg = FALSE;             /* WHR */
 int        r_flg = FALSE, l_flg = FALSE, debug = FALSE;             /* WCC */
 char        Epson[]         = "\033@\017\033Q\204";                     /* WC

 void exit();

 /*-------------------------------------------*/

 void main(argc,argv)
 int        argc;
 char        **argv;
 {
      char  *arg, cc;
      void nl(), prnt_tbl(), proc_file(), use_err();

      if (argc < 2) use_err();
      (void)strcpy(gbl_fil,*++argv);
      --argc;
      if(gbl_fil[0] == '-')
           use_err();
      while(--argc != 0)
      {          if(*(arg=*++argv) == '-')
     /*****{    switch( toupper(*++arg) )     *** side effect in Microsoft C *
           {    switch( cc=*++arg, toupper(cc) )                     /* Micros
                {   case 'I':  i_flg++;
                               break;
                    case 'R':  r_flg++;
                               break;
                    case 'L':  l_flg++;
                               break;
                    case 'O': {o_flg++;
                               if(--argc == 0) use_err();
                               (void)strcpy(lst_fil,*++argv);
                               if(lst_fil[0] == '-') use_err();
                               if(debug) printf("lst_fil=>%s<",lst_fil);
                               break;
                              }
                    case 'D':  debug++;
                               break;
                    case 'E':  e_flg++;                                  /* WH
                               o_flg++;
                               (void)strcpy(lst_fil,"LPT1:");
                               break;
                    default:   use_err();
                }
           }
      else use_err();
      }
      if (debug) printf("\ni_flg=%d, r_flg=%d, l_flg=%d", i_flg,r_flg,l_flg);
      if (debug) printf("\no_flg=%d, debug=%d", o_flg,debug);
      if (o_flg)
      {          if ( (l_buffer = fopen(lst_fil,"w")) == NULL)          /*** o
           {    printf("ERROR Unable to create list file - %s\n",lst_fil);
                exit(0);
           }
           printf("\nXC ....... 'C' Concordance Utility  v2.3\n");
           printf("    Portable C,  Conversion 5 APR 1987\n\n");            /*
           if (e_flg) fprintf(l_buffer,"%s",Epson);
      }
      for(linum=0;linum < MAX_WRD;linum++) {
           id_vector[linum] = NULL;
      }
      for(linum=0;linum < MAX_ALPHA;linum++)
      {
           alp_vector[linum].alp_top =
                alp_vector[linum].alp_lst = NULL;
      }
      fil_cnt = wrd_cnt = linum = 0;
      filevl=paglin=pagno=edtnum=0;
      id_cnt=rhsh_cnt=0;
      proc_file(gbl_fil);
      if(!l_flg) {
          prnt_tbl();
          printf("\nAllowable Symbols: %d\n",MAX_WRD);
          printf("Unique    Symbols: %d\n",id_cnt);
      }
      if(o_flg) {
           nl();
           fprintf(l_buffer,"\nAllowable Symbols: %d\n",MAX_WRD);   /* WHR */
           fprintf(l_buffer,"Unique    Symbols: %d\n",id_cnt);           /* WH
           fprintf(l_buffer,"%c",FF);                                   /* WHR
           fflush(l_buffer);
           fclose(l_buffer);
      }
 }/*main.
 ----------------------------------------*/

 void use_err()
 {
      printf("\nERROR: Invalid parameter specification\n\n");
      printf("Usage: xc <filename> <flag(s)>\n\n");
      printf("Flags: -e             = Emit printer initialization string\n");
      printf("       -i             = Enable file inclusion\n");
      printf("       -l             = Generate listing only\n");
      printf("       -r             = Cross-reference reserved words\n");
      printf("       -o <filename>  = Write output to named file\n");
      exit(0);
 }/*use_err.
 -------------------------------------------*/


 void proc_file(filnam)
      char    *filnam;

 {
      FILE  *buffer;           /* allocated buffer pointer */            /* WH
      char  token[MAX_LEN]; /* token buffer */
      int   eof_flg;           /* end-of-file indicator */
      int   tok_len;           /* token length */
      int   incnum;           /* included line number */
      int chk_token(), get_token();
      void nl(), prt_hdr(), put_token();

      (void)strcpy(act_fil,filnam);
      if ((buffer = fopen(filnam,"r")) == NULL)        /*** input file ***/ /*
      {          printf("\nERROR: Unable to open input file: %s\n",filnam);
           exit(0);
      }
      if(filevl++ == 0) prt_hdr();
      eof_flg = FALSE;

      do {
           if(get_token(buffer,token,&tok_len,&eof_flg,0))
           {    if (debug) printf("\ntoken: %s   length: %d\n",token,&tok_len)
                if (chk_token(token))
                {
                      /* #include processing changed to accept drive:   WHR */
                     if (strcmp(token,"#include") == 0)
                     {         if (get_token(buffer,token,&tok_len,&eof_flg,1)
                          {    if (debug) printf("\ntoken: %s   length: %d\n",
                                                   token,&tok_len);
                               if (!i_flg) continue;
                               else
                               {           incnum=edtnum;
                                    edtnum=0;
                                    nl();
                                    proc_file(token);
                                    edtnum=incnum;
                                    (void)strcpy(act_fil,filnam);
                                    continue;
                               }
                          }
                     }
                     put_token(token,linum);
                }
           }
      } while (!eof_flg);

      filevl -= 1;
      fclose(buffer);
  /***         free(sav_buffer);  */
 }/*proc_file.
 -------------------------------------------*/

 int get_token(g_buffer,g_token,g_toklen,g_eoflg,g_flg)
      FILE    *g_buffer;
      char    *g_token;
      int     *g_toklen;
      int     *g_eoflg;
      int     g_flg;

     /*
      *         'getoken' returns the next valid identifier or
      *         reserved word from a given file along with the
      *         character length of the token and an end-of-file
      *         indicator
      *
      */

 {
      int     c, rdchr();
      char    *h_token;
      char    tmpch;
      char    tmpch2;                      /* WHR fix for B:filename.ext */

      h_token = g_token;

  gtk:                               /* top of loop, get new token */
      *g_toklen = 0;
      g_token = h_token;

     /*
      *        Scan and discard any characters until an alphabetic or
      *        '_' (underscore) character is encountered or an end-of-file
      *        condition occurs
      */

      while(  (!isalpha(*g_token = rdchr(g_buffer,g_eoflg,g_flg)))
              &&         !*g_eoflg        &&  *g_token != '_'
              && *g_token != '0' &&  *g_token != '#' );
      if(*g_eoflg) return(FALSE);

      *g_toklen += 1;

     /*
      *         Scan and collect identified alpanumeric token until
      *         a non-alphanumeric character is encountered or and
      *         end-of-file condition occurs
      */

      if(g_flg) {
           tmpch         = '.';
           tmpch2 = ':';                          /* WHR fix for B:filename.ex
      }
      else {
           tmpch         = '_';
           tmpch2 = '_';                          /* WHR fix for B:filename.ex
      }
      while( (isalpha(c=rdchr(g_buffer,g_eoflg,g_flg)) ||
             isdigit(c) || c == '_' || c == tmpch || c == tmpch2)
             && !*g_eoflg)                   /* WHR fix for B:filename.ext */
      {          if(*g_toklen < MAX_LEN)
           {    *++g_token = c;
                *g_toklen += 1;
           }
      }


     /*
      *            Check to see if a numeric hex or octal constant has
      *            been encountered ... if so dump it and try again
      */


      if (*h_token == '0') goto gtk;


     /*
      *            Tack a NULL character onto the end of the token
      */

      *++g_token = NULL;

     /*
      *            Screen out all #token strings except #include
      */

      if (*h_token == '#' && strcmp(h_token,"#include")) goto gtk;

      return (TRUE);
 }/*get_token.
 -----------------------------------------*/

 int fil_chr(f_buffer,f_eof)
      FILE *f_buffer;
      int *f_eof;
 {
      int fc;
      if ((fc = getc(f_buffer)) == EOF) {
           *f_eof = TRUE;
           fc = NULL;
      }
      return(fc);
 }/*fil_chr.
 ----------------------------------------*/

 int rdchr(r_buffer,r_eoflg,rd_flg)
      int     *r_eoflg, rd_flg;
      FILE    *r_buffer;

 /*
         'rdchr' returns the next valid character in a file
         and an end-of-file indicator. A valid character is
         defined as any which does not appear in either a
         commented or a quoted string ... 'rdchr' will correctly
         handle comment tokens which appear within a quoted
         string
 */

 {
      int     c;
      int     q_flg;             /* double quoted string flag */
      int     q1_flg;             /* single quoted string flag */
      int     cs_flg;             /* comment start flag */
      int     ce_flg;             /* comment end flag */
      int     c_cnt;             /* comment nesting level */
      int     t_flg;             /* transparency flag */
      void nl();

      q_flg = q1_flg = cs_flg = ce_flg = t_flg = FALSE;
      c_cnt  = 0;

 rch:

     /*
      *         Fetch character from file
      */

      c = fil_chr(r_buffer,r_eoflg);

      if (*r_eoflg) return(c);        /* EOF encountered */
      if (c == '\n')
            nl();
      else
           if (o_flg) fprintf(l_buffer,"%c",c);                        /* WHR
           else printf("%c",c);

      if (rd_flg) return(c);

      if (t_flg) {
           t_flg = !t_flg;
           goto rch;
      }

      if (c == '\\') {
           t_flg = TRUE;
           goto rch;
      }
         /*
         If the character is not part of a quoted string
         check for and process commented strings...
         nested comments are handled correctly but unbalanced
         comments are not ... the assumption is made that
         the syntax of the program being xref'd is correct
         */

      if (!q_flg         &&  !q1_flg) {
           if (c == '*'        &&  c_cnt  &&  !cs_flg) {
                ce_flg = TRUE;
                goto rch;
           }
           if (c == '/'        &&  ce_flg) {
                c_cnt -= 1;
                ce_flg = FALSE;
                goto rch;
           }
           ce_flg = FALSE;
           if (c == '/') {
                cs_flg = TRUE;
                goto rch;
           }
           if (c == '*'        &&  cs_flg) {
                c_cnt += 1;
                cs_flg = FALSE;
                goto rch;
           }
           cs_flg = FALSE;

           if (c_cnt) goto rch;
      }

         /*
         Check for and process quoted strings
         */

      if ( c == '"'  &&        !q1_flg) {        /* toggle quote flag */
           q_flg =  !q_flg;
           if(debug) printf("\nq_flg toggled to: %d\n" ,q_flg);
           goto rch;
      }
      if (q_flg) goto rch;

      if (c == '\'') {             /* toggle quote flag */
           q1_flg = !q1_flg;
           if(debug) printf("\nq1_flg toggled to: %d\n" ,q1_flg);
           goto rch;
      }
      if (q1_flg) goto rch;

         /*
         Valid character ... return to caller
         */

      return (c);
 }/*rdchr.
 -----------------------------------------------*/


 int chk_token(c_token)
      char    *c_token;
 {
      char  u_token[MAX_LEN];
      int   i;

      {
       if (r_flg) return(TRUE);
       i = 0;
       do { u_token[i] = toupper(c_token[i]);
       } while (c_token[i++] != NULL);

       switch(u_token[0]) {
         case 'A': if (strcmp(u_token,"AUTO") == 0) return(FALSE);
                   break;
         case 'B': if (strcmp(u_token,"BREAK") == 0) return(FALSE);
                   break;
         case 'C': if (strcmp(u_token,"CHAR") == 0) return (FALSE);
                   if (strcmp(u_token,"CONTINUE") == 0) return (FALSE);
                   if (strcmp(u_token,"CASE") == 0) return (FALSE);
                   break;

         case 'D': if(strcmp(u_token,"DOUBLE") == 0) return(FALSE);
                   if(strcmp(u_token,"DO") == 0) return(FALSE);
                   if(strcmp(u_token,"DEFAULT") == 0) return(FALSE);
                   break;
         case 'E': if(strcmp(u_token,"EXTERN") == 0) return(FALSE);
                   if(strcmp(u_token,"ELSE") == 0) return(FALSE);
                   if(strcmp(u_token,"ENTRY") == 0) return(FALSE);
                   break;
         case 'F': if(strcmp(u_token,"FLOAT") == 0) return(FALSE);
                   if(strcmp(u_token,"FOR") == 0) return(FALSE);
                   break;
         case 'G': if(strcmp(u_token,"GOTO") == 0) return(FALSE);
                   break;
         case 'I': if(strcmp(u_token,"INT") == 0) return(FALSE);
                   if(strcmp(u_token,"IF") == 0) return(FALSE);
                   break;
         case 'L': if(strcmp(u_token,"LONG") == 0) return(FALSE);
                   break;
         case 'R': if(strcmp(u_token,"RETURN") == 0) return(FALSE);
                   if(strcmp(u_token,"REGISTER") == 0) return(FALSE);
                   break;
         case 'S': if(strcmp(u_token,"STRUCT") == 0) return(FALSE);
                   if(strcmp(u_token,"SHORT") == 0) return(FALSE);
                   if(strcmp(u_token,"STATIC") == 0) return(FALSE);
                   if(strcmp(u_token,"SIZEOF") == 0) return(FALSE);
                   if(strcmp(u_token,"SWITCH") == 0) return(FALSE);
                   break;
         case 'T': if(strcmp(u_token,"TYPEDEF") == 0) return(FALSE);
                   break;
         case 'U': if(strcmp(u_token,"UNION") == 0) return(FALSE);
                   if(strcmp(u_token,"UNSIGNED") == 0) return(FALSE);
                   break;
         case 'W': if(strcmp(u_token,"WHILE") == 0) return(FALSE);
                   break; }
         }
   return (TRUE);
 }/*chk_token.
 ---------------------------------------------*/


   /*
    *        Install parsed token and line reference in linked structure
    */

 void put_token(p_token,p_ref)
 char *p_token;
 int  p_ref;
 {
      int  d, found, hsh_index, i, j;
      struct id_blk *idptr, *allo_id();
      struct rf_blk *allo_rf(), *add_rf();
      void chain_alpha();

      if (l_flg) return;
      j=0;
      for (i=0; p_token[i] != NULL; i++)         /* Hashing algorithm is far f
      {                                         /* optimal but is adequate for
          j = j * 10 + p_token[i];         /* memory-bound index vector!
      }
      hsh_index = abs(j) % MAX_WRD;

      found = FALSE;
      d = 1;
      do
      {          idptr = id_vector[hsh_index];
           if (idptr == NULL)
           {    id_cnt++;
                idptr = id_vector[hsh_index] = allo_id(p_token);
                chain_alpha(idptr,p_token);
                idptr->top_lnk = idptr->lst_lnk = allo_rf(p_ref);
                found = TRUE;
           }
           else
           if (strcmp(p_token,idptr->id_name) == 0)
           {    idptr->lst_lnk = add_rf(idptr->lst_lnk,p_ref);
                found = TRUE;
           }
           else
           {    hsh_index += d;
                d += 2;
                rhsh_cnt++;
                if (hsh_index >= MAX_WRD)
                     hsh_index -= MAX_WRD;
                if (d == MAX_WRD)
                {    printf("\nERROR: Symbol table overflow\n");
                     exit(0);
                }
           }
      } while (!found);
 }/*put_token.
 --------------------------------------------*/


 void chain_alpha(ca_ptr,ca_token)
 struct id_blk *ca_ptr;
 char  *ca_token;
 {
      char  c;
      struct id_blk *cur_ptr;
      struct id_blk *lst_ptr;

      c = ca_token[0];
      if (c == '_')  c = 0;
      else
      /**  isupper(c) ? c=1+((c-'A')*2) : c=2+((c-'a')*2) ;     error or not??
       **  A good one for the puzzle book! Is the () required around (c=..)?
       **  C86 and Microsoft C both req the ()'s, BDS C did not.
       **  Is it required because = has lower precedence than ?: ????
       **/
           isupper(c) ? (c=1+((c-'A')*2)) : (c=2+((c-'a')*2)) ;

      if(alp_vector[c].alp_top == NULL)
      {          alp_vector[c].alp_top =
                   alp_vector[c].alp_lst = ca_ptr;
           ca_ptr->alp_lnk = NULL;
           return;
      }

     /*        check to see if new id_blk should be inserted between
      *        the alp_vector header block and the first id_blk in
      *        the current alpha chain
      */

      if(strcmp(alp_vector[c].alp_top->id_name,ca_token) >0)
      {          ca_ptr->alp_lnk=alp_vector[c].alp_top;
           alp_vector[c].alp_top=ca_ptr;
           return;
      }

      if(strcmp(alp_vector[c].alp_lst->id_name,ca_token) < 0)
      {          alp_vector[c].alp_lst->alp_lnk = ca_ptr;
           ca_ptr->alp_lnk = NULL;
           alp_vector[c].alp_lst=ca_ptr;
           return;
      }

      cur_ptr = alp_vector[c].alp_top;
      while(strcmp(cur_ptr->id_name,ca_token) < 0)
      {          lst_ptr = cur_ptr;
           cur_ptr = lst_ptr->alp_lnk;
      }

      lst_ptr->alp_lnk = ca_ptr;
      ca_ptr->alp_lnk = cur_ptr;
      return;
 }/*chain_alpha.
 -----------------------------------------*/

 struct id_blk *allo_id(aid_token)
 char  *aid_token;
 {
      int  ai;
      struct id_blk *aid_ptr;
      char *malloc();                                             /* Microsoft

 /*** if((aid_ptr =  alloc(sizeof(oneid))) == 0) { ***/             /* Microso
      if((aid_ptr = (struct id_blk *) malloc(sizeof(oneid))) == 0) { /* MS C *

           printf("\nERROR: Unable to allocate identifier block\n");
           exit(0);
      }
      ai=0;
      do {
           aid_ptr->id_name[ai] = aid_token[ai];
      } while (aid_token[ai++] != NULL);
      return (aid_ptr);
 }/*id_blk.
 -----------------------------------------*/

 struct rf_blk *allo_rf(arf_ref)
 int  arf_ref;
 {
     int ri;
     struct rf_blk *arf_ptr;
     char *malloc();                                       /* Microsoft C */

 /** if((arf_ptr = alloc(sizeof(onerf))) == 0) { **/    /* Microsoft C */
     if((arf_ptr = (struct rf_blk *) malloc(sizeof(onerf))) == 0) { /* MS C */
          printf("\nERROR: Unable to allocate reference block\n");
          exit(0);
     }
     arf_ptr->ref_item[0] = arf_ref;
     arf_ptr->ref_cnt = 1;  arf_ptr->ref_lnk = NULL;
     for (ri=1;ri<MAX_REF;ri++)
           arf_ptr->ref_item[ri] = NULL;
     return (arf_ptr);
 }/*allo_rf.
 ------------------------------------------*/


 struct rf_blk *add_rf(adr_ptr,adr_ref)
 struct rf_blk *adr_ptr;
 int adr_ref;
 {
      if(adr_ptr->ref_cnt == MAX_REF)
           return adr_ptr->ref_lnk = allo_rf(adr_ref);
      else {
           adr_ptr->ref_item[adr_ptr->ref_cnt++] = adr_ref;
           return (adr_ptr);
      }
 }/*rf_blk.
 ------------------------------------------*/

 void prnt_tbl()
 {
      int lin_cnt, pref, prf_cnt, pti;
      struct id_blk *pid_ptr;
      struct rf_blk *ptb_ptr;
      void nl(), prt_hdr();

      prt_ref = TRUE;
      prt_hdr();
      for (pti=0;pti<MAX_ALPHA;pti++)
      {          if ((pid_ptr = alp_vector[pti].alp_top) != NULL)
           {    do
                {    if(o_flg)                                              /*
                          fprintf(l_buffer,"%-14.13s: ",pid_ptr->id_name);
                     else printf("%-14.13s: ",pid_ptr->id_name);
                     ptb_ptr=pid_ptr->top_lnk;
                     lin_cnt=prf_cnt=0;
                     do
                     {         if(prf_cnt == MAX_REF)
                          {    prf_cnt=0;
                               ptb_ptr = ptb_ptr->ref_lnk;
                          }
                          if(ptb_ptr)
                          {
                               if((pref=ptb_ptr->ref_item[prf_cnt++]) != 0)
                               {
                                    if (lin_cnt++ == REFS_PER_LINE)
                                    {        nl();                     /* WHR,
                                         if (o_flg) fprintf(l_buffer,"\t\t");
                                         else printf("\t\t");
                                         lin_cnt = 1;
                                    }
                                    if(o_flg) fprintf(l_buffer,"%-4d  ",pref);
                                    else printf("%-4d  ",pref);
                               }
                          }
                          else pref=0;
                     } while (pref);
                     nl();
                } while ((pid_ptr=pid_ptr->alp_lnk) != NULL);
           }
      }
 }/*prnt_tbl.
 ---------------------------------------*/


 void prt_hdr()
 {
      void nl();

      if (pagno++ != 0)
      if(o_flg) fprintf(l_buffer,"%c",FF);                        /* WHR */
      else printf("%c",FF);

      if(o_flg)
           fprintf(l_buffer,
                "XC ... 'C' Concordance Utility : %s\t\t\t\t Page %d",
                gbl_fil,pagno);                                       /* WHR *
      else printf("XC ... 'C' Concordance Utility : %s\t\t\t\t Page %d",
           gbl_fil,pagno);
      if (o_flg) fprintf(l_buffer,"\n\n");                       /* WHR */
      else printf("\n\n");

      nl();  paglin =3;        return;
 }/*prt_hdr.
 --------------------------------------*/

 void nl()
 {
      if (o_flg) fprintf(l_buffer,"\n");                               /* WHR
      else printf("\n");

      if (++paglin == LINES_PER_PAGE) prt_hdr();
      else if(!prt_ref)
           {    if (o_flg) fprintf(l_buffer,"%-4d %4d:\t",
                                 ++linum,++edtnum);               /* WHR */
                else printf("%-4d %4d:\t",++linum,++edtnum);

                if(o_flg)
                     if(linum % 60 == 1) printf("\n<%d>\t",linum);
                     else printf(".");
           }
      return;
 }/*nl.
 -------------------------------------------*/
 /*============= end of file xc.c ==========================*/



 XC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\XC1\XC.C

 /**********************************************************

       XC  -  A 'C' Concordance Utility

       Version 1.0   January, 1982

       Copyright (c) 1982 by Philip N. Hisley

               Philip N. Hisley
               548H Jamestown Court
               Edgewood, Maryland 21040
               (301) 679-4606

       Released for non-commercial distribution only




       Converted to IBM/PC CI/C86 by David N. Smith, May/June 1983
       with enhancements and Lattice compiler support in December 1983.

               David N. Smith
               44 Ole Musket Lane
               Danbury, CT 06810
               (203) 748-5934

       Changes Copyright (c) 1983 by David N. Smith

       PC Enhancements include:

            1)  Nested #INCLUDE statements
            2)  Single spaced cross-reference list
            3)  Removal of tabbing on output device
                (Since many printers don't support it)
            4)  #INCLUDE statements with both "--" and <-->
                syntax and with a full fileid in the quotes.
            5)  Multiple input filenames on command line.



       Abstract:

       'XC' is a cross-reference utility for 'C' programs.
       Its has the ability to handle nested include files
       to a depth of 8 levels and properly processes nested
       comments as supported by BDS C. Option flags support
       the following features:

       - Routing of list output to disk
       - Cross-referencing of reserved words
       - Processing of nested include files
       - Generation of listing only

       Usage: xc <filename> <flag(s)>

       Flags: -i            = Enable file inclusion
              -l            = Generate listing only
              -r            = Cross-ref reserved words
              -o <filename> = Write output to named file


 ***********************************************************/

 #include "e:stdio.h"

 /* Compiler specific stuff */
 #define Lattice

 #ifdef Lattice
 #include "e:ctype.h"
 #endif
 /* end compiler specific section */

 #ifndef  TRUE
 #define  TRUE             1
 #define  FALSE             0
 #endif

 #define  ERROR            -1
  MAX_REF     5                /* maximum refs per ref-block */
  MAX_LEN    20                /* maximum identifier length  */
  MAX_WRD   749                /* maximum number of identifiers */
  MAX_ALPHA  53                /* maximum alpha chain heads */
  REFS_PER_LINE        10        /* maximum refs per line */
 #define  LINES_PER_PAGE 60
  MAXCOL     78                /* default maximum column number for listing li
  MINCOL     30                /* minimum value for -w option */
  FF 0x0C                /* formfeed */

 struct        rf_blk {
                  int  ref_item[MAX_REF];
                  int  ref_cnt;
                } onerf;

 struct        id_blk {
                  char  id_name[MAX_LEN];
                  struct id_blk *alpha_lnk;
                  struct rf_blk *top_lnk;
                  struct rf_blk *lst_lnk;
                } oneid;

 struct id_blk *id_vector[MAX_WRD];

 struct alpha_hdr { struct id_blk *alpha_top;
                    struct id_blk *alpha_lst;
                  };

 struct alpha_hdr alpha_vector[MAX_ALPHA];

 int        linum;                /* line number */
 int        edtnum;         /* edit line number */
 int        fil_cnt;        /* active file index */
 int        wrd_cnt;        /* token count */
 int        pagno;                /* page number */
 int        id_cnt;         /* number of unique identifiers */
 int        rhsh_cnt;        /* number of conflict hits */
 int        filevl;         /* file level  */
 int        paglin;         /* page line counter */
 int        dummy;                /* dummy integer */
 int        maxcol=MAXCOL;        /* maximum right column for listing line */
 int        prt_ref;
 char        act_fil[MAX_LEN];
 char        lst_fil[MAX_LEN];
 char        gbl_fil[MAX_LEN];
 FILE        *f_lst_fil;
 int        i_flg,
         o_flg,
         r_flg,
         l_flg;

 long atoi();


 /*************************************************************************/

 main(p_argc, p_argv)
 int        p_argc;
 char        **p_argv;

 {
     char  *arg;
     int argc;
     char **argv;
     char c;
     int i;

     argc = p_argc;
     argv = p_argv;
     if (argc < 2) use_err();
     i_flg=r_flg=o_flg=l_flg=FALSE;
     while(--argc != 0)
      { if(*(arg=*++argv) == '-')
         {switch(*++arg)
          {
            case 'i':
            case 'I': i_flg++;
                      break;
            case 'r':
            case 'R': r_flg++;
                      break;
            case 'l':
            case 'L':  l_flg++;
                       break;
            case 'o':
            case 'O': { o_flg++;
                        if(--argc == 0) use_err();
                        strcpy(lst_fil,*++argv);
                        if(lst_fil[0] == '-') use_err();
                         break;}
            case 'w':
            case 'W': { if(--argc == 0) use_err();
                        i = atoi(*++argv);
                        if( i<=MINCOL || i>=255 ) use_err();
                        maxcol = i;
                        break;
                        }
            default: use_err();
          }
        }
      }

      if(o_flg)
        {if( (f_lst_fil=fopen(lst_fil,"w")) == NULL)
         { printf("ERROR: Unable to create list file - %s\n",lst_fil);
           exit(0);}
        printf("XC ... 'C' Concordance Utility  v1.0\n\n");
         }

     prt_ref = FALSE;
     for(linum=0;linum < MAX_WRD;linum++) {
        id_vector[linum] = NULL; }
     for(linum=0;linum < MAX_ALPHA;linum++)
      {
        alpha_vector[linum].alpha_top =
        alpha_vector[linum].alpha_lst = NULL;
      }
     fil_cnt = wrd_cnt = linum = 0;
     filevl=paglin=pagno=edtnum=0;
     id_cnt=rhsh_cnt=0;

     argc = p_argc;  argc--;
     argv = p_argv;
     while(argc--) {
        strcpy(gbl_fil,*++argv);
        if(*gbl_fil == '-')  break;
        proc_file(gbl_fil,dummy);
        }
     if(!l_flg) {
       gbl_fil[0] = '\0';
       prnt_tbl();
       printf("\nAllowable Symbols: %d\n",MAX_WRD);
       printf("Unique    Symbols: %d\n",id_cnt);}
     if(o_flg) {
      nl();
      /* if(fprintf(f_lst_fil,"%c",CPMEOF) == ERROR) lst_err(); */
      fclose(f_lst_fil);
     }
 }

 /*************************************************************************/

 lst_err()

 { printf("\nERROR: Write error on list output file - %s\n",
    lst_fil);
   exit(0);
 }

 /*************************************************************************/

 use_err()

        { printf("\nERROR: Invalid parameter specification\n\n");
        printf("Usage: xc <filename>... <flag(s)>\n\n");
        printf("Flags: -i            = Enable file inclusion\n");
        printf("       -l            = Generate listing only\n");
        printf("       -r            = Cross-reference reserved words\n");
        printf("       -o <outfile>  = Write output to named file\n");
        printf("       -w width      = Width of output page; default=78\n");
        printf("Flags must follow all input file names");
        exit(0); }

 /*************************************************************************/

 proc_file(filnam,incnum)
 char        *filnam;
 int         incnum;        /* prev. included line number (return to caller) *

 {
   char        token[MAX_LEN]; /* token buffer */
   int        eof_flg;        /* end-of-file indicator */
   int        tok_len;        /* token length */
   FILE        *infile;        /* input file */


   strcpy(act_fil,filnam);
   edtnum=0;

   if((infile=fopen(filnam,"r")) == NULL)
       {printf("\nERROR: Unable to open input file: %s\n",filnam);
         return;}  /* ignore error */
   if(filevl++ == 0) prt_hdr();
   eof_flg = FALSE;
   do {
        if(get_token(infile,token,&tok_len,&eof_flg,0))
           if(chk_token(token))
              {
              if(strcmp(token,"#include") == 0)
                 {
                 get_include_fileid(token,infile);
                 if(!i_flg) continue;
                 else
                    {
                    nl();
                    edtnum=proc_file(token,edtnum);
                    strcpy(act_fil,filnam);
                    continue;
                    }
                 }
             put_token(token,linum);
             }
      } while (!eof_flg);

      filevl -= 1;
      fclose(infile);

      return( incnum );
 }

 /*************************************************************************/

 get_include_fileid(token,infile)
 char *token;
 FILE *infile;
 {

    char c, term;

    while ( (term=getc(infile)) == ' ' )  echo(term);
    echo(term);
    if ( term=='<' ) term='>';   /* terminator is > or " */
    if ( (term!='>') && (term!='"') )
       {
       printf("Error scanning #INCLUDE fileid: %c\n", term);
       exit(1);
       }

    do {
       if ( (c = getc(infile)) != ' ')
          {
          *token++ = c;
          echo(c);
          }
       else
          echo(c);
       }
       while ( c!=term );

    *--token = '\0';

 }

 /*************************************************************************/

 echo(c)
 char c;
 {
    static int col = 11;
    int i;
    echochar(c);
    if( c == '\n' )
       col = 11;
    else if( ++col > maxcol )  {
       col = 11;
       paglin++;
       echochar('\n');
       for( i=1; i<=11; i++ )  echochar(' ');
       }
 }

 echochar(c)
 char c;
 {
    if(o_flg)  {
       if(fprintf(f_lst_fil,"%c",c) == ERROR)  lst_err();
       }
    else
       printf("%c",c);
 }
 /*************************************************************************/

 get_token(infile,g_token,g_toklen,g_eoflg,g_flg)

 FILE        *infile;
 char        *g_token;
 int        *g_toklen;
 int        *g_eoflg;
 int        g_flg;

 /*
         'getoken' returns the next valid identifier or
         reserved word from a given file along with the
         character length of the token and an end-of-file
         indicator
 */

 {
 int        c;
 char        *h_token;
 char        tmpchr;

 h_token = g_token;

 gtk:
 *g_toklen = 0;
 g_token = h_token;

 /*
         Scan and discard any characters until an alphabetic or
         '_' (underscore) character is encountered or an end-of-file
         condition occurs
 */

 while( (!isalpha(*g_token = rdchr(infile,g_eoflg,g_flg)))
   && !*g_eoflg
   && *g_token != '_'
   && *g_token != '0'
   && *g_token != '#');
 if(*g_eoflg) return(FALSE);
 *g_toklen += 1;

 /*
         Scan and collect identified alpanumeric token until
         a non-alphanumeric character is encountered or and
         end-of-file condition occurs
 */

 if(g_flg) tmpchr = '.';
      else tmpchr = '_';
 while( (isalpha(c=rdchr(infile,g_eoflg,g_flg))
         || isdigit(c)
         || c == '_'
         || c == tmpchr)
      && !*g_eoflg)
         {
          if(*g_toklen < MAX_LEN)
           { *++g_token = c;
           *g_toklen += 1; }
         }

 /*
         Check to see if a numeric hex or octal constant has
         been encountered ... if so dump it and try again
 */

         if (*h_token == '0') goto gtk;


 /*
         Tack a NULL character onto the end of the token
 */

  *++g_token = NULL;

 /*
         Screen out all #token strings except #include
 */

 if (*h_token == '#' && strcmp(h_token,"#include")) goto gtk;

  return(TRUE);
 }

 /*************************************************************************/

  fil_chr(infile,f_eof)
    FILE *infile;
    int *f_eof;
    { int fc;
    fc=getc(infile);
 /* if(fc == ERROR) {  /* omit since ERROR and EOF have save value for GETC  *
 /*   printf("\nERROR: Error while processing input file - %s\n",            *
 /*   act_fil);
 /*   exit(0);
 /*   }
     if (fc == EOF) { *f_eof = TRUE;
                                      fc = NULL; }
     return(fc);
 }

 /*************************************************************************/

 rdchr(infile,r_eoflg,rd_flg)

 int        *r_eoflg;
 FILE        *infile;
 int        rd_flg;

 /*
         'rdchr' returns the next valid character in a file
         and an end-of-file indicator. A valid character is
         defined as any which does not appear in either a
         commented or a quoted string ... 'rdchr' will correctly
         handle comment tokens which appear within a quoted
         string
 */

 {
 int        c;
 int        q_flg;                /* double quoted string flag */
 int        q1_flg;         /* single quoted string flag */
 int        cs_flg;         /* comment start flag */
 int        ce_flg;         /* comment end flag */
 int        c_cnt;                /* comment nesting level */
 int        t_flg;                /* transparency flag */

 q_flg = FALSE;
 q1_flg = FALSE;
 cs_flg = FALSE;
 ce_flg = FALSE;
 t_flg = FALSE;
 c_cnt  = 0;

 rch:

 /*
         Fetch character from file
 */

 c=fil_chr(infile,r_eoflg);
 if(*r_eoflg) return(c);   /* EOF encountered */
 if(c == '\n')
                 nl();
              else
                 echo(c);

 if(rd_flg) return(c);

 if(t_flg) { t_flg = !t_flg;
             goto rch;}

 if(c == '\\') { t_flg = TRUE;
                 goto rch;}
 /*
         If the character is not part of a quoted string
         check for and process commented strings...
         nested comments are handled correctly but unbalanced
         comments are not ... the assumption is made that
         the syntax of the program being xref'd is correct
 */

 if (!q_flg && !q1_flg) {
      if (c == '*' && c_cnt && !cs_flg) { ce_flg = TRUE;
                       goto rch;}
      if (c == '/' && ce_flg) { c_cnt -= 1;
                           ce_flg = FALSE;
                           goto rch; }
      ce_flg = FALSE;
      if (c == '/') { cs_flg = TRUE;
                 goto rch; }
      if (c == '*' && cs_flg) { c_cnt += 1;
                           cs_flg = FALSE;
                           goto rch; }
      cs_flg = FALSE;
      if (c_cnt) goto rch;
 }

 /*
         Check for and process quoted strings
 */

 if ( c == '"' && !q1_flg) { q_flg =  !q_flg; /* toggle quote flag */
                         goto rch;}
 if (q_flg) goto rch;

 if (c == '\'') { q1_flg = !q1_flg; /* toggle quote flag */
                 goto rch; }
 if (q1_flg) goto rch;

 /*
         Valid character ... return to caller
 */

 return(c);
 }

 /*************************************************************************/

 chk_token(c_token)
 char        *c_token;

 {
   char        u_token[MAX_LEN];
   int        i;

     {
       if(r_flg) return(TRUE);
       i = 0;
       do { u_token[i] = toupper(c_token[i]); }
          while (c_token[i++] != NULL);

       switch(u_token[0]) {
         case 'A': if (strcmp(u_token,"AUTO") == 0) return(FALSE);
                   break;
         case 'B': if (strcmp(u_token,"BREAK") == 0) return(FALSE);
                   break;
         case 'C': if (strcmp(u_token,"CHAR") == 0) return (FALSE);
                   if (strcmp(u_token,"CONTINUE") == 0) return (FALSE);
                   if (strcmp(u_token,"CASE") == 0) return (FALSE);
                   break;
         case 'D': if(strcmp(u_token,"DOUBLE") == 0) return(FALSE);
                   if(strcmp(u_token,"DO") == 0) return(FALSE);
                   if(strcmp(u_token,"DEFAULT") == 0) return(FALSE);
                   break;
         case 'E': if(strcmp(u_token,"EXTERN") == 0) return(FALSE);
                   if(strcmp(u_token,"ELSE") == 0) return(FALSE);
                   if(strcmp(u_token,"ENTRY") == 0) return(FALSE);
                   break;
         case 'F': if(strcmp(u_token,"FLOAT") == 0) return(FALSE);
                   if(strcmp(u_token,"FOR") == 0) return(FALSE);
                   break;
         case 'G': if(strcmp(u_token,"GOTO") == 0) return(FALSE);
                   break;
         case 'I': if(strcmp(u_token,"INT") == 0) return(FALSE);
                   if(strcmp(u_token,"IF") == 0) return(FALSE);
                   break;
         case 'L': if(strcmp(u_token,"LONG") == 0) return(FALSE);
                   break;
         case 'R': if(strcmp(u_token,"RETURN") == 0) return(FALSE);
                   if(strcmp(u_token,"REGISTER") == 0) return(FALSE);
                   break;
         case 'S': if(strcmp(u_token,"STRUCT") == 0) return(FALSE);
                   if(strcmp(u_token,"SHORT") == 0) return(FALSE);
                   if(strcmp(u_token,"STATIC") == 0) return(FALSE);
                   if(strcmp(u_token,"SIZEOF") == 0) return(FALSE);
                   if(strcmp(u_token,"SWITCH") == 0) return(FALSE);
                   break;
         case 'T': if(strcmp(u_token,"TYPEDEF") == 0) return(FALSE);
                   break;
         case 'U': if(strcmp(u_token,"UNION") == 0) return(FALSE);
                   if(strcmp(u_token,"UNSIGNED") == 0) return(FALSE);
                   break;
         case 'W': if(strcmp(u_token,"WHILE") == 0) return(FALSE);
                   break; }
         }
   return(TRUE);
 }

 /*************************************************************************/

 /*
    Install parsed token and line reference in linked structure
 */

 put_token(p_token,p_ref)

 char *p_token;
 int  p_ref;

 {
   int  hsh_index;
   int  i;
   int  j;
   int  d;
   int  found;
   struct id_blk *idptr;
   struct rf_blk *rfptr;
   struct id_blk *alloc_id();
   struct rf_blk *alloc_rf();
   struct rf_blk *add_rf();

   if(l_flg) return;
   j=0;
   for (i=0; p_token[i] != NULL; i++)  /* Hashing algorithm is far from */
   {                                      /* optimal but is adequate for a */
       j = j * 10 + p_token[i];              /* memory-bound index vector!
    }
   hsh_index = abs(j) % MAX_WRD;
   found = FALSE;
   d = 1;
   do {
        idptr = id_vector[hsh_index];
        if(idptr == NULL) {
          id_cnt++;
          idptr = id_vector[hsh_index] = alloc_id(p_token);
          chain_alpha(idptr,p_token);
          idptr->top_lnk = idptr->lst_lnk = alloc_rf(p_ref);
          found = TRUE;
        }
        else
        if(strcmp(p_token,idptr->id_name) == 0) {
          idptr->lst_lnk = add_rf(idptr->lst_lnk,p_ref);
            found = TRUE;
          }
        else
        { hsh_index += d;
          d += 2;
          rhsh_cnt++;
          if (hsh_index >= MAX_WRD)
             hsh_index -= MAX_WRD;
          if (d == MAX_WRD) {
             printf("\nERROR: Symbol table overflow\n");
             exit(0);
          }
        }
       } while (!found);
 }

 /*************************************************************************/

 chain_alpha(ca_ptr,ca_token)

 struct id_blk *ca_ptr;
 char  *ca_token;

 {
   char        c;
   int        f;
   struct id_blk *cur_ptr;
   struct id_blk *lst_ptr;

   c = ca_token[0];
   if(c == '_') c = 0;
     else
       if (isupper(c))  c=1+((c-'A')*2);
       else               c=2+((c-'a')*2);

   if(alpha_vector[c].alpha_top == NULL)
     { alpha_vector[c].alpha_top =
       alpha_vector[c].alpha_lst = ca_ptr;
       ca_ptr->alpha_lnk = NULL;
       return;
     }

 /* check to see if new id_blk should be inserted between
    the alpha_vector header block and the first id_blk in
    the current alpha chain
 */

  if(strcmp(alpha_vector[c].alpha_top->id_name,ca_token) >0)
   {
     ca_ptr->alpha_lnk=alpha_vector[c].alpha_top;
     alpha_vector[c].alpha_top=ca_ptr;
     return;
   }

   if(strcmp(alpha_vector[c].alpha_lst->id_name,ca_token) < 0)
     { alpha_vector[c].alpha_lst->alpha_lnk = ca_ptr;
       ca_ptr->alpha_lnk = NULL;
       alpha_vector[c].alpha_lst=ca_ptr;
       return;
     }

   cur_ptr = alpha_vector[c].alpha_top;
   while(strcmp(cur_ptr->id_name,ca_token) < 0)
    { lst_ptr = cur_ptr;
      cur_ptr = lst_ptr->alpha_lnk;
    }

   lst_ptr->alpha_lnk = ca_ptr;
   ca_ptr->alpha_lnk = cur_ptr;
   return;
 }

 /*************************************************************************/

 struct id_blk *alloc_id(aid_token)
   char        *aid_token;

   {
     int  ai;
     struct id_blk *aid_ptr;

      if((aid_ptr = alloc(sizeof(struct id_blk))) == 0) {
        printf("\nERROR: Unable to allocate identifier block\n");
        exit(0);
      }
      ai=0;
      do {
           aid_ptr->id_name[ai] = aid_token[ai];
         } while (aid_token[ai++] != NULL);
      return (aid_ptr);
 }

 /*************************************************************************/

 struct rf_blk *alloc_rf(arf_ref)

   int  arf_ref;

   {
     int ri;
     struct rf_blk *arf_ptr;

     if((arf_ptr = alloc(sizeof(struct rf_blk))) == 0) {
       printf("\nERROR: Unable to allocate reference block\n");
       exit(0);
     }
     arf_ptr->ref_item[0] = arf_ref;
     arf_ptr->ref_cnt = 1;
     for(ri=1;ri<MAX_REF;ri++)
       arf_ptr->ref_item[ri] = NULL;
     return (arf_ptr);
   }

 /*************************************************************************/

 struct rf_blk *add_rf(adr_ptr,adr_ref)

   struct rf_blk *adr_ptr;
   int adr_ref;

   {
     struct rf_blk *tmp_ptr;

     tmp_ptr = adr_ptr;
     if(adr_ptr->ref_cnt == MAX_REF) {
       tmp_ptr = adr_ptr->ref_cnt = alloc_rf(adr_ref);
     }
     else
     { adr_ptr->ref_item[adr_ptr->ref_cnt++] = adr_ref;
     }
     return (tmp_ptr);
   }

 /*************************************************************************/

 prnt_tbl()
 {  int prf_cnt;
    int pti;
    int pref;
    int lin_cnt;
    struct id_blk *pid_ptr;
    struct rf_blk *ptb_ptr;

   prt_ref = TRUE;
   prt_hdr();
   for (pti=0;pti<MAX_ALPHA;pti++)
   { if ((pid_ptr = alpha_vector[pti].alpha_top) != NULL)
       { do
      { if(o_flg)
          {if(fprintf(f_lst_fil,"%-20.19s: ",pid_ptr->id_name) == ERROR)
             lst_err();}
        else
           printf("%-20.19s: ",pid_ptr->id_name);
        ptb_ptr=pid_ptr->top_lnk;
        lin_cnt=prf_cnt=0;
        do { if(prf_cnt == MAX_REF)
               { prf_cnt=0;
                 ptb_ptr = ptb_ptr->ref_cnt;
               }
            if(ptb_ptr > MAX_REF)
             {
              if((pref=ptb_ptr->ref_item[prf_cnt++]) != 0)
                 { if(o_flg)
                  {if(fprintf(f_lst_fil,"%4d ",pref) == ERROR) lst_err();}
                 else
                 printf("%4d ",pref);
                 if (++lin_cnt == REFS_PER_LINE)
                     { nl();
                       if(o_flg)
                          {if(fprintf(f_lst_fil,"                      ") == E
                       else
                          printf("                      ");
                       lin_cnt=0;
                     }
                 }
               } else pref=0;
            } while (pref);
         nl();
         } while ((pid_ptr=pid_ptr->alpha_lnk) != NULL);
       }
    }/*for*/

    echo( '\n' );

 }

 /*************************************************************************/

 prt_hdr()

 {
   if (pagno++ != 0)    { echo( '\n' ); echo( FF ); }
   if (o_flg)
    {if(fprintf(f_lst_fil,
           "XC ... 'C' Concordance Utility   %-20s       Page %d",
      gbl_fil,pagno) == ERROR) lst_err();}
   else
    printf("XC ... 'C' Concordance Utility   %-20s       Page %d",
      gbl_fil,pagno);
   echo('\n');
   paglin = 3;
   nl();
 }

 /*************************************************************************/

 nl()

 {
   echo('\n');
   if(++paglin >= LINES_PER_PAGE) prt_hdr();
     else
   if(!prt_ref) {
     if(o_flg) {
        if(fprintf(f_lst_fil,"%-4d %4d: ",    ++linum,++edtnum) == ERROR)
        lst_err();
        }
     else
        printf("%-4d %4d: ",    ++linum,++edtnum);
     if(o_flg)
        if(linum % 60 == 1)
           printf("\n<%d> ",linum);
        else {
           printf(".");
 #if Lattice
           fflush(stdout);
 #endif
           }

     }
  return;
 }

 /*************************************************************************/

 #ifndef Lattice
 abs(i)
 int i;
 {
    if (i<0) return(-i);
    else     return( i);
 }
 #endif

 /*************************************************************************/

 #ifdef Lattice
 /*    cvt ascii to int or long         */

 long atoi(s)
 char *s;
 {
    long n;
    int sign = 0;

    while(*s==' ' || *s=='\t')  ++s;   /* move over blanks & tabs */
    if (*s=='-')
       sign=1;
    else
       if (*s!='+')  --s;
    ++s;                               /* skip sign */
    for( n=0; *s>='0' && *s<='9'; )
       n = n * 10 + (*s++ - '0');
    if (sign)   n = -n;
    return n;
 }
 #endif

 /*************************************************************************/

 alloc(i)
 int i;
 {
    return malloc(i);
 }


 XC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\XC.C

 /***********************************************************/
 /*    XC.C                                                   */
 /*                                                           */
 /*    Last modified:        22:50        20 May        84        RSW
 /*                                                           */
 /*    Abstract:                                                   */
 /*                                                           */
 /*    'XC' is a        cross-reference        utility        for 'C'        p
 /*    Its has the ability to handle nested include files   */
 /*    to a depth of 8 levels and properly processes nested */
 /*    comments as supported by BDS C. Option flags support */
 /*    the following features:                                   */
 /*                                                           */
 /*    -        Routing        of list        output to disk
 /*    -        Cross-referencing of reserved words                   */
 /*    -        Processing of nested include files                   */
 /*    -        Generation of listing only                           */
 /*                                                           */
 /*    Usage: xc        <filename> <flag(s)>                           */
 /*                                                           */
 /*    Flags: -i                   = Enable file inclusion           */
 /*             -l                   = Generate listing only           */
 /*             -c                   = Compressed        print listing
 /*             -r                   = Cross-ref reserved        words
 /*             -o        <filename> = Write output to named file           */
 /*                                                           */
 /*************************************************************************/
 /*  5-20-84  Changes                        R.S. White
 /*     - made compilation for Lattice C        ver 2.0        or Computer Inn
 /*              CI-C86 optional by setting #define labels        accordingly.
 /*     - made printer selection        for compressed print selectable
 /*              setting #define labels accordingly.  Added Epson FX and
 /*              Gemini-10X printer control strings.                         *
 /*************************************************************************/
 /*  1-01-84  Enhancements                S.R. Jacobson
 /*     - changed -e option to -c option        and added two strings:
 /*              cprint_hdr sets the printer to compressed        print mode
 /*              cprint_trlr resets the printer to        "normal" mode
 /*           This        makes it easier        for non-epson printer users
 /*     -  removed all the BDS C        comments (this makes it        easier
 /*              in the future.
 /*     -  changed name of the utility to the "print" utility
 /*     -  if the -i flag is not        used, the second line number will not
 /*              appear.
 /*     -  if a form feed is detected in        the source file, a new page is
 /*              started.        This is        useful for structuring the sou
 /*              code by placing each major section on a separate page.
 /*              You do this by embedding a form feed (control L) in a
 /*              comment.        The text following the form feed will be plac
 /*              on the top of the        new page.
 /*     -  tab characters in the        file are expanded to every 8 positions
 /*              This may be changed by changing the TABCNT define.         */
 /*     -  added        the date and time to the printed output. (C-86 only)
 /*     -  fixed        error in hashing algorithm.
 /*     -  control characters (other than \n, \f, or \t)        are stripped
 /*              from the input stream (converted to blanks).  This         */
 /*              prevents extraneous control chars        from interfering wit
 /*              operation        of xc.
 /*     -  cleaned up the structuring of        a number of routines.
 /*     -  added        the file latest        update date and        time to
 /*              output. ***DOS 2.0 ONLY ***                                 *
 /*************************************************************************/
 /*   9-26-83   Microsoft C 1.04         Conversion    WHR
 /*     -  \t between line numbers and text to fix indenting problem.
 /*     -  added        option -e for output to        Epson in condensed prin
 /*     -  toupper() and        isupper() are macros, not functions.
 /*     -  eliminate side effect        in toupper(*++arg) in main().
 /*     -  change alloc() to malloc().
 /*     -  add #define NAMES that are not in stdio.h                         *
 /*     -  MS-C requires        () in statement        A?(c=B):(c=C)        er
 /*                                                                         */
 /*   4-30-83   Computer        Innovations C-86 1.31 Conversion    WHR
 /*     -  #include filename changed to allow a disk drive prefix, D:
 /*     -  convert if(fprintf(...) == ERROR) lst_err(); to fprintf(..);
 /*     -  convert if(fopen(...)        == ERROR) statements to        == NUL0
 /*     -  C86 requires () in statement A?(c=B):(c=C)        error or not??
 /*     -  remove getc()        == ERROR check in fil_chr().
 /*     -  convert file conventions from        BDS C to C-86.
 /*     -  comment out BDS unique statements, mark revised statements.
 /*          keep all BDS statements to document conversion effort.         */
 /*                                                                         */
 /**  4-19-83   BDS C Version file XC.CQ        copied from Laurel RCPM
 /*************************************************************************/
 /*   **        Original Version: **                                   */
 /*                                                           */
 /*    Version 1.0   January, 1982                           */
 /*                                                           */
 /*    Copyright        (c) 1982 by Philip N. Hisley                   */
 /*                                                           */
 /*    Released for non-commercial distribution only           */
 /*                                                           */
 /*    Please report bugs/fixes/enhancements to:                   */
 /*                                                           */
 /*              Philip N.        Hisley                                   */
 /*              548H Jamestown Court                           */
 /*              Edgewood,        Maryland 21040                           */
 /*              (301) 679-4606                                   */
 /*              Net Addr:        PNH@MIT-AI                           */
 /*                                                           */
 /*                                                           */
 /***********************************************************/

 /*  DEFINITIONS AND VARIABLES        */                                /*SRJ

 <stdio.h>                                            /* WHR */

        LATTICE        1        /* set to use Lattice C        ver 2.0
        CIC86        0        /* disable Computer Innovations        compiler

        GEMIN10X 0        /* enable Gemini-10X printer codes        */  /*RSW*
        EPSONMX         0                                                    /
        EPSONFX         0                                                    /
        IDSPRISM 1                                                    /*RSW*/

 #if LATTICE
 <ctype.h>        /* Lattice C ver 2.0 - macros */            /*RSW*/
 #endif

         TABCNT            8                /* expand tabs to every        8 c
 #define         NUL0            0
         FALSE            0                                              /* WH
         TRUE            1                                              /* WHR
         CPMEOF          0x1A                      /* end of        file */
         ERROR          (-1)                                              /* W

         MAX_REF    5                /* maximum refs        per ref-block */

         MAX_LEN 39  /*        maximum        identifier length -n opt Lattice
         MAX_WRD   749                /* maximum number of identifiers */
         MX_ALPHA  53                /* maximum alpha chain heads */
         REFS_LIN  8                /* maximum refs        per line */
         LINE_PAG  60        /* note        Lattice        C gets confused
                         /* option is used and #define labels   */
                         /* are longer than 8 characters               */

 struct        id_blk {
                  char  id_name[MAX_LEN];
                  struct        id_blk *alpha_lnk;
                  struct        rf_blk *top_lnk;
                  struct        rf_blk *lst_lnk;
                } oneid;

 struct        rf_blk {
                  int  ref_item[MAX_REF];
                  int  ref_cnt;
                } onerf;

 struct id_blk *id_vector[MAX_WRD];

 struct alpha_hdr { struct id_blk *alpha_top;
                    struct id_blk *alpha_lst;
                  };

 struct alpha_hdr alpha_vector[MX_ALPHA];

 struct        regval        {
                 unsigned int ax,bx,cx,dx,si,di,ds,es;
                 } reg; /*structure for sysint*/                           /*S

 struct        regv        {
                 unsigned int csx,ssx,dsx,esx;
                 } regx;           /* structure        for segread*/


 int        y,mo,d;                        /* year,month and day for date */
 int        h,mi,s;                        /* hours, minutes, seconds for time

 char        *months[]=                /* month names for date        */
                 {"bad month","January","February","March","April","May","June
                 "July","August","September","October","November","December"};

 int        ln_chr=0;                /* # of        characters in the line (fo

 unsigned int        handle;                        /* dos file handle */
 unsigned int file_d,file_mo,file_y,file_h,file_mi; /* file m/d/y and h:m  SRJ

 FILE        *tb;                        /* temp        fd */


 int        linum;                /* line        number */
 int        edtnum;                /* edit        line number */
 int        fil_cnt;        /* active file index */
 int        wrd_cnt;        /* token count */
 int        pagno;                /* page        number */
 int        id_cnt;                /* number of unique identifiers        */
 int        rhsh_cnt;        /* number of conflict hits */
 int        filevl;                /* file        level  */
 int        paglin;                /* page        line counter */
 int        prt_ref;
 char        act_fil[MAX_LEN];
 char        lst_fil[MAX_LEN];
 char        gbl_fil[MAX_LEN];
 FILE   *l_buffer;                                             /*          WHR
 int        i_flg,o_flg,r_flg,l_flg;
 int        debug;
 int        c_flg;                                                     /*


 /* The following two strings are the compressed        print header and the
 trailer        that returns the printer to the        normal mode.  These mus
 be changed for each printer.  They are currently set up        for the

 GEMIN10X                                                                /*RSW
 char cprint_hdr[]="\x1bB\3\1bQ\x84"; /*        header string for Gemini-10X *
 char cprint_trlr[]="\x1bB\2"; /* ELITE mode trailer string for Gemini-10X */
 #endif

 IDSPRISM                                                                /*RSW
 char        cprint_hdr[] = "\037";  /* header string for Prism 80 */
 char        cprint_trlr[] =        "\035";        /* trailer string for Prism
 #endif

 EPSONMX                                                                /*RSW*
 char        cprint_hdr[] = "\x1b\x40\x0F\x1BQ\x84";
 char        cprint_trlr[] =        "\x1b\x40";    /* trailer string for Epson
 #endif

 EPSONFX                                                                /*RSW*
 char cprint_hdr[]="\x1b!\4\x1bQ\x84"; /* header        string for Epson FX */
 char cprint_trlr[]="\x1b!\1"; /*ELITE mode trailer string for Epson FX*/ /*RS
 #endif


 /* end of printer strings */
 /*  MAIN PROGRAM        */                                        /*SRJ*/


 main(argc,argv)
      int     argc;
      char    **argv;

      {char  *arg;
      char *strcpy();
 /*** int  toupper();   ***/                     /*        Microsoft C   macro
      char cc;                                     /*        Microsoft C */

 /*  The        the parameters        */

      if        (argc <        2) use_err();
      i_flg=r_flg=o_flg=l_flg=FALSE;
      debug = FALSE;
      strcpy(gbl_fil,*++argv);
      --argc;
      if(gbl_fil[0] == '-')
           use_err();
      while(--argc != 0)
      {          if(*(arg=*++argv) == '-')
     /*****{    switch( toupper(*++arg) )     *** side effect in        Micros
           {    switch( cc=*++arg, toupper(cc) )                     /*
                {   case        'I':  i_flg++;
                               break;
                    case        'R':  r_flg++;
                               break;
                    case        'L':  l_flg++;
                               break;
                    case        'O': {o_flg++;
                               if(--argc        == 0) use_err();
                               strcpy(lst_fil,*++argv);
                               if(lst_fil[0] == '-') use_err();
                               if(debug)        printf("lst_fil=>%s<",lst_fil)
                               break;
                              }
                    case        'D':  debug++;
                               break;
                    case        'C':  c_flg++;                        /* SRJ *
                               o_flg++;
                               strcpy(lst_fil,"PRN:");        /* SRJ */
                               break;
                    default:   use_err();
                }
           }
      else use_err();
      }
      if(debug) printf("\ni_flg=%d, r_flg=%d, l_flg=%d",        i_flg,r_flg,l_
      if(debug) printf("\no_flg=%d, debug=%d", o_flg,debug);
      if        (o_flg)
           {if (        (l_buffer = fopen(lst_fil,"w"))        == NUL0)   /***
               {printf("ERROR: Unable to create list file - %s\n",lst_fil);
                exit(0);
               }
           printf("\nXC ....... 'C' Print Utility  v1.1\n");                /*
           if (c_flg) fprintf(l_buffer,"%s",cprint_hdr);
           }
       else                                                                /*S
           l_buffer=stdout;        /* if no output        file, use stdout */

 /* THE FOLLOWING CODE GETS THE DATE AND        THE TIME FROM DOS.  IT USES TH
 ROUTINES SYSINT        AND SEGREAD PROVIDED BY        THE CI C-86 LIBRARY.  T
 DEPENDENT CODE AND MUST        BE CHANGED FOR OTHER COMPILERS
 /* added Lattice C ver 2.00 int86 calls        to do the same */

 segread(&regx);                /* get the segment registers */
 reg.ds=regx.dsx;        /* save        the ds in the sysint data */
 reg.es=regx.esx;        /* save        the es in the sysint data */

 /* get the date        */
 reg.ax=0x2A00;                        /* date        request        code */

 #if CIC86
 sysint(0x21,&reg,&reg);                /* DOS interrupt */
 #endif

 #if LATTICE
 int86(0x21,&reg,&reg);                /* Lattice C ver 2.0 interupt */
 #endif

 y=reg.cx;                        /* store year */                        /*SR
 mo=reg.dx>>8;                        /* store month */
 d=reg.dx & 0xFF;                /* get the day */                        /*SR

 /* get the time        */
 reg.ax=0x2C00;                        /* time        request        code */

 #if CIC86
 sysint(0x21,&reg,&reg);                /* DOS interrupt */
 #endif

 #if LATTICE
 int86(0x21,&reg,&reg);                /* Lattice C ver 2.0 interupt */
 #endif

 h=reg.cx>>8;                        /* get hours */
 mi=reg.cx & 0xFF;                /* get minutes */                        /*S
 s=reg.dx>>8;                        /* get seconds */

 /* NOW WE GET THE FILE LATEST UPDATE DATE AND TIME */

 /* first try to        open the file */

 if ((tb        = fopen(gbl_fil,"r")) == NUL0)        /*open the input file */
         {printf("\nERROR: Unable to open input file: %s\n",gbl_fil);        /
         exit(10);                                                        /*SR
         }
 fclose(tb);                        /* close the file */

 /* note-we have        no way to get an error indication back from the
 below (file open),  so we have to open it to see if it is there        before
 we can use the proceedure below        */

 /* now get the file date and time */                                        /

 /* open        the file   -  we assume        the file exists        */
 reg.ax=0x3D00;                        /* open        request        code */

 /* reg.dx=gbl_fil;   */                /* address of file name        */
 reg.dx = &gbl_fil;                /* address of file name        */

 #if CIC86
 sysint(0x21,&reg,&reg);                /* DOS interrupt */
 #endif

 #if LATTICE
 int86(0x21,&reg,&reg);                /* Lattice C ver 2.0 interupt */
 #endif

 handle=reg.ax;                        /* store file handle */

 /* get the date        and time */
 reg.ax=0x5700;                        /* time        request        code */
 reg.bx=handle;                        /* file        handle in bx */

 #if CIC86
 sysint(0x21,&reg,&reg);                /* DOS interrupt */
 #endif

 #if LATTICE
 int86(0x21,&reg,&reg);                /* Lattice C ver 2.0 interupt */
 #endif


 /* unpack the file time        */
 file_h=(reg.cx >> 11) &        0x1F;                /* get hours */
 file_mi=(reg.cx        >> 5) &        0x3f;                /* get minutes */

 /* unpack the file date        */
 file_d=reg.dx &        0x1F;                        /* get the day */
 file_mo= (reg.dx >> 5) & 0x0F;                /* get the month */

 file_y=( (reg.dx >> 9) & 0x7F )+80;        /* get the month */

 /* close the file */                                                        /

 reg.bx=handle;
 reg.ax=0x3D00;

 #if CIC86
 sysint(0x21,&reg,&reg);                /* DOS interrupt */
 #endif

 #if LATTICE
 int86(0x21,&reg,&reg);                /* Lattice C ver 2.0 interupt */
 #endif



 /* END OF compiler DEPENDENT CODE  */


      prt_ref = FALSE;
      for(linum=0;linum < MAX_WRD;linum++)
           id_vector[linum] = NUL0;

      for(linum=0;linum < MX_ALPHA;linum++)
           alpha_vector[linum].alpha_top        =
                alpha_vector[linum].alpha_lst = NUL0;

      fil_cnt = wrd_cnt = linum = 0;
      filevl=paglin=pagno=edtnum=0;
      id_cnt=rhsh_cnt=0;
      proc_file(gbl_fil);
      if(!l_flg)
          {prnt_tbl();
          printf("\nAllowable Symbols: %d\n",MAX_WRD);
          printf("Unique    Symbols: %d\n",id_cnt);
          }
      if(o_flg)
           {nl();
           fprintf(l_buffer,"\nAllowable Symbols: %d\n",MAX_WRD);   /* WHR */
           fprintf(l_buffer,"Unique    Symbols: %d\n",id_cnt);           /* WH
           fprintf(l_buffer,"\f%c",CPMEOF);                        /* WHR */
           fprintf(l_buffer,"%s",cprint_trlr); /* output        trailer
           fflush(l_buffer);
           fclose(l_buffer);
           }
 }
 /*   ERROR MESSAGE PRINT ROUTINES */                                /*SRJ*/

 lst_err()

 {printf("\nERROR: Write error on list output file - %s\n",lst_fil);
 exit(0);
 }


 use_err()

 {printf("\nERROR: Invalid parameter specification\n\n");
 printf("Usage: xc <filename> <flag(s)>\n\n");
 printf("Flags: -i             = Enable file inclusion\n");
 printf("       -l             = Generate listing only\n");
 printf("       -c             = Compressed print option\n");  /*SRJ*/
 printf("       -r             = Cross-reference reserved words\n");
 printf("       -o <filename>  = Write output to named file\n");
 exit(0);
 }

 /*   PROCESS THE FILE        */                                        /*SRJ

 proc_file(filnam)

 char        *filnam;

 {FILE  *buffer;           /* allocated        buffer pointer */            /*
 char  token[MAX_LEN]; /* token buffer */
 int   eof_flg;           /* end-of-file indicator */
 int   tok_len;           /* token length */
 int   incnum;           /* included line number */
 char *strcpy();

 strcpy(act_fil,filnam);
 if ((buffer = fopen(filnam,"r")) == NUL0)  /***        input file ***/
         {printf("\nERROR: Unable to open input file: %s\n",filnam);
         exit(0);
         }
 if(filevl++ == 0)
         {prt_hdr();
         nl();
         }
 eof_flg        = FALSE;

 do
         {if(get_token(buffer,token,&tok_len,&eof_flg,0))
                 {if (debug) printf("token: %s   length: %d\n",token,tok_len);
                 if (chk_token(token))

                      /*        #include processing changed to accept drive:
                         {if (strcmp(token,"#include") == 0)
                                 {if (get_token(buffer,token,&tok_len,&eof_flg
                                         {if (debug) printf("**token: %s   len
                                                   token,tok_len);
                                         if (!i_flg)
                                                 continue;
                                           else
                                                 {incnum=edtnum;
                                                 edtnum=0;
                                                 nl();
                                                 proc_file(token);
                                                 edtnum=incnum;
                                                 strcpy(act_fil,filnam);
                                                 continue;
                                                 }
                                         }
                                 }
                         put_token(token,linum);
                         }
                 }
         }
 while (!eof_flg);

 filevl -= 1;
 fclose(buffer);
 return;
 }
 /*   GET A TOKEN    */                                                /*SRJ*

 get_token(g_buffer,g_token,g_toklen,g_eoflg,g_flg)

 FILE        *g_buffer;
 char        *g_token;
 int        *g_toklen;
 int        *g_eoflg;
 int        g_flg;

 /*
 *         'getoken' returns the next valid identifier or
 *         reserved word from a given file along with the
 *         character length of the token and an end-of-file
 *         indicator
 *
 */

 {
      int     c;
      char    *h_token;
      char    tmpchr;
      char    tmpchr2;                      /* WHR fix for B:filename.ext */

      h_token = g_token;

  gtk:                               /* top of loop, get new token */
      *g_toklen = 0;
      g_token = h_token;

     /*
      *        Scan and discard any characters        until an alphabetic or
      *        '_' (underscore) character is encountered or an        end-of-f
      *        condition occurs
      */

      while(  (!isalpha(*g_token        = rdchr(g_buffer,g_eoflg,g_flg)))
              &&         !*g_eoflg        &&  *g_token !=        '_'
              &&        *g_token != '0'        &&  *g_token !=        '#' );
      if(*g_eoflg) return(FALSE);

      *g_toklen += 1;

     /*
      *         Scan and collect identified alpanumeric token until
      *         a non-alphanumeric character is encountered or        and
      *         end-of-file condition occurs
      */

      if(g_flg) {
           tmpchr  = '.';
           tmpchr2 = ':';                   /* WHR fix for B:filename.ext */
      }
      else {
           tmpchr  = '_';
           tmpchr2 = '_';                   /* WHR fix for B:filename.ext */
      }
      while( (isalpha(c=rdchr(g_buffer,g_eoflg,g_flg)) ||
             isdigit(c) || c == '_' || c        == tmpchr || c == tmpchr2)
             && !*g_eoflg)                   /* WHR fix for B:filename.ext */
      {          if(*g_toklen < MAX_LEN)
           {    *++g_token = c;
                *g_toklen += 1;
           }
      }


     /*
      *            Check to see if a numeric hex or octal constant has
      *            been encountered ... if so dump it and try again
      */


      if        (*h_token == '0') goto gtk;


     /*
      *            Tack a NUL0        character onto the end of the token
      */

      *++g_token        = NUL0;

     /*
      *            Screen out all #token strings except #include
      */

      if        (*h_token == '#' && strcmp(h_token,"#include"))        goto gt

      return (TRUE);
 }
 /*  READ A CHARACTER FROM THE FILE AND        PROCESS        IT */


 rdchr(r_buffer,r_eoflg,rd_flg)
      int     *r_eoflg;
      FILE    *r_buffer;
      int     rd_flg;

 /*
         'rdchr'        returns        the next valid character in a file
         and an end-of-file indicator. A        valid character        is
         defined        as any which does not appear in        either a
         commented or a quoted string ... 'rdchr' will correctly
         handle comment tokens which appear within a quoted
         string
 */

 {
      int     c;
      int     q_flg;             /*        double quoted string flag */
      int     q1_flg;             /*        single quoted string flag */
      int     cs_flg;             /*        comment        start flag */
      int     ce_flg;             /*        comment        end flag */
      int     c_cnt;             /*        comment        nesting        level
      int     t_flg;             /*        transparency flag */

      q_flg = FALSE;
      q1_flg = FALSE;
      cs_flg = FALSE;
      ce_flg = FALSE;
      t_flg = FALSE;
      c_cnt  = 0;

 rch:


     /*
      *         Fetch character from file
      */

      c = fil_chr(r_buffer,r_eoflg) & 0x7F;        /* read        only 7 bit a

      if        (*r_eoflg) return(c);        /* EOF encountered */

      switch(c)                        /* test        the returned character *
         {case '\n':                /* carriage return */                    /
                 nl();                /* output new line and line numbers */ /
                 ln_chr=0;        /* set to first        char in        line *
                 c=' ';                /* return a space */
                 break;

         case '\f':                /* form        feed */
                 prt_hdr();        /* output header and start new page*/ /*SRJ
                 fprintf(l_buffer,"     "); /* space over line #s */   /*SRJ*/
                 ln_chr=0;        /* set to first        char in        line *
                 c=' ';                /* set char to blank */
                 break;

         case '\t':                /* tab character */                /*SRJ*/
                 do                /* expand the tabs */                /*SRJ*
                         fputc(' ',l_buffer);                        /*SRJ*/
                 while( (++ln_chr % TABCNT) != 0);                /*SRJ*/
                 c=' ';                /* set char to blank */
                 break;


         default:
                 ln_chr++;                /* move        to next        char p
                 if( iscntrl(c) )        /* insure no control chars */ /*SRJ*/
                         c=' ';
                 fputc(c,l_buffer);        /* and output next char        */
         }

      if        (rd_flg) return(c);

      if        (t_flg)        {
           t_flg        = !t_flg;
           goto rch;
      }

      if        (c == '\\') {
           t_flg        = TRUE;
           goto rch;
      }
         /*
         If the character is not        part of        a quoted string
         check for and process commented        strings...
         nested comments        are handled correctly but unbalanced
         comments are not ... the assumption is made that
         the syntax of the program being        xref'd is correct
         */

      if        (!q_flg         &&  !q1_flg) {
           if (c        == '*'        &&  c_cnt  &&  !cs_flg)        {
                ce_flg =        TRUE;
                goto rch;
           }
           if (c        == '/'        &&  ce_flg) {
                c_cnt -=        1;
                ce_flg =        FALSE;
                goto rch;
           }
           ce_flg = FALSE;
           if (c        == '/')        {
                cs_flg =        TRUE;
                goto rch;
           }
           if (c        == '*'        &&  cs_flg) {
                c_cnt +=        1;
                cs_flg =        FALSE;
                goto rch;
           }
           cs_flg = FALSE;

           if (c_cnt) goto rch;
      }

         /*
         Check for and process quoted strings
         */

      if        ( c == '"'  &&  !q1_flg) {      /* toggle quote flag */
           q_flg        =  !q_flg;
           if(debug) printf("q_flg toggled to: %d\n" ,q_flg);
           goto rch;
      }
      if        (q_flg)        goto rch;

      if        (c == '\'') {        /* toggle quote flag */
           q1_flg = !q1_flg;
           if(debug) printf("q1_flg toggled to: %d\n" ,q1_flg);
           goto rch;
      }
      if        (q1_flg) goto rch;

         /*
         Valid character        ... return to caller
         */

      return (c);
 }/*rdchr.
 -----------------------------------------------*/
 fil_chr(f_buffer,f_eof)
      FILE *f_buffer;
      int *f_eof;
 {
      int fc;
      fc=getc(f_buffer);
      if        (fc == CPMEOF || fc == EOF) {
           *f_eof = TRUE;
           fc = NUL0;
      }
      return(fc);
 }
 /*   CHECK THE        TOKEN  */                                /*SRJ*/


 chk_token(c_token)
      char    *c_token;
 {
      char  u_token[MAX_LEN];
      int   i;

      {
       if (r_flg) return(TRUE);
       i        = 0;
       do { u_token[i] =        toupper(c_token[i]);
       }        while (c_token[i++] != NUL0);

       switch(u_token[0]) {
         case 'A': if (strcmp(u_token,"AUTO") ==        0) return(FALSE);
                   break;
         case 'B': if (strcmp(u_token,"BREAK") == 0) return(FALSE);
                   break;
         case 'C': if (strcmp(u_token,"CHAR") ==        0) return (FALSE);
                   if (strcmp(u_token,"CONTINUE") == 0) return (FALSE);
                   if (strcmp(u_token,"CASE") ==        0) return (FALSE);
                   break;

         case 'D': if(strcmp(u_token,"DOUBLE") == 0) return(FALSE);
                   if(strcmp(u_token,"DO") == 0)        return(FALSE);
                   if(strcmp(u_token,"DEFAULT") == 0) return(FALSE);
                   break;
         case 'E': if(strcmp(u_token,"EXTERN") == 0) return(FALSE);
                   if(strcmp(u_token,"ELSE") == 0) return(FALSE);
                   if(strcmp(u_token,"ENTRY") ==        0) return(FALSE);
                   break;
         case 'F': if(strcmp(u_token,"FLOAT") ==        0) return(FALSE);
                   if(strcmp(u_token,"FOR") == 0) return(FALSE);
                   break;
         case 'G': if(strcmp(u_token,"GOTO") == 0) return(FALSE);
                   break;
         case 'I': if(strcmp(u_token,"INT") == 0) return(FALSE);
                   if(strcmp(u_token,"IF") == 0)        return(FALSE);
                   break;
         case 'L': if(strcmp(u_token,"LONG") == 0) return(FALSE);
                   break;
         case 'R': if(strcmp(u_token,"RETURN") == 0) return(FALSE);
                   if(strcmp(u_token,"REGISTER")        == 0) return(FALSE);
                   break;
         case 'S': if(strcmp(u_token,"STRUCT") == 0) return(FALSE);
                   if(strcmp(u_token,"SHORT") ==        0) return(FALSE);
                   if(strcmp(u_token,"STATIC") == 0) return(FALSE);
                   if(strcmp(u_token,"SIZEOF") == 0) return(FALSE);
                   if(strcmp(u_token,"SWITCH") == 0) return(FALSE);
                   break;
         case 'T': if(strcmp(u_token,"TYPEDEF") == 0) return(FALSE);
                   break;
         case 'U': if(strcmp(u_token,"UNION") ==        0) return(FALSE);
                   if(strcmp(u_token,"UNSIGNED")        == 0) return(FALSE);
                   break;
         case 'W': if(strcmp(u_token,"WHILE") ==        0) return(FALSE);
                   break; }
         }
   return (TRUE);
 }/*chk_token.
 ---------------------------------------------*/
 /*   STORE THE        TOKEN  */                                        /*SRJ

   /*
    *        Install        parsed token and line reference        in linked s
    */

 put_token(p_token,p_ref)
      char *p_token;
      int  p_ref;
 {
      int  hsh_index;
      int  i;
 /*   unsigned long j;        */
      long int j;                                        /*RSW*/
      int  d;
      int  found;
      struct id_blk *idptr;
      struct rf_blk *rfptr;
      struct id_blk *alloc_id();
      struct rf_blk *alloc_rf();
      struct rf_blk *add_rf();

      if        (l_flg)        return;
      j=0;
      for (i=0; p_token[i] != NUL0; i++)         /* Hashing algorithm is far f
          j = j * 10 + p_token[i];         /* memory-bound index vector!

      hsh_index = j % MAX_WRD;

      if(debug) printf("hash index=%d ",hsh_index);

      found = FALSE;
      d = 1;
      do
           {idptr = id_vector[hsh_index];
           if (idptr == NUL0)
                {id_cnt++;
                idptr = id_vector[hsh_index] = alloc_id(p_token);
                chain_alpha(idptr,p_token);
                idptr->top_lnk =        idptr->lst_lnk = alloc_rf(p_ref);
                found = TRUE;
                if(debug) printf("empty cell in vector\n");
                }
             else
                if (strcmp(p_token,idptr->id_name) == 0)
                    {idptr->lst_lnk = add_rf(idptr->lst_lnk,p_ref);
                    if(debug) printf("duplicate token\n");
                    found = TRUE;
                    }
                 else
                    {hsh_index += d;
                    if(debug) printf("hash clash  hash index=%d\n",hsh_index);
                    d +=        2;
                    rhsh_cnt++;
                    if (hsh_index >= MAX_WRD)
                          hsh_index -= MAX_WRD;
                    if (d == MAX_WRD)
                          {printf("\nERROR: Symbol table overflow\n");
                          exit(0);
                          }
                    }
           }
       while (!found);

 return;
 }/*put_token.
 --------------------------------------------*/
 /*    BUILD THE CHAINS        */                                        /*SR

 chain_alpha(ca_ptr,ca_token)
      struct id_blk *ca_ptr;
      char  *ca_token;
 {
      char  c;
      int   f;
      struct id_blk *cur_ptr;
      struct id_blk *lst_ptr;
 /*** int isupper();   ****/               /** Microsoft C         macro **/


      c = ca_token[0];
      if        (c == '_')  c =        0;
      else
      /**  isupper(c) ? c=1+((c-'A')*2) : c=2+((c-'a')*2) ;     error or
       **  A good one for the puzzle book! Is the () required around (c=..)?
       **  C86 and Microsoft C both req the ()'s, BDS C did not.
       **  Is it        required because = has lower precedence        than ?:
       **/
           isupper(c) ? (c=1+((c-'A')*2)) : (c=2+((c-'a')*2)) ;

      if(alpha_vector[c].alpha_top == NUL0)
      {          alpha_vector[c].alpha_top =
                   alpha_vector[c].alpha_lst = ca_ptr;
           ca_ptr->alpha_lnk = NUL0;
           return;
      }

     /*        check to see if        new id_blk should be inserted between
      *        the alpha_vector header        block and the first id_blk in
      *        the current alpha chain
      */

      if(strcmp(alpha_vector[c].alpha_top->id_name,ca_token) >0)
      {          ca_ptr->alpha_lnk=alpha_vector[c].alpha_top;
           alpha_vector[c].alpha_top=ca_ptr;
           return;
      }

      if(strcmp(alpha_vector[c].alpha_lst->id_name,ca_token) < 0)
      {          alpha_vector[c].alpha_lst->alpha_lnk = ca_ptr;
           ca_ptr->alpha_lnk = NUL0;
           alpha_vector[c].alpha_lst=ca_ptr;
           return;
      }

      cur_ptr = alpha_vector[c].alpha_top;
      while(strcmp(cur_ptr->id_name,ca_token) < 0)
      {          lst_ptr = cur_ptr;
           cur_ptr = lst_ptr->alpha_lnk;
      }

      lst_ptr->alpha_lnk        = ca_ptr;
      ca_ptr->alpha_lnk = cur_ptr;
      return;
 }/*chain_alpha.
 -----------------------------------------*/
 /*   GET MEMORY FOR TOKEN TREE        */                                /*SR
      struct id_blk
 *alloc_id(aid_token)
      char  *aid_token;
 {
      int  ai;
      struct id_blk *aid_ptr;
      char *malloc();                                             /*        Mi

 /*** if((aid_ptr =  alloc(sizeof(oneid))) == 0)        { ***/             /*
      if((aid_ptr = (struct id_blk *) malloc(sizeof(oneid))) == 0) { /* MS C *

           printf("\nERROR: Unable to allocate identifier block\n");
           exit(0);
      }
      ai=0;
      do        {
           aid_ptr->id_name[ai] = aid_token[ai];
      } while (aid_token[ai++] != NUL0);
      return (aid_ptr);
 }/*id_blk.
 -----------------------------------------*/

      struct rf_blk
 *alloc_rf(arf_ref)
      int  arf_ref;
 {
     int        ri;
     struct rf_blk *arf_ptr;
     char * malloc();                                       /* Microsoft C */

 /** if((arf_ptr        = alloc(sizeof(onerf)))        == 0) {        **/    /
     if((arf_ptr        = (struct rf_blk *) malloc(sizeof(onerf))) == 0) { /*
          printf("\nERROR: Unable to allocate reference block\n");
          exit(0);
     }
     arf_ptr->ref_item[0] = arf_ref;
     arf_ptr->ref_cnt = 1;
     for        (ri=1;ri<MAX_REF;ri++)
           arf_ptr->ref_item[ri]        = NUL0;
     return (arf_ptr);
 }/*alloc_rf.
 ------------------------------------------*/
 /*   STORE REFERENCE IN TREE */                                        /*SRJ

      struct rf_blk
 *add_rf(adr_ptr,adr_ref)

      struct rf_blk *adr_ptr;
      int adr_ref;
 {
      struct rf_blk *tmp_ptr;

      tmp_ptr = adr_ptr;
      if(adr_ptr->ref_cnt == MAX_REF) {
      /*** tmp_ptr = adr_ptr->ref_cnt = alloc_rf(adr_ref);    Microsoft C **/
           adr_ptr->ref_cnt = alloc_rf(adr_ref);                  /* Microsoft
           tmp_ptr = (struct rf_blk *) adr_ptr->ref_cnt;          /* Microsoft
      }
      else
      {          adr_ptr->ref_item[adr_ptr->ref_cnt++]        = adr_ref;
      }
      return (tmp_ptr);
 }/*rf_blk.
 ------------------------------------------*/
 /*   PRINT THE        CROSS REFERENCE        TABLE */

 prnt_tbl()
 {
      int prf_cnt;
      int pti;
      int pref;
      int lin_cnt;
      struct id_blk *pid_ptr;
      struct rf_blk *ptb_ptr;

      prt_ref = TRUE;
      prt_hdr();
      nl();
      for (pti=0;pti<MX_ALPHA;pti++)
           {if ((pid_ptr        = alpha_vector[pti].alpha_top) != NUL0)
                {do
                     {fprintf(l_buffer,"%-14.13s: ",pid_ptr->id_name);/*WHR*/
                     ptb_ptr=pid_ptr->top_lnk;
                     lin_cnt=prf_cnt=0;
                     do
                          {if(prf_cnt ==        MAX_REF)
                               {prf_cnt=0;
                          /*** ptb_ptr =        ptb_ptr->ref_cnt;  Microsoft C
                               ptb_ptr =        (struct        rf_blk *)ptb_pt
                               }
                          if(ptb_ptr > MAX_REF)
                                  {if((pref=ptb_ptr->ref_item[prf_cnt++]) != 0
                                           {fprintf(l_buffer,"%-4d  ",pref); /
                                           if (++lin_cnt        == REFS_LIN )
                                                 {nl();
                                                 fprintf(l_buffer,"%16s",": ")
                                                 lin_cnt=0;
                                                 }
                                           }
                                  }
                                  else
                                            pref=0;
                          }
                     while (pref);
                     nl();
                     }
                while ((pid_ptr=pid_ptr->alpha_lnk) != NUL0);
                }
           }
 }/*prnt_tbl.
 ---------------------------------------*/
 /*   TOP OF PAGE AND PRINT THE        HEADER */                        /*SRJ

 prt_hdr()

 {fprintf(l_buffer,
   "\r\f%-10s [file d/t= %d/%02d/%02d  %d:%02d]   [clock d/t= %d %s %d  %d:%02
         gbl_fil,file_mo,file_d,file_y,file_h,file_mi,
         d,months[mo],y,h,mi,s,++pagno);                /*SRJ*/

 paglin =3;
 return;
 }
 /*  NEW LINE */                                                        /*SRJ

 nl()

 {fputc('\n',l_buffer);        /* output cr/lf        */

 if (++paglin >=        LINE_PAG )
         prt_hdr();
 if(!prt_ref)
         {fprintf(l_buffer,"%4d ",++linum);                /*SRJ*/
         if(i_flg)                                /*SRJ*/
                 fprintf(l_buffer," %4d: ",++edtnum);        /*SRJ*//*WHR*/
         }
 /* print the status on the console */
 if(o_flg)
         if(linum % 60 == 1)
                 printf("\n<%d>\t",linum);
           else
                 printf(".");
 return;
 }/*nl.
 -------------------------------------------*/
 /*=============        end of file xc.c ==========================*/


 XMEMASM.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\EXTMEM\XMEMASM.C

 #include <bios.h>
 #include <dos.h>

 #pragma inline

 #define EM_MEMSIZE 0x88
 #define EM_INT 0x15

 unsigned int get_size( void )
 {
 unsigned int flags;
 unsigned int res;

     _AH = EM_MEMSIZE;
         geninterrupt( EM_INT );
         asm pushf;
         asm pop bx;
         flags = _BX;
         res = _AX;
         if ( (flags & 1) != 0 )
             return( 0 );
         return( res );
 }



 XMEMC.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\EXTMEM\XMEMC.C

 #include <dos.h>

 static char ident[] = "VDISK  V3.2";

 unsigned long get_loc( void )
 {
 unsigned far *int19_seg = MK_FP( 0x0000, 4*0x19+2 );
 char far *txt_ptr;
 char *lcl_ptr;
 unsigned far *lo;
 unsigned char far *hi;

         /* VDISK's identification string is located in
                 the same segment as the int 0x19 handler, at
                 offset 0x12. */

     txt_ptr = MK_FP( *int19_seg, 0x12 );
     lcl_ptr = ident;
     while ( *lcl_ptr != 0 )
         if ( *lcl_ptr++ != *txt_ptr++ )
             return( 0x100000U );

         /* if VDISK is installed, the address
                 of the first byte of available extended
                 memory space is stored in the same segment
                 as the int 0x19 handler, at offset 0x2C,
                 0x2D, and 0x2E. */
     lo = MK_FP( *int19_seg, 0x2C );
     hi = MK_FP( *int19_seg, 0x2E );

         /* convert the address into a long */
     return( (unsigned long)*hi * 65536L + (unsigned long)*lo );
 }

 #if defined( TEST )

 #include <stdio.h>

 unsigned int get_size( void );

 void main()
 {
 unsigned long mem_size;
 unsigned long first_loc;

         first_loc = get_loc();
         mem_size = (unsigned long)get_size()*1024 - ( first_loc - 0x100000L )
         printf( "First loc = 0x%lX\nSize = %luK\n", first_loc, mem_size/1024
 }

 /* TEST */


 XMEMCOPY.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\EXTMEM\XMEMCOPY.C

 #include <dos.h>

 struct DESC
         {
         unsigned limit;
         unsigned base_lo;
         unsigned char base_hi;
         unsigned char rights;
         unsigned reserved;
         };

 struct GDT
         {
         struct DESC
                 dummy,
                 gdt_desc,
                 src,
                 tgt,
                 bios_cs,
                 st_reg;
         };

 static struct GDT gdt = {   { 0,0,0,0x93,0 },
                                                         { 0,0,0,0x93,0 },
                                                         { 0,0,0,0x93,0 },
                                                         { 0,0,0,0x93,0 },
                                                         { 0,0,0,0x93,0 },
                                                         { 0,0,0,0x93,0 }
                                                 };

 unsigned copy( unsigned long source, unsigned long dest, unsigned nbytes )
 {

         gdt.src.limit = nbytes;
         gdt.src.base_lo = source % 65536;
         gdt.src.base_hi = source / 65536;

         gdt.tgt.limit = nbytes;
         gdt.tgt.base_lo = dest % 65536;
         gdt.tgt.base_hi = dest / 65536;

         _ES = _DS;
         _SI = (unsigned)&gdt;
         _CX = nbytes/2;
         _AH = 0x87;
         geninterrupt( 0x15 );
         return( _AH );
 }


 XMEMTEST.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\TURBO_C\EXTMEM\XMEMTEST.C

 #include <stdio.h>
 #include <stdlib.h>
 #include <alloc.h>
 #include <dos.h>

 #define BLOCKSIZE 16384

 int ext_mem_present( void );
 unsigned get_size( void );
 unsigned long get_loc( void );
 unsigned copy( unsigned long source, unsigned long dest, unsigned nbytes );

 char far *buf;
 unsigned long ext_org;
 unsigned ext_size;
 unsigned long buf_org;

 void init( void )
 {
         ext_org = get_loc();
         printf( "Available extended memory begins at address %lX.\n", ext_org

         ext_size = get_size();
         printf( "Extended memory consists of %uK bytes,\n", ext_size );
         ext_size -= (ext_org - 0x100000L) >> 10;
         printf( "\twith %uK bytes available for use.\n\n", ext_size );

         if ( ext_size == 0 )
                 {
                 printf( "No external memory present.\n" );
                 exit(0);
                 }

         if ( (buf = farmalloc( BLOCKSIZE )) == 0L )
                 {
                 printf( "Unable to allocate buffer.\n" );
                 exit(0);
                 }

         buf_org = (unsigned long)FP_SEG(buf)*16L + (unsigned long)FP_OFF(buf)
 }

 void main()
 {
 unsigned char far *ptr;
 int wrong = 0, right = 0;
 int i;

         init();

         for ( ptr = buf, i = 0; i < BLOCKSIZE; i++ )
                 *ptr++ = i & 0xFF;

         if ( ext_size < 16 )
                 {
                 printf( "Insufficient extended memory available.\n" );
                 exit(0);
                 }

         printf( "Copying buffer to extended memory\n" );
         copy( buf_org, ext_org, BLOCKSIZE );

         printf( "Rewriting buffer contents\n" );
         for( ptr = buf, i = 0; i < BLOCKSIZE; i++ )
                 *ptr++ = 0;

         printf( "Copying extended memory back to buffer\n" );
         copy( ext_org, buf_org, BLOCKSIZE );

         printf( "Comparing copied buffer with original\n" );
         for( ptr = buf, i = 0; i < BLOCKSIZE; i++ )
                 if ( *ptr++ != (i & 0xFF) )
                         wrong++;
                 else
                         right++;

         printf( "\tNumber wrong = %d\n\tNumber right = %d\n", wrong, right );
 }


 XMODM11.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\XMODM11.C

 /*This program implements the Ward Christenson assembly language
   program in C.  All of the original modes are available, and a
   hide mode is added for restriction of file availability. A logger
   has been added, to keep a record of which files are most
   popular with BBS callers. Also, a local CRT display of errors
   and progress is implemented. This program as written is for the
   PMMI modem board, but may be changed for the D.C.Hayes via the
   proper equates. It requires CP/M Vers. 2.x to operate. Derived
   from CMODEM13.C

                                   original by Jack M. Wierda
                                   modified by Roderick W. Hart
                                   modified by William D. Earnest
 */
 #include     <bdscio.h>
 #include     <pmmi.h>

 #define      SOH 1
 #define      EOT 4
 #define      ACK 6
 #define      TAB 9
 #define      CPUCLK 4
 #define      ERRORMAX 10
 #define      RETRYMAX 10
 #define      LF 10
 #define      CR 13
      SPS 1500           /*loops per second */
 #define      NAK 21
 #define      CTRLZ 26
 #define      DELETE 127
 #define      TIMEOUT -1
      LRL 16      /* logger record lgth */
      RPB 8       /* logger rcrds per sector */
 #define      SECSIZ 0x80
      TBFSIZ 0x2000        /*moderate size, 0x8000 will not work with
                                   with BDS C, reduce buffer size as necessary
                                   for smaller systems*/

 char option,buffer[TBFSIZ],fcb[36],crtm[24];

 moready()
 { return (inp(STATPORT) & TBMT) == (MAHI ? TBMT : 0);
 }

 miready()
 { return (inp(STATPORT) & DAV) == (MAHI ? DAV : 0);
 }

 ctsready()
 { int lpc,seccnt;
     for(lpc=0; lpc < 25; lpc++)
         { seccnt = SPS * CPUCLK;
             while((inp(MODEMCP2) & CTS) == (CTSHI ? 0 : CTS) && seccnt--);
             if(seccnt >= 0)
                 return;
         }
     exit();
 }

 crtmsg(msg)
 char *msg;
 { while (*msg)
         { while((inp(CSTAT) & COMASK) == (CAHI ? 0 : COMASK));
             outp(CDATA,*msg);
             msg++;
         }
 }

 shocrt(sec,try,tot)
 int sec,try,tot;
 { sprintf(crtm,"\015Blk %04d Try %1d Err %03d",sec,try,tot);
     crtmsg(crtm);
 }

 sendline(data)
 char data;
 { ctsready();
     while(!MOREADY());
     outp(DATAPORT,data);
 }

 readline(seconds)
 int seconds;
 { char data;
     int lpc,seccnt;
     for (lpc = 0; lpc < CPUCLK; lpc++)
         { seccnt = seconds * SPS;
           ctsready();
           while (!MIREADY() && seccnt--);
           if(seccnt >= 0)
               { data = inp(DATAPORT);
                 return(data);
               }
         }
     return(TIMEOUT);
 }

 purgeline()
 { while (MIREADY())
       inp(DATAPORT);     /*PURGE THE RECEIVE REGISTER*/
   ctsready();
 }

 readfile(file)
 char *file;
 { int j, firstchar, sectnum, sectcurr, sectcomp, errors;
   int toterr,checksum;
   int errorflag, fd;
   int bufctr;

   fd = creat(file);
   if(fd == -1)
       { printf("Cannot create %s\n",file);
         exit();
       }
   else
       printf("\nReady to receive %s\n",file);
   sectnum = 0;
   errors = 0;
   toterr = 0;
   bufctr = 0;
   purgeline();
   shocrt(0,0,0);
   do
       { errorflag = FALSE;
         do
             firstchar = readline(10);
         while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);

         if(firstchar == TIMEOUT)
             errorflag = TRUE;
         if(firstchar == SOH)
             { sectcurr = readline(1);
               sectcomp = readline(1);
               if((sectcurr + sectcomp) == 255)
                   { if(sectcurr == sectnum + 1)
                         { checksum = 0;
                           for(j = bufctr;j < (bufctr + SECSIZ);j++)
                               { buffer[j] = readline(1);
                                 checksum = (checksum + buffer[j]) & 0xff;
                               }
                           if(checksum == readline(1))
                               { errors = 0;
                                 sectnum = sectcurr;
                                 bufctr = bufctr + SECSIZ;
                                 if(bufctr == TBFSIZ)
                                     { bufctr = 0;
                                       write(fd,buffer,TBFSIZ/SECSIZ);
                                     }
                                 shocrt(sectnum,errors,toterr);
                                 sendline(ACK);
                               }
                           else
                               errorflag = TRUE;
                         }
                     else
                         if(sectcurr == sectnum)
                             { do;
                               while(readline(1) != TIMEOUT);
                               sendline(ACK);
                             }
                         else
                             errorflag = TRUE;
                   }
               else
                   errorflag = TRUE;
             }
         if(errorflag == TRUE)
             { errors++;
               if(sectnum)
                   toterr++;
               while(readline(1) != TIMEOUT);
               shocrt(sectnum,errors,toterr);
               sendline(NAK);
             }
       }
   while(firstchar != EOT && errors != ERRORMAX);

   if((firstchar == EOT) && (errors < ERRORMAX))
       { sendline(ACK);
         write(fd,buffer,(bufctr+SECSIZ-1)/SECSIZ);
         close(fd);
       }
   else
       printf("Aborting\n");
 }

 sendfile(file)
 char *file;
 { char *npnt;
   int j, sectnum, sectors, attempts;
   int toterr,checksum;
   int bufctr, fd;

   fd = open(file,0);
   if(fd == -1)
       { printf("\n++File not found++\n");
         exit();
       }
   else
       { npnt = fcbaddr(fd);
         if(npnt[1] > 127 || npnt[2] > 127)
             { printf("\nFile %s not for distribution, Sorry.\n",file);
               exit();
             }
         else
             { attempts = rcfsiz(fd);
               printf("\nFile %s open, ",file);
               printf("size %d (%04xH) sectors.\n",attempts,attempts);
               printf("Ready to send, awaiting NAK.\n");
             }
       }
   purgeline();
   attempts=0;
   toterr = 0;
   shocrt(0,0,0);
   while((readline(10) != NAK) && (attempts != 8))
       { attempts++;
         shocrt(0,attempts,0);
       }
   if (attempts == 8)
       { printf("\nTimed out awaiting initial NAK\n");
         exit();
       }
   attempts = 0;
   sectnum = 1;
   while((sectors = read(fd,buffer,TBFSIZ/SECSIZ)) && (attempts != RETRYMAX))
       { if(sectors == -1)
             { printf("\nFile read error.\n");
               break;
             }
         else
             { bufctr = 0;
               do
                   { attempts = 0;
                     do
                         { shocrt(sectnum,attempts,toterr);
                           sendline(SOH);
                           sendline(sectnum);
                           sendline(-sectnum-1);
                           checksum = 0;
                           for(j = bufctr;j < (bufctr + SECSIZ);j++)
                               { sendline(buffer[j]);
                                 checksum = (checksum + buffer[j]) & 0xff;
                               }
                           sendline(checksum);
                           purgeline();
                           attempts++;
                           toterr++;
                         }
                     while((readline(10) != ACK) && (attempts != RETRYMAX));
                     bufctr = bufctr + SECSIZ;
                     sectnum++;
                     sectors--;
                     toterr--;
                   }
               while((sectors != 0) && (attempts != RETRYMAX));
             }
       }
         if(attempts == RETRYMAX)
             printf("\nNo ACK on sector, aborting\n");
         else
             { attempts = 0;
               do
                   { sendline(EOT);
                     purgeline();
                     attempts++;
                   }
               while((readline(10) != ACK) && (attempts != RETRYMAX));
               if(attempts == RETRYMAX)
                   printf("\nNo ACK on EOT, aborting\n");
             }
   close(fd);
 }

 docfile(file)
 char *file;
 { int fd,rcsz,rch;
   fd = open(file,0);
   if(fd == -1)
       { printf("\n++File %s not found++\n,file");
         exit();
       }
   else
       { rcsz=rcfsiz(fd);
         rch = (rcsz * 14) / 3;
         printf("\nFile %s is ",file);
         printf("%d (%04xH) sectors long.\n",rcsz,rcsz);
         printf("At 300 baud, it would take about ");
         printf("%d minutes, %d seconds to send.\n",rch / 60,rch % 60);
       }
 }

 int filfnd(file)
 char *file;
 { if(setfcb(fcb,file))
       return FALSE;
   if(bdos(17,fcb) != 255)
       return TRUE;
   else
       return FALSE;
 }

 char matchr(st,ch)
 char *st,ch;
 { int i;
   for(i=0; st[i]; i++)
       { if(st[i] == ch)
             return(i);
       }
   return(0);
 }

 ckfile(argc,argv) int argc;
 char **argv;
 { char *s,l;
   if(argc < 3)
       { printf("File name required\n");
         exit();
       }

   if(option == 'H')
       { l = matchr(*argv,'.');
         if(((l+3) > strlen(*argv)) || (!l))
             { printf("\nMust have full .typ to Hide\n");
               exit();
             }
       }

   for(s=*argv; *s; s++)
       { if((*s == '?') || (*s == '*'))
             { printf("\nNo 'Wild Card' characters allowed\n");
               exit();
             }
       }

   for(s=*argv; *s; s++)
       { if((*s == '.') && ((option == 'R') || (option == 'H')))
             { if(s[1] == 'C' && s[2] == 'O' && s[3] == 'M')
                   { printf("\nCan't accept a .COM file\n");
                     exit();
                   }
               if(option == 'H')
                   s[2] = s[2] | 0x80;
             }
       }
 }

 char bbcd(val)
 char val;
 { return(((val / 10) << 4) + (val % 10));
 }

 logfil(file)
 char *file;
 { int fd,rnum,bnum,savusr;
   char *i,*lrec,lbuf[128],*lnam;
   lnam = "A:\330\315ODEM.L\317G"; /* f1 & f2 flags, $sys */
   savusr = bdos(32,-1);
   bdos(32,0);
   fd = open(lnam,2);
   if(fd == -1)
       { fd = creat(lnam);
         if(fd == -1)
             return;
         else
             { setmem(lbuf,16,0x20);
               setmem(lbuf+16,112,CTRLZ);
               sprintf(lbuf,"%d",0);
             }
       }
   else
       read(fd,lbuf,1);
   rnum = atoi(lbuf)+1;
   sprintf(lbuf,"%d",rnum);
   seek(fd,0,0);
   write(fd,lbuf,1);
   bnum = rnum / RPB;
   rnum = (rnum % RPB) * LRL;
   seek(fd,bnum,0);
   if(rnum == 0)
       setmem(lbuf,128,CTRLZ);
   else
       read(fd,lbuf,1);
   if(peek(0xe802) == 0xc3)
       call(0xe802,0,0,0,0); /* r.t.c. put data in hi mem */
   lrec = lbuf+rnum;
   movmem(0xf406,lrec-4+LRL,4); /* time/date data from hi mem */
   for(i = lrec-4+LRL; i < lrec+LRL; i++)
       *i = bbcd(*i);
   movmem(0x6c,lrec,12);
   if(peek(0x6c) == 0)
       *lrec = peek(4) + 1;
   *lrec = *lrec | (peek(4) & 0xf0);
   if((option == 'R') || (option == 'H'))
       *lrec = *lrec | 0x80;
   seek(fd,bnum,0);
   write(fd,lbuf,1);
   close(fd);
   bdos(32,savusr); /* restore orig user nr */
 }

 main(argc,argv)
 int argc;
 char **argv;
 { char *s;
   printf("XMODEM (PMMI/BDS-C) ver 1.1    9-Jul-81\n");
   s=*++argv;
   ++argv;
   switch(s[0])
       { case 'R':
         case 'S':
         case 'H':
         case 'Q':
             option = s[0];
             break;

         default:
             printf("Command format: XMODEM option filename.typ\n");
             printf("Available options are:\n");
             printf("\tS: Send file     R: Receive file\n");
             printf("\tH: Hide file     Q: Query file size\n");
             exit();
             break;
       }

   switch(option)
       { case 'R':
         case 'H':
             ckfile(argc,argv);
             if (filfnd(*argv))
                 { printf("\nFile %s exists, pick another name.\n",*argv);
                   exit();
                 }
             else
                 { logfil(*argv);
                   readfile(*argv);
                 }
             break;

         case 'S':
             ckfile(argc,argv);
             if (filfnd(*argv))
                 { logfil(*argv);
                   sendfile(*argv);
                 }
             else
                 { printf("\n++File %s not found++\n",*argv);
                   exit();
                 }
             break;

         case 'Q':
             docfile(*argv);
             break;
       }
 }


 XREF.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\XREF.C

 /*
 TITLE: XREF - Cross Reference;
 VERSION: 1.0;
 DATE: 07/31/1986;
 DESCRIPTION:
  "Cross reference text from stdin to stdout.
  Optimized name storage allocation.";
 KEYWORDS: binary tree, name, reference, symbol, xref;
 SYSTEM: CP/M, any;
 FILENAME: XREF.C;
 WARNINGS: "Assumes 16-bit pointers.";
 SEE-ALSO: none;
 AUTHORS: Mark Antony Washburn;
 COMPILERS: Small-C, any C compiler;
 REFERENCES:
  AUTHORS: Nickolas Wirth;
  TITLE: "Algorithms+Data Structures=Programs";
  CITATION: "p.206"
 ENDREF;
 */

 <A:STDIO.H>  /* find STDIO.H */

 MEMOVERHEAD (1024)  /* leave room for stack */

 MAXWORDLEN 79  /* maximum name length - 1 */
 MAXWORDBUF 80  /* maximum name length */
 NUMPERLINE 14  /* assumes 80 columns */
 MAXLINENUM 9999  /* maximum number of source lines */

 DNLEFT 0  /* name node structure definitions */
 #define DNRIGHT 2
 #define DNFIRST 4
 #define DNLAST 6
 #define DNID 8

 DRLINE 0  /* reference link list structure definitions */
 #define DRNEXT 2
 #define DRLN 4

 char *membtm,*memtop;  /* pointers to bottom and top of memory */

 char *root;  /* root node pointer */
 char *nword;  /* global name node pointer */
 /* left and right node pointers, first and last reference links */
 int *nleft,*nright,*nfirst,*nlast;
 int *rline,*rnext;  /* global pointers reference instance */

 int c;  /* current char */
 int k;  /* current word index */
 int n;  /* current line number */
 char id[MAXWORDBUF];  /* current word */

 /*
 **  ouput character to stdout, then fetch next character
 **  from stdin
 */
 outcinc() {
   putchar(c);
   c = getchar(c);
   }

 /*
 ** output a string to stdout
 */
 outstr(l) char *l; {
   fputs(l, stdout);
   }

 /*
 **  output a right justified integer to stdout
 */
 outdec(i) int i; {
   char l[5];
   itod(i, l, 5);
   fputs(l, stdout);
   }

 /*
 **  get as much memory as possible for symbol tree
 */
 initmem() {
   int max;
   max = avail(YES);
   max -= MEMOVERHEAD;
   membtm = malloc(max);
   memtop = membtm + max;
   }

 /*
 **  get memory for next entry, otherwise abort
 */
 getmem(i) int i; {
   char *memp;
   if(memtop > membtm + i)  {
     memp = membtm;
     membtm += i;
     return(memp);
     }
   else {
     fputs("Not enough memory", stderr);
     abort(2);
     }
   }

 /*
 **  assign node pointers
 */
 nodeptrs(w) char *w; {
   nleft = w;
   nright = w + DNRIGHT;
   nfirst = w + DNFIRST;
   nlast = w + DNLAST;
   nword = w + DNID;
   }

 /*
 **  assign reference pointers
 */
 refptrs(x) char *x; {
   rline = x;
   rnext = x + DRNEXT;
   }

 /*
 **  if id is a new node then insert word and reference
 **  otherwise insert next reference
 */
 insert(w) char *w; {
   int *x, *lnode;
   int i;
   if(w == NULL) {
     w = getmem(DNID + k);
     nodeptrs(w);
     strcpy(nword, id);
     *nleft = NULL;
     *nright = NULL;
     refptrs(getmem(DRLN));
     *rline = n;
     *rnext = NULL;
     *nfirst = rline;
     *nlast = rline;
     if(root == NULL) root = w;
     else return(w);
     }
   else {
     nodeptrs(w);
     i = strcmp(id, nword);
     if(i == 0) {
       x = getmem(DRLN);
       refptrs(x);
       *rline = n;
       *rnext = NULL;
       refptrs(*nlast);
       *rnext = x;
       *nlast = x;
       }
     else if(i < 0) {
       lnode = nleft;
       x = insert(*nleft);
       if(x != NULL) *lnode = x;
       }
     else {
       lnode = nright;
       x = insert(*nright);
       if(x != NULL) *lnode = x;
       }
     }
     return(NULL);
   }

 /*
 ** print a word with its references
 */
 pword(w) char *w; {
   int l;
   int *t2;
   outstr("\n\n");
   outstr(w + DNID);
   outstr("\n");
   t2 = w + DNFIRST;
   t2 = *t2;
   l = 0;
   do {
     if(l == NUMPERLINE) {
       outstr("\n");
       l = 0;
       }
     ++l;
     outstr(" ");
     outdec(*t2);
     ++t2;
     t2 = *t2;
     } while (t2 != NULL);
   }

 /*
 **  print the cross reference tree
 */
 ptree(w) char *w; {
   int *wl, *wr;
   if(w != NULL) {
     wl = w + DNLEFT;
     wr = w + DNRIGHT;
     ptree(*wl);
     pword(w);
     ptree(*wr);
     }
   }

 main() {
   char l2[5];
   initmem();
   root = NULL;
   n = 0;
   c = getchar();
   while(c != EOF) {
     ++n;
     if(n > MAXLINENUM) n = 0;
     outdec(n);
     outstr(": ");
     while(c != '\n') {
       if(isalpha(c)) {
         k = 0;
         do {
           if(k < MAXWORDLEN) id[k++] = c;
           outcinc();
           } while(isalnum(c));
         id[k++] = '\0';
         insert(root);
         }
       else outcinc();
       if(c == EOF) break;
       }
     if(c != EOF) outcinc();
     }
   ptree(root);
   }


 Y1IMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\Y1IMP.C

 /* Impure data used by modules originally in Y1.C. External declarations in Y

 #define y1imp yes
 #include "dtxtrn.h"

 /* lookahead computations */

 int tbitset;  /* size of lookahead sets */
 struct looksets lkst [ LSETSIZE ];
 int nlset = 0; /* next lookahead set index */
 int nolook = 0; /* flag to suppress lookahead computations */
 struct looksets clset;  /* temporary storage for lookahead computations */

 /* working set computations */

 struct wset wsets[ WSETSIZE ];
 struct wset *cwp;

 /* state information */

 int nstate = 0;         /* number of states */
 struct item *pstate[NSTATES+2]; /* pointers to the descriptions of the states
 int tystate[NSTATES];   /* contains type information about the states */
 int indgo[NSTATES];             /* index to the stored goto table */
 int tstates[ NTERMS ]; /* states generated by terminal gotos */
 int ntstates[ NNONTERM ]; /* states generated by nonterminal gotos */
 int mstates[ NSTATES ]; /* chain of overflows of term/nonterm generation list

 /* storage for the actions in the parser */

 int amem[ACTSIZE];      /* action table storage */
 int *memp = amem;       /* next free action table position */

 /* other storage areas */

 int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or stat
 int lineno= 1; /* current input line number */
 int fatfl = 1;          /* if on, error is fatal */
 int nerrors = 0;        /* number of errors */

 /* storage for information about the nonterminals */

 int **pres[NNONTERM+2];  /* vector of pointers to productions yielding each n
 struct looksets *pfirst[NNONTERM+2];  /* vector of pointers to first sets for
 int pempty[NNONTERM+1];  /* vector of nonterminals nontrivially deriving e */

 /* accumulators for statistics information */

 struct wset *zzcwp = wsets;
 int zzgoent = 0;
 int zzgobest = 0;
 int zzacent = 0;
 int zzexcp = 0;
 int zzclose = 0;
 int zzsrconf = 0;
 int * zzmemsz = mem0;
 int zzrrconf = 0;

 /* data pulled from internal static to here */
 /* declared external only in user module    */

 int *pyield[NPROD];             /* from ycpres */
 char sarr[ISIZE];               /* from ywritm */



 Y2IMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\Y2IMP.C

 /* Impure data needed by routines pulled from Y2.C */

 #define y2imp YES
 #include "dtxtrn.h"

 /* communication variables between various I/O routines */

 char *infile;   /* input file name */
 int numbval;    /* value of an input number */
 char tokname[NAMESIZE]; /* input token name */

 /* storage of names */

 char cnames[CNAMSZ];    /* place where token and nonterminal names are stored
 int cnamsz = CNAMSZ;    /* size of cnames */
 char * cnamp = cnames;  /* place where next name is to be put in */
 int ndefout = 3;  /* number of defined symbols output */

 /* storage of types */
 int ntypes;     /* number of types defined */
 char * typeset[NTYPES]; /* pointers to type tags */

 /* symbol tables for tokens and nonterminals */

 int ntokens = 0;
 struct toksymb tokset[NTERMS];
 int toklev[NTERMS];
 int nnonter = -1;
 struct ntsymb nontrst[NNONTERM];
 int start;      /* start symbol */

 /* assigned token type values */
 int extval = 0;

 /* input and output file descriptors */

 FILE * finput;          /* yacc input file */
 FILE * faction;         /* file for saving actions */
 FILE * fdefine;         /* file for # defines */
 FILE * ftable;          /* y.tab.c file */
 FILE * ftemp;           /* tempfile to pass 2 */
 FILE * foutput;         /* y.output file */

 /* storage for grammar rules */

 int mem0[MEMSIZE] ; /* production storage */
 int *mem = mem0;
 int nprod= 1;   /* number of productions */
 int *prdptr[NPROD];     /* pointers to descriptions of productions */
 int levprd[NPROD] ;     /* precedence levels for the productions */

 /* Statics pulled from modules */

 int peekline;           /* from gettok() */


 Y3IMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\Y3IMP.C

 /* Impure data from modules split from y3.c */
 #define y3imp YES

 #include "dtxtrn.h"

 int lastred;            /* the number of the last reduction of a state */

 int defact[NSTATES];    /* the default actions of states */


 Y4IMP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\Y4IMP.C

 /* Impure data from y4.c modules */

 # include "dtxtrn.h"

 # define a amem
 # define pa indgo
 # define yypact temp1
 # define greed tystate

 # define NOMORE -1000

 int * ggreed = lkst[0].lset;
 int * pgo = wsets[0].ws.lset;
 int *yypgo = &nontrst[0].tvalue;

 int maxspr = 0;  /* maximum spread of any entry */
 int maxoff = 0;  /* maximum offset into a array */
 int *pmem = mem0;
 int *maxa;
 int nxdb = 0;
 int adb = 0;


 YAM1.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM1.C

 /*
 >>:yam1.c
  * Mainline for yam 18-Nov-82 (diff 10-25-81)
  * 'go', 'exit' and 'off' modifications by Bill Bolton, March 15, 1982
  * 'loop' and 'test' added for loopback testing of line, John Woolner,
  * August 28, 1982
  */
 #include "yam.h"
 #define MAXARGS 20

 main(argc, argv)
 char **argv;

 {
         int c;
         char *args[MAXARGS], **argp, **argq, *nextcmd, *p;

         init1_extra();        /* special initialisation in YAM11.C */

         nextcmd=NULL;
         printf("Yet Another Modem by Chuck Forsberg\n");
         printf("%s %s\n", FLAVOR, VERSION);
         init();
         if(argc>MAXARGS)
                 goto usage;
         /* copy given arguments to our own array */
         for(argp=argv,argq=args,c=argc; --c>=0;)
                 *argq++ = *argp++;

 #ifdef TERMRESET
         lprintf(TERMRESET);
 /* TERMRESRET */

         for(;;) {
                 if(argc < 2) {
                         if(nextcmd)
                                 cp=nextcmd;
                         else {
 #ifdef XMODEM
                                 printf("xYAM(%c%d)", defdisk+'A', user);
 #else
                                 printf(">>>%c%d:", defdisk+'a', user);
 /* XMODEM*/
                                 gets(cmdbuf);
 #ifdef TERMRESET
                                 lprintf(TERMRESET);
 /* TERMRESET */
                                 init2_extra();        /* in YAM11 */
                                 cp=cmdbuf;
 /*
  * Check for *text... which sends the rest of the line to
  * the modem
  */
                                 if((*cp)=='*') {
                                         abptr= ++cp;
                                         abend= cp + strlen(cp);
 /*  Add proper end of line stuff according to Txeoln */
                                         switch(Txeoln) {
                                         case EOL_CR:
                                         case EOL_CRWAIT:
                                         case EOL_CRPROMPT:
                                                 *abend++ = '\r';
                                                 break;
                                         case EOL_NOTHING:
                                         case TX_BINARY:
                                                 *abend++ = '\r';
                                         case EOL_NL:
                                                 *abend++ = '\n';
                                                 break;
                                         }
                                         Exoneof=TRUE;
                                         term();
                                         continue;
                                 }
                         }
                         if(nextcmd=index(';', cp))
                                 *nextcmd++ =0;        /*  ; separates command
                         else if(nextcmd=index('\\', cp))
                                 *nextcmd++ =0;        /*  \ separates command

                         argp= &args[1]; argc=1;
                         for(;;) {
                                 if(isgraphic(*cp)) {
                                         *argp++ = cp;
                                         argc++;
                                         while(isgraphic(*cp))
                                                 cp++;
                                 }
                                 while(*cp==' ' || *cp=='\t')
                                         *cp++ =0;
                                 if(*cp > ' ')
                                         continue;
                                 *cp=0;
                                 break;
                         }
                 }
                 for(argp= &args[1]; --argc>0; ) {
                         uncaps(*argp);
                         cp= *argp++;

                         Gototerm=Batch=Crcflg=Creamfile=Echo=Ctlview=
                           Chat=View=Type=Quiet=FALSE;
 #ifdef CPM
                         if(index(':', cp)) {
                                 chdir(cp);
                                 continue;
                         }
 /* CPM */
                         switch(*cp++) {
                         case 'b':
                                 if(cmdeq(cp, "ye")) {
 #ifdef BYEPROG
                                         cp=4; *cp=0;        /* reset user/dri
                                         exec(BYEPROG);
 #else
                                         bye();
                                         continue;
 /* BYEPROG */
                                 }
                                 else if(setbaud(atoi(cp)))
                                         goto usage;
                                 continue;
                         case 'c':
 #ifndef RESTRICTED
                                 if(cmdeq(cp, "all") && --argc ==1) {
                                         uncaps(*argp);        /* make name lc
                                         if(getphone(*argp++,Phone)==ERROR)
                                                 goto usage;
                                         else if(dial(Phone)==ERROR)
                                                 goto usage;
                                         continue;
                                 }
 /* RESTRICTED */
                                 if(cmdeq(cp, "hat")) {
                                         chat();
                                         continue;
                                 }
                                 if(cmdeq(cp, "lose")) {
                                         dumprxbuff();
                                         closerx(TRUE); closetx(TRUE);
                                         continue;
                                 }
                                 if(cmdeq(cp, "rck")) {
                                         docrck( --argc, argp);
                                         argc=0; continue;
                                 }
                                 goto usage;
                         case 'd':
                                 if(cmdeq(cp, "ir")) {
 #ifndef CDOS
                                         if(cp[2])
                                                 docomp(--argc, argp);
                                         else
 /* CDOS */
                                                 dodir(--argc, argp);
                                         argc=0;
                                 }
                                 else if(setval(0)==ERROR)
                                         goto usage;
                                 continue;
                         case 'e':
 #ifndef RESTRICTED
                                 if(cmdeq(cp, "ra")) {
                                         doerase( --argc, argp); argc=0;
                                         continue;
                                 }
 /* RESTRICTED */
                                 if(cmdeq(cp, "xit")) {
                                         dumprxbuff();
                                         closerx(TRUE); closetx(TRUE);
                                         printf("Exiting to DOS, files closed"
 #ifndef XMODEM
                                         onhook();
                                         printf(", modem disconnected.");
 /* XMODEM */
                                         printf("\n");
                                         exit(0);
                                 }
                                 if(setval(~0)==ERROR)
                                         goto usage;
                                 continue;
                         case 'f':
                                 closetx(TRUE);
                                 if(setval(~0)==ERROR)
                                         goto usage;
                                 if(--argc<=0 || opentx(*argp++)==ERROR)
                                         goto usage;
                                 if(Squelch) {
                                         /* frame file with ^R T if Squelch */
                                         sendline(022);
                                 }
                                 term(0);
                                 if(Squelch) {
                                         sendline(024);
                                 }
                                 continue;
                         case 'g':
                                 if(cmdeq(cp, "o"))
                                         exit();
                                 else
                                         goto usage;
                         case 'i':
                                 if(cmdeq(cp, "nit")) {
                                         init(); argc=nextcmd=0; continue;
                                 }
                                 else
                                         goto usage;
                         case '?':
                         case 'h':
 #ifdef XMODEM
                                 Type++; /* send to remote user */
 /* XMODEM */
                                 listfile(HELPFILE);
                                 continue;
                         case 'k':
                                 if(cmdeq(cp, "ill")) {
                                         clearbuf();
                                         continue;
                                 }
                                 else
                                         goto usage;
                         case 'l':
                                 if(cmdeq(cp, "ist")) {
                                         View++;
 listit:
                                         dolist( --argc, argp);
                                         argc=0;
                                         continue;
                                 }
 #ifndef RESTRICTED
                                 if (cmdeq(cp,"oop")) {
                                         loop(atoi(cp += 3));
                                         continue;
                                 }
 /* RESTRICTED */
                                 else
                                         goto usage;
 #ifndef RESTRICTED
                         case 'm':
                                 Sport=(Dport=atoi(cp))+(SPORT-DPORT);
                                 readbaud(); continue;
 /* RESTRICTED */
                         case 'o':
                                 if(cmdeq(cp, "ff")) {
 #ifdef TERMRESET
                                         lprintf(TERMRESET);
 /*TERMRESET */
 #ifdef BYEPROG
                                         cp=4; *cp=0;        /* reset user/dri
                                         exec(BYEPROG);
 #else
                                         onhook();
 /* BYEPROG */
                                         printf("Off Line\n"); Continue;
                                 }
                                 if(cmdeq(cp, "n")) {
                                         online();
                                         printf("On line\n");
                                         continue;
                                 }
                                 else
                                         goto usage;
                         case 'p':
                                 if(setparm(cp)==ERROR)
                                         goto usage;
                                 continue;
                         case 'q':
                                 if(cmdeq(cp, "uit")) {
                                         printf("Quitting YAM\n");
                                         exit();
                                 }
                                 goto usage;
                         case 'r':
                                 if(cmdeq(cp, "eset")) {
 #ifdef TERMINIT
                                         lprintf(TERMINIT);
 /* TERMINIT */
                                         closetx(TRUE);
                                         dumprxbuff();
                                         closerx(TRUE);
 #ifdef CPM
                                         bdos(13,0);
                                         bdos(14,defdisk);
 /* CPM */
                                         /* change buffer size for debugging *
                                         if(--argc>0) {
                                                 bufend= bufst + atoi(*argp++)
                                                 clearbuf();
                                                 dostat();
                                         }
                                         continue;
                                 }
                                 if(cmdeq(cp, "ep")) {
                                         replot(argc>1 ? (--argc,atoi(*argp++)
                                         continue;
                                 }
                                 if(cmdeq(cp, "ew")) {
                                         rewindcb(); continue;
                                 }
                                 if(chkbvq()==ERROR)
                                         goto usage;
                                 if(argc<2)
                                         Batch=TRUE;
                                 psxfer(wcreceive(--argc, argp));
                                 if(Gototerm)
                                         term();
                                 argc=0; continue;
                         case 's':
                                 if(*cp == 0 && argc==1) {
                                         dostat();
                                         continue;
                                 }
                                 if(argc<2 || chkbvq()==ERROR)
                                         goto usage;
                                 if( argc > 2
                                   || index('?',*argp) || index('*',*argp))
                                         Batch=TRUE;
 #ifdef XMODEM
                                 /* tell 'em how long it will take! */
                                 if(Batch)
                                         docomp(argc-1, argp);
 /* XMODEM */
                                 psxfer(wcsend(--argc, argp));
                                 if(Gototerm)
                                         term();
                                 argc=0;
                                 continue;
 #ifndef XMODEM
                         case 'u':
                                 if(argc>1)
                                         goto usage;        /* trap "user 0" *
                                 abptr=Wrapped?bufcq+1:bufst;
                                 abend=bufcq;
                                 /* fall through to T */
 /* XMODEM */
                         case 't':
                                 if(cmdeq(cp, "ype")){
 #ifdef XMODEM
                                         Type++;        /* send to remote user
 /* XMODEM */
                                         goto listit;
                                 }
 #ifndef RESTRICTED
                                 if (cmdeq(cp,"est")) {
                                         linetest(atoi(cp += 3));
                                         continue;
                                 }
 /* RESTRICTED */
 #ifndef XMODEM
                                 if(--argc > 0) {
                                         dumprxbuff(); closerx(TRUE);
                                         if(opencapt(*argp++)==ERROR)
                                                 goto usage;
                                 }
                                 switch(setval(~0)) {
                                 case ERROR:
                                         goto usage;
                                 case OK:
                                         term();
                                 case TRUE:
                                         /* remain in command mode if t..c  */
                                         break;
                                 }
                                 continue;
                         /* note: case u precedes T */
                         case 'w':
                                 dumprxbuff(); continue;
 /* XMODEM */
                         case 'x':
                                 continue;        /* in case you said "XMODEM"
                         case 0:
                         default:
                                 goto usage;
                         }
                         continue;

                 }
                 continue;
 usage:
                 printf("Type HELP for instructions\n");
                 nextcmd=argc=0; continue;

         }
 }

 chkbvq()
 {
         while(*cp)
                 switch(*cp++) {
                 case 'b':
                         Batch=TRUE; break;
                 case 'c':
                         Crcflg=TRUE; break;
                 case 'q':
                         Quiet=TRUE; break;
 #ifndef RESTRICTED
                 case 't':
                         Gototerm=TRUE; break;
                 case 'v':
                         View=TRUE; break;
                 case 'y':
                         Creamfile=TRUE; break;
 /* RESTRICTED */
                 default:
                         return ERROR;
                 }
         return FALSE;
 }
 setval(value)
 unsigned value;
 {
         FLAG dumped;
         dumped=FALSE;
         while(*cp)
                 switch(*cp++) {
                 case 'a':
                         Chat = value;
                         break;
                 case 'b':
                         Txeoln= value&TX_BINARY;
                         Txmoname="BINARY";
                         break;
                 case 'c':
                         dumprxbuff();
                         closerx(dumped=TRUE);
                         break;
                 case 'd':
                         Dumping = !Squelch || value;
                         break;
                 case 'e':
                         Echo=value;
                         break;
                 case 'f':
                         Hdx= !value;
                         break;
                 case 'g':
                         Txgo= value;
                         break;
                 case 'h':
                         Hdx=value;
                         break;
                 case 'i':
                         Image=value;
                         break;
                 case 'l':
                         Pflag=value;
                         break;
                 case 'n':
                         Txeoln =value&EOL_NL;
                         Txmoname="NL ONLY";
                         break;
                 case 'o':
                         Pflag= !value;
                         break;
                 case 'p':
                         Txeoln =value&EOL_CRPROMPT;
                         Txmoname="WAIT FOR PROMPT";
                         break;
                 case 'r':
                         Txeoln =value&EOL_CR;
                         Txmoname="CR ONLY";
                         break;
                 case 's':
                         Squelch=value;
                         break;
                 case 't':
                         Waitbunch=value;
                         break;
                 case 'v':
                         Ctlview++;
                         break;
                 case 'w':
                         Txeoln= value&EOL_CRWAIT;
                         Txmoname="CR WAIT FOR NL";
                         break;
                 case 'x':
                         Exoneof=value;
                         break;
                 case 'z':
                         Zeof=value;
                         break;
                 default:
                         return ERROR;
                 }
         return dumped;
 }

 init()
 {
 #ifdef BDSC
         char *endext(), *topofmem(), *codend(), *externs();
         if(codend() > externs()) {        /* check for bad -e value! */
                 printf("urk"); exit();
         }
 /* BDSC */
 #ifdef USERINIT
         userinit();        /* allows extra user externs' to be initialized */
 /* USERINIT */
         initdd();                /* fetch default disk and user number */
         bufst=endext();
         bufend=topofmem()-1024;        /* fudge so we don't crash ... */
         Dport=DPORT; Sport=SPORT;
 #ifndef DEFBAUD
         readbaud();
 #else
         Baudrate=DEFBAUD;
 /* DEFBAUD */
 #ifdef INITBAUD
         setbaud(Baudrate);
 /* INITBAUD */
         Mstatus=0;
         Rfile=Tfile=Pflag=FALSE;
         Image=Waitbunch=Exoneof=Hdx=Zeof=Squelch=FALSE;
         Txgo=TRUE;
         Parity= NORMAL;
         Originate= TRUE;
         Txeoln= EOL_NOTHING;
         Low= 400;
         Tpause=1500*CLKMHZ;
         Throttle=80*CLKMHZ;
         T1pause=311*CLKMHZ;
         Waitnum=1;
         GOchar= '\n';
         clearbuf();
 }

 clearbuf()
 {
         abptr=NULL;
         Xoffflg=Wrapped= FALSE;
         buffcdq=bufcq=bufcdq=bufpcdq=bufmark= bufst;
         Bufsize=Free= bufend-bufst-1;
 }


 cmdeq(s,p)
 char *s, *p;
 {
         while(*p)
                 if(*s++ != *p++)
                         return 0;
         return 1;
 }

 dostat()
 {

         printf("Capture %s Receiving %s ",
           Dumping?"ON":"SQUELCHED", Rfile?Rname:"<nil>");
         if(Image)
                 printf("Transparency mode ");
         if(Squelch)
                 printf("^R ^T Squelch ");
         if(Zeof)
                 printf("EOF on ^Z");
         printf("\n");

         if(Txeoln==EOL_NOTHING)
                 Txmoname="IMAGE";

         printf("%sSending %s in %s mode\n",
           Txgo? "" : "Pausing in ", Tfile?Tname:"<nil>", Txmoname);
         printf("%sWaiting %d loops every %u chars  Pause=%u GOchar=0%o\n",
           Waitbunch?"":"NOT ",Throttle, Waitnum, Tpause, GOchar);

         printf("Printer %s  ", Pflag?"ON":"OFF");
         if(Hdx)
                 printf("Half Duplex ");
         printf("At %u baud data port %u\n", Baudrate, Dport);
         printf("%u of %u chars used %u free%s\n",
           Bufsize-Free, Bufsize, Free, Wrapped?" POINTERS WRAPPED":"");
         printf("bufst=%x bufcq=%x bufcdq=%x\nbuffcdq=%x bufpcdq=%x bufend=%x\
           bufst, bufcq, bufcdq, buffcdq, bufpcdq, bufend);
 #ifndef CDOS
         printdfr();
 /* CDOS */
 }

 isgraphic(c)
 {
         if(c>' ' && c<0177)
                 return TRUE;
         else
                 return FALSE;
 }

 /*
  * index returns a pointer to the first occurrence of c in s,
  * NULL otherwise.
  */
 char *index(c, s)
 char c,*s;
 {
         for(; *s; s++)
                 if(c== *s)
                         return s;
         return NULL;
 }
 psxfer(status)
 {
         lpstat("\007File transfer(s) %s\007",
          status==ERROR?"ABORTED BY ERROR" : "successful");
 #ifndef CDOS
         printdfr();
 /* CDOS */
 }

 setparm(p)
 char *p;
 {
         if(*p)
                 switch(*p++) {
                 case 'g':
                         if((GOchar= *p) == '^')
                                 GOchar= (*++p & 037);
                         break;
                 case 'l':
                         Low=atoi(p);
                         break;
                 case 'p':
                         Tpause=atoi(p);
                         break;
                 case 't':
                         Throttle=atoi(p);
                         break;
                 case 'w':
                         Waitnum=atoi(p);
                         break;
                 default:
                         return ERROR;
          }
         return 0;
 }
 /* make strings lower case */
 uncaps(s)
 char *s;
 {
         while(*s)
                 *s = tolower(*s++);
 }

 /* end of YAM1.C */


 YAM10.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM10.C

 /*
 >> yam10.c 04-Mar-84
         File unsqueezer module taken from Richard Greenlaw's USQ
 */
 #include "yam.h"

 /* *** Stuff for first translation module *** */
 #define DLE 0x90
 /* *** Stuff for second translation module *** */
 SPEOF 256        /* special endfile token */
 #define LARGE 30000

 unsqueeze()

 {
         int i, c;
         char cc;

         char *p;
         int numnodes;                /* size of decoding tree */
         unsigned linect;        /* count of number of lines previewed */
         char origname[14];        /* Original file name without drive */

         /* Initialization */
         linect = 0;
         init_cr();
         init_huff();

         /* Process rest of header (RECOGNIZE already read) */
         getw(&fin);        /* ignore checksum ... */

         /* Get original file name */
         p = origname;        /* send it to array */
         do
         {
                 *p = getc(&fin);
         } while(*p++ != '\0');

         printf("%s -> %s\n", Tname, origname);

         numnodes = getw(&fin);
         if(numnodes < 0 || numnodes >= NUMVALS)
         {
                 printf("%s has invalid decode tree size\n", Tname);
                 return 1;
         }

         /* Initialize for possible empty tree (SPEOF only) */
         dnode[0].children[0] = -(SPEOF + 1);
         dnode[0].children[1] = -(SPEOF + 1);

         /* Get decoding tree from file */
         for(i = 0; i < numnodes; ++i)
         {
                 dnode[i].children[0] = getw(&fin);
                 dnode[i].children[1] = getw(&fin);
         }

         while((c = getcr()) != EOF)
         {
 #ifdef RESTRICTED
                 if (c == '\n')  /* new line? */
                 {
                         if (++linect >= MAXLINES)
                         {        printf("\n\n\t[== Squeezed file %d-line limi
                                 printf("\n\t[Use S mode to transfer file to y
                                 return CNTRLK;
                         }
                 }
 #endif
                 if( !(c=putcty(c)))
                         continue;
                 if(c == CNTRLC || c == CAN || c == CNTRLK)
                 {
                         return c;
                 }
         }
         return CPMEOF;
 }


 /* initialize decoding functions */

 init_cr()

 {
         repct = 0;
 }

 init_huff()
 {
         bpos = 99;        /* force initial read */
 }

 /* Get bytes with decoding - this decodes repetition,
  * calls getuhuff to decode file stream into byte
  * level code with only repetition encoding.
  *
  * The code is simple passing through of bytes except
  * that DLE is encoded as DLE-zero and other values
  * repeated more than twice are encoded as value-DLE-count.
  */

 int
 getcr()

 {
         int c;

         if(repct > 0)
         {
                 /* Expanding a repeated char */
                 --repct;
                 return value;
         }
         else
         {
                 /* Nothing unusual */
                 if((c = getuhuff()) != DLE)
                 {
                         /* It's not the special delimiter */
                         value = c;
                         if(value == EOF)
                                 repct = LARGE;
                         return value;
                 }
                 else
                 {
                         /* Special token */
                         if((repct = getuhuff()) == 0)
                         {
                                 /* DLE, zero represents DLE */
                                 return DLE;
                         }
                         else
                         {
                                 /* Begin expanding repetition */
                                 repct -= 2;        /* 2nd time */
                                 return value;
                         }
                 }
         }
 }

 /* Decode file stream into a byte level code with only
  * repetition encoding remaining.
  */

 int
 getuhuff()

 {
         int i;
         int bitval;

         /* Follow bit stream in tree to a leaf*/
         i = 0;        /* Start at root of tree */
         do
         {
                 if(++bpos > 7)
                 {
                         if((curin = getc(&fin)) == ERROR)
                                 return ERROR;
                         bpos = 0;
                         /* move a level deeper in tree */
                         i = dnode[i].children[1 & curin];
                 }
                 else
                 {
                         i = dnode[i].children[1 & (curin >>= 1)];
                 }
         } while(i >= 0);

         /* Decode fake node index to original data value */
         i = -(i + 1);
         /* Decode special endfile token to normal EOF */
         i = (i == SPEOF) ? EOF : i;
         return i;
 }


 YAM11.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM11.C

 /*
 >>:yam11.c   01-Jun-83
  * Console primitives
  * 'moment','pstat','lpstat','lprintf','getcty','putcty','sendcon'
  * extracted from all other YAM modules, and placed here so that
  * they may be more easily got at and altered for different
  * machines        (jdw).
  */

 #include "yam.h"

 /* following are BIOS calls */
 CONST 2                        /* bios console char ready */
 CONIN 3                        /* bios cons char input */
 CONOUT 4                /* bios cons char output */

 /* following are BDOS calls */
 BDOS 5                        /* address used to call bdos */
 SELDSK 14                /* bdos select disk 0=default disk */
 SRCH 17                        /* bdos search for file pattern*/
 SRCHNXT 18                /* search for next occurrence */
 GETDEFDISK 25                /* get current disk  (0-15) */
 SETDMA 26                /* set address for read, write, etc. */
 GETALLOCP 27                /* get address of allocation vector */
 SETATTRIB 30                /* update file attributes */
 GETDPBP 31                /* get DPB address for disk */
 SETGETUSER 32                /* set or get user number */
 COMPFILSIZ 35                /* compute file size into recn and recovf */
 UFNSIZE 15                /* a:foobar12.urk\0 is 15 chars */



 #ifdef        SORCERER

                    /* a local video handler for status line */
                    /* also keyboard cause unmodded Sorcerer
                       upsets UART port */

 putchar(c)
 char (c);
 {
     putch(c);
 }


 putch(c)
 char c;
 {
         int mwasav;

     mwasav = *mwalin;
     switch (c)
     {
         case (12) : callit(17);callit(' ');callit(17);
                     setmem(0xf080,1856,' ');
                     setmem(0xf780,64,'=');
                     break;

       case ('\t') : callit(' ');
                     while (*mwacol%8)
                        putch(' ');
                     break;

       case ('\n') : callit('\r');

           default : callit (c);
                     if((*mwacol==63) && (mwasav==*mwalin))
                         putch('\n');

                     if (*mwalin >= 1792)
                     {
                         movmem(0xf0c0,0xf080,1728);
                         setmem(0xf740,64,' ');
                         setmem(0xf780,64,'=');
                         callit(23);
                     }
                     break;
     }

 }

 getchar()
 {
         char c;
         c = getch();
         if (c) putchar(c);
         return c;
 }


 getch()
 {
         return (keyget());
 }




 /*
  * SORCERER implements 30th line. pstat starts at lpstat + 3
  * note that a call to lpstat will erase what pstat displays
  */

 pstat(a)
 char *a;
 {
         char lin[MAXLINE];

         setmem(0xf7c0 + statpos,64 - statpos,' ');
         _spr(lin,&a);
         txtplot(lin,29,statpos,0);

 }

 /*
  * Sorcerer 30th line. lpstat starts at col 1
  * Rest of line is erased
  */

 lpstat(a,b,c)
 char *a, *b, *c;
 {
         char lin[MAXLINE];

         setmem(0xf7c0,64,' ');
         _spr(lin,&a);
         txtplot(lin,29,0,0);
         statpos = strlen(lin) + 3;
 }



 char getcty()
 {
         return keyget();
 }
 char putcty(c)
 char c;
 {
 #ifdef RXNONO
         if(index(c, RXNONO))
                 return 0;
 #endif
         putchar(c);
         if(keyprs()) {
                 if( (c=(keyget() & KBMASK)) == XOFF)
                         keyget();
                 else
                         return c;
         }
         return FALSE;
 }

 /*
  * moment waits a moment and returns FALSE, unless a character is hit,
  * in which case that character is returned
  */

 moment(n)
 int n;
 {
         int c;
         for(c=n*CLKMHZ; --c>0;)
                 if(keyprs())
                         return(keyget());
         return FALSE;
 }



 sendcon(c)            /* direct output to console */

 char c;

 {
         putch(c);
 }

 /* Any special initialisation for console hardware goes here */

 init1_extra()

 {
         mwalin = mwa() + 0x68;
         mwacol = mwa() + 0x6a;
         statpos = 0;
 }

 init2_extra()

 {
 }

            /* SORCERER */

 #ifndef SORCERER

 /*
  * moment waits a moment and returns FALSE, unless a character is hit,
  * in which case that character is returned
  */

 moment(n)
 int n;

 {
         int c;
         for(c=n*CLKMHZ; --c>0;)
                 if(kbhit())
                         return(getchar());
         return FALSE;
 }

 pstat(a,b,c)
 char *a, *b, *c;

 {
         lprintf(a,b,c);
         lprintf("\n");
 }

 lpstat(a,b,c)
 char *a, *b, *c;

 {
         lprintf(a,b,c);
         lprintf("\n");
 }

 char getcty()

 {
         return bios(CONIN,0);
 }


 char putcty(c)
 char c;

 {
 #ifdef RXNONO
         if(index(c, RXNONO))
                 return 0;
 /* RXNONO */

         if(View)                /* view set by list command, allows ^p */
                 putchar(c);
         else{
                 sendcon(c);
                 if(Type)
                         sendline(c);        /* so remote user can see it */
         }
         if(bios(CONST,0)) {
                 if((c=(bios(CONIN,0)&KBMASK))==XOFF)
                         bios(CONIN,0);
                 else
                         return c;
         }
         return FALSE;
 }

 #ifdef XMODEM
 /*
  * lprintf is like regular printf but uses direct output to console
  * This prevents status printouts from disrupting file transfers, etc.
  */

 lprintf(a,b,c,d,e,f)
 char *a, *b, *c, *d, *e, *f;

 {
         char lbuf[CMDLEN];
         char *s;

         sprintf(lbuf, a,b,c,d,e,f);         /* format data into lbuf */
         for(s=&lbuf; *s != '\0' ; ) {        /* now send lbuf to console dire

                 MODEMON
                 if (CDO){
                         printf("Carrier lost in lprintf function\n");
                         exit();                        /* quit if carrier los
                 }
                 if(*s=='\n') {
                         sendcon('\r');                /* expand \n to \r\n */
                 }
                 sendcon(*s++);
         }
 }
 #endif

 sendcon(c)            /* direct output to console */
 char c;

 {
 #ifdef XMODEM
                 MODEMON
                 if (CDO){
                         printf("Carrier lost in sendcon function\n");
                         exit();
                 }
 /* XMODEM */

 #ifdef CODATA
                 CONSOLON
                 while(!COREADY)
                     ;
                 outp(CODATA,c);
 #else
                 bios(CONOUT,c);
 /* CODATA */
 }

 /* Any special initialisation for console hardware goes here */

 init1_extra()

 {
 }

 init2_extra()

 {
 }

 /* !SORCERER */

 /* end of YAM11.C   */


 YAM2.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM2.C

 /*
 >>:yam2.c 04-Jun-83 (diff 05-11-81)
  * Ward Christensen Protocol handler for sending and receiving
  * ascii and binary files.  Modified for choice of checksum or crc.
  */

 #include "yam.h"
 #define WCEOT (-10)

 wcsend(argc, argp)
 char **argp;
 {
         int wcs();

         dumprxbuff();                      /* flush buffers first  */
         closerx(TRUE); closetx(TRUE);

         Crcflg=FALSE;
         firstsec=TRUE;
         if(Batch)
         {
 #ifdef XMODEM
                 printf("Sending in Batch Mode\n");
 #endif
                 if(expand(wcs, argc, argp)==ERROR)
                 {
                         goto fubar;
                 }
                 if(wctxpn("")==ERROR)
                         goto fubar;
         }
         else
         {
                 for(; --argc>=0;)
                 {
                         if(opentx(*argp++)==ERROR)
                         {
                                 goto fubar;
                         }
                         if(wctx()==ERROR)
                                 goto fubar;
                 }
         }
         return OK;
 fubar:
         closetx(TRUE);
         sendline(CAN);
         sendline(CAN);
         sendline(CAN);
         return ERROR;
 }

 wcs(name)
 char *name;
 {
         if(opentx(name)==ERROR)
                 return ERROR;
         if(wctxpn(name)!= ERROR)
                 return wctx();
         else
         {
                 return ERROR;
         }
 }


 wcreceive(argc, argp)

 char **argp;

 {
         char rpn[SECSIZ];                /* rx path name */

         dumprxbuff();                      /* flush buffers first  */
         closerx(TRUE); closetx(TRUE);

         if(Batch || argc==0)
         {
                 printf("Receiving in Batch Mode\n");
                 for(;;)
                 {
                         if(wcrxpn(rpn)== ERROR)
                                 goto fubar;
                         if(*rpn==0)
                                 return OK;
                         if(wcrx(rpn)==ERROR)
                                 goto fubar;
                 }
         }
         else
                 for(; --argc>=0;)
                 {
 #ifdef XMODEM
                         printf("Receive:'%s' FILE OPEN\n", *argp);
 #endif
                         if(wcrx(*argp++)==ERROR)
                                 goto fubar;
                 }
         return OK;
 fubar:
         sendline(CAN);sendline(CAN);sendline(CAN);
         closerx(TRUE);
         return ERROR;
 }

 /*
  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
  * Length is indeterminate as long as less than SECSIZ
  * a null string represents no more files
  */

 wcrxpn(rpn)

 char *rpn;        /* receive a pathname */

 {
         char rname[SECSIZ];

         purgeline();
         firstsec = TRUE;
         sendline(Crcflg?WANTCRC:NAK);
         if(wcgetsec(rname, 100) != 0)
         {
                 printf("Pathname fetch failed\n");
                 return ERROR;
         }
         strcpy(rpn, rname);
         sendline(ACK);
         return OK;
 }


 wctxpn(name)

 char *name;

 {
         char *p;

         lpstat("Awaiting initial pathname NAK");
         if((firstch=readline(400))==TIMEOUT)
                 return ERROR;
         if(firstch==WANTCRC)
                 Crcflg=TRUE;
         /* don't send drive specification */
         if(p=index(':', name))
                 name= ++p;
         if(wcputsec(name, 0)==ERROR)
         {
                 printf("Can't send pathname %s\n", name);
                 return ERROR;
         }
         return OK;
 }

 /*
  * Adapted from CMODEM13.C, written by
  * Jack M. Wierda and Roderick W. Hart
  */

 wcrx(name)

 char *name;

 {
         int sectnum, sectcurr, sectcomp;
         char rxbuf[128], sendchar;

         if(openrx(name)==ERROR)
                 return ERROR;
         firstsec=TRUE;sectnum=0;
         sendchar=Crcflg?WANTCRC:NAK;

         for(;;)
         {
                 if(!Quiet
 #ifdef STATLINE
                 )
                         lpstat("Sector %3d", sectnum+1);
 #else
                 && !View)
                         lprintf("%s", (sectnum+1 &63)?"*":"*\n");
 #endif
                 purgeline();
                 sendline(sendchar);        /* send it now, we're ready! */
                 sectcurr=wcgetsec(rxbuf, (sectnum&0177)?100:200);
                 if(sectcurr==(sectnum+1 &0377))
                 {

                         sectnum++;
                         for(cp=rxbuf,wcj=128; --wcj>=0; )
                                 if(putc(*cp++, fout)==ERROR)
                                 {
                                         printf("\nDisk Full\n");
                                         return ERROR;
                                 }
 #ifndef XMODEM
                         if(View)
                                 for(cp=rxbuf,wcj=128;--wcj>=0;)
                                         putchar(*cp++);
 #endif
                         sendchar=ACK;
                 }
                 else if(sectcurr==sectnum)
                 {
                         pstat("Received dup Sector %d",sectcurr);
                         sendchar=ACK;
                 }
                 else if(sectcurr==WCEOT)
                 {
                         sendline(ACK);
                         /* don't pad the file any more than it already is */
                         closerx(FALSE);
                         return OK;
                 }
                 else if(sectcurr==ERROR)
                         return ERROR;
                 else
                 {
                         printf(" Sync Error\n");
                         return ERROR;
                 }
         }
 }

 /*
  * wcgetsec fetches a Ward Christensen type sector.
  * Returns sector number encountered or ERROR if valid sector not received,
  * or CAN CAN received
  * or WCEOT if eot sector
  * time is timeout for first char, set to 5 seconds thereafter
  ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
  *    (Caller must do that when he is good and ready to get next sector)
  */

 wcgetsec(rxbuf, time)

 char *rxbuf;
 int time;

 {
 /* BDSC
         register checksum, wcj, firstch;
 */
         int sectcurr,errors;

         for(Lastrx=errors=0; errors<RETRYMAX; errors++) {

                 firstch=readline(time);
                 if(firstch==SOH)
                 {
                         sectcurr=readline(1);
                         if((sectcurr+readline(1))==255)
                         {
                                 oldcrc=checksum=0;
                                 for(cp=rxbuf,wcj=128; --wcj>=0; )
                                 {
                                         if((firstch=readline(1)) < 0)
                                                 goto bilge;
                                         oldcrc=updcrc(firstch, oldcrc);
                                         checksum += (*cp++ = firstch);
                                 }
                                 if((firstch=readline(1)) < 0)
                                         goto bilge;
                                 if(Crcflg)
                                 {
                                         oldcrc=updcrc(firstch, oldcrc);
                                         if((firstch=readline(1)) < 0)
                                                 goto bilge;
                                         oldcrc=updcrc(firstch, oldcrc);
                                         if(oldcrc)
                                                 pstat("CRC=0%o Error #%d",
                                                   oldcrc, errors);
                                         else
                                         {
                                                 firstsec=FALSE;
                                                 return sectcurr;
                                         }
                                 }
                                 else if(((checksum-firstch)&0377)==0)
                                 {
                                         firstsec=FALSE;
                                         return sectcurr;
                                 }
                                 else
                                         pstat("Checksum Error #%d", errors);
                         }
                         else
                                 pstat("Sector number garbled #%d", errors);
                 }

                 /* make sure eot really is eot and not just mixmash */

                 else if(firstch==EOT && readline(1)==TIMEOUT)
                         return WCEOT;
                 else if(firstch==CAN)
                 {
                         if(Lastrx==CAN)
                         {
                                 printf("Sender CANcelled\n");
                                 return ERROR;
                         } else
                         {
                                 Lastrx=CAN;
                                 continue;
                         }
                 }
                 else if(firstch==TIMEOUT)
                         pstat("Timeout #%d", errors);
                 else if(firstch==ERROR)
                 {
 bilge:
                         pstat("Modem error #%d SR=%0o", errors, Mstatus);
                 }
                 else
                         pstat("Got 0%o sector header", firstch);
                 Lastrx=0;
                 while(readline(1)!=TIMEOUT)
                         ;
                 time=40;
                 sendline(Crcflg&&firstsec?WANTCRC:NAK);
         }

         /* try to stop the bubble machine. */

         sendline(CAN);sendline(CAN);sendline(CAN);
         return ERROR;
 }

 wctx()
 {
         int sectnum, attempts;
         char txbuf[SECSIZ];

         firstsec=TRUE;
         lpstat("Awaiting initial NAK");
         while((firstch=readline(400))!=NAK && firstch != WANTCRC
           && firstch!=TIMEOUT && firstch!=CAN)
                 lprintf("%c", firstch);        /* let user see it if strange
         if(firstch==CAN)
                 return ERROR;
         if(firstch==WANTCRC)
                 Crcflg=TRUE;
         sectnum=1;
         while(filbuf(txbuf, SECSIZ)) {
                 if(!Quiet
 #ifdef STATLINE
                 )
                         lpstat("Sector %3d", sectnum);
 #else
                 && !View)
                         lprintf("%s", (sectnum&63)?"*":"*\n");
 #endif
                 if(wcputsec(txbuf, sectnum)==ERROR)
                 {
                         return ERROR;
                 } else
                 {
                         if(View)        /* View can't be set in xyam */
                                 for(cp=txbuf,wcj=128;--wcj>=0;)
                                         putchar(*cp++);
                         sectnum++;
                 }
         }
         closetx(FALSE);
         attempts=0;
         do
         {
                 sendline(EOT);
                 purgeline();
                 attempts++;
         }
                 while((firstch=(readline(100)) != ACK) && attempts < RETRYMAX
         if(attempts == RETRYMAX)
         {
                 printf("No ACK on EOT\n");
                 return ERROR;
         }
         else
                 return OK;
 }

 wcputsec(txbuf, sectnum)
 char *txbuf;
 {
 /* BDSC
         register checksum, wcj, firstch;
 */
         int attempts;

         firstch=0;        /* part of logic to detect CAN CAN */

         for(attempts=0; attempts <= RETRYMAX; attempts++)
         {
                 Lastrx= firstch;
                 sendline(SOH);
                 sendline(sectnum);
                 sendline(-sectnum-1);
                 oldcrc=checksum=0;
                 for(wcj=SECSIZ,cp=txbuf; --wcj>=0; )
                 {
                         sendline(*cp);
                         oldcrc=updcrc(*cp, oldcrc);
                         checksum += *cp++;
                 }
                 if(Crcflg)
                 {
                         oldcrc=updcrc(0,updcrc(0,oldcrc));
                         sendline(oldcrc>>8);sendline(oldcrc);
                 }
                 else
                         sendline(checksum);
                 purgeline();

                 firstch=readline(100);
                 if(firstch==CAN && Lastrx==CAN)
                 {
 cancan:
                         printf("\nReceiver CANcelled transmission ");
                         return ERROR;
                 }
                 else if(firstch==ACK)
                 {
                         firstsec=FALSE;
                         return OK;
                 }
                 else if(firstch==TIMEOUT)
                         pstat("Timeout on sector ack attempt %d", attempts);
                 else
                 {
                         if(firstsec && firstch==WANTCRC)
                                 Crcflg=TRUE;
                         pstat("Got 0%o for sector ACK attempt %d",
                           firstch, attempts);
                         for(;;)
                         {
                                 Lastrx=firstch;
                                 /* let user see it if strange char */
                                 lprintf("%c", firstch);
                                 if((firstch=readline(1))==TIMEOUT)
                                         break;
                                 if(firstch==CAN && Lastrx==CAN)
                                         goto cancan;
                         }
                 }
         }
         printf("No ACK on sector; Abort\n");
         return ERROR;

 }

 /* end of YAM2.C */


 YAM3.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM3.C

 /*
 >>:yam3.c 28-Sep-82 (dif 10-17-81)
  *
  * two-way conversation with remote -whatever.
  * Printer is buffered such that it needn't be as fast as the baudrate
  * as long as it eventually gets a chance to catch up.
  * This buffering also allows one to write the received data out to disk
  * after the conservation has started.
  */
 #include "yam.h"

 term()
 {
 #ifndef BDSC
         register char cfast;
 #endif
         register c, cc;
         unsigned register charsent;
         sayterm();
         charsent=0;
         Waitecho=Txwait=FALSE;
         for(;;) {
                 MODEMON
                 if(MIREADY) {
                         *bufcq++ = MICHAR;
                         Timeout=0;
                         if(bufcq >= bufend) {
                                 Wrapped=TRUE;
                                 bufcq=bufst;
                         }
                         if(--Free == Low)
                                 sendline(Xoffflg=XOFF);
                         else if(Free==0)
                                 goto belch;
                         continue;
                 }
                 CONSOLON
                 if(COREADY && bufcdq != bufcq) {
                         switch(cfast= (*bufcdq & 0177) ) {
                         case '\b':
                                  if(Ttycol)
                                         --Ttycol;
                                 break;
                         case '\t':
                                 sendcon(' ');
                                 if(++Ttycol & 07)
                                         continue;
                                 else
                                         goto chuckit;
                         case '\r':
                                 Ttycol=0;
                         case '\n':
                                 break;
                         case XOFF:
 #ifdef STATLINE
                                 sayterm();
 #endif
                                 Txgo=FALSE; break;
                         case XON:
                                 Txgo=TRUE;
 #ifdef STATLINE
                                 sayterm();
 #endif
                                 break;
 #ifdef XMODEM
                         case CPMEOF:
 /*                                pstat(""); */
                                 return;
                         case 007:
                                 break;
 #endif
                         default:
                                 if(Ctlview)
                                 {
                                         if(cfast & 0200) {
                                                 cfast &= 0177;
                                                 if(Ctlview>1) {
                                                         putchar('~'); ++Ttyco
                                                 }
                                         }
                                         if(cfast<040) {
                                                 putchar('^');
                                                 putchar(cfast|0100);
                                                 Ttycol += 2;
                                                 goto chuckit;
                                         }
                                         else
                                                 ++Ttycol; break;
                                 }
                         }
                         if(cfast==GOchar && Txeoln==EOL_CRWAIT)
                                 Waitecho=FALSE;

 #ifdef RXNONO
                         if( !index(cfast, RXNONO))
 /* RXNONO */
                                 sendcon(cfast);
                         if(Echo) {
                                 sendline(cfast);
                                 if(Chat && cfast== '\r') {
                                         sendcon('\n');
 #ifndef XMODEM
                                         sendline('\n');
 #endif
                                 }
                         }
 chuckit:
                         if(++bufcdq >= bufend)
                                 bufcdq=bufst;
                         continue;
                 }
                 if(Pflag && bufpcdq!=bufcq && POREADY) {
 #ifdef CPM
                         bios(5, (*bufpcdq++ & 0177));
 #else
                         foobar...
 #endif
                         if(bufpcdq >= bufend)
                                 bufpcdq=bufst;
                 }
                 CONSOLON
                 if(CIREADY) {
                         switch(cfast= CICHAR & KBMASK){
                          case ENQ:
                                 if(moment(KTIME2))   /* ^E ^E quick sends one
                                         break;
 /*                                pstat(""); */
                                 putchar('\n');
                                 return;
                         case XON:
                                 if(Tfile && !Txgo) {
                                         Txgo=TRUE;
                                         sayterm();
                                 }
                                 break;
                         case XOFF:
                                 if(Tfile && Txgo) {
                                         Txgo=FALSE;
                                         sayterm();
                                 }
                                 break;
                         case 'v'&037:
                                 if(moment(KTIME2))
                                         break;
                                 replot(TLENGTH<<1);
                                 sayterm();
                                 continue;
                         case '\r':
                                 if(Hdx)
                                         printf("\n");
                                 if(Chat)
                                         sendline('\n');
                                 break;
                         default:
                                 break;
                         }
                         sendline(cfast);
                         if(Hdx) {
                                 sendcon(cfast);
                         }
                         continue;
                 }
                 MODEMON
                 if(MOREADY) {
                         if(Tfile && !Txwait && !Waitecho && Txgo) {
                                 c= getc(fin);
 #ifdef CPM
                                 if(c==EOF || (c==CPMEOF && Txeoln != TX_BINAR
 #else
                                 if(c==EOF)
 #endif
                                 {
                                         closetx(FALSE);
 #ifdef XMODEM
 /*                                        pstat(""); */
                                         return;
 #else
                                         if(Exoneof)
                                                 return;
                                         sayterm();
 #endif
                                 }
 offwithit:
                                 if(Waitbunch && ++charsent==Waitnum) {
                                         charsent=0;
                                         if(Waitnum>1) {
                                                 Waitecho=TRUE;
                                                 Timeout=0;
                                         } else {
                                                 Txwait=TRUE;
                                                 Txtimeout=Throttle;
                                         }
                                 }

                                 if(c=='\r') {        /* end of line processin
                                         switch(Txeoln) {
                                         case EOL_NL:
                                                 continue;
                                         case EOL_CRPROMPT:
                                         case EOL_CRWAIT:
                                                 Waitecho=TRUE;
                                                 Timeout=0;
                                         case EOL_CR:
                                                 if(Tfile) {
                                                         if((cc=getc(fin))!='\
                                                                 ungetc(cc, fi
                                                 }
                                                 else if(*++abptr != '\n')
                                                         --abptr;
                                                 break;
                                         }
                                 }
                                 sendline(c);
                                 continue;
                         }
                         if(abptr && !Txwait && !Waitecho && Txgo) {
                                 if(abptr>=abend) {
                                         abptr=NULL;
                                         if(Exoneof)
                                                 return;
                                 }
                                 else {
                                         c= *abptr++;
 #ifdef LOOPBACKNONO
                                         if(index(c, LOOPBACKNONO))
                                                 continue;
 #endif
                                         goto offwithit;
                                 }
                         }
                 }
                 if(++Timeout == Tpause) {
                         Waitecho=FALSE;
 belch:
                         if(Xoffflg) {
                                 dumprxbuff();
                                 MODEMON
                                 if(MIREADY) {
                                         lpstat("\007OVERRUN: DATA LOST");
                                         if(Low<1000)
                                                 return;
                                 }
                                 if(bufcdq != bufcq)
                                         continue;
                                 if(Pflag && bufpcdq != bufcq)
                                         continue;
                                 Free=Bufsize-1;
                                 Xoffflg=FALSE;
                                 sendline(XON);
                         }
 #ifdef CDO
                         MODEMON
                         if(CDO) {
                                 pstat("Carrier Lost");
                                 return;
                         }
 #endif
                 }
                 if(--Txtimeout==0)
                         Txwait=FALSE;
         }
 }

 /* display the appropriate status information */
 sayterm()
 {
 #ifdef TERMRESET
         lprintf(TERMRESET);
 #endif
         if(Tfile)
                 lpstat("Sending '%s' %s", Tname, Txgo?"":"Stopped by XOFF");
         if(Rfile)
                 pstat("Term Receiving '%s'", Rname);
         else
                 pstat("Term Function");
 }

 /* open a capture file and set the removal pointer to get max goods */
 opencapt(name)
 char *name;
 {
         dumprxbuff();
         closerx(TRUE);
         if(openrx(name)==ERROR)
                 return ERROR;
         if(buffcdq<bufst)
                 buffcdq=bufst;
         if(Wrapped)
                 buffcdq=bufcq+1;
         if(buffcdq >= bufend)
                 buffcdq=bufst;
 /*        dumprxbuff(); */
 }

 dumprxbuff()
 {
         register c;

         if(!Rfile || buffcdq==NULL)
                 return OK;
         while(buffcdq != bufcq) {
                 c= *buffcdq++;
                 if(buffcdq >= bufend)
                         buffcdq=bufst;
                 if(!Image) {
                         switch(c &= 0177) {
                          case 0:
                                  continue;
                         case 032:                /* ^Z or CPMEOF */
                                 if(Zeof) {
                                         closerx(TRUE);
                                         return;
                                 }
                                 else
 #ifdef CPM
                                         continue;
 #else
                                         break;
 #endif
                         case 022:
                                 if(Squelch) {
                                         Dumping=TRUE;
                                         continue;
                                 }
                                 break;
                         case 024:
                                 if(Squelch) {
                                         Dumping=FALSE;
                                         continue;
                                 }
                                 break;
                         default:
                                 break;
                         }
                 }
                 if(Dumping || Image)
                         if(putc(c, fout)==ERROR) {
                                 printf("\nDisk Full\n");
                                 closerx(FALSE);
                                 return ERROR;
                         }
         }
         Free=Bufsize-1;
         return OK;
 }

 rewindcb()
 {
         bufcdq=buffcdq=bufpcdq=Wrapped?bufcq+1:bufst;
 }

 /*
  * replot redisplays the buffer contents thru putcty allowing XOFF
  * number will represent how many lines to go back first
  */
 replot(number)
 {
         char *s, c;
         int count, shorts;

 fromtop:
         shorts=0;
         bufmark=Wrapped?bufcq+1:bufst;

         if(number) {
                 s=bufcq;
 backsome:
 #ifdef TERMINIT
                 /* backing up is confusing unless screen is cleard first */
                 lprintf(TERMINIT);
 #endif
                 for(;;) {
                         --s;
                         if(s<bufst) {
                                 if(Wrapped)
                                         s= bufend-1;
                                 else {
                                         s=bufst;
                                         break;
                                 }
                         }
                         if(s==bufcq)
                                 break;
                         if((*s&0177)=='\n' && --number<=0)
                                 break;
                 }
                 bufmark=s;
         }
         s=bufmark;
 nextscreen:
 #ifdef T4014
         /* Do the big flash on the 4014 or 4012 */
         printf("\033\014");
         sleep(CLKMHZ * 5);
 #endif
         count=TLENGTH - shorts;
         shorts =0;
 nextline:
         while(s != bufcq) {
                 cfast= *s++ & 0177;
                 if(s >= bufend)
                         s=bufst;
                 if(c=putcty(cfast))
                         goto choose;
                 if(cfast=='\r' && --count<=0)
                         break;
         }

 #ifdef STATLINE
         pstat("Replot cmd?");
 #endif
         c=getcty();
 #ifdef STATLINE
 /*        pstat(""); */
 #endif
 choose:
 /* Treat Control chars and letters the same */
         switch((c|0140)&0177) {
         case 'b':
                 number=0;
                 goto fromtop;
         case 'v':        /* control-v or v */
         case 'h':        /* backspace */
                 number=TLENGTH-2;
                 s=bufmark;
                 goto backsome;
         case 0140:                /* space bar */
                 shorts=2;
                 bufmark=s;
                 goto nextscreen;
         case 'p':
                 number=1;
                 s=bufmark;
                 goto backsome;
         case 'n':
         case 'j':        /* linefeed */
                 bufmark=s;
                 count=1;
                 goto nextline;
         default:
                 return;
         }
 }

 chat()
 {
 #ifdef XMODEM
         printf("Ring My Chimes, Maybe I'll Come\n");
         printf("Exit chat with ^Z\n");
 #endif
         Chat=Ctlview=Hdx=Echo=TRUE;
         term();
 }

 /* end of YAM3.C */


 YAM5.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM5.C

 /*
 >>:yam5.c 02-Jun-83
 *
 * This version implements parameterized #define in Sendline() routine
 *
 * Modem related functions. If your(modem supports baudrate setting,
 * and hangup, write your own routines here.
 * If your modem supports an autocall, put that routine here also
 * define MODEMSTUFF to suppress default baud rate related functions.
 * define AUTOCALL in your autocall routine to suppress the default
 * which merely prints the phone number and recommended baud rate.
 *
 * LOOP & TEST are used for loopback testing of the communications
 *               line.
 *
 * LOOP simply loop comm input to comm output as each character
 *        is processed, (or a timeout occurs) a '.' is printed to
 *        console.  This is simply to let you monitor what is
 *        going on. Slow dots = timeouts = nothing doing.
 *        Speedy dots = chars echoed.
 *
 *   usage 'LOOPn' where n is a number of characters (or timeouts)
 *                   to stay in the loop . Keyboard bashing exits
 *                   (n ommitted = 65535).
 *
 * TEST performs loopback tests (sending a char & reading the next
 *        received char to see if the same) on the line that is
 *        terminated in a loop, either physically (at modem) or
 *        by other end being in 'LOOP'.
 *        Successfully received chars output a '.' to console,
 *        while errors echo an '*', and timeouts say so.
 *
 *  usage 'TESTn' where n is number of characters to send to
 *                  line, keyboard bashing also exits.  Final
 *                  message is number of errors (not timeouts)
 *                  received.
 */

 #include "yam.h"

 #ifdef SORCERER
 #define MODEMSTUFF
 /*
 * set baud rate for modem driven by Sorcerer + bitrate chip
 */

 setbaud(nbaud)
 unsigned nbaud;
 {
         char baudcmd, *i;
         switch(nbaud)
         {
         case  300: baudcmd=0x80; break;
         case 1200: baudcmd=0xc0; break;
         default:
                 return ERROR;
         }

         i = mwa() + 0x45;

         Sport = 0xfd;
         Dport = 0xfc;
         Somask = 0x01;
         Simask = 0x02;

         outp(Sport,0xfb);        /* 8 bits, 1 stop, no parity */

         *i = (baudcmd);
         Baudrate=nbaud;
         return 0;
 }

 readbaud()
 {
         Baudrate=DEFBAUD;
 }

 /* Bye disconnects the line and allows another call */

 bye()
 {
         sleep(40/CLKMHZ);        /* wait two seconds */
         setbaud(Baudrate);
 }

 /* onhook disconnects the line for good */

 onhook()

 {}        /* no way to go on hook with this setup */

 /* online connects the line    */

 online()
 {}        /* not implemented        */

        /* Sorcerer        */

 #ifdef MONROE
 #define MODEMSTUFF
 /*
 * set baud rate for modem driven from MONROE
 */
 setbaud (nbaud)
 unsigned nbaud;
 {
         char command;
         unsigned baud,count;

         count=command=0;            /* to detect an error  */
         baud=nbaud;                    /* save for later           */



         /* Select required SIO range factor
         and also test for legal baudrates */

         switch(baud)
         {
         case(110)        :
         case(134)        :
         case(150)        :
         case(300)        :
                 command=0xce;
                 count=23437;
                 break;

         case(0600)        :
         case(1200)        :
         case(1800)        :
         case(2000)        :
         case(2400)        :
         case(3600)        :
         case(4800)        :
         case(7200)        :
         case(9600)        :
                 command=0x4e;
                 count=9375;        /* prescaling because can't handle */
                 baud/=10;        /* numbers like 1.5 million */
                 break;

         case(19200) :
                 command=0x0e;
                 count=15000;
                 baud/=100;
                 break;

         default        :
                 return ERROR;
         }

         count=(count/baud) + (((count%baud) > (baud/2)) ? 1 : 0);
                         /* divide with rounding */

         outp(Sport,04);                         /* select SIO divisor
         outp(Sport,command);

         outp(CTCPRT,0x45);
         outp(CTCPRT,count);                 /* set CTC to required count

         Baudrate=nbaud;
         return OK;
 }

 readbaud ()
 {
         Baudrate=DEFBAUD;
 }

 /* Bye disconnects the line and allows another call */
 bye ()
 {
         outp(Dport, 03);         /* send a ctrl C    */
         sleep(40/CLKMHZ);        /* wait two seconds */
         setbaud(Baudrate);
 }

 /* onhook disconnects the line for good */
 onhook ()
 {
         /* no way to go on hook with this setup */
 }

 /* online connects modem to the line */
 online ()
 {
         /* no way to go online with this setup */
 }

 /* MONROE */


 #ifdef SANYO
 #define MODEMSTUFF
 /*
 * set baud rate for modem driven from SANYO
 * Requires MBC-1000 to be jumpered for 4800 baud
 * Other software baud-rate pairs may be programmed
 * here instead of 4800 & 1200 baud. e.g. if MBC-1000
 * is programmed for 1200 baud these rates become
 * 1200 & 300 baud respectively.
 */
 setbaud (nbaud)
 unsigned nbaud;
 {

 unsigned command;

         switch (nbaud)
         {
         case(4800) : command = 0x4e; break;  /* U8251 div 16 */
         case(1200) : command = 0x4f; break;  /* U8251 div 64 */
         default           : return ERROR;
         }

         outp(Sport,0x80);        /* mode, set synch, one synch */
         outp(Sport,0x00);        /* synch */
         outp(Sport,0x00);        /* control */
         outp(Sport,0x00);        /* control */

         outp(Sport,0x40);        /* reset U8251 control */
         outp(Sport,command); /* send required command */

         outp(Sport,MI_ERROR_RESET);            /* reset all errors control */


         Baudrate=nbaud;
         return OK;
 }

 readbaud ()
 {
         Baudrate=DEFBAUD;
 }

 /* Bye disconnects the line and allows another call */
 bye ()
 {
         outp(Dport, 03);         /* send a ctrl C    */
         sleep(40/CLKMHZ);        /* wait two seconds */
         setbaud(Baudrate);
 }

 /* onhook disconnects the line for good */
 onhook ()
 {
         /* no way to go on hook with this setup */
 }

 /* online connects modem to the line */
 online ()
 {
         /* no way to go online with this setup */
 }

 /* SANYO */


 #ifdef OKI
 #define MODEMSTUFF
 /*
 * set baud rate for modem driven from Oki-if800
 */
 setbaud (nbaud)
 unsigned nbaud;
 {

 unsigned command;

         switch (nbaud)
         {
         case(110)  : command = 0; break;
         case(150)  : command = 1; break;
         case(300)  : command = 2; break;
         case(600)  : command = 3; break;
         case(1200) : command = 4; break;
         case(2400) : command = 5; break;
         case(4800) : command = 6; break;
         case(9600) : command = 7; break;
         default           : return ERROR;
         }

         outp(0x22,command);                /* Boy did I have fun finding this
                                         port number. Documents superb!!??##

 /*  Initialize the U8251 chip        */

         outp(Sport,0x80);        /* mode, set synch, one synch */
         outp(Sport,0x00);        /* synch */
         outp(Sport,0x00);        /* control */
         outp(Sport,0x00);        /* control */

         outp(Sport,0x40);        /* reset U8251 control */
         outp(Sport,0x4e);        /* send /16 8d, 1s, np */

         outp(Sport,MI_ERROR_RESET);            /* reset all errors control */


         Baudrate=nbaud;
         return OK;
 }

 readbaud ()
 {
         Baudrate=DEFBAUD;
 }

 /* Bye disconnects the line and allows another call */
 bye ()
 {
         outp(Dport, 03);         /* send a ctrl C    */
         sleep(40/CLKMHZ);        /* wait two seconds */
         setbaud(Baudrate);
 }

 /* onhook disconnects the line for good */
 onhook ()
 {
         /* no way to go on hook with this setup */
 }

 /* online connects modem to the line */
 online ()
 {
         /* no way to go online with this setup */
 }

 /* OKI */


 #ifdef U2651
 #define MODEMSTUFF
 /*
 * set baud rate for modem driven by 2651 UART
 */
 setbaud(nbaud)
 unsigned nbaud;
 {
         char command;
         char baudcmd;

         command=0;

         switch(nbaud) {
         case    50: baudcmd=  0; break;
         case    75: baudcmd=  1; break;
         case   110: baudcmd=  2; break;
         case   134: baudcmd=  3; break;
         case   150: baudcmd=  4; break;
         case   300: baudcmd=  5; break;
         case   600: baudcmd=  6; break;
         case  1200: baudcmd=  7; break;
         case  1800: baudcmd=  8; break;
         case  2000: baudcmd=  9; break;
         case  2400: baudcmd= 10; break;
         case  3600: baudcmd= 11; break;
         case  4800: baudcmd= 12; break;
         case  7200: baudcmd= 13; break;
         case  9600: baudcmd= 14; break;
         case 19200: baudcmd= 15; break;

         default:
                 return ERROR;
         }

         MODEMON
         outp(MPORT, MODE1);
         outp(MPORT, MODE2 + baudcmd);
         outp(CPORT, Commbyte);                /* just to be safe */
         Baudrate = nbaud;
         return OK;
 }

 readbaud()
 {
         char nbaud;

         MODEMON

         nbaud = inp(MPORT);                /* throw away first mode byte */
         nbaud = inp(MPORT) & 0X0F;        /* low nibble has baud rate */
         Commbyte = inp(CPORT);                /* get current command byte */

         switch(nbaud) {
         case  0: Baudrate=   50; break;
         case  1: Baudrate=   75; break;
         case  2: Baudrate=  110; break;
         case  3: Baudrate=  134; break;
         case  4: Baudrate=  150; break;
         case  5: Baudrate=  300; break;
         case  6: Baudrate=  600; break;
         case  7: Baudrate= 1200; break;
         case  8: Baudrate= 1800; break;
         case  9: Baudrate= 2000; break;
         case 10: Baudrate= 2400; break;
         case 11: Baudrate= 3600; break;
         case 12: Baudrate= 4800; break;
         case 13: Baudrate= 7200; break;
         case 14: Baudrate= 9600; break;
         case 15: Baudrate=19200; break;
         }
 }

 /* Bye disconnects the line and allows another call */
 bye()
 {
         onhook();                        /* turn of DTR */
         sleep(20/CLKMHZ);                /* wait one second */
         online();                        /* turn on DTR */
 }

 /* onhook disconnects the line for good */
 onhook()
 {
         if(Commbyte & 0x02){
                 MODEMON
                 outp(CPORT, Commbyte -= 0x02);
         }
 }

 /* online connects the modem to line */
 online()
 {
         if(!(Commbyte & 0x02)){
                 MODEMON
                 outp(CPORT, Commbyte += 0x02);
         }
 }
  /* U2651 */

 #ifdef TUART
 #define MODEMSTUFF
 /*
 * set baud rate for modem driven by Cromenco TUART
 */
 setbaud(nbaud)
 unsigned nbaud;
 {
         char command, baudcmd;
         command=0;
         switch(nbaud) {
         case   110: baudcmd=0001; break;
         case   150: baudcmd=0202; break;
         case   300: baudcmd=0204; break;
         case  1200: baudcmd=0210; break;
         case  2400: baudcmd=0220; break;
         case  4800: baudcmd=0240; break;
         case  9600: baudcmd=0300; break;
         case 19200: baudcmd=0220; command=020; break;
         case 38400: baudcmd=0240; command=020; break;
         default:
                 return ERROR;
         }
         outp(Sport, baudcmd);
         outp(Sport+2, command);
         Baudrate=nbaud;
         return 0;
 }
 readbaud()
 {
         Baudrate=DEFBAUD;
 }

 /* Bye disconnects the line and allows another call */
 bye()
 {
         outp(Sport+2, 03);        /* turn on break */
         sleep(40/CLKMHZ);        /* wait two seconds */
         setbaud(Baudrate);
 }

 /* onhook disconnects the line for good */
 onhook()
 {}        /* no way to go on hook with this setup */
 /* TUART */

 #ifdef Z89
 #define MODEMSTUFF
 /*
 * Routine to set baud rate for 8250 driven modem port
 */
 setbaud(nbaud)
 unsigned nbaud;
 {
         unsigned bcmd;

         if(nbaud==0)
                 return ERROR;
         bcmd= 57600;                /* 1.8432 Mhz clock */
         bcmd /= (nbaud/2);        /* this must be done unsigned! */
         outp(Dport+3, 0203);    /* enable divisor latch */
         outp(Dport, bcmd);
         outp(Dport+1, (bcmd>>8));

         /* 8 data bits, 1 stop bit (2 if 110 baud), disable divisor latch */

         outp(Dport+3, nbaud==110? 07:03);

         /* turn on dtr and rts, also output2 is baudrate is 1200 or more */

         outp(Dport+4, nbaud>=1200?017:03);
         Baudrate=nbaud;
 /*
         printf("bcmd=%d bcmdms=0%o bcmdls=0%o\n",bcmd,(bcmd>>8),(bcmd&0377));
 */
         return OK;
 }
 /* fetch the baudrate from the modem port */
 readbaud()
 {
         char dp3;
         unsigned div;

         dp3=inp(Dport+3);
         outp(Dport+3, 0200|dp3);
         div= inp(Dport) | (inp(Dport+1)<<8);        /* fetch divisor */
         outp(Dport+3, dp3);                        /* restore uart modes */
         Baudrate=57600;                        /* be sure all this remains un
         Baudrate /= div;
         Baudrate <<= 1;
 }

 /* Bye hangs up the line and then resets for another call */
 bye()
 {
         onhook();
         sleep(40/CLKMHZ);
         setbaud(Baudrate);
 }

 /* onhook goes off line for good */
 onhook()
 {
         outp(Dport+4, 0);
 }

 /* Z89 (8250) */

 #ifdef TRSII
 #define MODEMSTUFF
 /*
  * set baud rate for modem driven by TRS 80 MOD II with Pickles & Trout CP/M
  */
 setbaud(nbaud)
 unsigned nbaud;
 {
         char calla(), command, baudcmd, regB, regC, regD, regE, regH, regL;
         command=0;
         switch(nbaud) {
         case   110: baudcmd=0; break;
         case   150: baudcmd=2; break;
         case   300: baudcmd=3; break;
         case   600: baudcmd=4; break;
         case  1200: baudcmd=5; break;
         case  2400: baudcmd=6; break;
         case  4800: baudcmd=7; break;
         case  9600: baudcmd=8; break;
         default:
                 return ERROR;
         }

         regB = 0;                /* setup  serial ports */
         regC = 0;                /* port a, parity odd and disabled */
         regD = 0xe6;                /* DTR,RTS high, 8-bit wds, 1 stop */
         regE = baudcmd;                /* baud rate */
         regH = 19;                /* Xmit off char */
         regL = 17;                /* Xmit on-off handshaking; X-on char */
         calla(0x40,0,(regH << 8 | regL),(regB << 8 | regC),
                         (regD << 8 | regE));   /* call P&T special function *
         Baudrate=nbaud;
         return 0;
 }

 readbaud()
 {
         Baudrate=DEFBAUD;
 }

 /* Bye disconnects the line and allows another call */
 bye()
 {
         onhook();
         sleep(40/CLKMHZ);        /* wait two seconds */
         setbaud(Baudrate);
 }

 /* onhook disconnects the line for good */
 onhook()
 {
         char calla();
         calla(0x40,0,0,0x40,0);        /* set DTR, RTS low */
 }
 /* TRSII */

 #ifdef 8251
 #define MODEMSTUFF

 setbaud()
 {}                /* Baud rate set in hardware on many 8251 implemenetations

 onhook()
 {}                /* No way to set onhook on many 8251 implementations */

 online()
 {}                /* No way to set off hook on many 8251 implementations */

 bye()
 {}                /* No way to drop line on many 8251 implementtations */

 readbaud()
 {
         Baudrate=DEFBAUD;        /* Set to default baudrate */
 }

 /* 8251 */

 #ifndef MODEMSTUFF
 setbaud()
 {}        /* INSERT ROUTINE HERE IF AVAILABLE */
 onhook()
 {}        /* INSERT ROUTINE HERE IF AVAILABLE */
 online()
 {}        /* INSERT ROUTINE HERE IF AVAILABLE */
 bye()
 {}        /* INSERT ROUTINE HERE IF AVAILABLE */
 readbaud()
 {
         Baudrate=DEFBAUD;
 }
 /* !MODEMSTUFF */

 /*
  * Readline from MODEM13.C rewritten to allow much higher
  * baud rates.
  * Timeout is in deciseconds (1/10th's)
  * For top speed, character ready is checked in many places.
  * returns TIMEOUT if kbd character is ready.
  *
  * There are three versions of readline, the first is used if
  * there is a separate register for error conditions. The second
  * is used if error condx are in the same register asrx data ready.
  * The last, and quickest, does not check error conditions.
  */
 #ifdef MIERROR
 /* version for separate error register. NOT TESTED */
 readline(decisecs)

 int decissecs;

 {
         if(MIREADY) {
                 if(MIERROR)
                         goto fubar;
                 else
                         return MICHAR;
         }
         while(--decisecs>=0) {
                 if(MIREADY) {
                         if(MIERROR)
                                 goto fubar;
                         else
                                 return MICHAR;
                 }

 #ifdef CDO
                 if(CDO)
                         return TIMEOUT;
 #endif
                 if(CIREADY) {
                         CICHAR;                /* dismiss character */
                         return TIMEOUT;
                 }
                 for(Timeout=T1pause; --Timeout; )
                         if(MIREADY) {
                                 if(MIERROR)
                                         goto fubar;
                                 else
                                         return MICHAR;
                         }
         }
         return TIMEOUT;
 fubar:
         MICHAR;                /* throw the turkey away */
         MI_ERROR_RESET;
         return ERROR;
 }

 #define READLINE
 /* MIERROR */

 #ifdef MIREADYERROR
 /* Version for 8250, 8251, 2651, etc. with all bits in one register */
 readline(decisecs)

 int decisecs;

 {
         MODEMON
         if((Mstatus=inp(Sport))&MIREADYMASK)
                 goto getit;
         while(--decisecs>=0) {
                 if((Mstatus=inp(Sport))&MIREADYMASK)
                         goto getit;
 #ifdef CDO
                 if(CDO)
                         return TIMEOUT;
 /* CDO */
                 if((Mstatus=inp(Sport))&MIREADYMASK)
                         goto getit;
                 CONSOLON
                 if(CIREADY) {
                         CICHAR;                /* dismiss character */
                         return TIMEOUT;
                 }
                 MODEMON
                 if((Mstatus=inp(Sport))&MIREADYMASK)
                         goto getit;
                 for(Timeout=T1pause; --Timeout; )
                         if((Mstatus=inp(Sport))&MIREADYMASK) {
 getit:
                                 if(Mstatus&MIERRORMASK) {
                                         modreset();        /* reset error bit
                                         Mstatus &= MIERRORMASK;
                                         return ERROR;
                                 }
                                 else
                                         return MICHAR;
                         }
         }
         return TIMEOUT;
 }

 modreset()

 {
 #ifdef CPORT

         if(!(Commbyte & MI_ERROR_RESET)){
                 outp(CPORT, (Commbyte += MI_ERROR_RESET)); /* reset error */
         }
         else{
                 outp(CPORT, Commbyte);
         }
         outp(CPORT, (Commbyte -= MI_ERROR_RESET));        /* clear reset */

 /* CPORT */

 #ifdef MI_ERROR_RESET

         outp(Sport,MI_ERROR_RESET);                /* clear error on U8251

 /* MI_ERROR_RESET */

 /* CPORT */

         MICHAR;                                        /* throw away bad char
 }

 #define READLINE

 /* MIREADYERROR */

 #ifndef READLINE
 readline(decisecs)

 int decisecs;

 {
         MODEMON
         if(MIREADY)
                 return MICHAR;
         while(--decisecs>=0) {
                 if(MIREADY)
                         return MICHAR;
                 CONSOLON
                 if(CIREADY) {
                         CICHAR;                /* dismiss character */
                         return TIMEOUT;
                 }

                 MODEMON
                 if(MIREADY)
                         return MICHAR;
                 for(Timeout=T1pause; --Timeout; )
                         if(MIREADY)
                                 return MICHAR;
         }
         return TIMEOUT;
 }
 /* !READLINE */

 sendline(data)
 char data;

 {
         int        n;
         n = Tpause;        /* don't wait all day, 0.5 sec will do */

         MODEMON
         while(!MOREADY && n--)
                 ;
         MODATA(data);
 }

 purgeline()

 {
         MODEMON
         while(MIREADY)
                 MICHAR;
 }

 /* default "autodial" routine */
 #ifndef AUTODIAL
 dial(name)
 char *name;

 {
         char *s;
         if((s=cisubstr(name, "\tb")))
                 if(!setbaud(atoi(s+2)))
                         printf("Baudrate set to %u: ", Baudrate);
         printf("%s\n", name);
         return OK;
 }
 /* !AUTODIAL */


 linetest (n)
 int n;

 {
         int x,e;
         int c;
         char lstc;

         srand(n);
         printf(" Line test at %d Baud\n",Baudrate);
         CONSOLON
         while (CIREADY)
                 CICHAR;
         purgeline();
         for (e=0;--n;) {
                 if (moment(KTIME))
                         break;
                 lstc = rand();
                 sendline(lstc);
                 c = readline(10);

                 if (c == TIMEOUT)
                         printf("\nTimeout error");
                 else {
                         if (c==lstc)
                                 putchar('.');
                         else {
                                 e++;
                                 putchar('*');
                                 readline(10);
                         }

                         if (!(n&63))
                         putchar('\n');
                 }
         }
         printf("\n %d Errors detected\n",e);
 }

 loop (n)    /* loop back mode for doing line tests */
 int n;

 {
         CONSOLON
         while (CIREADY)
                 CICHAR;
         printf("Line looped, Hit any key to exit\n");
         while (!moment(KTIME) && --n) {
                 sendline( readline(10));
                 (n&63) ? putchar('.') : putchar('\n');
         }
         putch('\n');
 }

 /* end of YAM5.C  */


 YAM7.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YAM\YAM7.C

 /*
 >>:yam7.c 04-Mar-84 (diff 08-11-81)
  * Logfile sprinf fixed to write correct length record
  * closerx fixed so as not to pad a file abnormal due to write errors
  * File open and close stuff and more ...
  * This file assumes operation on a CP/M system
  */

 #include <YAM.H>

 /* dpb dph blocks from CP/M Interface Guide Sect 6.5 */

 struct dpb {        /* CP/M Version 2 Disk Parameter Block */
         unsigned dpb_spt;        /* sectors per track */
         char dpb_bsh;                /* block shift factor */
         char dpb_blm;
         char dpb_exm;                /* Extent Mask */
         unsigned dpb_dsm;        /* Highest block number on this disk */
         unsigned dpb_drm;        /* total number of directory entries -1 */
         unsigned dpb_al;        /* bit field corresponding to direc blocks */
         unsigned dpb_cks;        /* size of the directory check vector */
         unsigned dpb_off;        /* number of reserved tracks on this disk */
 };

 char *call();

 struct dph {        /* CP/M Version 2 Disk Parameter Header */
         char **dph_xlt;                /* logical to physical xlat vector */
         int dph_ooo;
         char *dph_dirbuf;        /* 128 byte scratchpad for directory use */
         struct dpb *dph_dpb;        /* disk param block for this type of disk
         char **dph_csv;                /* scratch area for detecting changed
         char *dph_alv;                /* pointer to bit vector alloc map for
 };

 struct fcb {        /* CP/M Version 2 fcb AS SEEN BY THE USER */
         char        dr;                /* drive number */
         char        fname[8];        /* fname[1] used by TAG2 */
         char        ftype[3];        /* ftype[1] 8th bit set for $SYS */
         char        ex;                /* file extent normally 0 */
         char        s1;                /* reserved for bdos's benefit */
         char        s2;                /* likewise, =0 on call to open,make,s
         char        rc;                /* record count for extent[ex]  0...12
         char        dmap[16];
         char        cr;                /* current record, initialized to 0 by
         unsigned recn;                /* highest record number */
         char        recovf;                /* overflow of above */
 };

 /* following are BIOS calls */
 CONST 2                        /* bios console char ready */
 CONIN 3                        /* bios cons char input */
 CONOUT 4                /* bios cons char output */

 /* following are BDOS calls */
 BDOS 5                        /* address used to call bdos */
 SELDSK 14                /* bdos select disk 0=default disk */
 SRCH 17                 /* bdos search for file pattern*/
 SRCHNXT 18                /* search for next occurrence */
 GETDEFDISK 25                /* get current disk  (0-15) */
 SETDMA 26                /* set address for read, write, etc. */
 GETALLOCP 27                /* get address of allocation vector */
 SETATTRIB 30                /* update file attributes */
 GETDPBP 31                /* get DPB address for disk */
 SETGETUSER 32                /* set or get user number */
 COMPFILSIZ 35                /* compute file size into recn and recovf */
 UFNSIZE 15                /* a:foobar12.urk\0 is 15 chars */

 openrx(name)
 char *name;
 {

 #ifdef RESTRICTED
         char *s;
         if(s=cisubstr(name, ".com"))        /* upload .com files as .obj */
                 strcpy(s, ".OBJ");
         if(cisubstr(name, "$$$"))
                 return ERROR;                /* don't allow upload of $$$.sub
         for(s=name; *s; )
                 if(*s++ > 'z')
                         return ERROR;        /* no garbage names please */
 #endif
         unspace(name);
         lprintf("'%s' ", name);                /* show the name right away */
         if(!Creamfile && fopen(name, fout) != ERROR) {
                 fclose(fout);
                 printf("Exists ", name);
 #ifdef XMODEM
                 return ERROR;
 #else
                 printf("Replace it (y/n)??");
                 if(tolower(getchar())!= 'y')
                         return ERROR;
 #endif
         }
         if(fcreat(name, fout)==ERROR){
                 printf("Can't create %s\n", name);
                 return ERROR;
         }
         Rfile= TRUE;
         strcpy(Rname, name);
         Dumping= !Squelch;
         lprintf("Created%s\n", Dumping? "" : " recording OFF");
         return OK;
 }

 closerx(pad)
 {
         if(Rfile) {
                 if(!Quiet)
                         lpstat("Closing %s", Rname);
 #ifdef BDSC
                 if(pad && (fout._nleft != ERROR))
                 /* only if requested, and file not error aborted */
                         do
                                 putc(CPMEOF, fout);
                                 while(fout._nleft % SECSIZ);
 #endif
                 fflush(fout);
                 fclose(fout);
                 Rfile=FALSE;
 #ifdef LOGFILE
                 logfile(Rname, pad?'*':'R');        /* record file xmsn */
 #endif
         }
 }

 opentx(name)
 char *name;
 {
         int printf();
 #ifdef XMODEM
         int lprintf();
 #endif
         struct fcb *fp, *fcbaddr();
         int (*fnx)();
 #ifndef CDOS
         unsigned spm, dminutes;
         struct fcb fstat;
         spm= Baudrate/23;
 #endif
 #ifdef XMODEM
         fnx=Batch? lprintf : printf;
 #else
         fnx=printf;
 #endif
         (*fnx)("'%s' ", name);
         unspace(name);


         if(fopen(name, fin)==ERROR){
                 printf("Can't open %s\n", name);
                 return ERROR;
         }
 #ifdef RESTRICTED
         if(cisubstr(name, ".bad")
          || (fp=fcbaddr(fin._fd))==ERROR
          || (fp->fname[1] & 0200)        /* tag2 */
          || (fp->ftype[1] & 0200)        /* $SYS */
          ) {
                 fclose(fin); printf("\n'%s' Not for Distribution\n", name);
                 return ERROR;
         }
 #endif
         Tfile= TRUE;
         strcpy(Tname, name);
 #ifndef CDOS
         setfcb( &fstat, name);
         bdos(COMPFILSIZ, &fstat);
         dminutes= 1+((10*(1+fstat.recn))/spm)+(fstat.recn/20);
         (*fnx)("Open %u Sectors %u.%u Minutes\n",
           fstat.recn, dminutes/10, dminutes%10);
 #else
         (*fnx)("Open\n");
 #endif
         return OK;
 }

 /* closetx(status) call with status != 0 if incomplete file xmsn */
 closetx(status)
 {
         if(Tfile) {
                 fclose(fin);
                 if(!Quiet)
                         lpstat("%s closed", Tname);
 #ifdef LOGFILE
                 if(!status)
                         logfile(Tname, 's');                /* record file xm
 #endif
                 Tfile=FALSE;
         }
 }
 /* search the phone file for name */
 getphone(name, buffer)
 char *name, *buffer;
 {
         closetx(TRUE);

         if(fopen(PHONES, fin)==ERROR) {
                 printf("Cannot open %s\n", PHONES);
                 return ERROR;
         } else {
                 while(fgets(buffer, fin))
                         if(cmdeq(buffer, name)) {
                                 fclose(fin);
                                 return OK;
                         }
         }
         printf("Can't find data for %s\n", name);
         fclose(fin);
         return ERROR;
 }

 /* change default disk and optionally, user number */
 chdir(p)
 char *p;
 {
         unsigned newuser;

         if(Rfile||Tfile) {
                 printf("Must close files first\n");
                 return ERROR;
         }
         newuser=user; *p=toupper(*p);
         if(index(*p, DISKS)) {
                 defdisk= *p - 'A';
                 bdos(SELDSK, defdisk);
 #ifdef CDOS
                 return OK;
 #else
                 printdfr();
                 if(!isdigit(p[1]))
                         return;
                 if((newuser=atoi(p+1)) <= MAXUSER) {
                         bdos(SETGETUSER, newuser);
                         user=newuser;
                         return OK;
                 }
 #endif
         }
         printf("Disk %c and/or User %d Illegal\n", *p, newuser);
         return ERROR;
 }

 /* fetch default disk and user number */
 initdd()
 {
         Secpblk=SECPBLK;
         defdisk= bdos(GETDEFDISK,0);
 #ifdef CDOS
         user=0;
 #else
         user=bdos(SETGETUSER, 0377);
 #endif
 }

 dolist(argc, argp)
 char **argp;

 {
         int listfile();
 #ifdef XMODEM
         printf("^S pauses, ^K skips to next file, ^X terminates\n");
 #endif
         expand(listfile, argc, argp);
         putch('\n');
 }

 listfile(name)
 char *name;

 {
         char *p;
         int c,d;

 #ifdef XMODEM
         printf("\nListing '%s'\n\022", name);
 #endif
         closetx(TRUE);
         if(opentx(name)==ERROR)
                 return ERROR;
 #ifdef USQ
         if((c=getw(fin))==RECOGNIZE)
                 c=unsqueeze();
         else if(c != ERROR) {
                 putcty(c);
                 putcty(c>>8);        /* pdp-11 sequence */
 #else
         else {
 #endif
                 while((c=getc(fin))!=EOF && c != CPMEOF) {
                         if( !(c=putcty(c)))
                                 continue;
                         if(c == CNTRLC || c == CAN || c == CNTRLK) {
                                 break;
                         }
                 }
         }
         if(c != CPMEOF)
                 putchar('\n');
         /* record complete xmsn iff terminated by (CPM)EOF */
         closetx(c != CPMEOF);
 #ifdef XMODEM
         sendline(024);        /* squelch in case user downloading */
 #endif
         /* cancel rest of files if ^C or ^X */
         if(c == CNTRLC || c == CAN)
                 return ERROR;
         else
                 return OK;
 }

 /* fill buf with count chars padding with ^Z for CPM */
 filbuf(buf, count)
 char *buf;
 {
         register c, m;
         m=count;
         while((c=getc(fin))!=EOF) {
                 *buf++ =c;
                 if(--m == 0)
                         break;
         }
         if(m==count)
                 return 0;
         else
                 while(--m>=0)
                         *buf++ = 032;
         return count;
 }

 dodir(argc, argp)
 char **argp;
 {
         int pdirent();
         cfast=0;                /* counter for 4 across format */
         expand(pdirent, argc, argp);
 #ifndef CDOS
         putch('\n');
         printdfr();
 #endif
 }

 pdirent(name)
 {
         printf("%-14s%c", name, (++cfast%DIRCOLS)?' ':'\n');
 }
 #ifndef CDOS
 /* docomp does a directory listing showing sectors for each matched file
  * and computes total transmission time of matched files in batch mode
  * time is sum of:
  *         number of files * open/close time (assumed 5 seconds)
  *        time to xmit and ACK each sector assuming no path delay or error
  *        disk i/o time at each end, not dependent on baud rate
  */
 docomp(argc,argp)
 char **argp;
 {
         unsigned compsecs();
         unsigned spm;        /* sectors per minute-baud */
         unsigned dminutes;        /* tenths of minutes */
         cfast=Numsecs=Numblks=0;
         expand(compsecs, argc, argp);
         /* (Baudrate*60)/(10 bits each char * 136 chars) */
         spm= Baudrate/23;
         dminutes= Numfiles+((10*(Numfiles+Numsecs))/spm)+(Numsecs/20);
         printf("\n%u Files %u Blocks %u K\n",
           Numfiles, Numblks, (Numblks*(Secpblk/8)));
         printf("%u Sectors %u.%u Minutes Xmsn Time at %u Baud\n",
           Numsecs, dminutes/10, dminutes%10, Baudrate);

 }
 /* add file length (in CP/M 128 byte records) to Numsecs */
 unsigned compsecs(ufn)
 char *ufn;
 {
         struct fcb fstat;
         printf("%-14s", ufn);
         unspace(ufn);
         setfcb( &fstat, ufn);
         bdos(COMPFILSIZ, &fstat);
         Numsecs += fstat.recn;
         Numblks += (fstat.recn+Secpblk)/Secpblk;
         printf("%4u%c",fstat.recn, (++cfast%DIRCOLS)?' ':'\n');
         return fstat.recn;
 }
 #endif

 expand(fnx, argc, argp)
 int (*fnx)();
 char **argp;
 {
         char name[PATHLEN], *s;
         Numfiles=0;

         if(argc<=0)
                 return e1xpand(fnx, "*.*");
         else
                 while(--argc>=0) {
                         /* change b: to b:*.*  */
                         strcpy(name, *argp++);
                         if((s=index(':', name)) && *++s == 0)
                                 strcpy(s, "*.*");
                         if(e1xpand(fnx, name)==ERROR)
                                 return ERROR;
                 }
         return OK;
 }

 /*
  * e1xpand expands ambiguous pathname afnp
  * calling fnx for each.
  * Modified from: Parameter list builder by Richard Greenlaw
  *                251 Colony Ct. Gahanna, Ohio 43230
  */
 e1xpand(fnx, afnp)
 int (*fnx)();
 char *afnp;        /* possible ambiguous file name*/
 {
         struct fcb sfcb, *pfcb;
         FLAG first;
         char *p, *q, i, byteaddr;
         int filecount, m;
         char tbuf[SECSIZ];
         struct {
                 char xYxx[UFNSIZE];                /* unambiguous file name *
         } *fp;
         int strcmp();


         /* build CPM fcb   */
         unspace(afnp);
         if(setfcb(&sfcb, afnp) == ERROR) {
                 printf("%s is bad pattern\n", afnp);
                 return ERROR;
         }

         if(Wrapped || (bufend-bufcq)<2048) {
                 dumprxbuff();                /* I need the space for building
                 clearbuff();                /* so the printer won't try to li
                 bufmark=bufst;
         } else
                 bufmark=bufcq;

         /* Search disk directory for all ufns which match afn*/
         for(fp=bufmark,filecount=0,first=TRUE;; fp++,filecount++) {
 tryanother:
                 bdos(SETDMA, tbuf);
                 /* seems CP/M outta know whether to use SRCH or SRCHNXT !! */
                 byteaddr=bdos(first? SRCH:SRCHNXT, &sfcb); first=FALSE;
                 if(byteaddr==255)
                         break;
                 /* calculate pointer to filename fcb returned by bdos */
                 pfcb = (tbuf + 32 * (byteaddr % 4));
 #ifdef RESTRICTED
                 /* check for $SYS or tag bit on 2nd byte of filename (TAG2) *
                 if((pfcb->fname[1]&0200) ||(pfcb->ftype[1]&0200))
                         goto tryanother;
 #else
                 /* check for $SYS with Sysfil flag */
                 if((pfcb->ftype[1]&0200) && !Sysfil)
                         goto tryanother;
 #endif

                 Numfiles++;
                 p = fp;
                 if(fp>bufend) {        /* Note: assumes some slop after bufen
                         printf("Out of Memory for pathname expansion\n");
                         return ERROR;
                 }
                 if(*(afnp+1) == ':') {
                         /* Drive spec.*/
                         *p++ = *afnp;
                         *p++ = ':';
                 }

                 /*Copy filename from directory*/
                 q = pfcb;
                 for(i =8; i; --i)
                         *p++ = (0177& *++q);
                 *p++ = '.' ;

                 /*Copy file extent*/
                 for(i = 3; i; --i)
                         *p++ = (0177& *++q);
                 *p = '\0' ;

         }
         if(filecount==0) {
                 printf("'%s' NOT FOUND\n", afnp);
                 return ERROR;
         }

         qsort(bufmark, filecount, UFNSIZE, strcmp);

         for(fp=bufmark; --filecount>=0;) {
                 p=fp++;
                 /* execute desired function with real pathname */
                 if((*fnx)(p)==ERROR)
                         return ERROR;
         }
         return OK;
 }

 /*
  * cisubstr(string, token) searches for lower case token in string s
  * returns pointer to token within string if found, NULL otherwise
  */
 char *cisubstr(s, t)
 char *s,*t;
 {
         char *ss,*tt;
         /* search for first char of token */
         for(ss=s; *s; s++)
                 if(tolower(*s)==*t)
                         /* compare token with substring */
                         for(ss=s,tt=t; ;) {
                                 if(*tt==0)
                                         return s;
                                 if(tolower(*ss++) != *tt++)
                                         break;
                         }
         return NULL;
 }

 /* copy string s onto itself deleting spaces "hello there" > "hellothere" */
 unspace(s)
 char *s;
 {
         char *p;
         for(p=s; *s; s++)
                 if(*s != ' ')
                         *p++ = *s;
         *p++ =0;
 }

 #ifdef LOGFILE
 /*
  * logfile keeps a record of files transmitted.
  * Mode is 's' for send file, 'r' for receive file, 't' for type file
  * Lifted from xcmodem by J. Wierda, R. Hart, and W. Earnest
 */

 RPB 4        /* log records per buffer */
 LRL 32        /* logical rec length LRL*RPB == SECSIZ */

 logfile(name, mode)
 char *name;
 char mode;
 {
         struct fcb *fcbaddr(), *fp;
         int fd, rnum, bnum, thedisk;
         char *i, *lrec, lbuf[SECSIZ+2];
         char date_str[6], time_str[6];

         /* find out what disk was used */

         thedisk = defdisk + 'a';
         if(i = index(':', name)) {
                 thedisk = *name;
                 name = ++i;
         }
         bdos(SETGETUSER, 0);        /* get it from user 0 */
         fd = open(LOGFILE,2);
         if(fd == ERROR) {        /* if file absent, create and initialize it
                 fd = creat(LOGFILE);
                 if(fd == ERROR)
                         return;
                 else {
                         rnum=1;
                         fp = fcbaddr(fd);
                         fp->fname[1] |= 0200;        /* set TAG2 bit */
                         fp->ftype[1] |= 0200;        /* set SYS bit */
                         bdos(SETATTRIB, fp);        /* and update attributes
                 }
         }
         else {
                 read(fd, lbuf, 1);
                 rnum = atoi(lbuf)+1;
         }
         setmem(lbuf, SECSIZ, 0);
         sprintf(lbuf, "%d\r\n", rnum);
         seek(fd,0,0);
         write(fd, lbuf, 1);                /* update last record number */
         bnum = rnum/RPB;
         rnum = (rnum%RPB)*LRL;
         seek(fd, bnum, 0);
         if(rnum == 0)
                 setmem(lbuf, SECSIZ, 0);
         else
                 read(fd, lbuf, 1);
         if (time(time_str)){
                 sprintf(time_str,"fill");
         }
         if (date(date_str)){
                 sprintf(date_str,"");
         }
         sprintf(&lbuf[rnum], "\r\n%c        %c%02d        %-12s        %5s
          mode, thedisk, user, name, time_str, date_str);
         seek(fd, bnum, 0);
         write(fd,lbuf,1);
         close(fd);
         bdos(SETGETUSER, user);
 }

 #ifdef LOGCLOCK

 #include <CLOCK.H>

 /* Real time system clock functions

    Extracted from DATEDEMO.C

    By Bill Bolton,
    Software Tools,
    P.O. Box 80,
    Newport Beach,
    NSW, 2106,
    AUSTRALIA

    Source Address TCY-396
    Phone (+61 2) 997-1018

    Version 1.1 for Godbout Systsem Support 1 clock 19/1/82

         char        date_str[5];        /* string (character array) for date
         char        time_str[5];        /* string for time */
         date(srt) will fill a string with date formatted as follows:

         "11/5" (in Eurodate format)
 */

 date(str)

 char        *str;                /* pointer to date string */

 {
         int        month[1];        /* month of the year, range 1 to 12 */
         int        mday[1];        /* day of the current month, range 0 to 31

         if (get_date(month,mday)){
                 return(-1);
         }
         sprintf(str,"%d/%d",*mday,*month);
         return(0);
 }

 /* get_date(month,mday) provides the basic data for formatting
    a date string, fetched from the clock board and converted to a useable
    set of values */

 int get_date(month,mday)

 int        *month;                /* pointer to current month */
 int        *mday;                /* pointer to day of the month */

 {
         if (inp(CDATA) == 0XFF )      /* no clock board present */
                 return(-1);
         *month = ((read_digit(MONTH10) & 1) * 10) + read_digit(MONTH1);
         *mday = ((read_digit(DAY10) & 3) * 10) + read_digit(DAY1);
         outp(CLKCMD,0);
         return(0);
 }


 int read_digit(address)

 int        address;

 {
         int        instruct;

         instruct = address + CREAD;
         outp(CLKCMD,instruct);
         return (inp(CDATA));
 }

 /* time(str,format) fills a string with the time of day in the
    following format :

                 18:00
 */

 time(str)

 char        *str;                /* string to fill with time */

 {
         int        t[4];

         if (read_clock(t)){
                 return(-1);
         }
         sprintf(str,"%d%d:%d%d",t[0],t[1],t[2],t[3]);
         return(0);
 }

 /* read_clock(t) fills an array with the time of day digits read from
    the clock board
 */

 int read_clock(t)

 int        *t;                /* array to store clock digits */

 {
         int        ptr;        /* pointer into digit array */

         if (inp(CDATA) == 0XFF )        /* no clock board present */
                 return(-1);
         t[0] = (read_digit(HOUR10) & 3);
         t[1] = read_digit(HOUR1);
         t[2] = (read_digit(MIN10) & 7);
         t[3] = read_digit(MIN1);
         outp(CLKCMD,0);
         return(0);
 }

 /* LOGCLOCK */

 time(str)
 char *str;

 {
         return(-1);
 }

 date(str)
 char *str;

 {
         return(-1);
 }

 /* LOGCLOCK */

 /* LOGFILE */


 docrck(argc, argp)
 char **argp;
 {
         int crckfile();

         expand(crckfile, argc, argp);
 }

 /* Accumulate and print a "crck" for a file */
 crckfile(name)
 char *name;
 {
         unsigned crck();
         char crbuf[SECSIZ]; int fd,st;

         printf("%14s ", name); unspace(name);
         if((fd=open(name, 0))==ERROR)
                 return ERROR;

         oldcrc=0;
         while((st=read(fd, crbuf, 1)) ==1)
                         oldcrc=crck(crbuf, SECSIZ, oldcrc);
         close(fd);
         if(st != 0)
                 printf("READ ERROR\n");
         else
                 printf("CRCK= %04x\n", oldcrc);
         return OK;
 }

 /* print number of free blocks on default disk */
 printdfr()
 {
         struct dpb *dp;

         dp=call(BDOS, 0, 0, GETDPBP, defdisk);
         Secpblk= 1 << dp->dpb_bsh;
         printf("%u kb Free on %c\n", getfree(defdisk), defdisk+'A');
 }

 /* return total free kilobytes of disk */
 unsigned getfree(disk)
 {
         struct dpb *dp;
         /* unsigned */ char v, c, *s;
         unsigned total, count;

         bdos(SELDSK, disk);
         dp=call(BDOS, 0, 0, GETDPBP, disk);
         s=call(BDOS, 0, 0, GETALLOCP, disk);
         total=0;
         count=dp->dpb_dsm+1;
         for(;;) {
                 v= *s++;
                 for(c=0200; c; c>>=1) {
                         if((v & c)==0)
                                 ++total;
                         if(--count ==0) {
                                 bdos(SELDSK, defdisk);
                                 return total << dp->dpb_bsh-3;
                         }
                 }
         }
 }

 doerase(argc, argp)
 char **argp;
 {
         int erasefile();
         expand(erasefile, argc, argp);
 #ifndef CDOS
         printdfr();
 #endif
 }

 erasefile(ufn)
 char *ufn;
 {
         register c;
         unspace(ufn);
         printf("Erase %s (y/n/q)? ",ufn);
         c=getchar();
         putchar('\n');
         if(tolower(c)=='y')
                 unlink(ufn);
         else if(tolower(c)=='n')
                 return FALSE;
         else
                 return ERROR;
         return FALSE;
 }

 /* end of YAM7.C */


 YEARCAL.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\ZED\YEARCAL\YEARCAL.C

 /********************************************************************
 **  YEARCAL.C   v0.01Td     Copyright (c) 1987, 1988 by Paul M. Sittler.
 **  All rights reserved.  The copyright owner hereby authorizes the
 **  no-charge, noncommercial making and/or distribution of copies of
 **  the entirety of this work unchanged and unincorporated in any
 **  other work (except "LiBRary" or "ARChive" disk files for the sole
 **  purpose of no-charge noncommercial distribution).  No other
 **  reproduction or use is authorized without the express prior
 **  written consent of the copyright owner.
 **
 **  Once upon a time, in a kingdom far away, people shared source
 **  code and many of us benefited from the sharing.  This silly
 **  little program is here presented with source in hopes that it may
 **  stimulate the renewed sharing of our efforts.
 **
 **  I am open to comment, suggestions for enhancements, and bug
 **  reports.
 **
 **  Paul M. Sittler
 **  1106 Berkeley Drive
 **  College Station, TX 77840
 **
 **  Modem (409) 764-0056 300/1200/2400 baud 24 hours/day
 **  My Word #2 Fido 117/1
 **  GENie User mail address P.M.SITTLER
 **
 **  Modified for Borland's Turbo-C
 **  26 August 1987 <pms>
 **
 **  Modified for Workaround for Borland's Turbo-C bug on % Operator
 **  Replaced calls to scanf with get_int routine.
 **  10 September 1987 <pms>
 **
 **  Modified to produce a "Programmer's" Calendar, which can
 **  display dates in Octal or Hexadecimal numbering.
 **  11 September 1987 <pms>
 **
 **  Modified to produce calendars in any of 14 different languages
 **  at user's option
 **  18 September 1987 <pms>
 **
 **  Modified to create a Julian date calendar.
 **  Modified to add support for Afrikaans language.
 **  29 September 1987 <pms>
 **
 **  Modified to add support for Korean language.
 **  Modified Julian date calendar to skip a line every five.
 **  Rewrote menu for language selection to save space.
 **  14 October 1987 <pms>
 **
 **  Added Daily and Weekly Scheduling sheets.  User may choose beginning
 **  hour for scheduling.
 **  16 October 1987 <pms>
 **
 **  Fixed Daily and Weekly scheduling sheets.
 **  Added ability to select number of hours to schedule, program
 **  adapts the page for it.
 **  25 October 1987 <pms>
 **
 **  Added Monthly Calendar.
 **  Added ability to specify number of lines and columns on a page for
 **  file and printer output.  Modified filename routines to shorten
 **  program slightly.
 **  31 October 1987 <pms>
 **
 **  Added title lines that include the last month and next month
 **  calendars and two user-defined title lines.  Rewrote the
 **  program to calculate three years worth of calendars for each
 **  year so that previous month's calendars can be displayed even
 **  when they are last years.  Added Programmers calendar option
 **  to the monthly, daily, and weekly schedule options.
 **  Made defaults firm or sticky, such that once user selects one,
 **  it stays the same while running program.
 **  1 November 1987 <pms>
 **
 **  Added Czechoslovakian Language Support thanks to Briggs Myrick.
 **  3 January 1988 <pms>
 **
 **  Default Page width changed to 80 cols from 85.
 **  Maximum Page width increased to 270 from 200 for 20 CPI on 13.5".
 **  5 January 1988 <pms>
 **  Added optional pause at end of each printed page defaulted off.
 **  Added a C/R after the FF at the end of a page so that dot matrix
 **  printers like Epson will process FF without buffering it.
 **  Added 3rd, 7th and 8th user-defined title lines.  Explained that Titles
 **  #4-#6 are used for dates.  Explained how to remove a title.
 **  8 January 1988 <pms>
 **  Changed "Marz" to "Maerz" per Brief von Ed Braaten, and "Rizen" to "Rijen
 **  on recommendation of Dr. Skrabanek.
 **  22 January 1988 <pms>
 **  Allow user to specify "Left Margin indent (spaces) ?"
 **  Make customized defaults "permanent" by writing them at end of .EXE file.
 **  Tnx to Alan Holub in C-Chest, DDJ, Feb 1988 4 February 1988 <pms>
 **  Someday, the following additions. . .
 **  Optional IBM/Epson graphic character set for printers/IBM screens.
 **  ?? February 1988 <pms>
 **************************************************************/

 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <conio.h>
 #include <ctype.h>
 <dos.h>        /* DOS-specific file from Borland */
 #include <fcntl.h>
 #include <io.h>
 #include <process.h>
 #include <string.h>

 #define DEF_SIG "(c) 1988, Paul M. Sittler.  All rights reserved."
 #define ERROR (-1)
 #define TRUE 1
 #define FALSE 0
 #define BUF 200
 #define LIN 80

 struct options
 {
     char signature[ sizeof(DEF_SIG) ];
     int chksum;
     int bh,        /* Beginning hour for schedules */
       copies,   /* Number of copies to print */
       indent,        /* Left Margin Indent in spaces */
       lang,        /* Language desired for calendar */
       more_yrs, /* Number of successive periods to print */
       nh,        /* Number of Hours to schedule */
       pl,        /* Page Length in lines */
       pw;        /* Page Width in characters or columns */
     char aggie;        /* Aggie calendar flag */
     char base;        /* Number base for Programmers Calendar, 0, H(ex), O(ct
     char fy;        /* Fiscal year flag */
     char julian;/* Julian calendar flag */
     char pause;        /* Page pause flag */
     char sched_type;/* Schedule type M(onthly), W(eekly), D(aily) */
     char title[8][LIN];
     /* This structure also contains fields for every option that
      * the user can change at runtime.  These are the default values
      * that are used if no other values have been specified by the
      * user during a run.
      */
 }
 Opt;

 /* extern int directvideo = 0;         * Gag me with a spoon! */
                                 /* An "enhancement" of Turbo-c v1.5 */
 /* Zero = use BIOS calls         One  = write to video ram for PC-Compats */
 /* For MSDOS generic, this must now be zero.  And it STILL doesn't work!! */
 /* The getch function generates wild interrupts on Z-100 */

 /* Suppress some library functions to conserve space */
 /* void _setargv () {}
  * void _setenvp () {}
  */

 struct month
 {
     int  length;
     int  first_day;
 };

 /* put month's lengths into structure */
 static struct month mon[] =
     {
     { 31, 0}, { 28, 0}, { 31, 0},
     { 30, 0}, { 31, 0}, { 30, 0},
     { 31, 0}, { 31, 0}, { 30, 0},
     { 31, 0}, { 30, 0}, { 31, 0}
     };

 int lingos = 17;        /* How many languages we gonna have available */
 char *lingo[] =
        {
 "Afrikaans",        /*  0 */
 "Czech",        /*  1 */
 "Danish",        /*  2 */
 "Dutch",        /*  3 */
 "English",        /*  4 */
 "Finnish",        /*  5 */
 "French",        /*  6 */
 "German",        /*  7 */
 "Italian",        /*  8 */
 "Korean",        /*  9 */
 "Norwegian",        /* 10 */
 "Polish",        /* 11 */
 "Portugese",        /* 12 */
 "Serbo-Croatian",/* 13 */
 "Spanish",        /* 14 */
 "Swedish",        /* 15 */
 "Texan"                /* 16 */
        } ;

 char *mnam[][12] =
        {
 /* Afrikaans        0 */  "JANUARI",   "FEBRUARI",   "MAART",     "APRIL",
 /* Czech        1 */  "LEDEN",     "UNOR",       "BREZEN",    "DUBEN",    "KV
 /* Danish        2 */  "JANUAR",    "FEBRUAR",    "MARTS",     "APRIL",    "M
 /* Dutch        3 */  "JANUARI",   "FEBRUARI",   "MAART",     "APRIL",    "ME
 /* English        4 */  "JANUARY",   "FEBRUARY",   "MARCH",     "APRIL",    "
 /* Finnish        5 */  "PRPRNUU",  "HELMIKUU",   "MAALISKUU", "HUHTIKUU", "T
 /* French        6 */  "JANVIER",   "FEVRIER",    "MARS",      "AVRIL",    "M
 /* German        7 */  "JANUAR",    "FEBRUAR",    "MAERZ",     "APRIL",    "M
 /* Italian        8 */  "GENNAIO",   "FEBBRAIO",   "MARZO",     "APRILE",   "
 /* Latin              "JANUARIUS", "FEBRUARIUS", "MARTIUS",   "APRILIS",  "MA
 /* Korean        9 */  "IL-WOL",    "I-WOL",      "SAM-WOL",   "SA-WOL",   "O
 /* Norwegian        10 */  "JANUAR",    "FEBRUAR",    "MARS",      "APRIL",
 /* Polish        11 */  "STYCZEN",   "LUTY",       "MARZEC",    "KWIECIEN", "
 /* Portugese        12 */  "JANEIRO",   "FEVEREIRO",  "MARCO",     "ABRIL",
 /* Serbo-Croatian 13 */  "JANUAR",    "FEBRUAR",    "MART",      "APRIL",
 /* Spanish        14 */  "ENERO",     "FEBRERO",    "MARZO",     "ABRIL",
 /* Swedish        15 */  "JANUARI",   "FEBRUARI",   "MARS",      "APRIL",
 /* Texan        16 */  "JANYEWARY", "FEBYEWARY",  "MAHCH",     "AYEPRIL",  "M
       } ;

 /* put names of days into array */
 char *wkday[][7] =
        {
 /* Afrikaans        0 */  "SONDAG",    "MAANDAG",       "DINSDAG",     "WOENS
 /* Czech        1 */  "NEDELE",    "PONDELI",       "UTERY",       "STREDA",
 /* Danish        2 */  "SONDAG",    "MANDAG",        "TIRSDAG",     "ONSDAG",
 /* Dutch        3 */  "ZONDAG",    "MAANDAG",       "DINSDAG",     "WOENSDAG"
 /* English        4 */  "SUNDAY",    "MONDAY",        "TUESDAY",     "WEDNESD
 /* Finnish        5 */  "SUNNUNTAI", "MAANANTAI",     "TIISTAI",     "KESKIVI
 /* French        6 */  "DIMANCHE",  "LUNDI",         "MARDI",       "MERCREDI
 /* German        7 */  "SONNTAG",   "MONTAG",        "DIENSTAG",    "MITTWOCH
 /* Italian        8 */  "DOMENICA",  "LUNEDI",        "MARTEDI",     "MERCOLE
 /* Latin              "DOMINICUS", "LUNES",         "MIUS",        "",
 /* Korean        9 */  "IL-YO-IL",  "WOL-YO-IL",     "HWA-YO-IL",   "SU-YO-IL
 /* Norwegian        10 */  "SONDAG",    "MANDAG",        "TIRSDAG",     "ONSD
 /* Polish        11 */  "NIEDZIELA", "PONIEDZIALEK",  "WTOREK",      "SRODA",
 /* Portugese        12 */  "DOMINGO",   "SEGUNDA-FEIRA", "TERCA-FIERA", "QUAR
 /* Serbo-Croatian 13 */  "NEDELJA",   "PONEDELJAK",    "UTORAK",      "SREDA"
 /* Spanish        14 */  "DOMINGO",   "LUNES",         "MARTES",      "MIERCO
 /* Swedish        15 */  "SONDAG",    "MANDAG",        "TISDAG",      "ONSDAG
 /* Texan        16 */  "SUNNY",     "MONEY",        "TEWSDI",      "WEDDSDI",
       } ;

 /* Hebrew - based on solar years and lunar months.
    shelema - 355 days - complete year, with Heshvan & Keslev having 30 days.
    sedur   - 354 days - normal year, Heshvan is defective (29 days).
    hasera  - 353 days - Heshvan & Kislev both defective (29 days).
    The 11 days by which the solar year (365 days) exceeds the lunar year
    (354 days) are accounted for by having a 13th month (Veadar of 30 days)
    on the 3rd, 6th, 8th, 11th, 14th, and 17th year of a 19 year cycle.

     "TISHRI", 30,        "HESHVAN", 29/30,        "KISLEV", 29/30,
     "TEBET", 29,        "SHEBAT", 30,                "ADAR", 30,        "VEAD
     "NISAN", 30,        "IYAR", 29,                "SIVIAN", 30,
     "TAMMUZ", 29,        "AB", 30,                "ELUL", 29
 */

 int yr[3][12][6][7];        /* Array for 3 yrs, 4-D, 3 years, */
                         /* 12 months/year, 6 weeks/month, 7 days/week */

 char *new_file  = "DATAFILE.$$$";
 char *file      = "DATAFILE.CAL";
 FILE *fp;

 void main(argc, argv)
 char **argv;
 int argc;
 {
   int bd,        /* Beginning day passed to functions */
       bm,       /* Beginning month passed to functions */
       by,        /* Beginning year passed to functions */
       fy_bm,        /* Fiscal year beginning month */
       fy_bd,        /* Fiscal year beginning date */
       i,
       j,
       year;
   char c,
        outp;

   int get_int(),
       get_yn(),
       leap();
   void agg_printer(),
        cal_printer(),
        day_printer(),
        get_opts(),
        jul_printer(),
        prep_cal(),
        put_opts(),
        sched_printer(),
        setup_files(),
        signon();
   struct date today;        /* dos.h from Borland */
   get_opts(argv[0]);
   signon();

                                 /* DOS specific. . . */
     getdate(&today);                /* Get DOS's idea of date */
     fy_bd = today.da_day;        /* Make it today */
     fy_bm = today.da_mon;        /* Make it this month */
     year  = today.da_year;        /* It was a very good year. . . */

   for ( ;; )
   {
     fprintf(stderr,
     "\nSchedule period to be <A>nnual, <M>onthly, <W>eekly, or <D>aily (A/M/W
                            Opt.sched_type ? Opt.sched_type : 'A' );
     for ( ;; )
     {
         c = toupper(getch());
         switch(c)
         {
             case  'M'  : break;
             case  'W'  : break;
             case  'D'  : break;
             case  'A'  : break;
             case '\033': exit(0);
             case '\r'  :
             case '\n'  : c = (Opt.sched_type == FALSE) ? 'A': Opt.sched_type;
             default    : ;
         }
         if( (c == 'M') ||
             (c == 'W') ||
             (c == 'D') ||
             (c == 'A')  )
         {
             Opt.sched_type = c;
             putch(c);
             if (Opt.sched_type == 'A')
                 Opt.sched_type = FALSE;
             break;
         }
         continue;
     }
     fputs("\nType year desired for calendar (1901-4000): ", stderr);
     year = get_int(year, 4, 1901, 4000);

     fprintf(stderr, "\nHow many successive %ss? (0-99): ",
                 (Opt.sched_type == 'M') ? "month" :
                 (Opt.sched_type == 'W') ? "week" :
                 (Opt.sched_type == 'D') ? "day" :
                                       "year");
     Opt.more_yrs = get_int(Opt.more_yrs, 2, 0, 99);

     if (! (Opt.sched_type) )
     {
         fputs("\nDo you want an Aggie Calendar", stderr);
         Opt.aggie = get_yn(Opt.aggie ? 'y' : 'n');
     }

     if (!Opt.aggie)
     {
         if (! (Opt.sched_type) )
         {
             fputs("\nDo you want a 3-digit Julian Calendar", stderr);
             Opt.julian = get_yn(Opt.julian ? 'y' : 'n');
         }

         if (! (Opt.julian | Opt.sched_type) )
         {
             fputs("\nFiscal year calendar ", stderr);
             Opt.fy = get_yn(Opt.fy ? 'y' : 'n');
         }

         if (Opt.fy | Opt.sched_type)
         {
             fprintf(stderr, "\n%s beginning month (1-12): ",
                 (Opt.sched_type == 'M') ? "Monthly calendar" :
                 (Opt.sched_type == 'W') ? "Weekly schedule" :
                 (Opt.sched_type == 'D') ? "Daily schedule" :
                                       "Fiscal year");
             fy_bm = get_int(fy_bm, 2, 1, 12);
                         /* make month J=0, F=1, . . . D=11 */

             if (Opt.sched_type != 'M')
             {
                 fprintf(stderr, "\n%s beginning date  (1-31): ",
                     (Opt.sched_type == 'W') ? "Weekly schedule" :
                     (Opt.sched_type == 'D') ? "Daily schedule" :
                                           "Fiscal year");
                 fy_bd = get_int(fy_bd, 2, 1, 31);
             }
             else fy_bd = 1;        /* make months start on first */
         }
     }

     if ( (Opt.sched_type) &&
          (Opt.sched_type != 'M') )
     {
         fprintf(stderr, "\n%s schedule beginning hour  (0-23): ",
             (Opt.sched_type == 'W') ? "Weekly" :
                                   "Daily" );
         Opt.bh = get_int(Opt.bh, 2, 0, 23);

         fprintf(stderr, "\n%s schedule number of hours (1-24): ",
             (Opt.sched_type == 'W') ? "Weekly" :
                                   "Daily" );
         Opt.nh = get_int(Opt.nh, 2, 1, 24);

     }

     if (Opt.sched_type)
     {
 fputs("\nYou may enter up to five custom title lines for the schedules.", std
 fputs("\nThe first three titles entered will be printed on the top three line
 fputs("\nThe last two titles will be printed below the date titles.", stderr)
         for (i = 0;
              i < 8;
              i++  )
         {
             if (i == 3)
             {
                 fprintf(stderr, "\nTitles #4, #5, and #6 are used for dates")
                 i = 6;        /* So skip to Title #7 */
             }
             fprintf(stderr,
       "\nTitle #%d currently is (RETURN to keep it the same, SPACE to erase):
                                      i + 1);
             fprintf(stderr, "\nTitle #%d: %s", i + 1,
                                           Opt.title[i][0] ?
                                           Opt.title[i]    :
                                           "\t(No title currently defined)" );
             fprintf(stderr, "\nTitle #%d: ", i + 1);
             gets(Opt.title[4]);
             if (Opt.title[4][0] != '\0')
                 strcpy(Opt.title[i], Opt.title[4]);
         }
     }

     fputs("\nProgrammer's Calendar", stderr);
     i = get_yn(Opt.base ? 'y' : 'n');
     if (!i)                        /* Decimal numbers used */
         Opt.base = FALSE;
     else                        /* Hexadecimal or Octal numbers */
     {
         fprintf(stderr,
         "\n<H>exadecimal or <O>ctal numbering (H/O)? %c\b",
                                (Opt.base == FALSE) ? 'H' : Opt.base);
         for ( ;; )
         {
             c = toupper(getch());
             switch(c)
             {
                 case  'O': break;
                 case  'H': break;
                 case '\r':
                 case '\n': c = (Opt.base == FALSE) ? 'H' : Opt.base ; break;
                 default  : c = '?';
             }
             if( (c == 'H') || (c == 'O') )
             {
                 putch(c);
                 Opt.base = c;
                 break;
             }
             continue;
         }
     }

     fputs("\nThe calendar(s) may be composed in several languages:\n", stderr
     for (i = 0;
          i < lingos;
          i++)
     {
         if (!(i % 3))
             fputs("\n", stderr);
         fprintf(stderr, "%2d = %-15s",
                          i +1, lingo[i]);
     }


     fprintf(stderr, "\nWhich language for this calendar? (1-%d): ", lingos);
     Opt.lang = get_int(Opt.lang, 2, 1, lingos);

     fputs("\n<V>iew, <P>rint, or write to <F>ile(s) (V/P/F)? V\b", stderr);
     for ( ;; )
     {
         c = toupper(getch());
         switch(c)
         {
             case  'F'  : outp = 'F'; break;
             case  'P'  : outp = 'P'; break;
             case '\033': exit(0);
             case '\r'  :
             case '\n'  :
             case  'V'  : outp = 'V'; break;
             default    : outp = '?';
         }
         if( (outp == 'F') || (outp == 'V') || (outp == 'P') )
         {
             putch(c);
             break;
         }
         continue;
     }

     if (Opt.sched_type)                /* Page width/length useful only */
                                 /* in M/W/D schedules at this time */

     if ( (outp == 'P') ||        /* We want hardcopy */
 /*       (outp == 'V') || */        /* He wants to look at it */
          (outp == 'F')  )        /* He wants a file */
     {
         fputs("\nType # of lines for each page (51-132): ", stderr);
         Opt.pl = get_int(Opt.pl, 3, 51, 132);

         fputs("\nType # of characters for each line (40-270): ", stderr);
         Opt.pw = get_int(Opt.pw, 3, 40, 270);

         fputs("\nType # of spaces for left margin indent (0-40): ", stderr);
         Opt.indent = get_int(Opt.indent, 2, 0, 40);
     }

     if (outp == 'P')                /* We want hardcopy */
     {
         fprintf(stderr,
         "\nType # of copies desired of each %s (1-999): ",
                      (Opt.sched_type == 'M') ? "month" :
                      (Opt.sched_type == 'W') ? "week"  :
                      (Opt.sched_type == 'D') ? "day"   :
                                            "year"  );
         Opt.copies = get_int(Opt.copies, 3, 1, 999);

         fputs("\nPause after each page", stderr);
         Opt.pause = get_yn(Opt.pause ? 'y' : 'n');
     }

     setup_files(outp);

     by = year;
     bm = fy_bm -1;
     bd = fy_bd;

     for (i = 0;
          i < Opt.more_yrs + 1;
          i++, (Opt.sched_type == 'M') ? bm++:
               (Opt.sched_type == 'W') ? bd += 7:
               (Opt.sched_type == 'D') ? bd++:
                                     by++)
     {
         if (leap(by))                /* Tidy up month length array */
             mon[1].length = 29; /* For this year by fixin' February. . . */
         else
             mon[1].length = 28;

         if (bd > mon[bm].length)/* Past this End Of Month */
         {
             bd -= mon[bm].length;
                                 /* So make it appropriate day. . . */
             bm++;                /* Of following month. . . */
         }

        if (bm > 11)                /* Egad! We are past December. . . */
        {
             bm = bm % 12;        /* Normalise it. . . */
             if (bm == 0)        /* Now have January? J=0, F=1 D=11 */
                 by++;                /* Ratchet the year. . . */
        }

         if (! (Opt.julian))                /* Prepare the calendar arrays */
             prep_cal(by);

         for ( j = 0;
               j < Opt.copies;
               j++)
             {
                if (Opt.sched_type)
                    sched_printer(by, outp, bm, bd, Opt.bh, Opt.nh, Opt.pl, Op
                else
                if (Opt.julian)
                    jul_printer(by, outp, Opt.base, Opt.lang, Opt.pause);
                else
                if (Opt.aggie)
                    agg_printer(by, outp, Opt.base, Opt.lang, Opt.pause);
                else
                if (Opt.fy)
                    cal_printer(by, outp, bm, Opt.fy, bd, Opt.base, Opt.lang,
                else
                    cal_printer(by, outp, 0,  Opt.fy,  1, Opt.base, Opt.lang,
             }
     }
     fputs("\nAnother calendar", stderr);
     if (!get_yn('n'))
     {
         if(outp != 'F')
             fclose(fp);
 /*      printf("\nClosed %s\n", file);*/
         fputs("\nRetain present options as defaults", stderr);
         if (get_yn('n'))
             put_opts(argv[0]);
         exit(0);
     }
   }
 }



 void setup_files(out)
 char out;
 {
     if (fp) fflush(fp);
     if(out == 'V')
     {
         if(!strcmp(file, "PRN"))
         {
             fclose(fp);
 /*           printf("\nClosed %s\n", file);*/
         }
         if(strcmp(file, "CON"))
         {
             strcpy(file, "CON");
             fp = fopen(file, "w");
 /*          printf("\nOpened %s for write\n", file);*/
         }
     }
     else
     if(out == 'P')
     {
         if(!strcmp(file, "CON"))
         {
             fclose(fp);
 /*          printf("\nClosed %s\n", file);*/
         }
         if(strcmp(file, "PRN"))
         {
             strcpy(file, "PRN");
             fp = fopen(file, "w");
 /*          printf("\nOpened %s for write\n", file);*/
         }
     }
 }



 void prep_cal(year)
 int year;
 {
     int count,                /* Count of the days */
         day,                /* Weekday Sun=0, Mon=2, ... Sat=6 */
         month,                /* Month Jan=0, Feb=1, ... Dec=11 */
         week,                /* Six weeks/month possible */
         yeer,                /* Year for calendar */
         y,                /* Year Last=0, This=1, Next=2 */
         leap(),
         weekday_month();
 /*printf("\nIn Prep_cal\n"); */
     for (y = 0;                /* Start at last year y[0] */
          y < 3;                /* Stop after next year y[2] */
          y++)
     {
 /*      printf("\nIn Prep_cal, y = [%d]\n", y); */
         yeer = (year + y - 1);
         if (leap(yeer))        /* Tidy up month length array */
             mon[1].length = 29; /* For this year by fixin' February. . . */
         else
             mon[1].length = 28;

         /* get weekday of first day of each month, put into array mon */
         /* Su = 0, Mo = 1, Tu = 2, We = 3, Th = 4, Fr = 5, Sa = 6   */
         for (month = 0;
              month < 12;        /* 12 months/year */
              month++)
         mon[month].first_day = weekday_month(month, yeer);

         /* form year array with 0 for unused dates, with dates */
         /* in their relative positions by weekday */
         for (month = 0;
              month < 12;        /* 12 months/year */
              month++)
         {
             count = 0;                /* set day counter to 0 */
             for (week = 0;
                  week < 6;        /* 6 weeks/month */
                  week++)
             {
                 for (day = 0;
                      day < 7;        /* 7 days/week */
                      day++)
                 {
                     if( (week == 0) &&  /* first week of month */
                         (day < mon[month].first_day))
                                         /* before first day */
                         yr[y][month][week][day] = 0;
                                         /* Zero it */
                     else
                     if (++count <= mon[month].length)
                                         /* Not past End of Month */
                         yr[y][month][week][day] = count;
                     else
                         yr[y][month][week][day] = 0;
                                         /* Zero it */
                 }
             }
         }
     }
 }



 /* Function to get first day index (day of week of 1st of month) */
 /* Jan = 0, Feb = 1, Mar = 2, Apr = 3, . . .  Dec = 11 */
 /* Su = 0, Mo = 1, Tu = 2, We = 3, Th = 4, Fr = 5, Sa = 6 */
 int weekday_month(Monat, Jahr) /* 1st day of any month after 1900 */
 int Monat;
 int Jahr;
 {
     long int date,        /* date after 1901 */
              numb_days; /* number of days to deal with */
     int      mt[12] = {   0,  31,  59,  90, 120, 151,
                         181, 212, 243, 273, 304, 334  };
     date       = Jahr - 1901;        /* subtract 1901 from year */
     numb_days  = date * 365;        /* # of yrs times 365 days/year */
     numb_days += ( ( date / 4)        /* add number of leap years */
               - (date / 100)        /* subtract non-leap centuries */
               + (date / 400 ))        /* add number of leap centuries */
               + mt[Monat];        /* add days offset for this year */
     if ( ( Jahr % 4) == 0 &&        /* if a conventional leap year */
            Monat > 1 )                /* and after February */
         numb_days++;                /* add a day for Feb 29th */
     return((numb_days +2) %7);        /* divide the number of days by 7 */
                                 /* and return the remainder */
 }



 /* Function to decide if a year is a leap year */
 int leap(years)
 int years;
 {                        /* Leap year sieve */
     if (years & 0x0003) /* Mask year to see if not leap year */
        return FALSE;    /* If we look at the last two bits, and */
                         /* one of them is on, then the year can't */
                         /* be divisible by four.  Thus it is not */
                         /* a leap year, so function returns FALSE. */
                         /* Test for the leap century. */
     else                /* Leap century:   years that are: */
     if (!(years % 100) && /* evenly divisible by 100:  not leap */
          (years % 400) )  /* years unless evenly divisible by 400 */
         return FALSE;        /* Gruenberger and Jaffray, "Problems for */
                         /* Computer Solution", Wiley, 1965. */
                         /* We have filtered out all years that are */
                         /* not evenly divisible by four as well as */
                         /* those evenly divisible by 100 that are */
                         /* evenly divisible by 400. */
                         /* It seems that all the rest are */
                         /*   (a) evenly divisible by four */
                         /*   (b) evenly divisible by 400  */
     return TRUE;        /*   (c) Thus, leap years. . . */
 }



 void cal_printer(year, out, bm, fy, bd, base, lang, pause)
 int year;
 char out;
 int bm;
 char fy;
 int bd;
 char base;        /* Number base used, 0 = Decimal, H = Hex, O = Octal */
 int lang;        /* Language used 1=Danish, 2=Dutch, 3=English etc. */
 char pause;        /* Page pause True/False */
 {
     char hdr1[] = {" Su Mo Tu We Th Fr Sa"},
          hdr2[] = {" -- -- -- -- -- -- --"};

     int y, month, week, day, count, stat;
     void hold();        /* Printing page pause function */
     char  linbuf[BUF],
           temp[BUF],
          *char_str(),
          *center(),
          *trim();
     char *off = (out == 'V') ? " " : "       ";
     y = 1;                /* Make year this year */

     sprintf(hdr1, " %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s",
            wkday[lang -1][0], wkday[lang -1][1], wkday[lang -1][2],
            wkday[lang -1][3], wkday[lang -1][4], wkday[lang -1][5],
            wkday[lang -1][6] );

     if(out == 'F')                /* setup for file output */
     {
         sprintf(file, fy ?
                   "%dFY%c" :
                   "%d%c",
                    year, base);
         strcpy(new_file, file);
         strcat(file, ".$$$");
         sprintf(temp, ".%3.3s", lingo[lang -1]);
         strcat(new_file, temp);
         fp = fopen(file, "w");
 /*      printf("\nOpened %s for write\n", file);*/
     }

     if ((pause)     &&                /* User wants time after each page */
         (out == 'P') )                /* gets printed to add paper etc... */
         hold();                        /* Wait for keystroke */

     fputs("\n\n\n", fp);
     sprintf(temp, fy ? "%s%s%s Calendar for Fiscal Year %d-%d":
                        "%s%s%s Calendar for %d",
 /*               ( (base == 'O') && (lang != 10) ) ? "Classical " : "" ,*/
                  base ? "Programmer's " : "" ,
                  base ? ( (base == 'O') ? "Octal " : "Hexadecimal ") : "",
                  lingo[lang -1],
                  year, year +1);

     fputs(center(temp, (out == 'V') ? 75 : 89), fp);
     fputs("\n\n\n", fp);

     if (bd == 1)                /* If fy month starts on 1st, */
         fy = FALSE;                /* treat like ordinary month */

     for (month = bm;                /* Start at beginning Month for FY */
          month < (12 + bm + fy);
          month += 3)
     {                                /* 4 sets of months  3 months across */
         sprintf(linbuf,
              "%s%s    ", off, center(mnam[lang -1][month %12], 21));

         if (month != (bm +12))        /* NOT FY and 13th month */
         {
             sprintf(temp,
                 "%s    ", center(mnam[lang -1][(month +1) %12], 21));
             strcat(linbuf, temp);
             sprintf(temp,
                 "%s"    , center(mnam[lang -1][(month +2) %12], 21));
             strcat(linbuf, temp);
         }

         strcat(linbuf, "\n");        /* add a newline */
         fputs(linbuf, fp);        /* Names of three Months */
         linbuf[0] = '\0';

         if(month != (bm +12))        /* NOT FY and 13th month */
         {
             fprintf(fp, "%s%s    %s    %s\n",
                         off, hdr1, hdr1, hdr1);
             fprintf(fp, "%s%s    %s    %s\n",
                         off, hdr2, hdr2, hdr2);
         }
         else                        /* FY and 13th month */
         if (bd != 1)                /* beginning after the 1st */
         {
             fprintf(fp, "%s%s\n",        /* Names of weekdays */
                         off, hdr1);
             fprintf(fp, "%s%s\n",        /* Lines of dashes */
                         off, hdr2);
         }

         for (week = 0;                /* One line per week */
              week < 6;                /* 6 wks/month possible */
              week++)
         {
             sprintf(linbuf, off);

             for (count = 0;        /* 3 months/line ordinarily */
                  count < ((month == (bm +12)) ?
                                             1 : /* FY 13th month alone */
                                             3); /* Ordinary line */
                  count++)
             {
                 for (day = 0;
                      day < 7;        /* 7 days/week */
                      day++)
                 {
                     if (((month + count) == bm) &&  /* FY 1st month */
                         (yr[y][month + count][week][day] < bd))
                          sprintf(temp, "   ");
                     else
                     if (((month + count) == (bm +12)) &&
                         (yr[y][month + count][week][day] >= bd))
                          sprintf(temp, "   ");
                     else
                     sprintf(temp,
                         yr[y][month + count][week][day] ?
                             (base ?
                                 ((base == 'O') ? "%3o" : "%3X" ) :
                                                  "%3d" ) :
                                                  "   ",
                         yr[y][month + count][week][day]);
                     strcat(linbuf, temp);
                 }
                 strcat(linbuf,
                 count < ((month < (bm +12)) ? 2 : 0) ? "    ": "\n" );
             }
             fputs(linbuf, fp);
             linbuf[0] = '\0';
         }
         fputs("\n\n", fp);
     }
     if (out != 'V') fputs("\f\r", fp);        /* no FF for screen */

     if (out == 'F')                        /* setup for file output */
         if ((stat = fclose(fp)) == ERROR)
             printf("\nCan't close %s.\n", file);
 /*      else
         printf("\nClosed %s\n", file);*/

     if (out == 'F')
     {
         if ((stat = rename(file, new_file)) == ERROR)
         {
             printf(
             "\nCan't rename %s to %s.  %s may already exist.\n",
                                  file, new_file, new_file);
         }
     }
 }



 void agg_printer(year, out, base, lang, pause)
 int year;
 char out;
 char base;        /* Number base used, 0 = Decimal, H = Hex, O = Octal */
 int lang;        /* Language used 1=Danish, 2=Dutch, 3=English etc. */
 char pause;        /* Page pause True/False */
 {
     int mf[12][2];        /* mf flag for aggie calendar */

     char agg1[] = {" Ja Fe Ma Ap Ma Jn Jl Au Se Oc No De"},
          agg2[] = {" -- -- -- -- -- -- -- -- -- -- -- --"};

     int y, month, week, day, count, stat, i, j;
     void hold();        /* Printing page pause function */
     char  linbuf[BUF],
           temp[BUF],
          *char_str(),
          *center(),
          *trim();
     char *off = (out == 'V') ? " " : "    ";
     y = 1;                /* Make year this year */
     sprintf(agg1, " %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.
            mnam[lang -1][0], mnam[lang -1][ 1], mnam[lang -1][ 2],
            mnam[lang -1][3], mnam[lang -1][ 4], mnam[lang -1][ 5],
            mnam[lang -1][6], mnam[lang -1][ 7], mnam[lang -1][ 8],
            mnam[lang -1][9], mnam[lang -1][10], mnam[lang -1][11] );

     if (out == 'F')
     {
         sprintf(file, "%dAGG%c", year, base);
         strcpy(new_file, file);
         strcat(file, ".$$$");
         sprintf(temp, ".%3.3s", lingo[lang -1]);
         strcat(new_file, temp);
         fp = fopen(file, "w");
 /*      printf("\nOpened %s for write\n", file);*/
     }

     if ((pause)     &&                /* User wants time after each page */
         (out == 'P') )                /* gets printed to add paper etc... */
         hold();                        /* Wait for keystroke */
     fputs("\n\n\n", fp);
     sprintf(temp, "%sAggie %s%sGig'Em %s Calander fer %d",
                  (base == 'O') ? "Olde " : "" ,
                  base ? "Hacker's " : "" ,
                  base ? ( (base == 'O') ? "Octal " : "Hexadecimal ") : "",
                  lingo[lang -1],
                  year);
     fputs(center(temp, (out == 'V') ? 75 : 89), fp);
     fputs("\n\n\n", fp);
     for (day = 0;
          day < 7;                /* 4 sets of days */
          day += 2)                /* 2  days across */
     {
          for (i = 0;
               i < 12;                /* 12 months in a day */
               i++)
              for (j = 0;
                   j < 2;        /* 2  days across */
                   j++)
                       mf[i][j] = 0;
         if (day < 6)
         {
             sprintf(linbuf, "%s%s    ", off, center(wkday[lang -1][day], 36))
             sprintf(temp,   "%s\n"  , center(wkday[lang -1][day +1], 36));
             strcat(linbuf, temp);
             fputs(linbuf, fp);
             linbuf[0] = '\0';
             fprintf(fp, "%s%s   %s\n", off, agg1, agg1);
             fprintf(fp, "%s%s   %s\n", off, agg2, agg2);
         }
         else
         {
             fprintf(fp, "%s%s\n", off, trim(center(wkday[lang -1][day], 79) )
             fprintf(fp, "%s%s\n", off, trim(center(agg1, 79) ) );
             fprintf(fp, "%s%s\n", off, trim(center(agg2, 79) ) );
         }
         for (week = 0;
              week < 5;                /* 5 weeks/day possible */
              week++)
         {
             sprintf(linbuf, off);
             for (count = 0;        /* 2 days across except Saturday */
                  count < ( (day == 6) ? 1 : 2) ;
                  count++)
             {
                 if (day == 6)
                     strcat(linbuf, "                      ");
                 for (month = 0;
                      month < 12;        /* 12 mnths/day */
                      month++)
                 {
                     if (!yr[y][month][week][day + count])
                         mf[month][count] = 1;
                     sprintf(temp,
                      yr[y][month][week +mf[month][count]][day +count] ?
                             (base ?
                                 ((base == 'O') ? "%3o" : "%3X" ) :
                                                  "%3d" ) :
                                                  "   ",
                      yr[y][month][week +mf[month][count]][day + count]);
                     strcat(linbuf, temp);
                 }
                 strcat(linbuf, count < 1 ? "   ": "\n" );
                 if (day == 6) strcat(linbuf, "\n");
             }
             fputs(linbuf, fp);
             linbuf[0] = '\0';
         }
         fputs("\n\n", fp);
     }
     if (out != 'V') fputs("\f\r", fp);        /* no FF for screen */
     if(out == 'F')                        /* setup for file output */
         if ((stat = fclose(fp)) == ERROR)
             printf("\nCan't close %s.\n", file);
 /*      else
         printf("\nClosed %s\n", file);*/
     if(out == 'F')
     {
         if ((stat = rename(file, new_file)) == ERROR)
         {
             printf(
             "\nCan't rename %s to %s.  %s may already exist.\n",
                                  file, new_file, new_file);
         }
     }
 }



 void jul_printer(year, out, base, lang, pause)
 int year;
 char out;
 char base;        /* Number base used, 0 = Decimal, H = Hex, O = Octal */
 int lang;        /* Language used 1=Danish, 2=Dutch, 3=English etc. */
 char pause;        /* Page pause True/False */
 {
     int month, day, stat, count, leep;
     void hold();        /* Printing page pause function */
     char  temp[BUF],
          *char_str(),
          *center(),
          *trim();
     int jul[12][31];        /* Array for Julian yr, 12 months/year */
                         /* 31 days/month */
     char *off = (out == 'V') ? " " : "    ";
     int month_length[12] =
     {
         0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
     };
     char jul1[] = {"Month:   Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct
     char jul2[] = {"         ---  ---  ---  ---  ---  ---  ---  ---  ---  ---

     leep = leap(year);        /* Find out if leap year */
     sprintf(jul1, "         %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s
            mnam[lang -1][0], mnam[lang -1][ 1], mnam[lang -1][ 2],
            mnam[lang -1][3], mnam[lang -1][ 4], mnam[lang -1][ 5],
            mnam[lang -1][6], mnam[lang -1][ 7], mnam[lang -1][ 8],
            mnam[lang -1][9], mnam[lang -1][10], mnam[lang -1][11] );
     if (out == 'F')
     {
         sprintf(file, "%dJUL%c", year, base);
         strcpy(new_file, file);
         strcat(file, ".$$$");
         sprintf(temp, ".%3.3s", lingo[lang -1]);
         strcat(new_file, temp);
         fp = fopen(file, "w");
 /*      printf("\nOpened %s for write\n", file);*/
     }

     if ((pause)     &&        /* User wants time after each page */
         (out == 'P') )        /* gets printed to add paper etc... */
         hold();                /* Wait for keystroke */
     fputs("\n\n\n", fp);
     sprintf(temp, "%s%s%s%s 3-Digit Julian Calendar for %d",
                  (base == 'O') ? "Olde " : "" ,
                  base ? "Hacker's " : "" ,
                  base ? ( (base == 'O') ? "Octal " : "Hexadecimal ") : "",
                  lingo[lang -1],
                  year);
     fputs(center(temp, (out == 'V') ? 75 : 89), fp);
     fputs("\n\n\n", fp);
     fprintf(fp, "%s%s\n", off, jul1);
     fprintf(fp, "%s%s\n", off, jul2);

     for (month = 0;
          month < 12;        /* 12 months */
          month++)
         for (day = 1;
              day < 32;        /* 31 days possible */
              day++)
         {
             count = (day + month_length[month] + ((month > 1) ? leep : 0) );
             if (count > (month_length[month +1] + ((month) ? leep : 0)) )
                 count = 0;
 /*          fprintf(stderr, "%6d", count); */
             jul[month][day -1] = count;
         }

     for (day = 0;
          day < 31;
          day++)
     {
         if ( (day)       &&
              (!(day % 2)) )
                 fprintf(fp, "\n");
         fprintf(fp, "%sDay #%2d", off, day +1);

         for (month = 0;
              month < 12;
              month++)
         {
             if (jul[month][day])
             {
                 fprintf(fp,
                    (base ?
                        ((base == 'O') ?
                            "  %3o" :
                            "  %3X" ) :
                            "  %3d" ),
                           jul[month][day]);
             }
             else
                 fprintf(fp, "     ");
         }
         fprintf(fp, "   Day #%2d\n", day +1);
     }

     if (out != 'V') fputs("\f\r", fp);        /* no FF for screen */
     if (out == 'F')                        /* setup for file output */
         if ((stat = fclose(fp)) == ERROR)
             printf("\nCan't close %s.\n", file);
 /*      else
         printf("\nClosed %s\n", file);*/
     if (out == 'F')
     {
         if ((stat = rename(file, new_file)) == ERROR)
         {
             printf(
             "\nCan't rename %s to %s.  %s may already exist.\n",
                                  file, new_file, new_file);
         }
     }
 }



 char *center(str, width)
 char *str;
 int width;
 {
     static char buf[BUF];        /* location of finished string */
     static char copy[BUF];        /* copy of str to avoid side effects */
     char  filler,
          *char_str(),
          *strcpy(),
          *strcat();
     int i;

     filler = ' ';
     strcpy(copy, str);          /* copy str to copy */
     if (strlen(copy) >= width)        /* Test for str longer than width */
         copy[width] = '\0';        /* Terminate it at width */
     strcpy(buf, char_str( (width - strlen(copy) ) >> 1, filler));
     strcat(buf, copy);
     i = strlen(buf);
     while (width - i)
          buf[i++] = filler;
     buf[i] = '\0';
     return(buf);
 }



 char *trim(str)                /* trim spaces from end of string */
 char *str;
 {
     static char buf[BUF];        /* location of finished string */
     char  filler,
          *char_str(),
          *strcpy(),
          *strcat();
     int i;
     filler = ' ';
     strcpy(buf, str);
     i = strlen(buf);
     while (buf[--i] == filler)
         buf[i] = '\0';
     return(buf);
 }



 char *char_str(length, c)
 int length;
 char c;
 {
     static char loc[BUF];
     char *ptr = loc;

     while (length--)
         *ptr++ = c;
     *ptr = '\0';
     return(loc);
 }



 int get_int(defalt, digits, lowest, highest)
 int defalt,        /* default value when C/R alone is struck */
     digits,        /* maximum number of digits accepted */
     lowest,        /* lowest value accepted */
     highest;        /* highest value accepted */
 {
     char buffer[80];        /* Buffer to store input string */
     int ch;                /* All purpose character ch */
     int index = 0;        /* Character array index */
     int value = 0;        /* value to return */
     int done = FALSE;        /* Done/Not Done Flag */
     char dfalt[10];        /* Buffer to store default value as string */
     int i, ii;                /* length of default value as a string */

     sprintf(dfalt, "%d", defalt); /* Convert default to string */
     i = ii = strlen(dfalt);        /* Calculate its length */
     printf("%s", dfalt);        /* Display default value */
     while (ii--)
         putch('\b');                /* Backspace to beginning */

     while (!done)
     {
         while (index < digits)  /* while not enough digits, grab 'em */
         {
             ch = getch();          /* Get a char from console, no echo */

             if (isdigit(ch))        /* Digit!! so . . .  */
             {
                 putch(ch);        /* Echo it to console, and */
                 buffer[index++] = ch;        /* Stuff it into buffer */
                 if (index == 1)         /* Entered first digit, so. . . */
                 {
                     for (ii = digits; --ii; )
                         putch(' ');        /* Blank it out */
                     for (ii = digits; --ii; )
                         putch('\b');        /* Backspace to beginning */
                 }
             }

             else
             if ((ch == '\b') && /* Backspace? */
                 (index) )        /* if index not zero */
             {
                 --index;        /* Reduce index */
                 putch(' ');        /* Blank it */
                 putch('\b');        /* Backspace over blank */
                 putch(ch);        /* Echo it to console */
             }

             else
             if (ch == '\033')        /* Escape */
                 exit(0);        /* says he's through */

             else
             if (ch == '\r')        /* Return? */
                 break;                /* says he's through */
         }        /* End while not enough digits, grab 'em */

         buffer[index] = '\0';        /* Terminate string */

         if (index == 0)                /* no digits entered before return */
         {
             value = defalt;        /* so use default */
             done  = TRUE;        /* We're through */
         }

         else                        /* some digits were entered */
         {
             value = atoi(buffer);        /* Convert string to integer */

             if ((value < lowest) ||        /* Range test value returned */
                 (value > highest) )
             {                                /* Out of allowable range. . . *
                 for (            ;
                        index;
                      --index )
                     putch('\b');        /* Backspace to beginning */
                 for (ii = digits;
                      ii;
                      --ii)
                     putch(' ');                /* Blank it out */
                 for (ii = digits;
                      ii;
                      --ii)
                     putch('\b');        /* Backspace to beginning */
                 printf("%s", dfalt);    /* Display default value */
                 for (ii = i;
                      ii;
                       --ii)
                     putch('\b');        /* Backspace to beginning */
             }

             else
             {
                 done  = TRUE;                /* We're through */
             }
         }
     }                /* end while !done */
     return(value);
 }



 int get_yn(defalt)
 char defalt;
 {
     char c;                        /* all purpose character */
     fputs(" (y/n) ? ", stderr); /* Prompt for Yes or No */
     putch(defalt);                /* Display default */
     putch('\b');                /* Backspace to it */
     do
     {
         c = tolower(getch());        /* Get a character, make it lowercase */
     }   while ( (c != 'y') &&        /* Until we get a y, n, ESC, or return *
                 (c != 'n') &&
                 (c != '\033') &&
                 (c != '\r') );

     if (c == '\033')        /* Escape */
         exit(0);        /* says he's through */
     else
     if (c == '\r')        /* If a return, make it the default */
         c = defalt;
     putch(c);                /* Display choice to user */
     return (c == 'y') ? TRUE : FALSE ;
 }



 void hold()
 {
     fputs("\nPrinter ready?  Any key to continue. . . ", stderr);
     getch();
 }



 void signon()
 {
     fputs(
     "\t\t\tYEARCAL v0.07T 3 Mar 1988\n\n\t\tCopyright 1987, 1988 by Paul M. S
     fputs(
     "\tYEARCAL makes calendars (A/M) or schedules (W/D) for years after 1901.
     fputs(
     "\tAt the user's option, Normal, Fiscal Year, AGGIE, or 3-Digit Julian\n"
     fputs(
     "\tDate Calendars can be produced, in multiple copies, for a number of\n"
     fputs(
     "\tconsecutive years, or both.  Fiscal Year calendars may be produced for
     fputs(
     "\tany arbitrary 12 or 13 month fiscal year.  The user may select a\n", s
     fputs(
     "\tProgrammer's calendar, numbered in Hexadecimal or Octal numbers rather
     fputs(
     "\tthan decimal numbers, and may choose one of several languages.\n\n", s
     fputs(
     "\tThe calendars may be displayed on the screen, printed, or written to\n
     fputs(
     "\ta file as desired.  If written to disk, files are named like YYYY.ENG\
     fputs(
     "\t(Normal ENGlish), YYYYFY.DUT (Fiscal-Year DUTch), YYYYAGG.TEX (Aggie-\
     fputs(
     "\ttype TEXan), or YYYYJUL.POL (3-Digit Julian Date POLish) calendars,\n"
     fputs(
     "\tetc.  Hex or Octal calendar files will have an \"H\" or \"O\" added to
     fputs(
     "\ttheir names, such as YYYYH.SPA, YYYYFYO.SER or YYYYAGGH.FRE.\n\n", std
     fputs(
     "\tYEARCAL may be freely distributed, and used for non-commercial\n", std
     fputs(
     "\tpurposes, as long as the unmodified program source code and\n", stderr
     fputs(
     "\tdocumentation files are distributed with it.\n", stderr);
 }



 void sched_printer(year, out, bm, bd, bh, nh, pl, pw, sched_type, title, base
 int year;        /* Year for calendar */
 char out;        /* Output goes where? View, Printer, File */
 int bm;                /* Month (beginning) for schedule */
 int bd;                /* Day (beginning) for schedule */
 int bh;                /* Hour (beginning) for schedule */
 int nh;                /* number of hours to schedule (1-24) */
 int pl;                /* Page Length in lines */
 int pw;                /* Page Width in characters or columns */
 char sched_type;/* Schedule type M(onthly), W(eekly), D(aily) */
 char title[][LIN];
 char base;        /* Number base used, 0 = Decimal, H = Hex, O = Octal */
 int lang;        /* Language used 1=Danish, 2=Dutch, 3=English etc. */
 char pause;        /* Page pause flag True/False */
 int indent;        /* Left margin indent (# of spaces) */
 {
     int bw,        /* Box width */
         day,
         first_day,
         i, j,
         month,
         stat,
         w,        /* Week number for printing top calendars */
         wk_day,
         y;
     void hold();        /* Printing page pause function */
     char  linbuf  [BUF],
           temp    [BUF],
           temp1   [BUF],
           temp2   [BUF],
           bnd     [BUF],
           sep     [BUF],
           hoursw  [BUF],
           spacerw [BUF],
           dates   [BUF],
 /*        bc, */
          *char_str(),
          *center(),
          *trim();
     char *off = ( (out == 'V') ?
                            " " :        /* Offset for screen */
     "                                        ");
     /* 40 spaces-----------------------------| Max Offset for printing */
     off[indent] = '\0';                /* clip offset to proper length */
     y = 1;                        /* Make year this year */
 /*  printf(
 "\nArgs: year=[%d], out=[%c], bm=[%d], bd=[%d], bh=[%d], nh=[%d], pl=[%d]\n",
        year,      out,      bm,      bd,      bh,      nh,      pl);
     printf(
 "Args: pw=[%d], sched_type=[%c], base=[%c], lang=[%d]\n",
        pw,      sched_type,      base,      lang);
  */
     if (out == 'V')                /* Gonna View it, so. . . */
           pw = 80  ;                /* pw is screen width */

     if (out == 'F')                /* setup for file output */
     {
         (sched_type == 'M') ?
             sprintf(file, "%d%3.3s%c", year, mnam[lang -1][bm], base):
             sprintf(file, "%d%02d%02d", year, bm + 1, bd);
         strcpy(new_file, file);
         strcat(file, ".$$$");
         sprintf(temp, ".%3.3s", lingo[lang -1]);
         strcat(new_file, temp);
         fp = fopen(file, "w");
 /*      printf("\nOpened %s for write\n", file);*/
     }

     first_day = weekday_month(bm, year);        /* 1st day of month */
     if (sched_type == 'M')
         wk_day = 0;
     else
         wk_day = ( (first_day + bd -1) % 7);        /* Gives us weekday */

     sprintf(title[5], "%s",
                    (sched_type == 'M')?                /* Monthly calendar */
                    "Monthly Calendar" :
                    (sched_type == 'W')? /* if weekly instead of daily */
                     "Weekly Schedule" :
                     "Daily Schedule");

     sprintf(title[4], (sched_type == 'W') ?
                      "Week begins on %s" :
                          (sched_type == 'D') ?
                                         "%s" :
                                           "" ,
                        wkday[lang -1][wk_day]);

     if (sched_type == 'M')
     {
         sprintf(title[3], "%s %d",
                    mnam[lang -1][bm], year );
     }
     else
         sprintf(title[3], "%d %s, %d",
                    bd,
                    mnam[lang -1][bm],
                    year );

     strcpy(hoursw, off);                /* Put offset into hoursw */
     strcpy(spacerw, off);                /* Put offset into spacerw */

     if (sched_type != 'M')                /* If Daily or Weekly */
     {
         sprintf(temp, "| %s00 |",
                             (base ?
                    ((base == 'O') ?
                             "%02o" :
                           "%02X" ) :
                           "%02d" ) );
         strcat(hoursw, temp);                /* Add header info to hoursw */
         strcat(spacerw, "|      |");        /* Add header info to spacerw */
     }
     else                                /* Monthly Calendar, so. . . */
     {
         strcat(hoursw, "|");                /* Add header info to hoursw */
         strcat(spacerw, "|");                /* Add header info to spacerw */
     }

     bw = (((pw - strlen(hoursw) ) / 7) -1);  /* Calculate Box Width */
     for (i = 0;                                /* Form strings for each day *
          i < bw;
          i++)
     {
         temp [i] = ' ';                        /* Using spaces */
     }
     if (sched_type == 'M')                /* Monthly Calendar */
     {
         strcpy(dates, temp);                /* Copy temp to dates for length
         dates[i -2] = '\0';                /* Cut dates to length */
     }

     temp[i++] =  (sched_type == 'D')?        /* If Daily */
                                  ' ':        /* Add ' ' */
                                  '|';        /* Otherwise add '|' */
     temp[i]   = '\0';                        /* Terminate string */

     for (i = 0;                                /* Adding multiple temps to */
          i < 7;
          i++)
     {
         if (sched_type != 'M')
             strcat(hoursw, temp);        /* Add temp to hoursw */
         strcat(spacerw, temp);                /* Add temp to spacerw */
     }
     if(sched_type == 'D')
     {
         hoursw [strlen(hoursw) -1] = '|';
         spacerw[strlen(spacerw)-1] = '|';
     }

     strcat(spacerw, "\n");        /* Add '\n' */
     strcat(hoursw, "\n");        /* Add '\n' */

     strcpy(bnd, off);                /* Put offset into boundary */
     strcpy(sep, off);                /* Put offset into separator */

     for (i = 0;                        /* Draw them lines. . . */
          i < (strlen(spacerw) - strlen(off) -1);
          i++)
     {
         temp[i] = '-';                /* Using Hyphens */
     }
     temp[i]     = '\n';                /* Add Newline */
     temp[i +1]  = '\0';                /* Terminate string */
     strcat(bnd, temp);                /* Add temp to bnd */
     temp[0]     = '|';
     temp[i -1]  = '|';
     strcat(sep, temp);                /* Add temp to sep */

     pw = strlen(bnd) -1;        /* Adjust Page Width */

     if ((pause)     &&        /* User wants time after each page */
         (out == 'P') )        /* gets printed to add paper etc... */
         hold();                /* Wait for keystroke */
     fputs("\n\n", fp);                /* Print two blank lines */
     /* Line One: Last and Next Month's names */
     sprintf(temp, "%s %d",        /* Last month's name and year */
                    mnam[lang -1]
                       [(sched_type == 'M') ?
                            (bm +11) % 12 :
                                       bm ],
                        (sched_type == 'M') ?
                                  (bm == 0) ?
                                  year -1 :
                                     year :
                                     year );
     sprintf(temp2,"%s %d",        /* Next month's name and year */
                    mnam[lang -1][(bm +1) %12],
                    (bm == 11) ? year +1 : year );
     strcpy(linbuf, off);
     strcat(linbuf, center(temp, 21) );
     strcat(linbuf, center(title[0], (pw -42 -strlen(off)) ) );
     strcat(linbuf, center(temp2, 21) );
     strcat(linbuf, "\n");
     fputs(linbuf, fp);

     /* Line Two: Weekday headers */
     temp[0] = '\0';
     for (i = 0;
          i < 7 ;
          i++)
     {
         sprintf(temp2, " %2.2s",
                         wkday[lang -1][i] );
         strcat(temp, temp2);
     }
     strcpy(linbuf, off);
     strcat(linbuf, center(temp, 21) );
     strcat(linbuf, center(title[1], (pw -42 -strlen(off)) ) );
     strcat(linbuf, center(temp, 21) );
     strcat(linbuf, "\n");
     fputs(linbuf, fp);

     /* Lines 3-8: Last and Next Month's first weeks */
     for (w = 0;
          w < 6;
          w++)
     {
         temp[0] = '\0';
         temp2[0] = '\0';
         for (day = 0;
              day < 7;        /* 7 days/week */
              day++)
         {
             sprintf(linbuf,
                  yr[(sched_type == 'M') ? (bm == 0) ? y -1 : y : y]
                  [(sched_type == 'M') ? (bm +11) % 12 : bm][w][day] ?
                                        (base ?
                               ((base == 'O') ?
                                        "%3o" :
                                      "%3X" ) :
                                      "%3d" ) :
                                         "   ",
                  yr[(sched_type == 'M') ? (bm == 0) ? y -1 : y : y]
                  [(sched_type == 'M') ? (bm +11) % 12 : bm][w][day]);
             sprintf(temp1,
                  yr[((bm == 11) ? y +1 : y)][(bm +1) %12][w][day] ?
                                        (base ?
                               ((base == 'O') ?
                                        "%3o" :
                                      "%3X" ) :
                                      "%3d" ) :
                                         "   ",
                  yr[((bm == 11) ? y +1 : y)][(bm +1) %12][w][day]);
             strcat(temp, linbuf);
             strcat(temp2, temp1);
         }
         strcpy(linbuf, off);
         strcat(linbuf, center(temp, 21) );
         strcat(linbuf, center(title[w + 2], (pw -42 -strlen(off)) ) );
         strcat(linbuf, center(temp2, 21) );
         strcat(linbuf, "\n");
         fputs(linbuf, fp);
     }

     fputs(bnd, fp);                /* print boundary */

   if (sched_type != 'M')        /* NOT Monthly calendar */
   {
     sprintf(linbuf, "%s|      |", off);
     for (i = day = bd, month = bm;
          i < (bd + 7);
          i++, day++)
     {
         if (day >  mon[month].length)        /* Past this month */
         {
             day -= mon[month].length;
                                 /* So make it appropriate day. . . */
             month++;                /* Of following month. . . */
             month = month % 12; /* And then normalise it. . . */
         }
         sprintf(temp1, "%d %3.3s", day, mnam[lang -1][month]);
         sprintf(temp, "%s|", center(temp1, bw) );
         strcat(linbuf, temp);
     }
     strcat(linbuf, "\n");
     fputs(linbuf, fp);
   }

     sprintf(linbuf, (sched_type != 'M')?
                            "%s|      |":
                            "%s|", off);
     for (i = wk_day;
          i < (wk_day + 7);
          i++)
     {
         sprintf(temp1, "%3.9s", wkday[lang -1][i % 7]);
         sprintf(temp, "%s|", center(temp1, bw) );
         strcat(linbuf, temp);
     }
     strcat(linbuf, "\n");
     fputs(linbuf, fp);

     if (sched_type == 'M')        /* Monthly calendar */
     {                                /* Months have 5 or 6 weeks */
         bh = 0;
         nh = (yr[y][bm][5][0])?        /* Sixth week, Sunday? */
                            6:        /* Six weeks/month */
                            5;        /* Five weeks/month */
     }

     for (i = bh;
          i < (bh + nh);
          i++)        /* print the hourly lines */
     {
         fputs(sep, fp);                /* print separators */
         if (sched_type == 'M')
         {
             sprintf(hoursw, "%s|", off);/* Initialize hoursw */
             for (j = 0;
                  j < 7;
                  j++)
             {
                 sprintf(temp,
                         yr[y][bm][i][j] ?
                             (base ?
                                 ((base == 'O') ? "%s%2o|" : "%s%2X|" ) :
                                                  "%s%2d|" ) :
                                                  "%s  |",
                         dates,
                         yr[y][bm][i][j]);
                 strcat(hoursw, temp);
             }
             strcat(hoursw, "\n");
         }

         fprintf(fp, hoursw, (i % 24)); /* print hour/week line */

         for (j = 2;
              j < ((pl - 18) / nh);
              j++)
             fputs(spacerw, fp);                /* print spacer line(s) */
     }
     fputs(bnd, fp);                        /* print boundary */

     if(out != 'V') fputs("\f\r", fp);        /* no FF for screen */
     if(out == 'F')                        /* setup for file output */
         if((stat = fclose(fp)) == ERROR)
             printf("\nCan't close %s.\n", file);
 /*  else
         printf("\nClosed %s\n", file);*/
     if(out == 'F')
     {
         if ((stat = rename(file, new_file)) == ERROR)
         {
             printf(
             "\nCan't rename %s to %s.  %s may already exist.\n",
                                  file, new_file, new_file);
         }
     }
 }



 /************************************************************************/
 void get_opts( name)
 char *name;        /* filename from argv[0] */
 {
         /* Various statistics (such as the last time the program was run)
         * are stored in a buffer at the end of the executable structure.
         * These stats and the settings for user selected options are all
         * stored in the "options" structure.  This function creates the
         * data area if it doesn't exist and initializes Opt as appropriate.
         * Alan Holub, C-Chest, DDJ Feb 1988.
         */

     int fd;                /* file descriptor handle */
     int i, *p;                /* used to create checksum */
     void ferr();        /* fatal error handler */

     if( (fd = open( name, O_RDWR | O_BINARY ) ) == ERROR)
     {
         perror( name);
         exit(1);
     }

     lseek(fd, 0L - sizeof(Opt), SEEK_END);

     /* Check to see if all of the options area is still there */
     if( read(fd, (char *) &Opt, sizeof(Opt) ) != sizeof(Opt) )
         ferr( "Internal error:  Can't read options\n");

     /* Check to see if the signature is still as it should be */
     if(strcmp( DEF_SIG, Opt.signature) != 0)
     {
         memset( &Opt, 0, sizeof(Opt));
         /* The memset is for debugging.  It shows us that the record has
          * been written correctly.
          */

         strcpy( Opt.signature, DEF_SIG);
         /* Initialize other fields in the Opt structure here. */
             Opt.aggie        = FALSE;        /* Not all are Aggies! */
         Opt.bh                =  6;                /* Hour defaults to 0600 *
         Opt.copies        =  1;                /* At least one copy. . . */
         Opt.fy                = FALSE;        /* Most are not Fiscal Year */
         Opt.indent      =  7;                /* Left Margin Indent in spaces
         Opt.julian        = FALSE;        /* Regular calendar is default */
         Opt.lang        =  5;                /* Select English as default Lan
         Opt.more_yrs        =  0;                /* One period at a time. . .
         Opt.nh                = 24;                /* Scheduled Hour defaults
         Opt.pause        = FALSE;        /* No pause at end of each printed p
         Opt.pl                = 66;                /* Page Length in lines */
         Opt.pw                = 80;                /* Page Width in character
         Opt.base        = FALSE;        /* Decimal for most */
         Opt.sched_type         = FALSE;        /* Annual calendar is default
         for (i = 0;                        /* Initialize title array */
              i < 8;
              i++)
              Opt.title[i][0] = '\0';

         Opt.chksum = 0;
         for (p = (int *)(&Opt), i = sizeof(Opt) / 2;
              --i >= 0;
                       )
             Opt.chksum -= *p++;

         lseek(fd, 0L, SEEK_END);

         if(write(fd, (char *) &Opt, sizeof(Opt)) != sizeof(Opt) )
             ferr("Internal error:  Can't initialize options\n");
     }
     close(fd);
 }



 void put_opts( name)
 char *name;
 {
     /* Update the options buffer at the end of the .EXE program (which
      * better exist).  If the options buffer doesn't exist, this function
      * will destroy the end of the file.  Alan Holub, C-Chest, DDJ Feb 1988.
      */

     int fd;                        /* file descriptor handle */
     int i, *p, checksum;        /* used to create checksum */
     void ferr();                /* fatal error handler */

     if( (fd = open( name, O_RDWR | O_BINARY) ) == -1)
     {
         perror( name );
         exit(1);
     }

     /* Recompute the checksum */

     checksum = 0;
     for (p = (int *)(&Opt), i = sizeof(Opt) / 2;
        --i >= 0;
                   )
         checksum -= *p++;

     if(checksum != Opt.chksum)
         printf("\tDefaults have been changed.");

     Opt.chksum = checksum;

     lseek(fd, 0L - sizeof(Opt), SEEK_END);
     if(write(fd, (char *) &Opt, sizeof(Opt)) != sizeof(Opt) )
         ferr("Can't do final options update\n");
     close(fd);
 }



 void ferr( fmt)
 char *fmt;
 {
     /* ferr() is used for fatal error processing.  It is used just like
      * printf().  However, it exits the program with a status of 1
      * immediately after printing the message.  I'm using ANSI, not UNIX
      * variable argument conventions here.  (Alan Holub, C-Chest Book, p. 299
      */

     va_list args;
     va_start(args, fmt);
     vfprintf(stderr, fmt, args);
     exit(1);
 }



 YERROR.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\YERROR.C



 YTAB.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\YTAB.C

 /*
  *                   * * *   W A R N I N G    * * *
  *
  * This file has been hand-modified from that which was produced by Yacc
  * from 'lex.y'. If you plan on rebuilding this with Yacc, be SURE to run
  * the virgin supplied 'lex.y' thru Yacc first, do a source compare of it's
  * output 'ytab.c' with this file, and note & understand the manual mods
  * that were made here.
  *                                              Bob Denny
  *
  * Modified 02-Dec-80 Bob Denny -- Conditionalized debug code for smaller siz
  *                                 YYSMALL no longer used.
  *                                 Removed hackish accent grave's.
  *                           01    Moved calls do dfa build, min, print and
  *                                  write, and to stat() to lex.c, so this
  *                                  module could be put in overlay region.
  *                                  Moved impure data out into ytdata.c to
  *                                  go to the root.
  *
  *          29-May-81 Bob Denny -- Define yysterm fwd. Remove from LEXLEX.H.
  *                                   for RSX overlaying.
  *          19-Mar-82 Bob Denny -- New compiler and library. Typcasts needed.
  *                                  Conditionally compile remote formats, not
  *                                  supported in VAX C.
  * More     03-May-82 Bob Denny -- Final touches, remove unreferenced autos
  * More                20-Nov-83 Scott Guthery -- Adapt for IBM PC & DeSmet C
  */

 #include <stdio.h>
 #include "ytab.h"
 #include "lexlex.h"

 char *yysterm[] = {
 "error",
 "NAME",
 "CCLASS",
 "STRING",
 "CONCAT",
 0 };

 /* char copr[] = "Copyright (c) 1978 Charles H. Forsyth";*/

 struct des {
         struct nfa *d_start;
         struct nfa *d_final;
 };
 extern struct nlist {                                           /* 01+ */
         struct  nlist   *nl_next;
         struct  nfa     *nl_base;
         struct  nfa     *nl_end;
         struct  nfa     *nl_start;
         struct  nfa     *nl_final;
         char    *nl_name;
 } *nlist;                                                       /* 01- */

 extern  int     str_length;
 extern  struct  nfa     *elem();
 extern  struct  des     *newdp();
 extern  struct  nlist   *lookup();
 extern int yydebug; /* 1 for debugging */                       /* 01+ */
 extern int yychar; /* current input token number */
 extern int yynerrs ;  /* number of errors */
 extern int yyerrflag ;  /* error recovery flag */               /* 01- */

 #define yyclearin yychar = -1
 #define yyerrok yyerrflag = 0

 #ifndef YYSTYPE
 #define YYSTYPE int

 #endif
 #ifndef YYVCOPY
 #define YYVCOPY(x,y)    (x)=(y)
 #endif

 extern YYSTYPE yyval;                                           /* 01+ */
 extern YYSTYPE *yypv;
 extern YYSTYPE yylval;

 # define YYMAXDEPTH 150
 extern YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */

 extern int      nlook;
 extern int      yyline;
 extern char     *breakc;
 extern char     *ignore;
 extern char     *illeg;                                         /* 01- */

 yyactr(__np__){

         struct nfa *np, *nbase;
         char *cp;
         struct des *dp;
         struct trans *tp;
         struct nlist *nl;
         int i, c;

 switch(__np__){

 case 7:
 {
                 dp = yypv[3];
                 nl = yypv[1];
                 np = nl->nl_base;
                 nl->nl_start = dp->d_start;
                 nl->nl_final = dp->d_final;
                 nl->nl_end = nfap;
 #ifdef DEBUG
                 fprintf(lexlog, "NFA (auxiliary definition) for %s\n",
                                 nl->nl_name);
                 nfaprint(dp->d_start, nl->nl_base);
 #endif
                 nbase = lalloc(i = nl->nl_end-nl->nl_base, sizeof(*nbase),
                         "nfa storage");
                 copynfa(nl, nbase, dp);
                 nl->nl_start = dp->d_start;
                 nl->nl_final = dp->d_final;
                 nl->nl_end = nbase+i;
                 nl->nl_base = nbase;
                 nfap = np;
                 spccl(nl->nl_name, "ignore", dp, &ignore);
                 spccl(nl->nl_name, "break", dp, &breakc);
                 spccl(nl->nl_name, "illegal", dp, &illeg);
         } break;
 case 8:
 { copycode(); } break;
 case 9:
 {
                 yyval = lookup(yypv[1]);

                 ((struct nlist *)yyval)->nl_base = nfap;
                 if (((struct nlist *)yyval)->nl_start)
                         yyerror("%s redefined", ((struct nlist *)yyval)->nl_n
         } break;
 case 10:
 { yyval = lookup(yypv[1]); } break;
 case 11:
 {
                 np = elem(CCL, yypv[1]);
                 yyval = newdp(np, np->n_succ[0] = elem(FIN));
         } break;
 case 12:
 {
                 cp = yypv[1];
                 if (str_length == 0) {
                         np = elem(EPSILON);
                         yyval = newdp(np, np->n_succ[0] = elem(FIN));
                         return;
                 }
                 yyval = np = elem(*cp++);
                 while (--str_length > 0)
                         np = np->n_succ[0] = elem(*cp++);
                 yyval = newdp(yyval, np->n_succ[0] = elem(FIN));
         } break;
 case 13:
 {
                 if ((nl = yypv[1])->nl_end == 0) {
                         yyerror("%s not defined", nl->nl_name);
                         nl->nl_base = nl->nl_end = elem(FIN);
                         nl->nl_start = nl->nl_final = nl->nl_base;
                 }
                 yyval = dp = lalloc(1, sizeof(*dp), "dfa input");
                 nbase = nfap;
                 i = nl->nl_end-nl->nl_base;
                 if ((nfap += i) >= &nfa[MAXNFA]) {
                         yyerror("Out of NFA nodes", NULL);
                         exit(1);
                 }
                 copynfa(nl, nbase, dp);
         } break;
 case 14:
 {
                 yyval = dp = yypv[1];
                 dp->d_start = newnfa(EPSILON, np = dp->d_start, 0);
                 dp->d_final->n_char = EPSILON;
                 dp->d_final->n_succ[0] = np;
                 dp->d_final->n_succ[1] = np = elem(FIN);
                 dp->d_start->n_succ[1] = np;
                 dp->d_final = np;

         } break;
 case 15:
 {
                 yyval = dp = yypv[1];
                 dp->d_start = newnfa(EPSILON, dp->d_start,
                         ((struct des *)yypv[3])->d_start);
                 dp->d_final->n_char = EPSILON;
                 dp->d_final = dp->d_final->n_succ[0] = np = elem(FIN);
                 dp = yypv[3];
                 dp->d_final->n_char = EPSILON;
                 dp->d_final->n_succ[0] = np;
                 free(yypv[3]);
         } break;
 case 16:
 {
                 yyval = yypv[1];
                 dp = yypv[2];
                 np = ((struct des *)yyval)->d_final;
                 ((struct des *)yyval)->d_final = dp->d_final;
                 np->n_char = dp->d_start->n_char;
                 np->n_ccl = dp->d_start->n_ccl;
                 np->n_succ[0] = dp->d_start->n_succ[0];
                 np->n_succ[1] = dp->d_start->n_succ[1];
                 free(yypv[2]);
         } break;
 case 17:
 { yyval = yypv[2]; } break;
 case 18:
 {
                 ending();
         trans1:
 #ifdef DEBUG
                 fprintf(lexlog, "\nNFA for complete syntax\n");
                 fprintf(lexlog, "state 0\n");
                 for (tp = trans; tp < transp; tp++)
                         fprintf(lexlog, "\tepsilon\t%d\n", tp->t_start-nfa);
                 for (tp = trans; tp < transp; tp++)
                         nfaprint(tp->t_start, nfa);
 #else
                 ;
 #endif
                                                                 /* 01 */
         } break;
 case 19:
 { goto trans1; } break;
 case 22:
 {
                 llactr();
         } break;
 case 23:
 { dp = yypv[1];  newtrans(dp->d_start, dp->d_final); } break;
 case 24:
 { copycode(); } break;
 case 25:

 {
                 ending();
                 while ((c = get()) != EOF)
                         putc(c, llout);
         } break;
 case 26:
 { action(); } break;
 case 27:
 {
                 if (nlook >= NBPW)
                         yyerror("More than %d translations with lookahead",
                                         NBPW);
                 yyval = dp = yypv[1];
                 np = dp->d_final;
                 np->n_char = EPSILON;
                 np->n_flag |= LOOK;
                 np->n_succ[0] = ((struct des *)yypv[3])->d_start;
                 dp->d_final = ((struct des *)yypv[3])->d_final;
                 np->n_look = nlook;
                 dp->d_final->n_look = nlook++;
                 dp->d_final->n_flag |= FLOOK;
                 free(yypv[3]);
         } break;
 }
 }
 int yyerrval = 256;

 /*
  * Lexical analyser
  * (it isn't done with lex...)
  */
 extern char     buffer[150];                                    /* 01 */

 yylex()
 {
         register c;
         register char *cp;
         int lno;

         if (yyline == 0)
                 yyline++;
 loop:
         c = get();
         if (isupper(c)) {
                 name(c);
                 for (cp = yylval; c = *cp; cp++)
                         if (isupper(c))
                                 *cp = tolower(c);
                 return(STRING);
         } else if (islower(c) || c == '_') {
                 name(c);
                 return(NAME);

         }
         switch (c) {
         case -1 /*EOF*/:
                 return(0);

         case '[':
                 return(cclass());

         case '(':
         case ')':
         case '{':
         case '}':
         case '*':
         case '|':
         case '=':
         case ';':
         case '%':
                 return(c);

         case '/':
                 if ((c = get()) != '*') {
                         unget(c);
                         return('/');
                 }
                 lno = yyline;
                 for (; c != EOF; c = get())
                         if (c == '*')
                                 if ((c = get()) == '/')
                                         goto loop; else
                                         unget(c);
                 yyline = lno;
                 yyerror("End of file in comment", NULL);

         case '\'':
         case '"':
                 yylval = buffer;
                 string(c);
                 return(STRING);

         case '\n':
                 case '\r':
         case ' ':
         case '\t':
                 goto loop;

         default:
                 yylval = buffer;
                 buffer[0] = c;
                 buffer[1] = 0;
                 str_length = 1;
                 return(STRING);
         }
 }

 extern char     ccl[(NCHARS+1)/NBPC];                           /* 01 */

 cclass()
 {
         register c, i, lc;
         int compl;

         compl = 0;
         for (i = 0; i < sizeof ccl; i++)

                 ccl[i] = 0;
         if ((c = get()) == '^')
                 compl++; else
                 unget(c);
         lc = -1;
         while ((c = mapc(']')) != EOF) {
                 if (c == '-' && lc >= 0) {
                         if ((c = mapc(']')) == EOF)
                                 break;
                         for (i = lc; i <= c; i++)
                                 ccl[i/NBPC] |= 1<<(i%NBPC);
                         lc = -1;
                         continue;
                 }
                 ccl[c/NBPC] |= 1<<(c%NBPC);
                 lc = c;
         }
         if (compl) {
                 for (i = 0; i < sizeof ccl; i++)
                         ccl[i] ^= -1;
                 if (aflag == 0)
                         for (i = 0200; i < (1<<NBPC); i++)
                                 ccl[i/NBPC] &= ~(1 << (i%NBPC));
         }
         yylval = newccl(ccl);
         return(CCLASS);
 }

 string(ec)
 {
         register char *cp;
         register c;

         for (cp = buffer; (c = mapc(ec)) != EOF;)
                 *cp++ = c;
         *cp = 0;
         str_length = cp-buffer;
 }

 mapc(ec)
 {
         register c, v, i;

         if ((c = get()) == ec)
                 return(EOF);
         switch(c) {
         case -1 /*EOF*/:
                 yyerror("End of file in string", NULL);
                 return(c);

         case '\\':
                 if ((c = get()) >= '0' && c <= '7') {
                         i = 0;
                         for (v = 0; c>='0' && c<='7' && i++<3; c = get())
                                 v = v*010 + c-'0';
                         unget(c);
                         return(v&0377);
                 }
                 switch (c) {
                 case 'n':
                         return('\n');
                 case 't':
                         return('\t');

                 case 'b':
                         return('\b');

                 case 'r':
                         return('\r');

                 case '\n':
                         yyline++;
                         return(mapc(ec));
                 }

         default:
                 return(c);
         }
 }

 name(c)
 register c;
 {
         register char *cp;

         for (yylval=cp=buffer; isalpha(c) || isdigit(c) || c=='_'; c=get())
                 *cp++ = c;
         *cp = 0;
         str_length = cp-buffer;
         unget(c);
 }

 /*
  * Miscellaneous functions
  * used only by lex.y
  */
 struct nfa *
 elem(k, v)
 {
         struct nfa *fp;

         fp = newnfa(k, 0, 0);
         if (k == CCL)
                 fp->n_ccl = v;
         return(fp);
 }

 struct des *
 newdp(st, fi)
 struct nfa *st, *fi;
 {
         register struct des *dp;

         dp = lalloc(1, sizeof(*dp), "dfa input");
         dp->d_start = st;
         dp->d_final = fi;
         return(dp);
 }

 action()
 {
         register c;
         int lno, lev;

         newcase(transp-trans);
         lno = yyline;
         lev = 0;
         for (; (c = get()) != EOF && (c != '}' || lev); putc(c, llout))
                 if (c == '{')
                         lev++;
                 else if (c == '}')
                         lev--;
                 else if (c == '\'' || c == '"') {
                         putc(c, llout);
                         skipstr(c);
                 }
         fprintf(llout, "\n         break;\n");
         if (c == EOF) {
                 yyline = lno;
                 yyerror("End of file in action", NULL);
         }
 }

 skipstr(ec)
 register ec;
 {
         register c;

         while ((c = get()) != ec && c != EOF) {
                 putc(c, llout);
                 if (c == '\\' && (c = get()) != EOF)
                         putc(c, llout);
         }
 }

 copycode()
 {
         int lno;
         register c;

         setline();
         lno = yyline;
         for (; (c = get()) != EOF; putc(c, llout))
                 if (c == '%') {
                         if ((c = get()) == '}')
                                 return;
                         unget(c);
                         c = '%';
                 }
         yyline = lno;
         yyerror("Incomplete %{ declaration", NULL);
         exit(1);
 }

 struct nlist *
 lookup(s)
 register char *s;
 {
         register struct nlist *nl;
         register char *cp;
         int i;
         for (nl = nlist; nl; nl = nl->nl_next)
                 if (!strcmp(s, nl->nl_name))
                         return(nl);

         nl = lalloc(1, sizeof(*nl), "namelist");
         nl->nl_start = nl->nl_end = nl->nl_base = nl->nl_end = 0;
         nl->nl_next = nlist;
         nlist = nl;
         i = 0;
         nl->nl_name = cp = lalloc(strlen(s) + 1, sizeof(*cp), "namelist");
         strcpy(cp, s);
         return(nl);
 }

 copynfa(nl, nbase, dp)
 struct nlist *nl;
 struct des *dp;
 struct nfa *nbase;
 {
         register struct nfa *np, *ob;
         register j;
         int i;

         ob = nl->nl_base;
         i = nl->nl_end-ob;
         copy(nbase, ob, sizeof(*np) * i);
         for (np = nbase; i-- > 0; np++) {
                 np->n_flag &= ~NPRT;
                 for (j = 0; j < 2; j++)
                         if (np->n_succ[j])
                                 np->n_succ[j] = (np->n_succ[j]-ob)+nbase;
         }
         dp->d_start = (nl->nl_start-ob)+nbase;
         dp->d_final = (nl->nl_final-ob)+nbase;
 }

 copy(out, in, count)
 register char   *out;
 register char   *in;
 register int    count;
 {
         while (--count >= 0)
                 *out++ = *in++;
 }

 spccl(nm, isit, dp, where)
 char                    *nm;
 char                    *isit;
 register struct des     *dp;
 char                    **where;
 {

         if (!strcmp(nm, isit)) {
                 if (*where != 0)
                         yyerror("Redefinition of %s class", isit);
                 if (dp->d_start->n_char == CCL &&
                                 dp->d_start->n_succ[0] == dp->d_final)
                         *where = dp->d_start->n_ccl;
                 else
                         yyerror("Illegal %s class", isit);
         }
 }

 get()
 {
         register int c;

         if ((c = unix_getc(lexin)) == '\n')
                 yyline++;
         return(c);
 }

 unget(c)
 register c;
 {
         if (c == '\n')
                 yyline--;
         ungetc(c, lexin);
 }

 yyerror(format, value)
 char *format, *value;
 {
                 char buffer[50];
         if (yyline)
                 fprintf(stderr, "%d: ", yyline);
         fprintf(stderr, format, value);
         if (yychar > 256)
                 fprintf(stderr, " near '%s'", yysterm[yychar-256]);
         else if (yychar < 256 && yychar > 0)
                 fprintf(stderr, " near '%c'", yychar);
         fprintf(stderr, "\n");
 }

 int nterms = 15;
 int nnonter = 13;
 int nstate = 41;

 char *yysnter[14] = {
 "$accept",
 "lexfile",
 "auxiliary_section",
 "translation_section",
 "auxiliaries",
 "auxiliary",
 "namedef",
 "regexp",
 "name",
 "translations",
 "translation",
 "llactr",
 "pattern",
 "action" };

 int yylast = 245;
 yyexcp(s)
 int s;
 {
         switch(s){
         case 1:
                 if( yychar == 0 ) return( -1 );
                 return( 0 );
         case 2:
                 if( yychar == 0 ) return( 19 );
                 return( 22 );
                 }
         }

 yyact[] = {

   23,  40,  32,  23,  29,  32,  23,  15,  32,  23,
   31,  32,  23,  35,  32,  18,  26,  13,  23,  32,
   34,  23,  37,  11,   4,   5,  16,  28,  17,  12,
   19,  19,  10,   9,  22,   6,  27,  25,   3,   8,
    2,   1,   0,   0,  36,   0,   0,   0,   0,   0,
    0,   0,   0,   0,  38,   0,  39,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,  33,   0,   0,  33,   0,   0,
   33,   0,   0,  33,   0,   0,  30,   0,   0,   0,
    0,   0,  14,  14,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,

    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,  24,  20,  21,
   24,  20,  21,  24,  20,  21,  24,  20,  21,  24,
   20,  21,   0,   0,   0,  24,  20,  21,  24,  20,
   21,   0,   0,   7,   7 };
 yypact[] = {

  -13,-2000,-2000, -14, -20,-1000, -54,-1000,-1000, -22,
  -22, -21,-1000,-1000,-1000, -19,-1000,-119, -27, -34,
 -1000,-1000,-1000, -19,-1000,-1000,-1000, -37,-1000,-1000,
 -1000,-1000,-1000, -19, -23, -19, -40,-1000, -28, -31,
 -1000 };
 yypgo[] = {

    0,  41,  40,  39,  38,  25,  35,  20,  34,  33,
   26,  32,  28,  27 };
 yyr1[] = {

    0,   1,   1,   2,   2,   4,   4,   5,   5,   6,
    8,   7,   7,   7,   7,   7,   7,   7,   3,   3,
    9,   9,  11,  10,  10,  10,  13,  12,  12,  -1 };
 yyr2[] = {

    0,   2,   0,   3,   2,   2,   1,   4,   2,   1,
    1,   1,   1,   1,   2,   3,   2,   3,   1,   0,
    2,   2,   0,   2,   2,   2,   1,   3,   1,  -1 };
 yychk[] = {

    0,  -1,  -2,  -4,  37,  -5,  -6, 257,  -3,  -9,
  -11,  37,  -5,  37, 123,  61, -10, -12,  37,  -7,
  258, 259,  -8,  40, 257, -10,  37,  -7, -13, 123,
  123,  37,  42, 124,  -7,  47,  -7,  59,  -7,  -7,
   41 };
 yydef[] = {

    2,  -2,  -2,   0,   0,   6,   0,   9,   1,  18,
    0,   0,   5,   4,   8,   0,  20,   0,   0,  28,
   11,  12,  13,   0,  10,  21,   3,   0,  23,  26,
   24,  25,  14,   0,  16,   0,   0,   7,  15,  27,
   17 };

 # define YYFLAG1 -1000
 # define YYFLAG2 -2000

 /* test me on cases where there are more than one reduction
 per state, leading to the necessity to look ahead, and other
 arcane flows of control.
 */

 /*      parser for yacc output  */
 /* extern YYSTYPE yyval;        -- defined in the table file
  * extern YYSTYPE yylval;       -- defined in the table file
  * extern YYSTYPE *yypv;        -- defined in the table file
  */

 #ifdef  DEBUG
 #define LOGOUT  lexlog
 #endif

 yyparse() {
    int yys[YYMAXDEPTH];
    int yyj;
    register yyn, yystate, *yyps;

    yystate = 0;
    yychar = -1;
    yynerrs = 0;
    yyerrflag = 0;
    yyps= &yys[0]-1;
    yypv= &yyv[0]-1;

  yystack:    /* put a state and value onto the stack */

 #ifdef DEBUG
    if( yydebug  )
         fprintf(LOGOUT, "state %d, value %d, char %d\n",yystate,yyval,yychar)
 #endif

    *++yyps = yystate;
    *++yypv = yyval;

  yynewstate:

    yyn = yypact[yystate];

    if( yyn<= YYFLAG1 ){ /* simple state */
       if( yyn == YYFLAG2 && yychar<0 ) yychar = yylex();
       goto yydefault;
       }

    if( yychar<0 ) yychar = yylex();
    if( (yyn += yychar)<0 || yyn >= yylast ) goto yydefault;

    if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
       yychar = -1;
       yyval = yylval;
       yystate = yyn;
       if( yyerrflag > 0 ) --yyerrflag;
       goto yystack;
       }

  yydefault:
    /* default state action */

    if( (yyn=yydef[yystate]) == -2 ) yyn = yyexcp( yystate );

   if( yyn == -1 ){ /* accept */
       return( 0 );

       }

    if( yyn == 0 ){ /* error */
       /* error ... attempt to resume parsing */

       switch( yyerrflag ){

       case 0:   /* brand new error */

          ++yynerrs;
          yyerror("syntax error", NULL);

       case 1:
       case 2: /* incompletely recovered error ... try again */

          yyerrflag = 3;

          /* find a state where "error" is a legal shift action */

          while ( yyps >= yys ) {
             yyn = yypact[*yyps] + yyerrval;
             if( yyn>= 0 && yyn < yylast && yychk[yyact[yyn]] == yyerrval ){
                yystate = yyact[yyn];  /* simulate a shift of "error" */
                goto yystack;
                }
             yyn = yypact[*yyps];

             /* the current yyps has no shift onn "error", pop stack */

 #ifdef DEBUG
             if(yydebug)
                 fprintf(LOGOUT, "error recovery pops state %d, uncovers %d\n"
                         *yyps, yyps[-1]);
 #endif
             --yyps;
             --yypv;
             }

          /* there is no state on the stack with an error shift ... abort */

     abort:
          return(1);

       case 3:  /* no shift yet; clobber input char */

 #ifdef DEBUG
          if (yydebug)
                 fprintf(LOGOUT, "error recovery discards char %d\n", yychar )
 #endif

          if( yychar == 0 ) goto abort; /* don't discard EOF, quit */
          yychar = -1;
          goto yynewstate;   /* try again in the same state */

          }

       }

    /* reduction by production yyn */

 #ifdef DEBUG
       if(yydebug) fprintf(LOGOUT, "reduce %d\n",yyn);
 #endif

       yyps -= yyr2[yyn];
       yypv -= yyr2[yyn];
 /*    YYVCOPY(yyval,yypv[1]);
  */   yyval = yypv[1];
       yyactr(yyn);
          /* consult goto table to find next state */
       yyn = yyr1[yyn];
       yyj = yypgo[yyn] + *yyps + 1;
       if( yyj>=yylast || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yy
       goto yystack;  /* stack new state and value */

    }


 YYLESS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\YYLESS.C

 yyless(x)

    {
    extern char yytext[];
    register char *lastch, *ptr;
    extern int yyleng;
    extern int yyprevious;
    lastch = yytext+yyleng;
    if (x>=0 && x <= yyleng)
       ptr = x + yytext;
    else
       ptr = x;
    while (lastch > ptr)
       yyunput(*--lastch);
    *lastch = 0;
    if (ptr >yytext)
       yyprevious = *--lastch;
    yyleng = ptr-yytext;
    }


 YYLEX.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\LEX\YYLEX.C

 /*
  * Bob Denny 28-Aug-82  Remove reference to stdio.h
  * Remove code to default lexin, change to call to
  * llstin(), generated by lex depending upon setting
  * of "-s" switch.  Eliminates hardwired dependency
  * on standard I/O library.  Moved declaration of
  * lexin to lexgetc().
  *
  * Bob Denny 31-Aug-82  Add call to lexswitch() in
  * the generated file, to switch to the table whose
  * name was given in the "-t" switch (or to "lextab"
  * if "-t" wasn't given).  Removed hardwired setting
  * of _tabp --> "lextab" here. Now handled automagically.
  *
  * Bob Denny 21-Oct-82  Add llinit() function to re-initialize
  * yylex(), making it serially reusable.
  *
  * Initialize _tabp to NULL so lexswitch() to real table happens
  * only once.
  *
  * Bob Denny 15-Apr-83 Move NBPW to LEX.H and make it 32 on VAX native,
  *                     else 16.
  * Scott Guthery 20-Nov-83        Adapt for IBM PC & DeSmet C
  */

 /*
  * yylex for lex tables
  */

 #include <lex.h>

 ERROR   256     /* yacc's value */

 tst__b(c, tab)
 register int    c;
 char            tab[];
 {
         return(tab[(c >> 3) & 037] & (1 << (c & 07)) );
 }

 struct  lextab  *_tabp = 0;

 extern char     *llsave[];      /* Right-context buffer                 */
 char    llbuf[100];             /* work buffer                          */
 char    *llp1   = &llbuf[0];    /* pointer to next avail. in token      */
 char    *llp2   = &llbuf[0];    /* pointer to end of lookahead          */
 char    *llend  = &llbuf[0];    /* pointer to end of token              */
 char    *llebuf = &llbuf[sizeof llbuf];
 int     lleof;
 int     yylval  = 0;
 int     yyline  = 0;

 yylex()
 {
         register int c, st;
         int final, l, llk, i;

         register struct lextab *lp;
         char *cp;

         /*
          * Call llstin() to default lexin to stdin
          * and assign _tabp to "real" table.
          */
         llstin();                       /* Initialize yylex() variables */

 loop:
         llk = 0;
         if (llset())
                 return(0);              /* Prevent EOF loop     */
         st = 0;
         final = -1;
         lp = _tabp;

         do {
                 if (lp->lllook && (l = lp->lllook[st])) {
                         for (c=0; c<NBPW; c++)
                                 if (l&(1<<c))
                                         llsave[c] = llp1;
                         llk++;
                 }
                 if ((i = lp->llfinal[st]) != -1) {
                         final = i;
                         llend = llp1;
                 }
                 if ((c = llinp()) < 0)
                         break;
                 if ((cp = lp->llbrk) && llk==0 && tst__b(c, cp)) {
                         llp1--;
                         break;
                 }
         } while ((st = (*lp->llmove)(lp, c, st)) != -1);


         if (llp2 < llp1)
                 llp2 = llp1;
         if (final == -1) {
                 llend = llp1;
                 if (st == 0 && c < 0)
                         return(0);
                 if ((cp = lp->llill) && tst__b(c, cp)) {
                         lexerror("Illegal character: %c (%03o)", c, c);
                         goto loop;
                 }
                 return(ERROR);
         }
         if (c = (final >> 11) & 037)
                 llend = llsave[c-1];
         if ((c = (*lp->llactr)(final&03777)) >= 0)
                 return(c);
         goto loop;
 }

 llinp()
 {

         register c;
         register struct lextab *lp;
         register char *cp;

         lp = _tabp;
         cp = lp->llign;                         /* Ignore class         */
         for (;;) {
                 /*
                  * Get the next character from the save buffer (if possible)
                  * If the save buffer's empty, then return EOF or the next
                  * input character.  Ignore the character if it's in the
                  * ignore class.
                  */
                 c = (llp1 < llp2) ? *llp1 & 0377 : (lleof) ? EOF : lexgetc();
                 if (c >= 0) {                   /* Got a character?     */
                         if (cp && tst__b(c, cp))
                                 continue;       /* Ignore it            */
                         if (llp1 >= llebuf) {   /* No, is there room?   */
                                 lexerror("Token buffer overflow");
                                 exit(1);
                         }
                         *llp1++ = c;            /* Store in token buff  */
                 } else
                         lleof = 1;              /* Set EOF signal       */
                 return(c);
         }
 }

 llset()
 /*
  * Return TRUE if EOF and nothing was moved in the look-ahead buffer
  */
 {
         register char *lp1, *lp2;

         for (lp1 = llbuf, lp2 = llend; lp2 < llp2;)
                 *lp1++ = *lp2++;
         llend = llp1 = llbuf;
         llp2 = lp1;
         return(lleof && lp1 == llbuf);
 }

 /*
  * Re-initialize yylex() so that it can be re-used on
  * another file.
  */
 llinit()
    {
    llp1 = llp2 = llend = llbuf;
    llebuf = llbuf + sizeof(llbuf);
    lleof = yylval = yyline = 0;
    }


 YYPARS.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\YYPARS.C

 # define YYFLAG -1000
 # define YYERROR goto yyerrlab
 # define YYACCEPT return(0)
 # define YYABORT return(1)

 /*      parser for yacc output  */

 int yydebug = 0; /* 1 for debugging */
 YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
 int yychar = -1; /* current input token number */
 int yynerrs = 0;  /* number of errors */
 short yyerrflag = 0;  /* error recovery flag */

 yyparse()
    {

    short yys[YYMAXDEPTH];
    short yyj, yym;
    register YYSTYPE *yypvt;
    register short yystate, *yyps, yyn;
    register YYSTYPE *yypv;
    register short *yyxi;

    yystate = 0;
    yychar = -1;
    yynerrs = 0;
    yyerrflag = 0;
    yyps= &yys[-1];
    yypv= &yyv[-1];

 yystack:    /* put a state and value onto the stack */

    if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
    if( ++yyps> &yys[YYMAXDEPTH] )
       {
       yyerror( "yacc stack overflow" );
       return(1);
       }
    *yyps = yystate;
    ++yypv;
 #ifdef UNION
    yyunion(yypv, &yyval);
 #else
    *yypv = yyval;
 #endif
 yynewstate:

    yyn = yypact[yystate];

    if( yyn<= YYFLAG ) goto yydefault; /* simple state */

    if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
    if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;

    if( yychk[ yyn=yyact[ yyn ] ] == yychar )
       {
       /* valid shift */
       yychar = -1;
 #ifdef UNION
           yyunion(&yyval, &yylval);
 #else
       yyval = yylval;
 #endif
       yystate = yyn;
       if( yyerrflag > 0 ) --yyerrflag;
       goto yystack;
       }
 yydefault:
    /* default state action */

    if( (yyn=yydef[yystate]) == -2 )
       {
       if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
       /* look through exception table */

       for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ;

       for(yyxi+=2; *yyxi >= 0; yyxi+=2)
          {
          if( *yyxi == yychar ) break;
          }
       if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
       }

    if( yyn == 0 )
       {
       /* error */
       /* error ... attempt to resume parsing */

       switch( yyerrflag )
          {

       case 0:   /* brand new error */

          yyerror( "syntax error" );
 yyerrlab:
          ++yynerrs;

       case 1:
       case 2: /* incompletely recovered error ... try again */

          yyerrflag = 3;

          /* find a state where "error" is a legal shift action */

          while ( yyps >= yys )
             {
             yyn = yypact[*yyps] + YYERRCODE;
             if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE )
                {
                yystate = yyact[yyn];  /* simulate a shift of "error" */
                goto yystack;
                }
             yyn = yypact[*yyps];

             /* the current yyps has no shift onn "error", pop stack */

             if( yydebug ) printf( "error recovery pops state %d, uncovers %d\
             --yyps;
             --yypv;
             }

          /* there is no state on the stack with an error shift ... abort */

 yyabort:
          return(1);


       case 3:  /* no shift yet; clobber input char */

          if( yydebug ) printf( "error recovery discards char %d\n", yychar );

          if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
          yychar = -1;
          goto yynewstate;   /* try again in the same state */

          }

       }

    /* reduction by production yyn */

    if( yydebug ) printf("reduce %d\n",yyn);
    yyps -= yyr2[yyn];
    yypvt = yypv;
    yypv -= yyr2[yyn];
 #ifdef UNION
    yyunion(&yyval, &yypv[1]);
 #else
    yyval = yypv[1];
 #endif
    yym=yyn;
    /* consult goto table to find next state */
    yyn = yyr1[yyn];
    yyj = yypgo[yyn] + *yyps + 1;
    if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact
    switch(yym)
       {
       $A
       }
    goto yystack;  /* stack new state and value */

    }


 YYWRAP.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\COMM\YACCUNX\YYWRAP.C



































































 yywrap()

    {
    return(1);
    }


 Z309.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\LIB\ME39SRC2\Z309.C

 /*
  * The routines in this file provide support for the Zenith Z-100 PC
  * family.  It goes directly to the graphics RAM to do screen output.
  * It compiles into nothing if not a Zenith driver.
  */

        termdef        1                        /* don't define "term" externa

 #include        <stdio.h>
 #include        "estruct.h"
 #include        "edef.h"

 #if     Z309

 /* set NROW to 25 for 25-line interlaced mode */
 NROW    50                      /* Screen size.                 */
 NCOL    80                      /* Edit if you want to.         */
        MARGIN        8                        /* size of minimim margin and
        SCRSIZ        64                        /* scroll size for extended li
        NPAUSE        200                        /* # times thru update to pau
 BEL     0x07                    /* BEL character.               */
 ESC     0x1B                    /* ESC character.               */
        SPACE        32                        /* space character

        SCADC        0xb8000000L                /* CGA address of screen RAM
        SCADM        0xb0000000L                /* MONO address of screen RAM

        CDMONO        0                        /* monochrome text card
        CDCGA50        1                        /* 50-line color graphics card
 CDCGI25 2                        /* 25-line interlaced CGA text        */
 CDCGA25 3                        /* 25-line color graphics card        */
        CDSENSE        9                        /* detect the card type

 int dtype = CDCGA50;                        /* current display type
 long scadd;                                /* address of screen ram        */
 int *scptr[NROW];                        /* pointer to screen lines        */
 int sline[NCOL];                        /* screen line image                *
 extern union REGS rg;                        /* cpu register for use of DOS c

 extern  int     ttopen();               /* Forward references.          */
 extern  int     ttgetc();
 extern  int     ttputc();
 extern  int     ttflush();
 extern  int     ttclose();
 extern  int     z309move();
 extern  int     z309eeol();
 extern  int     z309eeop();
 extern  int     z309beep();
 extern  int     z309open();
 extern        int        z309rev();
 extern        int        z309cres();
 extern        int        z309close();
 extern        int        z309putc();
 extern        int        z309kopen();
 extern        int        z309kclose();

 #if        COLOR
 extern        int        z309fcol();
 extern        int        z309bcol();

 int        cfcolor = -1;                /* current forground color */
 int        cbcolor = -1;                /* current background color */
 int        ctrans[] =                /* ansi to z309 color translation table
         {0, 4, 2, 6, 1, 5, 3, 7};
 #endif

 /*
  * Standard terminal interface dispatch table. Most of the fields point into
  * "termio" code.
  */
 TERM    term    = {
         NROW-1,
         NROW-1,
         NCOL,
         NCOL,
         MARGIN,
         SCRSIZ,
         NPAUSE,
         z309open,
         z309close,
         z309kopen,
         z309kclose,
         ttgetc,
         z309putc,
         ttflush,
         z309move,
         z309eeol,
         z309eeop,
         z309beep,
         z309rev,
         z309cres
 #if        COLOR
         , z309fcol,
         z309bcol
 #endif
 };

 extern union REGS rg;

 #if        COLOR
 z309fcol(color)                /* set the current output color */

 int color;        /* color to set */

 {
         cfcolor = ctrans[color];
 }

 z309bcol(color)                /* set the current background color */

 int color;        /* color to set */

 {
         cbcolor = ctrans[color];
 }
 #endif
 z309move(row, col)
 {
         rg.h.ah = 2;                /* set cursor position function code */
         rg.h.dl = col;
         rg.h.dh = row;
         rg.h.bh = 0;                /* set screen page number */
         int86(0x10, &rg, &rg);
 }

 z309eeol()        /* erase to the end of the line */

 {
         int attr;        /* attribute byte mask to place in RAM */
         int *lnptr;        /* pointer to the destination line */
         int i;
         int ccol;        /* current column cursor lives */
         int crow;        /*           row        */

         /* find the current cursor position */
         rg.h.ah = 3;                /* read cursor position function code */
         rg.h.bh = 0;                /* current video page */
         int86(0x10, &rg, &rg);
         ccol = rg.h.dl;                /* record current column */
         crow = rg.h.dh;                /* and row */

         /* build the attribute byte and setup the screen pointer */
 #if        COLOR
         if (dtype != CDMONO)
                 attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
         else
                 attr = 0x0700;
 #else
         attr = 0x0700;
 #endif
         lnptr = &sline[0];
         for (i=0; i < term.t_ncol; i++)
                 *lnptr++ = SPACE | attr;

 0        /* Heath/Zenith builds flicker-less CGAs */
         if (flickcode) {
                 /* wait for vertical retrace to be off */
                 while ((inp(0x3da) & 8))
                         ;

                 /* and to be back on */
                 while ((inp(0x3da) & 8) == 0)
                         ;
         }
 #endif

         /* and send the string out */
         movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2);

 }

 z309putc(ch)        /* put a character at the current position in the
                    current colors */

 int ch;

 {
         rg.h.ah = 14;                /* write char to screen with current att
         rg.h.al = ch;
 #if        COLOR
         if (dtype != CDMONO)
                 rg.h.bl = cfcolor;
         else
                 rg.h.bl = 0x07;
 #else
         rg.h.bl = 0x07;
 #endif
         int86(0x10, &rg, &rg);
 }

 z309eeop()
 {
         int attr;                /* attribute to fill screen with */

         rg.h.ah = 6;                /* scroll page up function code */
         rg.h.al = 0;                /* # lines to scroll (clear it) */
         rg.x.cx = 0;                /* upper left corner of scroll */
 /*HERE*/        rg.x.dx = 0x184f;        /* lower right corner of scroll */
 #if        COLOR
         if (dtype != CDMONO)
                 attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15)
         else
                 attr = 0;
 #else
         attr = 0;
 #endif
         rg.h.bh = attr;
         int86(0x10, &rg, &rg);
 }

 z309rev(state)                /* change reverse video state */

 int state;        /* TRUE = reverse, FALSE = normal */

 {
         /* This never gets used under the z309-PC driver */
 }

 z309cres(res)        /* change screen resolution */

 char *res;        /* resolution to change to */

 {
         if (strcmp(res, "CGA50") == 0) {
                 scinit(CDCGA50);
                 return(TRUE);
         } else if (strcmp(res, "MONO") == 0) {
                 scinit(CDMONO);
                 return(TRUE);
         } else
                 return(FALSE);
 }

 z309beep()
 {
 #if        MWC86
         putcnb(BEL);
 #else
         bdos(6, BEL, 0);
 #endif
 }

 z309open()
 {
         scinit(CDSENSE);
         revexist = TRUE;
         ttopen();
 }

 z309close()

 {
         rg.h.ah = 101;
         rg.h.al = 1;        /* 25-line interlace mode */
         int86(0x10, &rg, &rg);
 #if        COLOR
         z309fcol(7);
         z309bcol(0);
 #endif
         ttclose();
 }

 z309kopen()        /* open the keyboard */

 {
 }

 z309kclose()        /* close the keyboard */

 {
 }

 scinit(type)        /* initialize the screen head pointers */

 int type;        /* type of adapter to init for */

 {
         union {
                 long laddr;        /* long form of address */
                 int *paddr;        /* pointer form of address */
         } addr;
         int i;

         /* if asked...find out what display is connected */
         int86(0x11, &rg, &rg);
         dtype = CDCGA50;
         scadd = SCADC;
         strcpy(sres, "CGA50");
         if ((((rg.x.ax >> 4) & 11) == 3) || type == CDMONO) {
                 strcpy(sres, "MONO");
                 dtype = CDMONO;
                 scadd = SCADM;
         }
         else {
                 rg.h.ah = 101;
 /* set al = 1 for 25-line interlace mode */
                 rg.h.al = 2;        /* 50-line interlace mode */
                 int86(0x10, &rg, &rg);
         }

         /* initialize the screen pointer array */
         for (i = 0; i < NROW; i++) {
                 addr.laddr = scadd + (long)(NCOL * i * 2);
                 scptr[i] = addr.paddr;
         }
 }

 scwrite(row, outstr, forg, bacg)        /* write a line out*/

 int row;        /* row of screen to place outstr on */
 char *outstr;        /* string to write out (must be term.t_ncol long) */
 int forg;        /* forground color of string to write */
 int bacg;        /* background color */

 {
         int attr;        /* attribute byte mask to place in RAM */
         int *lnptr;        /* pointer to the destination line */
         int i;

         /* build the attribute byte and setup the screen pointer */
 #if        COLOR
         if (dtype != CDMONO)
                 attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) <<
         else
                 attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
 #else
         attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
 #endif
         lnptr = &sline[0];
         for (i=0; i<term.t_ncol; i++)
                 *lnptr++ = (outstr[i] & 255) | attr;

 0        /* Heath/Zenith builds flicker-less CGAs */
         if (flickcode) {
                 /* wait for vertical retrace to be off */
                 while ((inp(0x3da) & 8))
                         ;

                 /* and to be back on */
                 while ((inp(0x3da) & 8) == 0)
                         ;
         }
 #endif

         /* and send the string out */
         movmem(&sline[0], scptr[row],term.t_ncol*2);
 }

 #if        FLABEL
 fnclabel(f, n)                /* label a function key */

 int f,n;        /* default flag, numeric argument [unused] */

 {
         /* on machines with no function keys...don't bother */
         return(TRUE);
 }
 #endif
 #else
 z309hello()
 {
 }
 #endif


 ZAPLOAD.C
 CD-ROM Disc Path:   \SAMPCODE\ALDE_C\MISC\UTIL\ZAPLOAD\ZAPLOAD.C

 #include <stdio.h>
 #include <ctype.h>

         /********************************************************
         *                                                        *
         *        ZAPLOAD -- Binary to Intel hex Conversion        *
         *                        Utility                                *
         *                                                        *
         *                T. Jennings 26 Sept. 82                        *
         *                                                        *
         *                                                        *
         ********************************************************/

 /*        A nearly universal utility for converting binary to Intel hex
         outputting to one or more devices. See ZAPLOAD.DOC for details.

         A terminating record is sent following the last data record,
         to indicate end of load and to pass the start address.

         OPERATION:

         ZAPLOAD <file> <options>

                 where <file> is any legal filespec, and
                 <options> are one or more of the following options:

                 -B <number> Generate records of <number> bytes per record.
                         This must be less than 1025.
                 -L <number> Set starting address(default 0000)
                 -W <number> Delay between character transmission, where
                         <number> is a variable. No fixed time scale.
                 -M <number> delay at end of line.
                 -R <number> Set the run address to <number>. Default 0000 hex
                 -S <number> Skip <number> bytes at the beginning of the file,

                 -A        transmit the file to the AUX device.
                 -F        Send the data to disk file <file>

                 -Z        Generate 1's complement check sums.
                 -E        Do even bytes only,
                 -O        Do odd bytes only,
                 -X         Enable console output
                 -N        No EOF record generated.

         Each record is echoed on the console for verification. */

 int        inbuf,outbuf,punch;
 char        infile[18];
 char        outfile[18];
 char        record[1024];                /* this is very big!!! */

 int        sum_type;                /* 0 means 1's compl., 1 means 2's */
 int        disk_file;                /* true means send to the disk file */
 int         send_tuart;                /* true to send to TUART port C */
 int        send_pch;                /* true if sending to the punch, */
 int        dsk_err;                /* disk file error */
 unsigned load_address;                /* load address */
 unsigned start_address;                /* Starting address, */
 int        byte_count;                /* number of bytes to send, */
 int        delay;                        /* software delay counter, */
 int        eol_delay;
 int        console;                /* true if echoing to the console */
 int        alt_byte;                /* true if doing alternate bytes, */
 int        lsb;                        /* 1 if doing odd bytes, */
 int        doeof;                        /* true if making an EOF record. */
 int        skip;                        /* bytes to skip at start of file */
 int        byte_addr;                /* byte address in file, */
 unsigned datasum;                /* eyeball check checksum */
 int        eof;                        /* true at end of file */

 #define        CR        0x0d
 #define        LF        0x0a
 #define        ERROR        -1
 #define        TRUE        -1
 #define        FALSE        0
 #define        OK        0
 #define        NONE        0
        MAX_BYTES 64        /* max # data bytes in a record */
 MIN_BYTES 8        /* minimum bytes, */

 formfeed()
 {}

 /* Start by verifying the command line; must have at least one
 argument, the file. Get any options, and if the guy screws up,
 announce the proper way to invoke the program. */

 main(argc,argv)
 int        argc;
 char        **argv;
 {

 char        *s;
 int        is_ok;
 char        arg;

         is_ok=FALSE;                        /* set as bad cmd. line, */
         send_tuart =FALSE;                /* send to LST: port, */
         send_pch =FALSE;                /* send it to the punch, */
         disk_file =FALSE;                /* no disk file, */
         dsk_err =FALSE;                        /* no error yet, */
         doeof =TRUE;                        /* Make EOF records, */
         alt_byte =FALSE;                /* no alternate bytes, */
         console =FALSE;                        /* default to no echo */
         eof =FALSE;                        /* not end of file yet */
         skip =0;                        /* dont skip any bytes, */
         sum_type =1;                        /* two's complement checksum, */
         load_address =0;                /* load address of 0000 */
         start_address =0;                /* default start address */
         byte_count =32;                        /* default byte count */
         delay=0;                        /* no delay */
         eol_delay=0;
         byte_addr =0;                        /* byte within the file, */

         printf("\nBinary to Intel Hex Conversion Utility");
         printf("\n  Version 2.1a 26 Sept. 1982 by T. Jennings\n");

         if(argc >1) {
                 is_ok= TRUE;
                 strcpy(infile,argv[1]);        /* save the filename, */
                 argc -=2;                        /* two taken, */
                 argv +=2;                        /* move both, */

                 while(argc >0)                        /* now do all the optio
                 {        arg= toupper(**argv);
                         switch(arg)
                         {

 /* Skip leading dashes on the arguments */
                         case '-':
                                 ++*argv;        /* skip leading dashes */
                                 continue;
                                 break;

 /* Change the default load address */
                         case 'L':
                                 if((--argc >0) &&
                                 (make_hex(*++argv,&load_address)!=NONE))
                                 {        printf("Load address: %x\n",load_add
                                 }
                                 else
                                 {        printf("Bad hex number\n");
                                         is_ok =FALSE;
                                 }
                                 break;

 /* Change the default run address */
                         case 'R':
                                 if((--argc >0) &&
                                 (make_hex(*++argv,&start_address)!=NONE))
                                 {        printf("Start address: %x\n",start_a
                                 }
                                 else
                                 {        printf("Bad hex number\n");
                                         is_ok =FALSE;
                                 }
                                 break;

 /* Change the default bytes per record */
                         case 'B':
                                 if((--argc >0) &&
                                 (make_dec(*++argv,&byte_count)!=NONE))
                                 {        printf("%d Byte records\n",byte_coun
                                         if(byte_count > 1024)
                                         {        is_ok=FALSE;
                                                 printf("Byte count must be <1
                                         }
                                 }
                                 else
                                 {        printf("Bad decimal number\n");
                                         is_ok =FALSE;
                                 }
                                 break;


 /* Enable sending INTEL hex to the punch */
                         case 'A':
                                 send_pch =TRUE;
                                 printf("Output to AUX\n");
                                 punch= open("AUX",0x8001);
                                 break;

 /* Set number of bytes to skip at the start of the file. */
                         case 'S':
                                 if((--argc >0) &&(make_dec(*++argv,&skip)!=NO
                                 {        printf("Skip %d bytes\n",skip);
                                 }
                                 else
                                 {        printf("Bad decimal number\n");
                                         is_ok =FALSE;
                                 }
                                 break;

 /* Open an output file */
                         case 'F':
                                 if(--argc)
                                 {        strcpy(outfile,*++argv);/* save the
                                         printf("Sending output to %s\n",outfi
                                         disk_file=TRUE;
                                 }
                                 else
                                 {        printf("Missing a filename\n");
                                 }
                                 break;

 /* change the checksum type */
                         case 'Z':
                                 sum_type =0;
                                 printf("1's complement checksum\n");
                                 break;

 /* Set a software delay between chars */
                         case 'W':
                                 if((--argc >0) &&
                                 (make_dec(*++argv,&delay)!=NONE))
                                 {        printf("Delay %d between characters\
                                 }
                                 else
                                 {        printf("Bad decimal number\n");
                                         is_ok=FALSE;
                                 }
                                 break;

 /* Set a software delay at the end of the line*/
                         case 'M':
                                 if((--argc >0) &&
                                 (make_dec(*++argv,&eol_delay)!=NONE))
                                 {        printf("Delay %d at end of record\n"
                                 }
                                 else
                                 {        printf("Bad decimal number\n");
                                         is_ok=FALSE;
                                 }
                                 break;

 /* Do only the even bytes */
                         case 'E':
                                 lsb =0;        /* LSB address mask, */
                                 alt_byte =TRUE;
                                 printf("Doing only even bytes\n");
                                 break;
 /* Do the odd bytes */
                         case 'O':
                                 lsb =1;
                                 alt_byte =TRUE;
                                 printf("Doing only odd bytes\n");
                                 break;
 /* Dont generate an EOF record */
                         case 'N':
                                 doeof =FALSE;
                                 printf("Don't generate an EOF record\n");
                                 break;
                         case 'X':
                                 console =TRUE;
                                 printf("Output to the console\n");
                                 break;
 /* Gets here only on bad arguments */
                         default:
                                 printf("Bad option: %s\n",*argv);
                                 is_ok=FALSE;        /* none of the above!!! *
                                 break;
                         }

                 --argc; ++argv;
                 }
         }
 /* Now see what we got. Exit now on bad options, and try to open any files.
 Make sure theres at least one destination.  */

         if (is_ok) {
                 if ((inbuf= open(infile,0x8000)) ==ERROR) {
                         printf("\nCan't find %s",infile);
                         exit();
                 }
                 if (disk_file) {
                         if ((outbuf =creat(outfile,0x8001)) ==ERROR) {
                                 printf("\nCan't create %s",outfile);
                                 exit();
                         }
                 }
                 send_file();
                 if(disk_file) {
                         close(outbuf);
                 }
                 exit();
         }
         else {
                 printf("Try:  ZAPLOAD <file> <options>, where <options> is");
                 printf                 (" one or more of the following:");
                 printf("\n\t L <xxxx> set load address,(default 0000)");
                 printf("\n\t R <xxxx> set start address,(default 0000)");
                 printf("\n\t B <dddd> record byte count, default 32,");
                 printf("\n\t S <dddd> skip <dddd> bytes before processing,");
                 printf("\n\t W <dddd> delay between characters,(0-65535)");
                 printf("\n\t M <dddd> delay at end of line(0-65535),");
                 printf("\n\t F <file> send hex to <file>,");
                 printf("\n\t A Send to the AUX device,");
                 printf("\n\t Z Make 1's complement checksums,");
                 printf("\n\t X Output to the console,");
                 printf("\n\t E Do only even addressed bytes,");
                 printf("\n\t O Do only odd addressed bytes,");
                 exit();
         }
 }

 /* Now the file(s) are open, and the options are set. Send the file, converti
 it to INTEL hex records. */

 int        send_file()
 {
 int        total,this_record;
 char        dummy;

         while(skip--) {                /* skip any bytes in the file, */
                 eof =read(inbuf,&dummy,1);        /* as specified, */
                 eof =((eof == ERROR) || (eof == NULL));
         }
         byte_addr =0;                        /* start keeping track, */
         datasum= 0;                        /* zero the checksum, */
         total =0;
         while(!eof) {
                 this_record =make_record(byte_count); /* make data records, *
                 total +=this_record;        /* count bytes, */
         }
         printf("End of file\n");
         if(this_record > 0) {                /* if last record non-empty, */
                 make_record(0);                /* then make an EOF record, */
         }                                /* else we already did, */
         printf("Total byte count =%dd, data checksum =%xh\n",total,datasum);
         sendc(0x1a);                        /* send a control-Z, */
         return;                                /* then leave */
 }
 /* read bytes from the disk file, and make INTEL hex records. */

 int        make_record(count)
 int        count;
 {
 int        i,j,b;
 int        checksum;
 int        check;
 char        c;

 /* Write out an INTEL hex record. Pad it to the full length if the file
 empties out. If we are passed a count of 0, do only a EOF record. */

         checksum =0;                                /* zero the checksum, */
         for(i=0; i <count;  ) {
                 j= read(inbuf,&c,1);                /* read byte to C */
                 if((j ==ERROR) || (j == NONE)) {
                         eof =TRUE;
                         break;
                 }
                 check =byte_addr &1;                /* if alternate bytes, */
                 if(!alt_byte ||(alt_byte && (check ==lsb) )) {
                         record[i] =c;                /* save each byte, */
                         checksum +=c;                /* sum up the data bytes
                         datasum +=c;                /* add data to the sum al
                         ++i;                        /* Count another done, */
                 }
                 ++byte_addr;
         }

 /* Now we have an array of data bytes. If its not empty, send it out as a dat
 record, else send as a terminating record. */

         if(i) {                                        /* If data record ...
                 sendc(':');                                /* record start ch
                 sendb(i);                                /* send the byte cou
                 checksum +=i;                                /* update the ch
                 sendw(load_address);
                 checksum +=((load_address>>8) &0xff);/* add the address to th
                 checksum +=( load_address &0xff);        /* checksum, */
                 load_address += i;                        /* update the addre
                 sendb(0);                                /* set record type =
                 for(j=0,b=i; b>0; b--)                        /*send all the
                         sendb(record[j++])
                 ;
         }
         else if(doeof) {                                /*... its end of file
                 sendc(':');                                /* record start ch
                 sendb(i);                                /* send the byte cou
                 checksum +=i;                                /* update the ch
                 sendw(start_address);
                 checksum +=((start_address>>8) &0xff);/* add the address to t
                 checksum +=( start_address &0xff);        /* checksum, */
                 sendb(1);                                /* record type =end,
         }

 /* now make the correct checksum */

         if(i || doeof) {
                 checksum =( ~checksum);                /* ones complement, */
                 checksum += sum_type;                        /* correct it, *
                 sendb(checksum);                        /* send it, */
                 sendc(CR);                                /* for a pretty scr
                 sendc(LF);
         }
         return(i);                                        /* return number wr
 }

 /* Data transmission routines */

 /* This is the lowest level character I/O routine. It send the character to t
 CRT, any open disk file, and the LST: device. If enabled, it does a variable
 length software delay for the zap-80. */

 int         sendc(arg)
 int        arg;
 {
 char        character;
 int        i,j;

         character= arg;                                /* type conversion */
         if(console)
                 putchar(character);
         if(disk_file) {
                 write(outbuf,&character,1);
         }
         if(arg==CR)
         {        if(eol_delay)
                 {
                         for(i=eol_delay; i>0; i--)
                         {        for(j=0; j<100; j++);
                         }
                 }
         }
         else
         {        if(delay)
                 {
                         for(i=delay; i>0; i--)
                         {        for(j=0; j<100; j++);
                         }
                 }
         }
         if(send_pch)
                 write(punch,&character,1);
         return;
 }

 int        sendb(byte)
 int        byte;
 {
 char        h;
         byte =(byte &0xff);
         h=(byte >>4) &0x0f;
         sendc(((h>9) ? h+'A'-10 : h+'0'));
         h=(byte & 0x0f);
         sendc(((h>9) ? h+'A'-10 : h+'0'));
         return;
 }
 int        sendw(word)
 int        word;
 {
         sendb((word >>8) &0xff);
         sendb(word &0xff);
         return;
 }

 /* Make a string into a hex number. Return non-zero if OK. The actual
  return value is set via a calling pointer. */

 int        make_hex(string,hex_number)
 char        *string;
 int        *hex_number;
 {
         return(sscanf(string,"%x",hex_number));
 }

