From rjb%computer-lab.cambridge.ac.uk@NSFnet-Relay.AC.UK  Mon Nov 13 06:39:30 1989
Received: by iris (5.57/3.14)
        id AA14406; Mon, 13 Nov 89 06:39:30 PST
Received: from ucdavis.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
        id AA06558; Mon, 13 Nov 89 06:41:31 PST
Received: by ucdavis.ucdavis.edu (5.51/UCD2.02)
        id AA22992; Mon, 13 Nov 89 06:21:24 PST
Received: from sun.nsfnet-relay.ac.uk by vax.NSFnet-Relay.AC.UK
           via Janet with NIFTP  id aa07332; 13 Nov 89 13:59 GMT
Received: from jenny.cl.cam.ac.uk by scaup.Cl.Cam.AC.UK id ad05940;
          13 Nov 89 13:51 GMT
Date: Mon, 13 Nov 89 13:30:48 GMT
From: Richard Boulton <rjb%computer-lab.cambridge.ac.uk@NSFnet-Relay.AC.UK>
To: info-hol%clover.ucdavis.edu@NSFnet-Relay.AC.UK
Message-Id:  <8911131351.ad05940@scaup.Cl.Cam.AC.UK>


Have you ever wanted to run a HOL session non-interactively and have the input
included in the output along with the results?

Below you will find the code for two C programs which allow you to do just
that. `hol_merge' takes the output from a non-interactive HOL session and
merges the original input into it (provided you tell it to use the right file!)
`hol_batch' uses `hol_merge' and presents a simple command to do batch HOL
sessions.

The code may not be very good, but then I'm not really a C programmer.
Any bug reports or improvements would be gratefully received.

I hope you find these programs useful.

                        Richard Boulton (rjb@uk.ac.cam.cl), 11th November 1989.



/* hol_merge.c */

/* This program takes the output from running a HOL session and merges it    */
/* with the input file. The result appears exactly as if the input had been  */
/* given to HOL interactively. For example, executing the UNIX commands      */
/*                                                                           */
/*    hol <input.ml >output                                                  */
/*    hol_merge input.ml <output >results                                    */
/*                                                                           */
/* creates a file `output' with the output from the HOL session, but the     */
/* input to HOL does not appear. `results' does contain the input to the     */
/* session.                                                                  */
/*                                                                           */
/* The program works by detecting any occurrence of the HOL prompt at the    */
/* beginning of a line in `output'. At such an occurrence a line is read     */
/* from `input.ml' and inserted after the prompt. If the first prompt is     */
/* followed immediately by another prompt on the same line, it is treated in */
/* the same way, and so on until a non-prompt is found. The rest of the line */
/* is then copied to the output without modification.                        */
/*                                                                           */
/* The default HOL prompt is '#' and this is what hol_merge looks for unless */
/* told to do otherwise via the -p option on the command line. The argument  */
/* for -p may need to be quoted.                                             */
/*                                                                           */
/* This code can be compiled using the UNIX command                          */
/*                                                                           */
/*    cc -o hol_merge hol_merge.c                                            */


#include <stdio.h>

#define default_prompt "#"


int inchar;


main(argc, argv)
int argc;
char *argv[];
{
     extern int optind;
     extern char *optarg;
     FILE *fp, *fopen();
     int errflg, c;
     char *prompt;

     prompt = default_prompt;
     errflg = 0;
     while ((c = getopt(argc, argv, "?p:")) != -1)
          switch (c) {
          case 'p':
               prompt = optarg;
               break;
          case '?':
               errflg++;
             }
     if (optind != (argc - 1))
          errflg++;
     if (errflg) {
          (void)fprintf(stderr,
                        "usage: %s [-p prompt] ML_source_file\n", argv[0]);
          exit (2);
        }
     if ((fp = fopen(argv[optind], "r")) == NULL) {
          (void)fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
          exit (2);
        }
     inchar = '\n';
     while (inchar != EOF) {
          while (matchprompt(prompt))
               while ((c = getc(fp)) != EOF)
                    if (putchar(c) == '\n')
                         break;
          while ((inchar != EOF) && (inchar != '\n'))
               if (putchar(inchar = getchar()) == '\n')
                    break;
        }
     fclose(fp);
   }


