Merge from vendor branch BINUTILS:
[dragonfly.git] / contrib / nvi / vi / getc.c
1 /*-
2  * Copyright (c) 1992, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1992, 1993, 1994, 1995, 1996
5  *      Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  *
9  * @(#)getc.c   10.10 (Berkeley) 3/6/96
10  * $DragonFly: src/contrib/nvi/vi/getc.c,v 1.2 2003/06/17 04:24:04 dillon Exp $
11  */
12
13 #include "config.h"
14
15 #include <sys/types.h>
16 #include <sys/queue.h>
17 #include <sys/time.h>
18
19 #include <bitstring.h>
20 #include <ctype.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "../common/common.h"
26 #include "vi.h"
27
28 /*
29  * Character stream routines --
30  *      These routines return the file a character at a time.  There are two
31  *      special cases.  First, the end of a line, end of a file, start of a
32  *      file and empty lines are returned as special cases, and no character
33  *      is returned.  Second, empty lines include lines that have only white
34  *      space in them, because the vi search functions don't care about white
35  *      space, and this makes it easier for them to be consistent.
36  */
37
38 /*
39  * cs_init --
40  *      Initialize character stream routines.
41  *
42  * PUBLIC: int cs_init __P((SCR *, VCS *));
43  */
44 int
45 cs_init(sp, csp)
46         SCR *sp;
47         VCS *csp;
48 {
49         int isempty;
50
51         if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &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 __P((SCR *, VCS *));
71  */
72 int
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 __P((SCR *, VCS *));
123  */
124 int
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 __P((SCR *, VCS *));
145  */
146 int
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 __P((SCR *, VCS *));
167  */
168 int
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, &csp->cs_bp, &csp->cs_len)) {
182                         ++csp->cs_lno;
183                         return (1);
184                 }
185                 if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
186                         csp->cs_cno = 0;
187                         csp->cs_flags = CS_EMP;
188                 } else {
189                         csp->cs_flags = 0;
190                         csp->cs_cno = csp->cs_len - 1;
191                         csp->cs_ch = csp->cs_bp[csp->cs_cno];
192                 }
193                 break;
194         case CS_EOF:                            /* EOF: get previous char. */
195         case 0:
196                 if (csp->cs_cno == 0)
197                         if (csp->cs_lno == 1)
198                                 csp->cs_flags = CS_SOF;
199                         else
200                                 csp->cs_flags = CS_EOL;
201                 else
202                         csp->cs_ch = csp->cs_bp[--csp->cs_cno];
203                 break;
204         case CS_SOF:                            /* SOF. */
205                 break;
206         default:
207                 abort();
208                 /* NOTREACHED */
209         }
210         return (0);
211 }
212
213 /*
214  * cs_bblank --
215  *      Eat backward to the next non-whitespace character.
216  *
217  * PUBLIC: int cs_bblank __P((SCR *, VCS *));
218  */
219 int
220 cs_bblank(sp, csp)
221         SCR *sp;
222         VCS *csp;
223 {
224         for (;;) {
225                 if (cs_prev(sp, csp))
226                         return (1);
227                 if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
228                     csp->cs_flags == 0 && isblank(csp->cs_ch))
229                         continue;
230                 break;
231         }
232         return (0);
233 }