0001: /*
0002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: * Free SoftwareFoundation, Inc.
0023: * 59 Temple Place, Suite 330
0024: * Boston, MA 02111-1307 USA
0025: *
0026: * @author Scott Ferguson
0027: */
0028:
0029: package com.caucho.es.parser;
0030:
0031: import com.caucho.es.*;
0032: import com.caucho.java.LineMap;
0033: import com.caucho.util.CharBuffer;
0034: import com.caucho.util.IntMap;
0035: import com.caucho.vfs.Path;
0036: import com.caucho.vfs.WriteStream;
0037:
0038: import java.io.IOException;
0039: import java.util.ArrayList;
0040: import java.util.HashMap;
0041: import java.util.Iterator;
0042:
0043: class ParseClass {
0044: private String srcFilename;
0045: private LineMap lineMap;
0046:
0047: private Parser parser;
0048:
0049: // The full classname of the generated script.
0050: private String className;
0051: // The package name of the generated script.
0052: private String pkg;
0053: // The class name.
0054: private String name;
0055: private ESId proto;
0056:
0057: // the global parse class
0058: private ParseClass root;
0059:
0060: // class instance variables
0061: private HashMap variables = new HashMap();
0062:
0063: // child classes
0064: private ArrayList classes = new ArrayList();
0065:
0066: // class methods
0067: private ArrayList functions = new ArrayList();
0068:
0069: private IntMap funMap = new IntMap();
0070: private HashMap names = new HashMap();
0071: private HashMap literals = new HashMap();
0072: private HashMap mangledSet = new HashMap();
0073: private Function global;
0074: private int unique;
0075: private int callDepth;
0076: private ArrayList imports = new ArrayList();
0077: private ArrayList javaImports = new ArrayList();
0078: private WriteStream os;
0079:
0080: private int printDepth;
0081: private boolean isFirst;
0082:
0083: private int destLine;
0084: private Path sourcePath;
0085:
0086: /**
0087: * Creates a new parse class.
0088: *
0089: * @param srcFilename the name of the source (*.js)
0090: * @param name the classname.
0091: */
0092: ParseClass(String srcFilename, String name) {
0093: this .srcFilename = srcFilename;
0094: this .root = this ;
0095:
0096: className = name;
0097:
0098: int p = name.lastIndexOf('.');
0099:
0100: if (p >= 0) {
0101: pkg = name.substring(0, p);
0102: this .name = name.substring(p + 1);
0103: } else {
0104: this .name = name;
0105: }
0106:
0107: lineMap = new LineMap(name, srcFilename);
0108: lineMap.add(1, 1);
0109: destLine = 1;
0110: }
0111:
0112: /**
0113: * Sets the source path for searching import classes.
0114: */
0115: void setSourcePath(Path sourcePath) {
0116: this .sourcePath = sourcePath;
0117: }
0118:
0119: /**
0120: * Gets the script search path
0121: */
0122: Path getScriptPath() {
0123: return root.parser.getScriptPath();
0124: }
0125:
0126: void setParser(Parser parser) {
0127: root.parser = parser;
0128: }
0129:
0130: void setWriteStream(WriteStream os) {
0131: this .os = os;
0132: }
0133:
0134: /**
0135: * Creates a child subclasses of this class.
0136: *
0137: * @param id the new class name.
0138: */
0139: ParseClass newClass(ESId id) {
0140: ParseClass cl = new ParseClass(srcFilename, id.toString());
0141:
0142: classes.add(cl);
0143: cl.root = root;
0144:
0145: return cl;
0146: }
0147:
0148: Function newFunction(Function oldFun, ESId id, boolean isClass) {
0149: if (id == null)
0150: id = ESId.intern("$lambda" + unique++);
0151: String realId = "_f_" + id.toString();
0152:
0153: while (names.get(realId) != null) {
0154: realId = realId + unique++;
0155: }
0156: names.put(realId, realId);
0157:
0158: Function fun = new Function(this , oldFun, realId, id, isClass);
0159: setFunction(fun);
0160:
0161: return fun;
0162: }
0163:
0164: void setFunction(Function function) {
0165: int index;
0166: if ((index = funMap.get(function.name)) >= 0) {
0167: function.num = index;
0168: functions.set(index, function);
0169: } else {
0170: function.num = functions.size();
0171: funMap.put(function.name, functions.size());
0172: functions.add(function);
0173: }
0174: }
0175:
0176: void addImport(String importName) {
0177: if (!imports.contains(importName))
0178: imports.add(importName);
0179: }
0180:
0181: /**
0182: * Adds a Java class/package import to the list.
0183: */
0184: void addJavaImport(String importName) {
0185: if (!javaImports.contains(importName))
0186: javaImports.add(importName);
0187: }
0188:
0189: /**
0190: * Gets a class variable.
0191: */
0192: Variable getVariable(ESId id) {
0193: return (Variable) variables.get(id);
0194: }
0195:
0196: /**
0197: * Sets a new class variable.
0198: */
0199: void addVariable(ESId id, Variable var) {
0200: variables.put(id, var);
0201: var.setJavaGlobal(true);
0202: }
0203:
0204: void setGlobal(Function global) {
0205: this .global = global;
0206: }
0207:
0208: void setProto(ESId proto) {
0209: this .proto = proto;
0210: }
0211:
0212: void addFunction(Function function) {
0213: setFunction(function);
0214: }
0215:
0216: void writeCode(WriteStream os) throws IOException {
0217: this .os = os;
0218:
0219: println("/**");
0220: println(" * Generated by " + com.caucho.Version.FULL_VERSION);
0221: println(" */");
0222: println();
0223: println("package " + pkg + ";");
0224: println("import java.io.*;");
0225: println("import com.caucho.es.*;");
0226: println("import com.caucho.util.*;");
0227: for (int i = 0; i < javaImports.size(); i++)
0228: println("import " + javaImports.get(i) + ";");
0229:
0230: println("public class " + name
0231: + " extends com.caucho.es.Script {");
0232:
0233: pushDepth();
0234:
0235: writeExecute();
0236:
0237: writeClassContents();
0238:
0239: writeLastModified();
0240: printLineMap();
0241:
0242: popDepth();
0243:
0244: println("}");
0245: }
0246:
0247: /**
0248: * Writes the contents of the class. Actually generates two classes.
0249: * One is a straight Java class, the other is the wrapper.
0250: */
0251: void writeClassContents() throws IOException {
0252: if (os == null)
0253: os = root.os;
0254:
0255: String name = this == root ? "js_global" : this .name;
0256:
0257: println();
0258: println("public static class " + name + " {");
0259: pushDepth();
0260: println(name + "_es _js;");
0261:
0262: Iterator iter = variables.values().iterator();
0263: while (iter.hasNext()) {
0264: Variable var = (Variable) iter.next();
0265:
0266: writeVarDecl(var, true);
0267: }
0268:
0269: for (int i = 0; i < functions.size(); i++) {
0270: Function fun = (Function) functions.get(i);
0271:
0272: println();
0273: fun.writeCode(this );
0274: }
0275:
0276: popDepth();
0277: println("}");
0278:
0279: println();
0280: if (name.equals("js_global"))
0281: println("public static class js_global_es extends ESGlobal {");
0282: else
0283: println("public static class " + name
0284: + "_es extends ESClass {");
0285: pushDepth();
0286: println(name + " _js_object;");
0287: println();
0288:
0289: println();
0290: if (name.equals("js_global")) {
0291: println("js_global_es(Global resin)");
0292: println("{");
0293: println(" super(resin);");
0294: println(" resin.setGlobal(this);");
0295: } else {
0296: println(name + "_es()");
0297: println("{");
0298: }
0299: println(" _js_object = new " + name + "();");
0300: println(" _js_object._js = this;");
0301: println("}");
0302:
0303: writeMap();
0304:
0305: printGetProperty();
0306: printPropNames();
0307:
0308: writeInit();
0309: writeWrapperInit(name);
0310: writeStaticInit();
0311: writeExport();
0312:
0313: popDepth();
0314: println("}");
0315:
0316: for (int i = 0; i < classes.size(); i++) {
0317: ParseClass subClass = (ParseClass) classes.get(i);
0318:
0319: subClass.setWriteStream(os);
0320: subClass.writeClassContents();
0321: }
0322: }
0323:
0324: void writeExport() throws IOException {
0325: println();
0326: println("public void export(ESObject dst) throws Throwable");
0327: println("{");
0328:
0329: println(" ESBase tmp;");
0330:
0331: for (int i = 0; global.functions != null
0332: && i < global.functions.size(); i++) {
0333: Function fun = (Function) global.functions.get(i);
0334:
0335: println(" tmp = getProperty(\"" + fun.id + "\");");
0336: println(" dst.put(\"" + fun.id
0337: + "\", tmp, ESBase.DONT_ENUM);");
0338: }
0339:
0340: for (int i = 0; i < classes.size(); i++) {
0341: ParseClass cl = (ParseClass) classes.get(i);
0342:
0343: Function fun = cl.getFunction(ESId.intern(cl.name));
0344:
0345: println(" tmp = getProperty(\"" + cl.name + "\");");
0346: println(" dst.put(\"" + cl.name
0347: + "\", tmp, ESBase.DONT_ENUM);");
0348: }
0349:
0350: println("}");
0351: }
0352:
0353: void writeExecute() throws IOException {
0354: println("public ESGlobal initClass(Global resin) throws Throwable");
0355: println("{");
0356: pushDepth();
0357: println("resin.addScript(\"" + className + "\", this);");
0358:
0359: println("js_global_es test = new js_global_es(resin);");
0360: println("test._init(resin, test);");
0361: println("return test;");
0362: popDepth();
0363: println("}");
0364: }
0365:
0366: void writeWrapperInit(String name) throws IOException {
0367: }
0368:
0369: void writeVarDecl(Variable var, boolean init) throws IOException {
0370: if (var.getType() == Expr.TYPE_BOOLEAN) {
0371: print("boolean " + var.getId());
0372: if (init)
0373: println(" = false;");
0374: else
0375: println(";");
0376: } else if (var.getType() == Expr.TYPE_INTEGER) {
0377: print("int " + var.getId());
0378: if (init)
0379: println(" = 0;");
0380: else
0381: println(";");
0382: } else if (var.getType() == Expr.TYPE_NUMBER) {
0383: print("double " + var.getId());
0384: if (init)
0385: println(" = Double.NaN;");
0386: else
0387: println(";");
0388: } else if (var.getType() == Expr.TYPE_STRING) {
0389: print("ESString " + var.getId());
0390: if (init)
0391: println(" = ESString.create(\"\");");
0392: else
0393: println(";");
0394: } else if (var.getType() == Expr.TYPE_JAVA
0395: && var.getTypeExpr() != null) {
0396: TypeExpr type = (TypeExpr) var.getTypeExpr();
0397:
0398: println(type.getTypeName() + " " + var.getId() + ";");
0399: } else {
0400: if (init)
0401: println("ESBase " + var.getId()
0402: + " = ESBase.esUndefined;");
0403: else
0404: println("ESBase " + var.getId() + ";");
0405: }
0406: }
0407:
0408: void printId(ESId id) throws IOException {
0409: print("js_global_es.");
0410: print(getMangledLiteral(id));
0411: }
0412:
0413: String getMangledLiteral(ESBase value) {
0414: String literal = (String) literals.get(value);
0415:
0416: if (literal == null) {
0417: literal = mangleLiteral(value);
0418: literals.put(value, literal);
0419: }
0420:
0421: return literal;
0422: }
0423:
0424: // XXX: hacks
0425: void pushCall() {
0426: callDepth++;
0427: }
0428:
0429: void popCall(int n) {
0430: callDepth -= n;
0431: }
0432:
0433: int getCallDepth() {
0434: return callDepth;
0435: }
0436:
0437: void printLiteral(ESBase obj) throws IOException {
0438: if (obj == null)
0439: print("ESBase.esNull");
0440: else if (obj instanceof ESNull)
0441: print("ESBase.esNull");
0442: else if (obj instanceof ESUndefined)
0443: print("ESBase.esUndefined");
0444: else if (obj == ESBoolean.TRUE)
0445: print("ESBoolean.TRUE");
0446: else if (obj == ESBoolean.FALSE)
0447: print("ESBoolean.FALSE");
0448: else {
0449: String literal = (String) literals.get(obj);
0450:
0451: if (literal == null) {
0452: try {
0453: if (obj instanceof ESNumber
0454: && Double.isNaN(obj.toNum())) {
0455: print("ESNumber.NaN");
0456: return;
0457: }
0458: } catch (Throwable e) {
0459: }
0460: literal = mangleLiteral(obj);
0461: literals.put(obj, literal);
0462: }
0463:
0464: print("js_global_es.");
0465: print(literal);
0466: }
0467: }
0468:
0469: private String mangleLiteral(Object obj) {
0470: String s = obj.toString();
0471: CharBuffer cb = new CharBuffer("_l_");
0472: for (int i = 0; i < s.length() && i < 32; i++) {
0473: char ch = s.charAt(i);
0474: // Java can't really deal with non-ascii?
0475: if (Character.isJavaIdentifierPart(ch) && ch >= ' '
0476: && ch < 127)
0477: cb.append(ch);
0478: else if (cb.getLastChar() != '_')
0479: cb.append("_");
0480: }
0481:
0482: if (mangledSet.get(cb) != null)
0483: cb.append("_" + unique++);
0484: mangledSet.put(cb, cb);
0485:
0486: return cb.toString();
0487: }
0488:
0489: /**
0490: * Writes the method map.
0491: */
0492: void writeMap() throws IOException {
0493: println("public ESBase call(int n, Call call, int length)");
0494: println(" throws Throwable");
0495: println("{");
0496: println(" switch(n) {");
0497:
0498: for (int i = 0; i < functions.size(); i++) {
0499: Function fun = (Function) functions.get(i);
0500:
0501: println(" case " + i + ":");
0502: print(" return ");
0503:
0504: Expr expr = fun.getReturnType();
0505: boolean hasCoerce = false;
0506: if (expr == null) {
0507: } else if (expr.getType() == Expr.TYPE_INTEGER
0508: || expr.getType() == Expr.TYPE_NUMBER) {
0509: hasCoerce = true;
0510: print("ESNumber.create(");
0511: } else if (expr instanceof JavaTypeExpr) {
0512: print("call.global.wrap(");
0513: }
0514:
0515: print("_js_object.");
0516: print(fun.name + "(call, length");
0517: for (int j = 0; j < fun.getFormalSize(); j++) {
0518: Variable formal = fun.getFormal(j);
0519:
0520: if (formal.getTypeExpr() instanceof JavaTypeExpr) {
0521: TypeExpr type = (TypeExpr) formal.getTypeExpr();
0522:
0523: print(", (" + type.getTypeName()
0524: + ") call.getArgObject(" + j + ", length)");
0525: } else if (formal.getType() == Expr.TYPE_INTEGER)
0526: print(", call.getArgInt32(" + j + ", length)");
0527: }
0528: print(")");
0529: if (hasCoerce)
0530: print(")");
0531: println(";");
0532: }
0533:
0534: println(" default:");
0535: println(" throw new RuntimeException();");
0536: println(" }");
0537: println("}");
0538: }
0539:
0540: void printGetProperty() throws IOException {
0541: if (variables.size() == 0)
0542: return;
0543:
0544: println();
0545: println("public ESBase getProperty(ESString key) throws Throwable");
0546: println("{");
0547: pushDepth();
0548: println("switch (propNames.get(key)) {");
0549:
0550: Iterator iter = variables.values().iterator();
0551: int i = 0;
0552: while (iter.hasNext()) {
0553: Variable var = (Variable) iter.next();
0554:
0555: println("case " + i + ":");
0556: Class javaClass = var.getTypeExpr().getJavaClass();
0557: if (ESBase.class.isAssignableFrom(javaClass))
0558: println(" return _js_object." + var.getId() + ";");
0559: else
0560: println(" return wrap(_js_object." + var.getId()
0561: + ");");
0562:
0563: i++;
0564: }
0565:
0566: println("default:");
0567: println(" return super.getProperty(key);");
0568: println("}");
0569: popDepth();
0570: println("}");
0571: }
0572:
0573: void printSetProperty() throws IOException {
0574: if (variables.size() == 0)
0575: return;
0576:
0577: println();
0578: println("public void setProperty(ESString key, ESBase value) throws Throwable");
0579: println("{");
0580: pushDepth();
0581: println("switch (propNames.get(key)) {");
0582:
0583: Iterator iter = variables.values().iterator();
0584: int i = 0;
0585: while (iter.hasNext()) {
0586: Variable var = (Variable) iter.next();
0587:
0588: println("case " + i + ":");
0589: Class javaClass = var.getTypeExpr().getJavaClass();
0590: if (ESBase.class.isAssignableFrom(javaClass))
0591: println(" _js_object." + var.getId() + " = ("
0592: + javaClass.getName()
0593: + ") value.toJavaObject();");
0594: else
0595: println(" _js_object." + var.getId() + " = value;");
0596: println(" break;");
0597:
0598: i++;
0599: }
0600:
0601: println("default:");
0602: println(" return super.setProperty(key, value);");
0603: println("}");
0604: popDepth();
0605: println("}");
0606: }
0607:
0608: void printPropNames() throws IOException {
0609: if (variables.size() == 0)
0610: return;
0611:
0612: println();
0613: println("private static com.caucho.util.IntMap propNames;");
0614: println();
0615: println("static {");
0616: pushDepth();
0617: println("propNames = new com.caucho.util.IntMap();");
0618:
0619: Iterator iter = variables.values().iterator();
0620: int i = 0;
0621: while (iter.hasNext()) {
0622: Variable var = (Variable) iter.next();
0623:
0624: println("propNames.put(ESId.intern(\"" + var.getId()
0625: + "\"), " + i + ");");
0626:
0627: i++;
0628: }
0629:
0630: popDepth();
0631: println("}");
0632: }
0633:
0634: void writeInit() throws IOException {
0635: println();
0636: println("public void _init(Global resin, ESObject global) throws Throwable");
0637: println("{");
0638:
0639: pushDepth();
0640:
0641: for (int i = 0; i < imports.size(); i++) {
0642: String importName = (String) imports.get(i);
0643:
0644: print("resin.importScript(this, \"");
0645: printString(importName);
0646: println("\");");
0647: }
0648:
0649: println("ESClosure fun;");
0650:
0651: for (int i = 0; global.functions != null
0652: && i < global.functions.size(); i++) {
0653: Function fun = (Function) global.functions.get(i);
0654:
0655: print("fun = new ESClosure(");
0656: print(getMangledLiteral(fun.id));
0657: print(", this, null, " + fun.num + ", ");
0658: if (fun.getFormalSize() == 0)
0659: print("_a_null");
0660: else
0661: print("_a_" + fun.num);
0662: println(", global);");
0663: println("global.put(\"" + fun.id
0664: + "\", fun, ESBase.DONT_ENUM);");
0665: }
0666:
0667: println("ESObject protoProto;");
0668: println("ESObject proto;");
0669: for (int i = 0; i < classes.size(); i++) {
0670: ParseClass cl = (ParseClass) classes.get(i);
0671:
0672: Function fun = cl.getFunction(ESId.intern(cl.name));
0673:
0674: println("{");
0675: pushDepth();
0676: println(cl.name + "_es jsClass;");
0677:
0678: println("jsClass = new " + cl.name + "_es();");
0679: if (cl.proto != null) {
0680: print("proto = new ESObject(\"Object\", getProperty(");
0681: print(getMangledLiteral(cl.proto));
0682: println(").getProperty(");
0683: printLiteral(ESId.intern("prototype"));
0684: println("));");
0685: } else
0686: println("proto = resin.createObject();");
0687: println("jsClass._init(resin, proto);");
0688: print("fun = new ESClosure(");
0689: print(getMangledLiteral(ESId.intern(cl.name)));
0690: print(", jsClass, proto, " + fun.num + ", ");
0691: if (fun.getFormalSize() == 0)
0692: print("_a_null");
0693: else
0694: print("_a_" + (i + functions.size()));
0695: println(", null);");
0696: println("setProperty(\"" + cl.name + "\", fun);");
0697:
0698: popDepth();
0699: println("}");
0700: }
0701:
0702: popDepth();
0703: println("}");
0704: }
0705:
0706: void writeLastModified() throws IOException {
0707: println();
0708: println("public boolean isModified()");
0709: println("{");
0710: if (sourcePath == null || sourcePath.getLastModified() <= 0)
0711: println(" return false;");
0712: else if (getScriptPath().lookup(sourcePath.getUserPath())
0713: .exists()) {
0714: print(" return scriptPath.lookup(\"");
0715: printString(sourcePath.getUserPath());
0716: println("\").getLastModified() != "
0717: + sourcePath.getLastModified() + "L;");
0718: } else {
0719: print(" return com.caucho.vfs.Vfs.lookup(\"");
0720: printString(sourcePath.getFullPath());
0721: println("\").getLastModified() != "
0722: + sourcePath.getLastModified() + "L;");
0723: }
0724:
0725: println("}");
0726: }
0727:
0728: Function getFunction(ESId name) {
0729: for (int i = 0; i < functions.size(); i++) {
0730: Function fun = (Function) functions.get(i);
0731: if (fun.id == name)
0732: return fun;
0733: }
0734:
0735: return null;
0736: }
0737:
0738: boolean hasFunction(ArrayList functions, ESId var) {
0739: for (int i = 2; i < functions.size(); i++) {
0740: Function fun = (Function) functions.get(i);
0741: if (fun.id == var)
0742: return true;
0743: }
0744:
0745: return false;
0746: }
0747:
0748: void writeStaticInit() throws IOException {
0749: Iterator iter = literals.keySet().iterator();
0750:
0751: if (iter.hasNext())
0752: println();
0753:
0754: while (iter.hasNext()) {
0755: Object o = iter.next();
0756: String name = (String) literals.get(o);
0757:
0758: if (o instanceof ESId) {
0759: print("static ESId " + name);
0760: print(" = ESId.intern(\"");
0761: printString(String.valueOf(o));
0762: println("\");");
0763: } else if (o instanceof ESString) {
0764: print("static ESString " + name);
0765: print(" = ESString.create(\"");
0766: printString(String.valueOf(o));
0767: println("\");");
0768: } else if (o instanceof ESNumber) {
0769: print("static ESNumber " + name);
0770: double v = ((ESNumber) o).toNum();
0771: if (Double.isInfinite(v))
0772: println(" = ESNumber.create(Double.POSITIVE_INFINITY);");
0773: else if (Double.isInfinite(-v))
0774: println(" = ESNumber.create(Double.NEGATIVE_INFINITY);");
0775: else if (Double.isNaN(v))
0776: throw new RuntimeException();
0777: else
0778: println(" = ESNumber.create(" + o + "D);");
0779: } else
0780: throw new RuntimeException();
0781: }
0782:
0783: println("static ESId[] _a_null = new ESId[0];");
0784: for (int i = 0; i < functions.size(); i++) {
0785: Function fun = (Function) functions.get(i);
0786:
0787: printFormals(fun, i);
0788: }
0789:
0790: for (int i = 0; i < classes.size(); i++) {
0791: ParseClass cl = (ParseClass) classes.get(i);
0792:
0793: Function fun = cl.getFunction(ESId.intern(cl.name));
0794:
0795: printFormals(fun, i + functions.size());
0796: }
0797: }
0798:
0799: void setLine(String filename, int line) {
0800: lineMap.add(filename, line, destLine);
0801: }
0802:
0803: /**
0804: * Prints the mapping between java lines and the original *.js lines.
0805: */
0806: void printLineMap() throws IOException {
0807: String dst = name + ".java";
0808: String src = srcFilename;
0809: String srcTail = srcFilename;
0810:
0811: int p = srcTail.lastIndexOf('/');
0812: if (p >= 0)
0813: srcTail = srcTail.substring(p + 1);
0814: p = srcTail.lastIndexOf('\\');
0815: if (p >= 0)
0816: srcTail = srcTail.substring(p + 1);
0817:
0818: println();
0819: println("public com.caucho.java.LineMap getLineMap()");
0820: println("{");
0821: pushDepth();
0822: print("com.caucho.java.LineMap lineMap = new com.caucho.java.LineMap(\"");
0823: printString(dst);
0824: print("\", \"");
0825: printString(srcTail);
0826: println("\");");
0827: println("lineMap.add(1, 1);");
0828: Iterator iter = lineMap.iterator();
0829: while (iter.hasNext()) {
0830: LineMap.Line line = (LineMap.Line) iter.next();
0831:
0832: if (line.getSourceFilename() == src) {
0833: println("lineMap.add(" + line.getSourceLine() + ", "
0834: + line.getDestinationLine() + ");");
0835: } else {
0836: src = line.getSourceFilename();
0837: srcTail = src;
0838: p = srcTail.lastIndexOf('/');
0839: if (p >= 0)
0840: srcTail = srcTail.substring(p + 1);
0841: p = srcTail.lastIndexOf('\\');
0842: if (p >= 0)
0843: srcTail = srcTail.substring(p + 1);
0844:
0845: print("lineMap.add(\"");
0846: printString(srcTail);
0847: println("\", " + line.getSourceLine() + ", "
0848: + line.getDestinationLine() + ");");
0849: }
0850: }
0851:
0852: println("return lineMap;");
0853: popDepth();
0854: println("}");
0855: }
0856:
0857: private void printFormals(Function fun, int i) throws IOException {
0858: if (fun.getFormalSize() > 0) {
0859: print(" private static ESId[] _a_" + i + " = new ESId[] {");
0860: for (int j = 0; fun.formals != null
0861: && j < fun.formals.size(); j++) {
0862:
0863: if (j != 0)
0864: print(",");
0865: Variable var = (Variable) fun.formals.get(j);
0866: print(" ESId.intern(\"" + var.getId() + "\")");
0867: }
0868: println("};");
0869: }
0870: }
0871:
0872: /**
0873: * Escapes the string so the Java compiler can properly understand it.
0874: */
0875: void printString(String s) throws IOException {
0876: for (int i = 0; i < s.length(); i++) {
0877: if (i > 0 && i % (16 * 1024) == 0)
0878: os.print("\" + \"");
0879:
0880: char ch = s.charAt(i);
0881: switch (ch) {
0882: case '\\':
0883: os.print("\\\\");
0884: break;
0885: case '\n':
0886: os.print("\\n");
0887: break;
0888: case '\r':
0889: os.print("\\r");
0890: break;
0891: case '\t':
0892: os.print("\\t");
0893: break;
0894: case '"':
0895: os.print("\\\"");
0896: break;
0897: default:
0898: if (ch >= 32 && ch < 127)
0899: os.print(ch);
0900: else {
0901: os.print("\\u");
0902: printHex(ch >> 12);
0903: printHex(ch >> 8);
0904: printHex(ch >> 4);
0905: printHex(ch >> 0);
0906: }
0907: break;
0908: }
0909: }
0910: }
0911:
0912: void printHex(int i) throws IOException {
0913: i &= 0xf;
0914: if (i < 10) {
0915: os.print(i);
0916: } else {
0917: os.print((char) ('a' + i - 10));
0918: }
0919: }
0920:
0921: void pushDepth() {
0922: printDepth += 2;
0923: }
0924:
0925: void popDepth() {
0926: printDepth -= 2;
0927: }
0928:
0929: void print(boolean b) throws IOException {
0930: if (isFirst)
0931: printSpaces();
0932: root.os.print(b);
0933: }
0934:
0935: void print(int i) throws IOException {
0936: if (isFirst)
0937: printSpaces();
0938: root.os.print(i);
0939: }
0940:
0941: void print(char c) throws IOException {
0942: if (isFirst)
0943: printSpaces();
0944:
0945: root.os.print(c);
0946: if (c == '\n')
0947: destLine++;
0948: }
0949:
0950: void print(String s) throws IOException {
0951: if (isFirst)
0952: printSpaces();
0953:
0954: if (s == null)
0955: s = "null";
0956:
0957: for (int i = 0; i < s.length(); i++) {
0958: if (s.charAt(i) == '\n') {
0959: isFirst = true;
0960: destLine++;
0961: } else
0962: isFirst = false;
0963: }
0964:
0965: root.os.print(s);
0966: }
0967:
0968: void print(Object o) throws IOException {
0969: if (isFirst)
0970: printSpaces();
0971:
0972: print(String.valueOf(o));
0973: }
0974:
0975: void println() throws IOException {
0976: if (isFirst)
0977: printSpaces();
0978:
0979: root.os.println();
0980: destLine++;
0981: isFirst = true;
0982: }
0983:
0984: void println(String s) throws IOException {
0985: print(s);
0986: println();
0987: }
0988:
0989: void println(Object o) throws IOException {
0990: print(String.valueOf(o));
0991: println();
0992: }
0993:
0994: void printSpaces() throws IOException {
0995: for (int i = 0; i < printDepth; i++)
0996: root.os.print(' ');
0997: isFirst = false;
0998: }
0999:
1000: static class Location {
1001: String filename;
1002: int line;
1003:
1004: Location(String filename, int line) {
1005: this.filename = filename;
1006: this.line = line;
1007: }
1008: }
1009: }
|