1 /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
2  *
3  * GNU Library General Public License (LGPL) version 2 or later.
4  *
5  * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
6  */
7 
8 #include "_stdio.h"
9 
10 
11 #ifdef __DO_UNLOCKED
12 
13 
fgets_unlocked(char * __restrict s,int n,register FILE * __restrict stream)14 char *fgets_unlocked(char *__restrict s, int n,
15 					   register FILE * __restrict stream)
16 {
17 	register char *p;
18 	int c;
19 
20 	__STDIO_STREAM_VALIDATE(stream);
21 
22 #ifdef __UCLIBC_MJN3_ONLY__
23 #warning CONSIDER: What should fgets do if n <= 0?
24 #endif /* __UCLIBC_MJN3_ONLY__ */
25 	/* Should we assert here?  Or set errno?  Or just fail... */
26 	if (n <= 0) {
27 /* 		__set_errno(EINVAL); */
28 		goto ERROR;
29 	}
30 
31 	p = s;
32 
33 	while (--n) {
34 		if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) {
35 			if ((*p++ = __STDIO_STREAM_BUFFER_GET(stream)) == '\n') {
36 				break;
37 			}
38 		} else {
39 			if ((c = __fgetc_unlocked(stream)) == EOF) {
40 				if (__FERROR_UNLOCKED(stream)) {
41 					goto ERROR;
42 				}
43 				break;
44 			}
45 			if ((*p++ = c) == '\n') {
46 				break;
47 			}
48 		}
49 	}
50 
51 #ifdef __UCLIBC_MJN3_ONLY__
52 #warning CONSIDER: If n==1 and not at EOF, should fgets return an empty string?
53 #endif /* __UCLIBC_MJN3_ONLY__ */
54 	if (p > s) {
55 		*p = 0;
56 		return s;
57 	}
58 
59  ERROR:
60 	return NULL;
61 }
62 libc_hidden_def(fgets_unlocked)
63 
64 #ifndef __UCLIBC_HAS_THREADS__
65 strong_alias(fgets_unlocked,fgets)
66 libc_hidden_def(fgets)
67 #endif
68 
69 #elif defined __UCLIBC_HAS_THREADS__
70 
71 char *fgets(char *__restrict s, int n,
72 			register FILE * __restrict stream)
73 {
74 	char *retval;
75 	__STDIO_AUTO_THREADLOCK_VAR;
76 
77 	__STDIO_AUTO_THREADLOCK(stream);
78 
79 	retval = fgets_unlocked(s, n, stream);
80 
81 	__STDIO_AUTO_THREADUNLOCK(stream);
82 
83 	return retval;
84 }
85 libc_hidden_def(fgets)
86 
87 #endif
88