/*
   Simple example of a C program to invoke TPU.  This program allows you to
   use multiple input files with EVE

   This program is linked with the command
	$ LINK/EXE=medit sys$input:/option
	medit, -
	sys$library:tpushr/share, -
	sys$library:vaxcrtl/lib
	^Z

   In addtion you need to use a command line definition file

    DEFINE VERB medit
	    IMAGE medit$exe:medit
	    PARAMETER p1	    LABEL=file_list, PROMPT="Files",
				    VALUE (LIST, TYPE=$INFILE)

    where the logical name MEDIT$EXE points to the device and directory spec
    for the MEDIT image.
*/

#include stdio			/* Standard I/O definitions */
#include descrip		/* VMS string descriptor defintions */
#include stsdef			/* Status value handling defintions */

/* data structures needed */

struct bpv_arg			/* bound procedure value */
    {
    int *routine_add ;		/* pointer to routine */
    int env ;			/* environment pointer */
    } ;

struct item_list_entry		/* item list data structure */
    {
    short int buffer_length;	/* buffer length */
    short int item_code;	/* item code */
    int *buffer_add;		/* buffer address */
    int *return_len_add;	/* return address */
    } ;

/* Variables resolved at link time */

globalvalue tpu$_success;	/* TPU Success code */
globalvalue tpu$_quitting;	/* Exit code defined by TPU */

globalvalue			/* Cleanup codes defined by TPU */
    tpu$m_delete_journal, tpu$m_delete_exith,
    tpu$m_delete_buffers, tpu$m_delete_windows, tpu$m_delete_cache,
    tpu$m_prune_cache, tpu$m_execute_file, tpu$m_execute_proc,
    tpu$m_delete_context, tpu$m_reset_terminal, tpu$m_kill_processes,
    tpu$m_close_section, tpu$m_delete_others, tpu$m_last_time;
globalvalue			/* Item codes for item list entries */
    tpu$k_fileio, tpu$k_options, tpu$k_sectionfile,
    tpu$k_commandfile ;
globalvalue			/* Option codes for option item */
    tpu$m_display, tpu$m_section, tpu$m_command, tpu$m_create ;
globalvalue			/* Status codes returned by CLI$GET_VALUE */
    cli$_comma, cli$_concat, ss$_normal, cli$_absent;

/* External procedures */

int cli$get_value ();		/* RTL routine to get a command line value */
int lib$establish ();		/* RTL routine to establish an event handler */
int tpu$cleanup ();		/* TPU routine to free resources used */
int tpu$control ();		/* TPU routine to invoke the editor */
int tpu$execute_inifile ();	/* TPU routine to execute initialization code */
int tpu$fileio ();		/* TPU routine to preform file I/O */
int tpu$handler ();		/* TPU signal handling routine */
int tpu$initialize ();		/* TPU routine to initialize the editor */

/*
   This procedure formats the initialization item list and returns it as
   is return value.
 */
callrout()
{
    static struct bpv_arg add_block;		/* BPV for fileio routine */
    int options ;
    char *section_name = "TPUSECINI";
    static struct item_list_entry arg[] =
	{/* length code		     buffer add return add */
	       { 4,tpu$k_fileio,     0,		0 },
	       { 4,tpu$k_options,    0,		0 },
	       { 0,tpu$k_sectionfile,0,		0 },
	       { 0,0,		     0,		0 }
        };

    /* Setup file I/O routine item entry */
    add_block.routine_add = tpu$fileio;
    add_block.env = 0;
    arg[0].buffer_add = &add_block;

    /* Setup options item entry.  Leave journaling off. */
    options = tpu$m_display | tpu$m_section;
    arg[1].buffer_add = &options;

    /* Setup section file name */
    arg[2].buffer_length = strlen(section_name);
    arg[2].buffer_add = section_name;

    return arg;
}

/*
   This function gets the files specified in the command line and feeds them
   one at a time to EVE
 */
read_files ()
{
    int window_mode;
    int status;
    char eve_command[512];
    static $DESCRIPTOR (file_list_label, "FILE_LIST");
    struct dsc$descriptor_d dyn_mem_desc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
    struct dsc$descriptor_s command_desc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};

/* Fetch the first file specification from DCL */

    status = cli$get_value (&file_list_label, &dyn_mem_desc);
    if (status == cli$_absent)
	return tpu$_success;

/* Build the string to read a file */

    strcpy (eve_command, "eve_do ('get file ");
    strncat (eve_command,
		dyn_mem_desc.dsc$a_pointer,
		dyn_mem_desc.dsc$w_length);
    strcat (eve_command, "')");
    
/* Have TPU execute the command we just built */

    command_desc.dsc$w_length = strlen (eve_command);
    command_desc.dsc$a_pointer = eve_command;
    status = tpu$execute_command (&command_desc);
    if (! (status & STS$M_SUCCESS))
	return status;

/* Fetch any additional file specifications from DCL */

    window_mode = 1;
    do
	{
	status = cli$get_value (&file_list_label, &dyn_mem_desc);
	if (status != cli$_absent)
	    {

/* Put EVE into 2 window mode */

	    if (window_mode == 1)
		{
		command_desc.dsc$w_length = strlen ("eve_do ('two')");
		command_desc.dsc$a_pointer = "eve_do ('two')";
		status = tpu$execute_command (&command_desc);
		if (! (status & STS$M_SUCCESS))
		    return status;
		window_mode = 2;
		}

/* Build the string to position to the other window and fetch a file into it */

	    strcpy (eve_command, "eve_do ('other'); eve_do ('get file ");
	    strncat (eve_command, dyn_mem_desc.dsc$a_pointer,
				  dyn_mem_desc.dsc$w_length);
	    strcat (eve_command, "')");
    
/* Have TPU execute the command we just built */

	    command_desc.dsc$w_length = strlen (eve_command);
	    command_desc.dsc$a_pointer = &eve_command;
	    status = tpu$execute_command (&command_desc);
	    if (! (status & STS$M_SUCCESS))
		return status;
	    }
	}
    while (status != cli$_absent);

    return tpu$_success;
}

/*
   Main program.  Initializes TPU, then passes control to it.
 */
main()
{
    int return_status ;
    int cleanup_options;
    struct bpv_arg add_block;

/* Establish as condition handler the normal VAXTPU handler */

    lib$establish(tpu$handler);

/* Setup a BPV to point to the callback routine */

    add_block.routine_add = callrout ;
    add_block.env = 0;

/* Do the initialize of VAXTPU */

    return_status = tpu$initialize(&add_block);
    if (!return_status)
	exit(return_status);

/* Have TPU execute the procedure TPU$INIT_PROCEDURE from the section file */
/* and then compile and execute the code from the command file */

    return_status = tpu$execute_inifile();
    if (!return_status)
	exit (return_status);

/* Have EVE read in the files specified on the command line */
    return_status = read_files();
    if (!return_status)
	exit (return_status);

/* Turn control over to VAXTPU */

    return_status = tpu$control ();
    if (!return_status)
	exit(return_status);

/* Now clean up. */

    cleanup_options = tpu$m_last_time | tpu$m_delete_context;
    return_status = tpu$cleanup (&cleanup_options);
    exit (return_status);

    printf("Experiment complete");
}
