/* %Z%%M% %I% %E% */

/*
 * Copyright (c) 1991-2009 by Wayne C. Gramlich.
 * All rights reserved.
 */

/*
 * This is the stand-alone STIPPLE debugger.  It's entire purpose
 * in life is to print a prompt and take a "debug command".  It
 * must also know enough to estabblish a connect with stdbtool.
 */

#ifndef FILE_EXPORTS_H
#include "file_exports.h"
#endif

#ifndef HEAP_EXPORTS_H
#include "heap_exports.h"
#endif

#ifndef LIBC_EXPORTS_H
#include "libc_exports.h"
#endif

#ifndef LINT_H
#include "lint.h"
#endif

#ifndef RUN_TIME_DEFS_H
#include "run_time_defs.h"
#endif

#ifndef STR_EXPORTS_H
#include "str_exports.h"
#endif

#ifndef UNIX_ASSERT_H
#include "unix_assert.h"
#endif

#ifndef UNIX_STDIO_H
#include "unix_stdio.h"
#endif

#ifndef UNIX_STDLIB_H
#include "unix_stdlib.h"
#endif

#ifndef UNIX_UNISTD_H
#include "unix_unistd.h"
#endif

LOCAL Str		path_lookup(Run_time, Str);

int
main(
	int		argc,
	char		**argv)
{
	Str		arg;
	Vec(Str)	args;
	Str		*arg_vec;
	Str		*arg_vec_ptr;
	Heap		heap;
	int		index;
	Vec(module___object *) modules;
	int		run_dbxtool;
	Run_time	run_time;
	int		size;
	Str		std_path;

	argc--;
	argv++;

	heap = heap_standard_create();
	modules = vec_create(module___object *, heap);
	run_time = run__time__debug_initialize(Std_state_none, modules);

	/* Set up aliases */
	run__time__alias_set(run_time, "c", "continue");
	run__time__alias_set(run_time, "clear", "unstop_at");
	run__time__alias_set(run_time, "cont", "continue");
	run__time__alias_set(run_time, "d", "in");
	run__time__alias_set(run_time, "down", "in");
	run__time__alias_set(run_time, "i", "in");
	run__time__alias_set(run_time, "n", "step_over");
	run__time__alias_set(run_time, "next", "step_over");
	run__time__alias_set(run_time, "o", "out");
	run__time__alias_set(run_time, "p", "print");
	run__time__alias_set(run_time, "s", "step_in");
	run__time__alias_set(run_time, "sa", "stop_at");
	run__time__alias_set(run_time, "si", "stop_in");
	run__time__alias_set(run_time, "where", "stack");
	run__time__alias_set(run_time, "u", "out");
	run__time__alias_set(run_time, "up", "out");

	run_dbxtool = (getenv("DISPLAY") != (Str)0);
	args = vec_create(Str, heap);

	/* Search for -P option: */
	for (index = 0; index < argc; index++) {
		arg = argv[index];
		if (strequal(arg, "-P")) {
			index++;
			if (index >= argc) {
				(void)fprintf(stderr,
					      "No argument after -P\n");
				return 1;
			}
			run__time__pipe_initialize(run_time,
						   atoi(argv[index]));
			run_dbxtool = 0;
		} else if (strequal(arg, "-t")) {
			run_dbxtool = 0;
		} else if (strequal(arg, "-e")) {
			run_time->echo = 1;
		} else {
			vec_append(Str, args, arg);
		}
	}

	/* Execute dbxtool if necessary: */
	if (run_dbxtool) {
		std_path = path_lookup(run_time, "std");
		if (std_path == (Str)0) {
			(void)fprintf(stderr, "Could not find `%s' in path!\n",
			              std_path);
			exit(1);
		}
		size = vec_size(Str, args);
		arg_vec = (Str *)heap_alloc(heap, sizeof(Str) * (size + 10));
		arg_vec_ptr = arg_vec;
		*arg_vec_ptr++ = "stdtool";
		*arg_vec_ptr++ = "-usepipe";
		*arg_vec_ptr++ = "-db";
		*arg_vec_ptr++ = std_path;
		for (index = 0; index < size; index++) {
			arg = vec_fetch(Str, args, index);
			*arg_vec_ptr++ = arg;
		}
		*arg_vec_ptr = (Str)0;
		(void)execvp("stdtool", (const char *)arg_vec);
		assert_fail();
	}

	/* Set up buttons: */
	run__time__unbutton(run_time, "Display");
	run__time__unbutton(run_time, "Display *");
	run__time__unbutton(run_time, "Down");
	run__time__unbutton(run_time, "Up");
	run__time__unbutton(run_time, "Print");
	run__time__unbutton(run_time, "Print *");
	run__time__unbutton(run_time, "Where");
	run__time__unbutton(run_time, "Step");
	run__time__unbutton(run_time, "Next");
	run__time__unbutton(run_time, "Continue");
	run__time__unbutton(run_time, "Run");
	run__time__unbutton(run_time, "Clear");
	run__time__unbutton(run_time, "Stop In");
	run__time__unbutton(run_time, "Stop At");
	run__time__button(run_time, "Print", Dbx_button_literal);
	run__time__button(run_time, "Stop At", Dbx_button_line_num);
	run__time__button(run_time, "Stop In", Dbx_button_literal);
	run__time__button(run_time, "Continue", Dbx_button_ignore);
	run__time__button(run_time, "Step In", Dbx_button_ignore);
	run__time__button(run_time, "Step Over", Dbx_button_ignore);
	run__time__button(run_time, "Step To", Dbx_button_line_num);
	run__time__button(run_time, "Step Out", Dbx_button_ignore);
	run__time__button(run_time, "Stack", Dbx_button_ignore);
	run__time__button(run_time, "Unstop At", Dbx_button_line_num);
	run__time__button(run_time, "Unstop In", Dbx_button_literal);
	run__time__button(run_time, "In", Dbx_button_ignore);
	run__time__button(run_time, "Out", Dbx_button_ignore);
	run__time__button(run_time, "Run", Dbx_button_ignore);
	run__time__button(run_time, "Rerun", Dbx_button_ignore);
	run__time__button(run_time, "Status", Dbx_button_ignore);
	run__time__button(run_time, "Delete", Dbx_button_literal);

	run__time__cmd_loop();
	return 0;
}

/*
 * path_lookup(run_time, program)
 *	 This routine will return a path for "program".
 */
LOCAL Str
path_lookup(
	Run_time	run_time,
	Str		program)
{
	char		file_name[2000];
	Stdio		in_file;
	Str		path_var;
	Str		path_ptr1;
	Str		path_ptr2;

	path_var = run__time__env_str_get(run_time, "PATH");
	assert(path_var != (Str)0);
	path_ptr1 = path_var;
	for (;;) {
		path_ptr2 = strchr(path_ptr1, ':');
		if (path_ptr2 == (Str)0) {
			break;
		}
		*path_ptr2 = '\0';
		(void)sprintf(file_name, "%s/%s", path_ptr1, program);
		*path_ptr2 = ':';
		in_file = fopen(file_name, "r");
		if (in_file != (Stdio)0) {
			(void)fclose(in_file);
			return strdupl(file_name, run_time->heap);
		}
		path_ptr1 = path_ptr2 + 1;
	}
	return (Str)0;
}
