freeswitch/libs/unimrcp/build/svnrev/svnrev.c

382 lines
13 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* SvnRev
*
* This utility retrieves the highest number that follows the "$Id: $" keyword
* or a combination of the $Rev: $ and $Date: $ keywords. The Subversion
* version control system expands these keywords and keeps them up to date.
* For an example of the tag, see the end of this comment.
*
* Details on the usage and the operation of this utility is available on-line
* at http://www.compuphase.com/svnrev.htm.
*
*
* Acknowledgements
*
* The support for .java files is contributed by Tom McCann (tommc@spoken.com).
* The option for prefixing and/or suffixing the build number (in the string
* constant SVN_REVSTR) was suggested by Robert Nitzel.
*
*
* License
*
* Copyright (c) 2005-2009, ITB CompuPhase (www.compuphase.com).
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id: svnrev.c 1497 2010-02-12 17:20:21Z achaloyan $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <apr_pools.h>
#include <apr_file_io.h>
#if defined __WIN32__ || defined _Win32 || defined _WIN32
#define DIRSEP '\\'
#elif defined macintosh
#define DIRSEP ':'
#else
/* assume Linux/Unix */
#define DIRSEP '/'
#endif
#define MAX_LINELENGTH 512
#define MAX_SYMBOLLENGTH 32
static void about(void)
{
printf("svnrev 1.7.\n\n");
printf("Usage: svnrev [options] <input> [input [...]]\n\n"
"Options:\n"
"-ofilename\tOutput filename for the file with the build number. When no\n"
"\t\tfilename follows \"-o\", the result is written to stdout. The\n"
"\t\tdefault filename is \"svnrev.h\" for C/C++ and \"VersionInfo.java\"\n"
"\t\tfor Java.\n\n"
"-fpattern\tFormat: Adds text before or after the build number in the\n"
"\t\tconstant SVN_REVSTR. The pattern has the form \"text#text\"\n"
"\t\t(without the quotes) where \"text\" is arbitrary text and \"#\"\n"
"\t\twill be replaced by the build number.\n\n"
"-i\t\tIncremental: this option should be used when the list of input\n"
"\t\tfiles is a subset of all files in the project. When -i is\n"
"\t\tpresent, svnrev also scans the output file that was generated\n"
"\t\ton a previous run.\n\n"
"-jname\t\tJava: this option writes a java package file instead of a C/C++\n"
"\t\theader file. The name of the Java package must follow the\n"
"\t\toption (this is not the filename).\n\n"
"-v\t\tVerbose: prints the names of files that are modified since the\n"
"\t\tlast commit (into version control) to stderr.\n");
exit(1);
}
static void processfile(const char *name, int failsilent,
int *max_build, int *accum_build,
int *max_year, int *max_month, int *max_day,
int *ismodified)
{
char str[MAX_LINELENGTH], str_base[MAX_LINELENGTH];
char name_base[MAX_LINELENGTH];
char *p1;
FILE *fp, *fp_base;
int build, maj_build;
int year, month, day;
int cnt;
char modchar;
/* since we also want to verify whether the file is modified in version
* control, get the path to the working copy name
* for every source file "<path>\<filename>, the "working copy" base can
* be found in "<path>\.svn\text-base\<filename>.svn-base"
*/
if ((p1 = strrchr(name, DIRSEP)) != NULL) {
++p1; /* skip directory separator character ('\' in Windows, '/' in Linux) */
strncpy(name_base, name, (int)(p1 - name));
name_base[(int)(p1 - name)] = '\0';
} else {
name_base[0] = '\0';
p1 = (char*)name;
} /* if */
sprintf(name_base + strlen(name_base), ".svn%ctext-base%c%s.svn-base",
DIRSEP, DIRSEP, p1);
/* first extract the revision keywords */
fp = fopen(name, "r");
if (fp == NULL) {
if (!failsilent)
fprintf(stderr, "Failed to open input file '%s'\n", name);
return;
} /* if */
fp_base = fopen(name_base, "r"); /* fail silently */
build = 0;
maj_build = 0; /* RCS / CVS */
year = month = day = 0;
while (fgets(str, sizeof str, fp) != NULL) {
if (fp_base == NULL || fgets(str_base, sizeof str_base, fp_base) == NULL)
str_base[0] = '\0';
if ((p1 = strstr(str, "$Id:")) != NULL && strchr(p1+1, '$') != NULL) {
if (sscanf(p1, "$Id: %*s %d %d-%d-%d", &build, &year, &month, &day) < 4
&& sscanf(p1, "$Id: %*s %d %d/%d/%d", &build, &year, &month, &day) < 4)
if (sscanf(p1, "$Id: %*s %d.%d %d-%d-%d", &maj_build, &build, &year, &month, &day) < 5)
sscanf(p1, "$Id: %*s %d.%d %d/%d/%d", &maj_build, &build, &year, &month, &day);
} else if ((p1 = strstr(str, "$Rev:")) != NULL && strchr(p1+1, '$') != NULL) {
if (sscanf(p1, "$Rev: %d.%d", &maj_build, &build) < 2) {
sscanf(p1, "$Rev: %d", &build);
maj_build = 0;
} /* if */
} else if ((p1 = strstr(str, "$Revision:")) != NULL && strchr(p1+1, '$') != NULL) {
if (sscanf(p1, "$Revision: %d.%d", &maj_build, &build) < 2) {
/* SvnRev also writes this keyword in its own generated file; read it
* back for partial updates
*/
cnt = sscanf(p1, "$Revision: %d%c", &build, &modchar);
if (cnt == 2 && modchar == 'M' && ismodified != NULL)
*ismodified = 1;
maj_build = 0;
} /* if */
} else if ((p1 = strstr(str, "$Date:")) != NULL && strchr(p1+1, '$') != NULL) {
if (sscanf(p1, "$Date: %d-%d-%d", &year, &month, &day) < 3)
sscanf(p1, "$Date: %d/%d/%d", &year, &month, &day);
} else if (ismodified != NULL && *ismodified == 0 && fp_base != NULL) {
/* no keyword present, compare the lines for equivalence */
*ismodified = strcmp(str, str_base) != 0;
} /* if */
if (maj_build)
*accum_build += build; /* RCS / CVS */
else if (build > *max_build)
*max_build = build; /* Subversion */
if (year > *max_year
|| (year == *max_year && month > *max_month)
|| (year == *max_year && month == *max_month && day > *max_day))
{
*max_year = year;
*max_month = month;
*max_day = day;
} /* if */
if (build > 0 && year > 0 && (fp_base == NULL || ismodified == NULL || *ismodified != 0))
break; /* both build # and date found, not comparing or modification
* already found => no need to search further */
} /* while */
fclose(fp);
if (fp_base != NULL)
fclose(fp_base);
}
int main(int argc, char *argv[])
{
char *outname = NULL;
FILE *fp;
FILE *input_file;
char *input_file_name = NULL;
char *path_prefix = NULL;
int index;
int process_self = 0;
int verbose = 0;
int max_build, accum_build;
int max_year, max_month, max_day;
int ismodified, filemodified;
char prefix[MAX_SYMBOLLENGTH], suffix[MAX_SYMBOLLENGTH];
char modified_suffix[2];
int write_java = 0; /* flag for Java output, 0=.h output, 1=.java output */
/* java package to put revision info in.
* REVIEW - I assume if you want Java output you will specify a package. */
char *java_package = NULL;
if (argc <= 1)
about();
/* collect the options */
prefix[0] = '\0';
suffix[0] = '\0';
for (index = 1; index < argc; index++) {
/* check for options */
if (argv[index][0] == '-'
#if defined __WIN32__ || defined _Win32 || defined _WIN32
|| argv[index][0] == '/'
#endif
)
{
switch (argv[index][1]) {
case 'f': {
int len;
char *ptr = strchr(&argv[index][2], '#');
len = (ptr != NULL) ? (int)(ptr - &argv[index][2]) : (int)strlen(&argv[index][2]);
if (len >= MAX_SYMBOLLENGTH)
len = MAX_SYMBOLLENGTH - 1;
strncpy(prefix, &argv[index][2], len);
prefix[len] = '\0';
ptr = (ptr != NULL) ? ptr + 1 : strchr(argv[index], '\0');
len = (int)strlen(ptr);
if (len >= MAX_SYMBOLLENGTH)
len = MAX_SYMBOLLENGTH - 1;
strncpy(suffix, ptr, len);
suffix[len] = '\0';
break;
} /* case */
case 'i':
process_self = 1;
break;
case 'j':
write_java=1;
java_package = &argv[index][2];
break;
case 'o':
outname = &argv[index][2];
break;
case 'r':
input_file_name = &argv[index][2];
break;
case 'p':
path_prefix = &argv[index][2];
break;
case 'v':
verbose = 1;
break;
default:
fprintf(stderr, "Invalid option '%s'\n", argv[index]);
about();
} /* switch */
} /* if */
} /* for */
if (outname == NULL)
outname = write_java ? "SvnRevision.java" : "uni_revision.h";
if (!process_self && *outname != '\0')
remove(outname);
/* phase 1: scan through all files and get the highest build number */
max_build = 0;
accum_build = 0; /* for RCS / CVS */
max_year = max_month = max_day = 0;
ismodified = 0;
if(input_file_name) {
input_file = fopen(input_file_name, "r");
if (input_file != NULL) {
apr_dir_t *dir;
apr_finfo_t finfo;
apr_status_t rv;
apr_pool_t *pool;
char *file_path;
char dir_path[256]; /* line */
int offset = 0;
if(path_prefix)
offset = sprintf(dir_path, "%s", path_prefix);
else
offset = sprintf(dir_path, "../../");
apr_initialize();
apr_pool_create(&pool,NULL);
while (fgets(dir_path + offset, sizeof(dir_path) - offset, input_file) != NULL ) { /* read a line */
size_t len = strlen(dir_path)-1;
if(dir_path[len] == '\n')
dir_path[len] = 0;
rv = apr_dir_open(&dir,dir_path,pool);
if(rv == APR_SUCCESS) {
while (apr_dir_read(&finfo, APR_FINFO_NAME, dir) == APR_SUCCESS) { /* get next file */
if(finfo.filetype != APR_REG) continue;
apr_filepath_merge(&file_path,dir_path,finfo.name,0,pool);
filemodified = 0;
if (strcasecmp(file_path, outname)!=0)
processfile(file_path, 0, &max_build, &accum_build, &max_year, &max_month, &max_day, &filemodified);
if (filemodified && verbose)
fprintf(stderr, "\tNotice: modified file '%s'\n", file_path);
ismodified = ismodified || filemodified;
}
apr_dir_close(dir);
}
else {
fprintf(stderr, "No such directory '%s'\n", dir_path);
}
}
fclose (input_file);
apr_pool_destroy(pool);
apr_terminate();
}
else {
fprintf(stderr, "No such input file '%s'\n", input_file_name);
}
}
else {
for (index = 1; index < argc; index++) {
/* skip the options (already handled) */
if (argv[index][0] == '-'
#if defined __WIN32__ || defined _Win32 || defined _WIN32
|| argv[index][0] == '/'
#endif
)
continue;
filemodified = 0;
if (strcasecmp(argv[index], outname)!=0)
processfile(argv[index], 0, &max_build, &accum_build, &max_year, &max_month, &max_day, &filemodified);
if (filemodified && verbose)
fprintf(stderr, "\tNotice: modified file '%s'\n", argv[index]);
ismodified = ismodified || filemodified;
} /* for */
}
/* also run over the existing header file, if any */
if (process_self && *outname != '\0')
processfile(outname, 1, &max_build, &accum_build, &max_year, &max_month, &max_day, NULL/*&ismodified*/);
if (accum_build > max_build)
max_build = accum_build;
modified_suffix[0] = ismodified ? 'M' : '\0';
modified_suffix[1] = '\0';
/* phase 2: write a file with this highest build number */
if (*outname == '\0') {
fp = stdout;
} else if ((fp = fopen(outname, "w")) == NULL) {
fprintf(stderr, "Failed to create output file '%s'\n", outname);
return 2;
} /* if */
if (*outname != '\0') {
/* don't print the comments to stdout */
fprintf(fp, "/* This file was generated by the \"svnrev\" utility\n"
" * (http://www.compuphase.com/svnrev.htm).\n"
" * You should not modify it manually, as it may be re-generated.\n"
" *\n"
" * $Revision: %d%s$\n"
" * $Date: %04d-%02d-%02d$\n"
" */\n\n", max_build, modified_suffix, max_year, max_month, max_day);
} /* if */
fprintf(fp, "#ifndef UNI_REVISION_H\n");
fprintf(fp, "#define UNI_REVISION_H\n\n");
fprintf(fp, "#define UNI_REVISION\t\t%d\n", max_build);
fprintf(fp, "#define UNI_REVISION_STRING\t\"%s%d%s%s\"\n", prefix, max_build, modified_suffix, suffix);
fprintf(fp, "#define UNI_REVISION_DATE\t\"%04d-%02d-%02d\"\n", max_year, max_month, max_day);
fprintf(fp, "#define UNI_REVISION_STAMP\t%04d%02d%02dL\n", max_year, max_month, max_day);
fprintf(fp, "#define UNI_REVISION_MODIFIED\t%d\n", ismodified);
fprintf(fp, "\n#endif /* UNI_REVISION_H */\n");
if (*outname != '\0')
fclose(fp);
return 0;
}