1 | /* |
---|
2 | o---------------------------------------------------------------------o |
---|
3 | | |
---|
4 | | Numdiff |
---|
5 | | |
---|
6 | | Copyright (c) 2012+ laurent.deniau@cern.ch |
---|
7 | | Gnu General Public License |
---|
8 | | |
---|
9 | o---------------------------------------------------------------------o |
---|
10 | |
---|
11 | Purpose: |
---|
12 | provides utilities |
---|
13 | |
---|
14 | o---------------------------------------------------------------------o |
---|
15 | */ |
---|
16 | |
---|
17 | #include <stdio.h> |
---|
18 | #include <stdlib.h> |
---|
19 | #include <string.h> |
---|
20 | #include <assert.h> |
---|
21 | #include <time.h> |
---|
22 | |
---|
23 | #include "error.h" |
---|
24 | #include "utils.h" |
---|
25 | #include "args.h" |
---|
26 | |
---|
27 | static const double pow10_tbl[2*99+1] = { |
---|
28 | 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, |
---|
29 | 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80, |
---|
30 | 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, |
---|
31 | 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, |
---|
32 | 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, |
---|
33 | 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, |
---|
34 | 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, |
---|
35 | 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, |
---|
36 | 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, |
---|
37 | 1e-09, 1e-08, 1e-07, 1e-06, 1e-05, 1e-04, 1e-03, 1e-02, 1e-01, |
---|
38 | |
---|
39 | 1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06, 1e+07, 1e+08, 1e+09, |
---|
40 | 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, |
---|
41 | 1e+20, 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, |
---|
42 | 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, |
---|
43 | 1e+40, 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, |
---|
44 | 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, |
---|
45 | 1e+60, 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, |
---|
46 | 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, |
---|
47 | 1e+80, 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, |
---|
48 | 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, |
---|
49 | }; |
---|
50 | |
---|
51 | const double *const pow10_table99 = &pow10_tbl[99]; |
---|
52 | |
---|
53 | FILE* |
---|
54 | open_indexedFile(const char* str, int idx, const char *ext, int optext, int required) |
---|
55 | { |
---|
56 | char buf[FILENAME_MAX+100]; |
---|
57 | |
---|
58 | assert(str && ext); |
---|
59 | |
---|
60 | // copy filename |
---|
61 | strncpy(buf, str, sizeof buf); |
---|
62 | |
---|
63 | // find extension, if any |
---|
64 | const char *dot = strrchr(buf, '.'); |
---|
65 | int pos = (int)strlen(buf); |
---|
66 | |
---|
67 | // remove extension if it matches ext |
---|
68 | if (dot && !strcmp(dot, ext)) { |
---|
69 | pos = dot-buf; |
---|
70 | buf[pos] = 0; |
---|
71 | } |
---|
72 | |
---|
73 | // add formatted index |
---|
74 | if (idx > 0) pos += sprintf(buf+pos, option.fmt, idx); |
---|
75 | |
---|
76 | // copy filename into option for further reporting |
---|
77 | strncpy(option.indexed_filename, buf, sizeof option.indexed_filename); |
---|
78 | |
---|
79 | // add extension |
---|
80 | strncat(buf+pos, ext, sizeof buf - pos); |
---|
81 | |
---|
82 | // try to open |
---|
83 | FILE *fp = fopen(buf, "r"); |
---|
84 | |
---|
85 | // try again upon failure if extension is optional |
---|
86 | if (!fp && optext) { |
---|
87 | buf[pos] = 0; |
---|
88 | fp = fopen(buf, "r"); |
---|
89 | } |
---|
90 | |
---|
91 | if (!fp && required) ensure(fp, "failed to open %s", buf); |
---|
92 | |
---|
93 | // resize buffer for faster read |
---|
94 | if (fp && BUFSIZ < 65536 && setvbuf(fp, 0, _IOFBF, 65536)) { |
---|
95 | fclose(fp); |
---|
96 | error("unable to resize the stream buffer size"); |
---|
97 | } |
---|
98 | |
---|
99 | // debug information |
---|
100 | if (fp) { |
---|
101 | if (optext) inform("processing %s", option.indexed_filename); |
---|
102 | debug("file %s open for reading", buf); |
---|
103 | } else |
---|
104 | trace("<-open_indexedFile: unable to open file %s for reading", buf); |
---|
105 | |
---|
106 | return fp; |
---|
107 | } |
---|
108 | |
---|
109 | void |
---|
110 | accum_summary(int total, int failed, long lines, long numbers) |
---|
111 | { |
---|
112 | if (!option.acc) return; |
---|
113 | |
---|
114 | int n; |
---|
115 | // double tz; |
---|
116 | struct tm tm; |
---|
117 | time_t now = time(0); |
---|
118 | int total_tests=0, total_passed=0, total_failed=0; |
---|
119 | long total_lines=0, total_numbers=0; |
---|
120 | double total_ndtime=0; |
---|
121 | |
---|
122 | FILE *fp = fopen(option.acc, "r+"); |
---|
123 | if (fp) { |
---|
124 | // read time stamps |
---|
125 | n = fscanf(fp, " = tests summary (started at %d.%d.%d %d:%d:%d)\n", |
---|
126 | &tm.tm_year, &tm.tm_mon, &tm.tm_mday, |
---|
127 | &tm.tm_hour, &tm.tm_min, &tm.tm_sec); |
---|
128 | ensure(n == 6, "invalid summary file format %s", option.acc); |
---|
129 | tm.tm_year -= 1900; |
---|
130 | tm.tm_mon -= 1; |
---|
131 | |
---|
132 | // correct for TZ shift (i.e. emulate non-standard timegm) |
---|
133 | struct tm tm2 = tm; |
---|
134 | option.dat_t0 = mktime(&tm2); |
---|
135 | // tm2 = *gmtime(&now); |
---|
136 | // tz = difftime(now, mktime(&tm2)); |
---|
137 | |
---|
138 | // read diff time, line and number counts |
---|
139 | n = fscanf(fp, " total diff time %lf s - total lines %ld - total numbers %ld\n", |
---|
140 | &total_ndtime, &total_lines, &total_numbers); |
---|
141 | ensure(n == 3, "invalid summary file format %s (lines)", option.acc); |
---|
142 | // read tests counts |
---|
143 | n = fscanf(fp, " total run time %*f s - total files %d - PASSED %d - FAILED %d\n", |
---|
144 | &total_tests, &total_passed, &total_failed); |
---|
145 | ensure(n == 3, "invalid summary file format %s (files)", option.acc); |
---|
146 | ensure(total_tests == total_passed+total_failed, "invalid summary count in file %s", option.acc); |
---|
147 | |
---|
148 | // reset file |
---|
149 | rewind(fp); |
---|
150 | } |
---|
151 | else { |
---|
152 | // create the file |
---|
153 | fp = fopen(option.acc, "w+"); |
---|
154 | ensure(fp, "failed to create or read summary file %s", option.acc); |
---|
155 | |
---|
156 | // init the time stamp |
---|
157 | tm = *localtime(&option.dat_t0); |
---|
158 | // tz = 0; |
---|
159 | } |
---|
160 | |
---|
161 | double total_time = difftime(now, option.dat_t0); // + tz; |
---|
162 | total_ndtime += (option.clk_t1 - option.clk_t0) / CLOCKS_PER_SEC; |
---|
163 | total_lines += lines; |
---|
164 | total_numbers += numbers; |
---|
165 | |
---|
166 | fprintf(fp, " = tests summary (started at %04d.%02d.%02d %02d:%02d:%02d)\n", |
---|
167 | tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); |
---|
168 | |
---|
169 | fprintf(fp, " total diff time %6.2lf s - total lines %6ld - total numbers %8ld\n", |
---|
170 | total_ndtime, total_lines, total_numbers); |
---|
171 | |
---|
172 | fprintf(fp, " total run time %6.0f s - total files %6d - PASSED %4d - FAILED %4d\n", |
---|
173 | total_time, total_tests+total, total_passed+(total-failed), total_failed+failed); |
---|
174 | |
---|
175 | fclose(fp); |
---|
176 | } |
---|
177 | |
---|
178 | |
---|