1 /* $NetBSD: getc.c,v 1.2 2013/11/22 15:52:06 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 #ifndef lint 14 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 "; 15 #endif /* not lint */ 16 17 #include <sys/types.h> 18 #include <sys/queue.h> 19 #include <sys/time.h> 20 21 #include <bitstring.h> 22 #include <ctype.h> 23 #include <limits.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 27 #include "../common/common.h" 28 #include "vi.h" 29 30 /* 31 * Character stream routines -- 32 * These routines return the file a character at a time. There are two 33 * special cases. First, the end of a line, end of a file, start of a 34 * file and empty lines are returned as special cases, and no character 35 * is returned. Second, empty lines include lines that have only white 36 * space in them, because the vi search functions don't care about white 37 * space, and this makes it easier for them to be consistent. 38 */ 39 40 /* 41 * cs_init -- 42 * Initialize character stream routines. 43 * 44 * PUBLIC: int cs_init __P((SCR *, VCS *)); 45 */ 46 int 47 cs_init(SCR *sp, 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(SCR *sp, VCS *csp) 74 { 75 CHAR_T *p; 76 77 switch (csp->cs_flags) { 78 case CS_EMP: /* EMP; get next line. */ 79 case CS_EOL: /* EOL; get next line. */ 80 if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) { 81 --csp->cs_lno; 82 csp->cs_flags = CS_EOF; 83 } else { 84 csp->cs_bp = p; 85 if (csp->cs_len == 0 || 86 v_isempty(csp->cs_bp, csp->cs_len)) { 87 csp->cs_cno = 0; 88 csp->cs_flags = CS_EMP; 89 } else { 90 csp->cs_flags = 0; 91 csp->cs_ch = csp->cs_bp[csp->cs_cno = 0]; 92 } 93 } 94 break; 95 case 0: 96 if (csp->cs_cno == csp->cs_len - 1) 97 csp->cs_flags = CS_EOL; 98 else 99 csp->cs_ch = csp->cs_bp[++csp->cs_cno]; 100 break; 101 case CS_EOF: /* EOF. */ 102 break; 103 default: 104 abort(); 105 /* NOTREACHED */ 106 } 107 return (0); 108 } 109 110 /* 111 * cs_fspace -- 112 * If on a space, eat forward until something other than a 113 * whitespace character. 114 * 115 * XXX 116 * Semantics of checking the current character were coded for the fword() 117 * function -- once the other word routines are converted, they may have 118 * to change. 119 * 120 * PUBLIC: int cs_fspace __P((SCR *, VCS *)); 121 */ 122 int 123 cs_fspace(SCR *sp, VCS *csp) 124 { 125 if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch)) 126 return (0); 127 for (;;) { 128 if (cs_next(sp, csp)) 129 return (1); 130 if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch)) 131 break; 132 } 133 return (0); 134 } 135 136 /* 137 * cs_fblank -- 138 * Eat forward to the next non-whitespace character. 139 * 140 * PUBLIC: int cs_fblank __P((SCR *, VCS *)); 141 */ 142 int 143 cs_fblank(SCR *sp, VCS *csp) 144 { 145 for (;;) { 146 if (cs_next(sp, csp)) 147 return (1); 148 if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || 149 (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch))) 150 continue; 151 break; 152 } 153 return (0); 154 } 155 156 /* 157 * cs_prev -- 158 * Retrieve the previous character. 159 * 160 * PUBLIC: int cs_prev __P((SCR *, VCS *)); 161 */ 162 int 163 cs_prev(SCR *sp, VCS *csp) 164 { 165 switch (csp->cs_flags) { 166 case CS_EMP: /* EMP; get previous line. */ 167 case CS_EOL: /* EOL; get previous line. */ 168 if (csp->cs_lno == 1) { /* SOF. */ 169 csp->cs_flags = CS_SOF; 170 break; 171 } 172 if (db_get(sp, /* The line should exist. */ 173 --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) { 174 ++csp->cs_lno; 175 return (1); 176 } 177 if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { 178 csp->cs_cno = 0; 179 csp->cs_flags = CS_EMP; 180 } else { 181 csp->cs_flags = 0; 182 csp->cs_cno = csp->cs_len - 1; 183 csp->cs_ch = csp->cs_bp[csp->cs_cno]; 184 } 185 break; 186 case CS_EOF: /* EOF: get previous char. */ 187 case 0: 188 if (csp->cs_cno == 0) 189 if (csp->cs_lno == 1) 190 csp->cs_flags = CS_SOF; 191 else 192 csp->cs_flags = CS_EOL; 193 else 194 csp->cs_ch = csp->cs_bp[--csp->cs_cno]; 195 break; 196 case CS_SOF: /* SOF. */ 197 break; 198 default: 199 abort(); 200 /* NOTREACHED */ 201 } 202 return (0); 203 } 204 205 /* 206 * cs_bblank -- 207 * Eat backward to the next non-whitespace character. 208 * 209 * PUBLIC: int cs_bblank __P((SCR *, VCS *)); 210 */ 211 int 212 cs_bblank(SCR *sp, VCS *csp) 213 { 214 for (;;) { 215 if (cs_prev(sp, csp)) 216 return (1); 217 if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || 218 (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch))) 219 continue; 220 break; 221 } 222 return (0); 223 } 224