Merge lp:~zorba-coders/zorba/debugger_client into lp:zorba

Proposed by Gabriel Petrovay on 2011-12-19
Status: Merged
Approved by: Gabriel Petrovay on 2011-12-20
Approved revision: 10593
Merged at revision: 10588
Proposed branch: lp:~zorba-coders/zorba/debugger_client
Merge into: lp:zorba
Diff against target: 6749 lines (+3407/-2155)
47 files modified
CMakeConfiguration.txt (+7/-4)
bin/CMakeLists.txt (+21/-18)
bin/debug_client/debug_command.cpp (+0/-99)
bin/debug_client/event_handler_init.cpp.in (+0/-41)
bin/debug_client/lock_free_queue.cpp (+0/-16)
bin/debug_client/message-handler.xq (+0/-165)
bin/debugger/command.h (+164/-211)
bin/debugger/command_arg.h (+237/-0)
bin/debugger/command_line_handler.cpp (+350/-203)
bin/debugger/command_line_handler.h (+111/-58)
bin/debugger/command_prompt.cpp (+246/-0)
bin/debugger/command_prompt.h (+60/-0)
bin/debugger/config.h.cmake (+24/-0)
bin/debugger/event_handler.cpp (+82/-76)
bin/debugger/event_handler.h (+25/-12)
bin/debugger/lock_free_queue.h (+10/-2)
bin/debugger/main.cpp (+290/-14)
bin/debugger/tuple.h (+6/-0)
bin/zorbacmd.cpp (+7/-9)
cmake_modules/FindLibedit.cmake (+46/-0)
include/zorba/config.h.cmake (+8/-8)
include/zorba/debugger_client.h (+9/-1)
modules/com/zorba-xquery/www/modules/CMakeLists.txt (+7/-0)
modules/com/zorba-xquery/www/modules/debugger/dbgp-message-handler.xq (+277/-0)
src/compiler/expression/expr.cpp (+0/-1)
src/compiler/translator/translator.cpp (+5/-7)
src/debugger/debugger_client.cpp (+0/-2)
src/debugger/debugger_clientimpl.cpp (+545/-458)
src/debugger/debugger_clientimpl.h (+16/-9)
src/debugger/debugger_common.h (+3/-10)
src/debugger/debugger_commons.cpp (+122/-24)
src/debugger/debugger_commons.h (+11/-15)
src/debugger/debugger_communicator.cpp (+3/-3)
src/debugger/debugger_communicator.h (+4/-4)
src/debugger/debugger_protocol.cpp (+28/-16)
src/debugger/debugger_runtime.cpp (+308/-87)
src/debugger/debugger_runtime.h (+29/-12)
src/debugger/debugger_server.cpp (+229/-85)
src/debugger/debugger_server.h (+15/-1)
src/debugger/socket_streambuf.cpp (+68/-55)
src/debugger/socket_streambuf.h (+20/-9)
src/unit_tests/CMakeLists.txt (+0/-6)
src/unit_tests/test_debugger_protocol.cpp (+0/-414)
test/rbkt/ExpQueryResults/zorba/debugger/dmh/break_response.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/debugger/dmh/break_response_no_info.xml.res (+1/-0)
test/rbkt/Queries/zorba/debugger/dmh/break_response.xq (+5/-0)
test/rbkt/Queries/zorba/debugger/dmh/break_response_no_info.xq (+7/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/debugger_client
Reviewer Review Type Date Requested Status
David Graf (community) 2011-12-20 Approve on 2011-12-20
Gabriel Petrovay (community) Approve on 2011-12-19
Juan Zacarias 2011-12-19 Pending
Review via email: mp+86305@code.launchpad.net

Commit message

Mature zorba debugger with graceful degradation if libedit not found.

Description of the change

Mature zorba debugger with graceful degradation if libedit not found.

To post a comment you must log in.
review: Approve
David Graf (davidagraf) wrote :

I reviewed CMakeConfiguration.txt, bin/CMakeLists.txt, bin/debugger/config.h.cmake.

Looks good to me. I was only thinking if it would be a good idea to remove the option ZORBA_WITH_DEBUGGER_CLIENT (generating the debugger client if debugging is switched on). The less options to better.

review: Approve
Gabriel Petrovay (gabipetrovay) wrote :

Use the conversation "Can we please have libedit on the build server?" for opinions about ZORBA_WITH_DEBUGGER_CLIENT.

Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/debugger_client into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:272 (message):
  Validation queue job debugger_client-2011-12-20T16-40-29.862Z is finished.
  The final status was:

  No tests were run - build or configure step must have failed.

  Not commiting changes.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/debugger_client into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:272 (message):
  Validation queue job debugger_client-2011-12-20T17-21-18.291Z is finished.
  The final status was:

  1 tests did not succeed - changes not commited.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

10593. By Gabriel Petrovay on 2011-12-20

added missing version and xquery version from the dbgp-message-handler.xq module

Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job debugger_client-2011-12-20T18-12-16.752Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeConfiguration.txt'
2--- CMakeConfiguration.txt 2011-09-16 19:55:59 +0000
3+++ CMakeConfiguration.txt 2011-12-20 18:15:30 +0000
4@@ -70,10 +70,6 @@
5 SET(ZORBA_FOR_ONE_THREAD_ONLY OFF CACHE BOOL "compile zorba for single threaded use")
6 MESSAGE(STATUS "ZORBA_FOR_ONE_THREAD_ONLY: " ${ZORBA_FOR_ONE_THREAD_ONLY})
7
8-# by default the zorba command line client is deactivated until it gets to a more stable and userfriendly state
9-SET(ZORBA_WITH_DEBUGGER_CLIENT OFF CACHE BOOL "build and install zorbas command line debugger client")
10-MESSAGE(STATUS "ZORBA_WITH_DEBUGGER_CLIENT: " ${ZORBA_WITH_DEBUGGER_CLIENT})
11-
12 IF (DEFINED UNIX)
13 IF (NOT DEFINED ZORBA_HAVE_PTHREAD_H AND NOT DEFINED ZORBA_FOR_ONE_THREAD_ONLY)
14 MESSAGE(FATAL_ERROR "pthread is not available")
15@@ -93,6 +89,13 @@
16 SET(ZORBA_WITH_DEBUGGER ON CACHE BOOL "compile zorba with debugger support")
17 MESSAGE(STATUS "ZORBA_WITH_DEBUGGER [ON/OFF]: " ${ZORBA_WITH_DEBUGGER})
18
19+SET(ZORBA_WITH_DEBUGGER_CLIENT ON CACHE BOOL "compile zorba with a command line debugger client")
20+MESSAGE(STATUS "ZORBA_WITH_DEBUGGER_CLIENT [ON/OFF]: " ${ZORBA_WITH_DEBUGGER_CLIENT})
21+
22+IF (ZORBA_WITH_DEBUGGER_CLIENT AND NOT ZORBA_WITH_DEBUGGER)
23+ MESSAGE(FATAL_ERROR "Can not build a debugger client if the debugger support is disabled. Turn on ZORBA_WITH_DEBUGGER")
24+ENDIF (ZORBA_WITH_DEBUGGER_CLIENT AND NOT ZORBA_WITH_DEBUGGER)
25+
26 SET(ZORBA_TEST_TIMEOUT_VALUE 60 CACHE INTEGER "default test timeout value")
27 MESSAGE(STATUS "ZORBA_TEST_TIMEOUT_VALUE: " ${ZORBA_TEST_TIMEOUT_VALUE})
28
29
30=== modified file 'bin/CMakeLists.txt'
31--- bin/CMakeLists.txt 2011-11-04 11:40:20 +0000
32+++ bin/CMakeLists.txt 2011-12-20 18:15:30 +0000
33@@ -15,26 +15,29 @@
34 INCLUDE_DIRECTORIES(AFTER ${CMAKE_SOURCE_DIR}/src/)
35 INCLUDE_DIRECTORIES(AFTER ${CMAKE_CURRENT_SOURCE_DIR})
36
37-IF(ZORBA_WITH_DEBUGGER_CLIENT)
38- CONFIGURE_FILE (debug_client/event_handler_init.cpp.in debug_client/event_handler_init.cpp)
39-
40- SET(DEBUG_CLIENT_SRCS
41- debug_client/tuple.h
42- debug_client/main.cpp
43- debug_client/debug_command.h
44- debug_client/debug_command.cpp
45- debug_client/command_line_handler.h
46- debug_client/command_line_handler.cpp
47- debug_client/lock_free_queue.h
48- debug_client/event_handler.h
49- debug_client/event_handler.cpp
50- ${CMAKE_CURRENT_BINARY_DIR}/debug_client/event_handler_init.cpp
51+IF (ZORBA_WITH_DEBUGGER_CLIENT)
52+ IF (NOT WIN32)
53+ FIND_PACKAGE (Libedit)
54+ IF (LIBEDIT_FOUND)
55+ INCLUDE_DIRECTORIES (${LIBEDIT_INCLUDE_DIRS})
56+ SET (LIBEDIT_LIBS ${LIBEDIT_LIBRARIES})
57+ ENDIF (LIBEDIT_FOUND)
58+ ENDIF (NOT WIN32)
59+
60+ CHECK_INCLUDE_FILES ("editline/readline.h" ZORBA_HAVE_READLINE_H)
61+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/debugger/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/debugger/config.h)
62+ MESSAGE(STATUS "configured ${CMAKE_CURRENT_SOURCE_DIR}/debugger/config.h.cmake --> ${CMAKE_CURRENT_BINARY_DIR}/debugger/config.h")
63+ INCLUDE_DIRECTORIES (BEFORE ${CMAKE_CURRENT_BINARY_DIR}/debugger)
64+
65+ SET (DEBUG_CLIENT_SRCS
66+ debugger/main.cpp
67+ debugger/command_prompt.cpp
68+ debugger/command_line_handler.cpp
69+ debugger/event_handler.cpp
70 )
71
72- CONFIGURE_FILE (debug_client/message-handler.xq message-handler.xq)
73-
74- ZORBA_GENERATE_EXE("debuggercmd" "${DEBUG_CLIENT_SRCS}" "" "debugger" "bin")
75-ENDIF(ZORBA_WITH_DEBUGGER_CLIENT)
76+ ZORBA_GENERATE_EXE ("xqdb" "${DEBUG_CLIENT_SRCS}" "${LIBEDIT_LIBS}" "xqdb" "bin")
77+ENDIF (ZORBA_WITH_DEBUGGER_CLIENT)
78
79 SET(SRCS
80 zorbacmd.cpp
81
82=== removed file 'bin/debug_client/debug_command.cpp'
83--- bin/debug_client/debug_command.cpp 2011-07-01 01:53:24 +0000
84+++ bin/debug_client/debug_command.cpp 1970-01-01 00:00:00 +0000
85@@ -1,99 +0,0 @@
86-/*
87- * Copyright 2006-2008 The FLWOR Foundation.
88- *
89- * Licensed under the Apache License, Version 2.0 (the "License");
90- * you may not use this file except in compliance with the License.
91- * You may obtain a copy of the License at
92- *
93- * http://www.apache.org/licenses/LICENSE-2.0
94- *
95- * Unless required by applicable law or agreed to in writing, software
96- * distributed under the License is distributed on an "AS IS" BASIS,
97- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
98- * See the License for the specific language governing permissions and
99- * limitations under the License.
100- */
101-#include <iostream>
102-#include "debug_client/debug_command.h"
103-
104-namespace zorba { namespace debugclient {
105-
106-
107- void CommandLine::execute()
108- {
109- for (;;) {
110- std::cout << "zdb>> ";
111- std::string command;
112- std::getline(std::cin, command);
113- std::vector<std::string> args;
114- args << command;
115- std::map<std::string, UntypedCommand*>::iterator lIter = theCommands.find(args[0]);
116- if (lIter == theCommands.end()) {
117- std::cout << args[0] << ": Command not found" << std::endl;
118- continue;
119- }
120- if (!lIter->second->execute(args))
121- continue;
122- return;
123- }
124- }
125-
126-
127- CommandLine::~CommandLine()
128- {
129- for (std::map<std::string, UntypedCommand*>::iterator i = theCommands.begin();
130- i != theCommands.end(); ++i)
131- {
132- delete i->second;
133- }
134- }
135-
136- CommandLine& CommandLine::operator<<(UntypedCommand *aCommand)
137- {
138- theCommands.insert(std::make_pair(aCommand->get_name(), aCommand));
139- return *this;
140- }
141-}}
142-
143-namespace std {
144- vector<string>& operator<< (vector<string>& vec, const string& str)
145- {
146- string::size_type before = 0;
147- string::size_type pos = str.find(" ", 0);
148- while (pos != str.npos) {
149- std::string lSub = str.substr(before, pos - before);
150- if (lSub[0] == '"') {
151- std::string::size_type lBeforeCopy = before;
152- do {
153- lBeforeCopy = str.find("\"", lBeforeCopy + 1);
154- } while (pos != str.npos && str.size() > pos + 1 && str[pos + 1] == '\\');
155- pos = lBeforeCopy;
156- lSub = str.substr(before + 1, pos - before - 1);
157- }
158- vec.push_back(lSub);
159- before = pos + 1;
160- pos = str.find(" ", before);
161- }
162- std::string lSub = str.substr(before);
163- if (lSub[0] == '"') {
164- pos = str.find("\"", before + 1);
165- lSub = str.substr(before + 1, pos - before - 1);
166- }
167- vec.push_back(lSub);
168- return vec;
169- }
170-
171- set<string>& operator<< (set<string>& vec, const string& str)
172- {
173- string::size_type before = 0;
174- string::size_type pos = str.find(" ", 0);
175- while (pos != str.npos) {
176- vec.insert(str.substr(before, pos));
177- before = pos + 1;
178- pos = str.find(" ", before);
179- }
180- vec.insert(str.substr(before));
181- return vec;
182- }
183-
184-}
185
186=== removed file 'bin/debug_client/event_handler_init.cpp.in'
187--- bin/debug_client/event_handler_init.cpp.in 2011-07-01 01:53:24 +0000
188+++ bin/debug_client/event_handler_init.cpp.in 1970-01-01 00:00:00 +0000
189@@ -1,41 +0,0 @@
190-/*
191- * Copyright 2006-2008 The FLWOR Foundation.
192- *
193- * Licensed under the Apache License, Version 2.0 (the "License");
194- * you may not use this file except in compliance with the License.
195- * You may obtain a copy of the License at
196- *
197- * http://www.apache.org/licenses/LICENSE-2.0
198- *
199- * Unless required by applicable law or agreed to in writing, software
200- * distributed under the License is distributed on an "AS IS" BASIS,
201- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
202- * See the License for the specific language governing permissions and
203- * limitations under the License.
204- */
205-#include <fstream>
206-#include "debug_client/event_handler.h"
207-
208-namespace zorba { namespace debugclient {
209-
210- std::istream* EventHandler::getCurrentDirectory() {
211- const char* build_dir = "@CMAKE_BINARY_DIR@/bin/message-handler.xq";
212- const char* install_dir =
213-#ifndef WIN32
214- "@CMAKE_INSTALL_PREFIX@/bin/";
215-#else
216- "C:/Program Files/Zorba XQuery Processor @ZORBA_MAJOR_NUMBER@.@ZORBA_MINOR_NUMBER@.@ZORBA_PATCH_NUMBER@/bin/";
217-#endif
218- std::auto_ptr<std::ifstream> stream(new std::ifstream(build_dir));
219- if (stream->good()) {
220- return stream.release();
221- }
222- stream.reset(new std::ifstream(install_dir));
223- if (stream->good()) {
224- return stream.release();
225- }
226- return 0;
227- }
228-
229-}} // end of namespace zorba::debugclient
230-
231
232=== removed file 'bin/debug_client/lock_free_queue.cpp'
233--- bin/debug_client/lock_free_queue.cpp 2011-07-01 01:53:24 +0000
234+++ bin/debug_client/lock_free_queue.cpp 1970-01-01 00:00:00 +0000
235@@ -1,16 +0,0 @@
236-/*
237- * Copyright 2006-2008 The FLWOR Foundation.
238- *
239- * Licensed under the Apache License, Version 2.0 (the "License");
240- * you may not use this file except in compliance with the License.
241- * You may obtain a copy of the License at
242- *
243- * http://www.apache.org/licenses/LICENSE-2.0
244- *
245- * Unless required by applicable law or agreed to in writing, software
246- * distributed under the License is distributed on an "AS IS" BASIS,
247- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
248- * See the License for the specific language governing permissions and
249- * limitations under the License.
250- */
251-#include "lock_free_queue.h"
252
253=== removed file 'bin/debug_client/message-handler.xq'
254--- bin/debug_client/message-handler.xq 2011-08-26 23:36:24 +0000
255+++ bin/debug_client/message-handler.xq 1970-01-01 00:00:00 +0000
256@@ -1,165 +0,0 @@
257-(:
258- : Copyright 2006-2009 The FLWOR Foundation.
259- :
260- : Licensed under the Apache License, Version 2.0 (the "License");
261- : you may not use this file except in compliance with the License.
262- : You may obtain a copy of the License at
263- :
264- : http://www.apache.org/licenses/LICENSE-2.0
265- :
266- : Unless required by applicable law or agreed to in writing, software
267- : distributed under the License is distributed on an "AS IS" BASIS,
268- : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
269- : See the License for the specific language governing permissions and
270- : limitations under the License.
271-:)
272-
273-import module namespace refl = 'http://www.zorba-xquery.com/modules/reflection';
274-import module namespace sctx = "http://www.zorba-xquery.com/modules/introspection/sctx";
275-import module namespace base64 = "http://www.zorba-xquery.com/modules/converters/base64";
276-
277-
278-declare variable $local:localns as xs:string := 'http://www.w3.org/2005/xquery-local-functions';
279-
280-
281-declare variable $local:endl as xs:string := '
282-';
283-
284-declare function local:has-to-stop($resp as element())
285-{
286- fn:not(($resp/@command/data(.) eq "stop" and $resp/@reason/data(.) eq "ok")
287- or ($resp/@status/data(.) eq "stopped")
288- or ($resp/@status/data(.) eq "stopping"))
289-};
290-
291-declare function local:status($resp as element())
292-{
293- fn:concat(
294- "Status: ", $resp/@status/data(.), $local:endl,
295- "Reason: ", $resp/@reason/data(.), $local:endl,
296- let $msg := $resp/text()
297- return
298- if (fn:empty($msg) or $msg eq "") then
299- ""
300- else
301- fn:concat($msg, $local:endl)
302- )
303-};
304-
305-
306-declare function local:run($resp as element()) {
307- if ($resp/@status/data(.) eq "starting") then
308- "Starting query"
309- else
310- local:status($resp)
311-};
312-
313-declare function local:stop($resp as element())
314-{
315- local:status($resp)
316-};
317-
318-declare function local:breakpoint_set($resp as element())
319-{
320- if ($resp/error) then
321- fn:concat("Error when setting a breakpoint: ", if ($resp/error/message) then $resp/error/message/text() else concat(" errcode: ", data($resp/error/@code)))
322- else
323- fn:concat("set breakpoint with id ", data($resp/@id), " and state ", data($resp/@state))
324-};
325-
326-declare function local:breakpoint_list($resp as element())
327-{
328- string-join(
329- for $b in $resp/breakpoint
330- return concat("Breakpoint ", data($b/@id), " at ", data($b/@filename), ":", data($b/@lineno), " ", data($b/@state)),
331- $local:endl
332- )
333-};
334-
335-declare function local:breakpoint_remove($resp as element())
336-{
337- "Breakpoint removed"
338-};
339-
340-declare function local:stack_depth($resp as element())
341-{
342- concat("Depth: ", data($resp/@depth))
343-};
344-
345-declare function local:stack_get($resp as element())
346-{
347- string-join(
348- for $s in $resp/stack
349- return concat("Level ", data($s/@level), " at ", data($s/@filename), ":", data($s/@lineno)),
350- $local:endl
351- )
352-};
353-
354-
355-declare function local:context_names($resp as element())
356-{
357- string-join(
358- for $c in $resp/context
359- return concat("Context: ", data($c/@name), " id: ", data($c/@id)),
360- $local:endl
361- )
362-};
363-
364-declare function local:context_get($resp as element())
365-{
366- string-join(
367- for $p in $resp/property
368- return concat(data($p/@fullname), ": [", data($p/@type), "]",
369- if ($p/text() ne "") then concat(": ", base64:decode($p/text())) else ""),
370- $local:endl
371- )
372-};
373-
374-declare function local:eval($resp as element())
375-{
376- if (data($resp/@success) eq "1") then
377- local:context_get($resp)
378- else
379- concat("Eval failed", ":", $resp/error/message/text())
380-};
381-
382-declare function local:process-response($resp as element())
383-{
384- if (data($resp/@command) eq "") then
385- (fn:true(), $resp/@transaction_id/data(.), local:status($resp))
386- else
387- let $fun-cont-name := fn:QName($local:localns, concat("local:", $resp/@command/data(.), "-cont"))
388- let $fun-msg-name := fn:QName($local:localns, concat("local:", $resp/@command/data(.)))
389- return (
390- if (sctx:function-arguments-count($fun-cont-name) = 1) then
391- refl:invoke($fun-cont-name, $resp)
392- else
393- local:has-to-stop($resp),
394- $resp/@transaction_id/data(.),
395- if (sctx:function-arguments-count($fun-msg-name) = 1) then
396- refl:invoke($fun-msg-name, $resp)
397- else
398- "Recieved a message - command not implemented"
399- )
400-};
401-
402-declare function local:process-init($init as element())
403-{
404- fn:true(),
405- 0,
406- fn:concat(fn:string-join(
407- ('Established connection with', $init/@language/data(.), 'client', $init/@appid/data(.)), ' '), '
408-')
409-};
410-
411-declare function local:main($response as element()) {
412- let $process-fun as xs:QName := fn:QName($local:localns, concat("local:process-", node-name($response)))
413- return
414- if (sctx:function-arguments-count($process-fun) = 1) then
415- refl:invoke($process-fun, $response)
416- else (
417- true(),
418- ($response/@transaction_id, 0)[1]/data(.),
419- "ERROR: Recieved unknown node from client"
420- )
421-};
422
423=== renamed directory 'bin/debug_client' => 'bin/debugger'
424=== renamed file 'bin/debug_client/debug_command.h' => 'bin/debugger/command.h'
425--- bin/debug_client/debug_command.h 2011-07-04 08:05:46 +0000
426+++ bin/debugger/command.h 2011-12-20 18:15:30 +0000
427@@ -14,7 +14,9 @@
428 * limitations under the License.
429 */
430 #pragma once
431-#include <zorba/config.h>
432+#ifndef ZORBA_DEBUGGER_COMMAND_H
433+#define ZORBA_DEBUGGER_COMMAND_H
434+
435 #include <string>
436 #include <vector>
437 #include <iostream>
438@@ -23,151 +25,18 @@
439 #include <sstream>
440 #include <memory>
441 #include <typeinfo>
442-#include "debug_client/tuple.h"
443-
444-namespace zorba { namespace debugclient {
445+
446+#include <zorba/config.h>
447+
448+#include "command_arg.h"
449+#include "tuple.h"
450+
451+
452+namespace zorba { namespace debugger {
453
454 class DebugClientParseException : public std::exception {
455 };
456
457- template<typename Tuple>
458- class CommandArg;
459-
460- template<typename Tuple>
461- class CommandArgInstance {
462- public:
463- virtual int get_index() const = 0;
464- virtual const CommandArg<Tuple>* get_arg() const = 0;
465- virtual void insertValue(Tuple& t) = 0;
466- virtual bool isSet(Tuple& t) const = 0;
467- };
468-
469- template<typename T, int Idx, typename Tuple>
470- class TypedCommandArgInstance : public CommandArgInstance<Tuple>
471- {
472- public:
473- TypedCommandArgInstance(T aValue, const CommandArg<Tuple>* aArg)
474- : theValue(aValue), theArg(aArg) {}
475- virtual int get_index() const { return Idx; }
476- virtual const CommandArg<Tuple>* get_arg() const { return theArg; }
477- virtual void insertValue(Tuple& t)
478- {
479- ZORBA_TR1_NS::get<Idx>(t).first = true;
480- ZORBA_TR1_NS::get<Idx>(t).second = theValue;
481- }
482- virtual bool isSet(Tuple& t) const
483- {
484- return ZORBA_TR1_NS::get<Idx>(t).first;
485- }
486- private:
487- T theValue;
488- const CommandArg<Tuple>* theArg;
489- };
490-
491- template<typename Tuple>
492- class CommandArgType {
493- public:
494- virtual CommandArgInstance<Tuple>* parse(const std::string& str,
495- const CommandArg<Tuple>* arg) = 0;
496- virtual bool isVoid() const = 0;
497- virtual bool isSet(Tuple& t) const = 0;
498- virtual ~CommandArgType() {}
499- };
500-
501- template<typename T, int Idx, typename Tuple>
502- class TypedCommandArgType : public CommandArgType<Tuple> {
503- public:
504- typedef T Type;
505- public: // implementation
506- TypedCommandArgType(bool aIsVoid) : theIsVoid(aIsVoid) {}
507- TypedCommandArgType(const T& aValue,
508- bool aIsVoid)
509- : theDefault(aValue), theIsVoid(aIsVoid) {}
510- virtual CommandArgInstance<Tuple>* parse(const std::string& str,
511- const CommandArg<Tuple>* arg)
512- {
513- T aValue;
514- std::stringstream stream(str);
515- stream >> aValue;
516- if (stream.fail()) {
517- std::cerr << "Could not parse argument of type "
518- << typeid(T).name()
519- << std::endl;
520- return 0;
521- }
522- return new TypedCommandArgInstance<T, Idx, Tuple>(aValue, arg);
523- }
524- virtual bool isVoid() const { return theIsVoid; }
525- virtual bool isSet(Tuple& t) const
526- {
527- return ZORBA_TR1_NS::get<Idx>(t).first;
528- }
529- private:
530- TypedCommandArgType<T, Idx, Tuple>() {}
531- T theDefault;
532- bool theIsVoid;
533- };
534-
535- template<typename Tuple>
536- class CommandArg {
537- public:
538- CommandArg(unsigned aId,
539- CommandArgType<Tuple>* aType,
540- const std::set<std::string>& aFlags,
541- const std::string& aDescription,
542- bool aIsRequired)
543- : theId(aId),
544- theType(aType),
545- theFlags(aFlags),
546- theDescription(aDescription),
547- theIsRequired(aIsRequired)
548- {
549- }
550- ~CommandArg() { delete theType; }
551- unsigned get_id() const { return theId; }
552- bool canHandle(const std::string& arg) const
553- {
554- if (theFlags.find(arg) != theFlags.end()) {
555- return true;
556- }
557- return false;
558- }
559- CommandArgInstance<Tuple>* parse(const std::string& str) const
560- {
561- return theType->parse(str, this);
562- }
563- bool isVoid() const {
564- return theType->isVoid();
565- }
566- bool isRequired() const { return theIsRequired; }
567- std::string get_name() const {
568- return *(theFlags.begin());
569- }
570- bool isSet(Tuple& t) const
571- {
572- return theType->isSet(t);
573- }
574- private:
575- unsigned theId;
576- CommandArgType<Tuple>* theType;
577- std::set<std::string> theFlags;
578- std::string theDescription;
579- bool theIsRequired;
580- };
581-}} // end namespace zorba
582-
583-namespace std {
584-
585- /**
586- * This is a helper split function
587- */
588- vector<string>& operator<< (vector<string>& vec, const string& str);
589-
590- set<string>& operator<< (set<string>& vec, const string& str);
591-} //end namespace std
592-
593-namespace zorba { namespace debugclient {
594-
595 template<typename Func, typename Tuple, int CommandIdx>
596 class CommandInstance
597 {
598@@ -188,8 +57,10 @@
599
600 class UntypedCommand {
601 public:
602- virtual std::string get_name() const = 0;
603- virtual std::string get_description() const = 0;
604+ virtual std::string getName() const = 0;
605+ virtual std::set<std::string> getAliases() const = 0;
606+ virtual std::string getDescription() const = 0;
607+ virtual void printHelp() const = 0;
608 virtual bool execute(const std::vector<std::string>& args) = 0;
609 };
610
611@@ -197,77 +68,141 @@
612 class Command : public UntypedCommand {
613 public:
614 Command(const std::string& aName, Func& aFunction, const std::string& aDescription)
615- : theName(aName), theFunction(aFunction), theDescription(aDescription) {}
616+ : theName(aName), theFunction(aFunction), theDescription(aDescription)
617+ {}
618+
619+ Command(const std::string& aName, const std::set<std::string> aAliases, Func& aFunction, const std::string& aDescription)
620+ : theName(aName), theAliases(aAliases), theFunction(aFunction), theDescription(aDescription)
621+ {}
622+
623 ~Command();
624+
625 public:
626- Command& operator() (unsigned aId,
627- const std::string& aFlags,
628- CommandArgType<Tuple>* aType,
629- const std::string& aDescription = "",
630- bool isRequired = false);
631- virtual std::string get_name() const { return theName; }
632- virtual std::string get_description() const { return theDescription; }
633+
634+ void
635+ addArgument(
636+ unsigned aId,
637+ const std::string& aFlags,
638+ CommandArgType<Tuple>* aType,
639+ const std::string& aDescription = "",
640+ bool isRequired = false);
641+
642+ static void
643+ splitNames(
644+ const std::string& names,
645+ std::set<std::string>& set);
646+
647+ virtual std::string
648+ getName() const
649+ {
650+ return theName;
651+ }
652+
653+ virtual std::set<std::string> getAliases() const
654+ {
655+ return theAliases;
656+ }
657+
658+ virtual std::string
659+ getDescription() const
660+ {
661+ return theDescription;
662+ }
663+
664+ virtual void
665+ printHelp() const;
666+
667 virtual bool execute(const std::vector<std::string>& args)
668 {
669 CommandInstance<Func, Tuple, CommandIdx> instance(theFunction, theTuple);
670- if (instance.parseArguments(args, theArgs))
671+ if (instance.parseArguments(args, theArgs)) {
672 instance.execute();
673- else
674- return false;
675- return true;
676+ return true;
677+ }
678+ return false;
679 }
680 private:
681 std::string theName;
682+ std::set<std::string> theAliases;
683 Func& theFunction;
684 Tuple theTuple;
685 std::string theDescription;
686- std::map<std::string, CommandArg<Tuple>* > theArgs;
687- };
688-
689- class CommandLine {
690- public:
691- ~CommandLine();
692- public:
693- void execute();
694- CommandLine& operator<< (UntypedCommand* aCommand);
695- private:
696- std::map<std::string, UntypedCommand*> theCommands;
697- };
698-
699- template<typename Func, typename Tuple, int CommandIdx>
700- Command<Func, Tuple, CommandIdx>::~Command()
701- {
702- typedef std::map<std::string, CommandArg<Tuple>* > ArgType;
703- for (typename ArgType::iterator i = theArgs.begin(); i != theArgs.end(); ++i) {
704- delete i->second;
705- }
706- }
707-
708-
709- template<typename Func, typename Tuple, int CommandIdx>
710- Command<Func, Tuple, CommandIdx>&
711- Command<Func, Tuple, CommandIdx>::operator() (unsigned aId,
712- const std::string& aFlags,
713- CommandArgType<Tuple>* aType,
714- const std::string& aDescription,
715- bool isRequired)
716- {
717- std::set<std::string> args;
718- args << aFlags;
719- for (std::set<std::string>::iterator i = args.begin(); i != args.end(); ++i) {
720- std::string toAdd = (i->size() == 1) ? "-" + *i : "--" + *i;
721- theArgs.insert(std::make_pair(toAdd,
722- new CommandArg<Tuple>(aId,
723- aType,
724- args,
725- aDescription,
726- isRequired)
727- )
728- );
729- }
730- return *this;
731- }
732-
733+ std::map<std::string, CommandArg<Tuple>*> theArgs;
734+ };
735+
736+/*****************************************************************************/
737+/*****************************************************************************/
738+
739+template<typename Func, typename Tuple, int CommandIdx>
740+Command<Func, Tuple, CommandIdx>::~Command()
741+{
742+ typedef std::map<std::string, CommandArg<Tuple>*> ArgType;
743+ for (typename ArgType::iterator i = theArgs.begin(); i != theArgs.end(); ++i) {
744+ delete i->second;
745+ }
746+}
747+
748+template<typename Func, typename Tuple, int CommandIdx>
749+void
750+Command<Func, Tuple, CommandIdx>::printHelp() const
751+{
752+ std::cout << "Purpose: " << getDescription() << std::endl;
753+
754+ typename std::map<std::string, CommandArg<Tuple>*>::const_iterator lIter = theArgs.begin();
755+ if (lIter == theArgs.end()) {
756+ std::cout << "This command has no arguments." << std::endl;
757+ std::cout << std::endl;
758+ return;
759+ }
760+
761+ std::cout << "Arguments:" << std::endl << std::endl;
762+ for (; lIter != theArgs.end(); ++lIter) {
763+ std::cout << " " << lIter->first << "\t" << lIter->second->getDescription() << std::endl;
764+ }
765+ std::cout << std::endl;
766+}
767+
768+template<typename Func, typename Tuple, int CommandIdx>
769+void
770+Command<Func, Tuple, CommandIdx>::splitNames(const std::string& aNames, std::set<std::string>& aSet)
771+{
772+ std::string::size_type before = 0;
773+ std::string::size_type pos = aNames.find(" ", 0);
774+ while (pos != aNames.npos) {
775+ std::string lName = aNames.substr(before, pos);
776+ if (lName != "") {
777+ aSet.insert(lName);
778+ }
779+ before = pos + 1;
780+ pos = aNames.find(" ", before);
781+ }
782+ std::string lName = aNames.substr(before);
783+ if (lName != "") {
784+ aSet.insert(lName);
785+ }
786+}
787+
788+template<typename Func, typename Tuple, int CommandIdx>
789+void
790+Command<Func, Tuple, CommandIdx>::addArgument(
791+ unsigned aId,
792+ const std::string& aFlags,
793+ CommandArgType<Tuple>* aType,
794+ const std::string& aDescription,
795+ bool isRequired)
796+{
797+ std::set<std::string> lNames;
798+ splitNames(aFlags, lNames);
799+
800+ for (std::set<std::string>::iterator i = lNames.begin(); i != lNames.end(); ++i) {
801+ std::string toAdd = (i->size() == 1) ? "-" + *i : "--" + *i;
802+ CommandArg<Tuple>* lArg = new CommandArg<Tuple>(aId, aType, lNames, aDescription, isRequired);
803+ theArgs.insert(std::make_pair(toAdd, lArg));
804+ }
805+}
806+
807+/*****************************************************************************/
808+
809 template<typename Tuple, typename T, int Idx>
810 CommandArgType<Tuple>* createArgType(Tuple t)
811 {
812@@ -290,6 +225,16 @@
813 return new Command<Func, Tuple, CommandIdx>(aName, aFunction, aDescription);
814 }
815
816+ template<int CommandIdx, typename Tuple, typename Func>
817+ Command<Func, Tuple, CommandIdx>* createCommand(Tuple t,
818+ const std::string& aName,
819+ const std::set<std::string>& aAliases,
820+ Func& aFunction,
821+ const std::string& aDescription)
822+ {
823+ return new Command<Func, Tuple, CommandIdx>(aName, aAliases, aFunction, aDescription);
824+ }
825+
826 template<typename Func, typename Tuple, int CommandIdx>
827 bool CommandInstance<Func, Tuple, CommandIdx>::
828 parseArguments(const std::vector<std::string>& args,
829@@ -301,29 +246,34 @@
830 for (ArgType::size_type i = 1; i < size; ++i) {
831 typename CArgType::const_iterator pos = aCommandArgs.find(args[i]);
832 if (pos == aCommandArgs.end()) {
833- std::cerr << "Error: Unknown Argument " << args[i] << std::endl;
834+ std::cerr << "Error: Unknown option " << args[i] << std::endl;
835 parseError = true;
836 return false;
837 }
838 const CommandArg<Tuple>& arg = *(pos->second);
839- if (!arg.isVoid() && args[++i][0] == '-') {
840- std::cerr << "Did not expect parameter for option " << args[i] << std::endl;
841- return false;
842- }
843 std::auto_ptr<CommandArgInstance<Tuple> > instance;
844 if (arg.isVoid()) {
845 instance.reset(arg.parse("1"));
846 } else {
847+ ++i;
848+ if (i >= size) {
849+ std::cerr << "Error: Missing value for argument " << args[i - 1] << std::endl;
850+ parseError = true;
851+ allSet = false;
852+ return false;
853+ }
854 instance.reset(arg.parse(args[i]));
855 }
856- instance->insertValue(theTuple);
857+ if (instance.get()) {
858+ instance->insertValue(theTuple);
859+ }
860 }
861 bool allSet = true;
862 for (typename CArgType::const_iterator i = aCommandArgs.begin();
863 i != aCommandArgs.end(); ++i)
864 {
865 if (i->second->isRequired() && !i->second->isSet(theTuple)) {
866- std::cerr << "Error: Argument " << i->second->get_name() << " not set" << std::endl;
867+ std::cerr << "Error: Argument -" << i->second->getName() << " not set" << std::endl;
868 allSet = false;
869 }
870 }
871@@ -336,4 +286,7 @@
872 theFunction.template handle<CommandIdx>(this->theTuple);
873 }
874
875-}} // end of namespace zorba::debugclient
876+} // namespace zorba
877+} // namespace debugger
878+
879+#endif // ZORBA_DEBUGGER_COMMAND_H
880
881=== added file 'bin/debugger/command_arg.h'
882--- bin/debugger/command_arg.h 1970-01-01 00:00:00 +0000
883+++ bin/debugger/command_arg.h 2011-12-20 18:15:30 +0000
884@@ -0,0 +1,237 @@
885+/*
886+ * Copyright 2006-2008 The FLWOR Foundation.
887+ *
888+ * Licensed under the Apache License, Version 2.0 (the "License");
889+ * you may not use this file except in compliance with the License.
890+ * You may obtain a copy of the License at
891+ *
892+ * http://www.apache.org/licenses/LICENSE-2.0
893+ *
894+ * Unless required by applicable law or agreed to in writing, software
895+ * distributed under the License is distributed on an "AS IS" BASIS,
896+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
897+ * See the License for the specific language governing permissions and
898+ * limitations under the License.
899+ */
900+#pragma once
901+#ifndef ZORBA_DEBUGGER_COMMAND_ARG_H
902+#define ZORBA_DEBUGGER_COMMAND_ARG_H
903+
904+#include <string>
905+#include <iostream>
906+#include <set>
907+#include <sstream>
908+
909+#include "tuple.h"
910+
911+
912+namespace zorba { namespace debugger {
913+
914+template<typename Tuple>
915+class CommandArg;
916+
917+template<typename Tuple>
918+class CommandArgInstance {
919+ public:
920+ virtual int get_index() const = 0;
921+ virtual const CommandArg<Tuple>* get_arg() const = 0;
922+ virtual void insertValue(Tuple& t) = 0;
923+ virtual bool isSet(Tuple& t) const = 0;
924+};
925+
926+template<typename T, int Idx, typename Tuple>
927+class TypedCommandArgInstance : public CommandArgInstance<Tuple>
928+{
929+ public:
930+ TypedCommandArgInstance(T aValue, const CommandArg<Tuple>* aArg)
931+ : theValue(aValue), theArg(aArg)
932+ {
933+ }
934+
935+ virtual int
936+ get_index() const
937+ {
938+ return Idx;
939+ }
940+
941+ virtual const CommandArg<Tuple>*
942+ get_arg() const
943+ {
944+ return theArg;
945+ }
946+
947+ virtual void
948+ insertValue(Tuple& t)
949+ {
950+ ZORBA_TR1_NS::get<Idx>(t).first = true;
951+ ZORBA_TR1_NS::get<Idx>(t).second = theValue;
952+ }
953+
954+ virtual bool isSet(Tuple& t) const
955+ {
956+ return ZORBA_TR1_NS::get<Idx>(t).first;
957+ }
958+
959+ private:
960+
961+ T theValue;
962+ const CommandArg<Tuple>* theArg;
963+};
964+
965+template<typename Tuple>
966+class CommandArgType
967+{
968+ public:
969+ virtual CommandArgInstance<Tuple>*
970+ parse(
971+ const std::string& str,
972+ const CommandArg<Tuple>* arg) = 0;
973+
974+ virtual bool
975+ isVoid() const = 0;
976+
977+ virtual bool
978+ isSet(Tuple& t) const = 0;
979+
980+ virtual ~CommandArgType() {}
981+};
982+
983+ template<typename T, int Idx, typename Tuple>
984+ class TypedCommandArgType : public CommandArgType<Tuple> {
985+ public:
986+ typedef T Type;
987+ public: // implementation
988+ TypedCommandArgType(bool aIsVoid) : theIsVoid(aIsVoid) {}
989+ TypedCommandArgType(const T& aValue,
990+ bool aIsVoid)
991+ : theDefault(aValue), theIsVoid(aIsVoid) {}
992+ virtual CommandArgInstance<Tuple>* parse(const std::string& str,
993+ const CommandArg<Tuple>* arg)
994+ {
995+ T aValue;
996+
997+ // special treatment for strings
998+ // this is a double hack:
999+ // - we check the type name if this starts with: class std::basic_string
1000+ // - we use void* in readEntireString to workaround the template type T
1001+ // which would otherwise complain during compilation if types and
1002+ // operators do not match
1003+ // TOSO: probably someone can find a more elegant solution
1004+ std::string lTypeName(typeid(T).name());
1005+ if (lTypeName.find("class std::basic_string") == 0) {
1006+ readEntireString(str, &aValue);
1007+ } else {
1008+ std::stringstream stream(str);
1009+ std::stringstream out;
1010+ stream >> aValue;
1011+ if (stream.fail()) {
1012+ std::cerr << "Error: Could not parse value \"" << str << "\" as type "
1013+ << typeid(T).name()
1014+ << std::endl;
1015+ return 0;
1016+ }
1017+ }
1018+
1019+ return new TypedCommandArgInstance<T, Idx, Tuple>(aValue, arg);
1020+ }
1021+ virtual bool isVoid() const { return theIsVoid; }
1022+ virtual bool isSet(Tuple& t) const
1023+ {
1024+ return ZORBA_TR1_NS::get<Idx>(t).first;
1025+ }
1026+ private:
1027+ void readEntireString(std::string aIn, void* aValue)
1028+ {
1029+ *((std::string*)aValue) = aIn;
1030+ }
1031+
1032+ TypedCommandArgType<T, Idx, Tuple>() {}
1033+ T theDefault;
1034+ bool theIsVoid;
1035+ };
1036+
1037+ template<typename Tuple>
1038+ class CommandArg {
1039+ public:
1040+ CommandArg(unsigned aId,
1041+ CommandArgType<Tuple>* aType,
1042+ const std::set<std::string>& aNames,
1043+ const std::string& aDescription,
1044+ bool aIsRequired)
1045+ : theId(aId),
1046+ theType(aType),
1047+ theNames(aNames),
1048+ theDescription(aDescription),
1049+ theIsRequired(aIsRequired)
1050+ {
1051+ }
1052+
1053+ ~CommandArg()
1054+ {
1055+ delete theType;
1056+ }
1057+
1058+ unsigned
1059+ get_id() const
1060+ {
1061+ return theId;
1062+ }
1063+
1064+ bool
1065+ canHandle(const std::string& arg) const
1066+ {
1067+ if (theNames.find(arg) != theNames.end()) {
1068+ return true;
1069+ }
1070+ return false;
1071+ }
1072+
1073+ CommandArgInstance<Tuple>*
1074+ parse(const std::string& str) const
1075+ {
1076+ return theType->parse(str, this);
1077+ }
1078+
1079+ bool
1080+ isVoid() const
1081+ {
1082+ return theType->isVoid();
1083+ }
1084+
1085+ bool
1086+ isRequired() const
1087+ {
1088+ return theIsRequired;
1089+ }
1090+
1091+ std::string
1092+ getName() const
1093+ {
1094+ return *(theNames.begin());
1095+ }
1096+
1097+ std::string
1098+ getDescription() const
1099+ {
1100+ return theDescription;
1101+ }
1102+
1103+ bool
1104+ isSet(Tuple& t) const
1105+ {
1106+ return theType->isSet(t);
1107+ }
1108+
1109+ private:
1110+
1111+ unsigned theId;
1112+ CommandArgType<Tuple>* theType;
1113+ std::set<std::string> theNames;
1114+ std::string theDescription;
1115+ bool theIsRequired;
1116+ };
1117+
1118+} // namespace zorba
1119+} // namespace debugger
1120+
1121+#endif // ZORBA_DEBUGGER_COMMAND_ARG_H
1122
1123=== modified file 'bin/debugger/command_line_handler.cpp'
1124--- bin/debug_client/command_line_handler.cpp 2011-07-01 01:53:24 +0000
1125+++ bin/debugger/command_line_handler.cpp 2011-12-20 18:15:30 +0000
1126@@ -1,4 +1,4 @@
1127-/*
1128+ /*
1129 * Copyright 2006-2008 The FLWOR Foundation.
1130 *
1131 * Licensed under the Apache License, Version 2.0 (the "License");
1132@@ -23,225 +23,372 @@
1133 # define msleep Sleep
1134 #endif
1135
1136-namespace zorba { namespace debugclient {
1137+namespace zorba { namespace debugger {
1138
1139- using namespace ::std;
1140 using namespace ::ZORBA_TR1_NS;
1141
1142- CommandLineHandler::CommandLineHandler(unsigned short port,
1143- LockFreeConsumer<std::size_t>& aConsumer,
1144- LockFreeConsumer<bool>& aContinueQueue,
1145- EventHandler& aHandler,
1146- CommandLine& aCommandLine)
1147+CommandLineHandler::CommandLineHandler(
1148+ unsigned short port,
1149+ LockFreeConsumer<std::size_t>& aConsumer,
1150+ LockFreeConsumer<bool>& aContinueQueue,
1151+ EventHandler& aHandler,
1152+ CommandPrompt& aCommandPrompt)
1153 : theConsumer(aConsumer),
1154 theContinueQueue(aContinueQueue),
1155 theClient(DebuggerClient::createDebuggerClient(&aHandler, port, "localhost")),
1156- theCommandLine(aCommandLine),
1157- theQuit(false), theContinue(false), theWaitFor(0)
1158+ theCommandLine(aCommandPrompt),
1159+ theQuit(false), theTerminated(true), theContinue(false), theWaitFor(0)
1160 {
1161 addCommands();
1162 }
1163
1164- CommandLineHandler::~CommandLineHandler()
1165- {
1166- }
1167+CommandLineHandler::~CommandLineHandler()
1168+{
1169+}
1170
1171- void CommandLineHandler::execute()
1172- {
1173- theClient->accept();
1174- std::set<std::size_t> lIdList;
1175- do {
1176+void
1177+CommandLineHandler::execute()
1178+{
1179+ theClient->accept();
1180+ std::set<std::size_t> lIdList;
1181+ do {
1182+ getNextId(lIdList);
1183+ while (lIdList.find(theWaitFor) == lIdList.end()) {
1184 getNextId(lIdList);
1185- while (!theQuit && lIdList.find(theWaitFor) == lIdList.end()) {
1186- getNextId(lIdList);
1187- msleep(20);
1188- }
1189- while (!theContinueQueue.consume(theQuit)) {
1190- msleep(20);
1191- }
1192- theQuit = !theQuit;
1193- if (!theQuit) {
1194- theCommandLine.execute();
1195- while (theContinue) {
1196- theContinue = false;
1197- theCommandLine.execute();
1198- }
1199- }
1200- } while (!theQuit);
1201- }
1202-
1203- void CommandLineHandler::getNextId(std::set<std::size_t>& aIdList)
1204- {
1205- std::size_t result;
1206- if (theConsumer.consume(result)) {
1207- aIdList.insert(result);
1208- }
1209- }
1210-
1211- template<>
1212- void CommandLineHandler::handle<Status>(ZORBA_TR1_NS::tuple<> &t)
1213- {
1214- theWaitFor = theClient->status();
1215- }
1216-
1217- template<>
1218- void CommandLineHandler::handle<Quit>(ZORBA_TR1_NS::tuple<> &t)
1219- {
1220+ msleep(20);
1221+ }
1222+ bool lCanQuit;
1223+ while (!theContinueQueue.consume(lCanQuit)) {
1224+ msleep(20);
1225+ }
1226+ if (lCanQuit) {
1227+ theTerminated = true;
1228+ }
1229+ theCommandLine.execute();
1230+ while (theContinue) {
1231+ theContinue = false;
1232+ theCommandLine.execute();
1233+ }
1234+ } while (!theQuit);
1235+}
1236+
1237+void
1238+CommandLineHandler::getNextId(std::set<std::size_t>& aIdList)
1239+{
1240+ std::size_t result;
1241+ if (theConsumer.consume(result)) {
1242+ aIdList.insert(result);
1243+ }
1244+}
1245+
1246+template<>
1247+void
1248+CommandLineHandler::handle<Status>(ZORBA_TR1_NS::tuple<> &t)
1249+{
1250+ theWaitFor = theClient->status();
1251+}
1252+
1253+template<>
1254+void
1255+CommandLineHandler::handle<Variables>(ZORBA_TR1_NS::tuple<> &t)
1256+{
1257+ theWaitFor = theClient->variables();
1258+}
1259+
1260+template<>
1261+void
1262+CommandLineHandler::handle<Quit>(ZORBA_TR1_NS::tuple<> &t)
1263+{
1264+ if (!theTerminated) {
1265 bool answered = false;
1266 while (!answered) {
1267 std::cout << "Do you really want to stop debugging and exit? (y/n) ";
1268- char answer;
1269- std::cin >> answer;
1270- std::cout << std::endl;
1271- if (answer == 'y') {
1272+ std::string lAnswer;
1273+ std::getline(std::cin, lAnswer);
1274+ if (lAnswer == "y" || lAnswer == "yes") {
1275 answered = true;
1276- } else if (answered == 'n') {
1277+ } else if (lAnswer == "n" || lAnswer == "no") {
1278 theContinue = true;
1279 return;
1280 }
1281 }
1282- theWaitFor = theClient->stop();
1283- theClient->quit();
1284- }
1285-
1286- template<>
1287- void CommandLineHandler::handle<Run>(ZORBA_TR1_NS::tuple<> &t)
1288- {
1289- theWaitFor = theClient->run();
1290- }
1291-
1292- template<>
1293- void CommandLineHandler::handle<BreakpointSet>(std::tr1::tuple<bstring, bstring, bint> &t)
1294- {
1295- DebuggerClient::BreakpointType lType = DebuggerClient::Line;
1296- bool lEnabled = true;
1297- if (get<0>(t).first) {
1298- if (get<0>(t).second == "disabled") {
1299- lEnabled = false;
1300- }
1301- }
1302- theWaitFor = theClient->breakpoint_set(lType,
1303- lEnabled,
1304- get<1>(t).second,
1305- get<2>(t).second);
1306- }
1307-
1308- template<>
1309- void CommandLineHandler::handle<BreakpointGet>(tuple<bint> &aTuple)
1310- {
1311- theWaitFor = theClient->breakpoint_get(get<0>(aTuple).second);
1312- }
1313-
1314- template<>
1315- void CommandLineHandler::handle<BreakpointDel>(tuple<bint> &aTuple)
1316- {
1317- theWaitFor = theClient->breakpoint_remove(get<0>(aTuple).second);
1318- }
1319-
1320- template<>
1321- void CommandLineHandler::handle<BreakpointList>(tuple<> &t)
1322- {
1323- theWaitFor = theClient->breakpoint_list();
1324- }
1325-
1326- template<>
1327- void CommandLineHandler::handle<StackDepth>(tuple<> &t)
1328- {
1329- theWaitFor = theClient->stack_depth();
1330- }
1331-
1332- template<>
1333- void CommandLineHandler::handle<StackGet>(tuple<bint> &aTuple)
1334- {
1335- if (get<0>(aTuple).first) {
1336- theWaitFor = theClient->stack_get(get<0>(aTuple).second);
1337- } else {
1338- theWaitFor = theClient->stack_get();
1339- }
1340- }
1341-
1342- template<>
1343- void CommandLineHandler::handle<ContextNames>(tuple<>& aTuple)
1344- {
1345- theWaitFor = theClient->context_names();
1346- }
1347-
1348- template<>
1349- void CommandLineHandler::handle<ContextGet>(tuple<bint> &aTuple)
1350- {
1351- if (get<0>(aTuple).first)
1352- theWaitFor = theClient->context_get(get<0>(aTuple).second);
1353- else
1354- theWaitFor = theClient->context_get();
1355- }
1356-
1357- template<>
1358- void CommandLineHandler::handle<Eval>(tuple<bstring>& aTuple)
1359- {
1360- theWaitFor = theClient->eval(get<0>(aTuple).second);
1361- }
1362-
1363- void CommandLineHandler::addCommands()
1364- {
1365- theCommandLine << createCommand<Status>(tuple<>(), "status", *this,
1366- "Gets the status of the server");
1367- theCommandLine << createCommand<Quit>(tuple<>(), "quit", *this,
1368- "Stops debugging and quits the client");
1369- theCommandLine << createCommand<Run>(tuple<>(), "run", *this, "Run the Query");
1370- {
1371- Command<CommandLineHandler, tuple<bstring, bstring, bint>, BreakpointSet>* lCommand =
1372- createCommand<BreakpointSet>(tuple<bstring, bstring, bint>(), "break", *this, "Set a breakpoint");
1373- (*lCommand)(0, "s", createArgType<tuple<bstring, bstring, bint>, std::string, 0>(tuple<bstring, bstring, bint>()),
1374- "breakpoint state (enabled or disabled - default: enabled)", false);
1375- (*lCommand)(1, "f", createArgType<tuple<bstring, bstring, bint>, std::string, 1>(tuple<bstring, bstring, bint>()),
1376- "The name of the file where to stop", true);
1377- (*lCommand)(2, "l", createArgType<tuple<bstring, bstring, bint>, int, 2>(tuple<bstring, bstring, bint>()),
1378- "The line number", true);
1379-
1380- theCommandLine << lCommand;
1381- }
1382- {
1383- Command<CommandLineHandler, tuple<bint>, BreakpointGet>* lCommand
1384- = createCommand<BreakpointGet>(tuple<bint>(), "binfo", *this,
1385- "Get information about a given breakpoint");
1386- (*lCommand)(0, "i", createArgType<tuple<bint>, int, 0>(tuple<bint>()),
1387- "The id of the breakpoint", true);
1388-
1389- theCommandLine << lCommand;
1390- }
1391- {
1392- Command<CommandLineHandler, tuple<bint>, BreakpointDel>* lCommand
1393- = createCommand<BreakpointDel>(tuple<bint>(), "bdel", *this, "Delete a breakpoint with a given id");
1394- (*lCommand)(0, "i", createArgType<tuple<bint>, int, 0>(tuple<bint>()), "The id of the breakpoint", true);
1395-
1396- theCommandLine << lCommand;
1397- }
1398- theCommandLine << createCommand<BreakpointList>(tuple<>(), "blist", *this, "List all set breakpoints");
1399- theCommandLine << createCommand<StackDepth>(tuple<>(), "sdepth", *this, "Get the depth of the stack");
1400- {
1401- Command<CommandLineHandler, tuple<bint>, StackGet>* lCommand
1402- = createCommand<StackGet>(tuple<bint>(), "sget", *this, "Get information about one or all stack frames");
1403- (*lCommand)(0, "d", createArgType<tuple<bint>, int, 0>(tuple<bint>()), "The stack entry two show (show all if not provided)", false);
1404- theCommandLine << lCommand;
1405- }
1406- theCommandLine << createCommand<ContextNames>(tuple<>(), "cnames", *this, "Get the names of the avilable contexts");
1407- {
1408- Command<CommandLineHandler, tuple<bint>, ContextGet>* lCommand
1409- = createCommand<ContextGet>(tuple<bint>(), "cget", *this, "Get a context");
1410-
1411- (*lCommand)(0, "c", createArgType<tuple<bint>, int, 0>(tuple<bint>()), "The id of the context", false);
1412-
1413- theCommandLine << lCommand;
1414- }
1415- {
1416- Command<CommandLineHandler, tuple<bstring>, Eval>* lCommand
1417- = createCommand<Eval>(tuple<bstring>(), "eval", *this, "Evaluate a function");
1418-
1419- (*lCommand)(0, "c", createArgType<tuple<bstring>, std::string, 0>(tuple<bstring>()), "The command to evaluate", true);
1420-
1421- theCommandLine << lCommand;
1422- }
1423- }
1424-
1425-}} // namespace zorba::debugclient
1426-
1427+ }
1428+ theWaitFor = theClient->stop();
1429+ theClient->quit();
1430+ theQuit = true;
1431+}
1432+
1433+template<>
1434+void
1435+CommandLineHandler::handle<Run>(ZORBA_TR1_NS::tuple<> &t)
1436+{
1437+ theTerminated = false;
1438+ theWaitFor = theClient->run();
1439+}
1440+
1441+template<>
1442+void
1443+CommandLineHandler::handle<BreakpointSet>(std::tr1::tuple<bstring, bstring, bint> &aTuple)
1444+{
1445+ DebuggerClient::BreakpointType lType = DebuggerClient::Line;
1446+ bool lEnabled = true;
1447+ if (get<0>(aTuple).first) {
1448+ if (get<0>(aTuple).second == "disabled") {
1449+ lEnabled = false;
1450+ }
1451+ }
1452+ theWaitFor = theClient->breakpoint_set(lType,
1453+ lEnabled,
1454+ get<1>(aTuple).second,
1455+ get<2>(aTuple).second);
1456+}
1457+
1458+template<>
1459+void
1460+CommandLineHandler::handle<BreakpointGet>(tuple<bint> &aTuple)
1461+{
1462+ theWaitFor = theClient->breakpoint_get(get<0>(aTuple).second);
1463+}
1464+
1465+template<>
1466+void
1467+CommandLineHandler::handle<BreakpointRemove>(tuple<bint> &aTuple)
1468+{
1469+ theWaitFor = theClient->breakpoint_remove(get<0>(aTuple).second);
1470+}
1471+
1472+template<>
1473+void
1474+CommandLineHandler::handle<BreakpointList>(tuple<> &aTuple)
1475+{
1476+ theWaitFor = theClient->breakpoint_list();
1477+}
1478+
1479+template<>
1480+void
1481+CommandLineHandler::handle<StackDepth>(tuple<> &aTuple)
1482+{
1483+ theWaitFor = theClient->stack_depth();
1484+}
1485+
1486+template<>
1487+void
1488+CommandLineHandler::handle<StackGet>(tuple<bint> &aTuple)
1489+{
1490+ if (get<0>(aTuple).first) {
1491+ theWaitFor = theClient->stack_get(get<0>(aTuple).second);
1492+ } else {
1493+ theWaitFor = theClient->stack_get();
1494+ }
1495+}
1496+
1497+template<>
1498+void
1499+CommandLineHandler::handle<ContextNames>(tuple<>& aTuple)
1500+{
1501+ theWaitFor = theClient->context_names();
1502+}
1503+
1504+template<>
1505+void CommandLineHandler::handle<ContextGet>(tuple<bint, bint> &aTuple)
1506+{
1507+ int lDepth = -1;
1508+ int lContext = -1;
1509+
1510+ if (get<0>(aTuple).first) {
1511+ lDepth = get<0>(aTuple).second;
1512+ }
1513+ if (get<1>(aTuple).first) {
1514+ lContext = get<1>(aTuple).second;
1515+ }
1516+ theWaitFor = theClient->context_get(lDepth, lContext);
1517+}
1518+
1519+template<>
1520+void CommandLineHandler::handle<Source>(tuple<bint, bint, bstring> &aTuple)
1521+{
1522+ theWaitFor = theClient->source(
1523+ get<2>(aTuple).second,
1524+ get<0>(aTuple).second,
1525+ get<1>(aTuple).second);
1526+}
1527+
1528+template<>
1529+void CommandLineHandler::handle<Eval>(tuple<bstring>& aTuple)
1530+{
1531+ theWaitFor = theClient->eval(get<0>(aTuple).second);
1532+}
1533+
1534+template<>
1535+void
1536+CommandLineHandler::handle<StepIn>(ZORBA_TR1_NS::tuple<> &t)
1537+{
1538+ theTerminated = false;
1539+ theWaitFor = theClient->step_into();
1540+}
1541+
1542+template<>
1543+void
1544+CommandLineHandler::handle<StepOut>(ZORBA_TR1_NS::tuple<> &t)
1545+{
1546+ theWaitFor = theClient->step_out();
1547+}
1548+
1549+template<>
1550+void
1551+CommandLineHandler::handle<StepOver>(ZORBA_TR1_NS::tuple<> &t)
1552+{
1553+ theTerminated = false;
1554+ theWaitFor = theClient->step_over();
1555+}
1556+
1557+void
1558+CommandLineHandler::addCommands()
1559+{
1560+ typedef tuple<> TUPLE;
1561+ typedef tuple<bint> TUPLE_INT;
1562+ typedef tuple<bstring> TUPLE_STR;
1563+ typedef tuple<bint, bint> TUPLE_INT_INT;
1564+ typedef tuple<bstring, bstring, bint> TUPLE_STR_STR_INT;
1565+ typedef tuple<bint, bint, bstring> TUPLE_INT_INT_STR;
1566+
1567+ // DBGP: status
1568+ theCommandLine << createCommand<Status>(TUPLE(), "status", *this, "Gets the status of the server");
1569+
1570+ // ALIAS: variables (context_get -c -1)
1571+ {
1572+ std::set<std::string> lAliases;
1573+ lAliases.insert("vars");
1574+ theCommandLine << createCommand<Variables>(TUPLE(), "variables", lAliases, *this, "Gets the variables visible in the current scope");
1575+ }
1576+
1577+ // META: quit
1578+ theCommandLine << createCommand<Quit>(TUPLE(), "quit", *this, "Stops debugging and quits the client");
1579+
1580+ // DBGP: run
1581+ theCommandLine << createCommand<Run>(TUPLE(), "run", *this, "Run the query");
1582+
1583+ // DBGP: breakpoint_set
1584+ {
1585+ std::set<std::string> lAliases;
1586+ lAliases.insert("break");
1587+ Command<CommandLineHandler, TUPLE_STR_STR_INT, BreakpointSet>* lCommand =
1588+ createCommand<BreakpointSet>(TUPLE_STR_STR_INT(), "bset", lAliases, *this, "Set a breakpoint");
1589+
1590+ lCommand->addArgument(0, "s", createArgType<TUPLE_STR_STR_INT, std::string, 0>(TUPLE_STR_STR_INT()), "breakpoint state (optional, 'enabled' or 'disabled', default: enabled)", false);
1591+ lCommand->addArgument(1, "f", createArgType<TUPLE_STR_STR_INT, std::string, 1>(TUPLE_STR_STR_INT()), "name of the file where to stop", true);
1592+ lCommand->addArgument(2, "l", createArgType<TUPLE_STR_STR_INT, int, 2>(TUPLE_STR_STR_INT()), "line number", true);
1593+
1594+ theCommandLine << lCommand;
1595+ }
1596+
1597+ // DBGP: breakpoint_get
1598+ {
1599+ Command<CommandLineHandler, TUPLE_INT, BreakpointGet>* lCommand =
1600+ createCommand<BreakpointGet>(TUPLE_INT(), "bget", *this, "Get information about a given breakpoint");
1601+
1602+ lCommand->addArgument(0, "d", createArgType<TUPLE_INT, int, 0>(TUPLE_INT()), "breakpoint ID", true);
1603+
1604+ theCommandLine << lCommand;
1605+ }
1606+
1607+ // DBGP: breakpoint_remove
1608+ {
1609+ std::set<std::string> lAliases;
1610+ lAliases.insert("clear");
1611+ lAliases.insert("delete");
1612+ Command<CommandLineHandler, TUPLE_INT, BreakpointRemove>* lCommand =
1613+ createCommand<BreakpointRemove>(TUPLE_INT(), "bremove", lAliases, *this, "Delete a breakpoint");
1614+
1615+ lCommand->addArgument(0, "d", createArgType<TUPLE_INT, int, 0>(TUPLE_INT()), "breakpoint ID", true);
1616+
1617+ theCommandLine << lCommand;
1618+ }
1619+
1620+ // DBGP: breakpoint_list
1621+ theCommandLine << createCommand<BreakpointList>(TUPLE(), "blist", *this, "List all set breakpoints");
1622+
1623+ // DBGP: stack_depth
1624+ theCommandLine << createCommand<StackDepth>(TUPLE(), "sdepth", *this, "Get the depth of the stack");
1625+
1626+ // DBGP: stack_get
1627+ {
1628+ Command<CommandLineHandler, TUPLE_INT, StackGet>* lCommand =
1629+ createCommand<StackGet>(TUPLE_INT(), "sget", *this, "Get information about one or all stack frames");
1630+
1631+ lCommand->addArgument(0, "d", createArgType<TUPLE_INT, int, 0>(TUPLE_INT()), "stack frame to show: 0 for current stack frame, N for the main module (optional, all frames are shown if not provided)", false);
1632+
1633+ theCommandLine << lCommand;
1634+ }
1635+
1636+ // DBGP: context_names
1637+ theCommandLine << createCommand<ContextNames>(tuple<>(), "cnames", *this, "Get the names of the avilable contexts");
1638+ // the DBGP -d arguments for this command is omitted since we always have/return: 0 - Local, 1 - Global
1639+
1640+ // DBGP: context_get
1641+ {
1642+ Command<CommandLineHandler, TUPLE_INT_INT, ContextGet>* lCommand =
1643+ createCommand<ContextGet>(TUPLE_INT_INT(), "cget", *this, "Get a context (list variables in this context)");
1644+
1645+ lCommand->addArgument(0, "d", createArgType<TUPLE_INT_INT, int, 0>(TUPLE_INT_INT()), "stack depth (optional, default: 0)", false);
1646+ lCommand->addArgument(0, "c", createArgType<TUPLE_INT_INT, int, 1>(TUPLE_INT_INT()), "context ID: 0 for Local, 1 for Global (optional, default: 0)", false);
1647+
1648+ theCommandLine << lCommand;
1649+ }
1650+
1651+ // DBGP: source
1652+ {
1653+ std::set<std::string> lAliases;
1654+ lAliases.insert("list");
1655+ Command<CommandLineHandler, TUPLE_INT_INT_STR, Source>* lCommand =
1656+ createCommand<Source>(TUPLE_INT_INT_STR(), "source", lAliases, *this, "List source code");
1657+
1658+ lCommand->addArgument(0, "b", createArgType<TUPLE_INT_INT_STR, int, 0>(TUPLE_INT_INT_STR()), "begin line (optional, default: first line)", false);
1659+ lCommand->addArgument(1, "e", createArgType<TUPLE_INT_INT_STR, int, 1>(TUPLE_INT_INT_STR()), "end line (optional, default: last line)", false);
1660+ lCommand->addArgument(2, "f", createArgType<TUPLE_INT_INT_STR, std::string, 2>(TUPLE_INT_INT_STR()), "file URI (optional, default: the file in the top-most stack frame during execution, main module otherwise)", false);
1661+
1662+ theCommandLine << lCommand;
1663+ }
1664+
1665+ // DBGP: eval
1666+ {
1667+ std::set<std::string> lAliases;
1668+ lAliases.insert("print");
1669+ Command<CommandLineHandler, TUPLE_STR, Eval>* lCommand =
1670+ createCommand<Eval>(TUPLE_STR(), "eval", lAliases, *this, "Evaluate an expression");
1671+
1672+ // TODO: this argument should not be here at all. Eval has the form: eval -i transaction_id -- {DATA}
1673+ // Eval should be called with a command like: eval 1 + 3
1674+ // - no need for an argument name
1675+ // - everything following the fist contiguous set of whitespaces are sent as string
1676+ lCommand->addArgument(0, "c", createArgType<TUPLE_STR, std::string, 0>(TUPLE_STR()), "expression to evaluate", true);
1677+
1678+ theCommandLine << lCommand;
1679+ }
1680+
1681+ // DBGP: step_in
1682+ {
1683+ std::set<std::string> lAliases;
1684+ lAliases.insert("step");
1685+ lAliases.insert("s");
1686+ theCommandLine << createCommand<StepIn>(TUPLE(), "in", lAliases, *this, "Step in");
1687+ }
1688+
1689+ // DBGP: step_out
1690+ {
1691+ std::set<std::string> lAliases;
1692+ lAliases.insert("finish");
1693+ theCommandLine << createCommand<StepOut>(TUPLE(), "out", lAliases, *this, "Step out");
1694+ }
1695+
1696+ // DBGP: step_over
1697+ {
1698+ std::set<std::string> lAliases;
1699+ lAliases.insert("next");
1700+ lAliases.insert("n");
1701+ theCommandLine << createCommand<StepOver>(TUPLE(), "over", lAliases, *this, "Step over");
1702+ }
1703+}
1704+
1705+} // namespace zorba
1706+} // namespace debugger
1707
1708=== modified file 'bin/debugger/command_line_handler.h'
1709--- bin/debug_client/command_line_handler.h 2011-07-01 01:53:24 +0000
1710+++ bin/debugger/command_line_handler.h 2011-12-20 18:15:30 +0000
1711@@ -14,46 +14,69 @@
1712 * limitations under the License.
1713 */
1714 #pragma once
1715+#ifndef ZORBA_DEBUGGER_COMMAND_LINE_HANDLER_H
1716+#define ZORBA_DEBUGGER_COMMAND_LINE_HANDLER_H
1717
1718 #include <set>
1719 #include <cassert>
1720+
1721 #include <zorba/debugger_client.h>
1722-#include "debug_command.h"
1723+
1724+#include "command.h"
1725+#include "command_prompt.h"
1726 #include "event_handler.h"
1727
1728-namespace zorba { namespace debugclient {
1729-
1730+
1731+namespace zorba { namespace debugger {
1732+
1733 enum Commands {
1734 Status,
1735+ Variables,
1736+ Quit,
1737 Run,
1738 BreakpointSet,
1739 BreakpointGet,
1740- BreakpointDel,
1741+ BreakpointRemove,
1742 BreakpointList,
1743 StackDepth,
1744 StackGet,
1745 ContextNames,
1746 ContextGet,
1747+ Source,
1748 Eval,
1749- Quit
1750+ StepIn,
1751+ StepOut,
1752+ StepOver
1753 };
1754
1755- class CommandLineHandler {
1756+class CommandLineHandler
1757+{
1758 private:
1759+
1760 typedef std::pair<bool, std::string> bstring;
1761 typedef std::pair<bool, int> bint;
1762+
1763 public:
1764- CommandLineHandler(unsigned short port,
1765- LockFreeConsumer<std::size_t>& aConsumer,
1766- LockFreeConsumer<bool>& aContinueQueue,
1767- EventHandler& aHandler,
1768- CommandLine& aCommandLine);
1769+
1770+ CommandLineHandler(
1771+ unsigned short port,
1772+ LockFreeConsumer<std::size_t>& aConsumer,
1773+ LockFreeConsumer<bool>& aContinueQueue,
1774+ EventHandler& aHandler,
1775+ CommandPrompt& aCommandPrompt);
1776+
1777 ~CommandLineHandler();
1778+
1779 public:
1780 void execute();
1781+
1782 public: // Handlers
1783+
1784 template<int>
1785- void handle(ZORBA_TR1_NS::tuple<>& aTuple) { assert(false); }
1786+ void handle(ZORBA_TR1_NS::tuple<>& aTuple)
1787+ {
1788+ assert(false);
1789+ }
1790
1791 template<int>
1792 void handle(ZORBA_TR1_NS::tuple<bstring, bstring, bint>& t)
1793@@ -62,63 +85,93 @@
1794 }
1795
1796 template<int>
1797+ void handle(ZORBA_TR1_NS::tuple<bint, bint, bstring>& t)
1798+ {
1799+ assert(false);
1800+ }
1801+
1802+ template<int>
1803 void handle(ZORBA_TR1_NS::tuple<bint>& aTuple)
1804 {
1805 assert(false);
1806 }
1807
1808 template<int>
1809+ void handle(ZORBA_TR1_NS::tuple<bint, bint>& aTuple)
1810+ {
1811+ assert(false);
1812+ }
1813+
1814+ template<int>
1815 void handle(ZORBA_TR1_NS::tuple<bstring>& aTuple)
1816 {
1817 assert(false);
1818 }
1819+
1820 private:
1821- LockFreeConsumer<std::size_t>& theConsumer;
1822- LockFreeConsumer<bool>& theContinueQueue;
1823- DebuggerClient* theClient;
1824- CommandLine& theCommandLine;
1825- bool theQuit;
1826- bool theContinue;
1827- std::size_t theWaitFor;
1828+ LockFreeConsumer<std::size_t>& theConsumer;
1829+ LockFreeConsumer<bool>& theContinueQueue;
1830+ DebuggerClient* theClient;
1831+ CommandPrompt& theCommandLine;
1832+ bool theQuit;
1833+ bool theTerminated;
1834+ bool theContinue;
1835+ std::size_t theWaitFor;
1836+
1837 private:
1838 void getNextId(std::set<std::size_t>& aIdList);
1839 void addCommands();
1840- };
1841-
1842- template<>
1843- void CommandLineHandler::handle<Status> (ZORBA_TR1_NS::tuple<>& t);
1844-
1845- template<>
1846- void CommandLineHandler::handle<Quit> (ZORBA_TR1_NS::tuple<>& t);
1847-
1848- template<>
1849- void CommandLineHandler::handle<Run> (ZORBA_TR1_NS::tuple<> &t);
1850-
1851- template<>
1852- void CommandLineHandler::handle<StackDepth> (ZORBA_TR1_NS::tuple<>& t);
1853-
1854- template<>
1855- void CommandLineHandler::handle<BreakpointList> (ZORBA_TR1_NS::tuple<>& aTuple);
1856-
1857- template<>
1858- void CommandLineHandler::handle<BreakpointSet> (ZORBA_TR1_NS::tuple<bstring, bstring, bint> &t);
1859-
1860- template<>
1861- void CommandLineHandler::handle<BreakpointGet> (ZORBA_TR1_NS::tuple<bint>& aTuple);
1862-
1863- template<>
1864- void CommandLineHandler::handle<BreakpointDel>(ZORBA_TR1_NS::tuple<bint> &aTuple);
1865-
1866- template<>
1867- void CommandLineHandler::handle<StackGet> (ZORBA_TR1_NS::tuple<bint>& aTuple);
1868-
1869- template<>
1870- void CommandLineHandler::handle<ContextNames>(ZORBA_TR1_NS::tuple<> &aTuple);
1871-
1872- template<>
1873- void CommandLineHandler::handle<ContextGet>(ZORBA_TR1_NS::tuple<bint> &aTuple);
1874-
1875- template<>
1876- void CommandLineHandler::handle<Eval>(ZORBA_TR1_NS::tuple<bstring>& aTuple);
1877-
1878-}} // close namespaces zorba::debugclient
1879+};
1880+
1881+template<>
1882+void CommandLineHandler::handle<Status> (ZORBA_TR1_NS::tuple<>& t);
1883+
1884+template<>
1885+void CommandLineHandler::handle<Quit> (ZORBA_TR1_NS::tuple<>& t);
1886+
1887+template<>
1888+void CommandLineHandler::handle<Run> (ZORBA_TR1_NS::tuple<> &t);
1889+
1890+template<>
1891+void CommandLineHandler::handle<StackDepth> (ZORBA_TR1_NS::tuple<>& t);
1892+
1893+template<>
1894+void CommandLineHandler::handle<BreakpointList> (ZORBA_TR1_NS::tuple<>& aTuple);
1895+
1896+template<>
1897+void CommandLineHandler::handle<BreakpointSet> (ZORBA_TR1_NS::tuple<bstring, bstring, bint> &t);
1898+
1899+template<>
1900+void CommandLineHandler::handle<BreakpointGet> (ZORBA_TR1_NS::tuple<bint>& aTuple);
1901+
1902+template<>
1903+void CommandLineHandler::handle<BreakpointRemove>(ZORBA_TR1_NS::tuple<bint> &aTuple);
1904+
1905+template<>
1906+void CommandLineHandler::handle<StackGet> (ZORBA_TR1_NS::tuple<bint>& aTuple);
1907+
1908+template<>
1909+void CommandLineHandler::handle<ContextNames>(ZORBA_TR1_NS::tuple<> &aTuple);
1910+
1911+template<>
1912+void CommandLineHandler::handle<ContextGet>(ZORBA_TR1_NS::tuple<bint, bint> &aTuple);
1913+
1914+template<>
1915+void CommandLineHandler::handle<Source>(ZORBA_TR1_NS::tuple<bint, bint, bstring> &aTuple);
1916+
1917+template<>
1918+void CommandLineHandler::handle<Eval>(ZORBA_TR1_NS::tuple<bstring>& aTuple);
1919+
1920+template<>
1921+void CommandLineHandler::handle<StepIn> (ZORBA_TR1_NS::tuple<> &t);
1922+
1923+template<>
1924+void CommandLineHandler::handle<StepOut> (ZORBA_TR1_NS::tuple<> &t);
1925+
1926+template<>
1927+void CommandLineHandler::handle<StepOver> (ZORBA_TR1_NS::tuple<> &t);
1928+
1929+} // namespace zorba
1930+} // namespace debugger
1931+
1932+#endif // ZORBA_DEBUGGER_COMMAND_LINE_HANDLER_H
1933
1934=== added file 'bin/debugger/command_prompt.cpp'
1935--- bin/debugger/command_prompt.cpp 1970-01-01 00:00:00 +0000
1936+++ bin/debugger/command_prompt.cpp 2011-12-20 18:15:30 +0000
1937@@ -0,0 +1,246 @@
1938+/*
1939+ * Copyright 2006-2008 The FLWOR Foundation.
1940+ *
1941+ * Licensed under the Apache License, Version 2.0 (the "License");
1942+ * you may not use this file except in compliance with the License.
1943+ * You may obtain a copy of the License at
1944+ *
1945+ * http://www.apache.org/licenses/LICENSE-2.0
1946+ *
1947+ * Unless required by applicable law or agreed to in writing, software
1948+ * distributed under the License is distributed on an "AS IS" BASIS,
1949+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1950+ * See the License for the specific language governing permissions and
1951+ * limitations under the License.
1952+ */
1953+#include "command_prompt.h"
1954+
1955+#include <string>
1956+#include <vector>
1957+#include <map>
1958+#include <iostream>
1959+
1960+#include "config.h"
1961+
1962+#ifdef ZORBA_HAVE_READLINE_H
1963+# include <editline/readline.h>
1964+#endif
1965+
1966+#include "command.h"
1967+
1968+
1969+namespace zorba { namespace debugger {
1970+
1971+CommandPrompt::~CommandPrompt()
1972+{
1973+ std::map<std::string, UntypedCommand*>::iterator lIter;
1974+ for (lIter = theCommands.begin(); lIter != theCommands.end(); ++lIter) {
1975+ delete lIter->second;
1976+ }
1977+}
1978+
1979+void
1980+CommandPrompt::printHelp(UntypedCommand* aCommand)
1981+{
1982+ // if no command is provided, print all the available commands
1983+ if (!aCommand) {
1984+ std::cout << "Available commands:" << std::endl;
1985+
1986+ // print the names of all commands
1987+ std::map<std::string, UntypedCommand*>::iterator lIter = theCommands.begin();
1988+ while (lIter != theCommands.end()) {
1989+ std::cout << " " << (*lIter).first;
1990+ std::set<std::string> lAliases = (*lIter).second->getAliases();
1991+ std::set<std::string>::const_iterator lAliasIter = lAliases.begin();
1992+ while (lAliasIter != lAliases.end()) {
1993+ std::cout << ", " << *lAliasIter;
1994+ lAliasIter++;
1995+ }
1996+ std::cout << std::endl;
1997+ lIter++;
1998+ }
1999+
2000+ // some hints for detailed help
2001+ std::cout << std::endl;
2002+ std::cout << "Type help <command> to get more information about one command." << std::endl;
2003+ std::cout << std::endl;
2004+ } else {
2005+ // ok, so we have a command; then print the help
2006+ aCommand->printHelp();
2007+ }
2008+}
2009+
2010+void
2011+CommandPrompt::execute()
2012+{
2013+ for (;;) {
2014+#ifdef ZORBA_HAVE_READLINE_H
2015+ std::string lCommandLine(readline("(xqdb) "));
2016+#else
2017+ std::cout << "(xqdb) ";
2018+ std::string lCommandLine;
2019+ std::getline(std::cin, lCommandLine);
2020+#endif
2021+ std::vector<std::string> lArgs;
2022+
2023+ // split the command into arguments
2024+ parseLine(lCommandLine, lArgs);
2025+ std::string::size_type lSize = lArgs.size();
2026+
2027+ // empty command? do nothing!
2028+ if (lSize == 0) {
2029+ lArgs = theLastArgs;
2030+ if (lArgs.size() == 0) {
2031+ continue;
2032+ }
2033+ }
2034+ theLastArgs = lArgs;
2035+
2036+ UntypedCommand* lCommand = NULL;
2037+
2038+ // help is not a command but a hook here
2039+ if (lArgs.at(0) == "h" || lArgs.at(0) == "help") {
2040+ std::string lCmd = "";
2041+
2042+ // if the user needs the help for a specific command
2043+ if (lSize > 1) {
2044+ // do nothing if we don't have a command starting with this prefix?
2045+ // findCommand will print the appropriate errors
2046+ if (!findCommand(lArgs[1], lCommand)) {
2047+ continue;
2048+ }
2049+ }
2050+ printHelp(lCommand);
2051+ continue;
2052+ }
2053+ if (findCommand(lArgs[0], lCommand) && lCommand->execute(lArgs)) {
2054+ return;
2055+ }
2056+ continue;
2057+ }
2058+}
2059+
2060+CommandPrompt&
2061+CommandPrompt::operator<<(UntypedCommand *aCommand)
2062+{
2063+ theCommands.insert(std::make_pair(aCommand->getName(), aCommand));
2064+ return *this;
2065+}
2066+
2067+bool
2068+CommandPrompt::findCommand(const std::string& aPrefix, UntypedCommand*& aCommand)
2069+{
2070+ std::vector<UntypedCommand*> lFoundCommands;
2071+
2072+ std::map<std::string, UntypedCommand*>::iterator lIter = theCommands.begin();
2073+ while (lIter != theCommands.end()) {
2074+ // if a command name is equal with the prefix, this is the command we want
2075+ if ((*lIter).first == aPrefix) {
2076+ aCommand = (*lIter).second;
2077+ return true;
2078+ }
2079+
2080+ bool lIsCandidate = false;
2081+
2082+ // add this command to candidate commands if the prefix matches
2083+ if ((*lIter).first.find(aPrefix) == 0) {
2084+ lFoundCommands.push_back((*lIter).second);
2085+ lIsCandidate = true;
2086+ }
2087+
2088+ // now process the aliases
2089+ std::set<std::string> lAliases = (*lIter).second->getAliases();
2090+ std::set<std::string>::const_iterator lAliasIter = lAliases.begin();
2091+ while (lAliasIter != lAliases.end()) {
2092+ // if a command alias is equal with the prefix, this is the command we want
2093+ if (*lAliasIter == aPrefix) {
2094+ aCommand = (*lIter).second;
2095+ return true;
2096+ }
2097+
2098+ // add this command to candidate commands if the prefix matches one alias
2099+ // and if the command is not already added
2100+ if (!lIsCandidate && (*lAliasIter).find(aPrefix) == 0) {
2101+ lFoundCommands.push_back((*lIter).second);
2102+ break;
2103+ }
2104+ lAliasIter++;
2105+ }
2106+
2107+ lIter++;
2108+ }
2109+
2110+ if (lFoundCommands.empty()) {
2111+ std::cout << "Command not found: " << aPrefix << std::endl;
2112+ return false;
2113+ }
2114+
2115+ if (lFoundCommands.size() > 1) {
2116+ std::cout << "Ambigous command: " << aPrefix << std::endl;
2117+ // show all possible commands that start with this prefix
2118+ for (std::string::size_type i = 0; i < lFoundCommands.size(); i++) {
2119+ UntypedCommand* lCommand = lFoundCommands.at(i);
2120+
2121+ // commands
2122+ if (lCommand->getName().find(aPrefix) == 0) {
2123+ std::cout << " " << lCommand->getName() << std::endl;
2124+ }
2125+
2126+ // and aliases
2127+ std::set<std::string> lAliases = lCommand->getAliases();
2128+ std::set<std::string>::const_iterator lAliasIter = lAliases.begin();
2129+ while (lAliasIter != lAliases.end()) {
2130+ if ((*lAliasIter).find(aPrefix) == 0) {
2131+ std::cout << " " << *lAliasIter << std::endl;
2132+ }
2133+ lAliasIter++;
2134+ }
2135+ }
2136+ return false;
2137+ }
2138+
2139+ aCommand = lFoundCommands[0];
2140+ return true;
2141+}
2142+
2143+void
2144+CommandPrompt::parseLine(const std::string& aLine, std::vector<std::string>& aVector)
2145+{
2146+ std::string::size_type lBefore = 0;
2147+ std::string::size_type lPos = aLine.find_first_of(" \t", 0);
2148+
2149+ while (lPos != aLine.npos) {
2150+ std::string lSub = aLine.substr(lBefore, lPos - lBefore);
2151+
2152+ // if two consecutive spaces, you get an empty string here
2153+ if (lSub != "") {
2154+ if (lSub[0] == '"') {
2155+ std::string::size_type lBeforeCopy = lBefore;
2156+ do {
2157+ lBeforeCopy = aLine.find("\"", lBeforeCopy + 1);
2158+ } while (lPos != aLine.npos && aLine.size() > lPos + 1 && aLine[lPos + 1] == '\\');
2159+ lPos = lBeforeCopy;
2160+ lSub = aLine.substr(lBefore + 1, lPos - lBefore - 1);
2161+ }
2162+ aVector.push_back(lSub);
2163+ }
2164+
2165+ lBefore = lPos + 1;
2166+ lPos = aLine.find_first_of(" \t", lBefore);
2167+ }
2168+ std::string lSub = aLine.substr(lBefore);
2169+
2170+ // catching the case when the command ends with a space
2171+ if (lSub == "") {
2172+ return;
2173+ }
2174+
2175+ if (lSub[0] == '"') {
2176+ lPos = aLine.find("\"", lBefore + 1);
2177+ lSub = aLine.substr(lBefore + 1, lPos - lBefore - 1);
2178+ }
2179+ aVector.push_back(lSub);
2180+}
2181+
2182+} // namespace zorba
2183+} // namespace debugger
2184
2185=== added file 'bin/debugger/command_prompt.h'
2186--- bin/debugger/command_prompt.h 1970-01-01 00:00:00 +0000
2187+++ bin/debugger/command_prompt.h 2011-12-20 18:15:30 +0000
2188@@ -0,0 +1,60 @@
2189+/*
2190+ * Copyright 2006-2008 The FLWOR Foundation.
2191+ *
2192+ * Licensed under the Apache License, Version 2.0 (the "License");
2193+ * you may not use this file except in compliance with the License.
2194+ * You may obtain a copy of the License at
2195+ *
2196+ * http://www.apache.org/licenses/LICENSE-2.0
2197+ *
2198+ * Unless required by applicable law or agreed to in writing, software
2199+ * distributed under the License is distributed on an "AS IS" BASIS,
2200+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2201+ * See the License for the specific language governing permissions and
2202+ * limitations under the License.
2203+ */
2204+#pragma once
2205+#ifndef ZORBA_DEBUGGER_COMMAND_PROMPT_H
2206+#define ZORBA_DEBUGGER_COMMAND_PROMPT_H
2207+
2208+#include <string>
2209+#include <map>
2210+#include <vector>
2211+
2212+
2213+namespace zorba { namespace debugger {
2214+
2215+class UntypedCommand;
2216+
2217+class CommandPrompt
2218+{
2219+ public:
2220+ ~CommandPrompt();
2221+
2222+ public:
2223+
2224+ void execute();
2225+
2226+ CommandPrompt& operator<< (UntypedCommand* command);
2227+
2228+ private:
2229+
2230+ void
2231+ printHelp(UntypedCommand* command);
2232+
2233+ bool
2234+ findCommand(const std::string& prefix, UntypedCommand*& command);
2235+
2236+ void
2237+ parseLine(const std::string& line, std::vector<std::string>& vector);
2238+
2239+ private:
2240+ std::map<std::string, UntypedCommand*> theCommands;
2241+ std::vector<std::string> theLastArgs;
2242+};
2243+
2244+
2245+} // namespace zorba
2246+} // namespace debugger
2247+
2248+#endif // ZORBA_DEBUGGER_COMMAND_PROMPT_H
2249
2250=== added file 'bin/debugger/config.h.cmake'
2251--- bin/debugger/config.h.cmake 1970-01-01 00:00:00 +0000
2252+++ bin/debugger/config.h.cmake 2011-12-20 18:15:30 +0000
2253@@ -0,0 +1,24 @@
2254+/*
2255+ * Copyright 2006-2008 The FLWOR Foundation.
2256+ *
2257+ * Licensed under the Apache License, Version 2.0 (the "License");
2258+ * you may not use this file except in compliance with the License.
2259+ * You may obtain a copy of the License at
2260+ *
2261+ * http://www.apache.org/licenses/LICENSE-2.0
2262+ *
2263+ * Unless required by applicable law or agreed to in writing, software
2264+ * distributed under the License is distributed on an "AS IS" BASIS,
2265+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2266+ * See the License for the specific language governing permissions and
2267+ * limitations under the License.
2268+ */
2269+
2270+// This header is configured by Zorba's build process -- DO NOT EDIT!
2271+
2272+#ifndef ZORBA_DEBUGGER_CONFIG_H
2273+#define ZORBA_DEBUGGER_CONFIG_H
2274+
2275+#cmakedefine ZORBA_HAVE_READLINE_H
2276+
2277+#endif /* ZORBA_DEBUGGER_CONFIG_H */
2278
2279=== modified file 'bin/debugger/event_handler.cpp'
2280--- bin/debug_client/event_handler.cpp 2011-07-01 01:53:24 +0000
2281+++ bin/debugger/event_handler.cpp 2011-12-20 18:15:30 +0000
2282@@ -13,88 +13,94 @@
2283 * See the License for the specific language governing permissions and
2284 * limitations under the License.
2285 */
2286+
2287+#include "event_handler.h"
2288+
2289+#include <sstream>
2290+
2291 #include <zorba/zorba.h>
2292 #include <zorba/store_manager.h>
2293 #include <zorba/iterator.h>
2294-#include <sstream>
2295-#include "debug_client/event_handler.h"
2296
2297-namespace zorba { namespace debugclient {
2298+namespace zorba { namespace debugger {
2299
2300- EventHandler::EventHandler(LockFreeProducer<std::size_t>& aQueue, LockFreeProducer<bool>& aContProducer)
2301+EventHandler::EventHandler(LockFreeProducer<std::size_t>& aQueue, LockFreeProducer<bool>& aContProducer)
2302 : theIdQueue(aQueue), theContinueProducer(aContProducer),
2303 theStore(StoreManager::getStore()),
2304 theZorbaInstance(Zorba::getInstance(theStore)),
2305 theStaticContext(theZorbaInstance->createStaticContext())
2306-
2307- {
2308- try {
2309- Zorba_CompilerHints_t lHints;
2310- lHints.opt_level = ZORBA_OPT_LEVEL_O1;
2311- std::auto_ptr<std::istream> stream(getCurrentDirectory());
2312- zorba::String query;
2313- char buffer[1024];
2314- std::string::size_type s;
2315- while ((s = stream->readsome(buffer, 1024))) {
2316- query.append(std::string(buffer, s));
2317- }
2318- theStaticContext->loadProlog(query, lHints);
2319- } catch (zorba::ZorbaException& e) {
2320- std::cerr << "Exception: I was not able to load the query file:" << std::endl;
2321- std::cerr << e.what() << std::endl;
2322- throw;
2323- }
2324- }
2325-
2326- EventHandler::~EventHandler()
2327- {
2328- theStaticContext = 0;
2329- theZorbaInstance->shutdown();
2330- StoreManager::shutdownStore(theStore);
2331- }
2332-
2333- void EventHandler::parseMessage(const std::string &aMessage)
2334- {
2335- try {
2336- zorba::String queryString = "local:main(";
2337- queryString += aMessage + ")";
2338- XQuery_t query = theZorbaInstance->compileQuery(queryString, theStaticContext);
2339- Iterator_t lIter = query->iterator();
2340- Item item;
2341- lIter->open();
2342- bool doContinue = false;
2343- lIter->next(item);
2344- {
2345- const std::string& continueString = item.getStringValue().str();
2346- if (continueString == "true") {
2347- doContinue = true;
2348- } else if (continueString == "false") {
2349- doContinue = false;
2350- } else {
2351- std::stringstream stream(continueString);
2352- stream >> doContinue;
2353- }
2354- }
2355- lIter->next(item);
2356- std::size_t lId;
2357- {
2358- std::stringstream stream(item.getStringValue().c_str());
2359- stream >> lId;
2360- }
2361- lIter->next(item);
2362- std::cout << item.getStringValue() << std::endl;
2363- theContinueProducer.produce(doContinue);
2364- theIdQueue.produce(lId);
2365- } catch (ZorbaException& e) {
2366- std::cerr << "FATAL: could not execute query: " << std::endl;
2367- std::cerr << e << std::endl;
2368- std::cerr << "This is a bug, please report to zorba-users@lists.sourceforge.net" << std::endl;
2369- theContinueProducer.produce(false);
2370- }
2371- }
2372-
2373- void EventHandler::error(unsigned int errcode, const std::string &msg)
2374- {
2375- std::cerr << "Error " << errcode << ": " << msg << std::endl;
2376- }
2377-}}
2378+{
2379+}
2380+
2381+EventHandler::~EventHandler()
2382+{
2383+ theStaticContext = 0;
2384+ theZorbaInstance->shutdown();
2385+ StoreManager::shutdownStore(theStore);
2386+}
2387+
2388+void
2389+EventHandler::init()
2390+{
2391+ try {
2392+ Zorba_CompilerHints_t lHints;
2393+ lHints.opt_level = ZORBA_OPT_LEVEL_O1;
2394+ zorba::String lProlog("import module namespace dmh = 'http://www.zorba-xquery.com/modules/debugger/dbgp-message-handler';");
2395+ theStaticContext->loadProlog(lProlog, lHints);
2396+ } catch (zorba::ZorbaException& e) {
2397+ std::cerr << "Exception: I was not able to load the query file:" << std::endl;
2398+ std::cerr << e.what() << std::endl;
2399+ throw;
2400+ }
2401+}
2402+
2403+void
2404+EventHandler::parseMessage(const std::string &aMessage)
2405+{
2406+ try {
2407+#ifndef NDEBUG
2408+ // uncomment this to see the raw messages received by the event handler
2409+ //std::cout << "Processing response: " << aMessage << std::endl;
2410+#endif
2411+ // the query to process the response
2412+ std::stringstream lQueryStream;
2413+ lQueryStream << "dmh:process(" << aMessage << ")";
2414+ XQuery_t lQuery = theZorbaInstance->compileQuery(lQueryStream.str(), theStaticContext);
2415+
2416+ // get the query result sequrence:
2417+ // 1. a message
2418+ Iterator_t lIter = lQuery->iterator();
2419+ Item lItem;
2420+ lIter->open();
2421+ lIter->next(lItem);
2422+ std::size_t lId;
2423+ std::stringstream lStream(lItem.getStringValue().c_str());
2424+ lStream >> lId;
2425+
2426+ // 2. an "idle" flag (to disable quit confirmation)
2427+ bool lCanQuit = false;
2428+ if (lIter->next(lItem)) {
2429+ String lMessage = lItem.getStringValue();
2430+ lCanQuit = lMessage == "idle";
2431+ std::cout << std::endl << lItem.getStringValue() << std::endl;
2432+ }
2433+ theContinueProducer.produce(lCanQuit);
2434+
2435+ // go and solve the event with this id
2436+ theIdQueue.produce(lId);
2437+ } catch (ZorbaException& e) {
2438+ std::cerr << "FATAL: could not execute query: " << std::endl;
2439+ std::cerr << e << std::endl;
2440+ std::cerr << "This is a bug, please report to zorba-users@lists.sourceforge.net" << std::endl;
2441+ //theContinueProducer.produce(false);
2442+ }
2443+}
2444+
2445+void
2446+EventHandler::error(unsigned int errcode, const std::string &msg)
2447+{
2448+ std::cerr << "Error " << errcode << ": " << msg << std::endl;
2449+}
2450+
2451+} // namespace zorba
2452+} // namespace debugger
2453
2454=== modified file 'bin/debugger/event_handler.h'
2455--- bin/debug_client/event_handler.h 2011-07-01 01:53:24 +0000
2456+++ bin/debugger/event_handler.h 2011-12-20 18:15:30 +0000
2457@@ -14,33 +14,46 @@
2458 * limitations under the License.
2459 */
2460 #pragma once
2461+#ifndef ZORBA_DEBUGGER_EVENT_HANDLER_H
2462+#define ZORBA_DEBUGGER_EVENT_HANDLER_H
2463+
2464 #include <string>
2465 #include <iostream>
2466+
2467 #include <zorba/debugger_event_handler.h>
2468 #include <zorba/static_context.h>
2469+
2470 #include "lock_free_queue.h"
2471
2472-namespace zorba {
2473- class Zorba;
2474-}
2475-
2476-namespace zorba { namespace debugclient {
2477-
2478- class EventHandler : public zorba::DebuggerEventHandler
2479- {
2480+
2481+namespace zorba { namespace debugger {
2482+
2483+class EventHandler : public zorba::DebuggerEventHandler
2484+{
2485 public:
2486- EventHandler(LockFreeProducer<std::size_t>& aQueue, LockFreeProducer<bool>& aContQueue);
2487+ EventHandler(
2488+ LockFreeProducer<std::size_t>& aQueue,
2489+ LockFreeProducer<bool>& aContQueue);
2490+
2491 ~EventHandler();
2492+
2493 public:
2494 virtual void parseMessage(const std::string& aMessage);
2495+
2496 virtual void error(unsigned int errcode, const std::string& msg);
2497+
2498+ virtual void init();
2499+
2500 private:
2501- static std::istream* getCurrentDirectory();
2502 LockFreeProducer<std::size_t>& theIdQueue;
2503 LockFreeProducer<bool>& theContinueProducer;
2504 void* theStore;
2505 Zorba* theZorbaInstance;
2506 StaticContext_t theStaticContext;
2507- };
2508+
2509+};
2510
2511-}} // end of namespace zorba::debugclient
2512+} // namespace zorba
2513+} // namespace debugger
2514+
2515+#endif // ZORBA_DEBUGGER_EVENT_HANDLER_H
2516
2517=== modified file 'bin/debugger/lock_free_queue.h'
2518--- bin/debug_client/lock_free_queue.h 2011-07-01 01:53:24 +0000
2519+++ bin/debugger/lock_free_queue.h 2011-12-20 18:15:30 +0000
2520@@ -14,10 +14,14 @@
2521 * limitations under the License.
2522 */
2523 #pragma once
2524+#ifndef ZORBA_DEBUGGER_LOCK_FREE_QUEUE_H
2525+#define ZORBA_DEBUGGER_LOCK_FREE_QUEUE_H
2526+
2527 #include <iostream>
2528 #include <list>
2529
2530-namespace zorba { namespace debugclient {
2531+
2532+namespace zorba { namespace debugger {
2533
2534 template<typename T>
2535 class LockFreeProducer
2536@@ -80,4 +84,8 @@
2537 }
2538 return false;
2539 }
2540-}} // namespace zorba::debugclient
2541+
2542+} // namespace zorba
2543+} // namespace debugger
2544+
2545+#endif // ZORBA_DEBUGGER_LOCK_FREE_QUEUE_H
2546
2547=== modified file 'bin/debugger/main.cpp'
2548--- bin/debug_client/main.cpp 2011-07-01 01:53:24 +0000
2549+++ bin/debugger/main.cpp 2011-12-20 18:15:30 +0000
2550@@ -13,12 +13,244 @@
2551 * See the License for the specific language governing permissions and
2552 * limitations under the License.
2553 */
2554+
2555+#ifdef WIN32
2556+# include <windows.h>
2557+# include <string.h>
2558+# include <strsafe.h>
2559+#endif
2560+
2561+#include <vector>
2562+
2563 #include <zorba/config.h>
2564-#include "debug_command.h"
2565+
2566+#include "command_prompt.h"
2567 #include "command_line_handler.h"
2568
2569 using namespace zorba;
2570-using namespace zorba::debugclient;
2571+using namespace zorba::debugger;
2572+
2573+int
2574+startZorba(std::string& aExec, std::vector<std::string>& aArgs)
2575+{
2576+#ifdef WIN32
2577+ // **************************
2578+ // start a process on Windows
2579+
2580+ DWORD iReturnVal = 0;
2581+ DWORD dwExitCode = 0;
2582+
2583+ std::wstring lExec;
2584+ std::wstring lArgs;
2585+
2586+ lExec.assign(aExec.begin(), aExec.end());
2587+
2588+ // the executable must be the first in the list of arguments
2589+ lArgs.append(L"\"");
2590+ lArgs.append(lExec);
2591+ lArgs.append(L"\"");
2592+
2593+ for (std::vector<std::string>::size_type j = 0; j < aArgs.size(); j++) {
2594+ std::string lArg(aArgs.at(j));
2595+ std::wstring lArgW;
2596+ lArgW.assign(lArg.begin(), lArg.end());
2597+ lArgs.append(L" ");
2598+ lArgs.append(lArgW);
2599+ }
2600+
2601+ // CreateProcessW can modify Parameters thus we allocate needed memory
2602+ wchar_t * pwszParam = new wchar_t[lArgs.size() + 1];
2603+ if (pwszParam == 0) {
2604+ return 1;
2605+ }
2606+ const wchar_t* pchrTemp = lArgs.c_str();
2607+ wcscpy_s(pwszParam, lArgs.size() + 1, pchrTemp);
2608+
2609+ // CreateProcess API initialization
2610+ STARTUPINFOW siStartupInfo;
2611+ PROCESS_INFORMATION piProcessInfo;
2612+ memset(&siStartupInfo, 0, sizeof(siStartupInfo));
2613+ memset(&piProcessInfo, 0, sizeof(piProcessInfo));
2614+ siStartupInfo.cb = sizeof(siStartupInfo);
2615+
2616+ BOOL lResult = CreateProcessW(
2617+ const_cast<LPCWSTR>(lExec.c_str()),
2618+ pwszParam, 0, 0, false,
2619+ CREATE_DEFAULT_ERROR_MODE, 0, 0,
2620+ &siStartupInfo, &piProcessInfo);
2621+
2622+ if (lResult) {
2623+ // Watch the process
2624+ dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, 0);
2625+ }
2626+ else {
2627+ // CreateProcess failed
2628+ iReturnVal = GetLastError();
2629+ LPVOID lpMsgBuf;
2630+ LPVOID lpDisplayBuf;
2631+
2632+ FormatMessage(
2633+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
2634+ NULL,
2635+ iReturnVal,
2636+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2637+ (LPTSTR) &lpMsgBuf,
2638+ 0, NULL);
2639+
2640+ // Display the error message and exit the process
2641+
2642+ lpDisplayBuf = (LPVOID)LocalAlloc(
2643+ LMEM_ZEROINIT,
2644+ (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR));
2645+
2646+ StringCchPrintf(
2647+ (LPTSTR)lpDisplayBuf,
2648+ LocalSize(lpDisplayBuf) / sizeof(TCHAR),
2649+ TEXT("Error (%d) when starting zorba: %s"),
2650+ iReturnVal,
2651+ lpMsgBuf);
2652+
2653+ std::wstring lErrorW((wchar_t*)lpDisplayBuf);
2654+ std::string lError;
2655+ lError.assign(lErrorW.begin(), lErrorW.end());
2656+ std::cout << lError << std::endl;
2657+
2658+ LocalFree(lpMsgBuf);
2659+ LocalFree(lpDisplayBuf);
2660+ }
2661+
2662+ // Free memory
2663+ delete[]pwszParam;
2664+ pwszParam = 0;
2665+
2666+ // Release handles
2667+ CloseHandle(piProcessInfo.hProcess);
2668+ CloseHandle(piProcessInfo.hThread);
2669+
2670+ return iReturnVal;
2671+
2672+#else
2673+ // ************************
2674+ // start a process on Linux
2675+
2676+ pid_t pID = fork();
2677+ if (pID == 0) {
2678+ // Code only executed by child process
2679+ std::stringstream lCommand;
2680+ lCommand << aExec;
2681+ for (std::vector<std::string>::size_type j = 0; j < aArgs.size(); j++) {
2682+ lCommand << " " << aArgs.at(j);
2683+ }
2684+
2685+ int lRes = system(lCommand.str().c_str());
2686+ exit(lRes);
2687+ }
2688+ else {
2689+ // Code only executed by parent process
2690+ if (pID < 0) {
2691+ std::cerr << "Failed to fork Zorba" << std::endl;
2692+ return pID;
2693+ } else {
2694+ return 0;
2695+ }
2696+ }
2697+#endif
2698+}
2699+
2700+void printUsage(std::string& aProgram)
2701+{
2702+ std::cerr << "Usage:" << std::endl
2703+ << " " << aProgram << " <zorba_arguments>" << std::endl
2704+ << " this will start a debugger command line and a zorba process with the given arguments" << std::endl;
2705+}
2706+
2707+bool
2708+processArguments(
2709+ int argc,
2710+ char* argv[],
2711+ std::string& aProgram,
2712+ bool& aStandalone,
2713+ std::string& aZorba,
2714+ unsigned int& aPort,
2715+ std::vector<std::string>& aZorbaArgs)
2716+{
2717+ aPort = 28028;
2718+
2719+ // find the path to Zorba and this executable name
2720+ aProgram = argv[0];
2721+
2722+#ifdef WIN32
2723+ char lSep = '\\';
2724+#else
2725+ char lSep = '/';
2726+#endif
2727+ std::string::size_type lPos = aProgram.find_last_of(lSep);
2728+
2729+ std::stringstream lZs;
2730+
2731+ if (lPos == aProgram.npos) {
2732+ lZs << "." << lSep;
2733+ } else {
2734+ lZs << aProgram.substr(0, lPos + 1);
2735+ aProgram = aProgram.substr(lPos + 1);
2736+ }
2737+ lZs << "zorba";
2738+#ifdef WIN32
2739+ lZs << ".exe";
2740+#endif
2741+ aZorba = lZs.str();
2742+
2743+
2744+ bool lHasFileArg = false;
2745+ bool lHasQueryArg = false;
2746+ bool lHasQueryVal = false;
2747+
2748+ // find if the user asked for help or specified a specific port
2749+ for (int i = 1; i < argc; i++) {
2750+ std::string lArg = argv[i];
2751+ if (lArg == "-h" || lArg == "--help") {
2752+ return false;
2753+ }
2754+ else if (lArg == "-p" || lArg == "--debug-port") {
2755+ // if there is one more argument
2756+ if (i < argc - 1) {
2757+ // get the port value
2758+ int lPort;
2759+ std::stringstream lStream(argv[i + 1]);
2760+ lStream >> lPort;
2761+ if (!lStream.fail()) {
2762+ aPort = lPort;
2763+ }
2764+ }
2765+ }
2766+ else if (lArg == "-f") {
2767+ lHasFileArg = true;
2768+ }
2769+ else if (lArg == "-q") {
2770+ lHasQueryArg = true;
2771+ if (++i < argc) {
2772+ lHasQueryVal = true;
2773+ }
2774+ }
2775+ }
2776+
2777+ if (!lHasFileArg || !lHasQueryArg || !lHasQueryVal) {
2778+ std::cout << "Not enough arguments to start Zorba." << std::endl;
2779+ std::cout << "Running the standalone XQuery debugger client on port: " << aPort << std::endl;
2780+ return true;
2781+ }
2782+
2783+ // zorba will need the -d flag
2784+ aZorbaArgs.push_back("-d");
2785+
2786+ // gather all arguments (excepting the program name)
2787+ for (int i = 1; i < argc; i++) {
2788+ aZorbaArgs.push_back(argv[i]);
2789+ }
2790+
2791+ aStandalone = false;
2792+ return true;
2793+}
2794
2795 #ifndef _WIN32_WCE
2796 int
2797@@ -28,24 +260,68 @@
2798 _tmain(int argc, _TCHAR* argv[])
2799 #endif
2800 {
2801- int port = 28028;
2802- if (argv[1]) {
2803- std::stringstream stream(argv[1]);
2804- stream >> port;
2805- if (stream.fail() || argv[2]) {
2806- std::cerr << "Unknown argument. USAGE: " << argv[0] << " [PORT]" << std::endl;
2807- return 2;
2808+ // **************************************************************************
2809+ // processing arguments
2810+
2811+ std::string lProgram, lZorbaExec;
2812+ unsigned int lPort = 28028;
2813+ std::vector<std::string> lZorbaArgs;
2814+
2815+ bool lStandalone = true;
2816+ if (!processArguments(argc, argv, lProgram, lStandalone, lZorbaExec, lPort, lZorbaArgs)) {
2817+ printUsage(lProgram);
2818+ return 1;
2819+ }
2820+
2821+#ifndef NDEBUG
2822+ // **************************************************************************
2823+ // debug reporting
2824+
2825+ if (!lStandalone) {
2826+ std::cout << "Communication port: " << lPort << std::endl;
2827+ std::cout << "Zorba executable: " << lZorbaExec << std::endl;
2828+ std::cout << "Zorba arguments: ";
2829+ for (std::vector<std::string>::size_type j = 0; j < lZorbaArgs.size(); j++) {
2830+ std::cout << lZorbaArgs.at(j) << " ";
2831 }
2832+ std::cout << std::endl;
2833 }
2834+#endif
2835+
2836 try {
2837+ // **************************************************************************
2838+ // start a zorba
2839+
2840+ if (!lStandalone) {
2841+ int lResult = startZorba(lZorbaExec, lZorbaArgs);
2842+ if (lResult) {
2843+ return lResult;
2844+ }
2845+ } else {
2846+ std::cout << "Waiting for an incomming Zorba connection..." << std::endl;
2847+ }
2848+
2849+ // **************************************************************************
2850+ // start the debugger command line
2851+
2852 LockFreeQueue<std::size_t> lQueue;
2853 LockFreeQueue<bool> lContEvent;
2854- EventHandler lHandler(lQueue, lContEvent);
2855- CommandLine cli;
2856- CommandLineHandler handler(port, lQueue, lContEvent, lHandler, cli);
2857- handler.execute();
2858+ EventHandler lEventHandler(lQueue, lContEvent);
2859+ lEventHandler.init();
2860+
2861+ CommandPrompt lCommandPrompt;
2862+ CommandLineHandler lCommandLineHandler(lPort, lQueue, lContEvent, lEventHandler, lCommandPrompt);
2863+
2864+ lCommandLineHandler.execute();
2865+
2866+#ifndef WIN32
2867+ wait();
2868+#endif
2869+
2870 } catch (...) {
2871- return 4;
2872+ return -1;
2873 }
2874+
2875 return 0;
2876 }
2877+
2878
2879=== modified file 'bin/debugger/tuple.h'
2880--- bin/debug_client/tuple.h 2011-07-04 08:05:46 +0000
2881+++ bin/debugger/tuple.h 2011-12-20 18:15:30 +0000
2882@@ -14,9 +14,15 @@
2883 * limitations under the License.
2884 */
2885 #pragma once
2886+#ifndef ZORBA_DEBUGGER_TUPLE_H
2887+#define ZORBA_DEBUGGER_TUPLE_H
2888+
2889 #include <zorba/config.h>
2890+
2891 #if ZORBA_TR1_IN_TR1_SUBDIRECTORY
2892 # include <tr1/tuple>
2893 #else
2894 # include <tuple>
2895 #endif
2896+
2897+#endif // ZORBA_DEBUGGER_TUPLE_H
2898
2899=== modified file 'bin/zorbacmd.cpp'
2900--- bin/zorbacmd.cpp 2011-11-08 03:11:02 +0000
2901+++ bin/zorbacmd.cpp 2011-12-20 18:15:30 +0000
2902@@ -925,17 +925,15 @@
2903 lHost = "127.0.0.1";
2904 }
2905
2906- if (lProperties.debug()) {
2907- Zorba_SerializerOptions lSerOptions =
2908- Zorba_SerializerOptions::SerializerOptionsFromStringParams(
2909- lProperties.getSerializerParameters());
2910- createSerializerOptions(lSerOptions, lProperties);
2911+ Zorba_SerializerOptions lSerOptions =
2912+ Zorba_SerializerOptions::SerializerOptionsFromStringParams(
2913+ lProperties.getSerializerParameters());
2914+ createSerializerOptions(lSerOptions, lProperties);
2915
2916- if (!lProperties.hasNoLogo() && !lProperties.debug()) {
2917- std::cout << "Zorba XQuery Debugger Server\n" << copyright_str << std::endl;
2918- }
2919- lQuery->debug(*lOutputStream, lSerOptions, lHost, lProperties.getDebugPort());
2920+ if (!lProperties.hasNoLogo()) {
2921+ std::cout << "Zorba XQuery Debugger Server\n" << copyright_str << std::endl;
2922 }
2923+ lQuery->debug(*lOutputStream, lSerOptions, lHost, lProperties.getDebugPort());
2924 }
2925 catch (zorba::XQueryException const& qe)
2926 {
2927
2928=== added file 'cmake_modules/FindLibedit.cmake'
2929--- cmake_modules/FindLibedit.cmake 1970-01-01 00:00:00 +0000
2930+++ cmake_modules/FindLibedit.cmake 2011-12-20 18:15:30 +0000
2931@@ -0,0 +1,46 @@
2932+# Copyright 2011 The FLWOR Foundation.
2933+#
2934+# Licensed under the Apache License, Version 2.0 (the "License");
2935+# you may not use this file except in compliance with the License.
2936+# You may obtain a copy of the License at
2937+#
2938+# http://www.apache.org/licenses/LICENSE-2.0
2939+#
2940+# Unless required by applicable law or agreed to in writing, software
2941+# distributed under the License is distributed on an "AS IS" BASIS,
2942+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2943+# See the License for the specific language governing permissions and
2944+# limitations under the License.
2945+#
2946+# - Try to find the libedit library
2947+#
2948+# Once done this will define
2949+#
2950+# LIBEDIT_FOUND - True if libedit library is found
2951+# LIBEDIT_INCLUDE_DIRS - Directory to include to get libedit headers
2952+# LIBEDIT_LIBRARIES - Libraries to link against for the libedit library
2953+#
2954+
2955+FIND_PATH (
2956+ LIBEDIT_INCLUDE
2957+ editline/readline.h
2958+ PATHS ${LIBEDIT_INCLUDE_DIR} /usr/include /usr/local/include
2959+)
2960+MESSAGE(STATUS ${LIBEDIT_INCLUDE})
2961+
2962+FIND_LIBRARY (
2963+ LIBEDIT_LIBRARY
2964+ NAMES edit
2965+ PATHS ${LIBEDIT_LIBRARY_DIR} /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
2966+)
2967+MESSAGE(STATUS ${LIBEDIT_LIBRARY})
2968+
2969+SET (LIBEDIT_INCLUDE_DIRS ${LIBEDIT_INCLUDE})
2970+SET (LIBEDIT_LIBRARIES ${LIBEDIT_LIBRARY})
2971+
2972+FIND_PACKAGE_HANDLE_STANDARD_ARGS (
2973+ Libedit
2974+ DEFAULT_MSG
2975+ LIBEDIT_INCLUDE LIBEDIT_LIBRARY
2976+)
2977+
2978
2979=== modified file 'include/zorba/config.h.cmake'
2980--- include/zorba/config.h.cmake 2011-10-19 16:19:45 +0000
2981+++ include/zorba/config.h.cmake 2011-12-20 18:15:30 +0000
2982@@ -39,19 +39,19 @@
2983 #endif /* WIN32 */
2984
2985 // Platform headers
2986-#cmakedefine ZORBA_HAVE_COLL_H
2987+#cmakedefine ZORBA_HAVE_COLL_H
2988 #cmakedefine ZORBA_HAVE_EXECINFO_H
2989 #cmakedefine ZORBA_HAVE_FLEXLEXER_H
2990 #cmakedefine ZORBA_HAVE_ICONV_H
2991-#cmakedefine ZORBA_HAVE_INTTYPES_H
2992-#cmakedefine ZORBA_HAVE_LIMITS_H
2993-#cmakedefine ZORBA_HAVE_PTHREAD_H
2994-#cmakedefine ZORBA_HAVE_STDINT_H
2995-#cmakedefine ZORBA_HAVE_STDLIB_H
2996+#cmakedefine ZORBA_HAVE_INTTYPES_H
2997+#cmakedefine ZORBA_HAVE_LIMITS_H
2998+#cmakedefine ZORBA_HAVE_PTHREAD_H
2999+#cmakedefine ZORBA_HAVE_STDINT_H
3000+#cmakedefine ZORBA_HAVE_STDLIB_H
3001 #cmakedefine ZORBA_HAVE_SYS_MOUNT_H
3002 #cmakedefine ZORBA_HAVE_SYS_TYPES_H
3003-#cmakedefine ZORBA_HAVE_USTRING_H
3004-#cmakedefine ZORBA_HAVE_UTYPES_H
3005+#cmakedefine ZORBA_HAVE_USTRING_H
3006+#cmakedefine ZORBA_HAVE_UTYPES_H
3007
3008 // Platform functions
3009 #cmakedefine ZORBA_HAVE_CLOCKGETTIME_FUNCTION
3010
3011=== modified file 'include/zorba/debugger_client.h'
3012--- include/zorba/debugger_client.h 2011-07-24 22:28:31 +0000
3013+++ include/zorba/debugger_client.h 2011-12-20 18:15:30 +0000
3014@@ -162,6 +162,13 @@
3015 * @return The id of the request.
3016 */
3017 virtual std::size_t status() = 0;
3018+
3019+ /**
3020+ * @brief Get the variables in all the contexts in the topmost stack frame.
3021+ *
3022+ * @return The id of the request.
3023+ */
3024+ virtual std::size_t variables() = 0;
3025
3026 /**
3027 * @brief Query the debug engine for supported features.
3028@@ -521,6 +528,7 @@
3029 */
3030 virtual void quit() = 0;
3031 };
3032+
3033 }//end of namespace
3034+
3035 #endif
3036-/* vim:set et sw=2 ts=2: */
3037
3038=== modified file 'modules/com/zorba-xquery/www/modules/CMakeLists.txt'
3039--- modules/com/zorba-xquery/www/modules/CMakeLists.txt 2011-10-14 07:35:51 +0000
3040+++ modules/com/zorba-xquery/www/modules/CMakeLists.txt 2011-12-20 18:15:30 +0000
3041@@ -100,6 +100,13 @@
3042 DECLARE_ZORBA_MODULE(FILE store/static/integrity_constraints/dml.xq VERSION 2.0
3043 URI "http://www.zorba-xquery.com/modules/store/static/integrity_constraints/dml")
3044
3045+# debugger client DBGP message handler module
3046+IF (ZORBA_WITH_DEBUGGER)
3047+ DECLARE_ZORBA_MODULE (FILE debugger/dbgp-message-handler.xq VERSION 1.0
3048+ URI "http://www.zorba-xquery.com/modules/debugger/dbgp-message-handler")
3049+ENDIF (ZORBA_WITH_DEBUGGER)
3050+
3051+
3052 # error and warning modules
3053 DECLARE_ZORBA_MODULE (FILE pregenerated/errors.xq
3054 URI "http://www.zorba-xquery.com/errors"
3055
3056=== added directory 'modules/com/zorba-xquery/www/modules/debugger'
3057=== added file 'modules/com/zorba-xquery/www/modules/debugger/dbgp-message-handler.xq'
3058--- modules/com/zorba-xquery/www/modules/debugger/dbgp-message-handler.xq 1970-01-01 00:00:00 +0000
3059+++ modules/com/zorba-xquery/www/modules/debugger/dbgp-message-handler.xq 2011-12-20 18:15:30 +0000
3060@@ -0,0 +1,277 @@
3061+xquery version "3.0";
3062+
3063+(:
3064+ : Copyright 2006-2009 The FLWOR Foundation.
3065+ :
3066+ : Licensed under the Apache License, Version 2.0 (the "License");
3067+ : you may not use this file except in compliance with the License.
3068+ : You may obtain a copy of the License at
3069+ :
3070+ : http://www.apache.org/licenses/LICENSE-2.0
3071+ :
3072+ : Unless required by applicable law or agreed to in writing, software
3073+ : distributed under the License is distributed on an "AS IS" BASIS,
3074+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3075+ : See the License for the specific language governing permissions and
3076+ : limitations under the License.
3077+:)
3078+module namespace dmh = "http://www.zorba-xquery.com/modules/debugger/dbgp-message-handler";
3079+
3080+import module namespace base64 = "http://www.zorba-xquery.com/modules/converters/base64";
3081+
3082+declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
3083+declare option ver:module-version "1.0";
3084+
3085+
3086+declare variable $dmh:endl as xs:string := "
3087+";
3088+
3089+(:~
3090+ : Set this variale to true if you want to have mode debug information when
3091+ : an error occurs.
3092+ :)
3093+declare variable $dmh:debug as xs:boolean := fn:false();
3094+
3095+
3096+declare %private function dmh:status($resp as element(response))
3097+{
3098+ switch ($resp/@status)
3099+ case "starting"
3100+ case "stopping"
3101+ return "idle"
3102+ case "break"
3103+ return
3104+ let $status := $resp/@status
3105+ let $whyInfo :=
3106+ if ($resp/@reason ne "ok") then
3107+ fn:concat(" (", $resp/@reason, ")")
3108+ else
3109+ ""
3110+ let $whereInfo :=
3111+ if ($resp/text()[1] ne "") then
3112+ fn:concat(" in ", $resp/text()[1])
3113+ else
3114+ ""
3115+ return
3116+ fn:concat($status, $whyInfo, $whereInfo)
3117+ default
3118+ return $resp/@status
3119+};
3120+
3121+declare %private function dmh:source($resp as element(response))
3122+{
3123+ $resp/text()
3124+};
3125+
3126+declare %private function dmh:breakpoint-set($resp as element(response))
3127+{
3128+ fn:concat("set breakpoint with id ", data($resp/@id), " and state ", data($resp/@state))
3129+};
3130+
3131+declare %private function dmh:breakpoint-get($resp as element(response))
3132+{
3133+ let $b := $resp/breakpoint
3134+ return
3135+ fn:concat(
3136+ "Breakpoint ", $b/@id, $dmh:endl,
3137+ " type: ", $b/@type, $dmh:endl,
3138+ " file: ", $b/@filename, $dmh:endl,
3139+ " line: ", $b/@lineno, $dmh:endl,
3140+ " state: ", $b/@state
3141+ )
3142+};
3143+
3144+declare %private function dmh:breakpoint-list($resp as element(response))
3145+{
3146+ fn:string-join(
3147+ let $bs := $resp/breakpoint
3148+ return
3149+ if (fn:exists($bs)) then
3150+ fn:concat(
3151+ "--------------------------------------", $dmh:endl,
3152+ "| ID | State | Line | File", $dmh:endl,
3153+ "|--------|-----------|--------|-------", $dmh:endl,
3154+ fn:string-join(
3155+ for $b in $bs
3156+ return
3157+ fn:concat(
3158+ "| ", dmh:lpottl($b/@id, 6, " "), " ",
3159+ "| ", if ($b/@state eq "enabled") then "enabled " else "disabled ", " ",
3160+ "| ", dmh:lpottl($b/@lineno, 6, " "), " ",
3161+ "| ", $b/@filename, $dmh:endl),
3162+ ""
3163+ ),
3164+ "--------------------------------------", $dmh:endl
3165+ )
3166+ else
3167+ "No breakpoints set"
3168+ )
3169+};
3170+
3171+(:~
3172+ : left-pad-or-trim-to-length
3173+ :)
3174+declare %private function dmh:lpottl($value as xs:string, $length as xs:integer, $padChar as xs:string)
3175+ as xs:string
3176+{
3177+ let $padChar := fn:substring($padChar, 1, 1)
3178+ let $len := fn:string-length($value)
3179+ return
3180+ if ($len < $length) then
3181+ let $pad :=
3182+ fn:string-join(
3183+ for $i in 1 to $length - $len
3184+ return $padChar,
3185+ ""
3186+ )
3187+ return
3188+ fn:concat($pad, $value)
3189+ else
3190+ fn:substring($value, $len - $length + 1)
3191+};
3192+
3193+declare %private function dmh:breakpoint-remove($resp as element(response))
3194+{
3195+ "Breakpoint removed"
3196+};
3197+
3198+declare %private function dmh:stack-depth($resp as element(response))
3199+{
3200+ fn:concat("depth: ", $resp/@depth)
3201+};
3202+
3203+declare %private function dmh:stack-get($resp as element(response))
3204+{
3205+ fn:string-join(
3206+ for $s in $resp/stack
3207+ return
3208+ fn:concat("#", $s/@level, " in ", $s/@where, " at ", $s/@filename, ":", $s/@lineno),
3209+ $dmh:endl
3210+ )
3211+};
3212+
3213+
3214+declare %private function dmh:context-names($resp as element(response))
3215+{
3216+ fn:string-join(
3217+ for $c in $resp/context
3218+ return
3219+ fn:concat("context ", $c/@id, ": ", $c/@name),
3220+ $dmh:endl
3221+ )
3222+};
3223+
3224+declare %private function dmh:context-get($resp as element(response))
3225+{
3226+ fn:string-join(
3227+ for $p in $resp/property
3228+ return
3229+ fn:concat($p/@fullname, " ", $p/@type,
3230+ if ($p/text() ne "") then
3231+ fn:concat(": ", base64:decode($p/text()))
3232+ else
3233+ ""
3234+ ),
3235+ $dmh:endl
3236+ )
3237+};
3238+
3239+declare %private function dmh:eval($resp as element(response))
3240+{
3241+ if ($resp/@success eq "1") then
3242+ dmh:context-get($resp)
3243+ else
3244+ dmh:report-error("An unknown error occured while evaluating expression.")
3245+};
3246+
3247+declare %private function dmh:report-error(
3248+ $message as xs:string)
3249+{
3250+ dmh:report-error($message, ())
3251+};
3252+
3253+declare %private function dmh:report-error(
3254+ $message as xs:string,
3255+ $debugMessage as xs:string*)
3256+{
3257+ fn:string-join(
3258+ (
3259+ (: the error message :)
3260+ fn:concat("Error: ", $message),
3261+
3262+ (: the debug info :)
3263+ if ($dmh:debug and fn:string-length($debugMessage) gt 0) then
3264+ $debugMessage
3265+ else
3266+ ()
3267+ ),
3268+ $dmh:endl
3269+ )
3270+};
3271+
3272+declare %private function dmh:process-response($resp as element(response))
3273+{
3274+ switch ($resp/@command)
3275+ case "eval" return dmh:eval($resp)
3276+ case "context_get" return dmh:context-get($resp)
3277+ case "context_names" return dmh:context-names($resp)
3278+ case "stack_get" return dmh:stack-get($resp)
3279+ case "stack_depth" return dmh:stack-depth($resp)
3280+ case "breakpoint_remove" return dmh:breakpoint-remove($resp)
3281+ case "breakpoint_list" return dmh:breakpoint-list($resp)
3282+ case "breakpoint_get" return dmh:breakpoint-get($resp)
3283+ case "breakpoint_set" return dmh:breakpoint-set($resp)
3284+ case "source" return dmh:source($resp)
3285+
3286+ (: continuation command only need to display/process the status :)
3287+ case "run"
3288+ case "step_into"
3289+ case "step_out"
3290+ case "step_over"
3291+ case "stop"
3292+ case "status"
3293+ return dmh:status($resp)
3294+
3295+ default
3296+ return dmh:report-error(fn:concat("Command not implemented: ", $resp/@command))
3297+};
3298+
3299+declare function dmh:process-init($init as element(init))
3300+{
3301+ fn:string-join(
3302+ ("Established connection with", $init/@language, "client", $init/@appid),
3303+ " "
3304+ )
3305+};
3306+
3307+declare function dmh:process($message as element())
3308+{
3309+ let $nodeName := fn:local-name($message)
3310+ let $id := fn:data($message/@transaction_id)
3311+ return
3312+ if ($nodeName eq "response") then
3313+ (: no transaction_id :)
3314+ if (fn:count($id) eq 0 or $id eq "") then
3315+ (0, dmh:report-error("Invalid response", "Missing or empty response transaction ID."))
3316+ (: wrong transaction_id :)
3317+ else if (xs:string(fn:number($id)) eq "NaN") then
3318+ (0, dmh:report-error("Invalid response", "Invalid value for response transaction ID."))
3319+ (: no or empty command :)
3320+ else if (fn:count($message/@command) eq 0 or $message/@command eq "") then
3321+ ($id, dmh:report-error("Invalid response", "Missing or empty response command attribute."))
3322+ (: error response :)
3323+ else if (fn:exists($message/error)) then
3324+ ($id, dmh:report-error(fn:data($message/error/message), fn:concat("Error code: ", fn:data($message/error/@code))))
3325+ else
3326+ ($id, dmh:process-response($message))
3327+ else if ($nodeName eq "init") then
3328+ (0, dmh:process-init($message))
3329+ else
3330+ (
3331+ if (fn:count($id) eq 0 or $id eq "" or xs:string(fn:number($id)) eq "NaN") then
3332+ 0
3333+ else
3334+ $id,
3335+ dmh:report-error(fn:concat("Unknown message node: ", $nodeName))
3336+ )
3337+};
3338
3339=== modified file 'src/compiler/expression/expr.cpp'
3340--- src/compiler/expression/expr.cpp 2011-12-20 09:04:58 +0000
3341+++ src/compiler/expression/expr.cpp 2011-12-20 18:15:30 +0000
3342@@ -1469,7 +1469,6 @@
3343 compute_scripting_kind();
3344 }
3345
3346-
3347 void debugger_expr::serialize(::zorba::serialization::Archiver& ar)
3348 {
3349 serialize_baseclass(ar, (expr*)this);
3350
3351=== modified file 'src/compiler/translator/translator.cpp'
3352--- src/compiler/translator/translator.cpp 2011-12-20 11:50:23 +0000
3353+++ src/compiler/translator/translator.cpp 2011-12-20 18:15:30 +0000
3354@@ -1671,7 +1671,7 @@
3355 void wrap_in_debugger_expr(
3356 expr_t& aExpr,
3357 const QueryLoc& aLoc,
3358- bool aAddBreakable = true,
3359+ bool aIsMainModuleBreakable = false,
3360 bool aIsVarDeclaration = false)
3361 {
3362 #ifdef ZORBA_WITH_DEBUGGER
3363@@ -1686,9 +1686,7 @@
3364 // add the breakable expression in the debugger commons as a possible
3365 // breakpoint location
3366 Breakable lBreakable(aLoc);
3367- if (aAddBreakable) {
3368- theCCB->theDebuggerCommons->addBreakable(lBreakable);
3369- }
3370+ theCCB->theDebuggerCommons->addBreakable(lBreakable, aIsMainModuleBreakable);
3371
3372 // retrieve all variables that are in the current scope
3373 typedef std::vector<var_expr_t> VarExprVector;
3374@@ -2246,7 +2244,7 @@
3375 // the main module debug iterator has no location otherwise
3376 // this would take precedence over a child debug iterator
3377 // starting in the same line
3378- wrap_in_debugger_expr(program, program->get_loc(), false);
3379+ wrap_in_debugger_expr(program, program->get_loc(), true);
3380
3381 program = wrap_in_globalvar_assign(program);
3382
3383@@ -3725,7 +3723,7 @@
3384 QueryLoc lExpandedLocation = expandQueryLoc(v.get_name()->get_location(),
3385 initExpr->get_loc());
3386
3387- wrap_in_debugger_expr(initExpr, lExpandedLocation, true, true);
3388+ wrap_in_debugger_expr(initExpr, lExpandedLocation, false, true);
3389 }
3390 #endif
3391
3392@@ -3747,7 +3745,7 @@
3393 QueryLoc lExpandedLocation = expandQueryLoc(v.get_name()->get_location(),
3394 initExpr->get_loc());
3395
3396- wrap_in_debugger_expr(initExpr, lExpandedLocation, true, true);
3397+ wrap_in_debugger_expr(initExpr, lExpandedLocation, false, true);
3398 }
3399 #endif
3400
3401
3402=== modified file 'src/debugger/debugger_client.cpp'
3403--- src/debugger/debugger_client.cpp 2011-06-14 17:26:33 +0000
3404+++ src/debugger/debugger_client.cpp 2011-12-20 18:15:30 +0000
3405@@ -38,5 +38,3 @@
3406 }
3407
3408 }//end of namespace
3409-
3410-/* vim:set et sw=2 ts=2: */
3411
3412=== modified file 'src/debugger/debugger_clientimpl.cpp'
3413--- src/debugger/debugger_clientimpl.cpp 2011-07-06 20:43:46 +0000
3414+++ src/debugger/debugger_clientimpl.cpp 2011-12-20 18:15:30 +0000
3415@@ -24,462 +24,549 @@
3416
3417 namespace zorba {
3418
3419- DebuggerClient::~DebuggerClient()
3420- {}
3421-
3422- DebuggerClient* DebuggerClient::createDebuggerClient(DebuggerEventHandler* aHandler,
3423- unsigned short aPort,
3424- const std::string& aHost)
3425- {
3426- return new DebuggerClientImpl(aHost, aPort, aHandler);
3427- }
3428-
3429- DebuggerListener::DebuggerListener(DebuggerClientImpl* aClient)
3430+DebuggerClient*
3431+DebuggerClient::createDebuggerClient(
3432+ DebuggerEventHandler* aHandler,
3433+ unsigned short aPort,
3434+ const std::string& aHost)
3435+{
3436+ return new DebuggerClientImpl(aHost, aPort, aHandler);
3437+}
3438+
3439+// ****************************************************************************
3440+
3441+DebuggerListener::DebuggerListener(DebuggerClientImpl* aClient)
3442 : theClient(aClient), theStopLooping(false)
3443- {
3444- }
3445-
3446- void DebuggerListener::run()
3447- {
3448- while (!theStopLooping) {
3449- std::string str;
3450- std::getline(*(theClient->theStream), str, '\0');
3451-#ifndef NDEBUG
3452- std::stringstream lStr(str);
3453- std::size_t length;
3454- lStr >> length;
3455-#endif
3456- // we are not interested in the length, but only in the init
3457- // message
3458- std::getline(*(theClient->theStream), str, '\0');
3459-#ifndef NDEBUG
3460- assert(str.size() == length);
3461-#endif
3462- theClient->theHandler->parseMessage(str);
3463- this->sleep_(1000);
3464- }
3465- }
3466-
3467- void DebuggerListener::finish()
3468- {
3469- }
3470-
3471- void DebuggerListener::stopLooping()
3472- {
3473- theStopLooping = true;
3474- }
3475-
3476- DebuggerClientImpl::DebuggerClientImpl(const std::string& aHost,
3477- unsigned short aPort,
3478- DebuggerEventHandler* aHandler)
3479- : theServerSocket(aHost, aPort), theSocket(0), theStreamBuffer(0), theStream(0),
3480- theHandler(aHandler), theListener(this), theLastId(0)
3481- {
3482- }
3483-
3484- void DebuggerClientImpl::accept() {
3485- theSocket = theServerSocket.accept();
3486- theStreamBuffer = new socket_streambuf(*theSocket);
3487- theStream = new std::iostream(theStreamBuffer);
3488- theListener.start();
3489- }
3490-
3491- std::size_t DebuggerClientImpl::status()
3492- {
3493- std::size_t id = ++theLastId;
3494- *theStream << "status -i " << id << '\0';
3495- theStream->sync();
3496- return id;
3497- }
3498-
3499- std::size_t DebuggerClientImpl::feature_get(std::string const& aFeatureName)
3500- {
3501- std::size_t id = ++theLastId;
3502- *theStream << "feature-get -i " << id << " -n " << aFeatureName << '\0';
3503- theStream->sync();
3504- return id;
3505- }
3506-
3507- std::size_t DebuggerClientImpl::feature_set(std::string const &aFeatureName,
3508- std::string const &aValue)
3509- {
3510- std::size_t id = ++theLastId;
3511- *theStream << "feature-set -i " << id << " -n " << aFeatureName << " -v "
3512- << aValue << '\0';
3513- theStream->sync();
3514- return id;
3515- }
3516-
3517- std::size_t DebuggerClientImpl::run()
3518- {
3519- std::size_t id = ++theLastId;
3520- *theStream << "run -i " << id << '\0';
3521- theStream->sync();
3522- return id;
3523- }
3524-
3525- std::size_t DebuggerClientImpl::step_into()
3526- {
3527- std::size_t id = ++theLastId;
3528- *theStream << "step_into -i " << id << '\0';
3529- theStream->sync();
3530- return id;
3531- }
3532-
3533- std::size_t DebuggerClientImpl::step_over()
3534- {
3535- std::size_t id = ++theLastId;
3536- *theStream << "step_over -i " << id << '\0';
3537- theStream->sync();
3538- return id;
3539- }
3540-
3541- std::size_t DebuggerClientImpl::step_out()
3542- {
3543- std::size_t id = ++theLastId;
3544- *theStream << "step_out -i " << id << '\0';
3545- theStream->sync();
3546- return id;
3547- }
3548-
3549- std::size_t DebuggerClientImpl::stop()
3550- {
3551- std::size_t id = ++theLastId;
3552- *theStream << "stop -i " << id << '\0';
3553- theStream->sync();
3554- return id;
3555- }
3556-
3557- std::size_t DebuggerClientImpl::detach()
3558- {
3559- std::size_t id = ++theLastId;
3560- *theStream << "detach -i " << id << '\0';
3561- theStream->sync();
3562- return id;
3563- }
3564-
3565- std::size_t DebuggerClientImpl::breakpoint_set(BreakpointType aType,
3566- bool aEnabled,
3567- const std::string& aFilename,
3568- int aLinenumber,
3569- const std::string& aFunctionName,
3570- const std::string& aExceptionName,
3571- unsigned hit_value,
3572- HitCondition aCondition,
3573- bool aIsTemporary,
3574- const std::string& aExpression)
3575- {
3576- std::size_t id = ++theLastId;
3577- *theStream << "breakpoint_set -i " << id
3578- << " -t ";
3579- switch (aType) {
3580- case Line:
3581- *theStream << "line";
3582- break;
3583- case Call:
3584- *theStream << "call";
3585- break;
3586- case Return:
3587- *theStream << "return";
3588- break;
3589- case Exception:
3590- *theStream << "exception";
3591- break;
3592- case Conditional:
3593- *theStream << "conditional";
3594- break;
3595- case Watch:
3596- *theStream << "watch";
3597- break;
3598- }
3599- if (!aEnabled)
3600- *theStream << " -s disabled";
3601- if (aFilename != "") {
3602- *theStream << " -f " << aFilename;
3603- }
3604- if (aLinenumber != -1)
3605- *theStream << " -n " << aLinenumber;
3606- if (aFunctionName != "")
3607- *theStream << " -m " << aFunctionName;
3608- if (aExceptionName != "")
3609- *theStream << " -x " << aExceptionName;
3610- if (hit_value != 0)
3611- *theStream << " -h " << hit_value;
3612- switch (aCondition) {
3613- case BiggerEqual:
3614- break;
3615- case Equal:
3616- *theStream << " -o == ";
3617- break;
3618- case Multiple:
3619- *theStream << " -o % ";
3620- }
3621- if (aIsTemporary)
3622- *theStream << " -r 1 ";
3623- if (aExpression != "")
3624- *theStream << " -- " << aExpression;
3625- *theStream << '\0';
3626- theStream->sync();
3627- return id;
3628- }
3629-
3630- std::size_t DebuggerClientImpl::breakpoint_get(std::size_t aBreakpointId)
3631- {
3632- std::size_t id = ++theLastId;
3633- *theStream << "breakpoint_get -i " << id << " -d " << aBreakpointId << '\0';
3634- theStream->sync();
3635- return id;
3636- }
3637-
3638- std::size_t DebuggerClientImpl::breakpoint_update(std::size_t aBreakpointId,
3639- bool aEnabled,
3640- int aLinenumber,
3641- unsigned hit_value,
3642- HitCondition aCondition)
3643- {
3644- std::size_t id = ++theLastId;
3645- *theStream << "breakpoint_update -i " << id
3646- << " -d " << aBreakpointId;
3647- if (aEnabled)
3648- *theStream << " -s disabled";
3649- if (aLinenumber != -1)
3650- *theStream << " -n " << aLinenumber;
3651- if (hit_value != 0)
3652- *theStream << " -h " << hit_value;
3653- switch (aCondition) {
3654- case BiggerEqual:
3655- break;
3656- case Equal:
3657- *theStream << " -o == ";
3658- break;
3659- case Multiple:
3660- *theStream << " -o % ";
3661- }
3662- *theStream << '\0';
3663- theStream->sync();
3664- return id;
3665- }
3666-
3667- std::size_t DebuggerClientImpl::breakpoint_remove(std::size_t aBreakpointId)
3668- {
3669- std::size_t id = ++theLastId;
3670- *theStream << "breakpoint_remove -i " << id << " -d " << aBreakpointId << '\0';
3671- theStream->sync();
3672- return id;
3673- }
3674-
3675- std::size_t DebuggerClientImpl::breakpoint_list()
3676- {
3677- std::size_t id = ++theLastId;
3678- *theStream << "breakpoint_list -i " << id << '\0';
3679- theStream->sync();
3680- return id;
3681- }
3682-
3683- std::size_t DebuggerClientImpl::stack_depth()
3684- {
3685- std::size_t id = ++theLastId;
3686- *theStream << "stack_depth -i " << id << '\0';
3687- theStream->sync();
3688- return id;
3689- }
3690-
3691- std::size_t DebuggerClientImpl::stack_get(int depth)
3692- {
3693- std::size_t id = ++theLastId;
3694- *theStream << "stack_depth";
3695- if (depth > 0)
3696- *theStream << " -d " << depth;
3697- *theStream << " -i " << id << '\0';
3698- theStream->sync();
3699- return id;
3700- }
3701-
3702- std::size_t DebuggerClientImpl::context_names(int depth)
3703- {
3704- std::size_t id = ++theLastId;
3705- *theStream << "context_names";
3706- if (depth > 0)
3707- *theStream << " -d " << depth;
3708- *theStream << " -i " << id << '\0';
3709- theStream->sync();
3710- return id;
3711- }
3712-
3713- std::size_t DebuggerClientImpl::context_get(int depth, int contextId)
3714- {
3715- std::size_t id = ++theLastId;
3716- *theStream << "context_get";
3717- if (depth > 0)
3718- *theStream << " -d " << depth;
3719- if (contextId > 0)
3720- *theStream << " -c " << contextId;
3721- *theStream << " -i " << id << '\0';
3722- theStream->sync();
3723- return id;
3724- }
3725-
3726- std::size_t DebuggerClientImpl::typemap_get()
3727- {
3728- std::size_t id = ++theLastId;
3729- *theStream << "typemap_get -i " << id << '\0';
3730- theStream->sync();
3731- return id;
3732- }
3733-
3734- std::size_t DebuggerClientImpl::property_get(const std::string& aPropertyLongName,
3735- int aStackDepth,
3736- int aContextId,
3737- std::size_t aMaxDataSize,
3738- int aDatapage,
3739- const std::string& aPropertyKey)
3740- {
3741- std::size_t id = property_x("property_get", aPropertyLongName, aStackDepth, aContextId, aMaxDataSize);
3742- if (aDatapage >= 0)
3743- *theStream << " -p " << aDatapage;
3744- if (aPropertyKey != "")
3745- *theStream << " -k " << aPropertyKey;
3746- *theStream << '\0';
3747- theStream->sync();
3748- return id;
3749- }
3750-
3751- std::size_t DebuggerClientImpl::property_set(const std::string& aPropertyLongName,
3752- int aStackDepth,
3753- int aContextId,
3754- std::size_t aMaxDataSize,
3755- const std::string& aPropertyAddress)
3756- {
3757- std::size_t id = property_x("property_set", aPropertyLongName, aStackDepth, aContextId, aMaxDataSize);
3758- if (aPropertyAddress != "")
3759- *theStream << " -a " << aPropertyAddress;
3760- *theStream << '\0';
3761- theStream->sync();
3762- return id;
3763- }
3764-
3765- std::size_t DebuggerClientImpl::property_value(const std::string& aPropertyLongName,
3766- int aStackDepth,
3767- int aContextId,
3768- std::size_t aMaxDataSize,
3769- int aDatapage,
3770- const std::string& aPropertyKey,
3771- const std::string& aPropertyAddress)
3772- {
3773- std::size_t id = property_x("property_get", aPropertyLongName, aStackDepth, aContextId, aMaxDataSize);
3774- if (aDatapage >= 0)
3775- *theStream << " -p " << aDatapage;
3776- if (aPropertyKey != "")
3777- *theStream << " -k " << aPropertyKey;
3778- if (aPropertyAddress != "")
3779- *theStream << " -a " << aPropertyAddress;
3780- *theStream << '\0';
3781- theStream->sync();
3782- return id;
3783- }
3784-
3785- std::size_t DebuggerClientImpl::property_x(const std::string& aCommand,
3786- const std::string& aPropertyLongName,
3787- int aStackDepth,
3788- int aContextId,
3789- std::size_t aMaxDataSize)
3790- {
3791- std::size_t id = ++theLastId;
3792- *theStream << aCommand << " -i " << id << " -n " << aPropertyLongName;
3793- if (aStackDepth > 0)
3794- *theStream << " -d " << aStackDepth;
3795- if (aContextId > 0)
3796- *theStream << " -c " << aContextId;
3797- if (aMaxDataSize > 0)
3798- *theStream << " -m " << aMaxDataSize;
3799- theStream->sync();
3800- return id;
3801- }
3802-
3803- std::size_t DebuggerClientImpl::source(std::string const &aFile,
3804- unsigned int aBeginLine,
3805- unsigned int aEndLine)
3806- {
3807- std::size_t id = ++theLastId;
3808- *theStream << "source -i " << id << " -f " << aFile;
3809- if (aBeginLine)
3810- *theStream << " -b " << aBeginLine;
3811- if (aEndLine)
3812- *theStream << " -e " << aEndLine;
3813- *theStream << '\0';
3814- theStream->sync();
3815- return id;
3816- }
3817-
3818- std::size_t DebuggerClientImpl::stream_option(OutputStream aStream, StreamBehaviour aBehaviour)
3819- {
3820- std::size_t id = ++theLastId;
3821- switch (aStream) {
3822- case Stdout:
3823- *theStream << "stdout";
3824- break;
3825- case Stderr:
3826- *theStream << "stderr";
3827- break;
3828- case Stdin:
3829- *theStream << "stdin";
3830- break;
3831- }
3832- *theStream << " -i " << id << " -c ";
3833- switch (aBehaviour) {
3834- case Disable:
3835- *theStream << "0";
3836- break;
3837- case CopyData:
3838- *theStream << "1";
3839- break;
3840- case Redirection:
3841- *theStream << "2";
3842- break;
3843- }
3844- *theStream << '\0';
3845- theStream->sync();
3846- return id;
3847- }
3848-
3849- std::size_t DebuggerClientImpl::do_break()
3850- {
3851- std::size_t id = ++theLastId;
3852- *theStream << "break -i " << id << '\0';
3853- theStream->sync();
3854- return id;
3855- }
3856-
3857- std::size_t DebuggerClientImpl::eval(std::string const &aExpr)
3858- {
3859- std::size_t id = ++theLastId;
3860- *theStream << "eval -i " << id << " -- " << encoding::Base64::encode(aExpr.c_str()) << '\0';
3861- theStream->sync();
3862- return id;
3863- }
3864-
3865- void DebuggerClientImpl::quit() {
3866- theListener.stopLooping();
3867- theListener.join();
3868- }
3869-
3870-
3871-
3872- DebuggerClientImpl::~DebuggerClientImpl()
3873- {
3874- if (theListener.status() == DebuggerListener::RUNNING) {
3875- theListener.stopLooping();
3876- theListener.join();
3877- }
3878- if (theSocket) {
3879- theSocket->close();
3880- theSocket->cleanUp();
3881- delete theSocket;
3882- }
3883- if (theStream) {
3884- theStream->sync();
3885- delete theStream;
3886- delete theStreamBuffer;
3887- }
3888- }
3889-}
3890+{
3891+}
3892+
3893+void
3894+DebuggerListener::run()
3895+{
3896+ while (!theStopLooping) {
3897+ std::string str;
3898+ std::getline(*(theClient->theInStream), str, '\0');
3899+
3900+#ifndef NDEBUG
3901+ std::stringstream lStr(str);
3902+ std::size_t length;
3903+ lStr >> length;
3904+#endif
3905+
3906+ // we are not interested in the length, but only in the init message
3907+ std::getline(*(theClient->theInStream), str, '\0');
3908+
3909+#ifndef NDEBUG
3910+ assert(str.size() == length);
3911+#endif
3912+
3913+ theClient->theHandler->parseMessage(str);
3914+
3915+ // TODO: this was the initial implementation. This will have to change
3916+ this->sleep_(1000);
3917+ }
3918+}
3919+
3920+void
3921+DebuggerListener::finish()
3922+{
3923+}
3924+
3925+void
3926+DebuggerListener::stopLooping()
3927+{
3928+ theStopLooping = true;
3929+}
3930+
3931+// ****************************************************************************
3932+
3933+DebuggerClient::~DebuggerClient()
3934+{
3935+}
3936+
3937+DebuggerClientImpl::DebuggerClientImpl(
3938+ const std::string& aHost,
3939+ unsigned short aPort,
3940+ DebuggerEventHandler* aHandler)
3941+ : theServerSocket(aHost, aPort),
3942+ theSocket(0),
3943+ theInStreamBuffer(0),
3944+ theOutStreamBuffer(0),
3945+ theInStream(0),
3946+ theOutStream(0),
3947+ theHandler(aHandler),
3948+ theListener(0),
3949+ theLastId(0)
3950+{
3951+}
3952+
3953+DebuggerClientImpl::~DebuggerClientImpl()
3954+{
3955+ if (theListener) {
3956+ if (theListener->status() == DebuggerListener::RUNNING) {
3957+ theListener->stopLooping();
3958+ theListener->join();
3959+ }
3960+ delete theListener;
3961+ }
3962+ if (theSocket) {
3963+ theInStream->sync();
3964+ delete theInStream;
3965+
3966+ theOutStream->flush();
3967+ delete theInStream;
3968+
3969+ delete theOutStreamBuffer;
3970+ delete theInStreamBuffer;
3971+
3972+ theSocket->close();
3973+ theSocket->cleanUp();
3974+ delete theSocket;
3975+ }
3976+}
3977+
3978+void
3979+DebuggerClientImpl::accept()
3980+{
3981+ theListener = new DebuggerListener(this);
3982+ theSocket = theServerSocket.accept();
3983+ theInStreamBuffer = new SocketStreambuf(*theSocket);
3984+ theOutStreamBuffer = new SocketStreambuf(*theSocket);
3985+ theInStream = new std::istream(theInStreamBuffer);
3986+ theOutStream = new std::ostream(theOutStreamBuffer);
3987+ theListener->start();
3988+}
3989+
3990+std::size_t
3991+DebuggerClientImpl::status()
3992+{
3993+ std::size_t id = ++theLastId;
3994+ *theOutStream << "status -i " << id << '\0';
3995+ theOutStream->flush();
3996+ return id;
3997+}
3998+
3999+std::size_t
4000+DebuggerClientImpl::variables()
4001+{
4002+ // we hack the protocol to return all properties if the context ID is -1
4003+ std::size_t id = ++theLastId;
4004+ *theOutStream << "context_get -c -1 -i " << id << '\0';
4005+ theOutStream->flush();
4006+ return id;
4007+}
4008+
4009+std::size_t
4010+DebuggerClientImpl::feature_get(std::string const& aFeatureName)
4011+{
4012+ std::size_t id = ++theLastId;
4013+ *theOutStream << "feature_get -i " << id << " -n " << aFeatureName << '\0';
4014+ theOutStream->flush();
4015+ return id;
4016+}
4017+
4018+std::size_t
4019+DebuggerClientImpl::feature_set(std::string const &aFeatureName,
4020+ std::string const &aValue)
4021+{
4022+ std::size_t id = ++theLastId;
4023+ *theOutStream << "feature_set -i " << id << " -n " << aFeatureName << " -v "
4024+ << aValue << '\0';
4025+ theOutStream->flush();
4026+ return id;
4027+}
4028+
4029+std::size_t
4030+DebuggerClientImpl::run()
4031+{
4032+ std::size_t id = ++theLastId;
4033+ *theOutStream << "run -i " << id << '\0';
4034+ theOutStream->flush();
4035+ return id;
4036+}
4037+
4038+std::size_t
4039+DebuggerClientImpl::step_into()
4040+{
4041+ std::size_t id = ++theLastId;
4042+ *theOutStream << "step_into -i " << id << '\0';
4043+ theOutStream->flush();
4044+ return id;
4045+}
4046+
4047+std::size_t
4048+DebuggerClientImpl::step_over()
4049+{
4050+ std::size_t id = ++theLastId;
4051+ *theOutStream << "step_over -i " << id << '\0';
4052+ theOutStream->flush();
4053+ return id;
4054+}
4055+
4056+std::size_t
4057+DebuggerClientImpl::step_out()
4058+{
4059+ std::size_t id = ++theLastId;
4060+ *theOutStream << "step_out -i " << id << '\0';
4061+ theOutStream->flush();
4062+ return id;
4063+}
4064+
4065+std::size_t
4066+DebuggerClientImpl::stop()
4067+{
4068+ std::size_t id = ++theLastId;
4069+ *theOutStream << "stop -i " << id << '\0';
4070+ theOutStream->flush();
4071+ return id;
4072+}
4073+
4074+std::size_t
4075+DebuggerClientImpl::detach()
4076+{
4077+ std::size_t id = ++theLastId;
4078+ *theOutStream << "detach -i " << id << '\0';
4079+ theOutStream->flush();
4080+ return id;
4081+}
4082+
4083+std::size_t
4084+DebuggerClientImpl::breakpoint_set(
4085+ BreakpointType aType,
4086+ bool aEnabled,
4087+ const std::string& aFilename,
4088+ int aLinenumber,
4089+ const std::string& aFunctionName,
4090+ const std::string& aExceptionName,
4091+ unsigned hit_value,
4092+ HitCondition aCondition,
4093+ bool aIsTemporary,
4094+ const std::string& aExpression)
4095+{
4096+ std::size_t id = ++theLastId;
4097+ *theOutStream << "breakpoint_set -i " << id
4098+ << " -t ";
4099+ switch (aType) {
4100+ case Line:
4101+ *theOutStream << "line";
4102+ break;
4103+ case Call:
4104+ *theOutStream << "call";
4105+ break;
4106+ case Return:
4107+ *theOutStream << "return";
4108+ break;
4109+ case Exception:
4110+ *theOutStream << "exception";
4111+ break;
4112+ case Conditional:
4113+ *theOutStream << "conditional";
4114+ break;
4115+ case Watch:
4116+ *theOutStream << "watch";
4117+ break;
4118+ }
4119+ if (!aEnabled)
4120+ *theOutStream << " -s disabled";
4121+ if (aFilename != "") {
4122+ *theOutStream << " -f \"" << aFilename << "\"";
4123+ }
4124+ if (aLinenumber != -1)
4125+ *theOutStream << " -n " << aLinenumber;
4126+ if (aFunctionName != "")
4127+ *theOutStream << " -m " << aFunctionName;
4128+ if (aExceptionName != "")
4129+ *theOutStream << " -x " << aExceptionName;
4130+ if (hit_value != 0)
4131+ *theOutStream << " -h " << hit_value;
4132+ switch (aCondition) {
4133+ case BiggerEqual:
4134+ break;
4135+ case Equal:
4136+ *theOutStream << " -o == ";
4137+ break;
4138+ case Multiple:
4139+ *theOutStream << " -o % ";
4140+ }
4141+ if (aIsTemporary)
4142+ *theOutStream << " -r 1 ";
4143+ if (aExpression != "")
4144+ *theOutStream << " -- " << aExpression;
4145+ *theOutStream << '\0';
4146+ theOutStream->flush();
4147+ return id;
4148+}
4149+
4150+std::size_t
4151+DebuggerClientImpl::breakpoint_get(std::size_t aBreakpointId)
4152+{
4153+ std::size_t id = ++theLastId;
4154+ *theOutStream << "breakpoint_get -i " << id << " -d " << aBreakpointId << '\0';
4155+ theOutStream->flush();
4156+ return id;
4157+}
4158+
4159+std::size_t
4160+DebuggerClientImpl::breakpoint_update(
4161+ std::size_t aBreakpointId,
4162+ bool aEnabled,
4163+ int aLinenumber,
4164+ unsigned hit_value,
4165+ HitCondition aCondition)
4166+{
4167+ std::size_t id = ++theLastId;
4168+ *theOutStream << "breakpoint_update -i " << id
4169+ << " -d " << aBreakpointId;
4170+ if (aEnabled)
4171+ *theOutStream << " -s disabled";
4172+ if (aLinenumber != -1)
4173+ *theOutStream << " -n " << aLinenumber;
4174+ if (hit_value != 0)
4175+ *theOutStream << " -h " << hit_value;
4176+ switch (aCondition) {
4177+ case BiggerEqual:
4178+ break;
4179+ case Equal:
4180+ *theOutStream << " -o == ";
4181+ break;
4182+ case Multiple:
4183+ *theOutStream << " -o % ";
4184+ }
4185+ *theOutStream << '\0';
4186+ theOutStream->flush();
4187+ return id;
4188+}
4189+
4190+std::size_t
4191+DebuggerClientImpl::breakpoint_remove(std::size_t aBreakpointId)
4192+{
4193+ std::size_t id = ++theLastId;
4194+ *theOutStream << "breakpoint_remove -i " << id << " -d " << aBreakpointId << '\0';
4195+ theOutStream->flush();
4196+ return id;
4197+}
4198+
4199+std::size_t
4200+DebuggerClientImpl::breakpoint_list()
4201+{
4202+ std::size_t id = ++theLastId;
4203+ *theOutStream << "breakpoint_list -i " << id << '\0';
4204+ theOutStream->flush();
4205+ return id;
4206+}
4207+
4208+std::size_t
4209+DebuggerClientImpl::stack_depth()
4210+{
4211+ std::size_t id = ++theLastId;
4212+ *theOutStream << "stack_depth -i " << id << '\0';
4213+ theOutStream->flush();
4214+ return id;
4215+}
4216+
4217+std::size_t
4218+DebuggerClientImpl::stack_get(int depth)
4219+{
4220+ std::size_t id = ++theLastId;
4221+ *theOutStream << "stack_get";
4222+ if (depth >= 0) {
4223+ *theOutStream << " -d " << depth;
4224+ }
4225+ *theOutStream << " -i " << id << '\0';
4226+ theOutStream->flush();
4227+ return id;
4228+}
4229+
4230+std::size_t
4231+DebuggerClientImpl::context_names(int depth)
4232+{
4233+ std::size_t id = ++theLastId;
4234+ *theOutStream << "context_names";
4235+ if (depth >= 0) {
4236+ *theOutStream << " -d " << depth;
4237+ }
4238+ *theOutStream << " -i " << id << '\0';
4239+ theOutStream->flush();
4240+ return id;
4241+}
4242+
4243+std::size_t
4244+DebuggerClientImpl::context_get(int depth, int contextId)
4245+{
4246+ std::size_t id = ++theLastId;
4247+ *theOutStream << "context_get";
4248+ if (depth >= 0) {
4249+ *theOutStream << " -d " << depth;
4250+ }
4251+ if (contextId >= 0){
4252+ *theOutStream << " -c " << contextId;
4253+ }
4254+ *theOutStream << " -i " << id << '\0';
4255+ theOutStream->flush();
4256+ return id;
4257+}
4258+
4259+std::size_t
4260+DebuggerClientImpl::typemap_get()
4261+{
4262+ std::size_t id = ++theLastId;
4263+ *theOutStream << "typemap_get -i " << id << '\0';
4264+ theOutStream->flush();
4265+ return id;
4266+}
4267+
4268+std::size_t
4269+DebuggerClientImpl::property_get(
4270+ const std::string& aPropertyLongName,
4271+ int aStackDepth,
4272+ int aContextId,
4273+ std::size_t aMaxDataSize,
4274+ int aDatapage,
4275+ const std::string& aPropertyKey)
4276+{
4277+ std::size_t id = property_x("property_get", aPropertyLongName, aStackDepth, aContextId, aMaxDataSize);
4278+ if (aDatapage >= 0)
4279+ *theOutStream << " -p " << aDatapage;
4280+ if (aPropertyKey != "")
4281+ *theOutStream << " -k " << aPropertyKey;
4282+ *theOutStream << '\0';
4283+ theOutStream->flush();
4284+ return id;
4285+}
4286+
4287+std::size_t
4288+DebuggerClientImpl::property_set(
4289+ const std::string& aPropertyLongName,
4290+ int aStackDepth,
4291+ int aContextId,
4292+ std::size_t aMaxDataSize,
4293+ const std::string& aPropertyAddress)
4294+{
4295+ std::size_t id = property_x("property_set", aPropertyLongName, aStackDepth, aContextId, aMaxDataSize);
4296+ if (aPropertyAddress != "")
4297+ *theOutStream << " -a " << aPropertyAddress;
4298+ *theOutStream << '\0';
4299+ theOutStream->flush();
4300+ return id;
4301+}
4302+
4303+std::size_t
4304+DebuggerClientImpl::property_value(
4305+ const std::string& aPropertyLongName,
4306+ int aStackDepth,
4307+ int aContextId,
4308+ std::size_t aMaxDataSize,
4309+ int aDatapage,
4310+ const std::string& aPropertyKey,
4311+ const std::string& aPropertyAddress)
4312+{
4313+ std::size_t id = property_x("property_get", aPropertyLongName, aStackDepth, aContextId, aMaxDataSize);
4314+ if (aDatapage >= 0)
4315+ *theOutStream << " -p " << aDatapage;
4316+ if (aPropertyKey != "")
4317+ *theOutStream << " -k " << aPropertyKey;
4318+ if (aPropertyAddress != "")
4319+ *theOutStream << " -a " << aPropertyAddress;
4320+ *theOutStream << '\0';
4321+ theOutStream->flush();
4322+ return id;
4323+}
4324+
4325+std::size_t
4326+DebuggerClientImpl::property_x(
4327+ const std::string& aCommand,
4328+ const std::string& aPropertyLongName,
4329+ int aStackDepth,
4330+ int aContextId,
4331+ std::size_t aMaxDataSize)
4332+{
4333+ std::size_t id = ++theLastId;
4334+ *theOutStream << aCommand << " -i " << id << " -n " << aPropertyLongName;
4335+ if (aStackDepth > 0)
4336+ *theOutStream << " -d " << aStackDepth;
4337+ if (aContextId > 0)
4338+ *theOutStream << " -c " << aContextId;
4339+ if (aMaxDataSize > 0)
4340+ *theOutStream << " -m " << aMaxDataSize;
4341+ theOutStream->flush();
4342+ return id;
4343+}
4344+
4345+std::size_t
4346+DebuggerClientImpl::source(
4347+ std::string const &aFile,
4348+ unsigned int aBeginLine,
4349+ unsigned int aEndLine)
4350+{
4351+ std::size_t id = ++theLastId;
4352+ *theOutStream << "source -i " << id;
4353+ // enable zorba extensions
4354+ *theOutStream << " -z 1";
4355+ *theOutStream << " -f \"" << aFile << "\"";
4356+ if (aBeginLine)
4357+ *theOutStream << " -b " << aBeginLine;
4358+ if (aEndLine)
4359+ *theOutStream << " -e " << aEndLine;
4360+ *theOutStream << '\0';
4361+ theOutStream->flush();
4362+ return id;
4363+}
4364+
4365+std::size_t
4366+DebuggerClientImpl::stream_option(OutputStream aStream, StreamBehaviour aBehaviour)
4367+{
4368+ std::size_t id = ++theLastId;
4369+ switch (aStream) {
4370+ case Stdout:
4371+ *theOutStream << "stdout";
4372+ break;
4373+ case Stderr:
4374+ *theOutStream << "stderr";
4375+ break;
4376+ case Stdin:
4377+ *theOutStream << "stdin";
4378+ break;
4379+ }
4380+ *theOutStream << " -i " << id << " -c ";
4381+ switch (aBehaviour) {
4382+ case Disable:
4383+ *theOutStream << "0";
4384+ break;
4385+ case CopyData:
4386+ *theOutStream << "1";
4387+ break;
4388+ case Redirection:
4389+ *theOutStream << "2";
4390+ break;
4391+ }
4392+ *theOutStream << '\0';
4393+ theOutStream->flush();
4394+ return id;
4395+}
4396+
4397+std::size_t
4398+DebuggerClientImpl::do_break()
4399+{
4400+ std::size_t id = ++theLastId;
4401+ *theOutStream << "break -i " << id << '\0';
4402+ theOutStream->flush();
4403+ return id;
4404+}
4405+
4406+std::size_t
4407+DebuggerClientImpl::eval(std::string const &aExpr)
4408+{
4409+ std::size_t id = ++theLastId;
4410+ *theOutStream << "eval -i " << id << " -- " << encoding::Base64::encode(aExpr.c_str()) << '\0';
4411+ theOutStream->flush();
4412+ return id;
4413+}
4414+
4415+void
4416+DebuggerClientImpl::quit()
4417+{
4418+ theListener->stopLooping();
4419+ theListener->join();
4420+}
4421+
4422+} // namespace zorba
4423
4424=== modified file 'src/debugger/debugger_clientimpl.h'
4425--- src/debugger/debugger_clientimpl.h 2011-07-01 01:53:24 +0000
4426+++ src/debugger/debugger_clientimpl.h 2011-12-20 18:15:30 +0000
4427@@ -13,7 +13,8 @@
4428 * See the License for the specific language governing permissions and
4429 * limitations under the License.
4430 */
4431-#pragma once
4432+#ifndef ZORBA_DEBUGGER_CLIENTIMPL_H
4433+#define ZORBA_DEBUGGER_CLIENTIMPL_H
4434
4435 #include <string>
4436 #include <zorba/debugger_client.h>
4437@@ -21,7 +22,7 @@
4438 #include "zorbautils/runnable.h"
4439
4440 namespace zorba {
4441- class socket_streambuf;
4442+ class SocketStreambuf;
4443 class DebuggerEventHandler;
4444 class DebuggerListener;
4445 class DebuggerClientImpl;
4446@@ -48,6 +49,7 @@
4447 public: // API
4448 virtual void accept();
4449 virtual std::size_t status();
4450+ virtual std::size_t variables();
4451 virtual std::size_t feature_get(const std::string& aFeatureName);
4452 virtual std::size_t feature_set(const std::string& aFeatureName,
4453 const std::string& aValue);
4454@@ -110,12 +112,17 @@
4455 int aContextId = -1,
4456 std::size_t aMaxDataSize = 0);
4457 private:
4458- TCPServerSocket theServerSocket;
4459- TCPSocket* theSocket;
4460- socket_streambuf* theStreamBuffer;
4461- std::iostream* theStream;
4462+ TCPServerSocket theServerSocket;
4463+ TCPSocket* theSocket;
4464+ SocketStreambuf* theInStreamBuffer;
4465+ SocketStreambuf* theOutStreamBuffer;
4466+ std::istream* theInStream;
4467+ std::ostream* theOutStream;
4468 DebuggerEventHandler* theHandler;
4469- DebuggerListener theListener;
4470- std::size_t theLastId;
4471+ DebuggerListener* theListener;
4472+ std::size_t theLastId;
4473 };
4474-}
4475+
4476+} // namespace zorba
4477+
4478+#endif // ZORBA_DEBUGGER_CLIENTIMPL_H
4479
4480=== modified file 'src/debugger/debugger_common.h'
4481--- src/debugger/debugger_common.h 2011-06-22 11:19:07 +0000
4482+++ src/debugger/debugger_common.h 2011-12-20 18:15:30 +0000
4483@@ -20,22 +20,15 @@
4484 #include "common/common.h"
4485
4486 /* Type definitions */
4487-typedef unsigned char StepCommand;
4488 typedef unsigned char ExecutionStatus;
4489 typedef unsigned short SuspensionCause;
4490
4491-/* Kind of step command */
4492-const StepCommand STEP_INTO = 0x01;
4493-const StepCommand STEP_OUT = 0x02;
4494-const StepCommand STEP_OVER = 0x03;
4495-
4496 /* Status of the engine */
4497 const ExecutionStatus QUERY_IDLE = 0x01;
4498 const ExecutionStatus QUERY_RUNNING = 0x02;
4499-const ExecutionStatus QUERY_RESUMED = 0x03;
4500-const ExecutionStatus QUERY_SUSPENDED = 0x04;
4501-const ExecutionStatus QUERY_TERMINATED = 0x05;
4502-const ExecutionStatus QUERY_DETACHED = 0x06;
4503+const ExecutionStatus QUERY_SUSPENDED = 0x03;
4504+const ExecutionStatus QUERY_TERMINATED = 0x04;
4505+const ExecutionStatus QUERY_DETACHED = 0x05;
4506
4507 /* Cause of the suspension of the engine */
4508 const SuspensionCause CAUSE_USER = 0x01;
4509
4510=== modified file 'src/debugger/debugger_commons.cpp'
4511--- src/debugger/debugger_commons.cpp 2011-06-22 11:19:07 +0000
4512+++ src/debugger/debugger_commons.cpp 2011-12-20 18:15:30 +0000
4513@@ -151,13 +151,11 @@
4514 theBreakCondition(0),
4515 theExecEval(false),
4516 theStepping(false)
4517-
4518 {
4519 theRuntime = NULL;
4520 theCurrentStaticContext = NULL;
4521 theCurrentDynamicContext = NULL;
4522 thePlanState = NULL;
4523- theDebugIteratorState = NULL;
4524 }
4525
4526 DebuggerCommons::~DebuggerCommons()
4527@@ -185,8 +183,6 @@
4528
4529 if(ar.is_serializing_out())
4530 thePlanState = NULL;
4531- if(ar.is_serializing_out())
4532- theDebugIteratorState = NULL;
4533 ar & theEvalItem;
4534 ar & theExecEval;
4535 ar & theStepping;
4536@@ -230,17 +226,98 @@
4537 }
4538
4539 unsigned int
4540-DebuggerCommons::addBreakpoint(const QueryLoc& aLocation, bool aEnabled)
4541+DebuggerCommons::addBreakpoint(String& aFileName, int aLine, bool aEnabled)
4542 {
4543- BreakableIdMap::iterator lIter = theBreakableIDs.find(aLocation);
4544+ QueryLoc lLocation;
4545+ lLocation.setLineBegin(aLine);
4546+ lLocation.setLineEnd(aLine);
4547+ lLocation.setFilename(aFileName.c_str());
4548+
4549+ // we make sure that the this location file name is aligned with the internal ones
4550+ // it must have a valid URI and a scheme (file://, http://, or https://)
4551+ adjustLocationFilePath(lLocation);
4552+
4553+ BreakableIdMap::iterator lIter = theBreakableIDs.find(lLocation);
4554+ unsigned int lId;
4555
4556 if (lIter == theBreakableIDs.end()) {
4557+ String lFileName = aFileName;
4558+ // be prepared to throw an exception
4559 std::stringstream lSs;
4560- lSs << "The breakpoint could not be set at line " << aLocation.getLineBegin()
4561- << " in file: " << aLocation.getFilename();
4562- throw lSs.str();
4563- }
4564- unsigned int lId = lIter->second;
4565+ lSs << "The breakpoint could not be set at line " << aLine
4566+ << " in file \"" << lFileName << "\"";
4567+
4568+ // let us then try some search before we fail, be good to the user and help him
4569+ // 1. first we check if he sent a file URI; in this case, sorry!
4570+ if (lFileName.find("file://") == 0) {
4571+ throw lSs.str();
4572+ }
4573+
4574+ // now we have to normalize if we hope to find something
4575+ lFileName = URIHelper::encodeFileURI(lFileName).str();
4576+ // remove the added file schema prefix
4577+ // TODO: maybe there is a better way to do this encoding
4578+ lFileName = lFileName.substr(8);
4579+
4580+ // 2. secondly we hope he gave us part of a path of a file
4581+ lIter = theBreakableIDs.begin();
4582+ String::size_type lFileNameSize = lFileName.size();
4583+ std::vector<std::pair<QueryLoc, int> > lFoundBreakables;
4584+ zorba::String lFirstBreakablePath;
4585+ while (lIter != theBreakableIDs.end()) {
4586+ // for now, only valid if on the breakable is on the same line as requested
4587+ // TODO: this could be improved if the user wants to add a breakpoint to a line
4588+ // INSIDE a breakable that spans over multiple lines
4589+ if (lIter->second != theMainModuleBreakableId && lIter->first.getLineBegin() == aLine) {
4590+ zorba::String lBreakablePath = lIter->first.getFilename().str();
4591+
4592+ // dies the given string matche any part in the breakable file name?
4593+ if (lBreakablePath.find(lFileName) != String::npos) {
4594+ // we found the fist candidate path
4595+ if (lFirstBreakablePath == "") {
4596+ lFirstBreakablePath = lBreakablePath;
4597+ }
4598+ // but stop as soon as we are reaching a second different path (report ambiguity)
4599+ else if (lFirstBreakablePath != lBreakablePath){
4600+ lSs.str("");
4601+ lSs << "The file name \"" << aFileName << "\" is ambiguous. "
4602+ << "I already found two potential files to set a breakpoint in line " << aLine
4603+ << ":" << std::endl << " " << lFirstBreakablePath << std::endl << " " << lBreakablePath;
4604+ throw lSs.str();
4605+ }
4606+
4607+ // Yes! We found one!
4608+ lFoundBreakables.push_back(std::pair<QueryLoc, int>(lIter->first, lIter->second));
4609+ }
4610+ }
4611+ lIter++;
4612+ }
4613+
4614+ // what should I say, not a very successful search :(
4615+ if (lFoundBreakables.size() == 0) {
4616+ throw lSs.str();
4617+ }
4618+
4619+ // TODO: The best solution would be for the debugger to enable all the
4620+ // matched breakables but the protocol can send back only one ID of the
4621+ // breakpoint set.
4622+
4623+ // so we have multiple breakables, get the first in line
4624+ // TODO: this does not catch multiple breakables starting in the same line
4625+ // so only one will be picked (depending how the translator generated them)
4626+ unsigned int lMinCol = lFoundBreakables.at(0).first.getColumnBegin();
4627+ lId = lFoundBreakables.at(0).second;
4628+ for (std::size_t i = 1; i < lFoundBreakables.size(); i++) {
4629+ if (lMinCol > lFoundBreakables.at(i).first.getColumnBegin()) {
4630+ lId = lFoundBreakables.at(i).second;
4631+ }
4632+ }
4633+ }
4634+ else {
4635+ lId = lIter->second;
4636+ }
4637+
4638+ // now we have a breakable, so set it accordingly
4639 theBreakables[lId].setSet(true);
4640 theBreakables[lId].setEnabled(aEnabled);
4641 return lId;
4642@@ -253,6 +330,12 @@
4643 return theBreakables[aId];
4644 }
4645
4646+BreakableVector
4647+DebuggerCommons::getBreakpoints()
4648+{
4649+ return theBreakables;
4650+}
4651+
4652 void
4653 DebuggerCommons::checkBreakpoint(unsigned int aId)
4654 {
4655@@ -338,6 +421,7 @@
4656 bool
4657 DebuggerCommons::hasToBreakAt(QueryLoc aLocation)
4658 {
4659+ // we make sure that this location file name is a valid URI and has a scheme (file://, http://, or https://)
4660 adjustLocationFilePath(aLocation);
4661
4662 BreakableIdMap::const_iterator lIter = theBreakableIDs.find(aLocation);
4663@@ -449,14 +533,6 @@
4664 ZORBA_ASSERT(thePlanState == aPlanState);
4665 }
4666
4667-void
4668-DebuggerCommons::setDebugIteratorState(DebugIteratorState* aState)
4669-{
4670- theDebugIteratorState = aState;
4671- //Check postconditions
4672- ZORBA_ASSERT(theDebugIteratorState == aState);
4673-}
4674-
4675 std::list<std::pair<zstring, zstring> >
4676 DebuggerCommons::eval(const zstring& aExpr, Zorba_SerializerOptions& aSerOpts)
4677 {
4678@@ -511,11 +587,17 @@
4679 }
4680
4681 void
4682-DebuggerCommons::addBreakable(Breakable& aBreakable)
4683+DebuggerCommons::addBreakable(
4684+ Breakable& aBreakable,
4685+ bool aIsMainModuleBreakable)
4686 {
4687+ // we make sure that this breakable file name is a valid URI and has a scheme (file://, http://, or https://)
4688 adjustLocationFilePath(aBreakable.getLocation());
4689
4690 unsigned int lId = theBreakables.size();
4691+ if (aIsMainModuleBreakable) {
4692+ theMainModuleBreakableId = lId;
4693+ }
4694 theBreakables.push_back(aBreakable);
4695 theBreakableIDs[aBreakable.getLocation()] = lId;
4696 }
4697@@ -523,6 +605,9 @@
4698 void
4699 DebuggerCommons::pushStackFrame(QueryLoc aLocation, std::string& aFunctionName)
4700 {
4701+ // we make sure that the stack frame locations always have valid URIs and a scheme (file://, http://, or https://)
4702+ adjustLocationFilePath(aLocation);
4703+
4704 theStackTrace.push_back(std::pair<QueryLoc, std::string>(aLocation, aFunctionName));
4705 }
4706
4707@@ -541,11 +626,24 @@
4708 void
4709 DebuggerCommons::adjustLocationFilePath(QueryLoc& aLocation)
4710 {
4711- if (aLocation.getFilename().substr(0, 7) == "file://") {
4712- // adjust the file paths by removing the schema and encoding
4713- zstring lOldFilename(aLocation.getFilename());
4714+ zstring lOldFilename(aLocation.getFilename());
4715+ zstring lPrefix = lOldFilename.substr(0, 7);
4716+
4717+ if (lPrefix == "file://") {
4718+#ifdef WIN32
4719+ // decode and encode back to solve the driver column encoding: C:, D:, etc.
4720 const String lNewFilename = URIHelper::decodeFileURI(lOldFilename.str());
4721- aLocation.setFilename(lNewFilename.str());
4722+ const String lNewURI = URIHelper::encodeFileURI(lNewFilename);
4723+ aLocation.setFilename(lNewURI.str());
4724+#endif
4725+ return;
4726+ }
4727+
4728+ // just encode and assume file for non-URI locations
4729+ if (lPrefix != "http://" && lPrefix != "https:/") {
4730+ const String lNewURI = URIHelper::encodeFileURI(lOldFilename.str());
4731+ aLocation.setFilename(lNewURI.str());
4732+ return;
4733 }
4734 }
4735
4736
4737=== modified file 'src/debugger/debugger_commons.h'
4738--- src/debugger/debugger_commons.h 2011-06-22 11:19:07 +0000
4739+++ src/debugger/debugger_commons.h 2011-12-20 18:15:30 +0000
4740@@ -19,14 +19,17 @@
4741 #include <map>
4742 #include <string>
4743
4744+#include <zorba/util/uri.h>
4745+#include <zorba/zorba_string.h>
4746+
4747 #include "compiler/parser/query_loc.h"
4748 #include "runtime/core/item_iterator.h"
4749
4750 #include "zorbaserialization/serialization_engine.h"
4751 #include "zorbatypes/zstring.h"
4752
4753-#include "debugger/debugger_common.h"
4754-#include "debugger/query_locationimpl.h"
4755+#include "debugger_common.h"
4756+#include "query_locationimpl.h"
4757
4758
4759 struct Zorba_SerializerOptions;
4760@@ -208,16 +211,6 @@
4761 void setPlanState(PlanState* aPlanState);
4762
4763 /**
4764- * @brief Sets the current debugger state.
4765- *
4766- * When the debugger suspends, it saves its state.
4767- *
4768- * @param aState a pointer to the current debugger state.
4769- * @post aState == theDebugIteratorState
4770- */
4771- void setDebugIteratorState(DebugIteratorState* aState);
4772-
4773- /**
4774 * @brief Sets a setpoint according to the step out rules.
4775 *
4776 * This method sets a breakpoint according to the rules according to
4777@@ -245,11 +238,14 @@
4778 public:
4779
4780 unsigned int
4781- addBreakpoint(const QueryLoc& location, bool enabled);
4782+ addBreakpoint(String& fileName, int line, bool enabled);
4783
4784 Breakable
4785 getBreakpoint(unsigned int id);
4786
4787+ BreakableVector
4788+ getBreakpoints();
4789+
4790 void
4791 updateBreakpoint(unsigned int id, bool enabled);
4792
4793@@ -336,7 +332,7 @@
4794 std::string getFilepathOfURI(const std::string& aUri) const;
4795
4796 void
4797- addBreakable(Breakable& location);
4798+ addBreakable(Breakable& location, bool isMainModuleBreakable = false);
4799
4800 void
4801 pushStackFrame(QueryLoc location, std::string& functionName);
4802@@ -384,10 +380,10 @@
4803 std::vector<DebugIterator*> theIteratorStack;
4804 std::size_t theBreakCondition;
4805 PlanState* thePlanState;
4806- DebugIteratorState* theDebugIteratorState;
4807 store::Item_t theEvalItem;
4808 bool theExecEval;
4809 bool theStepping;
4810+ unsigned int theMainModuleBreakableId;
4811 };
4812
4813 }
4814
4815=== modified file 'src/debugger/debugger_communicator.cpp'
4816--- src/debugger/debugger_communicator.cpp 2011-07-29 23:01:30 +0000
4817+++ src/debugger/debugger_communicator.cpp 2011-12-20 18:15:30 +0000
4818@@ -77,15 +77,15 @@
4819 void
4820 DebuggerCommunicator::connect()
4821 {
4822- for (int i = 0; i < 3 && !theSocket; i++)
4823+ for (int i = 0; i < 5 && !theSocket; i++)
4824 {
4825 try
4826 {
4827 // Connect to the client on the given host and port
4828 std::auto_ptr<TCPSocket> lSocket(new TCPSocket(theHost, thePort));
4829 theSocket = lSocket.release();
4830- theSocketInStream = new socket_streambuf(*theSocket);
4831- theSocketOutStream = new socket_streambuf(*theSocket);
4832+ theSocketInStream = new SocketStreambuf(*theSocket);
4833+ theSocketOutStream = new SocketStreambuf(*theSocket);
4834 theCommunicatorInStream = new std::istream(theSocketInStream);
4835 theCommunicatorOutStream = new std::ostream(theSocketOutStream);
4836 theResponseQueue = new ResponseQueue(theCommunicatorOutStream);
4837
4838=== modified file 'src/debugger/debugger_communicator.h'
4839--- src/debugger/debugger_communicator.h 2011-07-01 16:07:54 +0000
4840+++ src/debugger/debugger_communicator.h 2011-12-20 18:15:30 +0000
4841@@ -28,7 +28,7 @@
4842 namespace zorba {
4843
4844 class TCPSocket;
4845-class socket_streambuf;
4846+class SocketStreambuf;
4847
4848 class DebuggerCommunicator {
4849
4850@@ -96,13 +96,13 @@
4851
4852
4853 TCPSocket* theSocket;
4854- socket_streambuf* theSocketInStream;
4855- socket_streambuf* theSocketOutStream;
4856+ SocketStreambuf* theSocketInStream;
4857+ SocketStreambuf* theSocketOutStream;
4858 std::istream* theCommunicatorInStream;
4859 std::ostream* theCommunicatorOutStream;
4860 ResponseQueue* theResponseQueue;
4861 };
4862
4863-}//end of namespace
4864+} //namespace zorba
4865
4866 #endif // ZORBA_DEBUGGER_COMMUNICATOR_H
4867
4868=== modified file 'src/debugger/debugger_protocol.cpp'
4869--- src/debugger/debugger_protocol.cpp 2011-06-22 11:19:07 +0000
4870+++ src/debugger/debugger_protocol.cpp 2011-12-20 18:15:30 +0000
4871@@ -28,25 +28,17 @@
4872 DebuggerCommand::DebuggerCommand(std::string& aCommand)
4873 : theData()
4874 {
4875+ // this implements the DBGP command specification:
4876+ // http://xdebug.org/docs-dbgp.php#ide-to-debugger-engine-communications
4877+
4878+ // the debugger client should only send space delimited command
4879+ // and arguments, therefore we only check for space character
4880 std::size_t lNameEnd = aCommand.find(" ");
4881+
4882+ // first whitespace delimited token is the command name
4883 theName = aCommand.substr(0, lNameEnd);
4884- std::size_t lDataBegin = aCommand.find("--", lNameEnd);
4885- std::string lArgs = aCommand.substr(lNameEnd + 1, lDataBegin);
4886
4887- if (lDataBegin != std::string::npos) {
4888- lDataBegin += 2;
4889- while (lDataBegin < aCommand.size()) {
4890- switch (aCommand.at(lDataBegin)) {
4891- case ' ':
4892- case '\t':
4893- ++lDataBegin;
4894- continue;
4895- default:
4896- theData = aCommand.substr(lDataBegin);
4897- lDataBegin = aCommand.size();
4898- }
4899- }
4900- }
4901+ std::string lArgs = aCommand.substr(lNameEnd + 1);
4902
4903 bool lFollowsArg = true;
4904 bool lInArgName = false;
4905@@ -74,6 +66,26 @@
4906 lInArgName = true;
4907 continue;
4908 }
4909+ // we found the encoded data in this message
4910+ if (lArgName.str() == "") {
4911+ // DBGP is fuzzy here: can there be whitespaces between "--" and the encoded data?
4912+ // so, tollerate the whitespaces before data starts
4913+ std::string::size_type lDataBegin = i + 1;
4914+ while (++i < lArgs.size()) {
4915+ switch (lArgs.at(i)) {
4916+ case ' ':
4917+ case '\t':
4918+ continue;
4919+ default:
4920+ lDataBegin = i;
4921+ // force the while to terminate
4922+ i = lArgs.size();
4923+ }
4924+ }
4925+
4926+ theData = lArgs.substr(lDataBegin);
4927+ }
4928+
4929 default:
4930 if (!lInArgName) {
4931 throw "error reading command";
4932
4933=== modified file 'src/debugger/debugger_runtime.cpp'
4934--- src/debugger/debugger_runtime.cpp 2011-08-03 02:26:53 +0000
4935+++ src/debugger/debugger_runtime.cpp 2011-12-20 18:15:30 +0000
4936@@ -21,6 +21,7 @@
4937 #include <memory>
4938 #include <vector>
4939 #include <sstream>
4940+#include <iomanip>
4941 #include <fstream>
4942
4943 #include <zorba/util/uri.h>
4944@@ -70,7 +71,8 @@
4945 thePlanIsOpen(false),
4946 theSerializer(0),
4947 theItemHandler(aHandler),
4948- theCallbackData(aCallBackData)
4949+ theCallbackData(aCallBackData),
4950+ theLastContinuationCommand()
4951 {
4952 }
4953
4954@@ -122,7 +124,7 @@
4955 DebuggerRuntime::runQuery()
4956 {
4957 theLock.wlock();
4958- theExecStatus = theExecStatus == QUERY_SUSPENDED ? QUERY_RESUMED : QUERY_RUNNING;
4959+ theExecStatus = QUERY_RUNNING;
4960
4961 try {
4962 DebuggerCommons* lCommons = getDebbugerCommons();
4963@@ -144,33 +146,23 @@
4964 theOStream.flush();
4965 } catch (FlowCtlException&) {
4966 // Runtime correctly terminated by user interrupt
4967- } catch (ZorbaException const& e){
4968- // this does not rethrow but only print the error message
4969- ZorbaImpl::notifyError(theQuery->theDiagnosticHandler, e);
4970+ } catch (ZorbaException const& e) {
4971+ std::cerr << e << std::endl;
4972 }
4973 theLock.wlock();
4974 theExecStatus = QUERY_TERMINATED;
4975 theLock.unlock();
4976 }
4977
4978-
4979-void
4980-DebuggerRuntime::setQueryRunning()
4981-{
4982- AutoLock lLock(theLock, Lock::WRITE);
4983- assert(theExecStatus == QUERY_RESUMED);
4984- theExecStatus = QUERY_RUNNING;
4985-}
4986-
4987 // ****************************************************************************
4988 // Breakpoints
4989
4990 unsigned int
4991-DebuggerRuntime::addBreakpoint(const QueryLoc& aLocation, bool aEnabled)
4992+DebuggerRuntime::addBreakpoint(String& aFileName, int aLine, bool aEnabled)
4993 {
4994 AutoLock lLock(theLock, Lock::WRITE);
4995 DebuggerCommons* lCommons = getDebbugerCommons();
4996- return lCommons->addBreakpoint(aLocation, aEnabled);
4997+ return lCommons->addBreakpoint(aFileName, aLine, aEnabled);
4998 }
4999
5000 Breakable
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches