PBSmallObjects.m


max21 Unternehmensgruppe
#import "Aprica.h"
//	Aprica2
//	copyright Pirmin Braun 1997-2007 - pirmin@pirmin.de
//	all Rights reserved;
// hier liegen kleinere Hilfsobjekte
@implementation PBWOEditorState : NSObject
ACCESSClassm(lastCombinedQ, setLastCombinedQ, PBSQLQualifier)
- (NSMutableArray *)ma; {return ma;}
- (int)maOffset; {return maOffset;}
- (void)setMaOffset:(int)i; {maOffset = i;}
- (int)countCombinedQ;{return countCombinedQ;}
- (void)setCountCombinedQ:(int)i;{countCombinedQ = i;}
- init;
{
    if(!(self = [super init]))return nil;
    MA(ma);
    maOffset = 0;
    [self setLastCombinedQ:nil];
    return self;
}
- (void)dealloc;
{
    [ma release];
    [lastCombinedQ release];
    [super dealloc];
}
+ (PBWOEditorState *)stateOf:(PBWOEditor *)e;
{
    PBWOEditorState *state = [[PBWOEditorState alloc]init];
    [[state ma] addObjectsFromArray:[e ma]];
    [state setMaOffset:[e maOffset]];
    [state setCountCombinedQ:[e countCombinedQ]];
    [state setLastCombinedQ:[e lastCombinedQ]];
    return [state autorelease];
}
- (void)updateStateFrom:(PBWOEditor *)e;
{
    [ma removeAllObjects];
    [ma addObjectsFromArray:[e ma]];
    maOffset = [e maOffset];
    countCombinedQ = [e countCombinedQ];
    [self setLastCombinedQ:[e lastCombinedQ]];
}
@end
@implementation PBVLO
ACCESSm(value, setValue)
ACCESSm(bez0, setBez0)
ACCESSm(bez1, setBez1)
- (NSString *)bez;
{
    if([_SESSION lang] && FILLED(bez1)){
        return bez1;
    }else{
        return bez0;
    }
}
- (id)initWithCoder:(NSCoder *)coder;
{
    if(!([self init]))return nil;
    [self setValue: [coder decodeObject]];
    [self setBez0: [coder decodeObject]];
    [self setBez1: [coder decodeObject]];
    return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:value];
    [coder encodeObject:bez0];
    [coder encodeObject:bez1];
}
+ (PBVLO *)pbvloWithValue:(NSString *)v bez0:(NSString *)b0 bez1:(NSString *)b1;
{
    PBVLO *pbvlo = [[PBVLO alloc]init];
    [pbvlo setValue:v];
    [pbvlo setBez0:b0];
    [pbvlo setBez1:b1];
    return [pbvlo autorelease];
}
- (BOOL)isEqual:(PBVLO *)o;
{
    return [value iE:[o value]];
}
- (void)dealloc;
{
    [value release];
    [bez0 release];
    [bez1 release];
    [super dealloc];
}
@end
@implementation PBActionO
ACCESSm(name, setName)
ACCESSm(guiName, setGuiName)
+ (PBActionO *)actionWithName:(NSString *)v_name gui:(NSString *)v_gui;
{
    PBActionO  *action = [[PBActionO alloc]init];
    if(!FILLED(v_name) || !FILLED(v_gui)){
        LOGS(([NSSWF @"name/guiname fehlt fuer action"]));
        [action release];
        return nil;
    }
    [action setName:v_name];
    [action setGuiName:v_gui]; //sollte uebersetzt werden
    return [action autorelease];
}
- (void)dealloc;
{
    [name release];
    [guiName release];
    [super dealloc];
}
- init;
{
    if(!(self=[super init]))return nil;
    [self setGuiName:nil];
    [self setName:nil];
    return self;
}
@end
@implementation PBStringWrapper
//stringWrapper, damit auch gleiche strings unterschieden werden, z.B. mehrfache <br>
+ (PBStringWrapper *)stringWrapperWithString:(NSString *)s;
{
    PBStringWrapper *sw;
    if(!s)return nil;
    sw = [[PBStringWrapper alloc]init];
    [sw setString:s];
    return sw;
}
- (NSString *)description;
{
    return [NSSWF @"PBSW:%@",string];
}
- (void)dealloc;
{
    [string release];
    [super dealloc];
}
ACCESSm(string,setString);
@end
@implementation PBWOTVCCol
ACCESSClassm(eAsso,setEAsso,PBWOAsso)
ACCESSm(columnTitle,setColumnTitle);
- (NSString *)tvNewGuiNameSort;
{
    NSString *s = [cAsso guiName];
    if(tvNewSortMode == SORTMODE_A)return [@"+" stringByAppendingString:s];
    if(tvNewSortMode == SORTMODE_D)return [@"-" stringByAppendingString:s];
    return s;
}
- (id)initWithWOAsso:(PBWOAsso *)wa;
{
    if(!(self = [super init]))return nil;
    cAsso = [wa retain];
    [cAsso setIsCAsso:YES];
    tvNewSortMode = SORTMODE_N;
    width = [[[[wa tvc] colWidthDict] ofk:[wa dbName]]intValue]; //customwidth
    [self setColumnTitle:[NSSWF TRANSLATION(@"nach %@ sortieren"),[wa guiName]]];
    if(width)return self;
    width = [[wa pba]widthForColumn];
    return self;
}
- (int)tvNewSortMode;
{
    return tvNewSortMode;
}
- (void)tvNewResetSortMode;
{
    tvNewSortMode = SORTMODE_N;
}
- (void)setTvNewSortMode:(int)sm;
{
    tvNewSortMode = sm;
}
- (NSString *)guiName;
{
    return [cAsso guiName];
}
- (void)dealloc;
{
    [cAsso release];
    [eAsso release];
    [columnTitle release];
    [super dealloc];
}
- (PBWOAsso *)cAsso;
{
    return cAsso;
}
- (int)width;
{
    return width;
}
- (void)setWidth:(int)i;
{
    width=i;
}
- (NSString *)dbName;
{
    return [cAsso dbName];
}
@end
@implementation Foreach : NSObject
ACCESSm(indexName,setIndexName);
ACCESSm(itemName,setItemName);
ACCESSClassm(a,setA,NSArray);
- (int)index;{return index;}
- (void)setIndex:(int)i;{index=i;}
- (void)dealloc;
{
    [a release];
    [indexName release];
    [itemName release];
    [super dealloc];
}
@end
@implementation BLZRecord : NSObject
- (int)blz;
{
    return blz;
}
ACCESSm(suchstring,setSuchstring);
ACCESSm(institut,setInstitut);
ACCESSm(ort,setOrt);
ACCESSm(pruefzifferverfahren,setPruefzifferverfahren);
- (void)dealloc;
{
    [institut release];
    [suchstring release];
    [ort release];
    [pruefzifferverfahren release];
    [super dealloc];
}
- (BOOL)matches:(NSString *)s;
{
    if(!FILLED(s))return NO;
    return ([suchstring rangeOfString:s].length > 0);
}
- (id)initWithBLZ4row:(NSString *)s;
{
    NSArray *a;
    if(!(self = [super init]))return nil;
    if(!FILLED(s))return nil;
    a = [s componentsSeparatedByString:@";"];
    if([a count] != 5)return nil;
    blz = [[a oai:0]intValue];
    [self setInstitut:[a oai:1]];
    [self setOrt:[a oai:3]];
    [self setSuchstring:[NSSWF @"%@%@",[institut simplyfiedString],[ort simplyfiedString]]];
    [self setPruefzifferverfahren:[a oai:4]];
    return self;
}
- (id)initWithBLZ5row:(NSString *)s;
{
// offset,laenge
    NSRange blzr = {0,8};
    NSRange institutr = {27,58};
    NSRange ortr = {110,29};
    NSRange pruefzr = {181,2};
    if(!(self = [super init]))return nil;
    if(!FILLED(s))return nil;
    if([s length] < 188)return nil;
    blz = [[s substringWithRange:blzr]intValue];
    [self setInstitut:[s substringWithRange:institutr]];
    [self setOrt:[s substringWithRange:ortr]];
    [self setSuchstring:[NSSWF @"%@%@",[institut simplyfiedString],[ort simplyfiedString]]];
    [self setPruefzifferverfahren:[s substringWithRange:pruefzr]];
    return self;
}
- (BOOL)isEqual:(BLZRecord *)r;
{
    if(![r isKindOfClass:[BLZRecord class]])return NO;
    return blz==[r blz] && [institut iE:[r institut]] && [ort iE:[r ort]];
}
@end
@implementation TerminO
// databearing Objekt f. Kalender; nicht zu verwechseln mit dem Modul TerminEWO
ACCESSm(descri,setDescri)
ACCESSm(termin,setTermin)
ACCESSm(terminv,setTerminv)
ACCESSm(terminb,setTerminb)
ACCESSm(beschreibung,setBeschreibung)
ACCESSm(stichworte,setStichworte)
ACCESSm(terminzeit,setTerminzeit)
ACCESSm(terminzeitv,setTerminzeitv)
ACCESSm(terminzeitb,setTerminzeitb)
ACCESSClassm(coveredEO,setCoveredEO,PBEO)
ACCESSClassm(owner,setOwner,PBEO)
ACCESSClassm(empfaenger,setEmpfaenger,PBEO)
ACCESSClassm(resource,setResource,PBEO)
- (void)dealloc;
{
    [descri release];
    [termin release];
    [terminv release];
    [terminb release];
    [beschreibung release];
    [stichworte release];
    [terminzeit release];
    [terminzeitv release];
    [terminzeitb release];
    [coveredEO release];
    [owner release];
    [empfaenger release];
    [resource release];
    [super dealloc];
}
- (void)setPrio:(int)i;
{
    prio = i;
}
- (void)setStatus:(int)i;
{
    status = i;
}
- (void)setAbhaengig:(BOOL)yn;
{
    abhaengig = yn;
}
- (void)setWiedervorlage:(BOOL)yn;
{
    wiedervorlage = yn;
}
- (int)prio;
{
    return prio;
}
- (int)status;
{
    return status;
}
- (BOOL)abhaengig;
{
    return abhaengig;
}
- (BOOL)wiedervorlage;
{
    return wiedervorlage;
}
- (NSString *)wiedervorlageS;
{
    if(wiedervorlage)return @"<span style=\"color:red;\" title=\"Wiedervorlage\">W</span>";
    return @"";
}
- (void)setPrivat:(BOOL)yn;
{
    privat = yn;
}
- (BOOL)privat;
{
    return privat;
}
- (NSString *)privatS;
{
    if(privat)return @"<span style=\"color:red;\" title=\"Privat\">P</span>";
    return @"";
}
- (BOOL)isHighPrio;
{
    return(prio==tpHigh);
}
- (NSString *)statusIconName;
{
    return [NSSWF @"/Aprica2_%@/Images/st_%i.gif",[_APP mandant],status];
}
- (NSString *)statusName;
{
    switch(status){
        case 0: return @"unbearbeitet";
        case 1: return @"gesichtet";
        case 2: return @"in Arbeit";
        case 3: return @"fertig";
        case 4: return @"blockiert";
    }
    return @"0";
}
- (NSString *)zeit;
{
    NSString *s;
    if(FILLED(terminb) && (![terminv iE:terminb])){
        if([terminv iE:termin]){
// erster Tag
            s = [NSSWF @"%@...",terminzeitv];
       }else if([terminb iE:termin]){
// letzter Tag
            s = [NSSWF @".. %@",terminzeitb];
        }else{
// mittendrin
            s = @".......";
        }
    }else{
// Termin an einem einzigen Tag
        s = [NSSWF @"%@-%@",terminzeitv,terminzeitb];
    }
    return s;
}
- (NSComparisonResult)compare:(TerminO *)anotherTerminO;
{
    NSComparisonResult cr = [[self termin] compare:[anotherTerminO termin]];
    if(cr == NSOrderedSame)cr = [[self terminzeitv] compare:[anotherTerminO terminzeitv]];
    return cr;
}
@end
@implementation XMLObject : NSObject
ACCESSm(name,setName)
ACCESSm(content,setContent)
// test wg. autorelease; gibt eigentlich retain-cycle
- (XMLObject *)parent;{return parent;}
- (void)setParent:(XMLObject *)v; {parent = v;};
// ACCESSClassm(parent,setParent,XMLObject)
- (int)typ;{return typ;}
- (void)setTyp:(int)i;{typ = i;}
- (NSMutableArray *)children;{return children;}
- (NSMutableArray *)ma;{return ma;}
- (NSMutableDictionary *)md;{return md;}
- init;
{
    if(!(self = [super init]))return nil;
    MA(children);
    ma = nil;
    md = nil;
    [self setContent:@""];
    [self setTyp:XMLObjectTyp_Container];
    return self;
}
- (NSString *)description;
{
    return [NSSWF @"name: %@ typ:%i content: %@",name,typ,content];
}
+ (XMLObject *)xmlObjectWithName:(NSString *)v;
{
    XMLObject *o = [[XMLObject alloc]init];
    [o setName:v];
    [o setContent:@""];
    return [o autorelease];
}
- (void)dealloc;
{
    [children release];
    [name release];
    [ma release];
    [md release];
    [content release];
//    [parent release]; // test wg. autorelease;
    [super dealloc];
}
- (NSArray *)childrenNames;
{
    LMAN(names);
    [names addObjectsUniq:[children valueForKey:@"name"]];
    return names;
}
- (NSArray *)childrenWithName:(NSString *)s;
{
    LMA;
    int i,j;
    if(!FILLED(s))return lma;
    for(i=0,j=[children count];i<j;i++){
        XMLObject *child = [children oai:i];
        if([[child name]iE:s]){
            [lma addObject:child];
        }
    }
    return lma;
}
- (BOOL)determineConreteContainer;
{
    if(typ == XMLObjectTyp_Container){
        int nc,cc,i,j;
        LMAN(names);
        cc = [children count];
        if(cc){
            [names addObjectsUniq:[children valueForKey:@"name"]];
            nc = [names count];
            if(nc == cc){
// jeder Name uniq
                if(nc == 1){
                    if([[names firstObject]iE:@"NSArrayItem"]){
                        MA(ma);
                    }else{
                        MD(md);
                    }
                }else{
// mehrere verschiedene namen
                    MD(md);
                }
            }else{
                MA(ma);
            }
            for(i=0,j=cc;i<j;i++){
                if(![[children oai:i]determineConreteContainer])return NO;
            }
        }
    }
    if(parent){
        [parent addToConcreteContainer:self];
    }
    return YES;
}
- (void)addToConcreteContainer:(XMLObject *)o;
{
    if([o typ] == XMLObjectTyp_Container){
        if(ma){
            if([o ma]){
                [ma addObject:[o ma]];
            }else{
                [ma addObject:[o md]];
            }
        }else{
            if([o ma]){
                [md setObject:[o ma] forKey:[o name]];
            }else{
                [md setObject:[o md] forKey:[o name]];
            }
        }
    }else{
// o ist ein Element
        if(ma){
            [ma addObject:[o content]];
        }else{
            [md setObject:[o content] forKey:[o name]];
        }
    }
}
@end
@implementation PBSQLQualifier
- init;
{
    if(!(self = [super init]))return nil;
    typ = PBSQLQplain;
    qualifiers = nil;
    [self setString:@""];
    return self;
}
- initMA;
{
    if(!([self init]))return nil;
    MA(qualifiers);
    return self;
}
+ (PBSQLQualifier *)qualifierWithString:(NSString *)s;
{
    PBSQLQualifier *q;
    if(!s)s=@"";
    q = [[PBSQLQualifier alloc]init];
    [q setString:[NSSWF @"%@",s]];
    return [q autorelease];
}
- (id)copyWithZone:(NSZone *)zone;
{
    return [self retain];
}
- (void)dealloc;
{
    [qualifiers release];
    [string release];
    [super dealloc];
}
- (NSString *)description;
{
    return [self string];
}
- (void)setString:(NSString *)_value;
{
    if(string != _value){
        [string release];
        string = [_value retain];
    }
}
- (NSString *)string;
{
// liefert die where-Clause
    PBSQLQualifier *q1;
    int i,j;
    NSString *s;
    NSMutableString *ms = [NSMutableString stringWithCapacity:100];
    if(typ == PBSQLQplain){
        return string;
    }
    if(typ == PBSQLQall){
        return  @"(1 = 1)";
    }
    if(typ == PBSQLQnothing){
        return  @"(2 = 1)";
    }
    [ms setString:@""];
    if(typ == PBSQLQor){
        j = [qualifiers count];
        if(j==0)return @"";
        for(i=0;i<j;i++){
            q1 = [qualifiers oai:i];
            if([q1 typ]==PBSQLQall)return @"(1 = 1)";
            if([q1 typ]==PBSQLQnothing)continue;
            s = [q1 string];
            if(FILLED(s)){
                if(FILLED(ms))[ms appendString:@" OR "];
                [ms appendFormat:@"(%@)",s];
            }
        }
        return ms;
    }
    if(typ == PBSQLQand){
        j = [qualifiers count];
        if(j==0)return @"";
        for(i=0;i<j;i++){
            q1 = [qualifiers oai:i];
            if([q1 typ]==PBSQLQall)continue;
            if([q1 typ]==PBSQLQnothing)return @"(1 = 2)";
            s = [q1 string];
            if(FILLED(s)){
                if(FILLED(ms))[ms appendString:@" AND "];
                [ms appendFormat:@"(%@)",s];
            }
        }
        return ms;
    }
    LOGS(@"ungueltiger Qualifier-Typ.");
    return EON;
}
- (void)setTyp:(int)i;
{
    typ = i;
}
- (int)typ;
{
    return typ;
}
+ (PBSQLQualifier *)orQualifier;
{
    PBSQLQualifier *q = [[PBSQLQualifier alloc]initMA];
    [q setTyp:PBSQLQor];
    return [q autorelease];
}
+ (PBSQLQualifier *)andQualifier;
{
    PBSQLQualifier *q = [[PBSQLQualifier alloc]initMA];
    [q setTyp:PBSQLQand];
    return [q autorelease];
}
+ (PBSQLQualifier *)nothingQualifier;
{
    PBSQLQualifier *q = [[PBSQLQualifier alloc]init];
    [q setTyp:PBSQLQnothing];
    return [q autorelease];
}
+ (PBSQLQualifier *)allQualifier;
{
    PBSQLQualifier *q = [[PBSQLQualifier alloc]init];
    [q setTyp:PBSQLQall];
    return [q autorelease];
}
- (void)addQualifier:(PBSQLQualifier *)q;
{
    if(q && [q isKindOfClass:[PBSQLQualifier class]])[qualifiers addObject:q];
}
- (void)addQualifiers:(NSArray *)a;
{
    [qualifiers addObjectsFromArray:a];
}
+ (PBSQLQualifier *)orQualifierWithArray:(NSArray *)a;
{
    PBSQLQualifier *q = [PBSQLQualifier orQualifier];
    [q addQualifiers:a];
    return q;
}
+ (PBSQLQualifier *)andQualifierWithArray:(NSArray *)a;
{
    PBSQLQualifier *q = [PBSQLQualifier andQualifier];
    [q addQualifiers:a];
    return q;
}
+ (PBSQLQualifier *)pkOrQualiFromEOArray:(NSArray *)a;
{
    PBSQLQualifier *q;
    if(![a count])return PBNOTHINGQ;
    if(![[a firstObject]isKindOfClass:[PBEO class]])return PBNOTHINGQ;
//exception abfangen; wer weiss, was fuer ein schrott im array steht...
    NS_DURING;
    q = [PBSQLQualifier orQualiFromArray:[a valuesForKey:@"primaryKey"] forDbName:[[a firstObject]primaryKeyName]];
    NS_HANDLER;
    q = PBNOTHINGQ;
    NS_ENDHANDLER;
    return q;
}
+ (PBSQLQualifier *)orQualiFromArray:(NSArray *)a forDbName:(NSString *)s;
{
    PBSQLQualifier *q;
    int i,j;
    j=[a count];
    if(!j)return PBNOTHINGQ;
    if(!FILLED(s))return PBNOTHINGQ;
    q = [PBSQLQualifier orQualifier];
    for(i=0;i<j;i++){
        [q addQualifier:[PBSQLQualifier qualifierWithString:[NSSWF @"%@ = '%@'",s,[a oai:i]]]];
    }
    return q;
}
+ (PBSQLQualifier *)qualifierFromKn:(NSString *)keyName  keyValue:(NSString *)keyValue;
{
    if(!FILLED(keyName)){
        LOGS(@"qualifierFromKn: kein key");
        // PRINTCURRENTSTACK;
        return PBNOTHINGQ;
    }
    if(!FILLED(keyValue))return PBNOTHINGQ; //eher normal; z.B.: getEOPkValue()
    return [PBSQLQualifier qualifierWithString:[NSSWF @"%@ = '%@'",keyName,keyValue]];
}
- (BOOL)isEqual:(PBSQLQualifier *)otherQ;
{
    if(![otherQ isKindOfClass:[PBSQLQualifier class]])return NO;
    return [[self string]iE:[otherQ string]];
}
@end
@implementation PBSortOrdering
{
    SEL _selector;
    NSString *_key;
}
+ (PBSortOrdering *)sortOrderingWithKey:(NSString *)key selector:(SEL)selector;
{
    return [[[PBSortOrdering alloc]initWithKey:key selector:selector]autorelease];
}
- initWithKey:(NSString *)key selector:(SEL)selector;
{
    if(!(self = [super init]))return nil;
    if(!key)return nil;
    if(!selector)return nil;
    _selector = selector;
    _key = [key retain];
    return self;
}
- (NSString *)key;{ return _key;}
- (SEL)selector;{ return _selector;}
@end
#define OPEN_PAR @"("
#define CLOSE_PAR @")"
@implementation PBExpression:NSObject
ACCESSm(content,setContent);
+ (PBExpression *)expressionFromString:(NSString *)s;
{
    return [[[PBExpression alloc]initWithString:s]autorelease];
}
- (PBExpression *)initWithString:(NSString *)s;
{
    if(!(self = [super init]))return nil;
    if([s rangeOfString:@" "].length){
        // zusammengesetzte Expression
        //
        NSArray *a = [s componentsSeparatedByString:@" "];
        int i,j;
        LMA;
        BOOL inPar = NO;
        MA(subExpressions);
        MA(operators);
        for(i=0,j=[a count];i<j;i++){
            NSString *token = [a oai:i];
            if(i % 2){
                // operator erwartet
                if(!([token iE:@"+"] || [token iE:@"-"] || [token iE:@"*"] || [token iE:@"/"] || [token iE:@"m"])){
                    return nil;
                }
                if(inPar){
                    [lma addObject:token];
                }else{
                    [operators addObject:token];
                }
            }else{
                // expression erwartet
                if(inPar){
                    if([token hasSecureSuffix:CLOSE_PAR]){
                        token = [token stringWithoutLastChar];
                        [lma addObject:token];
                        [subExpressions addObject:[PBExpression expressionFromString:[lma componentsJoinedByString:@" "]]];
                        inPar = NO;
                    }else{
                        [lma addObject:token];
                    }
                }else{
                    if([token hasSecurePrefix:OPEN_PAR]){
                        [lma removeAllObjects];
                        token = [token secureSubstringFromIndex:1];
                        [lma addObject:token];
                        inPar = YES;
                    }else{
                        [subExpressions addObject:[PBExpression expressionFromString:token]];
                    }
                }
            }
        }
    }else{
        // einfache Expression; sinnlose klammern weg
        [self setContent:[[s stringWithoutString:OPEN_PAR]stringWithoutString:CLOSE_PAR]];
    }
    return self;
}
- (void)dealloc;
{
    [operators release];
    [subExpressions release];
    [content release];
    [super dealloc];
}
- (NSString *)description;
{
    int j = [subExpressions count];
    if(j){
        return [subExpressions description];
    }else{
        // simple Expressions
        return content;
    }
}
- (NSObject *)valueForDatasource:(PBWOEditor *)datasource varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{
    int j = [subExpressions count];
    int j1 = [operators count];
    int i=0;
    if(j){
        // anzahl operators muss eins weniger als anzahl subExpressions sein
        NSString *collect = (NSString *)[[subExpressions firstObject]valueForDatasource:datasource varDict:varDict localVarDict:localVarDict];
        for(i=0;(((i + 1) < j) && (i < j1));i++){
            NSString *s = (NSString *)[[subExpressions oai:(i + 1)]valueForDatasource:datasource varDict:varDict localVarDict:localVarDict];
            NSString *op = [operators oai:i];
            if([op iE:@"+"]){
                collect = [NSString stringWithFormat:@"%f",([collect doubleValue] + [s doubleValue])];
            }else if([op iE:@"-"]){
                collect = [NSString stringWithFormat:@"%f",([collect doubleValue] - [s doubleValue])];
            }else if([op iE:@"*"]){
                collect = [NSString stringWithFormat:@"%f",([collect doubleValue] * [s doubleValue])];
            }else if([op iE:@"/"]){
                collect = [NSString stringWithFormat:@"%f",([collect doubleValue] / [s doubleValue])];
            }else if([op iE:@"m"]){
                collect = [NSString stringWithFormat:@"%i",([collect intValue] % [s intValue])];
            }
        }
        return collect;
    }else{
        // simple Expressions
        return [_APP valueFromExpression:content datasource:datasource varDict:varDict localVarDict:localVarDict];
    }
}
- (NSArray *)subExpressions;{return subExpressions;}
- (NSArray *)operators;{return operators;}
@end
@implementation PBOperand
ACCESSm(content,setContent);
ACCESSClassm(expr,setExpr,PBExpression);
- (enum OP_f)formatting; // formatierung
{
    return formatting;
}
- (PBOperand *)initWithConstantObject:(NSObject *)o;
{
    if(!(self = [super init]))return nil;
    formatting = 0;
    trim = 0;
    SET_FFLAG(OP_f_lit); // Konstant
    [self setContent:(NSString *)o];
    return self;
}
- (NSString *)description;
{
    LMA;
    NSString *f;
    if(formatting){
        f = [NSSWF @"  formatting: %x",formatting];
    }else{
        f = @"";
    }
    [lma addObject:[NSSWF @"    %@%@",content,f]];
    if(expr)[lma addObject:[NSSWF @"    expr: %@",[expr description]]];
    return [lma componentsJoinedByString:@"\n"];
}
- (PBOperand *)initWithString:(NSString *)s;
{
    BOOL collectFlags = YES;
    if(!(self = [super init]))return nil;
    formatting = 0;
    trim = 0;
    
// sonder konstanten
    SET_FFLAG(OP_f_lit); // per  default Konstanten
    if(!FILLED(s)){ [self setContent:@""]; return self;}
    if([s iE:@"%"]){ [self setContent:@"%"]; return self;}
    if([s iE:@"%%"]){[self setContent:@"%"]; return self;}
    if([s iE:@"\\r\\n"] || [s iE:@"\"\\r\\n"]){ [self setContent:@"\r\n"]; return self;} // cr + newline
    if([s iE:@"\\n"] || [s iE:@"\"\\n"]) { [self setContent:@"\n"]; return self;}// newline
    if([s iE:@"\\t"] || [s iE:@"\"\\t"]){ [self setContent:@"\t"]; return self;}// tab
    formatting = 0; // keine Konstante
// sonderfall %datasource
    if([s iE:@"%datasource"]){ [self setContent:@"%datasource"]; return self;}
    
    //Formatierungsoptionen vorangestellt fuer ganzen Ausdruck; Reihenfolge egal;
    while(collectFlags){
        if([s hasSecurePrefix:@"\""]){
            SET_FFLAG(OP_f_lit);	// Konstante
            SET_FFLAG(OP_f_dblquote);
            [self setContent:[s substringFromIndex:1]];
            return self;
        }
        if([s hasSecurePrefix:@"<lit>"]){ //literally
            SET_FFLAG(OP_f_lit); 	// Konstante
            [self setContent:[s substringFromIndex:5]];
            return self;
        }
        if([s hasSecurePrefix:@"'"]){ //literally
            SET_FFLAG(OP_f_lit);	// Konstante
            [self setContent:[s substringFromIndex:1]];
            return self;
        }
        if([s hasSecurePrefix:@"<trans>"]){ //translate standard;
            SET_FFLAG(OP_f_trans);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<trim"]){
            NSString *trims;
            SET_FFLAG(OP_f_trim);
            s = [s substringFromIndex:5];
            trims = [s substringToIndex:3]; //z.B. 20>
            trim=[trims intValue];
            s = [s substringFromIndex:3];
            continue;
        }
        if([s hasSecurePrefix:@"<stl"]){  // linksb. string
            NSString *trims;
            SET_FFLAG(OP_f_stl);
            s = [s substringFromIndex:4];
            trims = [s substringToIndex:3]; //z.B. 20>
            trim=[trims intValue];
            s = [s substringFromIndex:3];
            continue;
        }
        if([s hasSecurePrefix:@"<str"]){  // rechtsb. money
            NSString *trims;
            SET_FFLAG(OP_f_stl);
            s = [s substringFromIndex:4];
            trims = [s substringToIndex:3]; //z.B. 20>
            trim=[trims intValue];
            s = [s substringFromIndex:3];
            continue;
        }
        if([s hasSecurePrefix:@"<strs"]){  // rechtsb. string
            NSString *trims;
            SET_FFLAG(OP_f_strs);
            s = [s substringFromIndex:5];
            trims = [s substringToIndex:3]; //z.B. 20>
            trim=[trims intValue];
            s = [s substringFromIndex:3];
            continue;
        }
        if([s hasSecurePrefix:@"<date>"]){
            SET_FFLAG(OP_f_guidate);
            s = [s substringFromIndex:6];
            continue;
        }
        if([s hasSecurePrefix:@"<week>"]){
            SET_FFLAG(OP_f_week);
            s = [s substringFromIndex:6];
            continue;
        }
        if([s hasSecurePrefix:@"<month>"]){
            SET_FFLAG(OP_f_month);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<yw>"]){
            SET_FFLAG(OP_f_weekyear);
            s = [s substringFromIndex:4];
            continue;
        }
        if([s hasSecurePrefix:@"<year>"]){
            SET_FFLAG(OP_f_year);
            s = [s substringFromIndex:6];
            continue;
        }
        if([s hasSecurePrefix:@"<yy>"]){
            SET_FFLAG(OP_f_yy);
            s = [s substringFromIndex:4];
            continue;
        }
        if([s hasSecurePrefix:@"<wdayn>"]){
            SET_FFLAG(OP_f_wdayn);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<int>"]){
            SET_FFLAG(OP_f_guiint);
            s = [s substringFromIndex:5];
            continue;
        }
        if([s hasSecurePrefix:@"<round2>"]){
            SET_FFLAG(OP_f_rnd2);
            s = [s secureSubstringFromIndex:8];
            continue;
        }
        if([s hasSecurePrefix:@"<round1>"]){
            SET_FFLAG(OP_f_rnd1);
            s = [s secureSubstringFromIndex:8];
            continue;
        }
        if([s hasSecurePrefix:@"<intnd>"]){
            SET_FFLAG(OP_f_guiintnd);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<money>"]){
            SET_FFLAG(OP_f_guimoney);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<f1>"]){
            SET_FFLAG(OP_f_guif1);
            s = [s substringFromIndex:4];
            continue;
        }
        if([s hasSecurePrefix:@"<f3>"]){
            SET_FFLAG(OP_f_guif3);
            s = [s substringFromIndex:4];
            continue;
        }
        if([s hasSecurePrefix:@"<f1nd>"]){
            SET_FFLAG(OP_f_f1nd);
            s = [s substringFromIndex:6];
            continue;
        }
        if([s hasSecurePrefix:@"<f2nd>"]){
            SET_FFLAG(OP_f_f2nd);
            s = [s substringFromIndex:6];
            continue;
        }
        if([s hasSecurePrefix:@"<f3nd>"]){
            SET_FFLAG(OP_f_f3nd);
            s = [s substringFromIndex:6];
            continue;
        }
        if([s hasSecurePrefix:@"<floor>"]){
            SET_FFLAG(OP_f_flr);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<ceil>"]){
            SET_FFLAG(OP_f_ceil);
            s = [s substringFromIndex:7];
            continue;
        }
        if([s hasSecurePrefix:@"<uc>"]){
            SET_FFLAG(OP_f_uc);
            s = [s substringFromIndex:4];
            continue;
        }
        if([s hasSecurePrefix:@"<lc>"]){
            SET_FFLAG(OP_f_lc);
            s = [s substringFromIndex:4];
            continue;
        }
        // kein bekanntes Flag
        collectFlags = NO;
    }
    // flags aufgegessen, und nicht OP_f_lit
    // sollen konstanten spaces oder Klammern enthalten, muessen sie gequoted werden
    // Variablennamen duerfen keine spaces oder Klammern enthalten
    // trailing spaces und comments abschneiden
    s = [s stringWithoutTrailingWSC];
    if([s rangeOfString:@" "].length){
        // falls zusammengesetzte expression, ein extra expression Objekt anlegen
        [self setExpr:[PBExpression expressionFromString:s]];
        if(!expr){
            return nil;
        }
        [self setContent:s];
    }else{
        [self setContent:[[s stringWithoutString:OPEN_PAR]stringWithoutString:CLOSE_PAR]]; // wenn keine spaces, dann auch keine klammern noetig
        if(!FILLED(content) || (![content hasSecurePrefix:@"$"] && ![content hasSecurePrefix:@"%"])){
            SET_FFLAG(OP_f_lit);	// Konstante
        }
    }
    return self;
}
+ (PBOperand *)operandFromString:(NSString *)s;
{
    PBOperand *pbo = [[PBOperand alloc]initWithString:s];
    return [pbo autorelease];
}
+ (PBOperand *)operandWithConstantObject:(NSObject *)o;
{
    PBOperand *pbo = [[PBOperand alloc]initWithConstantObject:o];
    return [pbo autorelease];
}
- (BOOL)isConstant;
{
    return HAS_FFLAG(OP_f_lit);
}
- (NSObject *)valueForDatasource:(PBWOEditor *)datasource varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{
    NSObject *rv = nil;
// im context zu ermitteln
    if(!HAS_FFLAG(OP_f_lit)){
        if(expr){
            // zusammengesetzte expression, vorgeparster Baum
            rv = [expr valueForDatasource:datasource varDict:varDict localVarDict:localVarDict];
        }else{
            // einfache expression in content, kann auf einmal evaluiert werden
            rv = [_APP valueFromExpression:content datasource:datasource varDict:varDict localVarDict:localVarDict];
        }
    }else{
        // konstanter content
        rv = content;
    }
    if(!rv)return @"";
    
    // und formatieren
    if(HAS_FFLAG(OP_f_guidate)){
        rv = [(NSString *)rv guiDate];
    }
    if(HAS_FFLAG(OP_f_week)){
        rv = NSS([[PBDate dateWithDBString:(NSString *)rv] weekOfYear]);
    }
    if(HAS_FFLAG(OP_f_month)){
        rv = [[(NSString *)rv normalizedDate]nd_month];
    }
    if(HAS_FFLAG(OP_f_weekyear)){
        PBDate *pbd = [PBDate dateWithDBString:(NSString *)rv];
        rv = [NSSWF @"%04i/%02i",[pbd yearForWeek],[pbd weekOfYear]];
    }
    if(HAS_FFLAG(OP_f_year)){
        rv = [[(NSString *)rv normalizedDate]nd_year];
    }
    if(HAS_FFLAG(OP_f_yy)){
        rv = [[[(NSString *)rv normalizedDate]nd_year]secureSubstringFromIndex:2];
    }
    if(HAS_FFLAG(OP_f_wdayn)){
        rv = [[(NSString *)rv normalizedDate]nd_weekdayName];
    }
    if(HAS_FFLAG(OP_f_guiint)){
        rv = NSS((int)round0([(NSString *)rv doubleValue]));
    }
    if(HAS_FFLAG(OP_f_guiintnd)){
        rv = NSS([(NSString *)rv intValue]);
    }
    if(HAS_FFLAG(OP_f_rnd2)){
        rv = [NSString dbFromDouble:[(NSString *)rv doubleValue]];
    }
    if(HAS_FFLAG(OP_f_rnd1)){
        rv = [NSString dbFromDouble:[(NSString *)rv doubleValue] nak:1];
    }
    if(HAS_FFLAG(OP_f_guimoney)){
        rv = [NSString dottedGuiFromDouble:[(NSString *)rv doubleValue] nak:2];
    }
    if(HAS_FFLAG(OP_f_guif1)){
        rv = [NSString dottedGuiFromDouble:[(NSString *)rv doubleValue] nak:1];
    }
    if(HAS_FFLAG(OP_f_guif3)){
        rv = [NSString dottedGuiFromDouble:[(NSString *)rv doubleValue] nak:3];
    }
    if(HAS_FFLAG(OP_f_f1nd)){
        rv = [[NSSWF @"%0.1f",round1([(NSString *)rv doubleValue])]comma];
    }
    if(HAS_FFLAG(OP_f_f2nd)){
        rv = [[NSSWF @"%0.2f",round2([(NSString *)rv doubleValue])]comma];
    }
    if(HAS_FFLAG(OP_f_f3nd)){
        rv = [[NSSWF @"%0.3f",round3([(NSString *)rv doubleValue])]comma];
    }
    if(HAS_FFLAG(OP_f_flr)){
        rv = [[NSSWF @"%0.0f",floor([(NSString *)rv doubleValue])]comma];
    }
    if(HAS_FFLAG(OP_f_ceil)){
        rv = [[NSSWF @"%0.0f",ceil([(NSString *)rv doubleValue])]comma];
    }
    if(HAS_FFLAG(OP_f_uc)){
        rv = [(NSString *)rv uppercaseString];
    }
    if(HAS_FFLAG(OP_f_lc)){
        rv = [(NSString *)rv lowercaseString];
    }
    if(HAS_FFLAG(OP_f_trans)){
        rv = [_SESSION transScriptFor:(NSString *)rv];
    }
    if(HAS_FFLAG(OP_f_str) && trim){ // rechtsb. money, bei bedarf links mit spaces auffuellen
        rv = [(NSString *)rv str:trim];
    }
    if(HAS_FFLAG(OP_f_strs) && trim){ // rechtsb. string, bei bedarf links mit spaces auffuellen
        rv = [(NSString *)rv strs:trim];
    }
    if(HAS_FFLAG(OP_f_stl) && trim){ // linksb. string, bei bedarf rechts mit spaces auffuellenn
        rv = [(NSString *)rv strs:trim];
    }
    // evt. noch kuerzen
    if(HAS_FFLAG(OP_f_trim) && trim && [(NSString *)rv length]>trim)rv = [(NSString *)rv substringToIndex:trim];
    return rv;
}
- (void)dealloc;
{
    [expr release];
    [content release];
    [super dealloc];
}
@end
@implementation PBStatement
ACCESSClassm(op1,setOp1,PBOperand);
ACCESSClassm(op2,setOp2,PBOperand);
ACCESSClassm(op3,setOp3,PBOperand);
ACCESSClassm(op4,setOp4,PBOperand);
ACCESSm(line,setLine);
ACCESSm(error,setError);
ACCESSm(target,setTarget);
ACCESSm(targetFull,setTargetFull);
- (unsigned int)srclnr; {return srclnr;}
- (void)setSrclnr:(unsigned int)i; {srclnr = i;}
- (int)branch; {return branch;}
- (void)setBranch:(int)i; {branch = i;}
- (enum OPC)opcode;
{
    return opcode;
}
- (void)setOpcode:(enum OPC)opc;
{
    opcode = opc;
}
- (enum TGT_ds)target_ds;
{
    return target_ds;
}
- (void)setTarget_ds:(enum TGT_ds)tgt_ds;
{
    target_ds = tgt_ds;
}
- (NSMutableArray *)operands;
{
    return operands;
}
- (void)determine2Operands:(NSArray *)a;
{
    int i,j;
    for(i=0,j=[a count];i<j;i++){
        NSString *op = [a oai:i];
        PBOperand *pbop = [PBOperand operandFromString:op];
        if(pbop){
            [operands addObject:pbop];
            if(HAS_EFLAG([pbop formatting],OP_f_dblquote)){
                NSString *rv = [[a arrayFromIndex:i + 1]componentsJoinedByString:@","];
                if(FILLED(rv)){
                    [pbop setContent:[NSSWF @"%@,%@",[pbop content],rv]];
                }
                break;
            }
        }else{
            if(!FILLED(error)){
                [self setError:[NSSWF TRANSLATION(@"Operand %@ konnte nicht erzeugt werden"),op]];
            }
        }
    }
    j = [operands count];
    if(j-- > 0)[self setOp1:[operands oai:0]];
    if(j-- > 0)[self setOp2:[operands oai:1]];
    if(j-- > 0)[self setOp3:[operands oai:2]];
    if(j-- > 0)[self setOp4:[operands oai:3]];
}
- (PBStatement *)initWithLine:(NSString *)s;
{
    NSString *op;
    NSRange r;
    if(!(self = [super init]))return nil;
    if(!FILLED(s))return nil;
    if([s hasSecurePrefix:@"erklaerung"])return nil;
    if([s hasSecurePrefix:@"label "])return nil;
    MA(operands);
    [self setLine:s];
    opcode = OPC_NOP;
// kommentare duerfen hier nicht mehr vorkommen, da schon bei statementsForScript rausgefiltert
// Preprozessor Anweisungen werden zu NOPs
    if([line hasSecurePrefix:@"#"]){
        if([line hasSecurePrefix:@"#eo "]){
            NSArray *a = [line componentsSeparatedByString:@" "];
            NSString *vn,*tn;
            if([a count]!=3){
                [self setError:TRANSLATION(@"erwartet 2 Parameter:variableName und tableName")];
                return self;
            }
            vn = [[a oai:1]sbas:@"."];  // verwendung der Variablen in keypath
            tn = [a oai:2];
            if(![MYDD tableNamedCheap:tn]){
                [self setError:TRANSLATION(@"tableName ungueltig")];
                return self;
            }
            [self determine2Operands:[NSArray arrayWithObjects:vn,tn,nil]];
        }else if([line hasSecurePrefix:@"#warning "]){
            [self setError:@"warning# (not an Error)"];
        }
        return self;
    }
// Wertzuweisungen
    if([s hasPrefix:@"$"] || [s hasPrefix:@"%"]){ //Variable setzen; % extern, $ intern
        NSArray *a1 = [s componentsSeparatedByString:@","];
        NSString *tf;
        if([a1 count]<3){
            [self setError:TRANSLATION(@"weniger als 3 Elemente bei Zuweisungsbefehl")];
            return self;
        }
        tf = [a1 firstObject];
        [self setTargetFull:tf]; // f. Namechecking
        [self setTarget:[tf substringFromIndex:1]];
        if([tf hasSecurePrefix:@"$l_"]){
            target_ds = TGT_ds_localvardict; // intern
        }else if([tf hasPrefix:@"$"]){
            target_ds = TGT_ds_vardict;	// intern
        }else{
            target_ds = TGT_ds_datasource;
        }
        op = [[a1 oai:1]lowercaseString]; // der opcode
        
//der erste Operand, der mit doubleQuote beginnt, geht bis zum Ende der Zeile
        [self determine2Operands:[a1 arrayFromIndex:2]];
        if([op iE:@"spf"]){ //sprintf
            opcode = OPC_Z_spf; return self;
        }
        if([op iE:@"="]){ // string u. numerisch gleichermassen
            opcode = OPC_Z_set; return self;
        }
        if([op iE:@"ml"]){ // multi line; array of  strings ab naechster Zeile bis \end
            opcode = OPC_Z_ml; return self;
        }
        if([op iE:@"=:"] || [op iE:@":="]){ // zuweisung formatiert nach EO (der linke operand muss ein EO feld sein)
            opcode = OPC_Z_set_formatted; return self;
        }
        if([op iE:@"a"]){ //append string(s), add Objects
            opcode = OPC_Z_a; return self;
        }
        if([op iE:@"au"]){ //addUniq; nur fuer Arrays
            opcode = OPC_Z_au; return self;
        }
        if([op iE:@"ah"]){ //append hex; einzelne Bytes
            opcode = OPC_Z_ah; return self;
        }
        if([op iE:@"find"]){
            opcode = OPC_Z_find;
            if([operands count]<2){
                [self setError:TRANSLATION(@"mind. 2 Operanden: string, suchstring")];
            }
            return self;
        }
        if([op iE:@"ss"]){ //ss substring string,von,laenge
            opcode = OPC_Z_ss;
            if([operands count]!=3){
                [self setError:TRANSLATION(@"3 Operanden: string, von, laenge")];
            }
            return self;
        }
        if([op iE:@"geteopkvalue"]){ //eo fetchen
            opcode = OPC_Z_geteopkvalue;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: entityname, pk-value")];
            }
            return self;
        }
        if([op iE:@"geteoq"]){ //getEOQ,entityName,Qualifier
            opcode = OPC_Z_geteoq;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: entityname, qualifier")];
            }
            return self;
        }
        if([op iE:@"geteoqf"]){ //getEOQf,entityName,Qualifierformat
            opcode = OPC_Z_geteoqf;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: entityname, qualifierformat")];
            }
            return self;
        }
        if([op iE:@"geteosq"]){ //getEOsQ,entityName,Qualifier
            opcode = OPC_Z_geteosq;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: entityname, qualifier")];
            }
            return self;
        }
        if([op iE:@"geteosqf"]){ //getEOsQf,entityName,Qualifierformat
            opcode = OPC_Z_geteosqf;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: entityname, qualifierformat")];
            }
            return self;
        }
        if([op iE:@"geteosqsoa"]){ //getEOsQSoa,entityName,Qualifier,soa; optionaler limit-Count
            opcode = OPC_Z_geteosqsoa;
            if([operands count]<3){
                [self setError:TRANSLATION(@"mind 3 Operanden: entityname, qualifier, soa")];
            }
            return self;
        }
        if([op iE:@"soafrom"]){ //$name,soaFrom,op1,...	macht sortorder Array in $name; op1... sind die feldnamen mit angehaengtem :a bzw. :d
            opcode = OPC_Z_soafrom; return self;
        }
        if([op iE:@"newfile"]){ // liefert Filehandle
            opcode = OPC_Z_newfile; return self;
        }
        if([op iE:@"neweo"]){ //
            opcode = OPC_Z_neweo; return self;
        }
        if([op iE:@"newstring"]){ //
            opcode = OPC_Z_newstring; return self;
        }
        if([op iE:@"newdata"]){ //
            opcode = OPC_Z_newdata; return self;
        }
        if([op iE:@"newarraye"]){ // Array aus elementen
            opcode = OPC_Z_newarraye; return self;
        }
        if([op iE:@"newarray"]){ //
            opcode = OPC_Z_newarray; return self;
        }
        if([op iE:@"class"]){ // class pointer
            opcode = OPC_Z_class; return self;
        }
        if([op iE:@"newdict"]){ //
            opcode = OPC_Z_newdict; return self;
        }
        if([op iE:@"newset"]){ //
            opcode = OPC_Z_newset; return self;
        }
        if([op iE:@"count"]){ //
            opcode = OPC_Z_count; return self;
        }
        if([op iE:@"cat"]){ //$s,cat,$a,$s1,...
            opcode = OPC_Z_cat;
            if([operands count]<1){
                [self setError:TRANSLATION(@"mind. 1 Operand")];
            }
            return self;
        }
        if([op iE:@"oai"]){ //$v,oai,$array,$index
            opcode = OPC_Z_oai;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: array, index")];
            }
            return self;
        }
        if([op iE:@"ofk"]){ //$v,ofk,$dict,$key
            opcode = OPC_Z_ofk;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: dict, key")];
            }
            return self;
        }
        if([op iE:@"css"]){ //$v,css,$string,$sep
            opcode = OPC_Z_css;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: string, separator")];
            }
            return self;
        }
        if([op iE:@"cjs"]){ //$v,cjs,$array,$join
            opcode = OPC_Z_cjs;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: array, joinstring")];
            }
            return self;
        }
        if([op iE:@"cai"]){ //$v,cai,$string,$index
            opcode = OPC_Z_cai;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: string, index")];
            }
            return self;
        }
        if([op iE:@"allk"]){ //$v,allk,$dict
            opcode = OPC_Z_allk; return self;
        }
        if([op iE:@"description"]){ //$v,description,$o
            opcode = OPC_Z_allk; return self;
        }
        if([op iE:@"modul"]){ //modul,modulName	liefert das Modul namens modulNa
            opcode = OPC_Z_modul; return self;
        }
        if([op iE:@"allv"]){ //$v,allv,$dict
            opcode = OPC_Z_allv; return self;
        }
        if([op iE:@"q"] || [op iE:@"sqlq"]){ //$name,q,op1		macht pbsqlqualifier mit qualifierformat op1
            opcode = OPC_Z_q; return self;
        }
        if([op iE:@"qand"]){ //qand,array	macht einen and-qualifier
            opcode = OPC_Z_qand; return self;
        }
        if([op iE:@"qor"]){ //qor,array	macht einen or-qualifier
            opcode = OPC_Z_qor; return self;
        }
        if([op iE:@"allq"]){ // allQualifier
            opcode = OPC_Z_set;
            [operands removeAllObjects];
            [operands addObject:[PBOperand operandWithConstantObject:PBALLQ]];
            return self;
        }
        if([op iE:@"nothingq"]){ // Nothing-Qualifier
            opcode = OPC_Z_set;
            [operands removeAllObjects];
            [operands addObject:[PBOperand operandWithConstantObject:PBNOTHINGQ]];
            return self;
        }
        if([op iE:@"setfetchcond"]){ //$name,setFetchCond, qualifier,entityName,soa,handle; liefert J oder N;
            opcode = OPC_Z_setfetchcond;
            if([operands count]<4){
                [self setError:TRANSLATION(@"min. 4 Operanden: qualifier, entityName, soa, handle, fetchlimit")];
            }
            return self;
        }
        if([op iE:@"nextmdforhandle"]){ //$name,nextMDForHandle,op1  liefert in $name das MD bzw. nil, wenn nix mehr da
            opcode = OPC_Z_nextmdforhandle; return self;
        }
        if([op iE:@"nexteoforhandle"]){ //$name,nextMDForHandle,op1  liefert in $name das EO bzw. nil, wenn nix mehr da
            opcode = OPC_Z_nexteoforhandle; return self;
        }
        if([op iE:@"swcof"]){ //string with contents of file
            opcode = OPC_Z_swcof; return self;
        }
        if([op iE:@"attributes"]){ //file-Attribute
            opcode = OPC_Z_attributes; return self;
        }
        if([op iE:@"lookup"]){ //in tabelle nachschlagen
            opcode = OPC_Z_lookup;
            if([operands count]!=3){
                [self setError:TRANSLATION(@"3 Operanden: lookup-Tabellenname, row, col")];
            }
            return self;
        }
        if([op iE:@"singlevaluesql"]){ //getSingleValueAsResultFrom
            opcode = OPC_Z_singlevaluesql; return self;
        }
        if([op iE:@"singlerecordsql"]){ //getDictAsResultFrom
            opcode = OPC_Z_singlerecordsql; return self;
        }
        if([op iE:@"arraysql"]){ //macht getArrayAsResultFrom:sql, liefert ein array of dictionaries
            opcode = OPC_Z_arraysql; return self;
        }
        if([op iE:@"arraysqls"]){ //macht getArrayAsResultFrom:sql, liefert ein array of strings
            opcode = OPC_Z_arraysqls; return self;
        }
        if([op iE:@"nowformat"]){ //now with format
            opcode = OPC_Z_nowformat; return self;
        }
        if([op iE:@"tablenamed"]){ //Tabelle besorgen
            opcode = OPC_Z_tablenamed; return self;
        }
        if([op iE:@"d+"]){ // date add; oldObject muss ein normalizedDate sein
            opcode = OPC_Z_dplus;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: anzahl, intervall")];
            }
            return self;
        }
        if([op iE:@"d-"]){ // date add; oldObject muss ein normalizedDate sein
            opcode = OPC_Z_dminus;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: anzahl, intervall")];
            }
            return self;
        }
        if([op iE:@"dd"]){ // date difference; op1 u. op2 muessen normalizedDate sein
            opcode = OPC_Z_dd;
            if([operands count]!=2){
                [self setError:TRANSLATION(@"2 Operanden: datum1, datum2")];
            }
            return self;
        }
        if([op iE:@"+"] || [op iE:@"-"] || [op iE:@"*"] || [op iE:@"/"] || [op iE:@"m"]){
            if([operands count]!=1){
                [self setError:TRANSLATION(@"genau 1 Operand erforderlich")]; return self;
            }
            if([op iE:@"+"]){
                opcode = OPC_Z_plus; return self;
            }else if([op iE:@"-"]){
                opcode = OPC_Z_minus; return self;
            }else if([op iE:@"*"]){
                opcode = OPC_Z_mal; return self;
            }else if([op iE:@"/"]){
                opcode = OPC_Z_geteilt; return self;
            }else if([op iE:@"m"]){
                opcode = OPC_Z_modulo; return self;
            }
        }
        [self setError:TRANSLATION(@"falscher zuweisungsbefehl")]; return self;
    }
    
