// Copyright 2001, FreeHEP.
package org.freehep.postscript;
import java.io.IOException;
/**
* General Operators for PostScript Processor
*
* @author Mark Donszelmann
* @version $Id: GeneralOperator.java 8958 2006-09-12 23:37:43Z duns $
*/
public class GeneralOperator extends PSOperator {
public static Class[] operators = {
Length.class, Get.class, Put.class,
GetInterval.class, PutInterval.class,
ALoad.class, Copy.class, ForAll.class,
Token.class
};
public boolean execute(OperandStack os) {
throw new RuntimeException("Cannot execute class: "+getClass());
}
}
class Length extends GeneralOperator {
public boolean execute(OperandStack os) {
if (os.checkType(PSPackedArray.class)) {
PSPackedArray a = os.popPackedArray();
os.push(a.size());
} else if (os.checkType(PSDictionary.class)) {
PSDictionary d = os.popDictionary();
os.push(d.size());
} else if (os.checkType(PSString.class)) {
PSString s = os.popString();
os.push(s.size());
} else if (os.checkType(PSName.class)) {
PSName n = os.popName();
os.push(n.size());
} else {
error(os, new TypeCheck());
}
return true;
}
}
class Get extends GeneralOperator {
public boolean execute(OperandStack os) {
if (os.checkType(PSArray.class, PSInteger.class) ||
os.checkType(PSPackedArray.class, PSInteger.class)) {
PSInteger i = os.popInteger();
PSArray a = os.popArray();
if ((i.getValue() < 0) || (i.getValue() >= a.size())) {
error(os, new RangeCheck());
} else {
os.push(a.get(i.getValue()));
}
} else if (os.checkType(PSDictionary.class, PSObject.class)) {
PSObject key = os.popObject();
PSDictionary d = os.popDictionary();
PSObject o = d.get(key);
if (o == null) {
error(os, new Undefined());
} else {
os.push(o);
}
} else if (os.checkType(PSString.class, PSInteger.class)) {
PSInteger i = os.popInteger();
PSString s = os.popString();
if ((i.getValue() < 0) || (i.getValue() >= s.size())) {
error(os, new RangeCheck());
} else {
os.push(s.get(i.getValue()));
}
} else {
error(os, new TypeCheck());
}
return true;
}
}
class Put extends GeneralOperator {
public boolean execute(OperandStack os) {
if (os.checkType(PSArray.class, PSInteger.class, PSObject.class)) {
PSObject o = os.popObject();
PSInteger i = os.popInteger();
PSArray a = os.popArray();
if ((i.getValue() < 0) || (i.getValue() >= a.size())) {
error(os, new RangeCheck());
} else {
a.set(i.getValue(), o);
}
} else if (os.checkType(PSDictionary.class, PSObject.class, PSObject.class)) {
PSObject o = os.popObject();
PSObject key = os.popObject();
PSDictionary d = os.popDictionary();
d.put(key, o);
o.setName(key.cvs());
} else if (os.checkType(PSString.class, PSInteger.class, PSInteger.class)) {
PSInteger o = os.popInteger();
PSInteger i = os.popInteger();
PSString s = os.popString();
if ((i.getValue() < 0) || (i.getValue() >= s.size())) {
error(os, new RangeCheck());
} else {
s.set(i.getValue(), o.getValue());
}
} else {
error(os, new TypeCheck());
}
return true;
}
}
class GetInterval extends GeneralOperator {
public boolean execute(OperandStack os) {
if (os.checkType(PSArray.class, PSInteger.class, PSInteger.class)) {
PSInteger c = os.popInteger();
PSInteger i = os.popInteger();
PSArray a = os.popArray();
PSArray s = a.subArray(i.getValue(), c.getValue());
if (s == null) {
error(os, new RangeCheck());
} else {
os.push(s);
}
} else if (os.checkType(PSPackedArray.class, PSInteger.class, PSInteger.class)) {
PSInteger c = os.popInteger();
PSInteger i = os.popInteger();
PSPackedArray a = os.popPackedArray();
PSPackedArray s = a.subPackedArray(i.getValue(), c.getValue());
if (s == null) {
error(os, new RangeCheck());
} else {
os.push(s);
}
} else if (os.checkType(PSString.class, PSInteger.class, PSInteger.class)) {
PSInteger c = os.popInteger();
PSInteger i = os.popInteger();
PSString s = os.popString();
PSString ss = s.subString(i.getValue(), c.getValue());
if (ss == null) {
error(os, new RangeCheck());
} else {
os.push(ss);
}
} else {
error(os, new TypeCheck());
}
return true;
}
}
class PutInterval extends GeneralOperator {
public boolean execute(OperandStack os) {
if (os.checkType(PSArray.class, PSInteger.class, PSPackedArray.class)) {
PSPackedArray a2 = os.popPackedArray();
PSInteger i = os.popInteger();
PSArray a1 = os.popArray();
if ((i.getValue() < 0) || (i.getValue()+a2.size() > a1.size())) {
error(os, new RangeCheck());
} else {
for (int j=0; j<a2.size(); j++) {
a1.set(i.getValue()+j, a2.get(j));
}
}
} else if (os.checkType(PSString.class, PSInteger.class, PSString.class)) {
PSString s2 = os.popString();
PSInteger i = os.popInteger();
PSString s1 = os.popString();
if ((i.getValue() < 0) || (i.getValue()+s2.size() > s1.size())) {
error(os, new RangeCheck());
} else {
for (int j=0; j<s2.size(); j++) {
s1.set(i.getValue()+j, s2.get(j));
}
}
} else {
error(os, new TypeCheck());
}
return true;
}
}
class ALoad extends GeneralOperator {
{ operandTypes = new Class[] {PSPackedArray.class}; }
// FIXME nothing done about InvalidAccess
public boolean execute(OperandStack os) {
PSArray a = os.popArray();
for (int i=0; i<a.size(); i++) {
os.push(a.get(i));
}
os.push(a);
return true;
}
}
class Copy extends GeneralOperator {
// FIXME: access checks not done
public boolean execute(OperandStack os) {
if (os.checkType(PSInteger.class)) {
int n = os.popInteger().getValue();
if ((n < 0) || (n > os.size())) {
error(os, new RangeCheck());
} else {
os.copy(n);
}
} else {
if (os.checkType(PSArray.class, PSArray.class) ||
os.checkType(PSPackedArray.class, PSArray.class)) {
PSArray a2 = os.popArray();
PSPackedArray a1 = os.popPackedArray();
if (a2.size() < a1.size()) {
error(os, new RangeCheck());
} else {
for (int i=0; i<a1.size(); i++) {
a2.set(i, a1.get(i));
}
os.push(a2.subArray(0, a1.size()));
}
} else if (os.checkType(PSDictionary.class, PSDictionary.class)) {
PSDictionary d2 = os.popDictionary();
PSDictionary d1 = os.popDictionary();
d1.copyInto(d2);
os.push(d2);
} else if (os.checkType(PSString.class, PSString.class)) {
PSString s2 = os.popString();
PSString s1 = os.popString();
if (s2.size() < s1.size()) {
error(os, new RangeCheck());
} else {
for (int i=0; i<s1.size(); i++) {
s2.set(i, s1.get(i));
}
os.push(s2.subString(0, s1.size()));
}
} else if (os.checkType(PSGState.class, PSGState.class)) {
PSGState g2 = os.popGState();
PSGState g1 = os.popGState();
g1.copyInto(g2);
os.push(g2);
} else {
error(os, new TypeCheck());
}
}
return true;
}
}
class ForAll extends GeneralOperator implements LoopingContext {
private int index;
private PSPackedArray array;
private Object[] keys;
private PSDictionary dictionary;
private PSString string;
private PSPackedArray proc;
private ForAll(PSPackedArray a, PSPackedArray p) {
array = a;
proc = p;
index = 0;
}
private ForAll(PSDictionary d, PSPackedArray p) {
dictionary = d;
proc = p;
keys = dictionary.keys();
index = 0;
}
private ForAll(PSString s, PSPackedArray p) {
string = s;
proc = p;
index = 0;
}
public ForAll() {
}
public boolean execute(OperandStack os) {
if (proc == null) {
if (os.checkType(PSPackedArray.class, PSPackedArray.class)) {
PSPackedArray p = os.popPackedArray();
PSPackedArray a = os.popPackedArray();
os.execStack().pop();
os.execStack().push(new ForAll(a, p));
return false;
} else if (os.checkType(PSDictionary.class, PSPackedArray.class)) {
PSPackedArray p = os.popPackedArray();
PSDictionary d = os.popDictionary();
os.execStack().pop();
os.execStack().push(new ForAll(d, p));
return false;
} else if (os.checkType(PSString.class, PSPackedArray.class)) {
PSPackedArray p = os.popPackedArray();
PSString s = os.popString();
os.execStack().pop();
os.execStack().push(new ForAll(s, p));
return false;
} else {
error(os, new TypeCheck());
}
} else {
if (array != null) {
if (index < array.size()) {
os.push(array.get(index));
os.execStack().push(proc);
index++;
return false;
} else {
return true;
}
} else if (dictionary != null) {
if (index < keys.length) {
Object value = dictionary.get((PSObject)keys[index]);
if (value != null) {
os.push(keys[index]);
os.push(value);
os.execStack().push(proc);
}
index++;
return false;
} else {
return true;
}
} else if (string != null) {
if (index < string.size()) {
os.push((int)string.get(index));
os.execStack().push(proc);
index++;
return false;
} else {
return true;
}
} else {
System.err.println("Fatal Error in ForAll");
}
}
return false;
}
}
class Token extends GeneralOperator {
public boolean execute(OperandStack os) {
try {
if (os.checkType(PSString.class)) {
PSString string = os.popString();
PSObject obj = string.token(os.packingMode(), os.dictStack());
if (obj != null) {
os.push(string);
os.push(obj);
os.push(true);
} else {
os.push(false);
}
} else if (os.checkType(PSFile.class)) {
PSInputFile file = (PSInputFile)os.popFile();
PSObject obj = file.token(os.packingMode(), os.dictStack());
if (obj != null) {
os.push(obj);
os.push(true);
} else {
os.push(false);
}
} else {
error(os, new TypeCheck());
}
} catch (ClassCastException e) {
error(os, new InvalidAccess());
} catch (IOException e) {
error(os, new IOError());
} catch (SyntaxException e) {
error(os, new SyntaxError());
} catch (NameNotFoundException e) {
error(os, new Undefined());
}
return true;
}
}