File: | src/usr.bin/vi/build/../common/put.c |
Warning: | line 122, column 3 Null pointer passed as 1st argument to memory copy function |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: put.c,v 1.16 2016/05/27 09:18:11 martijn 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 | ||||
17 | #include <bitstring.h> | |||
18 | #include <ctype.h> | |||
19 | #include <limits.h> | |||
20 | #include <stdio.h> | |||
21 | #include <stdlib.h> | |||
22 | #include <string.h> | |||
23 | ||||
24 | #include "common.h" | |||
25 | ||||
26 | /* | |||
27 | * put -- | |||
28 | * Put text buffer contents into the file. | |||
29 | * | |||
30 | * PUBLIC: int put(SCR *, CB *, CHAR_T *, MARK *, MARK *, int); | |||
31 | */ | |||
32 | int | |||
33 | put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append) | |||
34 | { | |||
35 | CHAR_T name; | |||
36 | TEXT *ltp, *tp; | |||
37 | recno_t lno; | |||
38 | size_t blen, clen, len; | |||
39 | int rval; | |||
40 | char *bp, *p, *t; | |||
41 | ||||
42 | if (cbp == NULL((void *)0)) { | |||
| ||||
43 | if (namep == NULL((void *)0)) { | |||
44 | cbp = sp->gp->dcbp; | |||
45 | if (cbp == NULL((void *)0)) { | |||
46 | msgq(sp, M_ERR, | |||
47 | "The default buffer is empty"); | |||
48 | return (1); | |||
49 | } | |||
50 | } else { | |||
51 | name = *namep; | |||
52 | CBNAME(sp, cbp, name){ CHAR_T L__name; L__name = isupper(name) ? tolower(name) : ( name); for(((cbp)) = ((&(sp)->gp->cutq)->lh_first ); ((cbp))!= ((void *)0); ((cbp)) = (((cbp))->q.le_next)) if ((cbp)->name == L__name) break; }; | |||
53 | if (cbp == NULL((void *)0)) { | |||
54 | msgq(sp, M_ERR, "Buffer %s is empty", | |||
55 | KEY_NAME(sp, name)((unsigned char)(name) <= 254 ? (sp)->gp->cname[(unsigned char)(name)].name : v_key_name((sp), (name)))); | |||
56 | return (1); | |||
57 | } | |||
58 | } | |||
59 | } | |||
60 | tp = TAILQ_FIRST(&cbp->textq)((&cbp->textq)->tqh_first); | |||
61 | ||||
62 | /* | |||
63 | * It's possible to do a put into an empty file, meaning that the cut | |||
64 | * buffer simply becomes the file. It's a special case so that we can | |||
65 | * ignore it in general. | |||
66 | * | |||
67 | * !!! | |||
68 | * Historically, pasting into a file with no lines in vi would preserve | |||
69 | * the single blank line. This is surely a result of the fact that the | |||
70 | * historic vi couldn't deal with a file that had no lines in it. This | |||
71 | * implementation treats that as a bug, and does not retain the blank | |||
72 | * line. | |||
73 | * | |||
74 | * Historical practice is that the cursor ends at the first character | |||
75 | * in the file. | |||
76 | */ | |||
77 | if (cp->lno == 1) { | |||
78 | if (db_last(sp, &lno)) | |||
79 | return (1); | |||
80 | if (lno == 0) { | |||
81 | for (; tp; ++lno, ++sp->rptlines[L_ADDED0], | |||
82 | tp = TAILQ_NEXT(tp, q)((tp)->q.tqe_next)) | |||
83 | if (db_append(sp, 1, lno, tp->lb, tp->len)) | |||
84 | return (1); | |||
85 | rp->lno = 1; | |||
86 | rp->cno = 0; | |||
87 | return (0); | |||
88 | } | |||
89 | } | |||
90 | ||||
91 | /* If a line mode buffer, append each new line into the file. */ | |||
92 | if (F_ISSET(cbp, CB_LMODE)(((cbp)->flags) & ((0x01)))) { | |||
93 | lno = append ? cp->lno : cp->lno - 1; | |||
94 | rp->lno = lno + 1; | |||
95 | for (; tp; | |||
96 | ++lno, ++sp->rptlines[L_ADDED0], tp = TAILQ_NEXT(tp, q)((tp)->q.tqe_next)) | |||
97 | if (db_append(sp, 1, lno, tp->lb, tp->len)) | |||
98 | return (1); | |||
99 | rp->cno = 0; | |||
100 | (void)nonblank(sp, rp->lno, &rp->cno); | |||
101 | return (0); | |||
102 | } | |||
103 | ||||
104 | /* | |||
105 | * If buffer was cut in character mode, replace the current line with | |||
106 | * one built from the portion of the first line to the left of the | |||
107 | * split plus the first line in the CB. Append each intermediate line | |||
108 | * in the CB. Append a line built from the portion of the first line | |||
109 | * to the right of the split plus the last line in the CB. | |||
110 | * | |||
111 | * Get the first line. | |||
112 | */ | |||
113 | lno = cp->lno; | |||
114 | if (db_get(sp, lno, DBG_FATAL0x001, &p, &len)) | |||
115 | return (1); | |||
116 | ||||
117 | GET_SPACE_RET(sp, bp, blen, tp->len + len + 1){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp ; if (L__gp == ((void *)0) || (((L__gp)->flags) & ((0x0100 )))) { (bp) = ((void *)0); (blen) = 0; { void *L__bincp; if ( ((tp->len + len + 1)) > ((blen))) { if ((L__bincp = binc (((sp)), ((bp)), &((blen)), ((tp->len + len + 1)))) == ((void *)0)) return (1); ((bp)) = L__bincp; } }; } else { { void *L__bincp; if (((tp->len + len + 1)) > (L__gp->tmp_blen )) { if ((L__bincp = binc(((sp)), (L__gp->tmp_bp), &(L__gp ->tmp_blen), ((tp->len + len + 1)))) == ((void *)0)) return (1); (L__gp->tmp_bp) = L__bincp; } }; (bp) = L__gp->tmp_bp ; (blen) = L__gp->tmp_blen; (((L__gp)->flags) |= ((0x0100 ))); } }; | |||
118 | t = bp; | |||
119 | ||||
120 | /* Original line, left of the split. */ | |||
121 | if (len > 0 && (clen = cp->cno + (append ? 1 : 0)) > 0) { | |||
122 | memcpy(bp, p, clen); | |||
| ||||
123 | p += clen; | |||
124 | t += clen; | |||
125 | } | |||
126 | ||||
127 | /* First line from the CB. */ | |||
128 | if (tp->len != 0) { | |||
129 | memcpy(t, tp->lb, tp->len); | |||
130 | t += tp->len; | |||
131 | } | |||
132 | ||||
133 | /* Calculate length left in the original line. */ | |||
134 | clen = len == 0 ? 0 : len - (cp->cno + (append ? 1 : 0)); | |||
135 | ||||
136 | /* | |||
137 | * !!! | |||
138 | * In the historical 4BSD version of vi, character mode puts within | |||
139 | * a single line have two cursor behaviors: if the put is from the | |||
140 | * unnamed buffer, the cursor moves to the character inserted which | |||
141 | * appears last in the file. If the put is from a named buffer, | |||
142 | * the cursor moves to the character inserted which appears first | |||
143 | * in the file. In System III/V, it was changed at some point and | |||
144 | * the cursor always moves to the first character. In both versions | |||
145 | * of vi, character mode puts that cross line boundaries leave the | |||
146 | * cursor on the first character. Nvi implements the System III/V | |||
147 | * behavior, and expect POSIX.2 to do so as well. | |||
148 | */ | |||
149 | rp->lno = lno; | |||
150 | rp->cno = len == 0 ? 0 : sp->cno + (append && tp->len ? 1 : 0); | |||
151 | ||||
152 | /* | |||
153 | * If no more lines in the CB, append the rest of the original | |||
154 | * line and quit. Otherwise, build the last line before doing | |||
155 | * the intermediate lines, because the line changes will lose | |||
156 | * the cached line. | |||
157 | */ | |||
158 | if (TAILQ_NEXT(tp, q)((tp)->q.tqe_next) == NULL((void *)0)) { | |||
159 | if (clen > 0) { | |||
160 | memcpy(t, p, clen); | |||
161 | t += clen; | |||
162 | } | |||
163 | if (db_set(sp, lno, bp, t - bp)) | |||
164 | goto err; | |||
165 | if (sp->rptlchange != lno) { | |||
166 | sp->rptlchange = lno; | |||
167 | ++sp->rptlines[L_CHANGED1]; | |||
168 | } | |||
169 | } else { | |||
170 | /* | |||
171 | * Have to build both the first and last lines of the | |||
172 | * put before doing any sets or we'll lose the cached | |||
173 | * line. Build both the first and last lines in the | |||
174 | * same buffer, so we don't have to have another buffer | |||
175 | * floating around. | |||
176 | * | |||
177 | * Last part of original line; check for space, reset | |||
178 | * the pointer into the buffer. | |||
179 | */ | |||
180 | ltp = TAILQ_LAST(&cbp->textq, _texth)(*(((struct _texth *)((&cbp->textq)->tqh_last))-> tqh_last)); | |||
181 | len = t - bp; | |||
182 | ADD_SPACE_RET(sp, bp, blen, ltp->len + clen){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp ; if (L__gp != ((void *)0) && (bp) == L__gp->tmp_bp ) { (((L__gp)->flags) &= ~((0x0100))); { void *L__bincp ; if (((ltp->len + clen)) > (L__gp->tmp_blen)) { if ( (L__bincp = binc(((sp)), (L__gp->tmp_bp), &(L__gp-> tmp_blen), ((ltp->len + clen)))) == ((void *)0)) return (1 ); (L__gp->tmp_bp) = L__bincp; } }; (bp) = L__gp->tmp_bp ; (blen) = L__gp->tmp_blen; (((L__gp)->flags) |= ((0x0100 ))); } else { void *L__bincp; if (((ltp->len + clen)) > ((blen))) { if ((L__bincp = binc(((sp)), ((bp)), &((blen )), ((ltp->len + clen)))) == ((void *)0)) return (1); ((bp )) = L__bincp; } }; }; | |||
183 | t = bp + len; | |||
184 | ||||
185 | /* Add in last part of the CB. */ | |||
186 | memcpy(t, ltp->lb, ltp->len); | |||
187 | if (clen) | |||
188 | memcpy(t + ltp->len, p, clen); | |||
189 | clen += ltp->len; | |||
190 | ||||
191 | /* | |||
192 | * Now: bp points to the first character of the first | |||
193 | * line, t points to the last character of the last | |||
194 | * line, t - bp is the length of the first line, and | |||
195 | * clen is the length of the last. Just figured you'd | |||
196 | * want to know. | |||
197 | * | |||
198 | * Output the line replacing the original line. | |||
199 | */ | |||
200 | if (db_set(sp, lno, bp, t - bp)) | |||
201 | goto err; | |||
202 | if (sp->rptlchange != lno) { | |||
203 | sp->rptlchange = lno; | |||
204 | ++sp->rptlines[L_CHANGED1]; | |||
205 | } | |||
206 | ||||
207 | /* Output any intermediate lines in the CB. */ | |||
208 | for (tp = TAILQ_NEXT(tp, q)((tp)->q.tqe_next); TAILQ_NEXT(tp, q)((tp)->q.tqe_next); | |||
209 | ++lno, ++sp->rptlines[L_ADDED0], tp = TAILQ_NEXT(tp, q)((tp)->q.tqe_next)) | |||
210 | if (db_append(sp, 1, lno, tp->lb, tp->len)) | |||
211 | goto err; | |||
212 | ||||
213 | if (db_append(sp, 1, lno, t, clen)) | |||
214 | goto err; | |||
215 | ++sp->rptlines[L_ADDED0]; | |||
216 | } | |||
217 | rval = 0; | |||
218 | ||||
219 | if (0) | |||
220 | err: rval = 1; | |||
221 | ||||
222 | FREE_SPACE(sp, bp, blen){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp ; if (L__gp != ((void *)0) && (bp) == L__gp->tmp_bp ) (((L__gp)->flags) &= ~((0x0100))); else free(bp); }; | |||
223 | return (rval); | |||
224 | } |