aboutsummaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2006-05-04 20:56:43 +0000
committerRob Landley <rob@landley.net>2006-05-04 20:56:43 +0000
commit3b89039c25c8eb15435ed4f87bc8cb31c7941064 (patch)
tree0793ca73b2cbceca33e678571de77178364c5b6b /patches
parent846fe0c045eedb2a2e5b3432648f4c1f04353631 (diff)
downloadbusybox-3b89039c25c8eb15435ed4f87bc8cb31c7941064.tar.gz
It was sitting there, in the patches directory, for years. It was delete it
or apply it. It's small, simple, evil, part of SUSv3, and we can switch it off.
Diffstat (limited to 'patches')
-rw-r--r--patches/ed.patch1489
1 files changed, 0 insertions, 1489 deletions
diff --git a/patches/ed.patch b/patches/ed.patch
deleted file mode 100644
index 6d51830a5..000000000
--- a/patches/ed.patch
+++ /dev/null
@@ -1,1489 +0,0 @@
-Index: editors/Makefile.in
-===================================================================
---- editors/Makefile.in (revision 10144)
-+++ editors/Makefile.in (working copy)
-@@ -24,8 +24,9 @@
- srcdir=$(top_srcdir)/editors
-
- EDITOR-y:=
--EDITOR-$(CONFIG_AWK) += awk.o
--EDITOR-$(CONFIG_PATCH) += patch.o
-+EDITOR-$(CONFIG_AWK) += awk.o
-+EDITOR-$(CONFIG_ED) += ed.o
-+EDITOR-$(CONFIG_PATCH) += patch.o
- EDITOR-$(CONFIG_SED) += sed.o
- EDITOR-$(CONFIG_VI) += vi.o
- EDITOR_SRC:= $(EDITOR-y)
-Index: editors/Config.in
-===================================================================
---- editors/Config.in (revision 10144)
-+++ editors/Config.in (working copy)
-@@ -20,6 +20,12 @@
- Enable math functions of the Awk programming language.
- NOTE: This will require libm to be present for linking.
-
-+config CONFIG_ED
-+ bool "ed"
-+ default n
-+ help
-+ ed
-+
- config CONFIG_PATCH
- bool "patch"
- default n
-Index: include/usage.h
-===================================================================
---- include/usage.h (revision 10151)
-+++ include/usage.h (working copy)
-@@ -556,6 +561,9 @@
- "$ echo \"Erik\\nis\\ncool\"\n" \
- "Erik\\nis\\ncool\n")
-
-+#define ed_trivial_usage ""
-+#define ed_full_usage ""
-+
- #define env_trivial_usage \
- "[-iu] [-] [name=value]... [command]"
- #define env_full_usage \
-Index: include/applets.h
-===================================================================
---- include/applets.h (revision 10151)
-+++ include/applets.h (working copy)
-@@ -179,6 +179,9 @@
- #ifdef CONFIG_ECHO
- APPLET(echo, echo_main, _BB_DIR_BIN, _BB_SUID_NEVER)
- #endif
-+#ifdef CONFIG_ED
-+ APPLET(ed, ed_main, _BB_DIR_BIN, _BB_SUID_NEVER)
-+#endif
- #if defined(CONFIG_FEATURE_GREP_EGREP_ALIAS)
- APPLET_NOUSAGE("egrep", grep_main, _BB_DIR_BIN, _BB_SUID_NEVER)
- #endif
---- /dev/null 2005-04-24 01:00:01.350003056 -0400
-+++ ed.c 2005-04-24 01:38:51.000000000 -0400
-@@ -0,0 +1,1425 @@
-+/*
-+ * Copyright (c) 2002 by David I. Bell
-+ * Permission is granted to use, distribute, or modify this source,
-+ * provided that this copyright notice remains intact.
-+ *
-+ * The "ed" built-in command (much simplified)
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <fcntl.h>
-+#include <string.h>
-+#include <memory.h>
-+#include <time.h>
-+#include <ctype.h>
-+#include <sys/param.h>
-+#include <malloc.h>
-+#include "busybox.h"
-+
-+#define USERSIZE 1024 /* max line length typed in by user */
-+#define INITBUF_SIZE 1024 /* initial buffer size */
-+
-+typedef int BOOL;
-+typedef int NUM;
-+typedef int LEN;
-+
-+typedef struct LINE LINE;
-+struct LINE {
-+ LINE *next;
-+ LINE *prev;
-+ LEN len;
-+ char data[1];
-+};
-+
-+static LINE lines;
-+static LINE *curLine;
-+static NUM curNum;
-+static NUM lastNum;
-+static NUM marks[26];
-+static BOOL dirty;
-+static char *fileName;
-+static char searchString[USERSIZE];
-+
-+static char *bufBase;
-+static char *bufPtr;
-+static LEN bufUsed;
-+static LEN bufSize;
-+
-+static void doCommands(void);
-+static void subCommand(const char * cmd, NUM num1, NUM num2);
-+static BOOL getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum);
-+static BOOL setCurNum(NUM num);
-+static BOOL initEdit(void);
-+static void termEdit(void);
-+static void addLines(NUM num);
-+static BOOL insertLine(NUM num, const char * data, LEN len);
-+static BOOL deleteLines(NUM num1, NUM num2);
-+static BOOL printLines(NUM num1, NUM num2, BOOL expandFlag);
-+static BOOL writeLines(const char * file, NUM num1, NUM num2);
-+static BOOL readLines(const char * file, NUM num);
-+static NUM searchLines(const char * str, NUM num1, NUM num2);
-+static LINE * findLine(NUM num);
-+
-+static LEN findString(const LINE * lp, const char * str, LEN len, LEN offset);
-+
-+int ed_main(int argc, char **argv)
-+{
-+ if (!initEdit())
-+ return EXIT_FAILURE;
-+
-+ if (argc > 1) {
-+ fileName = strdup(argv[1]);
-+
-+ if (fileName == NULL) {
-+ bb_error_msg("No memory");
-+ termEdit();
-+ return EXIT_SUCCESS;
-+ }
-+
-+ if (!readLines(fileName, 1)) {
-+ termEdit();
-+ return EXIT_SUCCESS;
-+ }
-+
-+ if (lastNum)
-+ setCurNum(1);
-+
-+ dirty = FALSE;
-+ }
-+
-+ doCommands();
-+
-+ termEdit();
-+ return EXIT_SUCCESS;
-+}
-+
-+/*
-+ * Read commands until we are told to stop.
-+ */
-+static void doCommands(void)
-+{
-+ const char * cp;
-+ char * endbuf;
-+ char * newname;
-+ int len;
-+ NUM num1;
-+ NUM num2;
-+ BOOL have1;
-+ BOOL have2;
-+ char buf[USERSIZE];
-+
-+ while (TRUE)
-+ {
-+ printf(": ");
-+ fflush(stdout);
-+
-+ if (fgets(buf, sizeof(buf), stdin) == NULL)
-+ return;
-+
-+ len = strlen(buf);
-+
-+ if (len == 0)
-+ return;
-+
-+ endbuf = &buf[len - 1];
-+
-+ if (*endbuf != '\n')
-+ {
-+ bb_error_msg("Command line too long");
-+
-+ do
-+ {
-+ len = fgetc(stdin);
-+ }
-+ while ((len != EOF) && (len != '\n'));
-+
-+ continue;
-+ }
-+
-+ while ((endbuf > buf) && isblank(endbuf[-1]))
-+ endbuf--;
-+
-+ *endbuf = '\0';
-+
-+ cp = buf;
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ have1 = FALSE;
-+ have2 = FALSE;
-+
-+ if ((curNum == 0) && (lastNum > 0))
-+ {
-+ curNum = 1;
-+ curLine = lines.next;
-+ }
-+
-+ if (!getNum(&cp, &have1, &num1))
-+ continue;
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if (*cp == ',')
-+ {
-+ cp++;
-+
-+ if (!getNum(&cp, &have2, &num2))
-+ continue;
-+
-+ if (!have1)
-+ num1 = 1;
-+
-+ if (!have2)
-+ num2 = lastNum;
-+
-+ have1 = TRUE;
-+ have2 = TRUE;
-+ }
-+
-+ if (!have1)
-+ num1 = curNum;
-+
-+ if (!have2)
-+ num2 = num1;
-+
-+ switch (*cp++)
-+ {
-+ case 'a':
-+ addLines(num1 + 1);
-+ break;
-+
-+ case 'c':
-+ deleteLines(num1, num2);
-+ addLines(num1);
-+ break;
-+
-+ case 'd':
-+ deleteLines(num1, num2);
-+ break;
-+
-+ case 'f':
-+ if (*cp && !isblank(*cp))
-+ {
-+ bb_error_msg("Bad file command");
-+ break;
-+ }
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if (*cp == '\0')
-+ {
-+ if (fileName)
-+ printf("\"%s\"\n", fileName);
-+ else
-+ printf("No file name\n");
-+
-+ break;
-+ }
-+
-+ newname = strdup(cp);
-+
-+ if (newname == NULL)
-+ {
-+ bb_error_msg("No memory for file name");
-+ break;
-+ }
-+
-+ if (fileName)
-+ free(fileName);
-+
-+ fileName = newname;
-+ break;
-+
-+ case 'i':
-+ addLines(num1);
-+ break;
-+
-+ case 'k':
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if ((*cp < 'a') || (*cp > 'a') || cp[1])
-+ {
-+ bb_error_msg("Bad mark name");
-+ break;
-+ }
-+
-+ marks[*cp - 'a'] = num2;
-+ break;
-+
-+ case 'l':
-+ printLines(num1, num2, TRUE);
-+ break;
-+
-+ case 'p':
-+ printLines(num1, num2, FALSE);
-+ break;
-+
-+ case 'q':
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if (have1 || *cp)
-+ {
-+ bb_error_msg("Bad quit command");
-+ break;
-+ }
-+
-+ if (!dirty)
-+ return;
-+
-+ printf("Really quit? ");
-+ fflush(stdout);
-+
-+ buf[0] = '\0';
-+ fgets(buf, sizeof(buf), stdin);
-+ cp = buf;
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if ((*cp == 'y') || (*cp == 'Y'))
-+ return;
-+
-+ break;
-+
-+ case 'r':
-+ if (*cp && !isblank(*cp))
-+ {
-+ bb_error_msg("Bad read command");
-+ break;
-+ }
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if (*cp == '\0')
-+ {
-+ bb_error_msg("No file name");
-+ break;
-+ }
-+
-+ if (!have1)
-+ num1 = lastNum;
-+
-+ if (readLines(cp, num1 + 1))
-+ break;
-+
-+ if (fileName == NULL)
-+ fileName = strdup(cp);
-+
-+ break;
-+
-+ case 's':
-+ subCommand(cp, num1, num2);
-+ break;
-+
-+ case 'w':
-+ if (*cp && !isblank(*cp))
-+ {
-+ bb_error_msg("Bad write command");
-+ break;
-+ }
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ if (!have1) {
-+ num1 = 1;
-+ num2 = lastNum;
-+ }
-+
-+ if (*cp == '\0')
-+ cp = fileName;
-+
-+ if (cp == NULL)
-+ {
-+ bb_error_msg("No file name specified");
-+ break;
-+ }
-+
-+ writeLines(cp, num1, num2);
-+ break;
-+
-+ case 'z':
-+ switch (*cp)
-+ {
-+ case '-':
-+ printLines(curNum-21, curNum, FALSE);
-+ break;
-+ case '.':
-+ printLines(curNum-11, curNum+10, FALSE);
-+ break;
-+ default:
-+ printLines(curNum, curNum+21, FALSE);
-+ break;
-+ }
-+ break;
-+
-+ case '.':
-+ if (have1)
-+ {
-+ bb_error_msg("No arguments allowed");
-+ break;
-+ }
-+
-+ printLines(curNum, curNum, FALSE);
-+ break;
-+
-+ case '-':
-+ if (setCurNum(curNum - 1))
-+ printLines(curNum, curNum, FALSE);
-+
-+ break;
-+
-+ case '=':
-+ printf("%d\n", num1);
-+ break;
-+
-+ case '\0':
-+ if (have1)
-+ {
-+ printLines(num2, num2, FALSE);
-+ break;
-+ }
-+
-+ if (setCurNum(curNum + 1))
-+ printLines(curNum, curNum, FALSE);
-+
-+ break;
-+
-+ default:
-+ bb_error_msg("Unimplemented command");
-+ break;
-+ }
-+ }
-+}
-+
-+
-+/*
-+ * Do the substitute command.
-+ * The current line is set to the last substitution done.
-+ */
-+static void
-+subCommand(const char * cmd, NUM num1, NUM num2)
-+{
-+ int delim;
-+ char * cp;
-+ char * oldStr;
-+ char * newStr;
-+ LEN oldLen;
-+ LEN newLen;
-+ LEN deltaLen;
-+ LEN offset;
-+ LINE * lp;
-+ LINE * nlp;
-+ BOOL globalFlag;
-+ BOOL printFlag;
-+ BOOL didSub;
-+ BOOL needPrint;
-+ char buf[USERSIZE];
-+
-+ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
-+ {
-+ bb_error_msg("Bad line range for substitute");
-+
-+ return;
-+ }
-+
-+ globalFlag = FALSE;
-+ printFlag = FALSE;
-+ didSub = FALSE;
-+ needPrint = FALSE;
-+
-+ /*
-+ * Copy the command so we can modify it.
-+ */
-+ strcpy(buf, cmd);
-+ cp = buf;
-+
-+ if (isblank(*cp) || (*cp == '\0'))
-+ {
-+ bb_error_msg("Bad delimiter for substitute");
-+
-+ return;
-+ }
-+
-+ delim = *cp++;
-+ oldStr = cp;
-+
-+ cp = strchr(cp, delim);
-+
-+ if (cp == NULL)
-+ {
-+ bb_error_msg("Missing 2nd delimiter for substitute");
-+
-+ return;
-+ }
-+
-+ *cp++ = '\0';
-+
-+ newStr = cp;
-+ cp = strchr(cp, delim);
-+
-+ if (cp)
-+ *cp++ = '\0';
-+ else
-+ cp = "";
-+
-+ while (*cp) switch (*cp++)
-+ {
-+ case 'g':
-+ globalFlag = TRUE;
-+ break;
-+
-+ case 'p':
-+ printFlag = TRUE;
-+ break;
-+
-+ default:
-+ bb_error_msg("Unknown option for substitute");
-+
-+ return;
-+ }
-+
-+ if (*oldStr == '\0')
-+ {
-+ if (searchString[0] == '\0')
-+ {
-+ bb_error_msg("No previous search string");
-+
-+ return;
-+ }
-+
-+ oldStr = searchString;
-+ }
-+
-+ if (oldStr != searchString)
-+ strcpy(searchString, oldStr);
-+
-+ lp = findLine(num1);
-+
-+ if (lp == NULL)
-+ return;
-+
-+ oldLen = strlen(oldStr);
-+ newLen = strlen(newStr);
-+ deltaLen = newLen - oldLen;
-+ offset = 0;
-+ nlp = NULL;
-+
-+ while (num1 <= num2)
-+ {
-+ offset = findString(lp, oldStr, oldLen, offset);
-+
-+ if (offset < 0)
-+ {
-+ if (needPrint)
-+ {
-+ printLines(num1, num1, FALSE);
-+ needPrint = FALSE;
-+ }
-+
-+ offset = 0;
-+ lp = lp->next;
-+ num1++;
-+
-+ continue;
-+ }
-+
-+ needPrint = printFlag;
-+ didSub = TRUE;
-+ dirty = TRUE;
-+
-+ /*
-+ * If the replacement string is the same size or shorter
-+ * than the old string, then the substitution is easy.
-+ */
-+ if (deltaLen <= 0)
-+ {
-+ memcpy(&lp->data[offset], newStr, newLen);
-+
-+ if (deltaLen)
-+ {
-+ memcpy(&lp->data[offset + newLen],
-+ &lp->data[offset + oldLen],
-+ lp->len - offset - oldLen);
-+
-+ lp->len += deltaLen;
-+ }
-+
-+ offset += newLen;
-+
-+ if (globalFlag)
-+ continue;
-+
-+ if (needPrint)
-+ {
-+ printLines(num1, num1, FALSE);
-+ needPrint = FALSE;
-+ }
-+
-+ lp = lp->next;
-+ num1++;
-+
-+ continue;
-+ }
-+
-+ /*
-+ * The new string is larger, so allocate a new line
-+ * structure and use that. Link it in in place of
-+ * the old line structure.
-+ */
-+ nlp = (LINE *) malloc(sizeof(LINE) + lp->len + deltaLen);
-+
-+ if (nlp == NULL)
-+ {
-+ bb_error_msg("Cannot get memory for line");
-+
-+ return;
-+ }
-+
-+ nlp->len = lp->len + deltaLen;
-+
-+ memcpy(nlp->data, lp->data, offset);
-+
-+ memcpy(&nlp->data[offset], newStr, newLen);
-+
-+ memcpy(&nlp->data[offset + newLen],
-+ &lp->data[offset + oldLen],
-+ lp->len - offset - oldLen);
-+
-+ nlp->next = lp->next;
-+ nlp->prev = lp->prev;
-+ nlp->prev->next = nlp;
-+ nlp->next->prev = nlp;
-+
-+ if (curLine == lp)
-+ curLine = nlp;
-+
-+ free(lp);
-+ lp = nlp;
-+
-+ offset += newLen;
-+
-+ if (globalFlag)
-+ continue;
-+
-+ if (needPrint)
-+ {
-+ printLines(num1, num1, FALSE);
-+ needPrint = FALSE;
-+ }
-+
-+ lp = lp->next;
-+ num1++;
-+ }
-+
-+ if (!didSub)
-+ bb_error_msg("No substitutions found for \"%s\"", oldStr);
-+}
-+
-+
-+/*
-+ * Search a line for the specified string starting at the specified
-+ * offset in the line. Returns the offset of the found string, or -1.
-+ */
-+static LEN
-+findString( const LINE * lp, const char * str, LEN len, LEN offset)
-+{
-+ LEN left;
-+ const char * cp;
-+ const char * ncp;
-+
-+ cp = &lp->data[offset];
-+ left = lp->len - offset;
-+
-+ while (left >= len)
-+ {
-+ ncp = memchr(cp, *str, left);
-+
-+ if (ncp == NULL)
-+ return -1;
-+
-+ left -= (ncp - cp);
-+
-+ if (left < len)
-+ return -1;
-+
-+ cp = ncp;
-+
-+ if (memcmp(cp, str, len) == 0)
-+ return (cp - lp->data);
-+
-+ cp++;
-+ left--;
-+ }
-+
-+ return -1;
-+}
-+
-+
-+/*
-+ * Add lines which are typed in by the user.
-+ * The lines are inserted just before the specified line number.
-+ * The lines are terminated by a line containing a single dot (ugly!),
-+ * or by an end of file.
-+ */
-+static void
-+addLines(NUM num)
-+{
-+ int len;
-+ char buf[USERSIZE + 1];
-+
-+ while (fgets(buf, sizeof(buf), stdin))
-+ {
-+ if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0'))
-+ return;
-+
-+ len = strlen(buf);
-+
-+ if (len == 0)
-+ return;
-+
-+ if (buf[len - 1] != '\n')
-+ {
-+ bb_error_msg("Line too long");
-+
-+ do
-+ {
-+ len = fgetc(stdin);
-+ }
-+ while ((len != EOF) && (len != '\n'));
-+
-+ return;
-+ }
-+
-+ if (!insertLine(num++, buf, len))
-+ return;
-+ }
-+}
-+
-+
-+/*
-+ * Parse a line number argument if it is present. This is a sum
-+ * or difference of numbers, '.', '$', 'x, or a search string.
-+ * Returns TRUE if successful (whether or not there was a number).
-+ * Returns FALSE if there was a parsing error, with a message output.
-+ * Whether there was a number is returned indirectly, as is the number.
-+ * The character pointer which stopped the scan is also returned.
-+ */
-+static BOOL
-+getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum)
-+{
-+ const char * cp;
-+ char * endStr;
-+ char str[USERSIZE];
-+ BOOL haveNum;
-+ NUM value;
-+ NUM num;
-+ NUM sign;
-+
-+ cp = *retcp;
-+ haveNum = FALSE;
-+ value = 0;
-+ sign = 1;
-+
-+ while (TRUE)
-+ {
-+ while (isblank(*cp))
-+ cp++;
-+
-+ switch (*cp)
-+ {
-+ case '.':
-+ haveNum = TRUE;
-+ num = curNum;
-+ cp++;
-+ break;
-+
-+ case '$':
-+ haveNum = TRUE;
-+ num = lastNum;
-+ cp++;
-+ break;
-+
-+ case '\'':
-+ cp++;
-+
-+ if ((*cp < 'a') || (*cp > 'z'))
-+ {
-+ bb_error_msg("Bad mark name");
-+
-+ return FALSE;
-+ }
-+
-+ haveNum = TRUE;
-+ num = marks[*cp++ - 'a'];
-+ break;
-+
-+ case '/':
-+ strcpy(str, ++cp);
-+ endStr = strchr(str, '/');
-+
-+ if (endStr)
-+ {
-+ *endStr++ = '\0';
-+ cp += (endStr - str);
-+ }
-+ else
-+ cp = "";
-+
-+ num = searchLines(str, curNum, lastNum);
-+
-+ if (num == 0)
-+ return FALSE;
-+
-+ haveNum = TRUE;
-+ break;
-+
-+ default:
-+ if (!isdigit(*cp))
-+ {
-+ *retcp = cp;
-+ *retHaveNum = haveNum;
-+ *retNum = value;
-+
-+ return TRUE;
-+ }
-+
-+ num = 0;
-+
-+ while (isdigit(*cp))
-+ num = num * 10 + *cp++ - '0';
-+
-+ haveNum = TRUE;
-+ break;
-+ }
-+
-+ value += num * sign;
-+
-+ while (isblank(*cp))
-+ cp++;
-+
-+ switch (*cp)
-+ {
-+ case '-':
-+ sign = -1;
-+ cp++;
-+ break;
-+
-+ case '+':
-+ sign = 1;
-+ cp++;
-+ break;
-+
-+ default:
-+ *retcp = cp;
-+ *retHaveNum = haveNum;
-+ *retNum = value;
-+
-+ return TRUE;
-+ }
-+ }
-+}
-+
-+
-+/*
-+ * Initialize everything for editing.
-+ */
-+static BOOL
-+initEdit(void)
-+{
-+ int i;
-+
-+ bufSize = INITBUF_SIZE;
-+ bufBase = malloc(bufSize);
-+
-+ if (bufBase == NULL)
-+ {
-+ bb_error_msg("No memory for buffer");
-+
-+ return FALSE;
-+ }
-+
-+ bufPtr = bufBase;
-+ bufUsed = 0;
-+
-+ lines.next = &lines;
-+ lines.prev = &lines;
-+
-+ curLine = NULL;
-+ curNum = 0;
-+ lastNum = 0;
-+ dirty = FALSE;
-+ fileName = NULL;
-+ searchString[0] = '\0';
-+
-+ for (i = 0; i < 26; i++)
-+ marks[i] = 0;
-+
-+ return TRUE;
-+}
-+
-+
-+/*
-+ * Finish editing.
-+ */
-+static void
-+termEdit(void)
-+{
-+ if (bufBase)
-+ free(bufBase);
-+
-+ bufBase = NULL;
-+ bufPtr = NULL;
-+ bufSize = 0;
-+ bufUsed = 0;
-+
-+ if (fileName)
-+ free(fileName);
-+
-+ fileName = NULL;
-+
-+ searchString[0] = '\0';
-+
-+ if (lastNum)
-+ deleteLines(1, lastNum);
-+
-+ lastNum = 0;
-+ curNum = 0;
-+ curLine = NULL;
-+}
-+
-+
-+/*
-+ * Read lines from a file at the specified line number.
-+ * Returns TRUE if the file was successfully read.
-+ */
-+static BOOL
-+readLines(const char * file, NUM num)
-+{
-+ int fd;
-+ int cc;
-+ LEN len;
-+ LEN lineCount;
-+ LEN charCount;
-+ char * cp;
-+
-+ if ((num < 1) || (num > lastNum + 1))
-+ {
-+ bb_error_msg("Bad line for read");
-+
-+ return FALSE;
-+ }
-+
-+ fd = open(file, 0);
-+
-+ if (fd < 0)
-+ {
-+ perror(file);
-+
-+ return FALSE;
-+ }
-+
-+ bufPtr = bufBase;
-+ bufUsed = 0;
-+ lineCount = 0;
-+ charCount = 0;
-+ cc = 0;
-+
-+ printf("\"%s\", ", file);
-+ fflush(stdout);
-+
-+ do
-+ {
-+ cp = memchr(bufPtr, '\n', bufUsed);
-+
-+ if (cp)
-+ {
-+ len = (cp - bufPtr) + 1;
-+
-+ if (!insertLine(num, bufPtr, len))
-+ {
-+ close(fd);
-+
-+ return FALSE;
-+ }
-+
-+ bufPtr += len;
-+ bufUsed -= len;
-+ charCount += len;
-+ lineCount++;
-+ num++;
-+
-+ continue;
-+ }
-+
-+ if (bufPtr != bufBase)
-+ {
-+ memcpy(bufBase, bufPtr, bufUsed);
-+ bufPtr = bufBase + bufUsed;
-+ }
-+
-+ if (bufUsed >= bufSize)
-+ {
-+ len = (bufSize * 3) / 2;
-+ cp = realloc(bufBase, len);
-+
-+ if (cp == NULL)
-+ {
-+ bb_error_msg("No memory for buffer");
-+ close(fd);
-+
-+ return FALSE;
-+ }
-+
-+ bufBase = cp;
-+ bufPtr = bufBase + bufUsed;
-+ bufSize = len;
-+ }
-+
-+ cc = read(fd, bufPtr, bufSize - bufUsed);
-+ bufUsed += cc;
-+ bufPtr = bufBase;
-+
-+ }
-+ while (cc > 0);
-+
-+ if (cc < 0)
-+ {
-+ perror(file);
-+ close(fd);
-+
-+ return FALSE;
-+ }
-+
-+ if (bufUsed)
-+ {
-+ if (!insertLine(num, bufPtr, bufUsed))
-+ {
-+ close(fd);
-+
-+ return -1;
-+ }
-+
-+ lineCount++;
-+ charCount += bufUsed;
-+ }
-+
-+ close(fd);
-+
-+ printf("%d lines%s, %d chars\n", lineCount,
-+ (bufUsed ? " (incomplete)" : ""), charCount);
-+
-+ return TRUE;
-+}
-+
-+
-+/*
-+ * Write the specified lines out to the specified file.
-+ * Returns TRUE if successful, or FALSE on an error with a message output.
-+ */
-+static BOOL
-+writeLines(const char * file, NUM num1, NUM num2)
-+{
-+ int fd;
-+ LINE * lp;
-+ LEN lineCount;
-+ LEN charCount;
-+
-+ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
-+ {
-+ bb_error_msg("Bad line range for write");
-+
-+ return FALSE;
-+ }
-+
-+ lineCount = 0;
-+ charCount = 0;
-+
-+ fd = creat(file, 0666);
-+
-+ if (fd < 0) {
-+ perror(file);
-+
-+ return FALSE;
-+ }
-+
-+ printf("\"%s\", ", file);
-+ fflush(stdout);
-+
-+ lp = findLine(num1);
-+
-+ if (lp == NULL)
-+ {
-+ close(fd);
-+
-+ return FALSE;
-+ }
-+
-+ while (num1++ <= num2)
-+ {
-+ if (write(fd, lp->data, lp->len) != lp->len)
-+ {
-+ perror(file);
-+ close(fd);
-+
-+ return FALSE;
-+ }
-+
-+ charCount += lp->len;
-+ lineCount++;
-+ lp = lp->next;
-+ }
-+
-+ if (close(fd) < 0)
-+ {
-+ perror(file);
-+
-+ return FALSE;
-+ }
-+
-+ printf("%d lines, %d chars\n", lineCount, charCount);
-+
-+ return TRUE;
-+}
-+
-+
-+/*
-+ * Print lines in a specified range.
-+ * The last line printed becomes the current line.
-+ * If expandFlag is TRUE, then the line is printed specially to
-+ * show magic characters.
-+ */
-+static BOOL
-+printLines(NUM num1, NUM num2, BOOL expandFlag)
-+{
-+ const LINE * lp;
-+ const unsigned char * cp;
-+ int ch;
-+ LEN count;
-+
-+ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
-+ {
-+ bb_error_msg("Bad line range for print");
-+
-+ return FALSE;
-+ }
-+
-+ lp = findLine(num1);
-+
-+ if (lp == NULL)
-+ return FALSE;
-+
-+ while (num1 <= num2)
-+ {
-+ if (!expandFlag)
-+ {
-+ write(1, lp->data, lp->len);
-+ setCurNum(num1++);
-+ lp = lp->next;
-+
-+ continue;
-+ }
-+
-+ /*
-+ * Show control characters and characters with the
-+ * high bit set specially.
-+ */
-+ cp = lp->data;
-+ count = lp->len;
-+
-+ if ((count > 0) && (cp[count - 1] == '\n'))
-+ count--;
-+
-+ while (count-- > 0)
-+ {
-+ ch = *cp++;
-+
-+ if (ch & 0x80)
-+ {
-+ fputs("M-", stdout);
-+ ch &= 0x7f;
-+ }
-+
-+ if (ch < ' ')
-+ {
-+ fputc('^', stdout);
-+ ch += '@';
-+ }
-+
-+ if (ch == 0x7f)
-+ {
-+ fputc('^', stdout);
-+ ch = '?';
-+ }
-+
-+ fputc(ch, stdout);
-+ }
-+
-+ fputs("$\n", stdout);
-+
-+ setCurNum(num1++);
-+ lp = lp->next;
-+ }
-+
-+ return TRUE;
-+}
-+
-+
-+/*
-+ * Insert a new line with the specified text.
-+ * The line is inserted so as to become the specified line,
-+ * thus pushing any existing and further lines down one.
-+ * The inserted line is also set to become the current line.
-+ * Returns TRUE if successful.
-+ */
-+static BOOL
-+insertLine(NUM num, const char * data, LEN len)
-+{
-+ LINE * newLp;
-+ LINE * lp;
-+
-+ if ((num < 1) || (num > lastNum + 1))
-+ {
-+ bb_error_msg("Inserting at bad line number");
-+
-+ return FALSE;
-+ }
-+
-+ newLp = (LINE *) malloc(sizeof(LINE) + len - 1);
-+
-+ if (newLp == NULL)
-+ {
-+ bb_error_msg("Failed to allocate memory for line");
-+
-+ return FALSE;
-+ }
-+
-+ memcpy(newLp->data, data, len);
-+ newLp->len = len;
-+
-+ if (num > lastNum)
-+ lp = &lines;
-+ else
-+ {
-+ lp = findLine(num);
-+
-+ if (lp == NULL)
-+ {
-+ free((char *) newLp);
-+
-+ return FALSE;
-+ }
-+ }
-+
-+ newLp->next = lp;
-+ newLp->prev = lp->prev;
-+ lp->prev->next = newLp;
-+ lp->prev = newLp;
-+
-+ lastNum++;
-+ dirty = TRUE;
-+
-+ return setCurNum(num);
-+}
-+
-+
-+/*
-+ * Delete lines from the given range.
-+ */
-+static BOOL
-+deleteLines(NUM num1, NUM num2)
-+{
-+ LINE * lp;
-+ LINE * nlp;
-+ LINE * plp;
-+ NUM count;
-+
-+ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
-+ {
-+ bb_error_msg("Bad line numbers for delete");
-+
-+ return FALSE;
-+ }
-+
-+ lp = findLine(num1);
-+
-+ if (lp == NULL)
-+ return FALSE;
-+
-+ if ((curNum >= num1) && (curNum <= num2))
-+ {
-+ if (num2 < lastNum)
-+ setCurNum(num2 + 1);
-+ else if (num1 > 1)
-+ setCurNum(num1 - 1);
-+ else
-+ curNum = 0;
-+ }
-+
-+ count = num2 - num1 + 1;
-+
-+ if (curNum > num2)
-+ curNum -= count;
-+
-+ lastNum -= count;
-+
-+ while (count-- > 0)
-+ {
-+ nlp = lp->next;
-+ plp = lp->prev;
-+ plp->next = nlp;
-+ nlp->prev = plp;
-+ lp->next = NULL;
-+ lp->prev = NULL;
-+ lp->len = 0;
-+ free(lp);
-+ lp = nlp;
-+ }
-+
-+ dirty = TRUE;
-+
-+ return TRUE;
-+}
-+
-+
-+/*
-+ * Search for a line which contains the specified string.
-+ * If the string is NULL, then the previously searched for string
-+ * is used. The currently searched for string is saved for future use.
-+ * Returns the line number which matches, or 0 if there was no match
-+ * with an error printed.
-+ */
-+static NUM
-+searchLines(const char * str, NUM num1, NUM num2)
-+{
-+ const LINE * lp;
-+ int len;
-+
-+ if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
-+ {
-+ bb_error_msg("Bad line numbers for search");
-+
-+ return 0;
-+ }
-+
-+ if (*str == '\0')
-+ {
-+ if (searchString[0] == '\0')
-+ {
-+ bb_error_msg("No previous search string");
-+
-+ return 0;
-+ }
-+
-+ str = searchString;
-+ }
-+
-+ if (str != searchString)
-+ strcpy(searchString, str);
-+
-+ len = strlen(str);
-+
-+ lp = findLine(num1);
-+
-+ if (lp == NULL)
-+ return 0;
-+
-+ while (num1 <= num2)
-+ {
-+ if (findString(lp, str, len, 0) >= 0)
-+ return num1;
-+
-+ num1++;
-+ lp = lp->next;
-+ }
-+
-+ bb_error_msg("Cannot find string \"%s\"", str);
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * Return a pointer to the specified line number.
-+ */
-+static LINE *
-+findLine(NUM num)
-+{
-+ LINE * lp;
-+ NUM lnum;
-+
-+ if ((num < 1) || (num > lastNum))
-+ {
-+ bb_error_msg("Line number %d does not exist", num);
-+
-+ return NULL;
-+ }
-+
-+ if (curNum <= 0)
-+ {
-+ curNum = 1;
-+ curLine = lines.next;
-+ }
-+
-+ if (num == curNum)
-+ return curLine;
-+
-+ lp = curLine;
-+ lnum = curNum;
-+
-+ if (num < (curNum / 2))
-+ {
-+ lp = lines.next;
-+ lnum = 1;
-+ }
-+ else if (num > ((curNum + lastNum) / 2))
-+ {
-+ lp = lines.prev;
-+ lnum = lastNum;
-+ }
-+
-+ while (lnum < num)
-+ {
-+ lp = lp->next;
-+ lnum++;
-+ }
-+
-+ while (lnum > num)
-+ {
-+ lp = lp->prev;
-+ lnum--;
-+ }
-+
-+ return lp;
-+}
-+
-+
-+/*
-+ * Set the current line number.
-+ * Returns TRUE if successful.
-+ */
-+static BOOL
-+setCurNum(NUM num)
-+{
-+ LINE * lp;
-+
-+ lp = findLine(num);
-+
-+ if (lp == NULL)
-+ return FALSE;
-+
-+ curNum = num;
-+ curLine = lp;
-+
-+ return TRUE;
-+}
-+
-+/* END CODE */