I am debugging an expect program with the traditional debugging way by passing the -D 1 flag for the following script.
#!/usr/bin/expect
proc p3 {} {
set m 0
}
proc p2 {} {
set c 4
p3
set d 5
}
proc p1 {} {
set a 2
p2
set a 5
}
p1
With the debugger command w, I am trying to see the stack frame and got the following error.
dinesh#mypc:~/pgms/expect$ expect -D 1 stack.exp
1: proc p3 {} {
set m 0
}
dbg1.0> n
1: proc p2 {} {
set c 4
p3
set d 5
}
dbg1.1>
1: proc p1 {} {
set a 2
p2
set a 5
}
dbg1.2>
1: p1
dbg1.3> s
2: set a 2
dbg2.4>
2: p2
dbg2.5>
3: set c 4
dbg3.6> w
0: expect {-D} {1} {stack.exp}
Segmentation fault (core dumped)
dinesh#mypc:~/pgms/expect$
I am having the expect version 5.45.
Is there anything wrong in my way of command execution ?
In order to achieve the debugging trace, Expect pokes its fingers inside the implementation of Tcl. In particular, it has copies of the definitions of some of the internal structures used inside Tcl (e.g., the definition of the implementation of procedures and of stack frames). However, these structures change from time to time; we don't announce such internal implementation changes, as they shouldn't have any bearing on any other code, but that's obviously not the case.
Overall, this is a bug in Expect (and it might be that the fix is for a new C API function to be added to Tcl). In order to see about fixing this, we need to know not just the exact version of Expect but also the exact version of Tcl (use info patchlevel to get this).
Related
I am passing a postscript procedure (c) as an argument on the stack to a procedure (a), which then passes this as an argument on the stack to another procedure (b) that invokes the procedure (c).
When I use a dictionary to localize variables and use the same name for the argument in a and b, ghostscript hangs (in the below code, these are procedures a1 and a2 and they both use proc). When I make them different names (in the below code these are procedures a and b which use Aproc and Bproc, respectively), it runs correctly.
Note that I am aware that I can just use the stack to pass down the original argument and avoid the whole exch def step, but in my real world code, I want to capture the stack argument to use locally.
Below is a minimal working example of the issue:
%!PS
/c{
(C START) =
(C output) =
(C END) =
}bind def
/b{
(B START) =
1 dict begin
/Bproc exch def
Bproc
end
(B END) =
}bind def
/a{
(A START) =
1 dict begin
/Aproc exch def
{Aproc} b
end
(A END) =
}bind def
/b2{
(B2 START) =
1 dict begin
/proc exch def
proc
end
(B2 END) =
}bind def
/a2{
(A2 START) =
1 dict begin
/proc exch def
{proc} b2
end
(A2 END) =
}bind def
{c} a
% {c} a2
Here is the output with the above code (different argument names, no issues):
$ gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=test2.pdf test2.ps
GPL Ghostscript 9.54.0 (2021-03-30)
Copyright (C) 2021 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
A START
B START
C START
C output
C END
B END
A END
$
Change the last 2 lines of the code to the following (comment out first, uncomment out the second):
...
% {c} a
{c} a2
Now ghostscript just hangs:
$ gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=test2.pdf test2.ps
GPL Ghostscript 9.54.0 (2021-03-30)
Copyright (C) 2021 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
C-c C-c: *** Interrupt
$
Environment: OpenSuse:
$ uname -a
Linux localhost.localdomain 5.18.4-1-default #1 SMP PREEMPT_DYNAMIC Wed Jun 15 06:00:33 UTC 2022 (ed6345d) x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release
NAME="openSUSE Tumbleweed"
# VERSION="20220619"
ID="opensuse-tumbleweed"
ID_LIKE="opensuse suse"
VERSION_ID="20220619"
PRETTY_NAME="openSUSE Tumbleweed"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:opensuse:tumbleweed:20220619"
BUG_REPORT_URL="https://bugs.opensuse.org"
HOME_URL="https://www.opensuse.org/"
DOCUMENTATION_URL="https://en.opensuse.org/Portal:Tumbleweed"
LOGO="distributor-logo-Tumbleweed"
I think you are being tripped up by early and late name binding, which is a subtle point in PostScript and often traps newcomers to the language.
Because of late name binding you can change the definition of a key/value pair during the course of execution, which can have unexpected effects. This is broadly similar to self-modifying code.
See section 3.12 Early Name Binding on page 117 of the 3rd Edition PostScript Language Reference Manual for details, but the basic point is right at the first paragraph:
"Normally, when the PostScript language scanner encounters an executable name in the program being scanned, it simply produces an executable name object; it does not look up the value of the name. It looks up the name only when the name object is executed by the interpreter. The lookup occurs in the dictionaries that are on the dictionary tack at the time of execution."
Also you aren't quite (I think) doing what you think you are with the executable array tokens '{' and '}'. That isn't putting the definition on the stack, exactly, it is defining an executable array on the stack. Not quite the same thing. In particular it means that the content of the array (between { and }) isn't being executed.
If you wanted to put the original function on the stack you would do '/proc load'. For example if you wanted to define a function to be the same as showpage you might do:
/my_showpage /showpage load def
Not:
/my_showpage {showpage} def
So looking at your failing case.
In function a2 You start by creating and opening a new dictionary. Said dictionary is only present on the stack, so if you ever pop it off it will go out of scope and be garbage collected (I'm sure you know this of course).
In that dictionary you create a key '/proc' with the associated value of an executable array. The array contains {c}.
Then you create a new executable array on the stack {proc}
You then execute function b2 with that executable array on the stack.
b2 starts another new dictionary, again on the stack, and then defines a key/value pair '/proc' with the associated value {proc}.
You then execute proc. That executes the array, the only thing in it is a reference to 'proc', so that is looked up starting in the current dictionary.
Oh look! We have a definition in the current dictionary, it's an executable array. So we push that array and execute it. The only thing in it is a reference to 'proc', so we look that up in the current dictionary, and we have one, so we execute that array. Round and round and round we go.....
You can avoid this by simply changing :
/a2{
(A2 START) =
1 dict begin
/proc exch def
{proc} b2
end
(A2 END) =
}bind def
To :
/a2{
(A2 START) =
1 dict begin
/proc exch def
/proc load b2
end
(A2 END) =
}bind def
I have a TCL script that say, has 30 lines of automation code which I am executing in the dc shell (Synopsys Design Compiler). I want to stop and exit the script at line 10, exit the dc shell and bring it back up again after performing a manual review. However, this time, I want to run the script starting from line number 11, without having to execute the first 10 lines.
Instead of having two scripts, one which contains code till line number 10 and the other having the rest, I would like to make use of only one script and try to execute it from, let's say, line number N.
Something like:
source a.tcl -line 11
How can I do this?
If you have Tcl 8.6+ and if you consider re-modelling your script on top of a Tcl coroutine, you can realise this continuation behaviour in a few lines. This assumes that you run the script from an interactive Tcl shell (dc shell?).
# script.tcl
if {[info procs allSteps] eq ""} {
# We are not re-entering (continuing), so start all over.
proc allSteps {args} {
yield; # do not run when defining the coroutine;
puts 1
puts 2
puts 3
yield; # step out, once first sequence of steps (1-10) has been executed
puts 4
puts 5
puts 6
rename allSteps ""; # self-clean, once the remainder of steps (11-N) have run
}
coroutine nextSteps allSteps
}
nextSteps; # run coroutine
Pack your script into a proc body (allSteps).
Within the proc body: Place a yield to indicate the hold/ continuation point after your first steps (e.g., after the 10th step).
Create a coroutine nextSteps based on allSteps.
Protect the proc and coroutine definitions in a way that they do not cause a re-definition (when steps are pending)
Then, start your interactive shell and run source script.tcl:
% source script.tcl
1
2
3
Now, perform your manual review. Then, continue from within the same shell:
% source script.tcl
4
5
6
Note that you can run the overall 2-phased sequence any number of times (because of the self-cleanup of the coroutine proc: rename):
% source script.tcl
1
2
3
% source script.tcl
4
5
6
Again: All this assumes that you do not exit from the shell, and maintain your shell while performing your review. If you need to exit from the shell, for whatever reason (or you cannot run Tcl 8.6+), then Donal's suggestion is the way to go.
Update
If applicable in your case, you may improve the implementation by using an anonymous (lambda) proc. This simplifies the lifecycle management (avoiding re-definition, managing coroutine and proc, no need for a rename):
# script.tcl
if {[info commands nextSteps] eq ""} {
# We are not re-entering (continuing), so start all over.
coroutine nextSteps apply {args {
yield; # do not run when defining the coroutine;
puts 1
puts 2
puts 3
yield; # step out, once first sequence of steps (1-10) has been executed
puts 4
puts 5
puts 6
}}
}
nextSteps
The simplest way is to open the text file, parse it to get the first N commands (info complete is useful there), and then evaluate those (or the rest of the script). Doing this efficiently produces slightly different code when you're dropping the tail as opposed to when you're dropping the prefix.
proc ReadAllLines {filename} {
set f [open $filename]
set lines {}
# A little bit careful in case you're working with very large scripts
while {[gets $f line] >= 0} {
lappend lines $line
}
close $f
return $lines
}
proc SourceFirstN {filename n} {
set lines [ReadAllLines $filename]
set i 0
set script {}
foreach line $lines {
append script $line "\n"
if {[info complete $script] && [incr i] >= $n} {
break
}
}
info script $filename
unset lines
uplevel 1 $script
}
proc SourceTailN {filename n} {
set lines [ReadAllLines $filename]
set i 0
set script {}
for {set j 0} {$j < [llength $lines]} {incr j} {
set line [lindex $lines $j]
append script $line "\n"
if {[info complete $script]} {
if {[incr i] >= $n} {
info script $filename
set realScript [join [lrange $lines [incr j] end] "\n"]
unset lines script
return [uplevel 1 $realScript]
}
# Dump the prefix we don't need any more
set script {}
}
}
# If we get here, the script had fewer than n lines so there's nothing to do
}
Be aware that the kinds of files you're dealing with can get pretty large, and Tcl currently has some hard memory limits. On the other hand, if you can source the file at all, you're already within that limit…
I have a postscript file when i try to convert it into pdf or open it with postscript it gives the following error
undefined in execform
I am trying to fix this error. But there is no solution i found. Kindly Help me understand the issue.
This is postscript file
OK so a few observations to start;
The file is 8 pages long, uses many forms, and the first form it uses has nested forms. This really isn't suitable as an example file, you are expecting other programmers to dig through a lot of extraneous cruft to help you out. When you post an example, please try and reduce it to just the minimum required to reproduce the problem.
Have you actually tried to debug this problem yourself ? If so what did you do ? (and why didn't you start by reducing the file complexity ?)
I don't want to be offensive, but this is the third rather naive posting you've made recently, do you have much experience of PostScript programming ? Has anyone offered you any training in the language ? It appears you are working on behalf of a commercial organisation, you should talk to your line manager and try and arrange some training if you haven't already been given some.
The PostScript program does not give the error you stated
undefined in execform
In fact the error is a Ghostscript-specific error message:
Error: /undefined in --.execform1--
So that's the .execform1 operator (note the leading '.' to indicate a Ghostscript internal operator). That's only important because firstly its important to accurately quote error messages, and secondly because, for someone familiar with Ghostscript, it tells you that the error occurs while executing the form PaintProc, not while executing the execform operator.
After considerably reducing of the complexity of the file, the problem is absolutely nothing to do with the use of Forms. The offending Form executes code like this:
2 RM
0.459396 w
[(\0\1\0\2)]435.529999 -791.02002 T
(That's the first occurrence, and its where the error occurs)
That executes the procedure named T which is defined as:
/T{neg _LY add /_y ed _LX add /_x ed/_BLSY _y _BLY sub D/_BLX _x D/_BLY _y D _x _y TT}bd
Obviously that's using a number of other functions defined in the prolog, but the important point is that it executes TT which is defined as :
/TT{/_y ed/_x ed/_SX _x _LX sub D/_SY _y _LY sub D/_LX _x D/_LY _y D _x _y m 0 _rm eq{ dup type/stringtype eq{show}{{ dup type /stringtype eq{show}{ 0 rmoveto}?}forall}?} if
1 _rm eq {gsave 0 _scs eq { _sr setgray}if 1 _scs eq { _sr _sg _sb setrgbcolor}if 2 _scs eq { _sr _sg _sb _sk setcmykcolor} if dup type/stringtype eq{true charpath }{{dup type /stringtype eq{true charpath } { 0 rmoveto}?}forall}? S grestore} if
2 _rm eq {gsave 0 _fcs eq { _fr setgray}if 1 _fcs eq { _fr _fg _fb setrgbcolor}if 2 _fcs eq { _fr _fg _fb _fk setcmykcolor} if dup type/stringtype eq{true charpath }{{dup type /stringtype eq{true charpath } { 0 rmoveto}?}
forall}? gsave fill grestore 0 _scs eq { _sr setgray}if 1 _scs eq { _sr _sg _sb setrgbcolor}if 2 _scs eq { _sr _sg _sb _sk setcmykcolor}if S grestore} if
Under the conditions holding at the time TT is executed (RM sets _rm to 2), we go through this piece of code:
gsave 0 _fcs eq
However, _fcs is initially undefined, and only defined when the /fcs function is executed. Your program never executes /fcs so _fcs is undefined, leading to the error.
Is there a reason why you are defining each page in a PostScript Form ? This is not optimal, if the interpreter actually supports Forms then you are using up VM for no useful purpose (since you only execute each Form once).
If its because the original PDF input uses PDF Form XObjects I would recommend that you don't try and reproduce those in PostScript. Reuse of Form XObjects in PDF is rather rare (it does happen but non-reuse is much more common). The loss of efficiency due to describing PostScript Forms for each PDF Form XObject for all the files where the form isn't reused exceeds the benefit for the rare cases where it would actually be valuable.
I want to see what functions are called in my user-space C99 program and in what order. Also, which parameters are given.
Can I do this with DTrace?
E.g. for program
int g(int a, int b) { puts("I'm g"); }
int f(int a, int b) { g(5+a,b);g(8+b,a);}
int main() {f(5,2);f(5,3);}
I wand see a text file with:
main(1,{"./a.out"})
f(5,2);
g(10,2);
puts("I'm g");
g(10,5);
puts("I'm g");
f(5,3);
g(10,3);
puts("I'm g");
g(11,5);
puts("I'm g");
I want not to modify my source and the program is really huge - 9 thousand of functions.
I have all sources; I have a program with debug info compiled into it, and gdb is able to print function parameters in backtrace.
Is the task solvable with DTrace?
My OS is one of BSD, Linux, MacOS, Solaris. I prefer Linux, but I can use any of listed OS.
Here's how you can do it with DTrace:
script='pid$target:a.out::entry,pid$target:a.out::return { trace(arg1); }'
dtrace -F -n "$script" -c ./a.out
The output of this command is like as follows on FreeBSD 14.0-CURRENT:
dtrace: description 'pid$target:a.out::entry,pid$target:a.out::return ' matched 17 probes
I'm g
I'm g
I'm g
I'm g
dtrace: pid 39275 has exited
CPU FUNCTION
3 -> _start 34361917680
3 -> handle_static_init 140737488341872
3 <- handle_static_init 2108000
3 -> main 140737488341872
3 -> f 2
3 -> g 2
3 <- g 32767
3 -> g 5
3 <- g 32767
3 <- f 0
3 -> f 3
3 -> g 3
3 <- g 32767
3 -> g 5
3 <- g 32767
3 <- f 0
3 <- main 0
3 -> __do_global_dtors_aux 140737488351184
3 <- __do_global_dtors_aux 0
The annoying thing is that I've not found a way to print all the function arguments (see How do you print an associative array in DTrace?). A hacky workaround is to add trace(arg2), trace(arg3), etc. The problem is that for nonexistent arguments there will be garbage printed out.
Yes, you can do this with dtrace. But you probably will never be able to do it on linux. I've tried multiple versions of the linux port of dtrace and it's never done what I wanted. In fact, it once caused a CPU panic. Download the dtrace toolkit from http://www.brendangregg.com/dtrace.html. Then set your PATH accordingly. Then execute this:
dtruss -a yourprogram args...
Your question is exceedingly likely to be misguided. For any non-trivial program, printing the sequense of all function calls executed with their parameters will result in multi-MB or even multi-GB output, that you will not be able to make any sense of (too much detail for a human to understand).
That said, I don't believe you can achieve what you want with dtrace.
You might begin by using GCC -finstrument-functions flag, which would easily allow you to print function addresses on entry/exit to every function. You can then trivialy convert addresses into function names with addr2line. This gives you what you asked for (except parameters).
If the result doesn't prove to be too much detail, you can set a breakpoint on every function in GDB (with rb . command), and attach continue command to every breakpoint. This will result in a steady stream of breakpoints being hit (with parameters), but the execution will likely be at least 100 to 1000 times slower.
I have some R code inside a file called analyse.r. I would like to be able to, from the command line (CMD), run the code in that file without having to pass through the R terminal and I would also like to be able to pass parameters and use those parameters in my code, something like the following pseudocode:
C:\>(execute r script) analyse.r C:\file.txt
and this would execute the script and pass "C:\file.txt" as a parameter to the script and then it could use it to do some further processing on it.
How do I accomplish this?
You want Rscript.exe.
You can control the output from within the script -- see sink() and its documentation.
You can access command-arguments via commandArgs().
You can control command-line arguments more finely via the getopt and optparse packages.
If everything else fails, consider reading the manuals or contributed documentation
Identify where R is install. For window 7 the path could be
1.C:\Program Files\R\R-3.2.2\bin\x64>
2.Call the R code
3.C:\Program Files\R\R-3.2.2\bin\x64>\Rscript Rcode.r
There are two ways to run a R script from command line (windows or linux shell.)
1) R CMD way
R CMD BATCH followed by R script name. The output from this can also be piped to other files as needed.
This way however is a bit old and using Rscript is getting more popular.
2) Rscript way
(This is supported in all platforms. The following example however is tested only for Linux)
This example involves passing path of csv file, the function name and the attribute(row or column) index of the csv file on which this function should work.
Contents of test.csv file
x1,x2
1,2
3,4
5,6
7,8
Compose an R file “a.R” whose contents are
#!/usr/bin/env Rscript
cols <- function(y){
cat("This function will print sum of the column whose index is passed from commandline\n")
cat("processing...column sums\n")
su<-sum(data[,y])
cat(su)
cat("\n")
}
rows <- function(y){
cat("This function will print sum of the row whose index is passed from commandline\n")
cat("processing...row sums\n")
su<-sum(data[y,])
cat(su)
cat("\n")
}
#calling a function based on its name from commandline … y is the row or column index
FUN <- function(run_func,y){
switch(run_func,
rows=rows(as.numeric(y)),
cols=cols(as.numeric(y)),
stop("Enter something that switches me!")
)
}
args <- commandArgs(TRUE)
cat("you passed the following at the command line\n")
cat(args);cat("\n")
filename<-args[1]
func_name<-args[2]
attr_index<-args[3]
data<-read.csv(filename,header=T)
cat("Matrix is:\n")
print(data)
cat("Dimensions of the matrix are\n")
cat(dim(data))
cat("\n")
FUN(func_name,attr_index)
Runing the following on the linux shell
Rscript a.R /home/impadmin/test.csv cols 1
gives
you passed the following at the command line
/home/impadmin/test.csv cols 1
Matrix is:
x1 x2
1 1 2
2 3 4
3 5 6
4 7 8
Dimensions of the matrix are
4 2
This function will print sum of the column whose index is passed from commandline
processing...column sums
16
Runing the following on the linux shell
Rscript a.R /home/impadmin/test.csv rows 2
gives
you passed the following at the command line
/home/impadmin/test.csv rows 2
Matrix is:
x1 x2
1 1 2
2 3 4
3 5 6
4 7 8
Dimensions of the matrix are
4 2
This function will print sum of the row whose index is passed from commandline
processing...row sums
7
We can also make the R script executable as follows (on linux)
chmod a+x a.R
and run the second example again as
./a.R /home/impadmin/test.csv rows 2
This should also work for windows command prompt..
save the following in a text file
f1 <- function(x,y){
print (x)
print (y)
}
args = commandArgs(trailingOnly=TRUE)
f1(args[1], args[2])
No run the following command in windows cmd
Rscript.exe path_to_file "hello" "world"
This will print the following
[1] "hello"
[1] "world"