PR/10367: Mason Loring Bliss: fix delete word near end of file. Patch from tnozaki.diff -r1.1.1.2 -r1.2 src/dist/nvi/common/delete.c
(christos)
--- src/dist/nvi/common/Attic/delete.c 2008/05/18 14:29:41 1.1.1.2
+++ src/dist/nvi/common/Attic/delete.c 2012/01/21 17:12:56 1.2
@@ -1,160 +1,165 @@ | @@ -1,160 +1,165 @@ | |||
1 | /* $NetBSD: delete.c,v 1.1.1.2 2008/05/18 14:29:41 aymeric Exp $ */ | 1 | /* $NetBSD: delete.c,v 1.2 2012/01/21 17:12:56 christos Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1992, 1993, 1994 | 4 | * Copyright (c) 1992, 1993, 1994 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 | 6 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 | |
7 | * Keith Bostic. All rights reserved. | 7 | * Keith Bostic. All rights reserved. | |
8 | * | 8 | * | |
9 | * See the LICENSE file for redistribution information. | 9 | * See the LICENSE file for redistribution information. | |
10 | */ | 10 | */ | |
11 | 11 | |||
12 | #include "config.h" | 12 | #include "config.h" | |
13 | 13 | |||
14 | #ifndef lint | 14 | #ifndef lint | |
15 | static const char sccsid[] = "Id: delete.c,v 10.17 2001/06/25 15:19:09 skimo Exp (Berkeley) Date: 2001/06/25 15:19:09"; | 15 | static const char sccsid[] = "Id: delete.c,v 10.17 2001/06/25 15:19:09 skimo Exp (Berkeley) Date: 2001/06/25 15:19:09"; | |
16 | #endif /* not lint */ | 16 | #endif /* not lint */ | |
17 | 17 | |||
18 | #include <sys/types.h> | 18 | #include <sys/types.h> | |
19 | #include <sys/queue.h> | 19 | #include <sys/queue.h> | |
20 | 20 | |||
21 | #include <bitstring.h> | 21 | #include <bitstring.h> | |
22 | #include <errno.h> | 22 | #include <errno.h> | |
23 | #include <limits.h> | 23 | #include <limits.h> | |
24 | #include <stdio.h> | 24 | #include <stdio.h> | |
25 | #include <stdlib.h> | 25 | #include <stdlib.h> | |
26 | #include <string.h> | 26 | #include <string.h> | |
27 | 27 | |||
28 | #include "common.h" | 28 | #include "common.h" | |
29 | 29 | |||
30 | /* | 30 | /* | |
31 | * del -- | 31 | * del -- | |
32 | * Delete a range of text. | 32 | * Delete a range of text. | |
33 | * | 33 | * | |
34 | * PUBLIC: int del __P((SCR *, MARK *, MARK *, int)); | 34 | * PUBLIC: int del __P((SCR *, MARK *, MARK *, int)); | |
35 | */ | 35 | */ | |
36 | int | 36 | int | |
37 | del(SCR *sp, MARK *fm, MARK *tm, int lmode) | 37 | del(SCR *sp, MARK *fm, MARK *tm, int lmode) | |
38 | { | 38 | { | |
39 | db_recno_t lno; | 39 | db_recno_t lno; | |
40 | size_t blen, len, nlen, tlen; | 40 | size_t blen, len, nlen, tlen; | |
41 | CHAR_T *bp, *p; | 41 | CHAR_T *bp, *p; | |
42 | int eof, rval; | 42 | int eof, rval; | |
43 | 43 | |||
44 | bp = NULL; | 44 | bp = NULL; | |
45 | 45 | |||
46 | /* Case 1 -- delete in line mode. */ | 46 | /* Case 1 -- delete in line mode. */ | |
47 | if (lmode) { | 47 | if (lmode) { | |
48 | for (lno = tm->lno; lno >= fm->lno; --lno) { | 48 | for (lno = tm->lno; lno >= fm->lno; --lno) { | |
49 | if (db_delete(sp, lno)) | 49 | if (db_delete(sp, lno)) | |
50 | return (1); | 50 | return (1); | |
51 | ++sp->rptlines[L_DELETED]; | 51 | ++sp->rptlines[L_DELETED]; | |
52 | if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp)) | 52 | if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp)) | |
53 | break; | 53 | break; | |
54 | } | 54 | } | |
55 | goto done; | 55 | goto done; | |
56 | } | 56 | } | |
57 | 57 | |||
58 | /* | 58 | /* | |
59 | * Case 2 -- delete to EOF. This is a special case because it's | 59 | * Case 2 -- delete to EOF. This is a special case because it's | |
60 | * easier to pick it off than try and find it in the other cases. | 60 | * easier to pick it off than try and find it in the other cases. | |
61 | */ | 61 | */ | |
62 | if (db_last(sp, &lno)) | 62 | if (db_last(sp, &lno)) | |
63 | return (1); | 63 | return (1); | |
64 | if (tm->lno >= lno) { | 64 | if (tm->lno >= lno) { | |
65 | if (tm->lno == lno) { | 65 | if (tm->lno == lno) { | |
66 | if (db_get(sp, lno, DBG_FATAL, &p, &len)) | 66 | if (db_get(sp, lno, DBG_FATAL, &p, &len)) | |
67 | return (1); | 67 | return (1); | |
68 | eof = tm->cno >= len ? 1 : 0; | 68 | eof = tm->cno >= len ? 1 : 0; | |
69 | } else | 69 | } else | |
70 | eof = 1; | 70 | eof = 1; | |
71 | if (eof) { | 71 | if (eof) { | |
72 | for (lno = tm->lno; lno > fm->lno; --lno) { | 72 | for (lno = tm->lno; lno > fm->lno; --lno) { | |
73 | if (db_delete(sp, lno)) | 73 | if (db_delete(sp, lno)) | |
74 | return (1); | 74 | return (1); | |
75 | ++sp->rptlines[L_DELETED]; | 75 | ++sp->rptlines[L_DELETED]; | |
76 | if (lno % | 76 | if (lno % | |
77 | INTERRUPT_CHECK == 0 && INTERRUPTED(sp)) | 77 | INTERRUPT_CHECK == 0 && INTERRUPTED(sp)) | |
78 | break; | 78 | break; | |
79 | } | 79 | } | |
80 | if (db_get(sp, fm->lno, DBG_FATAL, &p, &len)) | 80 | if (db_get(sp, fm->lno, DBG_FATAL, &p, &len)) | |
81 | return (1); | 81 | return (1); | |
82 | GET_SPACE_RETW(sp, bp, blen, fm->cno); | 82 | GET_SPACE_RETW(sp, bp, blen, fm->cno); | |
83 | MEMCPYW(bp, p, fm->cno); | 83 | MEMCPYW(bp, p, fm->cno); | |
84 | if (db_set(sp, fm->lno, bp, fm->cno)) | 84 | if (db_set(sp, fm->lno, bp, fm->cno)) | |
85 | return (1); | 85 | return (1); | |
86 | goto done; | 86 | goto done; | |
87 | } | 87 | } | |
88 | } | 88 | } | |
89 | 89 | |||
90 | /* Case 3 -- delete within a single line. */ | 90 | /* Case 3 -- delete within a single line. */ | |
91 | if (tm->lno == fm->lno) { | 91 | if (tm->lno == fm->lno) { | |
92 | if (tm->cno == fm->cno) { | |||
93 | if (db_delete(sp, fm->lno)) | |||
94 | return (1); | |||
95 | goto done; | |||
96 | } | |||
92 | if (db_get(sp, fm->lno, DBG_FATAL, &p, &len)) | 97 | if (db_get(sp, fm->lno, DBG_FATAL, &p, &len)) | |
93 | return (1); | 98 | return (1); | |
94 | GET_SPACE_RETW(sp, bp, blen, len); | 99 | GET_SPACE_RETW(sp, bp, blen, len); | |
95 | if (fm->cno != 0) | 100 | if (fm->cno != 0) | |
96 | MEMCPYW(bp, p, fm->cno); | 101 | MEMCPYW(bp, p, fm->cno); | |
97 | MEMCPYW(bp + fm->cno, p + (tm->cno + 1), | 102 | MEMCPYW(bp + fm->cno, p + (tm->cno + 1), | |
98 | len - (tm->cno + 1)); | 103 | len - (tm->cno + 1)); | |
99 | if (db_set(sp, fm->lno, | 104 | if (db_set(sp, fm->lno, | |
100 | bp, len - ((tm->cno - fm->cno) + 1))) | 105 | bp, len - ((tm->cno - fm->cno) + 1))) | |
101 | goto err; | 106 | goto err; | |
102 | goto done; | 107 | goto done; | |
103 | } | 108 | } | |
104 | 109 | |||
105 | /* | 110 | /* | |
106 | * Case 4 -- delete over multiple lines. | 111 | * Case 4 -- delete over multiple lines. | |
107 | * | 112 | * | |
108 | * Copy the start partial line into place. | 113 | * Copy the start partial line into place. | |
109 | */ | 114 | */ | |
110 | if ((tlen = fm->cno) != 0) { | 115 | if ((tlen = fm->cno) != 0) { | |
111 | if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL)) | 116 | if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL)) | |
112 | return (1); | 117 | return (1); | |
113 | GET_SPACE_RETW(sp, bp, blen, tlen + 256); | 118 | GET_SPACE_RETW(sp, bp, blen, tlen + 256); | |
114 | MEMCPYW(bp, p, tlen); | 119 | MEMCPYW(bp, p, tlen); | |
115 | } | 120 | } | |
116 | 121 | |||
117 | /* Copy the end partial line into place. */ | 122 | /* Copy the end partial line into place. */ | |
118 | if (db_get(sp, tm->lno, DBG_FATAL, &p, &len)) | 123 | if (db_get(sp, tm->lno, DBG_FATAL, &p, &len)) | |
119 | goto err; | 124 | goto err; | |
120 | if (len != 0 && tm->cno != len - 1) { | 125 | if (len != 0 && tm->cno != len - 1) { | |
121 | /* | 126 | /* | |
122 | * XXX | 127 | * XXX | |
123 | * We can overflow memory here, if the total length is greater | 128 | * We can overflow memory here, if the total length is greater | |
124 | * than SIZE_T_MAX. The only portable way I've found to test | 129 | * than SIZE_T_MAX. The only portable way I've found to test | |
125 | * is depending on the overflow being less than the value. | 130 | * is depending on the overflow being less than the value. | |
126 | */ | 131 | */ | |
127 | nlen = (len - (tm->cno + 1)) + tlen; | 132 | nlen = (len - (tm->cno + 1)) + tlen; | |
128 | if (tlen > nlen) { | 133 | if (tlen > nlen) { | |
129 | msgq(sp, M_ERR, "002|Line length overflow"); | 134 | msgq(sp, M_ERR, "002|Line length overflow"); | |
130 | goto err; | 135 | goto err; | |
131 | } | 136 | } | |
132 | if (tlen == 0) { | 137 | if (tlen == 0) { | |
133 | GET_SPACE_RETW(sp, bp, blen, nlen); | 138 | GET_SPACE_RETW(sp, bp, blen, nlen); | |
134 | } else | 139 | } else | |
135 | ADD_SPACE_RETW(sp, bp, blen, nlen); | 140 | ADD_SPACE_RETW(sp, bp, blen, nlen); | |
136 | 141 | |||
137 | MEMCPYW(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1)); | 142 | MEMCPYW(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1)); | |
138 | tlen += len - (tm->cno + 1); | 143 | tlen += len - (tm->cno + 1); | |
139 | } | 144 | } | |
140 | 145 | |||
141 | /* Set the current line. */ | 146 | /* Set the current line. */ | |
142 | if (db_set(sp, fm->lno, bp, tlen)) | 147 | if (db_set(sp, fm->lno, bp, tlen)) | |
143 | goto err; | 148 | goto err; | |
144 | 149 | |||
145 | /* Delete the last and intermediate lines. */ | 150 | /* Delete the last and intermediate lines. */ | |
146 | for (lno = tm->lno; lno > fm->lno; --lno) { | 151 | for (lno = tm->lno; lno > fm->lno; --lno) { | |
147 | if (db_delete(sp, lno)) | 152 | if (db_delete(sp, lno)) | |
148 | goto err; | 153 | goto err; | |
149 | ++sp->rptlines[L_DELETED]; | 154 | ++sp->rptlines[L_DELETED]; | |
150 | if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp)) | 155 | if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp)) | |
151 | break; | 156 | break; | |
152 | } | 157 | } | |
153 | 158 | |||
154 | done: rval = 0; | 159 | done: rval = 0; | |
155 | if (0) | 160 | if (0) | |
156 | err: rval = 1; | 161 | err: rval = 1; | |
157 | if (bp != NULL) | 162 | if (bp != NULL) | |
158 | FREE_SPACEW(sp, bp, blen); | 163 | FREE_SPACEW(sp, bp, blen); | |
159 | return (rval); | 164 | return (rval); | |
160 | } | 165 | } |
--- src/dist/nvi/vi/Attic/getc.c 2011/03/21 14:53:04 1.3
+++ src/dist/nvi/vi/Attic/getc.c 2012/01/21 17:12:56 1.4
@@ -1,224 +1,228 @@ | @@ -1,224 +1,228 @@ | |||
1 | /* $NetBSD: getc.c,v 1.3 2011/03/21 14:53:04 tnozaki Exp $ */ | 1 | /* $NetBSD: getc.c,v 1.4 2012/01/21 17:12:56 christos Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1992, 1993, 1994 | 4 | * Copyright (c) 1992, 1993, 1994 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 | 6 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 | |
7 | * Keith Bostic. All rights reserved. | 7 | * Keith Bostic. All rights reserved. | |
8 | * | 8 | * | |
9 | * See the LICENSE file for redistribution information. | 9 | * See the LICENSE file for redistribution information. | |
10 | */ | 10 | */ | |
11 | 11 | |||
12 | #include "config.h" | 12 | #include "config.h" | |
13 | 13 | |||
14 | #ifndef lint | 14 | #ifndef lint | |
15 | 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 | 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"; | |
16 | #endif /* not lint */ | 16 | #endif /* not lint */ | |
17 | 17 | |||
18 | #include <sys/types.h> | 18 | #include <sys/types.h> | |
19 | #include <sys/queue.h> | 19 | #include <sys/queue.h> | |
20 | #include <sys/time.h> | 20 | #include <sys/time.h> | |
21 | 21 | |||
22 | #include <bitstring.h> | 22 | #include <bitstring.h> | |
23 | #include <ctype.h> | 23 | #include <ctype.h> | |
24 | #include <limits.h> | 24 | #include <limits.h> | |
25 | #include <stdio.h> | 25 | #include <stdio.h> | |
26 | #include <stdlib.h> | 26 | #include <stdlib.h> | |
27 | 27 | |||
28 | #include "../common/common.h" | 28 | #include "../common/common.h" | |
29 | #include "vi.h" | 29 | #include "vi.h" | |
30 | 30 | |||
31 | /* | 31 | /* | |
32 | * Character stream routines -- | 32 | * Character stream routines -- | |
33 | * These routines return the file a character at a time. There are two | 33 | * These routines return the file a character at a time. There are two | |
34 | * special cases. First, the end of a line, end of a file, start of a | 34 | * special cases. First, the end of a line, end of a file, start of a | |
35 | * file and empty lines are returned as special cases, and no character | 35 | * file and empty lines are returned as special cases, and no character | |
36 | * is returned. Second, empty lines include lines that have only white | 36 | * is returned. Second, empty lines include lines that have only white | |
37 | * space in them, because the vi search functions don't care about white | 37 | * space in them, because the vi search functions don't care about white | |
38 | * space, and this makes it easier for them to be consistent. | 38 | * space, and this makes it easier for them to be consistent. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | /* | 41 | /* | |
42 | * cs_init -- | 42 | * cs_init -- | |
43 | * Initialize character stream routines. | 43 | * Initialize character stream routines. | |
44 | * | 44 | * | |
45 | * PUBLIC: int cs_init __P((SCR *, VCS *)); | 45 | * PUBLIC: int cs_init __P((SCR *, VCS *)); | |
46 | */ | 46 | */ | |
47 | int | 47 | int | |
48 | cs_init(SCR *sp, VCS *csp) | 48 | cs_init(SCR *sp, VCS *csp) | |
49 | { | 49 | { | |
50 | int isempty; | 50 | int isempty; | |
51 | 51 | |||
52 | if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) { | 52 | if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) { | |
53 | if (isempty) | 53 | if (isempty) | |
54 | msgq(sp, M_BERR, "177|Empty file"); | 54 | msgq(sp, M_BERR, "177|Empty file"); | |
55 | return (1); | 55 | return (1); | |
56 | } | 56 | } | |
57 | if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { | 57 | if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { | |
58 | csp->cs_cno = 0; | 58 | csp->cs_cno = 0; | |
59 | csp->cs_flags = CS_EMP; | 59 | csp->cs_flags = CS_EMP; | |
60 | } else { | 60 | } else { | |
61 | csp->cs_flags = 0; | 61 | csp->cs_flags = 0; | |
62 | csp->cs_ch = csp->cs_bp[csp->cs_cno]; | 62 | csp->cs_ch = csp->cs_bp[csp->cs_cno]; | |
63 | } | 63 | } | |
64 | return (0); | 64 | return (0); | |
65 | } | 65 | } | |
66 | 66 | |||
67 | /* | 67 | /* | |
68 | * cs_next -- | 68 | * cs_next -- | |
69 | * Retrieve the next character. | 69 | * Retrieve the next character. | |
70 | * | 70 | * | |
71 | * PUBLIC: int cs_next __P((SCR *, VCS *)); | 71 | * PUBLIC: int cs_next __P((SCR *, VCS *)); | |
72 | */ | 72 | */ | |
73 | int | 73 | int | |
74 | cs_next(SCR *sp, VCS *csp) | 74 | cs_next(SCR *sp, VCS *csp) | |
75 | { | 75 | { | |
76 | CHAR_T *p; | 76 | CHAR_T *p; | |
77 | 77 | |||
78 | switch (csp->cs_flags) { | 78 | switch (csp->cs_flags) { | |
79 | case CS_EMP: /* EMP; get next line. */ | 79 | case CS_EMP: /* EMP; get next line. */ | |
80 | case CS_EOL: /* EOL; get next line. */ | 80 | case CS_EOL: /* EOL; get next line. */ | |
81 | if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) { | 81 | if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) { | |
82 | --csp->cs_lno; | 82 | --csp->cs_lno; | |
83 | csp->cs_flags = CS_EOF; | 83 | csp->cs_flags = CS_EOF; | |
84 | } else { | 84 | } else { | |
85 | csp->cs_bp = p; | 85 | csp->cs_bp = p; | |
86 | if (csp->cs_len == 0 || | 86 | if (csp->cs_len == 0 || | |
87 | v_isempty(csp->cs_bp, csp->cs_len)) { | 87 | v_isempty(csp->cs_bp, csp->cs_len)) { | |
88 | csp->cs_cno = 0; | 88 | csp->cs_cno = 0; | |
89 | csp->cs_flags = CS_EMP; | 89 | csp->cs_flags = CS_EMP; | |
90 | } else { | 90 | } else { | |
91 | csp->cs_flags = 0; | 91 | csp->cs_flags = 0; | |
92 | csp->cs_ch = csp->cs_bp[csp->cs_cno = 0]; | 92 | csp->cs_ch = csp->cs_bp[csp->cs_cno = 0]; | |
93 | } | 93 | } | |
94 | } | 94 | } | |
95 | break; | 95 | break; | |
96 | case 0: | 96 | case 0: | |
97 | if (csp->cs_cno == csp->cs_len - 1) | 97 | if (csp->cs_cno == csp->cs_len - 1) | |
98 | csp->cs_flags = CS_EOL; | 98 | csp->cs_flags = CS_EOL; | |
99 | else | 99 | else | |
100 | csp->cs_ch = csp->cs_bp[++csp->cs_cno]; | 100 | csp->cs_ch = csp->cs_bp[++csp->cs_cno]; | |
101 | break; | 101 | break; | |
102 | case CS_EOF: /* EOF. */ | 102 | case CS_EOF: /* EOF. */ | |
103 | break; | 103 | break; | |
104 | default: | 104 | default: | |
105 | abort(); | 105 | abort(); | |
106 | /* NOTREACHED */ | 106 | /* NOTREACHED */ | |
107 | } | 107 | } | |
108 | return (0); | 108 | return (0); | |
109 | } | 109 | } | |
110 | 110 | |||
111 | /* | 111 | /* | |
112 | * cs_fspace -- | 112 | * cs_fspace -- | |
113 | * If on a space, eat forward until something other than a | 113 | * If on a space, eat forward until something other than a | |
114 | * whitespace character. | 114 | * whitespace character. | |
115 | * | 115 | * | |
116 | * XXX | 116 | * XXX | |
117 | * Semantics of checking the current character were coded for the fword() | 117 | * Semantics of checking the current character were coded for the fword() | |
118 | * function -- once the other word routines are converted, they may have | 118 | * function -- once the other word routines are converted, they may have | |
119 | * to change. | 119 | * to change. | |
120 | * | 120 | * | |
121 | * PUBLIC: int cs_fspace __P((SCR *, VCS *)); | 121 | * PUBLIC: int cs_fspace __P((SCR *, VCS *)); | |
122 | */ | 122 | */ | |
123 | int | 123 | int | |
124 | cs_fspace(SCR *sp, VCS *csp) | 124 | cs_fspace(SCR *sp, VCS *csp) | |
125 | { | 125 | { | |
126 | if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch)) | 126 | if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch)) | |
127 | return (0); | 127 | return (0); | |
128 | for (;;) { | 128 | for (;;) { | |
129 | if (cs_next(sp, csp)) | 129 | if (cs_next(sp, csp)) | |
130 | return (1); | 130 | return (1); | |
131 | if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch)) | 131 | if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch)) | |
132 | break; | 132 | break; | |
133 | } | 133 | } | |
134 | return (0); | 134 | return (0); | |
135 | } | 135 | } | |
136 | 136 | |||
137 | /* | 137 | /* | |
138 | * cs_fblank -- | 138 | * cs_fblank -- | |
139 | * Eat forward to the next non-whitespace character. | 139 | * Eat forward to the next non-whitespace character. | |
140 | * | 140 | * | |
141 | * PUBLIC: int cs_fblank __P((SCR *, VCS *)); | 141 | * PUBLIC: int cs_fblank __P((SCR *, VCS *)); | |
142 | */ | 142 | */ | |
143 | int | 143 | int | |
144 | cs_fblank(SCR *sp, VCS *csp) | 144 | cs_fblank(SCR *sp, VCS *csp) | |
145 | { | 145 | { | |
146 | if (csp->cs_flags == CS_EMP) | |||
147 | return (0); | |||
146 | for (;;) { | 148 | for (;;) { | |
147 | if (cs_next(sp, csp)) | 149 | if (cs_next(sp, csp)) | |
148 | return (1); | 150 | return (1); | |
149 | if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || | 151 | if (csp->cs_flags == CS_EOL || | |
150 | (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch))) | 152 | (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch))) | |
151 | continue; | 153 | continue; | |
152 | break; | 154 | break; | |
153 | } | 155 | } | |
154 | return (0); | 156 | return (0); | |
155 | } | 157 | } | |
156 | 158 | |||
157 | /* | 159 | /* | |
158 | * cs_prev -- | 160 | * cs_prev -- | |
159 | * Retrieve the previous character. | 161 | * Retrieve the previous character. | |
160 | * | 162 | * | |
161 | * PUBLIC: int cs_prev __P((SCR *, VCS *)); | 163 | * PUBLIC: int cs_prev __P((SCR *, VCS *)); | |
162 | */ | 164 | */ | |
163 | int | 165 | int | |
164 | cs_prev(SCR *sp, VCS *csp) | 166 | cs_prev(SCR *sp, VCS *csp) | |
165 | { | 167 | { | |
166 | switch (csp->cs_flags) { | 168 | switch (csp->cs_flags) { | |
167 | case CS_EMP: /* EMP; get previous line. */ | 169 | case CS_EMP: /* EMP; get previous line. */ | |
168 | case CS_EOL: /* EOL; get previous line. */ | 170 | case CS_EOL: /* EOL; get previous line. */ | |
169 | if (csp->cs_lno == 1) { /* SOF. */ | 171 | if (csp->cs_lno == 1) { /* SOF. */ | |
170 | csp->cs_flags = CS_SOF; | 172 | csp->cs_flags = CS_SOF; | |
171 | break; | 173 | break; | |
172 | } | 174 | } | |
173 | if (db_get(sp, /* The line should exist. */ | 175 | if (db_get(sp, /* The line should exist. */ | |
174 | --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) { | 176 | --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) { | |
175 | ++csp->cs_lno; | 177 | ++csp->cs_lno; | |
176 | return (1); | 178 | return (1); | |
177 | } | 179 | } | |
178 | if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { | 180 | if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) { | |
179 | csp->cs_cno = 0; | 181 | csp->cs_cno = 0; | |
180 | csp->cs_flags = CS_EMP; | 182 | csp->cs_flags = CS_EMP; | |
181 | } else { | 183 | } else { | |
182 | csp->cs_flags = 0; | 184 | csp->cs_flags = 0; | |
183 | csp->cs_cno = csp->cs_len - 1; | 185 | csp->cs_cno = csp->cs_len - 1; | |
184 | csp->cs_ch = csp->cs_bp[csp->cs_cno]; | 186 | csp->cs_ch = csp->cs_bp[csp->cs_cno]; | |
185 | } | 187 | } | |
186 | break; | 188 | break; | |
187 | case CS_EOF: /* EOF: get previous char. */ | 189 | case CS_EOF: /* EOF: get previous char. */ | |
188 | case 0: | 190 | case 0: | |
189 | if (csp->cs_cno == 0) | 191 | if (csp->cs_cno == 0) | |
190 | if (csp->cs_lno == 1) | 192 | if (csp->cs_lno == 1) | |
191 | csp->cs_flags = CS_SOF; | 193 | csp->cs_flags = CS_SOF; | |
192 | else | 194 | else | |
193 | csp->cs_flags = CS_EOL; | 195 | csp->cs_flags = CS_EOL; | |
194 | else | 196 | else | |
195 | csp->cs_ch = csp->cs_bp[--csp->cs_cno]; | 197 | csp->cs_ch = csp->cs_bp[--csp->cs_cno]; | |
196 | break; | 198 | break; | |
197 | case CS_SOF: /* SOF. */ | 199 | case CS_SOF: /* SOF. */ | |
198 | break; | 200 | break; | |
199 | default: | 201 | default: | |
200 | abort(); | 202 | abort(); | |
201 | /* NOTREACHED */ | 203 | /* NOTREACHED */ | |
202 | } | 204 | } | |
203 | return (0); | 205 | return (0); | |
204 | } | 206 | } | |
205 | 207 | |||
206 | /* | 208 | /* | |
207 | * cs_bblank -- | 209 | * cs_bblank -- | |
208 | * Eat backward to the next non-whitespace character. | 210 | * Eat backward to the next non-whitespace character. | |
209 | * | 211 | * | |
210 | * PUBLIC: int cs_bblank __P((SCR *, VCS *)); | 212 | * PUBLIC: int cs_bblank __P((SCR *, VCS *)); | |
211 | */ | 213 | */ | |
212 | int | 214 | int | |
213 | cs_bblank(SCR *sp, VCS *csp) | 215 | cs_bblank(SCR *sp, VCS *csp) | |
214 | { | 216 | { | |
217 | if (csp->cs_flags == CS_EMP) | |||
218 | return (0); | |||
215 | for (;;) { | 219 | for (;;) { | |
216 | if (cs_prev(sp, csp)) | 220 | if (cs_prev(sp, csp)) | |
217 | return (1); | 221 | return (1); | |
218 | if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP || | 222 | if (csp->cs_flags == CS_EOL || | |
219 | (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch))) | 223 | (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch))) | |
220 | continue; | 224 | continue; | |
221 | break; | 225 | break; | |
222 | } | 226 | } | |
223 | return (0); | 227 | return (0); | |
224 | } | 228 | } |