TCL fails to expand environment variables - tcl

I have an environment variable which I can access without any problem when used in isolation
puts "$::env(LIB)"
/home/asic/lib
However when I try and use this as part of a longer string, the env var returns an empty string!
puts "$::env(LIB)/add/path/to/target"
/add/path/to/target
I am using Riviera Pro with $tcl_version=8.5 on a Linux system. It works fine on the Windows version.
How can I access the env var?
I have tried re-assigning to a local, but I still get the same issue. Neither do {} around the variable.

The perils of different line ending conventions.
The script used to create the env vars was created on a windows system, and when the vars were interpreted by TCL, it was seeing control characters in the variable. Once pushed through dos2unix, the vars are now being used correctly.

In standard Tcl, that code as written ought to work; the $…(…) variable form will not get confused by the surrounding "…" or by the trailing /… material. I don't know how Riviera Pro might be altering things, but I suppose that is possible.
What does parray ::env report? That should print all the environment variables and their contents. (The only really big differences between Windows and Linux with environment variables are that their names are case-sensitive on Linux, and each platform tends to have different characteristic variables set.)

Related

How do I find where a function is declared in Tcl?

I think this is more of a Tcl configuration question rather than a Tcl coding question...
I inherited a whole series of Tcl scripts that are used within a simulation tool that my company built in-house. In my scripts, I'm finding numerous instances where there are function calls to functions that don't seem to be declared anywhere. How can I trace the path to these phantom functions?
For example, rather than use source, someone build a custom include function that they named INCLUDE. Tclsh obviously balks when I try to run it there, but with my simulation software, it runs fine.
I've tried grep-ing through the entire simulation software for INCLUDE, but I'm not having any luck. Are there any other obvious locations outside the simulation software where a Tcl function might be defined?
The possibilities:
Within your software. (you have checked for this).
Within some other package included by the software.
Check and see if the environment variable TCLLIBPATH is set.
Also check and see if the simulation software sets TCLLIBPATH.
This will be a list of directories to search for Tcl packages, and you
will need to search the packages that are located outside of the
main source tree.
Another possibility is that the locations are specified in the pkgIndex.tcl file.
Check any pkgIndex.tcl files and look for locations outside the main source tree.
Within an unknown command handler. This could be in
your software or within some other package. You should be able to find
some code that processes the INCLUDE statement.
Within a binary package. These are shared libraries that are loaded
by Tcl. If this is the case, there should be some C code used to
build the shared library that can be searched.
Since you say there are numerous instances of unknown functions, my first
guess is that you have
not found all the directories where packages are loaded from. But an
''unknown'' command handler is also a possibility.
Edit:
One more possibility I forgot. Check and see if your software sets the auto_path variable. Check any directories added to the auto_path for
other packages.
This isn't a great answer for you, but I suspect it is the best you're going to get...
The procedure could be defined in a great many places. Your best bet for finding it is to use a tool like findstr (on Windows) or grep -R (on POSIX platforms) to search across all the relevant source files. But that still might not help! It might not be a procedure but instead a general command, which could be implemented in C and not as a procedure, or it could be defined in a packaged application archive (which are usually awkward to look inside). There are also other types of script-implemented command too, which could make things awkward. Generally searching and investigating is your best bet, but it might not work.
Tcl doesn't really differentiate strongly between different types of command except in some introspection operations. If you're lucky, you could find that info body tells you the definition of the procedure (and info args and info default tell you about the arguments) but that won't help with other command types at all. Tcl 8.7 will include a command (info cmdtype) that would help a lot with narrowing down what to do next, but that's no use to you now and it definitely doesn't exist in older versions.

Get configuration flags of a compiled tcl

I've a compiled tcl version 8.4 and want to check if --enable-threads was set when it was compiled or not ?
or if there is any another way to get the list of all passed flags.
Thanks
IMPORTANT NOTE!
Tcl 8.4 is out of long-term support. Absolutely no further changes will be forthcoming to it, not even if a catastrophic security error is discovered; if your issue isn't fixed by 8.4.20, you'll need to go to 8.5 or later. We don't know of any such security issues, but we aren't looking and won't fix them if they're found.
Support here is only on a “because we feel nice” basis. You should not create new work based on 8.4.
The global array element tcl_platform(threaded) is defined and set to 1 when the currently-used Tcl library is built with thread support. This is true from at least Tcl 8.4 onwards. Here's how to reliably get a nice boolean value you can check:
set isThreaded [expr {
[info exist tcl_platform(threaded)] && $tcl_platform(threaded)
}]
NB: Some platforms are virtually always threaded anyway (because of how they work internally; this is the case with Windows and OSX if I remember right). Future versions of Tcl (8.7 onwards) will default to threaded everywhere; this will be the only supported build mode from 9.0 on. You'll still need the Thread package to work with threads in your script, but that's a standard extension these days.
Starting with 8.5 (TIP 59), one can retrieve details about the build configuration using tcl::pkgconfig:
% tcl::pkgconfig get threaded
1
Note that this is not available in Tcl 8.4; if available, one does not have to protect against requesting an inexistent array entry tcl_platform(threaded).

short commands are not working in customized wish shell

