⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecosynth.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:

    // Similarly ignore SIGTSTP if running in graphical mode, it would
    // be inappropriate for the GUI to freeze if the eCos application is
    // suspended. If running in text mode then it is better for both
    // the application and the I/O auxiliary to freeze, halting any further
    // output.
    if (!no_windows) {
        signal(SIGTSTP, SIG_IGN);
    }

    Tcl_Main(argc+1, new_argv, &ecosynth_appinit);
    return EXIT_SUCCESS;
}


// ----------------------------------------------------------------------------
// Commands for the Tcl interpreter. These are few and far between because
// as much work as possible is done in Tcl.

// Send a SIGIO signal to the parent process. This is done whenever a new
// interrupt is pending. There is a possibility of strange behaviour if
// the synthetic target application is exiting at just the wrong moment
// and this process has become a zombie. An alternative approach would
// involve loading the Extended Tcl extension.
static int
ecosynth_send_SIGIO(ClientData  clientData __attribute__ ((unused)),
                    Tcl_Interp* interp,
                    int         argc,
                    char**      argv __attribute__ ((unused)))
{
    if (1 != argc) {
        Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_send_SIGIO\"" , TCL_STATIC);
        return TCL_ERROR;
    }
    
    (void) kill(parent_pid, SIGIO);
    return TCL_OK;
}

// Similarly send a SIGKILL (-9) to the parent process. This allows the GUI
// code to kill of the eCos application
static int
ecosynth_send_SIGKILL(ClientData clientData __attribute__ ((unused)),
                      Tcl_Interp* interp,
                      int         argc,
                      char**      argv __attribute__ ((unused)))
{
    if (1 != argc) {
        Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_send_SIGIO\"" , TCL_STATIC);
        return TCL_ERROR;
    }
    
    (void) kill(parent_pid, SIGKILL);
    return TCL_OK;
}


// ----------------------------------------------------------------------------
// Application-specific initialization.

