KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > es > parser > ParseClass


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.es.parser;
30
31 import com.caucho.es.*;
32 import com.caucho.java.LineMap;
33 import com.caucho.util.CharBuffer;
34 import com.caucho.util.IntMap;
35 import com.caucho.vfs.Path;
36 import com.caucho.vfs.WriteStream;
37
38 import java.io.IOException JavaDoc;
39 import java.util.ArrayList JavaDoc;
40 import java.util.HashMap JavaDoc;
41 import java.util.Iterator JavaDoc;
42
43 class ParseClass {
44   private String JavaDoc srcFilename;
45   private LineMap lineMap;
46
47   private Parser parser;
48   
49   // The full classname of the generated script.
50
private String JavaDoc className;
51   // The package name of the generated script.
52
private String JavaDoc pkg;
53   // The class name.
54
private String JavaDoc name;
55   private ESId proto;
56
57   // the global parse class
58
private ParseClass root;
59
60   // class instance variables
61
private HashMap JavaDoc variables = new HashMap JavaDoc();
62   
63   // child classes
64
private ArrayList JavaDoc classes = new ArrayList JavaDoc();
65   
66   // class methods
67
private ArrayList JavaDoc functions = new ArrayList JavaDoc();
68   
69   private IntMap funMap = new IntMap();
70   private HashMap JavaDoc names = new HashMap JavaDoc();
71   private HashMap JavaDoc literals = new HashMap JavaDoc();
72   private HashMap JavaDoc mangledSet = new HashMap JavaDoc();
73   private Function global;
74   private int unique;
75   private int callDepth;
76   private ArrayList JavaDoc imports = new ArrayList JavaDoc();
77   private ArrayList JavaDoc javaImports = new ArrayList JavaDoc();
78   private WriteStream os;
79   
80   private int printDepth;
81   private boolean isFirst;
82
83   private int destLine;
84   private Path sourcePath;
85
86   /**
87    * Creates a new parse class.
88    *
89    * @param srcFilename the name of the source (*.js)
90    * @param name the classname.
91    */

92   ParseClass(String JavaDoc srcFilename, String JavaDoc name)
93   {
94     this.srcFilename = srcFilename;
95     this.root = this;
96
97     className = name;
98     
99     int p = name.lastIndexOf('.');
100
101     if (p >= 0) {
102       pkg = name.substring(0, p);
103       this.name = name.substring(p + 1);
104     }
105     else {
106       this.name = name;
107     }
108     
109     lineMap = new LineMap(name, srcFilename);
110     lineMap.add(1, 1);
111     destLine = 1;
112   }
113
114   /**
115    * Sets the source path for searching import classes.
116    */

117   void setSourcePath(Path sourcePath)
118   {
119     this.sourcePath = sourcePath;
120   }
121
122   /**
123    * Gets the script search path
124    */

125   Path getScriptPath()
126   {
127     return root.parser.getScriptPath();
128   }
129
130   void setParser(Parser parser)
131   {
132     root.parser = parser;
133   }
134
135   void setWriteStream(WriteStream os)
136   {
137     this.os = os;
138   }
139
140   /**
141    * Creates a child subclasses of this class.
142    *
143    * @param id the new class name.
144    */

145   ParseClass newClass(ESId id)
146   {
147     ParseClass cl = new ParseClass(srcFilename, id.toString());
148     
149     classes.add(cl);
150     cl.root = root;
151
152     return cl;
153   }
154
155   Function newFunction(Function oldFun, ESId id, boolean isClass)
156   {
157     if (id == null)
158       id = ESId.intern("$lambda" + unique++);
159     String JavaDoc realId = "_f_" + id.toString();
160     
161     while (names.get(realId) != null) {
162       realId = realId + unique++;
163     }
164     names.put(realId, realId);
165
166     Function fun = new Function(this, oldFun, realId, id, isClass);
167     setFunction(fun);
168
169     return fun;
170   }
171
172   void setFunction(Function function)
173   {
174     int index;
175     if ((index = funMap.get(function.name)) >= 0) {
176       function.num = index;
177       functions.set(index, function);
178     }
179     else {
180       function.num = functions.size();
181       funMap.put(function.name, functions.size());
182       functions.add(function);
183     }
184   }
185
186   void addImport(String JavaDoc importName)
187   {
188     if (! imports.contains(importName))
189       imports.add(importName);
190   }
191
192   /**
193    * Adds a Java class/package import to the list.
194    */

195   void addJavaImport(String JavaDoc importName)
196   {
197     if (! javaImports.contains(importName))
198       javaImports.add(importName);
199   }
200
201   /**
202    * Gets a class variable.
203    */

204   Variable getVariable(ESId id)
205   {
206     return (Variable) variables.get(id);
207   }
208
209   /**
210    * Sets a new class variable.
211    */

212   void addVariable(ESId id, Variable var)
213   {
214     variables.put(id, var);
215     var.setJavaGlobal(true);
216   }
217
218   void setGlobal(Function global)
219   {
220     this.global = global;
221   }
222
223   void setProto(ESId proto)
224   {
225     this.proto = proto;
226   }
227
228   void addFunction(Function function)
229   {
230     setFunction(function);
231   }
232
233   void writeCode(WriteStream os) throws IOException JavaDoc
234   {
235     this.os = os;
236
237     println("/**");
238     println(" * Generated by " + com.caucho.Version.FULL_VERSION);
239     println(" */");
240     println();
241     println("package " + pkg + ";");
242     println("import java.io.*;");
243     println("import com.caucho.es.*;");
244     println("import com.caucho.util.*;");
245     for (int i = 0; i < javaImports.size(); i++)
246       println("import " + javaImports.get(i) + ";");
247     
248     println("public class " + name + " extends com.caucho.es.Script {");
249
250     pushDepth();
251
252     writeExecute();
253     
254     writeClassContents();
255     
256     writeLastModified();
257     printLineMap();
258     
259     popDepth();
260     
261     println("}");
262   }
263
264   /**
265    * Writes the contents of the class. Actually generates two classes.
266    * One is a straight Java class, the other is the wrapper.
267    */

268   void writeClassContents() throws IOException JavaDoc
269   {
270     if (os == null)
271       os = root.os;
272
273     String JavaDoc name = this == root ? "js_global" : this.name;
274
275     println();
276     println("public static class " + name + " {");
277     pushDepth();
278     println(name + "_es _js;");
279
280     Iterator JavaDoc iter = variables.values().iterator();
281     while (iter.hasNext()) {
282       Variable var = (Variable) iter.next();
283
284       writeVarDecl(var, true);
285     }
286     
287     for (int i = 0; i < functions.size(); i++) {
288       Function fun = (Function) functions.get(i);
289
290       println();
291       fun.writeCode(this);
292     }
293     
294     popDepth();
295     println("}");
296
297     println();
298     if (name.equals("js_global"))
299       println("public static class js_global_es extends ESGlobal {");
300     else
301       println("public static class " + name + "_es extends ESClass {");
302     pushDepth();
303     println(name + " _js_object;");
304     println();
305     
306     println();
307     if (name.equals("js_global")) {
308       println("js_global_es(Global resin)");
309       println("{");
310       println(" super(resin);");
311       println(" resin.setGlobal(this);");
312     }
313     else {
314       println(name + "_es()");
315       println("{");
316     }
317     println(" _js_object = new " + name + "();");
318     println(" _js_object._js = this;");
319     println("}");
320
321     writeMap();
322     
323     printGetProperty();
324     printPropNames();
325
326     writeInit();
327     writeWrapperInit(name);
328     writeStaticInit();
329     writeExport();
330
331     popDepth();
332     println("}");
333     
334     for (int i = 0; i < classes.size(); i++) {
335       ParseClass subClass = (ParseClass) classes.get(i);
336
337       subClass.setWriteStream(os);
338       subClass.writeClassContents();
339     }
340   }
341   
342   void writeExport() throws IOException JavaDoc
343   {
344     println();
345     println("public void export(ESObject dst) throws Throwable");
346     println("{");
347
348     println(" ESBase tmp;");
349
350     for (int i = 0;
351          global.functions != null && i < global.functions.size();
352          i++) {
353       Function fun = (Function) global.functions.get(i);
354
355       println(" tmp = getProperty(\"" + fun.id + "\");");
356       println(" dst.put(\"" + fun.id + "\", tmp, ESBase.DONT_ENUM);");
357     }
358
359     for (int i = 0; i < classes.size(); i++) {
360       ParseClass cl = (ParseClass) classes.get(i);
361
362       Function fun = cl.getFunction(ESId.intern(cl.name));
363         
364       println(" tmp = getProperty(\"" + cl.name + "\");");
365       println(" dst.put(\"" + cl.name + "\", tmp, ESBase.DONT_ENUM);");
366     }
367     
368     println("}");
369   }
370
371   void writeExecute()
372     throws IOException JavaDoc
373   {
374     println("public ESGlobal initClass(Global resin) throws Throwable");
375     println("{");
376     pushDepth();
377     println("resin.addScript(\"" + className + "\", this);");
378
379     println("js_global_es test = new js_global_es(resin);");
380     println("test._init(resin, test);");
381     println("return test;");
382     popDepth();
383     println("}");
384   }
385
386   void writeWrapperInit(String JavaDoc name)
387     throws IOException JavaDoc
388   {
389   }
390
391   void writeVarDecl(Variable var, boolean init)
392     throws IOException JavaDoc
393   {
394     if (var.getType() == Expr.TYPE_BOOLEAN) {
395       print("boolean " + var.getId());
396       if (init)
397         println(" = false;");
398       else
399         println(";");
400     }
401     else if (var.getType() == Expr.TYPE_INTEGER) {
402       print("int " + var.getId());
403       if (init)
404         println(" = 0;");
405       else
406         println(";");
407     }
408     else if (var.getType() == Expr.TYPE_NUMBER) {
409       print("double " + var.getId());
410       if (init)
411         println(" = Double.NaN;");
412       else
413         println(";");
414     }
415     else if (var.getType() == Expr.TYPE_STRING) {
416       print("ESString " + var.getId());
417       if (init)
418         println(" = ESString.create(\"\");");
419       else
420         println(";");
421     }
422     else if (var.getType() == Expr.TYPE_JAVA &&
423              var.getTypeExpr() != null) {
424       TypeExpr type = (TypeExpr) var.getTypeExpr();
425         
426       println(type.getTypeName() + " " + var.getId() + ";");
427     }
428     else {
429       if (init)
430         println("ESBase " + var.getId() + " = ESBase.esUndefined;");
431       else
432         println("ESBase " + var.getId() + ";");
433     }
434   }
435
436   void printId(ESId id) throws IOException JavaDoc
437   {
438     print("js_global_es.");
439     print(getMangledLiteral(id));
440   }
441
442   String JavaDoc getMangledLiteral(ESBase value)
443   {
444     String JavaDoc literal = (String JavaDoc) literals.get(value);
445     
446     if (literal == null) {
447       literal = mangleLiteral(value);
448       literals.put(value, literal);
449     }
450
451     return literal;
452   }
453
454   // XXX: hacks
455
void pushCall()
456   {
457     callDepth++;
458   }
459
460   void popCall(int n)
461   {
462     callDepth -= n;
463   }
464
465   int getCallDepth()
466   {
467     return callDepth;
468   }
469
470   void printLiteral(ESBase obj) throws IOException JavaDoc
471   {
472     if (obj == null)
473       print("ESBase.esNull");
474     else if (obj instanceof ESNull)
475       print("ESBase.esNull");
476     else if (obj instanceof ESUndefined)
477       print("ESBase.esUndefined");
478     else if (obj == ESBoolean.TRUE)
479       print("ESBoolean.TRUE");
480     else if (obj == ESBoolean.FALSE)
481       print("ESBoolean.FALSE");
482     else {
483       String JavaDoc literal = (String JavaDoc) literals.get(obj);
484     
485       if (literal == null) {
486         try {
487           if (obj instanceof ESNumber && Double.isNaN(obj.toNum())) {
488             print("ESNumber.NaN");
489             return;
490           }
491         } catch (Throwable JavaDoc e) {
492         }
493         literal = mangleLiteral(obj);
494         literals.put(obj, literal);
495       }
496
497       print("js_global_es.");
498       print(literal);
499     }
500   }
501
502   private String JavaDoc mangleLiteral(Object JavaDoc obj)
503   {
504     String JavaDoc s = obj.toString();
505     CharBuffer cb = new CharBuffer("_l_");
506     for (int i = 0; i < s.length() && i < 32; i++) {
507       char ch = s.charAt(i);
508       // Java can't really deal with non-ascii?
509
if (Character.isJavaIdentifierPart(ch) && ch >= ' ' && ch < 127)
510         cb.append(ch);
511       else if (cb.getLastChar() != '_')
512         cb.append("_");
513     }
514
515     if (mangledSet.get(cb) != null)
516       cb.append("_" + unique++);
517     mangledSet.put(cb, cb);
518     
519     return cb.toString();
520   }
521
522   /**
523    * Writes the method map.
524    */

525   void writeMap() throws IOException JavaDoc
526   {
527     println("public ESBase call(int n, Call call, int length)");
528     println(" throws Throwable");
529     println("{");
530     println(" switch(n) {");
531
532     for (int i = 0; i < functions.size(); i++) {
533       Function fun = (Function) functions.get(i);
534
535       println(" case " + i + ":");
536       print(" return ");
537
538       Expr expr = fun.getReturnType();
539       boolean hasCoerce = false;
540       if (expr == null) {
541       }
542       else if (expr.getType() == Expr.TYPE_INTEGER ||
543                expr.getType() == Expr.TYPE_NUMBER) {
544         hasCoerce = true;
545         print("ESNumber.create(");
546       }
547       else if (expr instanceof JavaTypeExpr) {
548         print("call.global.wrap(");
549       }
550
551       print("_js_object.");
552       print(fun.name + "(call, length");
553       for (int j = 0; j < fun.getFormalSize(); j++) {
554         Variable formal = fun.getFormal(j);
555         
556         if (formal.getTypeExpr() instanceof JavaTypeExpr) {
557           TypeExpr type = (TypeExpr) formal.getTypeExpr();
558
559           print(", (" + type.getTypeName() + ") call.getArgObject(" + j + ", length)");
560         }
561         else if (formal.getType() == Expr.TYPE_INTEGER)
562           print(", call.getArgInt32(" + j + ", length)");
563       }
564       print(")");
565       if (hasCoerce)
566         print(")");
567       println(";");
568     }
569     
570     println(" default:");
571     println(" throw new RuntimeException();");
572     println(" }");
573     println("}");
574   }
575
576   void printGetProperty() throws IOException JavaDoc
577   {
578     if (variables.size() == 0)
579       return;
580
581     println();
582     println("public ESBase getProperty(ESString key) throws Throwable");
583     println("{");
584     pushDepth();
585     println("switch (propNames.get(key)) {");
586
587     Iterator JavaDoc iter = variables.values().iterator();
588     int i = 0;
589     while (iter.hasNext()) {
590       Variable var = (Variable) iter.next();
591
592       println("case " + i + ":");
593       Class JavaDoc javaClass = var.getTypeExpr().getJavaClass();
594       if (ESBase.class.isAssignableFrom(javaClass))
595         println(" return _js_object." + var.getId() + ";");
596       else
597         println(" return wrap(_js_object." + var.getId() + ");");
598       
599       i++;
600     }
601     
602     println("default:");
603     println(" return super.getProperty(key);");
604     println("}");
605     popDepth();
606     println("}");
607   }
608
609   void printSetProperty() throws IOException JavaDoc
610   {
611     if (variables.size() == 0)
612       return;
613
614     println();
615     println("public void setProperty(ESString key, ESBase value) throws Throwable");
616     println("{");
617     pushDepth();
618     println("switch (propNames.get(key)) {");
619
620     Iterator JavaDoc iter = variables.values().iterator();
621     int i = 0;
622     while (iter.hasNext()) {
623       Variable var = (Variable) iter.next();
624
625       println("case " + i + ":");
626       Class JavaDoc javaClass = var.getTypeExpr().getJavaClass();
627       if (ESBase.class.isAssignableFrom(javaClass))
628         println(" _js_object." + var.getId() + " = (" + javaClass.getName() + ") value.toJavaObject();");
629       else
630         println(" _js_object." + var.getId() + " = value;");
631       println(" break;");
632       
633       i++;
634     }
635     
636     println("default:");
637     println(" return super.setProperty(key, value);");
638     println("}");
639     popDepth();
640     println("}");
641   }
642
643   void printPropNames() throws IOException JavaDoc
644   {
645     if (variables.size() == 0)
646       return;
647
648     println();
649     println("private static com.caucho.util.IntMap propNames;");
650     println();
651     println("static {");
652     pushDepth();
653     println("propNames = new com.caucho.util.IntMap();");
654
655     Iterator JavaDoc iter = variables.values().iterator();
656     int i = 0;
657     while (iter.hasNext()) {
658       Variable var = (Variable) iter.next();
659
660       println("propNames.put(ESId.intern(\"" + var.getId() + "\"), " + i + ");");
661
662       i++;
663     }
664     
665     popDepth();
666     println("}");
667   }
668   
669   void writeInit() throws IOException JavaDoc
670   {
671     println();
672     println("public void _init(Global resin, ESObject global) throws Throwable");
673     println("{");
674
675     pushDepth();
676
677     for (int i = 0; i < imports.size(); i++) {
678       String JavaDoc importName = (String JavaDoc) imports.get(i);
679
680       print("resin.importScript(this, \"");
681       printString(importName);
682       println("\");");
683     }
684     
685     println("ESClosure fun;");
686
687     for (int i = 0; global.functions != null && i < global.functions.size(); i++) {
688       Function fun = (Function) global.functions.get(i);
689
690       print("fun = new ESClosure(");
691       print(getMangledLiteral(fun.id));
692       print(", this, null, " + fun.num + ", ");
693       if (fun.getFormalSize() == 0)
694         print("_a_null");
695       else
696         print("_a_" + fun.num);
697       println(", global);");
698       println("global.put(\"" + fun.id + "\", fun, ESBase.DONT_ENUM);");
699     }
700
701     println("ESObject protoProto;");
702     println("ESObject proto;");
703     for (int i = 0; i < classes.size(); i++) {
704       ParseClass cl = (ParseClass) classes.get(i);
705
706       Function fun = cl.getFunction(ESId.intern(cl.name));
707
708       println("{");
709       pushDepth();
710       println(cl.name + "_es jsClass;");
711         
712       println("jsClass = new " + cl.name + "_es();");
713       if (cl.proto != null) {
714         print("proto = new ESObject(\"Object\", getProperty(");
715         print(getMangledLiteral(cl.proto));
716         println(").getProperty(");
717         printLiteral(ESId.intern("prototype"));
718         println("));");
719       }
720       else
721         println("proto = resin.createObject();");
722       println("jsClass._init(resin, proto);");
723       print("fun = new ESClosure(");
724       print(getMangledLiteral(ESId.intern(cl.name)));
725       print(", jsClass, proto, " + fun.num + ", ");
726       if (fun.getFormalSize() == 0)
727         print("_a_null");
728       else
729         print("_a_" + (i + functions.size()));
730       println(", null);");
731       println("setProperty(\"" + cl.name + "\", fun);");
732
733       popDepth();
734       println("}");
735     }
736
737     popDepth();
738     println("}");
739   }
740
741   void writeLastModified() throws IOException JavaDoc
742   {
743     println();
744     println("public boolean isModified()");
745     println("{");
746     if (sourcePath == null || sourcePath.getLastModified() <= 0)
747       println(" return false;");
748     else if (getScriptPath().lookup(sourcePath.getUserPath()).exists()) {
749       print(" return scriptPath.lookup(\"");
750       printString(sourcePath.getUserPath());
751       println("\").getLastModified() != " + sourcePath.getLastModified() + "L;");
752     }
753     else {
754       print(" return com.caucho.vfs.Vfs.lookup(\"");
755       printString(sourcePath.getFullPath());
756       println("\").getLastModified() != " + sourcePath.getLastModified() + "L;");
757     }
758
759     println("}");
760   }
761
762   Function getFunction(ESId name)
763   {
764     for (int i = 0; i < functions.size(); i++) {
765       Function fun = (Function) functions.get(i);
766       if (fun.id == name)
767         return fun;
768     }
769
770     return null;
771   }
772
773   boolean hasFunction(ArrayList JavaDoc functions, ESId var)
774   {
775     for (int i = 2; i < functions.size(); i++) {
776       Function fun = (Function) functions.get(i);
777       if (fun.id == var)
778         return true;
779     }
780
781     return false;
782   }
783
784   void writeStaticInit() throws IOException JavaDoc
785   {
786     Iterator JavaDoc iter = literals.keySet().iterator();
787     
788     if (iter.hasNext())
789       println();
790     
791     while (iter.hasNext()) {
792       Object JavaDoc o = iter.next();
793       String JavaDoc name = (String JavaDoc) literals.get(o);
794
795       if (o instanceof ESId) {
796         print("static ESId " + name);
797         print(" = ESId.intern(\"");
798         printString(String.valueOf(o));
799         println("\");");
800       }
801       else if (o instanceof ESString) {
802         print("static ESString " + name);
803         print(" = ESString.create(\"");
804         printString(String.valueOf(o));
805         println("\");");
806       }
807       else if (o instanceof ESNumber) {
808         print("static ESNumber " + name);
809         double v = ((ESNumber) o).toNum();
810         if (Double.isInfinite(v))
811           println(" = ESNumber.create(Double.POSITIVE_INFINITY);");
812         else if (Double.isInfinite(-v))
813           println(" = ESNumber.create(Double.NEGATIVE_INFINITY);");
814         else if (Double.isNaN(v))
815           throw new RuntimeException JavaDoc();
816         else
817           println(" = ESNumber.create(" + o + "D);");
818       }
819       else
820         throw new RuntimeException JavaDoc();
821     }
822
823     println("static ESId[] _a_null = new ESId[0];");
824     for (int i = 0; i < functions.size(); i++) {
825       Function fun = (Function) functions.get(i);
826
827       printFormals(fun, i);
828     }
829
830     for (int i = 0; i < classes.size(); i++) {
831       ParseClass cl = (ParseClass) classes.get(i);
832
833       Function fun = cl.getFunction(ESId.intern(cl.name));
834
835       printFormals(fun, i + functions.size());
836     }
837   }
838
839   void setLine(String JavaDoc filename, int line)
840   {
841     lineMap.add(filename, line, destLine);
842   }
843
844   /**
845    * Prints the mapping between java lines and the original *.js lines.
846    */

847   void printLineMap() throws IOException JavaDoc
848   {
849     String JavaDoc dst = name + ".java";
850     String JavaDoc src = srcFilename;
851     String JavaDoc srcTail = srcFilename;
852
853     int p = srcTail.lastIndexOf('/');
854     if (p >= 0)
855       srcTail = srcTail.substring(p + 1);
856     p = srcTail.lastIndexOf('\\');
857     if (p >= 0)
858       srcTail = srcTail.substring(p + 1);
859     
860     println();
861     println("public com.caucho.java.LineMap getLineMap()");
862     println("{");
863     pushDepth();
864     print("com.caucho.java.LineMap lineMap = new com.caucho.java.LineMap(\"");
865     printString(dst);
866     print("\", \"");
867     printString(srcTail);
868     println("\");");
869     println("lineMap.add(1, 1);");
870     Iterator JavaDoc iter = lineMap.iterator();
871     while (iter.hasNext()) {
872       LineMap.Line line = (LineMap.Line) iter.next();
873
874       if (line.getSourceFilename() == src) {
875         println("lineMap.add(" + line.getSourceLine() + ", " +
876                 line.getDestinationLine() + ");");
877       }
878       else {
879         src = line.getSourceFilename();
880         srcTail = src;
881         p = srcTail.lastIndexOf('/');
882         if (p >= 0)
883           srcTail = srcTail.substring(p + 1);
884         p = srcTail.lastIndexOf('\\');
885         if (p >= 0)
886           srcTail = srcTail.substring(p + 1);
887         
888         print("lineMap.add(\"");
889         printString(srcTail);
890         println("\", " +
891                 line.getSourceLine() + ", " +
892                 line.getDestinationLine() + ");");
893       }
894     }
895     
896     println("return lineMap;");
897     popDepth();
898     println("}");
899   }
900   
901   private void printFormals(Function fun, int i)
902     throws IOException JavaDoc
903   {
904     if (fun.getFormalSize() > 0) {
905       print(" private static ESId[] _a_" + i + " = new ESId[] {");
906       for (int j = 0; fun.formals != null && j < fun.formals.size(); j++) {
907         
908         if (j != 0)
909           print(",");
910         Variable var = (Variable) fun.formals.get(j);
911         print(" ESId.intern(\"" + var.getId() + "\")");
912       }
913       println("};");
914     }
915   }
916
917   /**
918    * Escapes the string so the Java compiler can properly understand it.
919    */

920   void printString(String JavaDoc s) throws IOException JavaDoc
921   {
922     for (int i = 0; i < s.length(); i++) {
923       if (i > 0 && i % (16 * 1024) == 0)
924         os.print("\" + \"");
925       
926       char ch = s.charAt(i);
927       switch (ch) {
928       case '\\':
929         os.print("\\\\");
930         break;
931       case '\n':
932         os.print("\\n");
933         break;
934       case '\r':
935         os.print("\\r");
936         break;
937       case '\t':
938         os.print("\\t");
939         break;
940       case '"':
941         os.print("\\\"");
942         break;
943       default:
944         if (ch >= 32 && ch < 127)
945           os.print(ch);
946         else {
947           os.print("\\u");
948           printHex(ch >> 12);
949           printHex(ch >> 8);
950           printHex(ch >> 4);
951           printHex(ch >> 0);
952         }
953         break;
954       }
955     }
956   }
957
958   void printHex(int i) throws IOException JavaDoc
959   {
960     i &= 0xf;
961     if (i < 10) {
962       os.print(i);
963     }
964     else {
965       os.print((char) ('a' + i - 10));
966     }
967   }
968
969   void pushDepth()
970   {
971     printDepth += 2;
972   }
973
974   void popDepth()
975   {
976     printDepth -= 2;
977   }
978
979   void print(boolean b) throws IOException JavaDoc
980   {
981     if (isFirst)
982       printSpaces();
983     root.os.print(b);
984   }
985   
986   void print(int i) throws IOException JavaDoc
987   {
988     if (isFirst)
989       printSpaces();
990     root.os.print(i);
991   }
992
993   void print(char c) throws IOException JavaDoc
994   {
995     if (isFirst)
996       printSpaces();
997     
998     root.os.print(c);
999     if (c == '\n')
1000      destLine++;
1001  }
1002
1003  void print(String JavaDoc s) throws IOException JavaDoc
1004  {
1005    if (isFirst)
1006      printSpaces();
1007    
1008    if (s == null)
1009      s = "null";
1010    
1011    for (int i = 0; i < s.length(); i++) {
1012      if (s.charAt(i) == '\n') {
1013        isFirst = true;
1014        destLine++;
1015      }
1016      else
1017        isFirst = false;
1018    }
1019    
1020    root.os.print(s);
1021  }
1022
1023  void print(Object JavaDoc o) throws IOException JavaDoc
1024  {
1025    if (isFirst)
1026      printSpaces();
1027    
1028    print(String.valueOf(o));
1029  }
1030
1031  void println() throws IOException JavaDoc
1032  {
1033    if (isFirst)
1034      printSpaces();
1035    
1036    root.os.println();
1037    destLine++;
1038    isFirst = true;
1039  }
1040
1041  void println(String JavaDoc s) throws IOException JavaDoc
1042  {
1043    print(s);
1044    println();
1045  }
1046
1047  void println(Object JavaDoc o) throws IOException JavaDoc
1048  {
1049    print(String.valueOf(o));
1050    println();
1051  }
1052
1053  void printSpaces() throws IOException JavaDoc
1054  {
1055    for (int i = 0; i < printDepth; i++)
1056      root.os.print(' ');
1057    isFirst = false;
1058  }
1059
1060  static class Location {
1061    String JavaDoc filename;
1062    int line;
1063    
1064    Location(String JavaDoc filename, int line)
1065    {
1066      this.filename = filename;
1067      this.line = line;
1068    }
1069  }
1070}
1071
Popular Tags