Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.debug.examples.core/pdavm/pda.pl')
-rw-r--r--org.eclipse.debug.examples.core/pdavm/pda.pl678
1 files changed, 0 insertions, 678 deletions
diff --git a/org.eclipse.debug.examples.core/pdavm/pda.pl b/org.eclipse.debug.examples.core/pdavm/pda.pl
deleted file mode 100644
index de0866eba..000000000
--- a/org.eclipse.debug.examples.core/pdavm/pda.pl
+++ /dev/null
@@ -1,678 +0,0 @@
-#!perl.exe
-
-use strict;
-use warnings;
-use IO::Socket;
-
-#####################################################################
-# Copyright (c) 2005, 2008 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# Bjorn Freeman-Benson - initial API and implementation
-# Pawel Piech - WindRiver Systems - Bug 217211: PDA example debugger does not run on linux
-#####################################################################
-
-#####################################################################
-# #
-# I N I T I A L I Z A T I O N A N D V A R I A B L E S #
-# #
-#####################################################################
-#
-# The push down automata stack (the data stack)
-#
-my @stack;
-#
-# Load all the code into memory
-# The code is stored as an array of strings, each line of
-# the source file being one entry in the array.
-#
-my $filename = shift;
-open INFILE, $filename or die $!;
-my @code = <INFILE>;
-close INFILE;
-
-my %labels;
-sub map_labels {
- #
- # A mapping of labels to indicies in the code array
- #
- %labels = ( );
- my $idx = 0;
- while( $idx <= $#code ) {
- if( length $code[$idx] > 0 ) {
- $code[$idx] =~ /^\s*(.+?)\s*$/;
- $code[$idx] = $1;
- $labels{$1} = $idx if( $code[$idx] =~ /^:(\S+)/ );
- } else {
- $code[$idx] = "\n";
- }
- $idx ++;
- }
-}
-map_labels();
-#
-# The stack of stack frames (the control stack)
-# Each stack frame is a mapping of variable names to values.
-# There are a number of special variable names:
-# _pc_ is the current program counter in the frame
-# the pc points to the next instruction to be executed
-# _func_ is the name of the function in this frame
-#
-my @frames;
-my $currentframe;
-$currentframe = {
- _pc_ => 0,
- _func_ => 'main'
- };
-
-#
-# The command line argument to start a debug session.
-#
-my $debugflag = shift;
-#
-# The port to listen for debug commands on
-# and the port to send debug events to
-#
-my $debugport;
-my $debugport2;
-#
-# The socket to listen for debug commands on
-# and the socket to send debug events on
-#
-my $debugsock;
-my $debugsock2;
-#
-# An input buffer
-#
-my $debugbuf;
-#
-# Breakpoint array
-# breakpoints are stored as a boolean for each line of code
-# if the boolean is true, there is a breakpoint on that line
-#
-my @breakpoints;
-#
-# Mapping of debugger commands to functions that evaluate them
-#
-my %debug_commands = (
- clear => \&debug_clear_breakpoint,
- data => \&debug_data,
- drop => \&debug_drop_frame,
- eval => \&debug_eval,
- eventstop => \&debug_event_stop,
- exit => \&debug_exit,
- popdata => \&debug_pop,
- pushdata => \&debug_push,
- resume => \&debug_resume,
- set => \&debug_set_breakpoint,
- setdata => \&debug_set_data,
- setvar => \&debug_set_variable,
- stack => \&debug_stack,
- step => \&debug_step,
- stepreturn => \&debug_step_return,
- suspend => \&debug_suspend,
- var => \&debug_var,
- watch => \&debug_watch
-);
-
-#
-# The run flag is true if the VM is running.
-# If the run flag is false, the VM exits the
-# next time the main instruction loop runs.
-#
-my $run = 1;
-#
-# The suspend flag is true if the VM should suspend
-# running the program and just listen for debug commands.
-#
-my $suspend = 0;
-my $started = 1;
-$suspend = "client" if( $debugflag );
-#
-# The step flag is used to control single-stepping.
-# See the implementation of the "step" debug command.
-# The stepreturn flag is used to control step-return.
-# The eventstops table holds which events cause suspends and which do not.
-# The watchpoints table holds watchpoint information.
-# variablename_stackframedepth => N
-# N = 0 is no watch
-# N = 1 is read watch
-# N = 2 is write watch
-# N = 3 is both, etc.
-#
-my $step = 0;
-my $stepreturn = 0;
-my %eventstops = ( "unimpinstr" => 0,
- "nosuchlabel" => 0,
- );
-my %watchpoints = ( );
-
-#
-# Mapping of the names of the instructions to the functions that evaluate them
-#
-my %instructions = (
- add => \&add,
- branch_not_zero => \&branch_not_zero,
- call => \&call,
- dec => \&dec,
- dup => \&dup,
- halt => \&halt,
- output => \&output,
- pop => \&ipop,
- push => \&ipush,
- return => \&ireturn,
- var => \&var,
- xyzzy => \&internal_end_eval,
-);
-
-#####################################################################
-# #
-# M A I N I N T E R P R E T E R #
-# #
-#####################################################################
-#
-# Open a debug session if the command line argument is given.
-#
-start_debugger();
-send_debug_event( "started", 0 );
-debug_ui() if( $suspend );
-#
-# The main run loop
-#
-while( $run ) {
- check_for_breakpoint();
- debug_ui() if( $suspend );
- yield_to_debug();
- my $instruction = fetch_instruction();
- increment_pc();
- do_one_instruction($instruction);
- if( $$currentframe{_pc_} > $#code ) {
- $run = 0;
- } elsif( $stepreturn ) {
- $instruction = fetch_instruction();
- $suspend = "step" if( is_return_instruction($instruction) );
- }
-}
-send_debug_event( "terminated", 0 );
-
-sub fetch_instruction {
- my $pc = $$currentframe{_pc_};
- my $theinstruction = $code[$pc];
- return $theinstruction;
-}
-sub is_return_instruction {
- my $theinstruction = shift;
- if( $theinstruction =~ /^:/ ) {
- return 0;
- } elsif( $theinstruction =~ /^#/ ) {
- return 0;
- } else {
- $theinstruction =~ /^(\S+)\s*(.*)/;
- return $1 eq "return";
- }
-}
-sub increment_pc {
- my $pc = $$currentframe{_pc_};
- $pc++;
- $$currentframe{_pc_} = $pc;
-}
-sub decrement_pc {
- my $pc = $$currentframe{_pc_};
- $pc--;
- $$currentframe{_pc_} = $pc;
-}
-sub do_one_instruction {
- my $theinstruction = shift;
- if( $theinstruction =~ /^:/ ) {
- # label
- $suspend = "step" if( $step );
- } elsif( $theinstruction =~ /^#/ ) {
- # comment
- } else {
- $theinstruction =~ /^(\S+)\s*(.*)/;
- my $op = $1;
- my $instr = $instructions{$op};
- if( $instr ) {
- &$instr( $theinstruction, $2 );
- $suspend = "step" if( $step );
- } else {
- send_debug_event( "unimplemented instruction $op", 1 );
- if( $eventstops{"unimpinstr"} ) {
- $suspend = "event unimpinstr";
- decrement_pc();
- }
- }
- }
-}
-
-#####################################################################
-# #
-# I N S T R U C T I O N S #
-# #
-#####################################################################
-sub add {
- my $val1 = pop @stack;
- my $val2 = pop @stack;
- my $val = $val1 + $val2;
- push @stack, $val;
-}
-
-sub branch_not_zero {
- my $val = pop @stack;
- if( $val ) {
- shift;
- my $label = shift;
- my $dest = $labels{$label};
- if( !defined $dest ) {
- send_debug_event( "no such label $label", 1 );
- if( $eventstops{"nosuchlabel"} ) {
- $suspend = "event nosuchlabel";
- push @stack, $val;
- decrement_pc();
- }
- } else {
- $$currentframe{_pc_} = $dest;
- }
- }
-}
-
-sub call {
- shift;
- my $label = shift;
- my $dest = $labels{$label};
- if( !defined $dest ) {
- send_debug_event( "no such label $label", 1 );
- if( $eventstops{"nosuchlabel"} ) {
- $suspend = "event nosuchlabel";
- decrement_pc();
- }
- } else {
- push @frames, $currentframe;
- $currentframe = {
- _pc_ => $dest,
- _func_ => $label
- };
- }
-}
-
-sub dec {
- my $val = pop @stack;
- $val--;
- push @stack, $val;
-}
-
-sub dup {
- my $val = pop @stack;
- push @stack, $val;
- push @stack, $val;
-}
-
-sub halt {
- $run = 0;
-}
-
-sub output {
- my $val = pop @stack;
- print "$val\n";
-}
-
-sub ipop {
- shift;
- my $arg = shift;
- if( $arg =~ /^\$(.*)/ ) {
- $$currentframe{$1} = pop @stack;
- my $key = "$$currentframe{_func_}\:\:$1";
- if( defined $watchpoints{$key} ) {
- if( $watchpoints{$key} & 2 ) {
- $suspend = "watch write $key";
- }
- }
- } else {
- pop @stack;
- }
-}
-
-sub ipush {
- shift;
- my $arg = shift;
- if( $arg =~ /^\$(.*)/ ) {
- my $val = $$currentframe{$1};
- push @stack, $val;
- my $key = "$$currentframe{_func_}\:\:$1";
- if( defined $watchpoints{$key} ) {
- if( $watchpoints{$key} & 1 ) {
- $suspend = "watch read $key";
- }
- }
- } else {
- push @stack, $arg;
- }
-}
-
-sub ireturn {
- $currentframe = pop @frames;
-}
-
-sub var {
- shift;
- my $name = shift;
- $$currentframe{$name} = 0;
-}
-
-#####################################################################
-# #
-# D E B U G G E R I N T E R F A C E #
-# #
-#####################################################################
-
-sub check_for_breakpoint {
- if( $debugflag ) {
- my $pc = $$currentframe{_pc_};
- if( $breakpoints[$pc] ) {
- $suspend = "breakpoint $pc" unless $suspend eq "eval";
- }
- }
-}
-#
-# For each instruction, we check the debug co-routine for
-# control input. If there is input, we process it.
-#
-sub yield_to_debug {
- if( $debugflag ) {
- my $bytes_to_read = 1024;
- my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read);
- if( defined($bytes_read) ) {
- #print "read $bytes_to_read\n";
- my $rin = '';
- my $win = '';
- my $ein = '';
- vec($rin,fileno($debugsock),1) = 1;
- $ein = $rin | $win;
- my $debugline = $debugbuf;
- while( !($debugline =~ /\n/) ) {
- select($rin, undef, undef, undef);
- my $bytes_to_read = 1024;
- my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read);
- $debugline .= $debugbuf;
- }
- #print "read: $debugline";
- process_debug_command($debugline);
- $debugline = '';
- } else {
- # no bytes read
- }
- }
-}
-
-#
-# If the execution is suspended, then we go into the debug
-# ui loop, reading and processing instructions.
-#
-sub debug_ui {
- return unless( $suspend );
- my $pc = $$currentframe{_pc_};
- if (!$started) {
- send_debug_event( "suspended $suspend", 0 );
- } else {
- $started = 0;
- }
- $step = 0;
- $stepreturn = 0;
- my $rin = '';
- my $win = '';
- my $ein = '';
- vec($rin,fileno($debugsock),1) = 1;
- $ein = $rin | $win;
- my $debugline = '';
- while( $suspend ) {
- select($rin, undef, undef, undef);
- my $bytes_to_read = 1024;
- my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read);
- $debugline .= $debugbuf;
- if( $debugline =~ /\n/ ) {
- #print "read: $debugline";
- process_debug_command($debugline);
- $debugline = '';
- }
- }
- send_debug_event( "resumed step", 0 ) if( $step );
- send_debug_event( "resumed client", 0 ) unless( $step );
-}
-
-sub process_debug_command {
- my $line = shift;
- return if( length $line < 2 );
- my @words = split /\s/, $line;
- my $command = lc($words[0]);
- my $dfunc = $debug_commands{$words[0]};
- if( $dfunc ) {
- &$dfunc( @words );
- }
-}
-
-sub debug_clear_breakpoint {
- shift;
- my $line = shift;
- $breakpoints[$line] = 0;
- print $debugsock "ok\n";
-}
-my @saved_code;
-my %saved_labels;
-my $saved_pc;
-sub debug_eval {
- shift;
- my $code = shift;
- my @lines = split /\|/, $code;
- my $newpc = scalar @code;
- @saved_code = @code;
- %saved_labels = %labels;
- foreach my $line ( @lines ) {
- $line =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
- push @code, $line;
- }
- push @code, "xyzzy";
- map_labels();
- $saved_pc = $$currentframe{_pc_};
- $$currentframe{_pc_} = $newpc;
- print $debugsock "ok\n";
- $suspend = 0;
-}
-sub internal_end_eval {
- my $result = pop @stack;
- @code = @saved_code;
- %labels = %saved_labels;
- $$currentframe{_pc_} = $saved_pc;
- send_debug_event( "evalresult $result", 0 );
- $suspend = "eval";
-}
-
-sub debug_data {
- my $result = '';
- foreach my $d ( @stack ) {
- $result .= $d . '|';
- }
- print $debugsock "$result\n";
-}
-sub debug_drop_frame {
- ireturn();
- decrement_pc();
- print $debugsock "ok\n";
- send_debug_event( "resumed drop", 0 );
- send_debug_event( "suspended drop", 0 );
-}
-sub debug_event_stop {
- shift;
- my $event = shift;
- my $bool = shift;
- $eventstops{$event} = $bool;
- print $debugsock "ok\n";
-}
-sub debug_exit {
- print $debugsock "ok\n";
- send_debug_event( "terminated", 0 );
- exit 0;
-}
-sub debug_pop {
- pop @stack;
- print $debugsock "ok\n";
-}
-sub debug_push {
- shift;
- my $value = shift;
- push @stack, $value;
- print $debugsock "ok\n";
-}
-sub debug_resume {
- $suspend = 0;
- print $debugsock "ok\n";
-}
-sub debug_set_breakpoint {
- shift;
- my $line = shift;
- $breakpoints[$line] = 1;
- print $debugsock "ok\n";
-}
-sub debug_set_data {
- shift;
- my $offset = shift;
- my $value = shift;
- $stack[$offset] = $value;
- print $debugsock "ok\n";
-}
-sub debug_set_variable {
- shift;
- my $sfnumber = shift;
- my $var = shift;
- my $value = shift;
- if( $sfnumber > $#frames ) {
- $$currentframe{$var} = $value;
- } else {
- my $theframe = $frames[$sfnumber];
- $$theframe{$var} = $value;
- }
- print $debugsock "ok\n";
-}
-sub debug_stack {
- my $result = '';
- foreach my $frame ( @frames ) {
- $result .= print_frame($frame);
- $result .= '#';
- }
- $result .= print_frame($currentframe);
- print $debugsock "$result\n";
-}
-sub debug_step {
- # set suspend to 0 to allow the debug loop to exit back to
- # the instruction loop and thus run an instruction. However,
- # we want to come back to the debug loop right away, so the
- # step flag is set to true which will cause the suspend flag
- # to get set to true when we get to the next instruction.
- $step = 1;
- $suspend = 0;
- print $debugsock "ok\n";
-}
-sub debug_step_return {
- $stepreturn = 1;
- $suspend = 0;
- print $debugsock "ok\n";
-}
-sub debug_suspend {
- $suspend = "client";
- print $debugsock "ok\n";
-}
-sub debug_var {
- shift;
- my $sfnumber = shift;
- my $var = shift;
- if( $sfnumber > $#frames ) {
- print $debugsock "$$currentframe{$var}\n";
- } else {
- my $theframe = $frames[$sfnumber];
- print $debugsock "$$theframe{$var}\n";
- }
-}
-sub debug_watch {
- shift;
- my $key = shift;
- my $value = shift;
- $watchpoints{$key} = $value;
- print $debugsock "ok\n";
-}
-#
-# Some event has happened so notify the debugger.
-# If there is no debugger, we may still want to report the
-# event (such as if it is an error).
-#
-sub send_debug_event {
- my $event = shift;
- if( $debugflag ) {
- print $debugsock2 "$event\n";
- } else {
- my $use_stderr = shift;
- print "Error: $event\n" if $use_stderr;
- }
-}
-#
-# The stack frame output is:
-# frame # frame # frame ...
-# where each frame is:
-# filename | line number | function name | var | var | var | var ...
-#
-sub print_frame {
- my $frame = shift;
- my $result = $filename;
- $result .= '|' . $$frame{_pc_};
- $result .= '|' . $$frame{_func_};
- for my $var ( keys %$frame ) {
- $result .= '|' . $var unless( substr($var,0,1) eq '_');
- }
- return $result;
-}
-
-sub start_debugger {
- if( defined($debugflag) ) {
- if( $debugflag eq "-debug" ) {
- { # make STDOUT unbuffered
- my $ofh = select STDOUT;
- $| = 1;
- select $ofh;
- }
- $debugflag = 1;
- $debugport = shift @ARGV;
- $debugport2 = shift @ARGV;
- print "-debug $debugport $debugport2\n";
-
- my $mainsock = new IO::Socket::INET (LocalHost => '127.0.0.1',
- LocalPort => $debugport,
- Listen => 1,
- Proto => 'tcp',
- Reuse => 1,
- );
- $debugsock = $mainsock->accept();
-
- # make the socket non-blocking on windows
- my $set_it = "1";
- my $ioctl_val = 0x80000000 | (4 << 16) | (ord('f') << 8) | 126;
- ioctl($debugsock, $ioctl_val, $set_it);
-
- # make the socket non-blocking on linux
- $debugsock->blocking(0);
-
- my $mainsock2 = new IO::Socket::INET (LocalHost => '127.0.0.1',
- LocalPort => $debugport2,
- Listen => 1,
- Proto => 'tcp',
- Reuse => 1,
- );
- $debugsock2 = $mainsock2->accept();
-
- print "debug connection accepted\n";
- } else {
- $debugflag = 0;
- }
- }
-}

Back to the top