1: /* 2: * Copyright (c) 1987 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifdef LIBC_SCCS 8: <@(#)puts.s 5.6 (Berkeley) 12/24/88\0> 9: .even 10: #endif LIBC_SCCS 11: 12: #include "DEFS.h" 13: #include "STDIO.h" 14: 15: /* 16: * BUFSIZ is only used if we're asked to output to an unbuffered output 17: * stream. Given that a majority of our arguments are going to be less 18: * than 80 characters (one screen line), we might as well use a fairly small 19: * value for BUFSIZ ... 20: */ 21: #define BUFSIZ 128. 22: 23: /* 24: * puts(s); 25: * char *s; 26: * 27: * argument: a source string. 28: * side effects: writes to the standard output using the data in 29: * the null-terminated source string; a newline is appended. 30: * result: technically void; for compatibility we return 0 for errors, 31: * a newline (\n) otherwise 32: */ 33: ENTRY(puts) 34: mov $STDOUT,r0 / out to stdout 35: mov $1,r1 / (append a newline) 36: br Lputs 37: 38: /* 39: * fputs(s, iop); 40: * char *s; 41: * FILE *iop; 42: * 43: * arguments: a source string and a file pointer. 44: * side effects: writes to the file indicated by iop using the data in 45: * the null-terminated source string. 46: * result: technically void; for compatibility we return 0 for errors, 47: * a newline (\n) otherwise 48: */ 49: ENTRY(fputs) 50: mov 4(sp),r0 / out to iop 51: clr r1 / (don't append a newline) 52: / br Lputs 53: /*FALLTHROUGH*/ 54: 55: /* 56: * ASENTRY(Lputs)(s::2(sp), iop::r0, nlflag::r1) 57: * char *s; 58: * FILE *iop; 59: * 60: * Implements puts and fputs. 61: */ 62: .globl __flsbuf, _fflush 63: 64: #define S r4 65: #define IOP r3 66: #define COUNT r2 67: #define P r1 68: #define C r0 69: /* 70: * P & C get trounced when we call someone else ... 71: */ 72: 73: Lputs: 74: mov r2,-(sp) / need a few registers 75: mov r3,-(sp) 76: mov r4,-(sp) 77: mov r0,IOP / put IOP in the right register 78: mov r1,-(sp) / save newline flag 79: mov 10.(sp),S / grab string pointer 80: sub $BUFSIZ+2,sp / allocate a buffer and flag on stack 81: 82: # define NLFLAG BUFSIZ+2(sp) 83: # define UNBUF BUFSIZ(sp) 84: # define BUF sp 85: 86: # define FRSIZE BUFSIZ+4 87: 88: /* 89: * For unbuffered I/O, line buffer the output line. 90: * Ugly but fast -- and doesn't CURRENTLY break anything (sigh). 91: */ 92: mov _FLAG(IOP),UNBUF / get a copy of the current flags for 93: bic $!_IONBF,UNBUF / iob - iob buffered? 94: beq 1f 95: 96: bic $_IONBF,_FLAG(IOP) / no, clear no-buffering flag 97: mov BUF,_BASE(IOP) / and set up to buffer into our on 98: mov BUF,_PTR(IOP) / stack buffer 99: mov $BUFSIZ,_BUFSIZ(IOP) 100: br 2f / have _flsbuf finish the buffer setup 101: 1: 102: tst _CNT(IOP) / has buffer been allocated? 103: bgt 3f 104: 2: 105: mov IOP,-(sp) / get _flsbuf('\0', stdout) to make 106: clr -(sp) / one 107: jsr pc,__flsbuf 108: cmp (sp)+,(sp)+ 109: tst r0 110: blt Lerror 111: inc _CNT(IOP) / unput the '\0' we sent 112: dec _PTR(IOP) 113: 3: 114: tstb (S) / null string? 115: beq Lnl 116: 117: mov _BASE(IOP),COUNT / figure out how much room is left 118: add _BUFSIZ(IOP),COUNT / in buffer (base+bufsiz-ptr) 119: mov _PTR(IOP),P 120: sub P,COUNT 121: Lloop: 122: /* 123: * Copy till terminating null found or out of room. 124: */ 125: mov COUNT,C 126: 1: 127: movb (S)+,(P)+ / found null? 128: beq Llast 129: sob C,1b / run out of room? 130: 131: mov P,_PTR(IOP) / yes, fix up IOP 132: clr _CNT(IOP) 133: mov IOP,-(sp) / the buffer is full - flush it 134: jsr pc,_fflush 135: tst (sp)+ 136: tst r0 137: blt Lerror 138: tstb (S) / more data?? 139: beq Lnl / nope, clean up ... 140: 141: mov _PTR(IOP),P / yes, easy to compute how much room 142: mov _BUFSIZ(IOP),COUNT / is left this time ... 143: br Lloop 144: Llast: 145: sub C,COUNT / how much did we actually move? 146: add COUNT,_PTR(IOP) / update IOP 147: sub COUNT,_CNT(IOP) 148: Lnl: 149: tst NLFLAG / need to append a newline? 150: beq 1f 151: 152: movb $NL,*_PTR(IOP) / yes, there's always room for one 153: inc _PTR(IOP) / more character at this point 154: dec _CNT(IOP) 155: 1: 156: bit $_IOLBF,_FLAG(IOP) / if line buffered ... 157: bne 2f 158: tst UNBUF / or unbuffered ... 159: bne 2f 160: tst _CNT(IOP) / or a full buffer ... 161: bgt 3f 162: 2: 163: mov IOP,-(sp) / ... flush the buffer 164: jsr pc,_fflush 165: tst (sp)+ 166: tst r0 167: blt Lerror 168: 3: 169: movb $NL,r0 / compatibility hack 170: Lfixup: 171: /* 172: * Fix up buffering again. 173: */ 174: tst UNBUF 175: beq Lret 176: bis $_IONBF,_FLAG(IOP) / reset flag 177: clr _BASE(IOP) / clear data structure 178: clr _BUFSIZ(IOP) 179: clr _CNT(IOP) 180: Lret: 181: add $FRSIZE,sp / deallocate local stack variables 182: mov (sp)+,r4 / restore registers 183: mov (sp)+,r3 184: mov (sp)+,r2 185: rts pc / and return 186: 187: /* 188: * Bomb out. Return 0 (why not? that's what the old one did). 189: */ 190: Lerror: 191: clr r0 192: br Lfixup