/*	Tool to convert SpiderMonkey error code table (in js.msg) into a plist for
	our error reporter. Requires some pre-massaging of js.msg to turn it into
	an ASCII plist array of arrays.
*/


#import <Foundation/Foundation.h>


void Handle1Spec(NSArray *spec);
NSString *ConvertName(NSString *name);


int main (int argc, const char * argv[])
{
	[NSAutoreleasePool new];
	
	if (argc < 2)
	{
		fprintf(stderr, "Specify path to js.msg.\n");
		return EXIT_FAILURE;
	}
	
	NSString *jsmsg = [NSString stringWithContentsOfFile:[NSString stringWithUTF8String:argv[1]]];
	if (jsmsg == nil)
	{
		fprintf(stderr, "Can't find %s.\n", argv[1]);
		return EXIT_FAILURE;
	}
	
	// Hit it with a hammer until it looks like an OpenStep plist array of arrays
	NSArray *components = [jsmsg componentsSeparatedByString:@")\n"];
	jsmsg = [components componentsJoinedByString:@"),\n"];
	
	jsmsg = [[@"(\n" stringByAppendingString:jsmsg] stringByAppendingString:@"())\n"];
	jsmsg = [[jsmsg componentsSeparatedByString:@"MSG_DEF"] componentsJoinedByString:@""];
	
	NSString *errorString = nil;
	NSArray *errors = [NSPropertyListSerialization propertyListFromData:[jsmsg dataUsingEncoding:NSASCIIStringEncoding]
													   mutabilityOption:NSPropertyListImmutable
																 format:NULL
													   errorDescription:&errorString];
	if (errors == nil)
	{
		fprintf(stderr, "Parse error: %s\n\n--\n%s\n", [errorString UTF8String], [jsmsg UTF8String]);
		return EXIT_FAILURE;
	}
	
	printf("// Identifiers for JavaScript error and warning codes\n// Automatically generated by JSErrorMunger.m\n\n{\n");
	for (NSArray *spec in errors)
	{
		Handle1Spec(spec);
	}
	printf("}\n");
	
	return EXIT_SUCCESS;
}


void Handle1Spec(NSArray *spec)
{
	if (spec.count < 2)  return;
	
	NSString *name = [spec objectAtIndex:0];
	NSNumber *index = [spec objectAtIndex:1];
	
	name = ConvertName(name);
	
	printf("\t\"%u\" = \"%s\";\n", [index intValue], [name UTF8String]);
}


NSString *ConvertName(NSString *name)
{
	if ([name isEqualToString:@"JSMSG_USER_DEFINED_ERROR"])
	{
		// Don't want "Error" here because it's also used for warnings.
		return @"ooliteDefined";
	}
	
	NSArray *components = [[name substringFromIndex:6] componentsSeparatedByString:@"_"];
	NSMutableString *result = [NSMutableString string];
	
	NSDictionary *specialCases = [NSDictionary dictionaryWithObjectsAndKeys:
								  @"XML", @"XML",
								  @"XMLList", @"XMLLIST",
								  @"XDR", @"XDR",
								  @"RHS", @"RHS",
								  @"LHS", @"LHS",
								  @"ID", @"ID",
								  @"URI", @"URI",
								  @"URL", @"URL",
								  @"newRegExp", @"NEWREGEXP",
								  @"NCR", @"NCR",
								  @"UTF8", @"UTF8",
								  @"NS", @"NS",
								  @"oolite", @"USER",
								  @"Assignment", @"ASS",
								  nil];
	
	for (NSString *comp in components)
	{
		NSString *converted = [specialCases objectForKey:comp];
		if (converted == nil)
		{
			if (result.length == 0)  converted = [comp lowercaseString];
			else  converted = [comp capitalizedString];
		}
		
		[result appendString:converted];
	}
	
	return result;
}
