; CALENDAR_TSR.MAR              Paul Klissner            1990 
;
; The following program draws a one month calendar in the upper
; right hand corner of the screen whenever the user presses the CTRL/D 
; key at the terminal. (The calendar display format is illustrated below).
;
; The time and current day of the month are highlighted on the
; screen for added information and impact.
;
; The code that follows creates a self-contained TSR.  It consists of
; loader and unloader sections, as well as a calendar drawing procedure 
; that gets relocated into P1 space.
;
;
; Example:
;
;
;              Mar.  12:45 pm  1991 
;              Su Mo Tu We Th Fr Sa
;                              1  2
;               3  4  5  6  7  8  9
;              10 11 12 13 14 15 16    
;              17 18 19 20 21 22 23    
;              24 25 26 27 28 29 30 
;              31
;
;
;---

.library 'sys$library:lib'       
.link    'sys$system:sys.stb'    

$lnmdef


; Modifiable parameter (specifies the TSR activation key):

        trap_key     = ^a'D' - 64       ; (CTRL/D)


; The following macros create conditional branchs that have destinations
; more than 127 bytes away.

.macro  BGTRU_W dest,?next
        blequ   next
        brw     dest
next:
        .endm

.macro  BNEQU_W dest,?next
        beqlu   next
        brw     dest
next:
.endm

.macro  BLBC_W  base,dest,?next
        blbs    base,next
        brw     dest
next:
.endm

.macro  BBC_W   pos,base,dest,?next
        bbs     pos,base,next
        brw     dest
next:
.endm


memloc:         .blkl                   ; Receives parse result
memlen:         .blkl                   ; Receives parse result
lendescr:       .long 4,hexlen          ; Descriptor for parsing logical name
locdescr:       .long 8,hexloc          ; Descriptor for parsing logical name
ttname:         .ascid 'TT'             ; Descriptor for current terminal
userchan:       .blkl                   ; User mode channel to terminal
loadmsg:        .ascid 'Loaded CALENDAR, ' ; Residency message
namedsc:        .long 132,10$              ;


10$:            .blkb 132                  ;
rmvname:        .ascii 'Removing CALENDAR, previously '
rmvname_len=.-rmvname
crlf:           .byte 10,13             ; Carriage return/Linefeed bytes

.entry MAIN,0

        $assign_s devnam=ttname,-       ; Assign user mode channel to terminal
                  chan=userchan

        $qiow_s chan=userchan,-         ; Jump down one line
                func=#io$_writevblk,-
                p1=crlf,-
                p2=#2

        ; **** Now see if process TSR is loaded ***

