home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / turtle.asc < prev    next >
Encoding:
Text File  |  1991-12-17  |  21.1 KB  |  808 lines

  1. _PROGRAMMING WITH PHAR LAP'S 286|DOS-EXTENDER_
  2. by Al Williams
  3.  
  4. [LISTING ONE]
  5.  
  6. /*****************************************************************
  7.  * XCI.H  Header for XCI command interpreter -- Al Williams      *
  8.  *****************************************************************/
  9. #ifndef XCI_HEADER
  10. #define XCI_HEADER
  11.  
  12. /* type for command functions */
  13. #define XCICMD void far
  14.  
  15. /* Pointer to command function */
  16. typedef void (far * XCICMDP)(int cmd,char far *line,void *udata);
  17.  
  18. /* Various hooks */
  19. extern char *xci_prompt;   /* string to prompt with */
  20. extern FILE *xci_infile;   /* input file */
  21. extern int xci_exitflag;   /* set to exit XCI */
  22. extern int xci_defaultbrk; /* default break handling */
  23. void (*xcif_prompt)();     /* function to prompt with */
  24. void (*xcif_prehelp)();    /* function to call before help */
  25. void (*xcif_posthelp)();   /* function to call after help */
  26. char *(*xcif_input)();     /* function to get input */
  27.  
  28. /* main function prototype */
  29. int command(char *dll,char *startfile,int caseflag, void far *ustruc,XCICMDP userfunc);
  30.  
  31. /* add command (not from DLL) */
  32. int addcmd(char *cmdnam,XCICMDP fn);
  33.  
  34. #endif
  35.  
  36.  
  37. [LISTING TWO]
  38.  
  39. /**********************************************************
  40.  * XCI.C     An extensible command interpreter for the    *
  41.  * Phar Lap 286 DOS Extender -- Al Williams               *
  42.  **********************************************************/
  43.  
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <malloc.h>
  48. #include <dos.h>
  49. #include <phapi.h>
  50. #include <setjmp.h>
  51. #include "xci.h"
  52.  
  53. /* Table of commands (dynamically allocated) */
  54. static struct cmdtbl
  55.   {
  56.   char far *cmd;
  57.   XCICMDP f;
  58.   } *cmds=NULL;
  59.  
  60. /* Number of commands in table */
  61. static unsigned int nrcmds=0;
  62.  
  63. /* Case sensitive? */
  64. static int truecase=0;
  65.  
  66. /* default hook function prototypes */
  67. void xci_prompter();     /* func to prompt */
  68. char *xci_input();       /* func to get input */
  69. void xci_preposthelp();  /* pre & post help command */
  70.  
  71. /* default prompt string -- can be changed by client */
  72. char *xci_prompt="? ";
  73.  
  74. /* default routines -- can be changed by client */
  75. void (*xcif_prompt)()=xci_prompter;
  76. void (*xcif_prehelp)()=xci_preposthelp;
  77. void (*xcif_posthelp)()=xci_preposthelp;
  78. char *(*xcif_input)()=xci_input;
  79.  
  80. /* flag set when break detected */
  81. static int broke;
  82. /* Jump to top level command loop */
  83. jmp_buf cmdloop;
  84.  
  85. /* default command function prototypes */
  86. XCICMD dofunc(int cmd,char *s,struct udata *data);
  87. XCICMD linkfunc(int cmd,char *s,struct udata *data);
  88. XCICMD quitfunc(int cmd,char *s,struct udata *data);
  89. XCICMD helpfunc(int cmd,char *s,struct udata *data);
  90.  
  91. /* default commands (client must enable goto if desired) */
  92. static char *defcmd[]= { "quit", "help", "link", "do" };
  93. /* addresses of default commands */
  94. static XCICMDP deffunc[]={quitfunc,helpfunc,linkfunc,dofunc};
  95. /* non-zero if running a script via DO */
  96. static int interactive=0;
  97. /* stack of file positions for nested DO commands */
  98. /* Files are closed and reopened to avoid DOS file limit */
  99. static struct fstack
  100.        {
  101.        char *fp;             /* file name */
  102.        long pos;             /* position in file */
  103.        struct fstack * next; /* next fstack record */
  104.        } *instack;
  105.  
  106. /* default stdin handle */
  107. static FILE *baseio;
  108. /* Current input file */
  109. FILE *xci_infile;
  110. /* Set to 1 when someone wants to exit */
  111. int xci_exitflag=0;
  112. /* Default break action */
  113. int xci_defaultbrk=1;
  114. /* Break vectors */
  115. PIHANDLER oldbreak;
  116. REALPTR oldbreal;
  117. PIHANDLER old1b;
  118. REALPTR old1breal;
  119.  
  120. /* Bios segment (you can't call DosGetBIOSseg from ISR) */
  121. USHORT biosseg;
  122. /* ^Break handlers */
  123. void _interrupt _far xci_int1b(REGS16 r)
  124.   {
  125.   union REGS rr;
  126.   unsigned int *keyhead,*keytail;
  127.   if (!xci_defaultbrk)
  128.     {
  129. /* Chain to old break handler (never returns) */
  130.     DosChainToRealIntr(old1breal);
  131.     }
  132.   keyhead=MAKEP(biosseg,0x1A);
  133.   keytail=MAKEP(biosseg,0x1C);
  134.   broke=1;
  135. /* purge keyboard buffer */
  136.   *keyhead=*keytail;
  137. /* push ^C at head */
  138.   rr.h.ah=5;
  139.   rr.x.cx=3;
  140.   int86(0x16,&rr,&rr);
  141.   }
  142. void _interrupt _far xci_int16(REGS16 r)
  143.   {
  144.   REGS16 r1;
  145.   unsigned ah=r.ax>>8;
  146.   _enable();
  147.   if (xci_defaultbrk&&(ah==0||ah==0x10||ah==1||ah==0x11))
  148.     {
  149.     do
  150.       {
  151.       r1.ax=0x100;
  152.       r1.flags=0;
  153. /* Simulate interrupt to old INT 16H handler */
  154.       DosRealFarCall(oldbreal,&r1,0,-1,r1.flags);
  155.       if ((r1.flags&64)&&(ah==1||ah==0x11))
  156.         {
  157.         r.flags=r1.flags;
  158.         return;
  159.         }
  160.       } while (r1.flags&64);
  161. /* If break character -- replace it with a carriage return */
  162.       if ((r1.ax&0xff)==3||r1.ax==0x300)
  163.         {
  164.         unsigned int *keyhead;
  165.         keyhead=MAKEP(biosseg,0x1A);
  166.         keyhead=MAKEP(biosseg,*keyhead);
  167.         *keyhead='\r';
  168.         broke=1;
  169.         }
  170.      }
  171.   DosChainToRealIntr(oldbreal);
  172.   }
  173. /* XCI Clean up */
  174. /* Note: DosExitList requires this to be a pascal function */
  175. void pascal far xci_clean(unsigned int reason)
  176.   {
  177. /* restore interrupt vectors */
  178.    DosSetRealProtVec(0x16,oldbreak,oldbreal,NULL,NULL);
  179.    DosSetRealProtVec(0x1b,old1b,old1breal,NULL,NULL);
  180. /* Exit handler must call DosExitList with EXLST_EXIT
  181.    to proceed with the termination */
  182.    DosExitList(EXLST_EXIT,NULL);
  183.   }
  184. /* default functions */
  185. void xci_prompter(char *s)
  186.    {
  187.    printf("%s",s);
  188.    }
  189. char *xci_input(char *inbuf,unsigned int siz,FILE *input)
  190.    {
  191.    return fgets(inbuf,siz,input);
  192.    }
  193. void xci_preposthelp()
  194.    {
  195.    }
  196. /* Main command routine */
  197. /* dll is initial DLL to load
  198.    startfile is initial file to DO
  199.    cases is 1 if case sensitivity is required
  200.    userfunc is pointer to user function called at
  201.             start and end */
  202. int command(char *dll, char *startfile, int cases,void far *user,XCICMDP userfunc)
  203.   {
  204.   int i;
  205.   char inbuf[129],*p;
  206.   if (!cmds)
  207.     {
  208. /* first time  (not done for recursive calls) */
  209.    DosGetBIOSSeg(&biosseg);
  210. /* Due to a bug in versions prior to 1.4, you must set
  211.    the INT 16H ProtVec before using PassToProtVec... */
  212.     DosSetProtVec(0x16,xci_int16,&oldbreak);
  213.     DosSetPassToProtVec(0x16,xci_int16,NULL,&oldbreal);
  214.     DosSetPassToProtVec(0x1b,xci_int1b,&old1b,&old1breal);
  215. /* set up exit handler */
  216.     DosExitList(EXLST_ADD,xci_clean);
  217.     truecase=cases;
  218.     xci_infile=stdin;
  219. /* install default commands */
  220.     cmds=(struct cmdtbl *)malloc(4*sizeof(struct cmdtbl));
  221.     if (!cmds) return 1;
  222.     nrcmds=4;
  223.     for (i=0;i<nrcmds;i++)
  224.       {
  225.       cmds[i].cmd=defcmd[i];
  226.       cmds[i].f=deffunc[i];
  227.       }
  228. /* load default DLL (if specified) */
  229.     if (dll&&*dll)
  230.       if (adddll(dll))
  231.          printf(
  232.            "Warning: unable to load default command DLL\n");
  233. /* call user function */
  234.     if (userfunc) userfunc(0,NULL,user);
  235. /* execute default DO file */
  236.     if (startfile&&*startfile) dofunc(0,startfile,user);
  237. /* set jump buffer for future longjmp's */
  238.     setjmp(cmdloop);
  239.     }
  240. /* initilization done -- begin main processing */
  241.   while (1)
  242.     {
  243.     char *token,*tail;
  244. /* if someone wants to quit then quit */
  245.     if (xci_exitflag)
  246.       {
  247. /* call user function */
  248.       if (userfunc) userfunc(1,NULL,user);
  249. /* reset some things in case we are called again */
  250. /* restore interrupt vectors */
  251.       DosSetRealProtVec(0x16,oldbreak,oldbreal,NULL,NULL);
  252.       DosSetRealProtVec(0x1b,old1b,old1breal,NULL,NULL);
  253.       DosExitList(EXLST_REMOVE,xci_clean);
  254.       xci_infile=stdin;
  255.       interactive=0;
  256.       instack=NULL;
  257.       free((void *)cmds);
  258.       cmds=NULL;
  259.       return 0;
  260.       }
  261. /* If interactive then prompt */
  262.     if (!interactive) (*xcif_prompt)(xci_prompt);
  263. /* get input from user or file */
  264.     *inbuf='\0';
  265.     (*xcif_input)(inbuf,sizeof(inbuf),xci_infile);
  266. /* If break detected then go to top level */
  267.     if (broke)
  268.       {
  269.       struct fstack *f;
  270.       broke=0;
  271.       /* free fstack entries */
  272.       for (f=instack;f;f=f->next) free(f->fp);
  273.       instack=NULL;
  274.       interactive=0;
  275.       xci_infile=stdin;
  276.       longjmp(cmdloop,1);
  277.       }
  278. /* If end of do file, return. If end of console, ignore */
  279.     if (!*inbuf&&feof(xci_infile))
  280.       {
  281.       if (interactive)
  282.         {
  283.         return 0;
  284.         }
  285.       clearerr(xci_infile);
  286.       continue;
  287.       }
  288. /* got some input -- lets look at it */
  289.     i=strspn(inbuf," \t");
  290. /* skip blank lines and comments */
  291.     if (inbuf[i]=='\n') continue;
  292.     if (inbuf[i]=='#') continue;
  293. /* eat off \n from line */
  294.     p=strchr(inbuf+i,'\n');
  295.     if (p) *p='\0';
  296. /* get a token */
  297.     token=strtok(inbuf+i," \t");
  298.     if (!token) continue;  /* this should never happen */
  299. /* do we recognize the command? */
  300.     i=findcmd(token);
  301. /* NO: error */
  302.     if (i==-1)
  303.       {
  304.       printf("Unknown command %s\n",token);
  305.       continue;
  306.       }
  307. /* YES: compute command's tail (arguments) */
  308.     tail=token+strlen(token)+1;
  309.     tail+=strspn(tail," \t");
  310. /* execute command */
  311.     cmds[i].f(0,tail,user);
  312.     }
  313.   }
  314. /* Find a command -- search backwards so new commands
  315.    replace old ones */
  316. static int findcmd(char *s)
  317.   {
  318.   int i,stat;
  319.   for (i=nrcmds-1;i>=0;i--)
  320.     {
  321.     if (!(truecase?
  322.            strcmp(s,cmds[i].cmd)
  323.            :
  324.            stricmp(s,cmds[i].cmd)))
  325.        return i;
  326.     }
  327.   return -1;
  328.   }
  329. /* Add a DLL to the command input table
  330.    returns 0 if successful  */
  331. static adddll(char *dll)
  332.   {
  333.   char cmdnam[33],*p;
  334.   HMODULE h=0;
  335.   unsigned ord=0;
  336.   p=strrchr(dll,'\\');
  337. /* check to see if module is already loaded */
  338.   if (!DosGetModHandle(p?p+1:dll,&h))
  339.     {
  340.     printf("%s already loaded\n",p?p+1:dll);
  341.     return 1;
  342.     }
  343. /* Load module if possible */
  344.   if (DosLoadModule(0,0,dll,&h))
  345.        return 1;
  346. /* find all exported functions in module */
  347.   while (!DosEnumProc(h,cmdnam,&ord))
  348.      {
  349.      PFN fn;
  350. /* Get function's address */
  351.      DosGetProcAddr(h,cmdnam,&fn);
  352. /* add command -- skipt 1st character (it is a _) */
  353.      if (addcmd(cmdnam+1,(XCICMDP) fn)) return 1;
  354.      }
  355.   return 0;
  356.   }
  357. /* add a command -- returns 0 for success */
  358. addcmd(char *cmdnam,XCICMDP fn)
  359.   {
  360.   struct cmdtbl *ct;
  361. /* make more room in table  */
  362.   ct=(struct cmdtbl *)
  363.       realloc(cmds,(nrcmds+1)*sizeof(struct cmdtbl));
  364.   if (!ct) return 1;
  365.   cmds=ct;
  366. /* add name and function */
  367.   cmds[nrcmds].cmd=strdup(cmdnam);
  368.   if (!cmds[nrcmds].cmd) return 1;
  369.   cmds[nrcmds++].f=(XCICMDP) fn;
  370.   return 0;
  371.   }
  372. /* currently executing file name */
  373. static char curfile[67];
  374. /* Command to transfer execution from one file to another
  375.    Only works from inside a file, and must be enabled by
  376.    client program: addcmd("GOTO",gotocmd); */
  377. XCICMD gotofunc(int cmd,char *s,struct udata *data)
  378.   {
  379.   FILE *f;
  380.   if (cmd==2)
  381.     {
  382.     printf("Execute commands from an ASCII file\n");
  383.     return;
  384.     }
  385.   if (cmd==1||!s||!*s)
  386.     {
  387.     printf("goto executes commands from an ASCII file\n"
  388.            "Usage: goto FILENAME\n");
  389.     return;
  390.     }
  391. /* open file */
  392.   f=fopen(s,"r");
  393.   if (!f)
  394.     {
  395.     printf("Can't open %s\n",s);
  396.     perror(s);
  397.     return;
  398.     }
  399.   if (!interactive)
  400.     {
  401.     printf("Use goto only from command files\n"
  402.            "Use do to execute a file\n");
  403.     return;
  404.     }
  405. /* register as current file */
  406.   strcpy(curfile,s);
  407.   fclose(xci_infile);
  408.   xci_infile=f;
  409.   }
  410. /* Do a command file */
  411. XCICMD dofunc(int cmd,char *s,struct udata *data)
  412.   {
  413.   FILE *ifile;
  414.   struct fstack recall;
  415.   if (cmd==2)
  416.     {
  417.     printf("Do commands from an ASCII file\n");
  418.     return;
  419.     }
  420.   if (cmd==1||!s||!*s)
  421.     {
  422.     printf("Do executes commands from an ASCII file\n"
  423.            "Usage: do FILENAME\n");
  424.     return;
  425.     }
  426. /* open file */
  427.   ifile=fopen(s,"r");
  428.   if (!ifile)
  429.     {
  430.     printf("Can't open %s\n",s);
  431.     perror(s);
  432.     return;
  433.     }
  434.   if (interactive)
  435.      {
  436. /* store current file name so we can resume later */
  437.      if (!(recall.fp=strdup(curfile)))
  438.         {
  439.         printf("Out of memory\n");
  440.         fclose(ifile);
  441.         return;
  442.         }
  443. /* store position in current file and close it */
  444.      recall.pos=ftell(xci_infile);
  445.      fclose(xci_infile);
  446.      }
  447.   else
  448.      {
  449. /* no current file, so remember this handle but don't close it */
  450.      baseio=xci_infile;
  451.      recall.fp=NULL;
  452.      }
  453. /* add recall to linked list of nested files */
  454.   recall.next=instack;
  455. /* make new file current */
  456.   strcpy(curfile,s);
  457.   xci_infile=ifile;
  458. /* mark nesting level */
  459.   interactive++;
  460. /* make recall the head of the fstack linked list */
  461.   instack=&recall;
  462. /* call command recursively */
  463.   command(NULL,NULL,0,data,NULL);
  464. /* close useless file */
  465.   fclose(xci_infile);
  466. /* restore old file */
  467.   if (instack->fp!=NULL)  /* is it a file? */
  468.      {
  469. /* open it */
  470.      xci_infile=fopen(instack->fp,"r");
  471.      if (!xci_infile)
  472.         {
  473. /* serious error! file vanished! reset to top level */
  474.         printf("Error opening %s\n",instack->fp);
  475.         xci_infile=baseio;
  476.         interactive=0;  /* bad error if nested */
  477.         }
  478.      else
  479.         {
  480. /* reposition old file */
  481.         fseek(xci_infile,instack->pos,SEEK_SET);
  482. /* make it current */
  483.         strcpy(curfile,instack->fp);
  484.         }
  485. /* release memory used for file name */
  486.      free(instack->fp);
  487.      }
  488.   else
  489.      {
  490. /* reset to console */
  491.      xci_infile=baseio;
  492.      }
  493. /* fix up linked list */
  494.   instack=instack->next;
  495.   interactive--;
  496.   }
  497. /* Link a dll */
  498. XCICMD linkfunc(int cmd,char *s,struct udata *data)
  499.   {
  500.   if (cmd==2)
  501.     {
  502.     printf("Add user-defined commands\n");
  503.     return;
  504.     }
  505.   if (cmd==1||!s||!*s)
  506.      {
  507.      printf("Add user-defined commands via a DLL\n"
  508.        "Usage: link DLLNAME\n");
  509.      return;
  510.      }
  511.   if (adddll(s))
  512.     {
  513.     printf("Unable to load dll: %s\n",s);
  514.     }
  515.   }
  516. /* Quit */
  517. XCICMD quitfunc(int cmd,char *s,struct udata *data)
  518.   {
  519.   if (cmd==0) { xci_exitflag=1; return; }
  520. /* long and short help message */
  521.   printf("Exits to DOS\n");
  522.   }
  523. /* provide general help (scan from end to 0 call with cmd==2)
  524.    or specific help find command and call with cmd==1 */
  525. XCICMD helpfunc(int cmd,char *s,struct udata *data)
  526.   {
  527.   int i,j=0;
  528.   if (cmd==2) printf("Get help\n");
  529.   if (cmd==1) printf(
  530.   "Use the help command to learn about the available"
  531.   " commands\nUse HELP for a list of help topics"
  532.   " or \"HELP topic\""
  533.   " for help on a specific topic.\n");
  534.   if (cmd) return;
  535. /* call user's prehelp */
  536.   (*xcif_prehelp)();
  537. /* if specific command... */
  538.   if (s&&*s)
  539.     {
  540. /* find it and ask it about itself (command==1) */
  541.     i=findcmd(s);
  542.     if (i==-1) printf("No such command: %s\n",s);
  543.     else cmds[i].f(1,NULL,NULL);
  544.     }
  545.   else
  546. /* No specific command -- do them all (command==2) */
  547.     for (i=nrcmds-1;i>=0;i--)
  548.       {
  549.       char buf[22];
  550. /* might be a lot of commands -- pause on screenfulls */
  551.       if (!(++j%25))
  552.         {
  553.         printf("--More--");
  554.         j=0;
  555.         if (!getch()) getch();
  556.         putchar('\n');
  557.         }
  558. /* print header */
  559.       strncpy(buf,cmds[i].cmd,20);
  560.       strcat(buf,":");
  561.       printf("%-21.21s",buf);
  562. /* ask command for short help */
  563.       cmds[i].f(2,NULL,NULL);
  564.       }
  565. /* call user's post help */
  566.   (*xcif_posthelp)();
  567.   }
  568.  
  569.  
  570. [LISTING THREE]
  571.  
  572. /*****************************************************************
  573.  * TURTLE.H  Header for TURTLE.EXE  -- Al Williams               *
  574.  *****************************************************************/
  575. #include <graph.h>
  576. typedef  unsigned long ulong;
  577. typedef  unsigned int uint;
  578.  
  579. /* graphics buffer */
  580. extern char _gbuf[64000];
  581.  
  582. /* Application data (passed to XCI commands) */
  583. struct  udata
  584.   {
  585.   char *gbuf;               /* pointer to graphics buffer */
  586.   char tbuf[4000];          /* text buffer */
  587.   char *gptr;               /* pointer to graphics screen */
  588.   char *tptr;               /* pointer to text screen */
  589.   struct xycoord graphxy;   /* x,y of graphic screen */
  590.   struct rccoord textxy;    /* x,y of text screen */
  591.   int color;                /* color */
  592.   long backcolor;           /* background color */
  593. /* store[10] & store[11] are for internal use */
  594.   char *store[12];          /* screen storage */
  595.   unsigned int mode:1;      /* draw or move */
  596.   unsigned int textgraph:1; /* if 1, don't exit graphic mode */
  597.   int heading;              /* turtle heading */
  598. /* X and Y are stored as reals too to combat rounding errors */
  599.   double realx;
  600.   double realy;
  601. /* 26 variables A-Z */
  602.   long vars[26];
  603. /* text color */
  604.   int tcolor;
  605.   };
  606. /* Application data structure */
  607. extern struct udata appdata;
  608.  
  609.  
  610. [LISTING FOUR]
  611.  
  612. /*****************************************************************
  613.  * TURTLE.C     Main program for TURTLE.C -- Al Williams         *
  614.  * TURTLE assumes large model -- see the MAKEFILE for compile    *
  615.  * instructions.                                                 *
  616.  *****************************************************************/
  617. #include <stdio.h>
  618. #include <graph.h>
  619. #include <dos.h>
  620. #include <phapi.h>
  621. #include "turtle.h"
  622. #include "xci.h"
  623.  
  624. /* XCI client's application data (see TURTLE.H) */
  625. struct udata appdata;
  626. int installcmds(void);
  627.  
  628. /* XCI startup command -- install commands */
  629. XCICMD startup(int cmd, char far *dummy)
  630.   {
  631.   if (cmd) return;
  632.   if (installcmds())
  633.     {
  634.     printf("Out of memory\n");
  635.     exit(1);
  636.     }
  637.   }
  638. /* Reset things before normal exit */
  639. void preexit()
  640.   {
  641.   _setvideomode(_DEFAULTMODE);
  642.   }
  643. /* MAIN PROGRAM */
  644. main()
  645.   {
  646.   void turtleprompt();
  647. /* register exit routine */
  648.   atexit(preexit);
  649. /* Set some graphics things */
  650.   _setvideomode(_TEXTC80);
  651.   _setactivepage(0);
  652.   _setvisualpage(0);
  653.   appdata.tcolor=appdata.color=15;
  654.   appdata.backcolor=0x003f0000L;   /* blue background */
  655. /* clear screen */
  656.   clearcmd(0,"",&appdata);
  657. /* Print banner */
  658.   printf("TURTLE VGA by Al Williams\n"
  659.          "Type HELP for help\n");
  660.  
  661. /* Take over XCI prompt function */
  662.   xcif_prompt=turtleprompt;
  663.   command("TSAVE.DLL","TURTLE.CMD",0,
  664.           &appdata,(XCICMDP) startup);
  665.   }
  666. /* XCI prompt -- if in graphics mode keep input on top line */
  667. void turtleprompt(char *s)
  668.   {
  669.   union REGS r;
  670.   if (appdata.textgraph)
  671.     {
  672. /* don't do newline in graphic mode */
  673.     if (*s=='\n')
  674.       {
  675.       printf(" ");
  676.       return;
  677.       }
  678. /* but do clear the line */
  679.      r.h.ah=2;
  680.      r.h.bh=0;
  681.      r.x.dx=0;
  682.      int86(0x10,&r,&r);
  683.      r.x.ax=0x0a00|' ';
  684.      r.x.bx=appdata.tcolor;
  685.      r.x.cx=40;
  686.      int86(0x10,&r,&r);       /* clear to end of line */
  687.     }
  688.   printf("%s",s);
  689.   }
  690.  
  691.  
  692.  
  693. [LISTING FIVE]
  694.  
  695. ######################################################
  696. # Makefile for TURTLE                                #
  697. # Use NMAKE to compile                               #
  698. ######################################################
  699.  
  700. all : turtle.exe tsave.dll
  701.  
  702. turtle.exe : turtle.obj tcmds.obj xci.obj texpr.obj
  703.         cl -AL -Lp turtle.obj tcmds.obj xci.obj \
  704.            texpr.obj c:\run286\lib\graphp.obj \
  705.            LLIBPE.LIB GRAPHICS.LIB
  706.         implib turtle.lib turtle.exe
  707. turtle.obj : turtle.c xci.h turtle.h
  708.         cl -AL -Ox -G2 -c turtle.c
  709. tcmds.obj : tcmds.c xci.h turtle.h
  710.         cl -AL -Ox -G2 -c tcmds.c
  711. texpr.obj : texpr.c turtle.h
  712.         cl -AL -Ox -G2 -c texpr.c
  713. xci.obj : xci.c xci.h
  714.         cl -AL -Ox -G2 -c xci.c
  715. tsave.dll : tsave.c dllstart.asm turtle.h xci.h turtle.lib
  716.         cl -ML -Gs -Lp -Ox -G2 tsave.c dllstart.asm turtle.lib
  717.  
  718.  
  719.  
  720. [LISTING SIX]
  721.  
  722. /******************************************************************
  723.  * TIMING.C - simple non-rigorous benchmark for 286|DOS Extender  *
  724.  * Compile with:                                                  *
  725.  * CL -AL -Lp -G2 -Ox timing.c graphp.obj llibpe.lib graphics.lib *
  726.  * (protected mode)                                               *
  727.  * OR:                                                            *
  728.  * CL -AL -G2 -Ox timing.c graphics.lib                           *
  729.  * (real mode)                                                    *
  730.  ******************************************************************/
  731. #include <stdio.h>
  732. #include <graph.h>
  733. #include <time.h>
  734.  
  735. #define time_mark time_it(0)
  736. #define time_done time_it(1)
  737.  
  738. main()
  739.   {
  740.   printf("Timing graphics operations\n");
  741.   time_mark;
  742.   gtest();
  743.   time_done;
  744.   printf("Timing file operations\n");
  745.   time_mark;
  746.   ftest();
  747.   time_done;
  748.   exit(0);
  749.   }
  750. /* Function to mark times */
  751. int time_it(int flag)
  752.   {
  753.   static clock_t sttime;
  754.   unsigned s;
  755.   if (!flag)
  756.     {
  757.     sttime=clock();
  758.     }
  759.   else
  760.     {
  761.     s=(clock()-sttime)/CLK_TCK;
  762.     printf("Elapsed time: %d seconds\n",s);
  763.     }
  764.   return 0;
  765.   }
  766. /* Graphics test -- must have VGA */
  767. int gtest()
  768.   {
  769.   int i,x,y;
  770.   _setvideomode(_MRES256COLOR);
  771.   for (i=1;i<11;i++)
  772.     {
  773.     _setcolor(i);
  774.     for (y=0;y<199;y++)
  775.       for (x=0;x<319;x++)
  776.         _setpixel(x,y);
  777.     }
  778.   _setvideomode(_DEFAULTMODE);
  779.   return 0;
  780.   }
  781. /* File test -- assumes 320K free on current drive */
  782. char filedata[64000];
  783. int ftest()
  784.   {
  785.   FILE *tfile;
  786.   int i,j;
  787.   for (j=0;j<10;j++)
  788.     {
  789.     tfile=fopen("~~TIMING.~@~","w");
  790.     if (!tfile)
  791.       {
  792.       perror("TIMING");
  793.       exit(1);
  794.       }
  795.     for (i=0;i<5;i++)
  796.       fwrite(filedata,sizeof(filedata),1,tfile);
  797.     if (fclose(tfile))
  798.       {
  799.       perror("TIMING");
  800.       }
  801.     unlink("~~TIMING.~@~");
  802.     }
  803.   return 0;
  804.   }
  805.  
  806.  
  807.  
  808.