Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
9.4 KiB

  1. /*
  2. This program reads in a file (or multiple files) of lines with whitespace seperate columns.
  3. After reading the whole file, it outputs the content formatted such that each field is padded
  4. on the right..err, left actually, with spaces to be the width of the longest value of that colume.
  5. There are two modes of operation.
  6. multiple files in place
  7. multiple files all written to one file (possibly among those read in)
  8. one file to itself falls out of either
  9. columns -inplace foo bar abc
  10. read each of foo bar abc and write each on top of itself
  11. columns -concat foo bar abc
  12. read foo and bar and write out abc
  13. columns -concat foo bar abc abc
  14. read foo, bar, and abc and write out abc
  15. columns - -
  16. read stdin, write stdout
  17. columns
  18. read stdin, write stdout
  19. All data must fit in memory.
  20. */
  21. #define NOMINMAX
  22. #include "yvals.h"
  23. #undef _MAX
  24. #undef _MIN
  25. #define _cpp_min min
  26. #define _cpp_max max
  27. #define _MIN min
  28. #define _MAX max
  29. #define min min
  30. #define max max
  31. #pragma warning(disable:4100)
  32. #pragma warning(disable:4663)
  33. #pragma warning(disable:4511)
  34. #pragma warning(disable:4512)
  35. #pragma warning(disable:4127)
  36. #pragma warning(disable:4018)
  37. #pragma warning(disable:4389)
  38. #pragma warning(disable:4702)
  39. #include <vector>
  40. #include <algorithm>
  41. #include <iostream>
  42. #include <fstream>
  43. #include <string>
  44. #include <string.h>
  45. #include "windows.h"
  46. #define NUMBER_OF(x) (sizeof(x)/sizeof((x)[0]))
  47. //
  48. // get msvcrt.dll wildcard processing on the command line
  49. //
  50. extern "C" { int _dowildcard = 1; }
  51. class String_t : public std::string
  52. {
  53. typedef std::string Base;
  54. public:
  55. String_t(const std::string & s) : Base(s) { }
  56. String_t() { }
  57. ~String_t() { }
  58. String_t(const String_t & s) : Base(s) { }
  59. String_t(const char * s) : Base(s) { }
  60. String_t(const_iterator i, const_iterator j) : Base(i, j) { }
  61. bool operator<( const String_t & s) const
  62. {
  63. return _stricmp(c_str(), s.c_str()) < 0;
  64. }
  65. bool operator==( const String_t & s) const
  66. {
  67. return _stricmp(c_str(), s.c_str()) == 0;
  68. }
  69. operator const char * () const { return c_str(); }
  70. };
  71. void Error(const char * s) { fprintf(stderr, "%s\n", s); exit(EXIT_FAILURE); }
  72. class Filename_t : public String_t
  73. {
  74. private:
  75. typedef String_t Base_t;
  76. public:
  77. Filename_t(const char * x) : Base_t(x), m_IsStdin(false), m_IsStdout(false) { }
  78. Filename_t(const Base_t& x) : Base_t(x), m_IsStdin(false), m_IsStdout(false) { }
  79. Filename_t() : m_IsStdin(false), m_IsStdout(false) { }
  80. ~Filename_t() { }
  81. static Filename_t Stdin() { Filename_t fn; fn.m_IsStdin = true; return fn; }
  82. static Filename_t Stdout() { Filename_t fn; fn.m_IsStdout = true; return fn; }
  83. bool m_IsStdin;
  84. bool m_IsStdout;
  85. void Open(std::fstream & File, std::ios_base::open_mode Flags)
  86. {
  87. switch ((m_IsStdin ? 1 : 0) | (m_IsStdout ? 2 : 0))
  88. {
  89. case 0:
  90. File.open(*this, Flags);
  91. break;
  92. case 1:
  93. static_cast<std::basic_ios<char>&>(File).rdbuf(std::cin.rdbuf());
  94. break;
  95. case 2:
  96. static_cast<std::basic_ios<char>&>(File).rdbuf(std::cout.rdbuf());
  97. break;
  98. case 3:
  99. Error("stdin and stdout");
  100. break;
  101. }
  102. }
  103. };
  104. template <typename Iterator>
  105. Iterator FindFirstNotOf(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
  106. {
  107. if (first2 == last2)
  108. return last1;
  109. for ( ; first1 != last1 ; ++first1)
  110. {
  111. if (std::find(first2, last2, *first1) == last2)
  112. {
  113. break;
  114. }
  115. }
  116. return first1;
  117. }
  118. template <typename Iterator>
  119. Iterator FindFirstOf(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
  120. {
  121. return std::find_first_of(first1, last1, first2, last2);
  122. }
  123. void SplitString(const String_t& String, const String_t& Delim, std::vector<String_t>& Fields)
  124. {
  125. String_t::const_iterator FieldBegin;
  126. String_t::const_iterator FieldEnd = String.begin();
  127. while ((FieldBegin = FindFirstNotOf(FieldEnd, String.end(), Delim.begin(), Delim.end())) != String.end())
  128. {
  129. FieldEnd = FindFirstOf(FieldBegin, String.end(), Delim.begin(), Delim.end());
  130. Fields.push_back(String_t(FieldBegin, FieldEnd));
  131. }
  132. }
  133. const String_t HorizontalWhitespace(" \t");
  134. class Row_t : public std::vector<String_t>
  135. {
  136. public:
  137. static void FromLine(Row_t & This, const String_t &);
  138. };
  139. class Columns_t
  140. {
  141. public:
  142. void Main(unsigned Argc, char ** Argv);
  143. Columns_t() : m_StdinSeen(false), m_StdoutSeen(false), m_Inplace(false), m_Concat(false) { }
  144. ~Columns_t() { }
  145. void Error(const char * s) { fprintf(stderr, "%s\n", s); exit(EXIT_FAILURE); }
  146. void Usage() { }
  147. bool m_StdinSeen;
  148. bool m_StdoutSeen;
  149. bool m_Inplace;
  150. bool m_Concat;
  151. std::vector<size_t> m_ColumWidths;
  152. std::vector<Row_t> m_Rows;
  153. std::vector<Filename_t> m_Filenames;
  154. };
  155. void PrintSpaces(std::ostream & Stream, size_t i)
  156. {
  157. const static char Spaces[] = " ";
  158. for ( ; i >= NUMBER_OF(Spaces) ; i -= NUMBER_OF(Spaces) - 1 )
  159. Stream << Spaces;
  160. Stream << (Spaces + NUMBER_OF(Spaces) - 1 - i);
  161. }
  162. void Columns_t::Main(unsigned Argc, char ** Argv)
  163. {
  164. unsigned Arg = 0;
  165. if (Argc == 0)
  166. {
  167. m_Filenames.push_back(Filename_t::Stdin());
  168. m_StdinSeen = true;
  169. m_Filenames.push_back(Filename_t::Stdout());
  170. m_StdoutSeen = true;
  171. m_Concat = true;
  172. }
  173. else
  174. {
  175. if (_stricmp(Argv[Arg], "-inplace") == 0)
  176. {
  177. ++Arg;
  178. m_Inplace = true;
  179. }
  180. else if (_stricmp(Argv[Arg], "-concat") == 0)
  181. {
  182. ++Arg;
  183. m_Concat = true;
  184. }
  185. for ( ; Arg < Argc ; Arg++)
  186. {
  187. if (_stricmp(Argv[Arg], "-") == 0)
  188. {
  189. if (m_StdinSeen)
  190. {
  191. if (m_StdoutSeen)
  192. {
  193. return Error("can't specify - more than twice");
  194. }
  195. if (Arg != (Argc - 1))
  196. {
  197. return Error("stdout must be last parameter");
  198. }
  199. m_StdoutSeen = true;
  200. m_Filenames.push_back(Filename_t::Stdout());
  201. }
  202. else
  203. {
  204. m_StdinSeen = true;
  205. m_Filenames.push_back(Filename_t::Stdin());
  206. }
  207. }
  208. else if (
  209. _stricmp(Argv[Arg], "-?") == 0
  210. || _stricmp(Argv[Arg], "/?") == 0
  211. || _stricmp(Argv[Arg], "-h") == 0
  212. || _stricmp(Argv[Arg], "/h") == 0
  213. || _stricmp(Argv[Arg], "-help") == 0
  214. || _stricmp(Argv[Arg], "/help") == 0
  215. )
  216. {
  217. return Usage();
  218. }
  219. else
  220. {
  221. m_Filenames.push_back(Argv[Arg]);
  222. }
  223. }
  224. }
  225. if (Argc == 2 && m_StdinSeen && m_StdoutSeen && !m_Inplace && !m_Concat)
  226. {
  227. m_Inplace = true;
  228. }
  229. if (m_StdinSeen && m_Inplace)
  230. {
  231. return Error("can't mix stdin and inplace");
  232. }
  233. if (!m_Inplace && !m_Concat)
  234. {
  235. return Error("must specify -inplace or -concat");
  236. }
  237. for (unsigned Filename = 0 ; Filename < m_Filenames.size() ; ++Filename)
  238. {
  239. if (Filename < m_Filenames.size() - (m_Concat ? 1 : 0))
  240. {
  241. std::fstream File;
  242. m_Filenames[Filename].Open(File, File.in);
  243. String_t Line;
  244. while (std::getline(File, Line))
  245. {
  246. Row_t Row;
  247. SplitString(Line, HorizontalWhitespace, Row);
  248. m_Rows.push_back(Row);
  249. m_ColumWidths.resize(std::max(m_ColumWidths.size(), Row.size()), 0);
  250. for (unsigned j = 0 ; j != Row.size() ; ++j)
  251. {
  252. size_t k = std::max(m_ColumWidths[j], Row[j].size());
  253. m_ColumWidths[j] = k;
  254. }
  255. }
  256. }
  257. if (m_Inplace || (m_Concat && Filename == m_Filenames.size() - 1))
  258. {
  259. if (!m_Filenames[Filename].m_IsStdin && !m_Filenames[Filename].m_IsStdout)
  260. {
  261. remove(m_Filenames[Filename]);
  262. }
  263. std::fstream File;
  264. m_Filenames[Filename].Open(File, File.out);
  265. File.fill(' ');
  266. for (unsigned RowIndex = 0 ; RowIndex != m_Rows.size() ; ++RowIndex)
  267. {
  268. const Row_t & Row = m_Rows[RowIndex];
  269. for (unsigned Column = 0 ; Column != Row.size() ; ++Column)
  270. {
  271. File << Row[Column];
  272. PrintSpaces(File, m_ColumWidths[Column] + 1 - Row[Column].size());
  273. }
  274. File << "\n";
  275. }
  276. if (m_Inplace)
  277. {
  278. m_Rows.clear();
  279. m_ColumWidths.clear();
  280. }
  281. }
  282. }
  283. }
  284. int __cdecl main(int argc, char ** argv)
  285. {
  286. Columns_t c;
  287. c.Main(static_cast<unsigned>(argc - (argc != 0)) , argv + 1);
  288. return 0;
  289. }