don't check when its clang masquerading as gcc
[AROS.git] / tools / ilbmtoicon / infoinfo.c
blob606a58b577a83170cef01f9a8d2e61fc520f0c09
1 /*
2 * Copyright (C) 2011, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
7 * This program dumps out a textual description of an icon,
8 * suitable for use with ilbmtoicon.
10 * We are intentionally using only the C library here, as this
11 * program should be able to be run on both Unix and AmigaOS
12 * systems.
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <fcntl.h>
22 #ifdef _WIN32
23 #include <winsock2.h>
24 #else
25 #include <arpa/inet.h>
26 #endif
28 #define HAS_DRAWERDATA (1 << 0)
29 #define HAS_GADGETRENDER (1 << 1)
30 #define HAS_SELECTRENDER (1 << 2)
31 #define HAS_USERDATA (1 << 3)
32 #define HAS_DEFAULTTOOL (1 << 4)
33 #define HAS_TOOLTYPES (1 << 5)
35 const char *file_in, *file_iff;
37 void w8(int fd, uint8_t val)
39 int err;
41 err = write(fd, &val, 1);
42 if (err != 1) {
43 perror(file_iff);
44 exit(EXIT_FAILURE);
48 void w32(int fd, uint32_t val)
50 int err;
52 val = htonl(val);
53 err = write(fd, &val, 4);
54 if (err != 4) {
55 perror(file_iff);
56 exit(EXIT_FAILURE);
60 uint32_t r32(int fd)
62 uint32_t val = 0;
63 if (read(fd, &val, 4) != 4) {
64 perror(file_in);
65 exit(EXIT_FAILURE);
68 return ntohl(val);
71 uint16_t r16(int fd)
73 uint16_t val = 0;
74 if (read(fd, &val, 2) != 2) {
75 perror(file_in);
76 exit(EXIT_FAILURE);
79 return ntohs(val);
82 uint8_t r8(int fd)
84 uint8_t val = 0;
85 if (read(fd, &val, 1) != 1) {
86 perror(file_in);
87 exit(EXIT_FAILURE);
90 return val;
93 #define DUMP8(name, fmt, cast) do { t8 = r8(fd); printf("%s = " fmt "\n", name, (cast)t8); } while (0);
94 #define DUMP16(name, fmt, cast) do { t16 = r16(fd); printf("%s = " fmt "\n", name, (cast)t16); } while (0);
95 #define DUMP32(name, fmt, cast) do { t32 = r32(fd); printf("%s = " fmt "\n", name, (cast)t32); } while (0);
97 #define COMMENT_X8(name) DUMP8("; " name, "0x%x", unsigned int)
98 #define COMMENT_U8(name) DUMP8("; " name, "%u", unsigned int)
99 #define COMMENT_X16(name) DUMP16("; " name, "0x%x", unsigned int)
100 #define COMMENT_I16(name) DUMP16("; " name, "%d", short)
101 #define COMMENT_U16(name) DUMP16("; " name, "%u", unsigned int)
102 #define COMMENT_X32(name) DUMP32("; " name, "0x%x", unsigned int)
104 #define FIELD_I16(name) DUMP16(name, "%d", short)
105 #define FIELD_I32(name) DUMP32(name, "%d", int)
106 #define FIELD_U16(name) DUMP16(name, "%u", unsigned int)
107 #define FIELD_U32(name) DUMP32(name, "%u", unsigned int)
109 uint32_t dump_diskobject(int fd)
111 uint32_t flags = 0;
112 uint32_t t32;
113 uint16_t t16;
114 uint8_t t8;
115 const char *tstr;
117 COMMENT_X16("MAGIC");
118 COMMENT_X16("VERSION");
119 COMMENT_X32("NEXTGADGET");
120 FIELD_I16("ICONLEFTPOS");
121 FIELD_I16("ICONTOPPOS");
122 COMMENT_U16("ICONWIDTH");
123 COMMENT_U16("ICONHEIGHT");
124 COMMENT_X16("ICONFLAGS");
125 COMMENT_X16("ICONACTIVATION");
126 COMMENT_U16("ICONGADGETTYPE");
127 COMMENT_X32("ICONGADGETRENDER");
128 if (t32) flags |= HAS_GADGETRENDER;
129 COMMENT_X32("ICONSELECTRENDER");
130 if (t32) flags |= HAS_SELECTRENDER;
131 COMMENT_X32("ICONGADGETTEXT");
132 COMMENT_X32("ICONMUTUALEXCLUDE");
133 COMMENT_X32("ICONSPECIALINFO");
134 COMMENT_X16("ICONGADGETID");
135 COMMENT_X32("ICONUSERDATA");
136 if (t32) flags |= HAS_USERDATA;
137 t8 = r8(fd);
138 tstr = NULL;
139 switch (t8) {
140 case 1: tstr = "DISK"; break;
141 case 2: tstr = "DRAWER"; break;
142 case 3: tstr = "TOOL"; break;
143 case 4: tstr = "PROJECT"; break;
144 case 5: tstr = "GARBAGE"; break;
145 case 6: tstr = "DEVICE"; break;
146 case 7: tstr = "KICK"; break;
147 case 8: tstr = "APPICON"; break;
148 default: break;
150 if (tstr)
151 printf("TYPE = %s\n", tstr);
152 else
153 printf("; TYPE = %u\n", (unsigned int)t8);
154 COMMENT_X8("ICONPADDING");
155 COMMENT_X32("ICONDEFAULTTOOL");
156 if (t32) flags |= HAS_DEFAULTTOOL;
157 COMMENT_X32("ICONTOOLTYPES");
158 if (t32) flags |= HAS_TOOLTYPES;
159 COMMENT_X32("ICONCURRENTX");
160 COMMENT_X32("ICONCURRENTY");
161 COMMENT_X32("ICONDRAWERDATA");
162 if (t32) flags |= HAS_DRAWERDATA;
163 COMMENT_X32("ICONTOOLWINDOW");
164 FIELD_U32("STACK");
166 return flags;
169 void dump_drawerdata(int fd)
171 uint32_t t32;
172 uint16_t t16;
173 uint32_t t8;
175 FIELD_I16("DRAWERLEFTPOS");
176 FIELD_I16("DRAWERTOPPOS");
177 FIELD_I16("DRAWERWIDTH");
178 FIELD_I16("DRAWERHEIGHT");
179 COMMENT_U8("DRAWERDETAILPEN");
180 COMMENT_U8("DRAWERBLOCKPEN");
181 COMMENT_X32("DRAWERIDCMP");
182 COMMENT_X32("DRAWERFLAGS");
183 COMMENT_X32("DRAWERFIRSTGADGET");
184 COMMENT_X32("DRAWERCHECKMARK");
185 COMMENT_X32("DRAWERTITLE");
186 COMMENT_X32("DRAWERSCREEN");
187 COMMENT_X32("DRAWERBITMAP");
188 COMMENT_U16("DRAWERMINWIDTH");
189 COMMENT_U16("DRAWERMINHEIGHT");
190 COMMENT_U16("DRAWERMAXWIDTH");
191 COMMENT_U16("DRAWERMAXHEIGHT");
192 COMMENT_U16("DRAWERTYPE");
193 FIELD_I32("DRAWERVIEWLEFT");
194 FIELD_I32("DRAWERVIEWTOP");
197 void dump_bitmap(int fd, int id)
199 uint16_t t16;
200 uint32_t t32;
201 uint8_t t8;
202 unsigned int depth, rows, bytesperrow;
203 unsigned int plane, x, y;
205 printf("; BitMap (%sRender)\n", id ? "Select" : "Gadget");
206 COMMENT_I16("LeftEdge");
207 COMMENT_I16("TopEdge");
208 COMMENT_U16("Width");
209 bytesperrow = ((((unsigned int)t16) + 15) & ~15) / 8;
210 COMMENT_U16("Height");
211 rows = (unsigned int)t16;
212 COMMENT_U16("Depth");
213 depth = (unsigned int)t16;
214 COMMENT_X32("ImageData");
215 COMMENT_X8("PlanePick");
216 COMMENT_X8("PlaneOnOff");
217 COMMENT_X32("NextImage");
219 for (plane = 0; plane < depth; plane++) {
220 printf("; Plane[%d] = { \n", plane);
221 for (y = 0; y < rows; y++) {
222 printf("; /* %-3d */", y);
223 for (x = 0; x < bytesperrow; x++) {
224 t8 = r8(fd);
225 printf(" 0x%2x,", (unsigned int)t8);
227 printf("\n");
232 void dump_string(int fd, const char *name)
234 uint32_t len;
236 printf("%s = \"", name);
237 for (len = r32(fd); len > 0; len--) {
238 uint8_t t8 = r8(fd);
239 printf("%c", t8);
241 printf("\"\n");
244 void dump_strings(int fd, const char *name)
246 uint32_t strings;
248 for (strings = (r32(fd)-4)/4; strings > 0; strings--) {
249 dump_string(fd, name);
253 void dump_newdrawerdata(int fd)
255 uint32_t t32;
256 uint16_t t16;
257 const char *tstr;
259 t32 = r32(fd);
260 tstr = NULL;
261 switch (t32) {
262 case 0: tstr = "DEFAULT"; break;
263 case 1: tstr = "ICONS"; break;
264 case 2: tstr = "ALL"; break;
265 default: break;
267 if (tstr == NULL)
268 printf("; DRAWERSHOW = 0x%x\n", (unsigned int)t32);
269 else
270 printf("DRAWERSHOW = %s\n", tstr);
272 t16 = r16(fd);
273 tstr = NULL;
274 switch (t16) {
275 case 0: tstr = "DEFAULT"; break;
276 case 1: tstr = "ICON"; break;
277 case 2: tstr = "TEXT_NAME"; break;
278 case 3: tstr = "TEXT_DATE"; break;
279 case 4: tstr = "TEXT_SIZE"; break;
280 case 5: tstr = "TEXT_TYPE"; break;
281 default: break;
283 if (tstr == NULL)
284 printf("; DRAWERSHOWAS = %u\n", (unsigned int)t16);
285 else
286 printf("DRAWERSHOWAS = %s\n", tstr);
289 #define MAKE_ID(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
290 #define IFF_FORM MAKE_ID('F', 'O', 'R', 'M')
291 #define IFF_CAT MAKE_ID('C', 'A', 'T', ' ')
292 #define IFF_LIST MAKE_ID('L', 'I', 'S', 'T')
294 static const char *type2str(uint32_t type)
296 static char str[5] = {};
298 str[0] = (type >> 24) & 0xff;
299 str[1] = (type >> 16) & 0xff;
300 str[2] = (type >> 8) & 0xff;
301 str[3] = (type >> 0) & 0xff;
303 return str;
306 uint32_t iff_copy_chunk(int fd, int ofd, int depth)
308 uint32_t type;
309 uint32_t len, total;
310 int err;
312 type = r32(fd);
313 len = total = r32(fd);
315 printf("; %*sBegin %s (%d)\n", depth, "", type2str(type), (int)len);
316 w32(ofd, type);
317 w32(ofd, len);
318 if (type == IFF_FORM) {
319 uint32_t subtype;
320 subtype = r32(fd);
321 len -= 4;
322 printf("; %*s FORM type %s\n", depth, "", type2str(subtype));
323 while (len > 0)
324 len -= iff_copy_chunk(fd, ofd, depth+1);
325 } else if (type == IFF_CAT) {
326 while (len > 0)
327 len -= iff_copy_chunk(fd, ofd, depth+1);
328 } else {
329 /* Just copy the bytes */
330 while (len > 0) {
331 uint8_t buff[256];
332 err = read(fd, buff, (len >= sizeof(buff)) ? sizeof(buff) : len);
333 if (err == 0) {
334 printf("ERROR: Still had %d bytes to read!\n", (int)len);
335 exit(EXIT_FAILURE);
337 if (err < 0) {
338 perror(file_in);
339 exit(EXIT_FAILURE);
341 if (write(ofd, buff, err) != err) {
342 perror(file_iff);
343 exit(EXIT_FAILURE);
345 len -= err;
348 if (total & 1) {
349 w8(ofd,r8(fd));
350 total++;
352 printf("; %*sEnd %s\n", depth, "", type2str(type));
354 return total + 8;
357 void dump_iff(int fd, const char *file_iff)
359 int ofd;
360 #if (0)
361 int len;
362 uint8_t buff[256];
363 #endif
365 ofd = open(file_iff, O_WRONLY | O_CREAT | O_TRUNC, 0666);
366 if (ofd < 0) {
367 perror(file_iff);
368 exit(EXIT_FAILURE);
371 /* Read a single IFF tag, which may contain nested data */
372 iff_copy_chunk(fd, ofd, 0);
374 close(ofd);
377 int main(int argc, char **argv)
379 int fd;
380 uint32_t flags;
382 if (argc != 2 && argc != 3) {
383 printf("Usage:\n%s file.info [file.iff] >file.info.src\n", argv[0]);
386 if (argc == 3)
387 file_iff = argv[2];
389 file_in = argv[1];
390 fd = open(file_in, O_RDONLY);
391 if (fd < 0) {
392 perror(file_in);
393 return EXIT_FAILURE;
396 flags = dump_diskobject(fd);
397 if (flags & HAS_DRAWERDATA) {
398 dump_drawerdata(fd);
400 if (flags & HAS_GADGETRENDER) {
401 dump_bitmap(fd, 0);
403 if (flags & HAS_SELECTRENDER) {
404 dump_bitmap(fd, 1);
406 if (flags & HAS_DEFAULTTOOL) {
407 dump_string(fd, "DEFAULTTOOL");
409 if (flags & HAS_TOOLTYPES) {
410 dump_strings(fd, "TOOLTYPE");
412 if ((flags & HAS_DRAWERDATA) && (flags & HAS_USERDATA)) {
413 dump_newdrawerdata(fd);
415 if (flags & HAS_USERDATA) {
416 if (file_iff == NULL) {
417 printf("; NewIcon v3.5 IFF data was in the file\n");
418 } else {
419 printf("; NewIcon v3.5 IFF data dumped to %s\n", file_iff);
420 dump_iff(fd, file_iff);
424 close(fd);
426 return 0;