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.
16 #include <sys/types.h>
26 #define VERINFO_STRING_CHARS_MAX 950 /* max chars in verinfo string */
27 #define CFILE_STRING_CHARS_MAX 2000 /* max chars in C file string */
29 #define DEPTH_MAX 6 /* maximum depth of src dir search (>= 3) */
31 #define CMLDIR_DFLT "../../src/CML" /* default starting point for search */
32 #define CMLDIR_BUFSZ ((DEPTH_MAX * (sizeof("../") - 1)) + sizeof("src/CML"))
33 static char cmldir[CMLDIR_BUFSZ];
36 #define STAMPS "stamps"
38 #define CML_STRING "cml_version_number[]=\"@(#)"
39 #define CML_VER_DECL "char " CML_STRING
40 char *cml_string = CML_VER_DECL;
42 #define VERINFO_BUILD_STRING "#define AFS_VERINFO_BUILD "
44 #define AFS_STRING "char* AFSVersion = \""
45 #define VERS_FILE "AFS_component_version_number"
53 deltaNames stateDeltas[MAXDELTAS], stampDeltas[MAXDELTAS];
64 } cfgFormat = CF_DEFAULT;
68 void PrintStamps(void);
72 printf("Usage: %s [-d directory] [-o output file name] [-c component] [-v | -t]\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");
80 printf("-c component - if not \"afs\" prefix for cml_version_number variable.\n");
81 printf("-v generate NT versioninfo style declarations.\n");
82 printf("-t generate text file style information.\n");
86 int main(int argc, char **argv)
88 char stampsFile[1024];
94 char *outputFile = NULL;
95 char outputFileBuf[sizeof(VERS_FILE) + 2];
100 char *cml_prefix = NULL;
102 /* initialize cmldir buffer and set default starting directory */
103 for (i = 0; i < DEPTH_MAX; i++) {
104 strcat(cmldir, "../");
106 strcat(cmldir, "src/CML");
108 baseDir = strstr(cmldir, CMLDIR_DFLT);
111 programName = argv[0];
113 for (i=1; i<argc; i++) {
114 if (!strcmp("-d", argv[i])) {
116 if (i>=argc || *argv[i] == '-') {
117 printf("Missing directory name for -d option.\n");
123 else if (!strcmp("-o", argv[i])) {
125 if (i>=argc || *argv[i] == '-') {
126 printf("Missing output file name for -o option.\n");
129 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];
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");
147 else if (!strcmp("-t", argv[i])) {
148 if (cfgFormat == CF_DEFAULT || cfgFormat == CF_TEXT) {
151 printf("Specify only one alternative output format\n");
156 printf("%s: Unknown argument.\n", argv[i]);
161 /* set outputFile if not specified */
163 if (outputFile == NULL) {
164 strcpy(outputFileBuf, VERS_FILE);
165 if (cfgFormat == CF_VERINFO) {
166 strcat(outputFileBuf, ".h");
167 } else if (cfgFormat == CF_TEXT) {
168 strcat(outputFileBuf, ".txt");
170 strcat(outputFileBuf, ".c");
172 outputFile = outputFileBuf;
175 /* Determine if we need to create the output file. */
177 if ((code = stat(outputFile, &sbuf)) < 0) {
179 versTime = (time_t)0; /* inidicates no output file. */
182 versTime = sbuf.st_mtime;
185 sprintf(stampsFile, "%s/%s", baseDir, STAMPS);
186 code = stat(stampsFile, &sbuf);
188 while (code < 0 && errno == ENOENT && !argDir && baseDir > cmldir) {
189 /* Try path at next level of depth. */
190 baseDir -= sizeof("../") - 1;
191 sprintf(stampsFile, "%s/%s", baseDir, STAMPS);
192 code = stat(stampsFile, &sbuf);
194 if (code == 0 && versTime <= sbuf.st_mtime) {
198 sprintf(stateFile, "%s/%s", baseDir, STATE);
201 code = stat(stateFile, &sbuf);
202 /* dont' check alternate base dir, since it would be reset above */
203 if (code == 0 && versTime <= sbuf.st_mtime)
208 printf("Not rebuilding %s since it is up to date.\n", outputFile);
213 cml_string = malloc(strlen("char ") +
214 strlen(cml_prefix) + strlen(CML_STRING) + 1);
216 printf("No space to use prefix in cml string, ignoring it.\n");
217 cml_string = CML_VER_DECL;
220 (void) sprintf(cml_string, "%s%s%s",
221 "char ", cml_prefix, CML_STRING);
225 fpState = fopen(stateFile, "r");
226 fpStamps = fopen(stampsFile, "r");
227 fpVers = fopen(outputFile, "w");
229 if (fpStamps == NULL || fpState == NULL || fpVers == NULL) {
231 if (cfgFormat == CF_VERINFO) {
233 "%s \"No configuration information available\"\n",
234 VERINFO_BUILD_STRING);
235 } else if (cfgFormat == CF_TEXT) {
237 "No configuration information available.\n");
240 "%sNo configuration information available\";\n",
242 fprintf(fpVers, "%safs??\";\n", AFS_STRING);
247 fprintf(stderr,"Can't write version information to %s.\n",
251 "No configuration information available, continuing...\n");
257 while (fgets(s, sizeof(s), fpState)) {
258 if (*s == 'I' || *s == 'N' || *s == 'C' || *s == 'O') {
259 stateDeltas[nStates].type = *s;
260 s[strlen(s)-1] = '\0';
261 (void) strcpy(stateDeltas[nStates].name, s+2);
275 void PrintStamps(void)
280 size_t outMax, outCount = 0;
282 if (cfgFormat == CF_VERINFO) {
283 outMax = VERINFO_STRING_CHARS_MAX;
284 } else if (cfgFormat == CF_TEXT) {
285 outMax = 0; /* signifies that there is no maximum */
287 outMax = CFILE_STRING_CHARS_MAX;
290 for (i=0; i<nStates; i++) {
291 if (stateDeltas[i].type == 'C') {
292 if (cfgFormat == CF_VERINFO) {
293 fprintf(fpVers, "%s \"Base configuration %s",
294 VERINFO_BUILD_STRING, stateDeltas[i].name);
295 } else if (cfgFormat == CF_TEXT) {
296 fprintf(fpVers, "Base configuration %s\n",
297 stateDeltas[i].name);
299 fprintf(fpVers, "%sBase configuration %s",
300 cml_string, stateDeltas[i].name);
302 c = stateDeltas[i].name;
307 for (i=0; i<nStates; i++) {
308 if (stateDeltas[i].type == 'I' || stateDeltas[i].type == 'N') {
309 outCount += strlen(stateDeltas[i].name) + 2;
310 if (outMax && outCount > outMax) {
313 if (cfgFormat == CF_TEXT) {
314 fprintf(fpVers, "%c%s\n", stateDeltas[i].type,
315 stateDeltas[i].name);
317 fprintf(fpVers, ";%c%s", stateDeltas[i].type,
318 stateDeltas[i].name);
323 for (i=0; i<nStates; i++) {
324 if (stateDeltas[i].type == 'O') {
325 outCount += strlen(stateDeltas[i].name) + 2;
326 if (outMax && outCount > outMax) {
329 if (cfgFormat == CF_TEXT) {
330 fprintf(fpVers, "%c%s\n", stateDeltas[i].type,
331 stateDeltas[i].name);
333 fprintf(fpVers, ";%c%s", stateDeltas[i].type,
334 stateDeltas[i].name);
339 if (outMax && outCount > outMax) {
340 fprintf(fpVers, ";[LIST TRUNCATED]");
343 if (cfgFormat == CF_VERINFO) {
344 fprintf(fpVers, "\"\n");
345 } else if (cfgFormat == CF_DEFAULT) {
346 fprintf(fpVers, "\";\n");
350 s = (char*)strchr(c, ' ');
353 fprintf(fpVers, "%s%s\";\n", AFS_STRING, c ? c : "Unknown");