Annotation of 40BSD/cmd/csh/doprnt.c, revision 1.1

1.1     ! root        1: /* static char *sccsid = "@(#)doprnt.c 4.1 10/9/80"; */
        !             2: 
        !             3:        # C library -- conversions
        !             4: 
        !             5: .globl __doprnt
        !             6: .globl __strout
        !             7: 
        !             8: #define flags r10
        !             9: #define literb 0
        !            10: #define liter 1
        !            11: #define ndfndb 0
        !            12: #define ndfnd 1
        !            13: #define ljustb 1
        !            14: #define ljust 2
        !            15: #define zfillb 2
        !            16: #define zfill 4
        !            17: #define precb 3
        !            18: #define prec 8
        !            19: #define psignb 4
        !            20: #define psign 16
        !            21: #define gflagb 5
        !            22: #define gflag 32
        !            23: #define width r9
        !            24: #define ndigit r8
        !            25: #define fdesc -4(fp)
        !            26: #define exp -8(fp)
        !            27: #define sign -9(fp)
        !            28:        .set one,010                    # 1.0 in floating immediate
        !            29:        .set ch.zer,'0                  # cpp doesn't like single appostrophes
        !            30: 
        !            31:        .align  1
        !            32: __doprnt:
        !            33:        .word   0xfc0                   # uses r11-r6
        !            34:        subl2 $128,sp
        !            35:        movl 4(ap),r11                  # addr of format string
        !            36:        movl 12(ap),fdesc               # output FILE ptr
        !            37:        movl 8(ap),ap                   # addr of first arg
        !            38: loop:
        !            39:        movl r11,r0                     # current point in format
        !            40:        bicl2 $liter,flags              # no literal characters yet
        !            41: L1:    movb (r11)+,width               # next character of format
        !            42:        beql L2                         # end of format string
        !            43:        cmpb width,$'%
        !            44:        beql L2                         # warning character
        !            45:        bisl2 $liter,flags              # literal character
        !            46:        jbr L1
        !            47: L2:    blbc flags,L3                   # bbc $literb,flags,L3 # no literals in format
        !            48:        pushl fdesc                     # file pointer
        !            49:        pushl $0                        # no left/right adjust
        !            50:        pushl r0                        # addr
        !            51:        subl3 r0,r11,r1                 # length
        !            52:        subl3 $1,r1,-(sp)               # % or null not part of literal
        !            53:        calls $4,__strout               # dump the literal
        !            54: L3:
        !            55:        blbs width,L4                   # % is odd; end of format?
        !            56:        ret                             # yes
        !            57: 
        !            58:        # htab overlaps last 16 characters of ftab
        !            59: ftab:  .byte    0, 0, 0,'c,'d,'e,'f,'g, 0, 0, 0,'+,'l,'-,'.,'o
        !            60: htab:  .byte   '0,'1,'2,'3,'4,'5,'6,'7,'8,'9,'a,'b,'c,'d,'e,'f
        !            61: 
        !            62: L4:    movl sp,r5                      # reset output buffer pointer
        !            63:        clrq r9                         # width; flags ljustb,ndfndb,zfillb
        !            64: L4a:   movzbl (r11)+,r0                # supposed format
        !            65:        extzv $0,$5,r0,r1                # bottom 5 bits
        !            66: L4b:   cmpb r0,ftab[r1]                # good enough?
        !            67:        jneq L6                         # no
        !            68: L4c:   casel r1,$3,$22                 # yes
        !            69: L5:    .word charac-L5                 # c
        !            70:        .word decimal-L5                # d
        !            71:        .word scien-L5                  # e
        !            72:        .word float-L5                  # f
        !            73:        .word general-L5                # g
        !            74:        .word L6-L5                     # h
        !            75:        .word L6-L5                     # i
        !            76:        .word L6-L5                     # j
        !            77:        .word plus-L5                   # +
        !            78:        .word longorunsg-L5             # l
        !            79:        .word minus-L5                  # -
        !            80:        .word dot-L5                    # .
        !            81:        .word octal-L5                  # o
        !            82:        .word gnum0-L5                  # 0
        !            83:        .word gnum-L5                   # 1
        !            84:        .word gnum-L5                   # 2
        !            85:        .word gnum-L5                   # 3
        !            86:        .word gnum-L5                   # 4
        !            87:        .word gnum-L5                   # 5
        !            88:        .word gnum-L5                   # 6
        !            89:        .word gnum-L5                   # 7
        !            90:        .word gnum-L5                   # 8
        !            91:        .word gnum-L5                   # 9
        !            92: 
        !            93: L6:    jbcs $5,r0,L4b                  # capitals same as small
        !            94:        cmpb r0,$'s
        !            95:        jeql string
        !            96:        cmpb r0,$'x
        !            97:        jeql hex
        !            98:        cmpb r0,$'u
        !            99:        jeql unsigned
        !           100:        cmpb r0,$'r
        !           101:        jeql remote
        !           102:        movzbl -1(r11),r0               # orginal "format" character
        !           103:        cmpb r0,$'*
        !           104:        jeql indir
        !           105: L9:    movb r0,(r5)+                   # print the unfound character
        !           106:        jbr prbuf
        !           107: 
        !           108: nulstr:
        !           109:        .byte '(,'n,'u,'l,'l,'),0
        !           110: 
        !           111: string:
        !           112:        movl ndigit,r0
        !           113:        jbs $precb,flags,L20            # max length was specified
        !           114:        mnegl $1,r0                     # default max length
        !           115: L20:   movl (ap)+,r2                   # addr first byte
        !           116:        bneq L21
        !           117:        movab nulstr,r2
        !           118: L21:   locc $0,r0,(r2)                 # find the zero at the end
        !           119:        movl r1,r5                      # addr last byte +1
        !           120:        movl r2,r1                      # addr first byte
        !           121:        jbr prstr
        !           122: 
        !           123: 
        !           124: longorunsg:
        !           125:        movb (r11)+,r0
        !           126:        cmpb r0,$'o
        !           127:        jeql loct
        !           128:        cmpb r0,$'x
        !           129:        jeql lhex
        !           130:        cmpb r0,$'d
        !           131:        jeql long
        !           132:        cmpb r0,$'u
        !           133:        jeql lunsigned
        !           134:        decl r11
        !           135:        jbr unsigned
        !           136: 
        !           137: loct:
        !           138: octal:
        !           139:        movl $30,r2                     # init position
        !           140:        movl $3,r3                      # field width
        !           141:        movl $10,r4                     # result length -1
        !           142:        jbr L10
        !           143: 
        !           144: lhex:
        !           145: hex:
        !           146:        movl $28,r2                     # init position
        !           147:        movl $4,r3                      # field width
        !           148:        movl $7,r4                      # result length -1
        !           149: L10:   mnegl r3,r6                     # increment
        !           150:        clrl r1
        !           151:        movl (ap)+,r0                   # fetch arg
        !           152: L11:   extzv r2,r3,r0,r1               # pull out a digit
        !           153:        movb htab[r1],(r5)+             # convert to character
        !           154: L12:   acbl $0,r6,r2,L11               # continue until done
        !           155:        clrb (r5)                       # flag end
        !           156:        skpc $'0,r4,(sp)                # skip over leading zeroes
        !           157:        jbr prstr
        !           158: 
        !           159: patdec:                                        # editpc pattern for decimal printing
        !           160:        .byte 0xA9                      # eo$float 9
        !           161:        .byte 0x01                      # eo$end_float
        !           162:        .byte 0x91                      # eo$move 1
        !           163:        .byte 0                         # eo$end
        !           164: 
        !           165: long:
        !           166: decimal:
        !           167:        cvtlp (ap)+,$10,(sp)            # 10 digits max
        !           168: L14:   editpc $10,(sp),patdec,8(sp)    # ascii at 8(sp); r5=end+1
        !           169:        skpc $' ,$10,8(sp)              # skip leading blanks; r1=first
        !           170: 
        !           171: prstr:                 # r1=addr first byte; r5=addr last byte +1
        !           172:        cvtbl $' ,-(sp)                 # blank fill
        !           173:        jbc $zfillb,flags,L15
        !           174:        cvtbl $'0,(sp)                  # zero fill
        !           175: L15:   pushl fdesc                     # FILE
        !           176:        subl2 r1,r5                     # r5=actual length=end+1-first
        !           177:        subl3 r5,width,r0               # if >0, how much to fill
        !           178:        bgeq L24
        !           179:        clrl r0                         # no fill
        !           180: L24:   jbs $ljustb,flags,L25
        !           181:        mnegl r0,r0
        !           182: L25:   pushl r0                        # fill count
        !           183:        pushl r1                        # addr first byte
        !           184:        pushl r5                        # length
        !           185:        calls $5,__strout
        !           186:        jbr     loop
        !           187: 
        !           188: pone:  .byte   0x1C                    # packed 1
        !           189:        
        !           190: unsigned:
        !           191: lunsigned:
        !           192:        extzv $1,$31,(ap),r0            # right shift logical 1 bit
        !           193:        cvtlp r0,$10,(sp)               # convert [n/2] to packed
        !           194:        movp $10,(sp),8(sp)             # copy packed
        !           195:        addp4 $10,8(sp),$10,(sp)        # 2*[n/2] in packed, at (sp)
        !           196:        blbc (ap)+,L14                  # n was even
        !           197:        addp4 $1,pone,$10,(sp)          # n was odd
        !           198:        jbr L14
        !           199: 
        !           200: charac:
        !           201:        movl $4,r0                      # chars per word
        !           202: L18:   movb (ap)+,(r5)+                # transfer char
        !           203:        bneq L19
        !           204:        decl r5                         # omit null characters
        !           205: L19:   sobgtr r0,L18
        !           206: 
        !           207: prbuf:
        !           208:        movl sp,r1                      # addr first byte
        !           209:        jbr prstr
        !           210: 
        !           211: plus:  bisl2 $psign,flags              # always print sign for floats
        !           212:        jbr L4a
        !           213: minus: bisl2 $ljust,flags              # left justification, please
        !           214:        jbr L4a
        !           215: gnum0: jbs $ndfndb,flags,gnum
        !           216:        jbs $precb,flags,gnump          # ignore when reading precision
        !           217:        bisl2 $zfill,flags              # leading zero fill, please
        !           218: gnum:  jbs $precb,flags,gnump
        !           219:        moval (width)[width],width      # width *= 5;
        !           220:        movaw -ch.zer(r0)[width],width  # width = 2*witdh + r0 - '0';
        !           221:        jbr gnumd
        !           222: gnump: moval (ndigit)[ndigit],ndigit   # ndigit *= 5;
        !           223:        movaw -ch.zer(r0)[ndigit],ndigit # ndigit = 2*ndigit + r0 - '0';
        !           224: gnumd: bisl2 $ndfnd,flags              # digit seen
        !           225:        jbr L4a
        !           226: dot:   clrl ndigit                     # start on the precision
        !           227:        bisl2 $prec,flags
        !           228:        bicl2 $ndfnd,flags
        !           229:        jbr L4a
        !           230: indir: movl (ap)+,ndigit               # width specified by parameter
        !           231:        jbr gnumd
        !           232: remote:        movl (ap)+,ap
        !           233:        movl (ap)+,r11
        !           234:        jbr loop
        !           235: 
        !           236: float:
        !           237:        bsbw fltcvt
        !           238: fltg:  jbs $ndfndb,flags,float1
        !           239:        movl $6,ndigit                  # default # digits to right of decpt.
        !           240: float1:        addl3 exp,ndigit,r7
        !           241:        movl r7,r6                      # for later "underflow" checking
        !           242:        bgeq fxplrd
        !           243:        clrl r7                         # poor programmer planning
        !           244: fxplrd:        cmpl r7,$31                     # expressible in packed decimal?
        !           245:        bleq fnarro                     # yes
        !           246:        movl $31,r7
        !           247: fnarro:        subl3 $17,r7,r0                 # where to round
        !           248:        ashp r0,$17,(sp),$5,r7,16(sp)   # do it
        !           249:        bvc fnovfl
        !           250:        # band-aid for microcode error (spurious overflow)
        !           251:        clrl r0                         # assume even length result
        !           252:        jlbc r7,fleven                  # right
        !           253:        movl $4,r0                      # odd length result
        !           254: fleven:        cmpv r0,$4,16(sp),$0            # top digit zero iff true overflow
        !           255:        bneq fnovfl
        !           256:        # end band-aid
        !           257:        aobleq $0,r6,fnovfl             # if "underflow" then jump
        !           258:        movl r7,r0
        !           259:        incl exp
        !           260:        incl r7
        !           261:        ashp r0,$1,pone,$0,r7,16(sp)
        !           262:        ashl $-1,r7,r0                  # displ to last byte
        !           263:        bisb2 sign,16(sp)[r0]           # insert sign
        !           264: fnovfl:
        !           265:        movc3 $4,patsci,(sp)
        !           266:        clrl r6                         # # digits moved so far
        !           267:        movl exp,r0
        !           268:        bleq fexpng
        !           269:        bsbb patmov                     # digits to left of decpt.
        !           270: fexpng:        tstl ndigit
        !           271:        jeql fnodp
        !           272:        movc3 $2,fpatdp,(r3)
        !           273:        tstl exp
        !           274:        bgeq fxppos
        !           275:        addl3 exp,ndigit,r6
        !           276:        bgeq  flfakl
        !           277:        clrl r6                         # it's all fill
        !           278: flfakl:        subl3 r6,$31,r6                 # fake length for patmov
        !           279: flfill:        movc3 $2,fpatzf,(r3)            # zero fill to right of dec.pt
        !           280: fxppos:        movl ndigit,r0
        !           281:        bsbb patmov
        !           282: fnodp: sobgeq r6,fledit                # must move at least 1 digit
        !           283:        movl $31,r6                     # none moved; fake it
        !           284:        aobleq $1,ndigit,flfill         # with a one-character zero fill
        !           285: fledit:        editpc r7,16(sp),(sp),32(sp)
        !           286:        jbr prflt
        !           287: 
        !           288: patexp:        .byte   0x03                    # eo$set_signif
        !           289:        .byte   0x44,'e                 # eo$insert 'e
        !           290:        .byte   0x42,'+                 # eo$load_plus '+
        !           291:        .byte   0x04                    # eo$store_sign
        !           292:        .byte   0x92                    # eo$move 2
        !           293:        .byte   0                       # eo$end
        !           294: patsci:        .byte   0x42,'+                 # eo$load_plus '+
        !           295:        .byte   0x03                    # eo$set_signif
        !           296:        .byte   0x04                    # eo$store_sign
        !           297:        .byte   0x91                    # eo$move 1
        !           298: fpatdp:        .byte   0x44,'.                 # eo$insert '.
        !           299: fpatzf:        .byte   0x40,'0                 # eo$load_fill '0
        !           300: 
        !           301:        # construct pattern at (r3) to move  r0  digits in  editpc;
        !           302:        #  r6  digits already moved for this number
        !           303: patmov:
        !           304:        movb $0x90,r2                   # eo$move
        !           305:        subl3 r6,$31,r1                 # # digits remaining in packed
        !           306:        addl2 r0,r6
        !           307:        cmpl r0,r1                      # enough digits remaining?
        !           308:        bleq patsml                     # yes
        !           309:        tstl exp                        # zero 'fill'; before or after rest?
        !           310:        bgeq pataft                     # after
        !           311:        pushl r1                        # # digits remaining
        !           312:        movb $0x80,r2                   # eo$fill
        !           313:        subl3 $31,r6,r0                 # number of fill bytes
        !           314:        bsbb patsml                     # recursion!
        !           315:        movl (sp)+,r0
        !           316:        movb $0x90,r2                   # eo$move
        !           317:        jbr patsml
        !           318: pataft:        movl r1,r0                      # last of the 31
        !           319:        bsbb patsml                     # recursion!
        !           320:        subl3 $31,r6,r0                 # number of fill bytes
        !           321:        movb $0x80,r2                   # eo$fill
        !           322: patsml:        tstl r0
        !           323:        bleq patzer                     # DEC doesn't like repetition counts of 0
        !           324:        mnegl $15,r1                    # 15 digits at a time
        !           325:        subl2 r1,r0                     # counteract acbl
        !           326:        jbr pattst
        !           327: patmlp:        bisb3 r2,$15,(r3)+              # 15
        !           328: pattst:        acbl $16,r1,r0,patmlp           # until <= 15 left
        !           329:        bisb3 r2,r0,(r3)+               # rest
        !           330: patzer:        clrb (r3)                       # eo$end
        !           331:        rsb
        !           332: 
        !           333: scien:
        !           334:        bsbw fltcvt                     # get packed digits
        !           335: scig:  incl ndigit
        !           336:        jbs $ndfndb,flags,L23
        !           337:        movl $7,ndigit
        !           338: L23:   subl3 $17,ndigit,r0             # rounding position
        !           339:        ashp r0,$17,(sp),$5,ndigit,16(sp) # shift and round
        !           340:        bvc snovfl
        !           341:        # band-aid for microcode error (spurious overflow)
        !           342:        clrl r0                         # assume even length result
        !           343:        jlbc ndigit,sceven              # right
        !           344:        movl $4,r0                      # odd length result
        !           345: sceven:        cmpv r0,$4,16(sp),$0            # top digit zero iff true overflow
        !           346:        bneq snovfl
        !           347:        # end band-aid
        !           348:        incl exp                        # rounding overflowed to 100...
        !           349:        subl3 $1,ndigit,r0
        !           350:        ashp r0,$1,pone,$0,ndigit,16(sp)
        !           351:        ashl $-1,ndigit,r0              # displ to last byte
        !           352:        bisb2 sign,16(sp)[r0]           # insert sign
        !           353: snovfl:
        !           354:        jbc $gflagb,flags,enotg         # not %g format
        !           355:  # find trailing zeroes in packed number
        !           356:        ashl $-1,ndigit,r0
        !           357:        addl2 r3,r0                     # addr of l.s.digit and sign
        !           358:        movl $4,r1                      # bit position of digit
        !           359:        movl ndigit,r7                  # current length of packed
        !           360:        jbr gtz
        !           361: gtz1:  xorl2 $4,r1                     # position of next digit
        !           362:        bneq gtz                        # same byte
        !           363:        decl r0                         # different byte
        !           364: gtz:   cmpv r1,$4,(r0),$0              # a trailing zero?
        !           365:        jneq gntz
        !           366:        sobgtr r7,gtz1
        !           367:        incl r7
        !           368: gntz:                                  # r7: minimum width of fraction
        !           369:        cmpl exp,$-4
        !           370:        jleq eg                         # small exponents use %e
        !           371:        subl3 r7,exp,r0
        !           372:        cmpl $5,r0
        !           373:        jleq eg                         # so do (w+5) <= exp
        !           374:        tstl r0                         # rest use %f
        !           375:        jleq fg                         # did we trim too many trailing zeroes?
        !           376:        movl exp,r7                     # yes
        !           377: fg:    subl3 ndigit,r7,r0
        !           378:        ashp r0,ndigit,16(sp),$0,r7,(sp)
        !           379:        movp r7,(sp),16(sp)
        !           380:        subl3 exp,r7,ndigit             # correct ndigit for %f
        !           381:        jbr fnovfl
        !           382: eg:    subl3 ndigit,r7,r0
        !           383:        ashp r0,ndigit,16(sp),$0,r7,(sp)
        !           384:        movp r7,(sp),16(sp)
        !           385:        movl r7,ndigit                  # packed number has been trimmed
        !           386: enotg:
        !           387:        movc3 $7,patsci,(sp)
        !           388:        movl $1,r6                      # 1P
        !           389:        subl3 $1,ndigit,r0              # digits after dec.pt
        !           390:        bsbw patmov
        !           391:        editpc ndigit,16(sp),(sp),32(sp)        # 32(sp)->result, r5->(end+1)
        !           392:        decl exp                        # compensate: 1 digit left of dec.pt
        !           393:        cvtlp exp,$2,(sp)               # exponent
        !           394:        editpc $2,(sp),patexp,(r5)
        !           395: prflt: movab 32(sp),r1
        !           396:        jbs $psignb,flags,prflt1
        !           397:        cmpb (r1)+,$'+
        !           398:        beql prflt1
        !           399:        decl r1
        !           400: prflt1:        skpc $' ,$63,(r1)
        !           401:        jbr prstr
        !           402: 
        !           403: general:
        !           404:        jbcs $gflagb,flags,scien
        !           405:        jbr scien                       # safety net
        !           406: 
        !           407:        # convert double-floating at (ap) to 17-digit packed at (sp),
        !           408:        # set 'sign' and 'exp', advance ap.
        !           409: fltcvt:
        !           410:        clrb sign
        !           411:        movd (ap)+,r5
        !           412:        jeql fzero
        !           413:        bgtr fpos
        !           414:        mnegd r5,r5
        !           415:        incb sign
        !           416: fpos:
        !           417:        extzv $7,$8,r5,r2               # exponent of 2
        !           418:        movaw -0600(r2)[r2],r2          # unbias and mult by 3
        !           419:        bgeq epos
        !           420:        subl2 $9,r2
        !           421: epos:  divl2 $10,r2
        !           422:        bsbb expten
        !           423:        cmpd r0,r5
        !           424:        bgtr ceil
        !           425:        incl r2
        !           426: ceil:  movl r2,exp
        !           427:        mnegl r2,r2
        !           428:        cmpl r2,$29                     # 10^(29+9) is all we can handle
        !           429:        bleq getman
        !           430:        muld2 ten16,r5
        !           431:        subl2 $16,r2
        !           432: getman:        addl2 $9,r2                     # -ceil(log10(x)) + 9
        !           433:        bsbb expten
        !           434:        emodd r0,r4,r5,r0,r5            # (r0+r4)*r5; r0=int, r5=frac
        !           435: fz1:   cvtlp r0,$9,16(sp)              # leading 9 digits
        !           436:        ashp $8,$9,16(sp),$0,$17,4(sp)  # as top 9 of 17
        !           437:        emodd ten8,$0,r5,r0,r5
        !           438:        cvtlp r0,$8,16(sp)              # trailing 8 digits
        !           439:        addp4 $8,16(sp),$17,4(sp)       # combine leading and trailing
        !           440:        bisb2 sign,12(sp)               # and insert sign
        !           441:        rsb
        !           442: fzero: clrl r0
        !           443:        movl $1,exp             # 0.000e+00 and 0.000 rather than 0.000e-01 and .000
        !           444:        jbr fz1
        !           445: 
        !           446:        # return 10^r2 as a double float in r0||r1 and 8 extra bits of precision in r4
        !           447:        # preserve r2, r5||r6
        !           448: expten:
        !           449:        movd $one,r0                    # begin computing 10^exp10
        !           450:        clrl r4                         # bit counter
        !           451:        movad ten1,r3                   # table address
        !           452:        tstl r2
        !           453:        bgeq e10lp
        !           454:        mnegl r2,r2                     # get absolute value
        !           455:        jbss $6,r2,e10lp                # flag as negative
        !           456: e10lp: jbc r4,r2,el1                   # want this power?
        !           457:        muld2 (r3),r0                   # yes
        !           458: el1:   addl2 $8,r3                     # advance to next power
        !           459:        aobleq $5,r4,e10lp              # through 10^32
        !           460:        jbcc $6,r2,el2                  # correct for negative exponent
        !           461:        divd3 r0,$one,r0                # by taking reciprocal
        !           462:        mnegl r2,r2
        !           463: el2:   clrl r4                         # 8 extra bits of precision
        !           464:        rsb
        !           465: 
        !           466:        # powers of ten
        !           467:        .align  2
        !           468: ten1:  .word   0x4220,0,0,0
        !           469: ten2:  .word   0x43c8,0,0,0
        !           470: ten4:  .word   0x471c,0x4000,0,0
        !           471: ten8:  .word   0x4dbe,0xbc20,0,0
        !           472: ten16: .word   0x5b0e,0x1bc9,0xbf04,0
        !           473: ten32: .word   0x759d,0xc5ad,0xa82b,0x70b6

unix.superglobalmegacorp.com

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