return 0;
}
-static char *skip_blank(const char *cp)
-{
- while (isblank(*cp))
- cp++;
- return (char *)cp;
-}
-
/*
* Return a pointer to the specified line number.
*/
const char *cp, *ncp;
cp = &lp->data[offset];
- left = lp->len - offset;
+ left = lp->len - offset - len;
- while (left >= len) {
- ncp = memchr(cp, *str, left);
+ while (left >= 0) {
+ ncp = memchr(cp, str[0], left + 1);
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);
/*
* 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.
+ * or difference of numbers, ".", "$", "'c", or a search string.
+ * Returns pointer which stopped the scan if successful
+ * (whether or not there was a number).
+ * Returns NULL 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)
+static const char* getNum(const char *cp, 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);
+ cp = skip_whitespace(cp);
switch (*cp) {
case '.':
case '\'':
cp++;
- if ((*cp < 'a') || (*cp > 'z')) {
+ if ((unsigned)(*cp - 'a') >= 26) {
bb_error_msg("bad mark name");
- return FALSE;
+ return NULL;
}
haveNum = TRUE;
- num = marks[*cp++ - 'a'];
+ num = marks[(unsigned)(*cp - 'a')];
+ cp++;
break;
case '/':
cp = "";
num = searchLines(str, curNum, lastNum);
if (num == 0)
- return FALSE;
+ return NULL;
haveNum = TRUE;
break;
default:
if (!isdigit(*cp)) {
- *retcp = cp;
*retHaveNum = haveNum;
*retNum = value;
- return TRUE;
+ return cp;
}
num = 0;
while (isdigit(*cp))
value += (minus ? -num : num);
- cp = skip_blank(cp);
+ cp = skip_whitespace(cp);
switch (*cp) {
case '-':
break;
default:
- *retcp = cp;
*retHaveNum = haveNum;
*retNum = value;
- return TRUE;
+ return cp;
}
}
}
* Now we exit to ed prompt. Is in important? */
return;
}
- if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0'))
+ if (buf[0] == '.' && buf[1] == '\n' && buf[2] == '\0')
return;
if (!insertLine(num++, buf, len))
return;
*/
static void doCommands(void)
{
- const char *cp;
- char *endbuf, buf[USERSIZE];
- int len, num1, num2;
- smallint have1, have2;
-
while (TRUE) {
+ char buf[USERSIZE];
+ const char *cp;
+ int len;
+ int n, num1, num2;
+ smallint h, have1, have2;
+
/* Returns:
* -1 on read errors or EOF, or on bare Ctrl-D.
* 0 on ctrl-C,
len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1);
if (len <= 0)
return;
- endbuf = &buf[len - 1];
- while ((endbuf > buf) && isblank(endbuf[-1]))
- endbuf--;
- *endbuf = '\0';
-
- cp = skip_blank(buf);
- have1 = FALSE;
- have2 = FALSE;
+ while (len && isspace(buf[--len]))
+ buf[len] = '\0';
if ((curNum == 0) && (lastNum > 0)) {
curNum = 1;
curLine = lines.next;
}
- if (!getNum(&cp, &have1, &num1))
+ have1 = FALSE;
+ have2 = FALSE;
+ /* Don't pass &haveN, &numN to getNum() since this forces
+ * compiler to keep them on stack, not in registers,
+ * which is usually quite suboptimal.
+ * Using intermediate variables shrinks code by ~150 bytes.
+ */
+ cp = getNum(skip_whitespace(buf), &h, &n);
+ if (!cp)
continue;
-
- cp = skip_blank(cp);
-
+ have1 = h;
+ num1 = n;
+ cp = skip_whitespace(cp);
if (*cp == ',') {
- cp++;
- if (!getNum(&cp, &have2, &num2))
+ cp = getNum(cp + 1, &h, &n);
+ if (!cp)
continue;
+ num2 = n;
if (!have1)
num1 = 1;
- if (!have2)
+ if (!h)
num2 = lastNum;
have1 = TRUE;
have2 = TRUE;
break;
case 'f':
- if (*cp && !isblank(*cp)) {
+ if (*cp != '\0' && *cp != ' ') {
bb_error_msg("bad file command");
break;
}
- cp = skip_blank(cp);
+ cp = skip_whitespace(cp);
if (*cp == '\0') {
if (fileName)
printf("\"%s\"\n", fileName);
break;
case 'i':
+ if (!have1 && lastNum == 0)
+ num1 = 1;
addLines(num1);
break;
case 'k':
- cp = skip_blank(cp);
- if ((*cp < 'a') || (*cp > 'z') || cp[1]) {
+ cp = skip_whitespace(cp);
+ if ((unsigned)(*cp - 'a') >= 26 || cp[1]) {
bb_error_msg("bad mark name");
break;
}
- marks[*cp - 'a'] = num2;
+ marks[(unsigned)(*cp - 'a')] = num2;
break;
case 'l':
break;
case 'q':
- cp = skip_blank(cp);
+ cp = skip_whitespace(cp);
if (have1 || *cp) {
bb_error_msg("bad quit command");
break;
/* read error/EOF - no way to continue */
if (len < 0)
return;
- cp = skip_blank(buf);
+ cp = skip_whitespace(buf);
if ((*cp | 0x20) == 'y') /* Y or y */
return;
break;
case 'r':
- if (*cp && !isblank(*cp)) {
+ if (*cp != '\0' && *cp != ' ') {
bb_error_msg("bad read command");
break;
}
- cp = skip_blank(cp);
+ cp = skip_whitespace(cp);
if (*cp == '\0') {
bb_error_msg("no file name");
break;
break;
case 'w':
- if (*cp && !isblank(*cp)) {
+ if (*cp != '\0' && *cp != ' ') {
bb_error_msg("bad write command");
break;
}
- cp = skip_blank(cp);
+ cp = skip_whitespace(cp);
+ if (*cp == '\0') {
+ cp = fileName;
+ if (!cp) {
+ bb_error_msg("no file name specified");
+ break;
+ }
+ }
if (!have1) {
num1 = 1;
num2 = lastNum;
- }
- if (*cp == '\0')
- cp = fileName;
- if (cp == NULL) {
- bb_error_msg("no file name specified");
- break;
+ dirty = FALSE;
}
writeLines(cp, num1, num2);
break;