📄 ecosynth.c
字号:
// 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 intecosynth_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 applicationstatic intecosynth_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 intecosynth_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 + -