shell-test.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include <stdbool.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #ifdef _MSC_VER
  6. # include <Windows.h>
  7. # define usleep(usecs) Sleep(usecs/1000)
  8. #else
  9. # include <unistd.h>
  10. #endif
  11. static void flush_wait(void)
  12. {
  13. fflush(NULL);
  14. usleep(10*1000); // Wait 10 ms.
  15. }
  16. static void help(void)
  17. {
  18. puts("Fake shell");
  19. puts("");
  20. puts("Usage:");
  21. puts(" shell-test --help");
  22. puts(" Prints this help to stdout.");
  23. puts(" shell-test");
  24. puts(" shell-test EXE");
  25. puts(" Prints \"ready $ \" to stderr.");
  26. puts(" shell-test -t {prompt text}");
  27. puts(" Prints \"{prompt text} $ \" to stderr.");
  28. puts(" shell-test EXE \"prog args...\"");
  29. puts(" Prints \"ready $ prog args...\\n\" to stderr.");
  30. puts(" shell-test -t {prompt text} EXE \"prog args...\"");
  31. puts(" Prints \"{prompt text} $ progs args...\" to stderr.");
  32. puts(" shell-test REP N {text}");
  33. puts(" Prints \"{lnr}: {text}\\n\" to stdout N times, taking N milliseconds.");
  34. puts(" Example:");
  35. puts(" shell-test REP 97 \"foo bar\"");
  36. puts(" 0: foo bar");
  37. puts(" ...");
  38. puts(" 96: foo bar");
  39. puts(" shell-test INTERACT");
  40. puts(" Prints \"interact $ \" to stderr, and waits for \"exit\" input.");
  41. puts(" shell-test EXIT {code}");
  42. puts(" Exits immediately with exit code \"{code}\".");
  43. }
  44. int main(int argc, char **argv)
  45. {
  46. if (argc == 2 && strcmp(argv[1], "--help") == 0) {
  47. help();
  48. }
  49. #ifdef _MSC_VER
  50. SetConsoleOutputCP(CP_UTF8);
  51. #endif
  52. if (argc >= 2) {
  53. if (strcmp(argv[1], "-t") == 0) {
  54. if (argc < 3) {
  55. fprintf(stderr, "Missing prompt text for -t option\n");
  56. return 5;
  57. } else {
  58. fprintf(stderr, "%s $ ", argv[2]);
  59. if (argc >= 5 && (strcmp(argv[3], "EXE") == 0)) {
  60. fprintf(stderr, "%s\n", argv[4]);
  61. }
  62. }
  63. } else if (strcmp(argv[1], "EXE") == 0) {
  64. fprintf(stderr, "ready $ ");
  65. if (argc >= 3) {
  66. fprintf(stderr, "%s\n", argv[2]);
  67. }
  68. } else if (strcmp(argv[1], "REP") == 0) {
  69. if (argc != 4) {
  70. fprintf(stderr, "REP expects exactly 3 arguments\n");
  71. return 4;
  72. }
  73. int count = 0;
  74. if (sscanf(argv[2], "%d", &count) != 1) {
  75. fprintf(stderr, "Invalid count: %s\n", argv[2]);
  76. return 4;
  77. }
  78. for (int i = 0; i < count; i++) {
  79. printf("%d: %s\n", i, argv[3]);
  80. if (i % 100 == 0) {
  81. usleep(1000); // Wait 1 ms (simulate typical output).
  82. }
  83. fflush(NULL);
  84. }
  85. } else if (strcmp(argv[1], "UTF-8") == 0) {
  86. // test split-up UTF-8 sequence
  87. printf("\xc3"); flush_wait();
  88. printf("\xa5\n"); flush_wait();
  89. // split up a 2+2 grapheme clusters all possible ways
  90. printf("ref: \xc3\xa5\xcc\xb2\n"); flush_wait();
  91. printf("1: \xc3"); flush_wait();
  92. printf("\xa5\xcc\xb2\n"); flush_wait();
  93. printf("2: \xc3\xa5"); flush_wait();
  94. printf("\xcc\xb2\n"); flush_wait();
  95. printf("3: \xc3\xa5\xcc"); flush_wait();
  96. printf("\xb2\n"); flush_wait();
  97. } else if (strcmp(argv[1], "INTERACT") == 0) {
  98. char input[256];
  99. char cmd[100];
  100. int arg;
  101. while (true) {
  102. fprintf(stderr, "interact $ ");
  103. if (fgets(input, sizeof(input), stdin) == NULL) {
  104. break; // EOF
  105. }
  106. if (1 == sscanf(input, "%99s %d", cmd, &arg)) {
  107. arg = 0;
  108. }
  109. if (strcmp(cmd, "exit") == 0) {
  110. return arg;
  111. } else {
  112. fprintf(stderr, "command not found: %s\n", cmd);
  113. }
  114. }
  115. } else if (strcmp(argv[1], "EXIT") == 0) {
  116. int code = 1;
  117. if (argc >= 3) {
  118. if (sscanf(argv[2], "%d", &code) != 1) {
  119. fprintf(stderr, "Invalid exit code: %s\n", argv[2]);
  120. return 2;
  121. }
  122. }
  123. return code;
  124. } else {
  125. fprintf(stderr, "Unknown first argument: %s\n", argv[1]);
  126. return 3;
  127. }
  128. fflush(NULL);
  129. return 0;
  130. } else if (argc == 1) {
  131. fprintf(stderr, "ready $ ");
  132. return 0;
  133. } else {
  134. fprintf(stderr, "Missing first argument\n");
  135. return 2;
  136. }
  137. }