xref: /aosp_15_r20/external/giflib/gifbuild.c (revision 324bb76b8d05e2a05aa88511fff61cf3f9ca5892)
1*324bb76bSAndroid Build Coastguard Worker /*****************************************************************************
2*324bb76bSAndroid Build Coastguard Worker 
3*324bb76bSAndroid Build Coastguard Worker gifbuild - dump GIF data in a textual format, or undump it to a GIF
4*324bb76bSAndroid Build Coastguard Worker 
5*324bb76bSAndroid Build Coastguard Worker SPDX-License-Identifier: MIT
6*324bb76bSAndroid Build Coastguard Worker 
7*324bb76bSAndroid Build Coastguard Worker *****************************************************************************/
8*324bb76bSAndroid Build Coastguard Worker 
9*324bb76bSAndroid Build Coastguard Worker #include <ctype.h>
10*324bb76bSAndroid Build Coastguard Worker #include <stdbool.h>
11*324bb76bSAndroid Build Coastguard Worker #include <stdio.h>
12*324bb76bSAndroid Build Coastguard Worker #include <stdlib.h>
13*324bb76bSAndroid Build Coastguard Worker #include <string.h>
14*324bb76bSAndroid Build Coastguard Worker 
15*324bb76bSAndroid Build Coastguard Worker #include "getarg.h"
16*324bb76bSAndroid Build Coastguard Worker #include "gif_lib.h"
17*324bb76bSAndroid Build Coastguard Worker 
18*324bb76bSAndroid Build Coastguard Worker #define PROGRAM_NAME "gifbuild"
19*324bb76bSAndroid Build Coastguard Worker 
20*324bb76bSAndroid Build Coastguard Worker static char *VersionStr = PROGRAM_NAME VERSION_COOKIE
21*324bb76bSAndroid Build Coastguard Worker     "	Eric Raymond,	" __DATE__ ",   " __TIME__ "\n"
22*324bb76bSAndroid Build Coastguard Worker     "(C) Copyright 1992 Eric Raymond.\n";
23*324bb76bSAndroid Build Coastguard Worker static char *CtrlStr =
24*324bb76bSAndroid Build Coastguard Worker     PROGRAM_NAME " v%- d%- t%-Characters!s h%- GifFile(s)!*s";
25*324bb76bSAndroid Build Coastguard Worker 
26*324bb76bSAndroid Build Coastguard Worker static char KeyLetters[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO"
27*324bb76bSAndroid Build Coastguard Worker                            "PQRSTUVWXYZ!\"#$%&'()*+,-./:<=>?@[\\]^_`{|}~";
28*324bb76bSAndroid Build Coastguard Worker #define PRINTABLES (sizeof(KeyLetters) - 1)
29*324bb76bSAndroid Build Coastguard Worker 
30*324bb76bSAndroid Build Coastguard Worker static void Icon2Gif(char *FileName, FILE *txtin, bool, int fdout);
31*324bb76bSAndroid Build Coastguard Worker static void Gif2Icon(char *FileName, int fdin, int fdout, char NameTable[]);
32*324bb76bSAndroid Build Coastguard Worker static int EscapeString(char *cp, char *tp);
33*324bb76bSAndroid Build Coastguard Worker 
34*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
35*324bb76bSAndroid Build Coastguard Worker  Main sequence
36*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
main(int argc,char ** argv)37*324bb76bSAndroid Build Coastguard Worker int main(int argc, char **argv) {
38*324bb76bSAndroid Build Coastguard Worker 	int NumFiles;
39*324bb76bSAndroid Build Coastguard Worker 	bool Error, DisasmFlag = false, HelpFlag = false, TextLineFlag = false,
40*324bb76bSAndroid Build Coastguard Worker 	            GifNoisyPrint = false;
41*324bb76bSAndroid Build Coastguard Worker 	char **FileNames = NULL;
42*324bb76bSAndroid Build Coastguard Worker 	char *TextLines[1];
43*324bb76bSAndroid Build Coastguard Worker 
44*324bb76bSAndroid Build Coastguard Worker 	if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &DisasmFlag,
45*324bb76bSAndroid Build Coastguard Worker 	                       &TextLineFlag, &TextLines[0], &HelpFlag,
46*324bb76bSAndroid Build Coastguard Worker 	                       &NumFiles, &FileNames)) != false) {
47*324bb76bSAndroid Build Coastguard Worker 		GAPrintErrMsg(Error);
48*324bb76bSAndroid Build Coastguard Worker 		GAPrintHowTo(CtrlStr);
49*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
50*324bb76bSAndroid Build Coastguard Worker 	}
51*324bb76bSAndroid Build Coastguard Worker 
52*324bb76bSAndroid Build Coastguard Worker 	if (HelpFlag) {
53*324bb76bSAndroid Build Coastguard Worker 		(void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
54*324bb76bSAndroid Build Coastguard Worker 		GAPrintHowTo(CtrlStr);
55*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_SUCCESS);
56*324bb76bSAndroid Build Coastguard Worker 	}
57*324bb76bSAndroid Build Coastguard Worker 
58*324bb76bSAndroid Build Coastguard Worker 	if (!DisasmFlag && NumFiles > 1) {
59*324bb76bSAndroid Build Coastguard Worker 		GIF_MESSAGE(
60*324bb76bSAndroid Build Coastguard Worker 		    "Error in command line parsing - one  text input please.");
61*324bb76bSAndroid Build Coastguard Worker 		GAPrintHowTo(CtrlStr);
62*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
63*324bb76bSAndroid Build Coastguard Worker 	}
64*324bb76bSAndroid Build Coastguard Worker 
65*324bb76bSAndroid Build Coastguard Worker 	if (!DisasmFlag && TextLineFlag) {
66*324bb76bSAndroid Build Coastguard Worker 		GIF_MESSAGE(
67*324bb76bSAndroid Build Coastguard Worker 		    "Error in command line parsing - -t invalid without -d.");
68*324bb76bSAndroid Build Coastguard Worker 		GAPrintHowTo(CtrlStr);
69*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
70*324bb76bSAndroid Build Coastguard Worker 	}
71*324bb76bSAndroid Build Coastguard Worker 
72*324bb76bSAndroid Build Coastguard Worker 	if (NumFiles == 0) {
73*324bb76bSAndroid Build Coastguard Worker 		if (DisasmFlag)
74*324bb76bSAndroid Build Coastguard Worker 			Gif2Icon("Stdin", 0, 1,
75*324bb76bSAndroid Build Coastguard Worker 			         TextLineFlag ? TextLines[0] : KeyLetters);
76*324bb76bSAndroid Build Coastguard Worker 		else
77*324bb76bSAndroid Build Coastguard Worker 			Icon2Gif("Stdin", stdin, GifNoisyPrint, 1);
78*324bb76bSAndroid Build Coastguard Worker 	} else {
79*324bb76bSAndroid Build Coastguard Worker 		int i;
80*324bb76bSAndroid Build Coastguard Worker 		for (i = 0; i < NumFiles; i++) {
81*324bb76bSAndroid Build Coastguard Worker 			FILE *fp;
82*324bb76bSAndroid Build Coastguard Worker 
83*324bb76bSAndroid Build Coastguard Worker 			if ((fp = fopen(FileNames[i], "r")) == (FILE *)NULL) {
84*324bb76bSAndroid Build Coastguard Worker 				(void)fprintf(stderr, "Can't open %s\n",
85*324bb76bSAndroid Build Coastguard Worker 				              FileNames[i]);
86*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
87*324bb76bSAndroid Build Coastguard Worker 			}
88*324bb76bSAndroid Build Coastguard Worker 
89*324bb76bSAndroid Build Coastguard Worker 			if (DisasmFlag) {
90*324bb76bSAndroid Build Coastguard Worker 				printf("#\n# GIF information from %s\n",
91*324bb76bSAndroid Build Coastguard Worker 				       FileNames[i]);
92*324bb76bSAndroid Build Coastguard Worker 				Gif2Icon(FileNames[i], -1, 1,
93*324bb76bSAndroid Build Coastguard Worker 				         TextLineFlag ? TextLines[0]
94*324bb76bSAndroid Build Coastguard Worker 				                      : KeyLetters);
95*324bb76bSAndroid Build Coastguard Worker 			} else {
96*324bb76bSAndroid Build Coastguard Worker 				Icon2Gif(FileNames[i], fp, GifNoisyPrint, 1);
97*324bb76bSAndroid Build Coastguard Worker 			}
98*324bb76bSAndroid Build Coastguard Worker 
99*324bb76bSAndroid Build Coastguard Worker 			(void)fclose(fp);
100*324bb76bSAndroid Build Coastguard Worker 		}
101*324bb76bSAndroid Build Coastguard Worker 	}
102*324bb76bSAndroid Build Coastguard Worker 
103*324bb76bSAndroid Build Coastguard Worker 	return 0;
104*324bb76bSAndroid Build Coastguard Worker }
105*324bb76bSAndroid Build Coastguard Worker 
106*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
107*324bb76bSAndroid Build Coastguard Worker  Parse image directives
108*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
109*324bb76bSAndroid Build Coastguard Worker #define PARSE_ERROR(str)                                                       \
110*324bb76bSAndroid Build Coastguard Worker 	(void)fprintf(stderr, "%s:%d: %s\n", FileName, LineNum, str);
111*324bb76bSAndroid Build Coastguard Worker 
Icon2Gif(char * FileName,FILE * txtin,bool GifNoisyPrint,int fdout)112*324bb76bSAndroid Build Coastguard Worker static void Icon2Gif(char *FileName, FILE *txtin, bool GifNoisyPrint,
113*324bb76bSAndroid Build Coastguard Worker                      int fdout) {
114*324bb76bSAndroid Build Coastguard Worker 	unsigned int ColorMapSize = 0;
115*324bb76bSAndroid Build Coastguard Worker 	GifColorType GlobalColorMap[256], LocalColorMap[256],
116*324bb76bSAndroid Build Coastguard Worker 	    *ColorMap = GlobalColorMap;
117*324bb76bSAndroid Build Coastguard Worker 	char GlobalColorKeys[PRINTABLES], LocalColorKeys[PRINTABLES],
118*324bb76bSAndroid Build Coastguard Worker 	    *KeyTable = GlobalColorKeys;
119*324bb76bSAndroid Build Coastguard Worker 	bool SortFlag = false;
120*324bb76bSAndroid Build Coastguard Worker 	unsigned int ExtCode, intval;
121*324bb76bSAndroid Build Coastguard Worker 	int red, green, blue, n;
122*324bb76bSAndroid Build Coastguard Worker 	char buf[BUFSIZ * 2], InclusionFile[64];
123*324bb76bSAndroid Build Coastguard Worker 	GifFileType *GifFileOut;
124*324bb76bSAndroid Build Coastguard Worker 	SavedImage *NewImage = NULL;
125*324bb76bSAndroid Build Coastguard Worker 	int LeadingExtensionBlockCount = 0;
126*324bb76bSAndroid Build Coastguard Worker 	ExtensionBlock *LeadingExtensionBlocks = NULL;
127*324bb76bSAndroid Build Coastguard Worker 	int ErrorCode, LineNum = 0;
128*324bb76bSAndroid Build Coastguard Worker 
129*324bb76bSAndroid Build Coastguard Worker 	if ((GifFileOut = EGifOpenFileHandle(fdout, &ErrorCode)) == NULL) {
130*324bb76bSAndroid Build Coastguard Worker 		PrintGifError(ErrorCode);
131*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
132*324bb76bSAndroid Build Coastguard Worker 	}
133*324bb76bSAndroid Build Coastguard Worker 
134*324bb76bSAndroid Build Coastguard Worker 	/* OK, interpret directives */
135*324bb76bSAndroid Build Coastguard Worker 	/* coverity[tainted_data_transitive] */
136*324bb76bSAndroid Build Coastguard Worker 	while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) {
137*324bb76bSAndroid Build Coastguard Worker 		char *cp;
138*324bb76bSAndroid Build Coastguard Worker 
139*324bb76bSAndroid Build Coastguard Worker 		++LineNum;
140*324bb76bSAndroid Build Coastguard Worker 
141*324bb76bSAndroid Build Coastguard Worker 		/*
142*324bb76bSAndroid Build Coastguard Worker 		 * Skip lines consisting only of whitespace and comments
143*324bb76bSAndroid Build Coastguard Worker 		 */
144*324bb76bSAndroid Build Coastguard Worker 		for (cp = buf; isspace((int)(*cp)); cp++) {
145*324bb76bSAndroid Build Coastguard Worker 			continue;
146*324bb76bSAndroid Build Coastguard Worker 		}
147*324bb76bSAndroid Build Coastguard Worker 		if (*cp == '#' || *cp == '\0') {
148*324bb76bSAndroid Build Coastguard Worker 			continue;
149*324bb76bSAndroid Build Coastguard Worker 		}
150*324bb76bSAndroid Build Coastguard Worker 
151*324bb76bSAndroid Build Coastguard Worker 		/*
152*324bb76bSAndroid Build Coastguard Worker 		 * If there's a trailing comment, nuke it and all preceding
153*324bb76bSAndroid Build Coastguard Worker 		 * whitespace. But preserve the EOL.
154*324bb76bSAndroid Build Coastguard Worker 		 */
155*324bb76bSAndroid Build Coastguard Worker 		if ((cp = strchr(buf, '#')) && (cp == strrchr(cp, '#'))) {
156*324bb76bSAndroid Build Coastguard Worker 			while (isspace((int)(*--cp))) {
157*324bb76bSAndroid Build Coastguard Worker 				continue;
158*324bb76bSAndroid Build Coastguard Worker 			}
159*324bb76bSAndroid Build Coastguard Worker 			*++cp = '\n';
160*324bb76bSAndroid Build Coastguard Worker 			*++cp = '\0';
161*324bb76bSAndroid Build Coastguard Worker 		}
162*324bb76bSAndroid Build Coastguard Worker 
163*324bb76bSAndroid Build Coastguard Worker 		/*
164*324bb76bSAndroid Build Coastguard Worker 		 * Explicit header declarations
165*324bb76bSAndroid Build Coastguard Worker 		 */
166*324bb76bSAndroid Build Coastguard Worker 
167*324bb76bSAndroid Build Coastguard Worker 		if (sscanf(buf, "screen width %d\n", &GifFileOut->SWidth) ==
168*324bb76bSAndroid Build Coastguard Worker 		    1) {
169*324bb76bSAndroid Build Coastguard Worker 			continue;
170*324bb76bSAndroid Build Coastguard Worker 		}
171*324bb76bSAndroid Build Coastguard Worker 
172*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "screen height %d\n",
173*324bb76bSAndroid Build Coastguard Worker 		                &GifFileOut->SHeight) == 1) {
174*324bb76bSAndroid Build Coastguard Worker 			continue;
175*324bb76bSAndroid Build Coastguard Worker 		}
176*324bb76bSAndroid Build Coastguard Worker 
177*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "screen colors %d\n", &n) == 1) {
178*324bb76bSAndroid Build Coastguard Worker 			int ResBits = GifBitSize(n);
179*324bb76bSAndroid Build Coastguard Worker 
180*324bb76bSAndroid Build Coastguard Worker 			if (n > 256 || n < 0 || n != (1 << ResBits)) {
181*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Invalid color resolution value.");
182*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
183*324bb76bSAndroid Build Coastguard Worker 			}
184*324bb76bSAndroid Build Coastguard Worker 
185*324bb76bSAndroid Build Coastguard Worker 			GifFileOut->SColorResolution = ResBits;
186*324bb76bSAndroid Build Coastguard Worker 			continue;
187*324bb76bSAndroid Build Coastguard Worker 		}
188*324bb76bSAndroid Build Coastguard Worker 
189*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "screen background %d\n",
190*324bb76bSAndroid Build Coastguard Worker 		                &GifFileOut->SBackGroundColor) == 1) {
191*324bb76bSAndroid Build Coastguard Worker 			continue;
192*324bb76bSAndroid Build Coastguard Worker 		}
193*324bb76bSAndroid Build Coastguard Worker 
194*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "pixel aspect byte %u\n", &intval) == 1) {
195*324bb76bSAndroid Build Coastguard Worker 			GifFileOut->AspectByte = (GifByteType)(intval & 0xff);
196*324bb76bSAndroid Build Coastguard Worker 			continue;
197*324bb76bSAndroid Build Coastguard Worker 		}
198*324bb76bSAndroid Build Coastguard Worker 
199*324bb76bSAndroid Build Coastguard Worker 		/*
200*324bb76bSAndroid Build Coastguard Worker 		 * Color table parsing
201*324bb76bSAndroid Build Coastguard Worker 		 */
202*324bb76bSAndroid Build Coastguard Worker 
203*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "screen map\n") == 0) {
204*324bb76bSAndroid Build Coastguard Worker 			if (GifFileOut->SColorMap != NULL) {
205*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("You've already declared a global "
206*324bb76bSAndroid Build Coastguard Worker 				            "color map.");
207*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
208*324bb76bSAndroid Build Coastguard Worker 			}
209*324bb76bSAndroid Build Coastguard Worker 
210*324bb76bSAndroid Build Coastguard Worker 			ColorMapSize = 0;
211*324bb76bSAndroid Build Coastguard Worker 			ColorMap = GlobalColorMap;
212*324bb76bSAndroid Build Coastguard Worker 			SortFlag = false;
213*324bb76bSAndroid Build Coastguard Worker 			KeyTable = GlobalColorKeys;
214*324bb76bSAndroid Build Coastguard Worker 			memset(GlobalColorKeys, '\0', sizeof(GlobalColorKeys));
215*324bb76bSAndroid Build Coastguard Worker 		}
216*324bb76bSAndroid Build Coastguard Worker 
217*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "image map\n") == 0) {
218*324bb76bSAndroid Build Coastguard Worker 			if (NewImage == NULL) {
219*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("No previous image declaration.");
220*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
221*324bb76bSAndroid Build Coastguard Worker 			}
222*324bb76bSAndroid Build Coastguard Worker 
223*324bb76bSAndroid Build Coastguard Worker 			ColorMapSize = 0;
224*324bb76bSAndroid Build Coastguard Worker 			ColorMap = LocalColorMap;
225*324bb76bSAndroid Build Coastguard Worker 			KeyTable = LocalColorKeys;
226*324bb76bSAndroid Build Coastguard Worker 			memset(LocalColorKeys, '\0', sizeof(LocalColorKeys));
227*324bb76bSAndroid Build Coastguard Worker 		}
228*324bb76bSAndroid Build Coastguard Worker 
229*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "	rgb %d %d %d is %c", &red, &green,
230*324bb76bSAndroid Build Coastguard Worker 		                &blue, &KeyTable[ColorMapSize]) == 4) {
231*324bb76bSAndroid Build Coastguard Worker 			if (ColorMapSize >= 256) {
232*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Too many color entries.");
233*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
234*324bb76bSAndroid Build Coastguard Worker 			}
235*324bb76bSAndroid Build Coastguard Worker 			ColorMap[ColorMapSize].Red = red;
236*324bb76bSAndroid Build Coastguard Worker 			ColorMap[ColorMapSize].Green = green;
237*324bb76bSAndroid Build Coastguard Worker 			ColorMap[ColorMapSize].Blue = blue;
238*324bb76bSAndroid Build Coastguard Worker 			ColorMapSize++;
239*324bb76bSAndroid Build Coastguard Worker 		}
240*324bb76bSAndroid Build Coastguard Worker 
241*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "	rgb %d %d %d", &red, &green, &blue) ==
242*324bb76bSAndroid Build Coastguard Worker 		         3) {
243*324bb76bSAndroid Build Coastguard Worker 			if (ColorMapSize >= 256) {
244*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Too many color entries.");
245*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
246*324bb76bSAndroid Build Coastguard Worker 			}
247*324bb76bSAndroid Build Coastguard Worker 			ColorMap[ColorMapSize].Red = red;
248*324bb76bSAndroid Build Coastguard Worker 			ColorMap[ColorMapSize].Green = green;
249*324bb76bSAndroid Build Coastguard Worker 			ColorMap[ColorMapSize].Blue = blue;
250*324bb76bSAndroid Build Coastguard Worker 			ColorMapSize++;
251*324bb76bSAndroid Build Coastguard Worker 		}
252*324bb76bSAndroid Build Coastguard Worker 
253*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "	sort flag on\n") == 0) {
254*324bb76bSAndroid Build Coastguard Worker 			SortFlag = true;
255*324bb76bSAndroid Build Coastguard Worker 		}
256*324bb76bSAndroid Build Coastguard Worker 
257*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "	sort flag off\n") == 0) {
258*324bb76bSAndroid Build Coastguard Worker 			SortFlag = false;
259*324bb76bSAndroid Build Coastguard Worker 		}
260*324bb76bSAndroid Build Coastguard Worker 
261*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "end\n") == 0) {
262*324bb76bSAndroid Build Coastguard Worker 			ColorMapObject *NewMap;
263*324bb76bSAndroid Build Coastguard Worker 
264*324bb76bSAndroid Build Coastguard Worker 			NewMap = GifMakeMapObject(1 << GifBitSize(ColorMapSize),
265*324bb76bSAndroid Build Coastguard Worker 			                          ColorMap);
266*324bb76bSAndroid Build Coastguard Worker 			if (NewMap == (ColorMapObject *)NULL) {
267*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Out of memory while allocating "
268*324bb76bSAndroid Build Coastguard Worker 				            "new color map.");
269*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
270*324bb76bSAndroid Build Coastguard Worker 			}
271*324bb76bSAndroid Build Coastguard Worker 
272*324bb76bSAndroid Build Coastguard Worker 			NewMap->SortFlag = SortFlag;
273*324bb76bSAndroid Build Coastguard Worker 
274*324bb76bSAndroid Build Coastguard Worker 			if (NewImage) {
275*324bb76bSAndroid Build Coastguard Worker 				NewImage->ImageDesc.ColorMap = NewMap;
276*324bb76bSAndroid Build Coastguard Worker 			} else {
277*324bb76bSAndroid Build Coastguard Worker 				GifFileOut->SColorMap = NewMap;
278*324bb76bSAndroid Build Coastguard Worker 			}
279*324bb76bSAndroid Build Coastguard Worker 		}
280*324bb76bSAndroid Build Coastguard Worker 
281*324bb76bSAndroid Build Coastguard Worker 		/* GIF inclusion */
282*324bb76bSAndroid Build Coastguard Worker 		/* ugly magic number is because scanf has no */
283*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "include %63s", InclusionFile) == 1) {
284*324bb76bSAndroid Build Coastguard Worker 			bool DoTranslation;
285*324bb76bSAndroid Build Coastguard Worker 			GifPixelType Translation[256];
286*324bb76bSAndroid Build Coastguard Worker 
287*324bb76bSAndroid Build Coastguard Worker 			GifFileType *Inclusion;
288*324bb76bSAndroid Build Coastguard Worker 			SavedImage *CopyFrom;
289*324bb76bSAndroid Build Coastguard Worker 
290*324bb76bSAndroid Build Coastguard Worker 			if ((Inclusion = DGifOpenFileName(
291*324bb76bSAndroid Build Coastguard Worker 			         InclusionFile, &ErrorCode)) == NULL) {
292*324bb76bSAndroid Build Coastguard Worker 				PrintGifError(ErrorCode);
293*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
294*324bb76bSAndroid Build Coastguard Worker 			}
295*324bb76bSAndroid Build Coastguard Worker 
296*324bb76bSAndroid Build Coastguard Worker 			if (DGifSlurp(Inclusion) == GIF_ERROR) {
297*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Inclusion read failed.");
298*324bb76bSAndroid Build Coastguard Worker 				// cppcheck-suppress knownConditionTrueFalse
299*324bb76bSAndroid Build Coastguard Worker 				if (Inclusion != NULL) {
300*324bb76bSAndroid Build Coastguard Worker 					PrintGifError(Inclusion->Error);
301*324bb76bSAndroid Build Coastguard Worker 					DGifCloseFile(Inclusion, NULL);
302*324bb76bSAndroid Build Coastguard Worker 				}
303*324bb76bSAndroid Build Coastguard Worker 				if (GifFileOut != NULL) {
304*324bb76bSAndroid Build Coastguard Worker 					EGifCloseFile(GifFileOut, NULL);
305*324bb76bSAndroid Build Coastguard Worker 				};
306*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
307*324bb76bSAndroid Build Coastguard Worker 			}
308*324bb76bSAndroid Build Coastguard Worker 
309*324bb76bSAndroid Build Coastguard Worker 			// cppcheck-suppress nullPointerRedundantCheck
310*324bb76bSAndroid Build Coastguard Worker 			if ((DoTranslation = (GifFileOut->SColorMap !=
311*324bb76bSAndroid Build Coastguard Worker 			                      (ColorMapObject *)NULL))) {
312*324bb76bSAndroid Build Coastguard Worker 				ColorMapObject *UnionMap;
313*324bb76bSAndroid Build Coastguard Worker 
314*324bb76bSAndroid Build Coastguard Worker 				UnionMap = GifUnionColorMap(
315*324bb76bSAndroid Build Coastguard Worker 				    // cppcheck-suppress nullPointerRedundantCheck
316*324bb76bSAndroid Build Coastguard Worker 				    GifFileOut->SColorMap, Inclusion->SColorMap,
317*324bb76bSAndroid Build Coastguard Worker 				    Translation);
318*324bb76bSAndroid Build Coastguard Worker 
319*324bb76bSAndroid Build Coastguard Worker 				if (UnionMap == NULL) {
320*324bb76bSAndroid Build Coastguard Worker 					PARSE_ERROR("Inclusion failed --- "
321*324bb76bSAndroid Build Coastguard Worker 					            "global map conflict.");
322*324bb76bSAndroid Build Coastguard Worker 					// cppcheck-suppress nullPointerRedundantCheck
323*324bb76bSAndroid Build Coastguard Worker 					PrintGifError(GifFileOut->Error);
324*324bb76bSAndroid Build Coastguard Worker 					// cppcheck-suppress knownConditionTrueFalse
325*324bb76bSAndroid Build Coastguard Worker 					if (Inclusion != NULL) {
326*324bb76bSAndroid Build Coastguard Worker 						DGifCloseFile(Inclusion, NULL);
327*324bb76bSAndroid Build Coastguard Worker 					}
328*324bb76bSAndroid Build Coastguard Worker 					if (GifFileOut != NULL) {
329*324bb76bSAndroid Build Coastguard Worker 						EGifCloseFile(GifFileOut, NULL);
330*324bb76bSAndroid Build Coastguard Worker 					}
331*324bb76bSAndroid Build Coastguard Worker 					exit(EXIT_FAILURE);
332*324bb76bSAndroid Build Coastguard Worker 				}
333*324bb76bSAndroid Build Coastguard Worker 
334*324bb76bSAndroid Build Coastguard Worker 				GifFreeMapObject(GifFileOut->SColorMap);
335*324bb76bSAndroid Build Coastguard Worker 				GifFileOut->SColorMap = UnionMap;
336*324bb76bSAndroid Build Coastguard Worker 			}
337*324bb76bSAndroid Build Coastguard Worker 
338*324bb76bSAndroid Build Coastguard Worker 			for (CopyFrom = Inclusion->SavedImages;
339*324bb76bSAndroid Build Coastguard Worker 			     CopyFrom <
340*324bb76bSAndroid Build Coastguard Worker 			     Inclusion->SavedImages + Inclusion->ImageCount;
341*324bb76bSAndroid Build Coastguard Worker 			     CopyFrom++) {
342*324bb76bSAndroid Build Coastguard Worker 				if ((NewImage = GifMakeSavedImage(
343*324bb76bSAndroid Build Coastguard Worker 				         GifFileOut, CopyFrom)) == NULL) {
344*324bb76bSAndroid Build Coastguard Worker 					PARSE_ERROR("Inclusion failed --- out "
345*324bb76bSAndroid Build Coastguard Worker 					            "of memory.");
346*324bb76bSAndroid Build Coastguard Worker 					// cppcheck-suppress nullPointerRedundantCheck
347*324bb76bSAndroid Build Coastguard Worker 					PrintGifError(GifFileOut->Error);
348*324bb76bSAndroid Build Coastguard Worker 					// cppcheck-suppress knownConditionTrueFalse
349*324bb76bSAndroid Build Coastguard Worker 					if (Inclusion != NULL) {
350*324bb76bSAndroid Build Coastguard Worker 						DGifCloseFile(Inclusion, NULL);
351*324bb76bSAndroid Build Coastguard Worker 					}
352*324bb76bSAndroid Build Coastguard Worker 					if (GifFileOut != NULL) {
353*324bb76bSAndroid Build Coastguard Worker 						EGifCloseFile(GifFileOut, NULL);
354*324bb76bSAndroid Build Coastguard Worker 					}
355*324bb76bSAndroid Build Coastguard Worker 					exit(EXIT_FAILURE);
356*324bb76bSAndroid Build Coastguard Worker 				} else if (DoTranslation) {
357*324bb76bSAndroid Build Coastguard Worker 					GifApplyTranslation(NewImage,
358*324bb76bSAndroid Build Coastguard Worker 					                    Translation);
359*324bb76bSAndroid Build Coastguard Worker 				}
360*324bb76bSAndroid Build Coastguard Worker 
361*324bb76bSAndroid Build Coastguard Worker 				GifQprintf("%s: Image %d at (%d, %d) [%dx%d]: "
362*324bb76bSAndroid Build Coastguard Worker 				           "from %s\n",
363*324bb76bSAndroid Build Coastguard Worker 				           PROGRAM_NAME, GifFileOut->ImageCount,
364*324bb76bSAndroid Build Coastguard Worker 				           NewImage->ImageDesc.Left,
365*324bb76bSAndroid Build Coastguard Worker 				           NewImage->ImageDesc.Top,
366*324bb76bSAndroid Build Coastguard Worker 				           NewImage->ImageDesc.Width,
367*324bb76bSAndroid Build Coastguard Worker 				           NewImage->ImageDesc.Height,
368*324bb76bSAndroid Build Coastguard Worker 				           InclusionFile);
369*324bb76bSAndroid Build Coastguard Worker 			}
370*324bb76bSAndroid Build Coastguard Worker 
371*324bb76bSAndroid Build Coastguard Worker 			(void)DGifCloseFile(Inclusion, NULL);
372*324bb76bSAndroid Build Coastguard Worker 		}
373*324bb76bSAndroid Build Coastguard Worker 
374*324bb76bSAndroid Build Coastguard Worker 		/*
375*324bb76bSAndroid Build Coastguard Worker 		 * Extension blocks.
376*324bb76bSAndroid Build Coastguard Worker 		 */
377*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "comment\n") == 0) {
378*324bb76bSAndroid Build Coastguard Worker 			int bc = 0;
379*324bb76bSAndroid Build Coastguard Worker 			while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) {
380*324bb76bSAndroid Build Coastguard Worker 				if (strcmp(buf, "end\n") == 0) {
381*324bb76bSAndroid Build Coastguard Worker 					break;
382*324bb76bSAndroid Build Coastguard Worker 				} else {
383*324bb76bSAndroid Build Coastguard Worker 					int Len;
384*324bb76bSAndroid Build Coastguard Worker 
385*324bb76bSAndroid Build Coastguard Worker 					buf[strlen(buf) - 1] = '\0';
386*324bb76bSAndroid Build Coastguard Worker 					Len = EscapeString(buf, buf);
387*324bb76bSAndroid Build Coastguard Worker 					if (GifAddExtensionBlock(
388*324bb76bSAndroid Build Coastguard Worker 					        &LeadingExtensionBlockCount,
389*324bb76bSAndroid Build Coastguard Worker 					        &LeadingExtensionBlocks,
390*324bb76bSAndroid Build Coastguard Worker 					        bc++ == CONTINUE_EXT_FUNC_CODE
391*324bb76bSAndroid Build Coastguard Worker 					            ? COMMENT_EXT_FUNC_CODE
392*324bb76bSAndroid Build Coastguard Worker 					            : 0,
393*324bb76bSAndroid Build Coastguard Worker 					        Len, (unsigned char *)buf) ==
394*324bb76bSAndroid Build Coastguard Worker 					    GIF_ERROR) {
395*324bb76bSAndroid Build Coastguard Worker 						PARSE_ERROR(
396*324bb76bSAndroid Build Coastguard Worker 						    "out of memory while "
397*324bb76bSAndroid Build Coastguard Worker 						    "adding comment block.");
398*324bb76bSAndroid Build Coastguard Worker 						exit(EXIT_FAILURE);
399*324bb76bSAndroid Build Coastguard Worker 					}
400*324bb76bSAndroid Build Coastguard Worker 				}
401*324bb76bSAndroid Build Coastguard Worker 			}
402*324bb76bSAndroid Build Coastguard Worker 		} else if (strcmp(buf, "plaintext\n") == 0) {
403*324bb76bSAndroid Build Coastguard Worker 			int bc = 0;
404*324bb76bSAndroid Build Coastguard Worker 			while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) {
405*324bb76bSAndroid Build Coastguard Worker 				if (strcmp(buf, "end\n") == 0) {
406*324bb76bSAndroid Build Coastguard Worker 					break;
407*324bb76bSAndroid Build Coastguard Worker 				} else {
408*324bb76bSAndroid Build Coastguard Worker 					int Len;
409*324bb76bSAndroid Build Coastguard Worker 
410*324bb76bSAndroid Build Coastguard Worker 					buf[strlen(buf) - 1] = '\0';
411*324bb76bSAndroid Build Coastguard Worker 					Len = EscapeString(buf, buf);
412*324bb76bSAndroid Build Coastguard Worker 					if (GifAddExtensionBlock(
413*324bb76bSAndroid Build Coastguard Worker 					        &LeadingExtensionBlockCount,
414*324bb76bSAndroid Build Coastguard Worker 					        &LeadingExtensionBlocks,
415*324bb76bSAndroid Build Coastguard Worker 					        bc++ == CONTINUE_EXT_FUNC_CODE
416*324bb76bSAndroid Build Coastguard Worker 					            ? PLAINTEXT_EXT_FUNC_CODE
417*324bb76bSAndroid Build Coastguard Worker 					            : 0,
418*324bb76bSAndroid Build Coastguard Worker 					        Len, (unsigned char *)buf) ==
419*324bb76bSAndroid Build Coastguard Worker 					    GIF_ERROR) {
420*324bb76bSAndroid Build Coastguard Worker 						PARSE_ERROR(
421*324bb76bSAndroid Build Coastguard Worker 						    "out of memory while "
422*324bb76bSAndroid Build Coastguard Worker 						    "adding plaintext block.");
423*324bb76bSAndroid Build Coastguard Worker 						exit(EXIT_FAILURE);
424*324bb76bSAndroid Build Coastguard Worker 					}
425*324bb76bSAndroid Build Coastguard Worker 				}
426*324bb76bSAndroid Build Coastguard Worker 			}
427*324bb76bSAndroid Build Coastguard Worker 		} else if (strcmp(buf, "graphics control\n") == 0) {
428*324bb76bSAndroid Build Coastguard Worker 			GraphicsControlBlock gcb;
429*324bb76bSAndroid Build Coastguard Worker 			size_t Len;
430*324bb76bSAndroid Build Coastguard Worker 
431*324bb76bSAndroid Build Coastguard Worker 			memset(&gcb, '\0', sizeof(gcb));
432*324bb76bSAndroid Build Coastguard Worker 			gcb.TransparentColor = NO_TRANSPARENT_COLOR;
433*324bb76bSAndroid Build Coastguard Worker 			while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) {
434*324bb76bSAndroid Build Coastguard Worker 				if (strcmp(buf, "end\n") == 0) {
435*324bb76bSAndroid Build Coastguard Worker 					break;
436*324bb76bSAndroid Build Coastguard Worker 				} else {
437*324bb76bSAndroid Build Coastguard Worker 					char *tp = buf;
438*324bb76bSAndroid Build Coastguard Worker 
439*324bb76bSAndroid Build Coastguard Worker 					while (isspace(*tp)) {
440*324bb76bSAndroid Build Coastguard Worker 						tp++;
441*324bb76bSAndroid Build Coastguard Worker 					}
442*324bb76bSAndroid Build Coastguard Worker 					if (sscanf(tp, "disposal mode %d\n",
443*324bb76bSAndroid Build Coastguard Worker 					           &gcb.DisposalMode)) {
444*324bb76bSAndroid Build Coastguard Worker 						continue;
445*324bb76bSAndroid Build Coastguard Worker 					}
446*324bb76bSAndroid Build Coastguard Worker 					if (strcmp(tp,
447*324bb76bSAndroid Build Coastguard Worker 					           "user input flag on\n") ==
448*324bb76bSAndroid Build Coastguard Worker 					    0) {
449*324bb76bSAndroid Build Coastguard Worker 						gcb.UserInputFlag = true;
450*324bb76bSAndroid Build Coastguard Worker 						continue;
451*324bb76bSAndroid Build Coastguard Worker 					}
452*324bb76bSAndroid Build Coastguard Worker 					if (strcmp(tp,
453*324bb76bSAndroid Build Coastguard Worker 					           "user input flag off\n") ==
454*324bb76bSAndroid Build Coastguard Worker 					    0) {
455*324bb76bSAndroid Build Coastguard Worker 						gcb.UserInputFlag = false;
456*324bb76bSAndroid Build Coastguard Worker 						continue;
457*324bb76bSAndroid Build Coastguard Worker 					}
458*324bb76bSAndroid Build Coastguard Worker 					if (sscanf(tp, "delay %d\n",
459*324bb76bSAndroid Build Coastguard Worker 					           &gcb.DelayTime)) {
460*324bb76bSAndroid Build Coastguard Worker 						continue;
461*324bb76bSAndroid Build Coastguard Worker 					}
462*324bb76bSAndroid Build Coastguard Worker 					if (sscanf(tp, "transparent index %d\n",
463*324bb76bSAndroid Build Coastguard Worker 					           &gcb.TransparentColor)) {
464*324bb76bSAndroid Build Coastguard Worker 						continue;
465*324bb76bSAndroid Build Coastguard Worker 					}
466*324bb76bSAndroid Build Coastguard Worker 					(void)fputs(tp, stderr);
467*324bb76bSAndroid Build Coastguard Worker 					PARSE_ERROR("unrecognized directive in "
468*324bb76bSAndroid Build Coastguard Worker 					            "GCB block.");
469*324bb76bSAndroid Build Coastguard Worker 					exit(EXIT_FAILURE);
470*324bb76bSAndroid Build Coastguard Worker 				}
471*324bb76bSAndroid Build Coastguard Worker 			}
472*324bb76bSAndroid Build Coastguard Worker 			Len = EGifGCBToExtension(&gcb, (GifByteType *)buf);
473*324bb76bSAndroid Build Coastguard Worker 			if (GifAddExtensionBlock(
474*324bb76bSAndroid Build Coastguard Worker 			        &LeadingExtensionBlockCount,
475*324bb76bSAndroid Build Coastguard Worker 			        &LeadingExtensionBlocks, GRAPHICS_EXT_FUNC_CODE,
476*324bb76bSAndroid Build Coastguard Worker 			        Len, (unsigned char *)buf) == GIF_ERROR) {
477*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("out of memory while adding GCB.");
478*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
479*324bb76bSAndroid Build Coastguard Worker 			}
480*324bb76bSAndroid Build Coastguard Worker 
481*324bb76bSAndroid Build Coastguard Worker 		} else if (sscanf(buf, "netscape loop %u", &intval)) {
482*324bb76bSAndroid Build Coastguard Worker 			unsigned char params[3] = {1, 0, 0};
483*324bb76bSAndroid Build Coastguard Worker 			/* Create a Netscape 2.0 loop block */
484*324bb76bSAndroid Build Coastguard Worker 			if (GifAddExtensionBlock(
485*324bb76bSAndroid Build Coastguard Worker 			        &LeadingExtensionBlockCount,
486*324bb76bSAndroid Build Coastguard Worker 			        &LeadingExtensionBlocks,
487*324bb76bSAndroid Build Coastguard Worker 			        APPLICATION_EXT_FUNC_CODE, 11,
488*324bb76bSAndroid Build Coastguard Worker 			        (unsigned char *)"NETSCAPE2.0") == GIF_ERROR) {
489*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR(
490*324bb76bSAndroid Build Coastguard Worker 				    "out of memory while adding loop block.");
491*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
492*324bb76bSAndroid Build Coastguard Worker 			}
493*324bb76bSAndroid Build Coastguard Worker 			params[1] = (intval & 0xff);
494*324bb76bSAndroid Build Coastguard Worker 			params[2] = (intval >> 8) & 0xff;
495*324bb76bSAndroid Build Coastguard Worker 			if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
496*324bb76bSAndroid Build Coastguard Worker 			                         &LeadingExtensionBlocks, 0,
497*324bb76bSAndroid Build Coastguard Worker 			                         sizeof(params),
498*324bb76bSAndroid Build Coastguard Worker 			                         params) == GIF_ERROR) {
499*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("out of memory while adding loop "
500*324bb76bSAndroid Build Coastguard Worker 				            "continuation.");
501*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
502*324bb76bSAndroid Build Coastguard Worker 			}
503*324bb76bSAndroid Build Coastguard Worker 
504*324bb76bSAndroid Build Coastguard Worker 		} else if (sscanf(buf, "extension %x", &ExtCode)) {
505*324bb76bSAndroid Build Coastguard Worker 			int bc = 0;
506*324bb76bSAndroid Build Coastguard Worker 			while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) {
507*324bb76bSAndroid Build Coastguard Worker 				if (strcmp(buf, "end\n") == 0) {
508*324bb76bSAndroid Build Coastguard Worker 					break;
509*324bb76bSAndroid Build Coastguard Worker 				} else {
510*324bb76bSAndroid Build Coastguard Worker 					int Len;
511*324bb76bSAndroid Build Coastguard Worker 
512*324bb76bSAndroid Build Coastguard Worker 					buf[strlen(buf) - 1] = '\0';
513*324bb76bSAndroid Build Coastguard Worker 					Len = EscapeString(buf, buf);
514*324bb76bSAndroid Build Coastguard Worker 					if (GifAddExtensionBlock(
515*324bb76bSAndroid Build Coastguard Worker 					        &LeadingExtensionBlockCount,
516*324bb76bSAndroid Build Coastguard Worker 					        &LeadingExtensionBlocks,
517*324bb76bSAndroid Build Coastguard Worker 					        bc++ == CONTINUE_EXT_FUNC_CODE
518*324bb76bSAndroid Build Coastguard Worker 					            ? ExtCode
519*324bb76bSAndroid Build Coastguard Worker 					            : 0,
520*324bb76bSAndroid Build Coastguard Worker 					        Len, (unsigned char *)buf) ==
521*324bb76bSAndroid Build Coastguard Worker 					    GIF_ERROR) {
522*324bb76bSAndroid Build Coastguard Worker 						PARSE_ERROR(
523*324bb76bSAndroid Build Coastguard Worker 						    "out of memory while "
524*324bb76bSAndroid Build Coastguard Worker 						    "adding extension block.");
525*324bb76bSAndroid Build Coastguard Worker 						exit(EXIT_FAILURE);
526*324bb76bSAndroid Build Coastguard Worker 					}
527*324bb76bSAndroid Build Coastguard Worker 				}
528*324bb76bSAndroid Build Coastguard Worker 			}
529*324bb76bSAndroid Build Coastguard Worker 		}
530*324bb76bSAndroid Build Coastguard Worker 
531*324bb76bSAndroid Build Coastguard Worker 		/*
532*324bb76bSAndroid Build Coastguard Worker 		 * Explicit image declarations
533*324bb76bSAndroid Build Coastguard Worker 		 */
534*324bb76bSAndroid Build Coastguard Worker 
535*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "image\n") == 0) {
536*324bb76bSAndroid Build Coastguard Worker 			if ((NewImage = GifMakeSavedImage(GifFileOut, NULL)) ==
537*324bb76bSAndroid Build Coastguard Worker 			    (SavedImage *)NULL) {
538*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Out of memory while allocating "
539*324bb76bSAndroid Build Coastguard Worker 				            "image block.");
540*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
541*324bb76bSAndroid Build Coastguard Worker 			}
542*324bb76bSAndroid Build Coastguard Worker 
543*324bb76bSAndroid Build Coastguard Worker 			/* use global table unless user specifies a local one */
544*324bb76bSAndroid Build Coastguard Worker 			ColorMap = GlobalColorMap;
545*324bb76bSAndroid Build Coastguard Worker 			KeyTable = GlobalColorKeys;
546*324bb76bSAndroid Build Coastguard Worker 
547*324bb76bSAndroid Build Coastguard Worker 			/* connect leading extension blocks */
548*324bb76bSAndroid Build Coastguard Worker 			NewImage->ExtensionBlockCount =
549*324bb76bSAndroid Build Coastguard Worker 			    LeadingExtensionBlockCount;
550*324bb76bSAndroid Build Coastguard Worker 			NewImage->ExtensionBlocks = LeadingExtensionBlocks;
551*324bb76bSAndroid Build Coastguard Worker 			LeadingExtensionBlockCount = 0;
552*324bb76bSAndroid Build Coastguard Worker 			LeadingExtensionBlocks = NULL;
553*324bb76bSAndroid Build Coastguard Worker 		}
554*324bb76bSAndroid Build Coastguard Worker 
555*324bb76bSAndroid Build Coastguard Worker 		/*
556*324bb76bSAndroid Build Coastguard Worker 		 * Nothing past this point is valid unless we've seen a previous
557*324bb76bSAndroid Build Coastguard Worker 		 * image declaration.
558*324bb76bSAndroid Build Coastguard Worker 		 */
559*324bb76bSAndroid Build Coastguard Worker 		else if (NewImage == (SavedImage *)NULL) {
560*324bb76bSAndroid Build Coastguard Worker 			(void)fputs(buf, stderr);
561*324bb76bSAndroid Build Coastguard Worker 			PARSE_ERROR("Syntax error in header block.");
562*324bb76bSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
563*324bb76bSAndroid Build Coastguard Worker 		}
564*324bb76bSAndroid Build Coastguard Worker 
565*324bb76bSAndroid Build Coastguard Worker 		/*
566*324bb76bSAndroid Build Coastguard Worker 		 * Accept image attributes
567*324bb76bSAndroid Build Coastguard Worker 		 */
568*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "image top %d\n",
569*324bb76bSAndroid Build Coastguard Worker 		                &NewImage->ImageDesc.Top) == 1) {
570*324bb76bSAndroid Build Coastguard Worker 			continue;
571*324bb76bSAndroid Build Coastguard Worker 		}
572*324bb76bSAndroid Build Coastguard Worker 
573*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "image left %d\n",
574*324bb76bSAndroid Build Coastguard Worker 		                &NewImage->ImageDesc.Left) == 1) {
575*324bb76bSAndroid Build Coastguard Worker 			continue;
576*324bb76bSAndroid Build Coastguard Worker 		}
577*324bb76bSAndroid Build Coastguard Worker 
578*324bb76bSAndroid Build Coastguard Worker 		else if (strcmp(buf, "image interlaced\n") == 0) {
579*324bb76bSAndroid Build Coastguard Worker 			NewImage->ImageDesc.Interlace = true;
580*324bb76bSAndroid Build Coastguard Worker 			continue;
581*324bb76bSAndroid Build Coastguard Worker 		}
582*324bb76bSAndroid Build Coastguard Worker 
583*324bb76bSAndroid Build Coastguard Worker 		else if (sscanf(buf, "image bits %d by %d",
584*324bb76bSAndroid Build Coastguard Worker 		                &NewImage->ImageDesc.Width,
585*324bb76bSAndroid Build Coastguard Worker 		                &NewImage->ImageDesc.Height) == 2) {
586*324bb76bSAndroid Build Coastguard Worker 			int i, j;
587*324bb76bSAndroid Build Coastguard Worker 			static GifPixelType *Raster;
588*324bb76bSAndroid Build Coastguard Worker 			int c;
589*324bb76bSAndroid Build Coastguard Worker 			bool hex = (strstr(buf, "hex") != NULL);
590*324bb76bSAndroid Build Coastguard Worker 
591*324bb76bSAndroid Build Coastguard Worker 			/* coverity[overflow_sink] */
592*324bb76bSAndroid Build Coastguard Worker 			if ((Raster = (GifPixelType *)malloc(
593*324bb76bSAndroid Build Coastguard Worker 			         sizeof(GifPixelType) *
594*324bb76bSAndroid Build Coastguard Worker 			         NewImage->ImageDesc.Width *
595*324bb76bSAndroid Build Coastguard Worker 			         NewImage->ImageDesc.Height)) == NULL) {
596*324bb76bSAndroid Build Coastguard Worker 				PARSE_ERROR("Failed to allocate raster block, "
597*324bb76bSAndroid Build Coastguard Worker 				            "aborted.");
598*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
599*324bb76bSAndroid Build Coastguard Worker 			}
600*324bb76bSAndroid Build Coastguard Worker 
601*324bb76bSAndroid Build Coastguard Worker 			GifQprintf("%s: Image %d at (%d, %d) [%dx%d]:     ",
602*324bb76bSAndroid Build Coastguard Worker 			           PROGRAM_NAME, GifFileOut->ImageCount,
603*324bb76bSAndroid Build Coastguard Worker 			           NewImage->ImageDesc.Left,
604*324bb76bSAndroid Build Coastguard Worker 			           NewImage->ImageDesc.Top,
605*324bb76bSAndroid Build Coastguard Worker 			           NewImage->ImageDesc.Width,
606*324bb76bSAndroid Build Coastguard Worker 			           NewImage->ImageDesc.Height);
607*324bb76bSAndroid Build Coastguard Worker 
608*324bb76bSAndroid Build Coastguard Worker 			GifByteType *tp = Raster;
609*324bb76bSAndroid Build Coastguard Worker 			for (i = 0; i < NewImage->ImageDesc.Height; i++) {
610*324bb76bSAndroid Build Coastguard Worker 
611*324bb76bSAndroid Build Coastguard Worker 				char *dp;
612*324bb76bSAndroid Build Coastguard Worker 
613*324bb76bSAndroid Build Coastguard Worker 				for (j = 0; j < NewImage->ImageDesc.Width;
614*324bb76bSAndroid Build Coastguard Worker 				     j++) {
615*324bb76bSAndroid Build Coastguard Worker 					if ((c = fgetc(txtin)) == EOF) {
616*324bb76bSAndroid Build Coastguard Worker 						PARSE_ERROR("input file ended "
617*324bb76bSAndroid Build Coastguard Worker 						            "prematurely.");
618*324bb76bSAndroid Build Coastguard Worker 						exit(EXIT_FAILURE);
619*324bb76bSAndroid Build Coastguard Worker 					} else if (c == '\n') {
620*324bb76bSAndroid Build Coastguard Worker 						--j;
621*324bb76bSAndroid Build Coastguard Worker 						++LineNum;
622*324bb76bSAndroid Build Coastguard Worker 					} else if (isspace(c)) {
623*324bb76bSAndroid Build Coastguard Worker 						--j;
624*324bb76bSAndroid Build Coastguard Worker 					} else if (hex) {
625*324bb76bSAndroid Build Coastguard Worker 						const static char *hexdigits =
626*324bb76bSAndroid Build Coastguard Worker 						    "0123456789ABCDEF";
627*324bb76bSAndroid Build Coastguard Worker 						unsigned char hi, lo;
628*324bb76bSAndroid Build Coastguard Worker 						dp = strchr(hexdigits,
629*324bb76bSAndroid Build Coastguard Worker 						            toupper(c));
630*324bb76bSAndroid Build Coastguard Worker 						if (dp == NULL) {
631*324bb76bSAndroid Build Coastguard Worker 							PARSE_ERROR(
632*324bb76bSAndroid Build Coastguard Worker 							    "Invalid hex high "
633*324bb76bSAndroid Build Coastguard Worker 							    "byte.");
634*324bb76bSAndroid Build Coastguard Worker 							exit(EXIT_FAILURE);
635*324bb76bSAndroid Build Coastguard Worker 						}
636*324bb76bSAndroid Build Coastguard Worker 						hi = (dp - hexdigits);
637*324bb76bSAndroid Build Coastguard Worker 						if ((c = fgetc(txtin)) == EOF) {
638*324bb76bSAndroid Build Coastguard Worker 							PARSE_ERROR(
639*324bb76bSAndroid Build Coastguard Worker 							    "input file ended "
640*324bb76bSAndroid Build Coastguard Worker 							    "prematurely.");
641*324bb76bSAndroid Build Coastguard Worker 							exit(EXIT_FAILURE);
642*324bb76bSAndroid Build Coastguard Worker 						}
643*324bb76bSAndroid Build Coastguard Worker 						dp = strchr(hexdigits,
644*324bb76bSAndroid Build Coastguard Worker 						            toupper(c));
645*324bb76bSAndroid Build Coastguard Worker 						if (dp == NULL) {
646*324bb76bSAndroid Build Coastguard Worker 							PARSE_ERROR(
647*324bb76bSAndroid Build Coastguard Worker 							    "Invalid hex low "
648*324bb76bSAndroid Build Coastguard Worker 							    "byte.");
649*324bb76bSAndroid Build Coastguard Worker 							exit(EXIT_FAILURE);
650*324bb76bSAndroid Build Coastguard Worker 						}
651*324bb76bSAndroid Build Coastguard Worker 						lo = (dp - hexdigits);
652*324bb76bSAndroid Build Coastguard Worker 						*tp++ = (hi << 4) | lo;
653*324bb76bSAndroid Build Coastguard Worker 					} else if ((dp = strchr(KeyTable, c))) {
654*324bb76bSAndroid Build Coastguard Worker 						*tp++ = (dp - KeyTable);
655*324bb76bSAndroid Build Coastguard Worker 					} else {
656*324bb76bSAndroid Build Coastguard Worker 						PARSE_ERROR(
657*324bb76bSAndroid Build Coastguard Worker 						    "Invalid ASCII pixel key.");
658*324bb76bSAndroid Build Coastguard Worker 						exit(EXIT_FAILURE);
659*324bb76bSAndroid Build Coastguard Worker 					}
660*324bb76bSAndroid Build Coastguard Worker 				}
661*324bb76bSAndroid Build Coastguard Worker 
662*324bb76bSAndroid Build Coastguard Worker 				if (GifNoisyPrint) {
663*324bb76bSAndroid Build Coastguard Worker 					fprintf(stderr, "\b\b\b\b%-4d", i);
664*324bb76bSAndroid Build Coastguard Worker 				}
665*324bb76bSAndroid Build Coastguard Worker 			}
666*324bb76bSAndroid Build Coastguard Worker 
667*324bb76bSAndroid Build Coastguard Worker 			if (GifNoisyPrint) {
668*324bb76bSAndroid Build Coastguard Worker 				putc('\n', stderr);
669*324bb76bSAndroid Build Coastguard Worker 			}
670*324bb76bSAndroid Build Coastguard Worker 
671*324bb76bSAndroid Build Coastguard Worker 			NewImage->RasterBits = (unsigned char *)Raster;
672*324bb76bSAndroid Build Coastguard Worker 		} else {
673*324bb76bSAndroid Build Coastguard Worker 			(void)fputs(buf, stderr);
674*324bb76bSAndroid Build Coastguard Worker 			PARSE_ERROR("Syntax error in image description.");
675*324bb76bSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
676*324bb76bSAndroid Build Coastguard Worker 		}
677*324bb76bSAndroid Build Coastguard Worker 	}
678*324bb76bSAndroid Build Coastguard Worker 
679*324bb76bSAndroid Build Coastguard Worker 	/* connect trailing extension blocks */
680*324bb76bSAndroid Build Coastguard Worker 	GifFileOut->ExtensionBlockCount = LeadingExtensionBlockCount;
681*324bb76bSAndroid Build Coastguard Worker 	GifFileOut->ExtensionBlocks = LeadingExtensionBlocks;
682*324bb76bSAndroid Build Coastguard Worker 	// LeadingExtensionBlockCount = 0;
683*324bb76bSAndroid Build Coastguard Worker 	LeadingExtensionBlocks = NULL;
684*324bb76bSAndroid Build Coastguard Worker 
685*324bb76bSAndroid Build Coastguard Worker 	EGifSpew(GifFileOut);
686*324bb76bSAndroid Build Coastguard Worker }
687*324bb76bSAndroid Build Coastguard Worker 
VisibleDumpBuffer(GifByteType * buf,int len)688*324bb76bSAndroid Build Coastguard Worker static void VisibleDumpBuffer(GifByteType *buf, int len)
689*324bb76bSAndroid Build Coastguard Worker /* Visibilize a given string */
690*324bb76bSAndroid Build Coastguard Worker {
691*324bb76bSAndroid Build Coastguard Worker 	GifByteType *cp;
692*324bb76bSAndroid Build Coastguard Worker 
693*324bb76bSAndroid Build Coastguard Worker 	for (cp = buf; cp < buf + len; cp++) {
694*324bb76bSAndroid Build Coastguard Worker 		if (isprint((int)(*cp)) || *cp == ' ') {
695*324bb76bSAndroid Build Coastguard Worker 			putchar(*cp);
696*324bb76bSAndroid Build Coastguard Worker 		} else if (*cp == '\n') {
697*324bb76bSAndroid Build Coastguard Worker 			putchar('\\');
698*324bb76bSAndroid Build Coastguard Worker 			putchar('n');
699*324bb76bSAndroid Build Coastguard Worker 		} else if (*cp == '\r') {
700*324bb76bSAndroid Build Coastguard Worker 			putchar('\\');
701*324bb76bSAndroid Build Coastguard Worker 			putchar('r');
702*324bb76bSAndroid Build Coastguard Worker 		} else if (*cp == '\b') {
703*324bb76bSAndroid Build Coastguard Worker 			putchar('\\');
704*324bb76bSAndroid Build Coastguard Worker 			putchar('b');
705*324bb76bSAndroid Build Coastguard Worker 		} else if (*cp < ' ') {
706*324bb76bSAndroid Build Coastguard Worker 			putchar('\\');
707*324bb76bSAndroid Build Coastguard Worker 			putchar('^');
708*324bb76bSAndroid Build Coastguard Worker 			putchar('@' + *cp);
709*324bb76bSAndroid Build Coastguard Worker 		} else {
710*324bb76bSAndroid Build Coastguard Worker 			printf("\\0x%02x", *cp);
711*324bb76bSAndroid Build Coastguard Worker 		}
712*324bb76bSAndroid Build Coastguard Worker 	}
713*324bb76bSAndroid Build Coastguard Worker }
714*324bb76bSAndroid Build Coastguard Worker 
DumpExtensions(GifFileType * GifFileOut,int ExtensionBlockCount,ExtensionBlock * ExtensionBlocks)715*324bb76bSAndroid Build Coastguard Worker static void DumpExtensions(GifFileType *GifFileOut, int ExtensionBlockCount,
716*324bb76bSAndroid Build Coastguard Worker                            ExtensionBlock *ExtensionBlocks) {
717*324bb76bSAndroid Build Coastguard Worker 	ExtensionBlock *ep;
718*324bb76bSAndroid Build Coastguard Worker 
719*324bb76bSAndroid Build Coastguard Worker 	for (ep = ExtensionBlocks; ep < ExtensionBlocks + ExtensionBlockCount;
720*324bb76bSAndroid Build Coastguard Worker 	     ep++) {
721*324bb76bSAndroid Build Coastguard Worker 		bool last = (ep - ExtensionBlocks == (ExtensionBlockCount - 1));
722*324bb76bSAndroid Build Coastguard Worker 		if (ep->Function == COMMENT_EXT_FUNC_CODE) {
723*324bb76bSAndroid Build Coastguard Worker 			printf("comment\n");
724*324bb76bSAndroid Build Coastguard Worker 			VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
725*324bb76bSAndroid Build Coastguard Worker 			putchar('\n');
726*324bb76bSAndroid Build Coastguard Worker 			while (!last &&
727*324bb76bSAndroid Build Coastguard Worker 			       ep[1].Function == CONTINUE_EXT_FUNC_CODE) {
728*324bb76bSAndroid Build Coastguard Worker 				++ep;
729*324bb76bSAndroid Build Coastguard Worker 				last = (ep - ExtensionBlocks ==
730*324bb76bSAndroid Build Coastguard Worker 				        (ExtensionBlockCount - 1));
731*324bb76bSAndroid Build Coastguard Worker 				VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
732*324bb76bSAndroid Build Coastguard Worker 				putchar('\n');
733*324bb76bSAndroid Build Coastguard Worker 			}
734*324bb76bSAndroid Build Coastguard Worker 			printf("end\n\n");
735*324bb76bSAndroid Build Coastguard Worker 		} else if (ep->Function == PLAINTEXT_EXT_FUNC_CODE) {
736*324bb76bSAndroid Build Coastguard Worker 			printf("plaintext\n");
737*324bb76bSAndroid Build Coastguard Worker 			VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
738*324bb76bSAndroid Build Coastguard Worker 			putchar('\n');
739*324bb76bSAndroid Build Coastguard Worker 			while (!last &&
740*324bb76bSAndroid Build Coastguard Worker 			       ep[1].Function == CONTINUE_EXT_FUNC_CODE) {
741*324bb76bSAndroid Build Coastguard Worker 				++ep;
742*324bb76bSAndroid Build Coastguard Worker 				last = (ep - ExtensionBlocks ==
743*324bb76bSAndroid Build Coastguard Worker 				        (ExtensionBlockCount - 1));
744*324bb76bSAndroid Build Coastguard Worker 				VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
745*324bb76bSAndroid Build Coastguard Worker 				putchar('\n');
746*324bb76bSAndroid Build Coastguard Worker 			}
747*324bb76bSAndroid Build Coastguard Worker 			printf("end\n\n");
748*324bb76bSAndroid Build Coastguard Worker 		} else if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
749*324bb76bSAndroid Build Coastguard Worker 			GraphicsControlBlock gcb;
750*324bb76bSAndroid Build Coastguard Worker 			printf("graphics control\n");
751*324bb76bSAndroid Build Coastguard Worker 			if (DGifExtensionToGCB(ep->ByteCount, ep->Bytes,
752*324bb76bSAndroid Build Coastguard Worker 			                       &gcb) == GIF_ERROR) {
753*324bb76bSAndroid Build Coastguard Worker 				GIF_MESSAGE("invalid graphics control block");
754*324bb76bSAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
755*324bb76bSAndroid Build Coastguard Worker 			}
756*324bb76bSAndroid Build Coastguard Worker 			printf("\tdisposal mode %d\n", gcb.DisposalMode);
757*324bb76bSAndroid Build Coastguard Worker 			printf("\tuser input flag %s\n",
758*324bb76bSAndroid Build Coastguard Worker 			       gcb.UserInputFlag ? "on" : "off");
759*324bb76bSAndroid Build Coastguard Worker 			printf("\tdelay %d\n", gcb.DelayTime);
760*324bb76bSAndroid Build Coastguard Worker 			printf("\ttransparent index %d\n",
761*324bb76bSAndroid Build Coastguard Worker 			       gcb.TransparentColor);
762*324bb76bSAndroid Build Coastguard Worker 			printf("end\n\n");
763*324bb76bSAndroid Build Coastguard Worker 		} else if (!last && ep->Function == APPLICATION_EXT_FUNC_CODE &&
764*324bb76bSAndroid Build Coastguard Worker 		           ep->ByteCount >= 11 && (ep + 1)->ByteCount >= 3 &&
765*324bb76bSAndroid Build Coastguard Worker 		           memcmp(ep->Bytes, "NETSCAPE2.0", 11) == 0) {
766*324bb76bSAndroid Build Coastguard Worker 			unsigned char *params = (++ep)->Bytes;
767*324bb76bSAndroid Build Coastguard Worker 			unsigned int loopcount = params[1] | (params[2] << 8);
768*324bb76bSAndroid Build Coastguard Worker 			printf("netscape loop %u\n\n", loopcount);
769*324bb76bSAndroid Build Coastguard Worker 		} else {
770*324bb76bSAndroid Build Coastguard Worker 			printf("extension 0x%02x\n", ep->Function);
771*324bb76bSAndroid Build Coastguard Worker 			VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
772*324bb76bSAndroid Build Coastguard Worker 			while (!last &&
773*324bb76bSAndroid Build Coastguard Worker 			       ep[1].Function == CONTINUE_EXT_FUNC_CODE) {
774*324bb76bSAndroid Build Coastguard Worker 				++ep;
775*324bb76bSAndroid Build Coastguard Worker 				last = (ep - ExtensionBlocks ==
776*324bb76bSAndroid Build Coastguard Worker 				        (ExtensionBlockCount - 1));
777*324bb76bSAndroid Build Coastguard Worker 				VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
778*324bb76bSAndroid Build Coastguard Worker 				putchar('\n');
779*324bb76bSAndroid Build Coastguard Worker 			}
780*324bb76bSAndroid Build Coastguard Worker 			printf("end\n\n");
781*324bb76bSAndroid Build Coastguard Worker 		}
782*324bb76bSAndroid Build Coastguard Worker 	}
783*324bb76bSAndroid Build Coastguard Worker }
784*324bb76bSAndroid Build Coastguard Worker 
Gif2Icon(char * FileName,int fdin,int fdout,char NameTable[])785*324bb76bSAndroid Build Coastguard Worker static void Gif2Icon(char *FileName, int fdin, int fdout, char NameTable[]) {
786*324bb76bSAndroid Build Coastguard Worker 	int ErrorCode, im, i, j, ColorCount = 0;
787*324bb76bSAndroid Build Coastguard Worker 	GifFileType *GifFile;
788*324bb76bSAndroid Build Coastguard Worker 
789*324bb76bSAndroid Build Coastguard Worker 	if (fdin == -1) {
790*324bb76bSAndroid Build Coastguard Worker 		if ((GifFile = DGifOpenFileName(FileName, &ErrorCode)) ==
791*324bb76bSAndroid Build Coastguard Worker 		    NULL) {
792*324bb76bSAndroid Build Coastguard Worker 			PrintGifError(ErrorCode);
793*324bb76bSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
794*324bb76bSAndroid Build Coastguard Worker 		}
795*324bb76bSAndroid Build Coastguard Worker 	} else {
796*324bb76bSAndroid Build Coastguard Worker 		/* Use stdin instead: */
797*324bb76bSAndroid Build Coastguard Worker 		if ((GifFile = DGifOpenFileHandle(fdin, &ErrorCode)) == NULL) {
798*324bb76bSAndroid Build Coastguard Worker 			PrintGifError(ErrorCode);
799*324bb76bSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
800*324bb76bSAndroid Build Coastguard Worker 		}
801*324bb76bSAndroid Build Coastguard Worker 	}
802*324bb76bSAndroid Build Coastguard Worker 
803*324bb76bSAndroid Build Coastguard Worker 	if (DGifSlurp(GifFile) == GIF_ERROR) {
804*324bb76bSAndroid Build Coastguard Worker 		PrintGifError(GifFile->Error);
805*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
806*324bb76bSAndroid Build Coastguard Worker 	}
807*324bb76bSAndroid Build Coastguard Worker 
808*324bb76bSAndroid Build Coastguard Worker 	printf("screen width %d\nscreen height %d\n", GifFile->SWidth,
809*324bb76bSAndroid Build Coastguard Worker 	       GifFile->SHeight);
810*324bb76bSAndroid Build Coastguard Worker 
811*324bb76bSAndroid Build Coastguard Worker 	printf(
812*324bb76bSAndroid Build Coastguard Worker 	    "screen colors %d\nscreen background %d\npixel aspect byte %u\n\n",
813*324bb76bSAndroid Build Coastguard Worker 	    1 << GifFile->SColorResolution, GifFile->SBackGroundColor,
814*324bb76bSAndroid Build Coastguard Worker 	    (unsigned)GifFile->AspectByte);
815*324bb76bSAndroid Build Coastguard Worker 
816*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->SColorMap) {
817*324bb76bSAndroid Build Coastguard Worker 		printf("screen map\n");
818*324bb76bSAndroid Build Coastguard Worker 
819*324bb76bSAndroid Build Coastguard Worker 		printf("\tsort flag %s\n",
820*324bb76bSAndroid Build Coastguard Worker 		       GifFile->SColorMap->SortFlag ? "on" : "off");
821*324bb76bSAndroid Build Coastguard Worker 
822*324bb76bSAndroid Build Coastguard Worker 		for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
823*324bb76bSAndroid Build Coastguard Worker 			if (GifFile->SColorMap->ColorCount < PRINTABLES) {
824*324bb76bSAndroid Build Coastguard Worker 				printf("\trgb %03d %03d %03d is %c\n",
825*324bb76bSAndroid Build Coastguard Worker 				       GifFile->SColorMap->Colors[i].Red,
826*324bb76bSAndroid Build Coastguard Worker 				       GifFile->SColorMap->Colors[i].Green,
827*324bb76bSAndroid Build Coastguard Worker 				       GifFile->SColorMap->Colors[i].Blue,
828*324bb76bSAndroid Build Coastguard Worker 				       NameTable[i]);
829*324bb76bSAndroid Build Coastguard Worker 			} else {
830*324bb76bSAndroid Build Coastguard Worker 				printf("\trgb %03d %03d %03d\n",
831*324bb76bSAndroid Build Coastguard Worker 				       GifFile->SColorMap->Colors[i].Red,
832*324bb76bSAndroid Build Coastguard Worker 				       GifFile->SColorMap->Colors[i].Green,
833*324bb76bSAndroid Build Coastguard Worker 				       GifFile->SColorMap->Colors[i].Blue);
834*324bb76bSAndroid Build Coastguard Worker 			}
835*324bb76bSAndroid Build Coastguard Worker 		}
836*324bb76bSAndroid Build Coastguard Worker 		printf("end\n\n");
837*324bb76bSAndroid Build Coastguard Worker 	}
838*324bb76bSAndroid Build Coastguard Worker 
839*324bb76bSAndroid Build Coastguard Worker 	for (im = 0; im < GifFile->ImageCount; im++) {
840*324bb76bSAndroid Build Coastguard Worker 		SavedImage *image = &GifFile->SavedImages[im];
841*324bb76bSAndroid Build Coastguard Worker 
842*324bb76bSAndroid Build Coastguard Worker 		DumpExtensions(GifFile, image->ExtensionBlockCount,
843*324bb76bSAndroid Build Coastguard Worker 		               image->ExtensionBlocks);
844*324bb76bSAndroid Build Coastguard Worker 
845*324bb76bSAndroid Build Coastguard Worker 		printf("image # %d\nimage left %d\nimage top %d\n", im + 1,
846*324bb76bSAndroid Build Coastguard Worker 		       image->ImageDesc.Left, image->ImageDesc.Top);
847*324bb76bSAndroid Build Coastguard Worker 		if (image->ImageDesc.Interlace) {
848*324bb76bSAndroid Build Coastguard Worker 			printf("image interlaced\n");
849*324bb76bSAndroid Build Coastguard Worker 		}
850*324bb76bSAndroid Build Coastguard Worker 
851*324bb76bSAndroid Build Coastguard Worker 		if (image->ImageDesc.ColorMap) {
852*324bb76bSAndroid Build Coastguard Worker 			printf("image map\n");
853*324bb76bSAndroid Build Coastguard Worker 
854*324bb76bSAndroid Build Coastguard Worker 			printf("\tsort flag %s\n",
855*324bb76bSAndroid Build Coastguard Worker 			       image->ImageDesc.ColorMap->SortFlag ? "on"
856*324bb76bSAndroid Build Coastguard Worker 			                                           : "off");
857*324bb76bSAndroid Build Coastguard Worker 
858*324bb76bSAndroid Build Coastguard Worker 			if (image->ImageDesc.ColorMap->ColorCount <
859*324bb76bSAndroid Build Coastguard Worker 			    PRINTABLES) {
860*324bb76bSAndroid Build Coastguard Worker 				for (i = 0;
861*324bb76bSAndroid Build Coastguard Worker 				     i < image->ImageDesc.ColorMap->ColorCount;
862*324bb76bSAndroid Build Coastguard Worker 				     i++) {
863*324bb76bSAndroid Build Coastguard Worker 					printf(
864*324bb76bSAndroid Build Coastguard Worker 					    "\trgb %03d %03d %03d is %c\n",
865*324bb76bSAndroid Build Coastguard Worker 					    image->ImageDesc.ColorMap->Colors[i]
866*324bb76bSAndroid Build Coastguard Worker 					        .Red,
867*324bb76bSAndroid Build Coastguard Worker 					    image->ImageDesc.ColorMap->Colors[i]
868*324bb76bSAndroid Build Coastguard Worker 					        .Green,
869*324bb76bSAndroid Build Coastguard Worker 					    image->ImageDesc.ColorMap->Colors[i]
870*324bb76bSAndroid Build Coastguard Worker 					        .Blue,
871*324bb76bSAndroid Build Coastguard Worker 					    NameTable[i]);
872*324bb76bSAndroid Build Coastguard Worker 				}
873*324bb76bSAndroid Build Coastguard Worker 			} else {
874*324bb76bSAndroid Build Coastguard Worker 				for (i = 0;
875*324bb76bSAndroid Build Coastguard Worker 				     i < image->ImageDesc.ColorMap->ColorCount;
876*324bb76bSAndroid Build Coastguard Worker 				     i++) {
877*324bb76bSAndroid Build Coastguard Worker 					printf(
878*324bb76bSAndroid Build Coastguard Worker 					    "\trgb %03d %03d %03d\n",
879*324bb76bSAndroid Build Coastguard Worker 					    image->ImageDesc.ColorMap->Colors[i]
880*324bb76bSAndroid Build Coastguard Worker 					        .Red,
881*324bb76bSAndroid Build Coastguard Worker 					    image->ImageDesc.ColorMap->Colors[i]
882*324bb76bSAndroid Build Coastguard Worker 					        .Green,
883*324bb76bSAndroid Build Coastguard Worker 					    image->ImageDesc.ColorMap->Colors[i]
884*324bb76bSAndroid Build Coastguard Worker 					        .Blue);
885*324bb76bSAndroid Build Coastguard Worker 				}
886*324bb76bSAndroid Build Coastguard Worker 			}
887*324bb76bSAndroid Build Coastguard Worker 			printf("end\n\n");
888*324bb76bSAndroid Build Coastguard Worker 		}
889*324bb76bSAndroid Build Coastguard Worker 
890*324bb76bSAndroid Build Coastguard Worker 		/* one of these conditions has to be true */
891*324bb76bSAndroid Build Coastguard Worker 		if (image->ImageDesc.ColorMap) {
892*324bb76bSAndroid Build Coastguard Worker 			ColorCount = image->ImageDesc.ColorMap->ColorCount;
893*324bb76bSAndroid Build Coastguard Worker 		} else if (GifFile->SColorMap) {
894*324bb76bSAndroid Build Coastguard Worker 			ColorCount = GifFile->SColorMap->ColorCount;
895*324bb76bSAndroid Build Coastguard Worker 		}
896*324bb76bSAndroid Build Coastguard Worker 
897*324bb76bSAndroid Build Coastguard Worker 		if (ColorCount < PRINTABLES) {
898*324bb76bSAndroid Build Coastguard Worker 			printf("image bits %d by %d\n", image->ImageDesc.Width,
899*324bb76bSAndroid Build Coastguard Worker 			       image->ImageDesc.Height);
900*324bb76bSAndroid Build Coastguard Worker 		} else {
901*324bb76bSAndroid Build Coastguard Worker 			printf("image bits %d by %d hex\n",
902*324bb76bSAndroid Build Coastguard Worker 			       image->ImageDesc.Width, image->ImageDesc.Height);
903*324bb76bSAndroid Build Coastguard Worker 		}
904*324bb76bSAndroid Build Coastguard Worker 		for (i = 0; i < image->ImageDesc.Height; i++) {
905*324bb76bSAndroid Build Coastguard Worker 			for (j = 0; j < image->ImageDesc.Width; j++) {
906*324bb76bSAndroid Build Coastguard Worker 				GifByteType ch =
907*324bb76bSAndroid Build Coastguard Worker 				    image->RasterBits
908*324bb76bSAndroid Build Coastguard Worker 				        [i * image->ImageDesc.Width + j];
909*324bb76bSAndroid Build Coastguard Worker 				if (ColorCount < PRINTABLES &&
910*324bb76bSAndroid Build Coastguard Worker 				    ch < PRINTABLES) {
911*324bb76bSAndroid Build Coastguard Worker 					putchar(NameTable[ch]);
912*324bb76bSAndroid Build Coastguard Worker 				} else {
913*324bb76bSAndroid Build Coastguard Worker 					printf("%02x", ch);
914*324bb76bSAndroid Build Coastguard Worker 				}
915*324bb76bSAndroid Build Coastguard Worker 			}
916*324bb76bSAndroid Build Coastguard Worker 			putchar('\n');
917*324bb76bSAndroid Build Coastguard Worker 		}
918*324bb76bSAndroid Build Coastguard Worker 		putchar('\n');
919*324bb76bSAndroid Build Coastguard Worker 	}
920*324bb76bSAndroid Build Coastguard Worker 
921*324bb76bSAndroid Build Coastguard Worker 	DumpExtensions(GifFile, GifFile->ExtensionBlockCount,
922*324bb76bSAndroid Build Coastguard Worker 	               GifFile->ExtensionBlocks);
923*324bb76bSAndroid Build Coastguard Worker 
924*324bb76bSAndroid Build Coastguard Worker 	/* Tell EMACS this is a picture... */
925*324bb76bSAndroid Build Coastguard Worker 	printf("# The following sets edit modes for GNU EMACS\n");
926*324bb76bSAndroid Build Coastguard Worker 	printf("# Local ");     /* ...break this up, so that EMACS doesn't */
927*324bb76bSAndroid Build Coastguard Worker 	printf("Variables:\n"); /* get confused when visiting *this* file! */
928*324bb76bSAndroid Build Coastguard Worker 	printf("# mode:picture\n");
929*324bb76bSAndroid Build Coastguard Worker 	printf("# truncate-lines:t\n");
930*324bb76bSAndroid Build Coastguard Worker 	printf("# End:\n");
931*324bb76bSAndroid Build Coastguard Worker 
932*324bb76bSAndroid Build Coastguard Worker 	if (fdin == -1) {
933*324bb76bSAndroid Build Coastguard Worker 		(void)printf("# End of %s dump\n", FileName);
934*324bb76bSAndroid Build Coastguard Worker 	}
935*324bb76bSAndroid Build Coastguard Worker 
936*324bb76bSAndroid Build Coastguard Worker 	/*
937*324bb76bSAndroid Build Coastguard Worker 	 * Sanity checks.
938*324bb76bSAndroid Build Coastguard Worker 	 */
939*324bb76bSAndroid Build Coastguard Worker 
940*324bb76bSAndroid Build Coastguard Worker 	/* check that the background color isn't garbage (SF bug #87) */
941*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->SBackGroundColor < 0 ||
942*324bb76bSAndroid Build Coastguard Worker 	    (GifFile->SColorMap &&
943*324bb76bSAndroid Build Coastguard Worker 	     GifFile->SBackGroundColor >= GifFile->SColorMap->ColorCount)) {
944*324bb76bSAndroid Build Coastguard Worker 		fprintf(stderr, "gifbuild: background color invalid for screen "
945*324bb76bSAndroid Build Coastguard Worker 		                "colormap.\n");
946*324bb76bSAndroid Build Coastguard Worker 	}
947*324bb76bSAndroid Build Coastguard Worker 
948*324bb76bSAndroid Build Coastguard Worker 	if (DGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) {
949*324bb76bSAndroid Build Coastguard Worker 		PrintGifError(ErrorCode);
950*324bb76bSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
951*324bb76bSAndroid Build Coastguard Worker 	}
952*324bb76bSAndroid Build Coastguard Worker }
953*324bb76bSAndroid Build Coastguard Worker 
EscapeString(char * cp,char * tp)954*324bb76bSAndroid Build Coastguard Worker static int EscapeString(char *cp, char *tp)
955*324bb76bSAndroid Build Coastguard Worker /* process standard C-style escape sequences in a string */
956*324bb76bSAndroid Build Coastguard Worker {
957*324bb76bSAndroid Build Coastguard Worker 	char *StartAddr = tp;
958*324bb76bSAndroid Build Coastguard Worker 
959*324bb76bSAndroid Build Coastguard Worker 	while (*cp) {
960*324bb76bSAndroid Build Coastguard Worker 		int cval = 0;
961*324bb76bSAndroid Build Coastguard Worker 
962*324bb76bSAndroid Build Coastguard Worker 		if (*cp == '\\' && strchr("0123456789xX", cp[1])) {
963*324bb76bSAndroid Build Coastguard Worker 			int dcount = 0;
964*324bb76bSAndroid Build Coastguard Worker 
965*324bb76bSAndroid Build Coastguard Worker 			if (*++cp == 'x' || *cp == 'X') {
966*324bb76bSAndroid Build Coastguard Worker 				char *dp,
967*324bb76bSAndroid Build Coastguard Worker 				    *hex = "00112233445566778899aAbBcCdDeEfF";
968*324bb76bSAndroid Build Coastguard Worker 				for (++cp;
969*324bb76bSAndroid Build Coastguard Worker 				     (dp = strchr(hex, *cp)) && (dcount++ < 2);
970*324bb76bSAndroid Build Coastguard Worker 				     cp++) {
971*324bb76bSAndroid Build Coastguard Worker 					cval = (cval * 16) + (dp - hex) / 2;
972*324bb76bSAndroid Build Coastguard Worker 				}
973*324bb76bSAndroid Build Coastguard Worker 			} else if (*cp == '0') {
974*324bb76bSAndroid Build Coastguard Worker 				while (strchr("01234567", *cp) !=
975*324bb76bSAndroid Build Coastguard Worker 				           (char *)NULL &&
976*324bb76bSAndroid Build Coastguard Worker 				       (dcount++ < 3)) {
977*324bb76bSAndroid Build Coastguard Worker 					cval = (cval * 8) + (*cp++ - '0');
978*324bb76bSAndroid Build Coastguard Worker 				}
979*324bb76bSAndroid Build Coastguard Worker 			} else {
980*324bb76bSAndroid Build Coastguard Worker 				while ((strchr("0123456789", *cp) !=
981*324bb76bSAndroid Build Coastguard Worker 				        (char *)NULL) &&
982*324bb76bSAndroid Build Coastguard Worker 				       (dcount++ < 3)) {
983*324bb76bSAndroid Build Coastguard Worker 					cval = (cval * 10) + (*cp++ - '0');
984*324bb76bSAndroid Build Coastguard Worker 				}
985*324bb76bSAndroid Build Coastguard Worker 			}
986*324bb76bSAndroid Build Coastguard Worker 		} else if (*cp == '\\') /* C-style character escapes */
987*324bb76bSAndroid Build Coastguard Worker 		{
988*324bb76bSAndroid Build Coastguard Worker 			switch (*++cp) {
989*324bb76bSAndroid Build Coastguard Worker 			case '\\':
990*324bb76bSAndroid Build Coastguard Worker 				cval = '\\';
991*324bb76bSAndroid Build Coastguard Worker 				break;
992*324bb76bSAndroid Build Coastguard Worker 			case 'n':
993*324bb76bSAndroid Build Coastguard Worker 				cval = '\n';
994*324bb76bSAndroid Build Coastguard Worker 				break;
995*324bb76bSAndroid Build Coastguard Worker 			case 't':
996*324bb76bSAndroid Build Coastguard Worker 				cval = '\t';
997*324bb76bSAndroid Build Coastguard Worker 				break;
998*324bb76bSAndroid Build Coastguard Worker 			case 'b':
999*324bb76bSAndroid Build Coastguard Worker 				cval = '\b';
1000*324bb76bSAndroid Build Coastguard Worker 				break;
1001*324bb76bSAndroid Build Coastguard Worker 			case 'r':
1002*324bb76bSAndroid Build Coastguard Worker 				cval = '\r';
1003*324bb76bSAndroid Build Coastguard Worker 				break;
1004*324bb76bSAndroid Build Coastguard Worker 			default:
1005*324bb76bSAndroid Build Coastguard Worker 				cval = *cp;
1006*324bb76bSAndroid Build Coastguard Worker 			}
1007*324bb76bSAndroid Build Coastguard Worker 			cp++;
1008*324bb76bSAndroid Build Coastguard Worker 		} else if (*cp == '^') /* expand control-character syntax */
1009*324bb76bSAndroid Build Coastguard Worker 		{
1010*324bb76bSAndroid Build Coastguard Worker 			cval = (*++cp & 0x1f);
1011*324bb76bSAndroid Build Coastguard Worker 			cp++;
1012*324bb76bSAndroid Build Coastguard Worker 		} else {
1013*324bb76bSAndroid Build Coastguard Worker 			cval = *cp++;
1014*324bb76bSAndroid Build Coastguard Worker 		}
1015*324bb76bSAndroid Build Coastguard Worker 		*tp++ = cval;
1016*324bb76bSAndroid Build Coastguard Worker 	}
1017*324bb76bSAndroid Build Coastguard Worker 
1018*324bb76bSAndroid Build Coastguard Worker 	return (tp - StartAddr);
1019*324bb76bSAndroid Build Coastguard Worker }
1020*324bb76bSAndroid Build Coastguard Worker 
1021*324bb76bSAndroid Build Coastguard Worker /* end */
1022