198 _iconsole_color_error = 3; |
191 _iconsole_color_error = 3; |
199 _iconsole_color_warning = 13; |
192 _iconsole_color_warning = 13; |
200 _iconsole_color_debug = 5; |
193 _iconsole_color_debug = 5; |
201 _iconsole_color_commands = 2; |
194 _iconsole_color_commands = 2; |
202 _iconsole_scroll = ICON_BUFFER; |
195 _iconsole_scroll = ICON_BUFFER; |
203 _iconsole_historypos = ICON_HISTORY_SIZE - 1; |
196 _iconsole_cmdbufferpos = ICON_CMDBUF_SIZE - 1; |
204 _iconsole_inited = true; |
197 _iconsole_inited = true; |
205 _iconsole_mode = ICONSOLE_CLOSED; |
198 _iconsole_mode = ICONSOLE_CLOSED; |
206 _iconsole_win = NULL; |
199 _iconsole_win = NULL; |
207 |
200 |
208 #ifdef ENABLE_NETWORK /* Initialize network only variables */ |
201 #ifdef ENABLE_NETWORK /* Initialize network only variables */ |
209 _redirect_console_to_client = 0; |
202 _redirect_console_to_client = 0; |
210 #endif |
203 #endif |
211 |
204 |
212 memset(_iconsole_history, 0, sizeof(_iconsole_history)); |
205 memset(_iconsole_cmdbuffer, 0, sizeof(_iconsole_cmdbuffer)); |
213 memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer)); |
206 memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer)); |
214 memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer)); |
207 memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer)); |
215 _iconsole_cmdline.buf = calloc(ICON_CMDLN_SIZE, sizeof(*_iconsole_cmdline.buf)); // create buffer and zero it |
208 _iconsole_cmdline.buf = calloc(ICON_CMDLN_SIZE, sizeof(*_iconsole_cmdline.buf)); // create buffer and zero it |
216 _iconsole_cmdline.maxlength = ICON_CMDLN_SIZE - 1; |
209 _iconsole_cmdline.maxlength = ICON_CMDLN_SIZE - 1; |
217 |
210 |
218 IConsoleStdLibRegister(); |
211 IConsoleStdLibRegister(); |
219 IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision); |
212 IConsolePrintF(13, "OpenTTD Game Console Revision 6 - %s", _openttd_revision); |
220 IConsolePrint(12, "------------------------------------"); |
213 IConsolePrint(12, "---------------------------------"); |
221 IConsolePrint(12, "use \"help\" for more info"); |
214 IConsolePrint(12, "use \"help\" for more info"); |
222 IConsolePrint(12, ""); |
215 IConsolePrint(12, ""); |
223 IConsoleClearCommand(); |
216 IConsoleClearCommand(); |
224 IConsoleHistoryAdd(""); |
217 IConsoleCmdBufferAdd(""); |
225 } |
218 } |
226 |
219 |
227 void IConsoleClear(void) |
220 void IConsoleClear(void) |
228 { |
221 { |
229 uint i; |
222 uint i; |
310 void IConsoleOpen(void) |
304 void IConsoleOpen(void) |
311 { |
305 { |
312 if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch(); |
306 if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch(); |
313 } |
307 } |
314 |
308 |
315 /** |
309 void IConsoleCmdBufferAdd(const char* cmd) |
316 * Add the entered line into the history so you can look it back |
310 { |
317 * scroll, etc. Put it to the beginning as it is the latest text |
311 int i; |
318 * @param cmd Text to be entered into the 'history' |
312 if (_iconsole_cmdbufferpos != (ICON_CMDBUF_SIZE - 1)) return; |
319 */ |
313 free(_iconsole_cmdbuffer[ICON_CMDBUF_SIZE - 2]); |
320 void IConsoleHistoryAdd(const char *cmd) |
314 for (i = (ICON_CMDBUF_SIZE - 2); i > 0; i--) _iconsole_cmdbuffer[i] = _iconsole_cmdbuffer[i - 1]; |
321 { |
315 _iconsole_cmdbuffer[0] = strdup(cmd); |
322 free(_iconsole_history[ICON_HISTORY_SIZE - 1]); |
316 } |
323 |
317 |
324 memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1)); |
318 void IConsoleCmdBufferNavigate(signed char direction) |
325 _iconsole_history[0] = strdup(cmd); |
319 { |
326 IConsoleResetHistoryPos(); |
320 int i; |
327 } |
321 i = _iconsole_cmdbufferpos + direction; |
328 |
322 if (i < 0) i = ICON_CMDBUF_SIZE - 1; |
329 /** |
323 if (i >= ICON_CMDBUF_SIZE) i = 0; |
330 * Navigate Up/Down in the history of typed commands |
|
331 * @param direction Go further back in history (+1), go to recently typed commands (-1) |
|
332 */ |
|
333 void IConsoleHistoryNavigate(signed char direction) |
|
334 { |
|
335 int i = _iconsole_historypos + direction; |
|
336 |
|
337 // watch out for overflows, just wrap around |
|
338 if (i < 0) i = ICON_HISTORY_SIZE - 1; |
|
339 if (i >= ICON_HISTORY_SIZE) i = 0; |
|
340 |
|
341 if (direction > 0) |
324 if (direction > 0) |
342 if (_iconsole_history[i] == NULL) i = 0; |
325 while (_iconsole_cmdbuffer[i] == NULL) { |
343 |
326 i++; |
344 if (direction < 0) { |
327 if (i >= ICON_CMDBUF_SIZE) i = 0; |
345 while (i > 0 && _iconsole_history[i] == NULL) i--; |
328 } |
346 } |
329 if (direction < 0) |
347 |
330 while (_iconsole_cmdbuffer[i] == NULL) { |
348 _iconsole_historypos = i; |
331 --i; |
|
332 if (i < 0) i = ICON_CMDBUF_SIZE - 1; |
|
333 } |
|
334 _iconsole_cmdbufferpos = i; |
349 IConsoleClearCommand(); |
335 IConsoleClearCommand(); |
350 // copy history to 'command prompt / bash' |
336 ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_cmdbuffer[i], _iconsole_cmdline.maxlength); |
351 assert(_iconsole_history[i] != NULL && IS_INT_INSIDE(i, 0, ICON_HISTORY_SIZE)); |
|
352 ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength); |
|
353 UpdateTextBufferSize(&_iconsole_cmdline); |
337 UpdateTextBufferSize(&_iconsole_cmdline); |
354 } |
338 } |
355 |
339 |
356 /** |
340 /** |
357 * Handle the printing of text entered into the console or redirected there |
341 * Handle the printing of text entered into the console or redirected there |
398 IConsoleWriteToLogFile(string); |
382 IConsoleWriteToLogFile(string); |
399 |
383 |
400 if (_iconsole_win != NULL) SetWindowDirty(_iconsole_win); |
384 if (_iconsole_win != NULL) SetWindowDirty(_iconsole_win); |
401 } |
385 } |
402 |
386 |
403 /** |
387 |
404 * Handle the printing of text entered into the console or redirected there |
|
405 * by any other means. Uses printf() style format, for more information look |
|
406 * at @IConsolePrint() |
|
407 */ |
|
408 void CDECL IConsolePrintF(uint16 color_code, const char* s, ...) |
388 void CDECL IConsolePrintF(uint16 color_code, const char* s, ...) |
409 { |
389 { |
410 va_list va; |
390 va_list va; |
411 char buf[ICON_MAX_STREAMSIZE]; |
391 char buf[1024]; |
|
392 int len; |
412 |
393 |
413 va_start(va, s); |
394 va_start(va, s); |
414 vsnprintf(buf, sizeof(buf), s, va); |
395 len = vsnprintf(buf, sizeof(buf), s, va); |
415 va_end(va); |
396 va_end(va); |
416 |
397 |
417 IConsolePrint(color_code, buf); |
398 IConsolePrint(color_code, buf); |
418 } |
399 } |
419 |
400 |
420 /** |
|
421 * It is possible to print debugging information to the console, |
|
422 * which is achieved by using this function. Can only be used by |
|
423 * @debug() in debug.c. You need at least a level 2 (developer) for debugging |
|
424 * messages to show up |
|
425 */ |
|
426 void IConsoleDebug(const char* string) |
401 void IConsoleDebug(const char* string) |
427 { |
402 { |
428 if (_stdlib_developer > 1) |
403 if (_stdlib_developer > 1) |
429 IConsolePrintF(_iconsole_color_debug, "dbg: %s", string); |
404 IConsolePrintF(_iconsole_color_debug, "dbg: %s", string); |
430 } |
405 } |
431 |
406 |
432 /** |
407 void IConsoleError(const char* string) |
433 * It is possible to print warnings to the console. These are mostly |
408 { |
434 * errors or mishaps, but non-fatal. You need at least a level 1 (developer) for |
409 if (_stdlib_developer > 0) |
435 * debugging messages to show up |
410 IConsolePrintF(_iconsole_color_error, "ERROR: %s", string); |
436 */ |
411 } |
|
412 |
437 void IConsoleWarning(const char* string) |
413 void IConsoleWarning(const char* string) |
438 { |
414 { |
439 if (_stdlib_developer > 0) |
415 if (_stdlib_developer > 0) |
440 IConsolePrintF(_iconsole_color_warning, "WARNING: %s", string); |
416 IConsolePrintF(_iconsole_color_warning, "WARNING: %s", string); |
441 } |
417 } |
442 |
418 |
443 /** |
419 void IConsoleCmdRegister(const char* name, _iconsole_cmd_addr addr) |
444 * It is possible to print error information to the console. This can include |
420 { |
445 * game errors, or errors in general you would want the user to notice |
421 char* _new; |
446 */ |
422 _iconsole_cmd* item; |
447 void IConsoleError(const char* string) |
423 _iconsole_cmd* item_new; |
448 { |
424 _iconsole_cmd* item_before; |
449 IConsolePrintF(_iconsole_color_error, "ERROR: %s", string); |
425 |
450 } |
426 _new = strdup(name); |
451 |
427 |
452 /** |
428 item_new = malloc(sizeof(_iconsole_cmd)); |
453 * Register a new command to be used in the console |
|
454 * @param name name of the command that will be used |
|
455 * @param addr function that will be called upon execution of command |
|
456 */ |
|
457 void IConsoleCmdRegister(const char *name, IConsoleCmdAddr addr) |
|
458 { |
|
459 IConsoleCmd *item, *item_before; |
|
460 char *new_cmd = strdup(name); |
|
461 IConsoleCmd *item_new = malloc(sizeof(IConsoleCmd)); |
|
462 |
429 |
463 item_new->_next = NULL; |
430 item_new->_next = NULL; |
464 item_new->addr = addr; |
431 item_new->addr = addr; |
465 item_new->name = new_cmd; |
432 item_new->name = _new; |
466 |
433 |
467 item_new->hook_access = NULL; |
434 item_new->hook_access = NULL; |
468 item_new->hook_after_exec = NULL; |
435 item_new->hook_after_exec = NULL; |
469 item_new->hook_before_exec = NULL; |
436 item_new->hook_before_exec = NULL; |
470 |
437 |
471 // first command |
|
472 if (_iconsole_cmds == NULL) { |
|
473 _iconsole_cmds = item_new; |
|
474 return; |
|
475 } |
|
476 |
|
477 item_before = NULL; |
438 item_before = NULL; |
478 item = _iconsole_cmds; |
439 item = _iconsole_cmds; |
479 |
440 |
480 /* BEGIN - Alphabetically insert the commands into the linked list */ |
441 if (item == NULL) { |
|
442 _iconsole_cmds = item_new; |
|
443 } else { |
|
444 while ((item->_next != NULL) && (strcmp(item->name,item_new->name)<=0)) { |
|
445 item_before = item; |
|
446 item = item->_next; |
|
447 } |
|
448 // insertion sort |
|
449 if (item_before==NULL) { |
|
450 if (strcmp(item->name,item_new->name)<=0) { |
|
451 // appending |
|
452 item ->_next = item_new; |
|
453 } else { |
|
454 // inserting as startitem |
|
455 _iconsole_cmds = item_new; |
|
456 item_new ->_next = item; |
|
457 } |
|
458 } else { |
|
459 if (strcmp(item->name,item_new->name)<=0) { |
|
460 // appending |
|
461 item ->_next = item_new; |
|
462 } else { |
|
463 // inserting |
|
464 item_new ->_next = item_before->_next; |
|
465 item_before ->_next = item_new; |
|
466 } |
|
467 } |
|
468 // insertion sort end |
|
469 } |
|
470 |
|
471 } |
|
472 |
|
473 _iconsole_cmd* IConsoleCmdGet(const char* name) |
|
474 { |
|
475 _iconsole_cmd* item; |
|
476 |
|
477 item = _iconsole_cmds; |
481 while (item != NULL) { |
478 while (item != NULL) { |
482 int i = strcmp(item->name, item_new->name); |
479 if (strcmp(item->name, name) == 0) return item; |
483 if (i == 0) { |
|
484 IConsoleError("a command with this name already exists; insertion aborted"); |
|
485 free(item_new); |
|
486 return; |
|
487 } |
|
488 |
|
489 if (i > 0) break; // insert at this position |
|
490 |
|
491 item_before = item; |
|
492 item = item->_next; |
480 item = item->_next; |
493 } |
481 } |
494 |
|
495 if (item_before == NULL) { |
|
496 _iconsole_cmds = item_new; |
|
497 } else |
|
498 item_before->_next = item_new; |
|
499 |
|
500 item_new->_next = item; |
|
501 /* END - Alphabetical insert */ |
|
502 } |
|
503 |
|
504 /** |
|
505 * Find the command pointed to by its string |
|
506 * @param name command to be found |
|
507 * @return return Cmdstruct of the found command, or NULL on failure |
|
508 */ |
|
509 IConsoleCmd *IConsoleCmdGet(const char *name) |
|
510 { |
|
511 IConsoleCmd *item; |
|
512 |
|
513 for (item = _iconsole_cmds; item != NULL; item = item->_next) { |
|
514 if (strcmp(item->name, name) == 0) return item; |
|
515 } |
|
516 return NULL; |
482 return NULL; |
517 } |
483 } |
518 |
484 |
519 /** |
485 void IConsoleAliasRegister(const char* name, const char* cmdline) |
520 * Register a an alias for an already existing command in the console |
486 { |
521 * @param name name of the alias that will be used |
487 char* _new; |
522 * @param cmd name of the command that 'name' will be alias of |
488 char* _newcmd; |
523 */ |
489 _iconsole_alias* item; |
524 void IConsoleAliasRegister(const char *name, const char *cmd) |
490 _iconsole_alias* item_new; |
525 { |
491 _iconsole_alias* item_before; |
526 IConsoleAlias *item, *item_before; |
492 |
527 char *new_alias = strdup(name); |
493 _new = strdup(name); |
528 char *cmd_aliased = strdup(cmd); |
494 _newcmd = strdup(cmdline); |
529 IConsoleAlias *item_new = malloc(sizeof(IConsoleAlias)); |
495 |
|
496 item_new = malloc(sizeof(_iconsole_alias)); |
530 |
497 |
531 item_new->_next = NULL; |
498 item_new->_next = NULL; |
532 item_new->cmdline = cmd_aliased; |
499 item_new->cmdline = _newcmd; |
533 item_new->name = new_alias; |
500 item_new->name = _new; |
534 |
501 |
535 item_before = NULL; |
502 item_before = NULL; |
536 item = _iconsole_aliases; |
503 item = _iconsole_aliases; |
537 |
504 |
538 // first command |
505 if (item == NULL) { |
539 if (_iconsole_aliases == NULL) { |
|
540 _iconsole_aliases = item_new; |
506 _iconsole_aliases = item_new; |
541 return; |
507 } else { |
542 } |
508 while ((item->_next != NULL) && (strcmp(item->name,item_new->name)<=0)) { |
543 |
509 item_before = item; |
544 item_before = NULL; |
510 item = item->_next; |
|
511 } |
|
512 // insertion sort |
|
513 if (item_before==NULL) { |
|
514 if (strcmp(item->name,item_new->name)<=0) { |
|
515 // appending |
|
516 item ->_next = item_new; |
|
517 } else { |
|
518 // inserting as startitem |
|
519 _iconsole_aliases = item_new; |
|
520 item_new ->_next = item; |
|
521 } |
|
522 } else { |
|
523 if (strcmp(item->name,item_new->name)<=0) { |
|
524 // appending |
|
525 item ->_next = item_new; |
|
526 } else { |
|
527 // inserting |
|
528 item_new ->_next = item_before->_next; |
|
529 item_before ->_next = item_new; |
|
530 } |
|
531 } |
|
532 // insertion sort end |
|
533 } |
|
534 |
|
535 } |
|
536 |
|
537 _iconsole_alias* IConsoleAliasGet(const char* name) |
|
538 { |
|
539 _iconsole_alias* item; |
|
540 |
545 item = _iconsole_aliases; |
541 item = _iconsole_aliases; |
546 |
|
547 /* BEGIN - Alphabetically insert the commands into the linked list */ |
|
548 while (item != NULL) { |
542 while (item != NULL) { |
549 int i = strcmp(item->name, item_new->name); |
543 if (strcmp(item->name, name) == 0) return item; |
550 if (i == 0) { |
|
551 IConsoleError("an alias with this name already exists; insertion aborted"); |
|
552 free(item_new); |
|
553 return; |
|
554 } |
|
555 |
|
556 if (i > 0) break; // insert at this position |
|
557 |
|
558 item_before = item; |
|
559 item = item->_next; |
544 item = item->_next; |
560 } |
545 } |
561 |
|
562 if (item_before == NULL) { |
|
563 _iconsole_aliases = item_new; |
|
564 } else |
|
565 item_before->_next = item_new; |
|
566 |
|
567 item_new->_next = item; |
|
568 /* END - Alphabetical insert */ |
|
569 } |
|
570 |
|
571 /** |
|
572 * Find the alias pointed to by its string |
|
573 * @param name alias to be found |
|
574 * @return return Aliasstruct of the found alias, or NULL on failure |
|
575 */ |
|
576 IConsoleAlias *IConsoleAliasGet(const char *name) |
|
577 { |
|
578 IConsoleAlias* item; |
|
579 |
|
580 for (item = _iconsole_aliases; item != NULL; item = item->_next) { |
|
581 if (strcmp(item->name, name) == 0) return item; |
|
582 } |
|
583 |
|
584 return NULL; |
546 return NULL; |
585 } |
547 } |
586 |
548 |
587 static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos) |
549 static void IConsoleAliasExec(const char* cmdline, char* tokens[20], byte tokentypes[20]) |
588 { |
550 { |
589 int len = min(ICON_MAX_STREAMSIZE - bufpos, strlen(src)); |
551 char* lines[ICON_MAX_ALIAS_LINES]; |
590 strncpy(dst, src, len); |
552 char* linestream; |
591 |
553 char* linestream_s; |
592 return len; |
|
593 } |
|
594 |
|
595 /** |
|
596 * An alias is just another name for a command, or for more commands |
|
597 * Execute it as well. |
|
598 * @param cmdstr is the alias of the command |
|
599 * @param tokens are the parameters given to the original command (0 is the first param) |
|
600 * @param tokencount the number of parameters passed |
|
601 */ |
|
602 static void IConsoleAliasExec(const char *cmdstr, char *tokens[ICON_TOKEN_COUNT], int tokencount) |
|
603 { |
|
604 const char *cmdptr; |
|
605 char *aliases[ICON_MAX_ALIAS_LINES], aliasstream[ICON_MAX_STREAMSIZE]; |
|
606 int i; |
|
607 uint a_index, astream_i; |
|
608 |
|
609 memset(&aliases, 0, sizeof(aliases)); |
|
610 memset(&aliasstream, 0, sizeof(aliasstream)); |
|
611 |
|
612 aliases[0] = aliasstream; |
|
613 for (cmdptr = cmdstr, a_index = 0, astream_i = 0; *cmdptr != '\0'; *cmdptr++) { |
|
614 if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break; |
|
615 |
|
616 switch (*cmdptr) { |
|
617 case '\'': /* ' will double for : */ |
|
618 aliasstream[astream_i++] = '"'; |
|
619 break; |
|
620 case ';': /* Cmd seperator, start new line */ |
|
621 aliasstream[astream_i] = '\0'; |
|
622 aliases[++a_index] = &aliasstream[++astream_i]; |
|
623 *cmdptr++; |
|
624 break; |
|
625 case '%': /* One specific parameter: %A = [param 1] %B = [param 2] ... */ |
|
626 *cmdptr++; |
|
627 switch (*cmdptr) { |
|
628 case '+': { /* All parameters seperated: "[param 1]" "[param 2]" */ |
|
629 for (i = 0; i != tokencount; i++) { |
|
630 aliasstream[astream_i++] = '"'; |
|
631 astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i); |
|
632 aliasstream[astream_i++] = '"'; |
|
633 aliasstream[astream_i++] = ' '; |
|
634 } |
|
635 } break; |
|
636 case '!': { /* Merge the parameters to one: "[param 1] [param 2] [param 3...]" */ |
|
637 aliasstream[astream_i++] = '"'; |
|
638 for (i = 0; i != tokencount; i++) { |
|
639 astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i); |
|
640 aliasstream[astream_i++] = ' '; |
|
641 } |
|
642 aliasstream[astream_i++] = '"'; |
|
643 |
|
644 } break; |
|
645 default: { |
|
646 int param = *cmdptr - 'A'; |
|
647 |
|
648 if (param < 0 || param >= tokencount) { |
|
649 IConsoleError("too many or wrong amount of parameters passed to alias, aborting"); |
|
650 return; |
|
651 } |
|
652 |
|
653 aliasstream[astream_i++] = '"'; |
|
654 astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[param], astream_i); |
|
655 aliasstream[astream_i++] = '"'; |
|
656 } break; |
|
657 } break; |
|
658 |
|
659 default: |
|
660 aliasstream[astream_i++] = *cmdptr; |
|
661 break; |
|
662 } |
|
663 } |
|
664 |
|
665 for (i = 0; i <= (int)a_index; i++) IConsoleCmdExec(aliases[i]); |
|
666 } |
|
667 |
|
668 #if 0 |
|
669 static void IConsoleAliasExec(const char* cmdline, char* tokens[TOKEN_COUNT], byte tokentypes[TOKEN_COUNT]) |
|
670 { |
|
671 char *lines[ICON_MAX_ALIAS_LINES]; |
|
672 char *linestream, *linestream_s; |
|
673 |
554 |
674 int c; |
555 int c; |
675 int i; |
556 int i; |
676 int l; |
557 int l; |
677 int x; |
558 int x; |
678 byte t; |
559 byte t; |
679 |
560 |
680 memset(lines, 0, ICON_MAX_ALIAS_LINES); // clear buffer |
561 //** clearing buffer **// |
681 |
562 |
682 linestream_s = linestream = malloc(1024 * ICON_MAX_ALIAS_LINES); |
563 for (i = 0; i < 40; i++) { |
683 memset(linestream, 0, 1024 * ICON_MAX_ALIAS_LINES); |
564 lines[0] = NULL; |
|
565 } |
|
566 linestream_s = linestream = malloc(1024*ICON_MAX_ALIAS_LINES); |
|
567 memset(linestream, 0, 1024*ICON_MAX_ALIAS_LINES); |
684 |
568 |
685 //** parsing **// |
569 //** parsing **// |
686 |
570 |
687 l = strlen(cmdline); |
571 l = strlen(cmdline); |
688 i = 0; |
572 i = 0; |
1142 break; |
1023 break; |
1143 } |
1024 } |
1144 return proc == NULL ? true : proc(hook_cmd); |
1025 return proc == NULL ? true : proc(hook_cmd); |
1145 } |
1026 } |
1146 |
1027 |
1147 /** |
|
1148 * Execute a given command passed to us. First chop it up into |
|
1149 * individual tokens, then execute it if possible |
|
1150 * @param cmdstr string to be parsed and executed |
|
1151 */ |
|
1152 void IConsoleCmdExec(const char *cmdstr) |
|
1153 { |
|
1154 IConsoleCmd *cmd = NULL; |
|
1155 IConsoleAlias *alias = NULL; |
|
1156 _iconsole_var *var = NULL; |
|
1157 |
|
1158 const char *cmdptr; |
|
1159 char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE]; |
|
1160 uint t_index, tstream_i; |
|
1161 |
|
1162 bool longtoken = false; |
|
1163 |
|
1164 for (cmdptr = cmdstr; *cmdptr != '\0'; *cmdptr++) { |
|
1165 if (!IsValidAsciiChar(*cmdptr)) { |
|
1166 IConsoleError("command contains malformed characters, aborting"); |
|
1167 return; |
|
1168 } |
|
1169 } |
|
1170 |
|
1171 if (_stdlib_con_developer) |
|
1172 IConsolePrintF(_iconsole_color_debug, "condbg: executing cmdline: %s", cmdstr); |
|
1173 |
|
1174 memset(&tokens, 0, sizeof(tokens)); |
|
1175 memset(&tokenstream, 0, sizeof(tokenstream)); |
|
1176 |
|
1177 /* 1. Split up commandline into tokens, seperated by spaces, commands |
|
1178 * enclosed in "" are taken as one token. We can only go as far as the amount |
|
1179 * of characters in our stream or the max amount of tokens we can handle */ |
|
1180 tokens[0] = tokenstream; |
|
1181 for (cmdptr = cmdstr, t_index = 0, tstream_i = 0; *cmdptr != '\0'; *cmdptr++) { |
|
1182 if (t_index >= lengthof(tokens) || tstream_i >= lengthof(tokenstream)) break; |
|
1183 |
|
1184 switch (*cmdptr) { |
|
1185 case ' ': /* Token seperator */ |
|
1186 if (!longtoken) { |
|
1187 tokenstream[tstream_i] = '\0'; |
|
1188 tokens[++t_index] = &tokenstream[tstream_i + 1]; |
|
1189 } else |
|
1190 tokenstream[tstream_i] = *cmdptr; |
|
1191 |
|
1192 tstream_i++; |
|
1193 break; |
|
1194 case '"': /* Tokens enclosed in "" are one token */ |
|
1195 longtoken = !longtoken; |
|
1196 break; |
|
1197 default: /* Normal character */ |
|
1198 tokenstream[tstream_i++] = *cmdptr; |
|
1199 break; |
|
1200 } |
|
1201 } |
|
1202 |
|
1203 t_index++; // index was 0 |
|
1204 |
|
1205 /* 2. Determine type of command (cmd, alias or variable) and execute |
|
1206 * First try commands, then aliases, and finally variables |
|
1207 */ |
|
1208 cmd = IConsoleCmdGet(tokens[0]); |
|
1209 if (cmd != NULL) { |
|
1210 if (IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_ACCESS)) { |
|
1211 IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_BEFORE_EXEC); |
|
1212 cmd->addr(t_index, tokens, NULL); |
|
1213 IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_AFTER_EXEC); |
|
1214 } |
|
1215 return; |
|
1216 } |
|
1217 |
|
1218 alias = IConsoleAliasGet(tokens[0]); |
|
1219 if (alias != NULL) { |
|
1220 IConsoleAliasExec(alias->cmdline, &tokens[1], t_index - 1); |
|
1221 return; |
|
1222 } |
|
1223 |
|
1224 var = IConsoleVarGet(tokens[0]); |
|
1225 if (var != NULL) { |
|
1226 IConsoleVarExec(tokens); |
|
1227 return; |
|
1228 } |
|
1229 |
|
1230 IConsoleError("command or variable not found"); |
|
1231 } |
|
1232 |
|
1233 #if 0 |
|
1234 void IConsoleCmdExec(const char* cmdstr) |
1028 void IConsoleCmdExec(const char* cmdstr) |
1235 { |
1029 { |
1236 IConsoleCmdAddr function; |
1030 _iconsole_cmd_addr function; |
1237 char* tokens[20]; |
1031 char* tokens[20]; |
1238 byte tokentypes[20]; |
1032 byte tokentypes[20]; |
1239 char* tokenstream; |
1033 char* tokenstream; |
1240 char* tokenstream_s; |
1034 char* tokenstream_s; |
1241 byte execution_mode; |
1035 byte execution_mode; |
1242 _iconsole_var* var = NULL; |
1036 _iconsole_var* var = NULL; |
1243 _iconsole_var* result = NULL; |
1037 _iconsole_var* result = NULL; |
1244 IConsoleCmd* cmd = NULL; |
1038 _iconsole_cmd* cmd = NULL; |
1245 IConsoleAlias* alias = NULL; |
1039 _iconsole_alias* alias = NULL; |
1246 |
1040 |
1247 bool longtoken; |
1041 bool longtoken; |
1248 bool valid_token; |
1042 bool valid_token; |
1249 bool skip_lt_change; |
1043 bool skip_lt_change; |
1250 |
1044 |
1251 uint c; |
1045 uint c; |
1252 uint i; |
1046 uint i; |
1253 uint l; |
1047 uint l; |
1254 |
1048 |
1255 for (; strchr("\n\r \t", *cmdstr) != NULL; cmdstr++) { |
1049 for (; strchr("\n\r \t", *cmdstr) != NULL; ++cmdstr) { |
1256 switch (*cmdstr) { |
1050 switch (*cmdstr) { |
1257 case '\0': case '#': return; |
1051 case '\0': |
1258 default: break; |
1052 case '#': |
|
1053 return; |
|
1054 |
|
1055 default: |
|
1056 break; |
1259 } |
1057 } |
1260 } |
1058 } |
1261 |
1059 |
1262 if (_stdlib_con_developer) |
1060 if (_stdlib_con_developer) |
1263 IConsolePrintF(_iconsole_color_debug, "CONDEBUG: execution_cmdline: %s", cmdstr); |
1061 IConsolePrintF(_iconsole_color_debug, "CONDEBUG: execution_cmdline: %s", cmdstr); |