.c	Friday  Dec 2,1983  1:45  LQ+4D.19H.52M.43S.  -*- Bolio -*-

.chapter "Environment Enquiries"

.section "The Host Environment"

.defun lisp-implementation-type
This returns a string which is the name of the lan{lisp}
implementation.  In lan{nil}, this string is 3"VAX NIL"*.
.end_defun

.defun lisp-implementation-version
This function returns a string which describes the versions of the
systems loaded in the lan{nil}.  In lan{nil}, this is the same as
calling 3(si:system-version-info t)* (see
(si:system-version-info-fun) for more details).
.end_defun

.defun machine-type
This returns a string which names the type of machine the lan{nil}
is running on, such as 3"DEC VAX-11/780"*.  In the current
implementation, this string is set manually in the lan{nil} site
parameters file, so may be inaccurate if that file was not correctly
updated when the lan{nil} was installed.
.end_defun

.defun machine-instance
Returns a string which is a (supposedly) unique string naming the
machine, such as 3"MIT-CORWIN"*.  This name will normally be the
same as that used as the "host" name by the pathname code.
.end_defun

.defun host-software-type
The software type of the machine.  In lan{nil}, this is always
3"VMS"*.
.end_defun

.defun short-site-name
This returns a short name of the site, for instance 3"MIT AI
Lab"*.  If this was not set up in the lan{nil} site parameters
file, it will default to what is returned by the
3machine-instance* function.
.end_defun

.defun long-site-name
This returns a long name for the site, such as 3"MIT Artificial
Intelligence Laboratory"*.  If this was not set up in the lan{nil}
site parameters file, it will default to the short site name (above),
or the machine instance.
.end_defun


.section "Maclisp-Compatible Status Enquiries"
.setq status-enquiries-section-page section-page

.table 3 250 250 0 0 0
.item (status date)
returns a list of the year (modulo 100), month, and day of the month.
.item (status daytime)
returns a list of the current hour, minute, and second.
.item (status dow)
returns a symbol which is the full name of the current day of the week
(in English, sorry).  The package the symbol is interned in is
probably 3system-internals*;  perhaps it should be the keyword
package, or the value should be a string anyway.
.item (status gctime)
Returns the runtime contribution of the garbage-collector.  This is,
of course, always 30* in the current lan{nil}.
.end_table
The first four of these may all be obtained by use of the functions in
(time-package-section-page).


.section "Privileges"

.defun get-privileges
This returns a list of keywords naming the privileges the lan{nil}
currently has enabled.  The keywords are listed below.
.end_defun

.defun set-privileges &rest keywords-and-values
This takes as arguments alternating privilege keywords and flags;  if
the flag is 3nil*, the corresponding privilege is disabled,
otherwise it is enabled (if that is possible).  3set-privileges*
returns a list of the privileges which were enabled when it finished,
just as 3get-privileges* does.  For instance,
.lisp
(set-privileges :sysprv t :bypass nil)
.end_lisp
(attempts to) turn on the 7sysprv* privilege, and turn off the
7bypass* privilege.
.end_defun

The privilege keywords defined are
.table 3 250 250 0 0 0
.item :cmkrnl
.item :cmexec
.item :sysnam
.item :grpnam
.item :allspool
.item :detach
.item :diagnose
.item :log_io
.item :group
.item :acnt
Note that for this privilege, the name used in lan{vms} is
3noacnt*;  however, lan{nil} uses 3acnt* because that is
the name used by lan{dcl}.
.item :prmceb
.item :prmmbx
.item :pswapm
.item :altpri
The internal name for this is 3setpri*, however lan{dcl} uses
3altpri*, so lan{nil} does also.
.item :setprv
.item :tmpmbx
.item :world
.item :mount
.item :oper
.item :exquota
.item :netmbx
.item :volpro
.item :phy_io
.item :bugchk
.item :prmgbl
.item :sysgbl
.item :pfnmap
.item :shmem
.item :sysprv
.item :bypass
.item :syslck
.end_table


.section "Memory Usage"

.defun room &optional stream
3room* prints out a fairly verbose English description of the
virtual memory usage of the lan{nil}, and some related information.
In particular, one of the things it tells is an estimation of how much
space is left for expansion of the 2living heap*, which is where
all ordinary consing is performed.
.end_defun

Note also the 3si:pagefault-count* function,
(si:pagefault-count-fun).


.section "Time and Date"
.setq time-package-section-page section-page

