summaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--editors/awk.c21
-rw-r--r--editors/diff.c26
-rw-r--r--editors/sed.c21
-rw-r--r--editors/vi.c66
4 files changed, 133 insertions, 1 deletions
diff --git a/editors/awk.c b/editors/awk.c
index d25508e5d..c4553728d 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -734,7 +734,11 @@ static char *skip_spaces(char *p)
734 if (*p == '\\' && p[1] == '\n') { 734 if (*p == '\\' && p[1] == '\n') {
735 p++; 735 p++;
736 t_lineno++; 736 t_lineno++;
737#if !ENABLE_PLATFORM_MINGW32
737 } else if (*p != ' ' && *p != '\t') { 738 } else if (*p != ' ' && *p != '\t') {
739#else
740 } else if (*p != ' ' && *p != '\t' && *p != '\r') {
741#endif
738 break; 742 break;
739 } 743 }
740 p++; 744 p++;
@@ -1991,6 +1995,21 @@ static int ptest(node *pattern)
1991 return istrue(evaluate(pattern, &G.ptest__v)); 1995 return istrue(evaluate(pattern, &G.ptest__v));
1992} 1996}
1993 1997
1998#if ENABLE_PLATFORM_MINGW32
1999static ssize_t FAST_FUNC safe_read_strip_cr(int fd, void *buf, size_t count)
2000{
2001 ssize_t n;
2002
2003 do {
2004 n = safe_read(fd, buf, count);
2005 } while (n > 0 && (n=remove_cr((char *)buf, n)) == 0);
2006
2007 return n;
2008}
2009
2010#define safe_read safe_read_strip_cr
2011#endif
2012
1994/* read next record from stream rsm into a variable v */ 2013/* read next record from stream rsm into a variable v */
1995static int awk_getline(rstream *rsm, var *v) 2014static int awk_getline(rstream *rsm, var *v)
1996{ 2015{
@@ -2100,7 +2119,7 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i
2100 const char *s = format; 2119 const char *s = format;
2101 2120
2102 if (int_as_int && n == (long long)n) { 2121 if (int_as_int && n == (long long)n) {
2103 r = snprintf(b, size, "%lld", (long long)n); 2122 r = snprintf(b, size, "%"LL_FMT"d", (long long)n);
2104 } else { 2123 } else {
2105 do { c = *s; } while (c && *++s); 2124 do { c = *s; } while (c && *++s);
2106 if (strchr("diouxX", c)) { 2125 if (strchr("diouxX", c)) {
diff --git a/editors/diff.c b/editors/diff.c
index 1462a9b18..cf531460f 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -709,6 +709,10 @@ static int diffreg(char *file[2])
709 FILE *fp[2]; 709 FILE *fp[2];
710 bool binary = false, differ = false; 710 bool binary = false, differ = false;
711 int status = STATUS_SAME, i; 711 int status = STATUS_SAME, i;
712#if ENABLE_PLATFORM_MINGW32
713 char *tmpfile[2] = { NULL, NULL };
714 char *tmpdir;
715#endif
712 716
713 fp[0] = stdin; 717 fp[0] = stdin;
714 fp[1] = stdin; 718 fp[1] = stdin;
@@ -730,10 +734,19 @@ static int diffreg(char *file[2])
730 * When we meet non-seekable file, we must make a temp copy. 734 * When we meet non-seekable file, we must make a temp copy.
731 */ 735 */
732 if (lseek(fd, 0, SEEK_SET) == -1 && errno == ESPIPE) { 736 if (lseek(fd, 0, SEEK_SET) == -1 && errno == ESPIPE) {
737#if !ENABLE_PLATFORM_MINGW32
733 char name[] = "/tmp/difXXXXXX"; 738 char name[] = "/tmp/difXXXXXX";
734 int fd_tmp = xmkstemp(name); 739 int fd_tmp = xmkstemp(name);
735 740
736 unlink(name); 741 unlink(name);
742#else
743 int fd_tmp;
744
745 if (!(tmpdir=getenv("TMPDIR")))
746 goto out;
747 tmpfile[i] = xasprintf("%s/difXXXXXX", tmpdir);
748 fd_tmp = xmkstemp(tmpfile[i]);
749#endif
737 if (bb_copyfd_eof(fd, fd_tmp) < 0) 750 if (bb_copyfd_eof(fd, fd_tmp) < 0)
738 xfunc_die(); 751 xfunc_die();
739 if (fd != STDIN_FILENO) 752 if (fd != STDIN_FILENO)
@@ -776,6 +789,14 @@ static int diffreg(char *file[2])
776out: 789out:
777 fclose_if_not_stdin(fp[0]); 790 fclose_if_not_stdin(fp[0]);
778 fclose_if_not_stdin(fp[1]); 791 fclose_if_not_stdin(fp[1]);
792#if ENABLE_PLATFORM_MINGW32
793 for (i = 0; i < 2; i++) {
794 if (tmpfile[i]) {
795 unlink(tmpfile[i]);
796 free(tmpfile[i]);
797 }
798 }
799#endif
779 800
780 return status; 801 return status;
781} 802}
@@ -1019,6 +1040,11 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
1019 * 255, or if a local inode number (st_ino) exceeds 16777215. 1040 * 255, or if a local inode number (st_ino) exceeds 16777215.
1020 */ 1041 */
1021 if (ENABLE_DESKTOP 1042 if (ENABLE_DESKTOP
1043 && (ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA)
1044#if ENABLE_FEATURE_EXTRA_FILE_DATA
1045 /* ignore invalid inode numbers */
1046 && stb[0].st_ino != 0
1047#endif
1022 && stb[0].st_ino == stb[1].st_ino 1048 && stb[0].st_ino == stb[1].st_ino
1023 && stb[0].st_dev == stb[1].st_dev 1049 && stb[0].st_dev == stb[1].st_dev
1024 && stb[0].st_size == stb[1].st_size 1050 && stb[0].st_size == stb[1].st_size
diff --git a/editors/sed.c b/editors/sed.c
index bb39de149..a5cedbd8d 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -74,6 +74,9 @@
74//usage: "\n Optionally back files up, appending SFX" 74//usage: "\n Optionally back files up, appending SFX"
75//usage: "\n -n Suppress automatic printing of pattern space" 75//usage: "\n -n Suppress automatic printing of pattern space"
76//usage: "\n -r,-E Use extended regex syntax" 76//usage: "\n -r,-E Use extended regex syntax"
77//usage: IF_PLATFORM_MINGW32(
78//usage: "\n -b Keep CR/LF (Windows-only)"
79//usage: )
77//usage: "\n" 80//usage: "\n"
78//usage: "\nIf no -e or -f, the first non-option argument is the sed command string." 81//usage: "\nIf no -e or -f, the first non-option argument is the sed command string."
79//usage: "\nRemaining arguments are input files (stdin if none)." 82//usage: "\nRemaining arguments are input files (stdin if none)."
@@ -132,6 +135,9 @@ static const char semicolon_whitespace[] ALIGN1 = "; \n\r\t\v";
132struct globals { 135struct globals {
133 /* options */ 136 /* options */
134 int be_quiet, regex_type; 137 int be_quiet, regex_type;
138#if ENABLE_PLATFORM_MINGW32
139 int keep_cr;
140#endif
135 141
136 FILE *nonstdout; 142 FILE *nonstdout;
137 char *outname, *hold_space; 143 char *outname, *hold_space;
@@ -1024,6 +1030,11 @@ static char *get_next_line(char *gets_char, char *last_puts_char)
1024 char c = temp[len-1]; 1030 char c = temp[len-1];
1025 if (c == '\n' || c == '\0') { 1031 if (c == '\n' || c == '\0') {
1026 temp[len-1] = '\0'; 1032 temp[len-1] = '\0';
1033#if ENABLE_PLATFORM_MINGW32
1034 if (!G.keep_cr && c == '\n' && len > 1 && temp[len-2] == '\r') {
1035 temp[len-2] = '\0';
1036 }
1037#endif
1027 gc = c; 1038 gc = c;
1028 if (c == '\0') { 1039 if (c == '\0') {
1029 int ch = fgetc(fp); 1040 int ch = fgetc(fp);
@@ -1498,7 +1509,12 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1498 "quiet\0" No_argument "n" 1509 "quiet\0" No_argument "n"
1499 "silent\0" No_argument "n" 1510 "silent\0" No_argument "n"
1500 "expression\0" Required_argument "e" 1511 "expression\0" Required_argument "e"
1512# if !ENABLE_PLATFORM_MINGW32
1501 "file\0" Required_argument "f"; 1513 "file\0" Required_argument "f";
1514# else
1515 "file\0" Required_argument "f"
1516 "binary\0" No_argument "b";
1517# endif
1502#endif 1518#endif
1503 1519
1504 INIT_G(); 1520 INIT_G();
@@ -1522,6 +1538,7 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1522 */ 1538 */
1523 opt = getopt32long(argv, "^" 1539 opt = getopt32long(argv, "^"
1524 "i::rEne:*f:*" 1540 "i::rEne:*f:*"
1541 IF_PLATFORM_MINGW32("b")
1525 "\0" "nn"/*count -n*/, 1542 "\0" "nn"/*count -n*/,
1526 sed_longopts, 1543 sed_longopts,
1527 &opt_i, &opt_e, &opt_f, 1544 &opt_i, &opt_e, &opt_f,
@@ -1535,6 +1552,10 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1535 G.regex_type |= REG_EXTENDED; // -r or -E 1552 G.regex_type |= REG_EXTENDED; // -r or -E
1536 //if (opt & 8) 1553 //if (opt & 8)
1537 // G.be_quiet++; // -n (implemented with a counter instead) 1554 // G.be_quiet++; // -n (implemented with a counter instead)
1555#if ENABLE_PLATFORM_MINGW32
1556 if (opt & 0x40)
1557 G.keep_cr = 1;
1558#endif
1538 while (opt_e) { // -e 1559 while (opt_e) { // -e
1539 add_cmd_block(llist_pop(&opt_e)); 1560 add_cmd_block(llist_pop(&opt_e));
1540 } 1561 }
diff --git a/editors/vi.c b/editors/vi.c
index c4360f8d3..a8b4dc5a4 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -349,7 +349,9 @@ struct globals {
349#if ENABLE_FEATURE_VI_USE_SIGNALS 349#if ENABLE_FEATURE_VI_USE_SIGNALS
350 sigjmp_buf restart; // int_handler() jumps to location remembered here 350 sigjmp_buf restart; // int_handler() jumps to location remembered here
351#endif 351#endif
352#if !ENABLE_PLATFORM_MINGW32
352 struct termios term_orig; // remember what the cooked mode was 353 struct termios term_orig; // remember what the cooked mode was
354#endif
353#if ENABLE_FEATURE_VI_COLON 355#if ENABLE_FEATURE_VI_COLON
354 char *initial_cmds[3]; // currently 2 entries, NULL terminated 356 char *initial_cmds[3]; // currently 2 entries, NULL terminated
355#endif 357#endif
@@ -545,6 +547,23 @@ static ALWAYS_INLINE int query_screen_dimensions(void)
545// sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready) 547// sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready)
546static int mysleep(int hund) 548static int mysleep(int hund)
547{ 549{
550#if ENABLE_PLATFORM_MINGW32
551 HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
552 DWORD ret;
553
554 if (hund == 0) {
555 // Allow two events in the queue. Otherwise pasted test isn't
556 // displayed because there's still a key release event waiting
557 // after the last character is processed.
558 DWORD nevent_out;
559
560 ret = GetNumberOfConsoleInputEvents(h, &nevent_out);
561 return ret != 0 ? (nevent_out > 2) : 0;
562 }
563 fflush_all();
564 ret = WaitForSingleObject(h, hund*10);
565 return ret != WAIT_TIMEOUT;
566#else
548 struct pollfd pfd[1]; 567 struct pollfd pfd[1];
549 568
550 if (hund != 0) 569 if (hund != 0)
@@ -553,9 +572,11 @@ static int mysleep(int hund)
553 pfd[0].fd = STDIN_FILENO; 572 pfd[0].fd = STDIN_FILENO;
554 pfd[0].events = POLLIN; 573 pfd[0].events = POLLIN;
555 return safe_poll(pfd, 1, hund*10) > 0; 574 return safe_poll(pfd, 1, hund*10) > 0;
575#endif
556} 576}
557 577
558//----- Set terminal attributes -------------------------------- 578//----- Set terminal attributes --------------------------------
579#if !ENABLE_PLATFORM_MINGW32
559static void rawmode(void) 580static void rawmode(void)
560{ 581{
561 // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals 582 // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals
@@ -567,6 +588,10 @@ static void cookmode(void)
567 fflush_all(); 588 fflush_all();
568 tcsetattr_stdin_TCSANOW(&term_orig); 589 tcsetattr_stdin_TCSANOW(&term_orig);
569} 590}
591#else
592#define rawmode() ((void)0)
593#define cookmode fflush_all
594#endif
570 595
571//----- Terminal Drawing --------------------------------------- 596//----- Terminal Drawing ---------------------------------------
572// The terminal is made up of 'rows' line of 'columns' columns. 597// The terminal is made up of 'rows' line of 'columns' columns.
@@ -1105,7 +1130,11 @@ static char *get_input_line(const char *prompt)
1105 c = get_one_char(); 1130 c = get_one_char();
1106 if (c == '\n' || c == '\r' || c == 27) 1131 if (c == '\n' || c == '\r' || c == 27)
1107 break; // this is end of input 1132 break; // this is end of input
1133#if !ENABLE_PLATFORM_MINGW32
1108 if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { 1134 if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) {
1135#else
1136 if (c == 8 || c == 127) {
1137#endif
1109 // user wants to erase prev char 1138 // user wants to erase prev char
1110 buf[--i] = '\0'; 1139 buf[--i] = '\0';
1111 write1("\b \b"); // erase char on screen 1140 write1("\b \b"); // erase char on screen
@@ -1858,6 +1887,18 @@ static char *yank_delete(char *start, char *stop, int dist, int yf, int undo)
1858 return p; 1887 return p;
1859} 1888}
1860 1889
1890#if ENABLE_PLATFORM_MINGW32
1891static int count_cr(char *p, int len)
1892{
1893 int i, cnt;
1894
1895 for (i = cnt = 0; i < len; ++i)
1896 if (p[i] == '\n')
1897 ++cnt;
1898 return cnt;
1899}
1900#endif
1901
1861// might reallocate text[]! 1902// might reallocate text[]!
1862static int file_insert(const char *fn, char *p, int initial) 1903static int file_insert(const char *fn, char *p, int initial)
1863{ 1904{
@@ -1870,7 +1911,11 @@ static int file_insert(const char *fn, char *p, int initial)
1870 if (p > end) 1911 if (p > end)
1871 p = end; 1912 p = end;
1872 1913
1914#if !ENABLE_PLATFORM_MINGW32
1873 fd = open(fn, O_RDONLY); 1915 fd = open(fn, O_RDONLY);
1916#else
1917 fd = open(fn, O_RDONLY | _O_TEXT);
1918#endif
1874 if (fd < 0) { 1919 if (fd < 0) {
1875 if (!initial) 1920 if (!initial)
1876 status_line_bold_errno(fn); 1921 status_line_bold_errno(fn);
@@ -1893,8 +1938,15 @@ static int file_insert(const char *fn, char *p, int initial)
1893 status_line_bold_errno(fn); 1938 status_line_bold_errno(fn);
1894 p = text_hole_delete(p, p + size - 1, NO_UNDO); // un-do buffer insert 1939 p = text_hole_delete(p, p + size - 1, NO_UNDO); // un-do buffer insert
1895 } else if (cnt < size) { 1940 } else if (cnt < size) {
1941#if ENABLE_PLATFORM_MINGW32
1942 // On WIN32 a partial read might just mean CRs have been removed
1943 int cnt_cr = cnt + count_cr(p, cnt);
1944#endif
1896 // There was a partial read, shrink unused space 1945 // There was a partial read, shrink unused space
1897 p = text_hole_delete(p + cnt, p + size - 1, NO_UNDO); 1946 p = text_hole_delete(p + cnt, p + size - 1, NO_UNDO);
1947#if ENABLE_PLATFORM_MINGW32
1948 if (cnt_cr < size)
1949#endif
1898 status_line_bold("can't read '%s'", fn); 1950 status_line_bold("can't read '%s'", fn);
1899 } 1951 }
1900 fi: 1952 fi:
@@ -2001,7 +2053,11 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2001 if ((p[-1] != '\n') && (dot > text)) { 2053 if ((p[-1] != '\n') && (dot > text)) {
2002 p--; 2054 p--;
2003 } 2055 }
2056#if !ENABLE_PLATFORM_MINGW32
2004 } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS 2057 } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS
2058#else
2059 } else if (c == 8 || c == 127) { // Is this a BS
2060#endif
2005 if (p > text) { 2061 if (p > text) {
2006 p--; 2062 p--;
2007 p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char 2063 p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char
@@ -2122,12 +2178,22 @@ static int file_write(char *fn, char *first, char *last)
2122 // By popular request we do not open file with O_TRUNC, 2178 // By popular request we do not open file with O_TRUNC,
2123 // but instead ftruncate() it _after_ successful write. 2179 // but instead ftruncate() it _after_ successful write.
2124 // Might reduce amount of data lost on power fail etc. 2180 // Might reduce amount of data lost on power fail etc.
2181#if !ENABLE_PLATFORM_MINGW32
2125 fd = open(fn, (O_WRONLY | O_CREAT), 0666); 2182 fd = open(fn, (O_WRONLY | O_CREAT), 0666);
2183#else
2184 fd = open(fn, (O_WRONLY | O_CREAT | _O_TEXT), 0666);
2185#endif
2126 if (fd < 0) 2186 if (fd < 0)
2127 return -1; 2187 return -1;
2128 cnt = last - first + 1; 2188 cnt = last - first + 1;
2129 charcnt = full_write(fd, first, cnt); 2189 charcnt = full_write(fd, first, cnt);
2190#if !ENABLE_PLATFORM_MINGW32
2130 ftruncate(fd, charcnt); 2191 ftruncate(fd, charcnt);
2192#else
2193 // File was written in text mode; this makes it bigger so adjust
2194 // the truncation to match.
2195 ftruncate(fd, charcnt + count_cr(first, cnt));
2196#endif
2131 if (charcnt == cnt) { 2197 if (charcnt == cnt) {
2132 // good write 2198 // good write
2133 //modified_count = FALSE; 2199 //modified_count = FALSE;