コード例 #1
0
static
void
showstats(void)
{
    fputs("memory allocation tracing statistics\n", stdout);
    fputs("------------------------------------\n", stdout);
    fprintf(stdout, "allocated: %lu (", stats.acount);
    printsize(stats.atotal);
    fprintf(stdout, ")\nfreed:     %lu (", stats.fcount);
    printsize(stats.ftotal);
    fprintf(stdout, ")\nunfreed:   %lu (", stats.acount - stats.fcount);
    printsize(stats.atotal - stats.ftotal);
    fprintf(stdout, ")\npeak:      %lu (", stats.pcount);
    printsize(stats.ptotal);
    fprintf(stdout, ")\nreserved:  %lu (", stats.rcount);
    printsize(stats.rtotal);
    fprintf(stdout, ")\ninternal:  %lu (", stats.icount);
    printsize(stats.itotal);
    fprintf(stdout, ")\ntotal:     %lu (", stats.rcount + stats.icount);
    printsize(stats.rtotal + stats.itotal);
    fputs(")\n\n", stdout);
    fputs("smallest size: ", stdout);
    printsize(stats.lsize);
    fputs("\nlargest size:  ", stdout);
    printsize(stats.usize);
    fputs("\naverage size:  ", stdout);
    printsize(rounddivide(stats.atotal, stats.acount));
    fputc('\n', stdout);
}
コード例 #2
0
ファイル: lib.c プロジェクト: bobsummerwill/VICE
void lib_debug_check(void)
{
#ifdef LIB_DEBUG
    unsigned int index, count;
    unsigned int leakbytes;

    count = 0;
    leakbytes = 0;

    for (index = 0; index < LIB_DEBUG_SIZE; index++) {
        if (lib_debug_address[index] != NULL) {
            count++;
#ifdef LIB_DEBUG_PINPOINT
            printf("%s:%d: ", lib_debug_filename[index], lib_debug_line[index]);
#endif
            printf("Warning: Memory block allocated here was not free'd (Memory leak with size 0x%x at %p).",
                   lib_debug_size[index], lib_debug_address[index]);
#ifdef LIB_DEBUG_CALLER
            printf("(called from %p)", lib_debug_caller[index]);
#endif
            printf("\n");
            leakbytes += lib_debug_size[index];
#if LIB_DEBUG_GUARD > 0
            lib_debug_guard_remove((char *)lib_debug_address[index]);
#endif
        }
    }
    printf("Total memory leaks: %d Bytes leaked: 0x%x\n", count, leakbytes);
    printf("max. total memory that was allocated: 0x%x bytes. (", lib_debug_max_total);
    printsize(lib_debug_max_total);
    printf(")\n");

#ifdef LIB_DEBUG_PINPOINT
    printf("\nTop %d largest allocated blocks:\n", LIB_DEBUG_TOPMAX);
    for (index = 0; index < LIB_DEBUG_TOPMAX; index++) {
        if (lib_debug_top_size[index]) {
            printf("%8x bytes (", lib_debug_top_size[index]);
            printsize(lib_debug_top_size[index]);
            printf(") allocated at %s:%d\n", lib_debug_top_filename[index], lib_debug_top_line[index]);
        }
    }
#endif

#endif
}
コード例 #3
0
ファイル: df.c プロジェクト: 00zhengfu00/platform_system_core
static void df(char *s, int always) {
    struct statfs st;

    if (statfs(s, &st) < 0) {
        fprintf(stderr, "%s: %s\n", s, strerror(errno));
        ok = EXIT_FAILURE;
    } else {
        if (st.f_blocks == 0 && !always)
            return;        
        printf("%-20s  ", s);
        printsize((long long)st.f_blocks * (long long)st.f_bsize);
        printf("  ");
        printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize);
        printf("  ");
        printsize((long long)st.f_bfree * (long long)st.f_bsize);
        printf("   %d\n", (int) st.f_bsize);
    }
}
コード例 #4
0
ファイル: print.c プロジェクト: Kaikaiw/apue
void
plong(FTSENT *p)
{
    char tmp[NAME_BUFSZ];
    FTSENT_PRT *prt=(FTSENT_PRT*)p->fts_pointer;
    int length=prt->s_name;
    if (f_inodenum)
        printf("%*lld ", prt->s_inode, 
               (LL)p->fts_statp->st_ino);
    if (f_dispblock) {
        LL b=p->fts_statp->st_blocks;
        b/=block_size_factor;
        printf("%*lld ", prt->s_block, b);
    }
    printmodestr(p);
    printf("%*hd ", prt->s_link, (short)p->fts_statp->st_nlink);
    if (f_numric) {
        printf("%*d  ", prt->s_uid, (int)p->fts_statp->st_uid);
        printf("%*d  ", prt->s_gid, (int)p->fts_statp->st_gid);
    }
    else {
        if (printuname(p, prt->s_uname)==-1)
            printf("%*d  ", prt->s_uid, (int)p->fts_statp->st_uid);
        if (printgname(p, prt->s_gname)==-1)
            printf("%*d  ", prt->s_gid, (int)p->fts_statp->st_gid);
    }
    printsize(p);
    if (f_sortbyacc)
        printtime(p->fts_statp->st_atime);
    else if (f_sortbychg)
        printtime(p->fts_statp->st_ctime);
    else
        printtime(p->fts_statp->st_mtime);
    if (f_displgd) {
        sprintf(tmp, "%s%c", p->fts_name, type(p));
        length++;
    }
    else
        sprintf(tmp, "%s", p->fts_name);
    printstr(tmp, length);
    if (S_ISLNK(p->fts_statp->st_mode)) {
        int l;
        char buf[NAME_BUFSZ], path[NAME_BUFSZ];
        if (p->fts_level==0)
            sprintf(path, "%s", p->fts_name);
        else
            sprintf(path, "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
        if ((l=readlink(path, buf, sizeof(path)))==-1)
            warn("%s", p->fts_path);
        buf[l]='\0';
        printf(" -> ");
        printstr(buf, prt->s_name);
    }
}
コード例 #5
0
ファイル: print.c プロジェクト: a565109863/src
void
printlong(DISPLAY *dp)
{
	struct stat *sp;
	FTSENT *p;
	NAMES *np;
	char buf[20];

	if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
		(void)printf("total %llu\n", howmany(dp->btotal, blocksize));

	for (p = dp->list; p; p = p->fts_link) {
		if (IS_NOPRINT(p))
			continue;
		sp = p->fts_statp;
		if (f_inode)
			(void)printf("%*llu ", dp->s_inode,
			    (unsigned long long)sp->st_ino);
		if (f_size)
			(void)printf("%*lld ", dp->s_block,
			    howmany((long long)sp->st_blocks, blocksize));
		(void)strmode(sp->st_mode, buf);
		np = p->fts_pointer;
		(void)printf("%s %*u ", buf, dp->s_nlink, sp->st_nlink);
		if (!f_grouponly)
			(void)printf("%-*s  ", dp->s_user, np->user);
		(void)printf("%-*s  ", dp->s_group, np->group);
		if (f_flags)
			(void)printf("%-*s ", dp->s_flags, np->flags);
		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
			(void)printf("%3d, %3d ",
			    major(sp->st_rdev), minor(sp->st_rdev));
		else if (dp->bcfile)
			(void)printf("%*s%*lld ",
			    8 - dp->s_size, "", dp->s_size,
			    (long long)sp->st_size);
		else
			printsize(dp->s_size, sp->st_size);
		if (f_accesstime)
			printtime(sp->st_atime);
		else if (f_statustime)
			printtime(sp->st_ctime);
		else
			printtime(sp->st_mtime);
		(void)mbsprint(p->fts_name, 1);
		if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
			(void)printtype(sp->st_mode);
		if (S_ISLNK(sp->st_mode))
			printlink(p);
		(void)putchar('\n');
	}
}
コード例 #6
0
void do_directory(const u8* base, u32 offset, u32 size,
		  const char* path, const char* name, int mode)
{
   printsize(size, size);
   printf("%s", name);
   
   // Check if we are actually unpacking
   if (path[0]=='-') {
      return;
   }

   // Make the local directory
   if (mkdir(path, mode) == -1) {
      perror(path);
      return;
   }
}
コード例 #7
0
ファイル: uncramfs.c プロジェクト: OliverGesch/epk2extract
void do_symlink(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) {
	// Allocate the uncompressed string
	u8 link_contents[size + 1];

	// do uncompression
	uncompress_data(base, base + offset, size, link_contents);
	link_contents[size] = 0;

	printsize(size, compressed_size(base, base + offset, size));
	printf("%s -> %s", name, link_contents);

	// Check if we are actually unpacking
	if (path[0] == '-') {
		return;
	}
	// Make local copy
	if (symlink((const char *)link_contents, path) == -1) {
		perror(path);
		exit(1);
	}
}
コード例 #8
0
ファイル: print.c プロジェクト: denir-li/freebsd
void
printlong(const DISPLAY *dp)
{
	struct stat *sp;
	FTSENT *p;
	NAMES *np;
	char buf[20];
#ifdef COLORLS
	int color_printed = 0;
#endif

	if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
	    (f_longform || f_size)) {
		xo_emit("{L:total} {:total-blocks/%lu}\n",
			howmany(dp->btotal, blocksize));
	}

	xo_open_list("entry");
	for (p = dp->list; p; p = p->fts_link) {
		char *name, *type;
		if (IS_NOPRINT(p))
			continue;
		xo_open_instance("entry");
		sp = p->fts_statp;
		name = getname(p->fts_name);
		if (name)
		    xo_emit("{ke:name/%hs}", name);
		if (f_inode)
			xo_emit("{t:inode/%*ju} ",
			    dp->s_inode, (uintmax_t)sp->st_ino);
		if (f_size)
			xo_emit("{t:blocks/%*jd} ",
			    dp->s_block, howmany(sp->st_blocks, blocksize));
		strmode(sp->st_mode, buf);
		aclmode(buf, p);
		np = p->fts_pointer;
		xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS);
		if (f_numericonly) {
			xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {td:user/%-*s}{e:user/%ju}  {td:group/%-*s}{e:group/%ju}  ",
				buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink,
				dp->s_user, np->user, sp->st_uid, dp->s_group, np->group, sp->st_gid);
		} else {
			xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {t:user/%-*s}  {t:group/%-*s}  ",
				buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink,
				dp->s_user, np->user, dp->s_group, np->group);
		}
		if (S_ISBLK(sp->st_mode))
			asprintf(&type, "block");
		if (S_ISCHR(sp->st_mode))
			asprintf(&type, "character");
		if (S_ISDIR(sp->st_mode))
			asprintf(&type, "directory");
		if (S_ISFIFO(sp->st_mode))
			asprintf(&type, "fifo");
		if (S_ISLNK(sp->st_mode))
			asprintf(&type, "symlink");
		if (S_ISREG(sp->st_mode))
			asprintf(&type, "regular");
		if (S_ISSOCK(sp->st_mode))
			asprintf(&type, "socket");
		if (S_ISWHT(sp->st_mode))
			asprintf(&type, "whiteout");
		xo_emit("{e:type/%s}", type);
		free(type);
		if (f_flags)
			xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags);
		if (f_label)
			xo_emit("{t:label/%-*s} ", dp->s_label, np->label);
		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
			printdev(dp->s_size, sp->st_rdev);
		else
			printsize("size", dp->s_size, sp->st_size);
		if (f_accesstime)
			printtime("access-time", sp->st_atime);
		else if (f_birthtime)
			printtime("birth-time", sp->st_birthtime);
		else if (f_statustime)
			printtime("change-time", sp->st_ctime);
		else
			printtime("modify-time", sp->st_mtime);
