cecho.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. cecho.c
  5. Abstract:
  6. This module implements the color echo application.
  7. Author:
  8. Evan Green 1-May-2014
  9. Environment:
  10. POSIX
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/lib/types.h>
  16. #include "swlib.h"
  17. #include <string.h>
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. #define CECHO_USAGE \
  22. "usage: cecho [-f <color>] [-b <color>] [-neE]\n" \
  23. "The cecho utility echoes command line parameters in color. Options are:\n"\
  24. " -f <color> -- Print with the given foreground color.\n" \
  25. " -b <color> -- Print with the given background color.\n" \
  26. " -n -- Do not print a newline at the end.\n" \
  27. " -e -- Enable escape processing.\n" \
  28. " -E -- Disable escape processing.\n" \
  29. "Use the -- argument to disable argument processing of all subsequent \n" \
  30. "parameters. The color type can be one of:\n" \
  31. " d -- Default color\n" \
  32. " k -- Black\n" \
  33. " r -- Dark red\n" \
  34. " g -- Dark green\n" \
  35. " y -- Dark yellow\n" \
  36. " b -- Dark blue\n" \
  37. " m -- Dark magenta\n" \
  38. " c -- Dark cyan\n" \
  39. " a -- Dark gray\n" \
  40. " D -- Bold default\n" \
  41. " A -- gray\n" \
  42. " R -- bright red\n" \
  43. " G -- bright green\n" \
  44. " Y -- bright yellow\n" \
  45. " B -- bright blue\n" \
  46. " M -- bright magenta\n" \
  47. " C -- bright cyan\n" \
  48. " W -- white\n"
  49. //
  50. // ------------------------------------------------------ Data Type Definitions
  51. //
  52. //
  53. // ----------------------------------------------- Internal Function Prototypes
  54. //
  55. CONSOLE_COLOR
  56. ColorEchoConvertToColor (
  57. CHAR Character
  58. );
  59. //
  60. // -------------------------------------------------------------------- Globals
  61. //
  62. //
  63. // ------------------------------------------------------------------ Functions
  64. //
  65. INT
  66. ColorEchoMain (
  67. INT ArgumentCount,
  68. CHAR **Arguments
  69. )
  70. /*++
  71. Routine Description:
  72. This routine is the main entry point for the color echo program.
  73. Arguments:
  74. ArgumentCount - Supplies the number of command line arguments the program
  75. was invoked with.
  76. Arguments - Supplies a tokenized array of command line arguments.
  77. Return Value:
  78. 0 on success.
  79. Non-zero on failure.
  80. --*/
  81. {
  82. PSTR Argument;
  83. ULONG ArgumentIndex;
  84. ULONG ArgumentLength;
  85. CONSOLE_COLOR BackgroundColor;
  86. CHAR Character;
  87. ULONG CharacterIndex;
  88. CHAR DigitCount;
  89. BOOL EscapeProcessing;
  90. CONSOLE_COLOR ForegroundColor;
  91. BOOL PrintTrailingNewline;
  92. CHAR Value;
  93. BOOL WasBackslash;
  94. EscapeProcessing = FALSE;
  95. PrintTrailingNewline = TRUE;
  96. BackgroundColor = ConsoleColorDefault;
  97. ForegroundColor = ConsoleColorDefault;
  98. //
  99. // Loop through processing arguments.
  100. //
  101. for (ArgumentIndex = 1; ArgumentIndex < ArgumentCount; ArgumentIndex += 1) {
  102. Argument = Arguments[ArgumentIndex];
  103. if (Argument[0] != '-') {
  104. break;
  105. }
  106. if (strcmp(Argument, "--help") == 0) {
  107. printf(CECHO_USAGE);
  108. return 1;
  109. }
  110. while (TRUE) {
  111. Argument += 1;
  112. if (Argument[0] == '\0') {
  113. break;
  114. } else if (Argument[0] == 'e') {
  115. EscapeProcessing = TRUE;
  116. } else if (Argument[0] == 'E') {
  117. EscapeProcessing = FALSE;
  118. } else if (Argument[0] == 'n') {
  119. PrintTrailingNewline = FALSE;
  120. } else if (Argument[0] == 'f') {
  121. ForegroundColor = ColorEchoConvertToColor(Argument[1]);
  122. if (ForegroundColor == -1) {
  123. return 1;
  124. }
  125. Argument += 1;
  126. } else if (Argument[0] == 'b') {
  127. BackgroundColor = ColorEchoConvertToColor(Argument[1]);
  128. if (BackgroundColor == -1) {
  129. return 1;
  130. }
  131. Argument += 1;
  132. } else if (Argument[0] == '-') {
  133. break;
  134. } else {
  135. break;
  136. }
  137. }
  138. if (Argument[0] != '\0') {
  139. break;
  140. }
  141. }
  142. //
  143. // Echo out the remainder of the arguments.
  144. //
  145. while (ArgumentIndex < ArgumentCount) {
  146. Argument = Arguments[ArgumentIndex];
  147. ArgumentIndex += 1;
  148. //
  149. // If not processing backslashes or there are none, just print it
  150. // directly and continue.
  151. //
  152. if ((EscapeProcessing == FALSE) || (strchr(Argument, '\\') == NULL)) {
  153. SwPrintInColor(BackgroundColor, ForegroundColor, "%s", Argument);
  154. //
  155. // Escape the darn thing by looping through every character in the
  156. // string.
  157. //
  158. } else {
  159. Value = 0;
  160. DigitCount = 0;
  161. WasBackslash = FALSE;
  162. ArgumentLength = strlen(Argument);
  163. for (CharacterIndex = 0;
  164. CharacterIndex < ArgumentLength;
  165. CharacterIndex += 1) {
  166. Character = Argument[CharacterIndex];
  167. //
  168. // If a \0 was detected, then this is in the process of
  169. // working through \0NNN, where NNN is one to three octal
  170. // characters.
  171. //
  172. if (DigitCount != 0) {
  173. if ((Character >= '0') && (Character <= '7')) {
  174. Value = (Value * 8) + (Character - '0');
  175. DigitCount += 1;
  176. if (DigitCount == 4) {
  177. DigitCount = 0;
  178. SwPrintInColor(BackgroundColor,
  179. ForegroundColor,
  180. "%c",
  181. Value);
  182. }
  183. //
  184. // This was a digit that counted towards the value, so
  185. // it shouldn't be considered for further printing.
  186. //
  187. continue;
  188. //
  189. // The number ended a bit early, so print it out and
  190. // consider this character for further printing.
  191. //
  192. } else {
  193. DigitCount = 0;
  194. SwPrintInColor(BackgroundColor,
  195. ForegroundColor,
  196. "%c",
  197. Value);
  198. }
  199. }
  200. if (WasBackslash != FALSE) {
  201. if (Character == 'a') {
  202. } else if (Character == 'b') {
  203. SwPrintInColor(BackgroundColor, ForegroundColor, "\b");
  204. } else if (Character == 'c') {
  205. PrintTrailingNewline = FALSE;
  206. goto MainEnd;
  207. } else if (Character == 'f') {
  208. SwPrintInColor(BackgroundColor, ForegroundColor, "\f");
  209. } else if (Character == 'n') {
  210. SwPrintInColor(BackgroundColor, ForegroundColor, "\n");
  211. } else if (Character == 'r') {
  212. SwPrintInColor(BackgroundColor, ForegroundColor, "\r");
  213. } else if (Character == 't') {
  214. SwPrintInColor(BackgroundColor, ForegroundColor, "\t");
  215. } else if (Character == '\\') {
  216. SwPrintInColor(BackgroundColor, ForegroundColor, "\\");
  217. } else if (Character == '0') {
  218. Value = 0;
  219. DigitCount = 1;
  220. } else {
  221. //
  222. // This backslash escape sequence isn't recognized, so
  223. // just print it out verbatim.
  224. //
  225. SwPrintInColor(BackgroundColor,
  226. ForegroundColor,
  227. "\\%c",
  228. Character);
  229. }
  230. //
  231. // Just a regular old character, print it out unless it begins
  232. // an escaped sequence.
  233. //
  234. } else if (Character != '\\') {
  235. SwPrintInColor(BackgroundColor,
  236. ForegroundColor,
  237. "%c",
  238. Character);
  239. }
  240. if (Character == '\\') {
  241. WasBackslash = !WasBackslash;
  242. } else {
  243. WasBackslash = FALSE;
  244. }
  245. }
  246. }
  247. if (ArgumentIndex != ArgumentCount) {
  248. SwPrintInColor(BackgroundColor, ForegroundColor, " ");
  249. }
  250. }
  251. MainEnd:
  252. if (PrintTrailingNewline != FALSE) {
  253. SwPrintInColor(BackgroundColor, ForegroundColor, "\n");
  254. }
  255. return 0;
  256. }
  257. //
  258. // --------------------------------------------------------- Internal Functions
  259. //
  260. CONSOLE_COLOR
  261. ColorEchoConvertToColor (
  262. CHAR Character
  263. )
  264. /*++
  265. Routine Description:
  266. This routine converts a color character to a console color enum.
  267. Arguments:
  268. Character - Supplies the character to convert.
  269. Return Value:
  270. Returns the console color on success.
  271. -1 if the character is not valid.
  272. --*/
  273. {
  274. CONSOLE_COLOR Color;
  275. switch (Character) {
  276. case 'd':
  277. Color = ConsoleColorDefault;
  278. break;
  279. case 'k':
  280. Color = ConsoleColorBlack;
  281. break;
  282. case 'r':
  283. Color = ConsoleColorDarkRed;
  284. break;
  285. case 'g':
  286. Color = ConsoleColorDarkGreen;
  287. break;
  288. case 'y':
  289. Color = ConsoleColorDarkYellow;
  290. break;
  291. case 'b':
  292. Color = ConsoleColorDarkBlue;
  293. break;
  294. case 'm':
  295. Color = ConsoleColorDarkMagenta;
  296. break;
  297. case 'c':
  298. Color = ConsoleColorDarkCyan;
  299. break;
  300. case 'a':
  301. Color = ConsoleColorDarkGray;
  302. break;
  303. case 'D':
  304. Color = ConsoleColorBoldDefault;
  305. break;
  306. case 'A':
  307. Color = ConsoleColorGray;
  308. break;
  309. case 'R':
  310. Color = ConsoleColorRed;
  311. break;
  312. case 'G':
  313. Color = ConsoleColorGreen;
  314. break;
  315. case 'Y':
  316. Color = ConsoleColorYellow;
  317. break;
  318. case 'B':
  319. Color = ConsoleColorBlue;
  320. break;
  321. case 'M':
  322. Color = ConsoleColorMagenta;
  323. break;
  324. case 'C':
  325. Color = ConsoleColorCyan;
  326. break;
  327. case 'W':
  328. Color = ConsoleColorWhite;
  329. break;
  330. default:
  331. fprintf(stderr, "cecho: Invalid color '%c'.\n", Character);
  332. Color = -1;
  333. }
  334. return Color;
  335. }