source: branches/1.4.0/src/org/armedbear/lisp/Extensions.java

Last change on this file was 14877, checked in by Mark Evenson, 9 years ago

Keywordize EXT:MAKE-TEMP-FILE for temp file name patterns

EXT:MAKE-TEMP-FILE &key (PREFIX "abcl") (SUFFIX ".tmp")

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.5 KB
Line 
1/*
2 * Extensions.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: Extensions.java 14877 2016-09-29 21:38:59Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38import java.io.File;
39import java.io.IOException;
40import java.util.*;
41
42public final class Extensions
43{
44  // ### *ed-functions*
45  public static final Symbol _ED_FUNCTIONS_ =
46    exportSpecial("*ED-FUNCTIONS*", PACKAGE_EXT,
47                  list(intern("DEFAULT-ED-FUNCTION", PACKAGE_SYS)));
48
49  // ### truly-the value-type form => result*
50  private static final SpecialOperator TRULY_THE = new truly_the();
51  private static class truly_the extends SpecialOperator {
52    truly_the() {
53      super("truly-the", PACKAGE_EXT, true, "type value");
54    }
55    @Override
56    public LispObject execute(LispObject args, Environment env)
57    {
58      if (args.length() != 2)
59        return error(new WrongNumberOfArgumentsException(this, 2));
60      return eval(args.cadr(), env, LispThread.currentThread());
61    }
62  }
63
64  // ### neq
65  private static final Primitive NEQ = new neq();
66  private static class neq extends Primitive
67  {
68    neq() 
69    {
70      super(Symbol.NEQ, "obj1 obj2");
71    }
72    @Override
73    public LispObject execute(LispObject first, LispObject second)
74    {
75        return first != second ? T : NIL;
76    }
77  }
78
79  // ### memq item list => tail
80  private static final Primitive MEMQ = new memq();
81  private static class memq extends Primitive
82  {
83    memq() 
84    {
85      super(Symbol.MEMQ, "item list");
86    }
87    @Override
88    public LispObject execute(LispObject item, LispObject list)
89    {
90      while (list instanceof Cons)
91        {
92          if (item == ((Cons)list).car)
93            return list;
94          list = ((Cons)list).cdr;
95        }
96      if (list != NIL)
97        type_error(list, Symbol.LIST);
98      return NIL;
99    }
100  }
101
102  // ### memql item list => tail
103  private static final Primitive MEMQL = new memql();
104  private static class memql extends Primitive
105  {
106    memql() {
107      super(Symbol.MEMQL, "item list");
108    }
109    @Override
110    public LispObject execute(LispObject item, LispObject list)
111    {
112      while (list instanceof Cons)
113        {
114          if (item.eql(((Cons)list).car))
115            return list;
116          list = ((Cons)list).cdr;
117        }
118      if (list != NIL)
119        type_error(list, Symbol.LIST);
120      return NIL;
121    }
122  }
123
124  // ### adjoin-eql item list => new-list
125  private static final Primitive ADJOIN_EQL = new adjoin_eql();
126  private static class adjoin_eql extends Primitive {
127    adjoin_eql() {
128      super(Symbol.ADJOIN_EQL, "item list");
129    }
130    @Override
131    public LispObject execute(LispObject item, LispObject list)
132    {
133      return memql(item, list) ? list : new Cons(item, list);
134    }
135  }
136
137  // ### special-variable-p
138  private static final Primitive SPECIAL_VARIABLE_P = new special_variable_p();
139  private static class special_variable_p extends Primitive {
140    special_variable_p() {
141      super("special-variable-p", PACKAGE_EXT, true);
142    }
143    @Override
144    public LispObject execute(LispObject arg)
145    {
146      return arg.isSpecialVariable() ? T : NIL;
147    }
148  }
149
150  // ### source symbol
151  private static final Primitive SOURCE = new source();
152  private static class source extends Primitive {
153    source() {
154      super("source", PACKAGE_EXT, true);
155    }
156    @Override
157    public LispObject execute(LispObject arg)
158    {
159      return get(arg, Symbol._SOURCE, NIL);
160    }
161  }
162
163  // ### source-file-position symbol
164  private static final Primitive SOURCE_FILE_POSITION = new source_file_position();
165  private static class source_file_position extends Primitive {
166    source_file_position() {
167      super("source-file-position", PACKAGE_EXT, true);
168    }
169    @Override
170    public LispObject execute(LispObject arg)
171    {
172      LispObject obj = get(arg, Symbol._SOURCE, NIL);
173      if (obj instanceof Cons)
174        return obj.cdr();
175      return NIL;
176    }
177  }
178
179  // XXX rename to something else as it doesn't always refer to a pathname.
180  public static final Primitive SOURCE_PATHNAME = new pf_source_pathname();
181  @DocString(
182    name="source-pathname",
183    args="symbol",
184    doc="Returns either the pathname corresponding to the file from which this symbol was compiled,"
185    + "or the keyword :TOP-LEVEL."
186  )
187  private static class pf_source_pathname extends Primitive {
188    pf_source_pathname() {
189      super("source-pathname", PACKAGE_EXT, true);
190    }
191    @Override
192    public LispObject execute(LispObject arg)
193    {
194      LispObject obj = get(arg, Symbol._SOURCE, NIL);
195      if (obj instanceof Cons)
196        return obj.car();
197      return obj;
198    }
199  }
200
201  // ### exit
202  private static final Primitive EXIT = new exit();
203  private static class exit extends Primitive {
204    exit() {
205      super("exit", PACKAGE_EXT, true, "&key status");
206    }
207    @Override
208    public LispObject execute()
209    {
210      throw new ProcessingTerminated();
211    }
212    @Override
213    public LispObject execute(LispObject first, LispObject second)
214     
215    {
216      int status = 0;
217      if (first == Keyword.STATUS)
218        {
219          if (second instanceof Fixnum)
220            status = ((Fixnum)second).value;
221        }
222      throw new ProcessingTerminated(status);
223    }
224  }
225
226  // ### quit
227  private static final Primitive QUIT = new quit();
228  private static class quit extends Primitive {
229    quit() {
230      super("quit", PACKAGE_EXT, true, "&key status");
231    }
232    @Override
233    public LispObject execute()
234    {
235      ((Stream)Symbol.STANDARD_OUTPUT.getSymbolValue())._finishOutput();
236      ((Stream)Symbol.ERROR_OUTPUT.getSymbolValue())._finishOutput();
237      throw new ProcessingTerminated();
238    }
239    @Override
240    public LispObject execute(LispObject first, LispObject second)
241    {
242      int status = 0;
243      if (first == Keyword.STATUS)
244        {
245          if (second instanceof Fixnum)
246            status = ((Fixnum)second).value;
247        }
248      throw new ProcessingTerminated(status);
249    }
250  }
251
252  // ### dump-java-stack
253  private static final Primitive DUMP_JAVA_STACK = new dump_java_stack();
254  private static class dump_java_stack extends Primitive {
255    dump_java_stack() {
256      super("dump-java-stack", PACKAGE_EXT, true);
257    }
258    @Override
259    public LispObject execute()
260    {
261      Thread.dumpStack();
262      return LispThread.currentThread().nothing();
263    }
264  }
265
266  public static final Primitive MAKE_TEMP_FILE = new make_temp_file();
267  @DocString(name="make-temp-file",
268             doc="Create and return the pathname of a previously non-existent file.",
269             args="&key prefix suffix")
270  private static class make_temp_file extends Primitive { 
271    make_temp_file() {
272      super("make-temp-file", PACKAGE_EXT, true, "&key prefix suffix");
273    }
274    @Override
275    public LispObject execute(LispObject ... args)
276    {
277      String prefix = "abcl";
278      String suffix = null; 
279      if ( args.length % 2 != 0) {
280        error(new WrongNumberOfArgumentsException("Expecting an even number of arguments including keywords."));
281      }
282
283      for (int i = 0; i < args.length; i++ ) {
284        if (args[i].SYMBOLP() != NIL) {
285          if (args[i].equals(Keyword.PREFIX)) {
286            String specifiedPrefix = args[i + 1].getStringValue();
287            if (specifiedPrefix != null) {
288              if (specifiedPrefix.equals(NIL.getStringValue())) {
289                error (new TypeError("Cannot create temporary file with NIL prefix."));
290              }
291              prefix = specifiedPrefix;
292              i += 1;
293            }
294          } else if (args[i].equals(Keyword.SUFFIX)) {
295            String specifiedSuffix = args[i + 1].getStringValue();
296            if (specifiedSuffix != null) {
297              if (specifiedSuffix.equals(NIL.getStringValue())) {
298                suffix =null;
299              } else {
300                suffix = specifiedSuffix;
301              }
302              i += 1;
303            }
304          }
305        } else {
306          error(new TypeError("Expected matching keyword argument.", args[i], Keyword.PREFIX.classOf()));
307        }
308      }
309      return createTempFile(prefix, suffix);
310    }
311
312    @Override
313    public LispObject execute() {
314      return createTempFile("abcl", null);
315    }
316
317    private LispObject createTempFile(String prefix, String suffix) {
318      try {
319        File file = File.createTempFile(prefix, suffix, null);
320        if (file != null)
321          return new Pathname(file.getPath());
322      } catch (IllegalArgumentException e) {
323        // "Failed to create temporary file due to argument problems."
324        error(new JavaException(e));
325      } catch (SecurityException e) {
326        //"Failed to create problem due to problems with JVM SecurityManager."
327        error(new JavaException(e));
328      } catch (IOException e) {
329        // "Failed to create temporary file."
330        error(new JavaException(e));
331      }
332      return NIL;
333    }
334  }
335
336  public static final Primitive MAKE_TEMP_DIRECTORY = new make_temp_directory();
337  @DocString(name="make-temp-directory",
338             doc="Create and return the pathname of a previously non-existent directory.")
339  private static class make_temp_directory extends Primitive { 
340    make_temp_directory() {
341      super("make-temp-directory", PACKAGE_EXT, true, "");
342    }
343    @Override
344    public LispObject execute()
345    {
346      try {
347        File dir = File.createTempFile("abcl", null);
348        dir.delete();
349        if (dir.mkdirs()) {
350          return new Pathname(dir + "/");
351        }
352      } catch (Throwable t) {
353        Debug.trace(t);
354      }
355      return NIL;
356    }
357  }
358
359  // ### interrupt-lisp
360  private static final Primitive INTERRUPT_LISP = new interrupt_lisp();
361  private static class interrupt_lisp extends Primitive {
362    interrupt_lisp() {
363      super("interrupt-lisp", PACKAGE_EXT, true, "");
364    }
365    @Override
366    public LispObject execute()
367    {
368      setInterrupted(true);
369      return T;
370    }
371  }
372
373  // ### getenv variable => string
374  private static final Primitive GETENV = new getenv();
375  private static class getenv extends Primitive
376  {
377    getenv() 
378    {
379      super("getenv", PACKAGE_EXT, true, "variable",
380             "Return the value of the environment VARIABLE if it exists, otherwise return NIL.");
381    }
382    @Override
383    public LispObject execute(LispObject arg)
384    {
385      AbstractString string;
386      if (arg instanceof AbstractString) {
387        string = (AbstractString) arg;
388      } else
389        return type_error(arg, Symbol.STRING);
390      String result = System.getenv(string.getStringValue());
391      if (result != null)
392        return new SimpleString(result);
393      else
394        return NIL;
395    }
396  }
397
398  // ### getenv-all variable => string
399  private static final Primitive GETENV_ALL = new getenv_all();
400  private static class getenv_all extends Primitive
401  {
402    getenv_all() 
403    {
404      super("getenv-all", PACKAGE_EXT, true, "variable",
405             "Returns all environment variables as an alist containing (name . value)");
406    }
407    @Override
408    public LispObject execute()
409    {
410      Cons result = new Cons(NIL);
411      Map<String, String> env = System.getenv();
412      for (Map.Entry<String, String> entry : env.entrySet()) {
413          Cons entryPair = new Cons(new SimpleString(entry.getKey()), 
414                                    new SimpleString(entry.getValue()));
415          result = new Cons(entryPair, result);
416      }
417      return result;
418    }
419  }
420}
Note: See TracBrowser for help on using the repository browser.