868505bab754845360da50cb4715a8d48499d47f
[reactos.git] / reactos / tools / buildno.c
1 /* $Id: buildno.c,v 1.1 2001/08/23 21:41:35 ekohl Exp $
2 *
3 * buildno - Generate the build number for ReactOS
4 *
5 * Copyright (c) 1999,2000 Emanuele Aliberti
6 *
7 * License: GNU GPL
8 *
9 * It assumes the last release date is defined in
10 * <reactos/version.h> as a macro named
11 *
12 * KERNEL_RELEASE_DATE
13 *
14 * as a 32-bit unsigned long YYYYMMDD (UTC;
15 * MM=01-12; DD=01-31).
16 *
17 * The build number is the number of full days
18 * elapsed since the last release date (UTC).
19 *
20 * The build number is stored in the file
21 * <reactos/buildno.h> as a set of macros:
22 *
23 * KERNEL_VERSION_BUILD base 10 number
24 * KERNEL_VERSION_BUILD_STR C string
25 * KERNEL_VERSION_BUILD_RC RC string
26 *
27 * REVISIONS
28 * ---------
29 * 2000-01-22 (ea)
30 * Fixed bugs: tm_year is (current_year - 1900),
31 * tm_month is 0-11 not 1-12 and code ignored TZ.
32 * 2000-12-10 (ea)
33 * Added -p option to make it simply print the
34 * version number, but skip buildno.h generation.
35 */
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <time.h>
39 #include "../include/reactos/version.h"
40
41 #define FALSE 0
42 #define TRUE 1
43
44 /* File to (over)write */
45 #define BUILDNO_INCLUDE_FILE "../include/reactos/buildno.h"
46
47 static char * argv0 = "";
48
49 #ifdef DBG
50 void
51 tm_dump (const char *tag, struct tm * t)
52 {
53 printf ("%s->tm_sec = %d\n", tag, t->tm_sec);
54 printf ("%s->tm_min = %d\n", tag, t->tm_min);
55 printf ("%s->tm_hour = %d\n", tag, t->tm_hour);
56 printf ("%s->tm_mday = %d\n", tag, t->tm_mday);
57 printf ("%s->tm_mon = %d\n", tag, t->tm_mon);
58 printf ("%s->tm_year = %d\n", tag, t->tm_year);
59 printf ("%s->tm_wday = %d\n", tag, t->tm_wday);
60 printf ("%s->tm_yday = %d\n", tag, t->tm_yday);
61 printf ("%s->tm_isdst = %d\n\n", tag, t->tm_isdst);
62 }
63 #endif
64
65
66 int
67 elapsed_days (
68 time_t t_today,
69 time_t t_release_day
70 )
71 {
72 double seconds = difftime (t_today, t_release_day);
73 double days = seconds / (double) 86400.0;
74 char buf [32];
75 char * dot = buf;
76
77 sprintf (buf, "%f", days );
78
79 while ( *dot && *dot != '.') ++dot;
80 *dot = '\0';
81
82 return atol (buf);
83 }
84
85 void
86 write_h (int build)
87 {
88 FILE *h = NULL;
89 char* s;
90 char* s1;
91 int length;
92
93 s1 = s = malloc(256 * 1024);
94
95 s = s + sprintf (s, "/* Do not edit - Machine generated */\n");
96
97 s = s + sprintf (s, "#ifndef _INC_REACTOS_BUILDNO\n" );
98 s = s + sprintf (s, "#define _INC_REACTOS_BUILDNO\n" );
99
100 s = s + sprintf (s, "#define KERNEL_VERSION_BUILD\t%d\n", build);
101 s = s + sprintf (s, "#define KERNEL_VERSION_BUILD_STR\t\"%d\"\n", build);
102 s = s + sprintf (s, "#define KERNEL_RELEASE_RC\t\"%d.%d.%d.%d\\0\"\n",
103 KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR,
104 KERNEL_VERSION_PATCH_LEVEL, build);
105 s = s + sprintf (s, "#define KERNEL_RELEASE_STR\t\"%d.%d.%d.%d\"\n",
106 KERNEL_VERSION_MAJOR,
107 KERNEL_VERSION_MINOR,
108 KERNEL_VERSION_PATCH_LEVEL,
109 build);
110 s = s + sprintf (s, "#define KERNEL_VERSION_RC\t\"%d.%d.%d\\0\"\n",
111 KERNEL_VERSION_MAJOR,
112 KERNEL_VERSION_MINOR,
113 KERNEL_VERSION_PATCH_LEVEL);
114 s = s + sprintf (s, "#define KERNEL_VERSION_STR\t\"%d.%d.%d\"\n",
115 KERNEL_VERSION_MAJOR,
116 KERNEL_VERSION_MINOR,
117 KERNEL_VERSION_PATCH_LEVEL);
118 s = s + sprintf (s, "#endif\n/* EOF */\n");
119
120 h = fopen (BUILDNO_INCLUDE_FILE, "r");
121 if (h != NULL)
122 {
123 fseek(h, 0, SEEK_END);
124 length = ftell(h);
125 if (length == strlen(s1))
126 {
127 char* orig;
128
129 orig = malloc(length);
130 fseek(h, 0, SEEK_SET);
131 fread(orig, 1, length, h);
132 if (memcmp(s1, orig, length) == 0)
133 {
134 fclose(h);
135 return;
136 }
137 }
138 fclose(h);
139 }
140
141 h = fopen (BUILDNO_INCLUDE_FILE, "w");
142 if (!h)
143 {
144 fprintf (stderr,
145 "%s: can not create file \"%s\"!\n",
146 argv0,
147 BUILDNO_INCLUDE_FILE);
148 return;
149 }
150 fwrite(s1, 1, strlen(s1), h);
151 fclose (h);
152 }
153
154 void
155 usage (void)
156 {
157 fprintf (
158 stderr,
159 "Usage: %s [-{p|q}]\n\n -p print version number and exit\n -q run in quiet mode\n",
160 argv0
161 );
162 exit (EXIT_SUCCESS);
163 }
164
165
166 int
167 main (int argc, char * argv [])
168 {
169 int print_only = FALSE;
170 int quiet = FALSE;
171
172 int year = 0;
173 int month = 0;
174 int day = 0;
175 int build = 0;
176
177 time_t t0 = 0;
178 struct tm t0_tm = {0};
179 time_t t1 = 0;
180 struct tm * t1_tm = NULL;
181
182 argv0 = argv[0];
183
184 switch (argc)
185 {
186 case 1:
187 break;
188 case 2:
189 if (argv[1][0] == '-')
190 {
191 if (argv[1][1] == 'q')
192 {
193 quiet = TRUE;
194 }
195 else if (argv[1][1] == 'p')
196 {
197 print_only = TRUE;
198 }
199 else
200 {
201 usage ();
202 }
203 }
204 else
205 {
206 usage ();
207 }
208 break;
209 default:
210 usage ();
211 }
212 /*
213 * Set TZ information.
214 */
215 tzset ();
216 /*
217 * We are building TODAY!
218 */
219 time (& t0);
220 /*
221 * "Parse" the release date.
222 */
223 day = KERNEL_RELEASE_DATE % 100;
224 month = ( ( KERNEL_RELEASE_DATE
225 % 10000
226 )
227 - day
228 )
229 / 100;
230 year =
231 ( KERNEL_RELEASE_DATE
232 - (month * 100)
233 - day
234 )
235 / 10000;
236 if (FALSE == quiet)
237 {
238 printf ( "\n\
239 ReactOS Build Number Generator\n\n\
240 Last release: %4d-%02d-%02d\n",
241 year,
242 month,
243 day
244 );
245 }
246 #ifdef DBG
247 tm_dump ("t0", & t0_tm);
248 #endif
249 t0_tm.tm_year = (year - 1900);
250 t0_tm.tm_mon = --month; /* 0-11 */
251 t0_tm.tm_mday = day;
252 t0_tm.tm_hour = 0;
253 t0_tm.tm_min = 0;
254 t0_tm.tm_sec = 1;
255 t0_tm.tm_isdst = -1;
256
257 #ifdef DBG
258 tm_dump ("t0", & t0_tm);
259 #endif
260
261 if (-1 == (t0 = mktime (& t0_tm)))
262 {
263 fprintf (
264 stderr,
265 "%s: can not convert release date!\n",
266 argv[0]
267 );
268 return EXIT_FAILURE;
269 }
270
271 time (& t1); /* current build time */
272 t1_tm = gmtime (& t1);
273
274 #ifdef DBG
275 tm_dump ("t1", t1_tm);
276 #endif
277 t1_tm->tm_year +=
278 (t1_tm->tm_year < 70)
279 ? 2000
280 : 1900;
281 #ifdef DBG
282 tm_dump ("t1", t1_tm);
283 #endif
284 if (FALSE == quiet)
285 {
286 printf (
287 "Current date: %4d-%02d-%02d\n\n",
288 t1_tm->tm_year,
289 (t1_tm->tm_mon + 1),
290 t1_tm->tm_mday
291 );
292 }
293 /*
294 * Compute delta days.
295 */
296 build = elapsed_days (t1, t0);
297
298 if (FALSE == quiet)
299 {
300 printf (
301 "Build number: %d (elapsed days since last release)\n",
302 build
303 );
304 printf (
305 "ROS Version : %d.%d.%d.%d\n",
306 KERNEL_VERSION_MAJOR,
307 KERNEL_VERSION_MINOR,
308 KERNEL_VERSION_PATCH_LEVEL,
309 build
310 );
311 }
312 /*
313 * (Over)write the include file, unless
314 * the user switched on -p.
315 */
316 if (FALSE == print_only)
317 {
318 write_h (build);
319 }
320 else
321 {
322 printf ("%s: no code generated", argv [0]);
323 }
324
325 return EXIT_SUCCESS;
326 }
327
328
329 /* EOF */