(See also (status-enquiries-section-page).)

lan{Nil} provides a set of functions for manipulating dates and
times.  A date and time is represented in one of two ways:  by a
term_i{universal-time}, which is an integer number of seconds from
00:00 January 1, 1900 GMT, and as a term_i{decoded time}, which
consists of the following components:
.table 2 250 250 0 0 0
.item seconds
.item minutes
.item hours
.item date
.item month
The one-origined month number: January is 31*, etc.
.item year
The full year, e.g., 31983*.
.item day-of-week
The zero-origined day of the week:  30* is Monday, 31* is
Tuesday, and 36* is Sunday.
.item daylight-savings-time-p
3t* or 3nil*, depending on whether the decoded time is
daylight savings time.
.item timezone
The number of the timezone:  30* is Greenwich time, 35* is
Eastern time, 3-2* is Eastern European time, and 3-4.5* is
Indian Standard time.
.end_table
This decoded time is not represented in any datastructure, but rather
is returned as multiple values by functions which decode
universal-time, or passed as arguments as other functions.

.subsection "The Main Functions"

The functions in this section are defined by lan{common-lisp}, and
all may be referred to without any package qualification.

.defun get-universal-time
This returns the current time in universal-time format.
.end_defun

.defun get-decoded-time
This returns the current time, decoded, as 9 values:  the current
second, minute, hour, date, month, year, day-of-week,
daylight-savings-time-p, and timezone.  It is effectively
.lisp
(decode-universal-time (get-universal-time))
.end_lisp
.end_defun

.defun decode-universal-time universal-time &optional timezone
2timezone* defaults to the current timezone (see
(*timezone*-var)).  This decodes 2universal-time* with respect
to 2timezone*, and returns 8 values:  the second, minute, hour,
date, month, year, day-of-week, daylight-savings-time-p, and timezone.
.end_defun

.defun encode-universal-time seconds minutes hours date month year &optional timezone
2timezone* defaults to the current timezone.  This encodes the
given date and time for the timezone, and returns a universal-time.
.end_defun

.subsection "Printing Dates and Times"

The following functions are not globalized, but must be referred to
with the 3time:* package prefix.  Most of them are the same as
those provided by lan{lisp machine lisp}.  All of them take a
2destination* argument, which may be a stream, 3t*, or
3nil*.  3t* means use the value of 3standard-output*;
3nil* means return the result as a string.  Note that this is
compatible with the way the 3format* function ((format-fun))
interprets its 2destination* argument, 2not* the way the
regular lan{nil} printing functions do.  The 2destination*
always defaults to 3t*, meaning print the output on
3standard-output*.

.defun time:print-time seconds minutes hours day month year &optional (destination t)
This prints the specified date and time in brief format, to
2destination*.  The format used is "10/03/83 23:02:59"--the month
number, the day in the month, the year (modulo 100), and the time.
.end_defun

.defun time:print-current-time &optional (destination t)
This does 3time:print-time* of the current time.
.end_defun

.defun time:print-universal-time universal-time &optional (destination t) timezone
This effectively does 3decode-universal-time* on
2universal-time* and 2timezone* (which defaults to the current
timezone), and then 3time:print-time* of the results to
2destination*.
.end_defun

.defun time:print-date seconds minutes hours date month year day-of-the-week &optional (destination t)
This prints the date in a format like
.lisp
Friday the seventh of October, 1983; 11:02:59 pm
.end_lisp
.end_defun

.defun time:print-current-date &optional (destination t)
Prints the current date, in 3time:print-date* format.
.end_defun

.defun time:print-universal-date universal-time &optional (destination t) timezone
Uses 3time:print-date* to print the decoding of
2universal-time* and 2timezone*.
.end_defun

.defun time:print-brief-universal-time universal-time &optional (destination t) reference-time
This prints 2universal-time* in a format like 310/07/83
23:02*.  However, portions of it will be omitted if they are the
same as the corresponding components of the universal-time
2reference-time* (which defaults to the current time).  In
particular, if the year is the same, it is omitted, and if the month
and day are also the same, the entire date is omitted.  So depending
on the reference time, one could get 310/07 23:02* or even just
323:02*.
.end_defun

.defun time:print-universal-mail-format-date universal-time &optional (destination t)
Prints the date and time specified by 2universal-time* in "mail
format".  This is a format which conforms to that specified in RFC822,
"Standard for the format of ARPA Internet Text Messages"
ref{RFC822}.  It looks like
.lisp
Fri, 7 Oct 83 23:02:59 EDT
.end_lisp
.end_defun