matchprompt(s)
char *s;
{
     int l;

     l = 0;
     while (s[l] != '\0') {
          if (inchar != EOF) {
               if (putchar(inchar = getchar()) != s[l++])
                    return(0);
             }
          else
               return(0);
        }
     return(1);
   }



/* hol_batch.c */

/* This program can be used to run a HOL session in a non-interactive manner */
/* to produce the output which would have appeared on the terminal if the    */
/* same input had been given in an interactive session.                      */
/*                                                                           */
/* A UNIX command of the form                                                */
/*                                                                           */
/*    hol_batch input.ml                                                     */
/*                                                                           */
/* is expanded to                                                            */
/*                                                                           */
/*    (hol <input.ml) | (hol_merge -p '#' input.ml)                          */
/*                                                                           */
/* by this program.                                                          */
/*                                                                           */
/*    hol_batch input.ml results                                             */
/*                                                                           */
/* expands to                                                                */
/*                                                                           */
/*    (hol <input.ml) | (hol_merge -p '#' input.ml >results)                 */
/*                                                                           */
/* If the HOL session uses a prompt other than '#', the prompt used must be  */
/* specified using the -p option to hol_batch. The names of the HOL          */
/* executable and the merge program to be used can also be changed from the  */
/* defaults above using the -h and -m options respectively.                  */
/*                                                                           */
/* If the size of the expanded command line exceeds `command_line_size' the  */
/* program is likely to fail in an unpleasant manner. The code does NOT      */
/* check that the call to allocate storage for the command line succeeded.   */
/*                                                                           */
/* This code can be compiled using the UNIX command                          */
/*                                                                           */
/*    cc -o hol_batch hol_batch.c                                            */


#include <stdio.h>
#include <string.h>

#define main_program       "hol"
#define merge_program      "hol_merge"
#define default_prompt     "#"
#define command_line_size  256


main(argc, argv)
int argc;
char *argv[];
{
     extern int optind;
     extern char *optarg;
     FILE *fp, *fopen();
     int errflg, c;
     char *call, *calloc(), *main, *merge, *prompt;

     main = main_program;
     merge = merge_program;
     prompt = default_prompt;
     errflg = 0;
     while ((c = getopt(argc, argv, "?p:h:m:")) != -1)
          switch (c) {
          case 'p':
               prompt = optarg;
               break;
          case 'h':
               main = optarg;
               break;
          case 'm':
               merge = optarg;
               break;
          case '?':
               errflg++;
             }
     if ((argc > (optind + 2)) || (argc < (optind + 1)))
          errflg++;
     if (errflg) {
          (void)fprintf(stderr,"usage:\n");
          (void)fprintf(stderr,"%s [-p prompt] [-h hol_exec] ", argv[0]);
          (void)fprintf(stderr,"[-m merge_exec] input_file [output_file]\n");
          exit (2);
        }
     if ((fp = fopen(argv[optind], "r")) == NULL) {
          (void)fprintf(stderr,
                        "%s: can't open %s\n", argv[0], argv[optind]);
          exit (2);
        }
     else
          fclose(fp);
     if (argc > (optind + 1)) {
          if ((fp = fopen(argv[optind + 1], "w")) == NULL) {
               (void)fprintf(stderr,
                             "%s: can't open %s\n", argv[0], argv[optind + 1]);
               exit (2);
             }
          else
               fclose(fp);
        }
     call = calloc(command_line_size,sizeof(char));
     strcpy(call,"(");
     strcat(call,main);
     strcat(call," <");
     strcat(call,argv[optind]);
     strcat(call,") | (");
     strcat(call,merge);
     strcat(call," -p '");
     strcat(call,prompt);
     strcat(call,"' ");
     strcat(call,argv[optind]);
     if (argc > (optind + 1)) {
          strcat(call," >");
          strcat(call,argv[optind + 1]);
        }
     strcat(call,")");
     system(call);
     free(call);
   }


