2.6 Architecture-specific: Windows

Q 2.6-1) How do I get the functionality of the ~/time/ and ~/date/ format directives available in 3.0.2 in 6.2?
Q 2.6-2) Why can't I use `dir' with run-shell-command?
Q 2.6-3) How do I get the functionality of the 3.0.2 function allegro:read-lisp-line?
Q 2.6-4) How do I control the stack size on Windows?
Q 2.6-5) How do I get ANSI ACL (rather than Modern ACL) to start when I double-click on an lpr file?

Go to main FAQ page.


Q 2.6-1) How do I get the functionality of the ~/time/ and ~/date/ format directives available in 3.0.2 in 6.2?

A 2.6-1) What follows below is a quick port, with all its features, of these features for ACL 6.1. To prevent symbol clashes, the code is called as ~/aclwin:format-date/ and ~/aclwin:format-time/.

Examples: (Note that where it reports timezone, it erroneously uses "PST" instead of "PDT" -- this bug also occurs with the same code in aclwin.)

CG-USER(93): (format t "~/aclwin:format-date/" (get-universal-time))
7/17/99
NIL
CG-USER(94): (format t "~:/aclwin:format-date/" (get-universal-time))
July 17, 1999
NIL
CG-USER(95): (format t "~@/aclwin:format-date/" (get-universal-time))
17/Jul/1999
NIL
CG-USER(96): (format t "~@:/aclwin:format-date/" (get-universal-time))
Friday, July 17, 1999
NIL
CG-USER(97): (format t "~/aclwin:format-time/" (get-universal-time))
14:19:15
NIL
CG-USER(98): (format t "~:/aclwin:format-time/" (get-universal-time))
14:19:41 PST
NIL
CG-USER(99): (format t "~@/aclwin:format-time/" (get-universal-time))
2:19:57 pm
NIL
CG-USER(100): (format t "~@:/aclwin:format-time/" (get-universal-time))
2:20:48 pm PST
NIL
CG-USER(101): 
;;
;; beginning of code file
;; 
(defpackage :aclwin
  (:export
   *format-date-style*
   format-date
   format-time))
