- 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 = xmalloc(sizeof(LINE) + lp->len + deltaLen);
-
- 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 int findString(const LINE *lp, const char *str, int len, int offset)
-{
- int left;
- const char *cp, *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(int num)
-{
- int len;
- char buf[USERSIZE + 1];
-
- while (1) {
- /* Returns:
- * -1 on read errors or EOF, or on bare Ctrl-D.
- * 0 on ctrl-C,
- * >0 length of input string, including terminating '\n'
- */
- len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1);
- if (len <= 0) {
- /* Previously, ctrl-C was exiting to shell.
- * Now we exit to ed prompt. Is in important? */
- return;
- }
- if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0'))
- 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 int getNum(const char **retcp, smallint *retHaveNum, int *retNum)
-{
- const char *cp;
- char *endStr, str[USERSIZE];
- int value, num;
- smallint haveNum, minus;
-
- cp = *retcp;
- value = 0;
- haveNum = FALSE;
- minus = 0;
-
- while (TRUE) {
- cp = skip_blank(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 += (minus ? -num : num);
-
- cp = skip_blank(cp);
-
- switch (*cp) {
- case '-':
- minus = 1;
- cp++;
- break;
-
- case '+':
- minus = 0;
- cp++;
- break;
-
- default:
- *retcp = cp;
- *retHaveNum = haveNum;
- *retNum = value;
- return TRUE;
- }
- }
-}
-
-
-/*
- * Read lines from a file at the specified line number.
- * Returns TRUE if the file was successfully read.
- */
-static int readLines(const char *file, int num)
-{
- int fd, cc;
- int len, lineCount, 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) {
- bb_simple_perror_msg(file);
- return FALSE;
- }
-
- bufPtr = bufBase;
- bufUsed = 0;
- lineCount = 0;
- charCount = 0;
- cc = 0;
-
- printf("\"%s\", ", file);
- fflush_all();
-
- 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;
- }