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>
23 #define VERINFO_STRING_CHARS_MAX 950 /* max chars in verinfo string */
24 #define CFILE_STRING_CHARS_MAX 2000 /* max chars in C file string */
26 #define DEPTH_MAX 6 /* maximum depth of src dir search (>= 3) */
28 #define CMLDIR_DFLT "../../src/CML" /* default starting point for search */
29 #define CMLDIR_BUFSZ ((DEPTH_MAX * (sizeof("../") - 1)) + sizeof("src/CML"))
30 static char cmldir
[CMLDIR_BUFSZ
];
33 #define STAMPS "stamps"
35 #define CML_STRING "cml_version_number[]=\"@(#)"
36 #define CML_VER_DECL "char " CML_STRING
37 char *cml_string
= CML_VER_DECL
;
39 #define VERINFO_BUILD_STRING "#define AFS_VERINFO_BUILD "
41 #define AFS_STRING "char* AFSVersion = \""
42 #define VERS_FILE "AFS_component_version_number"
50 deltaNames stateDeltas
[MAXDELTAS
], stampDeltas
[MAXDELTAS
];
62 } cfgFormat
= CF_DEFAULT
;
66 void PrintStamps(void);
72 ("Usage: %s [-d directory] [-o output file name] [-c component] [-v | -t | -x]\n",
74 printf("%s creates the AFS_component_version_number.c file.\n",
77 printf("-d directory - path of the CML directory, default is %s.\n",
79 printf("-o file name - alternate output file name.\n");
81 ("-c component - if not \"afs\" prefix for cml_version_number variable.\n");
82 printf("-v generate NT versioninfo style declarations.\n");
83 printf("-t generate text file style information.\n");
84 printf("-x generate XML revision information.\n");
89 main(int argc
, char **argv
)
91 char stampsFile
[1024];
97 char *outputFile
= NULL
;
98 char outputFileBuf
[sizeof(VERS_FILE
) + 4];
103 char *cml_prefix
= NULL
;
105 /* initialize cmldir buffer and set default starting directory */
106 for (i
= 0; i
< DEPTH_MAX
; i
++) {
107 strcat(cmldir
, "../");
109 strcat(cmldir
, "src/CML");
111 baseDir
= strstr(cmldir
, CMLDIR_DFLT
);
113 programName
= argv
[0];
115 for (i
= 1; i
< argc
; i
++) {
116 if (!strcmp("-d", argv
[i
])) {
118 if (i
>= argc
|| *argv
[i
] == '-') {
119 printf("Missing directory name for -d option.\n");
124 } else if (!strcmp("-o", argv
[i
])) {
126 if (i
>= argc
|| *argv
[i
] == '-') {
127 printf("Missing output file name for -o option.\n");
130 outputFile
= argv
[i
];
131 } else if (!strcmp("-c", argv
[i
])) {
133 if (i
>= argc
|| *argv
[i
] == '-') {
134 printf("Missing component for -c option.\n");
137 cml_prefix
= argv
[i
];
138 } else if (!strcmp("-v", argv
[i
])) {
139 if (cfgFormat
== CF_DEFAULT
|| cfgFormat
== CF_VERINFO
) {
140 cfgFormat
= CF_VERINFO
;
142 printf("Specify only one alternative output format\n");
145 } else if (!strcmp("-t", argv
[i
])) {
146 if (cfgFormat
== CF_DEFAULT
|| cfgFormat
== CF_TEXT
) {
149 printf("Specify only one alternative output format\n");
152 } else if (!strcmp("-x", argv
[i
])) {
153 if (cfgFormat
== CF_DEFAULT
|| cfgFormat
== CF_XML
) {
156 printf("Specify only one alternative output format\n");
160 printf("%s: Unknown argument.\n", argv
[i
]);
165 /* set outputFile if not specified */
167 if (outputFile
== NULL
) {
168 strcpy(outputFileBuf
, VERS_FILE
);
169 if (cfgFormat
== CF_VERINFO
) {
170 strcat(outputFileBuf
, ".h");
171 } else if (cfgFormat
== CF_TEXT
) {
172 strcat(outputFileBuf
, ".txt");
173 } else if (cfgFormat
== CF_XML
) {
174 strcat(outputFileBuf
, ".xml");
176 strcat(outputFileBuf
, ".c");
178 outputFile
= outputFileBuf
;
181 /* Determine if we need to create the output file. */
183 if ((code
= stat(outputFile
, &sbuf
)) < 0) {
185 versTime
= (time_t) 0; /* indicates no output file. */
187 versTime
= sbuf
.st_mtime
;
190 sprintf(stampsFile
, "%s/%s", baseDir
, STAMPS
);
191 code
= stat(stampsFile
, &sbuf
);
193 while (code
< 0 && errno
== ENOENT
&& !argDir
&& baseDir
> cmldir
) {
194 /* Try path at next level of depth. */
195 baseDir
-= sizeof("../") - 1;
196 sprintf(stampsFile
, "%s/%s", baseDir
, STAMPS
);
197 code
= stat(stampsFile
, &sbuf
);
199 if (code
== 0 && versTime
<= sbuf
.st_mtime
) {
203 sprintf(stateFile
, "%s/%s", baseDir
, STATE
);
206 code
= stat(stateFile
, &sbuf
);
207 /* dont' check alternate base dir, since it would be reset above */
208 if (code
== 0 && versTime
<= sbuf
.st_mtime
)
213 printf("Not rebuilding %s since it is up to date.\n", outputFile
);
219 (char *)malloc(strlen("char ") + strlen(cml_prefix
) + strlen(CML_STRING
) +
222 printf("No space to use prefix in cml string, ignoring it.\n");
223 cml_string
= CML_VER_DECL
;
225 (void)sprintf(cml_string
, "%s%s%s", "char ", cml_prefix
,
230 fpState
= fopen(stateFile
, "r");
231 fpStamps
= fopen(stampsFile
, "r");
232 fpVers
= fopen(outputFile
, "w");
234 if (fpStamps
== NULL
|| fpState
== NULL
|| fpVers
== NULL
) {
236 if (cfgFormat
== CF_VERINFO
) {
238 "%s \"No configuration information available\"\n",
239 VERINFO_BUILD_STRING
);
240 } else if (cfgFormat
== CF_TEXT
) {
241 fprintf(fpVers
, "No configuration information available.\n");
244 "%sNo configuration information available\";\n",
246 fprintf(fpVers
, "%safs??\";\n", AFS_STRING
);
250 fprintf(stderr
, "Can't write version information to %s.\n",
254 "No configuration information available, continuing...\n");
260 while (fgets(s
, sizeof(s
), fpState
)) {
261 if (*s
== 'I' || *s
== 'N' || *s
== 'C' || *s
== 'O') {
262 stateDeltas
[nStates
].type
= *s
;
263 s
[strlen(s
) - 1] = '\0';
264 (void)strcpy(stateDeltas
[nStates
].name
, s
+ 2);
284 size_t outMax
, outCount
= 0;
285 time_t t
= time(NULL
);
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_XML
) {
305 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
308 "Base configuration %s\n"
314 stateDeltas
[i
].name
, ctime(&t
));
316 fprintf(fpVers
, "%sBase configuration %s", cml_string
,
317 stateDeltas
[i
].name
);
319 c
= stateDeltas
[i
].name
;
324 for (i
= 0; i
< nStates
; i
++) {
325 if (stateDeltas
[i
].type
== 'I' || stateDeltas
[i
].type
== 'N') {
326 outCount
+= strlen(stateDeltas
[i
].name
) + 2;
327 if (outMax
&& outCount
> outMax
) {
330 if (cfgFormat
== CF_TEXT
) {
331 fprintf(fpVers
, "%c%s\n", stateDeltas
[i
].type
,
332 stateDeltas
[i
].name
);
333 } else if (cfgFormat
== CF_XML
) {
339 stateDeltas
[i
].name
);
341 fprintf(fpVers
, ";%c%s", stateDeltas
[i
].type
,
342 stateDeltas
[i
].name
);
347 for (i
= 0; i
< nStates
; i
++) {
348 if (stateDeltas
[i
].type
== 'O') {
349 outCount
+= strlen(stateDeltas
[i
].name
) + 2;
350 if (outMax
&& outCount
> outMax
) {
353 if (cfgFormat
== CF_TEXT
) {
354 fprintf(fpVers
, "%c%s\n", stateDeltas
[i
].type
,
355 stateDeltas
[i
].name
);
356 } else if (cfgFormat
== CF_XML
) {
362 stateDeltas
[i
].name
);
364 fprintf(fpVers
, ";%c%s", stateDeltas
[i
].type
,
365 stateDeltas
[i
].name
);
370 if (outMax
&& outCount
> outMax
) {
371 fprintf(fpVers
, ";[LIST TRUNCATED]");
374 if (cfgFormat
== CF_VERINFO
) {
375 fprintf(fpVers
, "\"\n");
376 } else if (cfgFormat
== CF_DEFAULT
) {
377 fprintf(fpVers
, "\";\n");
381 s
= (char *)strchr(c
, ' ');
384 fprintf(fpVers
, "%s%s\";\n", AFS_STRING
, c
? c
: "Unknown");
385 } else if (cfgFormat
== CF_XML
) {
386 fprintf(fpVers
, "</revision>\n");