.defun time:print-current-mail-format-date &optional (destination t)
Prints the current date and time, using
3time:print-universal-mail-format-date*.
.end_defun

.subsection "Namings"

The time package contains a small database of names of months and days
of the week, in various formats.  The format is split along two
dimensions:  the 2mode*, for instance 3:long*, 3:medium*,
or 3:short*, and the 2language*, such as 3:english*.
There is a global default for each of these:

.defvar time:*default-language*
The default value of this is 3:english*.
.end_defvar

.defvar time:*default-mode*
The default value of this is 3:long*.
.end_defvar

The mode and language are combined (by lookup) into a composite symbol
for which the lookup of the actual text format is performed.  For the
following functions, one may specify this composite symbol, such as
3:long-english*, just the mode (3:long*), in which case the
default language is used, or just the language, in which case the
default mode is used.  The three predefined modes are 3:long*,
3:medium*, and 3:short*, and there are entries for the
languages 3:english*, 3:french*, 3:german*,
3:spanish*, and 3:italian*.  Not all mode/language
combinations are supported;  in particular, 3:medium* is treated
as a special case, such that if it is not found, 3:short* is tried
instead.  The 3:short* mode typically implies the short standard
abbreviation;  this is usually three characters, however it is two for
3:german*.

.defun time:month-string month &optional modespec
Returns a string naming the month, in the format specified by
2modespec*.  Assuming the initial default values for
3time:*default-language** and 3time:*default-mode**,
.lisp
(time:month-string 12)		=>  "December"
(time:month-string 12 :short)	=>  "Dec"
(time:month-string 12 :spanish) =>  "diciembre"
(time:month-string 9 :medium)	=>  "Sept"
(time:month-string 9 :short)	=>  "Sep"
.end_lisp
.end_defun

.defun time:day-of-the-week-string day-of-the-week &optional modespec
Similar:
.lisp
(time:day-of-the-week-string 1)			=>  "Tuesday"
(time:day-of-the-week-string 1 :short)		=>  "Tue"
(time:day-of-the-week-string 1 :medium)		=>  "Tues"
(time:day-of-the-week-string 1 :german)		=>  "Dienstag"
(time:day-of-the-week-string 1 :short-german)	=>  "Di"
.end_lisp
.end_defun

.defun time:mode-language-fetch modespec hash-table what
This is the primitive which canonicalizes the mode, language, or
composite symbol into a composite symbol, and looks that up in
2hash-table*.  2what* is just a descriptive string for error
reporting, e.g., "Month name".  The two above functions use this
function to retrieve vectors from the following hash tables, which are
then indexed into to get the names.
.end_defun

.defvar time:*month-strings*
This is a hash table associating the composite mode/language symbols
(e.g., 3:long-english*, 3:short-german*) with vectors of the
strings for the given months.  The vectors are zero-origined, so
31* must be subtracted from the month number before the 3aref*
(or 3sgvref*) is performed.  The vectors are always simple general
vectors.
.end_defvar

.defvar time:*day-of-the-week-strings*
The hash table for day-of-the-week names.
.end_defvar

Thus, 3time:month-string* is defined (modulo error checking) as
.lisp
(defun month-string (month &optional modespec)
  (sgvref (mode-language-fetch
	     (or modespec *default-mode*) *month-strings*
	     "Month name string")
	  (1- month)))
.end_lisp
Fetching the vector and indexing into it can be useful if the vector
is going to be used repeatedly, for instance for printing a directory
listing.

.subsection "Timezones"

.defvar time:*timezone*
The value of this is the current timezone.  It should be initialized
in the lan{nil} site initialization file to the correct value;
otherwise, it will be 35*, which is Eastern time.
.end_defvar

.defun time:timezone-string &optional timezone daylight-savings-p
This returns the canonical three-character string for the timezone, or
3nil* if the name is not known to lan{nil}.
.lisp
(time:timezone-string 5 nil)	=>  "EST"
(time:timezone-string 5 t)	=>  "EDT"
(time:timezone-string 0 nil)	=>  "GMT"
.end_lisp
2timezone* defaults to the current timezone, and
2daylight-savings-p* to the value of
3(time:daylight-savings-p)*.
.end_defun

.subsection "Miscellaneous Other Functions"

