temp files, was: how to re-define the HOME directory?
Subject: temp files, was: how to re-define the HOME directory?
From: Leo Butler
Date: Fri, 5 Jun 2009 10:44:59 +0100 (BST)
On Thu, 4 Jun 2009, Robert Dodier wrote:
< On Thu, Jun 4, 2009 at 10:21 AM, Leo Butler <l.butler at ed.ac.uk> wrote:
<
< > I came up with the following lisp code to imitate mktemp. I modified plot-temp-file from
< > src/plot.lisp so that it now returns a name not already belonging to
< > an existing file.
<
< Leo, that's terrific. The one quibble I have is that the comment
< says "Implements mkstemp.c in C-L" but the Lisp version just
< returns the file name without creating the file (as mkstemp does).
< There is a disclaimer following that statement which says the
< file is not created, but it seems likely that "Implements mkstemp"
< would be seen without the disclaimer. So I'll recommend that you
< make the comment more accurate.
<
< Also can you please put a copyright claim (for yourself) and a
< license statement on it? S.t. like "Copyright Leo Butler 2009.
< I release this work under terms of the GNU General Public License."
< would be enough (for me, anyway). Of course as the author you
< can pick whatever license terms you want; GPL makes it simpler
< to include in Maxima, should we decide to import it.
Robert, I have made the revisions you requested, fixed a bracket issue
that was invisible in gcl and added an 'in-package' line at the top.
I do intend to extend this a bit, to make an interface so that maxima
users can create multiple files with a filename template like
"tmp-XXXXX" along the lines of mktemp. However, this already fixes a
user's problem, so I will defer that extension for now.
Here is output from a maxima session:
(%i1) to_lisp();
Type (to-maxima) to restart, ($quit) to quit Maxima.
MAXIMA> (load "/knoppix-home/work/lisp/mktemp.lisp")
WARNING: DEFUN/DEFMACRO: redefining function PLOT-TEMP-FILE in
/knoppix-home/work/lisp/mktemp.lisp, was defined in
/knoppix-home/work/maxima/maxima-5.18.1/src/binary-clisp/plot.fas
T
MAXIMA> (to-maxima)
Returning to Maxima
(%o1) true
(%i2) plot2d(sin(x),[x,-%pi,%pi])$
(%i3) plot2d(sin(x),[x,-%pi,%pi])$
(%i4) to_lisp();
Type (to-maxima) to restart, ($quit) to quit Maxima.
MAXIMA> (compile-file "/knoppix-home/work/lisp/mktemp.lisp")
;; Compiling file /knoppix-home/work/lisp/mktemp.lisp ...
;; Wrote file /knoppix-home/work/lisp/mktemp.fas
0 errors, 0 warnings
#P"/knoppix-home/work/lisp/mktemp.fas"
NIL
NIL
MAXIMA> (to-maxima)
Returning to Maxima
(%o4) true
(%i5) plot2d(sin(x),[x,-%pi,%pi])$
-------------------------
$ ls /tmp/maxout*
/tmp/maxout.gnuplot_pipesKcmTZu /tmp/maxout.gnuplot_pipesnJmJqK
/tmp/maxout.gnuplot_pipesx3b15x
As you can see, it works nicely (ok, you can't see the graphs...).
-----------------
Oliver, this fixes your problem. You can load this into each one of your
maxima sessions and be guaranteed that your gnuplot calls won't clobber
one another.
Leo
--
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
-------------- next part --------------
;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
;;
;; $Id: mktemp.lisp,v 1.2 2009/06/05 07:57:43 work Exp $
;;
;; Copyright: Leo Butler (l.butler at ed.ac.uk)
;;
;; This file is part of the Maxima CAS code (http://maxima.sourceforge.net/)
;;
;; It is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3 of the License, or (at your
;; option) any later version.
;;
;; This software is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
;; License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this file. If not, see http://www.gnu.org/licenses/.
;;
(in-package :maxima)
(defvar *admissible-characters* (vector #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
(defvar *num-admissible-characters* (length *admissible-characters*))
(defvar *default-suffix-length* 6)
(defvar *default-tempfile-root* "maxima-temp-")
(defvar *default-special-char* #\X)
(defun randomise-template (template &key (special-char *default-special-char*) (seed *random-state*))
(declare (type 'string template) (type 'string-char special-char))
(map 'string #'(lambda (u)
(if (char= u special-char)
(make-random-char :seed seed) u)) template))
(defun make-random-char (&key (seed *random-state*))
(let* ((c (random *num-admissible-characters* seed)) (rand-char (aref *admissible-characters* c)))
rand-char))
(defun make-template (&key (root *default-tempfile-root*) (suffix-length *default-suffix-length*) (special-char *default-special-char*))
(declare (type 'string root) (type 'fixnum suffix-length))
(let ((suf ""))
(if (> suffix-length 0)
(progn
(setf suf (make-string suffix-length :initial-element special-char))
(concatenate 'string root suf))
(make-template :root root :special-char special-char))))
(defun make-tempfilename (&key (template *default-tempfile-root*) (special-char *default-special-char*) (seed *random-state*))
"Function: make-tempfilename (&key (template *default-tempfile-root*) (special-char *default-special-char*) (seed *random-state*))
>(make-tempfilename) --> \"maxima-temp-FcUwTn\"
>(make-tempfilename :template \"maxout-XXXXXX.gnuplot\") --> \"maxout-dlEDpX.gnuplot\"
>(make-tempfilename :template \"tmp-YYYYYY\" :seed #$2134 :special-char #\Y) --> \"tmp-UGBt7S\" (GCL)
The seed is overwritten, so to re-use, you must save seed externally or pass a constant.
Implements the string manipulations of mkstemp.c in C-L (http://www.opensource.apple.com/source/shell_cmds/shell_cmds-118/mktemp/mktemp.c).
Due to portability issues (see http://www.faqs.org/faqs/lisp-faq/part2/section-19.html) we do not attempt to open/create files or directories."
(declare (type 'string template))
(when (string= template *default-tempfile-root*)
(setf template (make-template :root template)))
(if (stringp template)
(setf template (randomise-template template :special-char special-char :seed seed))
(make-tempfilename :special-char special-char :seed seed))
template)
;; Altered from src/plot.lisp
;; This adds 6 random chars at the end of
;; a file name, and returns this filename
;; if a file of that name does not exist.
(defun plot-temp-file (file &key (depth 0))
(let (tmp-file (max-depth most-positive-fixnum)) ;; 62^5 < most-positive-fixnum < 62^6
(if *maxima-tempdir*
(setf tmp-file (format nil "~a/~a" *maxima-tempdir* file))
(setf tmp-file file))
(setf tmp-file (make-tempfilename :template (make-template :root tmp-file)))
(when (and (probe-file tmp-file) (< depth max-depth))
(plot-temp-file file :depth (+ depth 1)))
tmp-file))