- Tree cleanups proposed on the mailing list. Move all non-Core OS modules to rosapps...
[reactos.git] / rosapps / sysutils / utils / tickcount / tickcount.c
1 /* $Id$
2 */
3 /*
4 tickcount -- Display the kernel tick count (or any tick count passed as an
5 argument or as input) in human-readable format
6
7 This is public domain software
8 */
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <tchar.h>
14 #include <windows.h>
15
16 typedef __int64 int64_;
17 typedef unsigned __int64 uint64_;
18
19 #define TICKS_YEAR (TICKS_DAY * ((uint64_)365))
20 #define TICKS_MONTH (TICKS_DAY * ((uint64_)30))
21 #define TICKS_WEEK (TICKS_DAY * ((uint64_)7))
22 #define TICKS_DAY (TICKS_HOUR * ((uint64_)24))
23 #define TICKS_HOUR (TICKS_MINUTE * ((uint64_)60))
24 #define TICKS_MINUTE (TICKS_SECOND * ((uint64_)60))
25 #define TICKS_SECOND ((uint64_)1000)
26
27 #define SLICES_COUNT (sizeof(ticks_per_slice) / sizeof(ticks_per_slice[0]))
28
29 uint64_ ticks_per_slice[] =
30 {
31 TICKS_YEAR,
32 TICKS_MONTH,
33 TICKS_WEEK,
34 TICKS_DAY,
35 TICKS_HOUR,
36 TICKS_MINUTE,
37 TICKS_SECOND,
38 1
39 };
40
41 _TCHAR * slice_names_singular[SLICES_COUNT] =
42 {
43 _T("year"),
44 _T("month"),
45 _T("week"),
46 _T("day"),
47 _T("hour"),
48 _T("minute"),
49 _T("second"),
50 _T("millisecond")
51 };
52
53 _TCHAR * slice_names_plural[SLICES_COUNT] =
54 {
55 _T("years"),
56 _T("months"),
57 _T("weeks"),
58 _T("days"),
59 _T("hours"),
60 _T("minutes"),
61 _T("seconds"),
62 _T("milliseconds")
63 };
64
65 void print_uptime
66 (
67 uint64_ tickcount,
68 uint64_ prevsliceval,
69 _TCHAR * prevsliceunit,
70 int curslice
71 )
72 {
73 uint64_ tick_cur = tickcount / ticks_per_slice[curslice];
74 uint64_ tick_residual = tickcount % ticks_per_slice[curslice];
75
76 assert(tick_cur <= (~((uint64_)0)));
77
78 if(tick_residual == 0)
79 {
80 /* the current slice is the last */
81
82 if(prevsliceval == 0)
83 {
84 /* the current slice is the only */
85 _tprintf
86 (
87 _T("%u %s"),
88 (unsigned)tick_cur,
89 (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice]
90 );
91 }
92 else
93 {
94 /* the current slice is the last, and there's a previous slice */
95 assert(prevsliceunit);
96
97 /* print the previous and the current slice, and terminate */
98 _tprintf
99 (
100 _T("%u %s %s %u %s"),
101 (unsigned)prevsliceval,
102 prevsliceunit,
103 _T("and"),
104 (unsigned)tick_cur,
105 (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice]
106 );
107 }
108 }
109 else if(tick_cur != 0)
110 {
111 /* the current slice is not the last, and non-zero */
112
113 if(prevsliceval != 0)
114 {
115 /* there's a previous slice: print it */
116 assert(prevsliceunit);
117 _tprintf(_T("%u %s, "), (unsigned)prevsliceval, prevsliceunit);
118 }
119
120 /* recursion on the next slice size, storing the current slice */
121 print_uptime
122 (
123 tick_residual,
124 tick_cur,
125 (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice],
126 curslice + 1
127 );
128 }
129 else
130 {
131 /*
132 the current slice is not the last, and zero: recursion, remembering the
133 previous non-zero slice
134 */
135 print_uptime(tick_residual, prevsliceval, prevsliceunit, curslice + 1);
136 }
137 }
138
139 int parse_print(const _TCHAR * str)
140 {
141 int64_ tickcount;
142
143 tickcount = _ttoi64(str);
144
145 if(tickcount < 0)
146 tickcount = - tickcount;
147 else if(tickcount == 0)
148 return 1;
149
150 print_uptime(tickcount, 0, NULL, 0);
151 _puttc(_T('\n'), stdout);
152
153 return 0;
154 }
155
156 int _tmain(int argc, _TCHAR * argv[])
157 {
158 int r;
159
160 if(argc <= 1)
161 {
162 print_uptime((uint64_)GetTickCount(), 0, NULL, 0);
163 _puttc(_T('\n'), stdout);
164 }
165 else if(argc == 2 && argv[1][0] == _T('-') && argv[1][1] == 0)
166 {
167 while(!feof(stdin))
168 {
169 _TCHAR buf[23];
170 _TCHAR * str;
171
172 str = _fgetts(buf, 22, stdin);
173
174 if(str == NULL)
175 return 0;
176
177 if((r = parse_print(str)) != 0)
178 return r;
179 }
180 }
181 else
182 {
183 int i;
184
185 for(i = 1; i < argc; ++ i)
186 if((r = parse_print(argv[i])) != 0)
187 return r;
188 }
189
190 return 0;
191 }