### 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?
> 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?

A 2.6-1) What follows below is a quick port, with all its features, of these features for ACL 7.0. 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, 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) Use the following function. which 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.

    (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 (for the executable allergo.exe, repeat the command for other executables):

>     editbin /stack:4000000 allegro.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. While Windows menu choices move about, try opening the View menu on the Windows Explorer and click on the Options... item or try the Tools men and the Folder Options choice. 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:

- The contents assume Allegro CL is installed in C:\\Program Files\ACL62\. If it is installed in a different location, correct the third (with DefaultIcon) and the sixth entries (with open\command) appropriately.
- The contents assume you want allegro-ansi.exe/allegro-ansi.dxl to be started. If you want another exe file and/or another dxl file, specify the exe file in the third and sixth entries and the dxl file in the sixth entry.
- Additional command-line arguments can be included in the sixth entry.

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, 2004 Franz Inc., Berkeley, CA. All rights reserved.
$Revision: 1.3 $