1 /*****************************************************************************
3 gifbuild - dump GIF data in a textual format, or undump it to a GIF
5 SPDX-License-Identifier: MIT
7 *****************************************************************************/
19 #define PROGRAM_NAME "gifbuild"
21 __attribute__((__section__(".tizen.build-id")))
27 __DATE__ ", " __TIME__ "\n"
28 "(C) Copyright 1992 Eric Raymond.\n";
32 " v%- d%- t%-Characters!s h%- GifFile(s)!*s";
34 static char KeyLetters[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:<=>?@[\\]^_`{|}~";
35 #define PRINTABLES (sizeof(KeyLetters) - 1)
37 static void Icon2Gif(char *FileName, FILE *txtin, int fdout);
38 static void Gif2Icon(char *FileName,
41 static int EscapeString(char *cp, char *tp);
43 /******************************************************************************
45 ******************************************************************************/
46 int main(int argc, char **argv)
49 bool Error, DisasmFlag = false, HelpFlag = false, TextLineFlag = false;
50 char **FileNames = NULL;
53 if ((Error = GAGetArgs(argc, argv, CtrlStr,
54 &GifNoisyPrint, &DisasmFlag, &TextLineFlag, &TextLines[0],
55 &HelpFlag, &NumFiles, &FileNames)) != false) {
57 GAPrintHowTo(CtrlStr);
62 (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
63 GAPrintHowTo(CtrlStr);
67 if (!DisasmFlag && NumFiles > 1) {
68 GIF_MESSAGE("Error in command line parsing - one text input please.");
69 GAPrintHowTo(CtrlStr);
73 if (!DisasmFlag && TextLineFlag) {
74 GIF_MESSAGE("Error in command line parsing - -t invalid without -d.");
75 GAPrintHowTo(CtrlStr);
83 Gif2Icon("Stdin", 0, 1, TextLineFlag ? TextLines[0] : KeyLetters);
85 Icon2Gif("Stdin", stdin, 1);
90 for (i = 0; i < NumFiles; i++)
94 if ((fp = fopen(FileNames[i], "r")) == (FILE *)NULL)
96 (void) fprintf(stderr, "Can't open %s\n", FileNames[i]);
102 printf("#\n# GIF information from %s\n", FileNames[i]);
103 Gif2Icon(FileNames[i], -1, 1, TextLineFlag ? TextLines[0] : KeyLetters);
107 Icon2Gif(FileNames[i], fp, 1);
117 /******************************************************************************
118 Parse image directives
119 ******************************************************************************/
120 #define PARSE_ERROR(str) (void) fprintf(stderr,"%s:%d: %s\n",FileName,LineNum,str);
122 static void Icon2Gif(char *FileName, FILE *txtin, int fdout)
124 unsigned int ColorMapSize = 0;
125 GifColorType GlobalColorMap[256], LocalColorMap[256],
126 *ColorMap = GlobalColorMap;
127 char GlobalColorKeys[PRINTABLES], LocalColorKeys[PRINTABLES],
128 *KeyTable = GlobalColorKeys;
129 bool SortFlag = false;
130 unsigned int ExtCode, intval;
131 int red, green, blue, n;
132 char buf[BUFSIZ * 2], InclusionFile[64];
133 GifFileType *GifFileOut;
134 SavedImage *NewImage = NULL;
135 int LeadingExtensionBlockCount = 0;
136 ExtensionBlock *LeadingExtensionBlocks = NULL;
137 int ErrorCode, LineNum = 0;
139 if ((GifFileOut = EGifOpenFileHandle(fdout, &ErrorCode)) == NULL) {
140 PrintGifError(ErrorCode);
144 /* OK, interpret directives */
145 /* coverity[tainted_data_transitive] */
146 while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
153 * Skip lines consisting only of whitespace and comments
155 for (cp = buf; isspace((int)(*cp)); cp++)
157 if (*cp == '#' || *cp == '\0')
161 * If there's a trailing comment, nuke it and all preceding whitespace.
162 * But preserve the EOL.
164 if ((cp = strchr(buf, '#')) && (cp == strrchr(cp, '#')))
166 while (isspace((int)(*--cp)))
173 * Explicit header declarations
176 if (sscanf(buf, "screen width %d\n", &GifFileOut->SWidth) == 1)
179 else if (sscanf(buf, "screen height %d\n", &GifFileOut->SHeight) == 1)
182 else if (sscanf(buf, "screen colors %d\n", &n) == 1)
184 int ResBits = GifBitSize(n);
186 if (n > 256 || n < 0 || n != (1 << ResBits))
188 PARSE_ERROR("Invalid color resolution value.");
192 GifFileOut->SColorResolution = ResBits;
197 "screen background %d\n",
198 &GifFileOut->SBackGroundColor) == 1)
201 else if (sscanf(buf, "pixel aspect byte %u\n", &intval) == 1) {
202 GifFileOut->AspectByte = (GifByteType)(intval & 0xff);
207 * Color table parsing
210 else if (strcmp(buf, "screen map\n") == 0)
212 if (GifFileOut->SColorMap != NULL)
214 PARSE_ERROR("You've already declared a global color map.");
219 ColorMap = GlobalColorMap;
221 KeyTable = GlobalColorKeys;
222 memset(GlobalColorKeys, '\0', sizeof(GlobalColorKeys));
225 else if (strcmp(buf, "image map\n") == 0)
227 if (NewImage == NULL)
229 PARSE_ERROR("No previous image declaration.");
234 ColorMap = LocalColorMap;
235 KeyTable = LocalColorKeys;
236 memset(LocalColorKeys, '\0', sizeof(LocalColorKeys));
239 else if (sscanf(buf, " rgb %d %d %d is %c",
240 &red, &green, &blue, &KeyTable[ColorMapSize]) == 4)
242 ColorMap[ColorMapSize].Red = red;
243 ColorMap[ColorMapSize].Green = green;
244 ColorMap[ColorMapSize].Blue = blue;
248 else if (sscanf(buf, " rgb %d %d %d", &red, &green, &blue) == 3)
250 ColorMap[ColorMapSize].Red = red;
251 ColorMap[ColorMapSize].Green = green;
252 ColorMap[ColorMapSize].Blue = blue;
256 else if (strcmp(buf, " sort flag on\n") == 0)
259 else if (strcmp(buf, " sort flag off\n") == 0)
262 else if (strcmp(buf, "end\n") == 0)
264 ColorMapObject *NewMap;
266 NewMap = GifMakeMapObject(1 << GifBitSize(ColorMapSize), ColorMap);
267 if (NewMap == (ColorMapObject *)NULL)
269 PARSE_ERROR("Out of memory while allocating new color map.");
273 NewMap->SortFlag = SortFlag;
276 NewImage->ImageDesc.ColorMap = NewMap;
278 GifFileOut->SColorMap = NewMap;
282 /* ugly magic number is because scanf has no */
283 else if (sscanf(buf, "include %63s", InclusionFile) == 1)
287 GifPixelType Translation[256];
289 GifFileType *Inclusion;
290 SavedImage *CopyFrom;
292 if ((Inclusion = DGifOpenFileName(InclusionFile, &ErrorCode)) == NULL) {
293 PrintGifError(ErrorCode);
297 if (DGifSlurp(Inclusion) == GIF_ERROR)
299 PARSE_ERROR("Inclusion read failed.");
300 if (Inclusion != NULL) {
301 PrintGifError(Inclusion->Error);
302 DGifCloseFile(Inclusion, NULL);
304 if (GifFileOut != NULL) {
305 EGifCloseFile(GifFileOut, NULL);
310 //cppcheck-suppress nullPointerRedundantCheck
311 if ((DoTranslation = (GifFileOut->SColorMap!=(ColorMapObject*)NULL)))
313 ColorMapObject *UnionMap;
315 //cppcheck-suppress nullPointerRedundantCheck
316 UnionMap = GifUnionColorMap(GifFileOut->SColorMap, Inclusion->SColorMap, Translation);
318 if (UnionMap == NULL)
320 PARSE_ERROR("Inclusion failed --- global map conflict.");
321 //cppcheck-suppress nullPointerRedundantCheck
322 PrintGifError(GifFileOut->Error);
323 if (Inclusion != NULL) DGifCloseFile(Inclusion, NULL);
324 if (GifFileOut != NULL) EGifCloseFile(GifFileOut, NULL);
328 GifFreeMapObject(GifFileOut->SColorMap);
329 GifFileOut->SColorMap = UnionMap;
332 //cppcheck-suppress nullPointerRedundantCheck
333 for (CopyFrom = Inclusion->SavedImages;
334 //cppcheck-suppress nullPointerRedundantCheck
335 CopyFrom < Inclusion->SavedImages + Inclusion->ImageCount;
338 SavedImage *NewImage;
339 if ((NewImage = GifMakeSavedImage(GifFileOut, CopyFrom)) == NULL)
341 PARSE_ERROR("Inclusion failed --- out of memory.");
342 //cppcheck-suppress nullPointerRedundantCheck
343 PrintGifError(GifFileOut->Error);
344 if (Inclusion != NULL) DGifCloseFile(Inclusion, NULL);
345 if (GifFileOut != NULL) EGifCloseFile(GifFileOut, NULL);
348 else if (DoTranslation)
349 GifApplyTranslation(NewImage, Translation);
352 "%s: Image %d at (%d, %d) [%dx%d]: from %s\n",
353 PROGRAM_NAME, GifFileOut->ImageCount,
354 NewImage->ImageDesc.Left, NewImage->ImageDesc.Top,
355 NewImage->ImageDesc.Width, NewImage->ImageDesc.Height,
359 (void) DGifCloseFile(Inclusion, NULL);
365 else if (strcmp(buf, "comment\n") == 0)
368 while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
369 if (strcmp(buf, "end\n") == 0)
375 buf[strlen(buf) - 1] = '\0';
376 Len = EscapeString(buf, buf);
377 if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
378 &LeadingExtensionBlocks,
379 bc++ == CONTINUE_EXT_FUNC_CODE ? COMMENT_EXT_FUNC_CODE : 0,
381 (unsigned char *)buf) == GIF_ERROR) {
382 PARSE_ERROR("out of memory while adding comment block.");
387 else if (strcmp(buf, "plaintext\n") == 0)
390 while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
391 if (strcmp(buf, "end\n") == 0)
397 buf[strlen(buf) - 1] = '\0';
398 Len = EscapeString(buf, buf);
399 if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
400 &LeadingExtensionBlocks,
401 bc++ == CONTINUE_EXT_FUNC_CODE ? PLAINTEXT_EXT_FUNC_CODE : 0,
403 (unsigned char *)buf) == GIF_ERROR) {
404 PARSE_ERROR("out of memory while adding plaintext block.");
409 else if (strcmp(buf, "graphics control\n") == 0)
411 GraphicsControlBlock gcb;
414 memset(&gcb, '\0', sizeof(gcb));
415 gcb.TransparentColor = NO_TRANSPARENT_COLOR;
416 while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
417 if (strcmp(buf, "end\n") == 0)
425 if (sscanf(tp, "disposal mode %d\n", &gcb.DisposalMode))
427 if (strcmp(tp, "user input flag on\n") == 0) {
428 gcb.UserInputFlag = true;
431 if (strcmp(tp, "user input flag off\n") == 0) {
432 gcb.UserInputFlag = false;
435 if (sscanf(tp, "delay %d\n", &gcb.DelayTime))
437 if (sscanf(tp, "transparent index %d\n",
438 &gcb.TransparentColor))
440 (void) fputs(tp, stderr);
441 PARSE_ERROR("unrecognized directive in GCB block.");
444 Len = EGifGCBToExtension(&gcb, (GifByteType *)buf);
445 if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
446 &LeadingExtensionBlocks,
447 GRAPHICS_EXT_FUNC_CODE,
449 (unsigned char *)buf) == GIF_ERROR) {
450 PARSE_ERROR("out of memory while adding GCB.");
455 else if (sscanf(buf, "netscape loop %u", &intval))
457 unsigned char params[3] = {1, 0, 0};
458 /* Create a Netscape 2.0 loop block */
459 if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
460 &LeadingExtensionBlocks,
461 APPLICATION_EXT_FUNC_CODE,
463 (unsigned char *)"NETSCAPE2.0")==GIF_ERROR) {
464 PARSE_ERROR("out of memory while adding loop block.");
467 params[1] = (intval & 0xff);
468 params[2] = (intval >> 8) & 0xff;
469 if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
470 &LeadingExtensionBlocks,
471 0, sizeof(params), params) == GIF_ERROR) {
472 PARSE_ERROR("out of memory while adding loop continuation.");
477 else if (sscanf(buf, "extension %x", &ExtCode))
480 while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
481 if (strcmp(buf, "end\n") == 0)
487 buf[strlen(buf) - 1] = '\0';
488 Len = EscapeString(buf, buf);
489 if (GifAddExtensionBlock(&LeadingExtensionBlockCount,
490 &LeadingExtensionBlocks,
491 bc++ == CONTINUE_EXT_FUNC_CODE ? ExtCode : 0,
493 (unsigned char *)buf) == GIF_ERROR) {
494 PARSE_ERROR("out of memory while adding extension block.");
501 * Explicit image declarations
504 else if (strcmp(buf, "image\n") == 0)
506 if ((NewImage = GifMakeSavedImage(GifFileOut, NULL)) == (SavedImage *)NULL)
508 PARSE_ERROR("Out of memory while allocating image block.");
512 /* use global table unless user specifies a local one */
513 ColorMap = GlobalColorMap;
514 KeyTable = GlobalColorKeys;
516 /* connect leading extension blocks */
517 NewImage->ExtensionBlockCount = LeadingExtensionBlockCount;
518 NewImage->ExtensionBlocks = LeadingExtensionBlocks;
519 LeadingExtensionBlockCount = 0;
520 LeadingExtensionBlocks = NULL;
524 * Nothing past this point is valid unless we've seen a previous
527 else if (NewImage == (SavedImage *)NULL)
529 (void) fputs(buf, stderr);
530 PARSE_ERROR("Syntax error in header block.");
535 * Accept image attributes
537 else if (sscanf(buf, "image top %d\n", &NewImage->ImageDesc.Top) == 1)
540 else if (sscanf(buf, "image left %d\n", &NewImage->ImageDesc.Left)== 1)
543 else if (strcmp(buf, "image interlaced\n") == 0)
545 NewImage->ImageDesc.Interlace = true;
550 "image bits %d by %d",
551 &NewImage->ImageDesc.Width,
552 &NewImage->ImageDesc.Height) == 2)
555 static GifPixelType *Raster, *cp;
557 bool hex = (strstr(buf, "hex") != NULL);
559 /* coverity[overflow_sink] */
560 if ((Raster = (GifPixelType *) malloc(sizeof(GifPixelType) * NewImage->ImageDesc.Width * NewImage->ImageDesc.Height))
562 PARSE_ERROR("Failed to allocate raster block, aborted.");
566 GifQprintf("%s: Image %d at (%d, %d) [%dx%d]: ",
567 PROGRAM_NAME, GifFileOut->ImageCount,
568 NewImage->ImageDesc.Left, NewImage->ImageDesc.Top,
569 NewImage->ImageDesc.Width, NewImage->ImageDesc.Height);
572 for (i = 0; i < NewImage->ImageDesc.Height; i++) {
576 for (j = 0; j < NewImage->ImageDesc.Width; j++)
577 if ((c = fgetc(txtin)) == EOF) {
578 PARSE_ERROR("input file ended prematurely.");
590 const static char *hexdigits = "0123456789ABCDEF";
591 unsigned char hi, lo;
592 dp = strchr(hexdigits, toupper(c));
594 PARSE_ERROR("Invalid hex high byte.");
597 hi = (dp - hexdigits);
598 if ((c = fgetc(txtin)) == EOF) {
599 PARSE_ERROR("input file ended prematurely.");
602 dp = strchr(hexdigits, toupper(c));
604 PARSE_ERROR("Invalid hex low byte.");
607 lo = (dp - hexdigits);
608 *cp++ = (hi << 4) | lo;
610 else if ((dp = strchr(KeyTable, c)))
611 *cp++ = (dp - KeyTable);
613 PARSE_ERROR("Invalid ASCII pixel key.");
618 fprintf(stderr, "\b\b\b\b%-4d", i);
624 NewImage->RasterBits = (unsigned char *) Raster;
628 (void) fputs(buf, stderr);
629 PARSE_ERROR("Syntax error in image description.");
634 /* connect trailing extension blocks */
635 GifFileOut->ExtensionBlockCount = LeadingExtensionBlockCount;
636 GifFileOut->ExtensionBlocks = LeadingExtensionBlocks;
637 //LeadingExtensionBlockCount = 0;
638 LeadingExtensionBlocks = NULL;
640 EGifSpew(GifFileOut);
643 static void VisibleDumpBuffer(GifByteType *buf, int len)
644 /* Visibilize a given string */
648 for (cp = buf; cp < buf + len; cp++)
650 if (isprint((int)(*cp)) || *cp == ' ')
652 else if (*cp == '\n')
654 putchar('\\'); putchar('n');
656 else if (*cp == '\r')
658 putchar('\\'); putchar('r');
660 else if (*cp == '\b')
662 putchar('\\'); putchar('b');
666 putchar('\\'); putchar('^'); putchar('@' + *cp);
669 printf("\\0x%02x", *cp);
673 static void DumpExtensions(GifFileType *GifFileOut,
674 int ExtensionBlockCount,
675 ExtensionBlock *ExtensionBlocks)
679 for (ep = ExtensionBlocks;
680 ep < ExtensionBlocks + ExtensionBlockCount;
682 bool last = (ep - ExtensionBlocks == (ExtensionBlockCount - 1));
683 if (ep->Function == COMMENT_EXT_FUNC_CODE) {
685 VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
687 while (!last && ep[1].Function == CONTINUE_EXT_FUNC_CODE) {
689 last = (ep - ExtensionBlocks == (ExtensionBlockCount - 1));
690 VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
695 else if (ep->Function == PLAINTEXT_EXT_FUNC_CODE) {
696 printf("plaintext\n");
697 VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
699 while (!last && ep[1].Function == CONTINUE_EXT_FUNC_CODE) {
701 last = (ep - ExtensionBlocks == (ExtensionBlockCount - 1));
702 VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
707 else if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
709 GraphicsControlBlock gcb;
710 printf("graphics control\n");
711 if (DGifExtensionToGCB(ep->ByteCount, ep->Bytes, &gcb) == GIF_ERROR) {
712 GIF_MESSAGE("invalid graphics control block");
715 printf("\tdisposal mode %d\n", gcb.DisposalMode);
716 printf("\tuser input flag %s\n",
717 gcb.UserInputFlag ? "on" : "off");
718 printf("\tdelay %d\n", gcb.DelayTime);
719 printf("\ttransparent index %d\n", gcb.TransparentColor);
723 && ep->Function == APPLICATION_EXT_FUNC_CODE
724 && ep->ByteCount >= 11
725 && (ep+1)->ByteCount >= 3
726 && memcmp(ep->Bytes, "NETSCAPE2.0", 11) == 0) {
727 unsigned char *params = (++ep)->Bytes;
728 unsigned int loopcount = params[1] | (params[2] << 8);
729 printf("netscape loop %u\n\n", loopcount);
732 printf("extension 0x%02x\n", ep->Function);
733 VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
734 while (!last && ep[1].Function == CONTINUE_EXT_FUNC_CODE) {
736 last = (ep - ExtensionBlocks == (ExtensionBlockCount - 1));
737 VisibleDumpBuffer(ep->Bytes, ep->ByteCount);
745 static void Gif2Icon(char *FileName,
749 int ErrorCode, im, i, j, ColorCount = 0;
750 GifFileType *GifFile;
753 if ((GifFile = DGifOpenFileName(FileName, &ErrorCode)) == NULL) {
754 PrintGifError(ErrorCode);
759 /* Use stdin instead: */
760 if ((GifFile = DGifOpenFileHandle(fdin, &ErrorCode)) == NULL) {
761 PrintGifError(ErrorCode);
766 if (DGifSlurp(GifFile) == GIF_ERROR) {
767 PrintGifError(GifFile->Error);
771 printf("screen width %d\nscreen height %d\n",
772 GifFile->SWidth, GifFile->SHeight);
774 printf("screen colors %d\nscreen background %d\npixel aspect byte %u\n\n",
775 1 << GifFile->SColorResolution,
776 GifFile->SBackGroundColor,
777 (unsigned)GifFile->AspectByte);
779 if (GifFile->SColorMap)
781 printf("screen map\n");
783 printf("\tsort flag %s\n", GifFile->SColorMap->SortFlag ? "on" : "off");
785 for (i = 0; i < GifFile->SColorMap->ColorCount; i++)
786 if (GifFile->SColorMap->ColorCount < PRINTABLES)
787 printf("\trgb %03d %03d %03d is %c\n",
788 GifFile->SColorMap ->Colors[i].Red,
789 GifFile->SColorMap ->Colors[i].Green,
790 GifFile->SColorMap ->Colors[i].Blue,
793 printf("\trgb %03d %03d %03d\n",
794 GifFile->SColorMap ->Colors[i].Red,
795 GifFile->SColorMap ->Colors[i].Green,
796 GifFile->SColorMap ->Colors[i].Blue);
800 for (im = 0; im < GifFile->ImageCount; im++) {
801 SavedImage *image = &GifFile->SavedImages[im];
803 DumpExtensions(GifFile,
804 image->ExtensionBlockCount, image->ExtensionBlocks);
806 printf("image # %d\nimage left %d\nimage top %d\n",
807 im+1, image->ImageDesc.Left, image->ImageDesc.Top);
808 if (image->ImageDesc.Interlace)
809 printf("image interlaced\n");
811 if (image->ImageDesc.ColorMap)
813 printf("image map\n");
815 printf("\tsort flag %s\n",
816 image->ImageDesc.ColorMap->SortFlag ? "on" : "off");
818 if (image->ImageDesc.ColorMap->ColorCount < PRINTABLES)
819 for (i = 0; i < image->ImageDesc.ColorMap->ColorCount; i++)
820 printf("\trgb %03d %03d %03d is %c\n",
821 image->ImageDesc.ColorMap ->Colors[i].Red,
822 image->ImageDesc.ColorMap ->Colors[i].Green,
823 image->ImageDesc.ColorMap ->Colors[i].Blue,
826 for (i = 0; i < image->ImageDesc.ColorMap->ColorCount; i++)
827 printf("\trgb %03d %03d %03d\n",
828 image->ImageDesc.ColorMap ->Colors[i].Red,
829 image->ImageDesc.ColorMap ->Colors[i].Green,
830 image->ImageDesc.ColorMap ->Colors[i].Blue);
834 /* one of these conditions has to be true */
835 if (image->ImageDesc.ColorMap)
836 ColorCount = image->ImageDesc.ColorMap->ColorCount;
837 else if (GifFile->SColorMap)
838 ColorCount = GifFile->SColorMap->ColorCount;
840 if (ColorCount < PRINTABLES)
841 printf("image bits %d by %d\n",
842 image->ImageDesc.Width, image->ImageDesc.Height);
844 printf("image bits %d by %d hex\n",
845 image->ImageDesc.Width, image->ImageDesc.Height);
846 for (i = 0; i < image->ImageDesc.Height; i++) {
847 for (j = 0; j < image->ImageDesc.Width; j++) {
848 GifByteType ch = image->RasterBits[i*image->ImageDesc.Width + j];
849 if (ColorCount < PRINTABLES && ch < PRINTABLES)
850 putchar(NameTable[ch]);
859 DumpExtensions(GifFile,
860 GifFile->ExtensionBlockCount, GifFile->ExtensionBlocks);
862 /* Tell EMACS this is a picture... */
863 printf("# The following sets edit modes for GNU EMACS\n");
864 printf("# Local "); /* ...break this up, so that EMACS doesn't */
865 printf("Variables:\n"); /* get confused when visiting *this* file! */
866 printf("# mode:picture\n");
867 printf("# truncate-lines:t\n");
871 (void) printf("# End of %s dump\n", FileName);
878 /* check that the background color isn't garbage (SF bug #87) */
879 if (GifFile->SBackGroundColor < 0
880 || (GifFile->SColorMap && GifFile->SBackGroundColor >= GifFile->SColorMap->ColorCount)) {
881 fprintf(stderr, "gifbuild: background color invalid for screen colormap.\n");
884 if (DGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) {
885 PrintGifError(ErrorCode);
890 static int EscapeString(char *cp, char *tp)
891 /* process standard C-style escape sequences in a string */
893 char *StartAddr = tp;
899 if (*cp == '\\' && strchr("0123456789xX", cp[1]))
903 if (*++cp == 'x' || *cp == 'X') {
904 char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
905 for (++cp; (dp = strchr(hex, *cp)) && (dcount++ < 2); cp++)
906 cval = (cval * 16) + (dp - hex) / 2;
907 } else if (*cp == '0')
908 while (strchr("01234567",*cp) != (char*)NULL && (dcount++ < 3))
909 cval = (cval * 8) + (*cp++ - '0');
911 while ((strchr("0123456789",*cp)!=(char*)NULL)&&(dcount++ < 3))
912 cval = (cval * 10) + (*cp++ - '0');
914 else if (*cp == '\\') /* C-style character escapes */
918 case '\\': cval = '\\'; break;
919 case 'n': cval = '\n'; break;
920 case 't': cval = '\t'; break;
921 case 'b': cval = '\b'; break;
922 case 'r': cval = '\r'; break;
927 else if (*cp == '^') /* expand control-character syntax */
929 cval = (*++cp & 0x1f);
937 return(tp - StartAddr);