260730.2 · 8cda03ed0dc8e97274d15c94d59327597cac15e5
released 7.8.3
- update #549 memory threshold
- update #550 man page formatting
- update #551 LZMA SDK to 26.02
reading declarations
@@ -3965,8 +3965,6 @@ in markdown: UGREP(1) User Commands UGREP(1) -- NAME ugrep, ug -- file pattern searcher @@ -4408,7 +4406,7 @@ in markdown: --from=FILE Read additional pathnames of files to search from FILE. When FILE is a `-', standard input is read. This option is useful with- `find+ `find ... -print | ugrep --from=- ...' to search specific files. -G, --basic-regexp Interpret patterns as basic regular expressions (BREs).@@ -4578,7 +4576,7 @@ in markdown: additional values are output. See also options --format and -u. -K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX- Start searching at line MIN, stop at line MAX when specified.+ Start searching at line MIN, stop reading input after line MAX. -k, --column-number The column number of a pattern match is displayed in front of the@@ -4593,10 +4591,9 @@ in markdown: -l, --files-with-matches Only the names of files containing selected lines are written to- standard output. ugrep will only search a file until a match has- been found, making searches potentially less expensive. Pathnames- are listed once per file searched. If the standard input is- searched, the string ``(standard input)'' is written.+ standard output. Pathnames are listed once per file searched. If+ the standard input is searched, the string ``(standard input)'' is+ written. Stop reading input upon the first match. --label=LABEL Displays the LABEL value when input is read from standard input@@ -4620,11 +4617,10 @@ in markdown: making recursive searches potentially more expensive. -m [MIN,][MAX], --min-count=MIN, --max-count=MAX- Require MIN matches, stop after MAX matches when specified.- Output MIN to MAX matches. For example, -m1 outputs the first- match and -cm1, (with a comma) counts nonzero matches. When -u or- --ungroup is specified, each individual match counts. See also- option -K.+ Require MIN matches, stop reading input upon MAX matches. Output+ MIN to MAX matches. For example, -m1 outputs the first match and+ -cm1, (with a comma) counts nonzero matches. When -u or --ungroup+ is specified, each individual match counts. See also option -K. --match Match all lines. Same as specifying an empty pattern to search.@@ -4875,9 +4871,9 @@ in markdown: Selected lines are those not matching any of the specified patterns. - --view[=COMMAND]+ --view[=[+]COMMAND] Use COMMAND to view/edit a file in -Q query TUI by pressing- CTRL-Y.+ CTRL-Y, +COMMAND waits for a key press after COMMAND terminated. -W, --with-hex Output binary matches in hexadecimal, leaving text matches alone.@@ -5545,9 +5541,7 @@ in markdown: BUGS Report bugs at: <https://github.com/Genivia/ugrep/issues> --- ugrep 7.6.0 March 5, 2026 UGREP(1)+ ugrep 7.8.3 July 30, 2026 UGREP(1) 🔝 [Back to table of contents](#toc)
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles.-# Generated by GNU Autoconf 2.73 for ugrep 7.8.2.+# Generated by GNU Autoconf 2.73 for ugrep 7.8.3. # # Report bugs to <https://github.com/Genivia/ugrep/issues>. #@@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ugrep' PACKAGE_TARNAME='ugrep'-PACKAGE_VERSION='7.8.2'-PACKAGE_STRING='ugrep 7.8.2'+PACKAGE_VERSION='7.8.3'+PACKAGE_STRING='ugrep 7.8.3' PACKAGE_BUGREPORT='https://github.com/Genivia/ugrep/issues' PACKAGE_URL='https://ugrep.com' @@ -1369,7 +1369,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF-'configure' configures ugrep 7.8.2 to adapt to many kinds of systems.+'configure' configures ugrep 7.8.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1440,7 +1440,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in- short | recursive ) echo "Configuration of ugrep 7.8.2:";;+ short | recursive ) echo "Configuration of ugrep 7.8.3:";; esac cat <<\_ACEOF @@ -1618,7 +1618,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF-ugrep configure 7.8.2+ugrep configure 7.8.3 generated by GNU Autoconf 2.73 Copyright (C) 2026 Free Software Foundation, Inc.@@ -2172,7 +2172,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ugrep $as_me 7.8.2, which was+It was created by ugrep $as_me 7.8.3, which was generated by GNU Autoconf 2.73. Invocation command line was $ $0$ac_configure_args_raw@@ -3786,7 +3786,7 @@ fi # Define the identity of the package. PACKAGE='ugrep'- VERSION='7.8.2'+ VERSION='7.8.3' printf '%s\n' "#define PACKAGE \"$PACKAGE\"" >>confdefs.h@@ -11899,7 +11899,7 @@ cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log="-This file was extended by ugrep $as_me 7.8.2, which was+This file was extended by ugrep $as_me 7.8.3, which was generated by GNU Autoconf 2.73. Invocation command line was CONFIG_FILES = $CONFIG_FILES@@ -11972,7 +11972,7 @@ ac_cs_config_escaped=`printf '%s\n' "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\-ugrep config.status 7.8.2+ugrep config.status 7.8.3 configured by $0, generated by GNU Autoconf 2.73, with options \\"\$ac_cs_config\\"
@@ -1,4 +1,4 @@-AC_INIT([ugrep],[7.8.2],[https://github.com/Genivia/ugrep/issues],[ugrep],[https://ugrep.com])+AC_INIT([ugrep],[7.8.3],[https://github.com/Genivia/ugrep/issues],[ugrep],[https://ugrep.com]) AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz no-dist-gzip]) AC_CONFIG_HEADERS([config.h]) AC_COPYRIGHT([Copyright (C) 2019-2026 Robert van Engelen, Genivia Inc.])
@@ -988,8 +988,8 @@ class AbstractMatcher { { return pos_ >= end_ && eof_; }- /// Set and force the end of input state.- inline void set_end(bool eof)+ /// Set and force the end of input state (default argument is true), or attempt to read more input (argument is false).+ inline void set_end(bool eof = true) { if (eof) flush();
@@ -954,7 +954,7 @@ class Pattern { typedef std::list<State*> List; static const uint16_t ALLOC = 1024; ///< allocate 1024 DFA states at a time, to improve performance static const uint16_t MAX_DEPTH = 256; ///< analyze DFA up to states this deep to improve predict match- static const Index MAX_STATES = Const::GMAX; ///< maximum number of DFA states is constrained by opcode table size+ static const Index MAX_STATES = Const::GMAX/3;///< maximum number of DFA states is constrained by opcode table size static const Index MAX_EDGES = 16*Const::GMAX;///< maximum number of DFA edges is constrained by opcode table size static const Index DEAD_PATH = 1; ///< state marker "path always and only reaches backedges" (a dead end) static const Index KEEP_PATH = MAX_DEPTH; ///< state marker "required path" (from a newline edge)
@@ -39,7 +39,7 @@ #include <sys/stat.h> #include <sys/types.h> -#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)+#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) # include <io.h> # include <fcntl.h> # define off_t __int64@@ -47,11 +47,7 @@ # define fseeko _fseeki64 #else # include <unistd.h> // off_t, fstat()-# if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64)) && (defined(__MINGW32__) || defined(__MINGW64__)) && defined(_UCRT)-# include <winsock2.h>-# else-# include <sys/select.h>-# endif+# include <sys/select.h> #endif namespace reflex {@@ -653,7 +649,7 @@ void Input::file_init() { // attempt to determine the file size with fstat() #if !defined(HAVE_CONFIG_H) || defined(HAVE_FSTAT)-#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)+#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) struct _stat st; if (_fstat(_fileno(file_), &st) == 0 && ((st.st_mode & S_IFMT) == S_IFREG) && st.st_size <= 4294967295LL) #else@@ -1030,7 +1026,7 @@ bool Input::file_ready() { if (file_ == NULL || feof(file_)) return false;-#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)+#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) return !ferror(file_); #else int fd = fileno(file_);
@@ -1,5 +1,5 @@ /* 7zArcIn.c -- 7z Input functions-2023-05-11 : Igor Pavlov : Public domain */+: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -11,7 +11,7 @@ #include "CpuArch.h" #define MY_ALLOC(T, p, size, alloc) \- { if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }+ { if ((p = (T *)ISzAlloc_Alloc(alloc, (size_t)(size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } #define MY_ALLOC_ZE(T, p, size, alloc) \ { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }@@ -22,8 +22,6 @@ #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ { if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } -#define k7zMajorVersion 0- enum EIdEnum { k7zIdEnd,@@ -52,15 +50,13 @@ enum EIdEnum k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy- // k7zNtSecure,- // k7zParent,- // k7zIsReal }; const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; #define SzBitUi32s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } +Z7_FORCE_INLINE static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) { if (num == 0)@@ -76,6 +72,7 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) return SZ_OK; } +Z7_FORCE_INLINE static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;@@ -84,13 +81,14 @@ static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) #define SzBitUi64s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } +Z7_FORCE_INLINE static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; } -+Z7_NO_INLINE static void SzAr_Init(CSzAr *p) { p->NumPackStreams = 0;@@ -110,23 +108,22 @@ static void SzAr_Init(CSzAr *p) p->RangeLimit = 0; } +Z7_NO_INLINE static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->PackPositions); SzBitUi32s_Free(&p->FolderCRCs, alloc);- ISzAlloc_Free(alloc, p->FoCodersOffsets); ISzAlloc_Free(alloc, p->FoStartPackStreamIndex); ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes); ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); ISzAlloc_Free(alloc, p->CoderUnpackSizes);- ISzAlloc_Free(alloc, p->CodersData); SzAr_Init(p); } -+Z7_NO_INLINE void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db);@@ -150,6 +147,7 @@ void SzArEx_Init(CSzArEx *p) SzBitUi64s_INIT(&p->CTime) } +Z7_NO_INLINE void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->UnpackPositions);@@ -172,15 +170,6 @@ void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) } -static int TestSignatureCandidate(const Byte *testBytes)-{- unsigned i;- for (i = 0; i < k7zSignatureSize; i++)- if (testBytes[i] != k7zSignature[i])- return 0;- return 1;-}- #define SzData_CLEAR(p) { (p)->Data = NULL; (p)->Size = 0; } #define SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) \@@ -199,14 +188,9 @@ static int TestSignatureCandidate(const Byte *testBytes) #define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } #define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } -#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \- dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);- static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) {- Byte firstByte, mask;- unsigned i;- UInt32 v;+ unsigned firstByte, mask, i, v; SZ_READ_BYTE(firstByte) if ((firstByte & 0x80) == 0)@@ -223,18 +207,18 @@ static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) SZ_READ_BYTE(mask) *value = v | ((UInt32)mask << 8); mask = 0x20;- for (i = 2; i < 8; i++)+ for (i = 2 * 8; i < 8 * 8; i += 8) {- Byte b;+ unsigned b; if ((firstByte & mask) == 0) { const UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);- *value |= (highPart << (8 * i));+ *value |= (highPart << i); return SZ_OK; }- SZ_READ_BYTE(b)- *value |= ((UInt64)b << (8 * i)); mask >>= 1;+ SZ_READ_BYTE(b)+ *value |= ((UInt64)b << i); } return SZ_OK; }@@ -242,7 +226,7 @@ static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) {- Byte firstByte;+ unsigned firstByte; UInt64 value64; if (sd->Size == 0) return SZ_ERROR_ARCHIVE;@@ -265,6 +249,7 @@ static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) #define ReadID(sd, value) ReadNumber(sd, value) +Z7_NO_INLINE static SRes SkipData(CSzData *sd) { UInt64 size;@@ -275,6 +260,7 @@ static SRes SkipData(CSzData *sd) return SZ_OK; } +Z7_NO_INLINE static SRes WaitId(CSzData *sd, UInt32 id) { for (;;)@@ -289,19 +275,11 @@ static SRes WaitId(CSzData *sd, UInt32 id) } } -static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)-{- const UInt32 numBytes = (numItems + 7) >> 3;- if (numBytes > sd->Size)- return SZ_ERROR_ARCHIVE;- *v = sd->Data;- SKIP_DATA(sd, numBytes)- return SZ_OK;-} +Z7_NO_INLINE static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) {- Byte b = 0;+ unsigned b = 0; unsigned m = 0; UInt32 sum = 0; for (; numItems != 0; numItems--)@@ -312,16 +290,16 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) m = 8; } m--;- sum += ((b >> m) & 1);+ sum += (UInt32)((b >> m) & 1); } return sum; } -static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)+static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, size_t numItems, Byte **v, ISzAllocPtr alloc) { Byte allAreDefined; Byte *v2;- const UInt32 numBytes = (numItems + 7) >> 3;+ const size_t numBytes = (numItems + 7) >> 3; *v = NULL; SZ_READ_BYTE(allAreDefined) if (numBytes == 0)@@ -339,40 +317,49 @@ static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, I memset(v2, 0xFF, (size_t)numBytes); { const unsigned numBits = (unsigned)numItems & 7;- if (numBits != 0)- v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));+ if (numBits)+ v2[(size_t)numBytes - 1] = (Byte)(0xff00u >> numBits); } return SZ_OK; } -static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)+static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) {- UInt32 i;- CSzData sd;+ size_t i;+ const Byte *data;+ size_t size; UInt32 *vals; const Byte *defs;- MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc)- sd = *sd2;+ MY_ALLOC_ZE(UInt32, vals, numItems, alloc)+ crcs->Vals = vals; defs = crcs->Defs;- vals = crcs->Vals;+ data = sd2->Data;+ size = sd2->Size; for (i = 0; i < numItems; i++) if (SzBitArray_Check(defs, i)) {- SZ_READ_32(vals[i])+ if (size < 4)+ return SZ_ERROR_ARCHIVE;+ size -= 4;+ vals[i] = GetUi32(data);+ data += 4; } else vals[i] = 0;- *sd2 = sd;+ sd2->Data = data;+ sd2->Size = size; return SZ_OK; } -static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)+static SRes ReadBitUi32s(CSzData *sd, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) {- SzBitUi32s_Free(crcs, alloc);+ if (crcs->Defs)+ return SZ_ERROR_ARCHIVE; RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)) return ReadUi32s(sd, numItems, crcs, alloc); } +Z7_NO_INLINE static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) { Byte allAreDefined;@@ -395,25 +382,26 @@ static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) { RINOK(SzReadNumber32(sd, &p->NumPackStreams))- RINOK(WaitId(sd, k7zIdSize))- MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc) {- UInt64 sum = 0;- UInt32 i;- const UInt32 numPackStreams = p->NumPackStreams;- for (i = 0; i < numPackStreams; i++)+ UInt64 *packPositions;+ UInt64 sum;+ size_t num = (size_t)p->NumPackStreams + 1;+ MY_ALLOC(UInt64, packPositions, num, alloc)+ p->PackPositions = packPositions;+ sum = 0;+ for (;;) { UInt64 packSize;- p->PackPositions[i] = sum;+ *packPositions++ = sum;+ if (--num == 0)+ break; RINOK(ReadNumber(sd, &packSize)) sum += packSize; if (sum < packSize) return SZ_ERROR_ARCHIVE; }- p->PackPositions[i] = sum; }- for (;;) { UInt64 type;@@ -430,85 +418,79 @@ static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) } } -/*-static SRes SzReadSwitch(CSzData *sd)-{- Byte external;- RINOK(SzReadByte(sd, &external));- return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;-}-*/ #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) {- UInt32 numCoders, i;- UInt32 numInStreams = 0;- const Byte *dataStart = sd->Data;+ UInt32 numCoders, i, numInStreams = 0;+ const Byte * const dataStart = sd->Data; - f->NumCoders = 0;- f->NumBonds = 0;- f->NumPackStreams = 0;+ // f->NumCoders = 0;+ // f->NumBonds = 0;+ // f->NumPackStreams = 0; f->UnpackStream = 0; RINOK(SzReadNumber32(sd, &numCoders)) if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) return SZ_ERROR_UNSUPPORTED;+ f->NumCoders = numCoders; for (i = 0; i < numCoders; i++) { Byte mainByte;- CSzCoderInfo *coder = f->Coders + i;- unsigned idSize, j;- UInt64 id;- - SZ_READ_BYTE(mainByte)- if ((mainByte & 0xC0) != 0)- return SZ_ERROR_UNSUPPORTED;- - idSize = (unsigned)(mainByte & 0xF);- if (idSize > sizeof(id))- return SZ_ERROR_UNSUPPORTED;- if (idSize > sd->Size)- return SZ_ERROR_ARCHIVE;- id = 0;- for (j = 0; j < idSize; j++)+ CSzCoderInfo *coder; {- id = ((id << 8) | *sd->Data);- sd->Data++;+ unsigned idSize, j;+ UInt64 id;+ const Byte *data;+ + if (!sd->Size)+ return SZ_ERROR_ARCHIVE; sd->Size--;+ data = sd->Data;+ mainByte = *data++;+ if (mainByte & 0xC0)+ return SZ_ERROR_UNSUPPORTED;+ idSize = mainByte & 0xF;+ if (idSize > sizeof(id))+ return SZ_ERROR_UNSUPPORTED;+ if (idSize > sd->Size)+ return SZ_ERROR_ARCHIVE;+ sd->Size -= idSize;+ id = 0;+ for (j = 0; j < idSize; j++)+ id = (id << 8) | *data++;+ sd->Data = data;+ if (id > (UInt32)0xFFFFFFFF)+ return SZ_ERROR_UNSUPPORTED;+ coder = f->Coders + i;+ coder->MethodID = (UInt32)id; }- if (id > (UInt32)0xFFFFFFFF)- return SZ_ERROR_UNSUPPORTED;- coder->MethodID = (UInt32)id; coder->NumStreams = 1; coder->PropsOffset = 0; coder->PropsSize = 0; - if ((mainByte & 0x10) != 0)+ if (mainByte & 0x10) { UInt32 numStreams;- RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; coder->NumStreams = (Byte)numStreams;- RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams != 1) return SZ_ERROR_UNSUPPORTED; } numInStreams += coder->NumStreams;- if (numInStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; - if ((mainByte & 0x20) != 0)+ if (mainByte & 0x20) {- UInt32 propsSize = 0;+ UInt32 propsSize; RINOK(SzReadNumber32(sd, &propsSize)) if (propsSize > sd->Size) return SZ_ERROR_ARCHIVE;@@ -521,14 +503,6 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) } } - /*- if (numInStreams == 1 && numCoders == 1)- {- f->NumPackStreams = 1;- f->PackStreams[0] = 0;- }- else- */ { Byte streamUsed[k_NumCodersStreams_in_Folder_MAX]; UInt32 numBonds, numPackStreams;@@ -545,14 +519,13 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) return SZ_ERROR_UNSUPPORTED; f->NumPackStreams = numPackStreams; - for (i = 0; i < numInStreams; i++)+ for (i = 0; i < Z7_ARRAY_SIZE(streamUsed); i++) // numInStreams streamUsed[i] = False; - if (numBonds != 0)+ if (numBonds) { Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];-- for (i = 0; i < numCoders; i++)+ for (i = 0; i < Z7_ARRAY_SIZE(coderUsed); i++) // numCoders coderUsed[i] = False; for (i = 0; i < numBonds; i++)@@ -570,24 +543,25 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) coderUsed[bp->OutIndex] = True; } - for (i = 0; i < numCoders; i++)+ for (i = 0;;)+ { if (!coderUsed[i])- {- f->UnpackStream = i; break;- }- - if (i == numCoders)- return SZ_ERROR_ARCHIVE;+ if (++i == numCoders)+ return SZ_ERROR_ARCHIVE;+ }+ f->UnpackStream = i; } if (numPackStreams == 1) {- for (i = 0; i < numInStreams; i++)+ for (i = 0;; i++)+ {+ if (i == numInStreams)+ return SZ_ERROR_ARCHIVE; if (!streamUsed[i]) break;- if (i == numInStreams)- return SZ_ERROR_ARCHIVE;+ } f->PackStreams[0] = i; } else@@ -601,40 +575,30 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) f->PackStreams[i] = index; } }-- f->NumCoders = numCoders;- return SZ_OK; } -static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)+static SRes SkipNumbers(CSzData *sd2, UInt32 num) {- CSzData sd;- sd = *sd2;+ const Byte *data = sd2->Data;+ size_t size = sd2->Size; for (; num != 0; num--) {- Byte firstByte, mask;+ unsigned firstByte; unsigned i;- SZ_READ_BYTE_2(firstByte)- if ((firstByte & 0x80) == 0)- continue;- if ((firstByte & 0x40) == 0)- {- if (sd.Size == 0)- return SZ_ERROR_ARCHIVE;- sd.Size--;- sd.Data++;- continue;- }- mask = 0x20;- for (i = 2; i < 8 && (firstByte & mask) != 0; i++)- mask >>= 1;- if (i > sd.Size)+ if (size == 0)+ return SZ_ERROR_ARCHIVE;+ firstByte = *data;+ for (i = 1; firstByte & 0x80; i++)+ firstByte <<= 1;+ if (size < i) return SZ_ERROR_ARCHIVE;- SKIP_DATA2(sd, i)+ size -= i;+ data += i; }- *sd2 = sd;+ sd2->Data = data;+ sd2->Size = size; return SZ_OK; } @@ -642,15 +606,10 @@ static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) #define k_Scan_NumCoders_MAX 64 #define k_Scan_NumCodersStreams_in_Folder_MAX 64 --static SRes ReadUnpackInfo(CSzAr *p,- CSzData *sd2,- UInt32 numFoldersMax,- const CBuf *tempBufs, UInt32 numTempBufs,- ISzAllocPtr alloc)+static SRes ReadUnpackInfo(CSzAr *p, CSzData *sd2, const UInt32 numFoldersMax,+ const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) { CSzData sd;- UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; const Byte *startBufPtr; Byte external;@@ -742,15 +701,12 @@ static SRes ReadUnpackInfo(CSzAr *p, { Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX]; Byte coderUsed[k_Scan_NumCoders_MAX];- UInt32 i; const UInt32 numBonds = numCoders - 1; if (numInStreams < numBonds) return SZ_ERROR_ARCHIVE;- if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED;- for (i = 0; i < numInStreams; i++) streamUsed[i] = False; for (i = 0; i < numCoders; i++)@@ -782,16 +738,15 @@ static SRes ReadUnpackInfo(CSzAr *p, return SZ_ERROR_ARCHIVE; streamUsed[index] = True; }- - for (i = 0; i < numCoders; i++)++ for (i = 0;;)+ { if (!coderUsed[i])- {- indexOfMainStream = i; break;- }- - if (i == numCoders)- return SZ_ERROR_ARCHIVE;+ if (++i == numCoders)+ return SZ_ERROR_ARCHIVE;+ }+ indexOfMainStream = i; } p->FoStartPackStreamIndex[fo] = packStreamIndex;@@ -806,31 +761,38 @@ static SRes ReadUnpackInfo(CSzAr *p, } } + {+ const size_t k_numCodersOutStreams_Limit = (size_t)1 << (sizeof(size_t) * 8 - 4);+ if (numCodersOutStreams >= k_numCodersOutStreams_Limit)+ return SZ_ERROR_UNSUPPORTED;+ } p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;- + p->FoStartPackStreamIndex[fo] = packStreamIndex; { const size_t dataSize = (size_t)(sd.Data - startBufPtr);- p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoCodersOffsets[fo] = dataSize; MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc) } - if (external != 0)+ if (external) {- if (sd.Size != 0)+ if (sd.Size) return SZ_ERROR_ARCHIVE; sd = *sd2; } RINOK(WaitId(&sd, k7zIdCodersUnpackSize))- - MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc) {- UInt32 i;- for (i = 0; i < numCodersOutStreams; i++)- {- RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i))- }+ UInt64 *sizes;+ MY_ALLOC_ZE(UInt64, sizes, (size_t)numCodersOutStreams, alloc)+ p->CoderUnpackSizes = sizes;+ if (numCodersOutStreams)+ do+ {+ RINOK(ReadNumber(&sd, sizes))+ sizes++;+ }+ while (--numCodersOutStreams); } for (;;)@@ -838,10 +800,7 @@ static SRes ReadUnpackInfo(CSzAr *p, UInt64 type; RINOK(ReadID(&sd, &type)) if (type == k7zIdEnd)- {- *sd2 = sd;- return SZ_OK;- }+ break; if (type == k7zIdCRC) { RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc))@@ -849,6 +808,8 @@ static SRes ReadUnpackInfo(CSzAr *p, } RINOK(SkipData(&sd)) }+ *sd2 = sd;+ return SZ_OK; } @@ -868,12 +829,12 @@ typedef struct } CSubStreamInfo; -static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)+static SRes ReadSubStreamsInfo(const CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { UInt64 type = 0;- UInt32 numSubDigests = 0; const UInt32 numFolders = p->NumFolders; UInt32 numUnpackStreams = numFolders;+ UInt32 numSubDigests = numFolders; UInt32 numUnpackSizesInData = 0; for (;;)@@ -882,6 +843,8 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) if (type == k7zIdNumUnpackStream) { UInt32 i;+ if (ssi->sdNumSubStreams.Data)+ return SZ_ERROR_UNSUPPORTED; ssi->sdNumSubStreams.Data = sd->Data; numUnpackStreams = 0; numSubDigests = 0;@@ -889,10 +852,10 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams))- if (numUnpackStreams > numUnpackStreams + numStreams)- return SZ_ERROR_UNSUPPORTED; numUnpackStreams += numStreams;- if (numStreams != 0)+ if (numUnpackStreams < numStreams)+ return SZ_ERROR_UNSUPPORTED;+ if (numStreams) numUnpackSizesInData += (numStreams - 1); if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) numSubDigests += numStreams;@@ -905,12 +868,8 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) RINOK(SkipData(sd)) } - if (!ssi->sdNumSubStreams.Data)- {- numSubDigests = numFolders;- if (p->FolderCRCs.Defs)- numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);- }+ if (!ssi->sdNumSubStreams.Data && p->FolderCRCs.Defs)+ numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); ssi->NumTotalSubStreams = numUnpackStreams; ssi->NumSubDigests = numSubDigests;@@ -929,6 +888,8 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) return SZ_OK; if (type == k7zIdCRC) {+ if (ssi->sdCRCs.Data)+ return SZ_ERROR_UNSUPPORTED; ssi->sdCRCs.Data = sd->Data; RINOK(SkipBitUi32s(sd, numSubDigests)) ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data);@@ -941,9 +902,11 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) } } + static SRes SzReadStreamsInfo(CSzAr *p, CSzData *sd,- UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,+ const UInt32 numFoldersMax,+ const CBuf * const tempBufs, const UInt32 numTempBufs, UInt64 *dataOffset, CSubStreamInfo *ssi, ISzAllocPtr alloc)@@ -985,12 +948,13 @@ static SRes SzReadStreamsInfo(CSzAr *p, return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); } + static SRes SzReadAndDecodePackedStreams( ILookInStreamPtr inStream, CSzData *sd,- CBuf *tempBufs,- UInt32 numFoldersMax,- UInt64 baseOffset,+ CBuf * const tempBufs,+ const UInt32 numFoldersMax,+ const UInt64 baseOffset, CSzAr *p, ISzAllocPtr allocTemp) {@@ -1027,59 +991,62 @@ static SRes SzReadAndDecodePackedStreams( return SZ_OK; } ++// (size & 1) == 0+// (data) is aligned for 2-bytes static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) {- size_t pos = 0;+ const Byte *p, *lim; *offsets++ = 0; if (numFiles == 0) return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; if (size < 2) return SZ_ERROR_ARCHIVE;- if (data[size - 2] != 0 || data[size - 1] != 0)+ lim = data + size;+ if (*(const UInt16 *)(const void *)(lim - 2)) return SZ_ERROR_ARCHIVE;+ p = data; do {- const Byte *p;- if (pos == size)+ if (p >= lim) return SZ_ERROR_ARCHIVE;- for (p = data + pos;- #ifdef _WIN32- *(const UInt16 *)(const void *)p != 0- #else- p[0] != 0 || p[1] != 0- #endif- ; p += 2);- pos = (size_t)(p - data) + 2;- *offsets++ = (pos >> 1);+ for (; *(const UInt16 *)(const void *)p; p += 2);+ p += 2;+ *offsets++ = (size_t)(p - data) >> 1; } while (--numFiles);- return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;+ return (p == lim) ? SZ_OK : SZ_ERROR_ARCHIVE; } -static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,- CSzData *sd2,- const CBuf *tempBufs, UInt32 numTempBufs,- ISzAllocPtr alloc)++static SRes ReadTime(CSzBitUi64s *p, size_t num, CSzData *sd2,+ const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) {- CSzData sd;- UInt32 i;+ const Byte *data;+ size_t size;+ size_t i; CNtfsFileTime *vals; Byte *defs; Byte external; + if (p->Defs)+ return SZ_ERROR_ARCHIVE; RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)) SZ_READ_BYTE_SD(sd2, external) if (external == 0)- sd = *sd2;+ {+ data = sd2->Data;+ size = sd2->Size;+ } else { UInt32 index; RINOK(SzReadNumber32(sd2, &index))- if (index >= numTempBufs)+ if (index >= numTempBufs || sd2->Size) return SZ_ERROR_ARCHIVE;- sd.Data = tempBufs[index].data;- sd.Size = tempBufs[index].size;+ data = tempBufs[index].data;+ size = tempBufs[index].size; } MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc)@@ -1088,18 +1055,18 @@ static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, for (i = 0; i < num; i++) if (SzBitArray_Check(defs, i)) {- if (sd.Size < 8)+ if (size < 8) return SZ_ERROR_ARCHIVE;- vals[i].Low = GetUi32(sd.Data);- vals[i].High = GetUi32(sd.Data + 4);- SKIP_DATA2(sd, 8)+ size -= 8;+ vals[i].Low = GetUi32(data);+ vals[i].High = GetUi32(data + 4);+ data += 8; } else vals[i].High = vals[i].Low = 0; - if (external == 0)- *sd2 = sd;- + if (size)+ return SZ_ERROR_ARCHIVE; return SZ_OK; } @@ -1107,16 +1074,11 @@ static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, #define NUM_ADDITIONAL_STREAMS_MAX 8 -static SRes SzReadHeader2(- CSzArEx *p, /* allocMain */- CSzData *sd,- ILookInStreamPtr inStream,- CBuf *tempBufs, UInt32 *numTempBufs,- ISzAllocPtr allocMain,- ISzAllocPtr allocTemp- )+static SRes SzReadHeader2(CSzArEx *p, CSzData *sd, ILookInStreamPtr inStream,+ CBuf * const tempBufs, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { CSubStreamInfo ssi;+ UInt32 numTempBufs = 0; { UInt64 type;@@ -1153,7 +1115,7 @@ static SRes SzReadHeader2( res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, p->startPosAfterHeader, &tempAr, allocTemp);- *numTempBufs = tempAr.NumFolders;+ numTempBufs = tempAr.NumFolders; SzAr_Free(&tempAr, allocTemp); if (res != SZ_OK)@@ -1163,24 +1125,21 @@ static SRes SzReadHeader2( if (type == k7zIdMainStreamsInfo) {- RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,+ static const UInt32 k_numFoldersMax = (UInt32)1 << 30;+ RINOK(SzReadStreamsInfo(&p->db, sd, k_numFoldersMax, tempBufs, numTempBufs, &p->dataPos, &ssi, allocMain)) p->dataPos += p->startPosAfterHeader; RINOK(ReadID(sd, &type)) } if (type == k7zIdEnd)- { return SZ_OK;- }- if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; } {- UInt32 numFiles = 0;- UInt32 numEmptyStreams = 0;+ UInt32 numFiles, numEmptyStreams = 0; const Byte *emptyStreams = NULL; const Byte *emptyFiles = NULL; @@ -1189,106 +1148,107 @@ static SRes SzReadHeader2( for (;;) {+ CSzData sdSwitch; UInt64 type;- UInt64 size; RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) break;- RINOK(ReadNumber(sd, &size))- if (size > sd->Size)- return SZ_ERROR_ARCHIVE;- - if (type >= ((UInt32)1 << 8)) {+ UInt64 size;+ RINOK(ReadNumber(sd, &size))+ if (size > sd->Size)+ return SZ_ERROR_ARCHIVE;+ sdSwitch.Data = sd->Data;+ sdSwitch.Size = (size_t)size; SKIP_DATA(sd, size) }- else switch ((unsigned)type)+ if (type >= 64)+ continue;+ + switch ((unsigned)type) {+ case k7zIdEmptyStream:+ {+ if (emptyStreams || emptyFiles)+ return SZ_ERROR_ARCHIVE;+ if ((numFiles + 7) >> 3 != sdSwitch.Size)+ return SZ_ERROR_ARCHIVE;+ emptyStreams = sdSwitch.Data;+ numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);+ break;+ }+ + case k7zIdEmptyFile:+ {+ if (emptyFiles)+ return SZ_ERROR_ARCHIVE;+ if ((numEmptyStreams + 7) >> 3 != sdSwitch.Size)+ return SZ_ERROR_ARCHIVE;+ emptyFiles = sdSwitch.Data;+ break;+ }+ case k7zIdName: { size_t namesSize; const Byte *namesData; Byte external;-- SZ_READ_BYTE(external)+ if (p->FileNameOffsets)+ return SZ_ERROR_ARCHIVE;+ SZ_READ_BYTE_SD(&sdSwitch, external) if (external == 0) {- namesSize = (size_t)size - 1;- namesData = sd->Data;+ namesData = sdSwitch.Data;+ namesSize = sdSwitch.Size; } else { UInt32 index;- RINOK(SzReadNumber32(sd, &index))- if (index >= *numTempBufs)+ RINOK(SzReadNumber32(&sdSwitch, &index))+ if (index >= numTempBufs || sdSwitch.Size) return SZ_ERROR_ARCHIVE;- namesData = (tempBufs)[index].data;- namesSize = (tempBufs)[index].size;+ namesData = tempBufs[index].data;+ namesSize = tempBufs[index].size; }-- if ((namesSize & 1) != 0)+ if (namesSize & 1) return SZ_ERROR_ARCHIVE; MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain) MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain) RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))- if (external == 0)- {- SKIP_DATA(sd, namesSize)- }- break;- }- case k7zIdEmptyStream:- {- RINOK(RememberBitVector(sd, numFiles, &emptyStreams))- numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);- emptyFiles = NULL;- break;- }- case k7zIdEmptyFile:- {- RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)) break; }+ case k7zIdWinAttrib: { Byte external;- CSzData sdSwitch;- CSzData *sdPtr;- SzBitUi32s_Free(&p->Attribs, allocMain);- RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain))-- SZ_READ_BYTE(external)- if (external == 0)- sdPtr = sd;- else+ if (p->Attribs.Defs)+ return SZ_ERROR_ARCHIVE;+ RINOK(ReadBitVector(&sdSwitch, numFiles, &p->Attribs.Defs, allocMain))+ SZ_READ_BYTE_SD(&sdSwitch, external)+ if (external) { UInt32 index;- RINOK(SzReadNumber32(sd, &index))- if (index >= *numTempBufs)+ RINOK(SzReadNumber32(&sdSwitch, &index))+ if (index >= numTempBufs || sdSwitch.Size) return SZ_ERROR_ARCHIVE;- sdSwitch.Data = (tempBufs)[index].data;- sdSwitch.Size = (tempBufs)[index].size;- sdPtr = &sdSwitch;+ sdSwitch.Data = tempBufs[index].data;+ sdSwitch.Size = tempBufs[index].size; }- RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain))+ RINOK(ReadUi32s(&sdSwitch, numFiles, &p->Attribs, allocMain))+ if (sdSwitch.Size)+ return SZ_ERROR_ARCHIVE; break; }- /*- case k7zParent:+ + case k7zIdMTime:+ case k7zIdCTime: {- SzBitUi32s_Free(&p->Parents, allocMain);- RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));- RINOK(SzReadSwitch(sd));- RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));+ RINOK(ReadTime((unsigned)type == k7zIdMTime ? &p->MTime: &p->CTime,+ numFiles, &sdSwitch, tempBufs, numTempBufs, allocMain)) break; }- */- case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break;- case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break;- default:- {- SKIP_DATA(sd, size)- }+ + default: break; } } @@ -1487,25 +1447,19 @@ static SRes SzReadHeader( ISzAllocPtr allocTemp) { UInt32 i;- UInt32 numTempBufs = 0; SRes res; CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Init(tempBufs + i); - res = SzReadHeader2(p, sd, inStream,- tempBufs, &numTempBufs,- allocMain, allocTemp);+ res = SzReadHeader2(p, sd, inStream, tempBufs, allocMain, allocTemp); for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Free(tempBufs + i, allocTemp); - RINOK(res)-- if (sd->Size != 0)- return SZ_ERROR_FAIL;-+ if (res == SZ_OK && sd->Size != 0)+ return SZ_ERROR_ARCHIVE; return res; } @@ -1516,53 +1470,52 @@ static SRes SzArEx_Open2( ISzAllocPtr allocTemp) { Byte header[k7zStartHeaderSize];- Int64 startArcPos;+ Int64 startPosAfterHeader; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buf; SRes res; - startArcPos = 0;- RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR))- RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE))-- if (!TestSignatureCandidate(header))- return SZ_ERROR_NO_ARCHIVE;- if (header[6] != k7zMajorVersion)- return SZ_ERROR_UNSUPPORTED;+ startPosAfterHeader = 0; // k7zStartHeaderSize+ RINOK(ILookInStream_Seek(inStream, &startPosAfterHeader, SZ_SEEK_CUR))+ p->startPosAfterHeader = (UInt64)startPosAfterHeader;+ {+ unsigned i;+ for (i = 0; i < k7zSignatureSize; i++)+ if (header[i] != k7zSignature[i])+ return SZ_ERROR_NO_ARCHIVE;+ if (header[6] != 0) // k7zMajorVersion+ return SZ_ERROR_UNSUPPORTED;+ }+ if (CrcCalc(header + 12, 20) != GetUi32(header + 8))+ return SZ_ERROR_CRC; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize;- - if (CrcCalc(header + 12, 20) != GetUi32(header + 8))- return SZ_ERROR_CRC;- p->db.RangeLimit = nextHeaderOffset;-+ if (nextHeaderOffset >= (UInt64)1 << 62 ||+ nextHeaderSize >= (UInt64)1 << 48)+ return SZ_ERROR_NO_ARCHIVE; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0)+ {+ if (nextHeaderOffset != 0 || nextHeaderCRC != 0)+ return SZ_ERROR_NO_ARCHIVE; return SZ_OK;- if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||- nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)- return SZ_ERROR_NO_ARCHIVE;-+ } { Int64 pos = 0; RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END))- if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset ||- (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset ||- (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)+ if ((UInt64)(pos - startPosAfterHeader) < nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; }-- RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset))+ RINOK(LookInStream_SeekTo(inStream, (UInt64)startPosAfterHeader + nextHeaderOffset)) if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM;@@ -1726,61 +1679,23 @@ SRes SzArEx_Extract( size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) {- const size_t offs = p->FileNameOffsets[fileIndex];- const size_t len = p->FileNameOffsets[fileIndex + 1] - offs;- if (dest != 0)+ const size_t * const offsets = p->FileNameOffsets;+ if (!offsets) {- size_t i;- const Byte *src = p->FileNames + offs * 2;- for (i = 0; i < len; i++)- dest[i] = GetUi16(src + i * 2);- }- return len;-}--/*-size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)-{- size_t len;- if (!p->FileNameOffsets)+ if (dest)+ *dest = 0; return 1;- len = 0;- for (;;)- {- UInt32 parent = (UInt32)(Int32)-1;- len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];- if SzBitWithVals_Check(&p->Parents, fileIndex)- parent = p->Parents.Vals[fileIndex];- if (parent == (UInt32)(Int32)-1)- return len;- fileIndex = parent; }-}--UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)-{- BoolInt needSlash;- if (!p->FileNameOffsets)- {- *(--dest) = 0;- return dest;- }- needSlash = False;- for (;;) {- UInt32 parent = (UInt32)(Int32)-1;- size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];- SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);- if (needSlash)- *(dest - 1) = '/';- needSlash = True;- dest -= curLen;-- if SzBitWithVals_Check(&p->Parents, fileIndex)- parent = p->Parents.Vals[fileIndex];- if (parent == (UInt32)(Int32)-1)- return dest;- fileIndex = parent;+ const size_t offs = offsets[fileIndex];+ const size_t len = offsets[fileIndex + 1] - offs;+ if (dest)+ {+ size_t i;+ const Byte *src = p->FileNames + offs * 2;+ for (i = 0; i < len; i++)+ dest[i] = GetUi16a(src + i * 2);+ }+ return len; } }-*/
@@ -1,94 +1,96 @@ /* 7zCrc.c -- CRC32 calculation and init-2023-04-02 : Igor Pavlov : Public domain */+2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "7zCrc.h" #include "CpuArch.h" -#define kCrcPoly 0xEDB88320+// for debug:+// #define __ARM_FEATURE_CRC32 1 -#ifdef MY_CPU_LE- #define CRC_NUM_TABLES 8-#else- #define CRC_NUM_TABLES 9+#ifdef __ARM_FEATURE_CRC32+// #pragma message("__ARM_FEATURE_CRC32")+#define Z7_CRC_HW_FORCE+#endif - UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);- UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);+// #define Z7_CRC_DEBUG_BE+#ifdef Z7_CRC_DEBUG_BE+#undef MY_CPU_LE+#define MY_CPU_BE #endif -#ifndef MY_CPU_BE- UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);- UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);+#ifdef Z7_CRC_HW_FORCE+ #define Z7_CRC_NUM_TABLES_USE 1+#else+#ifdef Z7_CRC_NUM_TABLES+ #define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES+#else+ #define Z7_CRC_NUM_TABLES_USE 12+#endif #endif -/*-extern-CRC_FUNC g_CrcUpdateT4;-CRC_FUNC g_CrcUpdateT4;-*/-extern-CRC_FUNC g_CrcUpdateT8;-CRC_FUNC g_CrcUpdateT8;-extern-CRC_FUNC g_CrcUpdateT0_32;-CRC_FUNC g_CrcUpdateT0_32;-extern-CRC_FUNC g_CrcUpdateT0_64;-CRC_FUNC g_CrcUpdateT0_64;-extern-CRC_FUNC g_CrcUpdate;-CRC_FUNC g_CrcUpdate;--UInt32 g_CrcTable[256 * CRC_NUM_TABLES];--UInt32 Z7_FASTCALL CrcUpdate(UInt32 v, const void *data, size_t size)-{- return g_CrcUpdate(v, data, size, g_CrcTable);-}+#if Z7_CRC_NUM_TABLES_USE < 1+ #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES+#endif -UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)-{- return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;-}+#if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1)+ #define Z7_CRC_NUM_TABLES_TOTAL Z7_CRC_NUM_TABLES_USE+#else+ #define Z7_CRC_NUM_TABLES_TOTAL (Z7_CRC_NUM_TABLES_USE + 1)+#endif -#if CRC_NUM_TABLES < 4 \- || (CRC_NUM_TABLES == 4 && defined(MY_CPU_BE)) \+#ifndef Z7_CRC_HW_FORCE++#if Z7_CRC_NUM_TABLES_USE == 1 \ || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))-UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);-UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))+#define Z7_CRC_UPDATE_T1_FUNC_NAME CrcUpdateGT1+static UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size) {+ const UInt32 *table = g_CrcTable; const Byte *p = (const Byte *)data;- const Byte *pEnd = p + size;- for (; p != pEnd; p++)+ const Byte *lim = p + size;+ for (; p != lim; p++) v = CRC_UPDATE_BYTE_2(v, *p); return v; } #endif ++#if Z7_CRC_NUM_TABLES_USE != 1+#ifndef MY_CPU_BE+ #define FUNC_NAME_LE_2(s) CrcUpdateT ## s+ #define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s)+ #define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE)+ UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table);+#endif+#ifndef MY_CPU_LE+ #define FUNC_NAME_BE_2(s) CrcUpdateT1_BeT ## s+ #define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s)+ #define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE)+ UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table);+#endif+#endif++#endif // Z7_CRC_HW_FORCE+ /* ---------- hardware CRC ---------- */ #ifdef MY_CPU_LE #if defined(MY_CPU_ARM_OR_ARM64)- // #pragma message("ARM*") - #if defined(_MSC_VER)- #if defined(MY_CPU_ARM64)- #if (_MSC_VER >= 1910)- #ifndef __clang__- #define USE_ARM64_CRC- #include <intrin.h>- #endif- #endif- #endif- #elif ( (defined(__clang__) && (__clang_major__ >= 3)) || \- (defined(__GNUC__) && (__GNUC__ > 4) ) ) && \- (__ARM_ARCH >= 8)+ #if (defined(__clang__) && (__clang_major__ >= 3)) \+ || defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \+ || defined(__GNUC__) && (__GNUC__ >= 8) #if !defined(__ARM_FEATURE_CRC32)+// #pragma message("!defined(__ARM_FEATURE_CRC32)")+Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define __ARM_FEATURE_CRC32 1+Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER+ #define Z7_ARM_FEATURE_CRC32_WAS_SET #if defined(__clang__) #if defined(MY_CPU_ARM64) #define ATTRIB_CRC __attribute__((__target__("crc")))@@ -97,100 +99,120 @@ UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UI #endif #else #if defined(MY_CPU_ARM64)+#if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000) #define ATTRIB_CRC __attribute__((__target__("+crc")))+#endif #else+#if !defined(Z7_GCC_VERSION) || (__GNUC__ >= 8)+#if defined(__ARM_FP) && __GNUC__ >= 8+// for -mfloat-abi=hard: similar to <arm_acle.h>+ #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc+simd")))+#else #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))+#endif+#endif #endif #endif #endif #if defined(__ARM_FEATURE_CRC32)- #define USE_ARM64_CRC+ // #pragma message("<arm_acle.h>")+/*+arm_acle.h (GGC):+ before Nov 17, 2017:+#ifdef __ARM_FEATURE_CRC32++ Nov 17, 2017: gcc10.0 (gcc 9.2.0) checked"+#if __ARM_ARCH >= 8+#pragma GCC target ("arch=armv8-a+crc")++ Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1:+#ifdef __ARM_FEATURE_CRC32+#ifdef __ARM_FP+#pragma GCC target ("arch=armv8-a+crc+simd")+#else+#pragma GCC target ("arch=armv8-a+crc")+#endif+*/+#if defined(__ARM_ARCH) && __ARM_ARCH < 8+#if defined(Z7_GCC_VERSION) && (__GNUC__ == 8) && (Z7_GCC_VERSION < 80400) \+ || defined(Z7_GCC_VERSION) && (__GNUC__ == 9) && (Z7_GCC_VERSION < 90201) \+ || defined(Z7_GCC_VERSION) && (__GNUC__ == 10) && (Z7_GCC_VERSION < 100100)+Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER+// #pragma message("#define __ARM_ARCH 8")+#undef __ARM_ARCH+#define __ARM_ARCH 8+Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER+#endif+#endif+ #define Z7_CRC_HW_USE #include <arm_acle.h> #endif+ #elif defined(_MSC_VER)+ #if defined(MY_CPU_ARM64)+ #if (_MSC_VER >= 1910)+ #ifdef __clang__+ // #define Z7_CRC_HW_USE+ // #include <arm_acle.h>+ #else+ #define Z7_CRC_HW_USE+ #include <intrin.h>+ #endif+ #endif+ #endif #endif -#else--// no hardware CRC--// #define USE_CRC_EMU--#ifdef USE_CRC_EMU--#pragma message("ARM64 CRC emulation")--Z7_FORCE_INLINE-UInt32 __crc32b(UInt32 v, UInt32 data)-{- const UInt32 *table = g_CrcTable;- v = CRC_UPDATE_BYTE_2(v, (Byte)data);- return v;-}+#else // non-ARM* -Z7_FORCE_INLINE-UInt32 __crc32w(UInt32 v, UInt32 data)-{- const UInt32 *table = g_CrcTable;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- return v;-}+// #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code+#ifdef Z7_CRC_HW_USE+#include "7zCrcEmu.h"+#endif -Z7_FORCE_INLINE-UInt32 __crc32d(UInt32 v, UInt64 data)-{- const UInt32 *table = g_CrcTable;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;- return v;-}+#endif // non-ARM* -#endif // USE_CRC_EMU -#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE) +#if defined(Z7_CRC_HW_USE) +// #pragma message("USE ARM HW CRC") -#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)+#ifdef MY_CPU_64BIT+ #define CRC_HW_WORD_TYPE UInt64+ #define CRC_HW_WORD_FUNC __crc32d+#else+ #define CRC_HW_WORD_TYPE UInt32+ #define CRC_HW_WORD_FUNC __crc32w+#endif -#define T0_32_UNROLL_BYTES (4 * 4)-#define T0_64_UNROLL_BYTES (4 * 8)+#define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4) -#ifndef ATTRIB_CRC-#define ATTRIB_CRC+#ifdef ATTRIB_CRC+ ATTRIB_CRC #endif-// #pragma message("USE ARM HW CRC")--ATTRIB_CRC-UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table);-ATTRIB_CRC-UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table)+Z7_NO_INLINE+#ifdef Z7_CRC_HW_FORCE+ UInt32 Z7_FASTCALL CrcUpdate+#else+ static UInt32 Z7_FASTCALL CrcUpdate_HW+#endif+ (UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data;- UNUSED_VAR(table);-- for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--)+ for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--) v = __crc32b(v, *p++);-- if (size >= T0_32_UNROLL_BYTES)+ if (size >= CRC_HW_UNROLL_BYTES) { const Byte *lim = p + size;- size &= (T0_32_UNROLL_BYTES - 1);+ size &= CRC_HW_UNROLL_BYTES - 1; lim -= size; do {- v = __crc32w(v, *(const UInt32 *)(const void *)(p));- v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;- v = __crc32w(v, *(const UInt32 *)(const void *)(p));- v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;+ v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));+ v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));+ p += 2 * sizeof(CRC_HW_WORD_TYPE);+ v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));+ v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));+ p += 2 * sizeof(CRC_HW_WORD_TYPE); } while (p != lim); }@@ -201,46 +223,86 @@ UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const return v; } -ATTRIB_CRC-UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table);-ATTRIB_CRC-UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table)+#ifdef Z7_ARM_FEATURE_CRC32_WAS_SET+Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER+#undef __ARM_FEATURE_CRC32+Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER+#undef Z7_ARM_FEATURE_CRC32_WAS_SET+#endif++#endif // defined(Z7_CRC_HW_USE)+#endif // MY_CPU_LE++++#ifndef Z7_CRC_HW_FORCE++#if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)+/*+typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC)+ (UInt32 v, const void *data, size_t size, const UInt32 *table);+Z7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate;+*/+static unsigned g_Crc_Algo;+#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))+static unsigned g_Crc_Be;+#endif+#endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)++++Z7_NO_INLINE+#ifdef Z7_CRC_HW_USE+ static UInt32 Z7_FASTCALL CrcUpdate_Base+#else+ UInt32 Z7_FASTCALL CrcUpdate+#endif+ (UInt32 crc, const void *data, size_t size) {- const Byte *p = (const Byte *)data;- UNUSED_VAR(table);+#if Z7_CRC_NUM_TABLES_USE == 1+ return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);+#else // Z7_CRC_NUM_TABLES_USE != 1+#ifdef Z7_CRC_UPDATE_T1_FUNC_NAME+ if (g_Crc_Algo == 1)+ return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);+#endif - for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--)- v = __crc32b(v, *p++);+#ifdef MY_CPU_LE+ return FUNC_NAME_LE(crc, data, size, g_CrcTable);+#elif defined(MY_CPU_BE)+ return FUNC_NAME_BE(crc, data, size, g_CrcTable);+#else+ if (g_Crc_Be)+ return FUNC_NAME_BE(crc, data, size, g_CrcTable);+ else+ return FUNC_NAME_LE(crc, data, size, g_CrcTable);+#endif+#endif // Z7_CRC_NUM_TABLES_USE != 1+} - if (size >= T0_64_UNROLL_BYTES)- {- const Byte *lim = p + size;- size &= (T0_64_UNROLL_BYTES - 1);- lim -= size;- do- {- v = __crc32d(v, *(const UInt64 *)(const void *)(p));- v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;- v = __crc32d(v, *(const UInt64 *)(const void *)(p));- v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;- }- while (p != lim);- }- - for (; size != 0; size--)- v = __crc32b(v, *p++); - return v;+#ifdef Z7_CRC_HW_USE+Z7_NO_INLINE+UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size)+{+ if (g_Crc_Algo == 0)+ return CrcUpdate_HW(crc, data, size);+ return CrcUpdate_Base(crc, data, size); }+#endif -#undef T0_32_UNROLL_BYTES-#undef T0_64_UNROLL_BYTES+#endif // !defined(Z7_CRC_HW_FORCE) -#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) -#endif // MY_CPU_LE++UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)+{+ return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;+} +MY_ALIGN(64)+UInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL]; void Z7_FASTCALL CrcGenerateTable(void)@@ -248,94 +310,111 @@ void Z7_FASTCALL CrcGenerateTable(void) UInt32 i; for (i = 0; i < 256; i++) {+#if defined(Z7_CRC_HW_FORCE)+ g_CrcTable[i] = __crc32b(i, 0);+#else+ #define kCrcPoly 0xEDB88320 UInt32 r = i; unsigned j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); g_CrcTable[i] = r;+#endif }- for (i = 256; i < 256 * CRC_NUM_TABLES; i++)+ for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++) { const UInt32 r = g_CrcTable[(size_t)i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } - #if CRC_NUM_TABLES < 4- g_CrcUpdate = CrcUpdateT1;- #elif defined(MY_CPU_LE)- // g_CrcUpdateT4 = CrcUpdateT4;- #if CRC_NUM_TABLES < 8- g_CrcUpdate = CrcUpdateT4;- #else // CRC_NUM_TABLES >= 8- g_CrcUpdateT8 = CrcUpdateT8;- /*- #ifdef MY_CPU_X86_OR_AMD64- if (!CPU_Is_InOrder())- #endif- */- g_CrcUpdate = CrcUpdateT8;- #endif- #else+#if !defined(Z7_CRC_HW_FORCE) && \+ (defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE))++#if Z7_CRC_NUM_TABLES_USE <= 1+ g_Crc_Algo = 1;+#else // Z7_CRC_NUM_TABLES_USE <= 1++#if defined(MY_CPU_LE)+ g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;+#else // !defined(MY_CPU_LE) {- #ifndef MY_CPU_BE+#ifndef MY_CPU_BE UInt32 k = 0x01020304; const Byte *p = (const Byte *)&k; if (p[0] == 4 && p[1] == 3)- {- #if CRC_NUM_TABLES < 8- // g_CrcUpdateT4 = CrcUpdateT4;- g_CrcUpdate = CrcUpdateT4;- #else // CRC_NUM_TABLES >= 8- g_CrcUpdateT8 = CrcUpdateT8;- g_CrcUpdate = CrcUpdateT8;- #endif- }+ g_Crc_Algo = Z7_CRC_NUM_TABLES_USE; else if (p[0] != 1 || p[1] != 2)- g_CrcUpdate = CrcUpdateT1;+ g_Crc_Algo = 1; else- #endif // MY_CPU_BE+#endif // MY_CPU_BE {- for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)+ for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--) { const UInt32 x = g_CrcTable[(size_t)i - 256]; g_CrcTable[i] = Z7_BSWAP32(x); }- #if CRC_NUM_TABLES <= 4- g_CrcUpdate = CrcUpdateT1;- #elif CRC_NUM_TABLES <= 8- // g_CrcUpdateT4 = CrcUpdateT1_BeT4;- g_CrcUpdate = CrcUpdateT1_BeT4;- #else // CRC_NUM_TABLES > 8- g_CrcUpdateT8 = CrcUpdateT1_BeT8;- g_CrcUpdate = CrcUpdateT1_BeT8;- #endif+#if defined(Z7_CRC_UPDATE_T1_FUNC_NAME)+ g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;+#endif+#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))+ g_Crc_Be = 1;+#endif } }- #endif // CRC_NUM_TABLES < 4+#endif // !defined(MY_CPU_LE) - #ifdef MY_CPU_LE- #ifdef USE_ARM64_CRC- if (CPU_IsSupported_CRC32())- {- g_CrcUpdateT0_32 = CrcUpdateT0_32;- g_CrcUpdateT0_64 = CrcUpdateT0_64;- g_CrcUpdate =- #if defined(MY_CPU_ARM)- CrcUpdateT0_32;- #else- CrcUpdateT0_64;- #endif- }- #endif- - #ifdef USE_CRC_EMU- g_CrcUpdateT0_32 = CrcUpdateT0_32;- g_CrcUpdateT0_64 = CrcUpdateT0_64;- g_CrcUpdate = CrcUpdateT0_64;- #endif+#ifdef MY_CPU_LE+#ifdef Z7_CRC_HW_USE+ if (CPU_IsSupported_CRC32())+ g_Crc_Algo = 0;+#endif // Z7_CRC_HW_USE+#endif // MY_CPU_LE++#endif // Z7_CRC_NUM_TABLES_USE <= 1+#endif // g_Crc_Algo was declared+}++Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo)+{+ if (algo == 0)+ return &CrcUpdate;++#if defined(Z7_CRC_HW_USE)+ if (algo == sizeof(CRC_HW_WORD_TYPE) * 8)+ {+#ifdef Z7_CRC_HW_FORCE+ return &CrcUpdate;+#else+ if (g_Crc_Algo == 0)+ return &CrcUpdate_HW;+#endif+ }+#endif++#ifndef Z7_CRC_HW_FORCE+ if (algo == Z7_CRC_NUM_TABLES_USE)+ return+ #ifdef Z7_CRC_HW_USE+ &CrcUpdate_Base;+ #else+ &CrcUpdate; #endif+#endif++ return NULL; } #undef kCrcPoly-#undef CRC64_NUM_TABLES+#undef Z7_CRC_NUM_TABLES_USE+#undef Z7_CRC_NUM_TABLES_TOTAL #undef CRC_UPDATE_BYTE_2+#undef FUNC_NAME_LE_2+#undef FUNC_NAME_LE_1+#undef FUNC_NAME_LE+#undef FUNC_NAME_BE_2+#undef FUNC_NAME_BE_1+#undef FUNC_NAME_BE++#undef CRC_HW_UNROLL_BYTES+#undef CRC_HW_WORD_FUNC+#undef CRC_HW_WORD_TYPE
@@ -1,5 +1,5 @@ /* 7zCrc.h -- CRC32 calculation-2023-04-02 : Igor Pavlov : Public domain */+2024-01-22 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_CRC_H #define ZIP7_INC_7Z_CRC_H@@ -20,7 +20,8 @@ void Z7_FASTCALL CrcGenerateTable(void); UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size); -typedef UInt32 (Z7_FASTCALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);+typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_FUNC)(UInt32 v, const void *data, size_t size);+Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo); EXTERN_C_END
@@ -1,117 +1,199 @@-/* 7zCrcOpt.c -- CRC32 calculation-2023-04-02 : Igor Pavlov : Public domain */+/* 7zCrcOpt.c -- CRC32 calculation (optimized functions)+2023-12-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "CpuArch.h" +#if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1++// for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu+// #define Z7_CRC_DEBUG_BE+#ifdef Z7_CRC_DEBUG_BE+#undef MY_CPU_LE+#define MY_CPU_BE+#endif++// the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c+#ifdef Z7_CRC_NUM_TABLES+#define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES+#else+#define Z7_CRC_NUM_TABLES_USE 12+#endif++#if Z7_CRC_NUM_TABLES_USE % 4 || \+ Z7_CRC_NUM_TABLES_USE < 4 * 1 || \+ Z7_CRC_NUM_TABLES_USE > 4 * 6+ #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES+#endif++ #ifndef MY_CPU_BE -#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) -UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);-UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)-{- const Byte *p = (const Byte *)data;- for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)- v = CRC_UPDATE_BYTE_2(v, *p);- for (; size >= 4; size -= 4, p += 4)- {- v ^= *(const UInt32 *)(const void *)p;- v =- (table + 0x300)[((v ) & 0xFF)]- ^ (table + 0x200)[((v >> 8) & 0xFF)]- ^ (table + 0x100)[((v >> 16) & 0xFF)]- ^ (table + 0x000)[((v >> 24))];- }- for (; size > 0; size--, p++)- v = CRC_UPDATE_BYTE_2(v, *p);- return v;-}+#define Q(n, d) \+ ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \+ ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \+ ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \+ ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )++#define R(a) *((const UInt32 *)(const void *)p + (a))++#define CRC_FUNC_PRE_LE2(step) \+UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table) -UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);-UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)+#define CRC_FUNC_PRE_LE(step) \+ CRC_FUNC_PRE_LE2(step); \+ CRC_FUNC_PRE_LE2(step)++CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE) { const Byte *p = (const Byte *)data;- for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)+ const Byte *lim;+ for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++) v = CRC_UPDATE_BYTE_2(v, *p);- for (; size >= 8; size -= 8, p += 8)+ lim = p + size;+ if (size >= Z7_CRC_NUM_TABLES_USE) {- UInt32 d;- v ^= *(const UInt32 *)(const void *)p;- v =- (table + 0x700)[((v ) & 0xFF)]- ^ (table + 0x600)[((v >> 8) & 0xFF)]- ^ (table + 0x500)[((v >> 16) & 0xFF)]- ^ (table + 0x400)[((v >> 24))];- d = *((const UInt32 *)(const void *)p + 1);- v ^=- (table + 0x300)[((d ) & 0xFF)]- ^ (table + 0x200)[((d >> 8) & 0xFF)]- ^ (table + 0x100)[((d >> 16) & 0xFF)]- ^ (table + 0x000)[((d >> 24))];+ lim -= Z7_CRC_NUM_TABLES_USE;+ do+ {+ v ^= R(0);+ {+#if Z7_CRC_NUM_TABLES_USE == 1 * 4+ v = Q(0, v);+#else+#define U2(r, op) \+ { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }+ UInt32 d, x;+ U2(1, =)+#if Z7_CRC_NUM_TABLES_USE >= 3 * 4+#define U(r) U2(r, ^=)+ U(2)+#if Z7_CRC_NUM_TABLES_USE >= 4 * 4+ U(3)+#if Z7_CRC_NUM_TABLES_USE >= 5 * 4+ U(4)+#if Z7_CRC_NUM_TABLES_USE >= 6 * 4+ U(5)+#if Z7_CRC_NUM_TABLES_USE >= 7 * 4+#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES+#endif+#endif+#endif+#endif+#endif+#undef U+#undef U2+ v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);+#endif+ }+ p += Z7_CRC_NUM_TABLES_USE;+ }+ while (p <= lim);+ lim += Z7_CRC_NUM_TABLES_USE; }- for (; size > 0; size--, p++)+ for (; p < lim; p++) v = CRC_UPDATE_BYTE_2(v, *p); return v; } +#undef CRC_UPDATE_BYTE_2+#undef R+#undef Q+#undef CRC_FUNC_PRE_LE+#undef CRC_FUNC_PRE_LE2+ #endif ++ #ifndef MY_CPU_LE -#define CRC_UINT32_SWAP(v) Z7_BSWAP32(v)+#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8)) -#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))+#define Q(n, d) \+ ( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \+ ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \+ ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \+ ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] ) -UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)-{- const Byte *p = (const Byte *)data;- table += 0x100;- v = CRC_UINT32_SWAP(v);- for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)- v = CRC_UPDATE_BYTE_2_BE(v, *p);- for (; size >= 4; size -= 4, p += 4)- {- v ^= *(const UInt32 *)(const void *)p;- v =- (table + 0x000)[((v ) & 0xFF)]- ^ (table + 0x100)[((v >> 8) & 0xFF)]- ^ (table + 0x200)[((v >> 16) & 0xFF)]- ^ (table + 0x300)[((v >> 24))];- }- for (; size > 0; size--, p++)- v = CRC_UPDATE_BYTE_2_BE(v, *p);- return CRC_UINT32_SWAP(v);-}+#ifdef Z7_CRC_DEBUG_BE+ #define R(a) GetBe32a((const UInt32 *)(const void *)p + (a))+#else+ #define R(a) *((const UInt32 *)(const void *)p + (a))+#endif+++#define CRC_FUNC_PRE_BE2(step) \+UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table) -UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)+#define CRC_FUNC_PRE_BE(step) \+ CRC_FUNC_PRE_BE2(step); \+ CRC_FUNC_PRE_BE2(step)++CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE) { const Byte *p = (const Byte *)data;+ const Byte *lim; table += 0x100;- v = CRC_UINT32_SWAP(v);- for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)+ v = Z7_BSWAP32(v);+ for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++) v = CRC_UPDATE_BYTE_2_BE(v, *p);- for (; size >= 8; size -= 8, p += 8)+ lim = p + size;+ if (size >= Z7_CRC_NUM_TABLES_USE) {- UInt32 d;- v ^= *(const UInt32 *)(const void *)p;- v =- (table + 0x400)[((v ) & 0xFF)]- ^ (table + 0x500)[((v >> 8) & 0xFF)]- ^ (table + 0x600)[((v >> 16) & 0xFF)]- ^ (table + 0x700)[((v >> 24))];- d = *((const UInt32 *)(const void *)p + 1);- v ^=- (table + 0x000)[((d ) & 0xFF)]- ^ (table + 0x100)[((d >> 8) & 0xFF)]- ^ (table + 0x200)[((d >> 16) & 0xFF)]- ^ (table + 0x300)[((d >> 24))];+ lim -= Z7_CRC_NUM_TABLES_USE;+ do+ {+ v ^= R(0);+ {+#if Z7_CRC_NUM_TABLES_USE == 1 * 4+ v = Q(0, v);+#else+#define U2(r, op) \+ { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }+ UInt32 d, x;+ U2(1, =)+#if Z7_CRC_NUM_TABLES_USE >= 3 * 4+#define U(r) U2(r, ^=)+ U(2)+#if Z7_CRC_NUM_TABLES_USE >= 4 * 4+ U(3)+#if Z7_CRC_NUM_TABLES_USE >= 5 * 4+ U(4)+#if Z7_CRC_NUM_TABLES_USE >= 6 * 4+ U(5)+#if Z7_CRC_NUM_TABLES_USE >= 7 * 4+#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES+#endif+#endif+#endif+#endif+#endif+#undef U+#undef U2+ v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);+#endif+ }+ p += Z7_CRC_NUM_TABLES_USE;+ }+ while (p <= lim);+ lim += Z7_CRC_NUM_TABLES_USE; }- for (; size > 0; size--, p++)+ for (; p < lim; p++) v = CRC_UPDATE_BYTE_2_BE(v, *p);- return CRC_UINT32_SWAP(v);+ return Z7_BSWAP32(v); } +#undef CRC_UPDATE_BYTE_2_BE+#undef R+#undef Q+#undef CRC_FUNC_PRE_BE+#undef CRC_FUNC_PRE_BE2++#endif+#undef Z7_CRC_NUM_TABLES_USE #endif
@@ -1,5 +1,5 @@ /* 7zDec.c -- Decoding from 7z folder-2023-04-02 : Igor Pavlov : Public domain */+: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -51,6 +51,7 @@ #ifndef Z7_NO_METHODS_FILTERS #define k_Delta 3+#define k_RISCV 0xb #define k_BCJ 0x3030103 #define k_PPC 0x3030205 #define k_IA64 0x3030401@@ -311,8 +312,9 @@ static BoolInt IS_MAIN_METHOD(UInt32 m) case k_PPMD: #endif return True;+ default:+ return False; }- return False; } static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)@@ -362,6 +364,7 @@ static SRes CheckSupportedFolder(const CSzFolder *f) case k_IA64: case k_SPARC: case k_ARM:+ case k_RISCV: #endif #ifdef Z7_USE_FILTER_ARM64 case k_ARM64:@@ -535,10 +538,10 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, } } }- #if defined(Z7_USE_BRANCH_FILTER)+#if defined(Z7_USE_BRANCH_FILTER) else if (ci == 1) {- #if !defined(Z7_NO_METHODS_FILTERS)+#if !defined(Z7_NO_METHODS_FILTERS) if (coder->MethodID == k_Delta) { if (coder->PropsSize != 1)@@ -550,22 +553,43 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, } continue; }- #endif+#endif - #ifdef Z7_USE_FILTER_ARM64+#ifdef Z7_USE_FILTER_ARM64 if (coder->MethodID == k_ARM64) { UInt32 pc = 0; if (coder->PropsSize == 4)+ { pc = GetUi32(propsData + coder->PropsOffset);+ if (pc & 3)+ return SZ_ERROR_UNSUPPORTED;+ } else if (coder->PropsSize != 0) return SZ_ERROR_UNSUPPORTED; z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc); continue; }- #endif- - #if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT)+#endif++#if !defined(Z7_NO_METHODS_FILTERS)+ if (coder->MethodID == k_RISCV)+ {+ UInt32 pc = 0;+ if (coder->PropsSize == 4)+ {+ pc = GetUi32(propsData + coder->PropsOffset);+ if (pc & 1)+ return SZ_ERROR_UNSUPPORTED;+ }+ else if (coder->PropsSize != 0)+ return SZ_ERROR_UNSUPPORTED;+ z7_BranchConv_RISCV_Dec(outBuffer, outSize, pc);+ continue;+ }+#endif+ +#if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) { if (coder->PropsSize != 0) return SZ_ERROR_UNSUPPORTED;@@ -579,7 +603,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0 break; }- CASE_BRA_CONV(PPC)+ case k_PPC: Z7_BRANCH_CONV_DEC_2(BranchConv_PPC)(outBuffer, outSize, 0); break; // pc = 0;+ // CASE_BRA_CONV(PPC) CASE_BRA_CONV(IA64) CASE_BRA_CONV(SPARC) CASE_BRA_CONV(ARM)@@ -592,9 +617,9 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, } continue; }- #endif+#endif } // (c == 1)- #endif+#endif // Z7_USE_BRANCH_FILTER else return SZ_ERROR_UNSUPPORTED; }
@@ -1,12 +1,11 @@ /* 7zFile.h -- File IO-2023-03-05 : Igor Pavlov : Public domain */+: Igor Pavlov : Public domain */ #ifndef ZIP7_INC_FILE_H #define ZIP7_INC_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE-// #include <windows.h> #endif #ifdef USE_WINDOWS_FILE
@@ -1,5 +1,5 @@ /* 7zTypes.h -- Basic types-2023-04-02 : Igor Pavlov : Public domain */+: Igor Pavlov : Public domain */ #ifndef ZIP7_7Z_TYPES_H #define ZIP7_7Z_TYPES_H@@ -46,8 +46,9 @@ typedef int SRes; #ifdef _MSC_VER+ #define MY_ALIGN_IN_STRUCT(n) __declspec(align(n)) #if _MSC_VER > 1200- #define MY_ALIGN(n) __declspec(align(n))+ #define MY_ALIGN(n) MY_ALIGN_IN_STRUCT(n) #else #define MY_ALIGN(n) #endif@@ -58,6 +59,7 @@ typedef int SRes; #define MY_ALIGN(n) alignas(n) */ #define MY_ALIGN(n) __attribute__ ((aligned(n)))+ #define MY_ALIGN_IN_STRUCT(n) MY_ALIGN(n) #endif @@ -530,20 +532,20 @@ struct ISzAlloc #define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m) */ #if defined (__clang__) || defined(__GNUC__)-#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \+#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")-#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL \+#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL \ _Pragma("GCC diagnostic pop") #else-#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL-#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL+#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL+#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL #endif #define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \- Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \+ Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \ type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \- Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL+ Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL #define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \ Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p)
@@ -1,11 +1,17 @@-/* 7zWindows.h -- StdAfx-2023-04-02 : Igor Pavlov : Public domain */+/* 7zWindows.h -- Windows.h and related code+Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_WINDOWS_H #define ZIP7_INC_7Z_WINDOWS_H #ifdef _WIN32 +#if defined(_MSC_VER) && _MSC_VER >= 1950 && !defined(__clang__) // VS2026+// <Windows.h> and some another windows files need that option+// VS2026: wtypesbase.h: warning C4865: 'tagCLSCTX': the underlying type will change from 'int' to 'unsigned int' when '/Zc:enumTypes' is specified on the command line+#pragma warning(disable : 4865)+#endif+ #if defined(__clang__) # pragma clang diagnostic push #endif
@@ -1,11 +1,11 @@ /* Bra.c -- Branch converters for RISC code-2023-04-02 : Igor Pavlov : Public domain */+2024-01-20 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Bra.h"-#include "CpuArch.h" #include "RotateDefs.h"+#include "CpuArch.h" #if defined(MY_CPU_SIZEOF_POINTER) \ && ( MY_CPU_SIZEOF_POINTER == 4 \@@ -26,7 +26,7 @@ #define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; // #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; -#define Z7_BRANCH_CONV(name) z7_BranchConv_ ## name+#define Z7_BRANCH_CONV(name) z7_ ## name #define Z7_BRANCH_FUNC_MAIN(name) \ static \@@ -42,11 +42,11 @@ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \ #ifdef Z7_EXTRACT_ONLY #define Z7_BRANCH_FUNCS_IMP(name) \- Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0)+ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) #else #define Z7_BRANCH_FUNCS_IMP(name) \- Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) \- Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC, 1)+ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \+ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1) #endif #if defined(__clang__)@@ -72,7 +72,7 @@ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \ #endif -Z7_BRANCH_FUNC_MAIN(ARM64)+Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64) { // Byte *p = data; const Byte *lim;@@ -121,10 +121,10 @@ Z7_BRANCH_FUNC_MAIN(ARM64) } } }-Z7_BRANCH_FUNCS_IMP(ARM64)+Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64) -Z7_BRANCH_FUNC_MAIN(ARM)+Z7_BRANCH_FUNC_MAIN(BranchConv_ARM) { // Byte *p = data; const Byte *lim;@@ -152,10 +152,10 @@ Z7_BRANCH_FUNC_MAIN(ARM) } } }-Z7_BRANCH_FUNCS_IMP(ARM)+Z7_BRANCH_FUNCS_IMP(BranchConv_ARM) -Z7_BRANCH_FUNC_MAIN(PPC)+Z7_BRANCH_FUNC_MAIN(BranchConv_PPC) { // Byte *p = data; const Byte *lim;@@ -192,14 +192,14 @@ Z7_BRANCH_FUNC_MAIN(PPC) } } }-Z7_BRANCH_FUNCS_IMP(PPC)+Z7_BRANCH_FUNCS_IMP(BranchConv_PPC) #ifdef Z7_CPU_FAST_ROTATE_SUPPORTED #define BR_SPARC_USE_ROTATE #endif -Z7_BRANCH_FUNC_MAIN(SPARC)+Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC) { // Byte *p = data; const Byte *lim;@@ -254,10 +254,10 @@ Z7_BRANCH_FUNC_MAIN(SPARC) } } }-Z7_BRANCH_FUNCS_IMP(SPARC)+Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC) -Z7_BRANCH_FUNC_MAIN(ARMT)+Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT) { // Byte *p = data; Byte *lim;@@ -335,12 +335,12 @@ Z7_BRANCH_FUNC_MAIN(ARMT) // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2)); // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2)); }-Z7_BRANCH_FUNCS_IMP(ARMT)+Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT) // #define BR_IA64_NO_INLINE -Z7_BRANCH_FUNC_MAIN(IA64)+Z7_BRANCH_FUNC_MAIN(BranchConv_IA64) { // Byte *p = data; const Byte *lim;@@ -417,4 +417,293 @@ Z7_BRANCH_FUNC_MAIN(IA64) } } }-Z7_BRANCH_FUNCS_IMP(IA64)+Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)+++#define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET;+#define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET;++#if 1 && defined(MY_CPU_LE_UNALIGN)+ #define RISCV_USE_UNALIGNED_LOAD+#endif++#ifdef RISCV_USE_UNALIGNED_LOAD+ #define RISCV_GET_UI32(p) GetUi32(p)+ #define RISCV_SET_UI32(p, v) { SetUi32(p, v) }+#else+ #define RISCV_GET_UI32(p) \+ ((UInt32)GetUi16a(p) + \+ ((UInt32)GetUi16a((p) + 2) << 16))+ #define RISCV_SET_UI32(p, v) { \+ SetUi16a(p, (UInt16)(v)) \+ SetUi16a((p) + 2, (UInt16)(v >> 16)) }+#endif++#if 1 && defined(MY_CPU_LE)+ #define RISCV_USE_16BIT_LOAD+#endif++#ifdef RISCV_USE_16BIT_LOAD+ #define RISCV_LOAD_VAL(p) GetUi16a(p)+#else+ #define RISCV_LOAD_VAL(p) (*(p))+#endif++#define RISCV_INSTR_SIZE 2+#define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE)+#define RISCV_STEP_2 4+#define RISCV_REG_VAL (2 << 7)+#define RISCV_CMD_VAL 3+#if 1+ // for code size optimization:+ #define RISCV_DELTA_7F 0x7f+#else+ #define RISCV_DELTA_7F 0+#endif++#define RISCV_CHECK_1(v, b) \+ (((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)++#if 1+ #define RISCV_CHECK_2(v, r) \+ ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \+ << 18) \+ < ((r) & 0x1d))+#else+ // this branch gives larger code, because+ // compilers generate larger code for big constants.+ #define RISCV_CHECK_2(v, r) \+ ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \+ & ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \+ < ((r) & 0x1d))+#endif+++#define RISCV_SCAN_LOOP \+ Byte *lim; \+ size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \+ if (size <= 6) return p; \+ size -= 6; \+ lim = p + size; \+ BR_PC_INIT \+ for (;;) \+ { \+ UInt32 a, v; \+ /* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \+ for (;;) \+ { \+ if Z7_UNLIKELY(p >= lim) { return p; } \+ a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \+ if ((a & 0x77) == 0) break; \+ a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \+ p += RISCV_INSTR_SIZE * 2; \+ if ((a & 0x77) == 0) \+ { \+ p -= RISCV_INSTR_SIZE; \+ if Z7_UNLIKELY(p >= lim) { return p; } \+ break; \+ } \+ }+// (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL+// (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL+// (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC+// (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC++Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)+{+ RISCV_SCAN_LOOP+ v = a;+ a = RISCV_GET_UI32(p);+#ifndef RISCV_USE_16BIT_LOAD+ v += (UInt32)p[1] << 8;+#endif++ if ((v & 8) == 0) // JAL+ {+ if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)+ {+ p += RISCV_INSTR_SIZE;+ continue;+ }+ {+ v = ((a & 1u << 31) >> 11)+ | ((a & 0x3ff << 21) >> 20)+ | ((a & 1 << 20) >> 9)+ | (a & 0xff << 12);+ BR_CONVERT_VAL_ENC(v)+ // ((v & 1) == 0)+ // v: bits [1 : 20] contain offset bits+#if 0 && defined(RISCV_USE_UNALIGNED_LOAD)+ a &= 0xfff;+ a |= ((UInt32)(v << 23))+ | ((UInt32)(v << 7) & ((UInt32)0xff << 16))+ | ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8));+ RISCV_SET_UI32(p, a)+#else // aligned+#if 0+ SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))+#else+ p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));+#endif++#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)+ v <<= 15;+ v = Z7_BSWAP32(v);+ SetUi16a(p + 2, (UInt16)v)+#else+ p[2] = (Byte)(v >> 9);+ p[3] = (Byte)(v >> 1);+#endif+#endif // aligned+ }+ p += 4;+ continue;+ } // JAL++ {+ // AUIPC+ if (v & 0xe80) // (not x0) and (not x2)+ {+ const UInt32 b = RISCV_GET_UI32(p + 4);+ if (RISCV_CHECK_1(v, b))+ {+ {+ const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);+ RISCV_SET_UI32(p, temp)+ }+ a &= 0xfffff000;+ {+#if 1+ const int t = -1 >> 1;+ if (t != -1)+ a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation+ else+#endif+ a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).+ }+ BR_CONVERT_VAL_ENC(a)+#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)+ a = Z7_BSWAP32(a);+ RISCV_SET_UI32(p + 4, a)+#else+ SetBe32(p + 4, a)+#endif+ p += 8;+ }+ else+ p += RISCV_STEP_1;+ }+ else+ {+ UInt32 r = a >> 27;+ if (RISCV_CHECK_2(v, r))+ {+ v = RISCV_GET_UI32(p + 4);+ r = (r << 7) + 0x17 + (v & 0xfffff000);+ a = (a >> 12) | (v << 20);+ RISCV_SET_UI32(p, r)+ RISCV_SET_UI32(p + 4, a)+ p += 8;+ }+ else+ p += RISCV_STEP_2;+ }+ }+ } // for+}+++Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)+{+ RISCV_SCAN_LOOP+#ifdef RISCV_USE_16BIT_LOAD+ if ((a & 8) == 0)+ {+#else+ v = a;+ a += (UInt32)p[1] << 8;+ if ((v & 8) == 0)+ {+#endif+ // JAL+ a -= 0x100 - RISCV_DELTA_7F;+ if (a & 0xd80)+ {+ p += RISCV_INSTR_SIZE;+ continue;+ }+ {+ const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;+#if 0 // unaligned+ a = GetUi32(p);+ v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)+ | (UInt32)(a >> 7) & ((UInt32)0xff << 9)+#elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)+ v = GetUi16a(p + 2);+ v = Z7_BSWAP32(v) >> 15+#else+ v = (UInt32)p[3] << 1+ | (UInt32)p[2] << 9+#endif+ | (UInt32)((a & 0xf000) << 5);+ BR_CONVERT_VAL_DEC(v)+ a = a_old+ | (v << 11 & 1u << 31)+ | (v << 20 & 0x3ff << 21)+ | (v << 9 & 1 << 20)+ | (v & 0xff << 12);+ RISCV_SET_UI32(p, a)+ }+ p += 4;+ continue;+ } // JAL++ {+ // AUIPC+ v = a;+#if 1 && defined(RISCV_USE_UNALIGNED_LOAD)+ a = GetUi32(p);+#else+ a |= (UInt32)GetUi16a(p + 2) << 16;+#endif+ if ((v & 0xe80) == 0) // x0/x2+ {+ const UInt32 r = a >> 27;+ if (RISCV_CHECK_2(v, r))+ {+ UInt32 b;+#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)+ b = RISCV_GET_UI32(p + 4);+ b = Z7_BSWAP32(b);+#else+ b = GetBe32(p + 4);+#endif+ v = a >> 12;+ BR_CONVERT_VAL_DEC(b)+ a = (r << 7) + 0x17;+ a += (b + 0x800) & 0xfffff000;+ v |= b << 20;+ RISCV_SET_UI32(p, a)+ RISCV_SET_UI32(p + 4, v)+ p += 8;+ }+ else+ p += RISCV_STEP_2;+ }+ else+ {+ const UInt32 b = RISCV_GET_UI32(p + 4);+ if (!RISCV_CHECK_1(v, b))+ p += RISCV_STEP_1;+ else+ {+ v = (a & 0xfffff000) | (b >> 20);+ a = (b << 12) | (0x17 + RISCV_REG_VAL);+ RISCV_SET_UI32(p, a)+ RISCV_SET_UI32(p + 4, v)+ p += 8;+ }+ }+ }+ } // for+}
@@ -1,5 +1,5 @@ /* Bra.h -- Branch converters for executables-2023-04-02 : Igor Pavlov : Public domain */+2024-01-20 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_BRA_H #define ZIP7_INC_BRA_H@@ -8,8 +8,12 @@ EXTERN_C_BEGIN -#define Z7_BRANCH_CONV_DEC(name) z7_BranchConv_ ## name ## _Dec-#define Z7_BRANCH_CONV_ENC(name) z7_BranchConv_ ## name ## _Enc+/* #define PPC BAD_PPC_11 // for debug */++#define Z7_BRANCH_CONV_DEC_2(name) z7_ ## name ## _Dec+#define Z7_BRANCH_CONV_ENC_2(name) z7_ ## name ## _Enc+#define Z7_BRANCH_CONV_DEC(name) Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name)+#define Z7_BRANCH_CONV_ENC(name) Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name) #define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec #define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc @@ -20,19 +24,20 @@ typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv)); typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); #define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0-Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_DEC(X86));-Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_ENC(X86));+Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86));+Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86)); #define Z7_BRANCH_FUNCS_DECL(name) \-Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_DEC(name)); \-Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_ENC(name));+Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \+Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name)); -Z7_BRANCH_FUNCS_DECL(ARM64)-Z7_BRANCH_FUNCS_DECL(ARM)-Z7_BRANCH_FUNCS_DECL(ARMT)-Z7_BRANCH_FUNCS_DECL(PPC)-Z7_BRANCH_FUNCS_DECL(SPARC)-Z7_BRANCH_FUNCS_DECL(IA64)+Z7_BRANCH_FUNCS_DECL (BranchConv_ARM64)+Z7_BRANCH_FUNCS_DECL (BranchConv_ARM)+Z7_BRANCH_FUNCS_DECL (BranchConv_ARMT)+Z7_BRANCH_FUNCS_DECL (BranchConv_PPC)+Z7_BRANCH_FUNCS_DECL (BranchConv_SPARC)+Z7_BRANCH_FUNCS_DECL (BranchConv_IA64)+Z7_BRANCH_FUNCS_DECL (BranchConv_RISCV) /* These functions convert data that contain CPU instructions.@@ -49,14 +54,14 @@ and one for decoding (_Enc/_Dec postfixes in function name). In params: data : data buffer size : size of data- pc : current virtual Program Counter (Instruction Pinter) value+ pc : current virtual Program Counter (Instruction Pointer) value In/Out param: state : pointer to state variable (for X86 converter only) Return: The pointer to position in (data) buffer after last byte that was processed. If the caller calls converter again, it must call it starting with that position.- But the caller is allowed to move data in buffer. so pointer to+ But the caller is allowed to move data in buffer. So pointer to current processed position also will be changed for next call. Also the caller must increase internal (pc) value for next call. @@ -65,6 +70,7 @@ Each converter has some characteristics: Endian, Alignment, LookAhead. X86 little 1 4 ARMT little 2 2+ RISCV little 2 6 ARM little 4 0 ARM64 little 4 0 PPC big 4 0
@@ -1,5 +1,5 @@ /* Compiler.h : Compiler specific defines and pragmas-2023-04-02 : Igor Pavlov : Public domain */+: Igor Pavlov : Public domain */ #ifndef ZIP7_INC_COMPILER_H #define ZIP7_INC_COMPILER_H@@ -25,11 +25,90 @@ #define Z7_MINGW #endif +#if defined(__LCC__) && (defined(__MCST__) || defined(__e2k__))+#define Z7_MCST_LCC+#define Z7_MCST_LCC_VERSION (__LCC__ * 100 + __LCC_MINOR__)+#endif++/*+#if defined(__AVX2__) \+ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \+ || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \+ || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \+ || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \+ || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)+ #define Z7_COMPILER_AVX2_SUPPORTED+ #endif+#endif+*/+ // #pragma GCC diagnostic ignored "-Wunknown-pragmas" #ifdef __clang__ // padding size of '' with 4 bytes to alignment boundary #pragma GCC diagnostic ignored "-Wpadded"++#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \+ && defined(__FreeBSD__)+// freebsd:+#pragma GCC diagnostic ignored "-Wexcess-padding"+#endif++#if defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 21+// warning: function MyAlloc might be an allocator wrapper+// clang in xcode: clang 21.0.0+#pragma GCC diagnostic ignored "-Wallocator-wrappers"+#endif++#if __clang_major__ >= 16+#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"+#endif++#if __clang_major__ == 13+#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)+// cheri+#pragma GCC diagnostic ignored "-Wcapability-to-integer-cast"+#endif+#endif++#if __clang_major__ == 13+ // for <arm_neon.h>+ #pragma GCC diagnostic ignored "-Wreserved-identifier"+#endif++#if __clang_major__ >= 22+// for "StdAfx.h" and "Precomp.h"+#pragma GCC diagnostic ignored "-Wshadow-header"+#endif++#endif // __clang__++#if defined(__clang__) && __clang_major__ >= 16+// #pragma GCC diagnostic ignored "-Wcast-function-type-strict"+#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \+ _Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"")+#else+#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION+#endif++typedef void (*Z7_void_Function)(void);+#if defined(__clang__) || defined(__GNUC__)+#define Z7_CAST_FUNC_C (Z7_void_Function)+#elif defined(_MSC_VER) && _MSC_VER > 1920+#define Z7_CAST_FUNC_C (void *)+// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'+#else+#define Z7_CAST_FUNC_C+#endif+/*+#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)+ // #pragma GCC diagnostic ignored "-Wcast-function-type"+#endif+*/+#ifdef __GNUC__+#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40000) && (Z7_GCC_VERSION < 70000)+#pragma GCC diagnostic ignored "-Wstrict-aliasing"+#endif #endif @@ -101,7 +180,8 @@ _Pragma("clang loop unroll(disable)") \ _Pragma("clang loop vectorize(disable)") #define Z7_ATTRIB_NO_VECTORIZE-#elif defined(__GNUC__) && (__GNUC__ >= 5)+#elif defined(__GNUC__) && (__GNUC__ >= 5) \+ && (!defined(Z7_MCST_LCC_VERSION) || (Z7_MCST_LCC_VERSION >= 12610)) #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) // __attribute__((optimize("no-unroll-loops"))); #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE@@ -114,6 +194,16 @@ #define Z7_ATTRIB_NO_VECTORIZE #endif +#if defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1920)+ #define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE _Pragma("optimize ( \"s\", on )")+ #define Z7_PRAGMA_OPTIMIZE_DEFAULT _Pragma("optimize ( \"\", on )")+#else+ #define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE+ #define Z7_PRAGMA_OPTIMIZE_DEFAULT+#endif+++ #if defined(MY_CPU_X86_OR_AMD64) && ( \ defined(__clang__) && (__clang_major__ >= 4) \ || defined(__GNUC__) && (__GNUC__ >= 5))@@ -142,15 +232,23 @@ #endif -#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 36000))-#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \+#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30600))++#if (Z7_CLANG_VERSION < 130000)+#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \+ _Pragma("GCC diagnostic push") \+ _Pragma("GCC diagnostic ignored \"-Wreserved-id-macro\"")+#else+#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"")-#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \+#endif++#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \ _Pragma("GCC diagnostic pop") #else-#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER-#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER+#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER+#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #define UNUSED_VAR(x) (void)x;
@@ -1,5 +1,5 @@ /* CpuArch.c -- CPU specific code-2023-05-18 : Igor Pavlov : Public domain */+Igor Pavlov : Public domain */ #include "Precomp.h" @@ -17,7 +17,7 @@ /* cpuid instruction supports (subFunction) parameter in ECX, that is used only with some specific (function) parameter values.- But we always use only (subFunction==0).+ most functions use only (subFunction==0). */ /* __cpuid(): MSVC and GCC/CLANG use same function/macro name@@ -49,43 +49,49 @@ #if defined(MY_CPU_AMD64) && defined(__PIC__) \ && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) -#define x86_cpuid_MACRO(p, func) { \+ /* "=&r" selects free register. It can select even rbx, if that register is free.+ "=&D" for (RDI) also works, but the code can be larger with "=&D"+ "2"(subFun) : 2 is (zero-based) index in the output constraint list "=c" (ECX). */++#define x86_cpuid_MACRO_2(p, func, subFunc) { \ __asm__ __volatile__ ( \ ASM_LN "mov %%rbx, %q1" \ ASM_LN "cpuid" \ ASM_LN "xchg %%rbx, %q1" \- : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }-- /* "=&r" selects free register. It can select even rbx, if that register is free.- "=&D" for (RDI) also works, but the code can be larger with "=&D"- "2"(0) means (subFunction = 0),- 2 is (zero-based) index in the output constraint list "=c" (ECX). */+ : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); } #elif defined(MY_CPU_X86) && defined(__PIC__) \ && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) -#define x86_cpuid_MACRO(p, func) { \+#define x86_cpuid_MACRO_2(p, func, subFunc) { \ __asm__ __volatile__ ( \ ASM_LN "mov %%ebx, %k1" \ ASM_LN "cpuid" \ ASM_LN "xchg %%ebx, %k1" \- : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }+ : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); } #else -#define x86_cpuid_MACRO(p, func) { \+#define x86_cpuid_MACRO_2(p, func, subFunc) { \ __asm__ __volatile__ ( \ ASM_LN "cpuid" \- : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }+ : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); } #endif +#define x86_cpuid_MACRO(p, func) x86_cpuid_MACRO_2(p, func, 0) void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { x86_cpuid_MACRO(p, func) } +static+void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)+{+ x86_cpuid_MACRO_2(p, func, subFunc)+}+ Z7_NO_INLINE UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)@@ -205,11 +211,39 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) __asm ret 0 } +static+void __declspec(naked) Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)+{+ UNUSED_VAR(p)+ UNUSED_VAR(func)+ UNUSED_VAR(subFunc)+ __asm push ebx+ __asm push edi+ __asm mov edi, ecx // p+ __asm mov eax, edx // func+ __asm mov ecx, [esp + 12] // subFunc+ __asm cpuid+ __asm mov [edi ], eax+ __asm mov [edi + 4], ebx+ __asm mov [edi + 8], ecx+ __asm mov [edi + 12], edx+ __asm pop edi+ __asm pop ebx+ __asm ret 4+}+ #else // MY_CPU_AMD64 #if _MSC_VER >= 1600 #include <intrin.h> #define MY_cpuidex __cpuidex++static+void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)+{+ __cpuidex((int *)p, func, subFunc);+}+ #else /* __cpuid (func == (0 or 7)) requires subfunction number in ECX.@@ -219,20 +253,25 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) We still can use __cpuid for low (func) values that don't require ECX, but __cpuid() in old MSVC will be incorrect for some func values: (func == 7). So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,- where ECX value is first parameter for FASTCALL / NO_INLINE func,+ where ECX value is first parameter for FASTCALL / NO_INLINE func. So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!! */ static-Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(UInt32 subFunction, UInt32 func, int *CPUInfo)+Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo) { UNUSED_VAR(subFunction) __cpuid(CPUInfo, func); } #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info) #pragma message("======== MY_cpuidex_HACK WAS USED ========")+static+void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)+{+ MY_cpuidex_HACK(subFunc, func, (Int32 *)p);+} #endif // _MSC_VER >= 1600 #if !defined(MY_CPU_AMD64)@@ -242,13 +281,13 @@ Z7_NO_INLINE #endif void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) {- MY_cpuidex((int *)p, (int)func, 0);+ MY_cpuidex((Int32 *)p, (Int32)func, 0); } Z7_NO_INLINE UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) {- int a[4];+ Int32 a[4]; MY_cpuidex(a, 0, 0); return a[0]; }@@ -384,7 +423,7 @@ BoolInt CPU_IsSupported_CMOV(void) UInt32 a[4]; if (!x86cpuid_Func_1(&a[0])) return 0;- return (a[3] >> 15) & 1;+ return (BoolInt)(a[3] >> 15) & 1; } BoolInt CPU_IsSupported_SSE(void)@@ -393,7 +432,7 @@ BoolInt CPU_IsSupported_SSE(void) CHECK_SYS_SSE_SUPPORT if (!x86cpuid_Func_1(&a[0])) return 0;- return (a[3] >> 25) & 1;+ return (BoolInt)(a[3] >> 25) & 1; } BoolInt CPU_IsSupported_SSE2(void)@@ -402,7 +441,7 @@ BoolInt CPU_IsSupported_SSE2(void) CHECK_SYS_SSE_SUPPORT if (!x86cpuid_Func_1(&a[0])) return 0;- return (a[3] >> 26) & 1;+ return (BoolInt)(a[3] >> 26) & 1; } #endif@@ -419,17 +458,17 @@ static UInt32 x86cpuid_Func_1_ECX(void) BoolInt CPU_IsSupported_AES(void) {- return (x86cpuid_Func_1_ECX() >> 25) & 1;+ return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1; } BoolInt CPU_IsSupported_SSSE3(void) {- return (x86cpuid_Func_1_ECX() >> 9) & 1;+ return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1; } BoolInt CPU_IsSupported_SSE41(void) {- return (x86cpuid_Func_1_ECX() >> 19) & 1;+ return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1; } BoolInt CPU_IsSupported_SHA(void)@@ -441,7 +480,24 @@ BoolInt CPU_IsSupported_SHA(void) { UInt32 d[4]; z7_x86_cpuid(d, 7);- return (d[1] >> 29) & 1;+ return (BoolInt)(d[1] >> 29) & 1;+ }+}+++BoolInt CPU_IsSupported_SHA512(void)+{+ if (!CPU_IsSupported_AVX2()) return False; // maybe CPU_IsSupported_AVX() is enough here++ if (z7_x86_cpuid_GetMaxFunc() < 7)+ return False;+ {+ UInt32 d[4];+ z7_x86_cpuid_subFunc(d, 7, 0);+ if (d[0] < 1) // d[0] - is max supported subleaf value+ return False;+ z7_x86_cpuid_subFunc(d, 7, 1);+ return (BoolInt)(d[0]) & 1; } } @@ -638,10 +694,10 @@ BoolInt CPU_IsSupported_AVX(void) { const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);- // printf("\n=== XGetBV=%d\n", bm);+ // printf("\n=== XGetBV=0x%x\n", bm); return 1- & (bm >> 1) // SSE state is supported (set by OS) for storing/restoring- & (bm >> 2); // AVX state is supported (set by OS) for storing/restoring+ & (BoolInt)(bm >> 1) // SSE state is supported (set by OS) for storing/restoring+ & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring } // since Win7SP1: we can use GetEnabledXStateFeatures(); }@@ -658,10 +714,39 @@ BoolInt CPU_IsSupported_AVX2(void) z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); return 1- & (d[1] >> 5); // avx2+ & (BoolInt)(d[1] >> 5); // avx2 } } +#if 0+BoolInt CPU_IsSupported_AVX512F_AVX512VL(void)+{+ if (!CPU_IsSupported_AVX())+ return False;+ if (z7_x86_cpuid_GetMaxFunc() < 7)+ return False;+ {+ UInt32 d[4];+ BoolInt v;+ z7_x86_cpuid(d, 7);+ // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);+ v = 1+ & (BoolInt)(d[1] >> 16) // avx512f+ & (BoolInt)(d[1] >> 31); // avx512vl+ if (!v)+ return False;+ }+ {+ const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);+ // printf("\n=== XGetBV=0x%x\n", bm);+ return 1+ & (BoolInt)(bm >> 5) // OPMASK+ & (BoolInt)(bm >> 6) // ZMM upper 256-bit+ & (BoolInt)(bm >> 7); // ZMM16 ... ZMM31+ }+}+#endif+ BoolInt CPU_IsSupported_VAES_AVX2(void) { if (!CPU_IsSupported_AVX())@@ -673,9 +758,9 @@ BoolInt CPU_IsSupported_VAES_AVX2(void) z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); return 1- & (d[1] >> 5) // avx2+ & (BoolInt)(d[1] >> 5) // avx2 // & (d[1] >> 31) // avx512vl- & (d[2] >> 9); // vaes // VEX-256/EVEX+ & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX } } @@ -688,7 +773,7 @@ BoolInt CPU_IsSupported_PageGB(void) if (d[0] < 0x80000001) return False; z7_x86_cpuid(d, 0x80000001);- return (d[3] >> 26) & 1;+ return (BoolInt)(d[3] >> 26) & 1; } } @@ -747,6 +832,18 @@ BoolInt CPU_IsSupported_NEON(void) return z7_sysctlbyname_Get_BoolInt("hw.optional.neon"); } +BoolInt CPU_IsSupported_SHA512(void)+{+ return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha512");+}++/*+BoolInt CPU_IsSupported_SHA3(void)+{+ return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha3");+}+*/+ #ifdef MY_CPU_ARM64 #define APPLE_CRYPTO_SUPPORT_VAL 1 #else@@ -760,33 +857,70 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } #else // __APPLE__ -#include <sys/auxv.h>+#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)+ #define Z7_GETAUXV_AVAILABLE+#elif !defined(__QNXNTO__)+// #pragma message("=== is not NEW GLIBC === ")+ #if defined __has_include+ #if __has_include (<sys/auxv.h>)+// #pragma message("=== sys/auxv.h is avail=== ")+ #define Z7_GETAUXV_AVAILABLE+ #endif+ #endif+#endif +#ifdef Z7_GETAUXV_AVAILABLE+// #pragma message("=== Z7_GETAUXV_AVAILABLE === ")+#include <sys/auxv.h> #define USE_HWCAP+#endif #ifdef USE_HWCAP +#if defined(__FreeBSD__) || defined(__OpenBSD__)+static unsigned long MY_getauxval(int aux)+{+ unsigned long val;+ if (elf_aux_info(aux, &val, sizeof(val)))+ return 0;+ return val;+}+#else+#define MY_getauxval getauxval+ #if defined __has_include+ #if __has_include (<asm/hwcap.h>) #include <asm/hwcap.h>+ #endif+ #endif+#endif #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \- BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; }+ BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP) & (HWCAP_ ## name2)); } #ifdef MY_CPU_ARM64 #define MY_HWCAP_CHECK_FUNC(name) \ MY_HWCAP_CHECK_FUNC_2(name, name)+#if 1 || defined(__ARM_NEON)+ BoolInt CPU_IsSupported_NEON(void) { return True; }+#else MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)+#endif // MY_HWCAP_CHECK_FUNC (ASIMD) #elif defined(MY_CPU_ARM) #define MY_HWCAP_CHECK_FUNC(name) \- BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; }+ BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); } MY_HWCAP_CHECK_FUNC_2(NEON, NEON) #endif #else // USE_HWCAP #define MY_HWCAP_CHECK_FUNC(name) \- BoolInt CPU_IsSupported_ ## name() { return 0; }+ BoolInt CPU_IsSupported_ ## name(void) { return 0; }+#if defined(__ARM_NEON)+ BoolInt CPU_IsSupported_NEON(void) { return True; }+#else MY_HWCAP_CHECK_FUNC(NEON)+#endif #endif // USE_HWCAP @@ -794,6 +928,19 @@ MY_HWCAP_CHECK_FUNC (CRC32) MY_HWCAP_CHECK_FUNC (SHA1) MY_HWCAP_CHECK_FUNC (SHA2) MY_HWCAP_CHECK_FUNC (AES)+#ifdef MY_CPU_ARM64+// <hwcap.h> supports HWCAP_SHA512 and HWCAP_SHA3 since 2017.+// we define them here, if they are not defined+#ifndef HWCAP_SHA3+// #define HWCAP_SHA3 (1 << 17)+#endif+#ifndef HWCAP_SHA512+// #pragma message("=== HWCAP_SHA512 define === ")+#define HWCAP_SHA512 (1 << 21)+#endif+MY_HWCAP_CHECK_FUNC (SHA512)+// MY_HWCAP_CHECK_FUNC (SHA3)+#endif #endif // __APPLE__ #endif // _WIN32
@@ -1,5 +1,5 @@ /* CpuArch.h -- CPU specific code-2023-04-02 : Igor Pavlov : Public domain */+Igor Pavlov : Public domain */ #ifndef ZIP7_INC_CPU_ARCH_H #define ZIP7_INC_CPU_ARCH_H@@ -20,6 +20,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) */ +#if !defined(_M_ARM64EC) #if defined(_M_X64) \ || defined(_M_AMD64) \ || defined(__x86_64__) \@@ -30,11 +31,17 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define MY_CPU_NAME "x32" #define MY_CPU_SIZEOF_POINTER 4 #else- #define MY_CPU_NAME "x64"+ #if defined(__APX_EGPR__) || defined(__EGPR__)+ #define MY_CPU_NAME "x64-apx"+ #define MY_CPU_AMD64_APX+ #else+ #define MY_CPU_NAME "x64"+ #endif #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT #endif+#endif #if defined(_M_IX86) \@@ -45,19 +52,34 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define MY_CPU_SIZEOF_POINTER 4 #endif +#if defined(__SSE2__) \+ || defined(MY_CPU_AMD64) \+ || defined(_M_IX86_FP) && (_M_IX86_FP >= 2)+#define MY_CPU_SSE2+#endif+ #if defined(_M_ARM64) \+ || defined(_M_ARM64EC) \ || defined(__AARCH64EL__) \ || defined(__AARCH64EB__) \ || defined(__aarch64__) #define MY_CPU_ARM64- #ifdef __ILP32__+#if defined(__ILP32__) \+ || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4) #define MY_CPU_NAME "arm64-32" #define MY_CPU_SIZEOF_POINTER 4- #else+#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)+ #define MY_CPU_NAME "arm64-128"+ #define MY_CPU_SIZEOF_POINTER 16+#else+#if defined(_M_ARM64EC)+ #define MY_CPU_NAME "arm64ec"+#else #define MY_CPU_NAME "arm64"+#endif #define MY_CPU_SIZEOF_POINTER 8- #endif+#endif #define MY_CPU_64BIT #endif @@ -133,8 +155,36 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif +#if defined(__sparc__) \+ || defined(__sparc)+ #define MY_CPU_SPARC+ #if defined(__LP64__) \+ || defined(_LP64) \+ || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)+ #define MY_CPU_NAME "sparcv9"+ #define MY_CPU_SIZEOF_POINTER 8+ #define MY_CPU_64BIT+ #elif defined(__sparc_v9__) \+ || defined(__sparcv9)+ #define MY_CPU_64BIT+ #if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)+ #define MY_CPU_NAME "sparcv9-32"+ #else+ #define MY_CPU_NAME "sparcv9m"+ #endif+ #elif defined(__sparc_v8__) \+ || defined(__sparcv8)+ #define MY_CPU_NAME "sparcv8"+ #define MY_CPU_SIZEOF_POINTER 4+ #else+ #define MY_CPU_NAME "sparc"+ #endif+#endif++ #if defined(__riscv) \ || defined(__riscv__)+ #define MY_CPU_RISCV #if __riscv_xlen == 32 #define MY_CPU_NAME "riscv32" #elif __riscv_xlen == 64@@ -145,6 +195,39 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif +#if defined(__loongarch__)+ #define MY_CPU_LOONGARCH+ #if defined(__loongarch64) || defined(__loongarch_grlen) && (__loongarch_grlen == 64)+ #define MY_CPU_64BIT+ #endif+ #if defined(__loongarch64)+ #define MY_CPU_NAME "loongarch64"+ #define MY_CPU_LOONGARCH64+ #else+ #define MY_CPU_NAME "loongarch"+ #endif+#endif+++// #undef MY_CPU_NAME+// #undef MY_CPU_SIZEOF_POINTER+// #define __e2k__+// #define __SIZEOF_POINTER__ 4+#if defined(__e2k__)+ #define MY_CPU_E2K+ #if defined(__ILP32__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)+ #define MY_CPU_NAME "e2k-32"+ #define MY_CPU_SIZEOF_POINTER 4+ #else+ #define MY_CPU_NAME "e2k"+ #if defined(__LP64__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)+ #define MY_CPU_SIZEOF_POINTER 8+ #endif+ #endif+ #define MY_CPU_64BIT+#endif++ #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) #define MY_CPU_X86_OR_AMD64 #endif@@ -171,6 +254,8 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif +// _LITTLE_ENDIAN macro can be defined for big-endian platform with some compilers+ #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM_LE) \ || defined(MY_CPU_ARM64_LE) \@@ -251,6 +336,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #ifndef MY_CPU_NAME+ // #define MY_CPU_IS_UNKNOWN #ifdef MY_CPU_LE #define MY_CPU_NAME "LE" #elif defined(MY_CPU_BE)@@ -295,9 +381,19 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define Z7_BSWAP64(v) _byteswap_uint64(v) #define Z7_CPU_FAST_BSWAP_SUPPORTED -#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \- || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16))- +/* GCC can generate slow code that calls function for __builtin_bswap32() for:+ - GCC for RISCV, if Zbb/XTHeadBb extension is not used.+ - GCC for SPARC.+ The code from CLANG for SPARC also is not fastest.+ So we don't define Z7_CPU_FAST_BSWAP_SUPPORTED in some cases.+*/+#elif (!defined(MY_CPU_RISCV) || defined (__riscv_zbb) || defined(__riscv_xtheadbb)) \+ && !defined(MY_CPU_SPARC) \+ && ( \+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \+ || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) \+ )+ #define Z7_BSWAP16(v) __builtin_bswap16(v) #define Z7_BSWAP32(v) __builtin_bswap32(v) #define Z7_BSWAP64(v) __builtin_bswap64(v)@@ -329,13 +425,48 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #ifdef MY_CPU_LE #if defined(MY_CPU_X86_OR_AMD64) \- || defined(MY_CPU_ARM64)+ || defined(MY_CPU_ARM64) \+ || defined(MY_CPU_RISCV) && defined(__riscv_misaligned_fast) \+ || defined(MY_CPU_E2K) && defined(__iset__) && (__iset__ >= 6) #define MY_CPU_LE_UNALIGN #define MY_CPU_LE_UNALIGN_64 #elif defined(__ARM_FEATURE_UNALIGNED)- /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment.- So we can't use unaligned 64-bit operations. */- #define MY_CPU_LE_UNALIGN+/* === ALIGNMENT on 32-bit arm and LDRD/STRD/LDM/STM instructions.+ Description of problems:+problem-1 : 32-bit ARM architecture:+ multi-access (pair of 32-bit accesses) instructions (LDRD/STRD/LDM/STM)+ require 32-bit (WORD) alignment (by 32-bit ARM architecture).+ So there is "Alignment fault exception", if data is not aligned for 32-bit.++problem-2 : 32-bit kernels and arm64 kernels:+ 32-bit linux kernels provide fixup for these "paired" instruction "Alignment fault exception".+ So unaligned paired-access instructions work via exception handler in kernel in 32-bit linux.+ + But some arm64 kernels do not handle these faults in 32-bit programs.+ So we have unhandled exception for such instructions.+ Probably some new arm64 kernels have fixed it, and unaligned+ paired-access instructions work in new kernels?++problem-3 : compiler for 32-bit arm:+ Compilers use LDRD/STRD/LDM/STM for UInt64 accesses+ and for another cases where two 32-bit accesses are fused+ to one multi-access instruction.+ So UInt64 variables must be aligned for 32-bit, and each+ 32-bit access must be aligned for 32-bit, if we want to+ avoid "Alignment fault" exception (handled or unhandled).++problem-4 : performace:+ Even if unaligned access is handled by kernel, it will be slow.+ So if we allow unaligned access, we can get fast unaligned+ single-access, and slow unaligned paired-access.++ We don't allow unaligned access on 32-bit arm, because compiler+ genarates paired-access instructions that require 32-bit alignment,+ and some arm64 kernels have no handler for these instructions.+ Also unaligned paired-access instructions will be slow, if kernel handles them.+*/+ // it must be disabled:+ // #define MY_CPU_LE_UNALIGN #endif #endif @@ -390,11 +521,19 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) +#if 0+// Z7_BSWAP16 can be slow for x86-msvc+#define GetBe16_to32(p) (Z7_BSWAP16 (*(const UInt16 *)(const void *)(p)))+#else+#define GetBe16_to32(p) (Z7_BSWAP32 (*(const UInt16 *)(const void *)(p)) >> 16)+#endif+ #define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) #define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); } #if defined(MY_CPU_LE_UNALIGN_64) #define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))+#define SetBe64(p, v) { (*(UInt64 *)(void *)(p)) = Z7_BSWAP64(v); } #endif #else@@ -417,21 +556,39 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif +#ifndef SetBe64+#define SetBe64(p, v) { Byte *_ppp_ = (Byte *)(p); UInt64 _vvv_ = (v); \+ _ppp_[0] = (Byte)(_vvv_ >> 56); \+ _ppp_[1] = (Byte)(_vvv_ >> 48); \+ _ppp_[2] = (Byte)(_vvv_ >> 40); \+ _ppp_[3] = (Byte)(_vvv_ >> 32); \+ _ppp_[4] = (Byte)(_vvv_ >> 24); \+ _ppp_[5] = (Byte)(_vvv_ >> 16); \+ _ppp_[6] = (Byte)(_vvv_ >> 8); \+ _ppp_[7] = (Byte)_vvv_; }+#endif+ #ifndef GetBe16+#ifdef GetBe16_to32+#define GetBe16(p) ( (UInt16) GetBe16_to32(p))+#else #define GetBe16(p) ( (UInt16) ( \ ((UInt16)((const Byte *)(p))[0] << 8) | \ ((const Byte *)(p))[1] )) #endif+#endif #if defined(MY_CPU_BE) #define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v) #define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) #define Z7_CONV_NATIVE_TO_BE_32(v) (v)+// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b1) | ((b0) << 8)) #elif defined(MY_CPU_LE) #define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) #define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v) #define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v)+// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b0) | ((b1) << 8)) #else #error Stop_Compiling_Unknown_Endian_CONV #endif@@ -439,23 +596,39 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #if defined(MY_CPU_BE) +#define GetBe64a(p) (*(const UInt64 *)(const void *)(p)) #define GetBe32a(p) (*(const UInt32 *)(const void *)(p)) #define GetBe16a(p) (*(const UInt16 *)(const void *)(p)) #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } +// gcc and clang for powerpc can transform load byte access to load reverse word access.+// sp we can use byte access instead of word access. Z7_BSWAP64 cab be slow+#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_64BIT)+#define GetUi64a(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))+#else+#define GetUi64a(p) GetUi64(p)+#endif++#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)+#define GetUi32a(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))+#else #define GetUi32a(p) GetUi32(p)+#endif+ #define GetUi16a(p) GetUi16(p) #define SetUi32a(p, v) SetUi32(p, v) #define SetUi16a(p, v) SetUi16(p, v) #elif defined(MY_CPU_LE) +#define GetUi64a(p) (*(const UInt64 *)(const void *)(p)) #define GetUi32a(p) (*(const UInt32 *)(const void *)(p)) #define GetUi16a(p) (*(const UInt16 *)(const void *)(p)) #define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); } +#define GetBe64a(p) GetBe64(p) #define GetBe32a(p) GetBe32(p) #define GetBe16a(p) GetBe16(p) #define SetBe32a(p, v) SetBe32(p, v)@@ -466,6 +639,11 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif +#ifndef GetBe16_to32+#define GetBe16_to32(p) GetBe16(p)+#endif++ #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM_OR_ARM64) \ || defined(MY_CPU_PPC_OR_PPC64)@@ -486,6 +664,7 @@ UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void); BoolInt CPU_IsSupported_AES(void); BoolInt CPU_IsSupported_AVX(void); BoolInt CPU_IsSupported_AVX2(void);+BoolInt CPU_IsSupported_AVX512F_AVX512VL(void); BoolInt CPU_IsSupported_VAES_AVX2(void); BoolInt CPU_IsSupported_CMOV(void); BoolInt CPU_IsSupported_SSE(void);@@ -493,6 +672,7 @@ BoolInt CPU_IsSupported_SSE2(void); BoolInt CPU_IsSupported_SSSE3(void); BoolInt CPU_IsSupported_SSE41(void); BoolInt CPU_IsSupported_SHA(void);+BoolInt CPU_IsSupported_SHA512(void); BoolInt CPU_IsSupported_PageGB(void); #elif defined(MY_CPU_ARM_OR_ARM64)@@ -510,6 +690,7 @@ BoolInt CPU_IsSupported_SHA1(void); BoolInt CPU_IsSupported_SHA2(void); BoolInt CPU_IsSupported_AES(void); #endif+BoolInt CPU_IsSupported_SHA512(void); #endif
@@ -1,5 +1,5 @@ /* Lzma2Dec.c -- LZMA2 Decoder-2023-03-03 : Igor Pavlov : Public domain */+2024-03-01 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ @@ -157,8 +157,10 @@ static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) p->decoder.prop.lp = (Byte)lp; return LZMA2_STATE_DATA; }+ + default:+ return LZMA2_STATE_ERROR; }- return LZMA2_STATE_ERROR; } static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
@@ -1,5 +1,5 @@ /* Ppmd7.c -- PPMdH codec-2023-04-02 : Igor Pavlov : Public domain+2023-09-07 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h"@@ -302,8 +302,17 @@ static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx) #define MEM_12_CPY(dest, src, num) \- { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \- do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }+ { UInt32 *d = (UInt32 *)(dest); \+ const UInt32 *z = (const UInt32 *)(src); \+ unsigned n = (num); \+ do { \+ d[0] = z[0]; \+ d[1] = z[1]; \+ d[2] = z[2]; \+ z += 3; \+ d += 3; \+ } while (--n); \+ } /*@@ -711,8 +720,8 @@ void Ppmd7_UpdateModel(CPpmd7 *p) if ((ns1 & 1) == 0) { /* Expand for one UNIT */- unsigned oldNU = ns1 >> 1;- unsigned i = U2I(oldNU);+ const unsigned oldNU = ns1 >> 1;+ const unsigned i = U2I(oldNU); if (i != U2I((size_t)oldNU + 1)) { void *ptr = Ppmd7_AllocUnits(p, i + 1);@@ -731,7 +740,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p) sum = c->Union2.SummFreq; /* max increase of Escape_Freq is 3 here. total increase of Union2.SummFreq for all symbols is less than 256 here */- sum += (UInt32)(2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1));+ sum += (UInt32)(unsigned)((2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1))); /* original PPMdH uses 16-bit variable for (sum) here. But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ // sum = (UInt16)sum;@@ -761,7 +770,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p) // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context s->Freq = (Byte)freq; // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here- sum = freq + p->InitEsc + (ns > 3);+ sum = (UInt32)(freq + p->InitEsc + (ns > 3)); } } @@ -933,10 +942,10 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) p->HiBitsFlag; { // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ- unsigned summ = (UInt16)see->Summ; // & 0xFFFF- unsigned r = (summ >> see->Shift);+ const unsigned summ = (UInt16)see->Summ; // & 0xFFFF+ const unsigned r = (summ >> see->Shift); see->Summ = (UInt16)(summ - r);- *escFreq = r + (r == 0);+ *escFreq = (UInt32)(r + (r == 0)); } } else@@ -981,9 +990,9 @@ void Ppmd7_Update1_0(CPpmd7 *p) CPpmd_State *s = p->FoundState; CPpmd7_Context *mc = p->MinContext; unsigned freq = s->Freq;- unsigned summFreq = mc->Union2.SummFreq;+ const unsigned summFreq = mc->Union2.SummFreq; p->PrevSuccess = (2 * freq > summFreq);- p->RunLength += (int)p->PrevSuccess;+ p->RunLength += (Int32)p->PrevSuccess; mc->Union2.SummFreq = (UInt16)(summFreq + 4); freq += 4; s->Freq = (Byte)freq;
@@ -1,5 +1,5 @@ /* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder-2023-04-02 : Igor Pavlov : Public domain+2023-09-07 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain */ @@ -58,7 +58,7 @@ static void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size) #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) void Ppmd7_UpdateModel(CPpmd7 *p); -#define MASK(sym) ((unsigned char *)charMask)[sym]+#define MASK(sym) ((Byte *)charMask)[sym] // Z7_FORCE_INLINE // static int Ppmd7z_DecodeSymbol(CPpmd7 *p)@@ -120,8 +120,8 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) MASK(s->Symbol) = 0; do {- unsigned sym0 = s2[0].Symbol;- unsigned sym1 = s2[1].Symbol;+ const unsigned sym0 = s2[0].Symbol;+ const unsigned sym1 = s2[1].Symbol; s2 += 2; MASK(sym0) = 0; MASK(sym1) = 0;@@ -209,17 +209,17 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) unsigned num2 = num / 2; num &= 1;- hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num);+ hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num); s += num; p->MinContext = mc; do {- unsigned sym0 = s[0].Symbol;- unsigned sym1 = s[1].Symbol;+ const unsigned sym0 = s[0].Symbol;+ const unsigned sym1 = s[1].Symbol; s += 2;- hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0)));- hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1)));+ hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));+ hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1))); } while (--num2); }@@ -238,13 +238,13 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p) s = Ppmd7_GetStats(p, p->MinContext); hiCnt = count;- // count -= s->Freq & (unsigned)(MASK(s->Symbol));+ // count -= s->Freq & (UInt32)(MASK(s->Symbol)); // if ((Int32)count >= 0) { for (;;) {- count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;- // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;+ count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;+ // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; } } s--;
@@ -1,10 +1,127 @@-/* Precomp.h -- StdAfx-2023-04-02 : Igor Pavlov : Public domain */+/* Precomp.h -- precompilation file+: Igor Pavlov : Public domain */ #ifndef ZIP7_INC_PRECOMP_H #define ZIP7_INC_PRECOMP_H +/*+ this file must be included before another *.h files and before <windows.h>.+ this file is included from the following files:+ C\*.c+ C\Util\*\Precomp.h <- C\Util\*\*.c+ CPP\Common\Common.h <- *\StdAfx.h <- *\*.cpp++ this file can set the following macros:+ Z7_LARGE_PAGES 1+ Z7_LONG_PATH 1+ Z7_WIN32_WINNT_MIN 0x0500 (or higher) : we require at least win2000+ for 7-Zip+ _WIN32_WINNT 0x0500 (or higher)+ WINVER _WIN32_WINNT+ UNICODE 1+ _UNICODE 1+*/+ #include "Compiler.h"-/* #include "7zTypes.h" */++#ifdef _MSC_VER+// #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty+#if _MSC_VER >= 1912+// #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.+#endif+#endif++/*+// for debug:+#define UNICODE 1+#define _UNICODE 1+#define _WIN32_WINNT 0x0500 // win2000+#ifndef WINVER+ #define WINVER _WIN32_WINNT+#endif+*/++#ifndef Z7_LARGE_PAGES+#if !defined(Z7_NO_LARGE_PAGES) && !defined(UNDER_CE)+#define Z7_LARGE_PAGES 1+#endif+#endif++#ifdef _WIN32+/*+ this "Precomp.h" file must be included before <windows.h>,+ if we want to define _WIN32_WINNT before <windows.h>.+*/++#ifndef Z7_LONG_PATH+#ifndef Z7_NO_LONG_PATH+#define Z7_LONG_PATH 1+#endif+#endif++#ifndef Z7_DEVICE_FILE+#ifndef Z7_NO_DEVICE_FILE+// #define Z7_DEVICE_FILE 1+#endif+#endif++// we don't change macros if included after <windows.h>+#ifndef _WINDOWS_++#ifndef Z7_WIN32_WINNT_MIN+ #if defined(_M_ARM64) || defined(__aarch64__)+ // #define Z7_WIN32_WINNT_MIN 0x0a00 // win10+ #define Z7_WIN32_WINNT_MIN 0x0600 // vista+ #elif defined(_M_ARM) && defined(_M_ARMT) && defined(_M_ARM_NT)+ // #define Z7_WIN32_WINNT_MIN 0x0602 // win8+ #define Z7_WIN32_WINNT_MIN 0x0600 // vista+ #elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IA64)+ #define Z7_WIN32_WINNT_MIN 0x0503 // win2003+ // #elif defined(_M_IX86) || defined(__i386__)+ // #define Z7_WIN32_WINNT_MIN 0x0500 // win2000+ #else // x86 and another(old) systems+ #define Z7_WIN32_WINNT_MIN 0x0500 // win2000+ // #define Z7_WIN32_WINNT_MIN 0x0502 // win2003 // for debug+ #endif+#endif // Z7_WIN32_WINNT_MIN+++#ifndef Z7_DO_NOT_DEFINE_WIN32_WINNT+#ifdef _WIN32_WINNT+ // #error Stop_Compiling_Bad_WIN32_WINNT+#else+ #ifndef Z7_NO_DEFINE_WIN32_WINNT+Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER+ #define _WIN32_WINNT Z7_WIN32_WINNT_MIN+Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER+ #endif+#endif // _WIN32_WINNT++#ifndef WINVER+ #define WINVER _WIN32_WINNT+#endif+#endif // Z7_DO_NOT_DEFINE_WIN32_WINNT+++#ifndef _MBCS+#ifndef Z7_NO_UNICODE+// UNICODE and _UNICODE are used by <windows.h> and by 7-zip code.++#ifndef UNICODE+#define UNICODE 1+#endif++#ifndef _UNICODE+Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER+#define _UNICODE 1+Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER+#endif++#endif // Z7_NO_UNICODE+#endif // _MBCS+#endif // _WINDOWS_++// #include "7zWindows.h"++#endif // _WIN32 #endif
@@ -1,4 +1,5 @@-This directory contains a subset of the LZMA SDK lzma2301/C files+This directory contains a subset of the LZMA SDK lzma2602/C files for 7z file+decompression with the LZMA SDK decompression API w/o compression API LZMA SDK is available from https://7-zip.org/sdk.html @@ -6,7 +7,8 @@ LZMA SDK is placed in the public domain. LZMA SDK by Igor Pavlov. -Updated 23.01 to apply YOKOTA Hiroshi's patches:+Updated to LZMA SDK 26.02.+Previously updated to LZMA SDK 23.01 to apply YOKOTA Hiroshi's patches: https://salsa.debian.org/debian/7zip/-/blob/master/debian/patches/0002-Disable-hardware-acceleration-support-on-armel.patch?ref_type=heads Included in this directory is a new C API written for ugrep to simplify
@@ -165,6 +165,7 @@ src/ugrep --help \ -e 's/\[,\([-A-Z]\{1,\}\)\]/[,\\fI\1\\fR]/g' \ -e 's/\[=\([-A-Z]\{1,\}\)\]/[=\\fI\1\\fR]/g' \ -e 's/=\([-A-Z]\{1,\}\)/=\\fI\1\\fR/g' \+ -e 's/\.\.\./\\\&.../g' \ | sed -e 's/-/\\-/g' >> man/ugrep.1 cat >> man/ugrep.1 << 'END' .SH "EXIT STATUS"@@ -697,7 +698,7 @@ ugrep-indexer(1), grep(1), zgrep(1). Report bugs at: <https://github.com/Genivia/ugrep/issues> END -man man/ugrep.1 | sed 's/.//g' > man.txt+env MANWIDTH=80 man man/ugrep.1 | sed 's/.//g' > man.txt echo "ugrep $1 manual page created and saved in man/ugrep.1" echo "ugrep text-only man page created and saved as man.txt"
@@ -1,4 +1,4 @@-.TH UGREP "1" "May 17, 2026" "ugrep 7.8.2" "User Commands"+.TH UGREP "1" "July 30, 2026" "ugrep 7.8.3" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS@@ -295,7 +295,7 @@ command line, ACTION defaults to `recurse` or option \fB\-r\fR. \fB\-\-delay\fR=\fIDELAY\fR Set the default \fB\-Q\fR key response delay. Default is 3 for 300ms. .TP-\fB\-\-depth\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-1\fR, \fB\-2\fR, \fB\-3\fR, ... \fB\-9\fR, \fB\-1\fR0, \fB\-1\fR1, ...+\fB\-\-depth\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-1\fR, \fB\-2\fR, \fB\-3\fR, \&... \fB\-9\fR, \fB\-1\fR0, \fB\-1\fR1, \&... Restrict recursive searches from MIN to MAX directory levels deep, where \fB\-1\fR (\fB\-\-depth\fR=1) searches the specified path without recursing into subdirectories. The short forms \fB\-3\fR \fB\-5\fR, \fB\-3\fR\-5 and \fB\-3\fR,5 search 3@@ -333,7 +333,7 @@ that specifies raw binary PATTERN matching. ENCODING can be: .TP \fB\-\-exclude\fR=\fIGLOB\fR Exclude files whose name matches GLOB, same as \fB\-g\fR ^GLOB. GLOB can-use **, *, ?, and [...] as wildcards and \\ to quote a wildcard or+use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched. Otherwise basenames are matched. When GLOB ends with a `/', directories are excluded as if \fB\-\-exclude\-dir\fR is@@ -343,7 +343,7 @@ quoted to prevent shell globbing. This option may be repeated. .TP \fB\-\-exclude\-dir\fR=\fIGLOB\fR Exclude directories whose name matches GLOB from recursive-searches, same as \fB\-g\fR ^GLOB/. GLOB may use **, *, ?, and [...] as+searches, same as \fB\-g\fR ^GLOB/. GLOB may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched. Otherwise basenames are matched. Note that \fB\-\-exclude\-dir\fR patterns@@ -352,7 +352,7 @@ to prevent shell globbing. This option may be repeated. .TP \fB\-\-exclude\-from\fR=\fIFILE\fR Read the globs from FILE and skip files and directories whose name-matches one or more globs. A glob may use **, *, ?, and [...] as+matches one or more globs. A glob may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When a glob contains a `/', full pathnames are matched. Otherwise basenames are matched. When a glob ends with a `/',@@ -434,7 +434,7 @@ Spacing (blanks and tabs) in regular expressions are ignored. \fB\-\-from\fR=\fIFILE\fR Read additional pathnames of files to search from FILE. When FILE is a `\-', standard input is read. This option is useful with `find-... \fB\-p\fRrint | ugrep \fB\-\-from\fR=\fI\-\fR ...' to search specific files.+\&... \fB\-p\fRrint | ugrep \fB\-\-from\fR=\fI\-\fR \&...' to search specific files. .TP \fB\-G\fR, \fB\-\-basic\-regexp\fR Interpret patterns as basic regular expressions (BREs).@@ -532,7 +532,7 @@ Do not ignore files, i.e. cancel \fB\-\-ignore\-files\fR when specified. .TP \fB\-\-include\fR=\fIGLOB\fR Only search files whose name matches GLOB, same as \fB\-g\fR \fIGLOB\fR. GLOB-may use **, *, ?, and [...] as wildcards and \\ to quote a wildcard+may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched and option \fB\-r\fR is enabled to recurse into directories if \fB\-d\fR, \fB\-r\fR or \fB\-R\fR is not already specified. Otherwise@@ -544,7 +544,7 @@ globbing. This option may be repeated. .TP \fB\-\-include\-dir\fR=\fIGLOB\fR Only directories whose name matches GLOB are included in recursive-searches, same as \fB\-g\fR \fIGLOB\fR/. GLOB may use **, *, ?, and [...] as+searches, same as \fB\-g\fR \fIGLOB\fR/. GLOB may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched and option \fB\-r\fR is enabled to recurse into directories if \fB\-d\fR, \fB\-r\fR or@@ -556,7 +556,7 @@ option may be repeated. \fB\-\-include\-from\fR=\fIFILE\fR Read the globs from FILE and search only files and directories whose name matches one or more globs. A glob may use **, *, ?, and-[...] as wildcards and \\ to quote a wildcard or backslash+[\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When a glob contains a `/', full pathnames are matched. Otherwise basenames are matched. When a glob ends with a `/', directories are included as if \fB\-\-include\-dir\fR is
@@ -1,4 +1,4 @@-.TH UGREP-INDEXER "1" "May 17, 2026" "ugrep-indexer 7.8.2" "User Commands"+.TH UGREP-INDEXER "1" "July 30, 2026" "ugrep-indexer 7.8.3" "User Commands" .SH NAME \fBugrep-indexer\fR -- file indexer to accelerate recursive searching .SH SYNOPSIS
@@ -1,4 +1,4 @@-.TH UGREP "1" "May 17, 2026" "ugrep 7.8.2" "User Commands"+.TH UGREP "1" "July 30, 2026" "ugrep 7.8.3" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS@@ -295,7 +295,7 @@ command line, ACTION defaults to `recurse` or option \fB\-r\fR. \fB\-\-delay\fR=\fIDELAY\fR Set the default \fB\-Q\fR key response delay. Default is 3 for 300ms. .TP-\fB\-\-depth\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-1\fR, \fB\-2\fR, \fB\-3\fR, ... \fB\-9\fR, \fB\-1\fR0, \fB\-1\fR1, ...+\fB\-\-depth\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-1\fR, \fB\-2\fR, \fB\-3\fR, \&... \fB\-9\fR, \fB\-1\fR0, \fB\-1\fR1, \&... Restrict recursive searches from MIN to MAX directory levels deep, where \fB\-1\fR (\fB\-\-depth\fR=1) searches the specified path without recursing into subdirectories. The short forms \fB\-3\fR \fB\-5\fR, \fB\-3\fR\-5 and \fB\-3\fR,5 search 3@@ -333,7 +333,7 @@ that specifies raw binary PATTERN matching. ENCODING can be: .TP \fB\-\-exclude\fR=\fIGLOB\fR Exclude files whose name matches GLOB, same as \fB\-g\fR ^GLOB. GLOB can-use **, *, ?, and [...] as wildcards and \\ to quote a wildcard or+use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched. Otherwise basenames are matched. When GLOB ends with a `/', directories are excluded as if \fB\-\-exclude\-dir\fR is@@ -343,7 +343,7 @@ quoted to prevent shell globbing. This option may be repeated. .TP \fB\-\-exclude\-dir\fR=\fIGLOB\fR Exclude directories whose name matches GLOB from recursive-searches, same as \fB\-g\fR ^GLOB/. GLOB may use **, *, ?, and [...] as+searches, same as \fB\-g\fR ^GLOB/. GLOB may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched. Otherwise basenames are matched. Note that \fB\-\-exclude\-dir\fR patterns@@ -352,7 +352,7 @@ to prevent shell globbing. This option may be repeated. .TP \fB\-\-exclude\-from\fR=\fIFILE\fR Read the globs from FILE and skip files and directories whose name-matches one or more globs. A glob may use **, *, ?, and [...] as+matches one or more globs. A glob may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When a glob contains a `/', full pathnames are matched. Otherwise basenames are matched. When a glob ends with a `/',@@ -434,7 +434,7 @@ Spacing (blanks and tabs) in regular expressions are ignored. \fB\-\-from\fR=\fIFILE\fR Read additional pathnames of files to search from FILE. When FILE is a `\-', standard input is read. This option is useful with `find-\&... \fB\-p\fRrint | ugrep \fB\-\-from\fR=\fI\-\fR ...' to search specific files.+\&... \fB\-p\fRrint | ugrep \fB\-\-from\fR=\fI\-\fR \&...' to search specific files. .TP \fB\-G\fR, \fB\-\-basic\-regexp\fR Interpret patterns as basic regular expressions (BREs).@@ -532,7 +532,7 @@ Do not ignore files, i.e. cancel \fB\-\-ignore\-files\fR when specified. .TP \fB\-\-include\fR=\fIGLOB\fR Only search files whose name matches GLOB, same as \fB\-g\fR \fIGLOB\fR. GLOB-may use **, *, ?, and [...] as wildcards and \\ to quote a wildcard+may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched and option \fB\-r\fR is enabled to recurse into directories if \fB\-d\fR, \fB\-r\fR or \fB\-R\fR is not already specified. Otherwise@@ -544,7 +544,7 @@ globbing. This option may be repeated. .TP \fB\-\-include\-dir\fR=\fIGLOB\fR Only directories whose name matches GLOB are included in recursive-searches, same as \fB\-g\fR \fIGLOB\fR/. GLOB may use **, *, ?, and [...] as+searches, same as \fB\-g\fR \fIGLOB\fR/. GLOB may use **, *, ?, and [\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When GLOB contains a `/', full pathnames are matched and option \fB\-r\fR is enabled to recurse into directories if \fB\-d\fR, \fB\-r\fR or@@ -556,7 +556,7 @@ option may be repeated. \fB\-\-include\-from\fR=\fIFILE\fR Read the globs from FILE and search only files and directories whose name matches one or more globs. A glob may use **, *, ?, and-[...] as wildcards and \\ to quote a wildcard or backslash+[\&...] as wildcards and \\ to quote a wildcard or backslash character literally. When a glob contains a `/', full pathnames are matched. Otherwise basenames are matched. When a glob ends with a `/', directories are included as if \fB\-\-include\-dir\fR is
@@ -35,7 +35,7 @@ */ // DO NOT ALTER THIS LINE: updated by makemake.sh and we need it physically here for MSVC++ build from source-#define UGREP_VERSION "7.8.2"+#define UGREP_VERSION "7.8.3" // use a task-parallel thread to decompress the stream into a pipe to search, also handles nested archives #define WITH_DECOMPRESSION_THREAD
@@ -38,7 +38,7 @@ #define UGREP_HPP // DO NOT ALTER THIS LINE: updated by makemake.sh and we need it physically here for MSVC++ build from source-#define UGREP_VERSION "7.8.2"+#define UGREP_VERSION "7.8.3" // disable mmap because mmap is almost always slower than the file reading speed improvements since 3.0.0 #define WITH_NO_MMAP