1) Although dbg will be dropped from being supported or bundled with PHPeclipse,...
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / model / PHPDBGEvalString.java
1 package net.sourceforge.phpdt.internal.debug.core.model;
2
3 /*
4  * Created on 17.04.2004
5  *
6  * To change the template for this generated file go to
7  * Window - Preferences - Java - Code Generation - Code and Comments
8  */
9 /**
10  * @author Chris Admin
11  *
12  * To change the template for this generated type comment go to
13  * Window - Preferences - Java - Code Generation - Code and Comments
14  */
15
16 import java.util.Vector;
17
18 import net.sourceforge.phpdt.internal.debug.core.PHPDebugCorePlugin;
19
20 import org.eclipse.core.runtime.Status;
21 import org.eclipse.debug.core.DebugException;
22
23 /**
24  *
25  */
26 public class PHPDBGEvalString {
27
28         String                            workStr;
29         private PHPStackFrame fStackFrame;
30
31         /**
32          *
33          */
34         public PHPDBGEvalString(PHPStackFrame stack, String dataStr) {
35                 fStackFrame = stack;
36                 workStr = dataStr;
37         }
38
39         /**
40          *
41          * @param chstart
42          * @param chend
43          * @param startIdx
44          * @return
45          */
46         String ExtractSubStr (char chstart, char chend, int startIdx) throws DebugException {
47                 int     idx;
48                 int     i;
49                 String  rslt;
50                 Status  status;
51
52                 idx = startIdx;
53
54                 if (idx >= (workStr.length () - 1) ||
55                     workStr.charAt (idx) != chstart) {
56                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "worng startIdx!", null);
57
58                         throw new DebugException (status);
59                 }
60
61                 i = ++idx;
62                 i = workStr.indexOf(chend, i);
63
64                 if (i == -1) {
65                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "endchar not found!", null);
66
67                         throw new DebugException (status);
68                 }
69                 rslt    = workStr.substring (idx, i);
70                 workStr = workStr.substring (i + 1);
71
72                 return rslt;
73         }
74
75         /**
76          * @param slen
77          * @param startIdx
78          * @return
79          */
80         String ExtractQuotedSubStr (int slen, int startIdx) throws DebugException {
81                 int     idx;
82                 String  rslt;
83                 Status  status;
84
85                 idx = startIdx;
86
87                 if ((idx + slen + 1) >= workStr.length () ||
88                                 workStr.charAt (idx)!= '"' ||
89                                 workStr.charAt (idx + slen + 1) != '"') {
90                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "no quoted substring found!", null);
91
92                         throw new DebugException (status);
93                 }
94
95                 rslt    = workStr.substring (idx + 1, idx + 1 + slen);
96                 workStr = workStr.substring (idx + 2 + slen);
97
98                 return rslt;
99         }
100
101         /**
102          *
103          * @param chstart
104          * @param chend
105          * @apram startIdx
106          * @return
107          */
108         int ExtractInt (char chstart, char chend, int startIdx) throws DebugException {
109                 String  subs;
110
111                 subs = ExtractSubStr (chstart, chend, startIdx);
112
113                 return (Integer.parseInt (subs));
114         }
115
116         /**
117          * @param name
118          * @param parent
119          * @param list       The list of PHPVariables
120          * @param var_list
121          * @param classname
122          * @param atype      The type of the variable (Either PEVT_ARRAY or PEVT_OBJECT)
123          * @return
124          */
125         PHPVariable ParseEvalArray (String name, PHPVariable parent, Vector list, Vector var_list, String classname, int atype)  throws DebugException {
126                 long            arritems;                                                                               // The number of items (or fields or entries) for the array (or short, array size)
127                 PHPVariable item;
128                 Vector          subitems = null;
129                 Status      status;
130
131                 arritems = ExtractInt (':', ':', 0);                                            // Get the number of items/fields for the array
132                                                                                                                                         // E.g. :12: means there are 12 entries in array
133
134                 if ((workStr.length () > 0) &&                              // Is there still something to parse?
135                     (workStr.charAt (0) != '{')) {                          // And the next character is not a '{', then output an error
136                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "no array startcharacter!", null);
137
138                         throw new DebugException (status);
139                 }
140
141                 workStr = workStr.substring (1);                            // Remove the '{'
142                 item    = new PHPVariable (fStackFrame, name, parent, classname, atype, null);  // Create a new (empty) PHPVariable
143
144                 list.add (item);                                            // Add the newly created PHPVariable to list
145
146                 if (var_list != null) {                                     //
147                         var_list.add (item);                                    // Add the PHPVariable also to the var_list
148                 }
149
150                 if (arritems > 0) {                                         // If the array is not empty
151                         subitems = new Vector ();                               // Create a new child variable list for the array
152                 } else if (workStr.charAt (0) != '}') {                     // If the array is empty the next character has to be '}'
153                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "no array endcharacter!", null);
154
155                         throw new DebugException (status);
156                 }
157
158                 while ((workStr.length () > 0) &&                           // Is there still something to parse?
159                        (workStr.charAt (0) != '}')) {                       // And the next character is not '}'
160                         Vector tmplst = new Vector ();                          // Create a temporary list
161
162                         parse ("", null, tmplst, null, false, 0);               // And parse the string for the array's name.
163
164                         if (tmplst.size () != 1) {                              // Parsing should return exactly on entry (which is the name)
165                                 status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "no name found!", null);
166
167                                 throw new DebugException (status);
168                         }
169                                                                                                                                         // Go for the array values
170                         parse (((PHPVariable) tmplst.elementAt (0)).getValue ().getValueString (), item, subitems, var_list, true, 0);
171                 }
172
173                 ((PHPValue) item.getValue ()).addVariable (subitems);       // Append the list of all child variables to this PHPVariables PHPValue
174                 workStr = workStr.substring (1);                            // Remove the '}'
175
176                 return item;                                                // And return the PHPVariable we just build
177         }
178
179         /**
180          *
181          * @param name
182          * @param parent
183          * @param list
184          * @param var_list
185          * @param startIdx
186          */
187         void ParseEvalNULL (String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException {
188                 int             idx;
189                 PHPVariable item;
190                 Status          status;
191
192                 idx = startIdx;
193
194                 if ((idx >= workStr.length ()) ||
195                     (workStr.charAt (idx) != ';')) {
196                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "NULL not found!", null);
197
198                         throw new DebugException(status);
199                 }
200
201                 workStr = workStr.substring (1);
202                 item    = new PHPVariable (fStackFrame, name, parent, "NULL", PHPValue.PEVT_UNKNOWN, null);
203
204                 list.add (item);
205
206                 if (var_list != null) {
207                         var_list.add (item);
208                 }
209         }
210
211         /**
212          *
213          * @param name
214          * @param parent
215          * @param list
216          * @param var_list
217          * @param startIdx
218          */
219         boolean ParseEvalInt (String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException {
220                 String          subs;
221                 PHPVariable item;
222
223                 subs = ExtractSubStr (':', ';', startIdx);
224                 item = new PHPVariable (fStackFrame, name, parent, subs, PHPValue.PEVT_LONG, null);
225
226                 list.add (item);
227
228                 if (var_list != null) {
229                         var_list.add (item);
230                 }
231
232                 return true;
233         }
234
235         /**
236          *
237          * @param name
238          * @param parent
239          * @param list
240          * @param var_list
241          * @param startIdx
242          */
243         boolean ParseEvalDouble (String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException {
244                 String          subs;
245                 PHPVariable item;
246
247                 subs = ExtractSubStr (':', ';', startIdx);
248                 item = new PHPVariable (fStackFrame, name, parent, subs, PHPValue.PEVT_DOUBLE, null);
249
250                 list.add (item);
251
252                 if (var_list != null) {
253                         var_list.add (item);
254                 }
255
256                 return true;
257         }
258
259         /**
260          *
261          * @param name
262          * @param parent
263          * @param list
264          * @param var_list
265          * @param MakePhpStr
266          * @param startIdx
267          */
268         boolean ParseEvalString (String name, PHPVariable parent, Vector list, Vector var_list, boolean MakePhpStr, int startIdx)
269                                         throws DebugException {
270                 int                     slen;
271                 Status          status;
272                 String          subs;
273                 PHPVariable item;
274
275                 slen = ExtractInt( ':', ':',startIdx);
276
277                 if ((workStr.length () <= slen) ||
278                     (workStr.charAt (0) != '"')) {
279                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (), Status.OK, "no String startcharecter!", null);
280
281                         throw new DebugException (status);
282                 }
283
284                 workStr = workStr.substring (1);
285                 subs    = workStr.substring (0, slen);
286
287                 // replace \\ with \
288                 subs = subs.replaceAll ("\\\\\\\\","\\\\");
289
290                 if (workStr.charAt (slen) != '"') {
291                         status = new Status (Status.ERROR, PHPDebugCorePlugin.getUniqueIdentifier (),Status.OK, "no String endcharecter!", null);
292                         throw new DebugException (status);
293                 }
294
295                 workStr = workStr.substring (slen + 2);
296
297 /*              if (MakePhpStr) {
298                         ConvertToPhpString(subs, &subs);
299                 }
300 */
301                 item = new PHPVariable (fStackFrame, name, parent, subs, PHPValue.PEVT_STRING, null);
302
303                 list.add (item);
304
305                 if (var_list != null) {
306                         var_list.add (item);
307                 }
308
309                 return true;
310         }
311
312         /**
313          *
314          * @param name
315          * @param parent
316          * @param list
317          * @param var_list
318          * @param startIdx
319          */
320         boolean ParseEvalBool (String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException {
321                 long            v;
322                 PHPVariable item;
323
324                 v    = ExtractInt (':', ';', startIdx);
325                 item = new PHPVariable (fStackFrame, name, parent, (v==0) ? ("FALSE") : ("TRUE"), PHPValue.PEVT_BOOLEAN, null);
326
327                 list.add (item);
328
329                 if (var_list != null) {
330                         var_list.add (item);
331                 }
332
333                 return true;
334         }
335
336         /**
337          *
338          * @param name
339          * @param parent
340          * @param list
341          * @param var_list
342          * @param startIdx
343          */
344         boolean ParseEvalObject (String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException {
345                 int             slen;
346                 String  classname;
347
348                 slen      = ExtractInt (':', ':', startIdx);
349                 classname = ExtractQuotedSubStr (slen, startIdx);
350
351                 if ((int) classname.length () != slen) {
352                         return false;
353                 }
354
355                 ParseEvalArray (name,parent, list, var_list, classname,PHPValue.PEVT_OBJECT);
356
357                 return true;
358         }
359
360         /**
361          *
362          * @param name
363          * @param parent
364          * @param list
365          * @param var_list
366          * @param startIdx
367          */
368         boolean ParseEvalResource (String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException {
369                 PHPVariable item;
370                 int                     slen;
371                 String          restype;
372                 String          val;
373
374                 slen    = ExtractInt (':', ':', startIdx);
375                 restype = ExtractQuotedSubStr (slen, startIdx);
376                 val     = ExtractSubStr (':', ';', startIdx);
377
378                 item = new PHPVariable (fStackFrame, name, parent, restype + ":" + val, PHPValue.PEVT_RESOURCE, null);
379
380                 list.add (item);
381
382                 if (var_list != null) {
383                         var_list.add (item);
384                 }
385
386                 return true;
387         }
388
389
390         /**
391          *
392          * @param name
393          * @param parent
394          * @param list
395          * @param var_list
396          * @param startIdx
397          */
398         private boolean ParseEvalRef (String name, PHPVariable parent, Vector list,
399                                                                   Vector var_list, boolean isSoftRef, int startIdx
400                                                                   ) throws DebugException {
401                 int         v;            // The ref ID (index into vector list)
402                 PHPVariable item;
403                 PHPVariable var_item;
404
405                 v    = ExtractInt (':', ';', startIdx);
406                 item = new PHPVariable (fStackFrame, name, parent, "",
407                                                 isSoftRef ? PHPValue.PEVT_SOFTREF : PHPValue.PEVT_REF, null);
408                 v--;                                                        // ref ID is 1-based, EvalList is 0-based
409
410                 if ((var_list == null) ||
411                     (v < 0) || (v >= var_list.size ())) {                   // Check ref ID (index) bounds
412                         //item.ref = item; // self-resolving
413                         return true;
414                 }
415                 else {
416 // This is the original code without the problems of stackframe overflow
417                         var_item = (PHPVariable) var_list.get (v);              // Get the variable from the list of all variables
418
419                         try {
420                                 item.setValue (var_item.getValue ());
421                                 item.setReferenceType (var_item.getReferenceType ());
422 //                              ((PHPValue) item.getValue ()).setParent (item);     // Set the new variable as parent for all child variables
423                         } catch (DebugException e) {
424                                 // TODO Auto-generated catch block
425                                 e.printStackTrace ();
426                         }
427
428                         list.add (item);
429
430 /*************
431  * this code produces a stackframe overflow if the reference contains loop references
432                         var_item = (PHPVariable) var_list.get (v);              // Get the referenced variable from the list of variables
433
434                         PHPValue new_val = (PHPValue) var_item.getValue ();
435
436                         if (isSoftRef) {
437                                 // expand reduced structure to full tree
438                                 // each value must have its appropriate parent
439                                 try {
440                                         new_val = copyItems (new_val, 0);               // Copy the child variables to the new referenced variable
441                                 } catch (CloneNotSupportedException e) {
442                                         // never occurs
443                                 }
444                         }
445
446                         try {
447                                 //item.setValue(var_item.getValue());
448                                 //item.setReferenceType(var_item.getReferenceType());
449                                 //((PHPValue) item.getValue()).setParent(item);
450                                 item.setValue (new_val);
451                                 item.setReferenceType (var_item.getReferenceType ());
452                                 new_val.setParent (item);
453                         } catch (DebugException e) {
454                                 // never occurs
455                         }
456
457                         list.add (item);
458  */
459                 }
460
461                 return true;
462         }
463
464         /**
465          *
466          * @return The array of PHPVariables
467          */
468         public PHPVariable[] getVars() {
469                 Vector list = new Vector();
470                 Vector var_list = new Vector();
471
472                 parse("", null, list, var_list, false, 0);
473
474                 return (PHPVariable[]) list.toArray(new PHPVariable[list.size()]); // Convert the list to an array and return the array
475         }
476
477         /**
478          *
479          * @return The PHPVariables as list
480          */
481         public Vector getVariables() {
482                 Vector list = new Vector();
483                 Vector var_list = new Vector();
484
485                 parse("", null, list, var_list, false, 0);
486
487                 //debugDump(list, "");
488                 return list; // return the PHPVariable list
489         }
490
491         /**
492          *
493          *
494          *
495          * @param name        The name of the PHPVariable
496          * @param parent      The PHPVariable to which this parsing belongs
497          * @param list
498          * @param var_list
499          * @param MakePhpStr
500          * @param startIdx
501          */
502         boolean parse (String name, PHPVariable parent, Vector list, Vector var_list, boolean MakePhpStr, int startIdx) {
503                 boolean ret_val = false;
504                 char    ch;
505
506                 if (startIdx >= workStr.length ()) {                        // Is there something to parse
507                         return false;                                           // No, then leave here
508                 }
509
510                 ch              = workStr.charAt (startIdx);                        // The first character denotes the type of variable
511                 workStr = workStr.substring (1);                            // Remove the 'variable type' character
512
513                 try {
514                         switch (ch) {                                           // Switch according the 'variable type'
515                                 case 'N': ParseEvalNULL         (name, parent, list, var_list, startIdx);                                break;
516                                 case 'i': ParseEvalInt          (name, parent, list, var_list, startIdx);                                break;
517                                 case 'd': ParseEvalDouble       (name, parent, list, var_list, startIdx);                                break;
518                                 case 's': ParseEvalString       (name, parent, list, var_list, MakePhpStr, startIdx);    break;
519                                 case 'a': ParseEvalArray        (name, parent, list, var_list, "", PHPValue.PEVT_ARRAY); break;
520                                 case 'O': ParseEvalObject       (name, parent, list, var_list, startIdx);                                break;
521                                 case 'b': ParseEvalBool         (name, parent, list, var_list, startIdx);                                break;
522                                 case 'z': ParseEvalResource (name, parent, list, var_list, startIdx);                            break;
523                                 case 'R': ParseEvalRef          (name, parent, list, var_list, false, startIdx);                 break;
524                                 case 'r': ParseEvalRef          (name, parent, list, var_list, true, startIdx);                  break;
525                                 case '?': ParseEvalUnknown(name, parent, list, var_list, startIdx);                                      break;
526                         }
527                 } catch (DebugException e) {
528                         PHPDebugCorePlugin.log(e);
529                 }
530
531 /*              if (!ret_val) { // try to recover
532                         unsigned int i=*startIdx;
533                         while (i<str.length() && str[i]!='{' && str[i]!=';') i++;
534                         if (i<str.length() && str[i] == '{') {
535                                 unsigned int cnt=1;
536                                 i++;
537                                 while (i<str.length() && cnt!=0) {
538                                         if (str[i] == '{')
539                                                 cnt++;
540                                         else if (str[i] == '}')
541                                                 cnt--;
542                                         i++;
543                                 }
544                         }
545                         *startIdx = i;
546                 }
547 */
548                 return  ret_val;                                                                                        // Always false
549         }
550
551         /*
552          *
553          */
554         private void ParseEvalUnknown(String name, PHPVariable parent, Vector list,
555                         Vector var_list, int startIdx) throws DebugException {
556
557                 if ((startIdx >= workStr.length()) || (workStr.charAt(startIdx) != ';')) {
558                         Status status = new Status(Status.ERROR, PHPDebugCorePlugin
559                                         .getUniqueIdentifier(), Status.OK, "unexpected response",
560                                         null);
561                         throw new DebugException(status);
562                 }
563
564                 workStr = workStr.substring(1);
565                 PHPVariable item = new PHPVariable(fStackFrame, name, parent, "?",
566                                 PHPValue.PEVT_UNKNOWN, null);
567                 list.add(item);
568                 if (var_list != null) {
569                         var_list.add(item);
570                 }
571         }
572
573         /*
574          * Copy referenced items tree
575          *
576          * @note We have to take care of recursion. We have to stop on recursion else
577          * we get a stack overflow!
578          *
579          * @param val The variable for which we build the tree of all childs
580          */
581         private PHPValue copyItems (PHPValue val, int nDepth) throws CloneNotSupportedException {
582                 PHPValue newVal   = (PHPValue) val.clone();
583                 Vector   vars     = newVal.getChildVariables();
584                 Vector   newVars  = new Vector();
585
586                 nDepth++;
587
588                 if (nDepth >= 10) {                                         // A very quick and very dirty way to avoid stack overflow
589                         return newVal;
590                 }
591
592                 for (int i = 0; i < vars.size(); i++) {
593                         PHPVariable newVar = (PHPVariable) ((PHPVariable) vars.get(i)).clone();
594
595                         try {
596                                 newVar.setValue (copyItems ((PHPValue) newVar.getValue(), nDepth));
597                         } catch (DebugException e) {
598                                 // never occurs
599                         }
600
601                         newVars.add (newVar);
602                 }
603
604                 val.setVariables (newVars);
605
606                 return newVal;
607         }
608
609 //      private void debugDump(Vector list, String indent) {
610 //              for (int i = 0; i < list.size(); i++) {
611 //                      PHPVariable var = (PHPVariable) list.get(i);
612 //                      System.out.print(indent + var.getName());
613 //                      PHPValue val = (PHPValue) var.getValue();
614 //                      try {
615 //                              if (val.hasVariables() && !var.getName().equals("['GLOBALS']")) {
616 //                                      System.out.println();
617 //                                      debugDump(val.getChildVariables(), indent + "    ");
618 //                              } else {
619 //                                      PHPVariable parent = var.getParent();
620 //                                      System.out.println(val.getValueString() + " \t>>" + (parent == null ? "null" : parent.getLongName()));
621 //                              }
622 //                      } catch (DebugException e) {
623 //                              e.printStackTrace();
624 //                      }
625 //              }
626 //      }
627 }