#ifdef COLORLS
		if (f_color)
			color_printed = colortype(sp->st_mode);
#endif

		if (name) {
		    xo_emit("{dk:name/%hs}", name);
		    free(name);
		}
		
#ifdef COLORLS
		if (f_color && color_printed)
			endcolor(0);
#endif
		if (f_type)
			(void)printtype(sp->st_mode);
		if (S_ISLNK(sp->st_mode))
			printlink(p);
		xo_close_instance("entry");
		xo_emit("\n");
	}
	xo_close_list("entry");
}
コード例 #9
0
ファイル: print.c プロジェクト: 2014-class/freerouter
void
printlong(const DISPLAY *dp)
{
	struct stat *sp;
	FTSENT *p;
	NAMES *np;
	char buf[20];
#ifdef COLORLS
	int color_printed = 0;
#endif

	if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
	    (f_longform || f_size)) {
		(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
	}

	for (p = dp->list; p; p = p->fts_link) {
		if (IS_NOPRINT(p))
			continue;
		sp = p->fts_statp;
		if (f_inode)
			(void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino);
		if (f_size)
			(void)printf("%*jd ",
			    dp->s_block, howmany(sp->st_blocks, blocksize));
		strmode(sp->st_mode, buf);
		aclmode(buf, p);
		np = p->fts_pointer;
		(void)printf("%s %*u %-*s  %-*s  ", buf, dp->s_nlink,
		    sp->st_nlink, dp->s_user, np->user, dp->s_group,
		    np->group);
		if (f_flags)
			(void)printf("%-*s ", dp->s_flags, np->flags);
		if (f_label)
			(void)printf("%-*s ", dp->s_label, np->label);
		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
			printdev(dp->s_size, sp->st_rdev);
		else
			printsize(dp->s_size, sp->st_size);
		if (f_accesstime)
			printtime(sp->st_atime);
		else if (f_birthtime)
			printtime(sp->st_birthtime);
		else if (f_statustime)
			printtime(sp->st_ctime);
		else
			printtime(sp->st_mtime);
#ifdef COLORLS
		if (f_color)
			color_printed = colortype(sp->st_mode);
#endif
		(void)printname(p->fts_name);
#ifdef COLORLS
		if (f_color && color_printed)
			endcolor(0);
#endif
		if (f_type)
			(void)printtype(sp->st_mode);
		if (S_ISLNK(sp->st_mode))
			printlink(p);
		(void)putchar('\n');
	}
}
コード例 #10
0
ファイル: mtd_debug.c プロジェクト: WiseMan787/ralink_sdk
int showinfo (int fd)
{
   int i,err,n;
   struct mtd_info_user mtd;
   static struct region_info_user region[1024];

   err = getmeminfo (fd,&mtd);
   if (err < 0)
	 {
		perror ("MEMGETINFO");
		return (1);
	 }

   err = getregions (fd,region,&n);
   if (err < 0)
	 {
		perror ("MEMGETREGIONCOUNT");
		return (1);
	 }

   printf ("mtd.type = ");
   switch (mtd.type)
	 {
	  case MTD_ABSENT:
		printf ("MTD_ABSENT");
		break;
	  case MTD_RAM:
		printf ("MTD_RAM");
		break;
	  case MTD_ROM:
		printf ("MTD_ROM");
		break;
	  case MTD_NORFLASH:
		printf ("MTD_NORFLASH");
		break;
	  case MTD_NANDFLASH:
		printf ("MTD_NANDFLASH");
		break;
	  case MTD_PEROM:
		printf ("MTD_PEROM");
		break;
	  case MTD_OTHER:
		printf ("MTD_OTHER");
		break;
	  case MTD_UNKNOWN:
		printf ("MTD_UNKNOWN");
		break;
	  default:
		printf ("(unknown type - new MTD API maybe?)");
	 }

   printf ("\nmtd.flags = ");
   if (mtd.flags == MTD_CAP_ROM)
	 printf ("MTD_CAP_ROM");
   else if (mtd.flags == MTD_CAP_RAM)
	 printf ("MTD_CAP_RAM");
   else if (mtd.flags == MTD_CAP_NORFLASH)
	 printf ("MTD_CAP_NORFLASH");
   else if (mtd.flags == MTD_CAP_NANDFLASH)
	 printf ("MTD_CAP_NANDFLASH");
   else if (mtd.flags == MTD_WRITEABLE)
	 printf ("MTD_WRITEABLE");
   else
	 {
		int i,first = 1;
		static struct
		  {
			 const char *name;
			 int value;
		  } flags[] =
		  {
			 { "MTD_CLEAR_BITS", MTD_CLEAR_BITS },
			 { "MTD_SET_BITS", MTD_SET_BITS },
			 { "MTD_ERASEABLE", MTD_ERASEABLE },
			 { "MTD_WRITEB_WRITEABLE", MTD_WRITEB_WRITEABLE },
			 { "MTD_VOLATILE", MTD_VOLATILE },
			 { "MTD_XIP", MTD_XIP },
			 { "MTD_OOB", MTD_OOB },
			 { "MTD_ECC", MTD_ECC },
			 { NULL, -1 }
		  };
		for (i = 0; flags[i].name != NULL; i++)
		  if (mtd.flags & flags[i].value)
			{
			   if (first)
				 {
					printf (flags[i].name);
					first = 0;
				 }
			   else printf (" | %s",flags[i].name);
			}
	 }

   printf ("\nmtd.size = ");
   printsize (mtd.size);

   printf ("\nmtd.erasesize = ");
   printsize (mtd.erasesize);

   printf ("\nmtd.oobblock = ");
   printsize (mtd.oobblock);

   printf ("\nmtd.oobsize = ");
   printsize (mtd.oobsize);

   printf ("\nmtd.ecctype = ");
   switch (mtd.ecctype)
	 {
	  case MTD_ECC_NONE:
		printf ("MTD_ECC_NONE");
		break;
	  case MTD_ECC_RS_DiskOnChip:
		printf ("MTD_ECC_RS_DiskOnChip");
		break;
	  case MTD_ECC_SW:
		printf ("MTD_ECC_SW");
		break;
	  default:
		printf ("(unknown ECC type - new MTD API maybe?)");
	 }

   printf ("\n"
		   "regions = %d\n"
		   "\n",
		   n);

   for (i = 0; i < n; i++)
	 {
		printf ("region[%d].offset = 0x%.8x\n"
				"region[%d].erasesize = ",
				i,region[i].offset,i);
		printsize (region[i].erasesize);
		printf ("\nregion[%d].numblocks = %d\n"
				"region[%d].regionindex = %d\n",
				i,region[i].numblocks,
				i,region[i].regionindex);
	 }
   return (0);
}
コード例 #11
0
ファイル: lib.c プロジェクト: Rakashazi/emu-ex-plus-alpha
void lib_debug_check(void)
{
#ifdef LIB_DEBUG
    unsigned int index, count;
    unsigned int leakbytes;
#ifdef LIB_DEBUG_CALLER
    char **btstring;
    int btidx, spc;
#endif
    count = 0;
    leakbytes = 0;
    lib_debug_leaklist_num = 0;

    for (index = 0; index < LIB_DEBUG_SIZE; index++) {
        if (lib_debug_address[index] != NULL) {
            count++;
#ifdef LIB_DEBUG_PINPOINT
            lib_debug_leaklist_add(index);
#else
            printf("Warning: Memory block allocated here was not free'd (Memory leak with size 0x%x at %p).",
                   lib_debug_size[index], lib_debug_address[index]);
            printf("\n");
#endif
            leakbytes += lib_debug_size[index];
#if LIB_DEBUG_GUARD > 0
            lib_debug_guard_remove((char *)lib_debug_address[index]);
#endif
        }
    }

#ifdef LIB_DEBUG_PINPOINT
    printf("\n");
    for (index = 0; index < lib_debug_leaklist_num; index++) {
        printf("%s:%d: Warning: Memory block(s) allocated here was not free'd (Memory leak with size 0x%x at %p).",
               lib_debug_leaklist_filename[index], lib_debug_leaklist_line[index], 
               lib_debug_leaklist_size[index], lib_debug_leaklist_address[index]);
#ifdef LIB_DEBUG_CALLER
        printf("\ncallstack:\n");
        btstring = backtrace_symbols(lib_debug_leaklist_bt_caller[index], lib_debug_leaklist_bt_numcaller[index]);
        if (btstring == NULL) {
            printf("             lookup failed\n");
        } else {
            for (btidx = 1; btidx < lib_debug_leaklist_bt_numcaller[index]; btidx++) {
                printf("             ");
                for (spc = 0; spc < btidx; spc++) {
                    printf(" ");
                }
                printf("%s\n", btstring[btidx]);
            }
        }
        free(btstring);
#endif
        printf("\n");
    }
#endif

    printf("\nTotal memory leaks: %d", count);
#ifdef LIB_DEBUG_PINPOINT
    printf(" in %d lines", lib_debug_leaklist_num);
#endif
    printf(". Total bytes leaked: 0x%x (", leakbytes);
    printsize(leakbytes);
    printf(").\n\nmax. total memory that was allocated: 0x%x bytes. (", lib_debug_max_total);
    printsize(lib_debug_max_total);
    printf(")\n");

#ifdef LIB_DEBUG_PINPOINT
    printf("\nTop %d largest allocated blocks:\n", LIB_DEBUG_TOPMAX);
    for (index = 0; index < LIB_DEBUG_TOPMAX; index++) {
        if (lib_debug_top_size[index]) {
            printf("%8x bytes (", lib_debug_top_size[index]);
            printsize(lib_debug_top_size[index]);
            printf(") allocated at %s:%d\n", lib_debug_top_filename[index], lib_debug_top_line[index]);
        }
    }
#endif

#endif
}
コード例 #12
0
void do_file(const u8* base, u32 offset, u32 size,
	     const char* path, const char* name, int mode)
{
   int fd;
   u8* file_data;
   const u8* srcdata;
   
   // Allow for uncompressed XIP executable
   if (mode & S_ISVTX) {
      // It seems that the offset may not necessarily be page
      // aligned. This is silly because mkcramfs wastes
      // the alignment space, whereas it might be used if it wasn't
      // bogusly in our file extent.
      //
      // blksize must be a power of 2 for the following to work, but it seems
      // quite likely.
 
      srcdata=(const u8*)(((u32)(base+offset)+blksize-1) & ~(blksize-1));
      printsize(size, srcdata+size-(base+offset));
      printf("%s", name);
   } else {
      printsize(size, compressed_size(base, base+offset, size) );
      printf("%s", name);
   }

   // Check if we are actually unpacking
   if (path[0]=='-') {
      return;
   }

   // Make local copy
   fd=open(path, O_CREAT|O_TRUNC|O_RDWR, mode);
   if (fd == -1) {
      perror("create");
      return;
   };

   if (ftruncate(fd, size) == -1) {
      perror("ftruncate");
      close(fd);
      return;
   }
   
   file_data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
   if (file_data == MAP_FAILED) {
      perror("mmap");
      close(fd);
      return;
   }

   // Allow for uncompressed XIP executable
   if (mode & S_ISVTX) {
      memcpy(file_data, srcdata, size);
   } else {
      if(uncompress_data(base, base+offset, size, file_data) == -1)
      {
         printf("failed to decompress data\n");
      }
   }
   
   munmap(file_data, size);
   close(fd);

}
コード例 #13
0
ファイル: mtd_debug.c プロジェクト: OpenNoah/mtd-utils
int showinfo (int fd)
{
	int i,err,n;
	struct mtd_info_user mtd;
	static struct region_info_user region[1024];

	err = getmeminfo (fd,&mtd);
	if (err < 0)
	{
		perror ("MEMGETINFO");
		return (1);
	}

	err = getregions (fd,region,&n);
	if (err < 0)
	{
		perror ("MEMGETREGIONCOUNT");
		return (1);
	}

	printf ("mtd.type = ");
	switch (mtd.type)
	{
		case MTD_ABSENT:
			printf ("MTD_ABSENT");
			break;
		case MTD_RAM:
			printf ("MTD_RAM");
			break;
		case MTD_ROM:
			printf ("MTD_ROM");
			break;
		case MTD_NORFLASH:
			printf ("MTD_NORFLASH");
			break;
		case MTD_NANDFLASH:
			printf ("MTD_NANDFLASH");
			break;
		case MTD_DATAFLASH:
			printf ("MTD_DATAFLASH");
			break;
		case MTD_UBIVOLUME:
			printf ("MTD_UBIVOLUME");
		default:
			printf ("(unknown type - new MTD API maybe?)");
	}

	printf ("\nmtd.flags = ");
	if (mtd.flags == MTD_CAP_ROM)
		printf ("MTD_CAP_ROM");
	else if (mtd.flags == MTD_CAP_RAM)
		printf ("MTD_CAP_RAM");
	else if (mtd.flags == MTD_CAP_NORFLASH)
		printf ("MTD_CAP_NORFLASH");
	else if (mtd.flags == MTD_CAP_NANDFLASH)
		printf ("MTD_CAP_NANDFLASH");
	else if (mtd.flags == MTD_WRITEABLE)
		printf ("MTD_WRITEABLE");
	else
	{
		int first = 1;
		static struct
		{
			const char *name;
			int value;
		} flags[] =
		{
			{ "MTD_WRITEABLE", MTD_WRITEABLE },
			{ "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE },
			{ "MTD_NO_ERASE", MTD_NO_ERASE },
			{ "MTD_STUPID_LOCK", MTD_STUPID_LOCK },
			{ NULL, -1 }
		};
		for (i = 0; flags[i].name != NULL; i++)
			if (mtd.flags & flags[i].value)
			{
				if (first)
				{
					printf (flags[i].name);
					first = 0;
				}
				else printf (" | %s",flags[i].name);
			}
	}

	printf ("\nmtd.size = ");
	printsize (mtd.size);

	printf ("\nmtd.erasesize = ");
	printsize (mtd.erasesize);

	printf ("\nmtd.writesize = ");
	printsize (mtd.writesize);

	printf ("\nmtd.oobsize = ");
	printsize (mtd.oobsize);

	printf ("\n"
			"regions = %d\n"
			"\n",
			n);

	for (i = 0; i < n; i++)
	{
		printf ("region[%d].offset = 0x%.8x\n"
				"region[%d].erasesize = ",
				i,region[i].offset,i);
		printsize (region[i].erasesize);
		printf ("\nregion[%d].numblocks = %d\n"
				"region[%d].regionindex = %d\n",
				i,region[i].numblocks,
				i,region[i].regionindex);
	}
	return (0);
}
コード例 #14
0
ファイル: iff2html.c プロジェクト: pepster98/Niotso
int main(int argc, char *argv[]){
    unsigned c;
    int slash;
    FILE * hFile;
    int overwrite = 0;
    char *InFile, *OutFile = NULL, *FileName, *OutDir = NULL;
    size_t FileSize;
    struct MD5Context md5c;
    unsigned char digest[16];
    uint8_t * IFFData;
    IFFFile * IFFFileInfo;
    IFFChunk * ChunkData;

    if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
        printf("Usage: iff2html [-f] infile (outfile)\n"
        "Produce an HTML webpage describing an EA IFF file.\n"
        "Use -f to force overwriting without confirmation.\n"
        "If outfile is unspecified, file.iff will output to file.html.\n"
        "\n"
        "Report bugs to <*****@*****.**>.\n"
        "iff2html is maintained by the Niotso project.\n"
        "Home page: <http://www.niotso.org/>\n");
        return 0;
    }

    if(argc >= 4 && !strcmp(argv[1], "-f")){
        overwrite++;
        InFile = argv[2];
        OutFile = argv[3];
    }else if(argc == 3){
        if(!strcmp(argv[1], "-f")){
            overwrite++;
            InFile = argv[2];
        }else{
            InFile = argv[1];
            OutFile = argv[2];
        }
    }else InFile = argv[1];
    if(OutFile == NULL){
        unsigned length = strlen(InFile);
        OutFile = malloc(max(length+2, 6));
        strcpy(OutFile, InFile);
        strcpy(max(OutFile+length-4, OutFile), ".html");
    }

    for(c=0, slash=-1; OutFile[c]; c++)
        if(OutFile[c] == '/' || OutFile[c] == '\\') slash = c;
    if(slash >= 0){
        OutDir = malloc(slash+2);
        memcpy(OutDir, OutFile, slash+1);
        OutDir[slash+1] = 0x00;
    }else OutDir = "";

    for(c=0, slash=-1; InFile[c]; c++)
        if(InFile[c] == '/' || InFile[c] == '\\') slash = c;
    FileName = InFile + slash + 1;

    /****
    ** Open the file and read in entire contents to memory
    */

    hFile = fopen(InFile, "rb");
    if(hFile == NULL){
        printf("%sThe specified input file does not exist or could not be opened for reading.", "iff2html: error: ");
        return -1;
    }
    fseek(hFile, 0, SEEK_END);
    FileSize = ftell(hFile);
    if(FileSize < 64){
        printf("%sNot a valid IFF file.", "iff2html: error: ");
        return -1;
    }
    fseek(hFile, 0, SEEK_SET);

    IFFData = malloc(FileSize);
    if(IFFData == NULL){
        printf("%sMemory for this file could not be allocated.", "iff2html: error: ");
        return -1;
    }
    if(!fread(IFFData, FileSize, 1, hFile)){
        printf("%sThe input file could not be read.", "iff2html: error: ");
        return -1;
    }
    fclose(hFile);

    /****
    ** Load header information
    */

    IFFFileInfo = iff_create();
    if(IFFFileInfo == NULL){
        printf("%sMemory for this file could not be allocated.", "iff2html: error: ");
        return -1;
    }
    if(!iff_read_header(IFFFileInfo, IFFData, FileSize)){
        printf("%sNot a valid IFF file.", "iff2html: error: ");
        return -1;
    }

    /****
    ** Load entry information
    */

    if(!iff_enumerate_chunks(IFFFileInfo, IFFData+64, FileSize-64)){
        printf("%sChunk data is corrupt.", "iff2html: error: ");
        return -1;
    }

    /* Calculate the MD5, and then we can free the IFF data because we're done with it */
    MD5Init(&md5c);
    MD5Update(&md5c, IFFData, FileSize);
    MD5Final(digest, &md5c);
    free(IFFData);

    for(c = 0, ChunkData = IFFFileInfo->Chunks; c < IFFFileInfo->ChunkCount; c++, ChunkData++)
        iff_parse_chunk(ChunkData, ChunkData->Data);

    /****
    ** Open the output file and write the header
    */
    if(!overwrite){
        hFile = fopen(OutFile, "rb");
        if(hFile != NULL){
            /* File exists */
            char c;
            fclose(hFile);
            printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile);
            c = getchar();
            if(c != 'y' && c != 'Y'){
                printf("\nAborted.");
                return -1;
            }
        }
    }
    hFile = fopen(OutFile, "wb");
    if(hFile == NULL){
        printf("%sThe output file could not be opened for writing.", "iff2html: error: ");
        return -1;
    }

    /****
    ** We're splitting fprintf by line to guarantee compatibility;
    ** even C99 compilers are only required to support 4096 byte strings in printf()-related functions
    */
    fprintf(hFile,
        "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
    fprintf(hFile, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n");
    fprintf(hFile, "<head>\n");
    fprintf(hFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n");
    fprintf(hFile, "<meta http-equiv=\"Content-Style-Type\" content=\"text/css; charset=iso-8859-1\" />\n");
    fprintf(hFile, "<meta http-equiv=\"Content-Language\" content=\"en\" />\n");
    fprintf(hFile, "<meta name=\"description\" content=\"%s (iff2html)\" />\n", FileName);
    fprintf(hFile, "<meta name=\"generator\" content=\"iff2html\" />\n");
    fprintf(hFile, "<title>%s (iff2html)</title>\n", FileName);
    fprintf(hFile, "<style type=\"text/css\" media=\"all\">\n");
    fprintf(hFile, "html, body {\n");
    fprintf(hFile, "    background: #fff;\n");
    fprintf(hFile, "    color: #000;\n");
    fprintf(hFile, "    font-family: sans-serif;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "a:link, a:visited, a:hover, a:active { color: #00f; }\n");
    fprintf(hFile, "a:link, a:visited { text-decoration: none; }\n");
    fprintf(hFile, "a:hover, a:active { text-decoration: underline; }\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "#attributes {\n");
    fprintf(hFile, "    border-left: 2px solid #888; padding-left: 4px; margin-bottom: 1em;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "#toc {\n");
    fprintf(hFile, "    display: table-cell;\n");
    fprintf(hFile, "    margin-top: 1em;\n");
    fprintf(hFile, "    background: #eee; border: 1px solid #bbb;\n");
    fprintf(hFile, "    padding: .25em;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "#toc div {\n");
    fprintf(hFile, "    border-bottom: 1px solid #aaa;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "#toc ul {\n");
    fprintf(hFile, "    list-style-type: none;\n");
    fprintf(hFile, "    padding: 0;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "ul ul {\n");
    fprintf(hFile, "    padding: 2em;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "h2 {\n");
    fprintf(hFile, "    border-bottom: 1px solid #888;\n");
    fprintf(hFile, "    margin: 2em 0 0.25em 0;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "h2 a {\n");
    fprintf(hFile, "    font-size: 9pt;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "table {\n");
    fprintf(hFile, "    border: 1px #aaa solid;\n");
    fprintf(hFile, "    border-collapse: collapse;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "th, td {\n");
    fprintf(hFile, "    border: 1px #aaa solid;\n");
    fprintf(hFile, "    padding: 0.2em;\n");
    fprintf(hFile, "    white-space: pre-wrap;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, ".center {\n");
    fprintf(hFile, "    margin: auto auto;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, ".centerall * {\n");
    fprintf(hFile, "    text-align: center;\n");
    fprintf(hFile, "    vertical-align: middle;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, ".palette td, .palette th {\n");
    fprintf(hFile, "    border: none;\n");
    fprintf(hFile, "    width: 16px;\n");
    fprintf(hFile, "    height: 16px;\n");
    fprintf(hFile, "    font-size: 12px;\n");
    fprintf(hFile, "    line-height: 16px;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, ".palette td[title] {\n");
    fprintf(hFile, "    border: 1px solid #000;\n");
    fprintf(hFile, "    cursor: help;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "#footer {\n");
    fprintf(hFile, "    margin-top: 2em;\n");
    fprintf(hFile, "    padding-bottom: 0.5em;\n");
    fprintf(hFile, "    text-align: center;\n");
    fprintf(hFile, "}\n");
    fprintf(hFile, "</style>\n");
    fprintf(hFile, "</head>\n");
    fprintf(hFile, "<body>\n");
    fprintf(hFile, "<h1>%s</h1>\n", FileName);
    fprintf(hFile, "<div id=\"attributes\">\n");
    fprintf(hFile, "<div>");
    for(c=0; c<16; c++)
        fprintf(hFile, "%.2x", digest[c]);
    fprintf(hFile, " (md5), ");
    printsize(hFile, FileSize);
    fprintf(hFile, "</div>\n");
    fprintf(hFile, "<div>Dumped by iff2html.</div></div>\n");
    fprintf(hFile, "\n");
    fprintf(hFile, "<div id=\"toc\"><div><b>Contents</b> &ndash; %u chunks</div>\n", IFFFileInfo->ChunkCount);
    fprintf(hFile, "<ul>\n");
    for(c=1, ChunkData = IFFFileInfo->Chunks; c <= IFFFileInfo->ChunkCount; c++, ChunkData++)
        fprintf(hFile, "<li><a href=\"#chunk%u_%.4x\">%u [%s] (%.4X)%s%s</a></li>\n",
            c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID,
            (ChunkData->Label[0] != 0x00) ? " &ndash; " : "", ChunkData->Label);
    fprintf(hFile, "</ul>\n");
    fprintf(hFile, "</div>\n");
    fprintf(hFile, "\n");

    for(c=0, ChunkData = IFFFileInfo->Chunks; c < IFFFileInfo->ChunkCount; c++, ChunkData++){
        fprintf(hFile, "<h2 id=\"chunk%u_%.4x\">%u [%s] (%.4X)%s%s <a href=\"#chunk%u_%.4x\">(Jump)</a></h2>\n",
            c+1, ChunkData->ChunkID, c+1, ChunkData->Type, ChunkData->ChunkID,
            (ChunkData->Label[0] != 0x00) ? " &ndash; " : "", ChunkData->Label,
            c+1, ChunkData->ChunkID);
        fprintf(hFile, "<div>\n");

        if(ChunkData->FormattedData == NULL){
            int success = 0;
            /* The iff library does not parse BMP_ or FBMP chunks */
            if(!strcmp(ChunkData->Type, "BMP_") || !strcmp(ChunkData->Type, "FBMP")){
                int bmp = !strcmp(ChunkData->Type, "BMP_");
                size_t Width, Height;
                char filename[32];
                sprintf(filename, "%s%s_%u_%.4x.png", OutDir, bmp ? "bmp" : "fbmp", c+1, ChunkData->ChunkID);

                if(WritePNG(filename, ChunkData, 0, NULL, &Width, &Height)){
                    fprintf(hFile, "<table class=\"center centerall\">\n");
                    fprintf(hFile, "<tr><th>Image</th></tr>\n");
                    fprintf(hFile, "<tr><td><img src=\"%s_%u_%.4x.png\" width=\"%u\" height=\"%u\" alt=\"\" /></td></tr>\n",
                        bmp ? "bmp" : "fbmp", c+1, ChunkData->ChunkID, (unsigned) Width, (unsigned) Height);
                    fprintf(hFile, "</table>\n");
                    success++;
                }
            }
            if(!success)
                fprintf(hFile, "The contents of this chunk could not be parsed.\n");
        }else if(!strcmp(ChunkData->Type, "STR#")  ||
            !strcmp(ChunkData->Type, "CTSS") ||
            !strcmp(ChunkData->Type, "FAMs") ||
            !strcmp(ChunkData->Type, "TTAs") ||
            !strcmp(ChunkData->Type, "CST")  ){
            /****
            ** STR# parsing
            */

            IFFString * StringData = ChunkData->FormattedData;
            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Format:</td><td>");
            switch(StringData->Format){
                case 0:  fprintf(hFile, "<tt>00 00</tt> (0)"); break;
                case -1: fprintf(hFile, "<tt>FF FF</tt> (&minus;1)"); break;
                case -2: fprintf(hFile, "<tt>FE FF</tt> (&minus;2)"); break;
                case -3: fprintf(hFile, "<tt>FD FF</tt> (&minus;3)"); break;
                case -4: fprintf(hFile, "<tt>FC FF</tt> (&minus;4)"); break;
                default: fprintf(hFile, "Unrecognized"); break;
            }
            fprintf(hFile, "</td></tr>\n");
            fprintf(hFile, "</table>\n");
            if(StringData->Format >= -4 && StringData->Format <= 0){
                unsigned LanguageSet;
                const char * LanguageStrings[] = {
                    "English (US)",
                    "English (International)",
                    "French",
                    "German",
                    "Italian",
                    "Spanish",
                    "Dutch",
                    "Danish",
                    "Swedish",
                    "Norwegian",
                    "Finnish",
                    "Hebrew",
                    "Russian",
                    "Portuguese",
                    "Japanese",
                    "Polish",
                    "Simplified Chinese",
                    "Traditional Chinese",
                    "Thai",
                    "Korean"
                };
                fprintf(hFile, "<br />\n");
                fprintf(hFile, "<table class=\"center\">\n");
                fprintf(hFile, "<tr><th>Language</th><th colspan=\"3\">String pairs</th></tr>\n");

                for(LanguageSet=0; LanguageSet<20; LanguageSet++){
                    IFFStringPair * Pair;
                    unsigned PairIndex;
                    if(StringData->LanguageSets[LanguageSet].PairCount == 0)
                        continue;

                    fprintf(hFile, "<tr><td rowspan=\"%u\">%s</td>\n", StringData->LanguageSets[LanguageSet].PairCount,
                        LanguageStrings[LanguageSet]);
                    for(PairIndex=1, Pair = StringData->LanguageSets[LanguageSet].Pairs;
                        PairIndex <= StringData->LanguageSets[LanguageSet].PairCount; PairIndex++, Pair++){
                        if(PairIndex != 1)
                            fprintf(hFile, "<tr>");
                        fprintf(hFile, "<td>%u</td><td>%s</td><td>%s</td></tr>\n", PairIndex,
                            (Pair->Key)   != NULL ? Pair->Key   : "",
                            (Pair->Value) != NULL ? Pair->Value : "");
                    }
                }

                fprintf(hFile, "</table>\n");
            }
        }else if(!strcmp(ChunkData->Type, "CATS")){
            /****
            ** Regular string pair
            */

            IFFStringPair * Pair = ChunkData->FormattedData;

            fprintf(hFile, "<table class=\"center\">\n");
            fprintf(hFile, "<tr><th>Key</th><th>Value</th></tr>\n");
            fprintf(hFile, "<tr><td>%s</td><td>%s</td></tr>\n",
                (Pair->Key)   != NULL ? Pair->Key   : "",
                (Pair->Value) != NULL ? Pair->Value : "");
            fprintf(hFile, "</table>\n");
        }else if(!strcmp(ChunkData->Type, "FWAV") || !strcmp(ChunkData->Type, "GLOB")){
            /****
            ** Regular string
            */

            fprintf(hFile, "<table class=\"center\">\n");
            fprintf(hFile, "<tr><th>String</th></tr>\n");
            fprintf(hFile, "<tr><td>%s</td></tr>\n", ChunkData->FormattedData ? (char*) ChunkData->FormattedData : "");
            fprintf(hFile, "</table>\n");
        }else if(!strcmp(ChunkData->Type, "BCON")){
            /****
            ** BCON parsing
            */

            IFF_BCON * BCONData = ChunkData->FormattedData;
            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Flags:</td><td><tt>%02X</tt> (%u)</td></tr>\n", BCONData->Flags, BCONData->Flags);
            fprintf(hFile, "</table>\n");
            if(BCONData->ConstantCount > 0){
                unsigned i;

                fprintf(hFile, "<br />\n");
                fprintf(hFile, "<table class=\"center\">\n");
                fprintf(hFile, "<tr><th colspan=\"2\">Constant Value</th></tr>\n");
                for(i=0; i<BCONData->ConstantCount; i++)
                    fprintf(hFile, "<tr><td>%u</td><td>%u</td></tr>\n", i+1, BCONData->Constants[i]);
                fprintf(hFile, "</table>\n");
            }
        }else if(!strcmp(ChunkData->Type, "FCNS")){
            /****
            ** FCNS parsing
            */

            IFFConstantList * List = ChunkData->FormattedData;
            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", List->Version);
            fprintf(hFile, "</table>\n");
            if(List->ConstantCount > 0){
                IFFConstant * Constant;
                unsigned i;

                fprintf(hFile, "<br />\n");
                fprintf(hFile, "<table class=\"center\">\n");
                fprintf(hFile, "<tr><th colspan=\"2\">Name</th><th>Value</th><th>Description</th></tr>\n");
                for(i=0, Constant=List->Constants; i<List->ConstantCount; i++, Constant++)
                    fprintf(hFile, "<tr><td>%u</td><td>%s</td><td>%g</td><td>%s</td></tr>\n",
                        i+1,
                        Constant->Name ? Constant->Name : "",
                        Constant->Value,
                        Constant->Description ? Constant->Description : "");
                fprintf(hFile, "</table>\n");
            }
        }else if(!strcmp(ChunkData->Type, "TMPL")){
            /****
            ** TMPL parsing
            */

            IFFTemplate * Template = ChunkData->FormattedData;
            IFFTemplateField * Field;
            unsigned i;
            fprintf(hFile, "<table class=\"center\">\n");
            fprintf(hFile, "<tr><th colspan=\"2\">Name</th><th>Type</th>\n");
            for(i=0, Field=Template->Fields; i<Template->FieldCount; i++, Field++)
                fprintf(hFile, "<tr><td>%u</td><td>%s</td><td>%s</td></tr>\n",
                    i+1,
                    Field->Name ? Field->Name : "",
                    Field->Type ? Field->Type : "");
            fprintf(hFile, "</table>\n");
        }else if(!strcmp(ChunkData->Type, "TRCN")){
            /****
            ** TRCN parsing
            */

            IFFRangeSet * RangeSet = ChunkData->FormattedData;
            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", RangeSet->Version);
            fprintf(hFile, "</table>\n");
            if(RangeSet->RangeCount > 0){
                unsigned i;
                IFFRangeEntry * Range;

                fprintf(hFile, "<br />\n");
                fprintf(hFile, "<table class=\"center\">\n");
                fprintf(hFile, "<tr><th colspan=\"2\">In use</th><th>Default value</th><th>Name</th>"
                    "<th>Comment</th><th>Range is enforced</th><th>Minimum</th><th>Maximum</th></tr>\n");
                for(i=0, Range=RangeSet->Ranges; i<RangeSet->RangeCount; i++, Range++)
                    fprintf(hFile,
                        "<tr><td>%u</td><td>%s</td><td>%u</td><td>%s</td><td>%s</td><td>%s</td><td>%u</td><td>%u</td></tr>\n",
                        i+1,
                        Range->IsUsed ? "Yes" : "No", Range->DefaultValue,
                        Range->Name ? Range->Name : "",
                        Range->Comment ? Range->Comment : "",
                        Range->Enforced ? "Yes" : "No",
                        Range->RangeMin, Range->RangeMax);
                fprintf(hFile, "</table>\n");
            }
        }else if(!strcmp(ChunkData->Type, "PALT")){
            /****
            ** PALT parsing
            */

            IFFPalette * Palette = ChunkData->FormattedData;
            uint8_t * Data = Palette->Data;
            unsigned i, j;

            fprintf(hFile, "<table class=\"center palette\" border=\"0\">\n");
            fprintf(hFile, "<tr><th></th>");
            for(i=0; i<16; i++) fprintf(hFile, "<th>%X</th>", i);
            fprintf(hFile, "</tr>\n");
            for(i=0; i<16; i++){
                fprintf(hFile, "<tr><th>%X</th>", i);
                for(j=0; j<16; j++){
                    if(i*16 + j < Palette->ColorCount){
                        unsigned red = *(Data++);
                        unsigned green = *(Data++);
                        unsigned blue = *(Data++);

                        fprintf(hFile, "\n<td style=\"background:#%.2x%.2x%.2x\" title=\"%u: #%.2x%.2x%.2x\"></td>",
                            red, green, blue, i*16 + j, red, green, blue);
                    }else
                        fprintf(hFile, "\n<td></td>");
                }
                fprintf(hFile, "</tr>\n");
            }
            fprintf(hFile, "</table>\n");
        }else if(!strcmp(ChunkData->Type, "SPR#") || !strcmp(ChunkData->Type, "SPR2")){
            /****
            ** SPR# and SPR2 parsing
            */

            int spr1 = !strcmp(ChunkData->Type, "SPR#");
            IFFSpriteList * SpriteList = ChunkData->FormattedData;
            IFFChunk * Palette = NULL;
            IFFPalette BlankPalette;
            IFFPalette * PaletteData;
            unsigned i;

            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", SpriteList->Version);
            fprintf(hFile, "<tr><td>Palette ID:</td><td>%.4X</td></tr>\n", SpriteList->PaletteID);
            fprintf(hFile, "</table>\n");

            if(SpriteList->PaletteID < 0xFFFF){
                Palette = iff_find_chunk(IFFFileInfo, "PALT", SpriteList->PaletteID);
                if(!Palette || !Palette->FormattedData) Palette = iff_find_chunk(IFFFileInfo, "PALT", ChunkData->ChunkID);
                if(!Palette || !Palette->FormattedData) Palette = iff_find_chunk(IFFFileInfo, "PALT", -1);
            }
            if(!Palette || !Palette->FormattedData){
                memset(&BlankPalette, 0, sizeof(IFFPalette));
                BlankPalette.Version = 1;
                BlankPalette.ColorCount = 256;
                PaletteData = &BlankPalette;
            }else PaletteData = Palette->FormattedData;

            fprintf(hFile, "<table class=\"center centerall\">\n");
            fprintf(hFile, "<tr><th colspan=\"2\">Sprite</th>");
            if(!spr1) fprintf(hFile, "<th>Z-Buffer</th>");
            fprintf(hFile, "</tr>\n");
            for(i=0; i<SpriteList->SpriteCount; i++){
                IFFSprite * Sprite = &SpriteList->Sprites[i];
                char filename[32];
                sprintf(filename, "%s%s_%u_%.4x_%u.png", OutDir, spr1 ? "spr1" : "spr2", c+1, ChunkData->ChunkID, i+1);

                fprintf(hFile, "<tr><td>%u</td><td", i+1);
                if(Sprite->IndexData && iff_depalette(Sprite, PaletteData)){
                    WritePNG(filename, NULL, 0, Sprite, NULL, NULL);
                    fprintf(hFile, "><img src=\"%s_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
                        spr1 ? "spr1" : "spr2", c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
                    if(!spr1){
                        sprintf(filename, "%sspr2_%u_%.4x_%u_z.png", OutDir, c+1, ChunkData->ChunkID, i+1);
                        if(Sprite->ZBuffer){
                            WritePNG(filename, NULL, 1, Sprite, NULL, NULL);
                            fprintf(hFile, "</td><td><img src=\"spr2_%u_%.4x_%u_z.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
                                c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
                        }else
                            fprintf(hFile, "None provided");
                    }
                }else
                    fprintf(hFile, Sprite->InvalidDimensions ? "%sBlank sprite" : "%sThis sprite cannot be displayed.",
                        !spr1 ? " colspan=\"2\">" : ">");
                fprintf(hFile, "</td></tr>\n");
            }
            fprintf(hFile, "</table>\n");
        }else if(!strcmp(ChunkData->Type, "DGRP")){
            /****
            ** DGRP parsing
            */

            IFFDrawGroup * Group = ChunkData->FormattedData;
            IFFDrawAngle * Angle;
            IFFSpriteInfo * Sprite;
            unsigned i,j;
            const char * Zooms[] = {"Far", "Middle", "Close"};

            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Group->Version);
            fprintf(hFile, "</table>\n");
            fprintf(hFile, "<br />\n");

            fprintf(hFile, "<table class=\"center\">\n");
            fprintf(hFile, "<tr><th>Direction</th><th>Zoom</th><th colspan=\"6\">Sprite</th></tr>\n");
            for(i=0, Angle=Group->DrawAngles; i<12; i++, Angle++){
                const char * Direction =
                    (Angle->Direction == IFFDIRECTION_NORTHEAST)  ? "North east" :
                    (Angle->Direction == IFFDIRECTION_SOUTHEAST)  ? "South east" :
                    (Angle->Direction == IFFDIRECTION_NORTHWEST)  ? "North west" :
                                                                    "South west";

                if(Angle->SpriteCount){
                    fprintf(hFile,
                        "<tr><td rowspan=\"%u\">%s</td><td rowspan=\"%u\">%s</td>"
                        "<th>#</th><th>Type</th><th>Chunk ID</th><th>Sprite index</th>"
                        "<th>Flags</th><th>Sprite offset</th><th>Object offset</th></tr>\n",
                        1+Angle->SpriteCount, Direction, 1+Angle->SpriteCount, Zooms[Angle->Zoom-1]);
                    for(j=0, Sprite = Angle->SpriteInfo; j<Angle->SpriteCount; j++, Sprite++)
                        fprintf(hFile, "<tr><td>%u</td><td>%u</td><td>%.4X</td><td>%u</td><td>%u</td>"
                            "<td>(%+d,%+d)</td><td>(%+g,%+g,%+g)</td></tr>",
                            j+1, Sprite->Type, Sprite->ChunkID, Sprite->SpriteIndex, Sprite->Flags,
                            Sprite->SpriteX, Sprite->SpriteY, Sprite->ObjectX, Sprite->ObjectY, Sprite->ObjectZ);

                }else{
                    fprintf(hFile, "<tr><td>%s</td><td>%s</td><td>None specified</td></tr>", Direction, Zooms[Angle->Zoom-1]);
                }
            }
            fprintf(hFile, "</table>\n");
        }else if(!strcmp(ChunkData->Type, "BHAV")){
            /****
            ** BHAV parsing
            */

            IFFBehavior * Behavior = ChunkData->FormattedData;
            IFFInstruction * Instruction;

            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Behavior->Version);
            fprintf(hFile, "<tr><td>Type:</td><td>%u</td></tr>\n", Behavior->Type);
            fprintf(hFile, "<tr><td>Arguments:</td><td>%u</td></tr>\n", Behavior->ArgumentCount);
            fprintf(hFile, "<tr><td>Locals:</td><td>%u</td></tr>\n", Behavior->LocalCount);
            fprintf(hFile, "<tr><td>Flags:</td><td>%.4X</td></tr>\n", Behavior->Flags);
            fprintf(hFile, "</table>\n");

            if(Behavior->InstructionCount > 0){
                unsigned i;

                fprintf(hFile, "<br />\n");
                fprintf(hFile, "<table class=\"center\">\n");
                fprintf(hFile, "<tr><th colspan=\"2\">Opcode</th><th>T-Dest</th><th>F-Dest</th><th>Operand data</th></tr>\n");
                for(i=0, Instruction = Behavior->Instructions; i<Behavior->InstructionCount; i++, Instruction++)
                    fprintf(hFile, "<tr><td>%u</td><td><tt>%.4X</tt></td><td>%u</td><td>%u</td>"
                        "<td><tt>%.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X</tt></td></tr>\n",
                        i, Instruction->Opcode, Instruction->TDest, Instruction->FDest,
                        Instruction->Operands[0], Instruction->Operands[1],
                        Instruction->Operands[2], Instruction->Operands[3],
                        Instruction->Operands[4], Instruction->Operands[5],
                        Instruction->Operands[6], Instruction->Operands[7]);
                fprintf(hFile, "</table>\n");
            }
        }else if(!strcmp(ChunkData->Type, "OBJf")){
            /****
            ** OBJf parsing
            */

            IFFFunctionTable * Table = ChunkData->FormattedData;
            fprintf(hFile, "<table>\n");
            fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Table->Version);
            fprintf(hFile, "</table>\n");

            if(Table->FunctionCount > 0){
                unsigned i;

                fprintf(hFile, "<br />\n");
                fprintf(hFile, "<table class=\"center\">\n");
                fprintf(hFile, "<tr><th colspan=\"2\">Condition function</th><th>Action function</th></tr>\n");
                for(i=0; i<Table->FunctionCount; i++)
                    fprintf(hFile,
                        "<tr><td>%u</td><td>%.4X</td><td>%.4X</td></tr>\n",
                        i+1, Table->Functions[i].ConditionID, Table->Functions[i].ActionID);
                fprintf(hFile, "</table>\n");
            }
        }else{
            fprintf(hFile, "The contents of this chunk cannot be shown on this page.\n");
        }

        fprintf(hFile, "</div>\n\n");
    }
    iff_delete(IFFFileInfo);

    fprintf(hFile,
        "<div id=\"footer\">This page was generated by the use of <a href=\"http://www.niotso.org/\">iff2html</a>.\n");
    fprintf(hFile, "The content of this page may be subject to copyright by the author(s) of the original iff file.</div>\n");
    fprintf(hFile, "</body>\n");
    fprintf(hFile, "</html>");
    fclose(hFile);

    printf("Wrote contents to '%s'.\n", OutFile);
    return 0;
}