// -----------------------------------------------------------------------------------------
// sonstige Befehle:
// Aufbau:Befehl [, Space, Operanden mit Komma getrennt]
    r = [s rangeOfString:@" "];
    if(r.length){
        op = [[line substringToIndex:r.location]lowercaseString];
        [self determine2Operands:[[s substringFromIndex:(r.location + r.length)]componentsSeparatedByString:@","]];
    }else{
        op = [s lowercaseString];
    }
    if([op hasSecurePrefix:@"debug"]){
        opcode = OPC_debug_start; return self;
    }
    if([op hasSecurePrefix:@"nodebug"] || [op hasSecurePrefix:@"enddebug"]){
        opcode = OPC_debug_end; return self;
    }
    if([op hasSecurePrefix:@"endif"]){
        opcode = OPC_endif; return self;
    }
    if([op iE:@"say"]){ // in scratchpad schreiben say clear; say x,y,{l,r},value;
        if(![[(PBOperand *)[operands firstObject]content]hasSecurePrefix:@"clear"] && ([operands count]<4))[self setError:TRANSLATION(@"mind. 4  Operanden: x,y,{l,r},value; oder clear;")];
        opcode = OPC_say; return self;
    }
    if([op iE:@"sayw"]){ // in scratchpad schreiben say clear; sayw x,y,{l,r},w,value
        if([operands count]<5)[self setError:TRANSLATION(@"mind. 5  Operanden: x,y,{l,r},w,value")];
        opcode = OPC_sayw; return self;
    }
    if([op iE:@"updat_eo"]){ //eo updaten
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: EO")];
        opcode = OPC_updat_eo; return self;
    }
    if([op iE:@"delet_eo"]){ //eo delete
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: EO")];
        opcode = OPC_delet_eo; return self;
    }
    if([op iE:@"insrt_eo"]){ //eo insert
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: EO")];
        opcode = OPC_insrt_eo; return self;
    }
    if([op iE:@"system"]){ //shell commando;
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: system-befehl")];
        opcode = OPC_system; return self;
    }
    if([op iE:@"suchexternal"]){ // suchexternal modul,q	fuehrt Suchexternal mit Qualifier q aus
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: modul,qualifier")];
        opcode = OPC_suchexternal; return self;
    }
    if([op iE:@"executestring"]){ //anderes Script, das in einem String liegt ausfuehren mit derselben datasource u. parmdict; Name muss eindeutig sein, imports werden aufgeloest; varDict des gerufenen Scripts kommt in _rv zurureck
// op1 = Name, op2 = script-Inhalt
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: scriptname,script-content")];
        opcode = OPC_executestring; return self;
    }
    if([op iE:@"execute"]){ //anderes Script ausfuehren mit derselben datasource u. parmdict; script wird nur im scriptDict gesucht; varDict des gerufenen Scripts kommt in _rv zurureck
        if([operands count]!=1){
            [self setError:TRANSLATION(@"1  Operand: scriptname")];
        }else{
            if([op1 isConstant]){
                if(![[_APP scriptDict]ofk:[op1 content]])[self setError:TRANSLATION(@"Script nicht vorhanden")];
            }
        }
        opcode = OPC_execute; return self;
    }
    if([op hasSecurePrefix:@"log"]){ //ausdruck loggen; vorangestelltes "" nimmt den String woertlich
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: log-Message")];
        if([op iE:@"log"]){
            opcode = OPC_log; return self;
        }
        if([op iE:@"logi"]){
            opcode = OPC_logi; return self;
        }
        opcode = OPC_logs; return self;
    }
    if([op iE:@"lookupbegin"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: lookupname")];
        opcode = OPC_lookupbegin; return self;
    }
    if([op iE:@"matrixbegin"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: matrixname")];
        opcode = OPC_matrixbegin; return self;
    }
    if([op iE:@"diaconfirm"]){ //Alertbox mit String, ja/nein
        opcode = OPC_diaconfirm; return self;
    }
    if([op iE:@"diaalert"]){ //Alertbox; nur zu bestaetigen
        opcode = OPC_diaalert; return self;
    }
    if([op iE:@"gosub"]){ //sprungziel kann auch in variable stehen
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: subroutine-name")];
        opcode = OPC_gosub; return self;
    }
    if([op hasSecurePrefix:@"endsub"]){
        opcode = OPC_endsub; return self;
    }
    if([op hasSecurePrefix:@"return"]){
        opcode = OPC_return; return self;
    }
    if([op iE:@"sub"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: subroutine-name")];
        opcode = OPC_sub; return self;
    }
    if(([op hasSecurePrefix:@"else"])){
        opcode = OPC_else; return self;
    }
    if([op hasSecurePrefix:@"continuefor"]){
        opcode = OPC_continuefor; return self;
    }
    if(([op hasSecurePrefix:@"endwhile"])){
        opcode = OPC_endwhile; return self;
    }
    if(([op hasSecurePrefix:@"continue"])){
        opcode = OPC_continue; return self;
    }
    if([op hasSecurePrefix:@"breakfor"]){
        opcode = OPC_breakfor; return self;
    }
    if([op hasSecurePrefix:@"break"]){
        opcode = OPC_break; return self;
    }
    if([op iE:@"rao"]){ //remove all objects
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: mutablearray oder mutabledict")];
        opcode = OPC_rao; return self;
    }
    if([op iE:@"rofk"]){ //rofk Dict,key
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: mutabledict,key")];
        opcode = OPC_rofk; return self;
    }
    if([op iE:@"sort"]){ //sort Array,soa
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: array,sortorderarray")];
        opcode = OPC_sort; return self;
    }
    if([op iE:@"roai"]){ //roai Array,index
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: mutablearray,index")];
        opcode = OPC_roai; return self;
    }
    if([op iE:@"ioai"]){ //ioai Array,index,o
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: mutablearray,index,object")];
        opcode = OPC_ioai; return self;
    }
    if([op iE:@"wtf"]){ //write to file: String,Path,[encoding(default:utf8)]
        if([operands count]<2)[self setError:TRANSLATION(@"mind. 2  Operanden: string,path")];
        opcode = OPC_wtf; return self;
    }
    if([op hasSecurePrefix:@"ps"] || [op iE:@"invk"]){ //invk object message arg1, arg2, ...
// NSInvocation;
        if([operands count]<2)[self setError:TRANSLATION(@"mind. 2  Operanden: target,selector")];
        opcode = OPC_invk; return self;
    }
    if([op iE:@"foreach"]){ // item,array[,index]
        if([operands count]<2)[self setError:TRANSLATION(@"mind. 2  Operanden: item-name,array")];
        opcode = OPC_foreach; return self;
    }
    if([op hasSecurePrefix:@"endfor"]){
        opcode = OPC_endfor; return self;
    }
    if(([op hasSecurePrefix:@"end"])){
        opcode = OPC_end; return self;
    }
    if(([op iE:@"if"]) ||  ([op iE:@"while"])){ //bedingt ausfuehren if exp1,op,exp2 bzw. while-Schleife
        PBOperand *pbop;
        NSString *vgl;
        if([operands count]<3){
            [self setError:TRANSLATION(@"mind 3  Operanden: exp1,vgl-op,exp2")];
        }
        if([op iE:@"if"]){
            opcode = OPC_if;
        }else{
            opcode = OPC_while;
        }
        if(error)return self;
        pbop = [operands oai:1];
        vgl = [pbop content];
        if([vgl hasSecurePrefix:@"!"]){
            negate=YES;
            vgl = [vgl substringFromIndex:1];
        }
        if([vgl iE:@"in"]){ // Auflistung alternativer Werte
            comparison = CMP_in;
        }else if([vgl iE:@"eq"]){ //string Vergleich
            comparison = CMP_eq;
        }else if([vgl iE:@"ne"]){ //string Vergleich
            comparison = CMP_ne;
        }else if([vgl iE:@"prefix"]){ //hasPrefix
            comparison = CMP_prefix;
        }else if([vgl iE:@"suffix"]){ //hasSuffix
            comparison = CMP_suffix;
        }else if([vgl iE:@"FILLED"]){ //test auf gefuellt; geht fuer alle Objekte;
            comparison = CMP_filled;
        }else if([vgl iE:@"FILLEDNUM"]){ //test auf gefuellt und numerisch <> 0; geht fuer alle Objekte;
            comparison = CMP_fillednum;
        }else if([vgl iE:@"exists"]){ //test auf File existent
            comparison = CMP_exists;
        }else if([vgl iE:@"contains"]){ //containsObject: testen
            comparison = CMP_contains;
        }else if([vgl iE:@"like"]){ //mit wildcards
            comparison = CMP_like;
        }else if([vgl iE:@"=="] || [vgl iE:@"="]){ //numerisch Vergleich; auch falsch geschrieben
            comparison = CMP_equals;
        }else if([vgl iE:@">"]){ //numerisch Vergleich
            comparison = CMP_gt;
        }else if([vgl iE:@"<"]){ //numerisch Vergleich
            comparison = CMP_lt;
        }else if([vgl iE:@">="] || [vgl iE:@"=>"]){ //numerisch Vergleich
            comparison = CMP_ge;
        }else if([vgl iE:@"<="] || [vgl iE:@"=<"]){ //numerisch Vergleich
            comparison = CMP_le;
        }else{
            [self setError:@"falscher Vergleichsoperator"];
        }
        return self;
    }
    if([op iE:@"dbnr"]){ //setzt dbnr
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: db-nr")];
        opcode = OPC_dbnr; return self;
    }
    if([op hasSecurePrefix:@"autorelease"]){
        opcode = OPC_autorelease; return self;
    }
    if([op iE:@"lang"]){ //setzt Script-Sprache abweichend von user-sprache fuer <trans>
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: sprachen-nr.")];
        opcode = OPC_lang; return self;
    }
    if([op iE:@"fieldon"]){
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: feld-name")];
        opcode = OPC_fieldon; return self;
    }
    if([op iE:@"fieldoff"]){
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: feld-name")];
        opcode = OPC_fieldoff; return self;
    }
    if([op iE:@"markerror"]){
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: feld-name")];
        opcode = OPC_markerror; return self;
    }
    if([op iE:@"optionstd"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: vl-name")];
        opcode = OPC_optionstd; return self;
    }
    if([op iE:@"optionadd"]){
        if([operands count]<3)[self setError:TRANSLATION(@"mind 3  Operanden: vl-name,vl-wert,vl-bez")];
        opcode = OPC_optionadd; return self;
    }
    if([op iE:@"optionrem"]){
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: vl-name,vl-wert")];
        opcode = OPC_optionadd; return self;
    }
    if([op hasSecurePrefix:@"allfieldson"]){
        opcode = OPC_allfieldson; return self;
    }
    if([op hasSecurePrefix:@"allfieldsoff"]){
        opcode = OPC_allfieldsoff; return self;
    }
    if([op hasSecurePrefix:@"allfieldsvisible"]){
        opcode = OPC_allfieldsvisible; return self;
    }
    if([op iE:@"fieldvisible"]){
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: feld-name")];
        opcode = OPC_fieldvisible; return self;
    }
    if([op iE:@"fieldinvisible"]){
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: feld-name")];
        opcode = OPC_fieldinvisible; return self;
    }
    if([op iE:@"registerinvisible"]){
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: register-name")];
        opcode = OPC_registerinvisible; return self;
    }
    if([op hasSecurePrefix:@"registervisible"]){
        opcode = OPC_registervisible; return self;
    }
    if([op iE:@"createbutton"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: on/off")];
        opcode = OPC_createbutton; return self;
    }
    if([op iE:@"duplicatebutton"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: on/off")];
        opcode = OPC_duplicatebutton; return self;
    }
    if([op iE:@"deletebutton"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: on/off")];
        opcode = OPC_deletebutton; return self;
    }
    if([op iE:@"sql"]){ //sql commando; vorangestelltes "" nimmt den String woertlich
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: sql-statement")];
        opcode = OPC_sql; return self;
    }
// =====================================================================================
// Druck-Kommandos
// damit kann man sich selbst ein limit setzen, um z.B. Benutzereingaben, die zuviel Seiten produzieren wuerden, abzubrechen
    if([op iE:@"pages"]){
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: max. anzahl seiten")];
        opcode = OPC_pdf_pages; return self;
    }
    if([op hasSecurePrefix:@"newpageqm"]){
        opcode = OPC_pdf_newpageqm; return self;
    }
    if([op hasSecurePrefix:@"newpagequer"]){
        opcode = OPC_pdf_newpagequer; return self;
    }
    if([op hasSecurePrefix:@"newpagea5quer"]){
        opcode = OPC_pdf_newpagea5quer; return self;
    }
    if([op iE:@"newpagewh"]){
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: width, height")];
        opcode = OPC_pdf_newpagewh; return self;
    }
    if([op hasSecurePrefix:@"newpage"]){
        opcode = OPC_pdf_newpage; return self;
    }
    if([op hasSecurePrefix:@"lsn"]){ //linestyle normal
        opcode = OPC_pdf_lsn; return self;
    }
    if([op iE:@"scale"]){ //scale 10 -> 1/10 mm; 1 -> 1 mm
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: skalierungsfaktor")];
        opcode = OPC_pdf_scale; return self;
    }
    if([op iE:@"sprache"]){ //obsolet
        opcode = OPC_NOP; return self;
    }
    if([op iE:@"o"]){ //Delta x,y-offset  o 1,2
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: offset-x,offset-y")];
        opcode = OPC_pdf_o; return self;
    }
    if([op iE:@"f"]){ //font f Arial,12
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: font-name")];
        opcode = OPC_pdf_f; return self;
    }
    if([op iE:@"s"]){ //size  s 12
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: font-groesse")];
        opcode = OPC_pdf_s; return self;
    }
    if([op iE:@"lc"]){ //lineColor  lc 85      100 =weiss, 0 schwarz;
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: grauwert")];
        opcode = OPC_pdf_lc; return self;
    }
    if([op iE:@"lc#"]){ //lineColor  hex;
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: hex-farbcode")];
        opcode = OPC_pdf_lchex; return self;
    }
    if([op iE:@"lc255"]){ //lineColor  0...255 jeweils
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: r,g,b")];
        opcode = OPC_pdf_lc255; return self;
    }
    if([op iE:@"lcrgb"]){
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: r,g,b")];
        opcode = OPC_pdf_lcrgb; return self;
    }
    if([op iE:@"fc"]){ // fill/fontColor        100 =weiss, 0 schwarz;
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: grauwert")];
        opcode = OPC_pdf_fc; return self;
    }
    if([op iE:@"fc#"]){ // fillColor  hex;
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: hex-farbcode")];
        opcode = OPC_pdf_fchex; return self;
    }
    if([op iE:@"fc255"]){ // fillColor  0...255 jeweils
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: r,g,b")];
        opcode = OPC_pdf_fc255; return self;
    }
    if([op iE:@"fcrgb"]){
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: r,g,b")];
        opcode = OPC_pdf_fcrgb; return self;
    }
    if([op iE:@"lw"]){ //lineWidth  lw 30  -> 3 mm
        if([operands count]!=1)[self setError:TRANSLATION(@"1  Operand: line-width")];
        opcode = OPC_pdf_lw; return self;
    }
    if([op iE:@"ls"]){ //linestyle x1,x2
        if([operands count]!=2)[self setError:TRANSLATION(@"2  Operanden: mark,space")];
        opcode = OPC_pdf_ls; return self;
    }
    if([op iE:@"rf"]){ //rahmen filled rf x,y,dx,dy   x,y Koord., width, height mit current fillStroke
        if([operands count]!=4)[self setError:TRANSLATION(@"4  Operanden: x,y,width,height")];
        opcode = OPC_pdf_rf; return self;
    }
    if([op iE:@"rl"]){ //rahmen leerx,y Koord., width, height
        if([operands count]!=4)[self setError:TRANSLATION(@"4  Operanden: x,y,width,height")];
        opcode = OPC_pdf_rl; return self;
    }
    if([op iE:@"kf"]){ //kreis filled x,y,radius
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: x,y,radius")];
        opcode = OPC_pdf_kf; return self;
    }
    if([op iE:@"kl"]){ //kreis leer x,y,radius
        if([operands count]!=3)[self setError:TRANSLATION(@"3  Operanden: x,y,radius")];
        opcode = OPC_pdf_kl; return self;
    }
    if([op iE:@"lvb"]){ //line  lvb x1,y1,x2,y2   2 pt. verbinden; mit current lineWidth u. grayStroke
        if([operands count]!=4)[self setError:TRANSLATION(@"4  Operanden: x1,y1,x2,y2")];
        opcode = OPC_pdf_lvb; return self;
    }
    if([op iE:@"l"]){ //line  l x,y,o,l   x,y Koord., orientation, length; mit current lineWidth u. grayStroke
        if([operands count]!=4)[self setError:TRANSLATION(@"4  Operanden: x1,y1,orientation,length")];
        opcode = OPC_pdf_l; return self;
    }
    if([op iE:@"?"]){ // print dBase style
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: ausgabestring")];
        opcode = OPC_pdf_print; return self;
    }
    if([op iE:@"?b"]){ // print dBase style bold
        if([operands count]<1)[self setError:TRANSLATION(@"mind. 1  Operand: ausgabestring")];
        opcode = OPC_pdf_printb; return self;
    }
    if([op iE:@"v"]){
        if([operands count]<4)[self setError:TRANSLATION(@"mind. 4  Operanden: x,y,orientation,ausgabestring")];
        opcode = OPC_pdf_v; return self;
    }
    if([op iE:@"vc"]){
        if([operands count]<4)[self setError:TRANSLATION(@"mind. 4  Operanden: x,y,orientation,ausgabestring")];
        opcode = OPC_pdf_vc; return self;
    }
    if([op iE:@"vw"]){
        if([operands count]<5)[self setError:TRANSLATION(@"mind. 5  Operanden: x,y,orientation,width,ausgabestring")];
        opcode = OPC_pdf_vw; return self;
    }
    if([op hasSecurePrefix:@"render"]){ //in file rendern; script kann danach mit dem file was machen
        opcode = OPC_pdf_render; return self;
    }
    if([op hasSecurePrefix:@"dont_render"]){ //finischPDF davon abhalten, das PDF rendern zu wollen
        opcode = OPC_pdf_dont_render; return self;
    }
    if([op hasSecurePrefix:@"ub"]){ //underline beginn;
        opcode = OPC_pdf_ub; return self;
    }
    if([op hasSecurePrefix:@"ue"]){ //underline end;
        opcode = OPC_pdf_ue; return self;
    }
    if([op iE:@"b"]){
        if([operands count]<6)[self setError:TRANSLATION(@"mind. 6  Operanden: x,y,width,height,orientation,ausgabestring")];
        opcode = OPC_pdf_b; return self;
    }
    if([op iE:@"bf"]){
        if([operands count]<5)[self setError:TRANSLATION(@"mind. 5  Operanden: x,y,width,height,orientation")];
        opcode = OPC_pdf_bf; return self;
    }
    if([op iE:@"dg"]){
        opcode = OPC_pdf_dg; return self;
    }
    if([op iE:@"g"] || [op iE:@"gw"]){
        if([operands count]!=4)[self setError:TRANSLATION(@"4  Operanden: x,y,width,path")];
        opcode = OPC_pdf_g; return self;
    }
    if([op iE:@"gh"]){
        if([operands count]!=4)[self setError:TRANSLATION(@"4  Operanden: x,y,height,path")];
        opcode = OPC_pdf_gh; return self;
    }
    [self setError:@"unknown opcode"];
    return self;
}
+ (PBStatement *)statementFromLine:(NSString *)s;
{
    PBStatement *stmt = [[PBStatement alloc]initWithLine:s];
    return [stmt autorelease];
}
- (NSString *)debugDescription;
{
    LMA;
    NSString *tf,*br,*cmp;
    [lma addObject:[NSSWF @"%03i %@",srclnr,line]];
    if(branch){
        br = [NSSWF @"  branch: %i",branch];
    }else{
        br = @"";
    }
    if(comparison){
        cmp = [NSSWF @"  comparison: %i",comparison];
    }else{
        cmp = @"";
    }
    if(targetFull){
        tf = [NSSWF @"  targetFull: %@",targetFull];
    }else{
        tf = @"";
    }
    [lma addObject:[NSSWF @"    opcode: %i%@%@%@",opcode,br,cmp,tf]];
    if([operands count]){
        int i,j;
        for(i=0,j=[operands count];i<j;i++){
            PBOperand *op = [operands oai:i];
            NSArray *a = [[op description]componentsSeparatedByString:@"\n"];
            int i1,j1;
            for(i1=0,j1=[a count];i1<j1;i1++){
                [lma addObject:[NSSWF @"        %@",[a oai:i1]]];
            }
        }
    }
    return [lma componentsJoinedByString:@"\n"];
}
- (NSString *)htmlDescription;
{
// ist nur fuer html
    if(error){
        if([line hasSecurePrefix:@"#warning"]){
            return [NSSWF @"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%@ (%04i)",[line htmlEscapedString],srclnr + 1]; // Editor zaehlt Zeilen ab 1
        }else{
            return [NSSWF @"&nbsp;&nbsp;&nbsp;%04i %@ *** %@",srclnr + 1,[line htmlEscapedString],[error htmlEscapedString]]; // Editor zaehlt Zeilen ab 1
        }
    }
    return [line htmlEscapedString];
}
- (NSString *)description;
{
    if(error){
        if([line hasSecurePrefix:@"#warning"]){
            return [NSSWF @"\t\t%@ (%04i)",line,srclnr + 1]; // Editor zaehlt Zeilen ab 1
        }else{
            return [NSSWF @"\t%04i %@ *** %@",srclnr + 1,line,error]; // Editor zaehlt Zeilen ab 1
        }
    }
    return line;
}
- (BOOL)negate;
{
    return negate;
}
- (void)dealloc;
{
    [op1 release];
    [op2 release];
    [op3 release];
    [op4 release];
    [line release];
    [error release];
    [target release];
    [targetFull release];
    [operands release];
    [super dealloc];
}
@end
Foto