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: <@(#)fgets.s 5.6 (Berkeley) 9/2/88\0> 9: .even 10: #endif LIBC_SCCS 11: 12: #include "DEFS.h" 13: #include "STDIO.h" 14: 15: .globl __filbuf 16: 17: #define S r4 18: #define IOP r3 19: #define COUNT r2 20: #define P r1 21: #define C r0 22: /* 23: * P & C get trounced when we call someone else ... 24: */ 25: 26: /* 27: * char *fgets(s, n, iop); 28: * char *s; 29: * int n; 30: * FILE *iop; 31: * 32: * arguments: a target string, a length, and a file pointer. 33: * side effects: reads up to and including a newline, or up to n-1 bytes, 34: * whichever is less, from the file indicated by iop into the target 35: * string and null terminates. 36: * result: the target string if successful, 0 otherwise. 37: */ 38: ENTRY(fgets) 39: mov r2,-(sp) / need a few registers 40: mov r3,-(sp) 41: mov r4,-(sp) 42: 43: # define OLD_S 8.(sp) 44: 45: mov OLD_S,S / grab string pointer 46: mov 10.(sp),COUNT / string length 47: mov 12.(sp),IOP / and I/O pointer 48: 49: /* 50: * Sanity check -- is the string big enough? Has to hold at least 51: * a null ... 52: */ 53: dec COUNT / We scan at most n-1 characters 54: ble Lerror 55: 56: /* 57: * If no characters, call _filbuf() to get some. 58: */ 59: tst _CNT(IOP) 60: bgt Lscan 61: 62: Lloop: 63: mov IOP,-(sp) / _filbuf(stdin) 64: jsr pc,__filbuf 65: tst (sp)+ 66: tst r0 / _filbuf return EOF? 67: blt Leof 68: movb r0,(S)+ / save the returned character 69: dec COUNT / out of space? 70: ble 1f 71: cmpb r0,$NL / a newline? 72: bne 2f 73: 1: 74: clrb (S) / yes, terminate the string and return 75: br Lret / with a pointer to it 76: 2: 77: tst _BASE(IOP) / is input buffered? 78: beq Lloop / no, have to do it the hard way ... 79: tst _CNT(IOP) / did __filbuf leave us anything 80: beq Lloop / to work with?? 81: 82: Lscan: 83: /* 84: * Copy till terminating newline found or end of buffer or end of 85: * string. 86: */ 87: mov _PTR(IOP),P / grab pointer into I/O buffer 88: mov _CNT(IOP),C / and how many characters in it 89: sub C,COUNT / more in buffer than we can take? 90: bge 1f 91: add COUNT,C / only copy till end of string then 92: clr COUNT 93: 1: 94: movb (P),(S)+ / copy from buffer to string 95: cmpb (P)+,$NL / was it a newline? 96: beq 2f 97: sob C,1b / repeat till we run out ... 98: tst COUNT / more room in string? 99: bne Lloop / yes, go back for another buffer 100: 2: 101: clrb (S) / terminate string 102: sub _PTR(IOP),P / figure out how much we took from 103: add P,_PTR(IOP) / the buffer and update IOP 104: sub P,_CNT(IOP) 105: 106: Lret: 107: mov OLD_S,r0 / return pointer to string 108: Lexit: 109: mov (sp)+,r4 / restore registers 110: mov (sp)+,r3 111: mov (sp)+,r2 112: rts pc / and return 113: 114: /* 115: * End of file? Check to see if we copied any data. 116: */ 117: Leof: 118: cmp S,OLD_S / did we copy anything? 119: beq Lerror / nope, return null 120: clrb (S) / yes, terminate string 121: br Lret / and return a pointer to it 122: 123: /* 124: * Error/eof return -- null pointer. 125: */ 126: Lerror: 127: clr r0 128: br Lexit