diff options
author | Jonathan Kew <jfkthame@googlemail.com> | 2006-10-06 09:54:57 +0000 |
---|---|---|
committer | Jonathan Kew <jfkthame@googlemail.com> | 2006-10-06 09:54:57 +0000 |
commit | d449c410a7ca823910ac416ca5dd9604b16cdd89 (patch) | |
tree | e1b4be6ce833b14b8f823d2f25e7317950009c2a /Build/source/texk/xdv2pdf/SimplePSInterpreter.m | |
parent | 65e25e4262054c29d9bf925b5362ebea5b1385d8 (diff) |
added xdv2pdf driver for xetex (on OS X only)
git-svn-id: svn://tug.org/texlive/trunk@2246 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/xdv2pdf/SimplePSInterpreter.m')
-rw-r--r-- | Build/source/texk/xdv2pdf/SimplePSInterpreter.m | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/Build/source/texk/xdv2pdf/SimplePSInterpreter.m b/Build/source/texk/xdv2pdf/SimplePSInterpreter.m new file mode 100644 index 00000000000..230bb98a49c --- /dev/null +++ b/Build/source/texk/xdv2pdf/SimplePSInterpreter.m @@ -0,0 +1,851 @@ +// +// SimplePSInterpreter.m +// T1Wrap +// +// Created by Massimiliano Gubinelli on 10/02/2005. +// Copyright 2005 Massimiliano Gubinelli. All rights reserved. +// + +// Based on a Perl script by Jonathan Kew (February 2005) + +#import "SimplePSInterpreter.h" + +static NSString *SimplePSInterpreterException = @"SimplePSInterpreterException"; + +@interface NSMutableArray (Stack) +- pop; +@end + +@implementation NSMutableArray (Stack) +- pop +{ + id value = [[[self lastObject] retain] autorelease]; + [self removeLastObject]; + return value; +} +@end + +@interface SimplePSInterpreter (Private) +- (void) execProc:(NSArray *)proc; +- (void) execObj:(id)obj; +- (void) execName:(NSString *)identifier; + +// PS operators +- (void) opString; +- (void) opReadstring; +- (void) opDef; +- (void) opNot; +- (void) opDict; +- (void) opBegin; +- (void) opEnd; +- (void) opPop; +- (void) opDup; +- (void) opNop; +- (void) opGet; +- (void) opPut; +- (void) opGetinterval; +- (void) opPutinterval; +- (void) opArray; +- (void) opMark; +- (void) opCleartomark; +- (void) opExch; +- (void) opIndex; +- (void) opFor; +- (void) opKnown; +- (void) opIf; +- (void) opIfelse; +- (void) opCurrentdict; +- (void) opCurrentfile; +- (void) opClosefile; +- (void) opDefinefont; +- (void) opEexec; +- (void) opExec; +- (void) opNe; +- (void) opEq; +- (void) initializeInterpreter; +@end // interface + +@implementation SimplePSInterpreter + +static NSString *StackMarkObject = @" MARK "; +static NSString *NullPSObject = @"[NIL]"; + +- (void) opString +{ + int n = 0; + id obj = [stack pop]; + if (![obj isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException format:@"string parameter is not a number"]; + else n = [obj intValue]; +#if 0 + NSMutableString *emptyString = [NSMutableString stringWithCapacity:[(NSNumber*)obj intValue]]; + while (n--) [emptyString appendString:@" "]; + [stack addObject:emptyString]; +#else +// char *ss = alloca(n+1); + char *ss = alloca(n); +// ss[n] = 0x0; + int i = n; + while (i) ss[--i] = ' '; +// [stack addObject:[NSString stringWithCString:ss length:n]]; + [stack addObject:[[NSString alloc] initWithBytes:ss length:n encoding:NSMacOSRomanStringEncoding]]; +#endif + +} + +- (void) opReadstring +{ + id stringobj = [stack pop]; + id fileobj = [stack pop]; + if (![fileobj isKindOfClass:[NSString class]] || ![stringobj isKindOfClass:[NSString class]] ) + [NSException raise:SimplePSInterpreterException format:@"wrong arguments in readstring"]; + if (![(NSString*)fileobj isEqualToString:@" <FILE> "]) + [NSException raise:SimplePSInterpreterException format:@"cannot read string from file %@",fileobj]; + int len = [(NSString*)stringobj length]; + + NSString *dataString = [inputStream substringWithRange:NSMakeRange([sc scanLocation]+1,len)]; + [sc setScanLocation:[sc scanLocation]+1+len]; // skip whitespace & data string + [stack addObject:dataString]; + [stack addObject:[NSNumber numberWithInt:1]]; +} + +- (void) opDef +{ + id obj = [stack pop]; + id nameobj = [stack pop]; + if (![nameobj isKindOfClass:[NSString class]]) + [NSException raise:SimplePSInterpreterException format:@"defining non name"]; + else { + NSString *name = nameobj; + if ([name characterAtIndex:0] != '/') NSLog(@"Warning: defining non literal name"); + [(NSMutableDictionary*)[dicts lastObject] setObject:obj forKey:name]; + [(NSMutableArray*)[(NSDictionary*)[dicts lastObject] objectForKey:@"[KEY ORDER]"] addObject:name]; + } +} + +- (void) opNot +{ + id myBool = [stack pop]; + if ([myBool isKindOfClass:[NSNumber class]]) { + [stack addObject:[NSNumber numberWithInt:([(NSNumber*)myBool intValue]? 0 : 1)]]; + } + else [NSException raise:SimplePSInterpreterException format:@"cannot apply <not> to non-boolean object"]; +} + +- (void) opNe +{ + id a = [stack pop]; + id b = [stack pop]; + [stack addObject:[NSNumber numberWithInt:([a isEqualTo:b] ? 0 : 1 )]]; +} + + +- (void) opEq +{ + id a = [stack pop]; + id b = [stack pop]; + [stack addObject:[NSNumber numberWithInt:([a isEqualTo:b] ? 1 : 0 )]]; +} + +- (void) execProc:(NSArray *)procwrapper +{ + NSArray *proc = [procwrapper objectAtIndex:1]; + NSEnumerator *en = [proc objectEnumerator]; + id obj; + while ((obj = [en nextObject])) { + [self execObj:obj]; + } +} + +- (void) execObj:(id)obj +{ + if ([obj isKindOfClass:[NSInvocation class]]) + { + [(NSInvocation*)obj setTarget:self]; + [(NSInvocation*)obj invoke]; + } else if ([obj isKindOfClass:[NSArray class]]) + { +#if 1 + NSString *type = [(NSArray*)obj objectAtIndex:0]; + if ([type isEqualToString:@"proc"]) [self execProc:obj]; + else +#endif + [stack addObject:obj]; + + } else if ([obj isKindOfClass:[NSString class]]) + { + NSString *identifier = obj; + if ([identifier characterAtIndex:0]=='/') + [stack addObject:identifier]; + else + [self execName:identifier]; + } else + [stack addObject:obj]; +} + +- (void) execName:(NSString *)identifier +{ + NSEnumerator *en = [dicts reverseObjectEnumerator]; + NSDictionary *d; + id value = nil; + while (d = [en nextObject]) { + if (!(value = [d objectForKey:identifier])) value = [d objectForKey:[@"/" stringByAppendingString:identifier]]; + if (value) break; + } + + if (value) { + [self execObj: value]; + } + else { + [stack addObject:identifier]; + } +} + +- (void) opDict +{ + id obj = [stack pop]; + if (![obj isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException format:@"wrong type argument for dict"]; + NSMutableDictionary *newDict = [NSMutableDictionary dictionaryWithCapacity:[(NSNumber*)obj intValue]+1]; + [newDict setObject:[NSMutableArray arrayWithCapacity:[(NSNumber*)obj intValue]] + forKey:@"[KEY ORDER]"]; // KEY ORDER auxiliary array + [stack addObject:newDict]; +} + + +- (void) opBegin +{ + id obj = [stack pop]; + if (![obj isKindOfClass:[NSDictionary class]]) + [NSException raise:SimplePSInterpreterException format:@"wrong type argument for begin, expecting a dictionary"]; + [dicts addObject:obj]; +} + + +- (void) opEnd +{ + if ([dicts count]==0) + [NSException raise:SimplePSInterpreterException format:@"dictionary stack underflow"]; + [dicts removeLastObject]; +} + +- (void) opPop +{ + [stack removeLastObject]; +} + +- (void) opDup +{ +#if 0 + id aCopy = [[stack lastObject] copy]; + [stack addObject:aCopy]; + [aCopy release]; +#else + id aCopy = [stack lastObject]; + [stack addObject:aCopy]; +#endif +} + +- (void) opNop +{ +} + +- (void) opGet +{ + id key = [stack pop]; + id target = [stack pop]; + if ([target isKindOfClass:[NSArray class]]) + { + if (![key isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"wrong type argument for get, key should be a number"]; + + [stack addObject:[(NSArray*)[(NSArray*)target objectAtIndex:1] objectAtIndex:[(NSNumber*)key intValue]]]; + } else if ([target isKindOfClass:[NSDictionary class]]) { + if (![key isKindOfClass:[NSString class]]) + [NSException raise:SimplePSInterpreterException + format:@"wrong type argument for get, key should be a number"]; + if ([(NSString*)key characterAtIndex:0] != '/') + [NSException raise:SimplePSInterpreterException + format:@"expecting literal dictionary key for get"]; + id value = [(NSDictionary*)target objectForKey:key]; + if (value) + [stack addObject:value]; + else + [stack addObject:NullPSObject]; + } else + [NSException raise:SimplePSInterpreterException + format:@"applying get to nonarray/dict"]; +} + +- (void) opPut +{ + id value = [stack pop]; + id key = [stack pop]; + id target = [stack pop]; + if ([target isKindOfClass:[NSArray class]]) + { + if (![key isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"wrong type argument for put, key should be a number"]; + + [(NSMutableArray*)[(NSArray*)target objectAtIndex:1] replaceObjectAtIndex:[(NSNumber*)key intValue] + withObject:value]; + } else if ([target isKindOfClass:[NSDictionary class]]) { + if (![key isKindOfClass:[NSString class]]) + [NSException raise:SimplePSInterpreterException + format:@"wrong type argument for put, key should be a number"]; + if ([(NSString*)key characterAtIndex:0] != '/') + [NSException raise:SimplePSInterpreterException + format:@"expecting literal dictionary key for put"]; + + [(NSMutableDictionary*)target setObject:value forKey:key]; + [(NSMutableArray*)[(NSMutableDictionary*)target objectForKey:@"[KEY ORDER]"] + addObject:key]; + } else + [NSException raise:SimplePSInterpreterException + format:@"applying put to nonarray/dict"]; + +} + + +- (void) opGetinterval +{ + id count = [stack pop]; + id index = [stack pop]; + id array = [stack pop]; + if ([array isKindOfClass:[NSArray class]]) { + if ([count isKindOfClass:[NSNumber class]] && [index isKindOfClass:[NSNumber class]]) + [stack addObject:[NSArray arrayWithObjects:@"array",[(NSArray*)[(NSArray*)array objectAtIndex:1] subarrayWithRange: + NSMakeRange([(NSNumber*)index intValue],[(NSNumber*)count intValue])],nil]]; + else + [NSException raise:SimplePSInterpreterException + format:@"applying getinterval with nonnumber count or index"]; + } + else + [NSException raise:SimplePSInterpreterException + format:@"applying getinterval to nonarray"]; + +} + +- (void) opPutinterval +{ + id array2 = [stack pop]; + id index = [stack pop]; + id array = [stack pop]; + if ([array isKindOfClass:[NSArray class]]) { + if (![array2 isKindOfClass:[NSArray class]]) + [NSException raise:SimplePSInterpreterException + format:@"using putinterval with nonarray source"]; + if (![index isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"using putinterval with nonnumber index"]; + NSArray *source = [(NSArray*)array2 objectAtIndex:1]; + int count = [array2 count]; + [(NSMutableArray*)[(NSArray*)array objectAtIndex:1] + replaceObjectsInRange:NSMakeRange([(NSNumber*)index intValue],count) + withObjectsFromArray:source + range:NSMakeRange(0,count)]; + } + else + [NSException raise:SimplePSInterpreterException + format:@"applying putinterval to nonarray"]; +} + +- (void) opArray +{ + id countobj = [stack pop]; + if (![countobj isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"using array with nonnumber count"]; + int count = [countobj intValue]; + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:count]; + while(count--) [array addObject:NullPSObject]; + [stack addObject:[NSArray arrayWithObjects:@"array",array,nil]]; + [array release]; +} + +- (void) opMark +{ + [stack addObject:StackMarkObject]; +} + +- (void) opCleartomark +{ + id obj; + while ((obj = [stack lastObject])) { + if (obj == StackMarkObject) break; + [stack removeLastObject]; + } + if (obj) [stack removeLastObject]; +} + +- (void) opExch +{ + id a = [stack pop]; + id b = [stack pop]; + [stack addObject:a]; + [stack addObject:b]; +} + +- (void) opIndex +{ + id index = [stack pop]; + if (![index isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"using index with nonnumber count"]; + [stack addObject:[stack objectAtIndex:[stack count]-[(NSNumber*)index intValue]-1]]; +} + +- (void) opFor +{ + id proc = [stack pop]; + id limitobj = [stack pop]; + id stepobj = [stack pop]; + id startobj = [stack pop]; + if ([limitobj isKindOfClass:[NSNumber class]] && + [stepobj isKindOfClass:[NSNumber class]] && + [startobj isKindOfClass:[NSNumber class]] && + [proc isKindOfClass:[NSArray class]] ) { + int limit = [(NSNumber*)limitobj intValue]; + int step = [(NSNumber*)stepobj intValue]; + int start = [(NSNumber*)startobj intValue]; + for ( ;start <= limit;start += step) { + [stack addObject:[NSNumber numberWithInt:start]]; + [self execProc: proc]; + }; + } + else + [NSException raise:SimplePSInterpreterException + format:@"wrong arguments in for"]; + +} + + +- (void) opKnown +{ + id key = [stack pop]; + id dict = [stack pop]; + [stack addObject:[NSNumber numberWithInt:([(NSDictionary*)dict objectForKey:key] ? 1 : 0)]]; +} + +- (void) opIf +{ + id trueproc = [stack pop]; + id condition = [stack pop]; + + if (![condition isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"condition in if is not a boolean"]; + + if ([(NSNumber*)condition intValue]) [self execProc:trueproc]; +} + +- (void) opIfelse +{ + id falseproc = [stack pop]; + id trueproc = [stack pop]; + id condition = [stack pop]; + + if (![condition isKindOfClass:[NSNumber class]]) + [NSException raise:SimplePSInterpreterException + format:@"condition in ifelse is not a boolean"]; + + if ([(NSNumber*)condition intValue]) + [self execProc:trueproc]; + else [self execProc:falseproc]; +} + +- (void) opCurrentdict +{ + [stack addObject:[dicts lastObject]]; +} + +- (void) opCurrentfile +{ + [stack addObject:@" <FILE> "]; +} + +- (void) opClosefile +{ + [stack pop]; +} + +- (void) opDefinefont +{ + id font = [stack pop]; + id key = [stack pop]; + [fontDir setObject:font forKey:key]; + [stack addObject:font]; +} + +NSString *decryptString(NSString *inString) +{ + unsigned const char *inbuf = [inString cString]; + unsigned long insize = [inString cStringLength]; + NSMutableData *result = [NSMutableData dataWithLength:insize]; + unsigned char *outbuf = [result mutableBytes]; + unsigned short R = 55665; /* key */ + unsigned short c1 = 52845; + unsigned short c2 = 22719; + unsigned long counter; + + for(counter = 0; counter < insize; counter++) { + outbuf[counter] = (inbuf[counter] ^ (R>>8)); + R = (inbuf[counter] + R) * c1 + c2; + } +// NSString *resString = [NSString stringWithCString:outbuf length:insize]; + NSString *resString = [[NSString alloc] initWithData:result encoding:NSMacOSRomanStringEncoding]; + return resString; +} + +- (void) opEexec +{ + id fileobj = [stack pop]; + [sc scanCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] + intoString:nil]; + int startLoc = [sc scanLocation]; + NSString *dataString; + if ([sc scanUpToString:@"00000000000000000000" intoString:&dataString]) + { + NSString *decryptedStream = decryptString(dataString); + [inputStream deleteCharactersInRange:NSMakeRange(startLoc,[inputStream length]-startLoc)]; + [inputStream appendString:[decryptedStream substringFromIndex:4]]; // skip first 4 characters + [sc setScanLocation:startLoc]; + } else + [NSException raise:SimplePSInterpreterException + format:@"cannot find end of stream in eexec"]; +} + + + +- (void) opExec +{ + id obj = [stack pop]; + if ([obj isKindOfClass:[NSString class]]) [self execName:obj]; + if ([obj isKindOfClass:[NSArray class]] && [(NSString*)[(NSArray*)obj objectAtIndex:0] isEqualToString:@"proc"]) + { + [self execProc:obj]; + } + else [NSException raise:SimplePSInterpreterException + format:@"unimplemented exec feature"]; +} + +- (void) opCount +{ + [stack addObject:[NSNumber numberWithInt:[stack count]]]; +} + +- (void) opType +{ + id obj = [stack pop]; + NSString *type = @"/nulltype"; + if ([obj isKindOfClass:[NSNumber class]]) + type = @"/integertype"; + else if ([obj isKindOfClass:[NSDictionary class]]) + type = @"/dicttype"; + else if ([obj isKindOfClass:[NSArray class]]) { + NSString *head = [(NSArray*)obj objectAtIndex:0]; + if ([head isEqualToString:@"array"]) + type = @"/arraytype"; + else + type = @"/arraytype"; // not quite correct... + } else if ([obj isKindOfClass:[NSString class]]) { + if ([obj characterAtIndex:0] == '/') type = @"/nametype" ; + else + type = @"/stringtype"; + } + + [stack addObject:type]; +} + +- (NSInvocation *) makeInvocationForOp:(SEL) theSelector +{ + NSMethodSignature *aSignature; + NSInvocation *anInvocation; + aSignature = [[self class] instanceMethodSignatureForSelector:theSelector]; + anInvocation = [NSInvocation invocationWithMethodSignature:aSignature]; + [anInvocation setSelector:theSelector]; + return anInvocation; +} + +- (void)initializeInterpreter +{ + if (stack) [stack release]; + if (dicts) [dicts release]; + if (fontDir) [fontDir release]; + if (inputStream) [inputStream release]; + if (sc) [sc release]; + + stack = [[NSMutableArray arrayWithCapacity:10000] retain]; + dicts = [[NSMutableArray arrayWithCapacity:10] retain]; + fontDir = [[NSMutableDictionary dictionaryWithCapacity:10] retain]; + inputStream = nil; + sc = nil; + nStoringProc = 0; + + NSArray *standardEncoding = [NSArray arrayWithObjects: + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/space", @"/exclam", @"/quotedbl", @"/numbersign", @"/dollar", @"/percent", @"/ampersand", @"/quoteright", + @"/parenleft", @"/parenright", @"/asterisk", @"/plus", @"/comma", @"/hyphen", @"/period", @"/slash", + @"/zero", @"/one", @"/two", @"/three", @"/four", @"/five", @"/six", @"/seven", + @"/eight", @"/nine", @"/colon", @"/semicolon", @"/less", @"/equal", @"/greater", @"/question", + @"/at", @"/A", @"/B", @"/C", @"/D", @"/E", @"/F", @"/G", + @"/H", @"/I", @"/J", @"/K", @"/L", @"/M", @"/N", @"/O", + @"/P", @"/Q", @"/R", @"/S", @"/T", @"/U", @"/V", @"/W", + @"/X", @"/Y", @"/Z", @"/bracketleft", @"/backslash", @"/bracketright", @"/asciicircum", @"/underscore", + @"/quoteleft", @"/a", @"/b", @"/c", @"/d", @"/e", @"/f", @"/g", + @"/h", @"/i", @"/j", @"/k", @"/l", @"/m", @"/n", @"/o", + @"/p", @"/q", @"/r", @"/s", @"/t", @"/u", @"/v", @"/w", + @"/x", @"/y", @"/z", @"/braceleft", @"/bar", @"/braceright", @"/asciitilde", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/exclamdown", @"/cent", @"/sterling", @"/fraction", @"/yen", @"/florin", @"/section", + @"/currency", @"/quotesingle", @"/quotedblleft", @"/guillemotleft", @"/guilsinglleft", @"/guilsinglright", @"/fi", @"/fl", + @"/.notdef", @"/endash", @"/dagger", @"/daggerdbl", @"/periodcentered", @"/.notdef", @"/paragraph", + @"/bullet", @"/quotesinglbase", @"/quotedblbase", @"/quotedblright", @"/guillemotright", @"/ellipsis", @"/perthousand", @"/.notdef", @"/questiondown", + @"/.notdef", @"/grave", @"/acute", @"/circumflex", @"/tilde", @"/macron", @"/breve", @"/dotaccent", + @"/dieresis", @"/.notdef", @"/ring", @"/cedilla", @"/.notdef", @"/hungarumlaut", @"/ogonek", @"/caron", + @"/emdash", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/AE", @"/.notdef", @"/ordfeminine", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/Lslash", @"/Oslash", @"/OE", @"/ordmasculine", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", + @"/.notdef", @"/ae", @"/.notdef", @"/.notdef", @"/.notdef", @"/dotlessi", @"/.notdef", @"/.notdef", + @"/lslash", @"/oslash", @"/oe", @"/germandbls", @"/.notdef", @"/.notdef", @"/.notdef", @"/.notdef", nil + ]; + + NSMutableDictionary *userdict = [[NSDictionary dictionaryWithObjectsAndKeys: + fontDir, @"/FontDirectory", + [NSArray arrayWithObjects: @"array", standardEncoding, nil], @"/StandardEncoding", + nil + ] mutableCopy]; + + NSMutableDictionary *systemdict = [NSMutableDictionary dictionaryWithCapacity:1000]; + NSMutableDictionary *errordict = [NSMutableDictionary dictionaryWithCapacity:10]; + + NSDictionary *auxDict = [NSDictionary dictionaryWithObjectsAndKeys: + [self makeInvocationForOp:@selector(opDef)], @"def", + [self makeInvocationForOp:@selector(opDup)], @"dup", + [self makeInvocationForOp:@selector(opIndex)], @"index", + [self makeInvocationForOp:@selector(opExch)], @"exch", + [self makeInvocationForOp:@selector(opFor)], @"for", + [self makeInvocationForOp:@selector(opDict)], @"dict", + [self makeInvocationForOp:@selector(opArray)], @"array", + [self makeInvocationForOp:@selector(opMark)], @"mark", + [self makeInvocationForOp:@selector(opCleartomark)], @"cleartomark", + [self makeInvocationForOp:@selector(opBegin)], @"begin", + [self makeInvocationForOp:@selector(opEnd)], @"end", + [self makeInvocationForOp:@selector(opExec)], @"exec", + [self makeInvocationForOp:@selector(opGet)], @"get", + [self makeInvocationForOp:@selector(opPut)], @"put", + [self makeInvocationForOp:@selector(opGetinterval)], @"getinterval", + [self makeInvocationForOp:@selector(opPutinterval)], @"putinterval", + [self makeInvocationForOp:@selector(opPop)], @"pop", + [self makeInvocationForOp:@selector(opString)], @"string", + [self makeInvocationForOp:@selector(opReadstring)], @"readstring", + [self makeInvocationForOp:@selector(opNop)], @"readonly", + [self makeInvocationForOp:@selector(opNop)], @"executeonly", + [self makeInvocationForOp:@selector(opNop)], @"noaccess", + [self makeInvocationForOp:@selector(opNop)], @"bind", + [self makeInvocationForOp:@selector(opIf)], @"if", + [self makeInvocationForOp:@selector(opIfelse)], @"ifelse", + [self makeInvocationForOp:@selector(opKnown)], @"known", + [self makeInvocationForOp:@selector(opNot)], @"not", + [self makeInvocationForOp:@selector(opCurrentdict)], @"currentdict", + [self makeInvocationForOp:@selector(opCurrentfile)], @"currentfile", + [self makeInvocationForOp:@selector(opClosefile)], @"closefile", + [self makeInvocationForOp:@selector(opEexec)], @"eexec", + [self makeInvocationForOp:@selector(opDefinefont)], @"definefont", + /* more operators */ + [self makeInvocationForOp:@selector(opNe)], @"ne", + [self makeInvocationForOp:@selector(opEq)], @"eq", + [self makeInvocationForOp:@selector(opCount)], @"count", + [self makeInvocationForOp:@selector(opType)], @"type", + /* some variables */ + [NSNumber numberWithInt:1], @"true", + [NSNumber numberWithInt:0], @"false", + userdict, @"userdict", + systemdict, @"systemdict", + errordict, @"errordict", + nil]; + + [errordict setObject:[NSArray arrayWithObjects:@"proc", + [NSArray arrayWithObjects:@"pop",nil],nil] + forKey:@"/invalidaccess"]; + + [systemdict addEntriesFromDictionary:auxDict]; + + [dicts addObject:systemdict]; + [dicts addObject:userdict]; + +} + + +- (void)doString:(NSString *)anInputString +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + + inputStream = [[anInputString mutableCopy] retain]; + + NSString *identifierString; + + if (sc) [sc release]; + sc = [[NSScanner scannerWithString:inputStream] retain]; + +// NSCharacterSet *sCS= [NSCharacterSet whitespaceAndNewlineCharacterSet]; + NSCharacterSet *sCS= [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r"]; + NSCharacterSet *idCS= [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r[]{}()%/"]; + NSCharacterSet *nlCS= [NSCharacterSet characterSetWithCharactersInString:@"\n\r"]; + NSCharacterSet *parCS= [NSCharacterSet characterSetWithCharactersInString:@"()"]; + float tmpFloat; + + while (![sc isAtEnd]) { + unichar ch; + + /* + BUG? + [sc scanCharactersFromSet:sCS intoString:nil]; does not scan through /r at + the beginning of the string. Actually it does not scan through ANY of the + characters in cCS!!! + we must do it by hand ... + */ + + while (1) { + [sc scanCharactersFromSet:sCS intoString:nil]; + ch =[inputStream characterAtIndex:[sc scanLocation]]; + if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') + [sc setScanLocation:(int)[sc scanLocation]+1]; + else break; + }; + switch (ch) + { + case '%' : // comment + [sc scanUpToCharactersFromSet:nlCS intoString:nil]; + [sc setScanLocation:[sc scanLocation]+1]; + continue; + case '/' : // literal + [sc scanString:@"/" intoString:nil]; + if ([sc scanUpToCharactersFromSet:idCS intoString:&identifierString]) { + [stack addObject:[@"/" stringByAppendingString:identifierString]]; + } + continue; + case '(' : // string + { + int nesting = 0; + NSMutableString *curString = [NSMutableString stringWithCapacity:100]; + NSString *fragment; + [sc scanString:@"(" intoString:nil]; + while (1) { + [sc scanUpToCharactersFromSet:parCS intoString:&fragment]; + [curString appendString:fragment]; + if ([inputStream characterAtIndex:[sc scanLocation]] == '(') + { + nesting++; [curString appendString:@"("]; [sc scanString:@"(" intoString:nil]; + } + else { + [sc scanString:@")" intoString:nil]; + if (nesting) { + nesting--; [curString appendString:@")"]; + } + else break; + } + } + [stack addObject:curString]; + } + continue; + case '{' : // begin proc + [sc scanString:@"{" intoString:nil]; + nStoringProc++; + [stack addObject:StackMarkObject]; + continue; + case '}' : // end proc + { + [sc scanString:@"}" intoString:nil]; + nStoringProc--; + id obj; + NSMutableArray *proc = [NSMutableArray arrayWithCapacity:100]; + while ((obj = [stack lastObject]) != StackMarkObject) { + [proc insertObject:obj atIndex:0]; + [stack removeLastObject]; + } + if (obj == StackMarkObject) [stack removeLastObject]; + [stack addObject:[NSArray arrayWithObjects:@"proc",proc,nil]]; + } + continue; + case '[' : // begin array + [sc scanString:@"[" intoString:nil]; + [stack addObject:StackMarkObject]; + continue; + case ']' : // end array + { + [sc scanString:@"]" intoString:nil]; + id obj; + NSMutableArray *array = [NSMutableArray arrayWithCapacity:100]; + while ((obj = [stack lastObject]) != StackMarkObject) { + [array insertObject:obj atIndex:0]; + [stack removeLastObject]; + } + if (obj == StackMarkObject) [stack removeLastObject]; + [stack addObject:[NSArray arrayWithObjects:@"array",array,nil]]; + } + continue; + + case '<' : // hex string + [NSException raise:SimplePSInterpreterException format:@"hexstring not yet implemented!"]; + continue; + + default : // check if it is a number or a symbol + + if ([sc scanFloat:&tmpFloat]) { + [stack addObject:[NSNumber numberWithFloat:tmpFloat]]; + } else if ([sc scanUpToCharactersFromSet:idCS intoString:&identifierString]) { + if (nStoringProc) { + [stack addObject:identifierString]; + } else { + [self execName:identifierString]; + } + } else + [NSException raise:SimplePSInterpreterException format:@"Exhausted possible cases. I'm lost!"]; + } + } + + [sc release]; + [inputStream release]; + sc = nil; + inputStream = nil; + + [pool release]; +} + + +- init +{ + self = [super init]; + if (self) { + [self initializeInterpreter]; + } + return self; +} + +- (void) dealloc +{ + [stack release]; + [fontDir release]; + [dicts release]; + + [super dealloc]; +} + + +- (NSDictionary*)fontDir +{ + return fontDir; +} + +@end |