├── sed-4.9-xp.exe ├── sed-4.9-x64.exe ├── sed-4.9-x86.exe ├── archive ├── sed-4.3.exe ├── sed-4.4.exe ├── sed-4.5.exe ├── sed-4.7.exe ├── sed-4.3-x64.exe ├── sed-4.4-x64.exe ├── sed-4.5-x64.exe ├── sed-4.7-x64.exe ├── sed-4.7-xp.exe ├── sed-4.8-x64.exe ├── sed-4.8-x86.exe ├── sed-4.8-xp.exe ├── sed-4.5-build-VS9-x86.txt ├── sed-4.7-build-VS9-x86.txt ├── sed-4.8-build-VS9-x86.txt ├── sed-4.3-build-VS9-x86.txt ├── sed-4.4-build-VS9-x86.txt ├── sed-4.3-build-VS14-x64.txt ├── sed-4.5-build-VS17-x64.txt ├── sed-4.7-build-VS19-x64.txt ├── sed-4.8-build-VS19-x64.txt ├── sed-4.4-build-VS17-x64.txt ├── sed-4.7-build-MINGW.txt ├── sed-4.3-build-patch-howto.txt ├── sed-4.4-src.patch ├── sed-4.4-build-patch-howto.txt ├── sed-4.5-build-patch-howto.txt ├── sed-4.5-src.patch ├── sed-4.3-win-headers.patch ├── sed-4.8-win-headers.patch ├── sed-4.8-build-patch-howto.txt ├── sed-4.7-build-patch-howto.txt ├── sed-4.3-src.patch ├── sed-4.7-src.patch └── sed-4.8-src.patch ├── sed-4.9-build-MINGW.txt ├── sed-4.9-build.txt ├── README.md ├── sed-4.9-win-headers.patch ├── sed-4.9-build-patch-howto.txt └── sed-4.9-src.patch /sed-4.9-xp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/sed-4.9-xp.exe -------------------------------------------------------------------------------- /sed-4.9-x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/sed-4.9-x64.exe -------------------------------------------------------------------------------- /sed-4.9-x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/sed-4.9-x86.exe -------------------------------------------------------------------------------- /archive/sed-4.3.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.3.exe -------------------------------------------------------------------------------- /archive/sed-4.4.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.4.exe -------------------------------------------------------------------------------- /archive/sed-4.5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.5.exe -------------------------------------------------------------------------------- /archive/sed-4.7.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.7.exe -------------------------------------------------------------------------------- /archive/sed-4.3-x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.3-x64.exe -------------------------------------------------------------------------------- /archive/sed-4.4-x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.4-x64.exe -------------------------------------------------------------------------------- /archive/sed-4.5-x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.5-x64.exe -------------------------------------------------------------------------------- /archive/sed-4.7-x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.7-x64.exe -------------------------------------------------------------------------------- /archive/sed-4.7-xp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.7-xp.exe -------------------------------------------------------------------------------- /archive/sed-4.8-x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.8-x64.exe -------------------------------------------------------------------------------- /archive/sed-4.8-x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.8-x86.exe -------------------------------------------------------------------------------- /archive/sed-4.8-xp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuilov/sed-windows/HEAD/archive/sed-4.8-xp.exe -------------------------------------------------------------------------------- /archive/sed-4.5-build-VS9-x86.txt: -------------------------------------------------------------------------------- 1 | How to build native win32 sed.exe with Visual Studio 9.0 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget http://ftp.gnu.org/gnu/sed/sed-4.5.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.5.tar.xz 7 | 3) go to sed sources: cd sed-4.5 8 | 9 | 4) fix sed-4.5-build-VS9-x86.patch - change path to location of Visual Studio 9.0 10 | 11 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' sed-4.5-build-VS9-x86.patch 12 | 13 | 5) patch sed: patch -Np1 -i sed-4.5-build-VS9-x86.patch 14 | 6) run dos prompt: cmd.exe /c "start cmd.exe" 15 | 7) setup compiler: "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 16 | 8) do compile: make.bat 17 | 9) check build result: sed\sed.exe --version 18 | -------------------------------------------------------------------------------- /archive/sed-4.7-build-VS9-x86.txt: -------------------------------------------------------------------------------- 1 | How to build native win32 sed.exe with Visual Studio 9.0 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget https://ftp.gnu.org/gnu/sed/sed-4.7.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.7.tar.xz 7 | 3) go to sed sources: cd sed-4.7 8 | 9 | 4) fix sed-4.7-build-VS9-x86.patch - change path to location of Visual Studio 9.0 10 | 11 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' sed-4.7-build-VS9-x86.patch 12 | 13 | 5) patch sed: patch -Np1 -i sed-4.7-build-VS9-x86.patch 14 | 6) run dos prompt: cmd.exe /c "start cmd.exe" 15 | 7) setup compiler: "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 16 | 8) do compile: make.bat 17 | 9) check build result: sed\sed.exe --version 18 | -------------------------------------------------------------------------------- /archive/sed-4.8-build-VS9-x86.txt: -------------------------------------------------------------------------------- 1 | How to build native win32 sed.exe with Visual Studio 9.0 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.8.tar.xz 7 | 3) go to sed sources: cd sed-4.8 8 | 9 | 4) fix sed-4.8-build-VS9-x86.patch - change path to location of Visual Studio 9.0 10 | 11 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' sed-4.8-build-VS9-x86.patch 12 | 13 | 5) patch sed: patch -Np1 -i sed-4.8-build-VS9-x86.patch 14 | 6) run dos prompt: cmd.exe /c "start cmd.exe" 15 | 7) setup compiler: "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 16 | 8) do compile: make.bat 17 | 9) check build result: sed\sed.exe --version --locale=C 18 | -------------------------------------------------------------------------------- /archive/sed-4.3-build-VS9-x86.txt: -------------------------------------------------------------------------------- 1 | How to build native win32 sed.exe with Visual Studio 9.0 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget http://ftp.gnu.org/gnu/sed/sed-4.3.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.3.tar.xz 7 | 3) go to sed sources: cd sed-4.3 8 | 4) apply a patch: patch -Np1 -i sed-4.3-src.patch 9 | 10 | 5) fix sed-4.3-build-VS9-x86.patch - change path to location of Visual Studio 9.0 11 | 12 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' sed-4.3-build-VS9-x86.patch 13 | 14 | 6) patch sed headers: patch -Np1 -i sed-4.3-build-VS9-x86.patch 15 | 7) run dos prompt: cmd.exe /c "start cmd.exe" 16 | 8) setup compiler: "c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 17 | 9) do compile: make.bat 18 | 10) check build result: sed\sed.exe --version 19 | -------------------------------------------------------------------------------- /archive/sed-4.4-build-VS9-x86.txt: -------------------------------------------------------------------------------- 1 | How to build native win32 sed.exe with Visual Studio 9.0 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget http://ftp.gnu.org/gnu/sed/sed-4.4.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.4.tar.xz 7 | 3) go to sed sources: cd sed-4.4 8 | 4) apply a patch: patch -Np1 -i sed-4.4-src.patch 9 | 10 | 5) Visual Studio 2008 C-compiler doesn't support C99, so apply one more patch: 11 | patch -Np1 -i sed-4.4-src-non-c99.patch 12 | 13 | 6) fix sed-4.4-build-VS9-x86.patch - change path to location of Visual Studio 9.0 14 | 15 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' sed-4.4-build-VS9-x86.patch 16 | 17 | 7) patch sed headers: patch -Np1 -i sed-4.4-build-VS9-x86.patch 18 | 8) run dos prompt: cmd.exe /c "start cmd.exe" 19 | 9) setup compiler: "c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 20 | 10) do compile: make.bat 21 | 11) check build result: sed\sed.exe --version 22 | -------------------------------------------------------------------------------- /archive/sed-4.3-build-VS14-x64.txt: -------------------------------------------------------------------------------- 1 | How to build native win64 sed.exe with Visual Studio 14.0 and WDK10 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget http://ftp.gnu.org/gnu/sed/sed-4.3.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.3.tar.xz 7 | 3) go to sed sources: cd sed-4.3 8 | 4) apply a patch: patch -Np1 -i sed-4.3-src.patch 9 | 10 | 5) fix sed-4.3-build-VS14-x64.patch - change paths to locations of Visual Studio 14.0 and WDK10 11 | 12 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\include@' sed-4.3-build-VS14-x64.patch 13 | sed -i '/Windows Kits/s@C:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\ucrt@' sed-4.3-build-VS14-x64.patch 14 | 15 | 6) patch sed headers: patch -Np1 -i sed-4.3-build-VS14-x64.patch 16 | 7) run dos prompt: cmd.exe /c "start cmd.exe" 17 | 8) setup compiler: "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 18 | 9) do compile: make.bat 19 | 10) check build result: sed\sed.exe --version 20 | -------------------------------------------------------------------------------- /archive/sed-4.5-build-VS17-x64.txt: -------------------------------------------------------------------------------- 1 | How to build native win64 sed.exe with Visual Studio 2017 and WDK10 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget http://ftp.gnu.org/gnu/sed/sed-4.5.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.5.tar.xz 7 | 3) go to sed sources: cd sed-4.5 8 | 9 | 4) fix sed-4.5-build-VS17-x64.patch - change paths to locations of Visual Studio 2017 and WDK10 10 | 11 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.14.26428\\include@' sed-4.5-build-VS17-x64.patch 12 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.17134.0\\ucrt@' sed-4.5-build-VS17-x64.patch 13 | 14 | 5) patch sed: patch -Np1 -i sed-4.5-build-VS17-x64.patch 15 | 6) run dos prompt: cmd.exe /c "start cmd.exe" 16 | 7) setup compiler: "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 17 | 8) do compile: make.bat 18 | 9) check build result: sed\sed.exe --version 19 | -------------------------------------------------------------------------------- /archive/sed-4.7-build-VS19-x64.txt: -------------------------------------------------------------------------------- 1 | How to build native win64 sed.exe with Visual Studio 2019 and WDK10 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget https://ftp.gnu.org/gnu/sed/sed-4.7.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.7.tar.xz 7 | 3) go to sed sources: cd sed-4.7 8 | 9 | 4) fix sed-4.7-build-VS19-x64.patch - change paths to locations of Visual Studio 2019 and WDK10 10 | 11 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.23.28105\\include@' sed-4.7-build-VS19-x64.patch 12 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt@' sed-4.7-build-VS19-x64.patch 13 | 14 | 5) patch sed: patch -Np1 -i sed-4.7-build-VS19-x64.patch 15 | 6) run dos prompt: cmd.exe /c "start cmd.exe" 16 | 7) setup compiler: "D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 17 | 8) do compile: make.bat 18 | 9) check build result: sed\sed.exe --version 19 | -------------------------------------------------------------------------------- /archive/sed-4.8-build-VS19-x64.txt: -------------------------------------------------------------------------------- 1 | How to build native win64 sed.exe with Visual Studio 2019 and WDK10 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.8.tar.xz 7 | 3) go to sed sources: cd sed-4.8 8 | 9 | 4) fix sed-4.8-build-VS19-x64.patch - change paths to locations of Visual Studio 2019 and WDK10 10 | 11 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\include@' sed-4.8-build-VS19-x64.patch 12 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt@' sed-4.8-build-VS19-x64.patch 13 | 14 | 5) patch sed: patch -Np1 -i sed-4.8-build-VS19-x64.patch 15 | 6) run dos prompt: cmd.exe /c "start cmd.exe" 16 | 7) setup compiler: "D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 17 | 8) do compile: make.bat 18 | 9) check build result: sed\sed.exe --version --locale=C 19 | -------------------------------------------------------------------------------- /archive/sed-4.4-build-VS17-x64.txt: -------------------------------------------------------------------------------- 1 | How to build native win64 sed.exe with Visual Studio 17.0 and WDK10 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget http://ftp.gnu.org/gnu/sed/sed-4.4.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.4.tar.xz 7 | 3) go to sed sources: cd sed-4.4 8 | 4) apply a patch: patch -Np1 -i sed-4.4-src.patch 9 | 10 | 5) fix sed-4.4-build-VS17-x64.patch - change paths to locations of Visual Studio 2017 and WDK10 11 | 12 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.10.25017\\include@' sed-4.4-build-VS17-x64.patch 13 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\ucrt@' sed-4.4-build-VS17-x64.patch 14 | 15 | 6) patch sed headers: patch -Np1 -i sed-4.4-build-VS17-x64.patch 16 | 7) run dos prompt: cmd.exe /c "start cmd.exe" 17 | 8) setup compiler: "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 18 | 9) do compile: make.bat 19 | 10) check build result: sed\sed.exe --version 20 | -------------------------------------------------------------------------------- /sed-4.9-build-MINGW.txt: -------------------------------------------------------------------------------- 1 | Building native 64-bit SED with MINGW. 2 | 3 | 1) Install MSYS2 (https://www.msys2.org/) 4 | 5 | 2) Install gcc toolchain and utilities (in the MSYS2 window) 6 | pacman -Sy mingw-w64-x86_64-toolchain 7 | pacman -S wget 8 | pacman -S tar 9 | pacman -S patch 10 | pacman -S make 11 | 12 | 3) Restart MSYS2 (so configure script will be able to find gcc): 13 | either find "MSYS2 MinGW 64-bit" from the start menu or run directly: 14 | C:\msys64\msys2_shell.cmd -mingw64 15 | 16 | 4) Download and unpack sed: 17 | wget https://ftp.gnu.org/gnu/sed/sed-4.9.tar.xz 18 | tar xf sed-4.9.tar.xz && cd sed-4.9 19 | 20 | 5) Download sed patches: 21 | wget https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.9-src.patch 22 | 23 | 6) Apply patches to the sed: 24 | patch -Np1 -i sed-4.9-src.patch 25 | 26 | 7) Fix sed makefile for linking sed as a unicode application (https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/): 27 | sed -i 's/^sed_sed_LINK = $(CCLD)/& -municode/' Makefile.in 28 | 29 | 8) Fix sed makefile - to fix "lib/getrandom.c:128: undefined reference to `BCryptGenRandom'" link error 30 | sed -i 's/$(sed_sed_LINK) .*/& $(LIB_GETRANDOM)/' Makefile.in 31 | 32 | 9) Configure sed: 33 | ./configure --disable-dependency-tracking --disable-nls CFLAGS="-g -O2 -fstack-protector" 34 | 35 | 10) And finally, build sed: 36 | make 37 | 38 | 11) Check built executable: 39 | ./sed/sed.exe --locale=C --version 40 | 41 | BUGS: 42 | Utf-8 locales don't seem to be supported on mingw64 builds right now. 43 | It's possible to specify a code page to use, like "sed.exe --locale=.866", but code page 65001 isn't supported. 44 | -------------------------------------------------------------------------------- /archive/sed-4.7-build-MINGW.txt: -------------------------------------------------------------------------------- 1 | Building native 64-bit SED with MINGW. 2 | 3 | 1) Install MSYS2 (https://www.msys2.org/) 4 | 5 | 2) Install gcc toolchain and utilities (in the MSYS2 window) 6 | pacman -Sy mingw-w64-x86_64-toolchain 7 | pacman -S wget 8 | pacman -S tar 9 | pacman -S patch 10 | pacman -S make 11 | 12 | 3) Restart MSYS2 (so configure script will be able to find gcc): 13 | either find "MSYS2 MinGW 64-bit" from the start menu or run directly: 14 | C:\msys64\msys2_shell.cmd -mingw64 15 | 16 | 4) Download and unpack sed: 17 | wget https://ftp.gnu.org/gnu/sed/sed-4.7.tar.xz 18 | tar xf sed-4.7.tar.xz && cd sed-4.7 19 | 20 | 5) Download sed patches: 21 | wget https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.7-src.patch 22 | 23 | 6) Apply patches to the sed: 24 | patch -Np1 -i sed-4.7-src.patch 25 | 26 | 7) Fix sed makefile for linking sed as a unicode application (https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/): 27 | sed -i 's/^sed_sed_LINK = $(CCLD)/& -municode/' Makefile.in 28 | 29 | 8) Fix sed makefile to avoid failing gnulib tests: 30 | sed -i '/^SUBDIRS = /s/ gnulib-tests/# gnulib-tests/' Makefile.in 31 | 32 | 9) Configure sed: 33 | ./configure --disable-dependency-tracking --disable-nls 34 | 35 | 10) Fix config.h - mingw-w64 may not support fortified functions, so don't define _FORTIFY_SOURCE: 36 | sed -i '/# define _FORTIFY_SOURCE/d' config.h 37 | 38 | 11) And finally, build sed: 39 | make 40 | 41 | 12) Check built executable: 42 | sed/sed.exe 43 | 44 | BUGS: 45 | Utf-8 locales don't seem to be supported on mingw64 builds right now. 46 | It's possible to specify a code page to use, like "sed.exe --locale=.866", but code page 65001 isn't supported. 47 | -------------------------------------------------------------------------------- /sed-4.9-build.txt: -------------------------------------------------------------------------------- 1 | How to build native 32/64-bit Gnu sed.exe with Visual Studio 2022 and WDK10 or with Visual Studio 2008 2 | 3 | From cygwin or other unix shell: 4 | 5 | 1) get sed archive: wget https://ftp.gnu.org/gnu/sed/sed-4.9.tar.xz 6 | 2) unpack sed archive: tar xf sed-4.9.tar.xz 7 | 3) go to sed sources: cd sed-4.9 8 | 4) run dos prompt: cmd /c "start cmd.exe" 9 | 5) setup compiler: 10 | for 64-bit build: "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64 11 | for 32-bit build: "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x86 12 | for Visual Studio 2008: "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 13 | 6) temporary run sh: sh 14 | 7) copy build patch: 15 | for 64-bit build: cp -v ../sed-4.9-build-VS22-x64.patch ./build.patch 16 | for 32-bit build: cp -v ../sed-4.9-build-VS22-x86.patch ./build.patch 17 | for Visual Studio 2008: cp -v ../sed-4.9-build-VS9-x86.patch ./build.patch 18 | 8) fix build patch - change paths to locations of Visual Studio 2022 and WDK10: 19 | sed -i '/Visual Studio/s@.:.*include@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[^=;]*[0-9]\\\\include\).*$@\1@p')"'@' ./build.patch 20 | sed -i '/Windows Kits/s@.:.*ucrt@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\ucrt\).*$@\1@p')"'@' ./build.patch 21 | --tip: for Visual Studio 2008: 22 | sed -i '/Visual Studio/s@.:.*[iI][nN][cC][lL][uU][dD][eE]@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[iI][nN][cC][lL][uU][dD][eE]\).*$@\1@p')"'@' ./build.patch 23 | 9) patch sed: patch -Np1 -i ./build.patch 24 | 10) exit sh: exit 25 | 11) do compile: make.bat 26 | 12) check build result: sed\sed.exe --version --locale=C 27 | -------------------------------------------------------------------------------- /archive/sed-4.3-build-patch-howto.txt: -------------------------------------------------------------------------------- 1 | How to build native sed.exe and create sed-4.3-build-VS..-xxx.patch 2 | 3 | 1) get archive: wget http://ftp.gnu.org/gnu/sed/sed-4.3.tar.xz 4 | 2) unpack archive: tar xf sed-4.3.tar.xz 5 | 3) go to sed sources: cd sed-4.3 6 | 4) apply a patch: patch -Np1 -i sed-4.3-src.patch 7 | 5) run dos prompt: cmd.exe /c "start cmd.exe" 8 | 6) setup compiler: "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 9 | 7) run bash: bash 10 | 8) check make is working: make --version 11 | 12 | 9) configure sed: 13 | CC=cl CPP="cl -E" LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules 14 | 15 | 10) fix generated Makefile: 16 | sed -i '/^NEXT/s/=.*/=""/' Makefile 17 | sed -i '/lib_libsed_a_AR/s/ lib/lib/' Makefile 18 | sed -i '/sed_libver_a_AR/s/ sed/sed/' Makefile 19 | sed -i 's/^AR = .*/AR = lib/' Makefile 20 | sed -i 's/^all-local:.*/all-local:/' Makefile 21 | 22 | 11) fix sed target: echo 'sed_sed_LINK = link /DEFAULTLIB:LIBCPMT.lib /OUT:$@' >> Makefile 23 | 12) add gen target: echo 'gen: $(BUILT_SOURCES)' >> Makefile 24 | 13) generate sed headers: make gen 25 | 26 | 14) fix sed-4.3-win-headers.patch - change paths to locations of Visual Studio 14.0 and WDK10 27 | 28 | sed -i '/Visual Studio/s@C:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\include@' sed-4.3-win-headers.patch 29 | sed -i '/Windows Kits/s@C:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\ucrt@' sed-4.3-win-headers.patch 30 | 31 | 15) patch generated headers: patch -Np1 -i sed-4.3-win-headers.patch 32 | 16) do compile sed: make > make.bat 33 | 17) check build result: sed/sed.exe --version 34 | 35 | compilation should be ok, native sed/sed.exe should be created 36 | 37 | Now it is possible to create a patch file - to compile sed.exe without any unix emulation layer: 38 | 1) diff current directory with original just unpacked sed-4.3.tar.xz orig-dir 39 | 2) remove unneeded built files in current directory (object files, libs, etc...) 40 | 3) edit make.bat 41 | 4) create a patch: diff -Naur {orig-dir} {curr-dir} > sed-4.3-build-VS..-xxx.patch 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sed-windows 2 | Instructions for building [Gnu Sed](https://www.gnu.org/software/sed) as a native windows application 3 | 4 | All patches under the same license as sources of [Gnu Sed](https://www.gnu.org/software/sed): [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) or later 5 | 6 | Author of the patches: Michael M. Builov (mbuilov@yandex.ru) 7 | 8 | ## Fixed bugs: 9 | - wrong directory of input file in in-place editing mode ('-i' switch) (sed: cannot rename ./sed8JEw8l: Improper link) 10 | - sources were fixed for correct processing of text files with Windows line endings (if Sed is built under CYGWIN) 11 | - fixed support of UTF-8 locale (e.g. "Russian_Russia.UTF-8", available starting with Windows 7) 12 | - fixed interaction with standard Windows console in UTF-8 code page (set by chcp 65001) 13 | 14 | ## Added features: 15 | - native Sed is capable for resolving wildcards in file arguments 16 | - native Sed takes locale settings from environment variables LC_ALL, LC_CTYPE or LANG 17 | - new switch '-C' or '--ignore-locale' - forces Sed to use the standard "C" locale; this switch is most usable in binary mode, to avoid possible interpretation of input data as multi-byte encoded strings (depending on the system locale) 18 | - new switch '--locale' - to explicitly specify locale to use (and ignore environment variables LC_ALL, LC_CTYPE and LANG) 19 | 20 | ## Pre-built executables: 21 | - [`sed-4.9-x64.exe`](/../../raw/master/sed-4.9-x64.exe) - sed 4.9 built for Windows10 x64 (sha1sum: 517226430b5a708cc8d2dfa4caa624f6a5b0449a) 22 | - [`sed-4.9-x86.exe`](/../../raw/master/sed-4.9-x86.exe) - sed 4.9 built for Windows10 x86 (sha1sum: ecf1bbc23264ebb19ea71332c5fa0f90e9f23465) 23 | - [`sed-4.9-xp.exe`](/../../raw/master/sed-4.9-xp.exe) - sed 4.9 built for windowsXP x86 (does not support .UTF-8 locale) (sha1sum: 6b2f68bdb53b59f090e9bfc1c97df219f5622e55) 24 | 25 | ## Instructions how to create the build patch 26 | - [`sed-4.9-build-patch-howto.txt`](/sed-4.9-build-patch-howto.txt) 27 | 28 | ## Instructions how to apply build patch to compile sed using native tools only 29 | - [`sed-4.9-build.txt`](/sed-4.9-build.txt) 30 | 31 | ## Prepared build patches 32 | For x64/Windows10/VS22: 33 | - [`sed-4.9-build-VS22-x64.patch`](/sed-4.9-build-VS22-x64.patch) 34 | 35 | For x86/Windows10/VS22 36 | - [`sed-4.9-build-VS22-x86.patch`](/sed-4.9-build-VS22-x86.patch) 37 | 38 | For x86/WindowsXP/VS9 39 | - [`sed-4.9-build-VS9-x86.patch`](/sed-4.9-build-VS9-x86.patch) 40 | -------------------------------------------------------------------------------- /archive/sed-4.4-src.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.3-orig/sed/execute.c sed-4.3-patched/sed/execute.c 2 | --- sed-4.3-orig/sed/execute.c 2016-12-13 01:59:59.000000000 +0300 3 | +++ sed-4.3-patched/sed/execute.c 2017-01-13 10:11:06.590125000 +0300 4 | @@ -28,6 +28,11 @@ 5 | #include 6 | #include 7 | #include 8 | +#if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 9 | + || defined MSDOS || defined __EMX__ 10 | +#include 11 | +#include 12 | +#endif 13 | #include 14 | #include 15 | #include "stat-macros.h" 16 | @@ -557,11 +562,13 @@ 17 | if (name[0] == '-' && name[1] == '\0' && !in_place_extension) 18 | { 19 | clearerr(stdin); /* clear any stale EOF indication */ 20 | + input->fp = stdin; 21 | #if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 22 | || defined MSDOS || defined __EMX__ 23 | - input->fp = ck_fdopen (fileno (stdin), "stdin", read_mode, false); 24 | -#else 25 | - input->fp = stdin; 26 | + if ('r' == read_mode[0] && 'b' == read_mode[1]) 27 | + setmode(fileno(input->fp), O_BINARY); 28 | + else 29 | + setmode(fileno(input->fp), O_TEXT); 30 | #endif 31 | } 32 | else 33 | @@ -648,6 +655,13 @@ 34 | if (input->fp && unbuffered) 35 | setvbuf (input->fp, NULL, _IONBF, 0); 36 | output_file.fp = stdout; 37 | +#if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 38 | + || defined MSDOS || defined __EMX__ 39 | + if ('w' == write_mode[0] && 'b' == write_mode[1]) 40 | + setmode(fileno(output_file.fp), O_BINARY); 41 | + else 42 | + setmode(fileno(output_file.fp), O_TEXT); 43 | +#endif 44 | } 45 | } 46 | 47 | diff -Naur sed-4.3-orig/sed/sed.c sed-4.3-patched/sed/sed.c 48 | --- sed-4.3-orig/sed/sed.c 2016-11-27 20:15:52.000000000 +0300 49 | +++ sed-4.3-patched/sed/sed.c 2017-01-13 10:11:28.308875000 +0300 50 | @@ -60,9 +60,9 @@ 51 | /* How do we edit files in-place? (we don't if NULL) */ 52 | char *in_place_extension = NULL; 53 | 54 | -/* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ 55 | -char const *read_mode = "r"; 56 | -char const *write_mode = "w"; 57 | +/* The mode to use to read/write files, either "rt"/"wt" or "rb"/"wb". */ 58 | +char const *read_mode = "rt"; 59 | +char const *write_mode = "wt"; 60 | 61 | /* Do we need to be pedantically POSIX compliant? */ 62 | enum posixicity_types posixicity; 63 | @@ -104,7 +104,6 @@ 64 | G_file_to_unlink = NULL; 65 | } 66 | 67 | -static void usage (int); 68 | static void 69 | contact(int errmsg) 70 | { 71 | diff -Naur g/sed-4.4/sed/utils.c sed-4.4/sed/utils.c 72 | --- g/sed-4.4/sed/utils.c 2017-01-01 14:17:10.000000000 +0300 73 | +++ sed-4.4/sed/utils.c 2017-03-09 13:51:33.103824100 +0300 74 | @@ -22,6 +22,7 @@ 75 | #include 76 | #include 77 | #include 78 | +#include 79 | #include 80 | #include 81 | #include 82 | @@ -172,7 +173,7 @@ 83 | so unauthorized users cannot nip in before the file is ready. 84 | mkstemp forces O_BINARY on cygwin, so use mkostemp instead. */ 85 | mode_t save_umask = umask (0700); 86 | - int fd = mkostemp (template, 0); 87 | + int fd = mkostemp (template, ('w' == mode[0] && 'b' == mode[1]) ? O_BINARY : O_TEXT); 88 | umask (save_umask); 89 | if (fd == -1) 90 | panic(_("couldn't open temporary file %s: %s"), template, strerror(errno)); 91 | -------------------------------------------------------------------------------- /archive/sed-4.4-build-patch-howto.txt: -------------------------------------------------------------------------------- 1 | Instruction how to build native sed.exe with Microsoft Visual Studio from cygwin shell. 2 | 3 | While building, it is possible to save build log and create a patch - for compiling sed.exe using only Microsoft Visual Studio tools, without need for cygwin. 4 | 5 | This is how sed-4.4-build-VS17-x64.patch was created. 6 | 7 | (sed-4.4-build-VS9-x86.patch was created analogously in Microsoft Visual Studio 2008 environment) 8 | 9 | 10 | From cygwin shell: 11 | 12 | 1) get archive: 13 | wget http://ftp.gnu.org/gnu/sed/sed-4.4.tar.xz 14 | 15 | 2) unpack archive: 16 | tar xf sed-4.4.tar.xz 17 | 18 | 3) go to sed sources: 19 | cd sed-4.4 20 | 21 | 4) apply a patch to correctly open files in text (default) or binary (if sed is run with '-b' switch) mode: 22 | patch -Np1 -i sed-4.4-src.patch 23 | (patch location: https://github.com/mbuilov/sed-windows/blob/master/sed-4.4-src.patch) 24 | 25 | 5) to build with old non-c99 compiler (such as Microsoft Visual Studio 2008) apply one more patch: 26 | patch -Np1 -i sed-4.4-src-non-c99.patch 27 | (patch location: https://github.com/mbuilov/sed-windows/blob/master/sed-4.4-src-non-c99.patch) 28 | 29 | 6) now start dos prompt: 30 | cmd.exe /c "start cmd.exe" 31 | 32 | 7) setup compiler: 33 | "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 34 | (if Microsoft Visual Studio 2017 is installed in "D:\Program Files (x86)") 35 | 36 | 8) run bash from dos prompt (with environment prepared for compiling with Microsoft Visual Studio): 37 | bash 38 | 39 | 9) check Gnu Make is installed in cygwin and is working: 40 | make --version 41 | 42 | 10) configure sed: 43 | CFLAGS= CC=cl CPP="cl -E" LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules 44 | 45 | 11) configure script is not fully functional to create correct Makefile - it needs to be fixed manually: 46 | sed -i '/^NEXT/s/=.*/=""/' Makefile 47 | sed -i '/lib_libsed_a_AR/s/ lib/lib/' Makefile 48 | sed -i '/sed_libver_a_AR/s/ sed/sed/' Makefile 49 | sed -i 's/^AR = .*/AR = lib/' Makefile 50 | sed -i 's/^all-local:.*/all-local:/' Makefile 51 | sed -i 's/-c -o /-c -nologo -Fo/' Makefile 52 | 53 | 12) fix sed target in Makefile: 54 | echo 'sed_sed_LINK = link /DEFAULTLIB:LIBCPMT.lib /OUT:$@' >> Makefile 55 | 56 | 13) add gen target: 57 | echo 'gen: $(BUILT_SOURCES)' >> Makefile 58 | 59 | 14) execute Makefile to generate sed headers: 60 | make gen 61 | 62 | 15) some references to system header files are missing in generated headers - they need to be fixed manually. 63 | 64 | a) set paths to locations of Visual Studio 2017 and WDK10 in sed-4.3-win-headers.patch: 65 | for example, if Visual Studio 2017 is installed in "D:\Program Files (x86)" and WDK10 installed in "C:\Program Files (x86)" 66 | 67 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.10.25017\\include@' ./sed-4.3-win-headers.patch 68 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\ucrt@' ./sed-4.3-win-headers.patch 69 | 70 | (patch location: https://github.com/mbuilov/sed-windows/blob/master/sed-4.3-win-headers.patch) 71 | 72 | b) now patch generated headers with updated patch-file: 73 | patch -Np1 -i sed-4.3-win-headers.patch 74 | 75 | 16) do compile sed: 76 | make > make.bat 77 | 78 | 17) check build result: 79 | ./sed/sed.exe --version 80 | 81 | 82 | compilation should be ok, native ./sed/sed.exe should be created. 83 | 84 | 85 | Now it is possible to create a patch file - for compiling sed.exe using only Microsoft Visual Studio tools, without need for cygwin. 86 | 87 | 1) diff current directory with original just unpacked sed-4.4.tar.xz in '../orig' directory (use diff -rql . ../orig/sed-4.4) 88 | 2) remove unneeded built files in current directory (object files, libs, etc...) 89 | 3) edit make.bat 90 | 4) finally, create a patch: 91 | diff -Naur {orig-dir} {curr-dir} > sed-4.4-build-VS17-x64.patch 92 | -------------------------------------------------------------------------------- /archive/sed-4.5-build-patch-howto.txt: -------------------------------------------------------------------------------- 1 | Instruction how to build native sed.exe with Microsoft Visual Studio from cygwin shell. 2 | 3 | While building, it is possible to save build log and create a patch - for compiling sed.exe using only Microsoft Visual Studio tools, without need for cygwin. 4 | 5 | This is how sed-4.5-build-VS17-x64.patch was created. 6 | 7 | (sed-4.5-build-VS9-x86.patch was created analogously in Microsoft Visual Studio 2008 environment) 8 | 9 | 10 | From cygwin shell: 11 | 12 | 1) get archive: 13 | wget http://ftp.gnu.org/gnu/sed/sed-4.5.tar.xz 14 | 15 | 2) unpack archive: 16 | tar xf sed-4.5.tar.xz 17 | 18 | 3) go to sed sources: 19 | cd sed-4.5 20 | 21 | 4) apply a patch to correctly open files in text (default) or binary (if sed is run with '-b' switch) mode 22 | and to correctly determine directory of input file in in-place editing mode (enabled via '-i' switch): 23 | patch -Np1 -i sed-4.5-src.patch 24 | (patch location: https://github.com/mbuilov/sed-windows/blob/master/sed-4.5-src.patch) 25 | 26 | 5) to build with old non-c99 compiler (such as Microsoft Visual Studio 2008) apply one more patch: 27 | patch -Np1 -i sed-4.5-src-non-c99.patch 28 | (patch location: https://github.com/mbuilov/sed-windows/blob/master/sed-4.5-src-non-c99.patch) 29 | 30 | 6) now start dos prompt: 31 | cmd.exe /c "start cmd.exe" 32 | 33 | 7) setup compiler: 34 | "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 35 | (if Microsoft Visual Studio 2017 is installed in "D:\Program Files (x86)") 36 | 37 | --tip: for Visual Studio 2008: 38 | "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 39 | 40 | 8) run bash from dos prompt (with environment prepared for compiling with Microsoft Visual Studio): 41 | bash 42 | 43 | 9) check Gnu Make is installed in cygwin and it is working: 44 | make --version 45 | 46 | 10) configure sed: 47 | CFLAGS= CC=cl CPP="cl -E" LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules --disable-nls 48 | 49 | 11) configure script is not fully functional to create correct Makefile - it needs to be fixed manually: 50 | sed -i '/^SUBDIRS/s/=.*/= ./' Makefile 51 | sed -i '/^NEXT/s/=.*/=""/' Makefile 52 | sed -i '/lib_libsed_a_AR/s/ lib/lib/' Makefile 53 | sed -i '/sed_libver_a_AR/s/ sed/sed/' Makefile 54 | sed -i 's@^AR = .*@AR = lib /nologo@' Makefile 55 | sed -i 's/^all-local:.*/all-local:/' Makefile 56 | sed -i 's/-c -o /-c -nologo -Fo/' Makefile 57 | sed -i '/$(RANLIB)/d' Makefile 58 | 59 | 12) fix sed target in Makefile: 60 | echo 'sed_sed_LINK = link /nologo /DEFAULTLIB:LIBCPMT.lib /OUT:$@' >> Makefile 61 | 62 | 13) add gen target: 63 | echo 'gen: $(BUILT_SOURCES)' >> Makefile 64 | 65 | 14) execute Makefile to generate sed headers: 66 | make gen 67 | 68 | 15) some references to system header files are missing in generated headers - they need to be fixed manually. 69 | 70 | a) set paths to locations of Visual Studio 2017 and WDK10 in sed-4.3-win-headers.patch (assume it was copied to the current directory): 71 | for example, if Visual Studio 2017 is installed in "D:\Program Files (x86)" and WDK10 installed in "C:\Program Files (x86)" 72 | 73 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.14.26428\\include@' ./sed-4.3-win-headers.patch 74 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.17134.0\\ucrt@' ./sed-4.3-win-headers.patch 75 | 76 | (patch location: https://github.com/mbuilov/sed-windows/blob/master/sed-4.3-win-headers.patch) 77 | 78 | --tip: for Visual Studio 2008: 79 | sed -i '/Visual Studio/s@.:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' ./sed-4.3-win-headers.patch 80 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' ./sed-4.3-win-headers.patch 81 | 82 | b) now patch generated headers with updated patch-file: 83 | patch -Np1 -i sed-4.3-win-headers.patch 84 | 85 | Note: 86 | lib/wctype.h may be patched with a message: "Hunk #1 succeeded at 70 (offset 2 lines)." 87 | Ignore it. 88 | 89 | 16) do compile sed: 90 | make > make.bat 91 | 92 | 17) check build result: 93 | ./sed/sed.exe --version 94 | 95 | (should print sed version, e.g.: (GNU sed) 4.5) 96 | 97 | compilation should be ok, native ./sed/sed.exe should be created. 98 | 99 | 100 | Now it is possible to create a patch file - for compiling sed.exe using only Microsoft Visual Studio tools, without need for cygwin. 101 | 102 | 1) diff current directory with original just unpacked sed-4.5.tar.xz in '../orig' directory (use diff -rql . ../orig/sed-4.5) 103 | 2) remove unneeded built files in current directory (object files, libs, etc...) 104 | after this, diff should show something like: 105 | 106 | $ diff -rql . ../orig/sed-4.5 107 | Only in .: config.h 108 | Only in ./lib: alloca.h 109 | Only in ./lib: configmake.h 110 | Only in ./lib: ctype.h 111 | Only in ./lib: errno.h 112 | Only in ./lib: fcntl.h 113 | Only in ./lib: getopt.h 114 | Only in ./lib: getopt-cdefs.h 115 | Only in ./lib: langinfo.h 116 | Only in ./lib: limits.h 117 | Only in ./lib: locale.h 118 | Only in ./lib: selinux 119 | Only in ./lib: stdalign.h 120 | Only in ./lib: stddef.h 121 | Only in ./lib: stdint.h 122 | Only in ./lib: stdio.h 123 | Only in ./lib: stdlib.h 124 | Only in ./lib: string.h 125 | Only in ./lib: sys 126 | Only in ./lib: time.h 127 | Only in ./lib: unistd.h 128 | Only in ./lib: wchar.h 129 | Only in ./lib: wctype.h 130 | Only in .: make.bat 131 | Files ./sed/execute.c and ../orig/sed-4.5/sed/execute.c differ 132 | Files ./sed/sed.c and ../orig/sed-4.5/sed/sed.c differ 133 | Files ./sed/utils.c and ../orig/sed-4.5/sed/utils.c differ 134 | Only in ./sed: version.c 135 | Only in ./sed: version.h 136 | 137 | If patch sed-4.5-src-non-c99.patch was applied, diff will show additional differences: 138 | 139 | Files ./lib/dfa.c and ../orig/sed-4.5/lib/dfa.c differ 140 | Files ./lib/gettimeofday.c and ../orig/sed-4.5/lib/gettimeofday.c differ 141 | Files ./sed/regexp.c and ../orig/sed-4.5/sed/regexp.c differ 142 | 143 | 3) edit make.bat 144 | 4) finally, create a patch: 145 | diff -Naur ../orig/sed-4.5 . > ../sed-4.5-build-VS17-x64.patch 146 | or, for Visual Studio 2008: 147 | diff -Naur ../orig/sed-4.5 . > ../sed-4.5-build-VS9-x86.patch 148 | -------------------------------------------------------------------------------- /archive/sed-4.5-src.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.5-orig/sed/execute.c sed-4.5-patched/sed/execute.c 2 | --- sed-4.5-orig/sed/execute.c 2018-03-30 05:56:36.000000000 +0300 3 | +++ sed-4.5-patched/sed/execute.c 2018-11-02 13:12:10.072163600 +0300 4 | @@ -28,6 +28,11 @@ 5 | #include 6 | #include 7 | #include 8 | +#if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 9 | + || defined MSDOS || defined __EMX__ 10 | +#include 11 | +#include 12 | +#endif 13 | #include 14 | #include 15 | #include "stat-macros.h" 16 | @@ -37,6 +42,8 @@ 17 | #include "acl.h" 18 | #include "ignore-value.h" 19 | 20 | +#include "dirname.h" 21 | + 22 | /* The number of extra bytes that must be allocated/usable, beyond 23 | the declared "end" of each line buffer that may be passed to 24 | match_regex. This is imposed by its use of dfaexec. */ 25 | @@ -547,11 +554,13 @@ 26 | if (name[0] == '-' && name[1] == '\0' && !in_place_extension) 27 | { 28 | clearerr(stdin); /* clear any stale EOF indication */ 29 | + input->fp = stdin; 30 | #if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 31 | || defined MSDOS || defined __EMX__ 32 | - input->fp = ck_fdopen (fileno (stdin), "stdin", read_mode, false); 33 | -#else 34 | - input->fp = stdin; 35 | + if ('r' == read_mode[0] && 'b' == read_mode[1]) 36 | + setmode(fileno(input->fp), O_BINARY); 37 | + else 38 | + setmode(fileno(input->fp), O_TEXT); 39 | #endif 40 | } 41 | else 42 | @@ -574,17 +583,22 @@ 43 | if (in_place_extension) 44 | { 45 | int input_fd; 46 | - char *tmpdir, *p; 47 | + char *tmpdir; 48 | security_context_t old_fscreatecon; 49 | int reset_fscreatecon = 0; 50 | + size_t in_dir_len; 51 | memset (&old_fscreatecon, 0, sizeof (old_fscreatecon)); 52 | 53 | /* get the base name */ 54 | - tmpdir = ck_strdup(input->in_file_name); 55 | - if ((p = strrchr(tmpdir, '/'))) 56 | - *p = 0; 57 | + in_dir_len = dir_len(input->in_file_name); 58 | + if (in_dir_len) 59 | + { 60 | + tmpdir = xmalloc(in_dir_len + 1); 61 | + memcpy(tmpdir, input->in_file_name, in_dir_len); 62 | + tmpdir[in_dir_len] = '\0'; 63 | + } 64 | else 65 | - strcpy(tmpdir, "."); 66 | + tmpdir = ck_strdup("."); 67 | 68 | if (isatty (fileno (input->fp))) 69 | panic(_("couldn't edit %s: is a terminal"), input->in_file_name); 70 | @@ -638,6 +652,13 @@ 71 | if (input->fp && unbuffered) 72 | setvbuf (input->fp, NULL, _IONBF, 0); 73 | output_file.fp = stdout; 74 | +#if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 75 | + || defined MSDOS || defined __EMX__ 76 | + if ('w' == write_mode[0] && 'b' == write_mode[1]) 77 | + setmode(fileno(output_file.fp), O_BINARY); 78 | + else 79 | + setmode(fileno(output_file.fp), O_TEXT); 80 | +#endif 81 | } 82 | } 83 | 84 | diff -Naur sed-4.5-orig/sed/sed.c sed-4.5-patched/sed/sed.c 85 | --- sed-4.5-orig/sed/sed.c 2018-03-30 05:56:36.000000000 +0300 86 | +++ sed-4.5-patched/sed/sed.c 2018-11-02 13:14:07.615886700 +0300 87 | @@ -60,9 +60,12 @@ 88 | /* How do we edit files in-place? (we don't if NULL) */ 89 | char *in_place_extension = NULL; 90 | 91 | -/* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ 92 | -char const *read_mode = "r"; 93 | -char const *write_mode = "w"; 94 | +/* The mode to use to read/write files, either "rt"/"wt" or "rb"/"wb". */ 95 | +char const *read_mode = "rt"; 96 | +char const *write_mode = "wt"; 97 | + 98 | +/* Locale to set at startup. */ 99 | +char const *def_locale = ""; 100 | 101 | /* Do we need to be pedantically POSIX compliant? */ 102 | enum posixicity_types posixicity; 103 | @@ -104,7 +107,6 @@ 104 | G_file_to_unlink = NULL; 105 | } 106 | 107 | -static void usage (int); 108 | static void 109 | contact(int errmsg) 110 | { 111 | @@ -118,6 +120,9 @@ 112 | get reports for other people's bugs. */ 113 | if (!errmsg) 114 | fprintf(out, _("E-mail bug reports to: <%s>.\n"), PACKAGE_BUGREPORT); 115 | + 116 | + if (!errmsg) 117 | + fprintf(out, _("Patched by: Michael M. Builov .\n")); 118 | } 119 | 120 | _Noreturn static void 121 | @@ -154,6 +159,8 @@ 122 | open files in binary mode (CR+LFs are not" \ 123 | " processed specially)\n")); 124 | #endif 125 | + fprintf(out, _(" -C, --ignore-locale\n\ 126 | + ignore system locale, operate in the default \"C\" locale\n")); 127 | fprintf(out, _(" -l N, --line-length=N\n\ 128 | specify the desired line-wrap length for the `l' command\n")); 129 | fprintf(out, _(" --posix\n\ 130 | @@ -192,15 +199,16 @@ 131 | main (int argc, char **argv) 132 | { 133 | #ifdef REG_PERL 134 | -#define SHORTOPTS "bsnrzRuEe:f:l:i::V:" 135 | +#define SHORTOPTS "bCsnrzRuEe:f:l:i::V:" 136 | #else 137 | -#define SHORTOPTS "bsnrzuEe:f:l:i::V:" 138 | +#define SHORTOPTS "bCsnrzuEe:f:l:i::V:" 139 | #endif 140 | 141 | enum { SANDBOX_OPTION = CHAR_MAX+1 }; 142 | 143 | static const struct option longopts[] = { 144 | {"binary", 0, NULL, 'b'}, 145 | + {"ignore-locale", 0, NULL, 'C'}, 146 | {"regexp-extended", 0, NULL, 'r'}, 147 | #ifdef REG_PERL 148 | {"regexp-perl", 0, NULL, 'R'}, 149 | @@ -231,9 +239,27 @@ 150 | 151 | program_name = argv[0]; 152 | initialize_main (&argc, &argv); 153 | + 154 | + /* Suppress error reporting in getopt. */ 155 | + opterr = 0; 156 | + 157 | + while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF) 158 | + { 159 | + switch (opt) 160 | + { 161 | + case 'C': 162 | + def_locale = "C"; 163 | + break; 164 | + } 165 | + } 166 | + 167 | + /* Restore getopt behaviour. */ 168 | + opterr = 1; 169 | + optind = 1; 170 | + 171 | #if HAVE_SETLOCALE 172 | /* Set locale according to user's wishes. */ 173 | - setlocale (LC_ALL, ""); 174 | + setlocale (LC_ALL, def_locale); 175 | #endif 176 | set_program_name (argv[0]); 177 | initialize_mbcs (); 178 | @@ -320,6 +346,10 @@ 179 | write_mode = "wb"; 180 | break; 181 | 182 | + case 'C': 183 | + /* already processed */ 184 | + break; 185 | + 186 | case 'E': 187 | case 'r': 188 | #ifdef REG_PERL 189 | diff -Naur sed-4.5-orig/sed/utils.c sed-4.5-patched/sed/utils.c 190 | --- sed-4.5-orig/sed/utils.c 2018-03-30 05:56:36.000000000 +0300 191 | +++ sed-4.5-patched/sed/utils.c 2018-11-02 13:12:10.076163900 +0300 192 | @@ -22,6 +22,7 @@ 193 | #include 194 | #include 195 | #include 196 | +#include 197 | #include 198 | #include 199 | #include 200 | @@ -172,7 +173,7 @@ 201 | so unauthorized users cannot nip in before the file is ready. 202 | mkstemp forces O_BINARY on cygwin, so use mkostemp instead. */ 203 | mode_t save_umask = umask (0700); 204 | - int fd = mkostemp (template, 0); 205 | + int fd = mkostemp (template, ('w' == mode[0] && 'b' == mode[1]) ? O_BINARY : O_TEXT); 206 | umask (save_umask); 207 | if (fd == -1) 208 | panic(_("couldn't open temporary file %s: %s"), template, strerror(errno)); 209 | -------------------------------------------------------------------------------- /archive/sed-4.3-win-headers.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.3/lib/ctype.h sed-4.3-good/lib/ctype.h 2 | --- sed-4.3/lib/ctype.h 2017-01-11 18:02:22.838319800 +0300 3 | +++ sed-4.3-good/lib/ctype.h 2017-01-11 17:47:46.179080500 +0300 4 | @@ -32,7 +32,7 @@ 5 | 6 | /* Include the original . */ 7 | /* The include_next requires a split double-inclusion guard. */ 8 | -#include "" 9 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\ctype.h" 10 | 11 | #ifndef _GL_CTYPE_H 12 | #define _GL_CTYPE_H 13 | diff -Naur sed-4.3/lib/errno.h sed-4.3-good/lib/errno.h 14 | --- sed-4.3/lib/errno.h 2017-01-11 18:02:22.888319900 +0300 15 | +++ sed-4.3-good/lib/errno.h 2017-01-11 17:47:46.194680500 +0300 16 | @@ -24,7 +24,7 @@ 17 | 18 | 19 | /* The include_next requires a split double-inclusion guard. */ 20 | -#include "" 21 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\errno.h" 22 | 23 | #ifndef _GL_ERRNO_H 24 | #define _GL_ERRNO_H 25 | diff -Naur sed-4.3/lib/fcntl.h sed-4.3-good/lib/fcntl.h 26 | --- sed-4.3/lib/fcntl.h 2017-01-11 18:02:22.978320000 +0300 27 | +++ sed-4.3-good/lib/fcntl.h 2017-01-11 17:47:46.257080600 +0300 28 | @@ -58,7 +58,7 @@ 29 | # include 30 | #endif 31 | /* The include_next requires a split double-inclusion guard. */ 32 | -#include "" 33 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\fcntl.h" 34 | 35 | #ifndef _GL_FCNTL_H 36 | #define _GL_FCNTL_H 37 | diff -Naur sed-4.3/lib/limits.h sed-4.3-good/lib/limits.h 38 | --- sed-4.3/lib/limits.h 2017-01-11 18:02:23.108320200 +0300 39 | +++ sed-4.3-good/lib/limits.h 2017-01-11 17:47:46.179080500 +0300 40 | @@ -24,7 +24,7 @@ 41 | 42 | 43 | /* The include_next requires a split double-inclusion guard. */ 44 | -#include "" 45 | +#include "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\limits.h" 46 | 47 | #ifndef _GL_LIMITS_H 48 | #define _GL_LIMITS_H 49 | diff -Naur sed-4.3/lib/locale.h sed-4.3-good/lib/locale.h 50 | --- sed-4.3/lib/locale.h 2017-01-11 18:02:23.148320200 +0300 51 | +++ sed-4.3-good/lib/locale.h 2017-01-11 17:47:46.241480600 +0300 52 | @@ -35,7 +35,7 @@ 53 | #define _GL_ALREADY_INCLUDING_LOCALE_H 54 | 55 | /* The include_next requires a split double-inclusion guard. */ 56 | -#include "" 57 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\locale.h" 58 | 59 | #undef _GL_ALREADY_INCLUDING_LOCALE_H 60 | 61 | diff -Naur sed-4.3/lib/stddef.h sed-4.3-good/lib/stddef.h 62 | --- sed-4.3/lib/stddef.h 2017-01-11 18:02:23.398320600 +0300 63 | +++ sed-4.3-good/lib/stddef.h 2017-01-11 17:47:46.179080500 +0300 64 | @@ -52,7 +52,7 @@ 65 | 66 | /* The include_next requires a split double-inclusion guard. */ 67 | 68 | -# include "" 69 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\stddef.h" 70 | 71 | /* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ 72 | # if (0 \ 73 | diff -Naur sed-4.3/lib/stdint.h sed-4.3-good/lib/stdint.h 74 | --- sed-4.3/lib/stdint.h 2017-01-11 18:02:23.448320700 +0300 75 | +++ sed-4.3-good/lib/stdint.h 2017-01-11 17:47:46.241480600 +0300 76 | @@ -74,7 +74,7 @@ 77 | in would reinclude us, skipping our contents because 78 | _GL_STDINT_H is defined. 79 | The include_next requires a split double-inclusion guard. */ 80 | -# include "" 81 | +# include "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\stdint.h" 82 | #endif 83 | 84 | #if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H 85 | diff -Naur sed-4.3/lib/stdio.h sed-4.3-good/lib/stdio.h 86 | --- sed-4.3/lib/stdio.h 2017-01-11 18:02:23.558320800 +0300 87 | +++ sed-4.3-good/lib/stdio.h 2017-01-11 17:47:46.179080500 +0300 88 | @@ -40,7 +40,7 @@ 89 | #define _GL_ALREADY_INCLUDING_STDIO_H 90 | 91 | /* The include_next requires a split double-inclusion guard. */ 92 | -#include "" 93 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\stdio.h" 94 | 95 | #undef _GL_ALREADY_INCLUDING_STDIO_H 96 | 97 | diff -Naur sed-4.3/lib/stdlib.h sed-4.3-good/lib/stdlib.h 98 | --- sed-4.3/lib/stdlib.h 2017-01-11 18:02:23.648320900 +0300 99 | +++ sed-4.3-good/lib/stdlib.h 2017-01-11 17:47:46.194680500 +0300 100 | @@ -25,7 +25,7 @@ 101 | /* Special invocation conventions inside some gnulib header files, 102 | and inside some glibc header files, respectively. */ 103 | 104 | -#include "" 105 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\stdlib.h" 106 | 107 | #else 108 | /* Normal invocation convention. */ 109 | @@ -33,7 +33,7 @@ 110 | #ifndef _GL_STDLIB_H 111 | 112 | /* The include_next requires a split double-inclusion guard. */ 113 | -#include "" 114 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\stdlib.h" 115 | 116 | #ifndef _GL_STDLIB_H 117 | #define _GL_STDLIB_H 118 | diff -Naur sed-4.3/lib/string.h sed-4.3-good/lib/string.h 119 | --- sed-4.3/lib/string.h 2017-01-11 18:02:23.728321100 +0300 120 | +++ sed-4.3-good/lib/string.h 2017-01-11 17:47:46.194680500 +0300 121 | @@ -38,7 +38,7 @@ 122 | #define _GL_ALREADY_INCLUDING_STRING_H 123 | 124 | /* The include_next requires a split double-inclusion guard. */ 125 | -#include "" 126 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\string.h" 127 | 128 | #undef _GL_ALREADY_INCLUDING_STRING_H 129 | 130 | diff -Naur sed-4.3/lib/sys/stat.h sed-4.3-good/lib/sys/stat.h 131 | --- sed-4.3/lib/sys/stat.h 2017-01-11 18:02:23.788321100 +0300 132 | +++ sed-4.3-good/lib/sys/stat.h 2017-01-11 17:47:46.163480500 +0300 133 | @@ -29,7 +29,7 @@ 134 | #if defined __need_system_sys_stat_h 135 | /* Special invocation convention. */ 136 | 137 | -#include "" 138 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\sys\stat.h" 139 | 140 | #else 141 | /* Normal invocation convention. */ 142 | @@ -44,7 +44,7 @@ 143 | #include 144 | 145 | /* The include_next requires a split double-inclusion guard. */ 146 | -#include "" 147 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\sys\stat.h" 148 | 149 | #ifndef _GL_SYS_STAT_H 150 | #define _GL_SYS_STAT_H 151 | diff -Naur sed-4.3/lib/sys/types.h sed-4.3-good/lib/sys/types.h 152 | --- sed-4.3/lib/sys/types.h 2017-01-11 18:02:23.898321300 +0300 153 | +++ sed-4.3-good/lib/sys/types.h 2017-01-11 17:47:46.163480500 +0300 154 | @@ -25,7 +25,7 @@ 155 | 156 | /* The include_next requires a split double-inclusion guard. */ 157 | # define _GL_INCLUDING_SYS_TYPES_H 158 | -#include "" 159 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\sys\types.h" 160 | # undef _GL_INCLUDING_SYS_TYPES_H 161 | 162 | #ifndef _GL_SYS_TYPES_H 163 | diff -Naur sed-4.3/lib/time.h sed-4.3-good/lib/time.h 164 | --- sed-4.3/lib/time.h 2017-01-11 18:02:23.938321300 +0300 165 | +++ sed-4.3-good/lib/time.h 2017-01-11 17:47:46.194680500 +0300 166 | @@ -32,13 +32,13 @@ 167 | && !defined __MINGW32__) \ 168 | || defined _GL_TIME_H) 169 | 170 | -# include "" 171 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\time.h" 172 | 173 | #else 174 | 175 | # define _GL_TIME_H 176 | 177 | -# include "" 178 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\time.h" 179 | 180 | /* NetBSD 5.0 mis-defines NULL. */ 181 | # include 182 | diff -Naur sed-4.3/lib/wchar.h sed-4.3-good/lib/wchar.h 183 | --- sed-4.3/lib/wchar.h 2017-01-11 18:02:24.178321700 +0300 184 | +++ sed-4.3-good/lib/wchar.h 2017-01-11 17:47:46.241480600 +0300 185 | @@ -84,7 +84,7 @@ 186 | Some builds of uClibc lack it. */ 187 | /* The include_next requires a split double-inclusion guard. */ 188 | #if 1 189 | -# include "" 190 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\wchar.h" 191 | #endif 192 | 193 | #undef _GL_ALREADY_INCLUDING_WCHAR_H 194 | diff -Naur sed-4.3/lib/wctype.h sed-4.3-good/lib/wctype.h 195 | --- sed-4.3/lib/wctype.h 2017-01-11 18:02:24.228321800 +0300 196 | +++ sed-4.3-good/lib/wctype.h 2017-01-11 17:47:46.257080600 +0300 197 | @@ -68,7 +68,7 @@ 198 | BeOS 5 has the functions but no . */ 199 | /* The include_next requires a split double-inclusion guard. */ 200 | #if 1 201 | -# include "" 202 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt\wctype.h" 203 | #endif 204 | 205 | #ifndef _GL_WCTYPE_H 206 | -------------------------------------------------------------------------------- /archive/sed-4.8-win-headers.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.8-orig/lib/ctype.h sed-4.8/lib/ctype.h 2 | --- sed-4.8-orig/lib/ctype.h 2020-01-28 16:42:25.950994000 +0300 3 | +++ sed-4.8/lib/ctype.h 2020-01-28 16:43:15.086804400 +0300 4 | @@ -32,7 +32,7 @@ 5 | 6 | /* Include the original . */ 7 | /* The include_next requires a split double-inclusion guard. */ 8 | -#include "" 9 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\ctype.h" 10 | 11 | #ifndef _GL_CTYPE_H 12 | #define _GL_CTYPE_H 13 | diff -Naur sed-4.8-orig/lib/errno.h sed-4.8/lib/errno.h 14 | --- sed-4.8-orig/lib/errno.h 2020-01-28 16:42:26.130004300 +0300 15 | +++ sed-4.8/lib/errno.h 2020-01-28 16:43:15.088804500 +0300 16 | @@ -24,7 +24,7 @@ 17 | 18 | 19 | /* The include_next requires a split double-inclusion guard. */ 20 | -#include "" 21 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\errno.h" 22 | 23 | #ifndef _GL_ERRNO_H 24 | #define _GL_ERRNO_H 25 | diff -Naur sed-4.8-orig/lib/fcntl.h sed-4.8/lib/fcntl.h 26 | --- sed-4.8-orig/lib/fcntl.h 2020-01-28 16:42:26.369017900 +0300 27 | +++ sed-4.8/lib/fcntl.h 2020-01-28 16:43:15.090804700 +0300 28 | @@ -64,7 +64,7 @@ 29 | # include 30 | #endif 31 | /* The include_next requires a split double-inclusion guard. */ 32 | -#include "" 33 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\fcntl.h" 34 | 35 | /* Native Windows platforms declare open(), creat() in . */ 36 | #if (0 || IN_SED_GNULIB_TESTS || defined GNULIB_POSIXCHECK) \ 37 | diff -Naur sed-4.8-orig/lib/limits.h sed-4.8/lib/limits.h 38 | --- sed-4.8-orig/lib/limits.h 2020-01-28 16:42:27.229067100 +0300 39 | +++ sed-4.8/lib/limits.h 2020-01-28 16:43:15.093804800 +0300 40 | @@ -24,7 +24,7 @@ 41 | 42 | 43 | /* The include_next requires a split double-inclusion guard. */ 44 | -#include "" 45 | +#include "D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\limits.h" 46 | 47 | #ifndef _GL_LIMITS_H 48 | #define _GL_LIMITS_H 49 | diff -Naur sed-4.8-orig/lib/locale.h sed-4.8/lib/locale.h 50 | --- sed-4.8-orig/lib/locale.h 2020-01-28 16:42:27.478081400 +0300 51 | +++ sed-4.8/lib/locale.h 2020-01-28 16:43:15.095804900 +0300 52 | @@ -38,7 +38,7 @@ 53 | #define _GL_ALREADY_INCLUDING_LOCALE_H 54 | 55 | /* The include_next requires a split double-inclusion guard. */ 56 | -#include "" 57 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\locale.h" 58 | 59 | #undef _GL_ALREADY_INCLUDING_LOCALE_H 60 | 61 | diff -Naur sed-4.8-orig/lib/stddef.h sed-4.8/lib/stddef.h 62 | --- sed-4.8-orig/lib/stddef.h 2020-01-28 16:42:28.081115900 +0300 63 | +++ sed-4.8/lib/stddef.h 2020-01-28 16:43:15.098805100 +0300 64 | @@ -52,7 +52,7 @@ 65 | 66 | /* The include_next requires a split double-inclusion guard. */ 67 | 68 | -# include "" 69 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\stddef.h" 70 | 71 | /* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ 72 | # if (0 \ 73 | diff -Naur sed-4.8-orig/lib/stdint.h sed-4.8/lib/stdint.h 74 | --- sed-4.8-orig/lib/stdint.h 2020-01-28 16:42:28.376132700 +0300 75 | +++ sed-4.8/lib/stdint.h 2020-01-28 16:43:15.100805200 +0300 76 | @@ -74,7 +74,7 @@ 77 | in would reinclude us, skipping our contents because 78 | _GL_STDINT_H is defined. 79 | The include_next requires a split double-inclusion guard. */ 80 | -# include "" 81 | +# include "D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\stdint.h" 82 | #endif 83 | 84 | #if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H 85 | diff -Naur sed-4.8-orig/lib/stdio.h sed-4.8/lib/stdio.h 86 | --- sed-4.8-orig/lib/stdio.h 2020-01-28 16:42:29.153177200 +0300 87 | +++ sed-4.8/lib/stdio.h 2020-01-28 16:43:15.102805300 +0300 88 | @@ -40,7 +40,7 @@ 89 | #define _GL_ALREADY_INCLUDING_STDIO_H 90 | 91 | /* The include_next requires a split double-inclusion guard. */ 92 | -#include "" 93 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\stdio.h" 94 | 95 | #undef _GL_ALREADY_INCLUDING_STDIO_H 96 | 97 | diff -Naur sed-4.8-orig/lib/stdlib.h sed-4.8/lib/stdlib.h 98 | --- sed-4.8-orig/lib/stdlib.h 2020-01-28 16:42:29.856217400 +0300 99 | +++ sed-4.8/lib/stdlib.h 2020-01-28 16:43:15.104805500 +0300 100 | @@ -25,7 +25,7 @@ 101 | /* Special invocation conventions inside some gnulib header files, 102 | and inside some glibc header files, respectively. */ 103 | 104 | -#include "" 105 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\stdlib.h" 106 | 107 | #else 108 | /* Normal invocation convention. */ 109 | @@ -33,7 +33,7 @@ 110 | #ifndef _GL_STDLIB_H 111 | 112 | /* The include_next requires a split double-inclusion guard. */ 113 | -#include "" 114 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\stdlib.h" 115 | 116 | #ifndef _GL_STDLIB_H 117 | #define _GL_STDLIB_H 118 | diff -Naur sed-4.8-orig/lib/string.h sed-4.8/lib/string.h 119 | --- sed-4.8-orig/lib/string.h 2020-01-28 16:42:30.468252400 +0300 120 | +++ sed-4.8/lib/string.h 2020-01-28 16:43:15.106805600 +0300 121 | @@ -38,7 +38,7 @@ 122 | #define _GL_ALREADY_INCLUDING_STRING_H 123 | 124 | /* The include_next requires a split double-inclusion guard. */ 125 | -#include "" 126 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\string.h" 127 | 128 | #undef _GL_ALREADY_INCLUDING_STRING_H 129 | 130 | diff -Naur sed-4.8-orig/lib/sys/stat.h sed-4.8/lib/sys/stat.h 131 | --- sed-4.8-orig/lib/sys/stat.h 2020-01-28 16:42:30.850274200 +0300 132 | +++ sed-4.8/lib/sys/stat.h 2020-01-28 16:43:15.108805700 +0300 133 | @@ -29,7 +29,7 @@ 134 | #if defined __need_system_sys_stat_h 135 | /* Special invocation convention. */ 136 | 137 | -#include "" 138 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\sys\stat.h" 139 | 140 | #else 141 | /* Normal invocation convention. */ 142 | @@ -44,7 +44,7 @@ 143 | #include 144 | 145 | /* The include_next requires a split double-inclusion guard. */ 146 | -#include "" 147 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\sys\stat.h" 148 | 149 | #ifndef _GL_SYS_STAT_H 150 | #define _GL_SYS_STAT_H 151 | diff -Naur sed-4.8-orig/lib/sys/types.h sed-4.8/lib/sys/types.h 152 | --- sed-4.8-orig/lib/sys/types.h 2020-01-28 16:42:31.265298000 +0300 153 | +++ sed-4.8/lib/sys/types.h 2020-01-28 16:43:15.109805700 +0300 154 | @@ -36,7 +36,7 @@ 155 | 156 | /* The include_next requires a split double-inclusion guard. */ 157 | # define _GL_INCLUDING_SYS_TYPES_H 158 | -#include "" 159 | +#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\sys\types.h" 160 | # undef _GL_INCLUDING_SYS_TYPES_H 161 | 162 | #ifndef _GL_SYS_TYPES_H 163 | diff -Naur sed-4.8-orig/lib/time.h sed-4.8/lib/time.h 164 | --- sed-4.8-orig/lib/time.h 2020-01-28 16:42:31.591316600 +0300 165 | +++ sed-4.8/lib/time.h 2020-01-28 16:45:34.378771500 +0300 166 | @@ -32,7 +32,7 @@ 167 | && !defined __MINGW32__) \ 168 | || defined _GL_TIME_H) 169 | 170 | -# include "" 171 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\time.h" 172 | 173 | #else 174 | 175 | @@ -44,7 +44,7 @@ 176 | # include 177 | # endif 178 | 179 | -# include "" 180 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\time.h" 181 | 182 | /* NetBSD 5.0 mis-defines NULL. */ 183 | # include 184 | diff -Naur sed-4.8-orig/lib/wchar.h sed-4.8/lib/wchar.h 185 | --- sed-4.8-orig/lib/wchar.h 2020-01-28 16:42:33.349417200 +0300 186 | +++ sed-4.8/lib/wchar.h 2020-01-28 16:43:15.114806000 +0300 187 | @@ -85,7 +85,7 @@ 188 | Some builds of uClibc lack it. */ 189 | /* The include_next requires a split double-inclusion guard. */ 190 | #if 1 191 | -# include "" 192 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\wchar.h" 193 | #endif 194 | 195 | #undef _GL_ALREADY_INCLUDING_WCHAR_H 196 | diff -Naur sed-4.8-orig/lib/wctype.h sed-4.8/lib/wctype.h 197 | --- sed-4.8-orig/lib/wctype.h 2020-01-28 16:42:33.607431900 +0300 198 | +++ sed-4.8/lib/wctype.h 2020-01-28 16:43:15.116806100 +0300 199 | @@ -70,7 +70,7 @@ 200 | BeOS 5 has the functions but no . */ 201 | /* The include_next requires a split double-inclusion guard. */ 202 | #if 1 203 | -# include "" 204 | +# include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\wctype.h" 205 | #endif 206 | 207 | #ifndef _GL_WCTYPE_H 208 | -------------------------------------------------------------------------------- /archive/sed-4.8-build-patch-howto.txt: -------------------------------------------------------------------------------- 1 | Instructions how to build native sed.exe with Microsoft Visual Studio from CYGWIN shell. 2 | 3 | While building, it is possible to save build log and create a patch - for compiling sed.exe using only Microsoft Visual Studio tools, without need for CYGWIN. 4 | 5 | This is how sed-4.8-build-VS19-x64.patch was created. 6 | 7 | (sed-4.8-build-VS9-x86.patch was created analogously in Microsoft Visual Studio 2008 environment) 8 | 9 | 10 | From CYGWIN shell: 11 | 12 | 1) get archive: 13 | wget https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz 14 | 15 | 2) unpack archive: 16 | tar xf sed-4.8.tar.xz 17 | 18 | 3) go to sed sources: 19 | cd sed-4.8 20 | 21 | 4) patch the sources: 22 | patch -Np1 -i sed-4.8-src.patch 23 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.8-src.patch) 24 | 25 | 5) to build with old non-c99 compiler (such as Microsoft Visual Studio 2008) apply one more patch: 26 | patch -Np1 -i sed-4.8-src-non-c99.patch 27 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.8-src-non-c99.patch) 28 | 29 | 6) now start dos prompt: 30 | cmd.exe /c "start cmd.exe" 31 | 32 | 7) setup compiler: 33 | "D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 34 | (if Microsoft Visual Studio 2019 is installed in "D:\Program Files (x86)") 35 | 36 | --tip: for Visual Studio 2008: 37 | "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 38 | 39 | 8) run bash from the dos prompt (with environment prepared for compiling with Microsoft Visual Studio): 40 | bash 41 | 42 | 9) check that Gnu Make is installed in CYGWIN and it is working: 43 | make --version 44 | 45 | 10) configure sed: 46 | CFLAGS= CC=cl CPP="cl -E" LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules --disable-nls gl_cv_sys_struct_lconv_ok=yes 47 | 48 | 11) configure script is not fully functional to create correct Makefile - it needs to be fixed manually: 49 | sed -i '/^SUBDIRS/s/=.*/= ./' Makefile 50 | sed -i '/^NEXT/s/=.*/=""/' Makefile 51 | sed -i '/lib_libsed_a_AR/s/ lib/lib/' Makefile 52 | sed -i '/sed_libver_a_AR/s/ sed/sed/' Makefile 53 | sed -i 's@^AR = .*@AR = lib /nologo@' Makefile 54 | sed -i 's/-c -o /-c -nologo -Fo/' Makefile 55 | sed -i '/$(RANLIB)/d' Makefile 56 | 57 | 12) fix sed target in Makefile, add support for wildcards in program arguments: 58 | echo 'sed_sed_LINK = link /nologo /DEFAULTLIB:LIBCPMT.lib /OUT:$@ wsetargv.obj' >> Makefile 59 | 60 | 13) add gen target: 61 | echo 'gen: $(BUILT_SOURCES)' >> Makefile 62 | 63 | 14) execute Makefile to generate sed headers: 64 | make gen 65 | 66 | 15) some references to system header files are missing in generated headers - they need to be fixed manually. 67 | 68 | a) set paths to locations of Visual Studio 2019 and WDK10 in sed-4.8-win-headers.patch (assume it was copied to current directory): 69 | for example, if Visual Studio 2019 is installed in "D:\Program Files (x86)" and WDK10 installed in "C:\Program Files (x86)" 70 | 71 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\include@' ./sed-4.8-win-headers.patch 72 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt@' ./sed-4.8-win-headers.patch 73 | 74 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.8-win-headers.patch) 75 | 76 | --tip: for Visual Studio 2008: 77 | sed -i '/Visual Studio/s@.:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' ./sed-4.8-win-headers.patch 78 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' ./sed-4.8-win-headers.patch 79 | 80 | b) now patch generated headers with updated patch-file: 81 | patch -Np1 -i sed-4.8-win-headers.patch 82 | 83 | 16) do compile sed: 84 | make > make.bat 85 | 86 | 17) check build result: 87 | ./sed/sed.exe --version --locale=C 88 | 89 | (should print sed version, e.g.: (GNU sed) 4.8) 90 | 91 | compilation should be ok, native (unoptimized) ./sed/sed.exe should be created. 92 | 93 | 94 | Now it is possible to create a patch file - for compiling optimized sed.exe using only Microsoft Visual Studio tools, without need for CYGWIN. 95 | 96 | 1) create a directory for unpatched sed: 97 | mkdir ../orig 98 | 99 | 2) unpack sed: 100 | tar xf ../sed-4.8.tar.xz -C ../orig/ 101 | 102 | 3) diff current directory with original just unpacked sed-4.8.tar.xz in '../orig' directory 103 | diff -rql . ../orig/sed-4.8 104 | 105 | 4) remove unneeded built files in current directory (object files, libs, etc...) 106 | 107 | rm -rf \ 108 | ./Makefile \ 109 | ./stamp-h1 \ 110 | ./sed-4.8-win-headers.patch \ 111 | ./lib/*.obj \ 112 | ./lib/.dirstamp \ 113 | ./lib/.deps \ 114 | ./lib/glthread/*.obj \ 115 | ./lib/glthread/.dirstamp \ 116 | ./lib/glthread/.deps \ 117 | ./lib/libsed.a \ 118 | ./sed/*.obj \ 119 | ./sed/.dirstamp \ 120 | ./sed/.deps \ 121 | ./sed/sed.exe \ 122 | ./sed/libver.a \ 123 | ./po/Makefile \ 124 | ./po/Makefile.in \ 125 | ./po/POTFILES \ 126 | ./config.log \ 127 | ./config.status \ 128 | ./gnulib-tests/Makefile \ 129 | ./sed/sed.exp \ 130 | ./sed/sed.lib 131 | 132 | 5) after this, diff should show something like: 133 | 134 | diff -rql . ../orig/sed-4.8 135 | Only in .: config.h 136 | Only in ./lib: alloca.h 137 | Only in ./lib: ctype.h 138 | * Files ./lib/dfa.c and ../orig/sed-4.8/lib/dfa.c differ 139 | Only in ./lib: errno.h 140 | Only in ./lib: fcntl.h 141 | Only in ./lib: getopt.h 142 | Only in ./lib: getopt-cdefs.h 143 | * Files ./lib/gettimeofday.c and ../orig/sed-4.8/lib/gettimeofday.c differ 144 | Only in ./lib: inttypes.h 145 | Only in ./lib: langinfo.h 146 | Only in ./lib: limits.h 147 | Files ./lib/localcharset.c and ../orig/sed-4.8/lib/localcharset.c differ 148 | Only in ./lib: locale.h 149 | * Files ./lib/localeinfo.c and ../orig/sed-4.8/lib/localeinfo.c differ 150 | Files ./lib/mbtowc-lock.h and ../orig/sed-4.8/lib/mbtowc-lock.h differ 151 | Files ./lib/nl_langinfo.c and ../orig/sed-4.8/lib/nl_langinfo.c differ 152 | * Files ./lib/regcomp.c and ../orig/sed-4.8/lib/regcomp.c differ 153 | * Files ./lib/regexec.c and ../orig/sed-4.8/lib/regexec.c differ 154 | Only in ./lib: selinux 155 | Only in ./lib: stdalign.h 156 | ? Only in ./lib: stdbool.h 157 | Only in ./lib: stddef.h 158 | Only in ./lib: stdint.h 159 | Only in ./lib: stdio.h 160 | Only in ./lib: stdlib.h 161 | Only in ./lib: string.h 162 | * Files ./lib/strverscmp.c and ../orig/sed-4.8/lib/strverscmp.c differ 163 | Only in ./lib: sys 164 | Only in ./lib: time.h 165 | Only in ./lib: unistd.h 166 | Only in ./lib: wchar.h 167 | Only in ./lib: wctype.h 168 | Only in .: make.bat 169 | * Files ./sed/debug.c and ../orig/sed-4.8/sed/debug.c differ 170 | Files ./sed/execute.c and ../orig/sed-4.8/sed/execute.c differ 171 | * Files ./sed/regexp.c and ../orig/sed-4.8/sed/regexp.c differ 172 | Files ./sed/sed.c and ../orig/sed-4.8/sed/sed.c differ 173 | Files ./sed/utils.c and ../orig/sed-4.8/sed/utils.c differ 174 | Only in ./sed: version.c 175 | Only in ./sed: version.h 176 | 177 | * -- if sed-4.8-src-non-c99.patch was applied: 178 | ? -- if configured under Visual Studio 2008 179 | 180 | 6) edit make.bat 181 | 182 | cp make.bat make.bat.old 183 | sed -i -n '/^cl /p;/^lib /p;/^link /p' make.bat 184 | sed -i 's@-DLOCALEDIR=."/usr/local/share/locale.".*-c -nologo -F@/DLOCALEDIR="" /c /nologo /DGNULIB_WCHAR_SINGLE /F@' make.bat 185 | sed -i 's@ -c -nologo -F@/c /nologo /DGNULIB_WCHAR_SINGLE /F@' make.bat 186 | sed -i 's@lib/glthread/@lib\\glthread\\@g' make.bat 187 | sed -i 's@/Fosed/@/Fosed\\@;s@/Folib/@/Folib\\@' make.bat 188 | sed -i 's@`if test -f .@@;s@.; then.*@@' make.bat 189 | sed -i 's@`cygpath -w .@@;s@.`@@' make.bat 190 | sed -i 's@ lib/@ lib\\@g;s@ sed/@ sed\\@g' make.bat 191 | sed -i 's@-DHAVE_CONFIG_H -I. -I. -I./lib -I./lib -I./sed@/Ox /GF /Gy /GS- /GL /EHsc /DHAVE_CONFIG_H /I. /I.\\lib /I.\\sed@' make.bat 192 | sed -i 's@lib /nologo@lib /LTCG /nologo@' make.bat 193 | sed -i 's@/OUT:lib/@/OUT:lib\\@;s@/OUT:sed/@/OUT:sed\\@' make.bat 194 | sed -i 's@link /nologo@& /LTCG@' make.bat 195 | sed -i 's@$@ || exit /b@' make.bat 196 | rm make.bat.old 197 | 198 | 7) finally, create a patch: 199 | diff -Naur ../orig/sed-4.8 . > ../sed-4.8-build-VS19-x64.patch 200 | 201 | or, for Visual Studio 2008: 202 | diff -Naur ../orig/sed-4.8 . > ../sed-4.8-build-VS9-x86.patch 203 | -------------------------------------------------------------------------------- /archive/sed-4.7-build-patch-howto.txt: -------------------------------------------------------------------------------- 1 | Instructions how to build native sed.exe with Microsoft Visual Studio from CYGWIN shell. 2 | 3 | While building, it is possible to save build log and create a patch - for compiling sed.exe using only Microsoft Visual Studio tools, without need for CYGWIN. 4 | 5 | This is how sed-4.7-build-VS19-x64.patch was created. 6 | 7 | (sed-4.7-build-VS9-x86.patch was created analogously in Microsoft Visual Studio 2008 environment) 8 | 9 | 10 | From CYGWIN shell: 11 | 12 | 1) get archive: 13 | wget https://ftp.gnu.org/gnu/sed/sed-4.7.tar.xz 14 | 15 | 2) unpack archive: 16 | tar xf sed-4.7.tar.xz 17 | 18 | 3) go to sed sources: 19 | cd sed-4.7 20 | 21 | 4) patch the sources: 22 | patch -Np1 -i sed-4.7-src.patch 23 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.7-src.patch) 24 | 25 | 5) to build with old non-c99 compiler (such as Microsoft Visual Studio 2008) apply one more patch: 26 | patch -Np1 -i sed-4.7-src-non-c99.patch 27 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.7-src-non-c99.patch) 28 | 29 | Note: ignore warnings: 30 | for the sed/execute.c: 31 | Hunk #1 succeeded at 1025 (offset -4 lines). 32 | Hunk #2 succeeded at 1209 (offset -4 lines). 33 | Hunk #3 succeeded at 1228 (offset -4 lines). 34 | for the sed/utils.c: 35 | Hunk #1 succeeded at 181 (offset 6 lines). 36 | Hunk #2 succeeded at 202 (offset 6 lines). 37 | 38 | 6) now start dos prompt: 39 | cmd.exe /c "start cmd.exe" 40 | 41 | 7) setup compiler: 42 | "D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 43 | (if Microsoft Visual Studio 2019 is installed in "D:\Program Files (x86)") 44 | 45 | --tip: for Visual Studio 2008: 46 | "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 47 | 48 | 8) run bash from the dos prompt (with environment prepared for compiling with Microsoft Visual Studio): 49 | bash 50 | 51 | 9) check that Gnu Make is installed in CYGWIN and it is working: 52 | make --version 53 | 54 | 10) configure sed: 55 | CFLAGS= CC=cl CPP="cl -E" LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules --disable-nls 56 | 57 | 11) configure script is not fully functional to create correct Makefile - it needs to be fixed manually: 58 | sed -i '/^SUBDIRS/s/=.*/= ./' Makefile 59 | sed -i '/^NEXT/s/=.*/=""/' Makefile 60 | sed -i '/lib_libsed_a_AR/s/ lib/lib/' Makefile 61 | sed -i '/sed_libver_a_AR/s/ sed/sed/' Makefile 62 | sed -i 's@^AR = .*@AR = lib /nologo@' Makefile 63 | sed -i 's/-c -o /-c -nologo -Fo/' Makefile 64 | sed -i '/$(RANLIB)/d' Makefile 65 | 66 | 12) fix sed target in Makefile, add support for wildcards in program arguments: 67 | echo 'sed_sed_LINK = link /nologo /DEFAULTLIB:LIBCPMT.lib /OUT:$@ wsetargv.obj' >> Makefile 68 | 69 | 13) add gen target: 70 | echo 'gen: $(BUILT_SOURCES)' >> Makefile 71 | 72 | 14) execute Makefile to generate sed headers: 73 | make gen 74 | 75 | 15) some references to system header files are missing in generated headers - they need to be fixed manually. 76 | 77 | a) set paths to locations of Visual Studio 2019 and WDK10 in sed-4.3-win-headers.patch (assume it was copied to current directory): 78 | for example, if Visual Studio 2019 is installed in "D:\Program Files (x86)" and WDK10 installed in "C:\Program Files (x86)" 79 | 80 | sed -i '/Visual Studio/s@.:.*include@D:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.23.28105\\include@' ./sed-4.3-win-headers.patch 81 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt@' ./sed-4.3-win-headers.patch 82 | 83 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.3-win-headers.patch) 84 | 85 | --tip: for Visual Studio 2008: 86 | sed -i '/Visual Studio/s@.:.*include@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' ./sed-4.3-win-headers.patch 87 | sed -i '/Windows Kits/s@.:.*ucrt@C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\include@' ./sed-4.3-win-headers.patch 88 | 89 | b) now patch generated headers with updated patch-file: 90 | patch -Np1 -i sed-4.3-win-headers.patch 91 | 92 | Note: ignore warnings: 93 | lib/locale.h may be patched with a message: "Hunk #1 succeeded at 38 (offset 3 lines)." 94 | lib/sys/types.h may be patched with a message: "Hunk #1 succeeded at 36 (offset 11 lines)." 95 | lib/wctype.h may be patched with a message: "Hunk #1 succeeded at 70 (offset 2 lines)." 96 | 97 | 16) do compile sed: 98 | make > make.bat 99 | 100 | 17) check build result: 101 | ./sed/sed.exe --version 102 | 103 | (should print sed version, e.g.: (GNU sed) 4.7) 104 | 105 | compilation should be ok, native (unoptimized) ./sed/sed.exe should be created. 106 | 107 | 108 | Now it is possible to create a patch file - for compiling optimized sed.exe using only Microsoft Visual Studio tools, without need for CYGWIN. 109 | 110 | 1) create a directory for unpatched sed: 111 | mkdir ../orig 112 | 113 | 2) unpack sed: 114 | tar xf ../sed-4.7.tar.xz -C ../orig/ 115 | 116 | 3) diff current directory with original just unpacked sed-4.7.tar.xz in '../orig' directory 117 | diff -rql . ../orig/sed-4.7 118 | 119 | 4) remove unneeded built files in current directory (object files, libs, etc...) 120 | 121 | rm -fr \ 122 | ./Makefile \ 123 | ./stamp-h1 \ 124 | ./sed-4.3-win-headers.patch \ 125 | ./lib/*.obj \ 126 | ./lib/.dirstamp \ 127 | ./lib/.deps \ 128 | ./lib/glthread/*.obj \ 129 | ./lib/glthread/.dirstamp \ 130 | ./lib/glthread/.deps \ 131 | ./lib/libsed.a \ 132 | ./sed/*.obj \ 133 | ./sed/*.c.orig \ 134 | ./sed/.dirstamp \ 135 | ./sed/.deps \ 136 | ./sed/sed.exe \ 137 | ./sed/libver.a \ 138 | ./po/Makefile \ 139 | ./po/Makefile.in \ 140 | ./po/POTFILES \ 141 | ./config.log \ 142 | ./config.status \ 143 | ./gnulib-tests/Makefile \ 144 | ./lib/*.h.orig \ 145 | ./lib/sys/*.h.orig 146 | 147 | 5) after this, diff should show something like: 148 | 149 | diff -rql . ../orig/sed-4.7 150 | Only in .: config.h 151 | Only in ./lib: alloca.h 152 | Only in ./lib: ctype.h 153 | Only in ./lib: errno.h 154 | Only in ./lib: fcntl.h 155 | Only in ./lib: getopt.h 156 | Only in ./lib: getopt-cdefs.h 157 | Only in ./lib: langinfo.h 158 | Only in ./lib: limits.h 159 | Files ./lib/localcharset.c and ../orig/sed-4.7/lib/localcharset.c differ 160 | Only in ./lib: locale.h 161 | Files ./lib/nl_langinfo.c and ../orig/sed-4.7/lib/nl_langinfo.c differ 162 | Only in ./lib: selinux 163 | Only in ./lib: stdalign.h 164 | Only in ./lib: stddef.h 165 | Only in ./lib: stdint.h 166 | Only in ./lib: stdio.h 167 | Only in ./lib: stdlib.h 168 | Only in ./lib: string.h 169 | Only in ./lib: sys 170 | Only in ./lib: time.h 171 | Only in ./lib: unistd.h 172 | Only in ./lib: wchar.h 173 | Only in ./lib: wctype.h 174 | Only in .: make.bat 175 | Files ./sed/execute.c and ../orig/sed-4.7/sed/execute.c differ 176 | Files ./sed/sed.c and ../orig/sed-4.7/sed/sed.c differ 177 | Files ./sed/utils.c and ../orig/sed-4.7/sed/utils.c differ 178 | Only in ./sed: version.c 179 | Only in ./sed: version.h 180 | 181 | If patch sed-4.7-src-non-c99.patch was applied, diff will show additional differences: 182 | 183 | Files ./lib/dfa.c and ../orig/sed-4.7/lib/dfa.c differ 184 | Files ./lib/gettimeofday.c and ../orig/sed-4.7/lib/gettimeofday.c differ 185 | Files ./lib/regexec.c and ../orig/sed-4.7/lib/regexec.c differ 186 | Files ./sed/debug.c and ../orig/sed-4.7/sed/debug.c differ 187 | Files ./sed/regexp.c and ../orig/sed-4.7/sed/regexp.c differ 188 | 189 | 6) edit make.bat 190 | 191 | cp make.bat make.bat.old 192 | sed -i -n '/^cl /p;/^lib /p;/^link /p' make.bat 193 | sed -i 's@-DLOCALEDIR=."/usr/local/share/locale.".*-c -nologo -F@/DLOCALEDIR="" /c /nologo /DGNULIB_WCHAR_SINGLE /F@' make.bat 194 | sed -i 's@ -c -nologo -F@/c /nologo /DGNULIB_WCHAR_SINGLE /F@' make.bat 195 | sed -i 's@lib/glthread/@lib\\glthread\\@g' make.bat 196 | sed -i 's@/Fosed/@/Fosed\\@;s@/Folib/@/Folib\\@' make.bat 197 | sed -i 's@`if test -f .@@;s@.; then.*@@' make.bat 198 | sed -i 's@`cygpath -w .@@;s@.`@@' make.bat 199 | sed -i 's@ lib/@ lib\\@g;s@ sed/@ sed\\@g' make.bat 200 | sed -i 's@-DHAVE_CONFIG_H -I. -I. -I./lib -I./lib -I./sed@/Ox /GF /Gy /GS- /GL /EHsc /DHAVE_CONFIG_H /I. /I.\\lib /I.\\sed@' make.bat 201 | sed -i 's@lib /nologo@lib /LTCG /nologo@' make.bat 202 | sed -i 's@/OUT:lib/@/OUT:lib\\@;s@/OUT:sed/@/OUT:sed\\@' make.bat 203 | sed -i 's@link /nologo@& /LTCG@' make.bat 204 | sed -i 's@$@ || exit /b@' make.bat 205 | rm make.bat.old 206 | 207 | 7) finally, create a patch: 208 | diff -Naur ../orig/sed-4.7 . > ../sed-4.7-build-VS19-x64.patch 209 | 210 | or, for Visual Studio 2008: 211 | diff -Naur ../orig/sed-4.7 . > ../sed-4.7-build-VS9-x86.patch 212 | -------------------------------------------------------------------------------- /archive/sed-4.3-src.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.3-orig/lib/dfa.c sed-4.3-patched/lib/dfa.c 2 | --- sed-4.3-orig/lib/dfa.c 2016-12-19 19:49:33.000000000 +0300 3 | +++ sed-4.3-patched/lib/dfa.c 2017-01-13 10:25:17.590125000 +0300 4 | @@ -769,13 +769,13 @@ 5 | Adjust the growth according to three constraints: NITEMS_INCR_MIN, 6 | NITEMS_MAX, and what the C language can represent safely. */ 7 | 8 | - ptrdiff_t n, nbytes; 9 | + ptrdiff_t n, nbytes, adjusted_nbytes; 10 | if (INT_ADD_WRAPV (n0, n0 >> 1, &n)) 11 | n = PTRDIFF_MAX; 12 | if (0 <= nitems_max && nitems_max < n) 13 | n = nitems_max; 14 | 15 | - ptrdiff_t adjusted_nbytes 16 | + adjusted_nbytes 17 | = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes) 18 | ? MIN (PTRDIFF_MAX, SIZE_MAX) 19 | : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0); 20 | @@ -2096,7 +2096,7 @@ 21 | static void 22 | merge (position_set const *s1, position_set const *s2, position_set *m) 23 | { 24 | - return merge_constrained (s1, s2, -1, m); 25 | + merge_constrained (s1, s2, -1, m); 26 | } 27 | 28 | /* Delete a position from a set. Return the nonzero constraint of the 29 | @@ -2232,8 +2232,9 @@ 30 | epsclosure (position_set *initial, struct dfa const *d) 31 | { 32 | position_set tmp; 33 | + size_t i, j; 34 | alloc_position_set (&tmp, d->nleaves); 35 | - for (size_t i = 0; i < d->tindex; ++i) 36 | + for (i = 0; i < d->tindex; ++i) 37 | if (d->follows[i].nelem > 0 && d->tokens[i] >= NOTCHAR 38 | && d->tokens[i] != BACKREF && d->tokens[i] != ANYCHAR 39 | && d->tokens[i] != MBCSET && d->tokens[i] < CSET) 40 | @@ -2266,7 +2267,7 @@ 41 | 42 | delete (i, &d->follows[i]); 43 | 44 | - for (size_t j = 0; j < d->tindex; j++) 45 | + for (j = 0; j < d->tindex; j++) 46 | if (i != j && d->follows[j].nelem > 0) 47 | replace (&d->follows[j], i, &d->follows[i], constraint, &tmp); 48 | 49 | @@ -2909,7 +2910,8 @@ 50 | rebuilt, whereas rarely-used ones are cleared away. */ 51 | if (MAX_TRCOUNT <= d->trcount) 52 | { 53 | - for (state_num i = d->min_trcount; i < d->tralloc; i++) 54 | + state_num i; 55 | + for (i = d->min_trcount; i < d->tralloc; i++) 56 | { 57 | free (d->trans[i]); 58 | free (d->fails[i]); 59 | @@ -2923,8 +2925,11 @@ 60 | 61 | /* Fill transition table with a default value which means that the 62 | transited state has not been calculated yet. */ 63 | - for (int i = 0; i < NOTCHAR; i++) 64 | - trans[i] = -2; 65 | + { 66 | + int i; 67 | + for (i = 0; i < NOTCHAR; i++) 68 | + trans[i] = -2; 69 | + } 70 | } 71 | 72 | /* Set up the success bits for this state. */ 73 | @@ -2941,11 +2946,14 @@ 74 | /* Now go through the new transition table, and make sure that the trans 75 | and fail arrays are allocated large enough to hold a pointer for the 76 | largest state mentioned in the table. */ 77 | - state_num maxstate = -1; 78 | - for (int i = 0; i < NOTCHAR; i++) 79 | - if (maxstate < trans[i]) 80 | - maxstate = trans[i]; 81 | - realloc_trans_if_necessary (d, maxstate); 82 | + { 83 | + state_num maxstate = -1; 84 | + int i; 85 | + for (i = 0; i < NOTCHAR; i++) 86 | + if (maxstate < trans[i]) 87 | + maxstate = trans[i]; 88 | + realloc_trans_if_necessary (d, maxstate); 89 | + } 90 | 91 | return s; 92 | } 93 | diff -Naur sed-4.3-orig/sed/execute.c sed-4.3-patched/sed/execute.c 94 | --- sed-4.3-orig/sed/execute.c 2016-12-13 01:59:59.000000000 +0300 95 | +++ sed-4.3-patched/sed/execute.c 2017-01-13 10:11:06.590125000 +0300 96 | @@ -28,6 +28,11 @@ 97 | #include 98 | #include 99 | #include 100 | +#if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 101 | + || defined MSDOS || defined __EMX__ 102 | +#include 103 | +#include 104 | +#endif 105 | #include 106 | #include 107 | #include "stat-macros.h" 108 | @@ -557,11 +562,13 @@ 109 | if (name[0] == '-' && name[1] == '\0' && !in_place_extension) 110 | { 111 | clearerr(stdin); /* clear any stale EOF indication */ 112 | + input->fp = stdin; 113 | #if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 114 | || defined MSDOS || defined __EMX__ 115 | - input->fp = ck_fdopen (fileno (stdin), "stdin", read_mode, false); 116 | -#else 117 | - input->fp = stdin; 118 | + if ('r' == read_mode[0] && 'b' == read_mode[1]) 119 | + setmode(fileno(input->fp), O_BINARY); 120 | + else 121 | + setmode(fileno(input->fp), O_TEXT); 122 | #endif 123 | } 124 | else 125 | @@ -648,6 +655,13 @@ 126 | if (input->fp && unbuffered) 127 | setvbuf (input->fp, NULL, _IONBF, 0); 128 | output_file.fp = stdout; 129 | +#if defined WIN32 || defined _WIN32 || defined __CYGWIN__ \ 130 | + || defined MSDOS || defined __EMX__ 131 | + if ('w' == write_mode[0] && 'b' == write_mode[1]) 132 | + setmode(fileno(output_file.fp), O_BINARY); 133 | + else 134 | + setmode(fileno(output_file.fp), O_TEXT); 135 | +#endif 136 | } 137 | } 138 | 139 | @@ -1240,6 +1240,7 @@ 140 | { 141 | if (strncmp(line.active + idx, trans[2*i], mbclen) == 0) 142 | { 143 | + size_t prev_idx = idx; 144 | bool move_remain_buffer = false; 145 | const char *tr = trans[2*i+1]; 146 | size_t trans_len = *tr == '\0' ? 1 : strlen (tr); 147 | @@ -1261,7 +1262,6 @@ 148 | /* We must truncate the line buffer. */ 149 | move_remain_buffer = true; 150 | } 151 | - size_t prev_idx = idx; 152 | if (move_remain_buffer) 153 | { 154 | /* Move the remaining with \0. */ 155 | diff -Naur sed-4.3-orig/sed/regexp.c sed-4.3-patched/sed/regexp.c 156 | --- sed-4.3-orig/sed/regexp.c 2016-12-20 14:30:02.000000000 +0300 157 | +++ sed-4.3-patched/sed/regexp.c 2017-01-13 10:11:16.012000000 +0300 158 | @@ -140,9 +140,11 @@ 159 | bad_prog(buf); 160 | } 161 | 162 | - int dfaopts = buffer_delimiter == '\n' ? 0 : DFA_EOL_NUL; 163 | - new_regex->dfa = dfaalloc (); 164 | - dfasyntax (new_regex->dfa, &localeinfo, syntax, dfaopts); 165 | + { 166 | + int dfaopts = buffer_delimiter == '\n' ? 0 : DFA_EOL_NUL; 167 | + new_regex->dfa = dfaalloc (); 168 | + dfasyntax (new_regex->dfa, &localeinfo, syntax, dfaopts); 169 | + } 170 | dfacomp (new_regex->re, new_regex->sz, new_regex->dfa, 1); 171 | 172 | /* The patterns which consist of only ^ or $ often appear in 173 | diff -Naur sed-4.3-orig/sed/sed.c sed-4.3-patched/sed/sed.c 174 | --- sed-4.3-orig/sed/sed.c 2016-11-27 20:15:52.000000000 +0300 175 | +++ sed-4.3-patched/sed/sed.c 2017-01-13 10:11:28.308875000 +0300 176 | @@ -60,9 +60,9 @@ 177 | /* How do we edit files in-place? (we don't if NULL) */ 178 | char *in_place_extension = NULL; 179 | 180 | -/* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ 181 | -char const *read_mode = "r"; 182 | -char const *write_mode = "w"; 183 | +/* The mode to use to read/write files, either "rt"/"wt" or "rb"/"wb". */ 184 | +char const *read_mode = "rt"; 185 | +char const *write_mode = "wt"; 186 | 187 | /* Do we need to be pedantically POSIX compliant? */ 188 | enum posixicity_types posixicity; 189 | @@ -104,7 +104,6 @@ 190 | G_file_to_unlink = NULL; 191 | } 192 | 193 | -static void usage (int); 194 | static void 195 | contact(int errmsg) 196 | { 197 | diff -Naur sed-4.3-orig/sed/utils.c sed-4.3-patched/sed/utils.c 198 | --- sed-4.3-orig/sed/utils.c 2016-12-11 22:37:01.000000000 +0300 199 | +++ sed-4.3-patched/sed/utils.c 2017-01-13 10:11:38.637000000 +0300 200 | @@ -22,6 +22,7 @@ 201 | #include 202 | #include 203 | #include 204 | +#include 205 | #include 206 | #include 207 | #include 208 | @@ -171,16 +171,20 @@ 209 | /* The ownership might change, so omit some permissions at first 210 | so unauthorized users cannot nip in before the file is ready. 211 | mkstemp forces O_BINARY on cygwin, so use mkostemp instead. */ 212 | - mode_t save_umask = umask (0700); 213 | - int fd = mkostemp (template, 0); 214 | - umask (save_umask); 215 | - if (fd == -1) 216 | - panic(_("couldn't open temporary file %s: %s"), template, strerror(errno)); 217 | + { 218 | + mode_t save_umask = umask (0700); 219 | + int fd = mkostemp (template, ('w' == mode[0] && 'b' == mode[1]) ? O_BINARY : O_TEXT); 220 | + umask (save_umask); 221 | + if (fd == -1) 222 | + panic(_("couldn't open temporary file %s: %s"), template, strerror(errno)); 223 | 224 | - *p_filename = template; 225 | - FILE *fp = fdopen (fd, mode); 226 | - register_open_file (fp, template); 227 | - return fp; 228 | + *p_filename = template; 229 | + { 230 | + FILE *fp = fdopen (fd, mode); 231 | + register_open_file (fp, template); 232 | + return fp; 233 | + } 234 | + } 235 | } 236 | 237 | /* Panic on failing fwrite */ 238 | -------------------------------------------------------------------------------- /sed-4.9-win-headers.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.9/lib/assert.h sed-4.9-patched/lib/assert.h 2 | --- sed-4.9/lib/assert.h 2022-11-26 16:04:02.099843400 +0300 3 | +++ sed-4.9-patched/lib/assert.h 2022-11-26 18:59:48.162730800 +0300 4 | @@ -23,7 +23,7 @@ 5 | #endif 6 | 7 | 8 | -#include "" 9 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\assert.h" 10 | 11 | /* The definition of static_assert is copied here. */ 12 | /* Compile-time assert-like macros. 13 | diff -Naur sed-4.9/lib/ctype.h sed-4.9-patched/lib/ctype.h 14 | --- sed-4.9/lib/ctype.h 2022-11-26 16:04:02.271711100 +0300 15 | +++ sed-4.9-patched/lib/ctype.h 2022-11-26 18:59:48.162730800 +0300 16 | @@ -32,7 +32,7 @@ 17 | 18 | /* Include the original . */ 19 | /* The include_next requires a split double-inclusion guard. */ 20 | -#include "" 21 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\ctype.h" 22 | 23 | #ifndef _GL_CTYPE_H 24 | #define _GL_CTYPE_H 25 | diff -Naur sed-4.9/lib/errno.h sed-4.9-patched/lib/errno.h 26 | --- sed-4.9/lib/errno.h 2022-11-26 16:04:02.427972500 +0300 27 | +++ sed-4.9-patched/lib/errno.h 2022-11-26 18:59:48.162730800 +0300 28 | @@ -24,7 +24,7 @@ 29 | 30 | 31 | /* The include_next requires a split double-inclusion guard. */ 32 | -#include "" 33 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\errno.h" 34 | 35 | #ifndef _GL_ERRNO_H 36 | #define _GL_ERRNO_H 37 | diff -Naur sed-4.9/lib/fcntl.h sed-4.9-patched/lib/fcntl.h 38 | --- sed-4.9/lib/fcntl.h 2022-11-26 16:04:02.584226700 +0300 39 | +++ sed-4.9-patched/lib/fcntl.h 2022-11-26 19:00:33.709244500 +0300 40 | @@ -38,7 +38,7 @@ 41 | #if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) 42 | # include 43 | #endif 44 | -#include "" 45 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\fcntl.h" 46 | 47 | /* Native Windows platforms declare open(), creat() in . */ 48 | #if (0 || 1 || defined GNULIB_POSIXCHECK) \ 49 | @@ -64,7 +64,7 @@ 50 | # include 51 | #endif 52 | /* The include_next requires a split double-inclusion guard. */ 53 | -#include "" 54 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\fcntl.h" 55 | 56 | /* Native Windows platforms declare open(), creat() in . */ 57 | #if (0 || 1 || defined GNULIB_POSIXCHECK) \ 58 | diff -Naur sed-4.9/lib/limits.h sed-4.9-patched/lib/limits.h 59 | --- sed-4.9/lib/limits.h 2022-11-26 16:04:03.521717900 +0300 60 | +++ sed-4.9-patched/lib/limits.h 2022-11-26 18:59:48.178388300 +0300 61 | @@ -38,7 +38,7 @@ 62 | # define _GL_ALREADY_INCLUDING_LIMITS_H 63 | 64 | /* The include_next requires a split double-inclusion guard. */ 65 | -# include "" 66 | +# include "X:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.34.31933\include\limits.h" 67 | 68 | # undef _GL_ALREADY_INCLUDING_LIMITS_H 69 | 70 | diff -Naur sed-4.9/lib/locale.h sed-4.9-patched/lib/locale.h 71 | --- sed-4.9/lib/locale.h 2022-11-26 16:04:03.693586000 +0300 72 | +++ sed-4.9-patched/lib/locale.h 2022-11-26 18:59:48.178388300 +0300 73 | @@ -38,7 +38,7 @@ 74 | #define _GL_ALREADY_INCLUDING_LOCALE_H 75 | 76 | /* The include_next requires a split double-inclusion guard. */ 77 | -#include "" 78 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\locale.h" 79 | 80 | #undef _GL_ALREADY_INCLUDING_LOCALE_H 81 | 82 | diff -Naur sed-4.9/lib/stddef.h sed-4.9-patched/lib/stddef.h 83 | --- sed-4.9/lib/stddef.h 2022-11-26 16:04:04.443587600 +0300 84 | +++ sed-4.9-patched/lib/stddef.h 2022-11-26 18:59:48.178388300 +0300 85 | @@ -76,7 +76,7 @@ 86 | 87 | /* The include_next requires a split double-inclusion guard. */ 88 | 89 | -# include "" 90 | +# include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\stddef.h" 91 | 92 | /* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ 93 | # if (0 \ 94 | diff -Naur sed-4.9/lib/stdint.h sed-4.9-patched/lib/stdint.h 95 | --- sed-4.9/lib/stdint.h 2022-11-26 16:04:04.631094700 +0300 96 | +++ sed-4.9-patched/lib/stdint.h 2022-11-26 18:59:48.178388300 +0300 97 | @@ -74,7 +74,7 @@ 98 | in would reinclude us, skipping our contents because 99 | _GL_STDINT_H is defined. 100 | The include_next requires a split double-inclusion guard. */ 101 | -# include "" 102 | +# include "X:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.34.31933\include\stdint.h" 103 | #endif 104 | 105 | #if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H 106 | diff -Naur sed-4.9/lib/stdio.h sed-4.9-patched/lib/stdio.h 107 | --- sed-4.9/lib/stdio.h 2022-11-26 16:04:04.865496000 +0300 108 | +++ sed-4.9-patched/lib/stdio.h 2022-11-26 18:59:48.193914000 +0300 109 | @@ -40,7 +40,7 @@ 110 | #define _GL_ALREADY_INCLUDING_STDIO_H 111 | 112 | /* The include_next requires a split double-inclusion guard. */ 113 | -#include "" 114 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\stdio.h" 115 | 116 | #undef _GL_ALREADY_INCLUDING_STDIO_H 117 | 118 | diff -Naur sed-4.9/lib/stdlib.h sed-4.9-patched/lib/stdlib.h 119 | --- sed-4.9/lib/stdlib.h 2022-11-26 16:04:05.131096900 +0300 120 | +++ sed-4.9-patched/lib/stdlib.h 2022-11-26 18:59:48.193914000 +0300 121 | @@ -25,7 +25,7 @@ 122 | /* Special invocation conventions inside some gnulib header files, 123 | and inside some glibc header files, respectively. */ 124 | 125 | -#include "" 126 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\stdlib.h" 127 | 128 | #else 129 | /* Normal invocation convention. */ 130 | @@ -33,7 +33,7 @@ 131 | #ifndef _GL_STDLIB_H 132 | 133 | /* The include_next requires a split double-inclusion guard. */ 134 | -#include "" 135 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\stdlib.h" 136 | 137 | #ifndef _GL_STDLIB_H 138 | #define _GL_STDLIB_H 139 | diff -Naur sed-4.9/lib/string.h sed-4.9-patched/lib/string.h 140 | --- sed-4.9/lib/string.h 2022-11-26 16:04:05.334212700 +0300 141 | +++ sed-4.9-patched/lib/string.h 2022-11-26 18:59:48.193914000 +0300 142 | @@ -38,7 +38,7 @@ 143 | #define _GL_ALREADY_INCLUDING_STRING_H 144 | 145 | /* The include_next requires a split double-inclusion guard. */ 146 | -#include "" 147 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\string.h" 148 | 149 | #undef _GL_ALREADY_INCLUDING_STRING_H 150 | 151 | diff -Naur sed-4.9/lib/sys/stat.h sed-4.9-patched/lib/sys/stat.h 152 | --- sed-4.9/lib/sys/stat.h 2022-11-26 16:04:05.677960300 +0300 153 | +++ sed-4.9-patched/lib/sys/stat.h 2022-11-26 18:59:48.193914000 +0300 154 | @@ -44,7 +44,7 @@ 155 | #include 156 | 157 | /* The include_next requires a split double-inclusion guard. */ 158 | -#include "" 159 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\sys\stat.h" 160 | 161 | #ifndef _GL_SYS_STAT_H 162 | #define _GL_SYS_STAT_H 163 | diff -Naur sed-4.9/lib/sys/types.h sed-4.9-patched/lib/sys/types.h 164 | --- sed-4.9/lib/sys/types.h 2022-11-26 16:04:05.818593000 +0300 165 | +++ sed-4.9-patched/lib/sys/types.h 2022-11-26 18:59:48.209592900 +0300 166 | @@ -36,7 +36,7 @@ 167 | 168 | /* The include_next requires a split double-inclusion guard. */ 169 | # define _GL_INCLUDING_SYS_TYPES_H 170 | -#include "" 171 | +#include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\sys\types.h" 172 | # undef _GL_INCLUDING_SYS_TYPES_H 173 | 174 | #ifndef _GL_SYS_TYPES_H 175 | diff -Naur sed-4.9/lib/time.h sed-4.9-patched/lib/time.h 176 | --- sed-4.9/lib/time.h 2022-11-26 16:04:06.178421100 +0300 177 | +++ sed-4.9-patched/lib/time.h 2022-11-26 18:59:48.209592900 +0300 178 | @@ -32,7 +32,7 @@ 179 | && !defined __MINGW32__) \ 180 | || defined _GL_TIME_H) 181 | 182 | -# include "" 183 | +# include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\time.h" 184 | 185 | #else 186 | 187 | @@ -44,7 +44,7 @@ 188 | # include 189 | # endif 190 | 191 | -# include "" 192 | +# include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\time.h" 193 | 194 | /* NetBSD 5.0 mis-defines NULL. */ 195 | # include 196 | diff -Naur sed-4.9/lib/wchar.h sed-4.9-patched/lib/wchar.h 197 | --- sed-4.9/lib/wchar.h 2022-11-26 16:04:06.724874000 +0300 198 | +++ sed-4.9-patched/lib/wchar.h 2022-11-26 18:59:48.209592900 +0300 199 | @@ -77,7 +77,7 @@ 200 | Some builds of uClibc lack it. */ 201 | /* The include_next requires a split double-inclusion guard. */ 202 | #if 1 203 | -# include "" 204 | +# include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\wchar.h" 205 | #endif 206 | 207 | #undef _GL_ALREADY_INCLUDING_WCHAR_H 208 | diff -Naur sed-4.9/lib/wctype.h sed-4.9-patched/lib/wctype.h 209 | --- sed-4.9/lib/wctype.h 2022-11-26 16:04:06.896756900 +0300 210 | +++ sed-4.9-patched/lib/wctype.h 2022-11-26 18:59:48.209592900 +0300 211 | @@ -63,7 +63,7 @@ 212 | BeOS 5 has the functions but no . */ 213 | /* The include_next requires a split double-inclusion guard. */ 214 | #if 1 215 | -# include "" 216 | +# include "X:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\wctype.h" 217 | #endif 218 | 219 | #ifndef _GL_WCTYPE_H 220 | -------------------------------------------------------------------------------- /sed-4.9-build-patch-howto.txt: -------------------------------------------------------------------------------- 1 | Instructions how to build native sed.exe with Microsoft Visual Studio (or Build Tools for Visual Studio) from CYGWIN shell. 2 | 3 | While building, it is possible to save build log and create a patch - for compiling sed.exe using only Microsoft Visual Studio tools, without need for CYGWIN. 4 | 5 | This is how sed-4.9-build-VS22-x64.patch and sed-4.9-build-VS22-x86.patch were created. 6 | 7 | (sed-4.9-build-VS9-x86.patch was created analogously in Microsoft Visual Studio 2008 environment) 8 | 9 | 10 | From CYGWIN shell: 11 | 12 | 1) get archive: 13 | wget https://ftp.gnu.org/gnu/sed/sed-4.9.tar.xz 14 | 15 | 2) unpack archive: 16 | tar xf sed-4.9.tar.xz 17 | 18 | 3) go to sed sources: 19 | cd sed-4.9 20 | 21 | 4) patch the sources: 22 | patch -Np1 -i sed-4.9-src.patch 23 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.9-src.patch) 24 | 25 | 5) now start dos prompt: 26 | cmd /c "start cmd.exe" 27 | 28 | 6) setup compiler: 29 | "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64 30 | (if Microsoft Build Tools for Visual Studio 2022 is installed in "C:\Program Files (x86)") 31 | 32 | --tip: to build 32-bit version of the Gnu Sed utility, specify "x86" instead of "amd64" 33 | 34 | --tip: for Visual Studio 2008: 35 | "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 36 | 37 | 7) run bash from dos prompt (with environment prepared for compiling with Microsoft Build Tools for Visual Studio 2022): 38 | bash 39 | 40 | 8) check that Gnu Make is installed in CYGWIN and it is working (Gnu Make is required for the build): 41 | make --version 42 | 43 | 9) configure sed: 44 | - for 64-bit build: 45 | CFLAGS= \ 46 | CC="cl /Dssize_t=__int64" \ 47 | CPP="cl /Dssize_t=__int64 /E" \ 48 | LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules --disable-nls gl_cv_sys_struct_lconv_ok=yes gt_cv_ssize_t=yes 49 | 50 | - for 32-bit build: 51 | CFLAGS= CC=cl CPP="cl /E" LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules --disable-nls gl_cv_sys_struct_lconv_ok=yes 52 | 53 | --tip: for Visual Studio 2008, add "/D_WIN32_WINNT=0x501 /D__bool_true_false_are_defined /Dbool=int /Dtrue=1 /Dfalse=0" compiler switches: 54 | CFLAGS= \ 55 | CC="cl /D_WIN32_WINNT=0x501 /D__bool_true_false_are_defined /Dbool=int /Dtrue=1 /Dfalse=0" \ 56 | CPP="cl /D_WIN32_WINNT=0x501 /D__bool_true_false_are_defined /Dbool=int /Dtrue=1 /Dfalse=0 /E" \ 57 | LD=lib ARFLAGS="/OUT:" ./configure --enable-threads=windows --disable-dependency-tracking --disable-silent-rules --disable-nls gl_cv_sys_struct_lconv_ok=yes 58 | 59 | 10) configure script is not fully functional to create correct Makefiles - they are need to be fixed manually: 60 | sed -i '/^SUBDIRS/s/=.*/= ./' Makefile 61 | sed -i '/^NEXT/s/=.*/=""/' Makefile 62 | sed -i '/lib_libsed_a_AR/s/ lib/lib/' Makefile 63 | sed -i '/sed_libver_a_AR/s/ sed/sed/' Makefile 64 | sed -i 's@^AR = .*@AR = lib /nologo@' Makefile 65 | sed -i 's/-c -o /-c -nologo -Fo/' Makefile 66 | sed -i '/RANLIB/d' Makefile 67 | sed -i '/^sed_sed_LINK/{s/.*/sed_sed_LINK = $(LINK)/;n;d}' Makefile 68 | 69 | 11) fix linker command, add support for wildcards in program arguments: 70 | sed -i 's%^LINK = .*%LINK = link /nologo /SUBSYSTEM:CONSOLE /OUT:$@ /DEFAULTLIB:Advapi32.lib /DEFAULTLIB:LIBCPMT.lib wsetargv.obj%' ./Makefile 71 | 72 | --tip: for Visual Studio 2008, specify "/SUBSYSTEM:CONSOLE,5.01" linker switch: 73 | sed -i 's%^LINK = .*%LINK = link /nologo /SUBSYSTEM:CONSOLE,5.01 /OUT:$@ /DEFAULTLIB:Advapi32.lib /DEFAULTLIB:LIBCPMT.lib wsetargv.obj%' ./Makefile 74 | 75 | 12) add gen target: 76 | echo 'gen: $(BUILT_SOURCES)' >> Makefile 77 | 78 | 13) execute Makefile to generate sed headers: 79 | make gen 80 | 81 | 14) some references to system header files are missing in generated headers - they need to be fixed manually. 82 | 83 | a) set paths to locations of Build Tools for Visual Studio 2022 and WDK10 in sed-4.9-win-headers.patch (assume it was copied to the current directory): 84 | 85 | sed -i '/Visual Studio/s@.:.*include@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[^=;]*[0-9]\\\\include\).*$@\1@p')"'@' ./sed-4.9-win-headers.patch 86 | sed -i '/Windows Kits/s@.:.*ucrt@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\ucrt\).*$@\1@p')"'@' ./sed-4.9-win-headers.patch 87 | 88 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.9-win-headers.patch) 89 | 90 | note: sub-command 91 | env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[^=;]*[0-9]\\\\include\).*$@\1@p' 92 | should extract path to MSVC headers, like: 93 | C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Tools\\MSVC\\14.30.30705\\include 94 | 95 | and sub-command 96 | env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\ucrt\).*$@\1@p' 97 | should extract path to WDK headers, like: 98 | C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.22000.0\\ucrt 99 | 100 | --tip: for Visual Studio 2008: 101 | sed -i '/Visual Studio/s@.:.*include@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[iI][nN][cC][lL][uU][dD][eE]\).*$@\1@p')"'@' ./sed-4.9-win-headers.patch 102 | sed -i '/Windows Kits/s@.:.*ucrt@'"$(env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[iI][nN][cC][lL][uU][dD][eE]\).*$@\1@p')"'@' ./sed-4.9-win-headers.patch 103 | 104 | note: sub-command 105 | env | sed -n 's@\\@\\\\@g;/^INCLUDE/s@.*[=;]\([^=;]*\\\\VC\\\\[iI][nN][cC][lL][uU][dD][eE]\).*$@\1@p' 106 | should extract path to MSVC headers, like: 107 | C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\INCLUDE 108 | 109 | b) lib/assert.h header file may not be generated if system has builtin static_assert support, fix the patch to avoid patching missing lib/assert.h 110 | test -f ./lib/assert.h || sed -i -n '\@diff -Naur .*/assert.h@{:b;n;/diff -Naur/!b b};p' ./sed-4.9-win-headers.patch 111 | 112 | c) now patch the previously generated headers with updated patch-file: 113 | patch -Np1 -i ./sed-4.9-win-headers.patch 114 | 115 | 15) add missing getopt sources: 116 | patch -Np1 -i sed-4.9-getopt.patch 117 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.9-getopt.patch) 118 | 119 | 16) add rules to make getopt objects: 120 | 121 | sed -i 's@^gl_LIBOBJS =.*@& lib/getopt.obj lib/getopt1.obj@' Makefile 122 | sed -i '$s@.*@&\nlib/libsed_a-getopt.obj: lib/getopt.c\n\t\$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_libsed_a_CFLAGS) $(CFLAGS) -c -nologo -Folib/libsed_a-getopt.obj `if test -f '"'"'lib/getopt.c'"'"'; then $(CYGPATH_W) '"'"'lib/getopt.c'"'"'; else $(CYGPATH_W) '"'"'$(srcdir)/lib/getopt.c'"'"'; fi`@' Makefile 123 | sed -i '$s@.*@&\nlib/libsed_a-getopt1.obj: lib/getopt1.c\n\t\$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_libsed_a_CFLAGS) $(CFLAGS) -c -nologo -Folib/libsed_a-getopt.obj `if test -f '"'"'lib/getopt1.c'"'"'; then $(CYGPATH_W) '"'"'lib/getopt1.c'"'"'; else $(CYGPATH_W) '"'"'$(srcdir)/lib/getopt1.c'"'"'; fi`@' Makefile 124 | 125 | 17) when building with Visual Studio 2008: 126 | 127 | a) fix sources for compilation with non-c99 compiler: 128 | patch -Np1 -i sed-4.9-src-non-c99.patch 129 | (patch location: https://raw.githubusercontent.com/mbuilov/sed-windows/master/sed-4.9-src-non-c99.patch) 130 | 131 | b) stdbool.h header file is missing, add it: 132 | echo > stdbool.h 133 | 134 | c) fix lib/string.h: 135 | sed -i 's@\*restrict @*@g' lib/string.h 136 | 137 | d) fix lib/ctype.h: 138 | sed -i -e '/undef isblank/{:r;n;/^#endif/!b r' -e 's@@&\nstatic __inline int isblank(int c) {return '"'"' '"'"' == c || '"'"'\\t'"'"' == c;}@}' lib/ctype.h 139 | 140 | 18) do compile sed: 141 | make > make.bat 142 | 143 | 19) check build result: 144 | ./sed/sed.exe --version --locale=C 145 | 146 | (should print sed version, e.g.: (GNU sed) 4.9) 147 | 148 | compilation should be ok, native (unoptimized) ./sed/sed.exe should be created. 149 | 150 | 151 | Now it is possible to create a patch file - for compiling optimized sed.exe using only Microsoft Visual Studio tools, without need for CYGWIN. 152 | 153 | 1) create directory for unpatched sed: 154 | mkdir ../orig 155 | 156 | 2) unpack sed: 157 | tar xf ../sed-4.9.tar.xz -C ../orig/ 158 | 159 | 3) diff current directory with original just unpacked sed-4.9.tar.xz in the '../orig' directory 160 | diff -rql . ../orig/sed-4.9 161 | 162 | 4) remove unneeded built files in the current directory (object files, libs, etc...) 163 | 164 | rm -rv \ 165 | ./Makefile \ 166 | ./stamp-h1 \ 167 | ./sed-4.9-win-headers.patch \ 168 | ./lib/*.obj \ 169 | ./lib/.dirstamp \ 170 | ./lib/.deps \ 171 | ./lib/glthread/*.obj \ 172 | ./lib/glthread/.dirstamp \ 173 | ./lib/glthread/.deps \ 174 | ./lib/libsed.a \ 175 | ./sed/*.obj \ 176 | ./sed/.dirstamp \ 177 | ./sed/.deps \ 178 | ./lib/malloc/*.obj \ 179 | ./lib/malloc/.dirstamp \ 180 | ./lib/malloc/.deps \ 181 | ./sed/sed.exe \ 182 | ./sed/libver.a \ 183 | ./po/Makefile \ 184 | ./po/Makefile.in \ 185 | ./po/POTFILES \ 186 | ./config.log \ 187 | ./config.status \ 188 | ./gnulib-tests/Makefile \ 189 | ./sed/sed.exp \ 190 | ./sed/sed.lib 191 | 192 | cp -fv \ 193 | ../orig/sed-4.9/doc/sed.1 ./doc/sed.1 194 | 195 | 5) after this, diff should print: 196 | 197 | diff -rql . ../orig/sed-4.9 198 | Only in .: config.h 199 | Only in ./lib: alloca.h 200 | # Only in ./lib: assert.h 201 | * Files ./lib/calloc.c and ../orig/sed-4.9/lib/calloc.c differ 202 | * Files ./lib/canonicalize-lgpl.c and ../orig/sed-4.9/lib/canonicalize-lgpl.c differ 203 | Only in ./lib: ctype.h 204 | * Files ./lib/dfa.c and ../orig/sed-4.9/lib/dfa.c differ 205 | Only in ./lib: errno.h 206 | Only in ./lib: fcntl.h 207 | Only in ./lib: getopt-cdefs.h 208 | Only in ./lib: getopt-core.h 209 | Only in ./lib: getopt-ext.h 210 | Only in ./lib: getopt-pfx-core.h 211 | Only in ./lib: getopt-pfx-ext.h 212 | Only in ./lib: getopt.c 213 | Only in ./lib: getopt.h 214 | Only in ./lib: getopt1.c 215 | Only in ./lib: getopt_int.h 216 | Only in ./lib: inttypes.h 217 | Only in ./lib: langinfo.h 218 | Only in ./lib: limits.h 219 | Files ./lib/localcharset.c and ../orig/sed-4.9/lib/localcharset.c differ 220 | Only in ./lib: locale.h 221 | * Files ./lib/localeinfo.c and ../orig/sed-4.9/lib/localeinfo.c differ 222 | Only in ./lib/malloc: dynarray-skeleton.gl.h 223 | Only in ./lib/malloc: dynarray.gl.h 224 | * Files ./lib/malloc/dynarray_emplace_enlarge.c and ../orig/sed-4.9/lib/malloc/dynarray_emplace_enlarge.c differ 225 | * Files ./lib/malloc/dynarray_finalize.c and ../orig/sed-4.9/lib/malloc/dynarray_finalize.c differ 226 | * Files ./lib/malloc/dynarray_resize.c and ../orig/sed-4.9/lib/malloc/dynarray_resize.c differ 227 | * Files ./lib/malloc/dynarray_resize_clear.c and ../orig/sed-4.9/lib/malloc/dynarray_resize_clear.c differ 228 | Only in ./lib/malloc: scratch_buffer.gl.h 229 | * Files ./lib/malloc/scratch_buffer_set_array_size.c and ../orig/sed-4.9/lib/malloc/scratch_buffer_set_array_size.c differ 230 | * Files ./lib/malloc.c and ../orig/sed-4.9/lib/malloc.c differ 231 | * Files ./lib/malloca.c and ../orig/sed-4.9/lib/malloca.c differ 232 | Files ./lib/mbtowc-lock.h and ../orig/sed-4.9/lib/mbtowc-lock.h differ 233 | Files ./lib/nl_langinfo.c and ../orig/sed-4.9/lib/nl_langinfo.c differ 234 | * Files ./lib/rawmemchr.c and ../orig/sed-4.9/lib/rawmemchr.c differ 235 | * Files ./lib/realloc.c and ../orig/sed-4.9/lib/realloc.c differ 236 | * Files ./lib/regcomp.c and ../orig/sed-4.9/lib/regcomp.c differ 237 | * Files ./lib/regexec.c and ../orig/sed-4.9/lib/regexec.c differ 238 | Only in ./lib: selinux 239 | Only in ./lib: stdalign.h 240 | Only in ./lib: stdckdint.h 241 | Only in ./lib: stddef.h 242 | Only in ./lib: stdint.h 243 | Only in ./lib: stdio.h 244 | Only in ./lib: stdlib.h 245 | Only in ./lib: string.h 246 | * Files ./lib/strverscmp.c and ../orig/sed-4.9/lib/strverscmp.c differ 247 | Only in ./lib: sys 248 | * Files ./lib/tempname.c and ../orig/sed-4.9/lib/tempname.c differ 249 | Only in ./lib: time.h 250 | Only in ./lib: unistd.h 251 | Only in ./lib: wchar.h 252 | Only in ./lib: wctype.h 253 | * Files ./lib/xmalloc.c and ../orig/sed-4.9/lib/xmalloc.c differ 254 | Only in .: make.bat 255 | * Files ./sed/debug.c and ../orig/sed-4.9/sed/debug.c differ 256 | Files ./sed/execute.c and ../orig/sed-4.9/sed/execute.c differ 257 | * Files ./sed/regexp.c and ../orig/sed-4.9/sed/regexp.c differ 258 | Files ./sed/sed.c and ../orig/sed-4.9/sed/sed.c differ 259 | Files ./sed/utils.c and ../orig/sed-4.9/sed/utils.c differ 260 | Only in ./sed: version.c 261 | Only in ./sed: version.h 262 | * Only in .: stdbool.h 263 | 264 | # -- if ./lib/assert.h was generated 265 | * -- if sed-4.9-src-non-c99.patch was applied 266 | 267 | 6) edit make.bat 268 | 269 | cp make.bat make.bat.old 270 | sed -i -n 's/.*cl /cl /p;/^lib /p;/^link /p' make.bat 271 | sed -i 's@-DLOCALEDIR=."/usr/local/share/locale.".*-c -nologo -F@/DLOCALEDIR="" /c /nologo /F@' make.bat 272 | sed -i 's@ -c -nologo -F@/c /nologo /F@' make.bat 273 | sed -i '/lc-charset-dispatch.c/s@ /nologo @&/DGNULIB_WCHAR_SINGLE_LOCALE=1 @' make.bat 274 | sed -i 's@lib/glthread/@lib\\glthread\\@g' make.bat 275 | sed -i 's@/Fosed/@/Fosed\\@;s@/Folib/@/Folib\\@' make.bat 276 | sed -i 's@`if test -f .@@;s@.; then.*@@' make.bat 277 | sed -i 's@`cygpath -w .@@;s@.`@@' make.bat 278 | sed -i 's@ lib/@ lib\\@g;s@ sed/@ sed\\@g' make.bat 279 | sed -i 's@\\malloc/@\\malloc\\@g' make.bat 280 | sed -i 's@-DHAVE_CONFIG_H -I. -I. -I./lib -I./lib -I./sed@/Ox /GF /Gy /GS- /GL /EHsc /DHAVE_CONFIG_H /I. /I.\\lib /I.\\sed@' make.bat 281 | sed -i 's@lib /nologo@lib /LTCG /nologo@' make.bat 282 | sed -i 's@/OUT:lib/@/OUT:lib\\@;s@/OUT:sed/@/OUT:sed\\@' make.bat 283 | sed -i 's@link /nologo@& /LTCG@' make.bat 284 | sed -i 's@$@ || exit /b 1@' make.bat 285 | rm make.bat.old 286 | 287 | 7) finally, create a patch: 288 | diff -Naur ../orig/sed-4.9 . > ../sed-4.9-build-VS22-x64.patch 289 | 290 | --tip: for the 32-bit build, use different patch name: 291 | diff -Naur ../orig/sed-4.9 . > ../sed-4.9-build-VS22-x86.patch 292 | 293 | --tip: for Visual Studio 2008: 294 | diff -Naur ../orig/sed-4.9 . > ../sed-4.9-build-VS9-x86.patch 295 | -------------------------------------------------------------------------------- /archive/sed-4.7-src.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.7/lib/localcharset.c sed-4.7-patched/lib/localcharset.c 2 | --- sed-4.7/lib/localcharset.c 2018-08-27 11:59:14.000000000 +0300 3 | +++ sed-4.7-patched/lib/localcharset.c 2019-12-20 16:14:46.317003700 +0300 4 | @@ -774,7 +774,16 @@ 5 | current_locale = setlocale (LC_CTYPE, NULL); 6 | 7 | pdot = strrchr (current_locale, '.'); 8 | - if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) 9 | + 10 | + /* After a dot may follow a codepage number, or the "utf8" string. */ 11 | + if (pdot && 12 | + ('u' == pdot[1] || 'U' == pdot[1]) && 13 | + ('t' == pdot[2] || 'T' == pdot[2]) && 14 | + ('f' == pdot[3] || 'F' == pdot[3]) && 15 | + (('8' == pdot[4] && '\0' == pdot[5]) || 16 | + ('-' == pdot[4] && '8' == pdot[5] && '\0' == pdot[6]))) 17 | + strcpy (buf, "UTF-8"); 18 | + else if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) 19 | sprintf (buf, "CP%s", pdot + 1); 20 | else 21 | { 22 | diff -Naur sed-4.7/lib/nl_langinfo.c sed-4.7-patched/lib/nl_langinfo.c 23 | --- sed-4.7/lib/nl_langinfo.c 2018-12-13 09:11:38.000000000 +0300 24 | +++ sed-4.7-patched/lib/nl_langinfo.c 2019-12-20 16:14:46.320003800 +0300 25 | @@ -71,12 +71,22 @@ 26 | GetACP, which returns the locale's codepage as a number (although 27 | this doesn't change according to what the 'setlocale' call specified). 28 | Either way, prepend "CP" to make it a valid codeset name. */ 29 | - codesetlen = strlen (codeset); 30 | - if (0 < codesetlen && codesetlen < sizeof buf - 2) 31 | - memmove (buf + 2, codeset, codesetlen + 1); 32 | + /* After a dot may follow a codepage number, or the "utf8" string. */ 33 | + if (('u' == codeset[0] || 'U' == codeset[0]) && 34 | + ('t' == codeset[1] || 'T' == codeset[1]) && 35 | + ('f' == codeset[2] || 'F' == codeset[2]) && 36 | + (('8' == codeset[3] && '\0' == codeset[4]) || 37 | + ('-' == codeset[3] && '8' == codeset[4] && '\0' == codeset[5]))) 38 | + codeset = strcpy (buf, "UTF-8"); 39 | else 40 | - sprintf (buf + 2, "%u", GetACP ()); 41 | - codeset = memcpy (buf, "CP", 2); 42 | + { 43 | + codesetlen = strlen (codeset); 44 | + if (0 < codesetlen && codesetlen < sizeof buf - 2) 45 | + memmove (buf + 2, codeset, codesetlen + 1); 46 | + else 47 | + sprintf (buf + 2, "%u", GetACP ()); 48 | + codeset = memcpy (buf, "CP", 2); 49 | + } 50 | # endif 51 | return codeset; 52 | } 53 | diff -Naur sed-4.7/sed/execute.c sed-4.7-patched/sed/execute.c 54 | --- sed-4.7/sed/execute.c 2018-12-10 06:26:36.000000000 +0300 55 | +++ sed-4.7-patched/sed/execute.c 2019-12-20 16:14:46.322004000 +0300 56 | @@ -37,6 +37,8 @@ 57 | #include "progname.h" 58 | #include "xalloc.h" 59 | 60 | +#include "dirname.h" 61 | + 62 | /* The number of extra bytes that must be allocated/usable, beyond 63 | the declared "end" of each line buffer that may be passed to 64 | match_regex. This is imposed by its use of dfaexec. */ 65 | @@ -571,17 +573,22 @@ 66 | if (in_place_extension) 67 | { 68 | int input_fd; 69 | - char *tmpdir, *p; 70 | + char *tmpdir; 71 | security_context_t old_fscreatecon; 72 | int reset_fscreatecon = 0; 73 | + size_t in_dir_len; 74 | memset (&old_fscreatecon, 0, sizeof (old_fscreatecon)); 75 | 76 | /* get the base name */ 77 | - tmpdir = xstrdup (input->in_file_name); 78 | - if ((p = strrchr (tmpdir, '/'))) 79 | - *p = 0; 80 | + in_dir_len = dir_len (input->in_file_name); 81 | + if (in_dir_len) 82 | + { 83 | + tmpdir = xmalloc (in_dir_len + 1); 84 | + memcpy (tmpdir, input->in_file_name, in_dir_len); 85 | + tmpdir[in_dir_len] = '\0'; 86 | + } 87 | else 88 | - strcpy (tmpdir, "."); 89 | + tmpdir = xstrdup ("."); 90 | 91 | if (isatty (fileno (input->fp))) 92 | panic (_("couldn't edit %s: is a terminal"), input->in_file_name); 93 | diff -Naur sed-4.7/sed/sed.c sed-4.7-patched/sed/sed.c 94 | --- sed-4.7/sed/sed.c 2018-12-13 09:06:47.000000000 +0300 95 | +++ sed-4.7-patched/sed/sed.c 2019-12-22 12:54:32.643815600 +0300 96 | @@ -66,9 +66,17 @@ 97 | /* How do we edit files in-place? (we don't if NULL) */ 98 | char *in_place_extension = NULL; 99 | 100 | -/* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ 101 | +/* The mode to use to read/write files, either "r(t)"/"w(t)" or "rb"/"wb". */ 102 | +#ifdef HAVE_FOPEN_RT 103 | +char const *read_mode = "rt"; 104 | +char const *write_mode = "wt"; 105 | +#else 106 | char const *read_mode = "r"; 107 | char const *write_mode = "w"; 108 | +#endif 109 | + 110 | +/* Locale to set at startup. */ 111 | +char const *def_locale = ""; 112 | 113 | #if O_BINARY 114 | /* Additional flag for binary mode on platforms with O_BINARY/O_TEXT. */ 115 | @@ -116,7 +124,145 @@ 116 | G_file_to_unlink = NULL; 117 | } 118 | 119 | -static void usage (int); 120 | +#if defined _WIN32 && !defined __CYGWIN__ 121 | +#define WINDOWS_NATIVE 122 | +#endif 123 | + 124 | +#ifdef WINDOWS_NATIVE 125 | + 126 | +/* Get value of command-line option: 127 | + --lo[cale]=locale-name or --lo[cale] locale-name, 128 | + Returns option value or NULL if the option is not specified. 129 | + Panics if the option specified without a value, 130 | + else terminates opt_name_array to the length of the option name. */ 131 | +/* Note: before the call, opt_name_array must contain "--locale". */ 132 | +static const wchar_t * 133 | +get_specified_locale (wchar_t **wa, char opt_name_array[]) 134 | +{ 135 | + const wchar_t *w = NULL; 136 | + for (; *wa; wa++) 137 | + { 138 | + w = *wa; 139 | + if (L'-' != w[0] || L'-' != w[1] || L'l' != w[2] || L'o' != w[3]) 140 | + continue; 141 | + w += 4; 142 | + if (L'=' == *w || !*w) 143 | + break; 144 | + if (L'c' != *w) 145 | + continue; 146 | + w++; 147 | + if (L'=' == *w || !*w) 148 | + break; 149 | + if (L'a' != *w) 150 | + continue; 151 | + w++; 152 | + if (L'=' == *w || !*w) 153 | + break; 154 | + if (L'l' != *w) 155 | + continue; 156 | + w++; 157 | + if (L'=' == *w || !*w) 158 | + break; 159 | + if (L'e' != *w) 160 | + continue; 161 | + w++; 162 | + if (L'=' == *w || !*w) 163 | + break; 164 | + } 165 | + 166 | + if (!*wa) 167 | + return NULL; /* --lo[cale] option wasn't found. */ 168 | + 169 | + opt_name_array[(unsigned) (w - *wa)] = '\0'; 170 | + if (*w) 171 | + return w + 1; /* --lo[cale]=locale-name, return locale-name. */ 172 | + 173 | + /* --lo[cale] locale-name. */ 174 | + { 175 | + const wchar_t *locale_name = wa[1]; 176 | + if (!locale_name) 177 | + panic (_("option '%s' requires an argument"), opt_name_array); 178 | + return locale_name; 179 | + } 180 | +} 181 | + 182 | +/* Set locale based on the values of environment variables. */ 183 | +static void 184 | +set_locale_from_env (const char *def) 185 | +{ 186 | + const char *locale = getenv ("LC_ALL"); 187 | + if (locale && locale[0]) 188 | + { 189 | + if (!setlocale (LC_ALL, locale)) 190 | + panic (_("Bad locale: LC_ALL=%s"), locale); 191 | + return; 192 | + } 193 | + 194 | + /* LANG is the default for all LC_... */ 195 | + locale = getenv ("LANG"); 196 | + 197 | + /* if LANG is not defined - set the system default. 198 | + (If def is "", locale may be be set to 199 | + e.g. Russian_Russia.1251). */ 200 | + if (!locale || !locale[0]) 201 | + locale = def; 202 | + 203 | + if (!setlocale (LC_ALL, locale)) 204 | + panic (_("Bad locale: LANG=%s"), locale); 205 | + 206 | + /* specific LC_... take precedence over LANG. */ 207 | + locale = getenv ("LC_CTYPE"); 208 | + if (locale && locale[0]) 209 | + { 210 | + if (!setlocale (LC_CTYPE, locale)) 211 | + panic (_("Bad locale: LC_CTYPE=%s"), locale); 212 | + } 213 | +} 214 | + 215 | +/* Convert wide-char args to multibyte. */ 216 | +static char ** 217 | +convert_wargv (int argc, wchar_t **wargv) 218 | +{ 219 | + /* Convert program arguments from wide-char to multibyte 220 | + according to the locale codepage. */ 221 | + /* Note: argv array must be NULL-terminated. */ 222 | + char **argv = (char**) xmalloc (sizeof(*argv)*(argc + 1)); 223 | + 224 | + wchar_t **wa = wargv; 225 | + for (; *wa; wa++) 226 | + { 227 | + const size_t need = wcstombs (NULL, *wa, 0); 228 | + 229 | + if ((size_t) -1 == need) 230 | + panic (_("failed to convert argument %u (Unicode -> LC_CTYPE=%s): %s"), 231 | + (unsigned) (wa - wargv), setlocale (LC_CTYPE, NULL), 232 | + strerror (errno)); 233 | + 234 | + { 235 | + char *a = (char*) xmalloc (need + 1); 236 | + wcstombs (a, *wa, need + 1); 237 | + argv[wa - wargv] = a; 238 | + } 239 | + } 240 | + 241 | + /* argv - is a NULL-terminated array of pointers */ 242 | + argv[wa - wargv] = NULL; 243 | + 244 | + return argv; 245 | +} 246 | + 247 | +/* Free arguments array allocated by convert_wargv (). */ 248 | +static void 249 | +free_argv (char **argv) 250 | +{ 251 | + char **a = argv; 252 | + for (; *a; a++) 253 | + free (*a); 254 | + free (argv); 255 | +} 256 | + 257 | +#endif /* WINDOWS_NATIVE */ 258 | + 259 | static void 260 | contact (int errmsg) 261 | { 262 | @@ -128,6 +274,9 @@ 263 | get reports for other people's bugs. */ 264 | if (!errmsg) 265 | fprintf (out, _("E-mail bug reports to: <%s>.\n"), PACKAGE_BUGREPORT); 266 | + 267 | + if (!errmsg) 268 | + fprintf (out, _("Patched (v2) by: Michael M. Builov .\n")); 269 | } 270 | 271 | _Noreturn static void 272 | @@ -159,6 +308,13 @@ 273 | open files in binary mode (CR+LFs are not" \ 274 | " processed specially)\n")); 275 | #endif 276 | + fprintf (out, _(" -C, --ignore-locale\n\ 277 | + ignore system locale, operate in the default \"C\" locale\n")); 278 | +#ifdef WINDOWS_NATIVE 279 | + fprintf (out, _(" --locale=locale-name\n\ 280 | + use the specified locale (ignore environment" \ 281 | + " variables LC_ALL, LC_CTYPE and LANG)\n")); 282 | +#endif 283 | fprintf (out, _(" -l N, --line-length=N\n\ 284 | specify the desired line-wrap length for the `l' command\n")); 285 | fprintf (out, _(" --posix\n\ 286 | @@ -191,16 +347,24 @@ 287 | } 288 | 289 | int 290 | +#ifndef WINDOWS_NATIVE 291 | main (int argc, char **argv) 292 | +#else 293 | +wmain (int argc, wchar_t **wargv) 294 | +#endif 295 | { 296 | -#define SHORTOPTS "bsnrzuEe:f:l:i::V:" 297 | +#define SHORTOPTS "bCsnrzuEe:f:l:i::V:" 298 | 299 | enum { SANDBOX_OPTION = CHAR_MAX+1, 300 | DEBUG_OPTION 301 | +#ifdef WINDOWS_NATIVE 302 | + ,LOCALE_OPTION 303 | +#endif 304 | }; 305 | 306 | static const struct option longopts[] = { 307 | {"binary", 0, NULL, 'b'}, 308 | + {"ignore-locale", 0, NULL, 'C'}, 309 | {"regexp-extended", 0, NULL, 'r'}, 310 | {"debug", 0, NULL, DEBUG_OPTION}, 311 | {"expression", 1, NULL, 'e'}, 312 | @@ -220,6 +384,9 @@ 313 | #ifdef ENABLE_FOLLOW_SYMLINKS 314 | {"follow-symlinks", 0, NULL, 'F'}, 315 | #endif 316 | +#ifdef WINDOWS_NATIVE 317 | + {"locale", 1, NULL, LOCALE_OPTION}, 318 | +#endif 319 | {NULL, 0, NULL, 0} 320 | }; 321 | 322 | @@ -227,11 +394,68 @@ 323 | int return_code; 324 | const char *cols = getenv ("COLS"); 325 | 326 | +#ifdef WINDOWS_NATIVE 327 | + char **old_argv = NULL; 328 | + char **argv; 329 | + 330 | + /* Set locale according to user's wishes. 331 | + (Current locale is "C"). */ 332 | + char opt_name_array[] = "--locale"; 333 | + const wchar_t *spec_locale; 334 | + 335 | + /* Temporary set program name. 336 | + This is needed for error messages - in case of bad locale. */ 337 | + set_program_name ("sed"); 338 | + 339 | + /* Command-line option takes precedence over environment vars. */ 340 | + spec_locale = get_specified_locale (wargv, opt_name_array); 341 | + if (!spec_locale) 342 | + set_locale_from_env (def_locale); 343 | + else if (!_wsetlocale (LC_ALL, spec_locale)) 344 | + panic (_("Bad locale name specified by the option '%s'"), opt_name_array); 345 | + 346 | + /* Convert program arguments to multibyte strings. */ 347 | + argv = convert_wargv (argc, wargv); 348 | +#endif /* WINDOWS_NATIVE */ 349 | + 350 | set_program_name (argv[0]); 351 | initialize_main (&argc, &argv); 352 | + 353 | + /* Suppress error reporting in getopt. */ 354 | + opterr = 0; 355 | + 356 | + while ((opt = getopt_long (argc, argv, SHORTOPTS, longopts, NULL)) != EOF) 357 | + { 358 | + switch (opt) 359 | + { 360 | + case 'C': 361 | + def_locale = "C"; 362 | + break; 363 | + } 364 | + } 365 | + 366 | + /* Restore getopt behaviour. */ 367 | + opterr = 1; 368 | + optind = 1; 369 | + 370 | #if HAVE_SETLOCALE 371 | +#ifndef WINDOWS_NATIVE 372 | /* Set locale according to user's wishes. */ 373 | - setlocale (LC_ALL, ""); 374 | + setlocale (LC_ALL, def_locale); 375 | +#else /* WINDOWS_NATIVE */ 376 | + if (def_locale[0]) 377 | + { 378 | + /* User wants to use "C"-locale. */ 379 | + if (spec_locale) 380 | + panic (_("Options '-C/--ignore-locale' and '--locale' cannot be used together.")); 381 | + setlocale (LC_ALL, def_locale); 382 | + 383 | + /* Cannot free argv array now: 384 | + argv[0] was passed to set_program_name (). */ 385 | + old_argv = argv; 386 | + argv = convert_wargv (argc, wargv); 387 | + } 388 | +#endif /* WINDOWS_NATIVE */ 389 | #endif 390 | initialize_mbcs (); 391 | init_localeinfo (&localeinfo); 392 | @@ -320,6 +544,10 @@ 393 | #endif 394 | break; 395 | 396 | + case 'C': 397 | + /* already processed */ 398 | + break; 399 | + 400 | case 'E': 401 | case 'r': 402 | extended_regexp_flags = REG_EXTENDED; 403 | @@ -337,6 +565,12 @@ 404 | debug = true; 405 | break; 406 | 407 | +#ifdef WINDOWS_NATIVE 408 | + case LOCALE_OPTION: 409 | + /* already processed */ 410 | + break; 411 | +#endif 412 | + 413 | case 'u': 414 | unbuffered = true; 415 | break; 416 | @@ -374,6 +608,15 @@ 417 | if (set_binary_mode ( fileno (stdout), O_BINARY) == -1) 418 | panic (_("failed to set binary mode on STDOUT")); 419 | } 420 | + else 421 | + { 422 | + /* Under CYGWIN, standard input/output streams are in BINARY 423 | + mode by default, make sure they are in TEXT mode. */ 424 | + if (set_binary_mode ( fileno (stdin), O_TEXT) == -1) 425 | + panic (_("failed to set binary mode on STDIN")); 426 | + if (set_binary_mode ( fileno (stdout), O_TEXT) == -1) 427 | + panic (_("failed to set binary mode on STDOUT")); 428 | + } 429 | #endif 430 | 431 | if (debug) 432 | @@ -384,5 +627,11 @@ 433 | finish_program (the_program); 434 | ck_fclose (NULL); 435 | 436 | +#ifdef WINDOWS_NATIVE 437 | + if (old_argv) 438 | + free_argv (old_argv); 439 | + free_argv (argv); 440 | +#endif 441 | + 442 | return return_code; 443 | } 444 | diff -Naur sed-4.7/sed/utils.c sed-4.7-patched/sed/utils.c 445 | --- sed-4.7/sed/utils.c 2018-12-13 09:06:47.000000000 +0300 446 | +++ sed-4.7-patched/sed/utils.c 2019-12-22 12:54:28.728208700 +0300 447 | @@ -14,6 +14,12 @@ 448 | You should have received a copy of the GNU General Public License 449 | along with this program; If not, see . */ 450 | 451 | +#if defined _WIN32 && !defined __CYGWIN__ 452 | +#define WIN32_LEAN_AND_MEAN 453 | +#include 454 | +#define WINDOWS_NATIVE 455 | +#endif 456 | + 457 | #include 458 | 459 | #include 460 | @@ -198,16 +204,527 @@ 461 | return fp; 462 | } 463 | 464 | +#ifdef WINDOWS_NATIVE 465 | + 466 | +/* Convert wide-character string to multibyte. 467 | + Returns NULL on error, else - malloc'ated '\0'-terminated 468 | + string, which caller should free via free(). */ 469 | +static char * 470 | +convert_wc_to_mb (const wchar_t *wc) 471 | +{ 472 | + const size_t need = wcstombs (NULL, wc, 0); 473 | + 474 | + if ((size_t) -1 == need) 475 | + return NULL; /* Error. errno is set to EILSEQ. */ 476 | + 477 | + { 478 | + char *a = (char*) xmalloc (need + 1); 479 | + wcstombs (a, wc, need + 1); 480 | + return a; 481 | + } 482 | +} 483 | + 484 | +/* Called on panic. */ 485 | +static const char * 486 | +get_last_err_msg (unsigned int last_err) 487 | +{ 488 | + /* First try to get message in locale encoding. */ 489 | + wchar_t *wmsg; 490 | + DWORD n_chars = FormatMessageW ( 491 | + FORMAT_MESSAGE_ALLOCATE_BUFFER | 492 | + FORMAT_MESSAGE_FROM_SYSTEM | 493 | + FORMAT_MESSAGE_IGNORE_INSERTS, 494 | + NULL, last_err, 0, (LPWSTR) &wmsg, 0, NULL); 495 | + 496 | + /* trim "\r\n" at end of msg */ 497 | + if (n_chars && L'\n' == wmsg[n_chars - 1]) 498 | + { 499 | + wmsg[--n_chars] = L'\0'; 500 | + if (n_chars && L'\r' == wmsg[n_chars - 1]) 501 | + wmsg[--n_chars] = L'\0'; 502 | + } 503 | + 504 | + if (!n_chars) 505 | + return ""; 506 | + 507 | + { 508 | + char *msg = convert_wc_to_mb (wmsg); 509 | + if (msg) 510 | + { 511 | + /* Check if failed to translate message to locale code page. */ 512 | + const char *c = msg; 513 | + while ('?' == *c || ' ' == *c) 514 | + c++; 515 | + if ('.' == *c && !c[1]) 516 | + c++; /* Something like "?????." */ 517 | + if (!*c) 518 | + { 519 | + free (msg); 520 | + msg = NULL; 521 | + } 522 | + } 523 | + 524 | + if (!msg) 525 | + { 526 | + /* Just get error message in English. */ 527 | + n_chars = FormatMessageA ( 528 | + FORMAT_MESSAGE_ALLOCATE_BUFFER | 529 | + FORMAT_MESSAGE_FROM_SYSTEM | 530 | + FORMAT_MESSAGE_IGNORE_INSERTS, 531 | + NULL, last_err, 532 | + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 533 | + (LPSTR) &msg, 0, NULL); 534 | + 535 | + /* trim "\r\n" at end of msg */ 536 | + if (n_chars && '\n' == msg[n_chars - 1]) 537 | + { 538 | + msg[--n_chars] = '\0'; 539 | + if (n_chars && '\r' == msg[n_chars - 1]) 540 | + msg[--n_chars] = '\0'; 541 | + } 542 | + 543 | + if (!n_chars) 544 | + return ""; 545 | + } 546 | + 547 | + return msg; 548 | + } 549 | +} 550 | + 551 | +/* Check if file descriptor fd designates a console. 552 | + If this is true, then due to bugs in MS UCRT, 553 | + standard stream i/o functions read(2)/write(2) 554 | + on the fd may fail, e.g. if the console may print 555 | + one symbol per multibyte character (for example, 556 | + if LC_CTYPE=Russian_Russia.1251 and the console 557 | + code page is 65001). */ 558 | +/* Return INVALID_HANDLE_VALUE if fd do not belongs 559 | + to a console. */ 560 | +static HANDLE 561 | +get_console_handle (int fd) 562 | +{ 563 | + HANDLE ch; 564 | + DWORD mode; 565 | + 566 | + if (!_isatty (fd)) 567 | + return INVALID_HANDLE_VALUE; 568 | + 569 | + ch = (HANDLE) _get_osfhandle (fd); 570 | + if (ch != INVALID_HANDLE_VALUE && 571 | + GetConsoleMode (ch, &mode)) 572 | + return ch; 573 | + 574 | + /* Not a console handle. */ 575 | + return INVALID_HANDLE_VALUE; 576 | +} 577 | + 578 | +/* As a workaround to MS UCRT bugs, call WriteConsoleW 579 | + directly. */ 580 | +/* Note: fwrite() internally calls WriteFile, which 581 | + in turn seems like calls WriteConsole expecting 582 | + that it will return number of bytes written. But 583 | + WriteConsole returns number of _chars_ written. 584 | + As result, writing stops after printing only one 585 | + multibyte character. */ 586 | +/* Returns non-zero on error: 587 | + - caller should check errno, then GetLastError(). */ 588 | +static int 589 | +write_to_console (const void *ptr, size_t size, HANDLE ch) 590 | +{ 591 | + /* Write only full mulitbyte chars, so may need to cache 592 | + a part of unwritten multibyte char. */ 593 | + static char remaining_wbuf[MB_LEN_MAX]; 594 | + static unsigned remaining_wbuf_filled = 0; 595 | + 596 | +#ifndef WINDOWS_CONSOLE_WBUF_SIZE 597 | +#define WINDOWS_CONSOLE_WBUF_SIZE 512 /* Must be > 1. */ 598 | +#endif 599 | + wchar_t tmp[WINDOWS_CONSOLE_WBUF_SIZE]; 600 | + wchar_t *at = tmp; 601 | + const char *c = (const char*) ptr; 602 | + const char *const e = c + size; 603 | + int n; 604 | + 605 | + if (remaining_wbuf_filled) 606 | + { 607 | + unsigned to_copy = sizeof(remaining_wbuf) - remaining_wbuf_filled; 608 | + if (to_copy > size) 609 | + to_copy = (unsigned) size; 610 | + memcpy (&remaining_wbuf[remaining_wbuf_filled], c, to_copy); 611 | + remaining_wbuf_filled += to_copy; 612 | + 613 | + n = mbtowc (at, remaining_wbuf, remaining_wbuf_filled); 614 | + if (n < 0) 615 | + { 616 | + if (remaining_wbuf_filled < sizeof(remaining_wbuf)) 617 | + return 0; /* need more bytes of multibyte char for one wide-character */ 618 | + 619 | + /* Cannot convert multibyte to wide-char in current locale. */ 620 | + errno = EILSEQ; 621 | + return -1; 622 | + } 623 | + 624 | + c += to_copy - (remaining_wbuf_filled - n); 625 | + remaining_wbuf_filled = 0; 626 | + at++; 627 | + } 628 | + 629 | + for (; c < e; at = tmp) 630 | + { 631 | + /* Convert to wide-characters. */ 632 | + do 633 | + { 634 | + const size_t to_convert = (size_t) (e - c); 635 | + n = mbtowc (at, c, to_convert); 636 | + if (n < 0) 637 | + { 638 | + if (to_convert < sizeof(remaining_wbuf)) 639 | + { 640 | + remaining_wbuf_filled = (unsigned) to_convert; 641 | + memcpy (remaining_wbuf, c, remaining_wbuf_filled); 642 | + c = e; 643 | + break; /* need more multibyte chars for one wide-character */ 644 | + } 645 | + 646 | + /* Cannot convert multibyte to wide-char in current locale. */ 647 | + errno = EILSEQ; 648 | + return -1; 649 | + } 650 | + 651 | + if (n) 652 | + c += n; 653 | + else 654 | + { 655 | + *at = L'\0'; 656 | + c++; 657 | + } 658 | + 659 | + if (&tmp[sizeof(tmp)/sizeof(tmp[0])] == ++at) 660 | + break; /* buffer is full */ 661 | + } 662 | + while (c < e); 663 | + 664 | + if (at == tmp) 665 | + break; /* nothing to print */ 666 | + 667 | + /* Write to the console. */ 668 | + { 669 | + DWORD NumberOfCharsWritten; 670 | + if (!WriteConsoleW (ch, tmp, (DWORD) (at - tmp), &NumberOfCharsWritten, NULL)) 671 | + { 672 | + errno = 0; /* Caller should check GetLastError(). */ 673 | + return -1; 674 | + } 675 | + } 676 | + } 677 | + 678 | + return 0; 679 | +} 680 | + 681 | +/* Buffer for characters read from the console. 682 | + Note: ReadConsole() cannot handle big buffers (about 64 Kib). */ 683 | +#ifndef WINDOWS_CONSOLE_RBUF_SIZE 684 | +#ifdef _WIN64 685 | +#define WINDOWS_CONSOLE_RBUF_SIZE 30000 /* Must be non-zero. */ 686 | +#else 687 | +#define WINDOWS_CONSOLE_RBUF_SIZE 15000 /* Must be non-zero. */ 688 | +#endif 689 | +#endif 690 | +static wchar_t console_rbuf[WINDOWS_CONSOLE_RBUF_SIZE]; 691 | +static unsigned console_rbuf_offset = 0; 692 | +static unsigned console_rbuf_filled = 0; 693 | + 694 | +/* May read only a part of a multibyte character, 695 | + so may need to cache remaining part of the character. */ 696 | +static char remaining_rbuf[MB_LEN_MAX]; 697 | +static unsigned remaining_rbuf_offset = 0; 698 | +static unsigned remaining_rbuf_filled = 0; 699 | + 700 | +/* Stop console input on Ctrl-Z or Ctrl-D. 701 | + See https://stackoverflow.com/questions/43836040/win-api-readconsole. */ 702 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK 703 | +#define WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) 704 | +#endif 705 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CHAR1 706 | +#define WINDOWS_CONSOLE_READ_STOP_CHAR1 'z' 707 | +#endif 708 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CHAR2 709 | +#define WINDOWS_CONSOLE_READ_STOP_CHAR2 'd' 710 | +#endif 711 | +#define WINDOWS_CONSOLE_READ_STOP_VALUE1 (WINDOWS_CONSOLE_READ_STOP_CHAR1 - 'a' + 1) 712 | +#define WINDOWS_CONSOLE_READ_STOP_VALUE2 (WINDOWS_CONSOLE_READ_STOP_CHAR2 - 'a' + 1) 713 | + 714 | +static CONSOLE_READCONSOLE_CONTROL console_ctrl = { 715 | + sizeof(CONSOLE_READCONSOLE_CONTROL), 0, 716 | + (1u << WINDOWS_CONSOLE_READ_STOP_VALUE1) | 717 | + (1u << WINDOWS_CONSOLE_READ_STOP_VALUE2), 0 718 | +}; 719 | + 720 | +#define is_win_console_stop_input \ 721 | + ((console_rbuf[console_rbuf_offset] == WINDOWS_CONSOLE_READ_STOP_VALUE1 || \ 722 | + console_rbuf[console_rbuf_offset] == WINDOWS_CONSOLE_READ_STOP_VALUE2) && \ 723 | + (console_ctrl.dwControlKeyState & WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK)) 724 | + 725 | +/* Read wide-characters from the console. 726 | + Returns non-zero on error: 727 | + - caller should check GetLastError(). */ 728 | +static int 729 | +read_from_console_w (HANDLE ch) 730 | +{ 731 | + DWORD NumberOfCharsRead; 732 | + if (!ReadConsoleW (ch, console_rbuf, 733 | + sizeof(console_rbuf)/sizeof(console_rbuf[0]), &NumberOfCharsRead, &console_ctrl)) 734 | + { 735 | + errno = 0; /* Caller should check GetLastError(). */ 736 | + return -1; 737 | + } 738 | + 739 | + /* Console is a text stream, so convert CRLF->LF. */ 740 | + if (NumberOfCharsRead >= 2 && 741 | + console_rbuf[NumberOfCharsRead - 2] == L'\r' && 742 | + console_rbuf[NumberOfCharsRead - 1] == L'\n') 743 | + console_rbuf[--NumberOfCharsRead - 1] = L'\n'; 744 | + 745 | + console_rbuf_filled = NumberOfCharsRead; 746 | + return 0; 747 | +} 748 | + 749 | +/* As a workaround to MS UCRT bugs, call ReadConsoleW 750 | + directly. */ 751 | +/* Note: fread() internally calls ReadFile, which 752 | + in turn seems like calls ReadConsole expecting 753 | + that it will return number of bytes read. But 754 | + ReadConsole returns number of _chars_ read. 755 | + As result, reading stops if read just one byte 756 | + of a multibyte character. */ 757 | +/* Returns number of bytes read, < size on eof/error: 758 | + - caller should check errno, then GetLastError(). */ 759 | +static size_t 760 | +read_from_console (void *ptr, size_t size, HANDLE ch) 761 | +{ 762 | + char *d = (char*) ptr; 763 | + const char *const e = d + size; 764 | + 765 | + if (remaining_rbuf_filled) 766 | + { 767 | + unsigned to_copy = remaining_rbuf_filled; 768 | + if (to_copy > size) 769 | + to_copy = (unsigned) size; 770 | + d = to_copy + (char*) memcpy (d, 771 | + &remaining_rbuf[remaining_rbuf_offset], to_copy); 772 | + remaining_rbuf_filled -= to_copy; 773 | + if (remaining_rbuf_filled || d == e) 774 | + { 775 | + remaining_rbuf_offset += to_copy; 776 | + return size; 777 | + } 778 | + } 779 | + 780 | + for (;; console_rbuf_offset = 0) 781 | + { 782 | + /* Convert wide-characters. */ 783 | + while (console_rbuf_filled) 784 | + { 785 | + int n; 786 | + 787 | + if (is_win_console_stop_input) 788 | + goto stop_input; 789 | + 790 | + n = wctomb (remaining_rbuf, console_rbuf[console_rbuf_offset]); 791 | + if (n < 0) 792 | + { 793 | + /* Cannot convert wide-char to multibyte in current locale. */ 794 | + errno = EILSEQ; 795 | + return (size_t) (d - (char*) ptr); /* < size */ 796 | + } 797 | + 798 | + console_rbuf_filled--; 799 | + console_rbuf_offset++; 800 | + 801 | + { 802 | + unsigned to_copy = n; 803 | + if (to_copy > (size_t) (e - d)) 804 | + to_copy = (unsigned) (e - d); 805 | + d = to_copy + (char*) memcpy (d, remaining_rbuf, to_copy); 806 | + if (d == e) 807 | + { 808 | + remaining_rbuf_filled = (unsigned) n - to_copy; 809 | + remaining_rbuf_offset = to_copy; 810 | + return (size_t) (d - (char*) ptr); /* == size */ 811 | + } 812 | + } 813 | + } 814 | + 815 | + /* Read from the console. */ 816 | + if (read_from_console_w (ch)) 817 | + return (size_t) (d - (char*) ptr); /* < size */ 818 | + } 819 | + 820 | +stop_input: 821 | + /* EOF: no error - both errno and last error are zero. */ 822 | + errno = 0; 823 | + SetLastError (0); 824 | + return (size_t) (d - (char*) ptr); /* < size */ 825 | +} 826 | + 827 | +/* As a workaround to MS UCRT bugs, call ReadConsoleW 828 | + directly. */ 829 | +/* Returns number of bytes read, including delimiter, but 830 | + not including terminating '\0', returns -1 on eof or error: 831 | + - caller should check errno, then GetLastError(). */ 832 | +static ssize_t 833 | +read_from_console_delim (char **text, size_t *buflen, char buffer_delimiter, HANDLE ch) 834 | +{ 835 | + size_t filled = 0; 836 | + 837 | + /* Previous ck_fread() should read whole multibyte characters, 838 | + (possibly by multiple calls). */ 839 | + if (remaining_rbuf_filled) 840 | + panic (_("encountered partially read multibyte character")); 841 | + 842 | + for (;; console_rbuf_offset = 0) 843 | + { 844 | + /* Convert wide-characters. */ 845 | + while (console_rbuf_filled) 846 | + { 847 | + char tmp[MB_LEN_MAX]; 848 | + int n; 849 | + 850 | + if (is_win_console_stop_input) 851 | + goto stop_input; 852 | + 853 | + n = wctomb (tmp, console_rbuf[console_rbuf_offset]); 854 | + if (n < 0) 855 | + { 856 | + /* Cannot convert wide-char to multibyte in current locale. */ 857 | + errno = EILSEQ; 858 | + return -1; 859 | + } 860 | + 861 | + console_rbuf_filled--; 862 | + console_rbuf_offset++; 863 | + 864 | + /* One byte is needed for the terminating '\0'. */ 865 | + if ((unsigned) n + 1 > *buflen - filled) 866 | + { 867 | + /* Don't have a space, need to realloc. */ 868 | +#ifndef READ_FROM_CONSOLE_DELIM_REALLOC_SIZE 869 | +#define READ_FROM_CONSOLE_DELIM_REALLOC_SIZE 256 /* Must be > MB_LEN_MAX */ 870 | +#endif 871 | + (void)sizeof(int[1-2*(READ_FROM_CONSOLE_DELIM_REALLOC_SIZE <= MB_LEN_MAX)]); 872 | + { 873 | + size_t need = *buflen + READ_FROM_CONSOLE_DELIM_REALLOC_SIZE; 874 | + void *new_buf = xrealloc (*text, need); 875 | + *text = (char*) new_buf; 876 | + *buflen = need; 877 | + } 878 | + } 879 | + 880 | + memcpy (*text + filled, tmp, (unsigned) n); 881 | + filled += (unsigned) n; 882 | + 883 | + if ((*text)[filled - 1] == buffer_delimiter) 884 | + { 885 | + (*text)[filled] = '\0'; 886 | + return (ssize_t) filled; 887 | + } 888 | + } 889 | + 890 | + /* Read from the console. */ 891 | + if (read_from_console_w (ch)) 892 | + return -1; 893 | + } 894 | + 895 | +stop_input: 896 | + if (filled) 897 | + { 898 | + (*text)[filled] = '\0'; 899 | + return (ssize_t) filled; 900 | + } 901 | + 902 | + /* EOF: no error - both errno and last error are zero. */ 903 | + errno = 0; 904 | + SetLastError (0); 905 | + return -1; 906 | +} 907 | + 908 | +/* Writing to console failed - panic. 909 | + First checks errno, then GetLastError(). */ 910 | +static void 911 | +write_console_panic (void) 912 | +{ 913 | + if (EILSEQ == errno) 914 | + panic (_("failed to write to console: cannot to convert character" 915 | + " (LC_CTYPE=%s -> Unicode): %s"), setlocale (LC_CTYPE, NULL), 916 | + strerror (errno)); 917 | + 918 | + if (errno) 919 | + panic (_("failed to write to console: %s"), strerror (errno)); 920 | + 921 | + { 922 | + const DWORD last_err = GetLastError (); 923 | + const char *msg = get_last_err_msg (last_err); 924 | + panic (_("failed to write to console, system error: 0x%x (%s)"), 925 | + last_err, msg); 926 | + } 927 | +} 928 | + 929 | +/* Check if reading from console failed. 930 | + First checks errno, then GetLastError(). 931 | + Panics on error. */ 932 | +static void 933 | +check_read_console_error (void) 934 | +{ 935 | + if (EILSEQ == errno) 936 | + panic (_("failed to read from console: cannot to convert character" 937 | + " (Unicode -> LC_CTYPE=%s): %s"), setlocale (LC_CTYPE, NULL), 938 | + strerror (errno)); 939 | + 940 | + if (errno) 941 | + panic (_("failed to read from console: %s"), strerror (errno)); 942 | + 943 | + { 944 | + DWORD last_err = GetLastError (); 945 | + if (last_err) 946 | + { 947 | + const char *msg = get_last_err_msg (last_err); 948 | + panic (_("failed to read from console, system error: 0x%x (%s)"), 949 | + last_err, msg); 950 | + } 951 | + } 952 | + 953 | + /* No error. */ 954 | +} 955 | + 956 | +#endif /* WINDOWS_NATIVE */ 957 | + 958 | /* Panic on failing fwrite */ 959 | void 960 | ck_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) 961 | { 962 | clearerr (stream); 963 | - if (size && fwrite (ptr, size, nmemb, stream) != nmemb) 964 | - panic (ngettext ("couldn't write %llu item to %s: %s", 965 | - "couldn't write %llu items to %s: %s", nmemb), 966 | - (unsigned long long) nmemb, utils_fp_name (stream), 967 | - strerror (errno)); 968 | + if (!size || !nmemb) 969 | + return; 970 | + 971 | +#ifdef WINDOWS_NATIVE 972 | + { 973 | + const HANDLE ch = get_console_handle (fileno (stream)); 974 | + if (ch != INVALID_HANDLE_VALUE) 975 | + { 976 | + if (write_to_console (ptr, size*nmemb, ch)) 977 | + write_console_panic (); 978 | + return; 979 | + } 980 | + } 981 | +#endif /* WINDOWS_NATIVE */ 982 | + 983 | + if (fwrite (ptr, size, nmemb, stream) == nmemb) 984 | + return; 985 | + 986 | + panic (ngettext ("couldn't write %llu item to %s: %s", 987 | + "couldn't write %llu items to %s: %s", nmemb), 988 | + (unsigned long long) nmemb, utils_fp_name (stream), 989 | + strerror (errno)); 990 | } 991 | 992 | /* Panic on failing fread */ 993 | @@ -215,7 +732,31 @@ 994 | ck_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) 995 | { 996 | clearerr (stream); 997 | - if (size && (nmemb=fread (ptr, size, nmemb, stream)) <= 0 && ferror (stream)) 998 | + if (!size) 999 | + return nmemb; 1000 | + 1001 | +#ifdef WINDOWS_NATIVE 1002 | + { 1003 | + const HANDLE ch = get_console_handle (fileno (stream)); 1004 | + if (ch != INVALID_HANDLE_VALUE) 1005 | + { 1006 | + /* Item sizes other than 1 (byte) are not supported. */ 1007 | + if (size != 1) 1008 | + panic (_("ck_fread assert: item size != 1")); 1009 | + 1010 | + { 1011 | + const size_t nread = read_from_console (ptr, nmemb, ch); 1012 | + 1013 | + if (nread < nmemb) 1014 | + check_read_console_error (); 1015 | + 1016 | + return nread; 1017 | + } 1018 | + } 1019 | + } 1020 | +#endif /* WINDOWS_NATIVE */ 1021 | + 1022 | + if ((nmemb=fread (ptr, size, nmemb, stream)) <= 0 && ferror (stream)) 1023 | panic (_("read error on %s: %s"), utils_fp_name (stream), strerror (errno)); 1024 | 1025 | return nmemb; 1026 | @@ -224,12 +765,24 @@ 1027 | size_t 1028 | ck_getdelim (char **text, size_t *buflen, char buffer_delimiter, FILE *stream) 1029 | { 1030 | - ssize_t result; 1031 | + ssize_t result = -1; /* Make compiler happy. */ 1032 | bool error; 1033 | 1034 | error = ferror (stream); 1035 | if (!error) 1036 | { 1037 | +#ifdef WINDOWS_NATIVE 1038 | + const HANDLE ch = get_console_handle (fileno (stream)); 1039 | + if (ch != INVALID_HANDLE_VALUE) 1040 | + { 1041 | + result = read_from_console_delim (text, buflen, buffer_delimiter, ch); 1042 | + 1043 | + if (result < 0) 1044 | + check_read_console_error (); 1045 | + 1046 | + return result; /* -1 if no line was read (and there is EOF). */ 1047 | + } 1048 | +#endif /* WINDOWS_NATIVE */ 1049 | result = getdelim (text, buflen, buffer_delimiter, stream); 1050 | error = ferror (stream); 1051 | } 1052 | -------------------------------------------------------------------------------- /sed-4.9-src.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.9/lib/localcharset.c sed-4.9-patched/lib/localcharset.c 2 | --- sed-4.9/lib/localcharset.c 2022-07-02 21:22:03.000000000 +0300 3 | +++ sed-4.9-patched/lib/localcharset.c 2022-11-23 16:34:49.440865300 +0300 4 | @@ -925,25 +925,32 @@ 5 | char *current_locale = setlocale (LC_CTYPE, NULL); 6 | char *pdot = strrchr (current_locale, '.'); 7 | 8 | - if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) 9 | - sprintf (buf, "CP%s", pdot + 1); 10 | - else 11 | - { 12 | - /* The Windows API has a function returning the locale's codepage as a 13 | - number: GetACP(). 14 | - When the output goes to a console window, it needs to be provided in 15 | - GetOEMCP() encoding if the console is using a raster font, or in 16 | - GetConsoleOutputCP() encoding if it is using a TrueType font. 17 | - But in GUI programs and for output sent to files and pipes, GetACP() 18 | - encoding is the best bet. */ 19 | - sprintf (buf, "CP%u", GetACP ()); 20 | - } 21 | - /* For a locale name such as "French_France.65001", in Windows 10, 22 | - setlocale now returns "French_France.utf8" instead. */ 23 | - if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0) 24 | + /* After a dot may follow a codepage number, or the "utf8"/"utf-8" string, 25 | + in any case. For example, "Russian_Russia.uTf-8". */ 26 | + /* Also, iterpret the code page number 65001 as utf8. */ 27 | + if (pdot && (!strcmp (pdot + 1, "65001") || ( 28 | + ('u' == pdot[1] || 'U' == pdot[1]) && 29 | + ('t' == pdot[2] || 'T' == pdot[2]) && 30 | + ('f' == pdot[3] || 'F' == pdot[3]) && 31 | + (('8' == pdot[4] && '\0' == pdot[5]) || 32 | + ('-' == pdot[4] && '8' == pdot[5] && '\0' == pdot[6]))))) 33 | codeset = "UTF-8"; 34 | else 35 | { 36 | + if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) 37 | + sprintf (buf, "CP%s", pdot + 1); 38 | + else 39 | + { 40 | + /* The Windows API has a function returning the locale's codepage as a 41 | + number: GetACP(). 42 | + When the output goes to a console window, it needs to be provided in 43 | + GetOEMCP() encoding if the console is using a raster font, or in 44 | + GetConsoleOutputCP() encoding if it is using a TrueType font. 45 | + But in GUI programs and for output sent to files and pipes, GetACP() 46 | + encoding is the best bet. */ 47 | + sprintf (buf, "CP%u", GetACP ()); 48 | + } 49 | + 50 | strcpy (resultbuf, buf); 51 | codeset = resultbuf; 52 | } 53 | diff -Naur sed-4.9/lib/nl_langinfo.c sed-4.9-patched/lib/nl_langinfo.c 54 | --- sed-4.9/lib/nl_langinfo.c 2022-07-02 21:22:03.000000000 +0300 55 | +++ sed-4.9-patched/lib/nl_langinfo.c 2022-11-23 16:45:34.097132300 +0300 56 | @@ -113,21 +113,27 @@ 57 | GetACP, which returns the locale's codepage as a number (although 58 | this doesn't change according to what the 'setlocale' call specified). 59 | Either way, prepend "CP" to make it a valid codeset name. */ 60 | + 61 | + /* After a dot may follow a codepage number, or the "utf8"/"utf-8" string 62 | + in any case. For example, "Russian_Russia.uTf-8". */ 63 | + /* Also, iterpret the code page number 65001 as utf8. */ 64 | + if (!strcmp (codeset, "65001") || ( 65 | + ('u' == codeset[0] || 'U' == codeset[0]) && 66 | + ('t' == codeset[1] || 'T' == codeset[1]) && 67 | + ('f' == codeset[2] || 'F' == codeset[2]) && 68 | + (('8' == codeset[3] && '\0' == codeset[4]) || 69 | + ('-' == codeset[3] && '8' == codeset[4] && '\0' == codeset[5])))) 70 | + return (char *) "UTF-8"; 71 | + 72 | codesetlen = strlen (codeset); 73 | if (0 < codesetlen && codesetlen < sizeof buf - 2) 74 | memmove (buf + 2, codeset, codesetlen + 1); 75 | else 76 | sprintf (buf + 2, "%u", GetACP ()); 77 | - /* For a locale name such as "French_France.65001", in Windows 10, 78 | - setlocale now returns "French_France.utf8" instead. */ 79 | - if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0) 80 | - return (char *) "UTF-8"; 81 | - else 82 | - { 83 | - memcpy (buf, "CP", 2); 84 | - strcpy (result, buf); 85 | - return result; 86 | - } 87 | + 88 | + memcpy (buf, "CP", 2); 89 | + strcpy (result, buf); 90 | + return result; 91 | # else 92 | strcpy (result, codeset); 93 | return result; 94 | diff -Naur sed-4.9/sed/execute.c sed-4.9-patched/sed/execute.c 95 | --- sed-4.9/sed/execute.c 2022-07-03 01:22:03.000000000 +0300 96 | +++ sed-4.9-patched/sed/execute.c 2022-11-23 16:50:44.097129200 +0300 97 | @@ -37,6 +37,8 @@ 98 | #include "progname.h" 99 | #include "xalloc.h" 100 | 101 | +#include "dirname.h" 102 | + 103 | /* The number of extra bytes that must be allocated/usable, beyond 104 | the declared "end" of each line buffer that may be passed to 105 | match_regex. This is imposed by its use of dfaexec. */ 106 | @@ -575,17 +577,22 @@ 107 | if (in_place_extension) 108 | { 109 | int input_fd; 110 | - char *tmpdir, *p; 111 | + char *tmpdir; 112 | char *old_fscreatecon; 113 | int reset_fscreatecon = 0; 114 | + size_t in_dir_len; 115 | memset (&old_fscreatecon, 0, sizeof (old_fscreatecon)); 116 | 117 | /* get the base name */ 118 | - tmpdir = xstrdup (input->in_file_name); 119 | - if ((p = strrchr (tmpdir, '/'))) 120 | - *p = 0; 121 | + in_dir_len = dir_len (input->in_file_name); 122 | + if (in_dir_len) 123 | + { 124 | + tmpdir = xmalloc (in_dir_len + 1); 125 | + memcpy (tmpdir, input->in_file_name, in_dir_len); 126 | + tmpdir[in_dir_len] = '\0'; 127 | + } 128 | else 129 | - strcpy (tmpdir, "."); 130 | + tmpdir = xstrdup ("."); 131 | 132 | if (isatty (fileno (input->fp))) 133 | panic (_("couldn't edit %s: is a terminal"), input->in_file_name); 134 | diff -Naur sed-4.9/sed/sed.c sed-4.9-patched/sed/sed.c 135 | --- sed-4.9/sed/sed.c 2022-09-15 22:51:33.000000000 +0300 136 | +++ sed-4.9-patched/sed/sed.c 2022-11-25 16:40:34.552985200 +0300 137 | @@ -67,9 +67,17 @@ 138 | /* How do we edit files in-place? (we don't if NULL) */ 139 | char *in_place_extension = NULL; 140 | 141 | -/* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ 142 | +/* The mode to use to read/write files, either "r(t)"/"w(t)" or "rb"/"wb". */ 143 | +#ifdef HAVE_FOPEN_RT 144 | +char const *read_mode = "rt"; 145 | +char const *write_mode = "wt"; 146 | +#else 147 | char const *read_mode = "r"; 148 | char const *write_mode = "w"; 149 | +#endif 150 | + 151 | +/* Locale to set at startup. */ 152 | +char const *def_locale = ""; 153 | 154 | #if O_BINARY 155 | /* Additional flag for binary mode on platforms with O_BINARY/O_TEXT. */ 156 | @@ -96,6 +104,145 @@ 157 | remove_cleanup_file (); 158 | } 159 | 160 | +#if defined _WIN32 && !defined __CYGWIN__ 161 | +#define WINDOWS_NATIVE 162 | +#endif 163 | + 164 | +#ifdef WINDOWS_NATIVE 165 | + 166 | +/* Get value of command-line option: 167 | + --lo[cale]=locale-name or --lo[cale] locale-name, 168 | + Returns option value or NULL if the option is not specified. 169 | + Panics if the option specified without a value, 170 | + else terminates opt_name_array to the length of the option name. */ 171 | +/* Note: before the call, opt_name_array must contain "--locale". */ 172 | +static const wchar_t * 173 | +get_specified_locale (wchar_t **wa, char opt_name_array[]) 174 | +{ 175 | + const wchar_t *w = NULL; 176 | + for (; *wa; wa++) 177 | + { 178 | + w = *wa; 179 | + if (L'-' != w[0] || L'-' != w[1] || L'l' != w[2] || L'o' != w[3]) 180 | + continue; 181 | + w += 4; 182 | + if (L'=' == *w || !*w) 183 | + break; 184 | + if (L'c' != *w) 185 | + continue; 186 | + w++; 187 | + if (L'=' == *w || !*w) 188 | + break; 189 | + if (L'a' != *w) 190 | + continue; 191 | + w++; 192 | + if (L'=' == *w || !*w) 193 | + break; 194 | + if (L'l' != *w) 195 | + continue; 196 | + w++; 197 | + if (L'=' == *w || !*w) 198 | + break; 199 | + if (L'e' != *w) 200 | + continue; 201 | + w++; 202 | + if (L'=' == *w || !*w) 203 | + break; 204 | + } 205 | + 206 | + if (!*wa) 207 | + return NULL; /* --lo[cale] option wasn't found. */ 208 | + 209 | + opt_name_array[(unsigned) (w - *wa)] = '\0'; 210 | + if (*w) 211 | + return w + 1; /* --lo[cale]=locale-name, return locale-name. */ 212 | + 213 | + /* --lo[cale] locale-name. */ 214 | + { 215 | + const wchar_t *locale_name = wa[1]; 216 | + if (!locale_name) 217 | + panic (_("option '%s' requires an argument"), opt_name_array); 218 | + return locale_name; 219 | + } 220 | +} 221 | + 222 | +/* Set locale based on the values of environment variables. */ 223 | +static void 224 | +set_locale_from_env (const char *def) 225 | +{ 226 | + const char *locale = getenv ("LC_ALL"); 227 | + if (locale && locale[0]) 228 | + { 229 | + if (!setlocale (LC_ALL, locale)) 230 | + panic (_("Bad locale: LC_ALL=%s"), locale); 231 | + return; 232 | + } 233 | + 234 | + /* LANG is the default for all LC_... */ 235 | + locale = getenv ("LANG"); 236 | + 237 | + /* if LANG is not defined - set the system default. 238 | + (If def is "", locale may be be set to 239 | + e.g. Russian_Russia.1251). */ 240 | + if (!locale || !locale[0]) 241 | + locale = def; 242 | + 243 | + if (!setlocale (LC_ALL, locale)) 244 | + panic (_("Bad locale: LANG=%s"), locale); 245 | + 246 | + /* specific LC_... take precedence over LANG. */ 247 | + locale = getenv ("LC_CTYPE"); 248 | + if (locale && locale[0]) 249 | + { 250 | + if (!setlocale (LC_CTYPE, locale)) 251 | + panic (_("Bad locale: LC_CTYPE=%s"), locale); 252 | + } 253 | +} 254 | + 255 | +/* Convert wide-char args to multibyte. */ 256 | +static char ** 257 | +convert_wargv (int argc, wchar_t **wargv) 258 | +{ 259 | + /* Convert program arguments from wide-char to multibyte 260 | + according to the locale codepage. */ 261 | + /* Note: argv array must be NULL-terminated. */ 262 | + char **argv = (char**) xmalloc (sizeof(*argv)*(argc + 1)); 263 | + 264 | + wchar_t **wa = wargv; 265 | + for (; *wa; wa++) 266 | + { 267 | + const size_t need = wcstombs (NULL, *wa, 0); 268 | + 269 | + if ((size_t) -1 == need) 270 | + panic (_("failed to convert argument %u (Unicode -> LC_CTYPE=%s): %s"), 271 | + (unsigned) (wa - wargv), setlocale (LC_CTYPE, NULL), 272 | + strerror (errno)); 273 | + 274 | + { 275 | + char *a = (char*) xmalloc (need + 1); 276 | + wcstombs (a, *wa, need + 1); 277 | + argv[wa - wargv] = a; 278 | + } 279 | + } 280 | + 281 | + /* argv - is a NULL-terminated array of pointers */ 282 | + argv[wa - wargv] = NULL; 283 | + 284 | + return argv; 285 | +} 286 | + 287 | +/* Free arguments array allocated by convert_wargv (). */ 288 | +static void 289 | +free_argv (char **argv) 290 | +{ 291 | + char **a = argv; 292 | + for (; *a; a++) 293 | + free (*a); 294 | + free (argv); 295 | +} 296 | + 297 | +#endif /* WINDOWS_NATIVE */ 298 | + 299 | static void 300 | contact (int errmsg) 301 | { 302 | @@ -107,6 +254,9 @@ 303 | get reports for other people's bugs. */ 304 | if (!errmsg) 305 | fprintf (out, _("E-mail bug reports to: <%s>.\n"), PACKAGE_BUGREPORT); 306 | + 307 | + if (!errmsg) 308 | + fprintf (out, _("Patched (v2) by: Michael M. Builov .\n")); 309 | } 310 | 311 | static void 312 | @@ -154,6 +304,13 @@ 313 | open files in binary mode (CR+LFs are not" \ 314 | " processed specially)\n")); 315 | #endif 316 | + fprintf (out, _(" -C, --ignore-locale\n\ 317 | + ignore system locale, operate in the default \"C\" locale\n")); 318 | +#ifdef WINDOWS_NATIVE 319 | + fprintf (out, _(" --locale=locale-name\n\ 320 | + use the specified locale (ignore environment" \ 321 | + " variables LC_ALL, LC_CTYPE and LANG)\n")); 322 | +#endif 323 | fprintf (out, _(" -l N, --line-length=N\n\ 324 | specify the desired line-wrap length for the `l' command\n")); 325 | fprintf (out, _(" --posix\n\ 326 | @@ -186,16 +343,24 @@ 327 | } 328 | 329 | int 330 | +#ifndef WINDOWS_NATIVE 331 | main (int argc, char **argv) 332 | +#else 333 | +wmain (int argc, wchar_t **wargv) 334 | +#endif 335 | { 336 | -#define SHORTOPTS "bsnrzuEe:f:l:i::V:" 337 | +#define SHORTOPTS "bCsnrzuEe:f:l:i::V:" 338 | 339 | enum { SANDBOX_OPTION = CHAR_MAX+1, 340 | DEBUG_OPTION 341 | +#ifdef WINDOWS_NATIVE 342 | + ,LOCALE_OPTION 343 | +#endif 344 | }; 345 | 346 | static const struct option longopts[] = { 347 | {"binary", 0, NULL, 'b'}, 348 | + {"ignore-locale", 0, NULL, 'C'}, 349 | {"regexp-extended", 0, NULL, 'r'}, 350 | {"debug", 0, NULL, DEBUG_OPTION}, 351 | {"expression", 1, NULL, 'e'}, 352 | @@ -215,6 +380,9 @@ 353 | #ifdef HAVE_READLINK 354 | {"follow-symlinks", 0, NULL, 'F'}, 355 | #endif 356 | +#ifdef WINDOWS_NATIVE 357 | + {"locale", 1, NULL, LOCALE_OPTION}, 358 | +#endif 359 | {NULL, 0, NULL, 0} 360 | }; 361 | 362 | @@ -222,11 +390,68 @@ 363 | int return_code; 364 | const char *cols = getenv ("COLS"); 365 | 366 | +#ifdef WINDOWS_NATIVE 367 | + char **old_argv = NULL; 368 | + char **argv; 369 | + 370 | + /* Set locale according to user's wishes. 371 | + (Current locale is "C"). */ 372 | + char opt_name_array[] = "--locale"; 373 | + const wchar_t *spec_locale; 374 | + 375 | + /* Temporary set program name. 376 | + This is needed for error messages - in case of bad locale. */ 377 | + set_program_name ("sed"); 378 | + 379 | + /* Command-line option takes precedence over environment vars. */ 380 | + spec_locale = get_specified_locale (wargv, opt_name_array); 381 | + if (!spec_locale) 382 | + set_locale_from_env (def_locale); 383 | + else if (!_wsetlocale (LC_ALL, spec_locale)) 384 | + panic (_("Bad locale name specified by the option '%s'"), opt_name_array); 385 | + 386 | + /* Convert program arguments to multibyte strings. */ 387 | + argv = convert_wargv (argc, wargv); 388 | +#endif /* WINDOWS_NATIVE */ 389 | + 390 | set_program_name (argv[0]); 391 | initialize_main (&argc, &argv); 392 | + 393 | + /* Suppress error reporting in getopt. */ 394 | + opterr = 0; 395 | + 396 | + while ((opt = getopt_long (argc, argv, SHORTOPTS, longopts, NULL)) != EOF) 397 | + { 398 | + switch (opt) 399 | + { 400 | + case 'C': 401 | + def_locale = "C"; 402 | + break; 403 | + } 404 | + } 405 | + 406 | + /* Restore getopt behaviour. */ 407 | + opterr = 1; 408 | + optind = 1; 409 | + 410 | #if HAVE_SETLOCALE 411 | +#ifndef WINDOWS_NATIVE 412 | /* Set locale according to user's wishes. */ 413 | - setlocale (LC_ALL, ""); 414 | + setlocale (LC_ALL, def_locale); 415 | +#else /* WINDOWS_NATIVE */ 416 | + if (def_locale[0]) 417 | + { 418 | + /* User wants to use "C"-locale. */ 419 | + if (spec_locale) 420 | + panic (_("Options '-C/--ignore-locale' and '--locale' cannot be used together.")); 421 | + setlocale (LC_ALL, def_locale); 422 | + 423 | + /* Cannot free argv array now: 424 | + argv[0] was passed to set_program_name (). */ 425 | + old_argv = argv; 426 | + argv = convert_wargv (argc, wargv); 427 | + } 428 | +#endif /* WINDOWS_NATIVE */ 429 | #endif 430 | initialize_mbcs (); 431 | init_localeinfo (&localeinfo); 432 | @@ -315,6 +540,10 @@ 433 | #endif 434 | break; 435 | 436 | + case 'C': 437 | + /* already processed */ 438 | + break; 439 | + 440 | case 'E': 441 | case 'r': 442 | extended_regexp_flags = REG_EXTENDED; 443 | @@ -332,6 +561,12 @@ 444 | debug = true; 445 | break; 446 | 447 | +#ifdef WINDOWS_NATIVE 448 | + case LOCALE_OPTION: 449 | + /* already processed */ 450 | + break; 451 | +#endif 452 | + 453 | case 'u': 454 | unbuffered = true; 455 | break; 456 | @@ -370,6 +605,15 @@ 457 | if (set_binary_mode ( fileno (stdout), O_BINARY) == -1) 458 | panic (_("failed to set binary mode on STDOUT")); 459 | } 460 | + else 461 | + { 462 | + /* Under CYGWIN, standard input/output streams are in BINARY 463 | + mode by default, make sure they are in TEXT mode. */ 464 | + if (set_binary_mode ( fileno (stdin), O_TEXT) == -1) 465 | + panic (_("failed to set binary mode on STDIN")); 466 | + if (set_binary_mode ( fileno (stdout), O_TEXT) == -1) 467 | + panic (_("failed to set binary mode on STDOUT")); 468 | + } 469 | #endif 470 | 471 | if (debug) 472 | @@ -380,5 +624,11 @@ 473 | finish_program (the_program); 474 | ck_fclose (NULL); 475 | 476 | +#ifdef WINDOWS_NATIVE 477 | + if (old_argv) 478 | + free_argv (old_argv); 479 | + free_argv (argv); 480 | +#endif 481 | + 482 | return return_code; 483 | } 484 | diff -Naur sed-4.9/sed/utils.c sed-4.9-patched/sed/utils.c 485 | --- sed-4.9/sed/utils.c 2022-09-15 22:51:33.000000000 +0300 486 | +++ sed-4.9-patched/sed/utils.c 2022-11-25 10:41:20.381142300 +0300 487 | @@ -14,6 +14,12 @@ 488 | You should have received a copy of the GNU General Public License 489 | along with this program; If not, see . */ 490 | 491 | +#if defined _WIN32 && !defined __CYGWIN__ 492 | +#define WIN32_LEAN_AND_MEAN 493 | +#include 494 | +#define WINDOWS_NATIVE 495 | +#endif 496 | + 497 | #include 498 | 499 | #include 500 | @@ -219,16 +225,527 @@ 501 | return fp; 502 | } 503 | 504 | +#ifdef WINDOWS_NATIVE 505 | + 506 | +/* Convert wide-character string to multibyte. 507 | + Returns NULL on error, else - malloc'ated '\0'-terminated 508 | + string, which caller should free via free(). */ 509 | +static char * 510 | +convert_wc_to_mb (const wchar_t *wc) 511 | +{ 512 | + const size_t need = wcstombs (NULL, wc, 0); 513 | + 514 | + if ((size_t) -1 == need) 515 | + return NULL; /* Error. errno is set to EILSEQ. */ 516 | + 517 | + { 518 | + char *a = (char*) xmalloc (need + 1); 519 | + wcstombs (a, wc, need + 1); 520 | + return a; 521 | + } 522 | +} 523 | + 524 | +/* Called on panic. */ 525 | +static const char * 526 | +get_last_err_msg (unsigned int last_err) 527 | +{ 528 | + /* First try to get message in locale encoding. */ 529 | + wchar_t *wmsg; 530 | + DWORD n_chars = FormatMessageW ( 531 | + FORMAT_MESSAGE_ALLOCATE_BUFFER | 532 | + FORMAT_MESSAGE_FROM_SYSTEM | 533 | + FORMAT_MESSAGE_IGNORE_INSERTS, 534 | + NULL, last_err, 0, (LPWSTR) &wmsg, 0, NULL); 535 | + 536 | + /* trim "\r\n" at end of msg */ 537 | + if (n_chars && L'\n' == wmsg[n_chars - 1]) 538 | + { 539 | + wmsg[--n_chars] = L'\0'; 540 | + if (n_chars && L'\r' == wmsg[n_chars - 1]) 541 | + wmsg[--n_chars] = L'\0'; 542 | + } 543 | + 544 | + if (!n_chars) 545 | + return ""; 546 | + 547 | + { 548 | + char *msg = convert_wc_to_mb (wmsg); 549 | + if (msg) 550 | + { 551 | + /* Check if failed to translate message to locale code page. */ 552 | + const char *c = msg; 553 | + while ('?' == *c || ' ' == *c) 554 | + c++; 555 | + if ('.' == *c && !c[1]) 556 | + c++; /* Something like "?????." */ 557 | + if (!*c) 558 | + { 559 | + free (msg); 560 | + msg = NULL; 561 | + } 562 | + } 563 | + 564 | + if (!msg) 565 | + { 566 | + /* Just get error message in English. */ 567 | + n_chars = FormatMessageA ( 568 | + FORMAT_MESSAGE_ALLOCATE_BUFFER | 569 | + FORMAT_MESSAGE_FROM_SYSTEM | 570 | + FORMAT_MESSAGE_IGNORE_INSERTS, 571 | + NULL, last_err, 572 | + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 573 | + (LPSTR) &msg, 0, NULL); 574 | + 575 | + /* trim "\r\n" at end of msg */ 576 | + if (n_chars && '\n' == msg[n_chars - 1]) 577 | + { 578 | + msg[--n_chars] = '\0'; 579 | + if (n_chars && '\r' == msg[n_chars - 1]) 580 | + msg[--n_chars] = '\0'; 581 | + } 582 | + 583 | + if (!n_chars) 584 | + return ""; 585 | + } 586 | + 587 | + return msg; 588 | + } 589 | +} 590 | + 591 | +/* Check if file descriptor fd designates a console. 592 | + If this is true, then due to bugs in MS UCRT, 593 | + standard stream i/o functions read(2)/write(2) 594 | + on the fd may fail, e.g. if the console may print 595 | + one symbol per multibyte character (for example, 596 | + if LC_CTYPE=Russian_Russia.1251 and the console 597 | + code page is 65001). */ 598 | +/* Return INVALID_HANDLE_VALUE if fd do not belongs 599 | + to a console. */ 600 | +static HANDLE 601 | +get_console_handle (int fd) 602 | +{ 603 | + HANDLE ch; 604 | + DWORD mode; 605 | + 606 | + if (!_isatty (fd)) 607 | + return INVALID_HANDLE_VALUE; 608 | + 609 | + ch = (HANDLE) _get_osfhandle (fd); 610 | + if (ch != INVALID_HANDLE_VALUE && 611 | + GetConsoleMode (ch, &mode)) 612 | + return ch; 613 | + 614 | + /* Not a console handle. */ 615 | + return INVALID_HANDLE_VALUE; 616 | +} 617 | + 618 | +/* As a workaround to MS UCRT bugs, call WriteConsoleW 619 | + directly. */ 620 | +/* Note: fwrite() internally calls WriteFile, which 621 | + in turn seems like calls WriteConsole expecting 622 | + that it will return number of bytes written. But 623 | + WriteConsole returns number of _chars_ written. 624 | + As result, writing stops after printing only one 625 | + multibyte character. */ 626 | +/* Returns non-zero on error: 627 | + - caller should check errno, then GetLastError(). */ 628 | +static int 629 | +write_to_console (const void *ptr, size_t size, HANDLE ch) 630 | +{ 631 | + /* Write only full mulitbyte chars, so may need to cache 632 | + a part of unwritten multibyte char. */ 633 | + static char remaining_wbuf[MB_LEN_MAX]; 634 | + static unsigned remaining_wbuf_filled = 0; 635 | + 636 | +#ifndef WINDOWS_CONSOLE_WBUF_SIZE 637 | +#define WINDOWS_CONSOLE_WBUF_SIZE 512 /* Must be > 1. */ 638 | +#endif 639 | + wchar_t tmp[WINDOWS_CONSOLE_WBUF_SIZE]; 640 | + wchar_t *at = tmp; 641 | + const char *c = (const char*) ptr; 642 | + const char *const e = c + size; 643 | + int n; 644 | + 645 | + if (remaining_wbuf_filled) 646 | + { 647 | + unsigned to_copy = sizeof(remaining_wbuf) - remaining_wbuf_filled; 648 | + if (to_copy > size) 649 | + to_copy = (unsigned) size; 650 | + memcpy (&remaining_wbuf[remaining_wbuf_filled], c, to_copy); 651 | + remaining_wbuf_filled += to_copy; 652 | + 653 | + n = mbtowc (at, remaining_wbuf, remaining_wbuf_filled); 654 | + if (n < 0) 655 | + { 656 | + if (remaining_wbuf_filled < sizeof(remaining_wbuf)) 657 | + return 0; /* need more bytes of multibyte char for one wide-character */ 658 | + 659 | + /* Cannot convert multibyte to wide-char in current locale. */ 660 | + errno = EILSEQ; 661 | + return -1; 662 | + } 663 | + 664 | + c += to_copy - (remaining_wbuf_filled - n); 665 | + remaining_wbuf_filled = 0; 666 | + at++; 667 | + } 668 | + 669 | + for (; c < e; at = tmp) 670 | + { 671 | + /* Convert to wide-characters. */ 672 | + do 673 | + { 674 | + const size_t to_convert = (size_t) (e - c); 675 | + n = mbtowc (at, c, to_convert); 676 | + if (n < 0) 677 | + { 678 | + if (to_convert < sizeof(remaining_wbuf)) 679 | + { 680 | + remaining_wbuf_filled = (unsigned) to_convert; 681 | + memcpy (remaining_wbuf, c, remaining_wbuf_filled); 682 | + c = e; 683 | + break; /* need more multibyte chars for one wide-character */ 684 | + } 685 | + 686 | + /* Cannot convert multibyte to wide-char in current locale. */ 687 | + errno = EILSEQ; 688 | + return -1; 689 | + } 690 | + 691 | + if (n) 692 | + c += n; 693 | + else 694 | + { 695 | + *at = L'\0'; 696 | + c++; 697 | + } 698 | + 699 | + if (&tmp[sizeof(tmp)/sizeof(tmp[0])] == ++at) 700 | + break; /* buffer is full */ 701 | + } 702 | + while (c < e); 703 | + 704 | + if (at == tmp) 705 | + break; /* nothing to print */ 706 | + 707 | + /* Write to the console. */ 708 | + { 709 | + DWORD NumberOfCharsWritten; 710 | + if (!WriteConsoleW (ch, tmp, (DWORD) (at - tmp), &NumberOfCharsWritten, NULL)) 711 | + { 712 | + errno = 0; /* Caller should check GetLastError(). */ 713 | + return -1; 714 | + } 715 | + } 716 | + } 717 | + 718 | + return 0; 719 | +} 720 | + 721 | +/* Buffer for characters read from the console. 722 | + Note: ReadConsole() cannot handle big buffers (about 64 Kib). */ 723 | +#ifndef WINDOWS_CONSOLE_RBUF_SIZE 724 | +#ifdef _WIN64 725 | +#define WINDOWS_CONSOLE_RBUF_SIZE 30000 /* Must be non-zero. */ 726 | +#else 727 | +#define WINDOWS_CONSOLE_RBUF_SIZE 15000 /* Must be non-zero. */ 728 | +#endif 729 | +#endif 730 | +static wchar_t console_rbuf[WINDOWS_CONSOLE_RBUF_SIZE]; 731 | +static unsigned console_rbuf_offset = 0; 732 | +static unsigned console_rbuf_filled = 0; 733 | + 734 | +/* May read only a part of a multibyte character, 735 | + so may need to cache remaining part of the character. */ 736 | +static char remaining_rbuf[MB_LEN_MAX]; 737 | +static unsigned remaining_rbuf_offset = 0; 738 | +static unsigned remaining_rbuf_filled = 0; 739 | + 740 | +/* Stop console input on Ctrl-Z or Ctrl-D. 741 | + See https://stackoverflow.com/questions/43836040/win-api-readconsole. */ 742 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK 743 | +#define WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) 744 | +#endif 745 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CHAR1 746 | +#define WINDOWS_CONSOLE_READ_STOP_CHAR1 'z' 747 | +#endif 748 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CHAR2 749 | +#define WINDOWS_CONSOLE_READ_STOP_CHAR2 'd' 750 | +#endif 751 | +#define WINDOWS_CONSOLE_READ_STOP_VALUE1 (WINDOWS_CONSOLE_READ_STOP_CHAR1 - 'a' + 1) 752 | +#define WINDOWS_CONSOLE_READ_STOP_VALUE2 (WINDOWS_CONSOLE_READ_STOP_CHAR2 - 'a' + 1) 753 | + 754 | +static CONSOLE_READCONSOLE_CONTROL console_ctrl = { 755 | + sizeof(CONSOLE_READCONSOLE_CONTROL), 0, 756 | + (1u << WINDOWS_CONSOLE_READ_STOP_VALUE1) | 757 | + (1u << WINDOWS_CONSOLE_READ_STOP_VALUE2), 0 758 | +}; 759 | + 760 | +#define is_win_console_stop_input \ 761 | + ((console_rbuf[console_rbuf_offset] == WINDOWS_CONSOLE_READ_STOP_VALUE1 || \ 762 | + console_rbuf[console_rbuf_offset] == WINDOWS_CONSOLE_READ_STOP_VALUE2) && \ 763 | + (console_ctrl.dwControlKeyState & WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK)) 764 | + 765 | +/* Read wide-characters from the console. 766 | + Returns non-zero on error: 767 | + - caller should check GetLastError(). */ 768 | +static int 769 | +read_from_console_w (HANDLE ch) 770 | +{ 771 | + DWORD NumberOfCharsRead; 772 | + if (!ReadConsoleW (ch, console_rbuf, 773 | + sizeof(console_rbuf)/sizeof(console_rbuf[0]), &NumberOfCharsRead, &console_ctrl)) 774 | + { 775 | + errno = 0; /* Caller should check GetLastError(). */ 776 | + return -1; 777 | + } 778 | + 779 | + /* Console is a text stream, so convert CRLF->LF. */ 780 | + if (NumberOfCharsRead >= 2 && 781 | + console_rbuf[NumberOfCharsRead - 2] == L'\r' && 782 | + console_rbuf[NumberOfCharsRead - 1] == L'\n') 783 | + console_rbuf[--NumberOfCharsRead - 1] = L'\n'; 784 | + 785 | + console_rbuf_filled = NumberOfCharsRead; 786 | + return 0; 787 | +} 788 | + 789 | +/* As a workaround to MS UCRT bugs, call ReadConsoleW 790 | + directly. */ 791 | +/* Note: fread() internally calls ReadFile, which 792 | + in turn seems like calls ReadConsole expecting 793 | + that it will return number of bytes read. But 794 | + ReadConsole returns number of _chars_ read. 795 | + As result, reading stops if read just one byte 796 | + of a multibyte character. */ 797 | +/* Returns number of bytes read, < size on eof/error: 798 | + - caller should check errno, then GetLastError(). */ 799 | +static size_t 800 | +read_from_console (void *ptr, size_t size, HANDLE ch) 801 | +{ 802 | + char *d = (char*) ptr; 803 | + const char *const e = d + size; 804 | + 805 | + if (remaining_rbuf_filled) 806 | + { 807 | + unsigned to_copy = remaining_rbuf_filled; 808 | + if (to_copy > size) 809 | + to_copy = (unsigned) size; 810 | + d = to_copy + (char*) memcpy (d, 811 | + &remaining_rbuf[remaining_rbuf_offset], to_copy); 812 | + remaining_rbuf_filled -= to_copy; 813 | + if (remaining_rbuf_filled || d == e) 814 | + { 815 | + remaining_rbuf_offset += to_copy; 816 | + return size; 817 | + } 818 | + } 819 | + 820 | + for (;; console_rbuf_offset = 0) 821 | + { 822 | + /* Convert wide-characters. */ 823 | + while (console_rbuf_filled) 824 | + { 825 | + int n; 826 | + 827 | + if (is_win_console_stop_input) 828 | + goto stop_input; 829 | + 830 | + n = wctomb (remaining_rbuf, console_rbuf[console_rbuf_offset]); 831 | + if (n < 0) 832 | + { 833 | + /* Cannot convert wide-char to multibyte in current locale. */ 834 | + errno = EILSEQ; 835 | + return (size_t) (d - (char*) ptr); /* < size */ 836 | + } 837 | + 838 | + console_rbuf_filled--; 839 | + console_rbuf_offset++; 840 | + 841 | + { 842 | + unsigned to_copy = n; 843 | + if (to_copy > (size_t) (e - d)) 844 | + to_copy = (unsigned) (e - d); 845 | + d = to_copy + (char*) memcpy (d, remaining_rbuf, to_copy); 846 | + if (d == e) 847 | + { 848 | + remaining_rbuf_filled = (unsigned) n - to_copy; 849 | + remaining_rbuf_offset = to_copy; 850 | + return (size_t) (d - (char*) ptr); /* == size */ 851 | + } 852 | + } 853 | + } 854 | + 855 | + /* Read from the console. */ 856 | + if (read_from_console_w (ch)) 857 | + return (size_t) (d - (char*) ptr); /* < size */ 858 | + } 859 | + 860 | +stop_input: 861 | + /* EOF: no error - both errno and last error are zero. */ 862 | + errno = 0; 863 | + SetLastError (0); 864 | + return (size_t) (d - (char*) ptr); /* < size */ 865 | +} 866 | + 867 | +/* As a workaround to MS UCRT bugs, call ReadConsoleW 868 | + directly. */ 869 | +/* Returns number of bytes read, including delimiter, but 870 | + not including terminating '\0', returns -1 on eof or error: 871 | + - caller should check errno, then GetLastError(). */ 872 | +static ssize_t 873 | +read_from_console_delim (char **text, size_t *buflen, char buffer_delimiter, HANDLE ch) 874 | +{ 875 | + size_t filled = 0; 876 | + 877 | + /* Previous ck_fread() should read whole multibyte characters, 878 | + (possibly by multiple calls). */ 879 | + if (remaining_rbuf_filled) 880 | + panic (_("encountered partially read multibyte character")); 881 | + 882 | + for (;; console_rbuf_offset = 0) 883 | + { 884 | + /* Convert wide-characters. */ 885 | + while (console_rbuf_filled) 886 | + { 887 | + char tmp[MB_LEN_MAX]; 888 | + int n; 889 | + 890 | + if (is_win_console_stop_input) 891 | + goto stop_input; 892 | + 893 | + n = wctomb (tmp, console_rbuf[console_rbuf_offset]); 894 | + if (n < 0) 895 | + { 896 | + /* Cannot convert wide-char to multibyte in current locale. */ 897 | + errno = EILSEQ; 898 | + return -1; 899 | + } 900 | + 901 | + console_rbuf_filled--; 902 | + console_rbuf_offset++; 903 | + 904 | + /* One byte is needed for the terminating '\0'. */ 905 | + if ((unsigned) n + 1 > *buflen - filled) 906 | + { 907 | + /* Don't have a space, need to realloc. */ 908 | +#ifndef READ_FROM_CONSOLE_DELIM_REALLOC_SIZE 909 | +#define READ_FROM_CONSOLE_DELIM_REALLOC_SIZE 256 /* Must be > MB_LEN_MAX */ 910 | +#endif 911 | + (void)sizeof(int[1-2*(READ_FROM_CONSOLE_DELIM_REALLOC_SIZE <= MB_LEN_MAX)]); 912 | + { 913 | + size_t need = *buflen + READ_FROM_CONSOLE_DELIM_REALLOC_SIZE; 914 | + void *new_buf = xrealloc (*text, need); 915 | + *text = (char*) new_buf; 916 | + *buflen = need; 917 | + } 918 | + } 919 | + 920 | + memcpy (*text + filled, tmp, (unsigned) n); 921 | + filled += (unsigned) n; 922 | + 923 | + if ((*text)[filled - 1] == buffer_delimiter) 924 | + { 925 | + (*text)[filled] = '\0'; 926 | + return (ssize_t) filled; 927 | + } 928 | + } 929 | + 930 | + /* Read from the console. */ 931 | + if (read_from_console_w (ch)) 932 | + return -1; 933 | + } 934 | + 935 | +stop_input: 936 | + if (filled) 937 | + { 938 | + (*text)[filled] = '\0'; 939 | + return (ssize_t) filled; 940 | + } 941 | + 942 | + /* EOF: no error - both errno and last error are zero. */ 943 | + errno = 0; 944 | + SetLastError (0); 945 | + return -1; 946 | +} 947 | + 948 | +/* Writing to console failed - panic. 949 | + First checks errno, then GetLastError(). */ 950 | +static void 951 | +write_console_panic (void) 952 | +{ 953 | + if (EILSEQ == errno) 954 | + panic (_("failed to write to console: cannot to convert character" 955 | + " (LC_CTYPE=%s -> Unicode): %s"), setlocale (LC_CTYPE, NULL), 956 | + strerror (errno)); 957 | + 958 | + if (errno) 959 | + panic (_("failed to write to console: %s"), strerror (errno)); 960 | + 961 | + { 962 | + const DWORD last_err = GetLastError (); 963 | + const char *msg = get_last_err_msg (last_err); 964 | + panic (_("failed to write to console, system error: 0x%x (%s)"), 965 | + last_err, msg); 966 | + } 967 | +} 968 | + 969 | +/* Check if reading from console failed. 970 | + First checks errno, then GetLastError(). 971 | + Panics on error. */ 972 | +static void 973 | +check_read_console_error (void) 974 | +{ 975 | + if (EILSEQ == errno) 976 | + panic (_("failed to read from console: cannot to convert character" 977 | + " (Unicode -> LC_CTYPE=%s): %s"), setlocale (LC_CTYPE, NULL), 978 | + strerror (errno)); 979 | + 980 | + if (errno) 981 | + panic (_("failed to read from console: %s"), strerror (errno)); 982 | + 983 | + { 984 | + DWORD last_err = GetLastError (); 985 | + if (last_err) 986 | + { 987 | + const char *msg = get_last_err_msg (last_err); 988 | + panic (_("failed to read from console, system error: 0x%x (%s)"), 989 | + last_err, msg); 990 | + } 991 | + } 992 | + 993 | + /* No error. */ 994 | +} 995 | + 996 | +#endif /* WINDOWS_NATIVE */ 997 | + 998 | /* Panic on failing fwrite */ 999 | void 1000 | ck_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) 1001 | { 1002 | clearerr (stream); 1003 | - if (size && fwrite (ptr, size, nmemb, stream) != nmemb) 1004 | - panic (ngettext ("couldn't write %llu item to %s: %s", 1005 | - "couldn't write %llu items to %s: %s", nmemb), 1006 | - (unsigned long long) nmemb, utils_fp_name (stream), 1007 | - strerror (errno)); 1008 | + if (!size || !nmemb) 1009 | + return; 1010 | + 1011 | +#ifdef WINDOWS_NATIVE 1012 | + { 1013 | + const HANDLE ch = get_console_handle (fileno (stream)); 1014 | + if (ch != INVALID_HANDLE_VALUE) 1015 | + { 1016 | + if (write_to_console (ptr, size*nmemb, ch)) 1017 | + write_console_panic (); 1018 | + return; 1019 | + } 1020 | + } 1021 | +#endif /* WINDOWS_NATIVE */ 1022 | + 1023 | + if (fwrite (ptr, size, nmemb, stream) == nmemb) 1024 | + return; 1025 | + 1026 | + panic (ngettext ("couldn't write %llu item to %s: %s", 1027 | + "couldn't write %llu items to %s: %s", nmemb), 1028 | + (unsigned long long) nmemb, utils_fp_name (stream), 1029 | + strerror (errno)); 1030 | } 1031 | 1032 | /* Panic on failing fread */ 1033 | @@ -236,7 +753,31 @@ 1034 | ck_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) 1035 | { 1036 | clearerr (stream); 1037 | - if (size && (nmemb=fread (ptr, size, nmemb, stream)) <= 0 && ferror (stream)) 1038 | + if (!size) 1039 | + return nmemb; 1040 | + 1041 | +#ifdef WINDOWS_NATIVE 1042 | + { 1043 | + const HANDLE ch = get_console_handle (fileno (stream)); 1044 | + if (ch != INVALID_HANDLE_VALUE) 1045 | + { 1046 | + /* Item sizes other than 1 (byte) are not supported. */ 1047 | + if (size != 1) 1048 | + panic (_("ck_fread assert: item size != 1")); 1049 | + 1050 | + { 1051 | + const size_t nread = read_from_console (ptr, nmemb, ch); 1052 | + 1053 | + if (nread < nmemb) 1054 | + check_read_console_error (); 1055 | + 1056 | + return nread; 1057 | + } 1058 | + } 1059 | + } 1060 | +#endif /* WINDOWS_NATIVE */ 1061 | + 1062 | + if ((nmemb=fread (ptr, size, nmemb, stream)) <= 0 && ferror (stream)) 1063 | panic (_("read error on %s: %s"), utils_fp_name (stream), strerror (errno)); 1064 | 1065 | return nmemb; 1066 | @@ -245,12 +786,24 @@ 1067 | size_t 1068 | ck_getdelim (char **text, size_t *buflen, char delim, FILE *stream) 1069 | { 1070 | - ssize_t result; 1071 | + ssize_t result = -1; /* Make compiler happy. */ 1072 | bool error; 1073 | 1074 | error = ferror (stream); 1075 | if (!error) 1076 | { 1077 | +#ifdef WINDOWS_NATIVE 1078 | + const HANDLE ch = get_console_handle (fileno (stream)); 1079 | + if (ch != INVALID_HANDLE_VALUE) 1080 | + { 1081 | + result = read_from_console_delim (text, buflen, delim, ch); 1082 | + 1083 | + if (result < 0) 1084 | + check_read_console_error (); 1085 | + 1086 | + return result; /* -1 if no line was read (and there is EOF). */ 1087 | + } 1088 | +#endif /* WINDOWS_NATIVE */ 1089 | result = getdelim (text, buflen, delim, stream); 1090 | error = ferror (stream); 1091 | } 1092 | --- sed-4.9/lib/mbtowc-lock.h 2022-07-02 21:22:03.000000000 +0300 1093 | +++ sed-4.9-patched/lib/mbtowc-lock.h 2022-11-25 16:43:38.693612500 +0300 1094 | @@ -44,7 +44,7 @@ 1095 | 1096 | #elif defined _WIN32 && !defined __CYGWIN__ 1097 | 1098 | -extern __declspec(dllimport) CRITICAL_SECTION *gl_get_mbtowc_lock (void); 1099 | +extern /*__declspec(dllimport)*/ CRITICAL_SECTION *gl_get_mbtowc_lock (void); 1100 | 1101 | static int 1102 | mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m) 1103 | -------------------------------------------------------------------------------- /archive/sed-4.8-src.patch: -------------------------------------------------------------------------------- 1 | diff -Naur sed-4.8/lib/localcharset.c sed-4.8-patched/lib/localcharset.c 2 | --- sed-4.8/lib/localcharset.c 2020-01-01 20:59:13.000000000 +0300 3 | +++ sed-4.8-patched/lib/localcharset.c 2020-01-28 15:07:00.987544800 +0300 4 | @@ -925,25 +925,32 @@ 5 | char *current_locale = setlocale (LC_CTYPE, NULL); 6 | char *pdot = strrchr (current_locale, '.'); 7 | 8 | - if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) 9 | - sprintf (buf, "CP%s", pdot + 1); 10 | - else 11 | - { 12 | - /* The Windows API has a function returning the locale's codepage as a 13 | - number: GetACP(). 14 | - When the output goes to a console window, it needs to be provided in 15 | - GetOEMCP() encoding if the console is using a raster font, or in 16 | - GetConsoleOutputCP() encoding if it is using a TrueType font. 17 | - But in GUI programs and for output sent to files and pipes, GetACP() 18 | - encoding is the best bet. */ 19 | - sprintf (buf, "CP%u", GetACP ()); 20 | - } 21 | - /* For a locale name such as "French_France.65001", in Windows 10, 22 | - setlocale now returns "French_France.utf8" instead. */ 23 | - if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0) 24 | + /* After a dot may follow a codepage number, or the "utf8"/"utf-8" string, 25 | + in any case. For example, "Russian_Russia.uTf-8". */ 26 | + /* Also, iterpret the code page number 65001 as utf8. */ 27 | + if (pdot && (!strcmp (pdot + 1, "65001") || ( 28 | + ('u' == pdot[1] || 'U' == pdot[1]) && 29 | + ('t' == pdot[2] || 'T' == pdot[2]) && 30 | + ('f' == pdot[3] || 'F' == pdot[3]) && 31 | + (('8' == pdot[4] && '\0' == pdot[5]) || 32 | + ('-' == pdot[4] && '8' == pdot[5] && '\0' == pdot[6]))))) 33 | codeset = "UTF-8"; 34 | else 35 | { 36 | + if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) 37 | + sprintf (buf, "CP%s", pdot + 1); 38 | + else 39 | + { 40 | + /* The Windows API has a function returning the locale's codepage as a 41 | + number: GetACP(). 42 | + When the output goes to a console window, it needs to be provided in 43 | + GetOEMCP() encoding if the console is using a raster font, or in 44 | + GetConsoleOutputCP() encoding if it is using a TrueType font. 45 | + But in GUI programs and for output sent to files and pipes, GetACP() 46 | + encoding is the best bet. */ 47 | + sprintf (buf, "CP%u", GetACP ()); 48 | + } 49 | + 50 | strcpy (resultbuf, buf); 51 | codeset = resultbuf; 52 | } 53 | diff -Naur sed-4.8/lib/nl_langinfo.c sed-4.8-patched/lib/nl_langinfo.c 54 | --- sed-4.8/lib/nl_langinfo.c 2020-01-01 20:30:53.000000000 +0300 55 | +++ sed-4.8-patched/lib/nl_langinfo.c 2020-01-28 16:04:46.044734800 +0300 56 | @@ -88,21 +88,27 @@ 57 | GetACP, which returns the locale's codepage as a number (although 58 | this doesn't change according to what the 'setlocale' call specified). 59 | Either way, prepend "CP" to make it a valid codeset name. */ 60 | + 61 | + /* After a dot may follow a codepage number, or the "utf8"/"utf-8" string 62 | + in any case. For example, "Russian_Russia.uTf-8". */ 63 | + /* Also, iterpret the code page number 65001 as utf8. */ 64 | + if (!strcmp (codeset, "65001") || ( 65 | + ('u' == codeset[0] || 'U' == codeset[0]) && 66 | + ('t' == codeset[1] || 'T' == codeset[1]) && 67 | + ('f' == codeset[2] || 'F' == codeset[2]) && 68 | + (('8' == codeset[3] && '\0' == codeset[4]) || 69 | + ('-' == codeset[3] && '8' == codeset[4] && '\0' == codeset[5])))) 70 | + return (char *) "UTF-8"; 71 | + 72 | codesetlen = strlen (codeset); 73 | if (0 < codesetlen && codesetlen < sizeof buf - 2) 74 | memmove (buf + 2, codeset, codesetlen + 1); 75 | else 76 | sprintf (buf + 2, "%u", GetACP ()); 77 | - /* For a locale name such as "French_France.65001", in Windows 10, 78 | - setlocale now returns "French_France.utf8" instead. */ 79 | - if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0) 80 | - return (char *) "UTF-8"; 81 | - else 82 | - { 83 | - memcpy (buf, "CP", 2); 84 | - strcpy (result, buf); 85 | - return result; 86 | - } 87 | + 88 | + memcpy (buf, "CP", 2); 89 | + strcpy (result, buf); 90 | + return result; 91 | # else 92 | strcpy (result, codeset); 93 | return result; 94 | diff -Naur sed-4.8/sed/execute.c sed-4.8-patched/sed/execute.c 95 | --- sed-4.8/sed/execute.c 2020-01-01 22:38:19.000000000 +0300 96 | +++ sed-4.8-patched/sed/execute.c 2020-01-28 16:06:05.970306300 +0300 97 | @@ -37,6 +37,8 @@ 98 | #include "progname.h" 99 | #include "xalloc.h" 100 | 101 | +#include "dirname.h" 102 | + 103 | /* The number of extra bytes that must be allocated/usable, beyond 104 | the declared "end" of each line buffer that may be passed to 105 | match_regex. This is imposed by its use of dfaexec. */ 106 | @@ -571,17 +573,22 @@ 107 | if (in_place_extension) 108 | { 109 | int input_fd; 110 | - char *tmpdir, *p; 111 | + char *tmpdir; 112 | security_context_t old_fscreatecon; 113 | int reset_fscreatecon = 0; 114 | + size_t in_dir_len; 115 | memset (&old_fscreatecon, 0, sizeof (old_fscreatecon)); 116 | 117 | /* get the base name */ 118 | - tmpdir = xstrdup (input->in_file_name); 119 | - if ((p = strrchr (tmpdir, '/'))) 120 | - *p = 0; 121 | + in_dir_len = dir_len (input->in_file_name); 122 | + if (in_dir_len) 123 | + { 124 | + tmpdir = xmalloc (in_dir_len + 1); 125 | + memcpy (tmpdir, input->in_file_name, in_dir_len); 126 | + tmpdir[in_dir_len] = '\0'; 127 | + } 128 | else 129 | - strcpy (tmpdir, "."); 130 | + tmpdir = xstrdup ("."); 131 | 132 | if (isatty (fileno (input->fp))) 133 | panic (_("couldn't edit %s: is a terminal"), input->in_file_name); 134 | diff -Naur sed-4.8/sed/sed.c sed-4.8-patched/sed/sed.c 135 | --- sed-4.8/sed/sed.c 2020-01-12 06:24:08.000000000 +0300 136 | +++ sed-4.8-patched/sed/sed.c 2020-01-28 16:14:57.314697400 +0300 137 | @@ -67,9 +67,17 @@ 138 | /* How do we edit files in-place? (we don't if NULL) */ 139 | char *in_place_extension = NULL; 140 | 141 | -/* The mode to use to read/write files, either "r"/"w" or "rb"/"wb". */ 142 | +/* The mode to use to read/write files, either "r(t)"/"w(t)" or "rb"/"wb". */ 143 | +#ifdef HAVE_FOPEN_RT 144 | +char const *read_mode = "rt"; 145 | +char const *write_mode = "wt"; 146 | +#else 147 | char const *read_mode = "r"; 148 | char const *write_mode = "w"; 149 | +#endif 150 | + 151 | +/* Locale to set at startup. */ 152 | +char const *def_locale = ""; 153 | 154 | #if O_BINARY 155 | /* Additional flag for binary mode on platforms with O_BINARY/O_TEXT. */ 156 | @@ -117,6 +125,145 @@ 157 | G_file_to_unlink = NULL; 158 | } 159 | 160 | +#if defined _WIN32 && !defined __CYGWIN__ 161 | +#define WINDOWS_NATIVE 162 | +#endif 163 | + 164 | +#ifdef WINDOWS_NATIVE 165 | + 166 | +/* Get value of command-line option: 167 | + --lo[cale]=locale-name or --lo[cale] locale-name, 168 | + Returns option value or NULL if the option is not specified. 169 | + Panics if the option specified without a value, 170 | + else terminates opt_name_array to the length of the option name. */ 171 | +/* Note: before the call, opt_name_array must contain "--locale". */ 172 | +static const wchar_t * 173 | +get_specified_locale (wchar_t **wa, char opt_name_array[]) 174 | +{ 175 | + const wchar_t *w = NULL; 176 | + for (; *wa; wa++) 177 | + { 178 | + w = *wa; 179 | + if (L'-' != w[0] || L'-' != w[1] || L'l' != w[2] || L'o' != w[3]) 180 | + continue; 181 | + w += 4; 182 | + if (L'=' == *w || !*w) 183 | + break; 184 | + if (L'c' != *w) 185 | + continue; 186 | + w++; 187 | + if (L'=' == *w || !*w) 188 | + break; 189 | + if (L'a' != *w) 190 | + continue; 191 | + w++; 192 | + if (L'=' == *w || !*w) 193 | + break; 194 | + if (L'l' != *w) 195 | + continue; 196 | + w++; 197 | + if (L'=' == *w || !*w) 198 | + break; 199 | + if (L'e' != *w) 200 | + continue; 201 | + w++; 202 | + if (L'=' == *w || !*w) 203 | + break; 204 | + } 205 | + 206 | + if (!*wa) 207 | + return NULL; /* --lo[cale] option wasn't found. */ 208 | + 209 | + opt_name_array[(unsigned) (w - *wa)] = '\0'; 210 | + if (*w) 211 | + return w + 1; /* --lo[cale]=locale-name, return locale-name. */ 212 | + 213 | + /* --lo[cale] locale-name. */ 214 | + { 215 | + const wchar_t *locale_name = wa[1]; 216 | + if (!locale_name) 217 | + panic (_("option '%s' requires an argument"), opt_name_array); 218 | + return locale_name; 219 | + } 220 | +} 221 | + 222 | +/* Set locale based on the values of environment variables. */ 223 | +static void 224 | +set_locale_from_env (const char *def) 225 | +{ 226 | + const char *locale = getenv ("LC_ALL"); 227 | + if (locale && locale[0]) 228 | + { 229 | + if (!setlocale (LC_ALL, locale)) 230 | + panic (_("Bad locale: LC_ALL=%s"), locale); 231 | + return; 232 | + } 233 | + 234 | + /* LANG is the default for all LC_... */ 235 | + locale = getenv ("LANG"); 236 | + 237 | + /* if LANG is not defined - set the system default. 238 | + (If def is "", locale may be be set to 239 | + e.g. Russian_Russia.1251). */ 240 | + if (!locale || !locale[0]) 241 | + locale = def; 242 | + 243 | + if (!setlocale (LC_ALL, locale)) 244 | + panic (_("Bad locale: LANG=%s"), locale); 245 | + 246 | + /* specific LC_... take precedence over LANG. */ 247 | + locale = getenv ("LC_CTYPE"); 248 | + if (locale && locale[0]) 249 | + { 250 | + if (!setlocale (LC_CTYPE, locale)) 251 | + panic (_("Bad locale: LC_CTYPE=%s"), locale); 252 | + } 253 | +} 254 | + 255 | +/* Convert wide-char args to multibyte. */ 256 | +static char ** 257 | +convert_wargv (int argc, wchar_t **wargv) 258 | +{ 259 | + /* Convert program arguments from wide-char to multibyte 260 | + according to the locale codepage. */ 261 | + /* Note: argv array must be NULL-terminated. */ 262 | + char **argv = (char**) xmalloc (sizeof(*argv)*(argc + 1)); 263 | + 264 | + wchar_t **wa = wargv; 265 | + for (; *wa; wa++) 266 | + { 267 | + const size_t need = wcstombs (NULL, *wa, 0); 268 | + 269 | + if ((size_t) -1 == need) 270 | + panic (_("failed to convert argument %u (Unicode -> LC_CTYPE=%s): %s"), 271 | + (unsigned) (wa - wargv), setlocale (LC_CTYPE, NULL), 272 | + strerror (errno)); 273 | + 274 | + { 275 | + char *a = (char*) xmalloc (need + 1); 276 | + wcstombs (a, *wa, need + 1); 277 | + argv[wa - wargv] = a; 278 | + } 279 | + } 280 | + 281 | + /* argv - is a NULL-terminated array of pointers */ 282 | + argv[wa - wargv] = NULL; 283 | + 284 | + return argv; 285 | +} 286 | + 287 | +/* Free arguments array allocated by convert_wargv (). */ 288 | +static void 289 | +free_argv (char **argv) 290 | +{ 291 | + char **a = argv; 292 | + for (; *a; a++) 293 | + free (*a); 294 | + free (argv); 295 | +} 296 | + 297 | +#endif /* WINDOWS_NATIVE */ 298 | + 299 | static void 300 | contact (int errmsg) 301 | { 302 | @@ -128,6 +275,9 @@ 303 | get reports for other people's bugs. */ 304 | if (!errmsg) 305 | fprintf (out, _("E-mail bug reports to: <%s>.\n"), PACKAGE_BUGREPORT); 306 | + 307 | + if (!errmsg) 308 | + fprintf (out, _("Patched (v2) by: Michael M. Builov .\n")); 309 | } 310 | 311 | static void 312 | @@ -175,6 +325,13 @@ 313 | open files in binary mode (CR+LFs are not" \ 314 | " processed specially)\n")); 315 | #endif 316 | + fprintf (out, _(" -C, --ignore-locale\n\ 317 | + ignore system locale, operate in the default \"C\" locale\n")); 318 | +#ifdef WINDOWS_NATIVE 319 | + fprintf (out, _(" --locale=locale-name\n\ 320 | + use the specified locale (ignore environment" \ 321 | + " variables LC_ALL, LC_CTYPE and LANG)\n")); 322 | +#endif 323 | fprintf (out, _(" -l N, --line-length=N\n\ 324 | specify the desired line-wrap length for the `l' command\n")); 325 | fprintf (out, _(" --posix\n\ 326 | @@ -207,16 +364,24 @@ 327 | } 328 | 329 | int 330 | +#ifndef WINDOWS_NATIVE 331 | main (int argc, char **argv) 332 | +#else 333 | +wmain (int argc, wchar_t **wargv) 334 | +#endif 335 | { 336 | -#define SHORTOPTS "bsnrzuEe:f:l:i::V:" 337 | +#define SHORTOPTS "bCsnrzuEe:f:l:i::V:" 338 | 339 | enum { SANDBOX_OPTION = CHAR_MAX+1, 340 | DEBUG_OPTION 341 | +#ifdef WINDOWS_NATIVE 342 | + ,LOCALE_OPTION 343 | +#endif 344 | }; 345 | 346 | static const struct option longopts[] = { 347 | {"binary", 0, NULL, 'b'}, 348 | + {"ignore-locale", 0, NULL, 'C'}, 349 | {"regexp-extended", 0, NULL, 'r'}, 350 | {"debug", 0, NULL, DEBUG_OPTION}, 351 | {"expression", 1, NULL, 'e'}, 352 | @@ -236,6 +401,9 @@ 353 | #ifdef ENABLE_FOLLOW_SYMLINKS 354 | {"follow-symlinks", 0, NULL, 'F'}, 355 | #endif 356 | +#ifdef WINDOWS_NATIVE 357 | + {"locale", 1, NULL, LOCALE_OPTION}, 358 | +#endif 359 | {NULL, 0, NULL, 0} 360 | }; 361 | 362 | @@ -243,11 +411,68 @@ 363 | int return_code; 364 | const char *cols = getenv ("COLS"); 365 | 366 | +#ifdef WINDOWS_NATIVE 367 | + char **old_argv = NULL; 368 | + char **argv; 369 | + 370 | + /* Set locale according to user's wishes. 371 | + (Current locale is "C"). */ 372 | + char opt_name_array[] = "--locale"; 373 | + const wchar_t *spec_locale; 374 | + 375 | + /* Temporary set program name. 376 | + This is needed for error messages - in case of bad locale. */ 377 | + set_program_name ("sed"); 378 | + 379 | + /* Command-line option takes precedence over environment vars. */ 380 | + spec_locale = get_specified_locale (wargv, opt_name_array); 381 | + if (!spec_locale) 382 | + set_locale_from_env (def_locale); 383 | + else if (!_wsetlocale (LC_ALL, spec_locale)) 384 | + panic (_("Bad locale name specified by the option '%s'"), opt_name_array); 385 | + 386 | + /* Convert program arguments to multibyte strings. */ 387 | + argv = convert_wargv (argc, wargv); 388 | +#endif /* WINDOWS_NATIVE */ 389 | + 390 | set_program_name (argv[0]); 391 | initialize_main (&argc, &argv); 392 | + 393 | + /* Suppress error reporting in getopt. */ 394 | + opterr = 0; 395 | + 396 | + while ((opt = getopt_long (argc, argv, SHORTOPTS, longopts, NULL)) != EOF) 397 | + { 398 | + switch (opt) 399 | + { 400 | + case 'C': 401 | + def_locale = "C"; 402 | + break; 403 | + } 404 | + } 405 | + 406 | + /* Restore getopt behaviour. */ 407 | + opterr = 1; 408 | + optind = 1; 409 | + 410 | #if HAVE_SETLOCALE 411 | +#ifndef WINDOWS_NATIVE 412 | /* Set locale according to user's wishes. */ 413 | - setlocale (LC_ALL, ""); 414 | + setlocale (LC_ALL, def_locale); 415 | +#else /* WINDOWS_NATIVE */ 416 | + if (def_locale[0]) 417 | + { 418 | + /* User wants to use "C"-locale. */ 419 | + if (spec_locale) 420 | + panic (_("Options '-C/--ignore-locale' and '--locale' cannot be used together.")); 421 | + setlocale (LC_ALL, def_locale); 422 | + 423 | + /* Cannot free argv array now: 424 | + argv[0] was passed to set_program_name (). */ 425 | + old_argv = argv; 426 | + argv = convert_wargv (argc, wargv); 427 | + } 428 | +#endif /* WINDOWS_NATIVE */ 429 | #endif 430 | initialize_mbcs (); 431 | init_localeinfo (&localeinfo); 432 | @@ -336,6 +561,10 @@ 433 | #endif 434 | break; 435 | 436 | + case 'C': 437 | + /* already processed */ 438 | + break; 439 | + 440 | case 'E': 441 | case 'r': 442 | extended_regexp_flags = REG_EXTENDED; 443 | @@ -353,6 +582,12 @@ 444 | debug = true; 445 | break; 446 | 447 | +#ifdef WINDOWS_NATIVE 448 | + case LOCALE_OPTION: 449 | + /* already processed */ 450 | + break; 451 | +#endif 452 | + 453 | case 'u': 454 | unbuffered = true; 455 | break; 456 | @@ -391,6 +626,15 @@ 457 | if (set_binary_mode ( fileno (stdout), O_BINARY) == -1) 458 | panic (_("failed to set binary mode on STDOUT")); 459 | } 460 | + else 461 | + { 462 | + /* Under CYGWIN, standard input/output streams are in BINARY 463 | + mode by default, make sure they are in TEXT mode. */ 464 | + if (set_binary_mode ( fileno (stdin), O_TEXT) == -1) 465 | + panic (_("failed to set binary mode on STDIN")); 466 | + if (set_binary_mode ( fileno (stdout), O_TEXT) == -1) 467 | + panic (_("failed to set binary mode on STDOUT")); 468 | + } 469 | #endif 470 | 471 | if (debug) 472 | @@ -401,5 +645,11 @@ 473 | finish_program (the_program); 474 | ck_fclose (NULL); 475 | 476 | +#ifdef WINDOWS_NATIVE 477 | + if (old_argv) 478 | + free_argv (old_argv); 479 | + free_argv (argv); 480 | +#endif 481 | + 482 | return return_code; 483 | } 484 | diff -Naur sed-4.8/sed/utils.c sed-4.8-patched/sed/utils.c 485 | --- sed-4.8/sed/utils.c 2020-01-01 22:38:19.000000000 +0300 486 | +++ sed-4.8-patched/sed/utils.c 2020-01-28 16:16:18.960367300 +0300 487 | @@ -14,6 +14,12 @@ 488 | You should have received a copy of the GNU General Public License 489 | along with this program; If not, see . */ 490 | 491 | +#if defined _WIN32 && !defined __CYGWIN__ 492 | +#define WIN32_LEAN_AND_MEAN 493 | +#include 494 | +#define WINDOWS_NATIVE 495 | +#endif 496 | + 497 | #include 498 | 499 | #include 500 | @@ -198,16 +204,527 @@ 501 | return fp; 502 | } 503 | 504 | +#ifdef WINDOWS_NATIVE 505 | + 506 | +/* Convert wide-character string to multibyte. 507 | + Returns NULL on error, else - malloc'ated '\0'-terminated 508 | + string, which caller should free via free(). */ 509 | +static char * 510 | +convert_wc_to_mb (const wchar_t *wc) 511 | +{ 512 | + const size_t need = wcstombs (NULL, wc, 0); 513 | + 514 | + if ((size_t) -1 == need) 515 | + return NULL; /* Error. errno is set to EILSEQ. */ 516 | + 517 | + { 518 | + char *a = (char*) xmalloc (need + 1); 519 | + wcstombs (a, wc, need + 1); 520 | + return a; 521 | + } 522 | +} 523 | + 524 | +/* Called on panic. */ 525 | +static const char * 526 | +get_last_err_msg (unsigned int last_err) 527 | +{ 528 | + /* First try to get message in locale encoding. */ 529 | + wchar_t *wmsg; 530 | + DWORD n_chars = FormatMessageW ( 531 | + FORMAT_MESSAGE_ALLOCATE_BUFFER | 532 | + FORMAT_MESSAGE_FROM_SYSTEM | 533 | + FORMAT_MESSAGE_IGNORE_INSERTS, 534 | + NULL, last_err, 0, (LPWSTR) &wmsg, 0, NULL); 535 | + 536 | + /* trim "\r\n" at end of msg */ 537 | + if (n_chars && L'\n' == wmsg[n_chars - 1]) 538 | + { 539 | + wmsg[--n_chars] = L'\0'; 540 | + if (n_chars && L'\r' == wmsg[n_chars - 1]) 541 | + wmsg[--n_chars] = L'\0'; 542 | + } 543 | + 544 | + if (!n_chars) 545 | + return ""; 546 | + 547 | + { 548 | + char *msg = convert_wc_to_mb (wmsg); 549 | + if (msg) 550 | + { 551 | + /* Check if failed to translate message to locale code page. */ 552 | + const char *c = msg; 553 | + while ('?' == *c || ' ' == *c) 554 | + c++; 555 | + if ('.' == *c && !c[1]) 556 | + c++; /* Something like "?????." */ 557 | + if (!*c) 558 | + { 559 | + free (msg); 560 | + msg = NULL; 561 | + } 562 | + } 563 | + 564 | + if (!msg) 565 | + { 566 | + /* Just get error message in English. */ 567 | + n_chars = FormatMessageA ( 568 | + FORMAT_MESSAGE_ALLOCATE_BUFFER | 569 | + FORMAT_MESSAGE_FROM_SYSTEM | 570 | + FORMAT_MESSAGE_IGNORE_INSERTS, 571 | + NULL, last_err, 572 | + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 573 | + (LPSTR) &msg, 0, NULL); 574 | + 575 | + /* trim "\r\n" at end of msg */ 576 | + if (n_chars && '\n' == msg[n_chars - 1]) 577 | + { 578 | + msg[--n_chars] = '\0'; 579 | + if (n_chars && '\r' == msg[n_chars - 1]) 580 | + msg[--n_chars] = '\0'; 581 | + } 582 | + 583 | + if (!n_chars) 584 | + return ""; 585 | + } 586 | + 587 | + return msg; 588 | + } 589 | +} 590 | + 591 | +/* Check if file descriptor fd designates a console. 592 | + If this is true, then due to bugs in MS UCRT, 593 | + standard stream i/o functions read(2)/write(2) 594 | + on the fd may fail, e.g. if the console may print 595 | + one symbol per multibyte character (for example, 596 | + if LC_CTYPE=Russian_Russia.1251 and the console 597 | + code page is 65001). */ 598 | +/* Return INVALID_HANDLE_VALUE if fd do not belongs 599 | + to a console. */ 600 | +static HANDLE 601 | +get_console_handle (int fd) 602 | +{ 603 | + HANDLE ch; 604 | + DWORD mode; 605 | + 606 | + if (!_isatty (fd)) 607 | + return INVALID_HANDLE_VALUE; 608 | + 609 | + ch = (HANDLE) _get_osfhandle (fd); 610 | + if (ch != INVALID_HANDLE_VALUE && 611 | + GetConsoleMode (ch, &mode)) 612 | + return ch; 613 | + 614 | + /* Not a console handle. */ 615 | + return INVALID_HANDLE_VALUE; 616 | +} 617 | + 618 | +/* As a workaround to MS UCRT bugs, call WriteConsoleW 619 | + directly. */ 620 | +/* Note: fwrite() internally calls WriteFile, which 621 | + in turn seems like calls WriteConsole expecting 622 | + that it will return number of bytes written. But 623 | + WriteConsole returns number of _chars_ written. 624 | + As result, writing stops after printing only one 625 | + multibyte character. */ 626 | +/* Returns non-zero on error: 627 | + - caller should check errno, then GetLastError(). */ 628 | +static int 629 | +write_to_console (const void *ptr, size_t size, HANDLE ch) 630 | +{ 631 | + /* Write only full mulitbyte chars, so may need to cache 632 | + a part of unwritten multibyte char. */ 633 | + static char remaining_wbuf[MB_LEN_MAX]; 634 | + static unsigned remaining_wbuf_filled = 0; 635 | + 636 | +#ifndef WINDOWS_CONSOLE_WBUF_SIZE 637 | +#define WINDOWS_CONSOLE_WBUF_SIZE 512 /* Must be > 1. */ 638 | +#endif 639 | + wchar_t tmp[WINDOWS_CONSOLE_WBUF_SIZE]; 640 | + wchar_t *at = tmp; 641 | + const char *c = (const char*) ptr; 642 | + const char *const e = c + size; 643 | + int n; 644 | + 645 | + if (remaining_wbuf_filled) 646 | + { 647 | + unsigned to_copy = sizeof(remaining_wbuf) - remaining_wbuf_filled; 648 | + if (to_copy > size) 649 | + to_copy = (unsigned) size; 650 | + memcpy (&remaining_wbuf[remaining_wbuf_filled], c, to_copy); 651 | + remaining_wbuf_filled += to_copy; 652 | + 653 | + n = mbtowc (at, remaining_wbuf, remaining_wbuf_filled); 654 | + if (n < 0) 655 | + { 656 | + if (remaining_wbuf_filled < sizeof(remaining_wbuf)) 657 | + return 0; /* need more bytes of multibyte char for one wide-character */ 658 | + 659 | + /* Cannot convert multibyte to wide-char in current locale. */ 660 | + errno = EILSEQ; 661 | + return -1; 662 | + } 663 | + 664 | + c += to_copy - (remaining_wbuf_filled - n); 665 | + remaining_wbuf_filled = 0; 666 | + at++; 667 | + } 668 | + 669 | + for (; c < e; at = tmp) 670 | + { 671 | + /* Convert to wide-characters. */ 672 | + do 673 | + { 674 | + const size_t to_convert = (size_t) (e - c); 675 | + n = mbtowc (at, c, to_convert); 676 | + if (n < 0) 677 | + { 678 | + if (to_convert < sizeof(remaining_wbuf)) 679 | + { 680 | + remaining_wbuf_filled = (unsigned) to_convert; 681 | + memcpy (remaining_wbuf, c, remaining_wbuf_filled); 682 | + c = e; 683 | + break; /* need more multibyte chars for one wide-character */ 684 | + } 685 | + 686 | + /* Cannot convert multibyte to wide-char in current locale. */ 687 | + errno = EILSEQ; 688 | + return -1; 689 | + } 690 | + 691 | + if (n) 692 | + c += n; 693 | + else 694 | + { 695 | + *at = L'\0'; 696 | + c++; 697 | + } 698 | + 699 | + if (&tmp[sizeof(tmp)/sizeof(tmp[0])] == ++at) 700 | + break; /* buffer is full */ 701 | + } 702 | + while (c < e); 703 | + 704 | + if (at == tmp) 705 | + break; /* nothing to print */ 706 | + 707 | + /* Write to the console. */ 708 | + { 709 | + DWORD NumberOfCharsWritten; 710 | + if (!WriteConsoleW (ch, tmp, (DWORD) (at - tmp), &NumberOfCharsWritten, NULL)) 711 | + { 712 | + errno = 0; /* Caller should check GetLastError(). */ 713 | + return -1; 714 | + } 715 | + } 716 | + } 717 | + 718 | + return 0; 719 | +} 720 | + 721 | +/* Buffer for characters read from the console. 722 | + Note: ReadConsole() cannot handle big buffers (about 64 Kib). */ 723 | +#ifndef WINDOWS_CONSOLE_RBUF_SIZE 724 | +#ifdef _WIN64 725 | +#define WINDOWS_CONSOLE_RBUF_SIZE 30000 /* Must be non-zero. */ 726 | +#else 727 | +#define WINDOWS_CONSOLE_RBUF_SIZE 15000 /* Must be non-zero. */ 728 | +#endif 729 | +#endif 730 | +static wchar_t console_rbuf[WINDOWS_CONSOLE_RBUF_SIZE]; 731 | +static unsigned console_rbuf_offset = 0; 732 | +static unsigned console_rbuf_filled = 0; 733 | + 734 | +/* May read only a part of a multibyte character, 735 | + so may need to cache remaining part of the character. */ 736 | +static char remaining_rbuf[MB_LEN_MAX]; 737 | +static unsigned remaining_rbuf_offset = 0; 738 | +static unsigned remaining_rbuf_filled = 0; 739 | + 740 | +/* Stop console input on Ctrl-Z or Ctrl-D. 741 | + See https://stackoverflow.com/questions/43836040/win-api-readconsole. */ 742 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK 743 | +#define WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) 744 | +#endif 745 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CHAR1 746 | +#define WINDOWS_CONSOLE_READ_STOP_CHAR1 'z' 747 | +#endif 748 | +#ifndef WINDOWS_CONSOLE_READ_STOP_CHAR2 749 | +#define WINDOWS_CONSOLE_READ_STOP_CHAR2 'd' 750 | +#endif 751 | +#define WINDOWS_CONSOLE_READ_STOP_VALUE1 (WINDOWS_CONSOLE_READ_STOP_CHAR1 - 'a' + 1) 752 | +#define WINDOWS_CONSOLE_READ_STOP_VALUE2 (WINDOWS_CONSOLE_READ_STOP_CHAR2 - 'a' + 1) 753 | + 754 | +static CONSOLE_READCONSOLE_CONTROL console_ctrl = { 755 | + sizeof(CONSOLE_READCONSOLE_CONTROL), 0, 756 | + (1u << WINDOWS_CONSOLE_READ_STOP_VALUE1) | 757 | + (1u << WINDOWS_CONSOLE_READ_STOP_VALUE2), 0 758 | +}; 759 | + 760 | +#define is_win_console_stop_input \ 761 | + ((console_rbuf[console_rbuf_offset] == WINDOWS_CONSOLE_READ_STOP_VALUE1 || \ 762 | + console_rbuf[console_rbuf_offset] == WINDOWS_CONSOLE_READ_STOP_VALUE2) && \ 763 | + (console_ctrl.dwControlKeyState & WINDOWS_CONSOLE_READ_STOP_CONTROL_MASK)) 764 | + 765 | +/* Read wide-characters from the console. 766 | + Returns non-zero on error: 767 | + - caller should check GetLastError(). */ 768 | +static int 769 | +read_from_console_w (HANDLE ch) 770 | +{ 771 | + DWORD NumberOfCharsRead; 772 | + if (!ReadConsoleW (ch, console_rbuf, 773 | + sizeof(console_rbuf)/sizeof(console_rbuf[0]), &NumberOfCharsRead, &console_ctrl)) 774 | + { 775 | + errno = 0; /* Caller should check GetLastError(). */ 776 | + return -1; 777 | + } 778 | + 779 | + /* Console is a text stream, so convert CRLF->LF. */ 780 | + if (NumberOfCharsRead >= 2 && 781 | + console_rbuf[NumberOfCharsRead - 2] == L'\r' && 782 | + console_rbuf[NumberOfCharsRead - 1] == L'\n') 783 | + console_rbuf[--NumberOfCharsRead - 1] = L'\n'; 784 | + 785 | + console_rbuf_filled = NumberOfCharsRead; 786 | + return 0; 787 | +} 788 | + 789 | +/* As a workaround to MS UCRT bugs, call ReadConsoleW 790 | + directly. */ 791 | +/* Note: fread() internally calls ReadFile, which 792 | + in turn seems like calls ReadConsole expecting 793 | + that it will return number of bytes read. But 794 | + ReadConsole returns number of _chars_ read. 795 | + As result, reading stops if read just one byte 796 | + of a multibyte character. */ 797 | +/* Returns number of bytes read, < size on eof/error: 798 | + - caller should check errno, then GetLastError(). */ 799 | +static size_t 800 | +read_from_console (void *ptr, size_t size, HANDLE ch) 801 | +{ 802 | + char *d = (char*) ptr; 803 | + const char *const e = d + size; 804 | + 805 | + if (remaining_rbuf_filled) 806 | + { 807 | + unsigned to_copy = remaining_rbuf_filled; 808 | + if (to_copy > size) 809 | + to_copy = (unsigned) size; 810 | + d = to_copy + (char*) memcpy (d, 811 | + &remaining_rbuf[remaining_rbuf_offset], to_copy); 812 | + remaining_rbuf_filled -= to_copy; 813 | + if (remaining_rbuf_filled || d == e) 814 | + { 815 | + remaining_rbuf_offset += to_copy; 816 | + return size; 817 | + } 818 | + } 819 | + 820 | + for (;; console_rbuf_offset = 0) 821 | + { 822 | + /* Convert wide-characters. */ 823 | + while (console_rbuf_filled) 824 | + { 825 | + int n; 826 | + 827 | + if (is_win_console_stop_input) 828 | + goto stop_input; 829 | + 830 | + n = wctomb (remaining_rbuf, console_rbuf[console_rbuf_offset]); 831 | + if (n < 0) 832 | + { 833 | + /* Cannot convert wide-char to multibyte in current locale. */ 834 | + errno = EILSEQ; 835 | + return (size_t) (d - (char*) ptr); /* < size */ 836 | + } 837 | + 838 | + console_rbuf_filled--; 839 | + console_rbuf_offset++; 840 | + 841 | + { 842 | + unsigned to_copy = n; 843 | + if (to_copy > (size_t) (e - d)) 844 | + to_copy = (unsigned) (e - d); 845 | + d = to_copy + (char*) memcpy (d, remaining_rbuf, to_copy); 846 | + if (d == e) 847 | + { 848 | + remaining_rbuf_filled = (unsigned) n - to_copy; 849 | + remaining_rbuf_offset = to_copy; 850 | + return (size_t) (d - (char*) ptr); /* == size */ 851 | + } 852 | + } 853 | + } 854 | + 855 | + /* Read from the console. */ 856 | + if (read_from_console_w (ch)) 857 | + return (size_t) (d - (char*) ptr); /* < size */ 858 | + } 859 | + 860 | +stop_input: 861 | + /* EOF: no error - both errno and last error are zero. */ 862 | + errno = 0; 863 | + SetLastError (0); 864 | + return (size_t) (d - (char*) ptr); /* < size */ 865 | +} 866 | + 867 | +/* As a workaround to MS UCRT bugs, call ReadConsoleW 868 | + directly. */ 869 | +/* Returns number of bytes read, including delimiter, but 870 | + not including terminating '\0', returns -1 on eof or error: 871 | + - caller should check errno, then GetLastError(). */ 872 | +static ssize_t 873 | +read_from_console_delim (char **text, size_t *buflen, char buffer_delimiter, HANDLE ch) 874 | +{ 875 | + size_t filled = 0; 876 | + 877 | + /* Previous ck_fread() should read whole multibyte characters, 878 | + (possibly by multiple calls). */ 879 | + if (remaining_rbuf_filled) 880 | + panic (_("encountered partially read multibyte character")); 881 | + 882 | + for (;; console_rbuf_offset = 0) 883 | + { 884 | + /* Convert wide-characters. */ 885 | + while (console_rbuf_filled) 886 | + { 887 | + char tmp[MB_LEN_MAX]; 888 | + int n; 889 | + 890 | + if (is_win_console_stop_input) 891 | + goto stop_input; 892 | + 893 | + n = wctomb (tmp, console_rbuf[console_rbuf_offset]); 894 | + if (n < 0) 895 | + { 896 | + /* Cannot convert wide-char to multibyte in current locale. */ 897 | + errno = EILSEQ; 898 | + return -1; 899 | + } 900 | + 901 | + console_rbuf_filled--; 902 | + console_rbuf_offset++; 903 | + 904 | + /* One byte is needed for the terminating '\0'. */ 905 | + if ((unsigned) n + 1 > *buflen - filled) 906 | + { 907 | + /* Don't have a space, need to realloc. */ 908 | +#ifndef READ_FROM_CONSOLE_DELIM_REALLOC_SIZE 909 | +#define READ_FROM_CONSOLE_DELIM_REALLOC_SIZE 256 /* Must be > MB_LEN_MAX */ 910 | +#endif 911 | + (void)sizeof(int[1-2*(READ_FROM_CONSOLE_DELIM_REALLOC_SIZE <= MB_LEN_MAX)]); 912 | + { 913 | + size_t need = *buflen + READ_FROM_CONSOLE_DELIM_REALLOC_SIZE; 914 | + void *new_buf = xrealloc (*text, need); 915 | + *text = (char*) new_buf; 916 | + *buflen = need; 917 | + } 918 | + } 919 | + 920 | + memcpy (*text + filled, tmp, (unsigned) n); 921 | + filled += (unsigned) n; 922 | + 923 | + if ((*text)[filled - 1] == buffer_delimiter) 924 | + { 925 | + (*text)[filled] = '\0'; 926 | + return (ssize_t) filled; 927 | + } 928 | + } 929 | + 930 | + /* Read from the console. */ 931 | + if (read_from_console_w (ch)) 932 | + return -1; 933 | + } 934 | + 935 | +stop_input: 936 | + if (filled) 937 | + { 938 | + (*text)[filled] = '\0'; 939 | + return (ssize_t) filled; 940 | + } 941 | + 942 | + /* EOF: no error - both errno and last error are zero. */ 943 | + errno = 0; 944 | + SetLastError (0); 945 | + return -1; 946 | +} 947 | + 948 | +/* Writing to console failed - panic. 949 | + First checks errno, then GetLastError(). */ 950 | +static void 951 | +write_console_panic (void) 952 | +{ 953 | + if (EILSEQ == errno) 954 | + panic (_("failed to write to console: cannot to convert character" 955 | + " (LC_CTYPE=%s -> Unicode): %s"), setlocale (LC_CTYPE, NULL), 956 | + strerror (errno)); 957 | + 958 | + if (errno) 959 | + panic (_("failed to write to console: %s"), strerror (errno)); 960 | + 961 | + { 962 | + const DWORD last_err = GetLastError (); 963 | + const char *msg = get_last_err_msg (last_err); 964 | + panic (_("failed to write to console, system error: 0x%x (%s)"), 965 | + last_err, msg); 966 | + } 967 | +} 968 | + 969 | +/* Check if reading from console failed. 970 | + First checks errno, then GetLastError(). 971 | + Panics on error. */ 972 | +static void 973 | +check_read_console_error (void) 974 | +{ 975 | + if (EILSEQ == errno) 976 | + panic (_("failed to read from console: cannot to convert character" 977 | + " (Unicode -> LC_CTYPE=%s): %s"), setlocale (LC_CTYPE, NULL), 978 | + strerror (errno)); 979 | + 980 | + if (errno) 981 | + panic (_("failed to read from console: %s"), strerror (errno)); 982 | + 983 | + { 984 | + DWORD last_err = GetLastError (); 985 | + if (last_err) 986 | + { 987 | + const char *msg = get_last_err_msg (last_err); 988 | + panic (_("failed to read from console, system error: 0x%x (%s)"), 989 | + last_err, msg); 990 | + } 991 | + } 992 | + 993 | + /* No error. */ 994 | +} 995 | + 996 | +#endif /* WINDOWS_NATIVE */ 997 | + 998 | /* Panic on failing fwrite */ 999 | void 1000 | ck_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) 1001 | { 1002 | clearerr (stream); 1003 | - if (size && fwrite (ptr, size, nmemb, stream) != nmemb) 1004 | - panic (ngettext ("couldn't write %llu item to %s: %s", 1005 | - "couldn't write %llu items to %s: %s", nmemb), 1006 | - (unsigned long long) nmemb, utils_fp_name (stream), 1007 | - strerror (errno)); 1008 | + if (!size || !nmemb) 1009 | + return; 1010 | + 1011 | +#ifdef WINDOWS_NATIVE 1012 | + { 1013 | + const HANDLE ch = get_console_handle (fileno (stream)); 1014 | + if (ch != INVALID_HANDLE_VALUE) 1015 | + { 1016 | + if (write_to_console (ptr, size*nmemb, ch)) 1017 | + write_console_panic (); 1018 | + return; 1019 | + } 1020 | + } 1021 | +#endif /* WINDOWS_NATIVE */ 1022 | + 1023 | + if (fwrite (ptr, size, nmemb, stream) == nmemb) 1024 | + return; 1025 | + 1026 | + panic (ngettext ("couldn't write %llu item to %s: %s", 1027 | + "couldn't write %llu items to %s: %s", nmemb), 1028 | + (unsigned long long) nmemb, utils_fp_name (stream), 1029 | + strerror (errno)); 1030 | } 1031 | 1032 | /* Panic on failing fread */ 1033 | @@ -215,7 +732,31 @@ 1034 | ck_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) 1035 | { 1036 | clearerr (stream); 1037 | - if (size && (nmemb=fread (ptr, size, nmemb, stream)) <= 0 && ferror (stream)) 1038 | + if (!size) 1039 | + return nmemb; 1040 | + 1041 | +#ifdef WINDOWS_NATIVE 1042 | + { 1043 | + const HANDLE ch = get_console_handle (fileno (stream)); 1044 | + if (ch != INVALID_HANDLE_VALUE) 1045 | + { 1046 | + /* Item sizes other than 1 (byte) are not supported. */ 1047 | + if (size != 1) 1048 | + panic (_("ck_fread assert: item size != 1")); 1049 | + 1050 | + { 1051 | + const size_t nread = read_from_console (ptr, nmemb, ch); 1052 | + 1053 | + if (nread < nmemb) 1054 | + check_read_console_error (); 1055 | + 1056 | + return nread; 1057 | + } 1058 | + } 1059 | + } 1060 | +#endif /* WINDOWS_NATIVE */ 1061 | + 1062 | + if ((nmemb=fread (ptr, size, nmemb, stream)) <= 0 && ferror (stream)) 1063 | panic (_("read error on %s: %s"), utils_fp_name (stream), strerror (errno)); 1064 | 1065 | return nmemb; 1066 | @@ -224,12 +765,24 @@ 1067 | size_t 1068 | ck_getdelim (char **text, size_t *buflen, char buffer_delimiter, FILE *stream) 1069 | { 1070 | - ssize_t result; 1071 | + ssize_t result = -1; /* Make compiler happy. */ 1072 | bool error; 1073 | 1074 | error = ferror (stream); 1075 | if (!error) 1076 | { 1077 | +#ifdef WINDOWS_NATIVE 1078 | + const HANDLE ch = get_console_handle (fileno (stream)); 1079 | + if (ch != INVALID_HANDLE_VALUE) 1080 | + { 1081 | + result = read_from_console_delim (text, buflen, buffer_delimiter, ch); 1082 | + 1083 | + if (result < 0) 1084 | + check_read_console_error (); 1085 | + 1086 | + return result; /* -1 if no line was read (and there is EOF). */ 1087 | + } 1088 | +#endif /* WINDOWS_NATIVE */ 1089 | result = getdelim (text, buflen, buffer_delimiter, stream); 1090 | error = ferror (stream); 1091 | } 1092 | --- ./lib/mbtowc-lock.h 2020-01-04 09:06:14.000000000 +0300 1093 | +++ ./lib/mbtowc-lock.h-patched 2020-01-28 17:26:35.038513200 +0300 1094 | @@ -34,7 +34,7 @@ 1095 | 1096 | #if defined _WIN32 && !defined __CYGWIN__ 1097 | 1098 | -extern __declspec(dllimport) CRITICAL_SECTION *gl_get_mbtowc_lock (void); 1099 | +extern /*__declspec(dllimport)*/ CRITICAL_SECTION *gl_get_mbtowc_lock (void); 1100 | 1101 | static int 1102 | mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m) 1103 | --------------------------------------------------------------------------------