summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdv2pdf/SimplePSInterpreter.m
diff options
context:
space:
mode:
authorJonathan Kew <jfkthame@googlemail.com>2006-10-06 09:54:57 +0000
committerJonathan Kew <jfkthame@googlemail.com>2006-10-06 09:54:57 +0000
commitd449c410a7ca823910ac416ca5dd9604b16cdd89 (patch)
treee1b4be6ce833b14b8f823d2f25e7317950009c2a /Build/source/texk/xdv2pdf/SimplePSInterpreter.m
parent65e25e4262054c29d9bf925b5362ebea5b1385d8 (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.m851
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