xref: /minix/external/bsd/nvi/dist/vi/getc.c (revision 0a6a1f1d)
1 /*	$NetBSD: getc.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
2 /*-
3  * Copyright (c) 1992, 1993, 1994
4  *	The Regents of the University of California.  All rights reserved.
5  * Copyright (c) 1992, 1993, 1994, 1995, 1996
6  *	Keith Bostic.  All rights reserved.
7  *
8  * See the LICENSE file for redistribution information.
9  */
10 
11 #include "config.h"
12 
13 #include <sys/cdefs.h>
14 #if 0
15 #ifndef lint
16 static const char sccsid[] = "Id: getc.c,v 10.12 2001/06/25 15:19:30 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:30 ";
17 #endif /* not lint */
18 #else
19 __RCSID("$NetBSD: getc.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
20 #endif
21 
22 #include <sys/types.h>
23 #include <sys/queue.h>
24 #include <sys/time.h>
25 
26 #include <bitstring.h>
27 #include <ctype.h>
28 #include <limits.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 
32 #include "../common/common.h"
33 #include "vi.h"
34 
35 /*
36  * Character stream routines --
37  *	These routines return the file a character at a time.  There are two
38  *	special cases.  First, the end of a line, end of a file, start of a
39  *	file and empty lines are returned as special cases, and no character
40  *	is returned.  Second, empty lines include lines that have only white
41  *	space in them, because the vi search functions don't care about white
42  *	space, and this makes it easier for them to be consistent.
43  */
44 
45 /*
46  * cs_init --
47  *	Initialize character stream routines.
48  *
49  * PUBLIC: int cs_init __P((SCR *, VCS *));
50  */
51 int
cs_init(SCR * sp,VCS * csp)52 cs_init(SCR *sp, VCS *csp)
53 {
54 	int isempty;
55 
56 	if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) {
57 		if (isempty)
58 			msgq(sp, M_BERR, "177|Empty file");
59 		return (1);
60 	}
61 	if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
62 		csp->cs_cno = 0;
63 		csp->cs_flags = CS_EMP;
64 	} else {
65 		csp->cs_flags = 0;
66 		csp->cs_ch = csp->cs_bp[csp->cs_cno];
67 	}
68 	return (0);
69 }
70 
71 /*
72  * cs_next --
73  *	Retrieve the next character.
74  *
75  * PUBLIC: int cs_next __P((SCR *, VCS *));
76  */
77 int
cs_next(SCR * sp,VCS * csp)78 cs_next(SCR *sp, VCS *csp)
79 {
80 	CHAR_T *p;
81 
82 	switch (csp->cs_flags) {
83 	case CS_EMP:				/* EMP; get next line. */
84 	case CS_EOL:				/* EOL; get next line. */
85 		if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) {
86 			--csp->cs_lno;
87 			csp->cs_flags = CS_EOF;
88 		} else {
89 			csp->cs_bp = p;
90 			if (csp->cs_len == 0 ||
91 			    v_isempty(csp->cs_bp, csp->cs_len)) {
92 				csp->cs_cno = 0;
93 				csp->cs_flags = CS_EMP;
94 			} else {
95 				csp->cs_flags = 0;
96 				csp->cs_ch = csp->cs_bp[csp->cs_cno = 0];
97 			}
98 		}
99 		break;
100 	case 0:
101 		if (csp->cs_cno == csp->cs_len - 1)
102 			csp->cs_flags = CS_EOL;
103 		else
104 			csp->cs_ch = csp->cs_bp[++csp->cs_cno];
105 		break;
106 	case CS_EOF:				/* EOF. */
107 		break;
108 	default:
109 		abort();
110 		/* NOTREACHED */
111 	}
112 	return (0);
113 }
114 
115 /*
116  * cs_fspace --
117  *	If on a space, eat forward until something other than a
118  *	whitespace character.
119  *
120  * XXX
121  * Semantics of checking the current character were coded for the fword()
122  * function -- once the other word routines are converted, they may have
123  * to change.
124  *
125  * PUBLIC: int cs_fspace __P((SCR *, VCS *));
126  */
127 int
cs_fspace(SCR * sp,VCS * csp)128 cs_fspace(SCR *sp, VCS *csp)
129 {
130 	if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch))
131 		return (0);
132 	for (;;) {
133 		if (cs_next(sp, csp))
134 			return (1);
135 		if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch))
136 			break;
137 	}
138 	return (0);
139 }
140 
141 /*
142  * cs_fblank --
143  *	Eat forward to the next non-whitespace character.
144  *
145  * PUBLIC: int cs_fblank __P((SCR *, VCS *));
146  */
147 int
cs_fblank(SCR * sp,VCS * csp)148 cs_fblank(SCR *sp, VCS *csp)
149 {
150 	for (;;) {
151 		if (cs_next(sp, csp))
152 			return (1);
153 		if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
154 		    (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch)))
155 			continue;
156 		break;
157 	}
158 	return (0);
159 }
160 
161 /*
162  * cs_prev --
163  *	Retrieve the previous character.
164  *
165  * PUBLIC: int cs_prev __P((SCR *, VCS *));
166  */
167 int
cs_prev(SCR * sp,VCS * csp)168 cs_prev(SCR *sp, VCS *csp)
169 {
170 	switch (csp->cs_flags) {
171 	case CS_EMP:				/* EMP; get previous line. */
172 	case CS_EOL:				/* EOL; get previous line. */
173 		if (csp->cs_lno == 1) {		/* SOF. */
174 			csp->cs_flags = CS_SOF;
175 			break;
176 		}
177 		if (db_get(sp,			/* The line should exist. */
178 		    --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) {
179 			++csp->cs_lno;
180 			return (1);
181 		}
182 		if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
183 			csp->cs_cno = 0;
184 			csp->cs_flags = CS_EMP;
185 		} else {
186 			csp->cs_flags = 0;
187 			csp->cs_cno = csp->cs_len - 1;
188 			csp->cs_ch = csp->cs_bp[csp->cs_cno];
189 		}
190 		break;
191 	case CS_EOF:				/* EOF: get previous char. */
192 	case 0:
193 		if (csp->cs_cno == 0)
194 			if (csp->cs_lno == 1)
195 				csp->cs_flags = CS_SOF;
196 			else
197 				csp->cs_flags = CS_EOL;
198 		else
199 			csp->cs_ch = csp->cs_bp[--csp->cs_cno];
200 		break;
201 	case CS_SOF:				/* SOF. */
202 		break;
203 	default:
204 		abort();
205 		/* NOTREACHED */
206 	}
207 	return (0);
208 }
209 
210 /*
211  * cs_bblank --
212  *	Eat backward to the next non-whitespace character.
213  *
214  * PUBLIC: int cs_bblank __P((SCR *, VCS *));
215  */
216 int
cs_bblank(SCR * sp,VCS * csp)217 cs_bblank(SCR *sp, VCS *csp)
218 {
219 	for (;;) {
220 		if (cs_prev(sp, csp))
221 			return (1);
222 		if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
223 		    (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch)))
224 			continue;
225 		break;
226 	}
227 	return (0);
228 }
229