summaryrefslogtreecommitdiff
path: root/tools/mkversion.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mkversion.c')
-rw-r--r--tools/mkversion.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/tools/mkversion.c b/tools/mkversion.c
new file mode 100644
index 0000000..005babd
--- /dev/null
+++ b/tools/mkversion.c
@@ -0,0 +1,218 @@
+/*
+** This C program generates the "VERSION.h" header file from information
+** extracted out of the "manifest", "manifest.uuid", and "VERSION" files.
+** Call this program with three arguments:
+**
+** ./a.out manifest.uuid manifest VERSION
+**
+** Note that the manifest.uuid and manifest files are generated by Fossil.
+**
+** The output becomes the "VERSION.h" file. The output is a C-language
+** header that contains #defines for various properties of the build:
+**
+** MANIFEST_UUID These values are text strings that
+** MANIFEST_VERSION identify the Fossil check-in to which
+** the source tree belongs. They do not
+** take into account any uncommitted edits.
+**
+** FOSSIL_BUILD_HASH A hexadecimal string that is a strong hash
+** of the MANIFEST_UUID together with the
+** current time of the build. We normally want
+** this to be different on each build, as the
+** value is used to expire ETag: fields in
+** HTTP requests. But if you need to do
+** repeatable byte-for-byte identical builds,
+** add the -DFOSSIL_BUILD_EPOCH=n option.
+**
+** MANIFEST_DATE The date/time of the source-code check-in
+** MANIFEST_YEAR in various formats.
+** MANIFEST_NUMERIC_DATE
+** MANIFEST_NUMERIC_TIME
+**
+** RELEASE_VERSION The version number (from the VERSION source
+** RELEASE_VERSION_NUMBER file) in various format.
+** RELEASE_RESOURCE_VERSION
+**
+** New #defines may be added in the future.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+
+#if defined(_MSC_VER) && (_MSC_VER < 1800) /* MSVS 2013 */
+# define strtoll _strtoi64
+#endif
+
+static FILE *open_for_reading(const char *zFilename){
+ FILE *f = fopen(zFilename, "r");
+ if( f==0 ){
+ fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
+ exit(1);
+ }
+ return f;
+}
+
+/*
+** Given an arbitrary-length input string key zIn, generate
+** an N-byte hexadecimal hash of that string into zOut.
+*/
+static void hash(const char *zIn, int N, char *zOut){
+ unsigned char i, j, t;
+ int m, n;
+ unsigned char s[256];
+ for(m=0; m<256; m++){ s[m] = m; }
+ for(j=0, m=n=0; m<256; m++, n++){
+ j += s[m] + zIn[n];
+ if( zIn[n]==0 ){ n = -1; }
+ t = s[j];
+ s[j] = s[m];
+ s[m] = t;
+ }
+ i = j = 0;
+ for(n=0; n<N-2; n+=2){
+ i++;
+ t = s[i];
+ j += t;
+ s[i] = s[j];
+ s[j] = t;
+ t += s[i];
+ zOut[n] = "0123456789abcdef"[(t>>4)&0xf];
+ zOut[n+1] = "0123456789abcdef"[t&0xf];
+ }
+ zOut[n] = 0;
+}
+
+/* Local strcpy() clone to squelch an unwarranted warning from OpenBSD. */
+static void local_strcpy(char *dest, const char *src){
+ while( (*(dest++) = *(src++))!=0 ){}
+}
+
+int main(int argc, char *argv[]){
+ FILE *m,*u,*v;
+ char *z;
+#if defined(__DMC__) /* e.g. 0x857 */
+ int i = 0;
+#endif
+ int j = 0, x = 0, d = 0;
+ size_t n;
+ int vn[3];
+ char b[1000];
+ char vx[1000];
+ if( argc!=4 ){
+ fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]);
+ exit(1);
+ }
+ memset(b,0,sizeof(b));
+ memset(vx,0,sizeof(vx));
+ u = open_for_reading(argv[1]);
+ if( fgets(b, sizeof(b)-1,u)==0 ){
+ fprintf(stderr, "malformed manifest.uuid file: %s\n", argv[1]);
+ exit(1);
+ }
+ fclose(u);
+ for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
+ *z = 0;
+ printf("#define MANIFEST_UUID \"%s\"\n",b);
+ printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b);
+ n = strlen(b);
+ if( n + 50 < sizeof(b) ){
+#ifdef FOSSIL_BUILD_EPOCH
+#define str(s) #s
+ snprintf(b+n, sizeof(b)-n,
+ "%d", (int)strtoll(str(FOSSIL_BUILD_EPOCH), 0, 10));
+#else
+ const char *zEpoch = getenv("SOURCE_DATE_EPOCH");
+ if( zEpoch && isdigit(zEpoch[0]) ){
+ snprintf(b+n, sizeof(b)-n, "%d", (int)strtoll(zEpoch, 0, 10));
+ }else{
+ snprintf(b+n, sizeof(b)-n, "%d", (int)time(0));
+ }
+#endif
+ hash(b,33,vx);
+ printf("#define FOSSIL_BUILD_HASH \"%s\"\n", vx);
+ }
+ m = open_for_reading(argv[2]);
+ while(b == fgets(b, sizeof(b)-1,m)){
+ if(0 == strncmp("D ",b,2)){
+ int k, n;
+ char zDateNum[30];
+ printf("#define MANIFEST_DATE \"%.10s %.8s\"\n",b+2,b+13);
+ printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2);
+ n = 0;
+ for(k=0; k<10; k++){
+ if( isdigit(b[k+2]) ) zDateNum[n++] = b[k+2];
+ }
+ zDateNum[n] = 0;
+ printf("#define MANIFEST_NUMERIC_DATE %s\n", zDateNum);
+ n = 0;
+ for(k=0; k<8; k++){
+ if( isdigit(b[k+13]) ) zDateNum[n++] = b[k+13];
+ }
+ zDateNum[n] = 0;
+ for(k=0; zDateNum[k]=='0'; k++){}
+ printf("#define MANIFEST_NUMERIC_TIME %s\n", zDateNum+k);
+ }
+ }
+ fclose(m);
+ v = open_for_reading(argv[3]);
+ if( fgets(b, sizeof(b)-1,v)==0 ){
+ fprintf(stderr, "malformed VERSION file: %s\n", argv[3]);
+ exit(1);
+ }
+ fclose(v);
+ for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
+ *z = 0;
+ printf("#define RELEASE_VERSION \"%s\"\n", b);
+ z=b;
+ vn[0] = vn[1] = vn[2] = 0;
+ while(1){
+ if( z[0]>='0' && z[0]<='9' ){
+ x = x*10 + z[0] - '0';
+ }else{
+ if( j<3 ) vn[j++] = x;
+ x = 0;
+ if( z[0]==0 ) break;
+ }
+ z++;
+ }
+ for(z=vx; z[0]=='0'; z++){}
+ printf("#define RELEASE_VERSION_NUMBER %d%02d%02d\n", vn[0], vn[1], vn[2]);
+ memset(vx,0,sizeof(vx));
+ local_strcpy(vx,b);
+ for(z=vx; z[0]; z++){
+ if( z[0]=='-' ){
+ z[0] = 0;
+ break;
+ }
+ if( z[0]!='.' ) continue;
+ if ( d<3 ){
+ z[0] = ',';
+ d++;
+ }else{
+ z[0] = '\0';
+ break;
+ }
+ }
+ printf("#define RELEASE_RESOURCE_VERSION %s", vx);
+ while( d<3 ){ printf(",0"); d++; }
+ printf("\n");
+#if defined(__DMC__) /* e.g. 0x857 */
+ d = (__DMC__ & 0xF00) >> 8; /* major */
+ x = (__DMC__ & 0x0F0) >> 4; /* minor */
+ i = (__DMC__ & 0x00F); /* revision */
+ printf("#define COMPILER_VERSION \"%d.%d.%d\"\n", d, x, i);
+#elif defined(__POCC__) /* e.g. 700 */
+ d = (__POCC__ / 100); /* major */
+ x = (__POCC__ % 100); /* minor */
+ printf("#define COMPILER_VERSION \"%d.%02d\"\n", d, x);
+#elif defined(_MSC_VER) /* e.g. 1800 */
+ /* _MSC_FULL_VER also defined, e.g. 193030709 */
+ d = (_MSC_VER / 100); /* major */
+ x = (_MSC_VER % 100); /* minor */
+ printf("#define COMPILER_VERSION \"%d.%02d.", d, x);
+ printf("%05d\"\n",(int)(_MSC_FULL_VER % 100000)); /* build (patch) */
+#endif
+ return 0;
+}