001: // Copyright (C) 2000 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ../../COPYING.
003:
004: package kawa.standard;
005:
006: import gnu.expr.*;
007: import kawa.lang.*;
008: import gnu.lists.*;
009: import java.io.File;
010: import gnu.mapping.*;
011: import gnu.kawa.lispexpr.*;
012:
013: public class define_autoload extends Syntax {
014: public static final define_autoload define_autoload = new define_autoload(
015: "define-autoload", false);
016: public static final define_autoload define_autoloads_from_file = new define_autoload(
017: "define-autoloads-from-file", true);
018:
019: boolean fromFile;
020:
021: public define_autoload(String name, boolean fromFile) {
022: super (name);
023: this .fromFile = fromFile;
024: }
025:
026: public boolean scanForDefinitions(Pair st, java.util.Vector forms,
027: ScopeExp defs, Translator tr) {
028: if (!(st.cdr instanceof Pair))
029: return super .scanForDefinitions(st, forms, defs, tr);
030: Pair p = (Pair) st.cdr;
031: if (fromFile) {
032: for (;;) {
033: if (!(p.car instanceof FString))
034: break;
035: if (!scanFile(p.car.toString(), defs, tr))
036: return false;
037: Object rest = p.cdr;
038: if (rest == LList.Empty)
039: return true;
040: if (!(rest instanceof Pair))
041: break;
042: p = (Pair) p.cdr;
043: }
044: tr
045: .syntaxError("invalid syntax for define-autoloads-from-file");
046: return false;
047: }
048: Object names = p.car;
049: Object filename = null;
050: if (p.cdr instanceof Pair) {
051: p = (Pair) p.cdr;
052: filename = p.car;
053: return process(names, filename, forms, defs, tr);
054: }
055: tr.syntaxError("invalid syntax for define-autoload");
056: return false;
057: }
058:
059: public boolean scanFile(String filespec, ScopeExp defs,
060: Translator tr) {
061: if (filespec.endsWith(".el"))
062: ;
063: File file = new File(filespec);
064: if (!file.isAbsolute())
065: file = new File(new File(tr.getFileName()).getParent(),
066: filespec);
067: String filename = file.getPath();
068: int dot = filename.lastIndexOf('.');
069: Language language;
070: if (dot >= 0) {
071: String extension = filename.substring(dot);
072: language = Language.getInstance(extension);
073: if (language == null) {
074: tr.syntaxError("unknown extension for " + filename);
075: return true;
076: }
077: gnu.text.Lexer lexer;
078:
079: /*
080: // Since (module-name ...) is not handled in this pass,
081: // we won't see it until its too late. FIXME.
082: ModuleExp module = tr.getModule();
083: String prefix = module == null ? null : module.getName();
084: System.err.println("module:"+module);
085: if (prefix == null)
086: prefix = kawa.repl.compilationPrefix;
087: else
088: {
089: int i = prefix.lastIndexOf('.');
090: if (i < 0)
091: prefix = null;
092: else
093: prefix = prefix.substring(0, i+1);
094: }
095: */
096: String prefix = tr.classPrefix;
097: int extlen = extension.length();
098: int speclen = filespec.length();
099: String cname = filespec.substring(0, speclen - extlen);
100: while (cname.startsWith("../")) {
101: int i = prefix.lastIndexOf('.', prefix.length() - 2);
102: if (i < 0) {
103: tr.syntaxError("cannot use relative filename \""
104: + filespec + "\" with simple prefix \""
105: + prefix + "\"");
106: return false;
107: }
108: prefix = prefix.substring(0, i + 1);
109: cname = cname.substring(3);
110: }
111: String classname = (prefix + cname).replace('/', '.');
112:
113: try {
114: InPort port = InPort.openFile(filename);
115: lexer = language.getLexer(port, tr.getMessages());
116: findAutoloadComments((LispReader) lexer, classname,
117: defs, tr);
118: } catch (Exception ex) {
119: tr.syntaxError("error reading " + filename + ": " + ex);
120: return true;
121: }
122: }
123: return true;
124: }
125:
126: public static void findAutoloadComments(LispReader in,
127: String filename, ScopeExp defs, Translator tr)
128: throws java.io.IOException, gnu.text.SyntaxException {
129: boolean lineStart = true;
130: String magic = ";;;###autoload";
131: int magicLength = magic.length();
132: mainLoop: for (;;) {
133: int ch = in.peek();
134: if (ch < 0)
135: return;
136: if (ch == '\n' || ch == '\r') {
137: in.read();
138: lineStart = true;
139: continue;
140: }
141: if (lineStart && ch == ';') {
142: int i = 0;
143: for (;;) {
144: if (i == magicLength)
145: break;
146: ch = in.read();
147: if (ch < 0)
148: return;
149: if (ch == '\n' || ch == '\r') {
150: lineStart = true;
151: continue mainLoop;
152: }
153: if (i < 0 || ch == magic.charAt(i++))
154: continue;
155: i = -1; // No match.
156: }
157: if (i > 0) {
158: Object form = in.readObject();
159: if (form instanceof Pair) {
160: Pair pair = (Pair) form;
161: Object value = null;
162: String name = null;
163: Object car = pair.car;
164: String command = car instanceof String ? car
165: .toString()
166: : car instanceof Symbol ? ((Symbol) car)
167: .getName()
168: : null;
169: if (command == "defun") {
170: name = ((Pair) pair.cdr).car.toString();
171: value = new AutoloadProcedure(name,
172: filename, tr.getLanguage());
173: } else
174: tr.error('w',
175: "unsupported ;;;###autoload followed by: "
176: + pair.car);
177: if (value != null) {
178: Declaration decl = defs.getDefine(name,
179: 'w', tr);
180: Expression ex = new QuoteExp(value);
181: decl.setFlag(Declaration.IS_CONSTANT);
182: decl.noteValue(ex);
183: decl.setProcedureDecl(true);
184: decl.setType(Compilation.typeProcedure);
185: }
186: }
187: lineStart = false;
188: continue;
189: }
190: }
191: lineStart = false;
192: in.skip();
193: if (ch == '#') {
194: if (in.peek() == '|') {
195: in.skip();
196: in.readNestedComment('#', '|');
197: continue;
198: }
199: }
200: if (Character.isWhitespace((char) ch))
201: ;
202: else {
203: Object skipped = in.readObject(ch);
204: if (skipped == Sequence.eofValue)
205: return;
206: }
207: }
208: }
209:
210: public static boolean process(Object names, Object filename,
211: java.util.Vector forms, ScopeExp defs, Translator tr) {
212: if (names instanceof Pair) {
213: Pair p = (Pair) names;
214: return (process(p.car, filename, forms, defs, tr) && process(
215: p.cdr, filename, forms, defs, tr));
216: }
217: if (names == LList.Empty)
218: return true;
219: String fn;
220: int len;
221:
222: /*
223: if (names == "*" && filename instanceof String
224: && (len = (fn = (String) filename).length()) > 2
225: && fn.charAt(0) == '<' && fn.charAt(len-1) == '>')
226: {
227: fn = fn.substring(1, len-1);
228: try
229: {
230: Class fclass = Class.forName(fn);
231: Object instance = require.find(ctype, env);
232: ...;
233: }
234: catch (ClassNotFoundException ex)
235: {
236: tr.syntaxError("class <"+fn+"> not found");
237: return false;
238: }
239: }
240: */
241:
242: if (names instanceof String || names instanceof Symbol) {
243: String name = names.toString();
244: Declaration decl = defs.getDefine(name, 'w', tr);
245: if (filename instanceof String
246: && (len = (fn = (String) filename).length()) > 2
247: && fn.charAt(0) == '<' && fn.charAt(len - 1) == '>')
248: filename = fn.substring(1, len - 1);
249: Object value = new AutoloadProcedure(name, filename
250: .toString(), tr.getLanguage());
251: Expression ex = new QuoteExp(value);
252: decl.setFlag(Declaration.IS_CONSTANT);
253: decl.noteValue(ex);
254: return true;
255: }
256: return false;
257: }
258:
259: public Expression rewriteForm(Pair form, Translator tr) {
260: return null;
261: }
262: }
|