4 static uint TokenizeList(char * string, const uint maxTokens, const char seperator, char * tokens[])
9 bool quoted = false; //bool escaped = false;
12 for(; *string && count < maxTokens; string++)
21 else if(*string == '\"')
23 else if(*string == '{' || *string == '[' || *string == '(' || *string == '<')
25 else if(*string == '}' || *string == ']' || *string == ')' || *string == '>')
27 else if(*string == seperator && !level)
29 tokens[count++] = start;
34 if(start && count < maxTokens)
36 tokens[count++] = start;
42 // String Unescape Copy
43 // TOFIX: THIS DOESN'T HANDLE NUMERIC ESCAPE CODES (OCTAL/HEXADECIMAL...)?
44 // Seems very similar to ReadString in pass15.ec (which also misses numeric escape codes :) )
45 static void struscpy(char * d, char * s)
97 static char * StripBrackets(char * string)
99 int length = strlen(string);
100 if(length > 1 && *string == '[' && string[length - 1] == ']')
103 string[length - 1] = '\0';
110 static char * StripCurlies(char * string)
112 int length = strlen(string);
113 if(length > 1 && *string == '{' && string[length - 1] == '}')
116 string[length - 1] = '\0';
123 class TempListItem : struct
129 static bool TokenizeListItem(char * string, TempListItem item)
131 char * equal = strstr(string, "=");
145 class Output : struct
158 class Command : struct
169 outputs.Free(Output::Free);
173 /*class TreeStackItem : struct
180 class TagButton : public Button
185 class GDBDialog : Window
187 text = $"GDB Command";
188 background = formColor;
189 borderStyle = sizable;
202 this, direction = horizontal, gap = 0;
203 isActiveClient = true;
204 background = darkGray;//formColor
205 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
212 bg, this, gap = 4, margin = 4 ;
213 isActiveClient = true;
214 background = darkGray;
216 anchor = { top = 0, bottom = 0 };
221 PaneSplitter splitter
223 this, leftPane = leftCol, rightPane = rightCol, split = 200;
228 bg, this, gap = 4, margin = 4;
229 isActiveClient = true;
230 background = darkGray;
232 anchor = { top = 0, bottom = 0 };
237 Label lhistory { leftCol, this, position = { 4, 4 }, labeledWindow = history };
240 leftCol, this, borderStyle = deep, hasVertScroll = true, hasHorzScroll = true;
241 // selectionColor = unfocusedSelectorColor;
242 fullRowSelect = true, alwaysHighLight = true;
245 anchor = { left = leftCol.margin, right = leftCol.margin };
246 text = $"Command History";
248 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
252 lastCommand = (Command)(intptr)row.tag;
253 command.contents = lastCommand.command;
260 Label commandLabel { rightCol, this, position = { 4, 4 }, labeledWindow = command };
263 rightCol, this, text = $"Command:", size = { 328, 19 }, anchor = { left = rightCol.margin, right = rightCol.margin };
265 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
267 if((SmartKey)key == up || (SmartKey)key == down)
271 bool previous = ((SmartKey)key == up);
274 lastCommand = previous ? commands.last : commands.first;
276 lastCommand = previous ? lastCommand.prev : lastCommand.next;
280 command.contents = lastCommand.command;
284 lastCommand = previous ? commands.first : commands.last;
287 else if((SmartKey)key == enter)
288 OnCommand(command.contents);
295 rightCol, this, direction = horizontal, gap = 4;
296 isActiveClient = true;
297 background = darkGray;
299 anchor = { left = rightCol.margin, right = rightCol.margin };
302 TagButton infoLibs { toolBar, this, text = "libs", tag = "info shared", NotifyClicked = QuickCommandNotifyClicked; };
303 TagButton infoPaths { toolBar, this, text = "paths", tag = "-environment-path", NotifyClicked = QuickCommandNotifyClicked; };
304 TagButton infoWorkDir { toolBar, this, text = "wd", tag = "-environment-pwd", NotifyClicked = QuickCommandNotifyClicked; };
305 TagButton infoDirs { toolBar, this, text = "pths", tag = "-environment-directory", NotifyClicked = QuickCommandNotifyClicked; };
306 TagButton infoTemp { toolBar, this, text = "pths", tag = "-environment-temp", NotifyClicked = QuickCommandNotifyClicked; };
308 bool QuickCommandNotifyClicked(Button button, int x, int y, Modifiers mods)
310 TagButton tagButton = (TagButton)button;
311 OnCommand(tagButton.tag);
315 Label outputLabel { rightCol, this, position = { 4, 4 }, labeledWindow = output };
318 rightCol, this, text = $"Output:", multiLine = true, hasVertScroll = true, hasHorzScroll = true;
320 anchor = { left = rightCol.margin, right = rightCol.margin };
321 font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic };
324 Label treeLabel { rightCol, this, position = { 4, 4 }, labeledWindow = tree };
327 rightCol, this, text = $"Tree:";
328 multiSelect = false, fullRowSelect = false, hasVertScroll = true, hasHorzScroll = true;
329 borderStyle = deep, collapseControl = true, treeBranches = true;
330 anchor = { left = rightCol.margin, right = rightCol.margin };
331 font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic };
338 for(out = lastCommand.outputs.first; out; out = out.next)
340 output.AddS(out.output);
348 if(lastCommand && lastCommand.outputs.first)
351 int i, j, outTksCount, subTksCount;
352 char * outTokens[3200], * subTokens[3200];
353 DataRow root, frame, row;
354 TempListItem item { };
358 root = tree.AddString("Output");
360 for(out = lastCommand.outputs.first; out; out = out.next)
362 if(out.output && out.output[0])
364 t = CopyString(out.output);
370 outTksCount = TokenizeList(s, sizeof(outTokens) / sizeof(char *), ',', outTokens);
371 row = root.AddString(outTokens[0]);
372 if(!strcmp(outTokens[0], "^done"))
374 for(i = 1; i < outTksCount; i++)
376 if(TokenizeListItem(outTokens[i], item))
378 if(!strcmp(item.name, "bkpt"))
380 row = root.AddString(item.name);
381 item.value = StripCurlies(item.value);
382 subTksCount = TokenizeList(item.value, sizeof(subTokens) / sizeof(char *), ',', subTokens);
383 for(j = 0; j < subTksCount; j++)
385 if(TokenizeListItem(subTokens[j], item))
386 UpdateTreeValue(item, row);
388 row.AddString("Bad");
391 else if(!strcmp(item.name, "stack"))
393 row = root.AddString(item.name);
394 item.value = StripBrackets(item.value);
395 subTksCount = TokenizeList(item.value, sizeof(subTokens) / sizeof(char *), ',', subTokens);
396 for(j = 0; j < subTksCount; j++)
398 if(TokenizeListItem(subTokens[j], item))
400 frame = row.AddString(item.name);
401 if(!strcmp(item.name, "frame"))
402 UpdateTreeFrame(item, frame);
404 UpdateTreeValue(item, row);
407 row.AddString("Bad");
410 else if(!strcmp(item.name, "path"))
412 StripQuotes(item.value, item.value);
413 subTksCount = TokenizeList(item.value, sizeof(subTokens) / sizeof(char *), ':', subTokens);
414 for(j = 0; j < subTksCount; j++)
416 row = root.AddString(subTokens[j]);
420 UpdateTreeValue(item, row);
423 row.AddString("Bad");
426 else if(!strcmp(outTokens[0], "^running"))
429 row.AddString(outTokens[1]);
431 else if(!strcmp(outTokens[0], "^exit"))
434 row.AddString(outTokens[1]);
436 else if(!strcmp(outTokens[0], "^error"))
439 row.AddString(outTokens[1]);
443 row = row.AddString("Unknown output");
445 row.AddString(outTokens[1]);
449 outTksCount = TokenizeList(s, sizeof(outTokens) / sizeof(char *), ',', outTokens);
450 row = root.AddString(outTokens[0]);
452 row = root.AddString("Unknown status-async-output");
457 outTksCount = TokenizeList(s, sizeof(outTokens) / sizeof(char *), ',', outTokens);
458 row = root.AddString(outTokens[0]);
459 //if(!strcmp(outTokens[0], "=thread-group-created")) //=thread-group-created,id="7611"
460 //else if(!strcmp(outTokens[0], "=thread-created")) //=thread-created,id="1",group-id="7611"
461 //else if(!strcmp(outTokens[0], "=library-loaded")) //=library-loaded,id="/lib/ld-linux.so.2",target-name="/lib/ld-linux.so.2",host-name="/lib/ld-linux.so.2",symbols-loaded="0"
462 if(!strcmp(outTokens[0], "=thread-group-created") || !strcmp(outTokens[0], "=thread-created") || !strcmp(outTokens[0], "=library-loaded"))
464 for(i = 1; i < outTksCount; i++)
465 row.AddString(outTokens[i]);
469 row = root.AddString("Unknown notify-async-output");
474 outTksCount = TokenizeList(s, sizeof(outTokens) / sizeof(char *), ',', outTokens);
475 row = root.AddString(outTokens[0]);
476 if(!strcmp(outTokens[0], "*stopped"))
478 for(i = 1; i < outTksCount; i++)
480 if(TokenizeListItem(outTokens[i], item))
482 if(!strcmp(item.name, "frame"))
484 frame = row.AddString(item.name);
485 UpdateTreeFrame(item, frame);
487 UpdateTreeValue(item, row);
490 row.AddString("Bad");
495 row = root.AddString("Unknown exec-async-output");
497 row.AddString(outTokens[1]);
501 if(!strcmpi(s, "(gdb) "))
507 row = root.AddString("Unknown prompt");
514 if(TrimEscapedNewLineChar(s))
516 s = StripBrackets(s);
517 if(!strncmp(s, "Executable and object file path: ", 33))
520 outTksCount = TokenizeList(s, sizeof(outTokens) / sizeof(char *), ':', outTokens);
521 for(i = 0; i < outTksCount; i++)
523 row = root.AddString(outTokens[i]);
533 if(TrimEscapedNewLineChar(s))
540 row = root.AddString("Unknown output");
551 void UpdateTreeValue(TempListItem item, DataRow row)
554 StripQuotes(item.value, item.value);
555 string = new char[strlen(item.name) + strlen(item.value) + 3];
556 sprintf(string, "%s: %s", item.name, item.value);
557 row.AddString(string);
561 void UpdateTreeFrame(TempListItem item, DataRow frame)
563 int k, l, m, frameTksCount, argsTksCount, mTksCount;
564 char * frameTokens[3200], * argsTokens[3200], * mTokens[3200];
566 item.value = StripCurlies(item.value);
567 frameTksCount = TokenizeList(item.value, sizeof(frameTokens) / sizeof(char *), ',', frameTokens);
568 for(k = 0; k < frameTksCount; k++)
570 if(TokenizeListItem(frameTokens[k], item))
572 if(!strcmp(item.name, "level"))
575 StripQuotes(item.value, item.value);
576 string = new char[strlen(item.value) + strlen(frame.string) + 7];
577 // WTH do I need to do in order to print with leading zeros
578 sprintf(string, "%d %s", atoi(item.value), frame.string);
579 frame.string = string;
582 else if(!strcmp(item.name, "addr"))
585 StripQuotes(item.value, item.value);
586 string = new char[strlen(item.value) + strlen(frame.string) + 4];
587 sprintf(string, "%s (%s)", frame.string, item.value);
588 frame.string = string;
591 else if(!strcmp(item.name, "args"))
594 args = frame.AddString("args");
595 item.value = StripBrackets(item.value);
596 argsTksCount = TokenizeList(item.value, sizeof(argsTokens) / sizeof(char *), ',', argsTokens);
597 for(l = 0; l < argsTksCount; l++)
599 arg = args.AddString("arg");
600 argsTokens[l] = StripCurlies(argsTokens[l]);
601 mTksCount = TokenizeList(argsTokens[l], sizeof(mTokens) / sizeof(char *), ',', mTokens);
602 for(m = 0; m < mTksCount; m++)
604 if(TokenizeListItem(mTokens[m], item))
606 if(!strcmp(item.name, "name"))
609 StripQuotes(item.value, item.value);
610 string = new char[strlen(arg.string) + strlen(item.value) + 2];
611 sprintf(string, "%s %s", arg.string, item.value);
615 else if(!strcmp(item.name, "value"))
618 StripQuotes(item.value, item.value);
619 string = new char[strlen(arg.string) + strlen(item.value) + 4];
620 sprintf(string, "%s = %s", arg.string, item.value);
625 UpdateTreeValue(item, args);
628 frame.AddString("Bad");
633 UpdateTreeValue(item, frame);
636 frame.AddString("Bad");
640 int TrimEscapedNewLineChar(char * s)
643 if(s[len - 1] == 'n' && s[len - 2] == '\\')
651 void AddCommand(char * string)
653 if(string && strlen(string))
655 Command cmd = Command { command = CopyString(string) };
657 history.AddString(string).tag = (uint64)(uintptr)cmd;
658 lastCommand = commands.last;
662 command.contents = string;
668 void AddOutput(char * string)
670 if(string && strlen(string))
672 Command last = commands.last;
675 last.outputs.Add(Output { output = CopyString(string) });
676 if(last == lastCommand)
682 virtual void OnCommand(const char * string);
696 command.contents = lastCommand.command;
704 commands.Free(Command::Free);