File: | src/usr.bin/vi/build/../common/put.c |
Warning: | line 186, 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
| ||||
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
| ||||
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 | } |