📄 main.c
字号:
/* * main.c -- * * Main program for "dlxview" simulator for DLX architecture. * * This file is part of DISC. It was modified by Yinong Zhang * (yinong@ecn.purdue.edu) from the file "main.c" in the distribution * of "dlxsim" available at: * ftp://max.stanford.edu/pub/hennessy-patterson.software/dlx.tar.Z * * The original source code is copyright as follows: * * Copyright 1989 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * */#include <stdio.h>#include <tcl.h>#include <tk.h>#include <signal.h>#include "dlx.h"#include "purdue.h"/* * Declarations for various library procedures and variables (don't want * to include tkInt.h or tkConfig.h here, because people might copy this * file out of the Tk source directory to make their own modified versions). */extern void exit ();extern int isatty ();extern int read ();extern char * strrchr ();/* * Global variables used by the main program: */static Tk_Window mainWindow; /* The main window for the application. If * NULL then the application no longer * exists. */static Tcl_Interp *interp; /* Interpreter for this application. */static Tcl_DString command; /* Used to assemble lines of terminal input * into Tcl commands. */static int tty; /* Non-zero means standard input is a * terminal-like device. Zero means it's * a file. */static char errorExitCmd[] = "exit 1";static DLX *machPtr;/* * Command-line options: */static int synchronize = 0;static char *fileName = NULL;static char *name = NULL;static char *display = NULL;static char *geometry = NULL;static Tk_ArgvInfo argTable[] = { {"-file", TK_ARGV_STRING, (char *) NULL, (char *) &fileName, "File from which to read commands"}, {"-geometry", TK_ARGV_STRING, (char *) NULL, (char *) &geometry, "Initial geometry for window"}, {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display, "Display to use"}, {"-name", TK_ARGV_STRING, (char *) NULL, (char *) &name, "Name to use for application"}, {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize, "Use synchronous mode for display server"}, {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL, (char *) NULL}};/* * Declaration for Tcl command procedure to create demo widget. This * procedure is only invoked if SQUARE_DEMO is defined. */extern int SquareCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]));/* * Forward declarations for procedures defined later in this file: */static void Prompt (Tcl_Interp *, int);static void StdinProc (ClientData, int);static void Interrupt(int);/* *---------------------------------------------------------------------- * * main -- * * Top-level procedure for dlxview simulator. * * Results: * None. * * Side effects: * Tons: read the user manual for details. * *---------------------------------------------------------------------- */intmain(argc, argv) int argc; /* Number of arguments. */ char **argv; /* Array of argument strings. */{ char *p, *msg; int code; char *tcl_RcFileName; interp = Tcl_CreateInterp(); /* * Parse command-line arguments. */ if (Tk_ParseArgv(interp, (Tk_Window) NULL, &argc, argv, argTable, 0) != TCL_OK) { fprintf(stderr, "%s\n", interp->result); exit(1); } if (name == NULL) { if (fileName != NULL) { p = fileName; } else { p = argv[0]; } name = strrchr(p, '/'); if (name != NULL) { name++; } else { name = p; } } /* * If a display was specified, put it into the DISPLAY * environment variable so that it will be available for * any sub-processes created by us. */ if (display != NULL) { Tcl_SetVar2(interp, "env", "DISPLAY", display, TCL_GLOBAL_ONLY); } /* * Initialize the Tk application. */#if defined(TK40) mainWindow = Tk_CreateMainWindow(interp, display, name, "Tk"); if (mainWindow == NULL) { fprintf(stderr, "%s\n", interp->result); exit(1); }#endif if (synchronize) { XSynchronize(Tk_Display(mainWindow), True); }#if defined(TK40) Tk_GeometryRequest(mainWindow, 200, 200); #endif /* * Set the "tcl_interactive" variable. */ tty = isatty(0); Tcl_SetVar(interp, "tcl_interactive", ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY); /* * Add a few application-specific commands to the application's * interpreter. */ /* * Invoke application-specific initialization. */ if (Tcl_Init(interp) != TCL_OK) { fprintf(stderr, "Tcl_Init failed: %s\n", interp->result); } if (Tk_Init(interp) != TCL_OK) { fprintf(stderr, "Tk_Init failed: %s\n", interp->result); } tcl_RcFileName = "~/.dlxviewrc"; machPtr = Sim_Create(interp); (void) signal(SIGINT, Interrupt); Tk_DefineBitmap(interp, Tk_GetUid("purdue"), (char *)pur_bits, pur_width, pur_height);#ifdef SCRIPT code = Tcl_VarEval(interp, "source dlxview.tcl", (char *) NULL); if (code != TCL_OK) { goto error; } #else Script_Read(interp);#endif Sim_Initialize(machPtr); /* * Set the geometry of the main window, if requested. */ if (geometry != NULL) { code = Tcl_VarEval(interp, "wm geometry . ", geometry, (char *) NULL); if (code != TCL_OK) { fprintf(stderr, "%s\n", interp->result); } } /* * Invoke the script specified on the command line, if any. */ if (fileName != NULL) { code = Tcl_VarEval(interp, "source ", fileName, (char *) NULL); if (code != TCL_OK) { goto error; } tty = 0; } else { /* * Commands will come from standard input, so set up an event * handler for standard input. If the input device is aEvaluate the * .rc file, if one has been specified, set up an event handler * for standard input, and print a prompt if the input * device is a terminal. *//* if (tcl_RcFileName != NULL) { Tcl_DString buffer; char *fullName; FILE *f; fullName = Tcl_TildeSubst(interp, tcl_RcFileName, &buffer); if (fullName == NULL) { fprintf(stderr, "%s\n", interp->result); } else { f = fopen(fullName, "r"); if (f != NULL) { code = Tcl_EvalFile(interp, fullName); if (code != TCL_OK) { fprintf(stderr, "%s\n", interp->result); } fclose(f); } } Tcl_DStringFree(&buffer); }*/ Tk_CreateFileHandler(0, TK_READABLE, StdinProc, (ClientData) 0); if (tty) { Prompt(interp, 0); } } fflush(stdout); Tcl_DStringInit(&command); /* * Loop infinitely, waiting for commands to execute. When there * are no windows left, Tk_MainLoop returns and we exit. */ Tk_MainLoop(); /* * Don't exit directly, but rather invoke the Tcl "exit" command. * This gives the application the opportunity to redefine "exit" * to do additional cleanup. */ Tcl_Eval(interp, "exit"); exit(1);error: msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); if (msg == NULL) { msg = interp->result; } fprintf(stderr, "%s\n", msg); Tcl_Eval(interp, errorExitCmd); return 1; /* Needed only to prevent compiler warnings. */}/* *---------------------------------------------------------------------- * * StdinProc -- * * This procedure is invoked by the event dispatcher whenever * standard input becomes readable. It grabs the next line of * input characters, adds them to a command being assembled, and * executes the command if it's complete. * * Results: * None. * * Side effects: * Could be almost arbitrary, depending on the command that's * typed. * *---------------------------------------------------------------------- */ /* ARGSUSED */static voidStdinProc(clientData, mask) ClientData clientData; /* Not used. */ int mask; /* Not used. */{#define BUFFER_SIZE 4000 char input[BUFFER_SIZE+1]; static int gotPartial = 0; char *cmd; int code, count; count = read(fileno(stdin), input, BUFFER_SIZE); if (count <= 0) { if (!gotPartial) { if (tty) { Tcl_Eval(interp, "exit"); exit(1); } else { Tk_DeleteFileHandler(0); } return; } else { count = 0; } } cmd = Tcl_DStringAppend(&command, input, count); if (count != 0) { if ((input[count-1] != '\n') && (input[count-1] != ';')) { gotPartial = 1; goto prompt; } if (!Tcl_CommandComplete(cmd)) { gotPartial = 1; goto prompt; } } gotPartial = 0; /* * Disable the stdin file handler while evaluating the command; * otherwise if the command re-enters the event loop we might * process commands from stdin before the current command is * finished. Among other things, this will trash the text of the * command being evaluated. */ Tk_CreateFileHandler(0, 0, StdinProc, (ClientData) 0); code = Tcl_RecordAndEval(interp, cmd, 0); Tk_CreateFileHandler(0, TK_READABLE, StdinProc, (ClientData) 0); Tcl_DStringFree(&command); if (*interp->result != 0) { if ((code != TCL_OK) || (tty)) { printf("%s\n", interp->result); } } /* * Output a prompt. */ prompt: if (tty) { Prompt(interp, gotPartial); }}/* *---------------------------------------------------------------------- * * Prompt -- * * Issue a prompt on standard output, or invoke a script * to issue the prompt. * * Results: * None. * * Side effects: * A prompt gets output, and a Tcl script may be evaluated * in interp. * *---------------------------------------------------------------------- */static voidPrompt(interp, partial) Tcl_Interp *interp; /* Interpreter to use for prompting. */ int partial; /* Non-zero means there already * exists a partial command, so use * the secondary prompt. */{ char *promptCmd; int code; promptCmd = Tcl_GetVar(interp, partial ? "tcl_prompt2" : "tcl_prompt1", TCL_GLOBAL_ONLY); if (promptCmd == NULL) { defaultPrompt: if (!partial) { fputs("(dlxview) ", stdout); } } else { code = Tcl_Eval(interp, promptCmd); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); fprintf(stderr, "%s\n", interp->result); goto defaultPrompt; } } fflush(stdout);}/* *---------------------------------------------------------------------- * * Interrupt -- * * This procedure is invoked when the interrupt key is typed: * it causes the simulation to stop. * * Results: * None. * * Side effects: * Causes simultor to stop after next instruction. * *---------------------------------------------------------------------- */static voidInterrupt(dumb) int dumb;{ fprintf( stderr, "interrupt\n" ); Sim_Stop(machPtr);}/* *---------------------------------------------------------------------- * * Main_QuitCmd -- * * This procedure is invoked to process the "quit" Tcl command. * See the user documentation for details on what it does. * * Results: * None: this command never returns. * * Side effects: * The program exits. * *---------------------------------------------------------------------- *//* ARGSUSED */intMain_QuitCmd(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ exit(0); return TCL_OK; /* Never gets executed. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -