diff options
Diffstat (limited to 'patches')
-rw-r--r-- | patches/ed.patch | 1489 |
1 files changed, 0 insertions, 1489 deletions
diff --git a/patches/ed.patch b/patches/ed.patch deleted file mode 100644 index 6d51830..0000000 --- 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 */ |