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