.defun time:leap-year-p year
Returns 3t* if 2year* is a leap year, 3nil* otherwise.
.end_defun

.defun time:daylight-savings-p
Returns 3t* if it is currently daylight savings time, 3nil*
otherwise.
.end_defun

.defun time:month-length month year
Returns the length of the month 3month* in 2year*.
.end_defun

.defun time:daylight-savings-time-p hour day month year &optional timezone
Returns 3t* if the specified day/time is in daylight savings time
in the specified timezone (which defaults to the current timezone),
3nil* otherwise.  (The specified hour is assumed to be standard
time.)  Note also (dst-hacking-section-page).
.end_defun

.defun time:day-of-the-week (day month year)
Returns the number of the day of the week of the specified date.
.end_defun

.defun time:verify-date day month year day-of-week
If 2day* is a day within 2month* which fell on
2day-of-week*, this returns 3nil*;  otherwise, it returns a
string describing the conflict.
.end_defun

.defun time:moonphase &optional universal-time
Returns the phase of the moon decoded into five values:  the
(zero-origined) number of the quarter, the day, hour, minute, and
second.  The quarters are (from 0 to 3) new moon, first quarter, full
moon, and last quarter.  This is presumably the uncorrected mean
longitude.
.end_defun


.defun time:print-moonphase quarter day hour minute second
Prints the phase of the moon in a format like "FM+2D.3H.29M.57S.".
The first field will be one of "NM", "FQ", "FM", or "LQ".
Zero-suppression is performed on the other fields;  for instance,
"FM+2D.29M.".
.end_defun

.defun time:print-current-moonphase &optional (destination t)
Similar.
.end_defun

Note also the 3get-internal-run-time* and
3get-internal-real-time* functions, on
(get-internal-run-time-fun).

.subsection "Variations in Daylight Savings Time"
.setq patchup-dst-section-page section-page

The timezone objects lan{nil} uses to store information on
particular timezones include a function which may be used to tell if
a particular hour, day, month, and year (when interpreted as standard
time) is in daylight time.  Most of the initial timezone entries have
3nil* in this component, which is taken to mean that the zone
never uses daylight time.  It may be necessary to patch this up;  some
functions and hacks are presented here to aid in this.

.defun time:zoneconv timezone
If 2timezone* is a timezone object (an object of type
3time:timezone*), it is returned.  If it is a number, then an
existing timezone entry for that offset in the list
3time:*timezones** is returned.  (Otherwise an error is
signalled.)
.end_defun

