📄 ecosynth.tcl
字号:
# -nw, -w, and related options have been processed by the C code.
# Look them up anyway to consume them.
synth::_argv_lookup "-io"
synth::_argv_lookup "-nw"
synth::_argv_lookup "-no-windows"
synth::_argv_lookup "-w"
synth::_argv_lookup "-windows"
# Now cope with the other standard flags
if { [synth::argv_defined "-v"] || [synth::argv_defined "--version"] } {
# Just output the version message and exit. The eCos application
# will do the same. The version is obtained from configure.in,
# and also from the install directory. The synthetic target
# startup code will exit quietly if the auxiliary exits at this
# stage. This output should go via puts rather than the
# synth:: output routines, since the GUI will never appear if
# --version is specified.
puts "ecosynth: version $synth::_ecosynth_version"
puts " : install location [file dirname [info script]]"
exit 0
}
if { [synth::argv_defined "-l="] } {
set synth::logfile [synth::argv_get_value "-l="]
} elseif { [synth::argv_defined "-logfile="] } {
set synth::logfile [synth::argv_get_value "-logfile="]
}
if { "" != $synth::logfile } {
synth::logfile_open
}
# -h/--help would normally also result in an immediate exit. However,
# the device-specific scripts have not yet been loaded so there
# is no way of reporting their options. Hence the usage information
# is delayed until later. Suppressing GUI mode as a side effect is
# probably a good idea as well, that way the output appears in the
# current console window.
if { [synth::argv_defined "-h"] || [synth::argv_defined "-help"] } {
set synth::flag_help 1
set synth::flag_gui 0
}
if { [synth::argv_defined "-debug"] } {
set synth::flag_debug 1
}
if { [synth::argv_defined "-k"] || [synth::argv_defined "-keep-going"] } {
set synth::flag_keep_going 1
}
if { [synth::argv_defined "-nr"] || [synth::argv_defined "-no-rc"]} {
set synth::flag_no_rc 1
}
if { [synth::argv_defined "-x"] || [synth::argv_defined "-exit"] } {
set synth::flag_immediate_exit 1
} elseif { [synth::argv_defined "-nx"] || [synth::argv_defined "-no-exit"] } {
set synth::flag_immediate_exit 0
}
if { [synth::argv_defined "-V"] || [synth::argv_defined "-verbose"] } {
set synth::flag_verbose 1
}
if { [synth::argv_defined "-t="] } {
set synth::target_definition [synth::argv_get_value "-t="]
} elseif { [synth::argv_defined "-target="] } {
set synth::target_definition [synth::argv_get_value "-target="]
}
# Arguably -geometry should only be checked when the GUI is enabled,
# but doing so at all times is harmless.
# Note that '-geometry ""' means that any value held in the
# preferences file should be ignored. Hence the regexp below
# accepts the empty string, and treats it separately from
# uninitialized.
if { [synth::argv_defined "-geometry="] } {
set synth::geometry [synth::argv_get_value "-geometry="]
if { ![regexp -- {^([0-9]+x[0-9]+)?([+-][0-9]+[+-][0-9]+)?$} $synth::geometry] } {
synth::report_warning "Invalid geometry string $synth::geometry\n"
set synth::geometry "<none>"
}
}
if { $synth::flag_debug } {
synth::report \
"Results of initial command-line parsing:\n \
--help $synth::flag_help\n \
--keep-going $synth::flag_keep_going\n \
--no-rc $synth::flag_no_rc\n \
--exit $synth::flag_immediate_exit\n \
--verbose $synth::flag_verbose\n \
logfile $synth::logfile\n \
target definition $synth::target_definition\n \
geometry $synth::geometry\n \
unconsumed [synth::get_unconsumed_args]\n"
}
}
# }}}
# {{{ Create and populate ~/.ecos/synth
# ----------------------------------------------------------------------------
# If the per-user configuration directories do not exist yet, create them.
# Also install default initrc.tcl and mainrc.tcl files which do nothing, but
# which can be edited. If problems occur then the user gets a warning
# but execution proceeds.
#
# Some people may object to this automatic creation of directories and
# configuration files. However there is plenty of precedent, and the
# files involved are small. Messages are generated so that the user
# knows what has happened.
#
# Currently the default target definition file is not copied from
# the install tree into the per-user tree. Although some users will
# be happy having this file in ~/.ecos/synth, others may prefer it
# to be more visible in the current directory.
if { ![file exists "~/.ecos"] } {
synth::report "Creating new directory ~/.ecos for eCos configuration files.\n"
if { 0 != [catch { file mkdir "~/.ecos" }] } {
synth::report_warning "failed to create directory ~/.ecos\n"
}
}
if { [file exists "~/.ecos"] && [file isdirectory "~/.ecos"] && ![file exists "~/.ecos/synth"] } {
synth::report "Creating new directory ~/.ecos/synth for synthetic target configuration files.\n"
if { 0 != [catch { file mkdir "~/.ecos/synth" } ] } {
synth::report_warning "failed to create directory ~/.ecos/synth\n"
} else {
# initrc and mainrc are only copied when the directory is first created,
# so that users can delete them if unwanted - even though the
# default versions do nothing.
synth::report "Installing default configuration files ~/.ecos/synth/initrc.tcl and ~/.ecos/synth/mainrc.tcl\n"
catch { file copy -- [file join $synth::install_dir "user_initrc.tcl"] "~/.ecos/synth/initrc.tcl"}
catch { file copy -- [file join $synth::install_dir "user_mainrc.tcl"] "~/.ecos/synth/mainrc.tcl"}
}
}
# }}}
# {{{ Read target definition file
# ----------------------------------------------------------------------------
# Once the GUI is up and running it is possible to start reading in some
# configuration files. The first of these is the target definition file.
# Typically this would be ~/.ecos/synth/default.tdf. An alternative
# definition file can be specified on the command line with the
# -t argument, and the code will look in the current directory,
# in ~/.ecos/synth, and in the install tree.
#
# The purpose of the target definition file is to specify exactly
# how I/O gets implemented. For example the eCos application may
# want to access a network device eth0, but that device could be
# implemented in a variety of ways (e.g. a real ethernet device
# on the Linux host, or a fake device provided by the ethertap
# facility). It is the target definition file that provides
# this information.
#
# The file is of course just another Tcl script, running in the
# current interpreter. There seems little point in using a safe
# interpreter given the considerable number of other Tcl scripts
# that are being used, some of which need the ability to e.g.
# run other programs. The main command is synth_device which
# takes two arguments, a device name and some options for that
# device, e.g.:
#
# synth_device eth0 {
# use eth1
# }
#
# synth_device eth1 {
# use tap0
# }
#
# When the eCos device driver looks up eth0 this will cause a
# device-specific Tcl script to be loaded, which can examine
# this data.
#
# This code has no way of knowing what constitutes valid or invalid
# contents for an eth0 device, especially since the Tcl script that
# could provide such knowledge has not been loaded. Instead it is
# assumed that the contents is another set of Tcl commands such as
# "physical", which will of course not be defined so the Tcl interpreter
# will invoke "unknown" which is temporarily redefined here. This makes
# it possible for the device-specific commands to have arbitrary number
# of arguments, or to define Tcl fragments for hooks, or whatever.
#
# As with argument processing, the code attempts to keep track of
# which devices and options have been "consumed" and can issue
# warnings about any unused devices or options. This helps to track
# down typos and similar problems. These warnings are only output
# when running at verbose mode, since it is fairly normal practice
# to have a single target definition file which supports
# a number of different eCos applications with different I/O
# requirements.
namespace eval synth {
# A list of all devices specified in the target definition file.
# For now assume that a given device will only be specified once.
variable _tdf_devices [list]
# An array with additional details of each device. This will have
# entries such as _tdf_device_options(eth0,4), where the second
# argument is a per-device index. The value of each entry is
# a list of the actual command and its arguments. This use of
# an index allows for multiple instances of a per-device
# option.
array set _tdf_device_options [list]
# While reading in the device details it is necessary to keep track
# of the current device, if any. Otherwise the implementation of
# "unknown" will not be able to update _tdf_device_options. An index
# is needed as well.
variable _tdf_current_device ""
variable _tdf_current_index 0
# Keep track of which devices and options have been consumed
variable _tdf_consumed_devices [list]
variable _tdf_consumed_options [list]
proc tdf_has_device { name } {
return [expr -1 != [lsearch -exact $synth::_tdf_devices $name]]
}
proc tdf_get_devices { } {
return $synth::_tdf_devices
}
proc _tdf_get_option_index { devname option } {
synth::_tdf_consume_device $devname
for { set i 0 } { [info exists synth::_tdf_device_options($devname,$i)] } { incr i } {
if { $option == [lindex $synth::_tdf_device_options($devname,$i) 0] } {
synth::_tdf_consume_option $devname $i
return $i
}
}
return -1
}
proc _tdf_get_option_indices { devname option } {
synth::_tdf_consume_device $devname
set result [list]
for { set i 0 } { [info exists synth::_tdf_device_options($devname,$i)] } { incr i } {
if { $option == [lindex $synth::_tdf_device_options($devname,$i) 0] } {
synth::_tdf_consume_option $devname $i
lappend result $i
}
}
return $result
}
proc tdf_has_option { devname option } {
return [expr -1 != [synth::_tdf_get_option_index $devname $option]]
}
proc tdf_get_option { devname option } {
set index [synth::_tdf_get_option_index $devname $option]
if { -1 != $index } {
lappend synth::_tdf_consumed_options "$devname,$index"
return [lrange $synth::_tdf_device_options($devname,$index) 1 end]
} else {
return [list]
}
}
proc tdf_get_options { devname option } {
set result [list]
set indices [synth::_tdf_get_option_indices $devname $option]
foreach index $indices {
lappend result [lrange $synth::_tdf_device_options($devname,$index) 1 end]
}
return $result
}
proc tdf_get_all_options { devname } {
set result [list]
for { set i 0 } { [info exists synth::_tdf_device_options($devname,$i)] } { incr i } {
lappend synth::_tdf_consumed_options "$devname,$index"
lappend result $synth::_tdf_device_options($devname,$i)
}
return $result
}
proc _tdf_consume_device { name } {
if { -1 == [lsearch -exact $synth::_tdf_consumed_devices $name] } {
lappend synth::_tdf_consumed_devices $name
}
}
proc _tdf_consume_option { devname index } {
if { -1 == [lsearch -exact $synth::_tdf_consumed_options "$devname,$index"] } {
lappend synth::_tdf_consumed_options "$devname,$index"
}
}
proc tdf_get_unconsumed_devices { } {
set result [list]
foreach devname $synth::_tdf_devices {
if { -1 == [lsearch -exact $synth::_tdf_consumed_devices $devname] } {
lappend result $devname
}
}
return $result
}
proc tdf_get_unconsumed_options { } {
set result [list]
foreach devname $synth::_tdf_devices {
if { -1 == [lsearch -exact $synth::_tdf_consumed_devices $devname] } {
# Do not report all the options for a device that has not been consumed at all
continue
}
for { set i 0 } { [info exists synth::_tdf_device_options($devname,$i)] } { incr i } {
if { -1 == [lsearch -exact $synth::_tdf_consumed_options "$devname,$i"] } {
lappend result [list $devname $synth::_tdf_device_options($devname,$i)]
}
}
}
return $result
}
}
# Look for the target definition file.
set _tdf $synth::target_definition
if { "" == $_tdf } {
set _tdf "default"
}
set _config_file ""
set _dirlist [list [pwd] "~/.ecos/synth" $synth::install_dir]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -