package kpc.common.kawa; import gnu.expr.Expression; import gnu.expr.ScopeExp; import gnu.kawa.io.BinaryInPort; import gnu.kawa.io.InPort; import gnu.kawa.io.Path; import gnu.kawa.lispexpr.LispReader; import gnu.lists.LList; import gnu.lists.Pair; import gnu.lists.Sequence; import gnu.text.Lexer; import kawa.lang.Syntax; import kawa.lang.Translator; import kpc.api.fs.FileSystem; import java.io.File; import java.io.InputStream; import java.nio.charset.Charset; public final class include extends Syntax { private final FileSystem fs; public include(FileSystem fs){ super("include"); this.fs = fs; } @Override public void scanForm(Pair st, ScopeExp defs, Translator tr){ this.process(st.getCdr(), tr, defs); } @Override public Expression rewrite(Object obj, Translator tr){ return tr.rewrite(this.process(obj, tr, null)); } private Object process(Object rest, Translator tr, ScopeExp defs){ LList result = LList.Empty; Pair pair; for(Pair lastPair = null; rest instanceof Pair; rest = pair.getCdr()){ pair = (Pair) rest; Object pairCar = pair.getCar(); Object savePos = tr.pushPositionOf(pair); if(!(pairCar instanceof CharSequence)){ tr.error('e', "find parameters must be strings"); } String fName = pairCar.toString(); Path path; BinaryInPort inp; while(true){ File f = this.fs.resolve("/include/" + fName).toFile(); Path reader = Path.valueOf(f); try{ path = reader.resolve(fName); InputStream lexer = path.openInputStream(); try{ inp = BinaryInPort.openHeuristicFile(lexer, path); break; } catch(Exception e){ tr.error('e', "error reading file \"" + path + "\": " + e.getMessage()); return result; } } catch(Exception e){ // Fallthrough } } tr.popPositionOf(savePos); LispReader reader = new LispReader(inp, tr.getMessages()); Lexer lexer = tr.lexer; tr.lexer = reader; try{ if(inp.getCharset() == null && lexer != null){ InPort sexp = lexer.getPort(); if(sexp instanceof BinaryInPort){ Charset npair = ((BinaryInPort) sexp).getCharset(); if(npair != null){ inp.setDefaultCharset(npair); } } } while(true){ Object sexp; try{ sexp = reader.readCommand(); if(sexp == Sequence.eofValue){ break; } } catch(Exception e){ tr.error('e', "error reading file \"" + path + "\": " + e.getMessage()); return result; } if(defs != null){ tr.scanForm(sexp, defs); } else{ Pair npair = new Pair(sexp, LList.Empty); if(lastPair == null){ result = npair; } else{ lastPair.setCdrBackdoor(npair); } lastPair = npair; } } } finally{ tr.lexer = lexer; } } if(rest != LList.Empty){ tr.error('e', "improper list"); } return result; } }