blob: c010f4c6bfa260c998e51fec50c081d719da3ba6 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001#include "common.h"
2
3#define LINE_LEN 79
4#define STATUS_LEN 22
5#define PROGBAR_MAX (LINE_LEN - STATUS_LEN - 1)
6
7static char status_msg[128];
8static int progbar_scale = 0;
9static int progbar_len = 0;
10static int progbar_pos = -1;
11
12int quietmode = 0;
13int errorlog = 0;
14
15static png_uint_32 counter;
16static png_uint_32 maxcount;
17static int barlen;
18
19#define isoption(p) (IsOptChar((p)[0]) && (p)[1]!='\0')
20
21static void print_status(void)
22{
23 fprintf(stderr, "\r%-*.*s ", STATUS_LEN, STATUS_LEN, status_msg);
24 fflush(stderr);
25 progbar_pos = 0;
26}
27
28static void put_dots(int dotchar, int num)
29{
30 int i;
31
32 if (num > PROGBAR_MAX) num = PROGBAR_MAX;
33 if (progbar_pos == -1) print_status();
34
35 for (i = progbar_pos; i < num; i++)
36 fputc(dotchar, stderr);
37
38 if (progbar_pos < num) {
39 progbar_pos = num;
40 fflush(stderr);
41 }
42}
43
44static void print_scale(void)
45{
46 if (progbar_pos != 0) print_status();
47 put_dots('.', progbar_len);
48 print_status();
49 progbar_scale = 1;
50}
51
52static void init_progress_bar(int max)
53{
54 if (quietmode) return;
55
56 progbar_len = max;
57 print_scale();
58}
59
60static void update_progress_bar(int num)
61{
62 if (quietmode) return;
63
64 if (!progbar_scale) print_scale();
65 put_dots('o', num);
66}
67
68static void clear_line(void)
69{
70 if (quietmode) return;
71
72 fprintf(stderr, "\r%*c\r", LINE_LEN, ' ');
73 progbar_scale = 0;
74 progbar_pos = -1;
75}
76
77void xxprintf(const char *fmt, ...)
78{
79 va_list ap;
80 FILE *f;
81
82 va_start(ap, fmt);
83
84 clear_line();
85 vfprintf(stderr, fmt, ap);
86 fflush(stderr);
87
88 if (errorlog && (f = fopen(errlogfile, "a")) != NULL) {
89 vfprintf(f, fmt, ap);
90 fclose(f);
91 }
92
93 va_end(ap);
94}
95
96void set_status(const char *fmt, ...)
97{
98 va_list ap;
99
100 if (quietmode) return;
101
102 va_start(ap, fmt);
103 vsprintf(status_msg, fmt, ap);
104 va_end(ap);
105
106 print_status();
107}
108
109void feed_line(void)
110{
111 if (quietmode) return;
112
113 fputc('\n', stderr);
114 fflush(stderr);
115 progbar_scale = 0;
116 progbar_pos = -1;
117}
118
119static png_uint_32 maxcount_adam7(png_uint_32 width, png_uint_32 height)
120{
121 png_uint_32 c = 0;
122
123 if ( 1 ) c += ((height - 0 + 7) / 8) * 1;
124 if (width > 4) c += ((height - 0 + 7) / 8) * 1;
125 if ( 1 ) c += ((height - 4 + 7) / 8) * 2;
126 if (width > 2) c += ((height - 0 + 3) / 4) * 2;
127 if ( 1 ) c += ((height - 2 + 3) / 4) * 4;
128 if (width > 1) c += ((height - 0 + 1) / 2) * 4;
129 if ( 1 ) c += ((height - 1 + 1) / 2) * 8;
130
131 return c;
132}
133
134void init_progress_meter(png_structp png_ptr, png_uint_32 width,
135 png_uint_32 height)
136{
137 enum { W = 1024, H = 768 };
138
139 if (png_set_interlace_handling(png_ptr) == 7) {
140 maxcount = maxcount_adam7(width, height);
141 } else {
142 maxcount = height;
143 }
144 if (height > ((png_uint_32)W * H) / width) {
145 barlen = PROGBAR_MAX;
146 } else {
147 barlen = (PROGBAR_MAX * width * height + (W * H - 1)) / (W * H);
148 }
149 counter = 0;
150 init_progress_bar(barlen);
151}
152
153void row_callback(png_structp png_ptr, png_uint_32 row, int pass)
154{
155
156 if (row == 0) pass--;
157
158
159 counter += (1 << (pass >> 1)); /* step[pass]; */
160 update_progress_bar(barlen * counter / maxcount);
161}
162
163FILE *binary_stdio(int fd)
164{
165 FILE *fp;
166
167 if (fd != 0 && fd != 1)
168 return NULL;
169
170 printf("---------binary_stdio----else ------\n");
171 fp = (fd == 0) ? stdin : stdout;
172
173 return fp;
174}
175
176char *suffix(const char *path)
177{
178 char c, *p, *q, *r;
179
180 for (r = q = p = basname(path); (c = *p) != '\0'; p++)
181 if (c == '.') q = p;
182 if (q == r) q = p; /* dotfile with no suffix */
183
184 return q;
185}
186
187char *basname(const char *path)
188{
189 const char *p, *q;
190
191 for (p = path_skiproot(path);
192 *(q = path_nextslash(p)) != '\0'; p = q + 1) ;
193
194 return (char *)p;
195}
196
197char *addslash(char *path)
198{
199 char *p, *q;
200
201 for (p = path_skiproot(path);
202 *(q = path_nextslash(p)) != '\0'; p = q + 1) ;
203
204 if (q != p) {
205 *q++ = PATHDELIM;
206 *q = '\0';
207 }
208
209 return path;
210}
211
212
213char *path_skiproot(const char *path)
214{
215 if (IsPathDelim(path[0])) path++;
216 return (char *)path;
217}
218
219char *path_nextslash(const char *path)
220{
221 char c;
222
223 for (; (c = *path) != '\0'; path++) {
224 if (IsDBCSLead((unsigned char)c)) {
225 if (*(++path) == '\0') break;
226 continue;
227 }
228 if (IsPathDelim(c)) break;
229 }
230 return (char *)path;
231}
232
233char *delslash(char *path)
234{
235 char *p, *q, *s;
236
237 for (p = s = path_skiproot(path);
238 *(q = path_nextslash(p)) != '\0'; p = q + 1) ;
239
240 if (q == s) {
241 *q++ = '.';
242 *q = '\0';
243 } else if (q == p) {
244 *--q = '\0';
245 }
246
247 return path;
248}
249
250
251void png_my_error(png_structp png_ptr, png_const_charp message)
252{
253 xxprintf("ERROR(libpng): %s - %s\n", message,
254 (char *)png_get_error_ptr(png_ptr));
255 longjmp(png_jmpbuf(png_ptr), 1);
256}
257
258void png_my_warning(png_structp png_ptr, png_const_charp message)
259{
260 xxprintf("WARNING(libpng): %s - %s\n", message,
261 (char *)png_get_error_ptr(png_ptr));
262}
263
264BOOL imgbuf_alloc(IMAGE *img)
265{
266 BYTE *bp, **rp;
267 LONG n;
268
269 if (img->palnum > 0) {
270 img->palette = malloc((size_t)img->palnum * sizeof(PALETTE));
271 if (img->palette == NULL) { imgbuf_init(img); return FALSE; }
272 } else {
273 img->palette = NULL;
274 }
275 img->rowbytes = ((DWORD)img->width * img->pixdepth + 31) / 32 * 4;
276 img->imgbytes = img->rowbytes * img->height;
277 img->rowptr = malloc((size_t)img->height * sizeof(BYTE *));
278 img->bmpbits = malloc((size_t)img->imgbytes);
279
280 if (img->rowptr == NULL || img->bmpbits == NULL) {
281 imgbuf_free(img); imgbuf_init(img); return FALSE;
282 }
283
284 n = img->height;
285 rp = img->rowptr;
286 bp = img->bmpbits;
287
288 if (img->topdown) {
289 while (--n >= 0) {
290 *(rp++) = bp;
291 bp += img->rowbytes;
292
293 }
294 } else { /* bottom-up */
295 bp += img->imgbytes;
296 while (--n >= 0) {
297
298 ((DWORD *)bp)[-1] = 0;
299 bp -= img->rowbytes;
300 *(rp++) = bp;
301 }
302 }
303
304 return TRUE;
305}
306
307void imgbuf_free(IMAGE *img)
308{
309 free(img->palette);
310 free(img->rowptr);
311 free(img->bmpbits);
312}
313
314void imgbuf_init(IMAGE *img)
315{
316 img->palette = NULL;
317 img->rowptr = NULL;
318 img->bmpbits = NULL;
319}
320
321int parsearg(int *opt, char **arg, int argc, char **argv, char *aopts)
322{
323 static int agi = 1;
324 static char *agp = NULL;
325 char *p;
326 int c, i;
327
328 if (agp != NULL && *agp == '\0') {
329 agp = NULL;
330 agi++;
331 }
332 if (agi >= argc)
333 return 0;
334
335 if (p = argv[agi], agp == NULL && !isoption(p)) {
336
337 c = 0;
338 agi++;
339 } else {
340 if (agp == NULL) agp = p + 1;
341 if (c = (*agp & 0xFF), strchr(aopts, c) != NULL) {
342
343 if (p = agp + 1, *p != '\0') {
344 /*NULL*/;
345 } else if (i = agi + 1, p = argv[i], i < argc && !isoption(p)) {
346 agi = i;
347 } else {
348 p = NULL;
349 }
350 agp = NULL;
351 agi++;
352 } else {
353
354 p = NULL;
355 agp++;
356 }
357 }
358 *opt = c;
359 *arg = p;
360
361 return 1;
362}
363
364char **envargv(int *argcp, char ***argvp, const char *envn)
365{
366 int argc, nagc, envc, i;
367 char **argv, **nagv, *envs, *ep;
368
369 ep = getenv(envn);
370 if (ep == NULL || ep[0] == '\0') return NULL;
371
372 envs = malloc(strlen(ep) + 1);
373 if (envs == NULL) return NULL;
374 strcpy(envs, ep);
375
376 envc = tokenize(envs, envs);
377 if (envc == 0) { free(envs); return NULL; }
378
379 argc = *argcp;
380 argv = *argvp;
381 nagv = malloc((argc + envc + 1) * sizeof(char *));
382 if (nagv == NULL) { free(envs); return NULL; }
383
384 nagc = 1;
385 nagv[0] = argv[0];
386
387 for (i = 0; i < envc; i++) {
388 nagv[nagc++] = envs;
389 while (*(envs++) != '\0') ;
390 }
391 for (i = 1; i < argc; i++) {
392 nagv[nagc++] = argv[i];
393 }
394 nagv[nagc] = NULL;
395
396 *argcp = nagc;
397 *argvp = nagv;
398
399 return argv;
400}
401
402int tokenize(char *buf, const char *str)
403{
404 enum { STR = 0x01, QUOTE = 0x02 };
405 int flag = 0;
406 int num = 0;
407 char c;
408 int i;
409
410 while ((c = *str++) != '\0') {
411 if (!(flag & QUOTE) &&
412 (c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
413 if (flag & STR) {
414 flag &= ~STR;
415 *buf++ = '\0';
416 }
417 } else {
418 if (!(flag & STR)) {
419 flag |= STR;
420 num++;
421 }
422 switch (c) {
423 case '\\':
424
425 for (i = 1; (c = *str) == '\\'; str++, i++) ;
426 if (c == '"') {
427 while ((i -= 2) >= 0)
428 *buf++ = '\\';
429 if (i == -1) {
430 *buf++ = '"';
431 str++;
432 }
433 } else {
434 while ((--i) >= 0)
435 *buf++ = '\\';
436 }
437 break;
438
439 case '"':
440 flag ^= QUOTE;
441 break;
442
443 default:
444 *buf++ = c;
445 }
446 }
447 }
448 if (flag & STR) *buf = '\0';
449
450 return num;
451}
452
453int makedir(const char *path)
454{
455 char dir[FILENAME_MAX];
456 struct stat sbuf;
457 char *p, c;
458 int r;
459
460 delslash(strcpy(dir, path));
461 if (stat(dir, &sbuf) == 0) {
462 if ((sbuf.st_mode & S_IFMT) == S_IFDIR) return 0;
463
464 return -1;
465 }
466 p = path_skiproot(dir);
467 do {
468 p = path_nextslash(p);
469 c = *p; *p = '\0';
470 r = MKDIR(dir, 0777);
471 *p++ = c;
472 } while (c != '\0');
473
474 return r;
475}
476
477int renbak(const char *path)
478{
479 char bak[FILENAME_MAX];
480 struct stat sbuf;
481 char *sfx;
482 int i;
483
484 strcpy(bak, path);
485 if (stat(bak, &sbuf) != 0) return 0;
486
487 sfx = bak + strlen(bak);
488
489 strcpy(sfx, ".bak");
490 i = 0;
491 while (1) {
492 if (stat(bak, &sbuf) != 0 && rename(path, bak) == 0) return 0;
493 if (i >= 1000) break;
494 sprintf(sfx, ".%03d", i++);
495 }
496 return -1;
497}
498
499int cpyftime(const char *srcf, const char *dstf)
500{
501 struct stat sbuf;
502 struct utimbuf ubuf;
503
504 if (stat(srcf, &sbuf) != 0) return -1;
505
506 ubuf.actime = sbuf.st_atime;
507 ubuf.modtime = sbuf.st_mtime;
508
509 return utime(dstf, &ubuf);
510}
511
512