aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-09-25 11:55:57 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-09-25 11:55:57 +0000
commitd9391b15f166cfc016f5768c8d6a89858e0d7e41 (patch)
tree0524b8ff17be49d32a88250a6b899e35b0d000d3
parenta545726d2baa08b28510336b32d85de91df51d9e (diff)
downloadbusybox-w32-d9391b15f166cfc016f5768c8d6a89858e0d7e41.tar.gz
busybox-w32-d9391b15f166cfc016f5768c8d6a89858e0d7e41.tar.bz2
busybox-w32-d9391b15f166cfc016f5768c8d6a89858e0d7e41.zip
ed: large cleanup
function old new delta bad_nums - 43 +43 skip_blank - 24 +24 getNum 557 578 +21 insertLine 159 163 +4 setCurNum 31 33 +2 lastNum 4 - -4 fileName 4 - -4 dirty 4 - -4 curNum 4 - -4 curLine 4 - -4 bufUsed 4 - -4 bufSize 4 - -4 bufPtr 4 - -4 bufBase 4 - -4 printLines 357 345 -12 findLine 165 152 -13 lines 16 - -16 deleteLines 203 144 -59 readLines 538 473 -65 addLines 163 87 -76 marks 104 - -104 termEdit 140 - -140 ed_main 3125 2654 -471 ------------------------------------------------------------------------------ (add/remove: 2/12 grow/shrink: 3/6 up/down: 94/-992) Total: -898 bytes text data bss dec hex filename 771142 1034 10564 782740 bf194 busybox_old 770265 1034 10404 781703 bed87 busybox_unstripped # size */ed.o text data bss dec hex filename 6370 0 156 6526 197e editors.org/ed.o 5505 0 0 5505 1581 editors/ed.o
-rw-r--r--editors/ed.c440
1 files changed, 135 insertions, 305 deletions
diff --git a/editors/ed.c b/editors/ed.c
index e6576b406..f5b9c39bb 100644
--- a/editors/ed.c
+++ b/editors/ed.c
@@ -9,6 +9,14 @@
9 9
10#include "libbb.h" 10#include "libbb.h"
11 11
12typedef struct LINE {
13 struct LINE *next;
14 struct LINE *prev;
15 int len;
16 char data[1];
17} LINE;
18
19
12#define searchString bb_common_bufsiz1 20#define searchString bb_common_bufsiz1
13 21
14enum { 22enum {
@@ -17,64 +25,92 @@ enum {
17 INITBUF_SIZE = 1024, /* initial buffer size */ 25 INITBUF_SIZE = 1024, /* initial buffer size */
18}; 26};
19 27
20typedef struct LINE { 28struct globals {
21 struct LINE *next; 29 int curNum;
22 struct LINE *prev; 30 int lastNum;
23 int len; 31 int bufUsed;
24 char data[1]; 32 int bufSize;
25} LINE; 33 LINE *curLine;
34 char *bufBase;
35 char *bufPtr;
36 char *fileName;
37 LINE lines;
38 smallint dirty;
39 int marks[26];
40};
41#define G (*ptr_to_globals)
42#define curLine (G.curLine )
43#define bufBase (G.bufBase )
44#define bufPtr (G.bufPtr )
45#define fileName (G.fileName )
46#define curNum (G.curNum )
47#define lastNum (G.lastNum )
48#define bufUsed (G.bufUsed )
49#define bufSize (G.bufSize )
50#define dirty (G.dirty )
51#define lines (G.lines )
52#define marks (G.marks )
53#define INIT_G() do { \
54 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
55} while (0)
26 56
27static LINE lines, *curLine;
28static int curNum, lastNum, marks[26], dirty;
29static char *bufBase, *bufPtr, *fileName;
30static int bufUsed, bufSize;
31 57
32static void doCommands(void); 58static void doCommands(void);
33static void subCommand(const char *cmd, int num1, int num2); 59static void subCommand(const char *cmd, int num1, int num2);
34static int getNum(const char **retcp, int *retHaveNum, int *retNum); 60static int getNum(const char **retcp, smallint *retHaveNum, int *retNum);
35static int setCurNum(int num); 61static int setCurNum(int num);
36static int initEdit(void);
37static void termEdit(void);
38static void addLines(int num); 62static void addLines(int num);
39static int insertLine(int num, const char *data, int len); 63static int insertLine(int num, const char *data, int len);
40static int deleteLines(int num1, int num2); 64static void deleteLines(int num1, int num2);
41static int printLines(int num1, int num2, int expandFlag); 65static int printLines(int num1, int num2, int expandFlag);
42static int writeLines(const char *file, int num1, int num2); 66static int writeLines(const char *file, int num1, int num2);
43static int readLines(const char *file, int num); 67static int readLines(const char *file, int num);
44static int searchLines(const char *str, int num1, int num2); 68static int searchLines(const char *str, int num1, int num2);
45static LINE *findLine(int num); 69static LINE *findLine(int num);
46
47static int findString(const LINE *lp, const char * str, int len, int offset); 70static int findString(const LINE *lp, const char * str, int len, int offset);
48 71
72
73static int bad_nums(int num1, int num2, const char *for_what)
74{
75 if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) {
76 bb_error_msg("bad line range for %s", for_what);
77 return 1;
78 }
79 return 0;
80}
81
82
83static char *skip_blank(const char *cp)
84{
85// NB: fix comment in skip_whitespace!
86 while (isblank(*cp))
87 cp++;
88 return (char *)cp;
89}
90
91
49int ed_main(int argc, char **argv); 92int ed_main(int argc, char **argv);
50int ed_main(int argc, char **argv) 93int ed_main(int argc, char **argv)
51{ 94{
52 if (!initEdit()) 95 INIT_G();
53 return EXIT_FAILURE;
54
55 if (argc > 1) {
56 fileName = strdup(argv[1]);
57 96
58 if (fileName == NULL) { 97 bufSize = INITBUF_SIZE;
59 bb_error_msg("no memory"); 98 bufBase = xmalloc(bufSize);
60 termEdit(); 99 bufPtr = bufBase;
61 return EXIT_SUCCESS; 100 lines.next = &lines;
62 } 101 lines.prev = &lines;
63 102
103 if (argc > 1) {
104 fileName = xstrdup(argv[1]);
64 if (!readLines(fileName, 1)) { 105 if (!readLines(fileName, 1)) {
65 termEdit();
66 return EXIT_SUCCESS; 106 return EXIT_SUCCESS;
67 } 107 }
68
69 if (lastNum) 108 if (lastNum)
70 setCurNum(1); 109 setCurNum(1);
71
72 dirty = FALSE; 110 dirty = FALSE;
73 } 111 }
74 112
75 doCommands(); 113 doCommands();
76
77 termEdit();
78 return EXIT_SUCCESS; 114 return EXIT_SUCCESS;
79} 115}
80 116
@@ -85,42 +121,25 @@ static void doCommands(void)
85{ 121{
86 const char *cp; 122 const char *cp;
87 char *endbuf, *newname, buf[USERSIZE]; 123 char *endbuf, *newname, buf[USERSIZE];
88 int len, num1, num2, have1, have2; 124 int len, num1, num2;
125 smallint have1, have2;
89 126
90 while (TRUE) { 127 while (TRUE) {
91 printf(": "); 128// NB: fix comment in lineedit.c!
92 fflush(stdout); 129 /* Returns:
93 130 * -1 on read errors or EOF, or on bare Ctrl-D.
94 if (fgets(buf, sizeof(buf), stdin) == NULL) 131 * 0 on ctrl-C,
95 return; 132 * >0 length of input string, including terminating '\n'
96 133 */
97 len = strlen(buf); 134 len = read_line_input(": ", buf, sizeof(buf), NULL);
98 135 if (len <= 0)
99 if (len == 0)
100 return; 136 return;
101
102 endbuf = &buf[len - 1]; 137 endbuf = &buf[len - 1];
103
104 if (*endbuf != '\n') {
105 bb_error_msg("command line too long");
106
107 do {
108 len = fgetc(stdin);
109 } while ((len != EOF) && (len != '\n'));
110
111 continue;
112 }
113
114 while ((endbuf > buf) && isblank(endbuf[-1])) 138 while ((endbuf > buf) && isblank(endbuf[-1]))
115 endbuf--; 139 endbuf--;
116
117 *endbuf = '\0'; 140 *endbuf = '\0';
118 141
119 cp = buf; 142 cp = skip_blank(buf);
120
121 while (isblank(*cp))
122 cp++;
123
124 have1 = FALSE; 143 have1 = FALSE;
125 have2 = FALSE; 144 have2 = FALSE;
126 145
@@ -132,28 +151,21 @@ static void doCommands(void)
132 if (!getNum(&cp, &have1, &num1)) 151 if (!getNum(&cp, &have1, &num1))
133 continue; 152 continue;
134 153
135 while (isblank(*cp)) 154 cp = skip_blank(cp);
136 cp++;
137 155
138 if (*cp == ',') { 156 if (*cp == ',') {
139 cp++; 157 cp++;
140
141 if (!getNum(&cp, &have2, &num2)) 158 if (!getNum(&cp, &have2, &num2))
142 continue; 159 continue;
143
144 if (!have1) 160 if (!have1)
145 num1 = 1; 161 num1 = 1;
146
147 if (!have2) 162 if (!have2)
148 num2 = lastNum; 163 num2 = lastNum;
149
150 have1 = TRUE; 164 have1 = TRUE;
151 have2 = TRUE; 165 have2 = TRUE;
152 } 166 }
153
154 if (!have1) 167 if (!have1)
155 num1 = curNum; 168 num1 = curNum;
156
157 if (!have2) 169 if (!have2)
158 num2 = num1; 170 num2 = num1;
159 171
@@ -176,10 +188,7 @@ static void doCommands(void)
176 bb_error_msg("bad file command"); 188 bb_error_msg("bad file command");
177 break; 189 break;
178 } 190 }
179 191 cp = skip_blank(cp);
180 while (isblank(*cp))
181 cp++;
182
183 if (*cp == '\0') { 192 if (*cp == '\0') {
184 if (fileName) 193 if (fileName)
185 printf("\"%s\"\n", fileName); 194 printf("\"%s\"\n", fileName);
@@ -187,17 +196,12 @@ static void doCommands(void)
187 printf("No file name\n"); 196 printf("No file name\n");
188 break; 197 break;
189 } 198 }
190
191 newname = strdup(cp); 199 newname = strdup(cp);
192
193 if (newname == NULL) { 200 if (newname == NULL) {
194 bb_error_msg("no memory for file name"); 201 bb_error_msg("no memory for file name");
195 break; 202 break;
196 } 203 }
197 204 free(fileName);
198 if (fileName)
199 free(fileName);
200
201 fileName = newname; 205 fileName = newname;
202 break; 206 break;
203 207
@@ -206,14 +210,11 @@ static void doCommands(void)
206 break; 210 break;
207 211
208 case 'k': 212 case 'k':
209 while (isblank(*cp)) 213 cp = skip_blank(cp);
210 cp++; 214 if ((*cp < 'a') || (*cp > 'z') || cp[1]) {
211
212 if ((*cp < 'a') || (*cp > 'a') || cp[1]) {
213 bb_error_msg("bad mark name"); 215 bb_error_msg("bad mark name");
214 break; 216 break;
215 } 217 }
216
217 marks[*cp - 'a'] = num2; 218 marks[*cp - 'a'] = num2;
218 break; 219 break;
219 220
@@ -226,30 +227,20 @@ static void doCommands(void)
226 break; 227 break;
227 228
228 case 'q': 229 case 'q':
229 while (isblank(*cp)) 230 cp = skip_blank(cp);
230 cp++;
231
232 if (have1 || *cp) { 231 if (have1 || *cp) {
233 bb_error_msg("bad quit command"); 232 bb_error_msg("bad quit command");
234 break; 233 break;
235 } 234 }
236
237 if (!dirty) 235 if (!dirty)
238 return; 236 return;
239 237 len = read_line_input("Really quit? ", buf, 16, NULL);
240 printf("Really quit? "); 238 /* read error/EOF - no way to continue */
241 fflush(stdout); 239 if (len < 0)
242 240 return;
243 buf[0] = '\0'; 241 cp = skip_blank(buf);
244 fgets(buf, sizeof(buf), stdin); 242 if ((*cp | 0x20) == 'y') /* Y or y */
245 cp = buf;
246
247 while (isblank(*cp))
248 cp++;
249
250 if ((*cp == 'y') || (*cp == 'Y'))
251 return; 243 return;
252
253 break; 244 break;
254 245
255 case 'r': 246 case 'r':
@@ -257,24 +248,17 @@ static void doCommands(void)
257 bb_error_msg("bad read command"); 248 bb_error_msg("bad read command");
258 break; 249 break;
259 } 250 }
260 251 cp = skip_blank(cp);
261 while (isblank(*cp))
262 cp++;
263
264 if (*cp == '\0') { 252 if (*cp == '\0') {
265 bb_error_msg("no file name"); 253 bb_error_msg("no file name");
266 break; 254 break;
267 } 255 }
268
269 if (!have1) 256 if (!have1)
270 num1 = lastNum; 257 num1 = lastNum;
271
272 if (readLines(cp, num1 + 1)) 258 if (readLines(cp, num1 + 1))
273 break; 259 break;
274
275 if (fileName == NULL) 260 if (fileName == NULL)
276 fileName = strdup(cp); 261 fileName = strdup(cp);
277
278 break; 262 break;
279 263
280 case 's': 264 case 's':
@@ -286,36 +270,30 @@ static void doCommands(void)
286 bb_error_msg("bad write command"); 270 bb_error_msg("bad write command");
287 break; 271 break;
288 } 272 }
289 273 cp = skip_blank(cp);
290 while (isblank(*cp))
291 cp++;
292
293 if (!have1) { 274 if (!have1) {
294 num1 = 1; 275 num1 = 1;
295 num2 = lastNum; 276 num2 = lastNum;
296 } 277 }
297
298 if (*cp == '\0') 278 if (*cp == '\0')
299 cp = fileName; 279 cp = fileName;
300
301 if (cp == NULL) { 280 if (cp == NULL) {
302 bb_error_msg("no file name specified"); 281 bb_error_msg("no file name specified");
303 break; 282 break;
304 } 283 }
305
306 writeLines(cp, num1, num2); 284 writeLines(cp, num1, num2);
307 break; 285 break;
308 286
309 case 'z': 287 case 'z':
310 switch (*cp) { 288 switch (*cp) {
311 case '-': 289 case '-':
312 printLines(curNum-21, curNum, FALSE); 290 printLines(curNum - 21, curNum, FALSE);
313 break; 291 break;
314 case '.': 292 case '.':
315 printLines(curNum-11, curNum+10, FALSE); 293 printLines(curNum - 11, curNum + 10, FALSE);
316 break; 294 break;
317 default: 295 default:
318 printLines(curNum, curNum+21, FALSE); 296 printLines(curNum, curNum + 21, FALSE);
319 break; 297 break;
320 } 298 }
321 break; 299 break;
@@ -325,29 +303,24 @@ static void doCommands(void)
325 bb_error_msg("no arguments allowed"); 303 bb_error_msg("no arguments allowed");
326 break; 304 break;
327 } 305 }
328
329 printLines(curNum, curNum, FALSE); 306 printLines(curNum, curNum, FALSE);
330 break; 307 break;
331 308
332 case '-': 309 case '-':
333 if (setCurNum(curNum - 1)) 310 if (setCurNum(curNum - 1))
334 printLines(curNum, curNum, FALSE); 311 printLines(curNum, curNum, FALSE);
335
336 break; 312 break;
337 313
338 case '=': 314 case '=':
339 printf("%d\n", num1); 315 printf("%d\n", num1);
340 break; 316 break;
341
342 case '\0': 317 case '\0':
343 if (have1) { 318 if (have1) {
344 printLines(num2, num2, FALSE); 319 printLines(num2, num2, FALSE);
345 break; 320 break;
346 } 321 }
347
348 if (setCurNum(curNum + 1)) 322 if (setCurNum(curNum + 1))
349 printLines(curNum, curNum, FALSE); 323 printLines(curNum, curNum, FALSE);
350
351 break; 324 break;
352 325
353 default: 326 default:
@@ -362,17 +335,15 @@ static void doCommands(void)
362 * Do the substitute command. 335 * Do the substitute command.
363 * The current line is set to the last substitution done. 336 * The current line is set to the last substitution done.
364 */ 337 */
365static void subCommand(const char * cmd, int num1, int num2) 338static void subCommand(const char *cmd, int num1, int num2)
366{ 339{
367 char *cp, *oldStr, *newStr, buf[USERSIZE]; 340 char *cp, *oldStr, *newStr, buf[USERSIZE];
368 int delim, oldLen, newLen, deltaLen, offset; 341 int delim, oldLen, newLen, deltaLen, offset;
369 LINE *lp, *nlp; 342 LINE *lp, *nlp;
370 int globalFlag, printFlag, didSub, needPrint; 343 int globalFlag, printFlag, didSub, needPrint;
371 344
372 if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { 345 if (bad_nums(num1, num2, "substitute"))
373 bb_error_msg("bad line range for substitute");
374 return; 346 return;
375 }
376 347
377 globalFlag = FALSE; 348 globalFlag = FALSE;
378 printFlag = FALSE; 349 printFlag = FALSE;
@@ -394,7 +365,6 @@ static void subCommand(const char * cmd, int num1, int num2)
394 oldStr = cp; 365 oldStr = cp;
395 366
396 cp = strchr(cp, delim); 367 cp = strchr(cp, delim);
397
398 if (cp == NULL) { 368 if (cp == NULL) {
399 bb_error_msg("missing 2nd delimiter for substitute"); 369 bb_error_msg("missing 2nd delimiter for substitute");
400 return; 370 return;
@@ -414,11 +384,9 @@ static void subCommand(const char * cmd, int num1, int num2)
414 case 'g': 384 case 'g':
415 globalFlag = TRUE; 385 globalFlag = TRUE;
416 break; 386 break;
417
418 case 'p': 387 case 'p':
419 printFlag = TRUE; 388 printFlag = TRUE;
420 break; 389 break;
421
422 default: 390 default:
423 bb_error_msg("unknown option for substitute"); 391 bb_error_msg("unknown option for substitute");
424 return; 392 return;
@@ -429,7 +397,6 @@ static void subCommand(const char * cmd, int num1, int num2)
429 bb_error_msg("no previous search string"); 397 bb_error_msg("no previous search string");
430 return; 398 return;
431 } 399 }
432
433 oldStr = searchString; 400 oldStr = searchString;
434 } 401 }
435 402
@@ -437,7 +404,6 @@ static void subCommand(const char * cmd, int num1, int num2)
437 strcpy(searchString, oldStr); 404 strcpy(searchString, oldStr);
438 405
439 lp = findLine(num1); 406 lp = findLine(num1);
440
441 if (lp == NULL) 407 if (lp == NULL)
442 return; 408 return;
443 409
@@ -455,11 +421,9 @@ static void subCommand(const char * cmd, int num1, int num2)
455 printLines(num1, num1, FALSE); 421 printLines(num1, num1, FALSE);
456 needPrint = FALSE; 422 needPrint = FALSE;
457 } 423 }
458
459 offset = 0; 424 offset = 0;
460 lp = lp->next; 425 lp = lp->next;
461 num1++; 426 num1++;
462
463 continue; 427 continue;
464 } 428 }
465 429
@@ -473,7 +437,6 @@ static void subCommand(const char * cmd, int num1, int num2)
473 */ 437 */
474 if (deltaLen <= 0) { 438 if (deltaLen <= 0) {
475 memcpy(&lp->data[offset], newStr, newLen); 439 memcpy(&lp->data[offset], newStr, newLen);
476
477 if (deltaLen) { 440 if (deltaLen) {
478 memcpy(&lp->data[offset + newLen], 441 memcpy(&lp->data[offset + newLen],
479 &lp->data[offset + oldLen], 442 &lp->data[offset + oldLen],
@@ -481,20 +444,15 @@ static void subCommand(const char * cmd, int num1, int num2)
481 444
482 lp->len += deltaLen; 445 lp->len += deltaLen;
483 } 446 }
484
485 offset += newLen; 447 offset += newLen;
486
487 if (globalFlag) 448 if (globalFlag)
488 continue; 449 continue;
489
490 if (needPrint) { 450 if (needPrint) {
491 printLines(num1, num1, FALSE); 451 printLines(num1, num1, FALSE);
492 needPrint = FALSE; 452 needPrint = FALSE;
493 } 453 }
494
495 lp = lp->next; 454 lp = lp->next;
496 num1++; 455 num1++;
497
498 continue; 456 continue;
499 } 457 }
500 458
@@ -503,8 +461,7 @@ static void subCommand(const char * cmd, int num1, int num2)
503 * structure and use that. Link it in in place of 461 * structure and use that. Link it in in place of
504 * the old line structure. 462 * the old line structure.
505 */ 463 */
506 nlp = (LINE *) malloc(sizeof(LINE) + lp->len + deltaLen); 464 nlp = malloc(sizeof(LINE) + lp->len + deltaLen);
507
508 if (nlp == NULL) { 465 if (nlp == NULL) {
509 bb_error_msg("cannot get memory for line"); 466 bb_error_msg("cannot get memory for line");
510 return; 467 return;
@@ -513,9 +470,7 @@ static void subCommand(const char * cmd, int num1, int num2)
513 nlp->len = lp->len + deltaLen; 470 nlp->len = lp->len + deltaLen;
514 471
515 memcpy(nlp->data, lp->data, offset); 472 memcpy(nlp->data, lp->data, offset);
516
517 memcpy(&nlp->data[offset], newStr, newLen); 473 memcpy(&nlp->data[offset], newStr, newLen);
518
519 memcpy(&nlp->data[offset + newLen], 474 memcpy(&nlp->data[offset + newLen],
520 &lp->data[offset + oldLen], 475 &lp->data[offset + oldLen],
521 lp->len - offset - oldLen); 476 lp->len - offset - oldLen);
@@ -554,7 +509,7 @@ static void subCommand(const char * cmd, int num1, int num2)
554 * Search a line for the specified string starting at the specified 509 * Search a line for the specified string starting at the specified
555 * offset in the line. Returns the offset of the found string, or -1. 510 * offset in the line. Returns the offset of the found string, or -1.
556 */ 511 */
557static int findString( const LINE * lp, const char * str, int len, int offset) 512static int findString(const LINE *lp, const char *str, int len, int offset)
558{ 513{
559 int left; 514 int left;
560 const char *cp, *ncp; 515 const char *cp, *ncp;
@@ -564,20 +519,14 @@ static int findString( const LINE * lp, const char * str, int len, int offset)
564 519
565 while (left >= len) { 520 while (left >= len) {
566 ncp = memchr(cp, *str, left); 521 ncp = memchr(cp, *str, left);
567
568 if (ncp == NULL) 522 if (ncp == NULL)
569 return -1; 523 return -1;
570
571 left -= (ncp - cp); 524 left -= (ncp - cp);
572
573 if (left < len) 525 if (left < len)
574 return -1; 526 return -1;
575
576 cp = ncp; 527 cp = ncp;
577
578 if (memcmp(cp, str, len) == 0) 528 if (memcmp(cp, str, len) == 0)
579 return (cp - lp->data); 529 return (cp - lp->data);
580
581 cp++; 530 cp++;
582 left--; 531 left--;
583 } 532 }
@@ -597,23 +546,20 @@ static void addLines(int num)
597 int len; 546 int len;
598 char buf[USERSIZE + 1]; 547 char buf[USERSIZE + 1];
599 548
600 while (fgets(buf, sizeof(buf), stdin)) { 549 while (1) {
601 if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0')) 550 /* Returns:
602 return; 551 * -1 on read errors or EOF, or on bare Ctrl-D.
603 552 * 0 on ctrl-C,
604 len = strlen(buf); 553 * >0 length of input string, including terminating '\n'
605 554 */
606 if (len == 0) 555 len = read_line_input("", buf, sizeof(buf), NULL);
607 return; 556 if (len <= 0) {
608 557 /* Previously, ctrl-C was exiting to shell.
609 if (buf[len - 1] != '\n') { 558 * Now we exit to ed prompt. Is in important? */
610 bb_error_msg("line too long");
611 do {
612 len = fgetc(stdin);
613 } while ((len != EOF) && (len != '\n'));
614 return; 559 return;
615 } 560 }
616 561 if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0'))
562 return;
617 if (!insertLine(num++, buf, len)) 563 if (!insertLine(num++, buf, len))
618 return; 564 return;
619 } 565 }
@@ -628,20 +574,20 @@ static void addLines(int num)
628 * Whether there was a number is returned indirectly, as is the number. 574 * Whether there was a number is returned indirectly, as is the number.
629 * The character pointer which stopped the scan is also returned. 575 * The character pointer which stopped the scan is also returned.
630 */ 576 */
631static int getNum(const char **retcp, int *retHaveNum, int *retNum) 577static int getNum(const char **retcp, smallint *retHaveNum, int *retNum)
632{ 578{
633 const char *cp; 579 const char *cp;
634 char *endStr, str[USERSIZE]; 580 char *endStr, str[USERSIZE];
635 int haveNum, value, num, sign; 581 int value, num;
582 smallint haveNum, minus;
636 583
637 cp = *retcp; 584 cp = *retcp;
638 haveNum = FALSE;
639 value = 0; 585 value = 0;
640 sign = 1; 586 haveNum = FALSE;
587 minus = 0;
641 588
642 while (TRUE) { 589 while (TRUE) {
643 while (isblank(*cp)) 590 cp = skip_blank(cp);
644 cp++;
645 591
646 switch (*cp) { 592 switch (*cp) {
647 case '.': 593 case '.':
@@ -658,12 +604,10 @@ static int getNum(const char **retcp, int *retHaveNum, int *retNum)
658 604
659 case '\'': 605 case '\'':
660 cp++; 606 cp++;
661
662 if ((*cp < 'a') || (*cp > 'z')) { 607 if ((*cp < 'a') || (*cp > 'z')) {
663 bb_error_msg("bad mark name"); 608 bb_error_msg("bad mark name");
664 return FALSE; 609 return FALSE;
665 } 610 }
666
667 haveNum = TRUE; 611 haveNum = TRUE;
668 num = marks[*cp++ - 'a']; 612 num = marks[*cp++ - 'a'];
669 break; 613 break;
@@ -671,19 +615,14 @@ static int getNum(const char **retcp, int *retHaveNum, int *retNum)
671 case '/': 615 case '/':
672 strcpy(str, ++cp); 616 strcpy(str, ++cp);
673 endStr = strchr(str, '/'); 617 endStr = strchr(str, '/');
674
675 if (endStr) { 618 if (endStr) {
676 *endStr++ = '\0'; 619 *endStr++ = '\0';
677 cp += (endStr - str); 620 cp += (endStr - str);
678 } 621 } else
679 else
680 cp = ""; 622 cp = "";
681
682 num = searchLines(str, curNum, lastNum); 623 num = searchLines(str, curNum, lastNum);
683
684 if (num == 0) 624 if (num == 0)
685 return FALSE; 625 return FALSE;
686
687 haveNum = TRUE; 626 haveNum = TRUE;
688 break; 627 break;
689 628
@@ -694,29 +633,25 @@ static int getNum(const char **retcp, int *retHaveNum, int *retNum)
694 *retNum = value; 633 *retNum = value;
695 return TRUE; 634 return TRUE;
696 } 635 }
697
698 num = 0; 636 num = 0;
699
700 while (isdigit(*cp)) 637 while (isdigit(*cp))
701 num = num * 10 + *cp++ - '0'; 638 num = num * 10 + *cp++ - '0';
702
703 haveNum = TRUE; 639 haveNum = TRUE;
704 break; 640 break;
705 } 641 }
706 642
707 value += num * sign; 643 value += (minus ? -num : num);
708 644
709 while (isblank(*cp)) 645 cp = skip_blank(cp);
710 cp++;
711 646
712 switch (*cp) { 647 switch (*cp) {
713 case '-': 648 case '-':
714 sign = -1; 649 minus = 1;
715 cp++; 650 cp++;
716 break; 651 break;
717 652
718 case '+': 653 case '+':
719 sign = 1; 654 minus = 0;
720 cp++; 655 cp++;
721 break; 656 break;
722 657
@@ -731,74 +666,10 @@ static int getNum(const char **retcp, int *retHaveNum, int *retNum)
731 666
732 667
733/* 668/*
734 * Initialize everything for editing.
735 */
736static int initEdit(void)
737{
738 int i;
739
740 bufSize = INITBUF_SIZE;
741 bufBase = malloc(bufSize);
742
743 if (bufBase == NULL) {
744 bb_error_msg("no memory for buffer");
745 return FALSE;
746 }
747
748 bufPtr = bufBase;
749 bufUsed = 0;
750
751 lines.next = &lines;
752 lines.prev = &lines;
753
754 curLine = NULL;
755 curNum = 0;
756 lastNum = 0;
757 dirty = FALSE;
758 fileName = NULL;
759 searchString[0] = '\0';
760
761 for (i = 0; i < 26; i++)
762 marks[i] = 0;
763
764 return TRUE;
765}
766
767
768/*
769 * Finish editing.
770 */
771static void termEdit(void)
772{
773 if (bufBase)
774 free(bufBase);
775
776 bufBase = NULL;
777 bufPtr = NULL;
778 bufSize = 0;
779 bufUsed = 0;
780
781 if (fileName)
782 free(fileName);
783
784 fileName = NULL;
785
786 searchString[0] = '\0';
787
788 if (lastNum)
789 deleteLines(1, lastNum);
790
791 lastNum = 0;
792 curNum = 0;
793 curLine = NULL;
794}
795
796
797/*
798 * Read lines from a file at the specified line number. 669 * Read lines from a file at the specified line number.
799 * Returns TRUE if the file was successfully read. 670 * Returns TRUE if the file was successfully read.
800 */ 671 */
801static int readLines(const char * file, int num) 672static int readLines(const char *file, int num)
802{ 673{
803 int fd, cc; 674 int fd, cc;
804 int len, lineCount, charCount; 675 int len, lineCount, charCount;
@@ -810,7 +681,6 @@ static int readLines(const char * file, int num)
810 } 681 }
811 682
812 fd = open(file, 0); 683 fd = open(file, 0);
813
814 if (fd < 0) { 684 if (fd < 0) {
815 perror(file); 685 perror(file);
816 return FALSE; 686 return FALSE;
@@ -830,18 +700,15 @@ static int readLines(const char * file, int num)
830 700
831 if (cp) { 701 if (cp) {
832 len = (cp - bufPtr) + 1; 702 len = (cp - bufPtr) + 1;
833
834 if (!insertLine(num, bufPtr, len)) { 703 if (!insertLine(num, bufPtr, len)) {
835 close(fd); 704 close(fd);
836 return FALSE; 705 return FALSE;
837 } 706 }
838
839 bufPtr += len; 707 bufPtr += len;
840 bufUsed -= len; 708 bufUsed -= len;
841 charCount += len; 709 charCount += len;
842 lineCount++; 710 lineCount++;
843 num++; 711 num++;
844
845 continue; 712 continue;
846 } 713 }
847 714
@@ -853,19 +720,17 @@ static int readLines(const char * file, int num)
853 if (bufUsed >= bufSize) { 720 if (bufUsed >= bufSize) {
854 len = (bufSize * 3) / 2; 721 len = (bufSize * 3) / 2;
855 cp = realloc(bufBase, len); 722 cp = realloc(bufBase, len);
856
857 if (cp == NULL) { 723 if (cp == NULL) {
858 bb_error_msg("no memory for buffer"); 724 bb_error_msg("no memory for buffer");
859 close(fd); 725 close(fd);
860 return FALSE; 726 return FALSE;
861 } 727 }
862
863 bufBase = cp; 728 bufBase = cp;
864 bufPtr = bufBase + bufUsed; 729 bufPtr = bufBase + bufUsed;
865 bufSize = len; 730 bufSize = len;
866 } 731 }
867 732
868 cc = read(fd, bufPtr, bufSize - bufUsed); 733 cc = safe_read(fd, bufPtr, bufSize - bufUsed);
869 bufUsed += cc; 734 bufUsed += cc;
870 bufPtr = bufBase; 735 bufPtr = bufBase;
871 736
@@ -882,7 +747,6 @@ static int readLines(const char * file, int num)
882 close(fd); 747 close(fd);
883 return -1; 748 return -1;
884 } 749 }
885
886 lineCount++; 750 lineCount++;
887 charCount += bufUsed; 751 charCount += bufUsed;
888 } 752 }
@@ -900,21 +764,18 @@ static int readLines(const char * file, int num)
900 * Write the specified lines out to the specified file. 764 * Write the specified lines out to the specified file.
901 * Returns TRUE if successful, or FALSE on an error with a message output. 765 * Returns TRUE if successful, or FALSE on an error with a message output.
902 */ 766 */
903static int writeLines(const char * file, int num1, int num2) 767static int writeLines(const char *file, int num1, int num2)
904{ 768{
905 LINE *lp; 769 LINE *lp;
906 int fd, lineCount, charCount; 770 int fd, lineCount, charCount;
907 771
908 if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { 772 if (bad_nums(num1, num2, "write"))
909 bb_error_msg("bad line range for write");
910 return FALSE; 773 return FALSE;
911 }
912 774
913 lineCount = 0; 775 lineCount = 0;
914 charCount = 0; 776 charCount = 0;
915 777
916 fd = creat(file, 0666); 778 fd = creat(file, 0666);
917
918 if (fd < 0) { 779 if (fd < 0) {
919 perror(file); 780 perror(file);
920 return FALSE; 781 return FALSE;
@@ -924,19 +785,17 @@ static int writeLines(const char * file, int num1, int num2)
924 fflush(stdout); 785 fflush(stdout);
925 786
926 lp = findLine(num1); 787 lp = findLine(num1);
927
928 if (lp == NULL) { 788 if (lp == NULL) {
929 close(fd); 789 close(fd);
930 return FALSE; 790 return FALSE;
931 } 791 }
932 792
933 while (num1++ <= num2) { 793 while (num1++ <= num2) {
934 if (write(fd, lp->data, lp->len) != lp->len) { 794 if (full_write(fd, lp->data, lp->len) != lp->len) {
935 perror(file); 795 perror(file);
936 close(fd); 796 close(fd);
937 return FALSE; 797 return FALSE;
938 } 798 }
939
940 charCount += lp->len; 799 charCount += lp->len;
941 lineCount++; 800 lineCount++;
942 lp = lp->next; 801 lp = lp->next;
@@ -964,13 +823,10 @@ static int printLines(int num1, int num2, int expandFlag)
964 const char *cp; 823 const char *cp;
965 int ch, count; 824 int ch, count;
966 825
967 if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { 826 if (bad_nums(num1, num2, "print"))
968 bb_error_msg("bad line range for print");
969 return FALSE; 827 return FALSE;
970 }
971 828
972 lp = findLine(num1); 829 lp = findLine(num1);
973
974 if (lp == NULL) 830 if (lp == NULL)
975 return FALSE; 831 return FALSE;
976 832
@@ -979,7 +835,6 @@ static int printLines(int num1, int num2, int expandFlag)
979 write(1, lp->data, lp->len); 835 write(1, lp->data, lp->len);
980 setCurNum(num1++); 836 setCurNum(num1++);
981 lp = lp->next; 837 lp = lp->next;
982
983 continue; 838 continue;
984 } 839 }
985 840
@@ -995,22 +850,18 @@ static int printLines(int num1, int num2, int expandFlag)
995 850
996 while (count-- > 0) { 851 while (count-- > 0) {
997 ch = *cp++; 852 ch = *cp++;
998
999 if (ch & 0x80) { 853 if (ch & 0x80) {
1000 fputs("M-", stdout); 854 fputs("M-", stdout);
1001 ch &= 0x7f; 855 ch &= 0x7f;
1002 } 856 }
1003
1004 if (ch < ' ') { 857 if (ch < ' ') {
1005 fputc('^', stdout); 858 fputc('^', stdout);
1006 ch += '@'; 859 ch += '@';
1007 } 860 }
1008
1009 if (ch == 0x7f) { 861 if (ch == 0x7f) {
1010 fputc('^', stdout); 862 fputc('^', stdout);
1011 ch = '?'; 863 ch = '?';
1012 } 864 }
1013
1014 fputc(ch, stdout); 865 fputc(ch, stdout);
1015 } 866 }
1016 867
@@ -1031,7 +882,7 @@ static int printLines(int num1, int num2, int expandFlag)
1031 * The inserted line is also set to become the current line. 882 * The inserted line is also set to become the current line.
1032 * Returns TRUE if successful. 883 * Returns TRUE if successful.
1033 */ 884 */
1034static int insertLine(int num, const char * data, int len) 885static int insertLine(int num, const char *data, int len)
1035{ 886{
1036 LINE *newLp, *lp; 887 LINE *newLp, *lp;
1037 888
@@ -1041,7 +892,6 @@ static int insertLine(int num, const char * data, int len)
1041 } 892 }
1042 893
1043 newLp = malloc(sizeof(LINE) + len - 1); 894 newLp = malloc(sizeof(LINE) + len - 1);
1044
1045 if (newLp == NULL) { 895 if (newLp == NULL) {
1046 bb_error_msg("failed to allocate memory for line"); 896 bb_error_msg("failed to allocate memory for line");
1047 return FALSE; 897 return FALSE;
@@ -1054,7 +904,6 @@ static int insertLine(int num, const char * data, int len)
1054 lp = &lines; 904 lp = &lines;
1055 else { 905 else {
1056 lp = findLine(num); 906 lp = findLine(num);
1057
1058 if (lp == NULL) { 907 if (lp == NULL) {
1059 free((char *) newLp); 908 free((char *) newLp);
1060 return FALSE; 909 return FALSE;
@@ -1075,20 +924,17 @@ static int insertLine(int num, const char * data, int len)
1075/* 924/*
1076 * Delete lines from the given range. 925 * Delete lines from the given range.
1077 */ 926 */
1078static int deleteLines(int num1, int num2) 927static void deleteLines(int num1, int num2)
1079{ 928{
1080 LINE *lp, *nlp, *plp; 929 LINE *lp, *nlp, *plp;
1081 int count; 930 int count;
1082 931
1083 if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { 932 if (bad_nums(num1, num2, "delete"))
1084 bb_error_msg("bad line numbers for delete"); 933 return;
1085 return FALSE;
1086 }
1087 934
1088 lp = findLine(num1); 935 lp = findLine(num1);
1089
1090 if (lp == NULL) 936 if (lp == NULL)
1091 return FALSE; 937 return;
1092 938
1093 if ((curNum >= num1) && (curNum <= num2)) { 939 if ((curNum >= num1) && (curNum <= num2)) {
1094 if (num2 < lastNum) 940 if (num2 < lastNum)
@@ -1100,10 +946,8 @@ static int deleteLines(int num1, int num2)
1100 } 946 }
1101 947
1102 count = num2 - num1 + 1; 948 count = num2 - num1 + 1;
1103
1104 if (curNum > num2) 949 if (curNum > num2)
1105 curNum -= count; 950 curNum -= count;
1106
1107 lastNum -= count; 951 lastNum -= count;
1108 952
1109 while (count-- > 0) { 953 while (count-- > 0) {
@@ -1111,22 +955,17 @@ static int deleteLines(int num1, int num2)
1111 plp = lp->prev; 955 plp = lp->prev;
1112 plp->next = nlp; 956 plp->next = nlp;
1113 nlp->prev = plp; 957 nlp->prev = plp;
1114 lp->next = NULL;
1115 lp->prev = NULL;
1116 lp->len = 0;
1117 free(lp); 958 free(lp);
1118 lp = nlp; 959 lp = nlp;
1119 } 960 }
1120 961
1121 dirty = TRUE; 962 dirty = TRUE;
1122
1123 return TRUE;
1124} 963}
1125 964
1126 965
1127/* 966/*
1128 * Search for a line which contains the specified string. 967 * Search for a line which contains the specified string.
1129 * If the string is NULL, then the previously searched for string 968 * If the string is "", then the previously searched for string
1130 * is used. The currently searched for string is saved for future use. 969 * is used. The currently searched for string is saved for future use.
1131 * Returns the line number which matches, or 0 if there was no match 970 * Returns the line number which matches, or 0 if there was no match
1132 * with an error printed. 971 * with an error printed.
@@ -1136,17 +975,14 @@ static int searchLines(const char *str, int num1, int num2)
1136 const LINE *lp; 975 const LINE *lp;
1137 int len; 976 int len;
1138 977
1139 if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { 978 if (bad_nums(num1, num2, "search"))
1140 bb_error_msg("bad line numbers for search");
1141 return 0; 979 return 0;
1142 }
1143 980
1144 if (*str == '\0') { 981 if (*str == '\0') {
1145 if (searchString[0] == '\0') { 982 if (searchString[0] == '\0') {
1146 bb_error_msg("no previous search string"); 983 bb_error_msg("no previous search string");
1147 return 0; 984 return 0;
1148 } 985 }
1149
1150 str = searchString; 986 str = searchString;
1151 } 987 }
1152 988
@@ -1156,14 +992,12 @@ static int searchLines(const char *str, int num1, int num2)
1156 len = strlen(str); 992 len = strlen(str);
1157 993
1158 lp = findLine(num1); 994 lp = findLine(num1);
1159
1160 if (lp == NULL) 995 if (lp == NULL)
1161 return 0; 996 return 0;
1162 997
1163 while (num1 <= num2) { 998 while (num1 <= num2) {
1164 if (findString(lp, str, len, 0) >= 0) 999 if (findString(lp, str, len, 0) >= 0)
1165 return num1; 1000 return num1;
1166
1167 num1++; 1001 num1++;
1168 lp = lp->next; 1002 lp = lp->next;
1169 } 1003 }
@@ -1196,12 +1030,10 @@ static LINE *findLine(int num)
1196 1030
1197 lp = curLine; 1031 lp = curLine;
1198 lnum = curNum; 1032 lnum = curNum;
1199
1200 if (num < (curNum / 2)) { 1033 if (num < (curNum / 2)) {
1201 lp = lines.next; 1034 lp = lines.next;
1202 lnum = 1; 1035 lnum = 1;
1203 } 1036 } else if (num > ((curNum + lastNum) / 2)) {
1204 else if (num > ((curNum + lastNum) / 2)) {
1205 lp = lines.prev; 1037 lp = lines.prev;
1206 lnum = lastNum; 1038 lnum = lastNum;
1207 } 1039 }
@@ -1228,10 +1060,8 @@ static int setCurNum(int num)
1228 LINE *lp; 1060 LINE *lp;
1229 1061
1230 lp = findLine(num); 1062 lp = findLine(num);
1231
1232 if (lp == NULL) 1063 if (lp == NULL)
1233 return FALSE; 1064 return FALSE;
1234
1235 curNum = num; 1065 curNum = num;
1236 curLine = lp; 1066 curLine = lp;
1237 return TRUE; 1067 return TRUE;