1$:     $trnlnm_s tabnam = lnm_table,-  ;Check process logical name table to 
                  lognam = lnm_name,-   ;see if this code is already resident.
                  itmlst = lnm_list     ;(we don't want to load it twice)
        blbs    r0, 3$                  ;branch if translation was successful
        $cmkrnl_s routin = loader       ;Load code and table into p1 space
        blbc    r0,2$

        ; **** Display loaded message, if TSR was installed ****

        $qiow_s chan=userchan,-         ;Display 'loaded' message
                func=#io$_writevblk,-
                p1=loadmsg+8,-
                p2=loadmsg

        $qiow_s chan=userchan,-         ;Describe TSR memory location
                func=#io$_writevblk,-
                p1=lnm_equiv,-
                p2=#lnm_equiv_len+2

2$:     $exit_s r0
        
3$:     ; **** Display removal message, if TSR was previously installed ****

        $qiow_s chan=userchan,-         ;Display removal message
                func=#io$_writevblk,-
                p1=rmvname,-
                p2=#rmvname_len

        $qiow_s chan=userchan,-         ;Describe previous location
                func=#io$_writevblk,-
                p1=lnm_equiv,-
                p2=#lnm_equiv_len+2

        ; *** PARSE LOGICAL NAME TO GET TSR MEMORY POINTER VALUES ***

        ; Get memory address
        pushl   #4                      ;# bytes to convert


        pushal  memloc                  ;Address of integer longword
        pushal  locdescr                ;Address of text source
        calls   #3,g^ots$cvt_tz_l       ;Convert from hex text to integer
        blbc    r0,exit2                ;branch if error
        
        ; Get memory size
        pushl   #2                      ;2 bytes to cvt
        pushal  memlen                  ;Address of variable to convert to
        pushal  lendescr                ;hex text length to convert from
        calls   #3,g^ots$cvt_tz_l       ;convert from hex text to integer 
        blbc    r0,exit2                ;branch if error

        $cmkrnl_s routin = unloader     ;Unload the TSR
        
exit2:  $exit_s r0                      ;Exit with status

;--
; The following routine executes in Kernel mode.  It allocates memory 
; for the TSR, and relocates the TSR it into P1 space.  It then activates
; The TSR by calling it at non-AST level to initialize it.  This routine
; also creates a process private logical name to describe the TSR.
;--
.entry LOADER,0

        $assign_s devnam=ttname,-       ;get kernal mode channel to terminal
                  chan=ttkrnl

1$:     movl    #code_size,r1           ;Get the size to allocate
        jsb     g^exe$alop1proc         ;Get memory to last beyond 
                                        ;the life of the image  
        blbc    r0,return               ;Return if we couldn't get the memory.
        movl    r1,ast_memory_size      ;Save size of actual allocation
        movl    r2,ast_vector           ;Save the address of the region

        movc    #code_size,-            ;Copy ast code into buffer
                ast_code,-
                @ast_vector             

        calls   #0,@ast_vector          ;Activate AST code

; **** Fill in residency logical name with address and length of TSR code ****

        pushl   #4                      ;4 bytes to convert
        pushl   #8                      ;8 hex digits, minimum.
        pushal  locdescr                ;address of target text
        pushal  ast_vector              ;source value
        calls   #4,g^ots$cvt_l_tz       ;convert
        blbc    r0,return               ;branch if error

        pushl   #2                      ;2 bytes to convert
        pushl   #4                      ;4 hex digits, minimum.
        pushal  lendescr                ;address of target text
        pushal  ast_memory_size         ;source value
        calls   #4,g^ots$cvt_l_tz       ;convert


        blbc    r0,return               ;branch if error
        

        $crelnm_s attr   = lnm_attributes,-     ;Create the Logical name
                  tabnam = lnm_table,-
                  lognam = lnm_name,-
                  itmlst = lnm_list
return: ret

;---
; The following routine gets called in kernel mode to remove the TSR
; completely from the process.  Before being called, the location and size
; of the TSR memory is saved at MEMLOC, and MEMLEN.  The logical name
; describing the TSR is removed, and the kernel mode channel is deassigned.
; (Note that the channel number is reserved at the beginning of the located
; code for easy accessability).
;--
.entry UNLOADER,0

;  ****  Unloads the TSR from P1 space, at non-ast level ****

        $dellnm_s tabnam=lnm_table,-    ;Delete the logical name
                  lognam=lnm_name 

        movl    memloc,r0               ;Get the address of the tsr code
        $dassgn_s chan = 5(r0)          ;Remove the kernel mode channel
        movl    memloc,r0               ;get the address of the tsr code again
        beqlu   10$
        movzwl  memlen,r1               ;get the length
        beqlu   10$
        jsb     g^exe$deap1             ;Deallocate the code
10$:    ret                             ;and return

;---
;  Everything from this point forward comprises the resident code
;  and data that is be relocated into P1 pool at runtime.  Note 
;  that part of the initialization logic updates descriptors 
;  with the MOVAL instruction after the code is relocated 
;  so that all of the memory references reflect the new location 
;  of the TSR routine.
;---
TSR_CODE_ADDRESS = . 

AST_CODE:: 

        ;IMPORTANT: This routine must preserve all registers

        .word ^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

        ; The following two lines must immediately follow the entry mask
        ; so that the unloader can retrieve that channel number the out-of-band
        ; key is assigned on.

        brw     ttkrnl+4


ttkrnl: .blkl                           
        

        tstl    init_flag                       ; Initialized yet?
        bnequ   1$                              ; Branch if so
        jsb     initialize                      ; Otherwise initialize AST code
        ret                                     ; And exit

        ;******************************************************************;
        ;  THIS CODE CREATES AND DISPLAYS A CALENDAR FOR THE CURRENT MONTH ;
        ;******************************************************************;

1$:     movb    #^x30,col                      ;Initialize display column
        moval   col,outbuf+4                   ;Get pointer to column text
        $qiow_s   chan=ttkrnl,-                ;Get terminal charactersitics
                  func=#io$_sensemode,-
                  p1=ttcharbuf,-
                  p2=#12
        blbc_w  r0,astexit                     ;Branch if error
        bbc_w   #tt2$v_avo,ttcharbuf+8,astexit ;Exit if TT doesn't have AVO
        extzv   #16,#16,ttcharbuf,ttwidth      ;Get the terminal width
        subl    #25,ttwidth                    ;Subtract calendar width from
                                               ;terminal width setting
        cmpl    ttwidth,#99                    ;How many digits in width?
        bgtr    5$                             ;Branch if greater than two
        addl    #1,outbuf+4                    ;Shift descriptor reference
5$:     $fao_s  ctrstr=faobuf,-                ;Convert width to ASCII string
                outbuf=outbuf,-
                p1=ttwidth      
        blbc_w  r0,astexit                     ;Branch if error

        $qiow_s chan=ttkrnl,-
                func=#io$_writevblk,-
                p1=save_pos,-
                p2=#2

        ; *** Fill in major components of the Calendar header ***

        movc5   #0,dda,#32,#126,dda             ;Blank fill display array
        $asctim_s timbuf=systime_dsc            ;Get current VMS time
        movc    #11,systime,work_date+8         ;Copy the current date
        movw    #^x3130,work_date+8             ;Adjust to be 1st of month
        movc    #3,systime_mo ,  header_mo      ;Move month into header
        bisw    #^x2020,header_mo+1             ;2nd two digits to lower case
        movc    #4,systime_year, header_year    ;Move year into header
        movl    feb29+4,r3                      ;Get address of FEB 29 string
        movc    #4,systime_year, 7(r3)          ;Fill in year for Feb 29 check
        movc    #5,systime_hhmm, header_hhmm    ;Move in unconverted HH:MM
        $bintim_s timbuf=feb29,timadr=work_quad1;Check for validity
        blbc    r0,7$                           ;Branch if not a leap year
        movb    #29,month_tbl+3                 ;Make Feb. a 29 day month
7$:     $bintim_s timbuf=work_date,-            ;Get binary time for the
                  timadr=work_quad1             ; first day of the month



        ;Calculate the day of week
        movq    work_quad1,r0                   ;Get the current day
        ediv    #60*10*1000*1000,r0,r0,r1       ;Get the time in min. from 1858
        clrl    r1                              ;(only 32 bits)
        ediv    #24*60,r0,r0,r1                 ;Time in days into r0
        addl2   #2,r0                           ;Nov. 17,1858 is a Wednesday
        clrl    r1                              ;Again only 32 bits
        ediv    #7,r0,r0,r1                     ;R0 = # of weeks from ref. time.
                                                ;R1 = Day of week
        addl3   #1,r1,dow                       ;Adjust and save day of week

        ; ***** DETERMINE # OF DAYS IN CURRENT MONTH *****

        clrq    r6                              ;Clear search indicies
        moval   months,r8                       ;Addr of month name table
8$:     cmpc    #3,(r8)[r6],systime_mo          ;Month name match?
        beql    9$                              ;Branch if so
        addl    #3,r6                           ;Check next array entry
        aobleq  #11,r7,8$                       ;Check next
9$:     movl    month_tbl[r7],r3                ;Get # of days in month

        ;*** Fill the calendar display array with the day number for
        ;    the month, with the first day positioned under the correct
        ;    day of the week.

        moval   dda,r8                          ;Addr. of array
        movq    #1,r6                           ;Initialize day counter
        mull3   #3,dow,r2                       ;Calc. initial offset in 
                                                ;Day Display Array (DDA) 
10$:    clrq    r4                              ;Clear R4/R5
        ediv    #10,r6,r4,r5                    ;Get digits of month day
        bisl    #^x30,r4                        ;Make high digit ASCII
        bisl    #^x30,r5                        ;Make low digit ASCII
        cmpl    r4,#^x30                        ;High digit 0?
        bnequ   20$                             ;Branch if not
        movl    #^x20,r4                        ;Convert to a blank
20$:    movb    r4,(r8)[r2]                     ;Move into display array slot
        movb    r5,1(r8)[r2]                    ;Save for second digit
        incl    r6                              ;Increment day of month
        addl    #3,r2                           ;Point to next stash slot
        sobgtr  r3,10$                          ;Loop till day count exhausted

        ;***** ADJUST DISPLAY TIME TO CIVILIAN FORMAT ****

adjust_time:    
        movc    #3,amtext,header_ampm-1         ;Reset AM/PM text state
        bicw    #^x3030,header_hhmm             ;Cvt from ASCII HH to decimal values
        clrl    r1                              ;Zero the longword
        mulb3   header_hhmm,#10,r1              ;Get high order digit of hour*10
        addb    header_hhmm+1,r1                ;add in the low order digit HH
                                                ;(result is integer value of HH)
        cmpl    r1,#12                          ;Compare to the hour of noon
        beqlu   10$                             ;Branch if noon hour now


        blssu   20$                             ;Branch if before hour of noon
        subl    #12,r1                          ;Its afternoon, cvt 
                                                ;from military time by 
                                                ;subtracting 12
        clrl    r2                              ;Clean up high order part
        ediv    #10,r1,r1,r2                    ;Get High order digit value 
                                                ;into r1, and low order into r2
        movb    r1,header_hhmm                  ;Restore high order into
                                                ;its position in time buffer
        movb    r2,header_hhmm+1                ;Restore low order into time 
                                                ;buffer
10$:    movb    #^a"p",header_ampm              ;Set to PM time
20$:    bisw    #^x3030,header_hhmm             ;Convert HH to displayable ASCII
        cmpb    header_hhmm,#^a"0"              ;Leading 0?
        bnequ   30$                             ;Branch if not
        movb    #^a" ",header_hhmm              ;If so, convert it to a blank
30$:    clrl    r5                              ;Line index
40$:    addb3   #49,r5,row                      ;Setup the display
        $qiow_s chan=ttkrnl,-                   ;Clear line and position cursor
                func=#io$_writevblk,-
                p1=clreol,-
                p2=#clreol_size
        movl    display_array[r5],r2            ;Addr. of next line to display
        movl    #20,r0                          ;Assume it is a short line
        tstl    r5                              ;Is it the long line?
        bnequ   41$                             ;Branch if not
        movl    #27,r0                          ;Correct the line length var.
                                                ;Display current line from table
41$:    $qiow_s chan=ttkrnl,-                   ;Display the line from the array
                func=#io$_writevblk,-
                p1=(r2),-
                p2=r0   

        aoblss  #9,r5,40$                       ;Branch to display [next] line


; *************** Highlight Current Day of Month on Calendar *****************
;
; Following algorithm used:
;
;  <linear index> = <day of month to highlight> + <day of week for 1st of month>
;  <cursor display row> = ( <linear index>/7 ) + 3
;  <cursor display col> = ( <remainder-1>*3 ) + ttwidth + 3
;
        movb    systime_day,r1          ;Get high order digit (HOD)
        cmpb    r1,#^x30                ;Digit 0?
        bneq    50$                     ;Branch if not
        movb    #^x20,systime_day       ;Change it to a blank for later
50$:    movb    systime_day+1,r0        ;Get LOD
        bicl    #^x30,r0                ;Convert to integer
        bicl    #^x30,r1                ;Convert to integer
        mulb3   r1,#10,r1               ;high order digit * 10
        addb    r0,r1                   ;+low order digit
                                        ;(yields highlight day as integer)


        addl    dow,r1                  ;add day of week offset, 
                                        ;yeilding <linear index>
        clrl    r2                      ;Prep. for ediv.
        clrq    r3                      ; .
        decl    r1                      ;Correct day of week offset
        ediv    #7,r1,r3,r4             ;Divide <linear index> by 7
        addb3   #^x33,r3,csr_row        ;Cursor Row is calculated
        decl    r4                      ;Remainder - 1
        mull    #3,r4                   ;horiz. index x 
                                        ;(display width for single day)
        addl    ttwidth,r4              ;Add pos offset to display region
        addl    #6,r4                   ;Add pos offset within display region
        moval   csr_col,outbuf+4        ;Setup descriptor so FAO moves literal
                                        ; in to terminal cursor control area
        cmpl    r4,#100                 ;r4 > 100?
        bgtr    60$                     ;branch if so
        incl    outbuf+4                ;If not shift right
60$:    movb    #^x30,csr_col           ;Initialize with a leading 0
        movl    r4,scratch              ;Save

        $fao_s  ctrstr=faobuf,-         ;Convert cursor location for esc. seq.
                outbuf=outbuf,-
                p1=scratch

        $qiow_s chan=ttkrnl,-           ;Relocate the cursor to point to
                func=#io$_writevblk,-   ;Current day of month and turn on
                p1=csr_ctl,-            ;highlighting
                p2=#ctlsize

        $qiow_s chan=ttkrnl,-           ;Display day of month
                func=#io$_writevblk,-
                p1=systime_day,-
                p2=#2

        $qiow_s chan=ttkrnl,-           ;Turn off highlighting
                func=#io$_writevblk,-
                p1=attrib_off,-
                p2=#3   

        $qiow_s chan=ttkrnl,-           ;Restore cursor to its position
                func=#io$_writevblk,-   ;before the calendar was displayed
                p1=restore_pos,-
                p2=#2

astexit: ret

;--
; The following code initializes the TSR by enabling the out-of-band
; key on the kernel mode channel, relocating pointers, and displaying
; an initialization message on the terminal.
;--
INITIALIZE:

; **** Initializes the AST level TSR code ****


        incl     init_flag

        $qiow_s  chan=ttkrnl,-                          ;Setup out of band key
                 func=#io$_setmode!io$m_outband,-
                 p1=@ast_vector,-
                 p2=#omask


10$:    moval   faobuf+8,faobuf+4                       ;Relocate descriptors
        moval   feb29+8,feb29+4                         ;   .
        moval   work_date+8,work_date+4                 ;   .
        moval   systime,systime_dsc+4                   ;   .
        moval   hdr1,display_array                      ;   .
        moval   hdr2,display_array+4                    ;   .
        moval   lin1,display_array+8                    ;   .
        moval   lin2,display_array+12                   ;   .
        moval   lin3,display_array+16                   ;   .
        moval   lin4,display_array+20                   ;   .
        moval   lin5,display_array+24                   ;   .
        moval   lin6,display_array+28                   ;   .
        moval   lin7,display_array+32                   ;   .
        moval   lnm_table+8,lnm_table+4                 ;   .
        moval   lnm_name+8,lnm_name+4                   ;   .
        moval   lnm_equiv+8,lnm_equiv+4                 ;   .

        $qiow_s chan=ttkrnl,-                           ;Display message
                func=#io$_writevblk!io$m_breakthru,-
                p1 = install_msg,-
                p2 = #install_size

        rsb

; **** The following code is not used by this calendar, but
;      serves as an example of how a TSR can remove itself,
;      and the memory the it resides in without attempting to 
;      execute in deleted address space.
;
;      It involves some special stack manipulation.
;
;       $dellnm_s tabnam=lnm_table,-    ;Delete the logical name
;                  lognam=lnm_name 
;
;       $dassgn_s chan = ttkrnl         ;Remove the kernel mode channel
;       movl    ast_vector,r0           ;Get the address of the TSR memory
;       movzwl  ast_memory_size,r1      ;Get the length of the memory block
;
;        ;The following line pushes two macro instructions on the stack
;       pushl   #^x045e04c0             ;    ADDL #4,SP  /  RET
;
;       movl    sp,r7                   ;Get stack pointer
;       pushl   r7                      ;Save on stack
;       jmp     g^exe$deap1             ;Deallocate the code,
;                                       ;and return onto the kernel mode
;                                       ;stack.  The instructions on the


;                                       ;stack will clean themselves off
;                                       ;of the stack, and return from the
;                                       ;AST routine.
;-----------------------------------------------------------

; **** AST routine data areas ****

hdr1:   .ascii  'MMM.  '                ;Calendar header
        .byte   27,^a'[',^a'1',^a'm'    ;Turns on highlight
        .ascii  'HH:MM AM'              ;Template for current time display
        .byte   27,^a'[',^a'm'          ;Turns off highlight
        .ascii  '  YYYY '               ;Raw Calendar display template

hdr2:   .ascii  'Su Mo Tu We Th Fr Sa ' ;2nd line of header
dda:                                    ;Day Display Array
lin1:   .ascii  'xx xx xx xx xx xx xx ' ;         "
lin2:   .ascii  'xx xx xx xx xx xx xx ' ;         "
lin3:   .ascii  'xx xx xx xx xx xx xx ' ;         "
lin4:   .ascii  'xx xx xx xx xx xx xx ' ;         "
lin5:   .ascii  'xx xx xx xx xx xx xx ' ;         "
lin6:   .ascii  'xx xx xx xx xx xx xx ' ;         "

                                ;Blank line to reset attrib 
lin7:   .byte 27,^a'[',^a'm',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

                                ;Vector for line by line output
display_array:   .long hdr1,hdr2,lin1,lin2,lin3,lin4,lin5,lin6,lin7     

amtext:         .ascii " am"    ;Text to initialize am/pm display field
ttwidth:        .blkl           ;Current terminal width - display compensation
ttcharbuf:      .blkl 3         ;Buffer to receive current terminal chars
faobuf:         .ascid '!ZB'    ;Control string for FAO
outbuf:         .long 3,col     ;Adjustable output descriptor for FAO

                                ;Look up table for month names
months:         .ascii "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"

                                ;Parallel table containing # of days in months
month_tbl:      .long   31,28,31,30,31,30,31,31,30,31,30,31

                                ;Used to check existance of FEB 29 for year.
feb29:          .ascid '29-FEB-xxxx'

                                ;Work Date field for intermediary calculations
work_date:      .ascid 'DD-MMM-YYYY'

work_quad1:     .blkq           ;Quadword time for intermediary date calcs
dow:            .blkl           ;Field to hold the Day of Week number
scratch:        .blkl           ;Work field
save_pos:       .byte 27,^a'7'  ;Control terminal to save cursor postion/attrib.
restore_pos:    .byte 27,^a'8'  ;Control terminal to restore cursor/attrib.
attrib_off:     .byte 27,^a'[',^a'm' ;Turn of attrib.

csr_ctl:        .byte 27,^a'['  ;Move cursor and turn on highlight


csr_row:        .ascii "0;"     
csr_col:        .byte ^x30,^x30,^x30,^a'H',27,^a'[',^a'1',^a';',^a'7',^a'm'
ctlsize = .-csr_ctl     

clreol:         .byte 27,^a'['  ;Move cursor, clear to EOL, and cancel highlight
  row:          .ascii "0;"
  col:          .byte ^x30,^x30,^x30,^a'H',27,^a'[',^a'0',^a'm'
                .byte 27,^a'[',^a'K',^x20,^x20,^x20
clreol_size = .-clreol

systime_dsc: .long 23,systime_dsc+8     ;Descriptor for time text buffer
systime:     .blkb 23                   ;Time text buffer

; Define named offsets

header_mo   = hdr1                      ;Offset to month (MMM) text in header
header_hhmm = hdr1+10                   ;Offset to hour/minute in header
header_ampm = hdr1+16                   ;Offset to AM/PM indicator
header_year = hdr1+23                   ;Offset to year  (YYYY)

systime_day  = systime                  ;Offset to day of month in sys-time
systime_mo   = systime+3                ;Offset to month of year
systime_year = systime+7                ;Offset to year
systime_hhmm = systime+12               ;Offset to time

screen_clear_sequence_132:              ;Clr. Screen and set width to 132 col.
                .byte 27,91,72,27,91,74,27,91,63,51,104
screen_clear_size_132 = .- screen_clear_sequence_132

screen_clear_sequence_80:               ;Clr. Screen and set width to 132 col.
                .byte 27,91,72,27,91,74,27,91,63,51,108
screen_clear_size_80 = .- screen_clear_sequence_80

remove_msg:     .byte 10,13             ;Removal message
                .ascii 'Removing Calendar from process'
                .byte 10,13
remove_size = .-remove_msg

install_msg:    .byte 10,13             ;Installation message
                .ascii 'TSR Activation key:    ^D - Displays time/calendar'
                .byte 10,10,13
install_size = .-install_msg

.blkb   20
init_flag:       .blkl                  ;One-shot initialization
ast_vector:      .blkl                  ;Address of relocated code
ast_memory_size: .blkl                  ;Size of relocated code
omask:           .long 0,<1@trap_key>   ;Out of band key mask
lnm_attributes:  .long <lnm$m_confine!- ;logical name flags
                        lnm$m_no_alias> 
lnm_table:       .ascid 'LNM$PROCESS_TABLE';Specify process private table
lnm_name:        .ascid '* CALENDAR [TSR]' ;Logical name
lnm_equiv:       .ascii 'resident at '  ;Parsable equivalence string
hexloc:          .ascii '00000000'      ;Location of p1 memory


                 .ascii ' ('            ;
hexlen:          .ascii '0000'          ;Size of p1 block
                 .ascii ' bytes).'      ;
lnm_equiv_len =  .-lnm_equiv            ;
                 .byte 10,13            ;
lnm_list:        .word 34,lnm$_string   ;Logical name item list
                 .long lnm_equiv,0,0    ;
descr:           .long 34,lnm_equiv     ;

code_size  = .-tsr_code_address         ;Calculates the size of the
                                        ;code that gets relocated

.end main
