Glob as the argument of a shell function - function

I'm writing a reusable function, so I need the argument to be as flexible as possible.
Consider a simple example:
function testf(){
print ./*.$1
}
This works. For example, with testf mp3 it lists all the files ending with .mp3 in an array, making possible the use of for loops. But this way it only allows me to work with the extension name.
Therefore, I tried:
function testf(){
print ./$1
}
However, it doesn't work. Using testf *.mp3, unlike using print *.mp3 in the terminal, it will only pass the first matching string instead of the whole array.
Any suggestion?

ists all the files ending with .mp3 in an array ... there is no array involved in your question.
But to your problem: First, you want to pass to your function a wildcard pattern, but this is not what you are actually doing. testf *.mp3 expands the pattern before the function is invoked (this process is called filename generation), and your testf gets just a list of files as parameters. You can pass a pattern, but you have to ask the shell not to expand it:
testf '*.mp3'
In this case, your $1 indeed will contain the string *.mp3. However, your print ./$1 will still not work. The reason is that filename generation occurs before parameter expansion (which is the process where $1 is replaced by the string it contains). Again, you have to ask the shell to do it the other way round:
print ./${~1}

The shell performs several types of expansions before launching the command. When you enter
testf *.mp3
the shell will expand the glob first, and pass each filename as a separate argument to the function
Your function could look like this:
function testf(){
printf './%s\n' "$#"
}

Related

how to find a part of a path using tcl?

I am farily new to tcl. I am trying to write a tcl script that will perform a few thins on certain files in a tree structure, but on all files.
I have in my tree a number of files ending with .xci.
Now I want to filter our all .gbn files except the ones in a part of my tree (i.e. /src/ps/<a number of directories>/<a number of files>.xci) that contains the path part "/ps/"
I have done this:
foreach xci_file [get_files *.xci] {
#if (ps_is_found_in_path_of_${xci_file}) {
generate_target simulation [get_files $xci_file]
}
}
The foreach search through all files in my project and returns the filename (including the full path). How do I write the if statement to avoid target generation of the files whose paths include "/ps/"?
Is there a nice soul out there who could share some light on this?
You want:
if {"ps" in [file split $xci_file]} {
The quotes are required here: expr (which handles if's first argument)
needs literal strings quoted.

Converting Tcl to C++

I am trying to convert some tcl script into a C++ program. I don't have much experience with tcl and am hoping someone could explain what some of the following things are actually doing in the tcl script:
1) set rtn [true_test_sfm $run_dir]
2) cd [glob $run_dir]
3) set pwd [pwd]
Is the first one just checking if true_test_sfm directory exists in run_dir?
Also, I am programming on a windows machine. Would the system function be the equivalent to exec statements in tcl? And if so how would I print the result of the system function call to stdout?
In Tcl, square brackets indicate "evaluate the code between the square brackets". The result of that evaluation is substituted for the entire square-bracketed expression. So, the first line invokes the function true_test_sfm with a single argument $run_dir; the result of that function call is then assigned to the variable rtn. Unfortunately, true_test_sfm is not a built-in Tcl function, which means it's user-defined, which means there's no way we can tell you what the effect of that function call will be based on the information you've provided here.
glob is a built-in Tcl function which takes a file pattern as an argument and then lists files that match that pattern. For example, if a directory contains files "foo", "bar" and "baz", glob b* would return a list of two files, "bar" and "baz". Therefore the second line is looking for any files that match the pattern given by $run_dir, then using the cd command (another Tcl built-in) to change to the directory found by glob. Probably $run_dir is not actually a file pattern, but an explicit file name (ie, no globbing characters like * or ? in the string), otherwise this code may break unexpectedly. On Windows, some combination of FindFirstFile/FindNextFile in C++ could be used as a substitute for glob in Tcl, and SetCurrentDirectory could substitute for cd.
pwd is another built-in Tcl function which returns the process current working directory as an absolute path. So the last line is querying the current working directory and saving the result in a variable named pwd. Here you could use GetCurrentDirectory as a substitute for pwd.

Break on namespace function in gdb (llvm)

I'm trying to step through llvm's opt program (for an assignment) and the instructor suggested setting a breakpoint at runOnFunction. I see this in one of the files:
bool InstCombiner::runOnFunction(Function &F) { /* (Code removed for SO) */ }
but gdb does not seem to find the runOnFunction breakpoint. It occurred to me that the problem might be namespaces? I tried this but gdb never breaks, it just creates the fooOpt.s file:
(gdb) b runOnFunction
Function "runOnFunction" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (runOnFunction) pending.
(gdb) r -S -instcombine -debug -o ~/Desktop/fooOpt.s ~/Desktop/foo.s
I'm on a Mac so I don't have objdump but otool produces 5.6 million lines, wading through that for a starting point does not seem reasonable as runOnFunction appears more than once there.
Gdb has several builtin commands to find name of such functions. First is info functions, which can be used with optional regexp argument to grep all available functions, https://sourceware.org/gdb/current/onlinedocs/gdb/Symbols.html
info functions regexp
Print the names and data types of all defined functions whose names contain a match for regular expression regexp. Thus, ‘info fun step’ finds all functions whose names include step; ‘info fun ^step’ finds those whose names start with step. If a function name contains characters that conflict with the regular expression language (e.g. ‘operator*()’), they may be quoted with a backslash.
So, you can try info functions runOnFunction to get the name. Sometimes it can be useful to add quotes around name when doing break command.
The other way is to use rbreak command instead of break (b). rbreak will do regexp search in functions names and may define several breakpoints: https://sourceware.org/gdb/current/onlinedocs/gdb/Set-Breaks.html#Set-Breaks
rbreak regex
Set breakpoints on all functions matching the regular expression regex. This command sets an unconditional breakpoint on all matches, printing a list of all breakpoints it set. ...
The syntax of the regular expression is the standard one used with tools like grep. Note that this is different from the syntax used by shells, so for instance foo* matches all functions that include an fo followed by zero or more os. There is an implicit .* leading and trailing the regular expression you supply, so to match only functions that begin with foo, use ^foo.
(or even rbreak file:regex to limit search to single source file)
PS: if you want, you can turn on or off C++ function name demangling with set print demangle on or off (https://sourceware.org/gdb/current/onlinedocs/gdb/Debugging-C-Plus-Plus.html#Debugging-C-Plus-Plus). With demangling turned off it will be easier to copy function name to break command.

Trying to redirect output of a command to a variable

>> set signal_name [get_fanout abc_signal]
{xyz_blah_blah}
>> echo $signal_name
#142
>> set signal_name [get_fanout abc_signal]
{xyz_blah_blah}
>> echo $signal_name
#144
>>
I tried other stuff like catch etc, and every where, it returns #number. My goal is to be able to print the actual value instead of the number - xyz_blah_blah.
I am new to tcl. Want to understand, if this is an array or a pointer to an array or something like that. When I try the exact same thing with a different command, which returns just a value, then it works. This is a new command which returns value in parenthesis.
Please help. Thanks.
Every Tcl command produces a result value, which you capture and use by putting the call of the command in [square brackets] and putting the whole lot as part of an argument to another command. Thus, in:
set signal_name [get_fanout abc_signal]
the result of the call to get_fanout is used as the second argument to set. I suggest that you might also like to try doing this:
puts "-->[get_fanout abc_signal]<--"
It's just the same, except this time we're concatenating it with some other small string bits and printing the whole lot out. (In case you're wondering, the result of puts itself is always the empty string if there isn't an error, and set returns the contents of the variable.)
If that is still printing the wrong value (as well as the right one beforehand, without arrow marks around it) the real issue may well be that get_fanout is not doing what you expect. While it is possible to capture the standard output of a command, doing so is a considerably more advanced technique; it is probably better to consider whether there is an alternate mechanism to achieve what you want. (The get_fanout command is not a standard part of the Tcl language library or any very common add-on library like Tk or the Tcllib collection, so we can only guess at its behavior.)

How to add certain search and replace pattern on filenames with specific strings

I have written a function, which does some search and replace on the file which I am editing. But for certain files (with some specific keyterms in the filename), I need to add some specific search and replace which is restricted to these files.
I need to know how to fix the following code:
function! Test()
" basic search and replace for all the files
%s/I'll /I will /ge
" if the filename starts with "blah-" the following additional search and replace needed otherwise not
if match(readfile(expand('%:t')),"^blah-")
%s/could'nt /could not /gec
endif
endfunc
And on calling the function :call Test() all these patterns will be executed. Hence, I do not need to worry about the specific instructions on certain file types.
Can anybody help me fixing this problem?
If there is no match -1 is returned from match(). Also, you probably don't need to call readfile() to check the filename. As such, change
if match(readfile(expand('%:t')),"^blah-")
...to...
if match(expand('%:t'), '^blah-') != -1
...and your blah-files (and only your blah-files) will have the extra substitution executed.