static int
ecosynth_appinit(Tcl_Interp* interp)
{
    Tcl_Channel from_app;
    Tcl_Channel to_app;

    // Tcl library initialization. This has the effect of executing init.tcl,
    // thus setting up package load paths etc. Not all of that initialization
    // is necessarily appropriate for ecosynth, but some devices may well want
    // to load in additional packages or whatever.
    if (Tcl_Init(interp) == TCL_ERROR) {
        return TCL_ERROR;
    }
    // Optionally initialize Tk as well. This can be suppressed by an
    // argument -nw. Possibly this could be done by the Tcl script
    // instead using dynamic loading.
    //
    // There is a problem with the way that Tk does its argument processing.
    // By default it will accept abbreviations for the standard wish arguments,
    // so if the user specifies e.g. -v then the Tk code will interpret this
    // as an abbreviation for -visual, and will probably complain because
    // -visual takes an argument whereas ecosynth's -v is just a flag.
    //
    // The Tk argument processing can be suppressed simply by temporarily
    // getting rid of the argv variable. The disadvantage is that some
    // standard arguments now have to be processed explicitly:
    //
    //     -colormap map      ignored, of little interest these days
    //     -display  display  currently ignored. This would have to be
    //                        implemented at the C level, not the Tcl level,
    //                        since Tk_Init() will start interacting with the
    //                        X server. Its implementation would involve a
    //                        setenv() call.
    //     -geometry geom     implemented in the Tcl code using "wm geometry"
    //     -name     name     ignored for now.
    //     -sync              ignored, of little interest to typical users
    //     -use      id       ignored, probably of little interest for now
    //     -visual   visual   ignored, of little interest these days
    //
    // so actually the only extra work that is required is for the Tcl code
    // to process -geometry.
    if (!no_windows) {
        Tcl_Obj* argv = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
        Tcl_IncrRefCount(argv);
        Tcl_UnsetVar(interp, "argv", TCL_GLOBAL_ONLY);
        if (Tk_Init(interp) == TCL_ERROR) {
            return TCL_ERROR;
        }
        Tcl_SetVar2Ex(interp, "argv", NULL, argv, TCL_GLOBAL_ONLY);
        Tcl_DecrRefCount(argv);
    }
    
    // Create the synth:: namespace. Currently this does not seem to be possible from
    // inside C.
    if (TCL_OK != Tcl_Eval(interp, 
                           "namespace eval synth {\n"
                           "    variable channel_from_app 0\n"
                           "    variable channel_to_app 0\n"
                           "}\n")) {
        fprintf(stderr, PROGNAME ": internal error, failed to create Tcl synth:: namespace\n");
        fprintf(stderr, "    Please check Tcl version (8.3 or later required).\n");
        exit(EXIT_FAILURE);
    }

    // The pipe to/from the application is exposed to Tcl, allowing
    // the main communication to be handled at the Tcl level and
    // specifically via the event loop. This requires two additional
    // Tcl channels to be created for file descriptors 3 and 4.
    from_app = Tcl_MakeFileChannel((ClientData) 3, TCL_READABLE);
    if (NULL == from_app) {
        fprintf(stderr, PROGNAME ": internal error, failed to create Tcl channel for pipe from application.\n");
        exit(EXIT_FAILURE);
    }
    Tcl_RegisterChannel(interp, from_app);

    // The channel name will be something like file0. Add a variable to the
    // interpreter to store this name.
    if (NULL == Tcl_SetVar(interp, "synth::_channel_from_app",  Tcl_GetChannelName(from_app), TCL_GLOBAL_ONLY)) {
        fprintf(stderr, PROGNAME ": internal error, failed to create Tcl variable from application channel 0\n");
        exit(EXIT_FAILURE);
    }

    // Repeat for the channel to the application.
    to_app = Tcl_MakeFileChannel((ClientData) 4, TCL_WRITABLE);
    if (NULL == to_app) {
        fprintf(stderr, PROGNAME ": internal error, failed to create Tcl channel for pipe to application.\n");
        exit(EXIT_FAILURE);
    }
    Tcl_RegisterChannel(interp, to_app);
    if (NULL == Tcl_SetVar(interp, "synth::_channel_to_app",  Tcl_GetChannelName(to_app), TCL_GLOBAL_ONLY)) {
        fprintf(stderr, PROGNAME ": internal error, failed to create Tcl variable from application channel 1\n");
        exit(EXIT_FAILURE);
    }

    // The auxiliary may spawn additional programs, via
    // device-specific scripts. Those programs should not have
    // direct access to the pipe - that would just lead to
    // confusion.
    fcntl(3, F_SETFD, FD_CLOEXEC);
    fcntl(4, F_SETFD, FD_CLOEXEC);
    
    // Add synthetic target-specific commands to the Tcl interpreter.
    Tcl_CreateCommand(interp, "synth::_send_SIGIO", &ecosynth_send_SIGIO, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateCommand(interp, "synth::_send_SIGKILL", &ecosynth_send_SIGKILL, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL);

    // Define additional variables.

    // The version, from the AM_INIT_AUTOMAKE() macro in configure.in
    Tcl_SetVar(interp, "synth::_ecosynth_version", ECOSYNTH_VERSION, TCL_GLOBAL_ONLY);

    // The parent process id, i.e. that for the eCos application itself.
    Tcl_SetVar2Ex(interp, "synth::_ppid", NULL, Tcl_NewIntObj(getppid()), TCL_GLOBAL_ONLY);
               
    // The various directories
    Tcl_SetVar(interp, "synth::_ecosynth_repository", ECOS_REPOSITORY, TCL_GLOBAL_ONLY);
    Tcl_SetVar(interp, "synth::_ecosynth_libexecdir", LIBEXECDIR, TCL_GLOBAL_ONLY);
    Tcl_SetVar(interp, "synth::_ecosynth_package_dir", PACKAGE_DIR, TCL_GLOBAL_ONLY);
    Tcl_SetVar(interp, "synth::_ecosynth_package_version", PACKAGE_VERSION, TCL_GLOBAL_ONLY);
    Tcl_SetVar(interp, "synth::_ecosynth_package_install", PACKAGE_INSTALL, TCL_GLOBAL_ONLY);
    
    return TCL_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -