[Scummvm-cvs-logs] SF.net SVN: scummvm:[41391] tools/branches/gsoc2009-gui

Remere at users.sourceforge.net Remere at users.sourceforge.net
Tue Jun 9 00:38:41 CEST 2009


Revision: 41391
          http://scummvm.svn.sourceforge.net/scummvm/?rev=41391&view=rev
Author:   Remere
Date:     2009-06-08 22:38:41 +0000 (Mon, 08 Jun 2009)

Log Message:
-----------
*Converted all extraction tools to new generic argument format (./tool [params] [-o dir] inputfile)
*Some tools are still untested with the new format, due to lack of data files.
*Added simple Filename class to util.h instead of the getPath/getFilename functions, boasts additional functionality, and easier to use. Missing a mkdir member to create the output directory if it doesn't exists (right now you have to do so manually, no simple cross-platform way to create dirs that I know of?)
*Most tools are DANGEROUSLY close to stack overflows, I'm sorta uncomfortable with using char arrays for everything, trusting that users don't have very long paths is generally not a viable way to prevent crashes.
*Minor code fixes, nothing ground-breaking.

Modified Paths:
--------------
    tools/branches/gsoc2009-gui/extract_agos.cpp
    tools/branches/gsoc2009-gui/extract_gob_stk.cpp
    tools/branches/gsoc2009-gui/extract_kyra.cpp
    tools/branches/gsoc2009-gui/extract_kyra.h
    tools/branches/gsoc2009-gui/extract_loom_tg16.cpp
    tools/branches/gsoc2009-gui/extract_mm_apple.cpp
    tools/branches/gsoc2009-gui/extract_mm_c64.cpp
    tools/branches/gsoc2009-gui/extract_mm_nes.cpp
    tools/branches/gsoc2009-gui/extract_parallaction.cpp
    tools/branches/gsoc2009-gui/extract_scumm_mac.cpp
    tools/branches/gsoc2009-gui/extract_zak_c64.cpp
    tools/branches/gsoc2009-gui/util.cpp
    tools/branches/gsoc2009-gui/util.h

Modified: tools/branches/gsoc2009-gui/extract_agos.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_agos.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_agos.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -24,6 +24,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "util.h"
+
 typedef unsigned int ULONG;
 typedef unsigned char UBYTE;
 
@@ -142,7 +144,7 @@
  * - call free() on ptr to free memory
  * - size of loaded file is available in global var 'filelen'
  */
-void *loadfile(char *name) {
+void *loadfile(const char *name) {
 	void *mem = NULL;
 	FILE *fd;
 
@@ -166,7 +168,7 @@
  *   the file named by [filename]
  * - returns zero if failed, or non-zero if successful
  */
-int savefile(char *name, void *mem, size_t length) {
+int savefile(const char *name, void *mem, size_t length) {
 	unsigned int bytesWritten;
 
 	FILE *fd = fopen(name, "wb");
@@ -184,37 +186,52 @@
 	return 1;
 }
 
-char filename[1024];
-
 int main(int argc, char *argv[]) {
-	int i;
+	int first_arg = 1;
+	int last_arg = argc;
 
-	if (argc < 2) {
-		printf("\nUsage: %s <file 1> ... <file n>\n", argv[0]);
-		exit(2);
-	}
+	Filename inpath, outpath;
 
-	for (i = 1; i < argc; i++) {
-		UBYTE *x = (UBYTE *) loadfile(argv[i]);
-		strcpy(filename, argv[i]);
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc);
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if ( parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
 
+	// Loop through all input files
+	for (int parsed_args = first_arg; parsed_args <= last_arg; ++parsed_args) {
+		const char *filename = argv[parsed_args];
+		UBYTE *x = (UBYTE *) loadfile(filename);
+
+		inpath.setFullPath(filename);
+		outpath.setFullName(inpath.getFullName());
+
 		if (x) {
 			ULONG decrlen = simon_decr_length(x, (ULONG) filelen);
 			UBYTE *out = (UBYTE *) malloc(decrlen);
 
 			if (out) {
 				if (simon_decr(x, out, filelen)) {
-					strcat(filename, ".out");
-					savefile(filename, out, decrlen);
+					savefile(outpath.getFullPath(), out, decrlen);
 				}
 				else {
-					printf("%s: decrunch error\n", filename);
+					notice("%s: decrunch error\n", filename);
 				}
 
 				free((void *) x);
 			}
 		}
+		else {
+			notice("Could not load file %s\n", filename);
+		}
 	}
 
 	return 0;
-}
+}
\ No newline at end of file

Modified: tools/branches/gsoc2009-gui/extract_gob_stk.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_gob_stk.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_gob_stk.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -39,39 +39,50 @@
 void extractError(FILE *f1, FILE *f2, Chunk *chunks, const char *msg);
 Chunk *readChunkList(FILE *stk, FILE *gobConf);
 Chunk *readChunkListV2(FILE *stk, FILE *gobConf);
-void extractChunks(FILE *stk, Chunk *chunks);
+void extractChunks(Filename *outpath, FILE *stk, Chunk *chunks);
 byte *unpackData(byte *src, uint32 &size);
 byte *unpackPreGobData(byte *src, uint32 &size, uint32 &compSize);
 
 int main(int argc, char **argv) {
 	char signature[7];
-	char *outFilename;
-	char *tmpStr;
 	Chunk *chunks;
 	FILE *stk;
 	FILE *gobConf;
 
-	if ((argc < 2) || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
-		printf("Usage: %s <file>\n\n", argv[0]);
-		printf("The files will be extracted into the current directory.\n");
-		return -1;
-	}
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-	if (!(stk = fopen(argv[1], "rb")))
-		error("Couldn't open file \"%s\"", argv[1]);
+	Filename inpath, outpath;
 
-	outFilename = new char[strlen(argv[1]) + 5];
-	getFilename(argv[1], outFilename);
-
-	tmpStr = strstr(outFilename, ".");
-	if (tmpStr != 0)
-		strcpy(tmpStr, ".gob");
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc);
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
 	else
-		strcat(outFilename, ".gob");
+		// Standard output dir
+		outpath.setFullPath("out/");
 
-	if (!(gobConf = fopen(outFilename, "w")))
-		error("Couldn't create config file \"%s\"", outFilename);
+	// We only got one input file
+	if (last_arg == first_arg)
+		error("Only one input file expected!\n");
 
+	inpath.setFullPath(argv[first_arg]);
+
+	if (!(stk = fopen(inpath.getFullPath(), "rb")))
+		error("Couldn't open file \"%s\"", inpath.getFullPath());
+
+	if (inpath.empty())
+		outpath = inpath;
+	outpath.addExtension(".gob");
+
+	if (!(gobConf = fopen(outpath.getFullPath(), "w")))
+		error("Couldn't create config file \"%s\"", outpath.getFullPath());
+
 	if (fread(signature, 1, 6, stk) < 6)
 		error("Unexpected EOF while reading signature in \"%s\"", argv[1]);
 
@@ -87,7 +98,7 @@
 
 	fclose(gobConf);
 
-	extractChunks(stk, chunks);
+	extractChunks(&outpath, stk, chunks);
 
 	delete chunks;
 	fclose(stk);
@@ -270,7 +281,7 @@
 	return chunks;
 }
 
-void extractChunks(FILE *stk, Chunk *chunks) {
+void extractChunks(Filename *outpath, FILE *stk, Chunk *chunks) {
 	Chunk *curChunk = chunks;
 	byte *unpackedData;
 
@@ -278,7 +289,8 @@
 		printf("Extracting \"%s\"\n", curChunk->name);
 
 		FILE *chunkFile;
-		if (!(chunkFile = fopen(curChunk->name, "wb")))
+		outpath->setFullName(curChunk->name);
+		if (!(chunkFile = fopen(outpath->getFullPath(), "wb")))
 			extractError(stk, 0, chunks, "Couldn't write file");
 
 		if (fseek(stk, curChunk->offset, SEEK_SET) == -1)

Modified: tools/branches/gsoc2009-gui/extract_kyra.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_kyra.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_kyra.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -24,74 +24,87 @@
 #include "kyra_pak.h"
 #include "kyra_ins.h"
 
-void showhelp(char *exename) {
-	printf("\nUsage: %s [params] <file>\n", exename);
-
-	printf("\nParams:\n");
-	printf( "-o <filename>     Extract only <filename>\n"
-			"-x                Extract all files\n"
-			"-a                Extract files from the Amiga .PAK files\n"
-			"-2                Extract files from HoF installer files\n");
-
-	exit(2);
-}
-
 int main(int argc, char **argv) {
 	char inputPath[768];
 
-	if (argc < 2)
-		showhelp(argv[0]);
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-	bool extractAll = false, extractOne = false, isAmiga = false, isHoFInstaller = false;
+	bool extractAll = true, extractOne = false, isAmiga = false, isHoFInstaller = false;
 	char singleFilename[256] = "";
-	int param;
 
-	for (param = 1; param < argc; param++) {
-		if (strcmp(argv[param], "-o") == 0) {
-			extractOne = true;
-			param++;
+	Filename outpath, inputpath;
 
-			if (param >= (argc - 1)) {
-				printf("You must supply a filename with -o\n");
-				printf("Example: %s -o ALGAE.CPS A_E.PAK\n", argv[0]);
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc, "\n"
+		"Usage: %s [params] [-o output] <archivefile> [-o output]\n"
+		"Default output path is ./out/\n"
+		"nParams:\n"
+		"-e <filename>     Extract only <filename> from the archive, wiil be extracted \n"
+		"                  into the current directory.\n"
+		"-x                Extract all files (default)\n"
+		"-a                Extract files from the Amiga .PAK files\n"
+		"-2                Extract files from HoF installer files\n");
 
-				exit(-1);
-			} else {
-				strcpy(singleFilename, argv[param]);
-			}
-		} else if (strcmp(argv[param], "-x") == 0) {
+	int param = first_arg;
+
+	// Parse our own arguments
+	for(; param < last_arg; ++param) {
+		if (strcmp(argv[param], "-x") == 0) {
 			extractAll = true;
+			extractOne = false;
 		} else if (strcmp(argv[param], "-a") == 0) {
 			isAmiga = true;
 		} else if (strcmp(argv[param], "-2") == 0) {
 			isHoFInstaller = true;
+		} else if (strcmp(argv[param], "-n") == 0) {
+			extractOne = true;
+			extractAll = false;
+
+			++param;
+
+			if (param >= last_arg) {
+				error("No filename supplied to -n\nShould be used on the form: %s -n ALGAE.CPS -o out/ A_E.PAK");
+			} else {
+				strcpy(singleFilename, argv[param]);
+			}
+		} else {
+			break;
 		}
 	}
 
-	if (param > argc)
-		showhelp(argv[0]);
+	// Parse output argument
+	if (parseOutputArguments(&outpath, argv, argc, param))
+		param += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, argc - 2))
+		last_arg -= 1;
+	else
+		outpath.setFullPath("out/");
 
+	// Extract files
+	if (first_arg != last_arg)
+		error("Expected only one input file.");
+
+	inputpath.setFullPath(argv[param]);
 	Extractor *extract = 0;
 	if (isHoFInstaller) {
-		extract = new HoFInstaller(argv[argc - 1]);
+		extract = new HoFInstaller(inputpath.getFullPath());
 	} else {
 		PAKFile *myfile = new PAKFile;
-		if (!myfile->loadFile(argv[argc - 1], isAmiga)) {
+		if (!myfile->loadFile(inputpath.getFullPath(), isAmiga)) {
 			delete myfile;
-			error("Couldn't load file '%s'", argv[argc - 1]);
+			error("Couldn't load file '%s'", inputpath.getFullPath());
 		}
 
 		extract = myfile;
 	}
 
-	getPath(argc[argv - 1], inputPath);
-
+	// Everything has been decided, do the actual extraction
 	if (extractAll) {
-		extract->outputAllFiles(inputPath);
+		extract->outputAllFiles(outpath.getFullPath());
 	} else if (extractOne) {
-		char outputFilename[1024];
-		snprintf(outputFilename, 1024, "%s/%s", inputPath, singleFilename);
-		extract->outputFileAs(singleFilename, outputFilename);
+		inputpath.setFullName(singleFilename);
+		extract->outputFileAs(singleFilename, inputpath.getFullPath());
 	} else {
 		extract->drawFileList();
 	}
@@ -99,4 +112,3 @@
 	delete extract;
 	return 0;
 }
-

Modified: tools/branches/gsoc2009-gui/extract_kyra.h
===================================================================
--- tools/branches/gsoc2009-gui/extract_kyra.h	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_kyra.h	2009-06-08 22:38:41 UTC (rev 41391)
@@ -31,7 +31,6 @@
 
 	virtual void drawFileList();
 
-	virtual bool outputAllFiles() { return outputAllFiles("./"); }
 	virtual bool outputAllFiles(const char *outputPath);
 
 	virtual bool outputFile(const char *file) { return outputFileAs(file, file); }

Modified: tools/branches/gsoc2009-gui/extract_loom_tg16.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_loom_tg16.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_loom_tg16.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -837,7 +837,8 @@
 				error("extract_resource(room) - length mismatch while extracting resource (was %04X, expected %04X)",rlen,r_length(res));
 			if (rtype != 0x01)
 				error("extract_resource(room) - resource tag is incorrect");
-			off = ftell(output);
+
+			off = (uint16)ftell(output);
 			rlen = 0;
 			write_clong(output, 0, &rlen);
 			write_cword(output, 'OR', &rlen); /* RO - Room */
@@ -1226,24 +1227,35 @@
 int main (int argc, char **argv) {
 #ifdef MAKE_LFLS
 	FILE *input, *output;
-	char fname[1024];
 	int i, j;
-	char inputPath[768];
 #else
 	FILE *input;
 	int i;
 #endif
 	uint32 CRC;
 
-	if (argc < 2) {
-		printf("\nUsage: %s <code_##.ISO>\n", argv[0]);
-		return 1;
-	}
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-	getPath(argv[argc - 1], inputPath);
-	input = fopen(argv[1], "rb");
+	char fname[256];
+	Filename inpath, outpath;
+
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc);
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
+	
+	input = fopen(argv[first_arg], "rb");
 	if (!input)
-		error("unable to open file %s for input", argv[1]);
+		error("unable to open file %s for input", argv[first_arg]);
 
 	InitCRC();
 	CRC = ISO_CRC(input);
@@ -1267,10 +1279,14 @@
 
 	for (i = 0; lfls[i].num != -1; i++) {
 		p_lfl lfl = &lfls[i];
-		sprintf(fname, "%s/%02i.LFL", inputPath, lfl->num);
-		output = fopen(fname, "wb");
+		sprintf(fname, "%02i.LFL", lfl->num);
+
+		outpath.setFullName(fname);
+		output = fopen(outpath.getFullPath(), "wb");
+
 		if (!output)
 			error("unable to create %s", fname);
+
 		notice("Creating %s...", fname);
 		for (j = 0; lfl->entries[j] != NULL; j++) {
 			p_resource entry = lfl->entries[j];
@@ -1301,11 +1317,12 @@
 
 		fclose(output);
 	}
-	sprintf(fname, "%s/00.LFL", inputPath);
-	output = fopen(fname, "wb");
+
+	outpath.setFullName("00.LFL");
+	output = fopen(outpath.getFullPath(), "wb");
 	if (!output)
 		error("Unable to create index file!");
-	notice("Creating %s...", fname);
+	notice("Creating 00.LFL...");
 
 	lfl_index.num_rooms = NUM_ROOMS;
 	lfl_index.num_costumes = NUM_COSTUMES;
@@ -1354,27 +1371,28 @@
 
 	fclose(output);
 
-	sprintf(fname, "%s/97.LFL", inputPath);
-	output = fopen(fname, "wb");
+	outpath.setFullName("97.LFL");
+	output = fopen(outpath.getFullPath(), "wb");
 	if (!output)
 		error("Unable to create charset file 97.LFL");
-	notice("Creating %s...", fname);
+
+	notice("Creating 97.LFL...");
 	extract_resource(input, output, &res_charset);
 	fclose(output);
 
-	sprintf(fname, "%s/98.LFL", inputPath);
-	output = fopen(fname, "wb");
+	outpath.setFullName("98.LFL");
+	output = fopen(outpath.getFullPath(), "wb");
 	if (!output)
 		error("Unable to create charset file 98.LFL");
-	notice("Creating %s...", fname);
+	notice("Creating 98.LFL...");
 	extract_resource(input, output, &res_charset);
 	fclose(output);
 
-	sprintf(fname, "%s/99.LFL", inputPath);
-	output = fopen(fname, "wb");
+	outpath.setFullName("99.LFL");
+	output = fopen(outpath.getFullPath(), "wb");
 	if (!output)
 		error("Unable to create charset file 99.LFL");
-	notice("Creating %s...", fname);
+	notice("Creating 99.LFL...");
 	extract_resource(input, output, &res_charset);
 	fclose(output);
 

Modified: tools/branches/gsoc2009-gui/extract_mm_apple.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_mm_apple.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_mm_apple.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -54,23 +54,38 @@
 
 int main (int argc, char **argv) {
 	FILE *input1, *input2, *output;
-	char fname[1024];
-	char inputPath[768];
 	int i, j;
 	unsigned short signature;
 
-	if (argc < 3) {
-		printf("\nUsage: %s <disk1.dsk> <disk2.dsk>\n", argv[0]);
-		exit(2);
-	}
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-	getPath(argv[argc - 1], inputPath);
+	char fname[256];
+	Filename inpath, outpath;
 
-	if (!(input1 = fopen(argv[1],"rb")))
-		error("Unable to open file %s for input!",argv[1]);
-	if (!(input2 = fopen(argv[2],"rb")))
-		error("Unable to open file %s for input!",argv[2]);
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc,
+		"\nUsage: %s [-o <output dir> = out/] <disk1.dsk> <disk2.dsk>\n");
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
 
+	if (last_arg - first_arg == 1)
+		error("Requires two disk files");
+
+	if (!(input1 = fopen(argv[first_arg],"rb")))
+		error("Unable to open file %s for input!",argv[first_arg]);
+	++first_arg;
+	if (!(input2 = fopen(argv[first_arg],"rb")))
+		error("Unable to open file %s for input!",argv[first_arg]);
+
 	fseek(input1, 142080, SEEK_SET);
 	fseek(input2, 143104, SEEK_SET);
 
@@ -83,7 +98,7 @@
 	if (signature != 0x0032)
 		error("Signature not found in disk 2!");
 
-	sprintf(fname, "%s/00.LFL", inputPath);
+	outpath.setFullName("00.LFL");
 	if (!(output = fopen(fname, "wb")))
 		error("Unable to create index file!");
 	notice("Creating 00.LFL...");
@@ -139,7 +154,8 @@
 		else
 			continue;
 
-		sprintf(fname, "%s/%02i.LFL", inputPath, i);
+		sprintf(fname, "%02i.LFL", i);
+		outpath.setFullName(fname);
 		output = fopen(fname, "wb");
 		if (output == NULL)
 			error("Unable to create %s!", fname);

Modified: tools/branches/gsoc2009-gui/extract_mm_c64.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_mm_c64.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_mm_c64.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -55,21 +55,38 @@
 
 int main (int argc, char **argv) {
 	FILE *input1, *input2, *output;
-	char fname[1024];
-	char inputPath[768];
 	int i, j;
 	unsigned short signature;
 
-	if (argc < 3) {
-		printf("\nUsage: %s <disk1.d64> <disk2.d64>\n", argv[0]);
-		exit(2);
-	}
-	getPath(argv[argc - 1], inputPath);
-	if (!(input1 = fopen(argv[1],"rb")))
-		error("Unable to open file %s for input!",argv[1]);
-	if (!(input2 = fopen(argv[2],"rb")))
-		error("Unable to open file %s for input!",argv[2]);
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
+	char fname[256];
+	Filename inpath, outpath;
+
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc,
+		"\nUsage: %s [-o <output dir> = out/] <disk1.d64> <disk2.d64>\n");
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
+
+	if (last_arg - first_arg == 1)
+		error("Requires two disk files");
+
+	if (!(input1 = fopen(argv[first_arg],"rb")))
+		error("Unable to open file %s for input!",argv[first_arg]);
+	++first_arg;
+	if (!(input2 = fopen(argv[first_arg],"rb")))
+		error("Unable to open file %s for input!",argv[first_arg]);
+
 	/* check signature */
 	signature = readUint16LE(input1);
 	if (signature != 0x0A31)
@@ -78,8 +95,8 @@
 	if (signature != 0x0132)
 		error("Signature not found in disk 2!");
 
-	sprintf(fname, "%s/00.LFL", inputPath);
-	if (!(output = fopen(fname, "wb")))
+	outpath.setFullName("00.LFL");
+	if (!(output = fopen(outpath.getFullPath(), "wb")))
 		error("Unable to create index file!");
 	notice("Creating 00.LFL...");
 
@@ -129,8 +146,9 @@
 		else
 			continue;
 
-		sprintf(fname, "%s/%02i.LFL", inputPath, i);
-		output = fopen(fname, "wb");
+		sprintf(fname, "%02i.LFL", i);
+		outpath.setFullName(fname);
+		output = fopen(outpath.getFullPath(), "wb");
 
 		if (output == NULL) {
 			error("Unable to create %s!", fname);

Modified: tools/branches/gsoc2009-gui/extract_mm_nes.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_mm_nes.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_mm_nes.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -1167,23 +1167,34 @@
 
 int main(int argc, char **argv) {
 	FILE *input, *output;
-	char fname[1024];
-	char inputPath[768];
 	int i, j;
 	uint32 CRC;
 
-	if (argc < 2) {
-		printf("\nUsage: %s <infile.PRG>\n", argv[0]);
-		printf("\tSupported versions: USA, Europe, Sweden, France, Germany, Spain\n");
-		printf("\tJapanese version is NOT supported!\n");
-		exit(2);
-	}
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-	getPath(argv[argc - 1], inputPath);
+	char fname[256];
+	Filename inpath, outpath;
 
-	if (!(input = fopen(argv[1], "rb")))
-		error("Unable to open file %s for input", argv[1]);
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc,
+		"\nUsage: %s [-o <output dir> = out/] <infile.PRG>\n"
+		"\tSupported versions: USA, Europe, Sweden, France, Germany, Spain\n"
+		"\tJapanese version is NOT supported!\n");
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
 
+	if (!(input = fopen(argv[first_arg], "rb")))
+		error("Unable to open file %s for input", argv[first_arg]);
+
 	if ((readByte(input) == 'N') && (readByte(input) == 'E') && (readByte(input) == 'S') && (readByte(input) == 0x1A)) {
 		printf("You have specified an iNES formatted ROM image, which is not supported.\n"
 			"You must input the PRG section only - see Maniac Mansion NES notes section of README.");
@@ -1232,11 +1243,14 @@
 
 	for (i = 0; lfls[i].num != -1; i++) {
 		const struct t_lfl *lfl = &lfls[i];
-		sprintf(fname, "%s/%02i.LFL", inputPath, lfl->num);
-		output = fopen(fname, "wb");
+
+		sprintf(fname, "%02i.LFL", lfl->num);
+		outpath.setFullName(fname);
+		output = fopen(outpath.getFullPath(), "wb");
 		if (!output)
 			error("Unable to create %s", fname);
 		notice("Creating %s...", fname);
+		
 		for (j = 0; lfl->entries[j].type != NULL; j++) {
 			const struct t_lflentry *entry = &lfl->entries[j];
 			switch (entry->type->type) {
@@ -1301,11 +1315,13 @@
 		writeUint16LE(output, 0xF5D1);
 		fclose(output);
 	}
-	sprintf(fname, "%s/00.LFL", inputPath);
-	output = fopen(fname, "wb");
+
+	outpath.setFullName("00.LFL");
+	output = fopen(outpath.getFullPath(), "wb");
 	if (!output)
 		error("Unable to create index file");
-	notice("Creating %s...", fname);
+	notice("Creating 00.LFL...");
+
 	writeUint16LE(output, 0x4643);
 	extract_resource(input, output, &res_globdata.langs[ROMset][0], res_globdata.type);
 	for (i = 0; i < (int)sizeof(struct t_lflindex); i++)

Modified: tools/branches/gsoc2009-gui/extract_parallaction.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_parallaction.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_parallaction.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -41,17 +41,17 @@
 	_file = NULL;
 }
 
-bool Archive::isPackedSubfile(byte* data) {
+bool Archive::isPackedSubfile(byte *data) {
 	return (data[0] == 'P' && data[1] == 'P' && data[2] == '2' && data[3] == '0');
 }
 
-uint32 Archive::getSizeOfPackedSubfile(byte* packedData, uint32 packedSize) {
-	uint32 size = *(uint32*)(packedData + packedSize - 4);
+uint32 Archive::getSizeOfPackedSubfile(byte *packedData, uint32 packedSize) {
+	uint32 size = *(uint32 *)(packedData + packedSize - 4);
 
 	return ((size & 0xFF00)) | ((size & 0xFF0000) >> 16);
 }
 
-int32 Archive::findSubfile(const char* filename) {
+int32 Archive::findSubfile(const char *filename) {
 	for (uint32 i = 0; i < _numFiles; i++) {
 		if (!scumm_stricmp(filename, _names[i])) return i;
 	}
@@ -59,7 +59,7 @@
 	return -1;
 }
 
-void Archive::unpackSubfile(byte* packedData, uint32 packedSize) {
+void Archive::unpackSubfile(byte *packedData, uint32 packedSize) {
 	ppdepack(packedData, _fileData, packedSize, _fileSize);
 }
 
@@ -82,13 +82,13 @@
 	uint32 srcOffset = _offsets[index];
 	uint32 srcSize = _sizes[index];
 
-	byte *srcData = (byte*)malloc(srcSize);
+	byte *srcData = (byte *)malloc(srcSize);
 	fseek(_file, srcOffset, SEEK_SET);
 	fread(srcData, 1, srcSize, _file);
 
 	if (isPackedSubfile(srcData)) {
 		_fileSize = getSizeOfPackedSubfile(srcData, srcSize);
-		_fileData = (byte*)malloc(_fileSize);
+		_fileData = (byte *)malloc(_fileSize);
 
 		unpackSubfile(srcData, srcSize);
 
@@ -99,7 +99,7 @@
 	}
 }
 
-void Archive::openSubfile(const char* filename) {
+void Archive::openSubfile(const char *filename) {
 
 	int32 index = findSubfile(filename);
 
@@ -110,14 +110,14 @@
 	return;
 }
 
-void Archive::readSubfile(byte* buf, uint32 size) {
+void Archive::readSubfile(byte *buf, uint32 size) {
 	assert(size + _filePos <= _fileSize);
 	memcpy(buf, _fileData + _filePos, size);
 	_filePos += size;
 	return;
 }
 
-void Archive::open(const char* filename, bool smallArchive) {
+void Archive::open(const char *filename, bool smallArchive) {
 	uint16 maxEntries = (smallArchive) ? 180 : 384;
 
 	_file = fopen(filename, "rb");
@@ -137,7 +137,7 @@
 	_numFiles = i;
 
 	if (_numFiles < maxEntries) {
-		uint32* t = (uint32*)_names[i];
+		uint32 *t = (uint32*)_names[i];
 
 		for (; i < (uint32)maxEntries + 1; i++) {
 			if (*t != 0)
@@ -173,16 +173,16 @@
 	return;
 }
 
-void Archive::dumpStructs(FILE* dump) {
+void Archive::dumpStructs(FILE *dump) {
 	char arcName[32];
 
-	char* s = strrchr(_name, '/');
+	char *s = strrchr(_name, '/');
 	if (s == NULL) {
 		s = strrchr(_name, '\\');
 		if (s == NULL) s = _name;
 	}
 
-	char* d = arcName;
+	char *d = arcName;
 
 	for (; *s; ) *d++ = toupper(*s++);
 	*d = '\0';
@@ -195,7 +195,7 @@
 
 #define val(p) ((p)[0]<<16 | (p)[1] << 8 | (p)[2])
 
-uint32  depackedlen(byte* packed, uint32 plen) {
+uint32  depackedlen(byte *packed, uint32 plen) {
 	if (packed[0] != 'P' || packed[1] != 'P' ||
 		packed[2] != '2' || packed[3] != '0')
 			return 0; /* not a powerpacker file */
@@ -224,7 +224,7 @@
 	return result;
 }
 
-void ppdepack(byte* packed, byte* depacked, uint32 plen, uint32 unplen) {
+void ppdepack(byte *packed, byte *depacked, uint32 plen, uint32 unplen) {
 	byte *dest;
 	int n_bits;
 	int idx;
@@ -298,7 +298,7 @@
 
 }
 
-void optDump(const char* file, const char* dir, bool smallArchive) {
+void optDump(const char *file, Filename *outpath, bool smallArchive) {
 	Archive arc;
 	arc.open(file, smallArchive);
 
@@ -306,41 +306,42 @@
 
 		arc.openSubfile(i);
 
-		char path[260];
-		strcpy(path, dir);
+		char filename[260], * d = filename;
 
-		char *d = path + (strlen(path) - 1);
-		if (*d == '/')
-			d++;
-		else {
-			if (*d != '\\')
-				d++;
-			*d++ = '/';
-			*d = '\0';
-		}
-
 		for (char *s = arc._names[i]; *s; s++, d++)
 			*d = *s == '/' ? '_' : *s;
-
 		*d = '\0';
 
-		FILE* ofile = fopen(path, "wb");
+		outpath->setFullName(d);
+
+		FILE *ofile = fopen(outpath->getFullPath(), "wb");
 		fwrite(arc._fileData, 1, arc._fileSize, ofile);
 		fclose(ofile);
 	}
 }
 
 int main(int argc, char *argv[]) {
+	Filename outpath;
 
-	if (argc < 3) {
-		printf("\nUsage: %s [--small] <file> <outputdir>\n", argv[0]);
-		exit(1);
-	}
+	parseHelpArguments(argv, argc,
+		"\nUsage: %s [--small] [-o <output dir> = out/] <file>\n");
 
-	if (!strcmp(argv[1], "--small")) {
-		optDump(argv[2], argv[3], true);
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	int arg = 1;
+	if (parseOutputArguments(&outpath, argv, argc, 1))
+		arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, argc - 3))
+		arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
+	
+
+	if (strcmp(argv[arg], "--small") == 0) {
+		optDump(argv[arg], &outpath, true);
 	} else {
-		optDump(argv[1], argv[2], false);
+		optDump(argv[arg], &outpath, false);
 	}
 
 	return 0;

Modified: tools/branches/gsoc2009-gui/extract_scumm_mac.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_scumm_mac.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_scumm_mac.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -31,25 +31,34 @@
 	unsigned long file_record_off, file_record_len;
 	unsigned long file_off, file_len;
 	unsigned long data_file_len;
-	char fname[1024];
-	char inputPath[768];
 	char file_name[0x20];
 	char *buf;
 	unsigned long i;
 	int j;
 
-	if (argc != 2) {
-		printf("\nUsage: %s <file>\n", argv[0]);
-		printf("\nNote: Some Lucas Arts CDs appear to contains only an application.\n");
-		printf("They actually contain a seperate data file as an invisible file.\n");
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-		exit(2);
-	}
+	Filename outpath;
 
-	getPath(argv[argc - 1], inputPath);
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc,
+		"\nUsage: %s [-o <output dir> = out/] <file>\n"
+		"\tSome Lucas Arts CDs appear to contains only an application.\n"
+		"\tThey actually contain a seperate data file as a hidden file.\n");
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
 
-	if ((ifp = fopen(argv[1], "rb")) == NULL) {
-		error("Could not open \'%s\'.", argv[1]);
+	if ((ifp = fopen(argv[first_arg], "rb")) == NULL) {
+		error("Could not open \'%s\'.", argv[first_arg]);
 	}
 
 	/* Get the length of the data file to use for consistency checks */
@@ -62,13 +71,13 @@
 	/* Do a quick check to make sure the offset and length are good */
 	if (file_record_off + file_record_len > data_file_len) {
 		fclose(ifp);
-		error("\'%s\'. file records out of bounds.", argv[1]);
+		error("\'%s\'. file records out of bounds.", argv[first_arg]);
 	}
 
 	/* Do a little consistancy check on file_record_length */
 	if (file_record_len % 0x28) {
 		fclose(ifp);
-		error("\'%s\'. file record length not multiple of 40.", argv[1]);
+		error("\'%s\'. file record length not multiple of 40.", argv[first_arg]);
 	}
 
 	/* Extract the files */
@@ -85,7 +94,7 @@
 
 		if (!file_name[0]) {
 			fclose(ifp);
-			error("\'%s\'. file has no name.", argv[1]);
+			error("\'%s\'. file has no name.", argv[first_arg]);
 		}
 		printf("extracting \'%s\'", file_name);
 
@@ -109,7 +118,7 @@
 		if (j == 0x20) {
 			file_name[0x1f] = 0;
 			fprintf(stderr, "\nwarning: \'%s\'. file name not null terminated.\n", file_name);
-			fprintf(stderr, "data file \'%s\' may be not a file extract_scumm_mac can extract.\n", argv[1]);
+			fprintf(stderr, "data file \'%s\' may be not a file extract_scumm_mac can extract.\n", argv[first_arg]);
 		}
 
 		printf(", saving as \'%s\'\n", file_name);
@@ -117,7 +126,7 @@
 		/* Consistency check. make sure the file data is in the file */
 		if (file_off + file_len > data_file_len) {
 			fclose(ifp);
-			error("\'%s\'. file out of bounds.", argv[1]);
+			error("\'%s\'. file out of bounds.", argv[first_arg]);
 		}
 
 		/* Write a file */
@@ -126,8 +135,8 @@
 			error("Seek error.");
 		}
 
-		sprintf(fname, "%s/%s", inputPath, file_name);
-		ofp = fopen(fname, "wb");
+		outpath.setFullName(file_name);
+		ofp = fopen(outpath.getFullPath(), "wb");
 
 		if (!(buf = (char *)malloc(file_len))) {
 			fclose(ifp);

Modified: tools/branches/gsoc2009-gui/extract_zak_c64.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_zak_c64.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/extract_zak_c64.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -55,22 +55,38 @@
 
 int main (int argc, char **argv) {
 	FILE *input1, *input2, *output;
-	char fname[1024];
-	char inputPath[768];
 	int i, j;
 	unsigned short signature;
 
-	if (argc < 3) {
-		printf("\nUsage: %s <disk1.d64> <disk2.d64>\n",argv[0]);
-		exit(2);
-	}
+	int first_arg = 1;
+	int last_arg = argc - 1;
 
-	getPath(argv[argc - 1], inputPath);
-	if (!(input1 = fopen(argv[1],"rb")))
-		error("Unable to open file %s for input!",argv[1]);
-	if (!(input2 = fopen(argv[2],"rb")))
-		error("Unable to open file %s for input!",argv[2]);
+	char fname[1024];
+	Filename outpath;
 
+	// Check if we should display some heplful text
+	parseHelpArguments(argv, argc,
+		"\nUsage: %s [-o <output dir> = out/] <disk1.d64> <disk2.d64>\n");
+	
+	// Continuing with finding out output directory
+	// also make sure we skip those arguments
+	if (parseOutputArguments(&outpath, argv, argc, first_arg))
+		first_arg += 2;
+	else if (parseOutputArguments(&outpath, argv, argc, last_arg - 2))
+		last_arg -= 2;
+	else
+		// Standard output dir
+		outpath.setFullPath("out/");
+
+	if (last_arg - first_arg == 1)
+		error("Requires two disk files");
+
+	if (!(input1 = fopen(argv[first_arg],"rb")))
+		error("Unable to open file %s for input!",argv[first_arg]);
+	++first_arg;
+	if (!(input2 = fopen(argv[first_arg],"rb")))
+		error("Unable to open file %s for input!",argv[first_arg]);
+
 	/* check signature */
 	signature = readUint16LE(input1);
 	if (signature != 0x0A31)
@@ -78,10 +94,10 @@
 	signature = readUint16LE(input2);
 	if (signature != 0x0132)
 		error("Signature not found in disk 2!");
-	sprintf(fname, "%s/00.LFL", inputPath);
-	if (!(output = fopen(fname, "wb")))
+	outpath.setFullName("00.LFL");
+	if (!(output = fopen(outpath.getFullPath(), "wb")))
 		error("Unable to create index file!");
-	notice("Creating %s...", fname);
+	notice("Creating 00.LFL...");
 
 	/* write signature */
 	writeUint16LE(output, signature);
@@ -132,14 +148,15 @@
 		else
 			continue;
 
-		sprintf(fname,"%s/%02i.LFL", inputPath, i);
-		output = fopen(fname, "wb");
+		sprintf(fname,"%02i.LFL", i);
+		outpath.setFullName(fname);
+		output = fopen(outpath.getFullPath(), "wb");
 
 		if (output == NULL) {
-			error("Unable to create %s!",fname);
+			error("Unable to create %s!", fname);
 		}
 
-		notice("Creating %s...",fname);
+		notice("Creating %s...", fname);
 		fseek(input, (SectorOffset[room_tracks[i]] + room_sectors[i]) * 256, SEEK_SET);
 
 		for (j = 0; j < ResourcesPerFile[i]; j++) {

Modified: tools/branches/gsoc2009-gui/util.cpp
===================================================================
--- tools/branches/gsoc2009-gui/util.cpp	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/util.cpp	2009-06-08 22:38:41 UTC (rev 41391)
@@ -146,48 +146,96 @@
 	return sz;
 }
 
-void getPath(const char *fullpath, char *path) {
-	const char *p;
+Filename::Filename(const char *path) {
+	strcpy(_path, path);
+}
 
-	/* Find the last occurence of '/' or '\'
-	 * Everything before this point is the path
-	 * Everything after this point is the filename
-	 */
-	p = strrchr(fullpath, '/');
-	if (!p) {
-		p = strrchr(fullpath, '\\');
+void Filename::setFullPath(const char *path) {
+	strcpy(_path, path);
+}
 
-		if (!p) {
-			p = fullpath - 1;
-		}
+Filename *Filename::setFullName(const char *newname) {
+	char p[1024];
+	if (getPath(p)) {
+		strcat(p, newname);
+		strcpy(_path, p);
+		return this;
 	}
+	return NULL;
+}
 
-	/* The path is everything before p, unless the file is in the current
-	 * directory, in which case the path is '.'
-	 */
-	if (p < fullpath) {
-		strcpy(path, ".");
-	} else {
-		strncpy(path, fullpath, p - fullpath);
-		path[strlen(fullpath) - strlen(p)] = '\0';
+void Filename::addExtension(const char *ext) {
+	strcat(_path, ext);
+}
+
+bool Filename::empty() const {
+	return *_path == 0;
+}
+
+const char *Filename::getFullPath() const {
+	return _path;
+}
+
+const char *Filename::getFullName(char *out) const {
+	const char *slash;
+	if ((slash = strrchr(_path, '/')) || (slash = strrchr(_path, '\\'))) {
+		strcpy(out, slash + 1);
+		return out;
 	}
+	return NULL;
 }
 
-void getFilename(const char *fullpath, char *filename) {
-	const char *p;
+const char *Filename::getFullName() const {
+	const char *slash;
+	if ((slash = strrchr(_path, '/')) || (slash = strrchr(_path, '\\'))) {
+		return slash + 1;
+	}
+	return NULL;
+}
 
-	/* Find the last occurence of '/' or '\'
-	 * Everything before this point is the path
-	 * Everything after this point is the filename
-	 */
-	p = strrchr(fullpath, '/');
-	if (!p) {
-		p = strrchr(fullpath, '\\');
+const char *Filename::getPath(char *out) const {
+	const char *slash;
+	if ((slash = strrchr(_path, '/')) || (slash = strrchr(_path, '\\'))) {
+		int end = strlen(_path) - strlen(slash) + 1;
+		strncpy(out, _path, end);
+		out[end] = 0;
+		return out;
+	}
+	// If there was no '/', this was a relative path
+	strcpy(out, _path);
+	return out;
+}
 
-		if (!p) {
-			p = fullpath - 1;
+void parseHelpArguments(const char * const argv[], int argc, const char *msg) {
+	if (argc < 2 || strcmp(argv[1], "--help") == 0 || stricmp(argv[1], "-h") == 0) {
+		if (!msg) {
+			printf("\nUsage: %s [-o <output dir> = out/] <file 1> ... <file n>\n", argv[0]);
 		}
+		else {
+			printf(msg, argv[0]);
+		}
+		exit(2);
 	}
+}
 
-	strcpy(filename, p + 1);
+bool parseOutputArguments(Filename *outputname, const char * const argv[], int argc, int start_arg) {
+	char lastchr;
+
+	if (start_arg >= 0 && (strcmp(argv[start_arg], "-o") == 0 || strcmp(argv[start_arg], "--output") == 0)) {
+		/* It's a -o argument, can we check next arg? */
+
+		if (start_arg + 1 < argc) {
+			outputname->setFullPath(argv[start_arg + 1]);
+
+			/* Ensure last character is a /, this way we force directory output */
+			lastchr = outputname->getFullPath()[strlen(outputname->getFullPath()) - 1];
+			if (lastchr != '/' && lastchr != '\\') {
+				strcat(outputname->_path, "/");
+			}
+			return true;
+		} else {
+			error("Expected directory path after '-o' or '--output'.");
+		}
+	}
+	return false;
 }

Modified: tools/branches/gsoc2009-gui/util.h
===================================================================
--- tools/branches/gsoc2009-gui/util.h	2009-06-08 22:18:52 UTC (rev 41390)
+++ tools/branches/gsoc2009-gui/util.h	2009-06-08 22:38:41 UTC (rev 41391)
@@ -158,7 +158,7 @@
 	return (b[0] << 8) + b[1];
 }
 FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) {
-	const byte *b = (const byte*)ptr;
+	const byte *b = (const byte *)ptr;
 	return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + (b[3]);
 }
 FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) {
@@ -204,7 +204,26 @@
 void warning(const char *s, ...);
 void debug(int level, const char *s, ...);
 void notice(const char *s, ...);
-void getPath(const char *fullpath, char *path);
-void getFilename(const char *fullpath, char *filename);
 
+struct Filename {
+	char _path[1024];
+
+	Filename(const char *path = "");
+
+	void setFullPath(const char *path);
+	Filename *setFullName(const char *name);
+	void addExtension(const char *ext);
+
+	bool empty() const;
+
+	const char *getFullPath() const;
+	const char *getFullName() const;
+	const char *getFullName(char *out) const;
+	const char *getPath(char *out) const;
+};
+
+void parseHelpArguments(const char * const argv[], int argc, const char *msg = NULL);
+bool parseOutputArguments(Filename *outputname, const char * const argv[], int argc, int start_arg);
+
+
 #endif


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list