2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* Make the AFS_component_version_number.c file. Do it in C since there's no
11 * guarantee of perl on an NT platform.
17 #include <sys/types.h>
24 #define VERINFO_STRING_CHARS_MAX 950 /* max chars in verinfo string */
25 #define CFILE_STRING_CHARS_MAX 2000 /* max chars in C file string */
27 #define DEPTH_MAX 6 /* maximum depth of src dir search (>= 3) */
29 #define CMLDIR_DFLT "../../src/CML" /* default starting point for search */
30 #define CMLDIR_BUFSZ ((DEPTH_MAX * (sizeof("../") - 1)) + sizeof("src/CML"))
31 static char cmldir[CMLDIR_BUFSZ];
34 #define STAMPS "stamps"
36 #define CML_STRING "cml_version_number[]=\"@(#)"
37 #define CML_VER_DECL "char " CML_STRING
38 char *cml_string = CML_VER_DECL;
40 #define VERINFO_BUILD_STRING "#define AFS_VERINFO_BUILD "
42 #define AFS_STRING "char* AFSVersion = \""
43 #define VERS_FILE "AFS_component_version_number"
51 deltaNames stateDeltas[MAXDELTAS], stampDeltas[MAXDELTAS];
63 } cfgFormat = CF_DEFAULT;
67 void PrintStamps(void);
73 ("Usage: %s [-d directory] [-o output file name] [-c component] [-v | -t | -x]\n",
75 printf("%s creates the AFS_component_version_number.c file.\n",
78 printf("-d directory - path of the CML directory, default is %s.\n",
80 printf("-o file name - alternate output file name.\n");
82 ("-c component - if not \"afs\" prefix for cml_version_number variable.\n");
83 printf("-v generate NT versioninfo style declarations.\n");
84 printf("-t generate text file style information.\n");
85 printf("-x generate XML revision information.\n");
90 main(int argc, char **argv)
92 char stampsFile[1024];
98 char *outputFile = NULL;
99 char outputFileBuf[sizeof(VERS_FILE) + 2];
104 char *cml_prefix = NULL;
106 /* initialize cmldir buffer and set default starting directory */
107 for (i = 0; i < DEPTH_MAX; i++) {
108 strcat(cmldir, "../");
110 strcat(cmldir, "src/CML");
112 baseDir = strstr(cmldir, CMLDIR_DFLT);
114 programName = argv[0];
116 for (i = 1; i < argc; i++) {
117 if (!strcmp("-d", argv[i])) {
119 if (i >= argc || *argv[i] == '-') {
120 printf("Missing directory name for -d option.\n");
125 } else if (!strcmp("-o", argv[i])) {
127 if (i >= argc || *argv[i] == '-') {
128 printf("Missing output file name for -o option.\n");
131 outputFile = argv[i];
132 } else if (!strcmp("-c", argv[i])) {
134 if (i >= argc || *argv[i] == '-') {
135 printf("Missing component for -c option.\n");
138 cml_prefix = argv[i];
139 } else if (!strcmp("-v", argv[i])) {
140 if (cfgFormat == CF_DEFAULT || cfgFormat == CF_VERINFO) {
141 cfgFormat = CF_VERINFO;
143 printf("Specify only one alternative output format\n");
146 } else if (!strcmp("-t", argv[i])) {
147 if (cfgFormat == CF_DEFAULT || cfgFormat == CF_TEXT) {
150 printf("Specify only one alternative output format\n");
153 } else if (!strcmp("-x", argv[i])) {
154 if (cfgFormat == CF_DEFAULT || cfgFormat == CF_XML) {
157 printf("Specify only one alternative output format\n");
161 printf("%s: Unknown argument.\n", argv[i]);
166 /* set outputFile if not specified */
168 if (outputFile == NULL) {
169 strcpy(outputFileBuf, VERS_FILE);
170 if (cfgFormat == CF_VERINFO) {
171 strcat(outputFileBuf, ".h");
172 } else if (cfgFormat == CF_TEXT) {
173 strcat(outputFileBuf, ".txt");
174 } else if (cfgFormat == CF_XML) {
175 strcat(outputFileBuf, ".xml");
177 strcat(outputFileBuf, ".c");
179 outputFile = outputFileBuf;
182 /* Determine if we need to create the output file. */
184 if ((code = stat(outputFile, &sbuf)) < 0) {
186 versTime = (time_t) 0; /* indicates no output file. */
188 versTime = sbuf.st_mtime;
191 sprintf(stampsFile, "%s/%s", baseDir, STAMPS);
192 code = stat(stampsFile, &sbuf);
194 while (code < 0 && errno == ENOENT && !argDir && baseDir > cmldir) {
195 /* Try path at next level of depth. */
196 baseDir -= sizeof("../") - 1;
197 sprintf(stampsFile, "%s/%s", baseDir, STAMPS);
198 code = stat(stampsFile, &sbuf);
200 if (code == 0 && versTime <= sbuf.st_mtime) {
204 sprintf(stateFile, "%s/%s", baseDir, STATE);
207 code = stat(stateFile, &sbuf);
208 /* dont' check alternate base dir, since it would be reset above */
209 if (code == 0 && versTime <= sbuf.st_mtime)
214 printf("Not rebuilding %s since it is up to date.\n", outputFile);
220 (char *)malloc(strlen("char ") + strlen(cml_prefix) + strlen(CML_STRING) +
223 printf("No space to use prefix in cml string, ignoring it.\n");
224 cml_string = CML_VER_DECL;
226 (void)sprintf(cml_string, "%s%s%s", "char ", cml_prefix,
231 fpState = fopen(stateFile, "r");
232 fpStamps = fopen(stampsFile, "r");
233 fpVers = fopen(outputFile, "w");
235 if (fpStamps == NULL || fpState == NULL || fpVers == NULL) {
237 if (cfgFormat == CF_VERINFO) {
239 "%s \"No configuration information available\"\n",
240 VERINFO_BUILD_STRING);
241 } else if (cfgFormat == CF_TEXT) {
242 fprintf(fpVers, "No configuration information available.\n");
245 "%sNo configuration information available\";\n",
247 fprintf(fpVers, "%safs??\";\n", AFS_STRING);
251 fprintf(stderr, "Can't write version information to %s.\n",
255 "No configuration information available, continuing...\n");
261 while (fgets(s, sizeof(s), fpState)) {
262 if (*s == 'I' || *s == 'N' || *s == 'C' || *s == 'O') {
263 stateDeltas[nStates].type = *s;
264 s[strlen(s) - 1] = '\0';
265 (void)strcpy(stateDeltas[nStates].name, s + 2);
285 size_t outMax, outCount = 0;
287 if (cfgFormat == CF_VERINFO) {
288 outMax = VERINFO_STRING_CHARS_MAX;
289 } else if (cfgFormat == CF_TEXT) {
290 outMax = 0; /* signifies that there is no maximum */
292 outMax = CFILE_STRING_CHARS_MAX;
295 for (i = 0; i < nStates; i++) {
296 if (stateDeltas[i].type == 'C') {
297 if (cfgFormat == CF_VERINFO) {
298 fprintf(fpVers, "%s \"Base configuration %s",
299 VERINFO_BUILD_STRING, stateDeltas[i].name);
300 } else if (cfgFormat == CF_TEXT) {
301 fprintf(fpVers, "Base configuration %s\n",
302 stateDeltas[i].name);
303 } else if (cfgFormat == CF_TEXT) {
305 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
308 "Base configuration %s\n"
310 stateDeltas[i].name);
312 fprintf(fpVers, "%sBase configuration %s", cml_string,
313 stateDeltas[i].name);
315 c = stateDeltas[i].name;
320 for (i = 0; i < nStates; i++) {
321 if (stateDeltas[i].type == 'I' || stateDeltas[i].type == 'N') {
322 outCount += strlen(stateDeltas[i].name) + 2;
323 if (outMax && outCount > outMax) {
326 if (cfgFormat == CF_TEXT) {
327 fprintf(fpVers, "%c%s\n", stateDeltas[i].type,
328 stateDeltas[i].name);
329 } else if (cfgFormat == CF_XML) {
335 stateDeltas[i].name);
337 fprintf(fpVers, ";%c%s", stateDeltas[i].type,
338 stateDeltas[i].name);
343 for (i = 0; i < nStates; i++) {
344 if (stateDeltas[i].type == 'O') {
345 outCount += strlen(stateDeltas[i].name) + 2;
346 if (outMax && outCount > outMax) {
349 if (cfgFormat == CF_TEXT) {
350 fprintf(fpVers, "%c%s\n", stateDeltas[i].type,
351 stateDeltas[i].name);
352 } else if (cfgFormat == CF_XML) {
358 stateDeltas[i].name);
360 fprintf(fpVers, ";%c%s", stateDeltas[i].type,
361 stateDeltas[i].name);
366 if (outMax && outCount > outMax) {
367 fprintf(fpVers, ";[LIST TRUNCATED]");
370 if (cfgFormat == CF_VERINFO) {
371 fprintf(fpVers, "\"\n");
372 } else if (cfgFormat == CF_DEFAULT) {
373 fprintf(fpVers, "\";\n");
377 s = (char *)strchr(c, ' ');
380 fprintf(fpVers, "%s%s\";\n", AFS_STRING, c ? c : "Unknown");
381 } else if (cfgFormat == CF_XML) {
382 fprintf(fpVers, "</revision>\n");