If the daylight-savings-time predicate lan{nil} supplies is not
appropriate for the site (or is just plain incorrect), it can be
patched by
.lisp
(setf (time:timezone-dst-rule
         (time:zoneconv 2timezone-offset*))
      'beandorfian-daylight-savings-time-p)
.end_lisp
where 2timezone-offset* is the offset from GMT of the timezone in
question, and 3beandorfian-daylight-savings-time-p* the predicate
which tells whether any particular hour in a particular year is in
daylight savings time.

.defun time:regular-american-daylight-savings-time-p hour day month year
This returns 3t* if 2hour*, 2day*, 2month*, and
2year* is between 1 am of the last Sunday in April and 1 am of the
last Sunday in October (see below).
.end_defun

.defun time:last-sunday-in-april year
Returns the day of the month on which the last Sunday falls in April.
.end_defun

.defun time:last-sunday-in-october year
Returns the day of the month on which the last Sunday falls in
October.
.end_defun

Computations like "last Sunday in April" are fairly easy to perform.
To find the last 2dow* day in a month, find the day-of-the-week of
the last day of the month, and subtract the number of days it takes to
get back to the desired day of the week.  For instance,
.lisp
(defun last-sunday-in-april (year)
  (-& 30 (\\& (-& (+& 7 (day-of-the-week 30 4 year)) 6) 7))
.end_lisp
The 330* is the last day in April, 34* the month April;
36* is Sunday, and the 37*s and arithmetic with them doing
modulus stuff.  Obviously the arithmetic can be simplified to
.lisp
(-& 30 (\\& (+& 1 (day-of-the-week 30 4 year)) 7))
.end_lisp
Because this actually finds the last day of a particular weekday on or
before some particular day, it could be used to find the 2first*
Sunday in a month by substituting 37* for the last day of the
month, and the 2second* Sunday by substituting 314*.

.subsection "Internal Conversions"

Internally, lan{nil} time measurements convert the lan{vms} 64-bit
integer (number of 100-nanosecond tics) into a double-float number of
seconds.  The following subprimitives are provided for the conversion:

.defun %convert-time-to-d_float simple-bit-vector
2simple-bit-vector* should be a simple bit vector 64 bits long.
It is assumed to contain the binary representation of a lan{vms}
absolute time. This quantity is returned as a double-float in seconds,
accurate to at least hundredths.
.end_defun

.defun %convert-d_float-to-time double-float simple-bit-vector
The inverse of 3%convert-time-to-d_float*;  the lan{vms}
representation is stored into 2simple-bit-vector*.
.end_defun

.defun time:convert-vms-time-to-universal-time vms-time
2vms-time* is a double-float absolute time representation, as
returned by 3%convert-time-to-d_float* (above) or
3elapsed-time* ((elapsed-time-fun)).  This converts it to a
universal-time.  This is used not only by 3get-universal-time*,
but also for the conversion of dates in the filesystem (as by, for
example, the 3file-creation-date* and 3directory* functions)
into universal time format.  See the following section for
environmental factors which affect the interpretation of
2vms-time*.
.end_defun

.subsection "Brain Damage"
.setq vms-time-bd-section-page section-page

The format of universal-time (which is defined by lan{common lisp})
is the same as that specified by the ARPA Internet Time Protocol
ref{RFC868} as a "site-independent, machine-readable date and time."
Because it is always an offset based on GMT, it is unaffected by local
time zones;  because this is always a standard time, it does not get
confused by local variations (daylight savings time).  Because it is
absolute, the local time can be computed from it by knowing only the
timezone and whatever rules and information are necessary to determine
when daylight savings time takes effect.  (The typical way this is
done is a fairly simple perpetual-calender-like computation to see if
the date and time falls between the last Sunday in April, and the last
Sunday in October.)

The absolute time used by lan{vms} is an offset (in 100-nanosecond
units) from 00:00 November 17, 1858, in the current local time.  No
distinction is made between standard and daylight time.  While this
appears to have the benefit of simplifying life by eliminating
daylight-savings-time computations, it has the side effect that to
change to and from daylight time, the base time must be modified,
2thus changing the only quantity useful for measuring absolute
times*.  There is also the fact that, in local time, there is an
hour which occurs twice (when daylight time is reset to standard
time), hence for that hour one cannot determine whether one is
actually in daylight or standard time.

Because lan{nil} must use the lan{vms} time to determine the
absolute time, 3get-universal-time* (and all things which return
results based on that quantity, which is just about all the time and
date functions in this section) can return an incorrect value.  Also,
the quantities returned by 3elapsed-time* ((elapsed-time-fun))
and 3get-internal-real-time* ((get-internal-real-time-fun)) are
based on this, meaning that if a shift in or out of daylight time
occurs and the lan{vms} base time is changed, elapsed time measured
around the shift will be incorrect.  There is a variable provided
for telling lan{nil} about two potential system-wide conventions for
bypassing this sort of lossage.

.defvar time:*system-time-kludge*
This may take on one of three values.
.table 3 250 250 0 0 0
.item nil
This is the default.  It means that the lan{vms} base time is always
the local time (potentially daylight time), and hence subject to
complete lossage.
.item :standard
This means that the lan{vms} base time is always based on the
standard time for the current timezone.
.item :gmt
This means that the lan{vms} base time is GMT (implies never
daylight time).
.end_table
Either of the last two options eliminate the ambigous-hour and
incorrect-elapsed-time problems which might be suffered otherwise.  Of
course, they mean that all the lan{vms} utilities which show dates
and times won't work quite right.  Oh well.
.end_defvar

The above variable is examined for conversion of all lan{vms}
internal times into universal time.  Additionally, for interpretation
of the 2current* time, if the above variable is 3nil*, then
the 7DST_SITE* logical name is examined.
'setq dst_site-logical-name page
'cindex DST_SITE logical name
'cindex logical name, DST_SITE
(This is a logical name used/defined by Chaosnet software distributed
by Symbolics, Inc.  However, as with other similar logical names used
by lan{nil}, the system manager could put its definition in the
system startup file.)  If this logical name is defined, then if it
translates to the string 7"ON"*, then daylight savings time is
assumed to be in effect;  translation into anything else is taken to
mean that standard time is in effect.  If the logical name is
undefined, then it is examined to see if it might be (a computation
which can be wrong near the times when the change is effected).

