Annotation of researchv10no/cmd/spitbol/oosint.s, revision 1.1.1.1

1.1       root        1: #
                      2: #      Operating System Interface to Berkeley VAX/UNIX
                      3: #                            for
                      4: #                     Macro SPITBOL V3.5
                      5: #      -----------------------------------------------
                      6: #
                      7: #              Copyright 1982
                      8: #              Dewar Information Systems Corporation
                      9: #              221 West Lake Street
                     10: #              Oak Park, Illinois 60302
                     11: #
                     12: #      this operating system interface, commonly referred to as osint,
                     13: #      provides the Macro SPITBOL compiler with a means to do all i/o
                     14: #      and other OS dependent activities. 
                     15: #
                     16: #      osint is composed of one medium sized assembly module, with
                     17: #      multiple entry points, and a collection of c functions. the
                     18: #      entire interface is not in c due to the compiler's use of
                     19: #      registers to pass parameters and other technicalities. all
                     20: #      entries, except for sbchk, have five letter names starting
                     21: #      with sys.
                     22: #
                     23: #      when spitbol first starts execution, control passes to function
                     24: #      main, just like in a normal c program. main processes any options
                     25: #      and does other initialization chores. after completing
                     26: #      initialization, main jumps to label sec04 to start
                     27: #      the compiler itself. from that point, the compiler makes calls
                     28: #      to sysxx routines to get service.
                     29: #
                     30: #      the c functions are called from this module to do most of the
                     31: #      hard and/or unix dependent work. an effort has been made to
                     32: #      do all the system calls from c functions. this goal has not
                     33: #      been entirely achieved.
                     34: #      
                     35: #
                     36: #      register masks
                     37: #
                     38:        .set    mr0,1
                     39:        .set    mr1,2
                     40:        .set    mr2,4
                     41:        .set    mr3,8
                     42:        .set    mr4,16
                     43:        .set    mr5,32
                     44:        .set    mr6,64
                     45:        .set    mr7,128
                     46:        .set    mr8,256
                     47:        .set    mr9,512
                     48:        .set    mr10,1024
                     49:        .set    mr11,2048
                     50: #
                     51: #      c functions assume that r0 -> r5 are scratch.  however, spitbol
                     52: #      uses r2, r3, and r5.  so, need to save these registers across
                     53: #      function calls.
                     54: #
                     55:        .set    mr235,mr2+mr3+mr5
                     56: #
                     57: #      mask for all registers used by compiler. necessary for dealing
                     58: #      with load modules.
                     59: #
                     60:        .set    cmpreg,mr2+mr3+mr5+mr6+mr7+mr8+mr9+mr10
                     61: #
                     62: #      miscellaneous equates
                     63: #
                     64:        .set    ch$lk,107       # upper case letter k
                     65:        .set    ch$mn,45        # dash (minus sign)
                     66:        .set    k,1024
                     67:        .set    kwords,k*4
                     68: #
                     69: #      internal spitbol blocks
                     70: #      -----------------------
                     71: #
                     72: #      these equates describe compiler control blocks used by osint.
                     73: #
                     74: #      chain of file control blocks
                     75: #
                     76:        .set    chtyp,0         # type word
                     77:        .set    chlen,4         # block length
                     78:        .set    chnxt,8         # -> next chblk
                     79:        .set    chfcb,12        # -> fcb
                     80:        .set    chsize,16       # size of chblk
                     81: #
                     82: #      icblk - integer block
                     83: #
                     84:        .set    ictyp,0         # type word
                     85:        .set    icval,4         # integer value
                     86: #
                     87: #      scblk - string block
                     88: #
                     89:        .set    sctyp,0         # type word
                     90:        .set    sclen,4         # string length
                     91:        .set    scstr,8         # start of string
                     92: #
                     93: #      interface control blocks
                     94: #      ------------------------
                     95: #
                     96: #      these control blocks are built by the interface to handle i/o.
                     97: #      for files other than standard input, standard output, and the
                     98: #      terminal, these control blocks reside in the compiler's 
                     99: #      dynamic area. this requires appropriate setting of the type
                    100: #      words to allow proper garbage collection.
                    101: #
                    102: #      blocks with type b$xnt contain non-relocatable addresses - that
                    103: #      is, no word may contain a pointer to another block in the
                    104: #      dynamic area.
                    105: #
                    106: #      blocks with type b$xrt contain relocatable addresses - that is
                    107: #      words may contain a pointer to another block in the dynamic area.
                    108: #
                    109: #      the basic structure is:
                    110: #
                    111: #      for each input or output associated file there is:
                    112: #
                    113: #              1 ioblk  containing all global information about
                    114: #                       the file:  filename, buffer block pointer,
                    115: #                       file descriptor number, flags
                    116: #
                    117: #              1 bfblk  containing the file buffer
                    118: #
                    119: #              1 or more fcblks  containing the access mode (line or
                    120: #                       raw), the record length, and a pointer to 
                    121: #                       the ioblk
                    122: #
                    123: #      the first INPUT() or OUTPUT() call for a file creates one block
                    124: #      of each type. subsequent calls to INPUT() or OUTPUT() for a 
                    125: #      previously associated file, may cause the creation of a new fcblk.
                    126: #      allowing multiple fcblks provides the program with different
                    127: #      ways of accessing the same file. for example, one type of access
                    128: #      can be a character at a time and another entire records.
                    129: #
                    130: #      the compiler keeps track of all active fcblks, and at times
                    131: #      like end-of-job provides the inteface with a chain of all fcblks.
                    132: #
                    133: #
                    134: #      bfblk - i/o buffer control block
                    135: #
                    136:        .set    bftyp,0         # type word - b$xnt
                    137:        .set    bflen,4         # block length
                    138:        .set    bfsiz,8         # buffer size in bytes
                    139:        .set    bfrem,12        # bytes remaining
                    140:        .set    bfoff,16        # offset to next remaining byte
                    141:        .set    bfsize,20       # end of fixed portion
                    142: #
                    143: #      fcblk - file control block
                    144: #
                    145:        .set    fctyp,0         # type word - b$xrt
                    146:        .set    fclen,4         # block length
                    147:        .set    fcrsz,8         # record size ( >0 line mode / <0 raw mode) 
                    148:        .set    fciob,12        # -> ioblk 
                    149:        .set    fcsize,16       # size of fcblk
                    150: #
                    151: #      ioblk - i/o control block
                    152: #
                    153:        .set    iotyp,0         # type word - b$xrt
                    154:        .set    iolen,4         # block length
                    155:        .set    iofnm,8         # -> filename scblk
                    156:        .set    iopid,12        # pid (if one end of pipe)
                    157:        .set    iobuf,16        # -> bfblk
                    158:        .set    iofdn,20        # file descriptor number
                    159:        .set    ioflg,24        # flags
                    160:        .set    iosize,28       # size of ioelt
                    161: #
                    162: #      defines that match "spitio.h" for flags in ioflg
                    163: #
                    164:        .set    IO_INP,1        # input associated
                    165:        .set    IO_OUP,2        # output associated
                    166:        .set    IO_APP,4        # output open for append
                    167:        .set    IO_OPN,8        # file is open
                    168:        .set    IO_EOF,16       # eof on input file
                    169:        .set    IO_ERR,32       # i/o error
                    170:        .set    IO_SYS,64       # this is an osint file
                    171:        .set    IO_WRC,128      # don't do buffering
                    172:        .set    IO_PIP,256      # this is one end of a pipe
                    173:        .set    IO_DED,512      # other end of pipe died
                    174:        .set    IO_ILL,1024     # i/o illegal according to sysfc
                    175: #
                    176: #      osint( argc,argv,environ ) is called just like the main
                    177: #      function of a c program.
                    178: #
                    179:        .globl  _main
                    180: _main: .word   0
                    181: #
                    182: #      normal start - process all command arguments.
                    183: #
                    184:        movl    4(ap),r4        # get number of options
                    185:        movl    r4,argc         #    and save
                    186:        movl    8(ap),r6        # -> option pointers
                    187:        movl    r6,argv         #    and save
                    188: #
                    189: #      if this is a restart from an load module, go handle.
                    190: #
                    191:        tstl    lmodstk         # if load module stack != 0 then
                    192:        jnequ   rstart          #    go handle
                    193: #
                    194:        tstl    (r6)+           # program name not interesting
                    195:        brb     gtcont          # process other args
                    196: gtarg: movl    (r6)+,r0        # -> option text
                    197:        cmpb    $ch$mn,(r0)     # if no leading - then
                    198:        bnequ   gtinp           #    treat as input filename
                    199:        incl    r0              # bump over -
                    200: 1:     movb    (r0)+,curopt+1  # set option character in table
                    201:        movl    $opttbl,r1      # -> option table
                    202: 2:     cmpl    curopt,(r1)     # if we have found it then
                    203:        beqlu   3f              #    process it
                    204:        addl2   $optsiz,r1      # -> next table entry
                    205:        brb     2b              # loop until found
                    206: 3:     movl    optrtn(r1),r11  # -> option routine
                    207:        jsb     (r11)           # call option routine
                    208: 4:     tstb    (r0)            # if char is binary zeros then
                    209:        beqlu   gtcont          #    done with this arg
                    210:        cmpb    $040,(r0)       # if next char is blank then
                    211:        bnequ   5f
                    212:        incl    r0              #    ignore it
                    213:        brb     4b              #    and check next char
                    214: 5:     cmpb    $ch$mn,(r0)     # if next char is not - then
                    215:        bnequ   1b              #    treat as option character
                    216:        incl    r0              # else skip over -
                    217:        brb     1b              #     and treat next char as option
                    218: gtinp: jsb     optinp          # process input filename(s)
                    219: gtcont:        sobgtr  r4,gtarg        # loop thru all options
                    220: #
                    221: #      switch to proper input file
                    222: #
                    223:        pushl   inpptr
                    224:        pushl   inpcnt
                    225:        calls   $2,_swcinp
                    226: #
                    227: #      call to do initial switch of output files.
                    228: #
                    229:        pushl   oupptr
                    230:        calls   $1,_swcoup
                    231: #
                    232: #      see if standard output is tty or not.
                    233: #
                    234:        pushl   $1              # file descriptor 1
                    235:        calls   $1,_testty      # call to check i/o chcaracteristics
                    236:        tstl    r0              # if r0 not 0 then
                    237:        bnequ   0f              #    not a tty
                    238:        clrl    lnsppg          # reset # lines per page
                    239:        bisl2   $prtich,sptflg  # else tell compiler
                    240: 0:
                    241: #
                    242: #      set signals for execution
                    243: #
                    244:        .globl  _setsigs
                    245:        calls   $0,_setsigs     # trap overflow signals
                    246: #
                    247: #      allocate initial dynamic memory
                    248: #
                    249:        mull3   meminc,$4,meminb# convert meminc to bytes
                    250:        pushl   meminb          # memory request increment
                    251:        calls   $1,_sbrk        # call to system call
                    252:        movl    r0,basmem       # save base of memory
                    253:        addl3   r0,meminb,topmem# computer top of memory
                    254:        mull3   datwds,$4,r1    # convert max data words to bytes
                    255:        addl3   r0,r1,maxmem    # computer top of memory
                    256: 0:     clrl    (r0)+           # clear initial allocation
                    257:        cmpl    r0,topmem       # loop until all cleared
                    258:        blssu   0b
                    259: #
                    260: #      set up lowest legal sp value, so that stack overflow can be detected,
                    261: #
                    262:        mull3   $4,stksiz,r0    # convert words to bytes
                    263:        subl3   r0,sp,lowsp     #    and compute lowest sp
                    264:        movl    sp,initsp       # save initial sp
                    265: #
                    266: #      clear registers, set dynamic area pointers, and jump off
                    267: #      to compiler
                    268: #
                    269:        clrl    r2
                    270:        clrl    r3
                    271:        clrl    r4
                    272:        clrl    r5
                    273:        clrl    r6
                    274:        clrl    r7
                    275:        clrl    r8
                    276:        movl    basmem,r9
                    277:        subl3   $4,topmem,r10
                    278:        jmp     sec04
                    279: #
                    280: #      here to restart program after EXIT() call. this means we are now
                    281: #      executing from an a.out file created by the interface.
                    282: #
                    283: rstart:
                    284: #
                    285: #      before restoring stack, set up values for proper checking of
                    286: #      stack overflow. (initial sp here will most probably differ
                    287: #      from initial sp when compile was done.)
                    288: #
                    289:        mull3   $4,stksiz,r0    # convert words to bytes
                    290:        subl3   r0,sp,lowsp     #    and compute lowest sp
                    291:        movl    sp,initsp       # save initial sp
                    292:        jsb     streloc         # relocate pointers into stack
                    293: #
                    294: #      restore stack from tscblk.
                    295: #
                    296:        movl    lmodstk,r0      # -> bottom word of stack
                    297:        movab   tscblk+scstr,r1 # -> top word of stack
                    298: 0:     movl    -(r0),-(sp)     # relocate word of stack
                    299:        cmpl    r0,r1           # if not at end of relocation then
                    300:        bgtru   0b              #    loop back
                    301: #
                    302: #      if restarting, we can always access the command line arguments
                    303: #
                    304:        movl    $1,cmdcnt
                    305: #
                    306: #      the system break will not be what it should, so reset it
                    307: #
                    308:        pushl   topmem
                    309:        calls   $1,_brk
                    310: #
                    311: #      reset signals to what they should be.
                    312: #
                    313:        calls   $0,_setsigs
                    314: #
                    315: #      forget about files open during compilation -
                    316: #
                    317:        clrl    inpptr          # no input files
                    318:        clrl    inpcnt          #    so count is 0 too
                    319:        clrl    oupptr          # no output file
                    320:        clrl    errfdn          # no error file
                    321: #
                    322: #      reset standard input buffer
                    323: #
                    324:        clrl    inpbf+bfrem     # no remaining chars
                    325:        clrl    inpbf+bfoff     # offset to next char
                    326: #
                    327: #      restore compiler's registers and off we go.
                    328: #
                    329:        popr    $cmpreg         # restore compiler's registers
                    330:        addl2   $8,(sp)
                    331:        rsb
                    332: #
                    333: #      sbchk is called by the compiler to check for stack overflow.
                    334: #
                    335:        .globl  sbchk
                    336: sbchk: cmpl    sp,lowsp        # if sp is ok then
                    337:        blssu   0f
                    338:        rsb                     #    return
                    339: 0:     tstl    (sp)+           # else pop stack
                    340:        jmp     sec05           #    and go to stack overflow section
                    341: #
                    342: #      unsupported entries that simply return.
                    343: #
                    344:        .globl  sysdc
                    345: sysdc:
                    346:        .globl  sysdm
                    347: sysdm:
                    348:        .globl  systt
                    349: systt:
                    350:        .globl  sysul
                    351: sysul:
                    352:        rsb
                    353: #
                    354: #      unsupported that take error returns
                    355: #
                    356:        .globl  sysex
                    357: sysex:
                    358:        .globl  sysld
                    359: sysld:
                    360:        pushr   $mr235          # save ye registers
                    361:        jbr     erxit1
                    362: #
                    363: #      sysax - after execution call
                    364: #
                    365: #      sysax is called immediately after execution, so that the interface
                    366: #      can do any cleanup. here, the standard output file is switched, if
                    367: #      necessary back to the listing file.
                    368: #
                    369:        .globl  sysax
                    370: sysax:
                    371:        pushr   $mr235
                    372:        pushl   oupptr
                    373:        calls   $1,_swcoup
                    374:        popr    $mr235
                    375:        rsb
                    376: #
                    377: #      sysbx - before execution call
                    378: #
                    379: #      sysbx is called after compilation and before execution begins.
                    380: #      sysbx allows the inteface to do any cleanup. here, the standard
                    381: #      listing file is switched to the standard output file.
                    382: #
                    383:        .globl  sysbx
                    384: sysbx:
                    385:        pushr   $mr235
                    386:        pushl   oupptr
                    387:        calls   $1,_swcoup
                    388:        popr    $mr235
                    389:        rsb
                    390: #
                    391: #      sysdt - get current date
                    392: #
                    393: #      return both date and time
                    394: #
                    395: #      jsb     sysdt                   # call to get date
                    396: #      (r10)                           # -> scblk
                    397: #
                    398:        .globl  sysdt
                    399: sysdt:
                    400:        pushr   $mr235
                    401:        movl    $tscblk,r10
                    402:        movl    $17,sclen(r10)          # dd/mm/yy hh.mm.ss
                    403:        pushl   $tscblk+scstr
                    404:        calls   $1,_getdate
                    405:        popr    $mr235
                    406:        rsb
                    407: #
                    408: #      sysef - eject file
                    409: #
                    410:        .globl  sysef
                    411: sysef:
                    412:        pushr   $mr235
                    413:        pushl   fciob(r6)       # -> ioblk
                    414:        calls   $1,_osopen      # call to do open
                    415:        tstl    r0              # if open error then
                    416:        jnequ   erxit1          #    take error exit
                    417:        pushl   $ffscb          # -> ff scblk
                    418:        pushl   fciob(r6)       # -> ioblk
                    419:        pushl   ffscb+sclen     # record length
                    420:        mnegl   fcrsz(r6),-(sp) # i/o mode - raw or line
                    421:        calls   $4,_oswrite     # call to do write
                    422:        tstl    r0              # if output error then
                    423:        jneq    erxit3          #    signal failure
                    424:        popr    $mr235
                    425:        addl2   $12,(sp)
                    426:        rsb
                    427: #
                    428: #      sysej - end of job
                    429: #
                    430:        .globl  sysej
                    431: sysej:
                    432:        movl    r10,_rzfcb      # copy head of fcb chain
                    433:        beqlu   1f              # if empty then nothing to close
                    434: 0:     movl    chfcb(r10),r1   # -> fcb
                    435:        pushl   fciob(r1)       # -> ioblk
                    436:        calls   $1,_osclose     # call to do close
                    437:        movl    chnxt(r10),r10  # -> next on chain
                    438:        bnequ   0b              #    and loop back for more
                    439: 1:     pushl   r7              # return &code
                    440:        calls   $1,__exit
                    441: #
                    442: #      sysem - get error message text
                    443: #
                    444:        .globl  sysem
                    445: sysem:
                    446:        pushr   $mr235
                    447:        movl    $tscblk,r9      # -> temp scblk
                    448:        clrl    sclen(r9)       # default error text is null string
                    449:        tstl    errfdn          # if error fd exists then
                    450:        bnequ   0f              #    skip open
                    451:        calls   $0,_openerr     # else open error text file
                    452:        movl    r0,errfdn       #    and save fd
                    453: 0:     tstl    errfdn          # if no error text file then
                    454:        blss    emxit           #    return null string
                    455:        decl    r6              # errors start at 1
                    456:        blss    emxit           #    but don't have error 0
                    457:        mull2   $49,r6          # compute byte offset of error text
                    458:        pushl   $0              # whence
                    459:        pushl   r6              # offset
                    460:        pushl   errfdn          # file descriptor number
                    461:        calls   $3,_lseek       # call to do seek
                    462:        tstl    r0              # if lseek fails then
                    463:        blss    emxit           #    return null string
                    464:        pushl   $48             # error text length w/out nl
                    465:        pushl   $tscblk+8       # buffer address
                    466:        pushl   errfdn          # file descriptor number
                    467:        calls   $3,_read        # call to do read
                    468:        tstl    r0              # if read failed then
                    469:        blss    emxit           #    return null string
                    470: 1:     cmpb    $' ,tscblk+7(r0)# if last character is
                    471:        bneq    2f              #   nonblank, return length
                    472:        sobgeq  r0,1b           # otherwise discard the blank, try again
                    473: 2:     movl    r0,sclen(r9)    # set actual length
                    474: emxit:
                    475:        popr    $mr235
                    476:        rsb                     # return
                    477: #
                    478: #      sysen - endfile
                    479: #
                    480:        .globl  sysen
                    481: sysen:
                    482:        pushr   $mr235
                    483:        movl    r$fcb,_rzfcb    # copy fcb chain head
                    484:        pushl   fciob(r6)       # -> ioblk
                    485:        calls   $1,_osclose     # call to do close
                    486:        popr    $mr235
                    487:        addl2   $12,(sp)
                    488:        rsb
                    489: #
                    490: #      sysej - eject standard output
                    491: #
                    492:        .globl  sysep
                    493: sysep:
                    494:        pushr   $mr235
                    495:        pushl   $1              # 1 character
                    496:        pushl   $ffstr          # -> ff
                    497:        pushl   $1              # fd 1
                    498:        calls   $3,_write       # call to do write
                    499:        popr    $mr235
                    500:        rsb
                    501: #
                    502: #      sysfc
                    503: #
                    504:        .globl  sysfc
                    505: sysfc:
                    506:        movl    (sp)+,(sp)      # remove stacked scblk
                    507:        pushr   $mr235
                    508:        tstl    sclen(r10)      # if null filearg1 then
                    509:        jeqlu   erxit1          #    error
                    510: #
                    511: #      get length of filename and scan off options.
                    512: #
                    513:        movl    r9,-(sp)        # -> filename scblk
                    514:        calls   $1,_lenfnm      # call to get filename length
                    515:        movl    r0,lenfname     # save length for later use
                    516:        jlss    erxit1          # length must not be negative
                    517:        movl    r9,-(sp)        # -> filename scblk
                    518:        movl    $tioblk,-(sp)   # -> temporary ioblk
                    519:        movl    r7,-(sp)        # input/output association flag
                    520:        calls   $3,_sioarg      # call to scan i/o args
                    521:        tstl    r0              # if error in args then
                    522:        jlss    erxit1          #    take error return
                    523: #
                    524: #      check for consistency of calls. cannot have both input
                    525: #      and output to same channel. if this happens, though,
                    526: #      set flag and let sysio take proper error exit.
                    527: #
                    528:        tstl    r6              # if no previous fcblk then
                    529:        beqlu   0f              #    skip
                    530:        movl    fciob(r6),r0    # -> ioblk
                    531:        movl    ioflg(r0),r0    # get previous flags
                    532:        mcoml   $IO_INP+IO_OUP,r1 # get mask for bicl
                    533:        bicl2   r1,r0           # remove all bits but INP&OUP
                    534:        bitl    tioblk+ioflg,r0 # if bits are not same then
                    535:        bnequ   0f
                    536:        bisl2   $IO_ILL,tioblk+ioflg    # then set error flag
                    537: 0:
                    538: #
                    539: #      handle null filenames here - must either have a previous
                    540: #      fcblk or specify -f arg.
                    541: #
                    542:        tstl    lenfname        # if non-null filename then
                    543:        bgtr    fcfnam          #    go handle below
                    544:        bitl    $IO_OPN,tioblk+ioflg
                    545:        bnequ   fcfarf          # if -f specified then merge w/non-null
                    546:        tstl    r6              # if no previous fcblk then
                    547:        jeqlu   erxit1          #    error
                    548:        clrl    r6              # assume that no new fcblk needed
                    549:        clrl    ioblkptr        # no ioblk ptr to stuff
                    550:        tstl    tioblk          # if however i/o args indicate one
                    551:        jeqlu   fcxit
                    552:        movl    fciob(r6),ioblkptr
                    553:        movl    $fcsize,r6      #    allocate one
                    554:        jbr     fcxit
                    555: #
                    556: #      handle real filenames and null filenames with -f arg here.
                    557: #      note that they're mutually exclusive.
                    558: #
                    559: fcfnam:        bitl    $IO_OPN,tioblk+ioflg
                    560:        jnequ   erxit1          # can't have -f arg too
                    561: fcfarf:        tstl    r6              # if previous fcblk passed then
                    562:        jnequ   erxit1          #    error
                    563:        clrl    ioblkptr
                    564:        addl3   $bfsize+3,tioblk+iopid,r6
                    565:        bicl2   $3,r6
                    566:        movl    r6,bfblksiz
                    567:        addl2   $fcsize+iosize,r6
                    568:        movl    $1,tioblk       # set newfcb flag
                    569: #
                    570: fcxit: clrl    r10             # no private fcblk
                    571:        clrl    r8              # xrblk please
                    572:        popr    $mr235
                    573:        addl2   $4,(sp)
                    574:        rsb
                    575: #
                    576: #      syshs
                    577: #
                    578:        .globl  syshs
                    579: syshs:
                    580:        pushr   $mr235
                    581:        cmpl    $b$icl,(r6)     # if arg1 not integer then
                    582:        jnequ   9f              #    return host string
                    583:        tstl    icval(r6)       # if integer 0 then
                    584:        beqlu   1f              #    return -u argument
                    585:        cmpl    $1,icval(r6)    # if integer 1 then
                    586:        beqlu   2f              #    do system call
                    587:        cmpl    $2,icval(r6)    # if integer 2 then
                    588:        jeqlu   3f              #    return command arg
                    589:        cmpl    $3,icval(r6)    # if integer 3 then
                    590:        jeqlu   4f              #    return number of 1st #! arg
                    591:        cmpl    $4,icval(r6)    # if integer 4 then
                    592:        jeqlu   5f              #    return value of environment variable
                    593:        jbr     erxit1          # else arg error
                    594: #
                    595: 1:     tstl    uarg            # if uarg is 0 then
                    596:        jeqlu   erxit4          #    return null string
                    597:        pushl   tscblk          # push scblk string length
                    598:        pushl   $tscblk         # -> temp scblk
                    599:        clrl    -(sp)           # ending character is 0
                    600:        pushl   uarg            # -> -u argument
                    601:        calls   $4,_cpys2sc     # copy string to scblk
                    602:        movab   tscblk,r10      # -> temp scblk
                    603:        jbr     erxit3          # return
                    604: #
                    605: 2:     cmpl    $b$scl,(r10)    # if 2nd arg not string then
                    606:        jnequ   erxit1          #    return error
                    607:        tstl    sclen(r10)      # if null string then
                    608:        jeqlu   erxit4          #    return null string
                    609:        pushl   r10             # -> command string
                    610:        calls   $1,_dosys       # call to do system call
                    611:        jbr     erxit4          # return null string
                    612: #
                    613: 3:     cmpl    $b$icl,(r10)    # if 2nd arg not integer then
                    614:        jnequ   erxit1          #    return error
                    615:        movl    tscblk,tscblk+sclen     # set max length of scblk
                    616:        pushab  tscblk          # push -> tscblk
                    617:        pushl   argv            # push -> pointers
                    618:        pushl   argc            # push number of args
                    619:        pushl   icval(r10)      # arg requested
                    620:        calls   $4,_arg2scb     # call to do real move
                    621:        tstl    r0              # if out of range then
                    622:        jlss    erxit6          #    fail
                    623:        jeqlu   erxit4          #    (if 0) return null string
                    624:        movab   tscblk,r10      # -> tscblk
                    625:        jbr     erxit3          # return
                    626: #
                    627: 4:     tstl    cmdcnt          # if not invoked by #! then
                    628:        jeqlu   erxit6          #    fail
                    629:        movab   temp1,r9        # -> temp icblk
                    630:        movl    $b$icl,(r9)     # set integer block
                    631:        movl    cmdcnt,icval(r9)# set value
                    632:        jbr     erxit5          # return result
                    633: #
                    634: 5:     cmpl    $b$scl,(r10)    # if 2nd arg not string then
                    635:        jnequ   erxit1          #    return error
                    636:        tstl    sclen(r10)      # if null string then
                    637:        jeqlu   erxit1          #    return error
                    638:        movl    tscblk,tscblk+sclen     # set max length of scblk
                    639:        pushab  tscblk          # push -> tscblk
                    640:        pushl   r10             # -> environment variable requested
                    641:        calls   $2,_rdenv       # fetch the environment variable
                    642:        tstl    r0              # if it couldn't be found
                    643:        jlss    erxit6          #    fail
                    644:        movab   tscblk,r10      # else return tscblk
                    645:        jbr     erxit3
                    646: #
                    647: 9:     pushl   hststr          # push length of host string
                    648:        pushab  hststr          # push -> host string scblk
                    649:        calls   $2,_gethost     # call to get host string
                    650:        tstl    hststr+sclen    # if null host string then
                    651:        jeqlu   erxit4          #    return null string
                    652:        movl    $hststr,r10     # -> host string
                    653:        jbr     erxit3          # return
                    654: #
                    655: #      sysid - return system id
                    656: #
                    657:        .globl  sysid
                    658: sysid:
                    659:        movl    $id1,r9
                    660:        movl    $id2,r10
                    661:        rsb
                    662: #
                    663: #      sysil - get input record length
                    664: #
                    665:        .globl  sysil
                    666: sysil:
                    667:        movl    fcrsz(r6),r6
                    668:        bgtr    0f
                    669:        mnegl   r6,r6
                    670: 0:
                    671:        rsb
                    672: #
                    673: #      sysin - read input record
                    674: #
                    675:        .globl  sysin
                    676: sysin:
                    677:        pushr   $mr235
                    678:        pushl   fciob(r6)       # -> ioblk
                    679:        calls   $1,_osopen      # call to open file
                    680:        tstl    r0              # if open unsuccessful then
                    681:        jnequ   erxit3          #    take error exit
                    682:        pushl   r9              # -> scblk
                    683:        pushl   fciob(r6)       # -> ioblk
                    684:        pushl   fcrsz(r6)       # push record length
                    685:        bgtr    0f
                    686:        mnegl   (sp),(sp)       # if negative then make it positive
                    687: 0:     pushl   fcrsz(r6)       # i/o mode - raw or line
                    688:        calls   $4,_osread      # call to do read
                    689:        cmpl    r0,$-1          # check for eof or input error
                    690:        jeql    erxit1          #   take eof exit
                    691:        jlss    erxit2          #   take error exit
                    692:        movl    r0,sclen(r9)    # set record length
                    693:        popr    $mr235
                    694:        addl2   $12,(sp)
                    695:        rsb
                    696: #
                    697: #      sysio
                    698: #
                    699:        .globl  sysio
                    700: sysio:
                    701:        pushr   $mr235
                    702:        bitl    $IO_ILL,tioblk+ioflg
                    703:        jnequ   erxit2          # if illegal then take error exit
                    704:        movl    r6,fcblkptr     # copy fcblk pointer for exit
                    705: #
                    706: #      fill in fcblk.
                    707: #
                    708:        tstl    tioblk+iotyp    # if no new fcb to build then
                    709:        jeqlu   iodon           #    done
                    710:        movl    $fcsize,fclen(r6)
                    711:        movl    tioblk+iolen,fcrsz(r6)
                    712:        movl    ioblkptr,fciob(r6)
                    713:        jnequ   iodon
                    714:        movab   fcsize(r6),fciob(r6)
                    715: #
                    716: #      fill in ioblk.
                    717: #
                    718:        movab   fcsize(r6),r6   # -> ioblk
                    719:        movl    $b$xrt,(r6)
                    720:        movl    $iosize,iolen(r6)
                    721:        movl    r9,iofnm(r6)
                    722:        clrl    iopid(r6)
                    723:        movab   iosize(r6),iobuf(r6)
                    724:        movl    tioblk+iofdn,iofdn(r6)
                    725:        movl    tioblk+ioflg,ioflg(r6)
                    726: #
                    727: #      if -f0 or -f1 specified then
                    728: #
                    729: #              for -f0 ensure that buffer is same as osint's
                    730: #
                    731: #              for -f1 no buffering should be done
                    732: #
                    733:        bitl    $IO_SYS,ioflg(r6)
                    734:        beqlu   9f
                    735:        cmpl    $1,iofdn(r6)
                    736:        blssu   9f
                    737:        beqlu   1f
                    738:        movl    $inpbf,iobuf(r6)
                    739:        jbr     9f
                    740: 1:     clrl    iobuf(r6)
                    741:        bisl2   $IO_WRC,ioflg(r6)
                    742: 9:
                    743: #
                    744: #      fill in bfblk
                    745: #
                    746:        movab   iosize(r6),r6   # -> bfblk
                    747:        movl    $b$xnt,(r6)
                    748:        movl    bfblksiz,bflen(r6)
                    749:        movl    tioblk+iopid,bfsiz(r6)
                    750:        clrl    bfrem(r6)
                    751:        clrl    bfoff(r6)
                    752: #
                    753: #      try to open the file
                    754: #
                    755:        movl    fcblkptr,r0
                    756:        pushl   fciob(r0)
                    757:        calls   $1,_osopen
                    758:        tstl    r0
                    759:        jneq    erxit2          # if open failed, indicate error
                    760: #
                    761: iodon: movl    fcblkptr,r10
                    762:        clrl    r8
                    763:        popr    $mr235
                    764:        addl2   $8,(sp)
                    765:        rsb
                    766: #
                    767: #      sysmm - get more memory
                    768: #
                    769:        .globl  sysmm
                    770: sysmm:
                    771:        cmpl    topmem,maxmem   # if already at top of memory then
                    772:        blssu   0f
                    773:        clrl    r9              #    no more to be had
                    774:        rsb
                    775: 0:                             # else {alloc some more}
                    776:        pushr   $mr235
                    777:        pushl   meminb          # size in bytes of memory request
                    778:        calls   $1,_sbrk        # call to get memory
                    779:        popr    $mr235
                    780:        tstl    r0              # if memory obtained then
                    781:        blss    1f
                    782:        addl2   meminb,topmem   #    adjust current top
                    783:        movl    meminc,r9       #    set number of words in block
                    784:        rsb                     #    return
                    785: 1:     clrl    r9              # else nothing to get
                    786:        rsb
                    787: #
                    788: #      sysmx - get maximum size of created objects
                    789: #
                    790:        .globl  sysmx
                    791: sysmx:
                    792:        mull3   $4,maxsiz,r6
                    793:        rsb
                    794: #
                    795: #      sysou - output record
                    796: #
                    797:        .globl  sysou
                    798: sysou:
                    799:        pushr   $mr235
                    800:        pushl   fciob(r6)       # -> ioblk
                    801:        calls   $1,_osopen      # call to do open
                    802:        tstl    r0              # if open error then
                    803:        jnequ   erxit1          #    take error exit
                    804:        pushl   r9              # -> scblk
                    805:        pushl   fciob(r6)       # -> ioblk
                    806:        pushl   sclen(r9)       # record length
                    807:        pushl   fcrsz(r6)       # i/o mode - raw or line
                    808:        calls   $4,_oswrite     # call to do write
                    809:        tstl    r0              # if output error,
                    810:        jneq    erxit2          #    take error exit
                    811:        popr    $mr235
                    812:        addl2   $8,(sp)
                    813:        rsb
                    814: #
                    815: #      syspi - print on interactive channel (terminal)
                    816: #
                    817:        .globl  syspi
                    818: syspi:
                    819:        movl    $ttyiob,r11
                    820:        jbr     piprt
                    821: #
                    822: #      syspp - return print parameters
                    823: #
                    824:        .globl  syspp
                    825: syspp:
                    826:        movl    pagwid,r6
                    827:        movl    lnsppg,r7
                    828:        movl    sptflg,r8
                    829:        movl    defcas,kvcas
                    830:        rsb
                    831: #
                    832: #      syspr - print on standard output
                    833: #
                    834:        .globl  syspr
                    835: syspr:
                    836:        movl    $oupiob,r11
                    837: #
                    838: #      handle both syspi and syspr here.
                    839: #
                    840: piprt:
                    841:        pushr   $mr235
                    842:        bisl2   $IO_WRC,ioflg(r11) # briefly set no buffering
                    843:        pushl   r9              # -> scblk
                    844:        pushl   r11             # -> ioblk
                    845:        pushl   r6              # number characters
                    846:        pushl   $1              # line mode
                    847:        calls   $4,_oswrite     # call to do write
                    848:        bicl2   $IO_WRC,ioflg(r11) # back to buffering
                    849:        tstl    r0              # if output error then
                    850:        jneq    erxit1          #    indicate error return
                    851:        popr    $mr235
                    852:        addl2   $4,(sp)
                    853:        rsb
                    854: #
                    855: #      sysrd - read from standard input
                    856: #
                    857:        .globl  sysrd
                    858: sysrd:
                    859:        pushr   $mr235
                    860:        movl    $inpiob,ioblkptr
                    861: #
                    862: #      handle both sysrd and sysri here.
                    863: #
                    864: rdmrg:
                    865:        pushl   r9              # -> scblk
                    866:        pushl   ioblkptr        # -> ioblk
                    867:        pushl   r8              # read length
                    868:        pushl   r8              # line mode
                    869:        calls   $4,_osread      # call to do read
                    870:        cmpl    r0,$-1          # check for eof or input error
                    871:        jeql    rdeof           #    take eof exit
                    872:        jlss    erxit1          #    take error exit
                    873:        movl    r0,sclen(r9)    # set read length
                    874: #
                    875: #      check for 1st record of standard input coming from a file specified
                    876: #      on the command line. if all of these conditions are true, allow
                    877: #      the program to access any arguments following the file name.
                    878: #
                    879:        tstl    rdrec1          # if already ready record 1 then
                    880:        bnequ   rdskp           #    skip
                    881:        cmpl    $inpiob,ioblkptr
                    882:        bnequ   rdskp           # if sysri entry then skip
                    883:        incl    rdrec1          # indicate read 1st record from std input
                    884:        tstl    inpptr          # if not file from command line then
                    885:        beqlu   rdskp           #    skip
                    886:        cmpb    $'#,scstr(r9)   # if 1st char not # then
                    887:        bnequ   rdskp           #    skip
                    888:        cmpb    $'!,scstr+1(r9) # if 2nd char not ! then
                    889:        bnequ   rdskp           #    skip
                    890:        subl3   inpcnt,argc,cmdcnt
                    891:        incl    cmdcnt          # compute # args after filename
                    892:        movl    $1,inpcnt       # reset input count
                    893:        brb     rdmrg           # ignore 1st record and try again
                    894: rdskp:
                    895:        popr    $mr235
                    896:        addl2   $4,(sp)
                    897:        rsb
                    898: #
                    899: #      come here to handle eof for both sysrd and sysri. if eof
                    900: #      is for sysrd, standard input, switch to next input file
                    901: #      if one exists.
                    902: #
                    903: rdeof: movl    ioblkptr,r4     # -> ioblk
                    904:        tstl    iofdn(r4)       # if not file descriptor 0 then
                    905:        jnequ   erxit1          #    real eof
                    906:        pushl   inpptr          # push -> array of pointers
                    907:        pushl   inpcnt          # push size of areray
                    908:        calls   $2,_swcinp      # call to switch input files
                    909:        tstl    r0              # if more to read then
                    910:        jeqlu   rdmrg           #    read it
                    911:        jmp     erxit1          # else signal eof
                    912: #
                    913: #      sysri - read from interactive channel (terminal)
                    914: #
                    915:        .globl  sysri
                    916: sysri:
                    917:        pushr   $mr235
                    918:        movl    $ttyiob,ioblkptr
                    919:        jbr     rdmrg
                    920: #
                    921: #      sysrw - rewind file
                    922: #
                    923:        .globl  sysrw
                    924: sysrw:
                    925:        pushr   $mr235
                    926:        pushl   fciob(r6)       # -> ioblk
                    927:        calls   $1,_osopen      # call to do open
                    928:        tstl    r0              # if open error then
                    929:        jnequ   erxit1          #    take error exit
                    930:        movl    fciob(r6),r1    # -> ioblk
                    931:        bitl    $IO_PIP,ioflg(r1)
                    932:        jnequ   erxit2          # if pipe then rewind not allowed
                    933:        cmpl    iofdn(r1),$2    # if fd < 2 then
                    934:        jlssu   erxit2          #    rewind not allowed
                    935:        pushl   $0              # whence
                    936:        pushl   $0              # offset
                    937:        pushl   fciob(r6)       # -> ioblk
                    938:        calls   $3,_doset       # call to do set
                    939:        popr    $mr235
                    940:        addl2   $12,(sp)
                    941:        rsb
                    942: #
                    943: #      sysst - set file pointer
                    944: #
                    945:        .globl  sysst
                    946: sysst:
                    947:        pushr   $mr235
                    948:        pushl   fciob(r6)       # -> ioblk
                    949:        calls   $1,_osopen      # call to do open
                    950:        tstl    r0              # if file open error then
                    951:        jnequ   erxit3          #    return error
                    952: #
                    953:        movl    fciob(r6),r1    # -> ioblk
                    954:        bitl    $IO_PIP,ioflg(r1)
                    955:        jnequ   erxit4          # if pipe then set not allowed
                    956:        cmpl    iofdn(r1),$2    # if fd < 2 then
                    957:        jlssu   erxit4          #    set not allowed
                    958: #
                    959:        cmpl    $b$icl,(r7)     # if already integer then
                    960:        bnequ   0f
                    961:        movl    icval(r7),temp1 #    grab value
                    962:        brb     1f
                    963: 0:     cmpl    $b$scl,(r7)     # else if not a string then
                    964:        jnequ   erxit1          #    error
                    965:        clrl    temp3           # clear scnint character count
                    966:        pushl   $temp3          # -> temp3
                    967:        pushl   sclen(r7)       # string length
                    968:        pushab  scstr(r7)       # -> string
                    969:        calls   $3,_scnint      # call to scan integer
                    970:        movl    r0,temp1        # and save
                    971: 1:
                    972: #
                    973:        cmpl    $b$icl,(r8)     # if already integer then
                    974:        bnequ   0f
                    975:        movl    icval(r8),temp2 #    grab value
                    976:        brb     1f
                    977: 0:     cmpl    $b$scl,(r8)     # else if not a string then
                    978:        jnequ   erxit1          #    error
                    979:        clrl    temp3           # clear scnint character count
                    980:        pushl   $temp3          # -> temp3
                    981:        pushl   sclen(r8)       # string length
                    982:        pushab  scstr(r8)       # -> string
                    983:        calls   $3,_scnint      # call to scan integer
                    984:        movl    r0,temp2        # and save
                    985: 1:
                    986: #
                    987:        pushl   temp2           # whence
                    988:        pushl   temp1           # offset
                    989:        pushl   fciob(r6)       # -> ioblk
                    990:        calls   $3,_doset       # call to do set
                    991:        popr    $mr235
                    992:        addl2   $20,(sp)
                    993:        rsb
                    994: #
                    995: #      systm - get execution time so far
                    996: #
                    997:        .globl  systm
                    998: systm:
                    999:        pushr   $mr2+mr3
                   1000:        movl    $tscblk+8,-(sp) # -> times buffer
                   1001:        calls   $1,_times       # call to do times
                   1002:        movl    tscblk+8,r5     # get user time in 60ths
                   1003:        mull2   $100,r5         #    mulitply by 100 to get 6000ths
                   1004:        divl2   $6,r5           #    divide by 6 to get 1000ths
                   1005:        popr    $mr2+mr3
                   1006:        rsb
                   1007: #
                   1008: #      sysxi - exit from executing program
                   1009: #
                   1010:        .globl  sysxi
                   1011: sysxi:
                   1012:        tstl    r10             # if 0 instead of scblk then
                   1013:        jeqlu   xilmod          #    try to write load module 
                   1014:        pushr   $mr235
                   1015:        cmpl    $b$scl,(r10)    # if not scblk then
                   1016:        jnequ   erxit1          #    error
                   1017:        pushl   r10             # push scblk pointer
                   1018:        calls   $1,_doexec      # go do exit
                   1019:        jmp     erxit2          # should never return
                   1020: #
                   1021: #      write load module
                   1022: #
                   1023: xilmod:        tstl    r5              # if r5 <= 0 then
                   1024:        bgtr    0f
                   1025:        pushr   $mr235          #    save regs for error exits
                   1026:        jbr     erxit1          #    and take error exit
                   1027: 0:     pushr   $cmpreg         # else save all compiler regs
                   1028: #
                   1029: #      need to save stack contents, so that when load module is
                   1030: #      invoked, stack can be recreated.
                   1031: #
                   1032:        subl3   sp,initsp,r0    # compute depth of stack
                   1033:        cmpl    r0,tscblk       # if stack won't fit in tscblk then
                   1034:        jgtru   xi2big          #    big trouble
                   1035:        movl    sp,r0           # -> into real stack
                   1036:        movab   tscblk+scstr,r1 # -> save stack area
                   1037: 1:     movl    (r0)+,(r1)+     # copy word of stack ...
                   1038:        cmpl    r0,initsp       #    until hit top word
                   1039:        blssu   1b
                   1040:        movl    r1,lmodstk      # set top of saved stack
                   1041: #
                   1042: #      before creating the load module, we must relativize the
                   1043: #      compiler cells that point into the stack.  We do this by
                   1044: #      temporarily negating initsp, calling streloc, and then
                   1045: #      restoring initsp.  After the load module has been written,
                   1046: #      another call to streloc will restore the stack pointers.
                   1047: #
                   1048:        mnegl   initsp,initsp   # negate initsp so streloc will subtract
                   1049:        jsb     streloc         # relativize the compiler cells
                   1050:        mnegl   initsp,initsp   # restore initsp to its previous value
                   1051: #
                   1052: #      create a.out header in hststr scblk.
                   1053: #
                   1054:        addl3   $1023,dnamp,r1  # round current memory in use
                   1055:        bicl3   $0x3ff,r1,-(sp) #   to a multiple of the page size
                   1056:        movab   hststr+scstr,r0 # -> a.out header block
                   1057:        pushl   r0              #   which will be the other argument
                   1058:        movl    $0413,(r0)+     # set magic number
                   1059:        bicl3   $0x3ff,$_etext,r1 # get text size, rounded down
                   1060:        movl    r1,(r0)+        #   and place it in a.out header
                   1061:        subl3   r1,4(sp),(r0)+  # data size = total - text size
                   1062:        clrl    (r0)+           # we will use no bss
                   1063:        clrl    (r0)+
                   1064:        clrl    (r0)+           # set starting address
                   1065:        clrl    (r0)+
                   1066:        clrl    (r0)+
                   1067: #
                   1068: #      call a workhorse c routine to actually write a.out file.
                   1069: #      the amount of memory to write has already been pushed.
                   1070: #
                   1071:        calls   $2,_wrtaout     # call to write a.out
                   1072: #
                   1073: #      restore compiler cells to their previous values
                   1074: #
                   1075:        jsb     streloc         # unrelativize stack pointers
                   1076: #
                   1077:        tstl    r0              # if error creating a.out then
                   1078:        blss    xi2big          #    return error
                   1079: #
                   1080: #      pop registers and set up call to sysej
                   1081: #
                   1082:        popr    $cmpreg         # restore all registers
                   1083:        movl    r7,r10          # -> chain of fcbs
                   1084:        clrl    r7              # set &CODE = 0
                   1085:        jsb     sysej           # call to end run
                   1086: #
                   1087: #      if stack too big
                   1088: #
                   1089: xi2big:        popr    $cmpreg         # restore all regs
                   1090:        pushr   $mr235          # push correct regs
                   1091:        jbr     erxit2          # take error exit
                   1092: #
                   1093: #      error/ppm exits - pick up n-th word following jsb and return
                   1094: #      to address contained in that word.
                   1095: #
                   1096: erxit1:
                   1097:        popr    $mr235
                   1098:        movl    (sp)+,r11
                   1099:        jmp     *(r11)+
                   1100: #
                   1101: erxit2:
                   1102:        popr    $mr235
                   1103:        addl3   $4,(sp)+,r11
                   1104:        jmp     *(r11)+
                   1105: #
                   1106: erxit3:
                   1107:        popr    $mr235
                   1108:        addl3   $8,(sp)+,r11
                   1109:        jmp     *(r11)+
                   1110: #
                   1111: erxit4:
                   1112:        popr    $mr235
                   1113:        addl3   $12,(sp)+,r11
                   1114:        jmp     *(r11)+
                   1115: #
                   1116: erxit5:
                   1117:        popr    $mr235
                   1118:        addl3   $16,(sp)+,r11
                   1119:        jmp     *(r11)+
                   1120: #
                   1121: erxit6:
                   1122:        popr    $mr235
                   1123:        addl3   $20,(sp)+,r11
                   1124:        jmp     *(r11)+
                   1125: #
                   1126: #      streloc - relocate stack pointers.  this routine adds
                   1127: #      initsp to every cell whose address appears in strellst.
                   1128: #
                   1129: streloc:
                   1130:        pushr   $mr0+mr1
                   1131:        moval   strellst,r1     # start of list of thing to relocate
                   1132:        jbr     strel1          # jump into the loop
                   1133: strel0:        addl2   initsp,(r0)     # relocate a pointer
                   1134: strel1:        movl    (r1)+,r0        # fetch a pointer to a cell
                   1135:        jneq    strel0          # if zero, we're done
                   1136:        popr    $mr0+mr1
                   1137:        rsb     
                   1138: #
                   1139: #      option routines
                   1140: #
                   1141: #      optclr  clears a flag
                   1142: #      opterr  signals an error
                   1143: #      optfld  sets defcas to 0 for no folding
                   1144: #      optnum  get numeric value
                   1145: #      optset  set option value
                   1146: #
                   1147: #      optclr
                   1148: #
                   1149: optclr:        bicl2   optflg(r1),sptflg
                   1150:        rsb
                   1151: #
                   1152: #      opterr
                   1153: #
                   1154: opterr:        pushr   $mr0+mr1+mr2+mr3+mr4+mr5
                   1155:        pushl   $6
                   1156:        pushl   $curopt
                   1157:        pushl   $2
                   1158:        calls   $3,_write
                   1159:        popr    $mr0+mr1+mr2+mr3+mr4+mr5
                   1160:        rsb
                   1161: #
                   1162: #      optinp
                   1163: #
                   1164: optinp:        tstl    inpptr          # if already processed input filenames then
                   1165:        bnequ   opterr          #    error
                   1166:        subl3   $4,r6,inpptr    # -> first input filename
                   1167:        movl    r4,inpcnt       # set number of filenames
                   1168:        movl    $1,r4           # done scanning options
                   1169:        rsb                     # return
                   1170: #
                   1171: #      optfld
                   1172: #
                   1173: optfld:        clrl    defcas
                   1174:        rsb
                   1175: #
                   1176: #      optnum
                   1177: #
                   1178: optnum:        pushl   r0              # -> number
                   1179:        jsb     getnum          # get number
                   1180:        movl    (sp)+,r0        # -> byte past last digit
                   1181:        movzbl  (r0),r2         # get byte past last digit
                   1182:        bisb2   $040,r2         # fold to lower case
                   1183:        cmpb    $ch$lk,r2       # if number followed by k then
                   1184:        bnequ   0f
                   1185:        mull2   $1024,r5        #    mulitply by 1024
                   1186:        incl    r0              #    skip over k
                   1187: 0:     tstl    r5              # if number zero or negative
                   1188:        bleq    opterr          #    treat as error
                   1189:        movl    r5,*optflg(r1)  # store option
                   1190:        rsb                     # return
                   1191: #
                   1192: #      optoup
                   1193: #
                   1194: optoup:        cmpl    $2,r4           # if no option after -o then
                   1195:        bgtru   opterr          #    error
                   1196:        movl    (r6),r1         # -> output filename
                   1197:        cmpb    $ch$mn,(r1)     # if filename starts with - then
                   1198:        beqlu   opterr          #    error
                   1199:        movl    (r6)+,oupptr    # save pointer to output filename
                   1200:        decl    r4              # one less option to process
                   1201:        rsb                     # return
                   1202: #
                   1203: #      optset
                   1204: #
                   1205: optset:        bisl2   optflg(r1),sptflg
                   1206:        rsb
                   1207: #
                   1208: #      optusr
                   1209: #
                   1210: optusr:        cmpl    $2,r4           # if fewer than 2 options then
                   1211:        jgtru   opterr          #    can't have argument
                   1212:        movl    (r6)+,uarg      # save -> argument
                   1213:        decl    r4              # dec number of remaining options
                   1214:        rsb
                   1215: #
                   1216: #      getnum
                   1217: #
                   1218: #      (sp)                    -> string to convert
                   1219: #      jsb     getnum
                   1220: #      (sp)                    -> char after last digit
                   1221: #      (r5)                    converted number
                   1222: #
                   1223: getnum:
                   1224:        movl    4(sp),r7                # -> string
                   1225:        clrl    r5              # clear accumulator
                   1226: 0:     cmpb    $060,(r7)       # if not a decimal digit then
                   1227:        bgtru   1f              #    done with conversion
                   1228:        cmpb    $071,(r7)       # 
                   1229:        blssu   1f
                   1230:        movzbl  (r7)+,r8        # load digit
                   1231:        subl2   $060,r8         # remove  unnecessary bits
                   1232:        mull2   $10,r5          # accum * 10
                   1233:        addl2   r8,r5           # add in this digit
                   1234:        brb     0b
                   1235: 1:     movl    r7,4(sp)                # return address of next byte
                   1236:        rsb                     # return
                   1237: #
                   1238: #      interface data area
                   1239: #      -------------------
                   1240: #
                   1241:        .data   1
                   1242: #
                   1243: #      flags for compiler
                   1244: #
                   1245:        .set    errors,1        # send errors to terminal
                   1246:        .set    prtich,2        # standard printer is terminal
                   1247:        .set    nolist,4        # suppress compilation listing
                   1248:        .set    nocmps,8        # suppress compilation statistics
                   1249:        .set    noexcs,16       # suppress execution statistics
                   1250:        .set    lnglst,32       # generate page ejects
                   1251:        .set    noexec,64       # suppress program execution
                   1252:        .set    trmnal,128      # terminal i/o association
                   1253:        .set    stdlst,256      # standard listing (intermediate)
                   1254:        .set    nohedr,512      # suppress sysid header
                   1255: #
                   1256:        .set    deflag,errors+nolist+nocmps+noexcs+trmnal+nohedr
                   1257: #
                   1258: #      option table
                   1259: #
                   1260:        .set    opttxt,0        # option characters
                   1261:        .set    optflg,4        # option flag - flags or address
                   1262:        .set    optrtn,8        # -> option processing routine
                   1263:        .set    optsiz,12       # size in bytes of entry
                   1264: #
                   1265: opttbl:
                   1266:        .ascii  "-f  "
                   1267:        .long   0,optfld
                   1268: #
                   1269:        .ascii  "-e  "
                   1270:        .long   errors,optclr
                   1271: #
                   1272:        .ascii  "-l  "
                   1273:        .long   nolist,optclr
                   1274: #
                   1275:        .ascii  "-c  "
                   1276:        .long   nocmps,optclr
                   1277: #
                   1278:        .ascii  "-x  "
                   1279:        .long   noexcs,optclr
                   1280: #
                   1281:        .ascii  "-a  "
                   1282:        .long   nolist+nocmps+noexcs,optclr
                   1283: #
                   1284:        .ascii  "-p  "
                   1285:        .long   lnglst,optset
                   1286: #
                   1287:        .ascii  "-z  "
                   1288:        .long   stdlst,optset
                   1289: #
                   1290:        .ascii  "-h  "
                   1291:        .long   nohedr,optclr
                   1292: #
                   1293:        .ascii  "-n  "
                   1294:        .long   noexec,optset
                   1295: #
                   1296:        .ascii  "-m  "
                   1297:        .long   maxsiz,optnum
                   1298: #
                   1299:        .ascii  "-s  "
                   1300:        .long   stksiz,optnum
                   1301: #
                   1302:        .ascii  "-d  "
                   1303:        .long   datwds,optnum
                   1304: #
                   1305:        .ascii  "-i  "
                   1306:        .long   meminc,optnum
                   1307: #
                   1308:        .ascii  "-o  "
                   1309:        .long   0,optoup
                   1310: #
                   1311:        .ascii  "-u  "
                   1312:        .long   0,optusr
                   1313: #
                   1314: curopt:        .ascii  "-   "
                   1315:        .ascii  "?\n  "
                   1316:        .long   opterr
                   1317:        .align  2
                   1318: #
                   1319: #      standard input/output pointers
                   1320: #
                   1321: inpcnt:        .long   0
                   1322: inpptr:        .long   0
                   1323: oupptr:        .long   0
                   1324: #
                   1325: #      pointer to -u arg
                   1326: #
                   1327: uarg:  .long   0
                   1328: #
                   1329: #      save argc and argv from initial call
                   1330: #
                   1331: argc:  .long   0
                   1332: argv:  .long   0
                   1333: #
                   1334: #      #! data areas
                   1335: #
                   1336: cmdcnt:        .long   0               # number of  command args
                   1337: rdrec1:        .long   0               # read record 1 from std in flag
                   1338: #
                   1339: #      standard ioblks
                   1340: #
                   1341: inpiob:        .space  iobuf
                   1342:        .long   inpbf           # -> input bfblk
                   1343:        .long   0               # file descriptor
                   1344:        .long   IO_INP|IO_OPN|IO_SYS
                   1345: #
                   1346: inpbf: .space  bfsiz
                   1347:        .long   1024            # buffer size
                   1348:        .long   0               # remaining chars to read
                   1349:        .long   0               # offset to next character to read
                   1350:        .space  1024            # buffer
                   1351: #
                   1352: #
                   1353: oupiob:        .space  iobuf
                   1354:        .long   0               # no buffer
                   1355:        .long   1               # file descriptor number
                   1356:        .long   IO_OUP|IO_OPN|IO_SYS
                   1357: #
                   1358: #
                   1359: ttyiob:        .space  iobuf
                   1360:        .long   ttybf           # -> tty buffer input
                   1361:        .long   2               # file descriptor number
                   1362:        .long   IO_INP|IO_OUP|IO_OPN|IO_SYS
                   1363: #
                   1364: ttybf: .space  bfsiz
                   1365:        .long   258             # buffer size
                   1366:        .long   0               # remaining chars to read
                   1367:        .long   0               # offset to next char to read
                   1368:        .space  258             # buffer
                   1369:        .align  2
                   1370: #
                   1371:        .globl  _rzfcb
                   1372: _rzfcb:        .long   0
                   1373: #
                   1374: fildes:        .long   0
                   1375: pr_len:        .long   0
                   1376: rd_len:        .long   0
                   1377: lenfname: .long        0
                   1378: ioblkptr: .long 0
                   1379: bfblkptr: .long        0
                   1380: bfblksiz: .long        0
                   1381: fcblkptr: .long        0
                   1382: tioblk:        .space  iosize
                   1383: #
                   1384: #      memory allocation variables
                   1385: #
                   1386: meminc:        .long   4*k             # increment in words for sbrk
                   1387: meminb:        .long   0               # meminc * 4 (to get bytes)
                   1388: datwds:        .long   256*k           # max size in words of dynamic area
                   1389: basmem:        .long   0               # base of dynamic memory
                   1390: topmem:        .long   0               # current top of dynamic memory
                   1391: maxmem:        .long   0               # maximum top of dynamic memory
                   1392: maxsiz:        .long   8*k             # maximum object size in words
                   1393: stksiz:        .long   2*k             # stack size in words
                   1394: initsp:        .long   0               # initial value of sp on entry to sec04
                   1395: lowsp: .long   0               # lowest legal sp value
                   1396: #
                   1397: #      default value for &case
                   1398: #
                   1399: defcas:        .long   1
                   1400: #
                   1401: #      values given to syspp for print parameters
                   1402: #
                   1403: lnsppg:        .long   60              # lines per page
                   1404: pagwid:        .long   120             # page width
                   1405: sptflg:        .long   deflag          # flags
                   1406: #
                   1407: #      flag that indicates that this is a load module. also, serves
                   1408: #      the dual purpose of indicating size of saved stack.
                   1409: #
                   1410: lmodstk: .long 0
                   1411: #
                   1412: temp1: .long   0
                   1413: temp2: .long   0
                   1414: temp3: .long   0
                   1415: #
                   1416: nulstr:        .long   0,0
                   1417: #
                   1418: tscblk:        .long   512,0
                   1419:        .space  512
                   1420: #
                   1421: hststr:        .long   128,0
                   1422:        .space  128
                   1423: #
                   1424: id1:   .long   0,id1l
                   1425:        .ascii  "(0.0)"
                   1426: id1e:
                   1427:        .set    id1l,id1e-id1-8
                   1428:        .align  2
                   1429: #
                   1430: id2:   .long   0,id2l
                   1431:        .ascii  "VAX/UNIX Version"
                   1432: id2e:
                   1433:        .set    id2l,id2e-id2-8
                   1434:        .align  2
                   1435: #
                   1436: ffscb: .long   0,1
                   1437: ffstr: .byte   12
                   1438: #
                   1439: nlstr: .ascii  "\n"
                   1440:        .align  2
                   1441: #
                   1442: errfdn:        .long   0
                   1443: #
                   1444: #      The following pointers address those cells in the compiler
                   1445: #      that point into the stack when a load module might be written,
                   1446: #      and which must therefore be relocated.
                   1447: strellst:
                   1448:        .long   flptr
                   1449:        .long   stbas
                   1450:        .long   gtcef
                   1451:        .long   0               # end of list marker

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.