I have a customized in version of wish 8.6 shell with own environment loaded.
The issue is in native wish shell, short command work.
eg. packa r xxx for package require or stri e $str1 $str2 for string comparison.
But the same thing when i run in my customized shell, it says
invalid command name "packa"
But it works for the options for the command, as package re works for requiring the package.
What could be the possible cause, that wish is unable to resolve command name?
I know it it's bit difficult to answer for a customized shell but if someone could share probable causes based of logics, that would be of great help.
It sounds like you're not setting the global tcl_interactive to 1. That enables expansion of abbreviated command names as well as calling external programs without an explicit exec and a few other things (all of which is done in the unknown command handler procedure, or things it calls; if you want to customise things instead of working like tclsh does, look there).
Handling of unique prefixes of subcommand names is entirely separate.

Setting environment variables from within TCL script

I was creating a Tcl script which will allow me to automate the installation of software. But the problem I am running into is that the software needs some environment variables set beforehand and I was wondering if its possible to set environment variables inside of the tcl script.
I was going to try exec /bin/sh -c "source /path/to/.bash_profile but that would create a shell script and source the variables into there and the tcl script wont pick it up then.
Can anyone give any other ideas?
In Tcl you have the global env array:
set ::env(foo) bar
And then any child process has the variable foo in its environment.
If you want to put environment variables in a central file (i.e. .bash_profile) so that other programs can source them, then it should be pretty easy to get Tcl to parse that file and set the variables in the env array.
Generally speaking (at least for Linux and Unix-like systems), it's not possible from within a child process to alter the environment of the parent. It's a frequently asked question about tcl
However, if you're launching some other software from within the Tcl script, you can do a couple of things, the simplest of which may be to create a shell script file which both sets environment variables and then launches your software. Then run the shell script from within Tcl.
The environment is exposed via the global env array in Tcl. The keys and values of the array default to the environment inherited from the parent process, any process that Tcl creates will inherit a copy of it, and code that examines the environment in the current process (including directly from C) will see the current state of it.
Picking up environment set in a shell script is quite tricky. The issue is that a .bashrc (for example) can do quite complex things as well as setting a bunch of environment variables. For example, it can also print out a message of the day, or conditionally take actions. But you can at least make a reasonable attempt by using the shell's env command:
set data [exec sh -c "source /path/to/file.sh.rc; env"]
# Now we parse with some regular expression magic
foreach {- key value} [regexp -all -inline {(?wi)^(\w+)=((?!')[^\n]+|'[^']+')$} $data] {
set extracted_env($key) [string trim $value "'"]
}
It's pretty awful, and isn't quite right (there are things that could confuse it) but it's pretty close. The values will be populated in the extracted_env array by it.
I think it's easier to get people to configure things via Tcl scripts…

Command line parameters or configuration file?

I'm developing a tool that will perform several types of analysis, and each analysis can have different levels of thoroughness. This app will have a fair amount of options to be given before it starts. I started implementing this using a configuration file, since the number of types of analysis specified were little. As the number of options implemented grew, I created more configuration files. Then, I started mixing some command line parameters since some of the options could only be flags. Now, I've mixed a bunch of command line parameters with configuration files and feel I need refactoring.
My question is, When and why would you use command line parameters instead of configuration files and vice versa?
Is it perhaps related to the language you use, personal preference, etc.?
EDIT: I'm developing a java app that will work in Windows and Mac. I don't have a GUI for now.
Command line parameters are useful for quickly overriding some parameter setting from the configuration file. As well, command line parameters are useful if there are not so many parameters. For your case, I'd suggest that you export parameter presets to command line.
Command line arguments:
Pros:
concise - no extra config files to maintain by itself
great interaction with bash scripts - e.g. variable substitution, variable reference, bash math, etc.
Cons:
it could get very long as the options become more complex
formatting is inflexible - besides some command line utilities that help you parse the high level switches and such, anything more complex (e.g. nested structured information) requires custom syntax such as using Regex, and the structure could be quite rigid - while JSON or YAML would be hard to specify at the command line level
Configuration files:
Pros:
it can be very large, as large as you need it to be
formatting is more flexible - you can use JSON, YAML, INI, or any other structural format to represent the information in a more human consumable way
Cons:
inflexible to interact with bash variable substitutions and references (as well as bash math) - you have to probably define your own substitution rules if you want the config file to be "generic" and reusable, while this is the biggest advantage of using command line arguments - variable math would be difficult in config files (if not impossible) - you have to define your own "operator" in the config files, or you have to rely on another bash script to carry out the variable math, and perform your custom variable substitution so the "generic" config file could become "concretely usable".
for all that it takes to have a generic config file (with custom defined variable substitution rules) ready, a bash script is still needed to carry out the actual substitution, and you still have to code your command line to accept all the variable substitutions, so either you have config files with no variable substitution, which means you "hard code" and repeat the config file for different scenarios, or the substitution logic with custom variable substitution rules make your in-app config file logic much more complex.
In my use case, I value being able to do variable substitution / reference (as well as bash math) in the bash scripts more important, since I'm using the same binary to start many server nodes with different responsibilities in a server backend cluster, and I kind of use the bash scripts as sort of a container or actually a config file to start the many different nodes with differing command line arguments.
my vote = both ala mysqld.exe
What environment/platform? In Windows you'd rather use a config file, or even a configuration panel/window in the gui.
I place configuration that don't really change in a configuration file.
Configuration that change often I place on the command-line.