diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/awk.c | 94 | ||||
-rw-r--r-- | editors/patch.c | 26 | ||||
-rw-r--r-- | editors/sed.c | 84 | ||||
-rw-r--r-- | editors/vi.c | 294 |
4 files changed, 282 insertions, 216 deletions
diff --git a/editors/awk.c b/editors/awk.c index 7685546e5..71abca215 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -25,6 +25,7 @@ | |||
25 | * to perform debug printfs to stderr: */ | 25 | * to perform debug printfs to stderr: */ |
26 | #define debug_printf_walker(...) do {} while (0) | 26 | #define debug_printf_walker(...) do {} while (0) |
27 | #define debug_printf_eval(...) do {} while (0) | 27 | #define debug_printf_eval(...) do {} while (0) |
28 | #define debug_printf_parse(...) do {} while (0) | ||
28 | 29 | ||
29 | #ifndef debug_printf_walker | 30 | #ifndef debug_printf_walker |
30 | # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) | 31 | # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) |
@@ -32,6 +33,9 @@ | |||
32 | #ifndef debug_printf_eval | 33 | #ifndef debug_printf_eval |
33 | # define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__)) | 34 | # define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__)) |
34 | #endif | 35 | #endif |
36 | #ifndef debug_printf_parse | ||
37 | # define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__)) | ||
38 | #endif | ||
35 | 39 | ||
36 | 40 | ||
37 | 41 | ||
@@ -238,6 +242,9 @@ typedef struct tsplitter_s { | |||
238 | * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1, | 242 | * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1, |
239 | * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string | 243 | * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string |
240 | */ | 244 | */ |
245 | #undef P | ||
246 | #undef PRIMASK | ||
247 | #undef PRIMASK2 | ||
241 | #define P(x) (x << 24) | 248 | #define P(x) (x << 24) |
242 | #define PRIMASK 0x7F000000 | 249 | #define PRIMASK 0x7F000000 |
243 | #define PRIMASK2 0x7E000000 | 250 | #define PRIMASK2 0x7E000000 |
@@ -432,13 +439,13 @@ struct globals { | |||
432 | smallint nextrec; | 439 | smallint nextrec; |
433 | smallint nextfile; | 440 | smallint nextfile; |
434 | smallint is_f0_split; | 441 | smallint is_f0_split; |
442 | smallint t_rollback; | ||
435 | }; | 443 | }; |
436 | struct globals2 { | 444 | struct globals2 { |
437 | uint32_t t_info; /* often used */ | 445 | uint32_t t_info; /* often used */ |
438 | uint32_t t_tclass; | 446 | uint32_t t_tclass; |
439 | char *t_string; | 447 | char *t_string; |
440 | int t_lineno; | 448 | int t_lineno; |
441 | int t_rollback; | ||
442 | 449 | ||
443 | var *intvar[NUM_INTERNAL_VARS]; /* often used */ | 450 | var *intvar[NUM_INTERNAL_VARS]; /* often used */ |
444 | 451 | ||
@@ -496,11 +503,11 @@ struct globals2 { | |||
496 | #define nextrec (G1.nextrec ) | 503 | #define nextrec (G1.nextrec ) |
497 | #define nextfile (G1.nextfile ) | 504 | #define nextfile (G1.nextfile ) |
498 | #define is_f0_split (G1.is_f0_split ) | 505 | #define is_f0_split (G1.is_f0_split ) |
506 | #define t_rollback (G1.t_rollback ) | ||
499 | #define t_info (G.t_info ) | 507 | #define t_info (G.t_info ) |
500 | #define t_tclass (G.t_tclass ) | 508 | #define t_tclass (G.t_tclass ) |
501 | #define t_string (G.t_string ) | 509 | #define t_string (G.t_string ) |
502 | #define t_lineno (G.t_lineno ) | 510 | #define t_lineno (G.t_lineno ) |
503 | #define t_rollback (G.t_rollback ) | ||
504 | #define intvar (G.intvar ) | 511 | #define intvar (G.intvar ) |
505 | #define fsplitter (G.fsplitter ) | 512 | #define fsplitter (G.fsplitter ) |
506 | #define rsplitter (G.rsplitter ) | 513 | #define rsplitter (G.rsplitter ) |
@@ -1008,6 +1015,7 @@ static uint32_t next_token(uint32_t expected) | |||
1008 | 1015 | ||
1009 | if (*p == '\0') { | 1016 | if (*p == '\0') { |
1010 | tc = TC_EOF; | 1017 | tc = TC_EOF; |
1018 | debug_printf_parse("%s: token found: TC_EOF\n", __func__); | ||
1011 | 1019 | ||
1012 | } else if (*p == '\"') { | 1020 | } else if (*p == '\"') { |
1013 | /* it's a string */ | 1021 | /* it's a string */ |
@@ -1023,6 +1031,7 @@ static uint32_t next_token(uint32_t expected) | |||
1023 | p++; | 1031 | p++; |
1024 | *s = '\0'; | 1032 | *s = '\0'; |
1025 | tc = TC_STRING; | 1033 | tc = TC_STRING; |
1034 | debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string); | ||
1026 | 1035 | ||
1027 | } else if ((expected & TC_REGEXP) && *p == '/') { | 1036 | } else if ((expected & TC_REGEXP) && *p == '/') { |
1028 | /* it's regexp */ | 1037 | /* it's regexp */ |
@@ -1045,6 +1054,7 @@ static uint32_t next_token(uint32_t expected) | |||
1045 | p++; | 1054 | p++; |
1046 | *s = '\0'; | 1055 | *s = '\0'; |
1047 | tc = TC_REGEXP; | 1056 | tc = TC_REGEXP; |
1057 | debug_printf_parse("%s: token found:'%s' TC_REGEXP\n", __func__, t_string); | ||
1048 | 1058 | ||
1049 | } else if (*p == '.' || isdigit(*p)) { | 1059 | } else if (*p == '.' || isdigit(*p)) { |
1050 | /* it's a number */ | 1060 | /* it's a number */ |
@@ -1054,6 +1064,7 @@ static uint32_t next_token(uint32_t expected) | |||
1054 | if (*p == '.') | 1064 | if (*p == '.') |
1055 | syntax_error(EMSG_UNEXP_TOKEN); | 1065 | syntax_error(EMSG_UNEXP_TOKEN); |
1056 | tc = TC_NUMBER; | 1066 | tc = TC_NUMBER; |
1067 | debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double); | ||
1057 | 1068 | ||
1058 | } else { | 1069 | } else { |
1059 | /* search for something known */ | 1070 | /* search for something known */ |
@@ -1076,6 +1087,7 @@ static uint32_t next_token(uint32_t expected) | |||
1076 | ) { | 1087 | ) { |
1077 | /* then this is what we are looking for */ | 1088 | /* then this is what we are looking for */ |
1078 | t_info = *ti; | 1089 | t_info = *ti; |
1090 | debug_printf_parse("%s: token found:'%.*s' t_info:%x\n", __func__, l, p, t_info); | ||
1079 | p += l; | 1091 | p += l; |
1080 | goto token_found; | 1092 | goto token_found; |
1081 | } | 1093 | } |
@@ -1099,14 +1111,17 @@ static uint32_t next_token(uint32_t expected) | |||
1099 | p = skip_spaces(p); | 1111 | p = skip_spaces(p); |
1100 | if (*p == '(') { | 1112 | if (*p == '(') { |
1101 | tc = TC_FUNCTION; | 1113 | tc = TC_FUNCTION; |
1114 | debug_printf_parse("%s: token found:'%s' TC_FUNCTION\n", __func__, t_string); | ||
1102 | } else { | 1115 | } else { |
1103 | if (*p == '[') { | 1116 | if (*p == '[') { |
1104 | p++; | 1117 | p++; |
1105 | tc = TC_ARRAY; | 1118 | tc = TC_ARRAY; |
1106 | } | 1119 | debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string); |
1120 | } else | ||
1121 | debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string); | ||
1107 | } | 1122 | } |
1108 | token_found: ; | ||
1109 | } | 1123 | } |
1124 | token_found: | ||
1110 | g_pos = p; | 1125 | g_pos = p; |
1111 | 1126 | ||
1112 | /* skipping newlines in some cases */ | 1127 | /* skipping newlines in some cases */ |
@@ -1178,6 +1193,8 @@ static node *parse_expr(uint32_t iexp) | |||
1178 | uint32_t tc, xtc; | 1193 | uint32_t tc, xtc; |
1179 | var *v; | 1194 | var *v; |
1180 | 1195 | ||
1196 | debug_printf_parse("%s(%x)\n", __func__, iexp); | ||
1197 | |||
1181 | sn.info = PRIMASK; | 1198 | sn.info = PRIMASK; |
1182 | sn.r.n = glptr = NULL; | 1199 | sn.r.n = glptr = NULL; |
1183 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; | 1200 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; |
@@ -1186,12 +1203,14 @@ static node *parse_expr(uint32_t iexp) | |||
1186 | 1203 | ||
1187 | if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { | 1204 | if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { |
1188 | /* input redirection (<) attached to glptr node */ | 1205 | /* input redirection (<) attached to glptr node */ |
1206 | debug_printf_parse("%s: input redir\n", __func__); | ||
1189 | cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); | 1207 | cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); |
1190 | cn->a.n = glptr; | 1208 | cn->a.n = glptr; |
1191 | xtc = TC_OPERAND | TC_UOPPRE; | 1209 | xtc = TC_OPERAND | TC_UOPPRE; |
1192 | glptr = NULL; | 1210 | glptr = NULL; |
1193 | 1211 | ||
1194 | } else if (tc & (TC_BINOP | TC_UOPPOST)) { | 1212 | } else if (tc & (TC_BINOP | TC_UOPPOST)) { |
1213 | debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__); | ||
1195 | /* for binary and postfix-unary operators, jump back over | 1214 | /* for binary and postfix-unary operators, jump back over |
1196 | * previous operators with higher priority */ | 1215 | * previous operators with higher priority */ |
1197 | vn = cn; | 1216 | vn = cn; |
@@ -1221,6 +1240,7 @@ static node *parse_expr(uint32_t iexp) | |||
1221 | vn->a.n = cn; | 1240 | vn->a.n = cn; |
1222 | 1241 | ||
1223 | } else { | 1242 | } else { |
1243 | debug_printf_parse("%s: other\n", __func__); | ||
1224 | /* for operands and prefix-unary operators, attach them | 1244 | /* for operands and prefix-unary operators, attach them |
1225 | * to last node */ | 1245 | * to last node */ |
1226 | vn = cn; | 1246 | vn = cn; |
@@ -1228,12 +1248,14 @@ static node *parse_expr(uint32_t iexp) | |||
1228 | cn->a.n = vn; | 1248 | cn->a.n = vn; |
1229 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; | 1249 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; |
1230 | if (tc & (TC_OPERAND | TC_REGEXP)) { | 1250 | if (tc & (TC_OPERAND | TC_REGEXP)) { |
1251 | debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__); | ||
1231 | xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp; | 1252 | xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp; |
1232 | /* one should be very careful with switch on tclass - | 1253 | /* one should be very careful with switch on tclass - |
1233 | * only simple tclasses should be used! */ | 1254 | * only simple tclasses should be used! */ |
1234 | switch (tc) { | 1255 | switch (tc) { |
1235 | case TC_VARIABLE: | 1256 | case TC_VARIABLE: |
1236 | case TC_ARRAY: | 1257 | case TC_ARRAY: |
1258 | debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__); | ||
1237 | cn->info = OC_VAR; | 1259 | cn->info = OC_VAR; |
1238 | v = hash_search(ahash, t_string); | 1260 | v = hash_search(ahash, t_string); |
1239 | if (v != NULL) { | 1261 | if (v != NULL) { |
@@ -1250,6 +1272,7 @@ static node *parse_expr(uint32_t iexp) | |||
1250 | 1272 | ||
1251 | case TC_NUMBER: | 1273 | case TC_NUMBER: |
1252 | case TC_STRING: | 1274 | case TC_STRING: |
1275 | debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__); | ||
1253 | cn->info = OC_VAR; | 1276 | cn->info = OC_VAR; |
1254 | v = cn->l.v = xzalloc(sizeof(var)); | 1277 | v = cn->l.v = xzalloc(sizeof(var)); |
1255 | if (tc & TC_NUMBER) | 1278 | if (tc & TC_NUMBER) |
@@ -1259,32 +1282,41 @@ static node *parse_expr(uint32_t iexp) | |||
1259 | break; | 1282 | break; |
1260 | 1283 | ||
1261 | case TC_REGEXP: | 1284 | case TC_REGEXP: |
1285 | debug_printf_parse("%s: TC_REGEXP\n", __func__); | ||
1262 | mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2)); | 1286 | mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2)); |
1263 | break; | 1287 | break; |
1264 | 1288 | ||
1265 | case TC_FUNCTION: | 1289 | case TC_FUNCTION: |
1290 | debug_printf_parse("%s: TC_FUNCTION\n", __func__); | ||
1266 | cn->info = OC_FUNC; | 1291 | cn->info = OC_FUNC; |
1267 | cn->r.f = newfunc(t_string); | 1292 | cn->r.f = newfunc(t_string); |
1268 | cn->l.n = condition(); | 1293 | cn->l.n = condition(); |
1269 | break; | 1294 | break; |
1270 | 1295 | ||
1271 | case TC_SEQSTART: | 1296 | case TC_SEQSTART: |
1297 | debug_printf_parse("%s: TC_SEQSTART\n", __func__); | ||
1272 | cn = vn->r.n = parse_expr(TC_SEQTERM); | 1298 | cn = vn->r.n = parse_expr(TC_SEQTERM); |
1299 | if (!cn) | ||
1300 | syntax_error("Empty sequence"); | ||
1273 | cn->a.n = vn; | 1301 | cn->a.n = vn; |
1274 | break; | 1302 | break; |
1275 | 1303 | ||
1276 | case TC_GETLINE: | 1304 | case TC_GETLINE: |
1305 | debug_printf_parse("%s: TC_GETLINE\n", __func__); | ||
1277 | glptr = cn; | 1306 | glptr = cn; |
1278 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; | 1307 | xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; |
1279 | break; | 1308 | break; |
1280 | 1309 | ||
1281 | case TC_BUILTIN: | 1310 | case TC_BUILTIN: |
1311 | debug_printf_parse("%s: TC_BUILTIN\n", __func__); | ||
1282 | cn->l.n = condition(); | 1312 | cn->l.n = condition(); |
1283 | break; | 1313 | break; |
1284 | } | 1314 | } |
1285 | } | 1315 | } |
1286 | } | 1316 | } |
1287 | } | 1317 | } |
1318 | |||
1319 | debug_printf_parse("%s() returns %p\n", __func__, sn.r.n); | ||
1288 | return sn.r.n; | 1320 | return sn.r.n; |
1289 | } | 1321 | } |
1290 | 1322 | ||
@@ -1353,18 +1385,25 @@ static void chain_group(void) | |||
1353 | } while (c & TC_NEWLINE); | 1385 | } while (c & TC_NEWLINE); |
1354 | 1386 | ||
1355 | if (c & TC_GRPSTART) { | 1387 | if (c & TC_GRPSTART) { |
1388 | debug_printf_parse("%s: TC_GRPSTART\n", __func__); | ||
1356 | while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) { | 1389 | while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) { |
1390 | debug_printf_parse("%s: !TC_GRPTERM\n", __func__); | ||
1357 | if (t_tclass & TC_NEWLINE) | 1391 | if (t_tclass & TC_NEWLINE) |
1358 | continue; | 1392 | continue; |
1359 | rollback_token(); | 1393 | rollback_token(); |
1360 | chain_group(); | 1394 | chain_group(); |
1361 | } | 1395 | } |
1396 | debug_printf_parse("%s: TC_GRPTERM\n", __func__); | ||
1362 | } else if (c & (TC_OPSEQ | TC_OPTERM)) { | 1397 | } else if (c & (TC_OPSEQ | TC_OPTERM)) { |
1398 | debug_printf_parse("%s: TC_OPSEQ | TC_OPTERM\n", __func__); | ||
1363 | rollback_token(); | 1399 | rollback_token(); |
1364 | chain_expr(OC_EXEC | Vx); | 1400 | chain_expr(OC_EXEC | Vx); |
1365 | } else { /* TC_STATEMNT */ | 1401 | } else { |
1402 | /* TC_STATEMNT */ | ||
1403 | debug_printf_parse("%s: TC_STATEMNT(?)\n", __func__); | ||
1366 | switch (t_info & OPCLSMASK) { | 1404 | switch (t_info & OPCLSMASK) { |
1367 | case ST_IF: | 1405 | case ST_IF: |
1406 | debug_printf_parse("%s: ST_IF\n", __func__); | ||
1368 | n = chain_node(OC_BR | Vx); | 1407 | n = chain_node(OC_BR | Vx); |
1369 | n->l.n = condition(); | 1408 | n->l.n = condition(); |
1370 | chain_group(); | 1409 | chain_group(); |
@@ -1379,12 +1418,14 @@ static void chain_group(void) | |||
1379 | break; | 1418 | break; |
1380 | 1419 | ||
1381 | case ST_WHILE: | 1420 | case ST_WHILE: |
1421 | debug_printf_parse("%s: ST_WHILE\n", __func__); | ||
1382 | n2 = condition(); | 1422 | n2 = condition(); |
1383 | n = chain_loop(NULL); | 1423 | n = chain_loop(NULL); |
1384 | n->l.n = n2; | 1424 | n->l.n = n2; |
1385 | break; | 1425 | break; |
1386 | 1426 | ||
1387 | case ST_DO: | 1427 | case ST_DO: |
1428 | debug_printf_parse("%s: ST_DO\n", __func__); | ||
1388 | n2 = chain_node(OC_EXEC); | 1429 | n2 = chain_node(OC_EXEC); |
1389 | n = chain_loop(NULL); | 1430 | n = chain_loop(NULL); |
1390 | n2->a.n = n->a.n; | 1431 | n2->a.n = n->a.n; |
@@ -1393,6 +1434,7 @@ static void chain_group(void) | |||
1393 | break; | 1434 | break; |
1394 | 1435 | ||
1395 | case ST_FOR: | 1436 | case ST_FOR: |
1437 | debug_printf_parse("%s: ST_FOR\n", __func__); | ||
1396 | next_token(TC_SEQSTART); | 1438 | next_token(TC_SEQSTART); |
1397 | n2 = parse_expr(TC_SEMICOL | TC_SEQTERM); | 1439 | n2 = parse_expr(TC_SEMICOL | TC_SEQTERM); |
1398 | if (t_tclass & TC_SEQTERM) { /* for-in */ | 1440 | if (t_tclass & TC_SEQTERM) { /* for-in */ |
@@ -1418,6 +1460,7 @@ static void chain_group(void) | |||
1418 | 1460 | ||
1419 | case OC_PRINT: | 1461 | case OC_PRINT: |
1420 | case OC_PRINTF: | 1462 | case OC_PRINTF: |
1463 | debug_printf_parse("%s: OC_PRINT[F]\n", __func__); | ||
1421 | n = chain_node(t_info); | 1464 | n = chain_node(t_info); |
1422 | n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM); | 1465 | n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM); |
1423 | if (t_tclass & TC_OUTRDR) { | 1466 | if (t_tclass & TC_OUTRDR) { |
@@ -1429,17 +1472,20 @@ static void chain_group(void) | |||
1429 | break; | 1472 | break; |
1430 | 1473 | ||
1431 | case OC_BREAK: | 1474 | case OC_BREAK: |
1475 | debug_printf_parse("%s: OC_BREAK\n", __func__); | ||
1432 | n = chain_node(OC_EXEC); | 1476 | n = chain_node(OC_EXEC); |
1433 | n->a.n = break_ptr; | 1477 | n->a.n = break_ptr; |
1434 | break; | 1478 | break; |
1435 | 1479 | ||
1436 | case OC_CONTINUE: | 1480 | case OC_CONTINUE: |
1481 | debug_printf_parse("%s: OC_CONTINUE\n", __func__); | ||
1437 | n = chain_node(OC_EXEC); | 1482 | n = chain_node(OC_EXEC); |
1438 | n->a.n = continue_ptr; | 1483 | n->a.n = continue_ptr; |
1439 | break; | 1484 | break; |
1440 | 1485 | ||
1441 | /* delete, next, nextfile, return, exit */ | 1486 | /* delete, next, nextfile, return, exit */ |
1442 | default: | 1487 | default: |
1488 | debug_printf_parse("%s: default\n", __func__); | ||
1443 | chain_expr(t_info); | 1489 | chain_expr(t_info); |
1444 | } | 1490 | } |
1445 | } | 1491 | } |
@@ -1457,19 +1503,24 @@ static void parse_program(char *p) | |||
1457 | while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | | 1503 | while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | |
1458 | TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) { | 1504 | TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) { |
1459 | 1505 | ||
1460 | if (tclass & TC_OPTERM) | 1506 | if (tclass & TC_OPTERM) { |
1507 | debug_printf_parse("%s: TC_OPTERM\n", __func__); | ||
1461 | continue; | 1508 | continue; |
1509 | } | ||
1462 | 1510 | ||
1463 | seq = &mainseq; | 1511 | seq = &mainseq; |
1464 | if (tclass & TC_BEGIN) { | 1512 | if (tclass & TC_BEGIN) { |
1513 | debug_printf_parse("%s: TC_BEGIN\n", __func__); | ||
1465 | seq = &beginseq; | 1514 | seq = &beginseq; |
1466 | chain_group(); | 1515 | chain_group(); |
1467 | 1516 | ||
1468 | } else if (tclass & TC_END) { | 1517 | } else if (tclass & TC_END) { |
1518 | debug_printf_parse("%s: TC_END\n", __func__); | ||
1469 | seq = &endseq; | 1519 | seq = &endseq; |
1470 | chain_group(); | 1520 | chain_group(); |
1471 | 1521 | ||
1472 | } else if (tclass & TC_FUNCDECL) { | 1522 | } else if (tclass & TC_FUNCDECL) { |
1523 | debug_printf_parse("%s: TC_FUNCDECL\n", __func__); | ||
1473 | next_token(TC_FUNCTION); | 1524 | next_token(TC_FUNCTION); |
1474 | g_pos++; | 1525 | g_pos++; |
1475 | f = newfunc(t_string); | 1526 | f = newfunc(t_string); |
@@ -1487,22 +1538,27 @@ static void parse_program(char *p) | |||
1487 | clear_array(ahash); | 1538 | clear_array(ahash); |
1488 | 1539 | ||
1489 | } else if (tclass & TC_OPSEQ) { | 1540 | } else if (tclass & TC_OPSEQ) { |
1541 | debug_printf_parse("%s: TC_OPSEQ\n", __func__); | ||
1490 | rollback_token(); | 1542 | rollback_token(); |
1491 | cn = chain_node(OC_TEST); | 1543 | cn = chain_node(OC_TEST); |
1492 | cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART); | 1544 | cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART); |
1493 | if (t_tclass & TC_GRPSTART) { | 1545 | if (t_tclass & TC_GRPSTART) { |
1546 | debug_printf_parse("%s: TC_GRPSTART\n", __func__); | ||
1494 | rollback_token(); | 1547 | rollback_token(); |
1495 | chain_group(); | 1548 | chain_group(); |
1496 | } else { | 1549 | } else { |
1550 | debug_printf_parse("%s: !TC_GRPSTART\n", __func__); | ||
1497 | chain_node(OC_PRINT); | 1551 | chain_node(OC_PRINT); |
1498 | } | 1552 | } |
1499 | cn->r.n = mainseq.last; | 1553 | cn->r.n = mainseq.last; |
1500 | 1554 | ||
1501 | } else /* if (tclass & TC_GRPSTART) */ { | 1555 | } else /* if (tclass & TC_GRPSTART) */ { |
1556 | debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__); | ||
1502 | rollback_token(); | 1557 | rollback_token(); |
1503 | chain_group(); | 1558 | chain_group(); |
1504 | } | 1559 | } |
1505 | } | 1560 | } |
1561 | debug_printf_parse("%s: TC_EOF\n", __func__); | ||
1506 | } | 1562 | } |
1507 | 1563 | ||
1508 | 1564 | ||
@@ -2627,7 +2683,7 @@ static var *evaluate(node *op, var *res) | |||
2627 | rsm = iF; | 2683 | rsm = iF; |
2628 | } | 2684 | } |
2629 | 2685 | ||
2630 | if (!rsm->F) { | 2686 | if (!rsm || !rsm->F) { |
2631 | setvar_i(intvar[ERRNO], errno); | 2687 | setvar_i(intvar[ERRNO], errno); |
2632 | setvar_i(res, -1); | 2688 | setvar_i(res, -1); |
2633 | break; | 2689 | break; |
@@ -2961,7 +3017,7 @@ static rstream *next_input_file(void) | |||
2961 | #define rsm (G.next_input_file__rsm) | 3017 | #define rsm (G.next_input_file__rsm) |
2962 | #define files_happen (G.next_input_file__files_happen) | 3018 | #define files_happen (G.next_input_file__files_happen) |
2963 | 3019 | ||
2964 | FILE *F = NULL; | 3020 | FILE *F; |
2965 | const char *fname, *ind; | 3021 | const char *fname, *ind; |
2966 | 3022 | ||
2967 | if (rsm.F) | 3023 | if (rsm.F) |
@@ -2969,19 +3025,21 @@ static rstream *next_input_file(void) | |||
2969 | rsm.F = NULL; | 3025 | rsm.F = NULL; |
2970 | rsm.pos = rsm.adv = 0; | 3026 | rsm.pos = rsm.adv = 0; |
2971 | 3027 | ||
2972 | do { | 3028 | for (;;) { |
2973 | if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) { | 3029 | if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) { |
2974 | if (files_happen) | 3030 | if (files_happen) |
2975 | return NULL; | 3031 | return NULL; |
2976 | fname = "-"; | 3032 | fname = "-"; |
2977 | F = stdin; | 3033 | F = stdin; |
2978 | } else { | 3034 | break; |
2979 | ind = getvar_s(incvar(intvar[ARGIND])); | ||
2980 | fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind)); | ||
2981 | if (fname && *fname && !is_assignment(fname)) | ||
2982 | F = xfopen_stdin(fname); | ||
2983 | } | 3035 | } |
2984 | } while (!F); | 3036 | ind = getvar_s(incvar(intvar[ARGIND])); |
3037 | fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind)); | ||
3038 | if (fname && *fname && !is_assignment(fname)) { | ||
3039 | F = xfopen_stdin(fname); | ||
3040 | break; | ||
3041 | } | ||
3042 | } | ||
2985 | 3043 | ||
2986 | files_happen = TRUE; | 3044 | files_happen = TRUE; |
2987 | setvar_s(intvar[FILENAME], fname); | 3045 | setvar_s(intvar[FILENAME], fname); |
@@ -2995,7 +3053,7 @@ int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
2995 | int awk_main(int argc, char **argv) | 3053 | int awk_main(int argc, char **argv) |
2996 | { | 3054 | { |
2997 | unsigned opt; | 3055 | unsigned opt; |
2998 | char *opt_F, *opt_W; | 3056 | char *opt_F; |
2999 | llist_t *list_v = NULL; | 3057 | llist_t *list_v = NULL; |
3000 | llist_t *list_f = NULL; | 3058 | llist_t *list_f = NULL; |
3001 | int i, j; | 3059 | int i, j; |
@@ -3057,7 +3115,7 @@ int awk_main(int argc, char **argv) | |||
3057 | } | 3115 | } |
3058 | } | 3116 | } |
3059 | opt_complementary = "v::f::"; /* -v and -f can occur multiple times */ | 3117 | opt_complementary = "v::f::"; /* -v and -f can occur multiple times */ |
3060 | opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W); | 3118 | opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL); |
3061 | argv += optind; | 3119 | argv += optind; |
3062 | argc -= optind; | 3120 | argc -= optind; |
3063 | if (opt & 0x1) | 3121 | if (opt & 0x1) |
@@ -3091,7 +3149,7 @@ int awk_main(int argc, char **argv) | |||
3091 | parse_program(*argv++); | 3149 | parse_program(*argv++); |
3092 | } | 3150 | } |
3093 | if (opt & 0x8) // -W | 3151 | if (opt & 0x8) // -W |
3094 | bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W); | 3152 | bb_error_msg("warning: option -W is ignored"); |
3095 | 3153 | ||
3096 | /* fill in ARGV array */ | 3154 | /* fill in ARGV array */ |
3097 | setvar_i(intvar[ARGC], argc); | 3155 | setvar_i(intvar[ARGC], argc); |
diff --git a/editors/patch.c b/editors/patch.c index ec5b8e7ad..13785ef46 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -70,8 +70,7 @@ struct double_list { | |||
70 | 70 | ||
71 | // Free all the elements of a linked list | 71 | // Free all the elements of a linked list |
72 | // Call freeit() on each element before freeing it. | 72 | // Call freeit() on each element before freeing it. |
73 | static | 73 | static void dlist_free(struct double_list *list, void (*freeit)(void *data)) |
74 | void dlist_free(struct double_list *list, void (*freeit)(void *data)) | ||
75 | { | 74 | { |
76 | while (list) { | 75 | while (list) { |
77 | void *pop = list; | 76 | void *pop = list; |
@@ -83,8 +82,7 @@ void dlist_free(struct double_list *list, void (*freeit)(void *data)) | |||
83 | } | 82 | } |
84 | 83 | ||
85 | // Add an entry before "list" element in (circular) doubly linked list | 84 | // Add an entry before "list" element in (circular) doubly linked list |
86 | static | 85 | static struct double_list *dlist_add(struct double_list **list, char *data) |
87 | struct double_list *dlist_add(struct double_list **list, char *data) | ||
88 | { | 86 | { |
89 | struct double_list *llist; | 87 | struct double_list *llist; |
90 | struct double_list *line = xmalloc(sizeof(*line)); | 88 | struct double_list *line = xmalloc(sizeof(*line)); |
@@ -232,7 +230,7 @@ static int apply_one_hunk(void) | |||
232 | else matcheof = 0; | 230 | else matcheof = 0; |
233 | if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); | 231 | if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); |
234 | } | 232 | } |
235 | matcheof = matcheof < TT.context; | 233 | matcheof = !matcheof || matcheof < TT.context; |
236 | 234 | ||
237 | if (PATCH_DEBUG) fdprintf(2,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); | 235 | if (PATCH_DEBUG) fdprintf(2,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); |
238 | 236 | ||
@@ -476,19 +474,21 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
476 | 474 | ||
477 | // We're deleting oldname if new file is /dev/null (before -p) | 475 | // We're deleting oldname if new file is /dev/null (before -p) |
478 | // or if new hunk is empty (zero context) after patching | 476 | // or if new hunk is empty (zero context) after patching |
479 | if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) | 477 | if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) { |
480 | { | ||
481 | name = reverse ? newname : oldname; | 478 | name = reverse ? newname : oldname; |
482 | empty++; | 479 | empty++; |
483 | } | 480 | } |
484 | 481 | ||
485 | // handle -p path truncation. | 482 | // handle -p path truncation. |
486 | for (i=0, s = name; *s;) { | 483 | for (i = 0, s = name; *s;) { |
487 | if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break; | 484 | if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) |
488 | if (*(s++)=='/') { | 485 | break; |
489 | name = s; | 486 | if (*s++ != '/') |
490 | i++; | 487 | continue; |
491 | } | 488 | while (*s == '/') |
489 | s++; | ||
490 | i++; | ||
491 | name = s; | ||
492 | } | 492 | } |
493 | 493 | ||
494 | if (empty) { | 494 | if (empty) { |
diff --git a/editors/sed.c b/editors/sed.c index 5c4e9cc3b..c8bb503ea 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * add_input_file() adds a FILE* to the list of input files. We need to | 26 | * add_input_file() adds a FILE* to the list of input files. We need to |
27 | * know all input sources ahead of time to find the last line for the $ match. | 27 | * know all input sources ahead of time to find the last line for the $ match. |
28 | * | 28 | * |
29 | * process_files() does actual sedding, reading data lines from each input FILE * | 29 | * process_files() does actual sedding, reading data lines from each input FILE* |
30 | * (which could be stdin) and applying the sed command list (sed_cmd_head) to | 30 | * (which could be stdin) and applying the sed command list (sed_cmd_head) to |
31 | * each of the resulting lines. | 31 | * each of the resulting lines. |
32 | * | 32 | * |
@@ -57,7 +57,8 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | //usage:#define sed_trivial_usage | 59 | //usage:#define sed_trivial_usage |
60 | //usage: "[-efinr] SED_CMD [FILE]..." | 60 | //usage: "[-inr] [-f FILE]... [-e CMD]... [FILE]...\n" |
61 | //usage: "or: sed [-inr] CMD [FILE]..." | ||
61 | //usage:#define sed_full_usage "\n\n" | 62 | //usage:#define sed_full_usage "\n\n" |
62 | //usage: " -e CMD Add CMD to sed commands to be executed" | 63 | //usage: " -e CMD Add CMD to sed commands to be executed" |
63 | //usage: "\n -f FILE Add FILE contents to sed commands to be executed" | 64 | //usage: "\n -f FILE Add FILE contents to sed commands to be executed" |
@@ -75,6 +76,13 @@ | |||
75 | #include "libbb.h" | 76 | #include "libbb.h" |
76 | #include "xregex.h" | 77 | #include "xregex.h" |
77 | 78 | ||
79 | #if 0 | ||
80 | # define dbg(...) bb_error_msg(__VA_ARGS__) | ||
81 | #else | ||
82 | # define dbg(...) ((void)0) | ||
83 | #endif | ||
84 | |||
85 | |||
78 | enum { | 86 | enum { |
79 | OPT_in_place = 1 << 0, | 87 | OPT_in_place = 1 << 0, |
80 | }; | 88 | }; |
@@ -89,6 +97,7 @@ typedef struct sed_cmd_s { | |||
89 | regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ | 97 | regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ |
90 | regex_t *sub_match; /* For 's/sub_match/string/' */ | 98 | regex_t *sub_match; /* For 's/sub_match/string/' */ |
91 | int beg_line; /* 'sed 1p' 0 == apply commands to all lines */ | 99 | int beg_line; /* 'sed 1p' 0 == apply commands to all lines */ |
100 | int beg_line_orig; /* copy of the above, needed for -i */ | ||
92 | int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($) */ | 101 | int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($) */ |
93 | 102 | ||
94 | FILE *sw_file; /* File (sw) command writes to, -1 for none. */ | 103 | FILE *sw_file; /* File (sw) command writes to, -1 for none. */ |
@@ -123,7 +132,7 @@ struct globals { | |||
123 | regex_t *previous_regex_ptr; | 132 | regex_t *previous_regex_ptr; |
124 | 133 | ||
125 | /* linked list of sed commands */ | 134 | /* linked list of sed commands */ |
126 | sed_cmd_t sed_cmd_head, *sed_cmd_tail; | 135 | sed_cmd_t *sed_cmd_head, **sed_cmd_tail; |
127 | 136 | ||
128 | /* Linked list of append lines */ | 137 | /* Linked list of append lines */ |
129 | llist_t *append_head; | 138 | llist_t *append_head; |
@@ -148,7 +157,7 @@ struct BUG_G_too_big { | |||
148 | #if ENABLE_FEATURE_CLEAN_UP | 157 | #if ENABLE_FEATURE_CLEAN_UP |
149 | static void sed_free_and_close_stuff(void) | 158 | static void sed_free_and_close_stuff(void) |
150 | { | 159 | { |
151 | sed_cmd_t *sed_cmd = G.sed_cmd_head.next; | 160 | sed_cmd_t *sed_cmd = G.sed_cmd_head; |
152 | 161 | ||
153 | llist_free(G.append_head, free); | 162 | llist_free(G.append_head, free); |
154 | 163 | ||
@@ -599,6 +608,7 @@ static void add_cmd(const char *cmdstr) | |||
599 | 608 | ||
600 | /* first part (if present) is an address: either a '$', a number or a /regex/ */ | 609 | /* first part (if present) is an address: either a '$', a number or a /regex/ */ |
601 | cmdstr += get_address(cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match); | 610 | cmdstr += get_address(cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match); |
611 | sed_cmd->beg_line_orig = sed_cmd->beg_line; | ||
602 | 612 | ||
603 | /* second part (if present) will begin with a comma */ | 613 | /* second part (if present) will begin with a comma */ |
604 | if (*cmdstr == ',') { | 614 | if (*cmdstr == ',') { |
@@ -630,8 +640,8 @@ static void add_cmd(const char *cmdstr) | |||
630 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); | 640 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
631 | 641 | ||
632 | /* Add the command to the command array */ | 642 | /* Add the command to the command array */ |
633 | G.sed_cmd_tail->next = sed_cmd; | 643 | *G.sed_cmd_tail = sed_cmd; |
634 | G.sed_cmd_tail = G.sed_cmd_tail->next; | 644 | G.sed_cmd_tail = &sed_cmd->next; |
635 | } | 645 | } |
636 | 646 | ||
637 | /* If we glued multiple lines together, free the memory. */ | 647 | /* If we glued multiple lines together, free the memory. */ |
@@ -777,7 +787,7 @@ static sed_cmd_t *branch_to(char *label) | |||
777 | { | 787 | { |
778 | sed_cmd_t *sed_cmd; | 788 | sed_cmd_t *sed_cmd; |
779 | 789 | ||
780 | for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | 790 | for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { |
781 | if (sed_cmd->cmd == ':' && sed_cmd->string && !strcmp(sed_cmd->string, label)) { | 791 | if (sed_cmd->cmd == ':' && sed_cmd->string && !strcmp(sed_cmd->string, label)) { |
782 | return sed_cmd; | 792 | return sed_cmd; |
783 | } | 793 | } |
@@ -953,24 +963,24 @@ static void process_files(void) | |||
953 | 963 | ||
954 | /* For every line, go through all the commands */ | 964 | /* For every line, go through all the commands */ |
955 | restart: | 965 | restart: |
956 | for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | 966 | for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { |
957 | int old_matched, matched; | 967 | int old_matched, matched; |
958 | 968 | ||
959 | old_matched = sed_cmd->in_match; | 969 | old_matched = sed_cmd->in_match; |
960 | 970 | ||
961 | /* Determine if this command matches this line: */ | 971 | /* Determine if this command matches this line: */ |
962 | 972 | ||
963 | //bb_error_msg("match1:%d", sed_cmd->in_match); | 973 | dbg("match1:%d", sed_cmd->in_match); |
964 | //bb_error_msg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line | 974 | dbg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line |
965 | // && !sed_cmd->beg_match && !sed_cmd->end_match)); | 975 | && !sed_cmd->beg_match && !sed_cmd->end_match)); |
966 | //bb_error_msg("match3:%d", (sed_cmd->beg_line > 0 | 976 | dbg("match3:%d", (sed_cmd->beg_line > 0 |
967 | // && (sed_cmd->end_line || sed_cmd->end_match | 977 | && (sed_cmd->end_line || sed_cmd->end_match |
968 | // ? (sed_cmd->beg_line <= linenum) | 978 | ? (sed_cmd->beg_line <= linenum) |
969 | // : (sed_cmd->beg_line == linenum) | 979 | : (sed_cmd->beg_line == linenum) |
970 | // ) | 980 | ) |
971 | // ) | 981 | )); |
972 | //bb_error_msg("match4:%d", (beg_match(sed_cmd, pattern_space))); | 982 | dbg("match4:%d", (beg_match(sed_cmd, pattern_space))); |
973 | //bb_error_msg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL)); | 983 | dbg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL)); |
974 | 984 | ||
975 | /* Are we continuing a previous multi-line match? */ | 985 | /* Are we continuing a previous multi-line match? */ |
976 | sed_cmd->in_match = sed_cmd->in_match | 986 | sed_cmd->in_match = sed_cmd->in_match |
@@ -981,7 +991,14 @@ static void process_files(void) | |||
981 | || (sed_cmd->beg_line > 0 | 991 | || (sed_cmd->beg_line > 0 |
982 | && (sed_cmd->end_line || sed_cmd->end_match | 992 | && (sed_cmd->end_line || sed_cmd->end_match |
983 | /* note: even if end is numeric and is < linenum too, | 993 | /* note: even if end is numeric and is < linenum too, |
984 | * GNU sed matches! We match too */ | 994 | * GNU sed matches! We match too, therefore we don't |
995 | * check here that linenum <= end. | ||
996 | * Example: | ||
997 | * printf '1\n2\n3\n4\n' | sed -n '1{N;N;d};1p;2,3p;3p;4p' | ||
998 | * first three input lines are deleted; | ||
999 | * 4th line is matched and printed | ||
1000 | * by "2,3" (!) and by "4" ranges | ||
1001 | */ | ||
985 | ? (sed_cmd->beg_line <= linenum) /* N,end */ | 1002 | ? (sed_cmd->beg_line <= linenum) /* N,end */ |
986 | : (sed_cmd->beg_line == linenum) /* N */ | 1003 | : (sed_cmd->beg_line == linenum) /* N */ |
987 | ) | 1004 | ) |
@@ -994,16 +1011,14 @@ static void process_files(void) | |||
994 | /* Snapshot the value */ | 1011 | /* Snapshot the value */ |
995 | matched = sed_cmd->in_match; | 1012 | matched = sed_cmd->in_match; |
996 | 1013 | ||
997 | //bb_error_msg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d", | 1014 | dbg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d", |
998 | //sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum); | 1015 | sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum); |
999 | 1016 | ||
1000 | /* Is this line the end of the current match? */ | 1017 | /* Is this line the end of the current match? */ |
1001 | 1018 | ||
1002 | if (matched) { | 1019 | if (matched) { |
1003 | /* once matched, "n,xxx" range is dead, disabling it */ | 1020 | /* once matched, "n,xxx" range is dead, disabling it */ |
1004 | if (sed_cmd->beg_line > 0 | 1021 | if (sed_cmd->beg_line > 0) { |
1005 | && !(option_mask32 & OPT_in_place) /* but not for -i */ | ||
1006 | ) { | ||
1007 | sed_cmd->beg_line = -2; | 1022 | sed_cmd->beg_line = -2; |
1008 | } | 1023 | } |
1009 | sed_cmd->in_match = !( | 1024 | sed_cmd->in_match = !( |
@@ -1017,7 +1032,8 @@ static void process_files(void) | |||
1017 | /* or does this line matches our last address regex */ | 1032 | /* or does this line matches our last address regex */ |
1018 | || (sed_cmd->end_match && old_matched | 1033 | || (sed_cmd->end_match && old_matched |
1019 | && (regexec(sed_cmd->end_match, | 1034 | && (regexec(sed_cmd->end_match, |
1020 | pattern_space, 0, NULL, 0) == 0)) | 1035 | pattern_space, 0, NULL, 0) == 0) |
1036 | ) | ||
1021 | ); | 1037 | ); |
1022 | } | 1038 | } |
1023 | 1039 | ||
@@ -1407,11 +1423,12 @@ int sed_main(int argc UNUSED_PARAM, char **argv) | |||
1407 | add_input_file(stdin); | 1423 | add_input_file(stdin); |
1408 | } else { | 1424 | } else { |
1409 | int i; | 1425 | int i; |
1410 | FILE *file; | ||
1411 | 1426 | ||
1412 | for (i = 0; argv[i]; i++) { | 1427 | for (i = 0; argv[i]; i++) { |
1413 | struct stat statbuf; | 1428 | struct stat statbuf; |
1414 | int nonstdoutfd; | 1429 | int nonstdoutfd; |
1430 | FILE *file; | ||
1431 | sed_cmd_t *sed_cmd; | ||
1415 | 1432 | ||
1416 | if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) { | 1433 | if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) { |
1417 | add_input_file(stdin); | 1434 | add_input_file(stdin); |
@@ -1423,11 +1440,13 @@ int sed_main(int argc UNUSED_PARAM, char **argv) | |||
1423 | status = EXIT_FAILURE; | 1440 | status = EXIT_FAILURE; |
1424 | continue; | 1441 | continue; |
1425 | } | 1442 | } |
1443 | add_input_file(file); | ||
1426 | if (!(opt & OPT_in_place)) { | 1444 | if (!(opt & OPT_in_place)) { |
1427 | add_input_file(file); | ||
1428 | continue; | 1445 | continue; |
1429 | } | 1446 | } |
1430 | 1447 | ||
1448 | /* -i: process each FILE separately: */ | ||
1449 | |||
1431 | G.outname = xasprintf("%sXXXXXX", argv[i]); | 1450 | G.outname = xasprintf("%sXXXXXX", argv[i]); |
1432 | nonstdoutfd = xmkstemp(G.outname); | 1451 | nonstdoutfd = xmkstemp(G.outname); |
1433 | G.nonstdout = xfdopen_for_write(nonstdoutfd); | 1452 | G.nonstdout = xfdopen_for_write(nonstdoutfd); |
@@ -1438,15 +1457,20 @@ int sed_main(int argc UNUSED_PARAM, char **argv) | |||
1438 | * but GNU sed 4.2.1 does not preserve them either */ | 1457 | * but GNU sed 4.2.1 does not preserve them either */ |
1439 | fchmod(nonstdoutfd, statbuf.st_mode); | 1458 | fchmod(nonstdoutfd, statbuf.st_mode); |
1440 | fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); | 1459 | fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); |
1441 | add_input_file(file); | 1460 | |
1442 | process_files(); | 1461 | process_files(); |
1443 | fclose(G.nonstdout); | 1462 | fclose(G.nonstdout); |
1444 | |||
1445 | G.nonstdout = stdout; | 1463 | G.nonstdout = stdout; |
1464 | |||
1446 | /* unlink(argv[i]); */ | 1465 | /* unlink(argv[i]); */ |
1447 | xrename(G.outname, argv[i]); | 1466 | xrename(G.outname, argv[i]); |
1448 | free(G.outname); | 1467 | free(G.outname); |
1449 | G.outname = NULL; | 1468 | G.outname = NULL; |
1469 | |||
1470 | /* Re-enable disabled range matches */ | ||
1471 | for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { | ||
1472 | sed_cmd->beg_line = sed_cmd->beg_line_orig; | ||
1473 | } | ||
1450 | } | 1474 | } |
1451 | /* Here, to handle "sed 'cmds' nonexistent_file" case we did: | 1475 | /* Here, to handle "sed 'cmds' nonexistent_file" case we did: |
1452 | * if (G.current_input_file >= G.input_file_count) | 1476 | * if (G.current_input_file >= G.input_file_count) |
diff --git a/editors/vi.c b/editors/vi.c index 9708679b4..d6d926e35 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -3072,7 +3072,6 @@ static void refresh(int full_screen) | |||
3072 | //----- Execute a Vi Command ----------------------------------- | 3072 | //----- Execute a Vi Command ----------------------------------- |
3073 | static void do_cmd(int c) | 3073 | static void do_cmd(int c) |
3074 | { | 3074 | { |
3075 | const char *msg = msg; // for compiler | ||
3076 | char *p, *q, *save_dot; | 3075 | char *p, *q, *save_dot; |
3077 | char buf[12]; | 3076 | char buf[12]; |
3078 | int dir; | 3077 | int dir; |
@@ -3081,8 +3080,8 @@ static void do_cmd(int c) | |||
3081 | 3080 | ||
3082 | // c1 = c; // quiet the compiler | 3081 | // c1 = c; // quiet the compiler |
3083 | // cnt = yf = 0; // quiet the compiler | 3082 | // cnt = yf = 0; // quiet the compiler |
3084 | // msg = p = q = save_dot = buf; // quiet the compiler | 3083 | // p = q = save_dot = buf; // quiet the compiler |
3085 | memset(buf, '\0', 12); | 3084 | memset(buf, '\0', sizeof(buf)); |
3086 | 3085 | ||
3087 | show_status_line(); | 3086 | show_status_line(); |
3088 | 3087 | ||
@@ -3198,19 +3197,18 @@ static void do_cmd(int c) | |||
3198 | case KEYCODE_LEFT: // cursor key Left | 3197 | case KEYCODE_LEFT: // cursor key Left |
3199 | case 8: // ctrl-H- move left (This may be ERASE char) | 3198 | case 8: // ctrl-H- move left (This may be ERASE char) |
3200 | case 0x7f: // DEL- move left (This may be ERASE char) | 3199 | case 0x7f: // DEL- move left (This may be ERASE char) |
3201 | if (--cmdcnt > 0) { | 3200 | do { |
3202 | do_cmd(c); | 3201 | dot_left(); |
3203 | } | 3202 | } while (--cmdcnt > 0); |
3204 | dot_left(); | ||
3205 | break; | 3203 | break; |
3206 | case 10: // Newline ^J | 3204 | case 10: // Newline ^J |
3207 | case 'j': // j- goto next line, same col | 3205 | case 'j': // j- goto next line, same col |
3208 | case KEYCODE_DOWN: // cursor key Down | 3206 | case KEYCODE_DOWN: // cursor key Down |
3209 | if (--cmdcnt > 0) { | 3207 | do { |
3210 | do_cmd(c); | 3208 | dot_next(); // go to next B-o-l |
3211 | } | 3209 | // try stay in same col |
3212 | dot_next(); // go to next B-o-l | 3210 | dot = move_to_col(dot, ccol + offset); |
3213 | dot = move_to_col(dot, ccol + offset); // try stay in same col | 3211 | } while (--cmdcnt > 0); |
3214 | break; | 3212 | break; |
3215 | case 12: // ctrl-L force redraw whole screen | 3213 | case 12: // ctrl-L force redraw whole screen |
3216 | case 18: // ctrl-R force redraw | 3214 | case 18: // ctrl-R force redraw |
@@ -3223,11 +3221,10 @@ static void do_cmd(int c) | |||
3223 | break; | 3221 | break; |
3224 | case 13: // Carriage Return ^M | 3222 | case 13: // Carriage Return ^M |
3225 | case '+': // +- goto next line | 3223 | case '+': // +- goto next line |
3226 | if (--cmdcnt > 0) { | 3224 | do { |
3227 | do_cmd(c); | 3225 | dot_next(); |
3228 | } | 3226 | dot_skip_over_ws(); |
3229 | dot_next(); | 3227 | } while (--cmdcnt > 0); |
3230 | dot_skip_over_ws(); | ||
3231 | break; | 3228 | break; |
3232 | case 21: // ctrl-U scroll up half screen | 3229 | case 21: // ctrl-U scroll up half screen |
3233 | dot_scroll((rows - 2) / 2, -1); | 3230 | dot_scroll((rows - 2) / 2, -1); |
@@ -3245,10 +3242,9 @@ static void do_cmd(int c) | |||
3245 | case ' ': // move right | 3242 | case ' ': // move right |
3246 | case 'l': // move right | 3243 | case 'l': // move right |
3247 | case KEYCODE_RIGHT: // Cursor Key Right | 3244 | case KEYCODE_RIGHT: // Cursor Key Right |
3248 | if (--cmdcnt > 0) { | 3245 | do { |
3249 | do_cmd(c); | 3246 | dot_right(); |
3250 | } | 3247 | } while (--cmdcnt > 0); |
3251 | dot_right(); | ||
3252 | break; | 3248 | break; |
3253 | #if ENABLE_FEATURE_VI_YANKMARK | 3249 | #if ENABLE_FEATURE_VI_YANKMARK |
3254 | case '"': // "- name a register to use for Delete/Yank | 3250 | case '"': // "- name a register to use for Delete/Yank |
@@ -3330,11 +3326,12 @@ static void do_cmd(int c) | |||
3330 | #endif /* FEATURE_VI_YANKMARK */ | 3326 | #endif /* FEATURE_VI_YANKMARK */ |
3331 | case '$': // $- goto end of line | 3327 | case '$': // $- goto end of line |
3332 | case KEYCODE_END: // Cursor Key End | 3328 | case KEYCODE_END: // Cursor Key End |
3333 | if (--cmdcnt > 0) { | 3329 | for (;;) { |
3330 | dot = end_line(dot); | ||
3331 | if (--cmdcnt > 0) | ||
3332 | break; | ||
3334 | dot_next(); | 3333 | dot_next(); |
3335 | do_cmd(c); | ||
3336 | } | 3334 | } |
3337 | dot = end_line(dot); | ||
3338 | break; | 3335 | break; |
3339 | case '%': // %- find matching char of pair () [] {} | 3336 | case '%': // %- find matching char of pair () [] {} |
3340 | for (q = dot; q < end && *q != '\n'; q++) { | 3337 | for (q = dot; q < end && *q != '\n'; q++) { |
@@ -3359,38 +3356,35 @@ static void do_cmd(int c) | |||
3359 | // | 3356 | // |
3360 | //**** fall through to ... ';' | 3357 | //**** fall through to ... ';' |
3361 | case ';': // ;- look at rest of line for last forward char | 3358 | case ';': // ;- look at rest of line for last forward char |
3362 | if (--cmdcnt > 0) { | 3359 | do { |
3363 | do_cmd(';'); | 3360 | if (last_forward_char == 0) |
3364 | } | 3361 | break; |
3365 | if (last_forward_char == 0) | 3362 | q = dot + 1; |
3366 | break; | 3363 | while (q < end - 1 && *q != '\n' && *q != last_forward_char) { |
3367 | q = dot + 1; | 3364 | q++; |
3368 | while (q < end - 1 && *q != '\n' && *q != last_forward_char) { | 3365 | } |
3369 | q++; | 3366 | if (*q == last_forward_char) |
3370 | } | 3367 | dot = q; |
3371 | if (*q == last_forward_char) | 3368 | } while (--cmdcnt > 0); |
3372 | dot = q; | ||
3373 | break; | 3369 | break; |
3374 | case ',': // repeat latest 'f' in opposite direction | 3370 | case ',': // repeat latest 'f' in opposite direction |
3375 | if (--cmdcnt > 0) { | ||
3376 | do_cmd(','); | ||
3377 | } | ||
3378 | if (last_forward_char == 0) | 3371 | if (last_forward_char == 0) |
3379 | break; | 3372 | break; |
3380 | q = dot - 1; | 3373 | do { |
3381 | while (q >= text && *q != '\n' && *q != last_forward_char) { | 3374 | q = dot - 1; |
3382 | q--; | 3375 | while (q >= text && *q != '\n' && *q != last_forward_char) { |
3383 | } | 3376 | q--; |
3384 | if (q >= text && *q == last_forward_char) | 3377 | } |
3385 | dot = q; | 3378 | if (q >= text && *q == last_forward_char) |
3379 | dot = q; | ||
3380 | } while (--cmdcnt > 0); | ||
3386 | break; | 3381 | break; |
3387 | 3382 | ||
3388 | case '-': // -- goto prev line | 3383 | case '-': // -- goto prev line |
3389 | if (--cmdcnt > 0) { | 3384 | do { |
3390 | do_cmd(c); | 3385 | dot_prev(); |
3391 | } | 3386 | dot_skip_over_ws(); |
3392 | dot_prev(); | 3387 | } while (--cmdcnt > 0); |
3393 | dot_skip_over_ws(); | ||
3394 | break; | 3388 | break; |
3395 | #if ENABLE_FEATURE_VI_DOT_CMD | 3389 | #if ENABLE_FEATURE_VI_DOT_CMD |
3396 | case '.': // .- repeat the last modifying command | 3390 | case '.': // .- repeat the last modifying command |
@@ -3422,9 +3416,6 @@ static void do_cmd(int c) | |||
3422 | // user changed mind and erased the "/"- do nothing | 3416 | // user changed mind and erased the "/"- do nothing |
3423 | break; | 3417 | break; |
3424 | case 'N': // N- backward search for last pattern | 3418 | case 'N': // N- backward search for last pattern |
3425 | if (--cmdcnt > 0) { | ||
3426 | do_cmd(c); | ||
3427 | } | ||
3428 | dir = BACK; // assume BACKWARD search | 3419 | dir = BACK; // assume BACKWARD search |
3429 | p = dot - 1; | 3420 | p = dot - 1; |
3430 | if (last_search_pattern[0] == '?') { | 3421 | if (last_search_pattern[0] == '?') { |
@@ -3436,41 +3427,41 @@ static void do_cmd(int c) | |||
3436 | case 'n': // n- repeat search for last pattern | 3427 | case 'n': // n- repeat search for last pattern |
3437 | // search rest of text[] starting at next char | 3428 | // search rest of text[] starting at next char |
3438 | // if search fails return orignal "p" not the "p+1" address | 3429 | // if search fails return orignal "p" not the "p+1" address |
3439 | if (--cmdcnt > 0) { | 3430 | do { |
3440 | do_cmd(c); | 3431 | const char *msg; |
3441 | } | ||
3442 | dc3: | 3432 | dc3: |
3443 | dir = FORWARD; // assume FORWARD search | 3433 | dir = FORWARD; // assume FORWARD search |
3444 | p = dot + 1; | 3434 | p = dot + 1; |
3445 | if (last_search_pattern[0] == '?') { | 3435 | if (last_search_pattern[0] == '?') { |
3446 | dir = BACK; | 3436 | dir = BACK; |
3447 | p = dot - 1; | 3437 | p = dot - 1; |
3448 | } | 3438 | } |
3449 | dc4: | 3439 | dc4: |
3450 | q = char_search(p, last_search_pattern + 1, dir, FULL); | 3440 | q = char_search(p, last_search_pattern + 1, dir, FULL); |
3451 | if (q != NULL) { | 3441 | if (q != NULL) { |
3452 | dot = q; // good search, update "dot" | 3442 | dot = q; // good search, update "dot" |
3453 | msg = ""; | 3443 | msg = NULL; |
3454 | goto dc2; | 3444 | goto dc2; |
3455 | } | 3445 | } |
3456 | // no pattern found between "dot" and "end"- continue at top | 3446 | // no pattern found between "dot" and "end"- continue at top |
3457 | p = text; | 3447 | p = text; |
3458 | if (dir == BACK) { | ||
3459 | p = end - 1; | ||
3460 | } | ||
3461 | q = char_search(p, last_search_pattern + 1, dir, FULL); | ||
3462 | if (q != NULL) { // found something | ||
3463 | dot = q; // found new pattern- goto it | ||
3464 | msg = "search hit BOTTOM, continuing at TOP"; | ||
3465 | if (dir == BACK) { | 3448 | if (dir == BACK) { |
3466 | msg = "search hit TOP, continuing at BOTTOM"; | 3449 | p = end - 1; |
3450 | } | ||
3451 | q = char_search(p, last_search_pattern + 1, dir, FULL); | ||
3452 | if (q != NULL) { // found something | ||
3453 | dot = q; // found new pattern- goto it | ||
3454 | msg = "search hit BOTTOM, continuing at TOP"; | ||
3455 | if (dir == BACK) { | ||
3456 | msg = "search hit TOP, continuing at BOTTOM"; | ||
3457 | } | ||
3458 | } else { | ||
3459 | msg = "Pattern not found"; | ||
3467 | } | 3460 | } |
3468 | } else { | ||
3469 | msg = "Pattern not found"; | ||
3470 | } | ||
3471 | dc2: | 3461 | dc2: |
3472 | if (*msg) | 3462 | if (msg) |
3473 | status_line_bold("%s", msg); | 3463 | status_line_bold("%s", msg); |
3464 | } while (--cmdcnt > 0); | ||
3474 | break; | 3465 | break; |
3475 | case '{': // {- move backward paragraph | 3466 | case '{': // {- move backward paragraph |
3476 | q = char_search(dot, "\n\n", BACK, FULL); | 3467 | q = char_search(dot, "\n\n", BACK, FULL); |
@@ -3589,18 +3580,17 @@ static void do_cmd(int c) | |||
3589 | case 'B': // B- back a blank-delimited Word | 3580 | case 'B': // B- back a blank-delimited Word |
3590 | case 'E': // E- end of a blank-delimited word | 3581 | case 'E': // E- end of a blank-delimited word |
3591 | case 'W': // W- forward a blank-delimited word | 3582 | case 'W': // W- forward a blank-delimited word |
3592 | if (--cmdcnt > 0) { | ||
3593 | do_cmd(c); | ||
3594 | } | ||
3595 | dir = FORWARD; | 3583 | dir = FORWARD; |
3596 | if (c == 'B') | 3584 | if (c == 'B') |
3597 | dir = BACK; | 3585 | dir = BACK; |
3598 | if (c == 'W' || isspace(dot[dir])) { | 3586 | do { |
3599 | dot = skip_thing(dot, 1, dir, S_TO_WS); | 3587 | if (c == 'W' || isspace(dot[dir])) { |
3600 | dot = skip_thing(dot, 2, dir, S_OVER_WS); | 3588 | dot = skip_thing(dot, 1, dir, S_TO_WS); |
3601 | } | 3589 | dot = skip_thing(dot, 2, dir, S_OVER_WS); |
3602 | if (c != 'W') | 3590 | } |
3603 | dot = skip_thing(dot, 1, dir, S_BEFORE_WS); | 3591 | if (c != 'W') |
3592 | dot = skip_thing(dot, 1, dir, S_BEFORE_WS); | ||
3593 | } while (--cmdcnt > 0); | ||
3604 | break; | 3594 | break; |
3605 | case 'C': // C- Change to e-o-l | 3595 | case 'C': // C- Change to e-o-l |
3606 | case 'D': // D- delete to e-o-l | 3596 | case 'D': // D- delete to e-o-l |
@@ -3651,20 +3641,19 @@ static void do_cmd(int c) | |||
3651 | case 'i': // i- insert before current char | 3641 | case 'i': // i- insert before current char |
3652 | case KEYCODE_INSERT: // Cursor Key Insert | 3642 | case KEYCODE_INSERT: // Cursor Key Insert |
3653 | dc_i: | 3643 | dc_i: |
3654 | cmd_mode = 1; // start insrting | 3644 | cmd_mode = 1; // start inserting |
3655 | break; | 3645 | break; |
3656 | case 'J': // J- join current and next lines together | 3646 | case 'J': // J- join current and next lines together |
3657 | if (--cmdcnt > 1) { | 3647 | do { |
3658 | do_cmd(c); | 3648 | dot_end(); // move to NL |
3659 | } | 3649 | if (dot < end - 1) { // make sure not last char in text[] |
3660 | dot_end(); // move to NL | 3650 | *dot++ = ' '; // replace NL with space |
3661 | if (dot < end - 1) { // make sure not last char in text[] | 3651 | file_modified++; |
3662 | *dot++ = ' '; // replace NL with space | 3652 | while (isblank(*dot)) { // delete leading WS |
3663 | file_modified++; | 3653 | dot_delete(); |
3664 | while (isblank(*dot)) { // delete leading WS | 3654 | } |
3665 | dot_delete(); | ||
3666 | } | 3655 | } |
3667 | } | 3656 | } while (--cmdcnt > 0); |
3668 | end_cmd_q(); // stop adding to q | 3657 | end_cmd_q(); // stop adding to q |
3669 | break; | 3658 | break; |
3670 | case 'L': // L- goto bottom line on screen | 3659 | case 'L': // L- goto bottom line on screen |
@@ -3708,20 +3697,19 @@ static void do_cmd(int c) | |||
3708 | case 'X': // X- delete char before dot | 3697 | case 'X': // X- delete char before dot |
3709 | case 'x': // x- delete the current char | 3698 | case 'x': // x- delete the current char |
3710 | case 's': // s- substitute the current char | 3699 | case 's': // s- substitute the current char |
3711 | if (--cmdcnt > 0) { | ||
3712 | do_cmd(c); | ||
3713 | } | ||
3714 | dir = 0; | 3700 | dir = 0; |
3715 | if (c == 'X') | 3701 | if (c == 'X') |
3716 | dir = -1; | 3702 | dir = -1; |
3717 | if (dot[dir] != '\n') { | 3703 | do { |
3718 | if (c == 'X') | 3704 | if (dot[dir] != '\n') { |
3719 | dot--; // delete prev char | 3705 | if (c == 'X') |
3720 | dot = yank_delete(dot, dot, 0, YANKDEL); // delete char | 3706 | dot--; // delete prev char |
3721 | } | 3707 | dot = yank_delete(dot, dot, 0, YANKDEL); // delete char |
3722 | if (c == 's') | 3708 | } |
3723 | goto dc_i; // start insrting | 3709 | } while (--cmdcnt > 0); |
3724 | end_cmd_q(); // stop adding to q | 3710 | end_cmd_q(); // stop adding to q |
3711 | if (c == 's') | ||
3712 | goto dc_i; // start inserting | ||
3725 | break; | 3713 | break; |
3726 | case 'Z': // Z- if modified, {write}; exit | 3714 | case 'Z': // Z- if modified, {write}; exit |
3727 | // ZZ means to save file (if necessary), then exit | 3715 | // ZZ means to save file (if necessary), then exit |
@@ -3752,23 +3740,22 @@ static void do_cmd(int c) | |||
3752 | break; | 3740 | break; |
3753 | case 'b': // b- back a word | 3741 | case 'b': // b- back a word |
3754 | case 'e': // e- end of word | 3742 | case 'e': // e- end of word |
3755 | if (--cmdcnt > 0) { | ||
3756 | do_cmd(c); | ||
3757 | } | ||
3758 | dir = FORWARD; | 3743 | dir = FORWARD; |
3759 | if (c == 'b') | 3744 | if (c == 'b') |
3760 | dir = BACK; | 3745 | dir = BACK; |
3761 | if ((dot + dir) < text || (dot + dir) > end - 1) | 3746 | do { |
3762 | break; | 3747 | if ((dot + dir) < text || (dot + dir) > end - 1) |
3763 | dot += dir; | 3748 | break; |
3764 | if (isspace(*dot)) { | 3749 | dot += dir; |
3765 | dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS); | 3750 | if (isspace(*dot)) { |
3766 | } | 3751 | dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS); |
3767 | if (isalnum(*dot) || *dot == '_') { | 3752 | } |
3768 | dot = skip_thing(dot, 1, dir, S_END_ALNUM); | 3753 | if (isalnum(*dot) || *dot == '_') { |
3769 | } else if (ispunct(*dot)) { | 3754 | dot = skip_thing(dot, 1, dir, S_END_ALNUM); |
3770 | dot = skip_thing(dot, 1, dir, S_END_PUNCT); | 3755 | } else if (ispunct(*dot)) { |
3771 | } | 3756 | dot = skip_thing(dot, 1, dir, S_END_PUNCT); |
3757 | } | ||
3758 | } while (--cmdcnt > 0); | ||
3772 | break; | 3759 | break; |
3773 | case 'c': // c- change something | 3760 | case 'c': // c- change something |
3774 | case 'd': // d- delete something | 3761 | case 'd': // d- delete something |
@@ -3853,11 +3840,10 @@ static void do_cmd(int c) | |||
3853 | } | 3840 | } |
3854 | case 'k': // k- goto prev line, same col | 3841 | case 'k': // k- goto prev line, same col |
3855 | case KEYCODE_UP: // cursor key Up | 3842 | case KEYCODE_UP: // cursor key Up |
3856 | if (--cmdcnt > 0) { | 3843 | do { |
3857 | do_cmd(c); | 3844 | dot_prev(); |
3858 | } | 3845 | dot = move_to_col(dot, ccol + offset); // try stay in same col |
3859 | dot_prev(); | 3846 | } while (--cmdcnt > 0); |
3860 | dot = move_to_col(dot, ccol + offset); // try stay in same col | ||
3861 | break; | 3847 | break; |
3862 | case 'r': // r- replace the current char with user input | 3848 | case 'r': // r- replace the current char with user input |
3863 | c1 = get_one_char(); // get the replacement char | 3849 | c1 = get_one_char(); // get the replacement char |
@@ -3875,19 +3861,18 @@ static void do_cmd(int c) | |||
3875 | last_forward_char = 0; | 3861 | last_forward_char = 0; |
3876 | break; | 3862 | break; |
3877 | case 'w': // w- forward a word | 3863 | case 'w': // w- forward a word |
3878 | if (--cmdcnt > 0) { | 3864 | do { |
3879 | do_cmd(c); | 3865 | if (isalnum(*dot) || *dot == '_') { // we are on ALNUM |
3880 | } | 3866 | dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM); |
3881 | if (isalnum(*dot) || *dot == '_') { // we are on ALNUM | 3867 | } else if (ispunct(*dot)) { // we are on PUNCT |
3882 | dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM); | 3868 | dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT); |
3883 | } else if (ispunct(*dot)) { // we are on PUNCT | 3869 | } |
3884 | dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT); | 3870 | if (dot < end - 1) |
3885 | } | 3871 | dot++; // move over word |
3886 | if (dot < end - 1) | 3872 | if (isspace(*dot)) { |
3887 | dot++; // move over word | 3873 | dot = skip_thing(dot, 2, FORWARD, S_OVER_WS); |
3888 | if (isspace(*dot)) { | 3874 | } |
3889 | dot = skip_thing(dot, 2, FORWARD, S_OVER_WS); | 3875 | } while (--cmdcnt > 0); |
3890 | } | ||
3891 | break; | 3876 | break; |
3892 | case 'z': // z- | 3877 | case 'z': // z- |
3893 | c1 = get_one_char(); // get the replacement char | 3878 | c1 = get_one_char(); // get the replacement char |
@@ -3903,17 +3888,16 @@ static void do_cmd(int c) | |||
3903 | dot = move_to_col(dot, cmdcnt - 1); // try to move to column | 3888 | dot = move_to_col(dot, cmdcnt - 1); // try to move to column |
3904 | break; | 3889 | break; |
3905 | case '~': // ~- flip the case of letters a-z -> A-Z | 3890 | case '~': // ~- flip the case of letters a-z -> A-Z |
3906 | if (--cmdcnt > 0) { | 3891 | do { |
3907 | do_cmd(c); | 3892 | if (islower(*dot)) { |
3908 | } | 3893 | *dot = toupper(*dot); |
3909 | if (islower(*dot)) { | 3894 | file_modified++; |
3910 | *dot = toupper(*dot); | 3895 | } else if (isupper(*dot)) { |
3911 | file_modified++; | 3896 | *dot = tolower(*dot); |
3912 | } else if (isupper(*dot)) { | 3897 | file_modified++; |
3913 | *dot = tolower(*dot); | 3898 | } |
3914 | file_modified++; | 3899 | dot_right(); |
3915 | } | 3900 | } while (--cmdcnt > 0); |
3916 | dot_right(); | ||
3917 | end_cmd_q(); // stop adding to q | 3901 | end_cmd_q(); // stop adding to q |
3918 | break; | 3902 | break; |
3919 | //----- The Cursor and Function Keys ----------------------------- | 3903 | //----- The Cursor and Function Keys ----------------------------- |