(in-package :aclwin)
(defvar *format-date-style* :us
  "The style for printing dates with ~/format-date/ directive. 
Possible values are: :european, :us")
(defun format-date (stream object &optional colon at-sign &rest args)
  (let ((mode 'short-numeric)
	(separator #\/))
    (when args
      (setq separator (car args)))
    (if* (and at-sign colon)
       then (setq mode 'long-alphabetic)
     elseif at-sign
       then (setq mode 'long-numeric)
     elseif colon
       then (setq mode 'short-alphabetic))
    (print-date stream mode separator object)))
(defun format-time (stream object &optional colon at-sign &rest args)
  (let ((mode 'twenty-four-hour)
	(separator #\:))
    (when args
      (setq separator (car args)))
    (if* (and at-sign colon)
       then (setq mode 'twelve-hour-with-time-zone)
     elseif at-sign
       then (setq mode 'twelve-hour)
     elseif colon
       then (setq mode 'twenty-four-hour-with-time-zone))
    (print-time stream mode separator object)))
(defun print-date (stream mode separator time)
  (multiple-value-bind (second minute hour date month year day-of-week 
			daylight-saving time-zone)
      (decode-universal-time time)
    (declare (ignore time-zone daylight-saving hour minute second))
    (let ((day-string 
	   (case day-of-week
	     (0 "Monday")
	     (1 "Tuesday")
	     (2 "Wednesday")
	     (3 "Thursday")
	     (4 "Friday")
	     (5 "Saturday")
	     (6 "Sunday")))
	  (month-string 
	   (case month
	     (1 "January")
	     (2 "February")
	     (3 "March")
	     (4 "April")
	     (5 "May")
	     (6 "June")
	     (7 "July")
	     (8 "August")
	     (9 "September")
	     (10 "October")
	     (11 "November")
	     (12 "December"))))
      (case mode
	(short-numeric 
	 (format stream "~d~c~2,'0d~c~2,'0d"
		 (case *format-date-style*
		   (:us month)
		   (t date))
		 separator
		 (case *format-date-style*
		   (:us date)
		   (t month))
		 separator
		 (irem year 100)))
	(long-numeric 
	 (format stream "~d~c~a~c~3,' d"
		 date
		 separator
		 (subseq month-string 0 3)
		 separator
		 year))
	(short-alphabetic
	 (format stream "~a ~d, ~3,' d"
		 month-string
		 date
		 year))
	(long-alphabetic
	 (format stream "~a, ~a ~d, ~3,' d"
		 day-string
		 month-string
		 date
		 year))))))
(defun print-time (stream mode separator time)
  (multiple-value-bind (second minute hour date month year day-of-week 
			daylight-saving time-zone)
      (decode-universal-time time)
    (declare (ignore day-of-week year month date))
    (case mode
      (twenty-four-hour (output-time stream hour minute second separator t))
      (twelve-hour (output-time stream hour minute second separator nil))
      (twenty-four-hour-with-time-zone 
       (output-time stream hour minute second separator t) 
       (format stream "~c" #\Space)
       (output-time-zone stream time-zone daylight-saving))
      (twelve-hour-with-time-zone 
       (output-time stream hour minute second separator nil) 
       (format stream "~c" #\Space)
       (output-time-zone stream time-zone daylight-saving)))))
(defun output-time (stream hour minute second separator |24HOURP|)
  (format stream "~:[~d~;~2,'0d~]~c~2,'0d~c~2,'0d"
	  |24HOURP|
	  (if |24HOURP| hour
	    (let ((hours (irem hour 12)))
	      (if (zerop hours) 12 hours)))
	  separator
	  minute
	  separator
	  second)
  (unless |24HOURP|
    (format stream "~c" #\Space) 
    (format stream "~a" (if (i>= hour 12) "pm" "am"))))
(defun output-time-zone (stream time-zone daylight-saving)
  (let ((time-zone-string 
	 (case time-zone
	   (0 (if daylight-saving "BST" "GMT"))
	   (1 "WET")
	   (5 "EST")
	   (6 "CST")
	   (7 "MST")
	   (8 "PST")
	   ;; there could be lots more time zone stuff here 
	   (otherwise nil))))
    (if time-zone-string (format stream "~a" time-zone-string) 
      (progn
	(format stream "~d" (i- time-zone))
	(format stream "hr")))))
;;
;; end of code file
;;

Q 2.6-2) Why can't I use `dir' with run-shell-command?

A 2.6-2) On Windows 95/98 and NT, excl:run-shell-command executes programs but does not invoke shell commands. The function is therefore misnamed for Windows. It is called run-shell-command to provide cross-platform compatibility between Windows and Unix and back compatibility for ACL4.3.x users. It does behave differently on Windows and Unix. The difference is related to differences between UNIX and Windows. See the documentation page for excl:run-shell-command for details on this point.


Q 2.6-3) How do I get the functionality of the 3.0.2 function allegro:read-lisp-line?

A 2.6-3) Although the symbol aclwin:read-lisp-line exists (some symbols in the 3.0.2 allegro package are in the aclwin package in 6.2, and allegro is now a nickname of the common-graphics package), it has no function binding. (In ACL 3.0.2, that function read a line of the optional stream argument and returned a list of the lisp objects on that line. It returned nil for blank lines and also when the end of the file was reached.)

This code mostly replicates the action of that function. The stream argument is required (rather than optional) and it returns :eof when the end of the file is reached (rather than nil). If an actual line is read, nil or a non-empty list is returned so testing whether the result is listp distinguishes between reading a line and reading an end-of-file.

The function here is named my-read-lisp-line. While we do not usually recommend this, you can define aclwin:read-lisp-line by changing the function name to aclwin:read-lisp-line and wrapping the form in excl:without-package-locks form.

(defun my-read-lisp-line (st)
  (let ((str (read-line st  nil :eof)))
    (if (eq str :eof) :eof ;; instead of nil
      (with-input-from-string (s str)
	(loop as x = (read s nil s)
	    until (eq x s)
	    collect x)))))

Q 2.6-4) How do I control the stack size on Windows?

A 2.6-4) The stack-size process attribute was supposed to control the stack allocation for the process. What the Windows documentation did not make clear, unfortunately, was that the running process can control the amount of swap space initially committed to the stack, but cannot select the amount of address space reserved for the stack.

The address space to be reserved for each thread's stack is a property of the executable image being used. The property is specified at link time, but it can be altered without relinking, through the EDITBIN program that is part of the VC+ development package.

To make each thread allocate a 4Meg stack, the command would be

editbin /stack:4000000 lisp.exe 

Unfortunately, MS Windows offers no way to have different reserve sizes for different threads in the same process, so all the threads have to be big enough to support the deepest computation on any thread.


Q 2.6-5) How do I get ANSI ACL (rather than Modern ACL) to start when I double-click on an lpr file?

A 2.6-5) The Windows registry associates file types with programs, so that double clicking on a file of a particular type initiates a program in a clearly defined way. (Thus, typically double clicking on a file with type txt typically initiates the Notepad utility in Windows, opening the file clicked on.) As defined by the installation procedure, lpr files (the files defining projects) are associated with allegro.exe/allegro.dxl, the Modern version of Allegro CL with the IDE. Double-clicking on an lpr file thus starts the Modern image with the IDE, and opens the project associated with the lpr file.

If you want the ANSI Allegro CL with the IDE (allegro-ansi.exe/allegro-ansi.dxl) to start instead, you must modify the registry.

The simplest way to do this is with a Windows tool. On Windows 95/98 and NT,  open the View menu on the Windows Explorer and click on the Options... item. This will display an Options dialog. Click on the File Types tab, and find Lisp project file in the displayed list of types. Select it and click on the Edit... button. Select open in the Actions pane and click on the Edit... button. Modify the text in the Application used to perform action field, changing allegro.exe to allegro-ansi.exe and allegro.dxl to allegro-ansi.dxl. Click on the OK buttons on the open dialogs to complete the change. On Windows 2000, open the Tools menu and click on the Folder Options item, and choose the LPR extension, click on the Advanced button, click on the open action, click on the Edit... button, find the associated command line, and modify it.

You can also make the change using a file, as we now describe. Create in any convenient location a file named foo.reg (filename is foo, type is reg) with the following contents (modified as necessary by the Notes following the contents):

REGEDIT4

[HKEY_CLASSES_ROOT\ACL.ProjectFile]
@="Lisp project file"

[HKEY_CLASSES_ROOT\ACL.ProjectFile\DefaultIcon]
@="C:\\PROGRAM FILES\\ACL60\\allegro-ansi.exe,0"

[HKEY_CLASSES_ROOT\ACL.ProjectFile\shell]

[HKEY_CLASSES_ROOT\ACL.ProjectFile\shell\open]

[HKEY_CLASSES_ROOT\ACL.ProjectFile\shell\open\command]
@="C:\\PROGRAM FILES\\ACL60\\allegro-ansi.exe -I allegro-ansi.dxl -project \"%1\""

Notes:

Once the file is ready, open the Windows Explorer to the directory containing the file, and double-click on the file. The registry will be updated.


Next FAQ topic: Architecture-specific problems: 2.7. Linux

Previous FAQ topic: Architecture-specific problems: 2.5. Compaq ALPHA


© Copyright 1999, 2000, 2001, 2002 Franz Inc., Berkeley, CA.  All rights reserved.
$Revision: 1.1.2.1 $