1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Datafile archiving utility for the Allegro library.
12 *
13 * By Shawn Hargreaves.
14 *
15 * Nathan Smith added the recursive handling of directories.
16 *
17 * See readme.txt for copyright information.
18 */
19
20
21 #define ALLEGRO_USE_CONSOLE
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include "allegro.h"
28 #include "datedit.h"
29
30 #if ((defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS)) && (!defined SCAN_DEPEND)
31 #define DAT_HAVE_CONIO_H
32 #include <conio.h>
33 #endif
34
35
36
37 static int err = 0;
38 static int changed = 0;
39
40 static int opt_command = 0;
41 static int opt_compression = -1;
42 static int opt_strip = -1;
43 static int opt_sort = -1;
44 static int opt_relf = FALSE;
45 static int opt_verbose = FALSE;
46 static int opt_keepnames = FALSE;
47 static int opt_colordepth = -1;
48 static int opt_gridx = -1;
49 static int opt_gridy = -1;
50 static int opt_gridw = -1;
51 static int opt_gridh = -1;
52 static char *opt_datafilename = NULL;
53 static char *opt_outputname = NULL;
54 static char *opt_headername = NULL;
55 static char *opt_dependencyfile = NULL;
56 static char *opt_objecttype = NULL;
57 static char *opt_prefixstring = NULL;
58 static char *opt_password = NULL;
59 static char *opt_palette = NULL;
60
61 static int attrib_ok = FA_ARCH|FA_RDONLY;
62
63 static char canonical_datafilename[1024];
64
65 static char **opt_proplist = NULL;
66 static int opt_numprops = 0;
67
68 static char **opt_fixedproplist = NULL;
69 static int opt_numfixedprops = 0;
70
71 static char **opt_namelist = NULL;
72 static int opt_numnames = 0;
73
74 static int *opt_usedname = NULL;
75
76
77
allocate(int n)78 static void allocate(int n)
79 {
80 static int max = 0;
81 if (n <= max)
82 return;
83 opt_proplist = realloc(opt_proplist, n * sizeof *opt_proplist);
84 opt_fixedproplist = realloc(opt_fixedproplist, n * sizeof *opt_fixedproplist);
85 opt_namelist = realloc(opt_namelist, n * sizeof *opt_namelist);
86 opt_usedname = realloc(opt_usedname, n * sizeof *opt_usedname);
87 max = n;
88 }
89
90
91
92 /* display help on the command syntax */
usage(void)93 static void usage(void)
94 {
95 printf("\nDatafile archiving utility for Allegro " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR "\n");
96 printf("By Shawn Hargreaves, " ALLEGRO_DATE_STR "\n\n");
97 printf("Usage: dat [options] filename.dat [names]\n\n");
98 printf("Options:\n");
99 printf("\t'-a' adds the named files to the datafile\n");
100 printf("\t'-bpp colordepth' grabs bitmaps in the specified format\n");
101 printf("\t'-c0' no compression\n");
102 printf("\t'-c1' compress objects individually\n");
103 printf("\t'-c2' global compression on the entire datafile\n");
104 printf("\t'-d' deletes the named objects from the datafile\n");
105 printf("\t'-dither' dithers when reducing color depths\n");
106 printf("\t'-e' extracts the named objects from the datafile\n");
107 printf("\t'-f' store references to original files as relative filenames\n");
108 printf("\t'-g x y w h' grabs bitmap data from a specific grid location\n");
109 printf("\t'-h outputfile.h' sets the output header file\n");
110 printf("\t'-k' keeps the original filenames when grabbing objects\n");
111 printf("\t'-l' lists the contents of the datafile\n");
112 printf("\t'-m dependencyfile' outputs makefile dependencies\n");
113 printf("\t'-n0' no sort: list the objects in the order they were added\n");
114 printf("\t'-n1' sort the objects of the datafile alphabetically by name\n");
115 printf("\t'-o output' sets the output file or directory when extracting data\n");
116 printf("\t'-p prefixstring' sets the prefix for the output header file\n");
117 printf("\t'-pal objectname' specifies which palette to use\n");
118 printf("\t'-r' recursively adds directories as nested datafiles\n");
119 printf("\t'-s0' no strip: save everything\n");
120 printf("\t'-s1' strip grabber specific information from the file\n");
121 printf("\t'-s2' strip all object properties and names from the file\n");
122 printf("\t'-s-PROP' do not strip object property PROP from the file\n");
123 printf("\t'-t type' sets the object type when adding files\n");
124 printf("\t'-transparency' preserves transparency through color conversion\n");
125 printf("\t'-u' updates the contents of the datafile\n");
126 printf("\t'-v' selects verbose mode\n");
127 printf("\t'-w' always updates the entire contents of the datafile\n");
128 printf("\t'-x' alias for -e\n");
129 printf("\t'-007 password' sets the file encryption key\n");
130 printf("\t'PROP=value' sets object properties\n");
131 }
132
133
134
135 /* callback for outputting messages */
datedit_msg(AL_CONST char * fmt,...)136 void datedit_msg(AL_CONST char *fmt, ...)
137 {
138 va_list args;
139 char buf[1024];
140
141 va_start(args, fmt);
142 vsprintf(buf, fmt, args);
143 va_end(args);
144
145 printf("%s\n", buf);
146 }
147
148
149
150 /* callback for starting a 2-part message output */
datedit_startmsg(AL_CONST char * fmt,...)151 void datedit_startmsg(AL_CONST char *fmt, ...)
152 {
153 va_list args;
154 char buf[1024];
155
156 va_start(args, fmt);
157 vsprintf(buf, fmt, args);
158 va_end(args);
159
160 printf("%s", buf);
161 fflush(stdout);
162 }
163
164
165
166 /* callback for ending a 2-part message output */
datedit_endmsg(AL_CONST char * fmt,...)167 void datedit_endmsg(AL_CONST char *fmt, ...)
168 {
169 va_list args;
170 char buf[1024];
171
172 va_start(args, fmt);
173 vsprintf(buf, fmt, args);
174 va_end(args);
175
176 printf("%s\n", buf);
177 }
178
179
180
181 /* callback for printing errors */
datedit_error(AL_CONST char * fmt,...)182 void datedit_error(AL_CONST char *fmt, ...)
183 {
184 va_list args;
185 char buf[1024];
186
187 va_start(args, fmt);
188 vsprintf(buf, fmt, args);
189 va_end(args);
190
191 fprintf(stderr, "%s\n", buf);
192
193 err = 1;
194 }
195
196
197
198 /* callback for asking questions */
datedit_ask(AL_CONST char * fmt,...)199 int datedit_ask(AL_CONST char *fmt, ...)
200 {
201 va_list args;
202 char buf[1024];
203 int c;
204
205 static int all = FALSE;
206
207 if (all)
208 return 'y';
209
210 va_start(args, fmt);
211 vsprintf(buf, fmt, args);
212 va_end(args);
213
214 printf("%s? (y/n/a/q) ", buf);
215 fflush(stdout);
216
217 for (;;) {
218 #ifdef DAT_HAVE_CONIO_H
219
220 /* raw keyboard input for platforms that have conio functions */
221 c = getch();
222 if ((c == 0) || (c == 0xE0))
223 getch();
224
225 #else
226
227 /* stdio version for other systems */
228 fflush(stdin);
229 c = getchar();
230
231 #endif
232
233 switch (c) {
234
235 case 'y':
236 case 'Y':
237 #ifdef DAT_HAVE_CONIO_H
238 printf("%c\n", c);
239 #endif
240 return 'y';
241
242 case 'n':
243 case 'N':
244 #ifdef DAT_HAVE_CONIO_H
245 printf("%c\n", c);
246 #endif
247 return 'n';
248
249 case 'a':
250 case 'A':
251 #ifdef DAT_HAVE_CONIO_H
252 printf("%c\n", c);
253 #endif
254 all = TRUE;
255 return 'y';
256
257 case 'q':
258 case 'Q':
259 #ifdef DAT_HAVE_CONIO_H
260 printf("%c\n", c);
261 #endif
262 return 27;
263
264 case 27:
265 #ifdef DAT_HAVE_CONIO_H
266 printf("\n");
267 #endif
268 return 27;
269 }
270 }
271 }
272
273
274
275 /* callback for the datedit functions to show a list of options */
276 /* Returns -1 if canceled */
datedit_select(AL_CONST char * (* list_getter)(int index,int * list_size),AL_CONST char * fmt,...)277 int datedit_select(AL_CONST char *(*list_getter)(int index, int *list_size), AL_CONST char *fmt, ...)
278 {
279 va_list args;
280 char buf[1024];
281 int c, num;
282
283 va_start(args, fmt);
284 vsprintf(buf, fmt, args);
285 va_end(args);
286
287 /* If there is only one choice, select it automatically. If the list is */
288 /* empty, return immediately. */
289 list_getter(-1, &num);
290 if (num<=1) return num-1;
291
292 printf("%s:\n", buf);
293 for (c=0; c<num; c++) {
294 printf("% 2d %s\n", c, list_getter(c, NULL));
295 }
296 printf("% 2d %s\n", -1, "Cancel");
297 fflush(stdout);
298 fscanf(stdin, "%d", &c);
299 if (c>num)
300 c = num-1;
301 return c;
302 }
303
304
305
306 /* checks if a string is one of the names specified on the command line */
is_name(AL_CONST char * name)307 static int is_name(AL_CONST char *name)
308 {
309 char str1[256], str2[256];
310 int i, e;
311
312 for (i=0; i<opt_numnames; i++) {
313 if ((stricmp(name, opt_namelist[i]) == 0) ||
314 (strcmp(opt_namelist[i], "*") == 0)) {
315 opt_usedname[i] = TRUE;
316 return TRUE;
317 }
318 else {
319 for (e=0; e<(int)strlen(opt_namelist[i]); e++) {
320 if (opt_namelist[i][e] == '*') {
321 strncpy(str1, opt_namelist[i], e);
322 str1[e] = 0;
323 strncpy(str2, name, e);
324 str2[e] = 0;
325 if (strcmp(str1, str2) == 0) {
326 opt_usedname[i] = TRUE;
327 return TRUE;
328 }
329 }
330 }
331 }
332 }
333
334 return FALSE;
335 }
336
337
338
339 /* does a view operation */
do_view(AL_CONST DATAFILE * dat,AL_CONST char * parentname)340 static void do_view(AL_CONST DATAFILE *dat, AL_CONST char *parentname)
341 {
342 int i, j;
343 AL_CONST char *name;
344 DATAFILE_PROPERTY *prop;
345 char tmp[256];
346
347 for (i=0; dat[i].type != DAT_END; i++) {
348 name = get_datafile_property(dat+i, DAT_NAME);
349 strcpy(tmp, parentname);
350 strcat(tmp, name);
351
352 if ((opt_numnames <= 0) || (is_name(tmp))) {
353 if (opt_verbose)
354 printf("\n");
355
356 printf("- %c%c%c%c - %s%-*s - %s\n",
357 (dat[i].type>>24)&0xFF, (dat[i].type>>16)&0xFF,
358 (dat[i].type>>8)&0xFF, dat[i].type&0xFF,
359 parentname, 28-(int)strlen(parentname), name,
360 datedit_desc(dat+i));
361
362 if (opt_verbose) {
363 prop = dat[i].prop;
364 if (prop) {
365 for (j=0; prop[j].type != DAT_END; j++) {
366 printf(" . %c%c%c%c '%s'\n",
367 (prop[j].type>>24)&0xFF, (prop[j].type>>16)&0xFF,
368 (prop[j].type>>8)&0xFF, prop[j].type&0xFF,
369 prop[j].dat);
370 }
371 }
372 }
373 }
374
375 if (dat[i].type == DAT_FILE) {
376 strcat(tmp, "/");
377 do_view((DATAFILE *)dat[i].dat, tmp);
378 }
379 }
380 }
381
382
383
384 /* does an export operation */
do_export(DATAFILE * dat,char * parentname)385 static void do_export(DATAFILE *dat, char *parentname)
386 {
387 int i;
388 AL_CONST char *name;
389 char tmp[256];
390
391 for (i=0; dat[i].type != DAT_END; i++) {
392 name = get_datafile_property(dat+i, DAT_NAME);
393 strcpy(tmp, parentname);
394 strcat(tmp, name);
395
396 if (is_name(tmp)) {
397 if (!datedit_export(dat+i, opt_outputname)) {
398 err = 1;
399 return;
400 }
401 }
402 else {
403 if (dat[i].type == DAT_FILE) {
404 strcat(tmp, "/");
405 do_export((DATAFILE *)dat[i].dat, tmp);
406 if (err)
407 return;
408 }
409 }
410 }
411 }
412
413
414
415 /* deletes objects from the datafile */
do_delete(DATAFILE ** dat,char * parentname)416 static void do_delete(DATAFILE **dat, char *parentname)
417 {
418 int i;
419 AL_CONST char *name;
420 char tmp[256];
421
422 for (i=0; (*dat)[i].type != DAT_END; i++) {
423 name = get_datafile_property((*dat)+i, DAT_NAME);
424 strcpy(tmp, parentname);
425 strcat(tmp, name);
426
427 if (is_name(tmp)) {
428 printf("Deleting %s\n", tmp);
429 *dat = datedit_delete(*dat, i);
430 changed = TRUE;
431 i--;
432 }
433 else {
434 if ((*dat)[i].type == DAT_FILE) {
435 DATAFILE *dattmp = (*dat)[i].dat;
436 strcat(tmp, "/");
437 do_delete(&dattmp, tmp);
438 (*dat)[i].dat = dattmp;
439 }
440 }
441 }
442 }
443
444
445
446 /* open a sub-datafile in the parent datafile */
open_sub_datafile(DATAFILE * parent,AL_CONST char * name)447 static DATAFILE *open_sub_datafile(DATAFILE *parent, AL_CONST char *name)
448 {
449 DATAFILE *dat;
450 int c;
451
452 /* Return the datafile if it already exists. */
453 for (c=0; parent[c].type != DAT_END; c++) {
454 if ((parent[c].type == DAT_FILE) && (stricmp(name, get_datafile_property(parent+c, DAT_NAME)) == 0))
455 return parent[c].dat;
456 }
457
458 /* Otherwise create a new datafile. */
459 printf("Creating sub-datafile %s\n", name);
460
461 dat = malloc(sizeof(DATAFILE));
462 dat->dat = NULL;
463 dat->type = DAT_END;
464 dat->size = 0;
465 dat->prop = NULL;
466
467 return dat;
468 }
469
470
471
472 /* close a sub-datafile from the parent datafile */
close_sub_datafile(DATAFILE * parent,AL_CONST char * name,DATAFILE * dat)473 static DATAFILE *close_sub_datafile(DATAFILE *parent, AL_CONST char *name, DATAFILE *dat)
474 {
475 int c;
476
477 /* Adjust the datafile if it already exists. */
478 for (c=0; parent[c].type != DAT_END; c++) {
479 if ((parent[c].type == DAT_FILE) && (stricmp(name, get_datafile_property(parent+c, DAT_NAME)) == 0)) {
480 parent[c].dat = dat;
481 return parent;
482 }
483 }
484
485 /* Otherwise insert the datafile. */
486 return datedit_insert(parent, NULL, name, DAT_FILE, dat, 0);
487 }
488
489
490
491 /* adds a file to the archive */
do_add_file(AL_CONST char * filename,int attrib,void * param)492 static int do_add_file(AL_CONST char *filename, int attrib, void *param)
493 {
494 DATEDIT_GRAB_PARAMETERS params;
495 DATAFILE **dat = param;
496 DATAFILE *d;
497 char fname[256];
498 char name[256];
499 int c;
500
501 canonicalize_filename(fname, filename, sizeof(fname));
502
503 strcpy(name, get_filename(fname));
504
505 if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
506 return 0;
507
508 if (!opt_keepnames) {
509 strupr(name);
510
511 for (c=0; name[c]; c++)
512 if (name[c] == '.')
513 name[c] = '_';
514 }
515
516 if (attrib & FA_DIREC) {
517 DATAFILE *sub_dat = open_sub_datafile(*dat, name);
518
519 if (!sub_dat) {
520 fprintf(stderr, "Error: failed to create sub-datafile %s\n", name);
521 err = 1;
522 return -1;
523 }
524
525 append_filename(fname, fname, "*", sizeof(fname));
526
527 if (for_each_file_ex(fname, 0, ~attrib_ok, do_add_file, &sub_dat) <= 0) {
528 fprintf(stderr, "Error: failed to add objects to %s\n", name);
529 err = 1;
530 return -1;
531 }
532
533 *dat = close_sub_datafile(*dat, name, sub_dat);
534 changed = TRUE;
535 return 0;
536 }
537
538 params.datafile = canonical_datafilename;
539 params.filename = fname;
540 params.name = name;
541 params.type = datedit_clean_typename(opt_objecttype);
542 params.x = opt_gridx;
543 params.y = opt_gridy;
544 params.w = opt_gridw;
545 params.h = opt_gridh;
546 params.colordepth = opt_colordepth;
547 params.relative = opt_relf;
548
549 for (c=0; (*dat)[c].type != DAT_END; c++) {
550 if (stricmp(name, get_datafile_property(*dat+c, DAT_NAME)) == 0) {
551 printf("Replacing %s -> %s\n", fname, name);
552 if (!datedit_grabreplace(*dat+c, ¶ms)) {
553 err = 1;
554 return -1;
555 }
556 else {
557 changed = TRUE;
558 return 0;
559 }
560 }
561 }
562
563 printf("Inserting %s -> %s\n", fname, name);
564 d = datedit_grabnew(*dat, ¶ms);
565 if (!d) {
566 err = 1;
567 return -1;
568 }
569 else {
570 *dat = d;
571 changed = TRUE;
572 return 0;
573 }
574 }
575
576
577
578 /* does an update operation */
do_update(DATAFILE * dat,int force,char * parentname)579 static void do_update(DATAFILE *dat, int force, char *parentname)
580 {
581 int i;
582 AL_CONST char *name;
583 char tmp[256];
584
585 for (i=0; dat[i].type != DAT_END; i++) {
586 name = get_datafile_property(dat+i, DAT_NAME);
587 strcpy(tmp, parentname);
588 strcat(tmp, name);
589
590 if (dat[i].type == DAT_FILE) {
591 strcat(tmp, "/");
592 do_update((DATAFILE *)dat[i].dat, force, tmp);
593 if (err)
594 return;
595 }
596 else if ((opt_numnames <= 0) || (is_name(tmp))) {
597 if (!datedit_update(dat+i, canonical_datafilename, force, opt_verbose, &changed)) {
598 err = 1;
599 return;
600 }
601 }
602 }
603 }
604
605
606
607 /* changes object properties */
do_set_props(DATAFILE * dat,char * parentname)608 static void do_set_props(DATAFILE *dat, char *parentname)
609 {
610 int i, j;
611 AL_CONST char *name;
612 char tmp[256];
613 char propname[256], *propvalue;
614 int type;
615
616 for (i=0; dat[i].type != DAT_END; i++) {
617 name = get_datafile_property(dat+i, DAT_NAME);
618 strcpy(tmp, parentname);
619 strcat(tmp, name);
620
621 if (is_name(tmp)) {
622 for (j=0; j<opt_numprops; j++) {
623 strcpy(propname, opt_proplist[j]);
624 propvalue = strchr(propname, '=');
625 if (propvalue) {
626 *propvalue = 0;
627 propvalue++;
628 }
629 else
630 propvalue = "";
631
632 type = datedit_clean_typename(propname);
633
634 if (opt_verbose) {
635 if (*propvalue) {
636 printf("%s: setting property %c%c%c%c = '%s'\n",
637 tmp, type>>24, (type>>16)&0xFF,
638 (type>>8)&0xFF, type&0xFF, propvalue);
639 }
640 else {
641 printf("%s: clearing property %c%c%c%c\n",
642 tmp, type>>24, (type>>16)&0xFF,
643 (type>>8)&0xFF, type&0xFF);
644 }
645 }
646
647 datedit_set_property(dat+i, type, propvalue);
648 changed = TRUE;
649 }
650 }
651
652 if (dat[i].type == DAT_FILE) {
653 strcat(tmp, "/");
654 do_set_props((DATAFILE *)dat[i].dat, tmp);
655 }
656 }
657 }
658
659
660
661 /* selects a specific palette */
do_setpal(DATAFILE ** dat,char * parentname)662 static void do_setpal(DATAFILE **dat, char *parentname)
663 {
664 int i;
665 AL_CONST char *name;
666 char tmp[256];
667
668 for (i=0; (*dat)[i].type != DAT_END; i++) {
669 name = get_datafile_property((*dat)+i, DAT_NAME);
670 strcpy(tmp, parentname);
671 strcat(tmp, name);
672
673 if (stricmp(tmp, opt_palette) == 0) {
674 if ((*dat)[i].type != DAT_PALETTE) {
675 printf("Error: %s is not a palette object\n", tmp);
676 err = 1;
677 return;
678 }
679 printf("Using palette %s\n", tmp);
680 memcpy(datedit_current_palette, (*dat)[i].dat, sizeof(PALETTE));
681 select_palette(datedit_current_palette);
682 return;
683 }
684 else {
685 if ((*dat)[i].type == DAT_FILE) {
686 DATAFILE *dattmp = (*dat)[i].dat;
687 strcat(tmp, "/");
688 do_setpal(&dattmp, tmp);
689 (*dat)[i].dat = dattmp;
690 }
691 }
692 }
693
694 printf("Error: %s not found\n", opt_palette);
695 err = 1;
696 }
697
698
699
700 /* recursive helper for writing out datafile dependencies */
save_dependencies(DATAFILE * dat,FILE * f,int * depth)701 static void save_dependencies(DATAFILE *dat, FILE *f, int *depth)
702 {
703 AL_CONST char *orig;
704 int c, i;
705 int hasspace;
706
707 for (c=0; dat[c].type != DAT_END; c++) {
708 orig = get_datafile_property(dat+c, DAT_ORIG);
709
710 if ((orig) && (orig[0])) {
711 if (*depth + strlen(orig) > 56) {
712 fprintf(f, " \\\n\t\t");
713 *depth = 0;
714 }
715 else {
716 fprintf(f, " ");
717 (*depth)++;
718 }
719
720 if (strchr(orig, ' ')) {
721 hasspace = TRUE;
722 fputc('"', f);
723 (*depth) += 2;
724 }
725 else
726 hasspace = FALSE;
727
728 for (i=0; orig[i]; i++) {
729 if (orig[i] == '\\')
730 fputc('/', f);
731 else
732 fputc(orig[i], f);
733 (*depth)++;
734 }
735
736 if (hasspace)
737 fputc('"', f);
738 }
739
740 if (dat[c].type == DAT_FILE)
741 save_dependencies((DATAFILE *)dat[c].dat, f, depth);
742 }
743 }
744
745
746
747 /* writes out a makefile dependency rule */
do_save_dependencies(DATAFILE * dat,char * srcname,char * depname)748 static int do_save_dependencies(DATAFILE *dat, char *srcname, char *depname)
749 {
750 char *pretty_name;
751 char tm[80];
752 time_t now;
753 FILE *f;
754 int c;
755
756 pretty_name = datedit_pretty_name(srcname, "dat", FALSE);
757 datedit_msg("Writing makefile dependencies into %s", depname);
758
759 f = fopen(depname, "w");
760 if (f) {
761 time(&now);
762 strcpy(tm, asctime(localtime(&now)));
763 for (c=0; tm[c]; c++)
764 if ((tm[c] == '\r') || (tm[c] == '\n'))
765 tm[c] = 0;
766
767 fprintf(f, "# Allegro datafile make dependencies, produced by dat v" ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR "\n");
768 fprintf(f, "# Datafile: %s\n", pretty_name);
769 fprintf(f, "# Date: %s\n", tm);
770 fprintf(f, "# Do not hand edit!\n\n");
771
772 if (opt_headername)
773 fprintf(f, "%s %s :", pretty_name, opt_headername);
774 else
775 fprintf(f, "%s :", pretty_name);
776
777 c = 0xFF;
778 save_dependencies(dat, f, &c);
779
780 fprintf(f, " \\\n\n\tdat -u %s", pretty_name);
781
782 if (opt_headername)
783 fprintf(f, " -h %s", opt_headername);
784
785 if (opt_password)
786 fprintf(f, " -007 %s", opt_password);
787
788 fprintf(f, "\n");
789 fclose(f);
790 }
791 else {
792 datedit_error("Error writing %s", depname);
793 return FALSE;
794 }
795
796 return TRUE;
797 }
798
799
800
main(int argc,char * argv[])801 int main(int argc, char *argv[])
802 {
803 int c, colorconv_mode = 0;
804 int *opt_fixed_prop = NULL;
805 DATAFILE *datafile = NULL;
806
807 if (install_allegro(SYSTEM_NONE, &errno, atexit) != 0)
808 return 1;
809 datedit_init();
810
811 for (c=0; c<PAL_SIZE; c++)
812 datedit_current_palette[c] = desktop_palette[c];
813
814 for (c=1; c<argc; c++) {
815 if (argv[c][0] == '-') {
816
817 switch (utolower(argv[c][1])) {
818
819 case 'd':
820 if (stricmp(argv[c]+2, "ither") == 0) {
821 colorconv_mode |= COLORCONV_DITHER;
822 break;
823 }
824 /* fall through */
825
826 case 'a':
827 case 'e':
828 case 'l':
829 case 'u':
830 case 'w':
831 case 'x':
832 if (opt_command) {
833 usage();
834 return 1;
835 }
836 opt_command = utolower(argv[c][1]);
837 break;
838
839 case 'b':
840 if ((opt_colordepth > 0) || (c >= argc-1)) {
841 usage();
842 return 1;
843 }
844 opt_colordepth = atoi(argv[++c]);
845 if ((opt_colordepth != 8) && (opt_colordepth != 15) &&
846 (opt_colordepth != 16) && (opt_colordepth != 24) &&
847 (opt_colordepth != 32)) {
848 usage();
849 return 1;
850 }
851 break;
852
853 case 'c':
854 if ((opt_compression >= 0) ||
855 (argv[c][2] < '0') || (argv[c][2] > '2')) {
856 usage();
857 return 1;
858 }
859 opt_compression = argv[c][2] - '0';
860 break;
861
862 case 'f':
863 opt_relf = TRUE;
864 break;
865
866 case 'g':
867 if ((opt_gridx > 0) || (c >= argc-4)) {
868 usage();
869 return 1;
870 }
871 opt_gridx = atoi(argv[++c]);
872 opt_gridy = atoi(argv[++c]);
873 opt_gridw = atoi(argv[++c]);
874 opt_gridh = atoi(argv[++c]);
875 if ((opt_gridx < 0) || (opt_gridy < 0) ||
876 (opt_gridw <= 0) || (opt_gridh <= 0)) {
877 usage();
878 return 1;
879 }
880 break;
881
882 case 'h':
883 if ((opt_headername) || (c >= argc-1)) {
884 usage();
885 return 1;
886 }
887 opt_headername = argv[++c];
888 break;
889
890 case 'k':
891 opt_keepnames = TRUE;
892 break;
893
894 case 'm':
895 if ((opt_dependencyfile) || (c >= argc-1)) {
896 usage();
897 return 1;
898 }
899 opt_dependencyfile = argv[++c];
900 break;
901
902 case 'n':
903 if ((opt_sort >= 0) ||
904 (argv[c][2] < '0') || (argv[c][2] > '1')) {
905 usage();
906 return 1;
907 }
908 opt_sort = argv[c][2] - '0';
909 break;
910
911 case 'o':
912 if ((opt_outputname) || (c >= argc-1)) {
913 usage();
914 return 1;
915 }
916 opt_outputname = argv[++c];
917 break;
918
919 case 'p':
920 if ((utolower(argv[c][2]) == 'a') &&
921 (utolower(argv[c][3]) == 'l') &&
922 (argv[c][4] == 0)) {
923 if ((opt_palette) || (c >= argc-1)) {
924 usage();
925 return 1;
926 }
927 opt_palette = argv[++c];
928 }
929 else {
930 if ((opt_prefixstring) || (c >= argc-1)) {
931 usage();
932 return 1;
933 }
934 opt_prefixstring = argv[++c];
935 }
936 break;
937
938 case 'r':
939 attrib_ok |= FA_DIREC;
940 break;
941
942 case 's':
943 if (argv[c][2] == '-') {
944 allocate(opt_numfixedprops + 1);
945 opt_fixedproplist[opt_numfixedprops++] = argv[c]+3;
946 }
947 else {
948 if ((opt_strip >= 0) ||
949 (argv[c][2] < '0') || (argv[c][2] > '2')) {
950 usage();
951 return 1;
952 }
953 opt_strip = argv[c][2] - '0';
954 }
955 break;
956
957 case 't':
958 if (stricmp(argv[c]+2, "ransparency") == 0) {
959 colorconv_mode |= COLORCONV_KEEP_TRANS;
960 break;
961 }
962
963 if ((opt_objecttype) || (c >= argc-1)) {
964 usage();
965 return 1;
966 }
967 opt_objecttype = argv[++c];
968 break;
969
970 case 'v':
971 opt_verbose = TRUE;
972 break;
973
974 case '0':
975 if ((opt_password) || (c >= argc-1)) {
976 usage();
977 return 1;
978 }
979 opt_password = argv[++c];
980 break;
981
982 case '-':
983 if (stricmp(argv[c]+2, "help") == 0) {
984 usage();
985 return 1;
986 }
987 break;
988
989 case '?':
990 usage();
991 return 1;
992
993 default:
994 printf("Unknown option '%s'\n", argv[c]);
995 return 1;
996 }
997 }
998 else {
999 if (strchr(argv[c], '=')) {
1000 allocate(opt_numprops + 1);
1001 opt_proplist[opt_numprops++] = argv[c];
1002 }
1003 else {
1004 if (!opt_datafilename)
1005 opt_datafilename = argv[c];
1006 else {
1007 allocate(opt_numnames + 1);
1008 opt_namelist[opt_numnames] = argv[c];
1009 opt_usedname[opt_numnames] = FALSE;
1010 opt_numnames++;
1011 }
1012 }
1013 }
1014 }
1015
1016 if ((!opt_datafilename) ||
1017 ((!opt_command) &&
1018 (opt_compression < 0) &&
1019 (opt_strip < 0) &&
1020 (opt_sort < 0) &&
1021 (!opt_numprops) &&
1022 (!opt_headername) &&
1023 (!opt_dependencyfile))) {
1024 usage();
1025 return 1;
1026 }
1027
1028 canonicalize_filename(canonical_datafilename, opt_datafilename, sizeof(canonical_datafilename));
1029
1030 if (colorconv_mode)
1031 set_color_conversion(colorconv_mode);
1032 else
1033 set_color_conversion(COLORCONV_NONE);
1034
1035 datafile = datedit_load_datafile(opt_datafilename, FALSE, opt_password);
1036
1037 if (datafile) {
1038
1039 if (opt_palette)
1040 do_setpal(&datafile, "");
1041
1042 if (!err) {
1043 switch (opt_command) {
1044
1045 case 'a':
1046 if (!opt_numnames) {
1047 printf("No files specified for addition\n");
1048 err = 1;
1049 }
1050 else {
1051 for (c=0; c<opt_numnames; c++) {
1052 if (for_each_file_ex(opt_namelist[c], 0, ~attrib_ok, do_add_file, &datafile) <= 0) {
1053 fprintf(stderr, "Error: %s not found\n", opt_namelist[c]);
1054 err = 1;
1055 break;
1056 }
1057 else
1058 opt_usedname[c] = TRUE;
1059 }
1060 }
1061 break;
1062
1063 case 'd':
1064 if (!opt_numnames) {
1065 printf("No objects specified for deletion\n");
1066 err = 1;
1067 }
1068 else
1069 do_delete(&datafile, "");
1070 break;
1071
1072 case 'e':
1073 case 'x':
1074 if (!opt_numnames) {
1075 printf("No objects specified: use '*' to extract everything\n");
1076 err = 1;
1077 }
1078 else
1079 do_export(datafile, "");
1080 break;
1081
1082 case 'l':
1083 do_view(datafile, "");
1084 break;
1085
1086 case 'u':
1087 do_update(datafile, FALSE, "");
1088 break;
1089
1090 case 'w':
1091 do_update(datafile, TRUE, "");
1092 break;
1093 }
1094 }
1095
1096 if (!err) {
1097 if (opt_command) {
1098 for (c=0; c<opt_numnames; c++) {
1099 if (!opt_usedname[c]) {
1100 fprintf(stderr, "Error: %s not found\n", opt_namelist[c]);
1101 err = 1;
1102 }
1103 }
1104 }
1105
1106 if (opt_numprops > 0) {
1107 if (!opt_numnames) {
1108 printf("No objects specified for setting properties\n");
1109 err = 1;
1110 }
1111 else {
1112 for (c=0; c<opt_numnames; c++)
1113 opt_usedname[c] = FALSE;
1114
1115 do_set_props(datafile, "");
1116
1117 for (c=0; c<opt_numnames; c++) {
1118 if (!opt_usedname[c]) {
1119 fprintf(stderr, "Error: %s not found\n", opt_namelist[c]);
1120 err = 1;
1121 }
1122 }
1123 }
1124 }
1125
1126 if (opt_numfixedprops > 0) {
1127 if (opt_strip < 0) {
1128 printf("Error: no strip mode\n");
1129 err = 1;
1130 }
1131 else {
1132 opt_fixed_prop = malloc((opt_numfixedprops+1)*sizeof(int));
1133
1134 for (c=0; c<opt_numfixedprops; c++)
1135 opt_fixed_prop[c] = datedit_clean_typename(opt_fixedproplist[c]);
1136
1137 opt_fixed_prop[c] = 0; /* end of array delimiter */
1138 }
1139 }
1140 }
1141
1142 if ((!err) && ((changed) || (opt_compression >= 0) || (opt_strip >= 0) || (opt_sort >= 0))) {
1143 DATEDIT_SAVE_DATAFILE_OPTIONS options;
1144
1145 options.pack = opt_compression;
1146 options.strip = opt_strip;
1147 options.sort = opt_sort;
1148 options.verbose = opt_verbose;
1149 options.write_msg = TRUE;
1150 options.backup = FALSE;
1151
1152 if (!datedit_save_datafile(datafile, opt_datafilename, opt_fixed_prop, &options, opt_password))
1153 err = 1;
1154 }
1155
1156 if ((!err) && (opt_headername))
1157 if (!datedit_save_header(datafile, opt_datafilename, opt_headername, "dat", opt_prefixstring, opt_verbose))
1158 err = 1;
1159
1160 if ((!err) && (opt_dependencyfile))
1161 if (!do_save_dependencies(datafile, opt_datafilename, opt_dependencyfile))
1162 err = 1;
1163
1164 if (opt_fixed_prop)
1165 free(opt_fixed_prop);
1166
1167 unload_datafile(datafile);
1168 }
1169
1170 return err;
1171 }
1172
1173 END_OF_MAIN()
1174