Spring Cleaning, Part Ichi (1)
Various minor things done to project files Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way) Updated regex project file and makefile --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401971
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D+
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L+
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$YD
|
||||
-$Z1
|
||||
-cg
|
||||
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M16384,1048576
|
||||
-K$00400000
|
||||
-LE"c:\program files\borland\delphi7\Projects\Bpl"
|
||||
-LN"c:\program files\borland\delphi7\Projects\Bpl"
|
||||
-w-UNSAFE_TYPE
|
||||
-w-UNSAFE_CODE
|
||||
-w-UNSAFE_CAST
|
||||
@@ -0,0 +1,101 @@
|
||||
(* SourceMod
|
||||
* compile.exe
|
||||
*
|
||||
* by the SourceMod Development Team (adapted from AMX Mod X's compiler tool)
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*)
|
||||
|
||||
program compile;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
{$R version.res}
|
||||
{$R icon.res}
|
||||
|
||||
uses
|
||||
SysUtils, Classes, IniFiles,
|
||||
uFunc in 'uFunc.pas';
|
||||
|
||||
var sr: TSearchRec;
|
||||
i: Word;
|
||||
cfg: TIniFile;
|
||||
outdir: String;
|
||||
begin
|
||||
WriteLn('//SourceMod Batch Compiler');
|
||||
WriteLn('// by the SourceMod Dev Team');
|
||||
WriteLn;
|
||||
|
||||
if not FileExists(ExtractFilePath(ParamStr(0))+COMPILER_EXE) then
|
||||
begin
|
||||
WriteLn('// Could not find '+COMPILER_EXE);
|
||||
AppExit;
|
||||
end;
|
||||
|
||||
cfg := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'compiler.ini');
|
||||
outdir := cfg.ReadString('Main', 'Output', '');
|
||||
if (outdir <> '') then begin
|
||||
if (DirectoryExists(outdir)) then
|
||||
outdir := IncludeTrailingPathDelimiter(outdir)
|
||||
else if (DirectoryExists(ExtractFilePath(ParamStr(0)) + outdir)) then
|
||||
outdir := ExtractFilePath(ParamStr(0)) + IncludeTrailingPathDelimiter(outdir);
|
||||
end
|
||||
else
|
||||
outdir := '';
|
||||
cfg.Free;
|
||||
|
||||
if (outdir = '') and (not DirectoryExists(ExtractFilePath(ParamStr(0))+'compiled')) then
|
||||
CreateDir(ExtractFilePath(ParamStr(0))+'compiled');
|
||||
|
||||
if ( ParamCount > 0 ) then
|
||||
begin
|
||||
for i := 1 to ParamCount do
|
||||
begin
|
||||
if FileExists(ParamStr(i)) then
|
||||
CompilePlugin(ParamStr(i), outdir)
|
||||
else
|
||||
begin
|
||||
WriteLn;
|
||||
WriteLn('// File not found.');
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if ( FindFirst('*.sp',faAnyFile,sr) = 0 ) then
|
||||
begin
|
||||
repeat
|
||||
CompilePlugin(sr.Name, outdir);
|
||||
until ( FindNext(sr) <> 0 );
|
||||
end
|
||||
else
|
||||
begin
|
||||
WriteLn('// No file found.');
|
||||
end;
|
||||
FindClose(sr);
|
||||
end;
|
||||
|
||||
AppExit;
|
||||
end.
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
SM ICON "pawn.ico"
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
@@ -0,0 +1,224 @@
|
||||
(* AMX Mod X
|
||||
* compile.exe
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*)
|
||||
|
||||
unit uFunc;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, SysUtils, Classes, Math, IniFiles;
|
||||
|
||||
resourcestring
|
||||
COMPILER_EXE = 'spcomp.exe';
|
||||
|
||||
procedure AppExit;
|
||||
procedure CompilePlugin(const Name, OutputDir: String);
|
||||
function GetAgeFromDat(const FileName: String): Integer;
|
||||
procedure SetAgeToDat(const FileName: String; const Age: Integer);
|
||||
function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
procedure AppExit;
|
||||
begin
|
||||
WriteLn;
|
||||
Write('Press enter to exit ...');
|
||||
ReadLn;
|
||||
Halt;
|
||||
end;
|
||||
|
||||
procedure CompilePlugin(const Name, OutputDir: String);
|
||||
var
|
||||
Output: TStringList;
|
||||
i: Word;
|
||||
cStart,cEnd: Longword;
|
||||
FileName, FilePath, Compiled: String;
|
||||
begin
|
||||
FileName := ExtractFileName(Name);
|
||||
FilePath := ExtractFilePath(Name);
|
||||
if (OutputDir = '') then
|
||||
Compiled := FilePath+'compiled\'+ChangeFileExt(Filename,'.smx')
|
||||
else
|
||||
Compiled := OutputDir+ChangeFileExt(Filename,'.smx');
|
||||
|
||||
if (FilePath='') then
|
||||
FilePath := ExtractFilePath(ParamStr(0));
|
||||
|
||||
WriteLn;
|
||||
WriteLn('//// '+ExtractFileName(FileName));
|
||||
|
||||
if FileExists(Compiled) and ( GetAgeFromDat(Name)=FileAge(Name) ) then
|
||||
begin
|
||||
WriteLn('// Already compiled.');
|
||||
WriteLn('// ----------------------------------------');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Output := TStringList.Create;
|
||||
|
||||
try
|
||||
cStart := GetTickCount;
|
||||
if not GetConsoleOutput(ExtractFilePath(ParamStr(0))+COMPILER_EXE+' "'+Name+'" "-o'+Compiled+'"',Output) then
|
||||
begin
|
||||
WriteLn('// Internal error.');
|
||||
AppExit;
|
||||
end;
|
||||
cEnd := GetTickCount;
|
||||
|
||||
for i := 3 to (Output.Count-1) do
|
||||
begin
|
||||
WriteLn('// '+Output.Strings[i]);
|
||||
end;
|
||||
|
||||
WriteLn('//');
|
||||
WriteLn('// Compilation Time: '+FloatToStr(SimpleRoundTo((cEnd-cStart) / 1000,-2))+' sec');
|
||||
WriteLn('// ----------------------------------------');
|
||||
Output.Free;
|
||||
except
|
||||
WriteLn('// Internal error.');
|
||||
AppExit;
|
||||
end;
|
||||
|
||||
SetAgeToDat(Name,FileAge(Name));
|
||||
end;
|
||||
|
||||
function GetAgeFromDat(const FileName: String): Integer;
|
||||
var
|
||||
Ini: TIniFile;
|
||||
begin
|
||||
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
|
||||
Result := Ini.ReadInteger(FileName,'Age',-1);
|
||||
Ini.Free;
|
||||
end;
|
||||
|
||||
procedure SetAgeToDat(const FileName: String; const Age: Integer);
|
||||
var
|
||||
Ini: TIniFile;
|
||||
begin
|
||||
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
|
||||
Ini.WriteInteger(FileName,'Age',Age);
|
||||
Ini.UpdateFile;
|
||||
Ini.Free;
|
||||
SetFileAttributes(PChar(ExtractFilePath(ParamStr(0))+'compile.dat'), faHidden);
|
||||
end;
|
||||
|
||||
function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
|
||||
var
|
||||
StartupInfo: TStartupInfo;
|
||||
ProcessInfo: TProcessInformation;
|
||||
SecurityAttr: TSecurityAttributes;
|
||||
PipeOutputRead: THandle;
|
||||
PipeOutputWrite: THandle;
|
||||
PipeErrorsRead: THandle;
|
||||
PipeErrorsWrite: THandle;
|
||||
Succeed: Boolean;
|
||||
Buffer: array [0..255] of Char;
|
||||
NumberOfBytesRead: DWORD;
|
||||
Stream: TMemoryStream;
|
||||
Errors: String;
|
||||
begin
|
||||
FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
|
||||
FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
|
||||
|
||||
SecurityAttr.nLength := SizeOf(SecurityAttr);
|
||||
SecurityAttr.bInheritHandle := True;
|
||||
SecurityAttr.lpSecurityDescriptor := nil;
|
||||
|
||||
CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
|
||||
CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
|
||||
|
||||
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
|
||||
StartupInfo.cb:=SizeOf(StartupInfo);
|
||||
StartupInfo.hStdInput := 0;
|
||||
StartupInfo.hStdOutput := PipeOutputWrite;
|
||||
StartupInfo.hStdError := PipeErrorsWrite;
|
||||
StartupInfo.wShowWindow := SW_HIDE;
|
||||
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
|
||||
|
||||
if CreateProcess(nil, PChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin
|
||||
Result := True;
|
||||
CloseHandle(PipeOutputWrite);
|
||||
CloseHandle(PipeErrorsWrite);
|
||||
|
||||
Stream := TMemoryStream.Create;
|
||||
try
|
||||
while True do begin
|
||||
Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
|
||||
if not Succeed then Break;
|
||||
Stream.Write(Buffer, NumberOfBytesRead);
|
||||
end;
|
||||
finally
|
||||
// nothing
|
||||
end;
|
||||
Stream.Position := 0;
|
||||
Output.LoadFromStream(Stream);
|
||||
Stream.Free;
|
||||
CloseHandle(PipeOutputRead);
|
||||
|
||||
Errors := '';
|
||||
try
|
||||
while True do
|
||||
begin
|
||||
Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
|
||||
if not Succeed then Break;
|
||||
Errors := Errors + Copy(Buffer, 1, NumberOfBytesRead);
|
||||
end;
|
||||
finally
|
||||
// nothing
|
||||
end;
|
||||
CloseHandle(PipeErrorsRead);
|
||||
|
||||
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
|
||||
CloseHandle(ProcessInfo.hProcess);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := False;
|
||||
CloseHandle(PipeOutputRead);
|
||||
CloseHandle(PipeOutputWrite);
|
||||
CloseHandle(PipeErrorsRead);
|
||||
CloseHandle(PipeErrorsWrite);
|
||||
end;
|
||||
// error management
|
||||
if (Errors <> '') then begin
|
||||
if (Output.Count > 1) then begin
|
||||
if (Trim(Output[Output.Count -2]) = '') then
|
||||
Output.Strings[Output.Count -2] := TrimRight(Errors)
|
||||
else
|
||||
Output.Insert(Output.Count -1, TrimRight(Errors));
|
||||
end
|
||||
else
|
||||
Output.Add(Errors);
|
||||
Output.Text := Output.Text; // pseudo-rearrangement
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,33 @@
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
|
||||
FILEVERSION 1,5,0,0
|
||||
PRODUCTVERSION 1,5,0,0
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP // VFT_APP VFT_DLL
|
||||
//FILEFLGAGS:
|
||||
// VS_FF_DEBUG VS_FF_PRERELEASE VS_FF_PATCHED VS_FF_PRIVATEBUILD VS_FF_INFOINFERRED VS_FF_SPECIALBUILD
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "SPCOMP compile.exe\0"
|
||||
//VALUE "CompanyName", "AMXX Development Team\0"
|
||||
VALUE "FileDescription", "SPCOMP compile.exe\0"
|
||||
VALUE "FileVersion", "1.0\0"
|
||||
VALUE "InternalName", "SPCOMP compile.exe\0"
|
||||
VALUE "LegalCopyright", "(c) 2007, SourceMod Development Team\0"
|
||||
//VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "compile.exe\0"
|
||||
//VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", "SPCOMP compile.exe\0"
|
||||
VALUE "ProductVersion", "1.0\0"
|
||||
//VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", LANG_ENGLISH SUBLANG_ENGLISH_US
|
||||
END
|
||||
END
|
||||
Binary file not shown.
@@ -0,0 +1,68 @@
|
||||
#(C)2004-2008 SourceMod Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
SMSDK = ../..
|
||||
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
|
||||
OPT_C_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing -fomit-frame-pointer
|
||||
OPT_CPP_FLAGS =
|
||||
DEBUG_C_FLAGS = -g -ggdb3
|
||||
CPP = gcc-4.1
|
||||
BINARY = spcomp
|
||||
|
||||
OBJECTS = libpawnc.c lstring.c memfile.c pawncc.c sc1.c sc2.c sc3.c sc4.c sc5.c \
|
||||
sc6.c sc7.c scexpand.c sci18n.c sclist.c scmemfil.c scstate.c sctracker.c \
|
||||
scvars.c sp_file.c binreloc.c zlib/adler32.c zlib/crc32.c zlib/deflate.c \
|
||||
zlib/gzio.c zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c \
|
||||
zlib/trees.c zlib/uncompr.c zlib/zutil.c zlib/compress.c
|
||||
|
||||
LINK = -lgcc -static-libgcc
|
||||
|
||||
INCLUDE = -I. -I$(SMSDK)/public/sourcepawn
|
||||
|
||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
|
||||
ifeq "$(GCC_VERSION)" "4"
|
||||
OPT_CPP_FLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
endif
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS = $(DEBUG_C_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS = $(OPT_C_FLAGS)
|
||||
CPPFLAGS += $(OPT_CPP_FLAGS)
|
||||
endif
|
||||
|
||||
CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC -m32
|
||||
CPPFLAGS += -Wno-deprecated -fno-exceptions -fno-rtti
|
||||
|
||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
OBJ_LINUX := $(OBJECTS:%.c=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||
|
||||
$(BIN_DIR)/%.o: %.c
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)/zlib
|
||||
$(MAKE) spcomp
|
||||
|
||||
spcomp: $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -m32 -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf Release/*.o
|
||||
rm -rf Release/$(BINARY)
|
||||
rm -rf Debug/*.o
|
||||
rm -rf Debug/$(BINARY)
|
||||
|
||||
@@ -0,0 +1,630 @@
|
||||
/* Pawn Abstract Machine (for the Pawn language)
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef AMX_H_INCLUDED
|
||||
#define AMX_H_INCLUDED
|
||||
|
||||
#include <stdlib.h> /* for size_t */
|
||||
#include <limits.h>
|
||||
|
||||
#if defined FREEBSD && !defined __FreeBSD__
|
||||
#define __FreeBSD__
|
||||
#endif
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#include <stdint.h>
|
||||
#if !defined HAVE_STDINT_H
|
||||
#define HAVE_STDINT_H
|
||||
#endif
|
||||
#elif !defined HAVE_STDINT_H
|
||||
#if defined __LCC__ || defined __DMC__ || defined LINUX || (defined __WATCOMC__ && __WATCOMC__ >= 1200)
|
||||
#if defined HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
||||
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got
|
||||
* here, these types are probably undefined.
|
||||
*/
|
||||
#if defined __MACH__
|
||||
#include <ppc/types.h>
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
#elif defined __FreeBSD__
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
typedef short int int16_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
#if defined SN_TARGET_PS2
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef long int int32_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#define HAVE_I64
|
||||
#elif defined __GNUC__
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#define HAVE_I64
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#define HAVE_STDINT_H
|
||||
#endif
|
||||
#if defined _LP64 || defined WIN64 || defined _WIN64
|
||||
#if !defined __64BIT__
|
||||
#define __64BIT__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
|
||||
#if !defined alloca
|
||||
#define alloca(n) _alloca(n)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined arraysize
|
||||
#define arraysize(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
#if !defined assert_static
|
||||
/* see "Compile-Time Assertions" by Ralf Holly,
|
||||
* C/C++ Users Journal, November 2004
|
||||
*/
|
||||
#define assert_static(e) \
|
||||
do { \
|
||||
enum { assert_static__ = 1/(e) }; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined PAWN_DLL
|
||||
#if !defined AMX_NATIVE_CALL
|
||||
#define AMX_NATIVE_CALL __stdcall
|
||||
#endif
|
||||
#if !defined AMXAPI
|
||||
#define AMXAPI __stdcall
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* calling convention for native functions */
|
||||
#if !defined AMX_NATIVE_CALL
|
||||
#define AMX_NATIVE_CALL
|
||||
#endif
|
||||
/* calling convention for all interface functions and callback functions */
|
||||
#if !defined AMXAPI
|
||||
#if defined STDECL
|
||||
#define AMXAPI __stdcall
|
||||
#elif defined CDECL
|
||||
#define AMXAPI __cdecl
|
||||
#elif defined GCC_HASCLASSVISIBILITY
|
||||
#define AMXAPI __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define AMXAPI
|
||||
#endif
|
||||
#endif
|
||||
#if !defined AMXEXPORT
|
||||
#define AMXEXPORT
|
||||
#endif
|
||||
|
||||
/* File format version (in CUR_FILE_VERSION)
|
||||
* 0 (original version)
|
||||
* 1 (opcodes JUMP.pri, SWITCH and CASETBL)
|
||||
* 2 (compressed files)
|
||||
* 3 (public variables)
|
||||
* 4 (opcodes SWAP.pri/alt and PUSHADDR)
|
||||
* 5 (tagnames table)
|
||||
* 6 (reformatted header)
|
||||
* 7 (name table, opcodes SYMTAG & SYSREQ.D)
|
||||
* 8 (opcode STMT, renewed debug interface)
|
||||
* 9 (macro opcodes)
|
||||
* MIN_FILE_VERSION is the lowest file version number that the current AMX
|
||||
* implementation supports. If the AMX file header gets new fields, this number
|
||||
* often needs to be incremented. MAX_AMX_VERSION is the lowest AMX version that
|
||||
* is needed to support the current file version. When there are new opcodes,
|
||||
* this number needs to be incremented.
|
||||
* The file version supported by the JIT may run behind MIN_AMX_VERSION. So
|
||||
* there is an extra constant for it: MAX_FILE_VER_JIT.
|
||||
*/
|
||||
#define CUR_FILE_VERSION 9 /* current file version; also the current AMX version */
|
||||
#define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */
|
||||
#define MIN_AMX_VERSION 9 /* minimum AMX version needed to support the current file format */
|
||||
#define MAX_FILE_VER_JIT 8 /* file version supported by the JIT */
|
||||
#define MIN_AMX_VER_JIT 8 /* AMX version supported by the JIT */
|
||||
|
||||
#if !defined PAWN_CELL_SIZE
|
||||
#define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */
|
||||
#endif
|
||||
#if PAWN_CELL_SIZE==16
|
||||
typedef uint16_t ucell;
|
||||
typedef int16_t cell;
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
typedef uint32_t ucell;
|
||||
typedef int32_t cell;
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
typedef uint64_t ucell;
|
||||
typedef int64_t cell;
|
||||
#else
|
||||
#error Unsupported cell size (PAWN_CELL_SIZE)
|
||||
#endif
|
||||
|
||||
#define UNPACKEDMAX (((cell)1 << (sizeof(cell)-1)*8) - 1)
|
||||
#define UNLIMITED (~1u >> 1)
|
||||
|
||||
struct tagAMX;
|
||||
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
|
||||
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
|
||||
cell *result, cell *params);
|
||||
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
|
||||
typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX *, cell *, int));
|
||||
#if !defined _FAR
|
||||
#define _FAR
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(disable:4103) /* disable warning message 4103 that complains
|
||||
* about pragma pack in a header file */
|
||||
#pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */
|
||||
#endif
|
||||
|
||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
||||
* compilers give a warning on unknown #pragmas, which is not so fine...
|
||||
*/
|
||||
#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
|
||||
#define AMX_NO_ALIGN
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
#else
|
||||
#pragma pack(push)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#if defined __TURBOC__
|
||||
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct tagAMX_NATIVE_INFO {
|
||||
const char _FAR *name;
|
||||
AMX_NATIVE func;
|
||||
} AMX_NATIVE_INFO;
|
||||
|
||||
#define AMX_USERNUM 4
|
||||
#define sEXPMAX 19 /* maximum name length for file version <= 6 */
|
||||
#define sNAMEMAX 31 /* maximum name length of symbol name */
|
||||
|
||||
typedef struct tagAMX_FUNCSTUB {
|
||||
ucell address;
|
||||
char name[sEXPMAX+1];
|
||||
} AMX_FUNCSTUB;
|
||||
|
||||
typedef struct tagFUNCSTUBNT {
|
||||
ucell address;
|
||||
uint32_t nameofs;
|
||||
} AMX_FUNCSTUBNT;
|
||||
|
||||
/* The AMX structure is the internal structure for many functions. Not all
|
||||
* fields are valid at all times; many fields are cached in local variables.
|
||||
*/
|
||||
typedef struct tagAMX {
|
||||
unsigned char _FAR *base; /* points to the AMX header plus the code, optionally also the data */
|
||||
unsigned char _FAR *data; /* points to separate data+stack+heap, may be NULL */
|
||||
AMX_CALLBACK callback;
|
||||
AMX_DEBUG debug ; /* debug callback */
|
||||
/* for external functions a few registers must be accessible from the outside */
|
||||
cell cip ; /* instruction pointer: relative to base + amxhdr->cod */
|
||||
cell frm ; /* stack frame base: relative to base + amxhdr->dat */
|
||||
cell hea ; /* top of the heap: relative to base + amxhdr->dat */
|
||||
cell hlw ; /* bottom of the heap: relative to base + amxhdr->dat */
|
||||
cell stk ; /* stack pointer: relative to base + amxhdr->dat */
|
||||
cell stp ; /* top of the stack: relative to base + amxhdr->dat */
|
||||
int flags ; /* current status, see amx_Flags() */
|
||||
/* user data */
|
||||
long usertags[AMX_USERNUM] ;
|
||||
void _FAR *userdata[AMX_USERNUM] ;
|
||||
/* native functions can raise an error */
|
||||
int error ;
|
||||
/* passing parameters requires a "count" field */
|
||||
int paramcount;
|
||||
/* the sleep opcode needs to store the full AMX status */
|
||||
cell pri ;
|
||||
cell alt ;
|
||||
cell reset_stk ;
|
||||
cell reset_hea ;
|
||||
/* extra fields for increased performance */
|
||||
cell sysreq_d ; /* relocated address/value for the SYSREQ.D opcode */
|
||||
#if defined JIT
|
||||
/* support variables for the JIT */
|
||||
int reloc_size ; /* required temporary buffer for relocations */
|
||||
long code_size ; /* estimated memory footprint of the native code */
|
||||
#endif
|
||||
} AMX;
|
||||
|
||||
/* The AMX_HEADER structure is both the memory format as the file format. The
|
||||
* structure is used internaly.
|
||||
*/
|
||||
typedef struct tagAMX_HEADER {
|
||||
int32_t size ; /* size of the "file" */
|
||||
uint16_t magic ; /* signature */
|
||||
char file_version ; /* file format version */
|
||||
char amx_version ; /* required version of the AMX */
|
||||
int16_t flags ;
|
||||
int16_t defsize ; /* size of a definition record */
|
||||
int32_t cod ; /* initial value of COD - code block */
|
||||
int32_t dat ; /* initial value of DAT - data block */
|
||||
int32_t hea ; /* initial value of HEA - start of the heap */
|
||||
int32_t stp ; /* initial value of STP - stack top */
|
||||
int32_t cip ; /* initial value of CIP - the instruction pointer */
|
||||
int32_t publics ; /* offset to the "public functions" table */
|
||||
int32_t natives ; /* offset to the "native functions" table */
|
||||
int32_t libraries ; /* offset to the table of libraries */
|
||||
int32_t pubvars ; /* the "public variables" table */
|
||||
int32_t tags ; /* the "public tagnames" table */
|
||||
int32_t nametable ; /* name table */
|
||||
} AMX_HEADER;
|
||||
|
||||
#if PAWN_CELL_SIZE==16
|
||||
#define AMX_MAGIC 0xf1e2
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
#define AMX_MAGIC 0xf1e0
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#define AMX_MAGIC 0xf1e1
|
||||
#endif
|
||||
|
||||
enum {
|
||||
AMX_ERR_NONE,
|
||||
/* reserve the first 15 error codes for exit codes of the abstract machine */
|
||||
AMX_ERR_EXIT, /* forced exit */
|
||||
AMX_ERR_ASSERT, /* assertion failed */
|
||||
AMX_ERR_STACKERR, /* stack/heap collision */
|
||||
AMX_ERR_BOUNDS, /* index out of bounds */
|
||||
AMX_ERR_MEMACCESS, /* invalid memory access */
|
||||
AMX_ERR_INVINSTR, /* invalid instruction */
|
||||
AMX_ERR_STACKLOW, /* stack underflow */
|
||||
AMX_ERR_HEAPLOW, /* heap underflow */
|
||||
AMX_ERR_CALLBACK, /* no callback, or invalid callback */
|
||||
AMX_ERR_NATIVE, /* native function failed */
|
||||
AMX_ERR_DIVIDE, /* divide by zero */
|
||||
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
|
||||
AMX_ERR_INVSTATE, /* invalid state for this access */
|
||||
|
||||
AMX_ERR_MEMORY = 16, /* out of memory */
|
||||
AMX_ERR_FORMAT, /* invalid file format */
|
||||
AMX_ERR_VERSION, /* file is for a newer version of the AMX */
|
||||
AMX_ERR_NOTFOUND, /* function not found */
|
||||
AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */
|
||||
AMX_ERR_DEBUG, /* debugger cannot run */
|
||||
AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */
|
||||
AMX_ERR_USERDATA, /* unable to set user data field (table full) */
|
||||
AMX_ERR_INIT_JIT, /* cannot initialize the JIT */
|
||||
AMX_ERR_PARAMS, /* parameter error */
|
||||
AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */
|
||||
AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */
|
||||
};
|
||||
|
||||
/* AMX_FLAG_CHAR16 0x01 no longer used */
|
||||
#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */
|
||||
#define AMX_FLAG_COMPACT 0x04 /* compact encoding */
|
||||
#define AMX_FLAG_SLEEP 0x08 /* script uses the sleep instruction (possible re-entry or power-down mode) */
|
||||
#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no BREAK opcodes */
|
||||
#define AMX_FLAG_SYSREQN 0x800 /* script new (optimized) version of SYSREQ opcode */
|
||||
#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
|
||||
#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
|
||||
#define AMX_FLAG_BROWSE 0x4000 /* busy browsing */
|
||||
#define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
|
||||
|
||||
#define AMX_EXEC_MAIN (-1) /* start at program entry point */
|
||||
#define AMX_EXEC_CONT (-2) /* continue from last address */
|
||||
|
||||
#define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
|
||||
|
||||
#if !defined AMX_COMPACTMARGIN
|
||||
#define AMX_COMPACTMARGIN 64
|
||||
#endif
|
||||
|
||||
/* for native functions that use floating point parameters, the following
|
||||
* two macros are convenient for casting a "cell" into a "float" type _without_
|
||||
* changing the bit pattern
|
||||
*/
|
||||
#if PAWN_CELL_SIZE==32
|
||||
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
|
||||
#define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
|
||||
#define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
|
||||
#define amx_StrParam(amx,param,result) \
|
||||
do { \
|
||||
cell *amx_cstr_; int amx_length_; \
|
||||
amx_GetAddr((amx), (param), &amx_cstr_); \
|
||||
amx_StrLen(amx_cstr_, &amx_length_); \
|
||||
if (amx_length_ > 0 && \
|
||||
((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \
|
||||
amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_ + 1); \
|
||||
else (result) = NULL; \
|
||||
} while (0)
|
||||
|
||||
uint16_t * AMXAPI amx_Align16(uint16_t *v);
|
||||
uint32_t * AMXAPI amx_Align32(uint32_t *v);
|
||||
#if defined _I64_MAX || defined HAVE_I64
|
||||
uint64_t * AMXAPI amx_Align64(uint64_t *v);
|
||||
#endif
|
||||
int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
|
||||
int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
|
||||
int AMXAPI amx_Cleanup(AMX *amx);
|
||||
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
|
||||
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
|
||||
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
|
||||
int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
|
||||
int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr);
|
||||
int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname);
|
||||
int AMXAPI amx_Flags(AMX *amx,uint16_t *flags);
|
||||
int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr);
|
||||
int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname);
|
||||
int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname);
|
||||
int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr);
|
||||
int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size);
|
||||
int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
|
||||
int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
|
||||
int AMXAPI amx_Init(AMX *amx, void *program);
|
||||
int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code);
|
||||
int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap);
|
||||
int AMXAPI amx_NameLength(AMX *amx, int *length);
|
||||
AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func);
|
||||
int AMXAPI amx_NumNatives(AMX *amx, int *number);
|
||||
int AMXAPI amx_NumPublics(AMX *amx, int *number);
|
||||
int AMXAPI amx_NumPubVars(AMX *amx, int *number);
|
||||
int AMXAPI amx_NumTags(AMX *amx, int *number);
|
||||
int AMXAPI amx_Push(AMX *amx, cell value);
|
||||
int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells);
|
||||
int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
|
||||
int AMXAPI amx_RaiseError(AMX *amx, int error);
|
||||
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
|
||||
int AMXAPI amx_Release(AMX *amx, cell amx_addr);
|
||||
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
|
||||
int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
|
||||
int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size);
|
||||
int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
|
||||
int AMXAPI amx_StrLen(const cell *cstring, int *length);
|
||||
int AMXAPI amx_UTF8Check(const char *string, int *length);
|
||||
int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value);
|
||||
int AMXAPI amx_UTF8Len(const cell *cstr, int *length);
|
||||
int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
|
||||
|
||||
#if PAWN_CELL_SIZE==16
|
||||
#define amx_AlignCell(v) amx_Align16(v)
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
#define amx_AlignCell(v) amx_Align32(v)
|
||||
#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
|
||||
#define amx_AlignCell(v) amx_Align64(v)
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
|
||||
#define amx_RegisterFunc(amx, name, func) \
|
||||
amx_Register((amx), amx_NativeInfo((name),(func)), 1);
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
#else
|
||||
#pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
OP_NONE, /* invalid opcode */
|
||||
OP_LOAD_PRI,
|
||||
OP_LOAD_ALT,
|
||||
OP_LOAD_S_PRI,
|
||||
OP_LOAD_S_ALT,
|
||||
OP_LREF_PRI,
|
||||
OP_LREF_ALT,
|
||||
OP_LREF_S_PRI,
|
||||
OP_LREF_S_ALT,
|
||||
OP_LOAD_I,
|
||||
OP_LODB_I,
|
||||
OP_CONST_PRI,
|
||||
OP_CONST_ALT,
|
||||
OP_ADDR_PRI,
|
||||
OP_ADDR_ALT,
|
||||
OP_STOR_PRI,
|
||||
OP_STOR_ALT,
|
||||
OP_STOR_S_PRI,
|
||||
OP_STOR_S_ALT,
|
||||
OP_SREF_PRI,
|
||||
OP_SREF_ALT,
|
||||
OP_SREF_S_PRI,
|
||||
OP_SREF_S_ALT,
|
||||
OP_STOR_I,
|
||||
OP_STRB_I,
|
||||
OP_LIDX,
|
||||
OP_LIDX_B,
|
||||
OP_IDXADDR,
|
||||
OP_IDXADDR_B,
|
||||
OP_ALIGN_PRI,
|
||||
OP_ALIGN_ALT,
|
||||
OP_LCTRL,
|
||||
OP_SCTRL,
|
||||
OP_MOVE_PRI,
|
||||
OP_MOVE_ALT,
|
||||
OP_XCHG,
|
||||
OP_PUSH_PRI,
|
||||
OP_PUSH_ALT,
|
||||
OP_PUSH_R,
|
||||
OP_PUSH_C,
|
||||
OP_PUSH,
|
||||
OP_PUSH_S,
|
||||
OP_POP_PRI,
|
||||
OP_POP_ALT,
|
||||
OP_STACK,
|
||||
OP_HEAP,
|
||||
OP_PROC,
|
||||
OP_RET,
|
||||
OP_RETN,
|
||||
OP_CALL,
|
||||
OP_CALL_PRI,
|
||||
OP_JUMP,
|
||||
OP_JREL,
|
||||
OP_JZER,
|
||||
OP_JNZ,
|
||||
OP_JEQ,
|
||||
OP_JNEQ,
|
||||
OP_JLESS,
|
||||
OP_JLEQ,
|
||||
OP_JGRTR,
|
||||
OP_JGEQ,
|
||||
OP_JSLESS,
|
||||
OP_JSLEQ,
|
||||
OP_JSGRTR,
|
||||
OP_JSGEQ,
|
||||
OP_SHL,
|
||||
OP_SHR,
|
||||
OP_SSHR,
|
||||
OP_SHL_C_PRI,
|
||||
OP_SHL_C_ALT,
|
||||
OP_SHR_C_PRI,
|
||||
OP_SHR_C_ALT,
|
||||
OP_SMUL,
|
||||
OP_SDIV,
|
||||
OP_SDIV_ALT,
|
||||
OP_UMUL,
|
||||
OP_UDIV,
|
||||
OP_UDIV_ALT,
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_SUB_ALT,
|
||||
OP_AND,
|
||||
OP_OR,
|
||||
OP_XOR,
|
||||
OP_NOT,
|
||||
OP_NEG,
|
||||
OP_INVERT,
|
||||
OP_ADD_C,
|
||||
OP_SMUL_C,
|
||||
OP_ZERO_PRI,
|
||||
OP_ZERO_ALT,
|
||||
OP_ZERO,
|
||||
OP_ZERO_S,
|
||||
OP_SIGN_PRI,
|
||||
OP_SIGN_ALT,
|
||||
OP_EQ,
|
||||
OP_NEQ,
|
||||
OP_LESS,
|
||||
OP_LEQ,
|
||||
OP_GRTR,
|
||||
OP_GEQ,
|
||||
OP_SLESS,
|
||||
OP_SLEQ,
|
||||
OP_SGRTR,
|
||||
OP_SGEQ,
|
||||
OP_EQ_C_PRI,
|
||||
OP_EQ_C_ALT,
|
||||
OP_INC_PRI,
|
||||
OP_INC_ALT,
|
||||
OP_INC,
|
||||
OP_INC_S,
|
||||
OP_INC_I,
|
||||
OP_DEC_PRI,
|
||||
OP_DEC_ALT,
|
||||
OP_DEC,
|
||||
OP_DEC_S,
|
||||
OP_DEC_I,
|
||||
OP_MOVS,
|
||||
OP_CMPS,
|
||||
OP_FILL,
|
||||
OP_HALT,
|
||||
OP_BOUNDS,
|
||||
OP_SYSREQ_PRI,
|
||||
OP_SYSREQ_C,
|
||||
OP_FILE, /* obsolete */
|
||||
OP_LINE, /* obsolete */
|
||||
OP_SYMBOL, /* obsolete */
|
||||
OP_SRANGE, /* obsolete */
|
||||
OP_JUMP_PRI,
|
||||
OP_SWITCH,
|
||||
OP_CASETBL,
|
||||
OP_SWAP_PRI,
|
||||
OP_SWAP_ALT,
|
||||
OP_PUSH_ADR,
|
||||
OP_NOP,
|
||||
OP_SYSREQ_N,
|
||||
OP_SYMTAG, /* obsolete */
|
||||
OP_BREAK,
|
||||
OP_PUSH2_C,
|
||||
OP_PUSH2,
|
||||
OP_PUSH2_S,
|
||||
OP_PUSH2_ADR,
|
||||
OP_PUSH3_C,
|
||||
OP_PUSH3,
|
||||
OP_PUSH3_S,
|
||||
OP_PUSH3_ADR,
|
||||
OP_PUSH4_C,
|
||||
OP_PUSH4,
|
||||
OP_PUSH4_S,
|
||||
OP_PUSH4_ADR,
|
||||
OP_PUSH5_C,
|
||||
OP_PUSH5,
|
||||
OP_PUSH5_S,
|
||||
OP_PUSH5_ADR,
|
||||
OP_LOAD_BOTH,
|
||||
OP_LOAD_S_BOTH,
|
||||
OP_CONST,
|
||||
OP_CONST_S,
|
||||
/* ----- */
|
||||
OP_SYSREQ_D,
|
||||
OP_SYSREQ_ND,
|
||||
/* ----- */
|
||||
OP_HEAP_I,
|
||||
OP_PUSH_H_C,
|
||||
OP_GENARRAY,
|
||||
OP_NUM_OPCODES
|
||||
} OPCODE;
|
||||
|
||||
#endif /* AMX_H_INCLUDED */
|
||||
@@ -0,0 +1,173 @@
|
||||
/* Abstract Machine for the Pawn compiler, debugger support
|
||||
*
|
||||
* This file contains extra definitions that are convenient for debugger
|
||||
* support.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2005
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef AMXDBG_H_INCLUDED
|
||||
#define AMXDBG_H_INCLUDED
|
||||
|
||||
#ifndef AMX_H_INCLUDED
|
||||
#include "amx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
||||
* compilers give a warning on unknown #pragmas, which is not so fine...
|
||||
*/
|
||||
#if defined SN_TARGET_PS2 || defined __GNUC__
|
||||
#define AMX_NO_ALIGN
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#define PACKED __attribute__((packed))
|
||||
#else
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
#else
|
||||
#pragma pack(push)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#if defined __TURBOC__
|
||||
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct tagAMX_DBG_HDR {
|
||||
int32_t size PACKED; /* size of the debug information chunk */
|
||||
uint16_t magic PACKED; /* signature, must be 0xf1ef */
|
||||
char file_version; /* file format version */
|
||||
char amx_version; /* required version of the AMX */
|
||||
int16_t flags PACKED; /* currently unused */
|
||||
int16_t files PACKED; /* number of entries in the "file" table */
|
||||
int16_t lines PACKED; /* number of entries in the "line" table */
|
||||
int16_t symbols PACKED; /* number of entries in the "symbol" table */
|
||||
int16_t tags PACKED; /* number of entries in the "tag" table */
|
||||
int16_t automatons PACKED; /* number of entries in the "automaton" table */
|
||||
int16_t states PACKED; /* number of entries in the "state" table */
|
||||
} PACKED AMX_DBG_HDR;
|
||||
#define AMX_DBG_MAGIC 0xf1ef
|
||||
|
||||
typedef struct tagAMX_DBG_FILE {
|
||||
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_FILE;
|
||||
|
||||
typedef struct tagAMX_DBG_LINE {
|
||||
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
|
||||
int32_t line PACKED; /* line number */
|
||||
} PACKED AMX_DBG_LINE;
|
||||
|
||||
typedef struct tagAMX_DBG_SYMBOL {
|
||||
ucell address PACKED; /* address in the data segment or relative to the frame */
|
||||
int16_t tag PACKED; /* tag for the symbol */
|
||||
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */
|
||||
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
|
||||
char ident; /* kind of symbol (function/variable) */
|
||||
char vclass; /* class of symbol (global/local) */
|
||||
int16_t dim PACKED; /* number of dimensions */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_SYMBOL;
|
||||
|
||||
typedef struct tagAMX_DBG_SYMDIM {
|
||||
int16_t tag PACKED; /* tag for the array dimension */
|
||||
ucell size PACKED; /* size of the array dimension */
|
||||
} PACKED AMX_DBG_SYMDIM;
|
||||
|
||||
typedef struct tagAMX_DBG_TAG {
|
||||
int16_t tag PACKED; /* tag id */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_TAG;
|
||||
|
||||
typedef struct tagAMX_DBG_MACHINE {
|
||||
int16_t automaton PACKED; /* automaton id */
|
||||
ucell address PACKED; /* address of state variable */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_MACHINE;
|
||||
|
||||
typedef struct tagAMX_DBG_STATE {
|
||||
int16_t state PACKED; /* state id */
|
||||
int16_t automaton PACKED; /* automaton id */
|
||||
const char name[1]; /* ASCII string, zero-terminated */
|
||||
} PACKED AMX_DBG_STATE;
|
||||
|
||||
typedef struct tagAMX_DBG {
|
||||
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
|
||||
AMX_DBG_FILE _FAR **filetbl PACKED;
|
||||
AMX_DBG_LINE _FAR *linetbl PACKED;
|
||||
AMX_DBG_SYMBOL _FAR **symboltbl PACKED;
|
||||
AMX_DBG_TAG _FAR **tagtbl PACKED;
|
||||
AMX_DBG_MACHINE _FAR **automatontbl PACKED;
|
||||
AMX_DBG_STATE _FAR **statetbl PACKED;
|
||||
} PACKED AMX_DBG;
|
||||
|
||||
#if !defined iVARIABLE
|
||||
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
||||
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
|
||||
#define iARRAY 3
|
||||
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
||||
#define iFUNCTN 9
|
||||
#endif
|
||||
|
||||
|
||||
int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
|
||||
int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr);
|
||||
|
||||
int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename);
|
||||
int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname);
|
||||
int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line);
|
||||
|
||||
int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address);
|
||||
int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address);
|
||||
int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name);
|
||||
int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name);
|
||||
int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name);
|
||||
int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym);
|
||||
int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim);
|
||||
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
#else
|
||||
#pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMXDBG_H_INCLUDED */
|
||||
|
||||
@@ -0,0 +1,766 @@
|
||||
/*
|
||||
* BinReloc - a library for creating relocatable executables
|
||||
* Written by: Hongli Lai <[email protected]>
|
||||
* http://autopackage.org/
|
||||
*
|
||||
* This source code is public domain. You can relicense this code
|
||||
* under whatever license you want.
|
||||
*
|
||||
* See http://autopackage.org/docs/binreloc/ for
|
||||
* more information and how to use this.
|
||||
*/
|
||||
|
||||
#ifndef __BINRELOC_C__
|
||||
#define __BINRELOC_C__
|
||||
|
||||
#ifdef ENABLE_BINRELOC
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "binreloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
/** @internal
|
||||
* Find the canonical filename of the executable. Returns the filename
|
||||
* (which must be freed) or NULL on error. If the parameter 'error' is
|
||||
* not NULL, the error code will be stored there, if an error occured.
|
||||
*/
|
||||
static char *
|
||||
_br_find_exe (BrInitError *error)
|
||||
{
|
||||
#ifndef ENABLE_BINRELOC
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_DISABLED;
|
||||
return NULL;
|
||||
#else
|
||||
char *path, *path2, *line, *result;
|
||||
size_t buf_size;
|
||||
ssize_t size;
|
||||
struct stat stat_buf;
|
||||
FILE *f;
|
||||
|
||||
/* Read from /proc/self/exe (symlink) */
|
||||
if (sizeof (path) > SSIZE_MAX)
|
||||
buf_size = SSIZE_MAX - 1;
|
||||
else
|
||||
buf_size = PATH_MAX - 1;
|
||||
path = (char *) malloc (buf_size);
|
||||
if (path == NULL) {
|
||||
/* Cannot allocate memory. */
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_NOMEM;
|
||||
return NULL;
|
||||
}
|
||||
path2 = (char *) malloc (buf_size);
|
||||
if (path2 == NULL) {
|
||||
/* Cannot allocate memory. */
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_NOMEM;
|
||||
free (path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy (path2, "/proc/self/exe", buf_size - 1);
|
||||
|
||||
while (1) {
|
||||
int i;
|
||||
|
||||
size = readlink (path2, path, buf_size - 1);
|
||||
if (size == -1) {
|
||||
/* Error. */
|
||||
free (path2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* readlink() success. */
|
||||
path[size] = '\0';
|
||||
|
||||
/* Check whether the symlink's target is also a symlink.
|
||||
* We want to get the final target. */
|
||||
i = stat (path, &stat_buf);
|
||||
if (i == -1) {
|
||||
/* Error. */
|
||||
free (path2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* stat() success. */
|
||||
if (!S_ISLNK (stat_buf.st_mode)) {
|
||||
/* path is not a symlink. Done. */
|
||||
free (path2);
|
||||
return path;
|
||||
}
|
||||
|
||||
/* path is a symlink. Continue loop and resolve this. */
|
||||
strncpy (path, path2, buf_size - 1);
|
||||
}
|
||||
|
||||
|
||||
/* readlink() or stat() failed; this can happen when the program is
|
||||
* running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
|
||||
|
||||
buf_size = PATH_MAX + 128;
|
||||
line = (char *) realloc (path, buf_size);
|
||||
if (line == NULL) {
|
||||
/* Cannot allocate memory. */
|
||||
free (path);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_NOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f = fopen ("/proc/self/maps", "r");
|
||||
if (f == NULL) {
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_OPEN_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The first entry should be the executable name. */
|
||||
result = fgets (line, (int) buf_size, f);
|
||||
if (result == NULL) {
|
||||
fclose (f);
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_READ_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get rid of newline character. */
|
||||
buf_size = strlen (line);
|
||||
if (buf_size <= 0) {
|
||||
/* Huh? An empty string? */
|
||||
fclose (f);
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_INVALID_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
if (line[buf_size - 1] == 10)
|
||||
line[buf_size - 1] = 0;
|
||||
|
||||
/* Extract the filename; it is always an absolute path. */
|
||||
path = strchr (line, '/');
|
||||
|
||||
/* Sanity check. */
|
||||
if (strstr (line, " r-xp ") == NULL || path == NULL) {
|
||||
fclose (f);
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_INVALID_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = strdup (path);
|
||||
free (line);
|
||||
fclose (f);
|
||||
return path;
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
}
|
||||
|
||||
|
||||
/** @internal
|
||||
* Find the canonical filename of the executable which owns symbol.
|
||||
* Returns a filename which must be freed, or NULL on error.
|
||||
*/
|
||||
static char *
|
||||
_br_find_exe_for_symbol (const void *symbol, BrInitError *error)
|
||||
{
|
||||
#ifndef ENABLE_BINRELOC
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_DISABLED;
|
||||
return (char *) NULL;
|
||||
#else
|
||||
#define SIZE PATH_MAX + 100
|
||||
FILE *f;
|
||||
size_t address_string_len;
|
||||
char *address_string, line[SIZE], *found;
|
||||
|
||||
if (symbol == NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
f = fopen ("/proc/self/maps", "r");
|
||||
if (f == NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
address_string_len = 4;
|
||||
address_string = (char *) malloc (address_string_len);
|
||||
found = (char *) NULL;
|
||||
|
||||
while (!feof (f)) {
|
||||
char *start_addr, *end_addr, *end_addr_end, *file;
|
||||
void *start_addr_p, *end_addr_p;
|
||||
size_t len;
|
||||
|
||||
if (fgets (line, SIZE, f) == NULL)
|
||||
break;
|
||||
|
||||
/* Sanity check. */
|
||||
if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
|
||||
continue;
|
||||
|
||||
/* Parse line. */
|
||||
start_addr = line;
|
||||
end_addr = strchr (line, '-');
|
||||
file = strchr (line, '/');
|
||||
|
||||
/* More sanity check. */
|
||||
if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
|
||||
continue;
|
||||
|
||||
end_addr[0] = '\0';
|
||||
end_addr++;
|
||||
end_addr_end = strchr (end_addr, ' ');
|
||||
if (end_addr_end == NULL)
|
||||
continue;
|
||||
|
||||
end_addr_end[0] = '\0';
|
||||
len = strlen (file);
|
||||
if (len == 0)
|
||||
continue;
|
||||
if (file[len - 1] == '\n')
|
||||
file[len - 1] = '\0';
|
||||
|
||||
/* Get rid of "(deleted)" from the filename. */
|
||||
len = strlen (file);
|
||||
if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
|
||||
file[len - 10] = '\0';
|
||||
|
||||
/* I don't know whether this can happen but better safe than sorry. */
|
||||
len = strlen (start_addr);
|
||||
if (len != strlen (end_addr))
|
||||
continue;
|
||||
|
||||
|
||||
/* Transform the addresses into a string in the form of 0xdeadbeef,
|
||||
* then transform that into a pointer. */
|
||||
if (address_string_len < len + 3) {
|
||||
address_string_len = len + 3;
|
||||
address_string = (char *) realloc (address_string, address_string_len);
|
||||
}
|
||||
|
||||
memcpy (address_string, "0x", 2);
|
||||
memcpy (address_string + 2, start_addr, len);
|
||||
address_string[2 + len] = '\0';
|
||||
sscanf (address_string, "%p", &start_addr_p);
|
||||
|
||||
memcpy (address_string, "0x", 2);
|
||||
memcpy (address_string + 2, end_addr, len);
|
||||
address_string[2 + len] = '\0';
|
||||
sscanf (address_string, "%p", &end_addr_p);
|
||||
|
||||
|
||||
if (symbol >= start_addr_p && symbol < end_addr_p) {
|
||||
found = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (address_string);
|
||||
fclose (f);
|
||||
|
||||
if (found == NULL)
|
||||
return (char *) NULL;
|
||||
else
|
||||
return strdup (found);
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
}
|
||||
|
||||
|
||||
#ifndef BINRELOC_RUNNING_DOXYGEN
|
||||
#undef NULL
|
||||
#define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */
|
||||
#endif
|
||||
|
||||
static char *exe = (char *) NULL;
|
||||
|
||||
|
||||
/** Initialize the BinReloc library (for applications).
|
||||
*
|
||||
* This function must be called before using any other BinReloc functions.
|
||||
* It attempts to locate the application's canonical filename.
|
||||
*
|
||||
* @note If you want to use BinReloc for a library, then you should call
|
||||
* br_init_lib() instead.
|
||||
*
|
||||
* @param error If BinReloc failed to initialize, then the error code will
|
||||
* be stored in this variable. Set to NULL if you want to
|
||||
* ignore this. See #BrInitError for a list of error codes.
|
||||
*
|
||||
* @returns 1 on success, 0 if BinReloc failed to initialize.
|
||||
*/
|
||||
int
|
||||
br_init (BrInitError *error)
|
||||
{
|
||||
exe = _br_find_exe (error);
|
||||
return exe != NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Initialize the BinReloc library (for libraries).
|
||||
*
|
||||
* This function must be called before using any other BinReloc functions.
|
||||
* It attempts to locate the calling library's canonical filename.
|
||||
*
|
||||
* @note The BinReloc source code MUST be included in your library, or this
|
||||
* function won't work correctly.
|
||||
*
|
||||
* @param error If BinReloc failed to initialize, then the error code will
|
||||
* be stored in this variable. Set to NULL if you want to
|
||||
* ignore this. See #BrInitError for a list of error codes.
|
||||
*
|
||||
* @returns 1 on success, 0 if a filename cannot be found.
|
||||
*/
|
||||
int
|
||||
br_init_lib (BrInitError *error)
|
||||
{
|
||||
exe = _br_find_exe_for_symbol ((const void *) "", error);
|
||||
return exe != NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Find the canonical filename of the current application.
|
||||
*
|
||||
* @param default_exe A default filename which will be used as fallback.
|
||||
* @returns A string containing the application's canonical filename,
|
||||
* which must be freed when no longer necessary. If BinReloc is
|
||||
* not initialized, or if br_init() failed, then a copy of
|
||||
* default_exe will be returned. If default_exe is NULL, then
|
||||
* NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_exe (const char *default_exe)
|
||||
{
|
||||
if (exe == (char *) NULL) {
|
||||
/* BinReloc is not initialized. */
|
||||
if (default_exe != (const char *) NULL)
|
||||
return strdup (default_exe);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
return strdup (exe);
|
||||
}
|
||||
|
||||
|
||||
/** Locate the directory in which the current application is installed.
|
||||
*
|
||||
* The prefix is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* dirname(exename)
|
||||
* \endcode
|
||||
*
|
||||
* @param default_dir A default directory which will used as fallback.
|
||||
* @return A string containing the directory, which must be freed when no
|
||||
* longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_dir
|
||||
* will be returned. If default_dir is NULL, then NULL will be
|
||||
* returned.
|
||||
*/
|
||||
char *
|
||||
br_find_exe_dir (const char *default_dir)
|
||||
{
|
||||
if (exe == NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_dir != NULL)
|
||||
return strdup (default_dir);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return br_dirname (exe);
|
||||
}
|
||||
|
||||
|
||||
/** Locate the prefix in which the current application is installed.
|
||||
*
|
||||
* The prefix is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* dirname(dirname(exename))
|
||||
* \endcode
|
||||
*
|
||||
* @param default_prefix A default prefix which will used as fallback.
|
||||
* @return A string containing the prefix, which must be freed when no
|
||||
* longer necessary. If BinReloc is not initialized, or if
|
||||
* the initialization function failed, then a copy of default_prefix
|
||||
* will be returned. If default_prefix is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_prefix (const char *default_prefix)
|
||||
{
|
||||
char *dir1, *dir2;
|
||||
|
||||
if (exe == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_prefix != (const char *) NULL)
|
||||
return strdup (default_prefix);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir1 = br_dirname (exe);
|
||||
dir2 = br_dirname (dir1);
|
||||
free (dir1);
|
||||
return dir2;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's binary folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/bin"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_bin_dir A default path which will used as fallback.
|
||||
* @return A string containing the bin folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if
|
||||
* the initialization function failed, then a copy of default_bin_dir will
|
||||
* be returned. If default_bin_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_bin_dir (const char *default_bin_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix ((const char *) NULL);
|
||||
if (prefix == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_bin_dir != (const char *) NULL)
|
||||
return strdup (default_bin_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (prefix, "bin");
|
||||
free (prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's superuser binary folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/sbin"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_sbin_dir A default path which will used as fallback.
|
||||
* @return A string containing the sbin folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_sbin_dir will
|
||||
* be returned. If default_bin_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_sbin_dir (const char *default_sbin_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix ((const char *) NULL);
|
||||
if (prefix == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_sbin_dir != (const char *) NULL)
|
||||
return strdup (default_sbin_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (prefix, "sbin");
|
||||
free (prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's data folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/share"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_data_dir A default path which will used as fallback.
|
||||
* @return A string containing the data folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_data_dir
|
||||
* will be returned. If default_data_dir is NULL, then NULL will be
|
||||
* returned.
|
||||
*/
|
||||
char *
|
||||
br_find_data_dir (const char *default_data_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix ((const char *) NULL);
|
||||
if (prefix == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_data_dir != (const char *) NULL)
|
||||
return strdup (default_data_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (prefix, "share");
|
||||
free (prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's localization folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/share/locale"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_locale_dir A default path which will used as fallback.
|
||||
* @return A string containing the localization folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_locale_dir will be returned.
|
||||
* If default_locale_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_locale_dir (const char *default_locale_dir)
|
||||
{
|
||||
char *data_dir, *dir;
|
||||
|
||||
data_dir = br_find_data_dir ((const char *) NULL);
|
||||
if (data_dir == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_locale_dir != (const char *) NULL)
|
||||
return strdup (default_locale_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (data_dir, "locale");
|
||||
free (data_dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's library folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/lib"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_lib_dir A default path which will used as fallback.
|
||||
* @return A string containing the library folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the initialization
|
||||
* function failed, then a copy of default_lib_dir will be returned.
|
||||
* If default_lib_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_lib_dir (const char *default_lib_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix ((const char *) NULL);
|
||||
if (prefix == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_lib_dir != (const char *) NULL)
|
||||
return strdup (default_lib_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (prefix, "lib");
|
||||
free (prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's libexec folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/libexec"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_libexec_dir A default path which will used as fallback.
|
||||
* @return A string containing the libexec folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the initialization
|
||||
* function failed, then a copy of default_libexec_dir will be returned.
|
||||
* If default_libexec_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_libexec_dir (const char *default_libexec_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix ((const char *) NULL);
|
||||
if (prefix == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_libexec_dir != (const char *) NULL)
|
||||
return strdup (default_libexec_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (prefix, "libexec");
|
||||
free (prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's configuration files folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/etc"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_etc_dir A default path which will used as fallback.
|
||||
* @return A string containing the etc folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the initialization
|
||||
* function failed, then a copy of default_etc_dir will be returned.
|
||||
* If default_etc_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_etc_dir (const char *default_etc_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix ((const char *) NULL);
|
||||
if (prefix == (char *) NULL) {
|
||||
/* BinReloc not initialized. */
|
||||
if (default_etc_dir != (const char *) NULL)
|
||||
return strdup (default_etc_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path (prefix, "etc");
|
||||
free (prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
* Utility functions
|
||||
***********************/
|
||||
|
||||
/** Concatenate str1 and str2 to a newly allocated string.
|
||||
*
|
||||
* @param str1 A string.
|
||||
* @param str2 Another string.
|
||||
* @returns A newly-allocated string. This string should be freed when no longer needed.
|
||||
*/
|
||||
char *
|
||||
br_strcat (const char *str1, const char *str2)
|
||||
{
|
||||
char *result;
|
||||
size_t len1, len2;
|
||||
|
||||
if (str1 == NULL)
|
||||
str1 = "";
|
||||
if (str2 == NULL)
|
||||
str2 = "";
|
||||
|
||||
len1 = strlen (str1);
|
||||
len2 = strlen (str2);
|
||||
|
||||
result = (char *) malloc (len1 + len2 + 1);
|
||||
memcpy (result, str1, len1);
|
||||
memcpy (result + len1, str2, len2);
|
||||
result[len1 + len2] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
br_build_path (const char *dir, const char *file)
|
||||
{
|
||||
char *dir2, *result;
|
||||
size_t len;
|
||||
int must_free = 0;
|
||||
|
||||
len = strlen (dir);
|
||||
if (len > 0 && dir[len - 1] != '/') {
|
||||
dir2 = br_strcat (dir, "/");
|
||||
must_free = 1;
|
||||
} else
|
||||
dir2 = (char *) dir;
|
||||
|
||||
result = br_strcat (dir2, file);
|
||||
if (must_free)
|
||||
free (dir2);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Emulates glibc's strndup() */
|
||||
static char *
|
||||
br_strndup (const char *str, size_t size)
|
||||
{
|
||||
char *result = (char *) NULL;
|
||||
size_t len;
|
||||
|
||||
if (str == (const char *) NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
len = strlen (str);
|
||||
if (len == 0)
|
||||
return strdup ("");
|
||||
if (size > len)
|
||||
size = len;
|
||||
|
||||
result = (char *) malloc (len + 1);
|
||||
memcpy (result, str, size);
|
||||
result[size] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** Extracts the directory component of a path.
|
||||
*
|
||||
* Similar to g_dirname() or the dirname commandline application.
|
||||
*
|
||||
* Example:
|
||||
* \code
|
||||
* br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local"
|
||||
* \endcode
|
||||
*
|
||||
* @param path A path.
|
||||
* @returns A directory name. This string should be freed when no longer needed.
|
||||
*/
|
||||
char *
|
||||
br_dirname (const char *path)
|
||||
{
|
||||
char *end, *result;
|
||||
|
||||
if (path == (const char *) NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
end = strrchr (path, '/');
|
||||
if (end == (const char *) NULL)
|
||||
return strdup (".");
|
||||
|
||||
while (end > path && *end == '/')
|
||||
end--;
|
||||
result = br_strndup (path, end - path + 1);
|
||||
if (result[0] == 0) {
|
||||
free (result);
|
||||
return strdup ("/");
|
||||
} else
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __BINRELOC_C__ */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* BinReloc - a library for creating relocatable executables
|
||||
* Written by: Hongli Lai <[email protected]>
|
||||
* http://autopackage.org/
|
||||
*
|
||||
* This source code is public domain. You can relicense this code
|
||||
* under whatever license you want.
|
||||
*
|
||||
* See http://autopackage.org/docs/binreloc/ for
|
||||
* more information and how to use this.
|
||||
*/
|
||||
|
||||
#ifndef __BINRELOC_H__
|
||||
#define __BINRELOC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */
|
||||
typedef enum {
|
||||
/** Cannot allocate memory. */
|
||||
BR_INIT_ERROR_NOMEM,
|
||||
/** Unable to open /proc/self/maps; see errno for details. */
|
||||
BR_INIT_ERROR_OPEN_MAPS,
|
||||
/** Unable to read from /proc/self/maps; see errno for details. */
|
||||
BR_INIT_ERROR_READ_MAPS,
|
||||
/** The file format of /proc/self/maps is invalid; kernel bug? */
|
||||
BR_INIT_ERROR_INVALID_MAPS,
|
||||
/** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */
|
||||
BR_INIT_ERROR_DISABLED
|
||||
} BrInitError;
|
||||
|
||||
|
||||
#ifndef BINRELOC_RUNNING_DOXYGEN
|
||||
/* Mangle symbol names to avoid symbol collisions with other ELF objects. */
|
||||
#define br_init SbCJ22537442193159_br_init
|
||||
#define br_init_lib SbCJ22537442193159_br_init_lib
|
||||
#define br_find_exe SbCJ22537442193159_br_find_exe
|
||||
#define br_find_exe_dir SbCJ22537442193159_br_find_exe_dir
|
||||
#define br_find_prefix SbCJ22537442193159_br_find_prefix
|
||||
#define br_find_bin_dir SbCJ22537442193159_br_find_bin_dir
|
||||
#define br_find_sbin_dir SbCJ22537442193159_br_find_sbin_dir
|
||||
#define br_find_data_dir SbCJ22537442193159_br_find_data_dir
|
||||
#define br_find_locale_dir SbCJ22537442193159_br_find_locale_dir
|
||||
#define br_find_lib_dir SbCJ22537442193159_br_find_lib_dir
|
||||
#define br_find_libexec_dir SbCJ22537442193159_br_find_libexec_dir
|
||||
#define br_find_etc_dir SbCJ22537442193159_br_find_etc_dir
|
||||
#define br_strcat SbCJ22537442193159_br_strcat
|
||||
#define br_build_path SbCJ22537442193159_br_build_path
|
||||
#define br_dirname SbCJ22537442193159_br_dirname
|
||||
|
||||
|
||||
#endif
|
||||
int br_init (BrInitError *error);
|
||||
int br_init_lib (BrInitError *error);
|
||||
|
||||
char *br_find_exe (const char *default_exe);
|
||||
char *br_find_exe_dir (const char *default_dir);
|
||||
char *br_find_prefix (const char *default_prefix);
|
||||
char *br_find_bin_dir (const char *default_bin_dir);
|
||||
char *br_find_sbin_dir (const char *default_sbin_dir);
|
||||
char *br_find_data_dir (const char *default_data_dir);
|
||||
char *br_find_locale_dir (const char *default_locale_dir);
|
||||
char *br_find_lib_dir (const char *default_lib_dir);
|
||||
char *br_find_libexec_dir (const char *default_libexec_dir);
|
||||
char *br_find_etc_dir (const char *default_etc_dir);
|
||||
|
||||
/* Utility functions */
|
||||
char *br_strcat (const char *str1, const char *str2);
|
||||
char *br_build_path (const char *dir, const char *file);
|
||||
char *br_dirname (const char *path);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __BINRELOC_H__ */
|
||||
@@ -0,0 +1,15 @@
|
||||
/* Extremely inefficient but portable POSIX getch(), see getch.c */
|
||||
#ifndef GETCH_H
|
||||
#define GETCH_H
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int getch(void);
|
||||
int kbhit(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GETCH_H */
|
||||
@@ -0,0 +1,270 @@
|
||||
/* LIBPAWNC.C
|
||||
*
|
||||
* A "glue file" for building the Pawn compiler as a DLL or shared library.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2000-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "sc.h"
|
||||
#include "memfile.h"
|
||||
|
||||
/* pc_printf()
|
||||
* Called for general purpose "console" output. This function prints general
|
||||
* purpose messages; errors go through pc_error(). The function is modelled
|
||||
* after printf().
|
||||
*/
|
||||
int pc_printf(const char *message,...)
|
||||
{
|
||||
int ret;
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr,message);
|
||||
ret=vprintf(message,argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pc_error()
|
||||
* Called for producing error output.
|
||||
* number the error number (as documented in the manual)
|
||||
* message a string describing the error with embedded %d and %s tokens
|
||||
* filename the name of the file currently being parsed
|
||||
* firstline the line number at which the expression started on which
|
||||
* the error was found, or -1 if there is no "starting line"
|
||||
* lastline the line number at which the error was detected
|
||||
* argptr a pointer to the first of a series of arguments (for macro
|
||||
* "va_arg")
|
||||
* Return:
|
||||
* If the function returns 0, the parser attempts to continue compilation.
|
||||
* On a non-zero return value, the parser aborts.
|
||||
*/
|
||||
int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr)
|
||||
{
|
||||
static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
|
||||
if (number!=0) {
|
||||
char *pre;
|
||||
int idx;
|
||||
|
||||
if (number < 120)
|
||||
idx = 0;
|
||||
else if (number < 200)
|
||||
idx = 1;
|
||||
else
|
||||
idx = 2;
|
||||
|
||||
pre=prefix[idx];
|
||||
if (firstline>=0)
|
||||
fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number);
|
||||
else
|
||||
fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number);
|
||||
} /* if */
|
||||
vfprintf(stdout,message,argptr);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pc_opensrc()
|
||||
* Opens a source file (or include file) for reading. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
* filename the name of the "file" to read from
|
||||
* Return:
|
||||
* The function must return a pointer, which is used as a "magic cookie" to
|
||||
* all I/O functions. When failing to open the file for reading, the
|
||||
* function must return NULL.
|
||||
* Note:
|
||||
* Several "source files" may be open at the same time. Specifically, one
|
||||
* file can be open for reading and another for writing.
|
||||
*/
|
||||
void *pc_opensrc(char *filename)
|
||||
{
|
||||
return fopen(filename,"rt");
|
||||
}
|
||||
|
||||
/* pc_createsrc()
|
||||
* Creates/overwrites a source file for writing. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
* filename the name of the "file" to create
|
||||
* Return:
|
||||
* The function must return a pointer which is used as a "magic cookie" to
|
||||
* all I/O functions. When failing to open the file for reading, the
|
||||
* function must return NULL.
|
||||
* Note:
|
||||
* Several "source files" may be open at the same time. Specifically, one
|
||||
* file can be open for reading and another for writing.
|
||||
*/
|
||||
void *pc_createsrc(char *filename)
|
||||
{
|
||||
return fopen(filename,"wt");
|
||||
}
|
||||
|
||||
/* pc_closesrc()
|
||||
* Closes a source file (or include file). The "handle" parameter has the
|
||||
* value that pc_opensrc() returned in an earlier call.
|
||||
*/
|
||||
void pc_closesrc(void *handle)
|
||||
{
|
||||
assert(handle!=NULL);
|
||||
fclose((FILE*)handle);
|
||||
}
|
||||
|
||||
/* pc_resetsrc()
|
||||
* "position" may only hold a pointer that was previously obtained from
|
||||
* pc_getpossrc()
|
||||
*/
|
||||
void pc_resetsrc(void *handle,void *position)
|
||||
{
|
||||
assert(handle!=NULL);
|
||||
fsetpos((FILE*)handle,(fpos_t *)position);
|
||||
}
|
||||
|
||||
/* pc_readsrc()
|
||||
* Reads a single line from the source file (or up to a maximum number of
|
||||
* characters if the line in the input file is too long).
|
||||
*/
|
||||
char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
||||
{
|
||||
return fgets((char*)target,maxchars,(FILE*)handle);
|
||||
}
|
||||
|
||||
/* pc_writesrc()
|
||||
* Writes to to the source file. There is no automatic line ending; to end a
|
||||
* line, write a "\n".
|
||||
*/
|
||||
int pc_writesrc(void *handle,unsigned char *source)
|
||||
{
|
||||
return fputs((char*)source,(FILE*)handle) >= 0;
|
||||
}
|
||||
|
||||
void *pc_getpossrc(void *handle)
|
||||
{
|
||||
static fpos_t lastpos; /* may need to have a LIFO stack of such positions */
|
||||
|
||||
fgetpos((FILE*)handle,&lastpos);
|
||||
return &lastpos;
|
||||
}
|
||||
|
||||
int pc_eofsrc(void *handle)
|
||||
{
|
||||
return feof((FILE*)handle);
|
||||
}
|
||||
|
||||
/* should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
* functions; return NULL for failure
|
||||
*/
|
||||
void *pc_openasm(char *filename)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
return fopen(filename,"w+t");
|
||||
#else
|
||||
return mfcreate(filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pc_closeasm(void *handle, int deletefile)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
if (handle!=NULL)
|
||||
fclose((FILE*)handle);
|
||||
if (deletefile)
|
||||
remove(outfname);
|
||||
#else
|
||||
if (handle!=NULL) {
|
||||
if (!deletefile)
|
||||
mfdump((MEMFILE*)handle);
|
||||
mfclose((MEMFILE*)handle);
|
||||
} /* if */
|
||||
#endif
|
||||
}
|
||||
|
||||
void pc_resetasm(void *handle)
|
||||
{
|
||||
assert(handle!=NULL);
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
fflush((FILE*)handle);
|
||||
fseek((FILE*)handle,0,SEEK_SET);
|
||||
#else
|
||||
mfseek((MEMFILE*)handle,0,SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
int pc_writeasm(void *handle,char *string)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
return fputs(string,(FILE*)handle) >= 0;
|
||||
#else
|
||||
return mfputs((MEMFILE*)handle,string);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *pc_readasm(void *handle, char *string, int maxchars)
|
||||
{
|
||||
#if defined __MSDOS__ || defined SC_LIGHT
|
||||
return fgets(string,maxchars,(FILE*)handle);
|
||||
#else
|
||||
return mfgets((MEMFILE*)handle,string,maxchars);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern memfile_t *bin_file;
|
||||
|
||||
/* Should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
* functions; return NULL for failure.
|
||||
*/
|
||||
void *pc_openbin(char *filename)
|
||||
{
|
||||
return memfile_creat(filename, 1);
|
||||
}
|
||||
|
||||
void pc_closebin(void *handle,int deletefile)
|
||||
{
|
||||
if (deletefile)
|
||||
{
|
||||
memfile_destroy((memfile_t *)handle);
|
||||
bin_file = NULL;
|
||||
} else {
|
||||
bin_file = (memfile_t *)handle;
|
||||
}
|
||||
}
|
||||
|
||||
/* pc_resetbin()
|
||||
* Can seek to any location in the file.
|
||||
* The offset is always from the start of the file.
|
||||
*/
|
||||
void pc_resetbin(void *handle,long offset)
|
||||
{
|
||||
memfile_seek((memfile_t *)handle, offset);
|
||||
}
|
||||
|
||||
int pc_writebin(void *handle,void *buffer,int size)
|
||||
{
|
||||
return memfile_write((memfile_t *)handle, buffer, size);
|
||||
}
|
||||
|
||||
long pc_lengthbin(void *handle)
|
||||
{
|
||||
return memfile_tell((memfile_t *)handle);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <windows.h>
|
||||
#if defined WIN32 || defined _WIN32 || defined __WIN32__
|
||||
# include <winver.h>
|
||||
#else
|
||||
# include <ver.h>
|
||||
#endif
|
||||
#include "svn_version.h"
|
||||
|
||||
AppIcon ICON "pawn.ico"
|
||||
|
||||
/* Version information
|
||||
*
|
||||
* All strings MUST have an explicit \0. See the Windows SDK documentation
|
||||
* for details on version information and the VERSIONINFO structure.
|
||||
*/
|
||||
|
||||
#define VERSIONNAME "smcomp.exe\0"
|
||||
#define VERSIONDESCRIPTION "SourcePawn Compiler\0"
|
||||
#define VERSIONPRODUCTNAME "smcomp\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SVN_FILE_VERSION
|
||||
PRODUCTVERSION SVN_FILE_VERSION
|
||||
FILEFLAGSMASK 0x0000003FL
|
||||
FILEFLAGS 0
|
||||
#if defined(WIN32)
|
||||
FILEOS VOS__WINDOWS32
|
||||
#else
|
||||
FILEOS VOS__WINDOWS16
|
||||
#endif
|
||||
FILETYPE VFT_DLL
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "(C)1998-2006 ITB CompuPhase, AlliedModders LLC\0"
|
||||
VALUE "FileDescription", VERSIONDESCRIPTION
|
||||
VALUE "FileVersion", SVN_FULL_VERSION
|
||||
VALUE "InternalName", VERSIONNAME
|
||||
VALUE "LegalCopyright", "(C)1998-2006 ITB CompuPhase, AlliedModders LLC\0"
|
||||
VALUE "OriginalFilename", VERSIONNAME
|
||||
VALUE "ProductName", VERSIONPRODUCTNAME
|
||||
VALUE "ProductVersion", SVN_FULL_VERSION
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Safe string copying and concatenation
|
||||
* These routines are originally distributed in two separate files. I have
|
||||
* copied the files verbatim in this single source file, including all comments.
|
||||
* The only change is that the second set of include files is commented out
|
||||
* (there is no need to include the same files twice).
|
||||
*/
|
||||
|
||||
#include "lstring.h"
|
||||
|
||||
#if !defined HAVE_SAFESTR
|
||||
|
||||
/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <[email protected]>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
#include <sys/types.h> already included through lstring.h
|
||||
*/
|
||||
#include <string.h> /* for strlen() */
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0) {
|
||||
do {
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <[email protected]>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
#include <sys/types.h> already included
|
||||
#include <string.h> already included
|
||||
*/
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
|
||||
#endif /* #if !defined HAVE_SAFESTR */
|
||||
@@ -0,0 +1,18 @@
|
||||
/* prototypes for strlcpy() and strlcat() */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined __WATCOMC__ && __WATCOMC__ >= 1240
|
||||
/* OpenWatcom introduced BSD "safe string functions" with version 1.4 */
|
||||
#define HAVE_SAFESTR
|
||||
#endif
|
||||
|
||||
#if !defined HAVE_SAFESTR
|
||||
|
||||
size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
size_t
|
||||
strlcat(char *dst, const char *src, size_t siz);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "memfile.h"
|
||||
#include <string.h>
|
||||
#include "osdefs.h"
|
||||
|
||||
memfile_t *memfile_creat(const char *name, size_t init)
|
||||
{
|
||||
memfile_t mf;
|
||||
memfile_t *pmf;
|
||||
|
||||
mf.size = init;
|
||||
mf.base = (char *)malloc(init);
|
||||
mf.usedoffs = 0;
|
||||
if (!mf.base)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mf.offs = 0;
|
||||
mf._static = 0;
|
||||
|
||||
pmf = (memfile_t *)malloc(sizeof(memfile_t));
|
||||
memcpy(pmf, &mf, sizeof(memfile_t));
|
||||
|
||||
pmf->name = strdup(name);
|
||||
|
||||
return pmf;
|
||||
}
|
||||
|
||||
void memfile_destroy(memfile_t *mf)
|
||||
{
|
||||
if (!mf)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mf->_static)
|
||||
{
|
||||
free(mf->name);
|
||||
free(mf->base);
|
||||
free(mf);
|
||||
}
|
||||
}
|
||||
|
||||
void memfile_seek(memfile_t *mf, long seek)
|
||||
{
|
||||
mf->offs = seek;
|
||||
}
|
||||
|
||||
long memfile_tell(memfile_t *mf)
|
||||
{
|
||||
return mf->offs;
|
||||
}
|
||||
|
||||
size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize)
|
||||
{
|
||||
if (!maxsize || mf->offs >= mf->usedoffs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mf->usedoffs - mf->offs < (long)maxsize)
|
||||
{
|
||||
maxsize = mf->usedoffs - mf->offs;
|
||||
if (!maxsize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buffer, mf->base + mf->offs, maxsize);
|
||||
|
||||
mf->offs += maxsize;
|
||||
|
||||
return maxsize;
|
||||
}
|
||||
|
||||
int memfile_write(memfile_t *mf, const void *buffer, size_t size)
|
||||
{
|
||||
if (mf->offs + size > mf->size)
|
||||
{
|
||||
size_t newsize = (mf->size + size) * 2;
|
||||
if (mf->_static)
|
||||
{
|
||||
char *oldbase = mf->base;
|
||||
mf->base = (char *)malloc(newsize);
|
||||
if (!mf->base)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(mf->base, oldbase, mf->size);
|
||||
} else {
|
||||
mf->base = (char *)realloc(mf->base, newsize);
|
||||
if (!mf->base)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
mf->_static = 0;
|
||||
mf->size = newsize;
|
||||
}
|
||||
memcpy(mf->base + mf->offs, buffer, size);
|
||||
mf->offs += size;
|
||||
|
||||
if (mf->offs > mf->usedoffs)
|
||||
{
|
||||
mf->usedoffs = mf->offs;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void memfile_reset(memfile_t *mf)
|
||||
{
|
||||
mf->usedoffs = 0;
|
||||
mf->offs = 0;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef _INCLUDE_MEMFILE_H
|
||||
#define _INCLUDE_MEMFILE_H
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
typedef struct memfile_s
|
||||
{
|
||||
char *name;
|
||||
char *base;
|
||||
long offs;
|
||||
long usedoffs;
|
||||
size_t size;
|
||||
int _static;
|
||||
} memfile_t;
|
||||
|
||||
/**
|
||||
* Creates a new memory file
|
||||
* init is the initial size in bytes
|
||||
*/
|
||||
memfile_t *memfile_creat(const char *name, size_t init);
|
||||
|
||||
/**
|
||||
* Frees the memory associated.
|
||||
*/
|
||||
void memfile_destroy(memfile_t *mf);
|
||||
|
||||
/**
|
||||
* Seeks to a given offset (always from start)
|
||||
*/
|
||||
void memfile_seek(memfile_t *mf, long seek);
|
||||
|
||||
/**
|
||||
* Writes to a memory buffer (expands as necessary).
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int memfile_write(memfile_t *mf, const void *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* Reads a number of bytes from a memory buffer.
|
||||
* Returns the number of bytes read until the end was hit.
|
||||
*/
|
||||
size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize);
|
||||
|
||||
/**
|
||||
* Returns the current position from the start.
|
||||
*/
|
||||
long memfile_tell(memfile_t *mf);
|
||||
|
||||
/**
|
||||
* Resets all the states of the memory buffer.
|
||||
* (does not actually free or zero memory)
|
||||
*/
|
||||
void memfile_reset(memfile_t *mf);
|
||||
|
||||
#endif //_INCLUDE_MEMFILE_H
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spcomp", "spcomp.vcproj", "{B4C844FF-008D-4BD5-B82F-DC06E706C64B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,466 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="spcomp"
|
||||
ProjectGUID="{B4C844FF-008D-4BD5-B82F-DC06E706C64B}"
|
||||
RootNamespace="spcomp"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
InlineFunctionExpansion="0"
|
||||
EnableIntrinsicFunctions="false"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="false"
|
||||
EnableFiberSafeOptimizations="false"
|
||||
AdditionalIncludeDirectories="..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="false"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories="..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\libpawnc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lstring.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\memfile.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\pawncc.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AssemblerOutput="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc1.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
CompileAs="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc2.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
CompileAs="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc3.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc4.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc5.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc6.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc7.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scexpand.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sci18n.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sclist.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scmemfil.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scstate.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sctracker.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scvars.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sp_file.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\amx.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\amxdbg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lstring.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\memfile.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\osdefs.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sctracker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sp_file.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\public\sourcepawn\sp_file_headers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\svn_version.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\libpawnc.rc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc5.scp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc7.scp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\svn_version.tpl"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="zlib"
|
||||
>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\zlib\adler32.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\compress.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\crc32.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\deflate.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\gzio.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\infback.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inffast.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inflate.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inftrees.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\trees.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\uncompr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\zutil.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\zlib\crc32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\deflate.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inffast.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inffixed.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inflate.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\inftrees.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\trees.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\zconf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\zlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zlib\zutil.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,109 @@
|
||||
/* __MSDOS__ set when compiling for DOS (not Windows)
|
||||
* _Windows set when compiling for any version of Microsoft Windows
|
||||
* __WIN32__ set when compiling for Windows95 or WindowsNT (32 bit mode)
|
||||
* __32BIT__ set when compiling in 32-bit "flat" mode (DOS or Windows)
|
||||
*
|
||||
* Copyright 1998-2005, ITB CompuPhase, The Netherlands.
|
||||
* [email protected].
|
||||
*/
|
||||
|
||||
#ifndef _OSDEFS_H
|
||||
#define _OSDEFS_H
|
||||
|
||||
/* Every compiler uses different "default" macros to indicate the mode
|
||||
* it is in. Throughout the source, we use the Borland C++ macros, so
|
||||
* the macros of Watcom C/C++ and Microsoft Visual C/C++ are mapped to
|
||||
* those of Borland C++.
|
||||
*/
|
||||
#if defined(__WATCOMC__)
|
||||
# if defined(__WINDOWS__) || defined(__NT__)
|
||||
# define _Windows 1
|
||||
# endif
|
||||
# ifdef __386__
|
||||
# define __32BIT__ 1
|
||||
# endif
|
||||
# if defined(_Windows) && defined(__32BIT__)
|
||||
# define __WIN32__ 1
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# if defined(_WINDOWS) || defined(_WIN32)
|
||||
# define _Windows 1
|
||||
# endif
|
||||
# ifdef _WIN32
|
||||
# define __WIN32__ 1
|
||||
# define __32BIT__ 1
|
||||
# endif
|
||||
# if _MSC_VER >= 1400
|
||||
# if !defined _CRT_SECURE_NO_DEPRECATE
|
||||
# define _CRT_SECURE_NO_DEPRECATE
|
||||
# endif
|
||||
# define strdup _strdup
|
||||
# define stricmp _stricmp
|
||||
# define access _access
|
||||
# define chdir _chdir
|
||||
# define strdup _strdup
|
||||
# define unlink _unlink
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#elif defined LINUX
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
/* Linux NOW has these */
|
||||
#if !defined BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
#if !defined LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
/* educated guess, BYTE_ORDER is undefined, i386 is common => little endian */
|
||||
#if !defined BYTE_ORDER
|
||||
#if defined UCLINUX
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined __MSDOS__ || defined __WIN32__ || defined _Windows
|
||||
#define DIRSEP_CHAR '\\'
|
||||
#elif defined macintosh
|
||||
#define DIRSEP_CHAR ':'
|
||||
#else
|
||||
#define DIRSEP_CHAR '/' /* directory separator character */
|
||||
#endif
|
||||
|
||||
/* _MAX_PATH is sometimes called differently and it may be in limits.h or
|
||||
* stdlib.h instead of stdio.h.
|
||||
*/
|
||||
#if !defined _MAX_PATH
|
||||
/* not defined, perhaps stdio.h was not included */
|
||||
#if !defined PATH_MAX
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if !defined _MAX_PATH && !defined PATH_MAX
|
||||
/* no _MAX_PATH and no MAX_PATH, perhaps it is in limits.h */
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#if !defined _MAX_PATH && !defined PATH_MAX
|
||||
/* no _MAX_PATH and no MAX_PATH, perhaps it is in stdlib.h */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
/* if _MAX_PATH is undefined, try common alternative names */
|
||||
#if !defined _MAX_PATH
|
||||
#if defined MAX_PATH
|
||||
#define _MAX_PATH MAX_PATH
|
||||
#elif defined _POSIX_PATH_MAX
|
||||
#define _MAX_PATH _POSIX_PATH_MAX
|
||||
#else
|
||||
/* everything failed, actually we have a problem here... */
|
||||
#define _MAX_PATH 1024
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _OSDEFS_H */
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
@@ -0,0 +1,501 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "memfile.h"
|
||||
#include "sp_file.h"
|
||||
#include "amx.h"
|
||||
#include "amxdbg.h"
|
||||
#include "osdefs.h"
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
enum FileSections
|
||||
{
|
||||
FS_Code, /* required */
|
||||
FS_Data, /* required */
|
||||
FS_Publics,
|
||||
FS_Pubvars,
|
||||
FS_Natives,
|
||||
FS_Nametable, /* required */
|
||||
FS_DbgFile,
|
||||
FS_DbgSymbol,
|
||||
FS_DbgLine,
|
||||
FS_DbgTags,
|
||||
FS_DbgAutomaton,
|
||||
FS_DbgState,
|
||||
FS_DbgStrings,
|
||||
FS_DbgInfo,
|
||||
FS_Tags,
|
||||
/* --- */
|
||||
FS_Number,
|
||||
};
|
||||
|
||||
int pc_printf(const char *message,...);
|
||||
int pc_compile(int argc, char **argv);
|
||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf);
|
||||
|
||||
memfile_t *bin_file = NULL;
|
||||
jmp_buf brkout;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if defined _DEBUG
|
||||
getchar();
|
||||
#endif
|
||||
if (pc_compile(argc,argv) == 0)
|
||||
{
|
||||
AMX_HEADER *hdr;
|
||||
AMX_DBG_HDR *dbg = NULL;
|
||||
int err;
|
||||
uint32_t i;
|
||||
sp_file_t *spf;
|
||||
memfile_t *dbgtab = NULL; //dbgcrab
|
||||
unsigned char *dbgptr = NULL;
|
||||
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0};
|
||||
FILE *fp;
|
||||
|
||||
if (bin_file == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr = (AMX_HEADER *)bin_file->base;
|
||||
|
||||
if ((spf=spfw_create(bin_file->name, NULL)) == NULL)
|
||||
{
|
||||
pc_printf("Error creating binary file!\n");
|
||||
memfile_destroy(bin_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err=setjmp(brkout))!=0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
spfw_add_section(spf, ".code");
|
||||
spfw_add_section(spf, ".data");
|
||||
|
||||
sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize;
|
||||
if (sections[FS_Publics])
|
||||
{
|
||||
spfw_add_section(spf, ".publics");
|
||||
}
|
||||
sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize;
|
||||
if (sections[FS_Pubvars])
|
||||
{
|
||||
spfw_add_section(spf, ".pubvars");
|
||||
}
|
||||
sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
if (sections[FS_Natives])
|
||||
{
|
||||
spfw_add_section(spf, ".natives");
|
||||
}
|
||||
sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize;
|
||||
if (sections[FS_Tags])
|
||||
{
|
||||
spfw_add_section(spf, ".tags");
|
||||
}
|
||||
|
||||
spfw_add_section(spf, ".names");
|
||||
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size);
|
||||
if (dbg->magic != AMX_DBG_MAGIC)
|
||||
{
|
||||
pc_printf("Error reading AMX_DBG_HDR, debug data will not be written.");
|
||||
} else {
|
||||
dbgtab = memfile_creat("", 512);
|
||||
dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR);
|
||||
if (dbg->files)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.files");
|
||||
sections[FS_DbgFile] = dbg->files;
|
||||
}
|
||||
if (dbg->lines)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.lines");
|
||||
sections[FS_DbgLine] = dbg->lines;
|
||||
}
|
||||
if (dbg->symbols)
|
||||
{
|
||||
spfw_add_section(spf, ".dbg.symbols");
|
||||
sections[FS_DbgSymbol] = dbg->symbols;
|
||||
}
|
||||
sections[FS_DbgInfo] = 1;
|
||||
sections[FS_DbgStrings] = 1;
|
||||
spfw_add_section(spf, ".dbg.info");
|
||||
spfw_add_section(spf, ".dbg.strings");
|
||||
}
|
||||
}
|
||||
|
||||
spfw_finalize_header(spf);
|
||||
|
||||
/**
|
||||
* Begin writing each of our known tables out
|
||||
*/
|
||||
|
||||
if (sections[FS_Code])
|
||||
{
|
||||
sp_file_code_t cod;
|
||||
unsigned char *cbase;
|
||||
|
||||
cod.cellsize = sizeof(cell);
|
||||
|
||||
cod.codesize = hdr->dat - hdr->cod;
|
||||
cod.codeversion = hdr->amx_version;
|
||||
cod.flags = 0;
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
cod.flags |= SP_FLAG_DEBUG;
|
||||
}
|
||||
cod.code = sizeof(cod);
|
||||
cod.main = hdr->cip;
|
||||
|
||||
/* write the code */
|
||||
cbase = (unsigned char *)hdr + hdr->cod;
|
||||
sfwrite(&cod, sizeof(cod), 1, spf);
|
||||
sfwrite(cbase, cod.codesize, 1, spf);
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Data])
|
||||
{
|
||||
sp_file_data_t dat;
|
||||
unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
|
||||
|
||||
dat.datasize = hdr->hea - hdr->dat;
|
||||
dat.memsize = hdr->stp;
|
||||
dat.data = sizeof(dat);
|
||||
|
||||
/* write header */
|
||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
||||
|
||||
if (dat.datasize)
|
||||
{
|
||||
/* write data */
|
||||
sfwrite(dbase, dat.datasize, 1, spf);
|
||||
}
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Publics])
|
||||
{
|
||||
sp_file_publics_t *pbtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t publics = sections[FS_Publics];
|
||||
|
||||
pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics);
|
||||
stubptr = (unsigned char *)hdr + hdr->publics;
|
||||
|
||||
for (i=0; i<publics; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbtbl[i].address = stub->address;
|
||||
pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (publics)
|
||||
{
|
||||
sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf);
|
||||
}
|
||||
free(pbtbl);
|
||||
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Pubvars])
|
||||
{
|
||||
sp_file_pubvars_t *pbvars;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t pubvars = sections[FS_Pubvars];
|
||||
|
||||
pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars);
|
||||
stubptr = (unsigned char *)hdr + hdr->pubvars;
|
||||
|
||||
for (i=0; i<pubvars; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
pbvars[i].address = stub->address;
|
||||
pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (pubvars)
|
||||
{
|
||||
sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf);
|
||||
}
|
||||
free(pbvars);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Natives])
|
||||
{
|
||||
sp_file_natives_t *nvtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
unsigned char *stubptr;
|
||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
||||
|
||||
nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives);
|
||||
stubptr = (unsigned char *)hdr + hdr->natives;
|
||||
|
||||
for (i=0; i<natives; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
||||
nvtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
|
||||
stubptr += hdr->defsize;
|
||||
}
|
||||
if (natives)
|
||||
{
|
||||
sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf);
|
||||
}
|
||||
free(nvtbl);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Tags])
|
||||
{
|
||||
uint32_t numTags = (uint32_t)sections[FS_Tags];
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
sp_file_tag_t tag;
|
||||
|
||||
for (i=0; i<numTags; i++)
|
||||
{
|
||||
stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (i * hdr->defsize));
|
||||
tag.tag_id = stub->address;
|
||||
tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
||||
sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf);
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_Nametable])
|
||||
{
|
||||
unsigned char *base;
|
||||
uint32_t namelen;
|
||||
|
||||
/* write the entire block */
|
||||
base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t);
|
||||
/**
|
||||
* note - the name table will be padded to sizeof(cell) bytes.
|
||||
* this may clip at most an extra three bytes in!
|
||||
*/
|
||||
namelen = hdr->cod - hdr->nametable;
|
||||
sfwrite(base, namelen, 1, spf);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
sp_fdbg_info_t info;
|
||||
|
||||
memset(&info, 0, sizeof(sp_fdbg_info_t));
|
||||
|
||||
if (sections[FS_DbgFile])
|
||||
{
|
||||
uint32_t idx;
|
||||
sp_fdbg_file_t dbgfile;
|
||||
AMX_DBG_FILE *_ptr;
|
||||
uint32_t len;
|
||||
for (idx=0; idx<sections[FS_DbgFile]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
_ptr = (AMX_DBG_FILE *)dbgptr;
|
||||
len = strlen(_ptr->name);
|
||||
/* store */
|
||||
dbgfile.addr = _ptr->address;
|
||||
dbgfile.name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf);
|
||||
/* write to tab, then move to next */
|
||||
memfile_write(dbgtab, _ptr->name, len + 1);
|
||||
dbgptr += sizeof(AMX_DBG_FILE) + len;
|
||||
info.num_files++;
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgLine])
|
||||
{
|
||||
uint32_t idx;
|
||||
AMX_DBG_LINE *line;
|
||||
sp_fdbg_line_t dbgline;
|
||||
for (idx=0; idx<sections[FS_DbgLine]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
line = (AMX_DBG_LINE *)dbgptr;
|
||||
/* store */
|
||||
dbgline.addr = (uint32_t)line->address;
|
||||
dbgline.line = (uint32_t)line->line;
|
||||
sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_LINE);
|
||||
info.num_lines++;
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (sections[FS_DbgSymbol])
|
||||
{
|
||||
uint32_t idx;
|
||||
uint32_t dnum;
|
||||
AMX_DBG_SYMBOL *sym;
|
||||
AMX_DBG_SYMDIM *dim;
|
||||
sp_fdbg_symbol_t dbgsym;
|
||||
sp_fdbg_arraydim_t dbgdim;
|
||||
uint32_t len;
|
||||
|
||||
for (idx=0; idx<sections[FS_DbgSymbol]; idx++)
|
||||
{
|
||||
/* get entry info */
|
||||
sym = (AMX_DBG_SYMBOL *)dbgptr;
|
||||
/* store */
|
||||
dbgsym.addr = *(int32_t *)&sym->address;
|
||||
dbgsym.tagid = sym->tag;
|
||||
dbgsym.codestart = (uint32_t)sym->codestart;
|
||||
dbgsym.codeend = (uint32_t)sym->codeend;
|
||||
dbgsym.dimcount = (uint16_t)sym->dim;
|
||||
dbgsym.vclass = (uint8_t)sym->vclass;
|
||||
dbgsym.ident = (uint8_t)sym->ident;
|
||||
dbgsym.name = (uint32_t)memfile_tell(dbgtab);
|
||||
sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf);
|
||||
/* write to tab */
|
||||
len = strlen(sym->name);
|
||||
memfile_write(dbgtab, sym->name, len + 1);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_SYMBOL) + len;
|
||||
/* look for any dimensions */
|
||||
info.num_syms++;
|
||||
for (dnum=0; dnum<dbgsym.dimcount; dnum++)
|
||||
{
|
||||
/* get entry info */
|
||||
dim = (AMX_DBG_SYMDIM *)dbgptr;
|
||||
/* store */
|
||||
dbgdim.size = (uint32_t)dim->size;
|
||||
dbgdim.tagid = dim->tag;
|
||||
sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf);
|
||||
/* move to next */
|
||||
dbgptr += sizeof(AMX_DBG_SYMDIM);
|
||||
info.num_arrays++;
|
||||
}
|
||||
}
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf);
|
||||
spfw_next_section(spf);
|
||||
|
||||
if (sections[FS_DbgStrings])
|
||||
{
|
||||
sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf);
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
}
|
||||
|
||||
spfw_finalize_all(spf);
|
||||
|
||||
/**
|
||||
* do compression
|
||||
* new block for scoping only
|
||||
*/
|
||||
{
|
||||
memfile_t *pOrig = (memfile_t *)spf->handle;
|
||||
sp_file_hdr_t *pHdr;
|
||||
unsigned char *proper;
|
||||
size_t size;
|
||||
Bytef *zcmp;
|
||||
uLong disksize;
|
||||
size_t header_size;
|
||||
int err = Z_OK;
|
||||
|
||||
/* reuse this memory block! */
|
||||
memfile_reset(bin_file);
|
||||
|
||||
/* copy tip of header */
|
||||
memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t));
|
||||
|
||||
/* get pointer to header */
|
||||
pHdr = (sp_file_hdr_t *)bin_file->base;
|
||||
|
||||
/* copy the rest of the header */
|
||||
memfile_write(bin_file,
|
||||
(unsigned char *)pOrig->base + sizeof(sp_file_hdr_t),
|
||||
pHdr->dataoffs - sizeof(sp_file_hdr_t));
|
||||
|
||||
header_size = pHdr->dataoffs;
|
||||
size = pHdr->imagesize - header_size;
|
||||
proper = (unsigned char *)pOrig->base + header_size;
|
||||
|
||||
/* get initial size estimate */
|
||||
disksize = compressBound(pHdr->imagesize);
|
||||
pHdr->disksize = (uint32_t)disksize;
|
||||
zcmp = (Bytef *)malloc(pHdr->disksize);
|
||||
|
||||
if ((err=compress2(zcmp,
|
||||
&disksize,
|
||||
(Bytef *)proper,
|
||||
(uLong)size,
|
||||
Z_BEST_COMPRESSION))
|
||||
!= Z_OK)
|
||||
{
|
||||
free(zcmp);
|
||||
pc_printf("Unable to compress (Z): error %d\n", err);
|
||||
pc_printf("Falling back to no compression.");
|
||||
memfile_write(bin_file,
|
||||
proper,
|
||||
size);
|
||||
} else {
|
||||
pHdr->disksize = (uint32_t)disksize + header_size;
|
||||
pHdr->compression = SPFILE_COMPRESSION_GZ;
|
||||
memfile_write(bin_file,
|
||||
(unsigned char *)zcmp,
|
||||
disksize);
|
||||
free(zcmp);
|
||||
}
|
||||
}
|
||||
|
||||
spfw_destroy(spf);
|
||||
memfile_destroy(dbgtab);
|
||||
|
||||
/**
|
||||
* write file
|
||||
*/
|
||||
if ((fp=fopen(bin_file->name, "wb")) != NULL)
|
||||
{
|
||||
fwrite(bin_file->base, bin_file->usedoffs, 1, fp);
|
||||
fclose(fp);
|
||||
} else {
|
||||
pc_printf("Unable to open %s for writing!", bin_file->name);
|
||||
}
|
||||
|
||||
memfile_destroy(bin_file);
|
||||
|
||||
return 0;
|
||||
|
||||
write_error:
|
||||
pc_printf("Error writing to file: %s", bin_file->name);
|
||||
|
||||
spfw_destroy(spf);
|
||||
unlink(bin_file->name);
|
||||
memfile_destroy(bin_file);
|
||||
memfile_destroy(dbgtab);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf)
|
||||
{
|
||||
if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count)
|
||||
{
|
||||
longjmp(brkout, 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,863 @@
|
||||
/* Pawn compiler
|
||||
*
|
||||
* Drafted after the Small-C compiler Version 2.01, originally created
|
||||
* by Ron Cain, july 1980, and enhanced by James E. Hendrix.
|
||||
*
|
||||
* This version comes close to a complete rewrite.
|
||||
*
|
||||
* Copyright R. Cain, 1980
|
||||
* Copyright J.E. Hendrix, 1982, 1983
|
||||
* Copyright ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#ifndef SC_H_INCLUDED
|
||||
#define SC_H_INCLUDED
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#if defined __BORLANDC__ && defined _Windows && !(defined __32BIT__ || defined __WIN32__)
|
||||
/* setjmp() and longjmp() not well supported in 16-bit windows */
|
||||
#include <windows.h>
|
||||
typedef int jmp_buf[9];
|
||||
#define setjmp(b) Catch(b)
|
||||
#define longjmp(b,e) Throw(b,e)
|
||||
#else
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
#include "osdefs.h"
|
||||
#include "amx.h"
|
||||
|
||||
/* Note: the "cell" and "ucell" types are defined in AMX.H */
|
||||
|
||||
#define PUBLIC_CHAR '@' /* character that defines a function "public" */
|
||||
#define CTRL_CHAR '\\' /* default control character */
|
||||
#define sCHARBITS 8 /* size of a packed character */
|
||||
|
||||
#define sDIMEN_MAX 4 /* maximum number of array dimensions */
|
||||
#define sLINEMAX 1023 /* input line length (in characters) */
|
||||
#define sCOMP_STACK 32 /* maximum nesting of #if .. #endif sections */
|
||||
#define sDEF_LITMAX 500 /* initial size of the literal pool, in "cells" */
|
||||
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
|
||||
#define PREPROC_TERM '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
|
||||
#define sDEF_PREFIX "sourcemod.inc" /* default prefix filename */
|
||||
#define sARGS_MAX 32 /* number of arguments a function can have, max */
|
||||
#define sTAGS_MAX 16 /* maximum number of tags on an argument */
|
||||
|
||||
typedef union {
|
||||
void *pv; /* e.g. a name */
|
||||
int i;
|
||||
} stkitem; /* type of items stored on the compiler stack */
|
||||
|
||||
typedef struct s_arginfo { /* function argument info */
|
||||
char name[sNAMEMAX+1];
|
||||
char ident; /* iVARIABLE, iREFERENCE, iREFARRAY or iVARARGS */
|
||||
char usage; /* uCONST */
|
||||
int *tags; /* argument tag id. list */
|
||||
int numtags; /* number of tags in the tag list */
|
||||
int dim[sDIMEN_MAX];
|
||||
int idxtag[sDIMEN_MAX];
|
||||
int numdim; /* number of dimensions */
|
||||
unsigned char hasdefault; /* bit0: is there a default value? bit6: "tagof"; bit7: "sizeof" */
|
||||
union {
|
||||
cell val; /* default value */
|
||||
struct {
|
||||
char *symname; /* name of another symbol */
|
||||
short level; /* indirection level for that symbol */
|
||||
} size; /* used for "sizeof" default value */
|
||||
struct {
|
||||
cell *data; /* values of default array */
|
||||
int size; /* complete length of default array */
|
||||
int arraysize; /* size to reserve on the heap */
|
||||
cell addr; /* address of the default array in the data segment */
|
||||
} array;
|
||||
} defvalue; /* default value, or pointer to default array */
|
||||
int defvalue_tag; /* tag of the default value */
|
||||
} arginfo;
|
||||
|
||||
/* Equate table, tagname table, library table */
|
||||
typedef struct s_constvalue {
|
||||
struct s_constvalue *next;
|
||||
char name[sNAMEMAX+1];
|
||||
cell value;
|
||||
int index; /* index level, for constants referring to array sizes/tags
|
||||
* automaton id. for states and automatons
|
||||
* tag for enumeration lists */
|
||||
} constvalue;
|
||||
|
||||
/* Symbol table format
|
||||
*
|
||||
* The symbol name read from the input file is stored in "name", the
|
||||
* value of "addr" is written to the output file. The address in "addr"
|
||||
* depends on the class of the symbol:
|
||||
* global offset into the data segment
|
||||
* local offset relative to the stack frame
|
||||
* label generated hexadecimal number
|
||||
* function offset into code segment
|
||||
*/
|
||||
typedef struct s_symbol {
|
||||
struct s_symbol *next;
|
||||
struct s_symbol *parent; /* hierarchical types (multi-dimensional arrays) */
|
||||
char name[sNAMEMAX+1];
|
||||
uint32_t hash; /* value derived from name, for quicker searching */
|
||||
cell addr; /* address or offset (or value for constant, index for native function) */
|
||||
cell codeaddr; /* address (in the code segment) where the symbol declaration starts */
|
||||
char vclass; /* sLOCAL if "addr" refers to a local symbol */
|
||||
char ident; /* see below for possible values */
|
||||
short usage; /* see below for possible values */
|
||||
char flags; /* see below for possible values */
|
||||
int compound; /* compound level (braces nesting level) */
|
||||
int tag; /* tagname id */
|
||||
union {
|
||||
int declared; /* label: how many local variables are declared */
|
||||
struct {
|
||||
int index; /* array & enum: tag of array indices or the enum item */
|
||||
int field; /* enumeration fields, where a size is attached to the field */
|
||||
} tags; /* extra tags */
|
||||
constvalue *lib; /* native function: library it is part of */
|
||||
long stacksize; /* normal/public function: stack requirements */
|
||||
} x; /* 'x' for 'extra' */
|
||||
union {
|
||||
arginfo *arglist; /* types of all parameters for functions */
|
||||
constvalue *enumlist;/* list of names for the "root" of an enumeration */
|
||||
struct {
|
||||
cell length; /* arrays: length (size) */
|
||||
cell slength; /* if a string index, this will be set to the original size */
|
||||
short level; /* number of dimensions below this level */
|
||||
} array;
|
||||
} dim; /* for 'dimension', both functions and arrays */
|
||||
constvalue *states; /* list of state function/state variable ids + addresses */
|
||||
int fnumber; /* static global variables: file number in which the declaration is visible */
|
||||
int lnumber; /* line number (in the current source file) for the declaration */
|
||||
struct s_symbol **refer; /* referrer list, functions that "use" this symbol */
|
||||
int numrefers; /* number of entries in the referrer list */
|
||||
char *documentation; /* optional documentation string */
|
||||
} symbol;
|
||||
|
||||
|
||||
/* Possible entries for "ident". These are used in the "symbol", "value"
|
||||
* and arginfo structures. Not every constant is valid for every use.
|
||||
* In an argument list, the list is terminated with a "zero" ident; labels
|
||||
* cannot be passed as function arguments, so the value 0 is overloaded.
|
||||
*/
|
||||
#define iLABEL 0
|
||||
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
||||
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
|
||||
#define iARRAY 3
|
||||
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
||||
#define iARRAYCELL 5 /* array element, cell that must be fetched indirectly */
|
||||
#define iARRAYCHAR 6 /* array element, character from cell from array */
|
||||
#define iEXPRESSION 7 /* expression result, has no address (rvalue) */
|
||||
#define iCONSTEXPR 8 /* constant expression (or constant symbol) */
|
||||
#define iFUNCTN 9
|
||||
#define iREFFUNC 10
|
||||
#define iVARARGS 11 /* function specified ... as argument(s) */
|
||||
|
||||
/* Possible entries for "usage"
|
||||
*
|
||||
* This byte is used as a serie of bits, the syntax is different for
|
||||
* functions and other symbols:
|
||||
*
|
||||
* VARIABLE
|
||||
* bits: 0 (uDEFINE) the variable is defined in the source file
|
||||
* 1 (uREAD) the variable is "read" (accessed) in the source file
|
||||
* 2 (uWRITTEN) the variable is altered (assigned a value)
|
||||
* 3 (uCONST) the variable is constant (may not be assigned to)
|
||||
* 4 (uPUBLIC) the variable is public
|
||||
* 6 (uSTOCK) the variable is discardable (without warning)
|
||||
*
|
||||
* FUNCTION
|
||||
* bits: 0 (uDEFINE) the function is defined ("implemented") in the source file
|
||||
* 1 (uREAD) the function is invoked in the source file
|
||||
* 2 (uRETVALUE) the function returns a value (or should return a value)
|
||||
* 3 (uPROTOTYPED) the function was prototyped (implicitly via a definition or explicitly)
|
||||
* 4 (uPUBLIC) the function is public
|
||||
* 5 (uNATIVE) the function is native
|
||||
* 6 (uSTOCK) the function is discardable (without warning)
|
||||
* 7 (uMISSING) the function is not implemented in this source file
|
||||
* 8 (uFORWARD) the function is explicitly forwardly declared
|
||||
*
|
||||
* CONSTANT
|
||||
* bits: 0 (uDEFINE) the symbol is defined in the source file
|
||||
* 1 (uREAD) the constant is "read" (accessed) in the source file
|
||||
* 2 (uWRITTEN) redundant, but may be set for constants passed by reference
|
||||
* 3 (uPREDEF) the constant is pre-defined and should be kept between passes
|
||||
* 5 (uENUMROOT) the constant is the "root" of an enumeration
|
||||
* 6 (uENUMFIELD) the constant is a field in a named enumeration
|
||||
*/
|
||||
#define uDEFINE 0x001
|
||||
#define uREAD 0x002
|
||||
#define uWRITTEN 0x004
|
||||
#define uRETVALUE 0x004 /* function returns (or should return) a value */
|
||||
#define uCONST 0x008
|
||||
#define uPROTOTYPED 0x008
|
||||
#define uPREDEF 0x008 /* constant is pre-defined */
|
||||
#define uPUBLIC 0x010
|
||||
#define uNATIVE 0x020
|
||||
#define uENUMROOT 0x020
|
||||
#define uSTOCK 0x040
|
||||
#define uENUMFIELD 0x040
|
||||
#define uMISSING 0x080
|
||||
#define uFORWARD 0x100
|
||||
#define uSTRUCT 0x200 /* :TODO: make this an ident */
|
||||
/* uRETNONE is not stored in the "usage" field of a symbol. It is
|
||||
* used during parsing a function, to detect a mix of "return;" and
|
||||
* "return value;" in a few special cases.
|
||||
*/
|
||||
#define uRETNONE 0x10
|
||||
|
||||
#define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */
|
||||
|
||||
#define uCOUNTOF 0x20 /* set in the "hasdefault" field of the arginfo struct */
|
||||
#define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
|
||||
#define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */
|
||||
|
||||
#define uMAINFUNC "main"
|
||||
#define uENTRYFUNC "entry"
|
||||
|
||||
#define sGLOBAL 0 /* global variable/constant class (no states) */
|
||||
#define sLOCAL 1 /* local variable/constant */
|
||||
#define sSTATIC 2 /* global life, local scope */
|
||||
|
||||
#define sSTATEVAR 3 /* criterion to find variables (sSTATEVAR implies a global variable) */
|
||||
|
||||
typedef struct s_value {
|
||||
symbol *sym; /* symbol in symbol table, NULL for (constant) expression */
|
||||
cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
|
||||
* also used for the size of a literal array */
|
||||
int tag; /* tag (of the expression) */
|
||||
int cmptag; /* for searching symbols: choose the one with the matching tag */
|
||||
char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
|
||||
* iEXPRESSION or iREFERENCE */
|
||||
char boolresult; /* boolean result for relational operators */
|
||||
cell *arrayidx; /* last used array indices, for checking self assignment */
|
||||
} value;
|
||||
|
||||
/* "while" statement queue (also used for "for" and "do - while" loops) */
|
||||
enum {
|
||||
wqBRK, /* used to restore stack for "break" */
|
||||
wqCONT, /* used to restore stack for "continue" */
|
||||
wqLOOP, /* loop start label number */
|
||||
wqEXIT, /* loop exit label number (jump if false) */
|
||||
/* --- */
|
||||
wqSIZE /* "while queue" size */
|
||||
};
|
||||
#define wqTABSZ (24*wqSIZE) /* 24 nested loop statements */
|
||||
|
||||
enum {
|
||||
statIDLE, /* not compiling yet */
|
||||
statFIRST, /* first pass */
|
||||
statWRITE, /* writing output */
|
||||
statSKIP, /* skipping output */
|
||||
};
|
||||
|
||||
typedef struct s_stringlist {
|
||||
struct s_stringlist *next;
|
||||
char *line;
|
||||
} stringlist;
|
||||
|
||||
typedef struct s_stringpair {
|
||||
struct s_stringpair *next;
|
||||
char *first;
|
||||
char *second;
|
||||
int matchlength;
|
||||
char flags;
|
||||
char *documentation;
|
||||
} stringpair;
|
||||
|
||||
/* macros for code generation */
|
||||
#define opcodes(n) ((n)*sizeof(cell)) /* opcode size */
|
||||
#define opargs(n) ((n)*sizeof(cell)) /* size of typical argument */
|
||||
|
||||
/* Tokens recognized by lex()
|
||||
* Some of these constants are assigned as well to the variable "lastst" (see SC1.C)
|
||||
*/
|
||||
#define tFIRST 256 /* value of first multi-character operator */
|
||||
#define tMIDDLE 280 /* value of last multi-character operator */
|
||||
#define tLAST 333 /* value of last multi-character match-able token */
|
||||
/* multi-character operators */
|
||||
#define taMULT 256 /* *= */
|
||||
#define taDIV 257 /* /= */
|
||||
#define taMOD 258 /* %= */
|
||||
#define taADD 259 /* += */
|
||||
#define taSUB 260 /* -= */
|
||||
#define taSHL 261 /* <<= */
|
||||
#define taSHRU 262 /* >>>= */
|
||||
#define taSHR 263 /* >>= */
|
||||
#define taAND 264 /* &= */
|
||||
#define taXOR 265 /* ^= */
|
||||
#define taOR 266 /* |= */
|
||||
#define tlOR 267 /* || */
|
||||
#define tlAND 268 /* && */
|
||||
#define tlEQ 269 /* == */
|
||||
#define tlNE 270 /* != */
|
||||
#define tlLE 271 /* <= */
|
||||
#define tlGE 272 /* >= */
|
||||
#define tSHL 273 /* << */
|
||||
#define tSHRU 274 /* >>> */
|
||||
#define tSHR 275 /* >> */
|
||||
#define tINC 276 /* ++ */
|
||||
#define tDEC 277 /* -- */
|
||||
#define tELLIPS 278 /* ... */
|
||||
#define tDBLDOT 279 /* .. */
|
||||
#define tDBLCOLON 280 /* :: */
|
||||
/* reserved words (statements) */
|
||||
#define tASSERT 281
|
||||
#define tBEGIN 282
|
||||
#define tBREAK 283
|
||||
#define tCASE 284
|
||||
#define tCELLSOF 285
|
||||
#define tCHAR 286
|
||||
#define tCONST 287
|
||||
#define tCONTINUE 288
|
||||
#define tDEFAULT 289
|
||||
#define tDEFINED 290
|
||||
#define tDO 291
|
||||
#define tELSE 292
|
||||
#define tEND 293
|
||||
#define tENUM 294
|
||||
#define tEXIT 295
|
||||
#define tFOR 296
|
||||
#define tFORWARD 297
|
||||
#define tFUNCENUM 298
|
||||
#define tFUNCTAG 299
|
||||
#define tGOTO 300
|
||||
#define tIF 301
|
||||
#define tNATIVE 302
|
||||
#define tNEW 303
|
||||
#define tDECL 304
|
||||
#define tOPERATOR 305
|
||||
#define tPUBLIC 306
|
||||
#define tRETURN 307
|
||||
#define tSIZEOF 308
|
||||
#define tSLEEP 309
|
||||
#define tSTATE 310
|
||||
#define tSTATIC 311
|
||||
#define tSTOCK 312
|
||||
#define tSTRUCT 313
|
||||
#define tSWITCH 314
|
||||
#define tTAGOF 315
|
||||
#define tTHEN 316
|
||||
#define tWHILE 317
|
||||
/* compiler directives */
|
||||
#define tpASSERT 318 /* #assert */
|
||||
#define tpDEFINE 319
|
||||
#define tpELSE 320 /* #else */
|
||||
#define tpELSEIF 321 /* #elseif */
|
||||
#define tpEMIT 322
|
||||
#define tpENDIF 323
|
||||
#define tpENDINPUT 324
|
||||
#define tpENDSCRPT 325
|
||||
#define tpERROR 326
|
||||
#define tpFILE 327
|
||||
#define tpIF 328 /* #if */
|
||||
#define tINCLUDE 329
|
||||
#define tpLINE 330
|
||||
#define tpPRAGMA 331
|
||||
#define tpTRYINCLUDE 332
|
||||
#define tpUNDEF 333
|
||||
/* semicolon is a special case, because it can be optional */
|
||||
#define tTERM 334 /* semicolon or newline */
|
||||
#define tENDEXPR 335 /* forced end of expression */
|
||||
/* other recognized tokens */
|
||||
#define tNUMBER 336 /* integer number */
|
||||
#define tRATIONAL 337 /* rational number */
|
||||
#define tSYMBOL 338
|
||||
#define tLABEL 339
|
||||
#define tSTRING 340
|
||||
#define tEXPR 341 /* for assigment to "lastst" only (see SC1.C) */
|
||||
#define tENDLESS 342 /* endless loop, for assigment to "lastst" only */
|
||||
|
||||
/* (reversed) evaluation of staging buffer */
|
||||
#define sSTARTREORDER 0x01
|
||||
#define sENDREORDER 0x02
|
||||
#define sEXPRSTART 0x80 /* top bit set, rest is free */
|
||||
#define sMAXARGS 127 /* relates to the bit pattern of sEXPRSTART */
|
||||
|
||||
#define sDOCSEP 0x01 /* to separate documentation comments between functions */
|
||||
|
||||
/* codes for ffabort() */
|
||||
#define xEXIT 1 /* exit code in PRI */
|
||||
#define xASSERTION 2 /* abort caused by failing assertion */
|
||||
#define xSTACKERROR 3 /* stack/heap overflow */
|
||||
#define xBOUNDSERROR 4 /* array index out of bounds */
|
||||
#define xMEMACCESS 5 /* data access error */
|
||||
#define xINVINSTR 6 /* invalid instruction */
|
||||
#define xSTACKUNDERFLOW 7 /* stack underflow */
|
||||
#define xHEAPUNDERFLOW 8 /* heap underflow */
|
||||
#define xCALLBACKERR 9 /* no, or invalid, callback */
|
||||
#define xSLEEP 12 /* sleep, exit code in PRI, tag in ALT */
|
||||
|
||||
/* Miscellaneous */
|
||||
#if !defined TRUE
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#define sIN_CSEG 1 /* if parsing CODE */
|
||||
#define sIN_DSEG 2 /* if parsing DATA */
|
||||
#define sCHKBOUNDS 1 /* bit position in "debug" variable: check bounds */
|
||||
#define sSYMBOLIC 2 /* bit position in "debug" variable: symbolic info */
|
||||
#define sRESET 0 /* reset error flag */
|
||||
#define sFORCESET 1 /* force error flag on */
|
||||
#define sEXPRMARK 2 /* mark start of expression */
|
||||
#define sEXPRRELEASE 3 /* mark end of expression */
|
||||
#define sSETPOS 4 /* set line number for the error */
|
||||
|
||||
enum {
|
||||
sOPTIMIZE_NONE, /* no optimization */
|
||||
sOPTIMIZE_NOMACRO, /* no macro instructions */
|
||||
sOPTIMIZE_DEFAULT, /* full optimization */
|
||||
/* ----- */
|
||||
sOPTIMIZE_NUMBER
|
||||
};
|
||||
|
||||
typedef enum s_regid {
|
||||
sPRI, /* indicates the primary register */
|
||||
sALT, /* indicates the secundary register */
|
||||
} regid;
|
||||
|
||||
typedef enum s_optmark {
|
||||
sEXPR, /* end of expression (for expressions that form a statement) */
|
||||
sPARM, /* end of parameter (in a function parameter list) */
|
||||
sLDECL, /* start of local declaration (variable) */
|
||||
} optmark;
|
||||
|
||||
#define suSLEEP_INSTR 0x01 /* the "sleep" instruction was used */
|
||||
|
||||
#if INT_MAX<0x8000u
|
||||
#define PUBLICTAG 0x8000u
|
||||
#define FIXEDTAG 0x4000u
|
||||
#define FUNCTAG 0x2000u
|
||||
#else
|
||||
#define PUBLICTAG 0x80000000Lu
|
||||
#define FIXEDTAG 0x40000000Lu
|
||||
#define FUNCTAG 0x20000000Lu
|
||||
#endif
|
||||
#define TAGMASK (~PUBLICTAG)
|
||||
#define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1)
|
||||
|
||||
|
||||
/* interface functions */
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions you call from the "driver" program
|
||||
*/
|
||||
int pc_compile(int argc, char **argv);
|
||||
int pc_addconstant(char *name,cell value,int tag);
|
||||
int pc_addtag(char *name);
|
||||
int pc_addfunctag(char *name);
|
||||
int pc_enablewarning(int number,int enable);
|
||||
|
||||
/*
|
||||
* Functions called from the compiler (to be implemented by you)
|
||||
*/
|
||||
|
||||
/* general console output */
|
||||
int pc_printf(const char *message,...);
|
||||
|
||||
/* error report function */
|
||||
int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr);
|
||||
|
||||
/* input from source file */
|
||||
void *pc_opensrc(char *filename); /* reading only */
|
||||
void *pc_createsrc(char *filename);
|
||||
void pc_closesrc(void *handle); /* never delete */
|
||||
void pc_resetsrc(void *handle,void *position); /* reset to a position marked earlier */
|
||||
char *pc_readsrc(void *handle,unsigned char *target,int maxchars);
|
||||
int pc_writesrc(void *handle,unsigned char *source);
|
||||
void *pc_getpossrc(void *handle); /* mark the current position */
|
||||
int pc_eofsrc(void *handle);
|
||||
|
||||
/* output to intermediate (.ASM) file */
|
||||
void *pc_openasm(char *filename); /* read/write */
|
||||
void pc_closeasm(void *handle,int deletefile);
|
||||
void pc_resetasm(void *handle);
|
||||
int pc_writeasm(void *handle,char *str);
|
||||
char *pc_readasm(void *handle,char *target,int maxchars);
|
||||
|
||||
/* output to binary (.AMX) file */
|
||||
void *pc_openbin(char *filename);
|
||||
void pc_closebin(void *handle,int deletefile);
|
||||
void pc_resetbin(void *handle,long offset);
|
||||
int pc_writebin(void *handle,void *buffer,int size);
|
||||
long pc_lengthbin(void *handle); /* return the length of the file */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* by default, functions and variables used in throughout the compiler
|
||||
* files are "external"
|
||||
*/
|
||||
#if !defined SC_FUNC
|
||||
#define SC_FUNC
|
||||
#endif
|
||||
#if !defined SC_VDECL
|
||||
#define SC_VDECL extern
|
||||
#endif
|
||||
#if !defined SC_VDEFINE
|
||||
#define SC_VDEFINE
|
||||
#endif
|
||||
|
||||
/* function prototypes in SC1.C */
|
||||
SC_FUNC void set_extension(char *filename,char *extension,int force);
|
||||
SC_FUNC symbol *fetchfunc(char *name,int tag);
|
||||
SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag);
|
||||
SC_FUNC char *funcdisplayname(char *dest,char *funcname);
|
||||
SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr);
|
||||
SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
|
||||
SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index);
|
||||
SC_FUNC void delete_consttable(constvalue *table);
|
||||
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
|
||||
SC_FUNC void exporttag(int tag);
|
||||
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
||||
SC_FUNC constvalue *find_tag_byval(int tag);
|
||||
|
||||
/* function prototypes in SC2.C */
|
||||
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
||||
#define PUSHSTK_I(v) { stkitem s_; s_.i=(v); pushstk(s_); }
|
||||
#define POPSTK_P() (popstk().pv)
|
||||
#define POPSTK_I() (popstk().i)
|
||||
SC_FUNC void pushstk(stkitem val);
|
||||
SC_FUNC stkitem popstk(void);
|
||||
SC_FUNC void clearstk(void);
|
||||
SC_FUNC int plungequalifiedfile(char *name); /* explicit path included */
|
||||
SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
|
||||
SC_FUNC void preprocess(void);
|
||||
SC_FUNC void lexinit(void);
|
||||
SC_FUNC int lex(cell *lexvalue,char **lexsym);
|
||||
SC_FUNC void lexpush(void);
|
||||
SC_FUNC void lexclr(int clreol);
|
||||
SC_FUNC int matchtoken(int token);
|
||||
SC_FUNC int tokeninfo(cell *val,char **str);
|
||||
SC_FUNC int needtoken(int token);
|
||||
SC_FUNC void litadd(cell value);
|
||||
SC_FUNC void litinsert(cell value,int pos);
|
||||
SC_FUNC int alphanum(char c);
|
||||
SC_FUNC int ishex(char c);
|
||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym);
|
||||
SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
|
||||
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom);
|
||||
SC_FUNC void markusage(symbol *sym,int usage);
|
||||
SC_FUNC uint32_t namehash(const char *name);
|
||||
SC_FUNC symbol *findglb(const char *name,int filter);
|
||||
SC_FUNC symbol *findloc(const char *name);
|
||||
SC_FUNC symbol *findconst(const char *name,int *matchtag);
|
||||
SC_FUNC symbol *finddepend(const symbol *parent);
|
||||
SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int usage);
|
||||
SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int dim[],int numdim,int idxtag[]);
|
||||
SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
int dim[],int numdim,int idxtag[],int slength);
|
||||
SC_FUNC int getlabel(void);
|
||||
SC_FUNC char *itoh(ucell val);
|
||||
|
||||
/* function prototypes in SC3.C */
|
||||
SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
|
||||
value *lval,int *resulttag);
|
||||
SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
|
||||
SC_FUNC int checktag(int tags[],int numtags,int exprtag);
|
||||
SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval);
|
||||
SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state);
|
||||
SC_FUNC cell array_totalsize(symbol *sym);
|
||||
SC_FUNC int matchtag_string(int ident, int tag);
|
||||
SC_FUNC int checktag_string(value *sym1, value *sym2);
|
||||
SC_FUNC int checktags_string(int tags[], int numtags, value *sym1);
|
||||
|
||||
/* function prototypes in SC4.C */
|
||||
SC_FUNC void writeleader(symbol *root);
|
||||
SC_FUNC void writetrailer(void);
|
||||
SC_FUNC void begcseg(void);
|
||||
SC_FUNC void begdseg(void);
|
||||
SC_FUNC void setline(int chkbounds);
|
||||
SC_FUNC void setfiledirect(char *name);
|
||||
SC_FUNC void setlinedirect(int line);
|
||||
SC_FUNC void setlabel(int index);
|
||||
SC_FUNC void markexpr(optmark type,const char *name,cell offset);
|
||||
SC_FUNC void startfunc(char *fname);
|
||||
SC_FUNC void endfunc(void);
|
||||
SC_FUNC void alignframe(int numbytes);
|
||||
SC_FUNC void rvalue(value *lval);
|
||||
SC_FUNC void address(symbol *ptr,regid reg);
|
||||
SC_FUNC void store(value *lval);
|
||||
SC_FUNC void loadreg(cell address,regid reg);
|
||||
SC_FUNC void storereg(cell address,regid reg);
|
||||
SC_FUNC void memcopy(cell size);
|
||||
SC_FUNC void copyarray(symbol *sym,cell size);
|
||||
SC_FUNC void fillarray(symbol *sym,cell size,cell value);
|
||||
SC_FUNC void ldconst(cell val,regid reg);
|
||||
SC_FUNC void moveto1(void);
|
||||
SC_FUNC void pushreg(regid reg);
|
||||
SC_FUNC void pushval(cell val);
|
||||
SC_FUNC void popreg(regid reg);
|
||||
SC_FUNC void genarray(int dims, int _autozero);
|
||||
SC_FUNC void swap1(void);
|
||||
SC_FUNC void ffswitch(int label);
|
||||
SC_FUNC void ffcase(cell value,char *labelname,int newtable);
|
||||
SC_FUNC void ffcall(symbol *sym,const char *label,int numargs);
|
||||
SC_FUNC void ffret(int remparams);
|
||||
SC_FUNC void ffabort(int reason);
|
||||
SC_FUNC void ffbounds(cell size);
|
||||
SC_FUNC void jumplabel(int number);
|
||||
SC_FUNC void defstorage(void);
|
||||
SC_FUNC void modstk(int delta);
|
||||
SC_FUNC void setstk(cell value);
|
||||
SC_FUNC void modheap(int delta);
|
||||
SC_FUNC void modheap_i();
|
||||
SC_FUNC void setheap_pri(void);
|
||||
SC_FUNC void setheap(cell value);
|
||||
SC_FUNC void cell2addr(void);
|
||||
SC_FUNC void cell2addr_alt(void);
|
||||
SC_FUNC void addr2cell(void);
|
||||
SC_FUNC void char2addr(void);
|
||||
SC_FUNC void charalign(void);
|
||||
SC_FUNC void addconst(cell value);
|
||||
SC_FUNC void setheap_save(cell value);
|
||||
SC_FUNC void stradjust(regid reg);
|
||||
|
||||
/* Code generation functions for arithmetic operators.
|
||||
*
|
||||
* Syntax: o[u|s|b]_name
|
||||
* | | | +--- name of operator
|
||||
* | | +----- underscore
|
||||
* | +--------- "u"nsigned operator, "s"igned operator or "b"oth
|
||||
* +------------- "o"perator
|
||||
*/
|
||||
SC_FUNC void os_mult(void); /* multiplication (signed) */
|
||||
SC_FUNC void os_div(void); /* division (signed) */
|
||||
SC_FUNC void os_mod(void); /* modulus (signed) */
|
||||
SC_FUNC void ob_add(void); /* addition */
|
||||
SC_FUNC void ob_sub(void); /* subtraction */
|
||||
SC_FUNC void ob_sal(void); /* shift left (arithmetic) */
|
||||
SC_FUNC void os_sar(void); /* shift right (arithmetic, signed) */
|
||||
SC_FUNC void ou_sar(void); /* shift right (logical, unsigned) */
|
||||
SC_FUNC void ob_or(void); /* bitwise or */
|
||||
SC_FUNC void ob_xor(void); /* bitwise xor */
|
||||
SC_FUNC void ob_and(void); /* bitwise and */
|
||||
SC_FUNC void ob_eq(void); /* equality */
|
||||
SC_FUNC void ob_ne(void); /* inequality */
|
||||
SC_FUNC void relop_prefix(void);
|
||||
SC_FUNC void relop_suffix(void);
|
||||
SC_FUNC void os_le(void); /* less or equal (signed) */
|
||||
SC_FUNC void os_ge(void); /* greater or equal (signed) */
|
||||
SC_FUNC void os_lt(void); /* less (signed) */
|
||||
SC_FUNC void os_gt(void); /* greater (signed) */
|
||||
|
||||
SC_FUNC void lneg(void);
|
||||
SC_FUNC void neg(void);
|
||||
SC_FUNC void invert(void);
|
||||
SC_FUNC void nooperation(void);
|
||||
SC_FUNC void inc(value *lval);
|
||||
SC_FUNC void dec(value *lval);
|
||||
SC_FUNC void jmp_ne0(int number);
|
||||
SC_FUNC void jmp_eq0(int number);
|
||||
SC_FUNC void outval(cell val,int newline);
|
||||
|
||||
/* function prototypes in SC5.C */
|
||||
SC_FUNC int error(int number,...);
|
||||
SC_FUNC void errorset(int code,int line);
|
||||
|
||||
/* function prototypes in SC6.C */
|
||||
SC_FUNC int assemble(FILE *fout,FILE *fin);
|
||||
|
||||
/* function prototypes in SC7.C */
|
||||
SC_FUNC void stgbuffer_cleanup(void);
|
||||
SC_FUNC void stgmark(char mark);
|
||||
SC_FUNC void stgwrite(const char *st);
|
||||
SC_FUNC void stgout(int index);
|
||||
SC_FUNC void stgdel(int index,cell code_index);
|
||||
SC_FUNC int stgget(int *index,cell *code_index);
|
||||
SC_FUNC void stgset(int onoff);
|
||||
SC_FUNC int phopt_init(void);
|
||||
SC_FUNC int phopt_cleanup(void);
|
||||
|
||||
/* function prototypes in SCLIST.C */
|
||||
SC_FUNC char* duplicatestring(const char* sourcestring);
|
||||
SC_FUNC stringpair *insert_alias(char *name,char *alias);
|
||||
SC_FUNC stringpair *find_alias(char *name);
|
||||
SC_FUNC int lookup_alias(char *target,char *name);
|
||||
SC_FUNC void delete_aliastable(void);
|
||||
SC_FUNC stringlist *insert_path(char *path);
|
||||
SC_FUNC char *get_path(int index);
|
||||
SC_FUNC void delete_pathtable(void);
|
||||
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen);
|
||||
SC_FUNC int get_subst(int index,char **pattern,char **substitution);
|
||||
SC_FUNC stringpair *find_subst(char *name,int length);
|
||||
SC_FUNC int delete_subst(char *name,int length);
|
||||
SC_FUNC void delete_substtable(void);
|
||||
SC_FUNC stringlist *insert_sourcefile(char *string);
|
||||
SC_FUNC char *get_sourcefile(int index);
|
||||
SC_FUNC void delete_sourcefiletable(void);
|
||||
SC_FUNC stringlist *insert_docstring(char *string);
|
||||
SC_FUNC char *get_docstring(int index);
|
||||
SC_FUNC void delete_docstring(int index);
|
||||
SC_FUNC void delete_docstringtable(void);
|
||||
SC_FUNC stringlist *insert_autolist(char *string);
|
||||
SC_FUNC char *get_autolist(int index);
|
||||
SC_FUNC void delete_autolisttable(void);
|
||||
SC_FUNC stringlist *insert_dbgfile(const char *filename);
|
||||
SC_FUNC stringlist *insert_dbgline(int linenr);
|
||||
SC_FUNC stringlist *insert_dbgsymbol(symbol *sym);
|
||||
SC_FUNC char *get_dbgstring(int index);
|
||||
SC_FUNC void delete_dbgstringtable(void);
|
||||
|
||||
/* function prototypes in SCMEMFILE.C */
|
||||
#if !defined tMEMFILE
|
||||
typedef unsigned char MEMFILE;
|
||||
#define tMEMFILE 1
|
||||
#endif
|
||||
MEMFILE *mfcreate(const char *filename);
|
||||
void mfclose(MEMFILE *mf);
|
||||
int mfdump(MEMFILE *mf);
|
||||
long mflength(const MEMFILE *mf);
|
||||
long mfseek(MEMFILE *mf,long offset,int whence);
|
||||
unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size);
|
||||
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size);
|
||||
char *mfgets(MEMFILE *mf,char *string,unsigned int size);
|
||||
int mfputs(MEMFILE *mf,const char *string);
|
||||
|
||||
/* function prototypes in SCI18N.C */
|
||||
#define MAXCODEPAGE 12
|
||||
SC_FUNC int cp_path(const char *root,const char *directory);
|
||||
SC_FUNC int cp_set(const char *name);
|
||||
SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr);
|
||||
SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr);
|
||||
SC_FUNC int scan_utf8(FILE *fp,const char *filename);
|
||||
|
||||
/* function prototypes in SCSTATE.C */
|
||||
SC_FUNC constvalue *automaton_add(const char *name);
|
||||
SC_FUNC constvalue *automaton_find(const char *name);
|
||||
SC_FUNC constvalue *automaton_findid(int id);
|
||||
SC_FUNC constvalue *state_add(const char *name,int fsa_id);
|
||||
SC_FUNC constvalue *state_find(const char *name,int fsa_id);
|
||||
SC_FUNC constvalue *state_findid(int id);
|
||||
SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid);
|
||||
SC_FUNC int state_addlist(int *list,int count,int fsa_id);
|
||||
SC_FUNC void state_deletetable(void);
|
||||
SC_FUNC int state_getfsa(int listid);
|
||||
SC_FUNC int state_count(int listid);
|
||||
SC_FUNC int state_inlist(int listid,int state);
|
||||
SC_FUNC int state_listitem(int listid,int index);
|
||||
SC_FUNC void state_conflict(symbol *root);
|
||||
SC_FUNC int state_conflict_id(int listid1,int listid2);
|
||||
|
||||
/* external variables (defined in scvars.c) */
|
||||
#if !defined SC_SKIP_VDECL
|
||||
SC_VDECL symbol loctab; /* local symbol table */
|
||||
SC_VDECL symbol glbtab; /* global symbol table */
|
||||
SC_VDECL cell *litq; /* the literal queue */
|
||||
SC_VDECL unsigned char pline[]; /* the line read from the input file */
|
||||
SC_VDECL const unsigned char *lptr;/* points to the current position in "pline" */
|
||||
SC_VDECL constvalue tagname_tab;/* tagname table */
|
||||
SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */
|
||||
SC_VDECL constvalue *curlibrary;/* current library */
|
||||
SC_VDECL int pc_addlibtable; /* is the library table added to the AMX file? */
|
||||
SC_VDECL symbol *curfunc; /* pointer to current function */
|
||||
SC_VDECL char *inpfname; /* name of the file currently read from */
|
||||
SC_VDECL char outfname[]; /* intermediate (assembler) file name */
|
||||
SC_VDECL char binfname[]; /* binary file name */
|
||||
SC_VDECL char errfname[]; /* error file name */
|
||||
SC_VDECL char sc_ctrlchar; /* the control character (or escape character) */
|
||||
SC_VDECL char sc_ctrlchar_org;/* the default control character */
|
||||
SC_VDECL int litidx; /* index to literal table */
|
||||
SC_VDECL int litmax; /* current size of the literal table */
|
||||
SC_VDECL int stgidx; /* index to the staging buffer */
|
||||
SC_VDECL int sc_labnum; /* number of (internal) labels */
|
||||
SC_VDECL int staging; /* true if staging output */
|
||||
SC_VDECL cell declared; /* number of local cells declared */
|
||||
SC_VDECL cell glb_declared; /* number of global cells declared */
|
||||
SC_VDECL cell code_idx; /* number of bytes with generated code */
|
||||
SC_VDECL int ntv_funcid; /* incremental number of native function */
|
||||
SC_VDECL int errnum; /* number of errors */
|
||||
SC_VDECL int warnnum; /* number of warnings */
|
||||
SC_VDECL int sc_debug; /* debug/optimization options (bit field) */
|
||||
SC_VDECL int sc_packstr; /* strings are packed by default? */
|
||||
SC_VDECL int sc_asmfile; /* create .ASM file? */
|
||||
SC_VDECL int sc_listing; /* create .LST file? */
|
||||
SC_VDECL int sc_compress; /* compress bytecode? */
|
||||
SC_VDECL int sc_needsemicolon;/* semicolon required to terminate expressions? */
|
||||
SC_VDECL int sc_dataalign; /* data alignment value */
|
||||
SC_VDECL int sc_alignnext; /* must frame of the next function be aligned? */
|
||||
SC_VDECL int pc_docexpr; /* must expression be attached to documentation comment? */
|
||||
SC_VDECL int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||
SC_VDECL cell pc_stksize; /* stack size */
|
||||
SC_VDECL cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */
|
||||
SC_VDECL cell pc_amxram; /* abstract machine data size limit */
|
||||
SC_VDECL int freading; /* is there an input file ready for reading? */
|
||||
SC_VDECL int fline; /* the line number in the current file */
|
||||
SC_VDECL short fnumber; /* number of files in the file table (debugging) */
|
||||
SC_VDECL short fcurrent; /* current file being processed (debugging) */
|
||||
SC_VDECL short sc_intest; /* true if inside a test */
|
||||
SC_VDECL int sideeffect; /* true if an expression causes a side-effect */
|
||||
SC_VDECL int stmtindent; /* current indent of the statement */
|
||||
SC_VDECL int indent_nowarn; /* skip warning "217 loose indentation" */
|
||||
SC_VDECL int sc_tabsize; /* number of spaces that a TAB represents */
|
||||
SC_VDECL short sc_allowtags; /* allow/detect tagnames in lex() */
|
||||
SC_VDECL int sc_status; /* read/write status */
|
||||
SC_VDECL int sc_rationaltag; /* tag for rational numbers */
|
||||
SC_VDECL int rational_digits; /* number of fractional digits */
|
||||
SC_VDECL int sc_allowproccall;/* allow/detect tagnames in lex() */
|
||||
SC_VDECL short sc_is_utf8; /* is this source file in UTF-8 encoding */
|
||||
SC_VDECL char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */
|
||||
SC_VDECL int sc_curstates; /* ID of the current state list */
|
||||
SC_VDECL int pc_optimize; /* (peephole) optimization level */
|
||||
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
|
||||
SC_VDECL int pc_functag; /* global function tag */
|
||||
SC_VDECL int pc_tag_string; /* global string tag */
|
||||
SC_VDECL int pc_anytag; /* global any tag */
|
||||
SC_VDECL int glbstringread; /* last global string read */
|
||||
|
||||
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
|
||||
SC_VDECL constvalue sc_state_tab; /* state table */
|
||||
|
||||
SC_VDECL FILE *inpf; /* file read from (source or include) */
|
||||
SC_VDECL FILE *inpf_org; /* main source file */
|
||||
SC_VDECL FILE *outf; /* file written to */
|
||||
|
||||
SC_VDECL jmp_buf errbuf; /* target of longjmp() on a fatal error */
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
SC_VDECL int sc_makereport; /* generate a cross-reference report */
|
||||
#endif
|
||||
|
||||
#if defined WIN32
|
||||
#if !defined snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* SC_SKIP_VDECL */
|
||||
|
||||
typedef struct array_info_s
|
||||
{
|
||||
const int *dim_list; /* Dimension sizes */
|
||||
int dim_count; /* Number of dimensions */
|
||||
const int *lastdim_list; /* Sizes of last dimensions, if variable */
|
||||
const cell *dim_offs_precalc; /* Cached calculations into the lastdim_list array */
|
||||
cell *data_offs; /* Current offset AFTER the indirection vectors (data) */
|
||||
int *cur_dims; /* Current dimensions the recursion is at */
|
||||
cell *base; /* &litq[startlit] */
|
||||
} array_info_t;
|
||||
|
||||
#endif /* SC_H_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,228 @@
|
||||
/* Pawn compiler - Error message system
|
||||
* In fact a very simple system, using only 'panic mode'.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#if defined __WIN32__ || defined _WIN32 || defined __MSDOS__
|
||||
#include <io.h>
|
||||
#endif
|
||||
#if defined LINUX || defined __GNUC__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h> /* ANSI standardized variable argument list functions */
|
||||
#include <string.h>
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#endif
|
||||
#include "sc.h"
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
|
||||
#endif
|
||||
|
||||
#include "sc5.scp"
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0])
|
||||
static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
|
||||
|
||||
static int errflag;
|
||||
static int errstart; /* line number at which the instruction started */
|
||||
static int errline; /* forced line number for the error message */
|
||||
|
||||
/* error
|
||||
*
|
||||
* Outputs an error message (note: msg is passed optionally).
|
||||
* If an error is found, the variable "errflag" is set and subsequent
|
||||
* errors are ignored until lex() finds a semicolumn or a keyword
|
||||
* (lex() resets "errflag" in that case).
|
||||
*
|
||||
* Global references: inpfname (reffered to only)
|
||||
* fline (reffered to only)
|
||||
* fcurrent (reffered to only)
|
||||
* errflag (altered)
|
||||
*/
|
||||
SC_FUNC int error(int number,...)
|
||||
{
|
||||
static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
static int lastline,errorcount;
|
||||
static short lastfile;
|
||||
char *msg,*pre;
|
||||
va_list argptr;
|
||||
char string[128];
|
||||
|
||||
/* errflag is reset on each semicolon.
|
||||
* In a two-pass compiler, an error should not be reported twice. Therefore
|
||||
* the error reporting is enabled only in the second pass (and only when
|
||||
* actually producing output). Fatal errors may never be ignored.
|
||||
*/
|
||||
if ((errflag || sc_status!=statWRITE) && (number<120 || number>=200))
|
||||
return 0;
|
||||
|
||||
/* also check for disabled warnings */
|
||||
if (number>=200) {
|
||||
int index=(number-200)/8;
|
||||
int mask=1 << ((number-200)%8);
|
||||
if ((warndisable[index] & mask)!=0)
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
if (number<120){
|
||||
msg=errmsg[number-1];
|
||||
pre=prefix[0];
|
||||
errflag=TRUE; /* set errflag (skip rest of erroneous expression) */
|
||||
errnum++;
|
||||
} else if (number<200){
|
||||
msg=fatalmsg[number-120];
|
||||
pre=prefix[1];
|
||||
errnum++; /* a fatal error also counts as an error */
|
||||
} else {
|
||||
msg=warnmsg[number-200];
|
||||
pre=prefix[2];
|
||||
warnnum++;
|
||||
} /* if */
|
||||
|
||||
strexpand(string,(unsigned char *)msg,sizeof string,SCPACK_TABLE);
|
||||
|
||||
assert(errstart<=fline);
|
||||
if (errline>0)
|
||||
errstart=errline;
|
||||
else
|
||||
errline=fline;
|
||||
assert(errstart<=errline);
|
||||
va_start(argptr,number);
|
||||
if (strlen(errfname)==0) {
|
||||
int start= (errstart==errline) ? -1 : errstart;
|
||||
if (pc_error(number,string,inpfname,start,errline,argptr)) {
|
||||
if (outf!=NULL) {
|
||||
pc_closeasm(outf,TRUE);
|
||||
outf=NULL;
|
||||
} /* if */
|
||||
longjmp(errbuf,3); /* user abort */
|
||||
} /* if */
|
||||
} else {
|
||||
FILE *fp=fopen(errfname,"a");
|
||||
if (fp!=NULL) {
|
||||
if (errstart>=0 && errstart!=errline)
|
||||
fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number);
|
||||
else
|
||||
fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number);
|
||||
vfprintf(fp,string,argptr);
|
||||
fclose(fp);
|
||||
} /* if */
|
||||
} /* if */
|
||||
va_end(argptr);
|
||||
|
||||
if (number>=120 && number<200 || errnum>25){
|
||||
if (strlen(errfname)==0) {
|
||||
va_start(argptr,number);
|
||||
pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr);
|
||||
va_end(argptr);
|
||||
} /* if */
|
||||
if (outf!=NULL) {
|
||||
pc_closeasm(outf,TRUE);
|
||||
outf=NULL;
|
||||
} /* if */
|
||||
longjmp(errbuf,2); /* fatal error, quit */
|
||||
} /* if */
|
||||
|
||||
errline=-1;
|
||||
/* check whether we are seeing many errors on the same line */
|
||||
if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
|
||||
errorcount=0;
|
||||
lastline=fline;
|
||||
lastfile=fcurrent;
|
||||
if (number<200)
|
||||
errorcount++;
|
||||
if (errorcount>=3)
|
||||
error(127); /* too many error/warning messages on one line */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SC_FUNC void errorset(int code,int line)
|
||||
{
|
||||
switch (code) {
|
||||
case sRESET:
|
||||
errflag=FALSE; /* start reporting errors */
|
||||
break;
|
||||
case sFORCESET:
|
||||
errflag=TRUE; /* stop reporting errors */
|
||||
break;
|
||||
case sEXPRMARK:
|
||||
errstart=fline; /* save start line number */
|
||||
break;
|
||||
case sEXPRRELEASE:
|
||||
errstart=-1; /* forget start line number */
|
||||
errline=-1;
|
||||
break;
|
||||
case sSETPOS:
|
||||
errline=line;
|
||||
break;
|
||||
} /* switch */
|
||||
}
|
||||
|
||||
/* sc_enablewarning()
|
||||
* Enables or disables a warning (errors cannot be disabled).
|
||||
* Initially all warnings are enabled. The compiler does this by setting bits
|
||||
* for the *disabled* warnings and relying on the array to be zero-initialized.
|
||||
*
|
||||
* Parameter enable can be:
|
||||
* o 0 for disable
|
||||
* o 1 for enable
|
||||
* o 2 for toggle
|
||||
*/
|
||||
int pc_enablewarning(int number,int enable)
|
||||
{
|
||||
int index;
|
||||
unsigned char mask;
|
||||
|
||||
if (number<200)
|
||||
return FALSE; /* errors and fatal errors cannot be disabled */
|
||||
number -= 200;
|
||||
if (number>=NUM_WARNINGS)
|
||||
return FALSE;
|
||||
|
||||
index=number/8;
|
||||
mask=(unsigned char)(1 << (number%8));
|
||||
switch (enable) {
|
||||
case 0:
|
||||
warndisable[index] |= mask;
|
||||
break;
|
||||
case 1:
|
||||
warndisable[index] &= (unsigned char)~mask;
|
||||
break;
|
||||
case 2:
|
||||
warndisable[index] ^= mask;
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#undef SCPACK_TABLE
|
||||
@@ -0,0 +1,360 @@
|
||||
/* Pawn compiler - Error message strings (plain and compressed formats)
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2000-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
|
||||
|
||||
#define SCPACK_TABLE errstr_table
|
||||
/*-*SCPACK start of pair table, do not change or remove this line */
|
||||
unsigned char errstr_table[][2] = {
|
||||
{101,32}, {111,110}, {116,32}, {105,110}, {97,114}, {115,32}, {116,105}, {100,32}, {101,114}, {37,115}, {101,110}, {134,129}, {34,137}, {140,34}, {97,108}, {117,110},
|
||||
{114,101}, {110,111}, {97,116}, {115,105}, {121,32}, {97,110}, {111,114}, {109,98}, {115,116}, {32,141}, {100,101}, {41,10}, {109,138}, {145,130}, {101,135}, {139,32},
|
||||
{98,108}, {111,108}, {114,97}, {143,99}, {118,142}, {102,163}, {115,121}, {166,151}, {167,161}, {97,32}, {117,115}, {103,32}, {115,147}, {132,162}, {97,160}, {136,32},
|
||||
{150,32}, {99,104}, {103,117}, {105,135}, {178,156}, {164,179}, {132,180}, {111,102}, {116,104}, {101,120}, {165,159}, {131,181}, {101,100}, {101,133}, {105,133}, {168,153},
|
||||
{154,102}, {118,132}, {183,32}, {105,174}, {193,195}, {116,111}, {173,148}, {109,97}, {99,129}, {101,10}, {115,10}, {112,144}, {116,97}, {182,130}, {98,128}, {152,146},
|
||||
{44,32}, {132,97}, {192,131}, {170,130}, {153,10}, {109,146}, {191,155}, {109,211}, {40,214}, {104,97}, {196,128}, {34,32}, {129,32}, {142,32}, {105,99}, {117,108},
|
||||
{99,111}, {147,122}, {110,32}, {100,105}, {101,108}, {108,111}, {111,112}, {116,136}, {200,152}, {131,32}, {149,32}, {131,171}, {213,177}, {58,212}, {109,101}, {102,105},
|
||||
{100,111}, {97,115}, {108,128}, {118,128}, {230,136}, {232,149}, {204,171}, {203,172}, {215,206}, {119,105}, {109,112}, {110,117}, {185,247}, {165,139}, {251,151}
|
||||
};
|
||||
/*-*SCPACK end of pair table, do not change or remove this line */
|
||||
|
||||
static char *errmsg[] = {
|
||||
#ifdef SCPACK
|
||||
/*001*/ "expected token: \"%s\", but found \"%s\"\n",
|
||||
/*002*/ "only a single statement (or expression) can follow each \"case\"\n",
|
||||
/*003*/ "declaration of a local variable must appear in a compound block\n",
|
||||
/*004*/ "function \"%s\" is not implemented\n",
|
||||
/*005*/ "function may not have arguments\n",
|
||||
/*006*/ "must be assigned to an array\n",
|
||||
/*007*/ "operator cannot be redefined\n",
|
||||
/*008*/ "must be a constant expression; assumed zero\n",
|
||||
/*009*/ "invalid array size (negative, zero or out of bounds)\n",
|
||||
/*010*/ "invalid function or declaration\n",
|
||||
/*011*/ "invalid outside functions\n",
|
||||
/*012*/ "invalid function call, not a valid address\n",
|
||||
/*013*/ "no entry point (no public functions)\n",
|
||||
/*014*/ "invalid statement; not in switch\n",
|
||||
/*015*/ "\"default\" case must be the last case in switch statement\n",
|
||||
/*016*/ "multiple defaults in \"switch\"\n",
|
||||
/*017*/ "undefined symbol \"%s\"\n",
|
||||
/*018*/ "initialization data exceeds declared size\n",
|
||||
/*019*/ "not a label: \"%s\"\n",
|
||||
/*020*/ "invalid symbol name \"%s\"\n",
|
||||
/*021*/ "symbol already defined: \"%s\"\n",
|
||||
/*022*/ "must be lvalue (non-constant)\n",
|
||||
/*023*/ "array assignment must be simple assignment\n",
|
||||
/*024*/ "\"break\" or \"continue\" is out of context\n",
|
||||
/*025*/ "function heading differs from prototype\n",
|
||||
/*026*/ "no matching \"#if...\"\n",
|
||||
/*027*/ "invalid character constant\n",
|
||||
/*028*/ "invalid subscript (not an array or too many subscripts): \"%s\"\n",
|
||||
/*029*/ "invalid expression, assumed zero\n",
|
||||
/*030*/ "compound statement not closed at the end of file (started at line %d)\n",
|
||||
/*031*/ "unknown directive\n",
|
||||
/*032*/ "array index out of bounds (variable \"%s\")\n",
|
||||
/*033*/ "array must be indexed (variable \"%s\")\n",
|
||||
/*034*/ "argument does not have a default value (argument %d)\n",
|
||||
/*035*/ "argument type mismatch (argument %d)\n",
|
||||
/*036*/ "empty statement\n",
|
||||
/*037*/ "invalid string (possibly non-terminated string)\n",
|
||||
/*038*/ "extra characters on line\n",
|
||||
/*039*/ "constant symbol has no size\n",
|
||||
/*040*/ "duplicate \"case\" label (value %d)\n",
|
||||
/*041*/ "invalid ellipsis, array size is not known\n",
|
||||
/*042*/ "invalid combination of class specifiers\n",
|
||||
/*043*/ "character constant exceeds range for packed string\n",
|
||||
/*044*/ "positional parameters must precede all named parameters\n",
|
||||
/*045*/ "too many function arguments\n",
|
||||
/*046*/ "unknown array size (variable \"%s\")\n",
|
||||
/*047*/ "array sizes do not match, or destination array is too small\n",
|
||||
/*048*/ "array (s do not match\n",
|
||||
/*049*/ "invalid line continuation\n",
|
||||
/*050*/ "invalid range\n",
|
||||
/*051*/ "invalid subscript, use \"[ ]\" operators on major dimensions\n",
|
||||
/*052*/ "multi-dimensional arrays must be fully initialized\n",
|
||||
/*053*/ "exceeding maximum number of dimensions\n",
|
||||
/*054*/ "unmatched closing brace (\"}\")\n",
|
||||
/*055*/ "start of function body without function header\n",
|
||||
/*056*/ "arrays, local variables and function arguments cannot be public (variable \"%s\")\n",
|
||||
/*057*/ "unfinished expression before compiler directive\n",
|
||||
/*058*/ "duplicate argument; same argument is passed twice\n",
|
||||
/*059*/ "function argument may not have a default value (variable \"%s\")\n",
|
||||
/*060*/ "multiple \"#else\" directives between \"#if ... #endif\"\n",
|
||||
/*061*/ "\"#elseif\" directive follows an \"#else\" directive\n",
|
||||
/*062*/ "number of operands does not fit the operator\n",
|
||||
/*063*/ "function result tag of operator \"%s\" must be \"%s\"\n",
|
||||
/*064*/ "cannot change predefined operators\n",
|
||||
/*065*/ "function argument may only have a single tag (argument %d)\n",
|
||||
/*066*/ "function argument may not be a reference argument or an array (argument \"%s\")\n",
|
||||
/*067*/ "variable cannot be both a reference and an array (variable \"%s\")\n",
|
||||
/*068*/ "invalid rational number precision in #pragma\n",
|
||||
/*069*/ "rational number format already defined\n",
|
||||
/*070*/ "rational number support was not enabled\n",
|
||||
/*071*/ "user-defined operator must be declared before use (function \"%s\")\n",
|
||||
/*072*/ "\"sizeof\" operator is invalid on \"function\" symbols\n",
|
||||
/*073*/ "function argument must be an array (argument \"%s\")\n",
|
||||
/*074*/ "#define pattern must start with an alphabetic character\n",
|
||||
/*075*/ "input line too long (after substitutions)\n",
|
||||
/*076*/ "syntax error in the expression, or invalid function call\n",
|
||||
/*077*/ "malformed UTF-8 encoding, or corrupted file: %s\n",
|
||||
/*078*/ "function uses both \"return\" and \"return <value>\"\n",
|
||||
/*079*/ "inconsistent return types (array & non-array)\n",
|
||||
/*080*/ "unknown symbol, or not a constant symbol (symbol \"%s\")\n",
|
||||
/*081*/ "cannot take a tag as a default value for an indexed array parameter (symbol \"%s\")\n",
|
||||
/*082*/ "user-defined operators and native functions may not have states\n",
|
||||
/*083*/ "a function or variable may only belong to a single automaton (symbol \"%s\")\n",
|
||||
/*084*/ "state conflict: one of the states is already assigned to another implementation (symbol \"%s\")\n",
|
||||
/*085*/ "no states are defined for symbol \"%s\"\n",
|
||||
/*086*/ "unknown automaton \"%s\"\n",
|
||||
/*087*/ "unknown state \"%s\" for automaton \"%s\"\n",
|
||||
/*088*/ "public variables and local variables may not have states (symbol \"%s\")\n",
|
||||
/*089*/ "state variables may not be initialized (symbol \"%s\")\n",
|
||||
/*090*/ "public functions may not return arrays (symbol \"%s\")\n",
|
||||
/*091*/ "ambiguous constant; tag override is required (symbol \"%s\")\n",
|
||||
/*092*/ "number of arguments does not match definition\n",
|
||||
/*093*/ "expected tag name identifier\n",
|
||||
/*094*/ "function enumeration requires unique tag\n",
|
||||
/*095*/ "cannot have required parameters after optional parameters\n",
|
||||
/*096*/ "could not find member \"%s\" in struct \"%s\"\n",
|
||||
/*097*/ "symbol \"%s\" does not have a matching type\n",
|
||||
/*098*/ "struct requires unique struct name\n",
|
||||
/*099*/ "member \"%s\" appears more than once in struct \"%s\"\n",
|
||||
/*100*/ "function prototypes do not match\n"
|
||||
#else
|
||||
"\271pect\236\305k\212:\231\320bu\202fo\217\207\215\012",
|
||||
"\201l\224\251s\203g\362\317e\234\202(\260\374\201) c\352f\241\345w ea\261 \042c\361e\042\012",
|
||||
"\232cl\321\237\302\251\345c\335\332\327appe\204 \351\251\340\372o\217\207\240ock\012",
|
||||
"\375\231 \276\235i\372le\234t\274\012",
|
||||
"\272\307\224\235\331\363\266t\312",
|
||||
"\370a\254gn\236\305 \352\255y\012",
|
||||
"\364\222\260c\225\235\316\220\322\274\012",
|
||||
"\370\251\365\202\374\201; \361sum\236z\210o\012",
|
||||
"\273\306\341\200(nega\206ve\320z\210o \260ou\202\302bo\217ds\233",
|
||||
"\273\272\260\232cl\321\213\012",
|
||||
"\273out\223d\200\375\312",
|
||||
"\273\272c\216l\320\235\251\265add\220s\312",
|
||||
"\221 \212tr\224po\203\202(\221 pu\240\336 \375s\233",
|
||||
"\273\317e\234t; \235\351s\371t\261\012",
|
||||
"\042\300a\337t\333c\361\200\370\270\200l\361\202c\361\200\351s\371t\261 \317e\234t\012",
|
||||
"m\337\206p\362\300a\337t\205\351\042s\371t\261\042\012",
|
||||
"\217\322\236\277\012",
|
||||
"\203i\206\216iza\237d\222\251\271ce\274\205\232cl\204\236\341\311",
|
||||
"\235\251lab\344\355",
|
||||
"\273\250 nam\200\215\012",
|
||||
"\250 \216\220ad\224\322\274\355",
|
||||
"\370l\244u\200(n\201-\365t\233",
|
||||
"\306a\254gn\234\202\370\223\372\362a\254gn\234t\012",
|
||||
"\042b\220ak\333\260\042\310t\203ue\333\276ou\202\302\310t\271t\012",
|
||||
"\272head\353\343ff\210\205from pro\305typ\311",
|
||||
"\221 \354\353\042#if...\042\012",
|
||||
"\273\261\321ct\257\365t\012",
|
||||
"\273subscrip\202(\235\352\306\260\305o m\225\224subscripts)\355",
|
||||
"\273\374\201\320\361sum\236z\210o\012",
|
||||
"\340\372o\217\207\317e\234\202\235c\345s\236a\202\270\200\212\207\302\357\362(\230\204t\236a\202l\203\200%d\233",
|
||||
"\217k\221w\342\343\220c\206v\311",
|
||||
"\306\203\232x ou\202\302bo\217d\205(\332\215\233",
|
||||
"\306\370\203\232x\236(\332\215\233",
|
||||
"\315\360\275\235\331\363\251\300a\337\202\244u\200(\315%d\233",
|
||||
"\315typ\200mis\354 (\315%d\233",
|
||||
"e\372t\224\317e\234t\012",
|
||||
"\273\230r\353(po\254\240\224n\201-\347m\203\222\236\230r\203g\233",
|
||||
"\271t\242 \261\321c\347\205\334l\203\311",
|
||||
"\365\202\250 \331\205\221 \341\311",
|
||||
"dupl\336\222\200\042c\361e\333lab\344 (\244u\200%d\233",
|
||||
"\273\344lip\223s\320\306\341\200\276\235k\221wn\012",
|
||||
"\273\340\227\203a\237\302cl\361\205speci\357\210\312",
|
||||
"\261\321ct\257\365\202\271ce\274\205r\225g\200f\260pack\236\230r\203g\012",
|
||||
"po\223\213\335p\321\356\347\205\327\313c\274\200\216l nam\236p\321\356\347\312",
|
||||
"\305o m\225\224\272\266t\312",
|
||||
"\217k\221w\342\306\341\200(\332\215\233",
|
||||
"\306\341\275\360 \235\354\320\260\232\230\203a\237\306\276\305o sm\216l\012",
|
||||
"\306(\205\360 \235\354\012",
|
||||
"\273l\203\200\310t\203ua\213\012",
|
||||
"\273r\225g\311",
|
||||
"\273subscript\320\252\200\042[ ]\333\364\222\226\205\334\307j\260\343\234\223\201\312",
|
||||
"m\337\206-\343\234\223\201\335\255y\205\370f\337l\224\203i\206\216iz\274\012",
|
||||
"\271ce\274\353\307ximum \376\257\302\343\234\223\201\312",
|
||||
"\217\354\236c\345s\353b\242c\200(\042}\042\233",
|
||||
"\230\204\202\302\272bod\224\371\270ou\202\272head\210\012",
|
||||
"\255ys\320\345c\335\304\275\225\207\272\266t\205c\225\235\316pu\240\336 (\332\215\233",
|
||||
"\217f\203ish\236\374\334bef\226\200\340\372il\257\343\220c\206v\311",
|
||||
"dupl\336\222\200\266t; sam\200\315\276p\361s\236tw\336\311",
|
||||
"\272\315\307\224\235\331\363\251\300a\337\202\244u\200(\332\215\233",
|
||||
"m\337\206p\362\042#\344se\333\343\220c\206v\275betwe\212 \042#if ... #\212\343f\042\012",
|
||||
"\042#\344seif\333\343\220c\206\363f\241\345w\205\352\042#\344se\333\343\220c\206v\311",
|
||||
"\376\257\302\364\225d\205\360\275\235\357\202\270\200\364\222\226\012",
|
||||
"\272\220s\337\202\366\302\364\222\226\231 \370\215\012",
|
||||
"c\225\235\261\225g\200\313\322\236\364\222\226\312",
|
||||
"\272\315\307\224\201l\224\331\363\251s\203g\362\366(\315%d\233",
|
||||
"\272\315\307\224\235\316\251\220f\210\212c\200\315\260\352\306(\315\215\233",
|
||||
"\332c\225\235\316bo\270 \251\220f\210\212c\200\225\207\352\306(\332\215\233",
|
||||
"\273\242\213\335\376\257\313ci\223\334\351#p\242g\307\012",
|
||||
"\242\213\335\376\257f\226\307\202\216\220ad\224\322\274\012",
|
||||
"\242\213\335\376\257supp\226\202wa\205\235\212\256\274\012",
|
||||
"\252\210-\322\236\364\222\260\370\232cl\204\236bef\226\200\252\200(\375\231\233",
|
||||
"\042\341e\267\333\364\222\260\276\273\334\042\375\333\250\312",
|
||||
"\272\315\370\352\306(\315\215\233",
|
||||
"#\322\200p\222\347\342\327\230\204\202\371\270 \352\216p\331be\206c \261\321c\347\012",
|
||||
"\203pu\202l\203\200\305o l\201\253(aft\257subs\206tu\213s\233",
|
||||
"\246n\314x \210r\260\351\270\200\374\201\320\260\273\272c\216l\012",
|
||||
"m\216f\226m\236UTF-8 \212\340d\203g\320\260c\226rupt\236\357le: \211\012",
|
||||
"\272\252\275bo\270 \042\220turn\333\225\207\042\220tur\342<\244ue>\042\012",
|
||||
"\203\310\223\230\212\202\220tur\342typ\275(\306& n\201-\255y\233",
|
||||
"\217k\221w\342\250\320\260\235\251\365\202\250 \330",
|
||||
"c\225\235\314k\200\251\366a\205\251\300a\337\202\244u\200f\260\352\203\232x\236\306p\321\356t\257\330",
|
||||
"\252\210-\322\236\364\222\226\205\225\207na\206\363\375\205\307\224\235\331\363\317e\312",
|
||||
"\251\272\260\332\307\224\201l\224b\344\201\253\305 \251s\203g\362au\305\325\334\330",
|
||||
"\317\200\310fl\336t: \201\200\302\270\200\317\275\276\216\220ad\224a\254gn\236\305 a\221\270\257i\372le\234\314\237\330",
|
||||
"\221 \317\275\204\200\322\236f\260\277\012",
|
||||
"\217k\221w\342au\305\325\201\324",
|
||||
"\217k\221w\342\317\200\215 f\260au\305\325\201\324",
|
||||
"pu\240\336 \304\275\225\207\345c\335\304\275\307\224\235\331\363\317\275\330",
|
||||
"\317\200\304\275\307\224\235\316\203i\206\216iz\236\330",
|
||||
"pu\240\336 \375\205\307\224\235\220tur\342\255y\205\330",
|
||||
"a\227i\262ou\205\365t; \366ov\210rid\200\276\220qui\220\207\330",
|
||||
"\376\257\302\266t\205\360\275\235\354 \322i\213\012",
|
||||
"\271pect\236\366nam\200id\212\206\357\210\012",
|
||||
"\272\212um\210a\237\220qui\220\205\217iqu\200\314g\012",
|
||||
"c\225\235\331\363\220qui\220\207p\321\356\347\205aft\257\346\213\335p\321\356\347\312",
|
||||
"\340\337\207\235f\203\207\356\227\210\231 \351\230ruc\202\215\012",
|
||||
"\277 \360\275\235\331\363\251\354\353typ\311",
|
||||
"\230ruc\202\220qui\220\205\217iqu\200\230ruc\202nam\311",
|
||||
"\356\227\210\231 appe\204\205m\226\200\270\352\201c\200\351\230ruc\202\215\012",
|
||||
"\272pro\305typ\275\360 \235\354\012"
|
||||
#endif
|
||||
};
|
||||
|
||||
static char *fatalmsg[] = {
|
||||
#ifdef SCPACK
|
||||
/*120*/ "cannot read from file: \"%s\"\n",
|
||||
/*121*/ "cannot write to file: \"%s\"\n",
|
||||
/*122*/ "table overflow: \"%s\"\n",
|
||||
/* table can be: loop table
|
||||
* literal table
|
||||
* staging buffer
|
||||
* option table (response file)
|
||||
* peephole optimizer table
|
||||
*/
|
||||
/*123*/ "insufficient memory\n",
|
||||
/*124*/ "invalid assembler instruction \"%s\"\n",
|
||||
/*125*/ "numeric overflow, exceeding capacity\n",
|
||||
/*126*/ "compiled script exceeds the maximum memory size (%ld bytes)\n",
|
||||
/*127*/ "too many error messages on one line\n",
|
||||
/*128*/ "codepage mapping file not found\n",
|
||||
/*129*/ "invalid path: \"%s\"\n",
|
||||
/*130*/ "assertion failed: %s\n",
|
||||
/*131*/ "user error: %s\n",
|
||||
#else
|
||||
"c\225\235\220a\207from \357le\355",
|
||||
"c\225\235writ\200\305 \357le\355",
|
||||
"t\256\200ov\210f\345w\355",
|
||||
"\203suff\336i\212\202\356m\226y\012",
|
||||
"\273\361se\227l\257\203\230ruc\213\324",
|
||||
"\373m\210\336 ov\210f\345w\320\271ce\274\353capacity\012",
|
||||
"\340\372il\236scrip\202\271ce\274\205\270\200\307ximum \356m\226\224\341\200(%l\207bytes\233",
|
||||
"\305o m\225\224\210r\260\356ssag\275\334\201\200l\203\311",
|
||||
"\340\232pag\200\307pp\353\357\362\235fo\217d\012",
|
||||
"\273p\222h\355",
|
||||
"\361s\210\237fail\274: \211\012",
|
||||
"\252\257\210r\226: \211\012"
|
||||
#endif
|
||||
};
|
||||
|
||||
static char *warnmsg[] = {
|
||||
#ifdef SCPACK
|
||||
/*200*/ "symbol \"%s\" is truncated to %d characters\n",
|
||||
/*201*/ "redefinition of constant/macro (symbol \"%s\")\n",
|
||||
/*202*/ "number of arguments does not match definition\n",
|
||||
/*203*/ "symbol is never used: \"%s\"\n",
|
||||
/*204*/ "symbol is assigned a value that is never used: \"%s\"\n",
|
||||
/*205*/ "redundant code: constant expression is zero\n",
|
||||
/*206*/ "redundant test: constant expression is non-zero\n",
|
||||
/*207*/ "unknown #pragma\n",
|
||||
/*208*/ "function with tag result used before definition, forcing reparse\n",
|
||||
/*209*/ "function \"%s\" should return a value\n",
|
||||
/*210*/ "possible use of symbol before initialization: \"%s\"\n",
|
||||
/*211*/ "possibly unintended assignment\n",
|
||||
/*212*/ "possibly unintended bitwise operation\n",
|
||||
/*213*/ "tag mismatch\n",
|
||||
/*214*/ "possibly a \"const\" array argument was intended: \"%s\"\n",
|
||||
/*215*/ "expression has no effect\n",
|
||||
/*216*/ "nested comment\n",
|
||||
/*217*/ "loose indentation\n",
|
||||
/*218*/ "old style prototypes used with optional semicolumns\n",
|
||||
/*219*/ "local variable \"%s\" shadows a variable at a preceding level\n",
|
||||
/*220*/ "expression with tag override must appear between parentheses\n",
|
||||
/*221*/ "label name \"%s\" shadows tag name\n",
|
||||
/*222*/ "number of digits exceeds rational number precision\n",
|
||||
/*223*/ "redundant \"sizeof\": argument size is always 1 (symbol \"%s\")\n",
|
||||
/*224*/ "indeterminate array size in \"sizeof\" expression (symbol \"%s\")\n",
|
||||
/*225*/ "unreachable code\n",
|
||||
/*226*/ "a variable is assigned to itself (symbol \"%s\")\n",
|
||||
/*227*/ "more initializers than enum fields\n",
|
||||
/*228*/ "length of initializer exceeds size of the enum field\n",
|
||||
/*229*/ "index tag mismatch (symbol \"%s\")\n",
|
||||
/*230*/ "no implementation for state \"%s\" in function \"%s\", no fall-back\n",
|
||||
/*231*/ "state specification on forward declaration is ignored\n",
|
||||
/*232*/ "output file is written, but with compact encoding disabled\n",
|
||||
/*233*/ "state variable \"%s\" shadows a global variable\n",
|
||||
/*234*/ "symbol \"%s\" is marked as deprecated: %s\n",
|
||||
/*235*/ "public function lacks forward declaration (symbol \"%s\")\n",
|
||||
/*236*/ "unknown parameter in substitution (incorrect #define pattern)\n"
|
||||
#else
|
||||
"\277 \276tr\243\222\236\305 %\207\261\321c\347\312",
|
||||
"\220\322i\237\302\365t/\307cro \330",
|
||||
"\376\257\302\266t\205\360\275\235\354 \322i\213\012",
|
||||
"\250 \276nev\257\252\274\355",
|
||||
"\250 \276a\254gn\236\251\244u\200\270a\202\276nev\257\252\274\355",
|
||||
"\220d\217d\225\202\340\232: \365\202\374\334\276z\210o\012",
|
||||
"\220d\217d\225\202te\230: \365\202\374\334\276n\201-z\210o\012",
|
||||
"\217k\221w\342#p\242g\307\012",
|
||||
"\272\371\270 \366\220s\337\202\252\236bef\226\200\322i\213\320f\226c\353\220p\204s\311",
|
||||
"\375\231 sho\337\207\220tur\342\251\244u\311",
|
||||
"po\254\240\200\252\200\302\250 bef\226\200\203i\206\216iza\213\355",
|
||||
"po\254\240\224\217\203t\212\232\207a\254gn\234t\012",
|
||||
"po\254\240\224\217\203t\212\232\207bit\371s\200\364a\213\012",
|
||||
"\366mis\354\012",
|
||||
"po\254\240\224\251\042\350\333\306\315wa\205\203t\212\232d\355",
|
||||
"\374\334\331\205\221 effect\012",
|
||||
"ne\230\236\340m\234t\012",
|
||||
"\345os\200\203d\212\314\213\012",
|
||||
"\241\207\230y\362pro\305typ\275\252\236\371\270 \346\213\335sem\336\241umn\312",
|
||||
"\345c\335\332\215 s\331\360w\205\251\332a\202\251\313c\274\353lev\344\012",
|
||||
"\374\334\371\270 \366ov\210rid\200\327appe\204 betwe\212 p\204\212\270ese\312",
|
||||
"lab\344 nam\200\215 s\331\360w\205\366nam\311",
|
||||
"\376\257\302\343git\205\271ce\274\205\242\213\335\376\257\313ci\223\201\012",
|
||||
"\220d\217d\225\202\042\341e\267\042: \315\341\200\276\216way\2051 \330",
|
||||
"\203\232\347m\203\222\200\306\341\200\351\042\341e\267\333\374\334\330",
|
||||
"\217\220a\261\256\200\340\232\012",
|
||||
"\251\332\276a\254gn\236\305 its\344f \330",
|
||||
"m\226\200\203i\206\216iz\210\205\270\352\212um \357\344d\312",
|
||||
"l\212g\270 \302\203i\206\216iz\257\271ce\274\205\341\200\302\270\200\212um \357\344d\012",
|
||||
"\203\232x \366mis\354 \330",
|
||||
"\221 i\372le\234\314\237f\260\317\200\215 \351\375\231\320\221 f\216l-back\012",
|
||||
"\317\200specif\336a\237\334f\226w\204\207\232cl\321\237\276ig\221\220d\012",
|
||||
"outpu\202\357\362\276writt\212\320bu\202\371\270 \340\372ac\202\212\340d\353\343s\256\274\012",
|
||||
"\317\200\332\215 s\331\360w\205\251g\345b\335\304\311",
|
||||
"\277 \276m\204k\236a\205\232\313c\222\274: \211\012",
|
||||
"pu\240\336 \272lack\205f\226w\204\207\232cl\321\237\330",
|
||||
"\217k\221w\342p\321\356t\257\351subs\206tu\237(\203c\226\220c\202#\322\200p\222\347n\233"
|
||||
#endif
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,703 @@
|
||||
/* Pawn compiler - Staging buffer and optimizer
|
||||
*
|
||||
* The staging buffer
|
||||
* ------------------
|
||||
* The staging buffer allows buffered output of generated code, deletion
|
||||
* of redundant code, optimization by a tinkering process and reversing
|
||||
* the ouput of evaluated expressions (which is used for the reversed
|
||||
* evaluation of arguments in functions).
|
||||
* Initially, stgwrite() writes to the file directly, but after a call to
|
||||
* stgset(TRUE), output is redirected to the buffer. After a call to
|
||||
* stgset(FALSE), stgwrite()'s output is directed to the file again. Thus
|
||||
* only one routine is used for writing to the output, which can be
|
||||
* buffered output or direct output.
|
||||
*
|
||||
* staging buffer variables: stgbuf - the buffer
|
||||
* stgidx - current index in the staging buffer
|
||||
* staging - if true, write to the staging buffer;
|
||||
* if false, write to file directly.
|
||||
*
|
||||
* The peephole optimizer uses a dual "pipeline". The staging buffer (described
|
||||
* above) gets optimized for each expression or sub-expression in a function
|
||||
* call. The peephole optimizer is recursive, but it does not span multiple
|
||||
* sub-expressions. However, the data gets written to a second buffer that
|
||||
* behaves much like the staging buffer. This second buffer gathers all
|
||||
* optimized strings from the staging buffer for a complete expression. The
|
||||
* peephole optmizer then runs over this second buffer to find optimzations
|
||||
* across function parameter boundaries.
|
||||
*
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for atoi() */
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#endif
|
||||
#include "sc.h"
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
|
||||
#endif
|
||||
|
||||
#include "sc7.scp"
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
static int stgstring(char *start,char *end);
|
||||
static void stgopt(char *start,char *end,int (*outputfunc)(char *str));
|
||||
|
||||
|
||||
#define sSTG_GROW 512
|
||||
#define sSTG_MAX 20480
|
||||
|
||||
static char *stgbuf=NULL;
|
||||
static int stgmax=0; /* current size of the staging buffer */
|
||||
|
||||
static char *stgpipe=NULL;
|
||||
static int pipemax=0; /* current size of the stage pipe, a second staging buffer */
|
||||
static int pipeidx=0;
|
||||
|
||||
#define CHECK_STGBUFFER(index) if ((int)(index)>=stgmax) grow_stgbuffer(&stgbuf, stgmax, (index)+1)
|
||||
#define CHECK_STGPIPE(index) if ((int)(index)>=pipemax) grow_stgbuffer(&stgpipe, pipemax, (index)+1)
|
||||
|
||||
static void grow_stgbuffer(char **buffer, int curmax, int requiredsize)
|
||||
{
|
||||
char *p;
|
||||
int clear= (*buffer==NULL); /* if previously none, empty buffer explicitly */
|
||||
|
||||
assert(curmax<requiredsize);
|
||||
/* if the staging buffer (holding intermediate code for one line) grows
|
||||
* over a few kBytes, there is probably a run-away expression
|
||||
*/
|
||||
if (requiredsize>sSTG_MAX)
|
||||
error(102,"staging buffer"); /* staging buffer overflow (fatal error) */
|
||||
curmax=requiredsize+sSTG_GROW;
|
||||
if (*buffer!=NULL)
|
||||
p=(char *)realloc(*buffer,curmax*sizeof(char));
|
||||
else
|
||||
p=(char *)malloc(curmax*sizeof(char));
|
||||
if (p==NULL)
|
||||
error(102,"staging buffer"); /* staging buffer overflow (fatal error) */
|
||||
*buffer=p;
|
||||
if (clear)
|
||||
**buffer='\0';
|
||||
}
|
||||
|
||||
SC_FUNC void stgbuffer_cleanup(void)
|
||||
{
|
||||
if (stgbuf!=NULL) {
|
||||
free(stgbuf);
|
||||
stgbuf=NULL;
|
||||
stgmax=0;
|
||||
} /* if */
|
||||
if (stgpipe!=NULL) {
|
||||
free(stgpipe);
|
||||
stgpipe=NULL;
|
||||
pipemax=0;
|
||||
pipeidx=0;
|
||||
} /* if */
|
||||
}
|
||||
|
||||
/* the variables "stgidx" and "staging" are declared in "scvars.c" */
|
||||
|
||||
/* stgmark
|
||||
*
|
||||
* Copies a mark into the staging buffer. At this moment there are three
|
||||
* possible marks:
|
||||
* sSTARTREORDER identifies the beginning of a series of expression
|
||||
* strings that must be written to the output file in
|
||||
* reordered order
|
||||
* sENDREORDER identifies the end of 'reverse evaluation'
|
||||
* sEXPRSTART + idx only valid within a block that is evaluated in
|
||||
* reordered order, it identifies the start of an
|
||||
* expression; the "idx" value is the argument position
|
||||
*
|
||||
* Global references: stgidx (altered)
|
||||
* stgbuf (altered)
|
||||
* staging (referred to only)
|
||||
*/
|
||||
SC_FUNC void stgmark(char mark)
|
||||
{
|
||||
if (staging) {
|
||||
CHECK_STGBUFFER(stgidx);
|
||||
stgbuf[stgidx++]=mark;
|
||||
} /* if */
|
||||
}
|
||||
|
||||
static int rebuffer(char *str)
|
||||
{
|
||||
if (sc_status==statWRITE) {
|
||||
if (pipeidx>=2 && stgpipe[pipeidx-1]=='\0' && stgpipe[pipeidx-2]!='\n')
|
||||
pipeidx-=1; /* overwrite last '\0' */
|
||||
while (*str!='\0') { /* copy to staging buffer */
|
||||
CHECK_STGPIPE(pipeidx);
|
||||
stgpipe[pipeidx++]=*str++;
|
||||
} /* while */
|
||||
CHECK_STGPIPE(pipeidx);
|
||||
stgpipe[pipeidx++]='\0';
|
||||
} /* if */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int filewrite(char *str)
|
||||
{
|
||||
if (sc_status==statWRITE)
|
||||
return pc_writeasm(outf,str);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* stgwrite
|
||||
*
|
||||
* Writes the string "st" to the staging buffer or to the output file. In the
|
||||
* case of writing to the staging buffer, the terminating byte of zero is
|
||||
* copied too, but... the optimizer can only work on complete lines (not on
|
||||
* fractions of it. Therefore if the string is staged, if the last character
|
||||
* written to the buffer is a '\0' and the previous-to-last is not a '\n',
|
||||
* the string is concatenated to the last string in the buffer (the '\0' is
|
||||
* overwritten). This also means an '\n' used in the middle of a string isn't
|
||||
* recognized and could give wrong results with the optimizer.
|
||||
* Even when writing to the output file directly, all strings are buffered
|
||||
* until a whole line is complete.
|
||||
*
|
||||
* Global references: stgidx (altered)
|
||||
* stgbuf (altered)
|
||||
* staging (referred to only)
|
||||
*/
|
||||
SC_FUNC void stgwrite(const char *st)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (staging) {
|
||||
assert(stgidx==0 || stgbuf!=NULL); /* staging buffer must be valid if there is (apparently) something in it */
|
||||
if (stgidx>=2 && stgbuf[stgidx-1]=='\0' && stgbuf[stgidx-2]!='\n')
|
||||
stgidx-=1; /* overwrite last '\0' */
|
||||
while (*st!='\0') { /* copy to staging buffer */
|
||||
CHECK_STGBUFFER(stgidx);
|
||||
stgbuf[stgidx++]=*st++;
|
||||
} /* while */
|
||||
CHECK_STGBUFFER(stgidx);
|
||||
stgbuf[stgidx++]='\0';
|
||||
} else {
|
||||
len=(stgbuf!=NULL) ? strlen(stgbuf) : 0;
|
||||
CHECK_STGBUFFER(len+strlen(st)+1);
|
||||
strcat(stgbuf,st);
|
||||
len=strlen(stgbuf);
|
||||
if (len>0 && stgbuf[len-1]=='\n') {
|
||||
filewrite(stgbuf);
|
||||
stgbuf[0]='\0';
|
||||
} /* if */
|
||||
} /* if */
|
||||
}
|
||||
|
||||
/* stgout
|
||||
*
|
||||
* Writes the staging buffer to the output file via stgstring() (for
|
||||
* reversing expressions in the buffer) and stgopt() (for optimizing). It
|
||||
* resets "stgidx".
|
||||
*
|
||||
* Global references: stgidx (altered)
|
||||
* stgbuf (referred to only)
|
||||
* staging (referred to only)
|
||||
*/
|
||||
SC_FUNC void stgout(int index)
|
||||
{
|
||||
int reordered=0;
|
||||
int idx;
|
||||
|
||||
if (!staging)
|
||||
return;
|
||||
assert(pipeidx==0);
|
||||
|
||||
/* first pass: sub-expressions */
|
||||
if (sc_status==statWRITE)
|
||||
reordered=stgstring(&stgbuf[index],&stgbuf[stgidx]);
|
||||
stgidx=index;
|
||||
|
||||
/* second pass: optimize the buffer created in the first pass */
|
||||
if (sc_status==statWRITE) {
|
||||
if (reordered) {
|
||||
stgopt(stgpipe,stgpipe+pipeidx,filewrite);
|
||||
} else {
|
||||
/* there is no sense in re-optimizing if the order of the sub-expressions
|
||||
* did not change; so output directly
|
||||
*/
|
||||
for (idx=0; idx<pipeidx; idx+=strlen(stgpipe+idx)+1)
|
||||
filewrite(stgpipe+idx);
|
||||
} /* if */
|
||||
} /* if */
|
||||
pipeidx=0; /* reset second pipe */
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *start,*end;
|
||||
} argstack;
|
||||
|
||||
/* stgstring
|
||||
*
|
||||
* Analyses whether code strings should be output to the file as they appear
|
||||
* in the staging buffer or whether portions of it should be re-ordered.
|
||||
* Re-ordering takes place in function argument lists; Pawn passes arguments
|
||||
* to functions from right to left. When arguments are "named" rather than
|
||||
* positional, the order in the source stream is indeterminate.
|
||||
* This function calls itself recursively in case it needs to re-order code
|
||||
* strings, and it uses a private stack (or list) to mark the start and the
|
||||
* end of expressions in their correct (reversed) order.
|
||||
* In any case, stgstring() sends a block as large as possible to the
|
||||
* optimizer stgopt().
|
||||
*
|
||||
* In "reorder" mode, each set of code strings must start with the token
|
||||
* sEXPRSTART, even the first. If the token sSTARTREORDER is represented
|
||||
* by '[', sENDREORDER by ']' and sEXPRSTART by '|' the following applies:
|
||||
* '[]...' valid, but useless; no output
|
||||
* '[|...] valid, but useless; only one string
|
||||
* '[|...|...] valid and usefull
|
||||
* '[...|...] invalid, first string doesn't start with '|'
|
||||
* '[|...|] invalid
|
||||
*/
|
||||
static int stgstring(char *start,char *end)
|
||||
{
|
||||
char *ptr;
|
||||
int nest,argc,arg;
|
||||
argstack *stack;
|
||||
int reordered=0;
|
||||
|
||||
while (start<end) {
|
||||
if (*start==sSTARTREORDER) {
|
||||
start+=1; /* skip token */
|
||||
/* allocate a argstack with sMAXARGS items */
|
||||
stack=(argstack *)malloc(sMAXARGS*sizeof(argstack));
|
||||
if (stack==NULL)
|
||||
error(103); /* insufficient memory */
|
||||
reordered=1; /* mark that the expression is reordered */
|
||||
nest=1; /* nesting counter */
|
||||
argc=0; /* argument counter */
|
||||
arg=-1; /* argument index; no valid argument yet */
|
||||
do {
|
||||
switch (*start) {
|
||||
case sSTARTREORDER:
|
||||
nest++;
|
||||
start++;
|
||||
break;
|
||||
case sENDREORDER:
|
||||
nest--;
|
||||
start++;
|
||||
break;
|
||||
default:
|
||||
if ((*start & sEXPRSTART)==sEXPRSTART) {
|
||||
if (nest==1) {
|
||||
if (arg>=0)
|
||||
stack[arg].end=start-1; /* finish previous argument */
|
||||
arg=(unsigned char)*start - sEXPRSTART;
|
||||
stack[arg].start=start+1;
|
||||
if (arg>=argc)
|
||||
argc=arg+1;
|
||||
} /* if */
|
||||
start++;
|
||||
} else {
|
||||
start+=strlen(start)+1;
|
||||
} /* if */
|
||||
} /* switch */
|
||||
} while (nest); /* enddo */
|
||||
if (arg>=0)
|
||||
stack[arg].end=start-1; /* finish previous argument */
|
||||
while (argc>0) {
|
||||
argc--;
|
||||
stgstring(stack[argc].start,stack[argc].end);
|
||||
} /* while */
|
||||
free(stack);
|
||||
} else {
|
||||
ptr=start;
|
||||
while (ptr<end && *ptr!=sSTARTREORDER)
|
||||
ptr+=strlen(ptr)+1;
|
||||
stgopt(start,ptr,rebuffer);
|
||||
start=ptr;
|
||||
} /* if */
|
||||
} /* while */
|
||||
return reordered;
|
||||
}
|
||||
|
||||
/* stgdel
|
||||
*
|
||||
* Scraps code from the staging buffer by resetting "stgidx" to "index".
|
||||
*
|
||||
* Global references: stgidx (altered)
|
||||
* staging (reffered to only)
|
||||
*/
|
||||
SC_FUNC void stgdel(int index,cell code_index)
|
||||
{
|
||||
if (staging) {
|
||||
stgidx=index;
|
||||
code_idx=code_index;
|
||||
} /* if */
|
||||
}
|
||||
|
||||
SC_FUNC int stgget(int *index,cell *code_index)
|
||||
{
|
||||
if (staging) {
|
||||
*index=stgidx;
|
||||
*code_index=code_idx;
|
||||
} /* if */
|
||||
return staging;
|
||||
}
|
||||
|
||||
/* stgset
|
||||
*
|
||||
* Sets staging on or off. If it's turned off, the staging buffer must be
|
||||
* initialized to an empty string. If it's turned on, the routine makes sure
|
||||
* the index ("stgidx") is set to 0 (it should already be 0).
|
||||
*
|
||||
* Global references: staging (altered)
|
||||
* stgidx (altered)
|
||||
* stgbuf (contents altered)
|
||||
*/
|
||||
SC_FUNC void stgset(int onoff)
|
||||
{
|
||||
staging=onoff;
|
||||
if (staging){
|
||||
assert(stgidx==0);
|
||||
stgidx=0;
|
||||
CHECK_STGBUFFER(stgidx);
|
||||
/* write any contents that may be put in the buffer by stgwrite()
|
||||
* when "staging" was 0
|
||||
*/
|
||||
if (strlen(stgbuf)>0)
|
||||
filewrite(stgbuf);
|
||||
} /* if */
|
||||
stgbuf[0]='\0';
|
||||
}
|
||||
|
||||
/* phopt_init
|
||||
* Initialize all sequence strings of the peehole optimizer. The strings
|
||||
* are embedded in the .EXE file in compressed format, here we expand
|
||||
* them (and allocate memory for the sequences).
|
||||
*/
|
||||
static SEQUENCE *sequences;
|
||||
|
||||
SC_FUNC int phopt_init(void)
|
||||
{
|
||||
int number, i, len;
|
||||
char str[160];
|
||||
|
||||
/* count number of sequences */
|
||||
for (number=0; sequences_cmp[number].find!=NULL; number++)
|
||||
/* nothing */;
|
||||
number++; /* include an item for the NULL terminator */
|
||||
|
||||
if ((sequences=(SEQUENCE*)malloc(number * sizeof(SEQUENCE)))==NULL)
|
||||
return FALSE;
|
||||
|
||||
/* pre-initialize all to NULL (in case of failure) */
|
||||
for (i=0; i<number; i++) {
|
||||
sequences[i].find=NULL;
|
||||
sequences[i].replace=NULL;
|
||||
sequences[i].savesize=0;
|
||||
} /* for */
|
||||
|
||||
/* expand all strings */
|
||||
for (i=0; i<number-1; i++) {
|
||||
len = strexpand(str,(unsigned char*)sequences_cmp[i].find,sizeof str,SCPACK_TABLE);
|
||||
assert(len<=sizeof str);
|
||||
assert(len==(int)strlen(str)+1);
|
||||
sequences[i].find=(char*)malloc(len);
|
||||
if (sequences[i].find!=NULL)
|
||||
strcpy(sequences[i].find,str);
|
||||
len = strexpand(str,(unsigned char*)sequences_cmp[i].replace,sizeof str,SCPACK_TABLE);
|
||||
assert(len<=sizeof str);
|
||||
assert(len==(int)strlen(str)+1);
|
||||
sequences[i].replace=(char*)malloc(len);
|
||||
if (sequences[i].replace!=NULL)
|
||||
strcpy(sequences[i].replace,str);
|
||||
sequences[i].savesize=sequences_cmp[i].savesize;
|
||||
if (sequences[i].find==NULL || sequences[i].replace==NULL)
|
||||
return phopt_cleanup();
|
||||
} /* for */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC int phopt_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
if (sequences!=NULL) {
|
||||
i=0;
|
||||
while (sequences[i].find!=NULL || sequences[i].replace!=NULL) {
|
||||
if (sequences[i].find!=NULL)
|
||||
free(sequences[i].find);
|
||||
if (sequences[i].replace!=NULL)
|
||||
free(sequences[i].replace);
|
||||
i++;
|
||||
} /* while */
|
||||
free(sequences);
|
||||
sequences=NULL;
|
||||
} /* if */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define MAX_OPT_VARS 5
|
||||
#define MAX_OPT_CAT 5 /* max. values that are concatenated */
|
||||
#if sNAMEMAX > (PAWN_CELL_SIZE/4) * MAX_OPT_CAT
|
||||
#define MAX_ALIAS sNAMEMAX
|
||||
#else
|
||||
#define MAX_ALIAS (PAWN_CELL_SIZE/4) * MAX_OPT_CAT
|
||||
#endif
|
||||
|
||||
static int matchsequence(char *start,char *end,char *pattern,
|
||||
char symbols[MAX_OPT_VARS][MAX_ALIAS+1],
|
||||
int *match_length)
|
||||
{
|
||||
int var,i;
|
||||
char str[MAX_ALIAS+1];
|
||||
char *start_org=start;
|
||||
cell value;
|
||||
char *ptr;
|
||||
|
||||
*match_length=0;
|
||||
for (var=0; var<MAX_OPT_VARS; var++)
|
||||
symbols[var][0]='\0';
|
||||
|
||||
while (*start=='\t' || *start==' ')
|
||||
start++;
|
||||
while (*pattern) {
|
||||
if (start>=end)
|
||||
return FALSE;
|
||||
switch (*pattern) {
|
||||
case '%': /* new "symbol" */
|
||||
pattern++;
|
||||
assert(isdigit(*pattern));
|
||||
var=atoi(pattern) - 1;
|
||||
assert(var>=0 && var<MAX_OPT_VARS);
|
||||
assert(*start=='-' || alphanum(*start));
|
||||
for (i=0; start<end && (*start=='-' || *start=='+' || alphanum(*start)); i++,start++) {
|
||||
assert(i<=MAX_ALIAS);
|
||||
str[i]=*start;
|
||||
} /* for */
|
||||
str[i]='\0';
|
||||
if (symbols[var][0]!='\0') {
|
||||
if (strcmp(symbols[var],str)!=0)
|
||||
return FALSE; /* symbols should be identical */
|
||||
} else {
|
||||
strcpy(symbols[var],str);
|
||||
} /* if */
|
||||
break;
|
||||
case '-':
|
||||
value=-strtol(pattern+1,&pattern,16);
|
||||
ptr=itoh((ucell)value);
|
||||
while (*ptr!='\0') {
|
||||
if (tolower(*start) != tolower(*ptr))
|
||||
return FALSE;
|
||||
start++;
|
||||
ptr++;
|
||||
} /* while */
|
||||
pattern--; /* there is an increment following at the end of the loop */
|
||||
break;
|
||||
case ' ':
|
||||
if (*start!='\t' && *start!=' ')
|
||||
return FALSE;
|
||||
while (start<end && (*start=='\t' || *start==' '))
|
||||
start++;
|
||||
break;
|
||||
case '!':
|
||||
while (start<end && (*start=='\t' || *start==' '))
|
||||
start++; /* skip trailing white space */
|
||||
if (*start==';')
|
||||
while (start<end && *start!='\n')
|
||||
start++; /* skip trailing comment */
|
||||
if (*start!='\n')
|
||||
return FALSE;
|
||||
assert(*(start+1)=='\0');
|
||||
start+=2; /* skip '\n' and '\0' */
|
||||
if (*(pattern+1)!='\0')
|
||||
while (start<end && *start=='\t' || *start==' ')
|
||||
start++; /* skip leading white space of next instruction */
|
||||
break;
|
||||
default:
|
||||
if (tolower(*start) != tolower(*pattern))
|
||||
return FALSE;
|
||||
start++;
|
||||
} /* switch */
|
||||
pattern++;
|
||||
} /* while */
|
||||
|
||||
*match_length=(int)(start-start_org);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char *replacesequence(char *pattern,char symbols[MAX_OPT_VARS][MAX_ALIAS+1],int *repl_length)
|
||||
{
|
||||
char *lptr;
|
||||
int var;
|
||||
char *buffer;
|
||||
|
||||
/* calculate the length of the new buffer
|
||||
* this is the length of the pattern plus the length of all symbols (note
|
||||
* that the same symbol may occur multiple times in the pattern) plus
|
||||
* line endings and startings ('\t' to start a line and '\n\0' to end one)
|
||||
*/
|
||||
assert(repl_length!=NULL);
|
||||
*repl_length=0;
|
||||
lptr=pattern;
|
||||
while (*lptr) {
|
||||
switch (*lptr) {
|
||||
case '%':
|
||||
lptr++; /* skip '%' */
|
||||
assert(isdigit(*lptr));
|
||||
var=atoi(lptr) - 1;
|
||||
assert(var>=0 && var<MAX_OPT_VARS);
|
||||
assert(symbols[var][0]!='\0'); /* variable should be defined */
|
||||
*repl_length+=strlen(symbols[var]);
|
||||
break;
|
||||
case '!':
|
||||
*repl_length+=3; /* '\t', '\n' & '\0' */
|
||||
break;
|
||||
default:
|
||||
*repl_length+=1;
|
||||
} /* switch */
|
||||
lptr++;
|
||||
} /* while */
|
||||
|
||||
/* allocate a buffer to replace the sequence in */
|
||||
if ((buffer=(char*)malloc(*repl_length))==NULL)
|
||||
return (char*)error(103);
|
||||
|
||||
/* replace the pattern into this temporary buffer */
|
||||
lptr=buffer;
|
||||
*lptr++='\t'; /* the "replace" patterns do not have tabs */
|
||||
while (*pattern) {
|
||||
assert((int)(lptr-buffer)<*repl_length);
|
||||
switch (*pattern) {
|
||||
case '%':
|
||||
/* write out the symbol */
|
||||
pattern++;
|
||||
assert(isdigit(*pattern));
|
||||
var=atoi(pattern) - 1;
|
||||
assert(var>=0 && var<MAX_OPT_VARS);
|
||||
assert(symbols[var][0]!='\0'); /* variable should be defined */
|
||||
strcpy(lptr,symbols[var]);
|
||||
lptr+=strlen(symbols[var]);
|
||||
break;
|
||||
case '!':
|
||||
/* finish the line, optionally start the next line with an indent */
|
||||
*lptr++='\n';
|
||||
*lptr++='\0';
|
||||
if (*(pattern+1)!='\0')
|
||||
*lptr++='\t';
|
||||
break;
|
||||
default:
|
||||
*lptr++=*pattern;
|
||||
} /* switch */
|
||||
pattern++;
|
||||
} /* while */
|
||||
|
||||
assert((int)(lptr-buffer)==*repl_length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void strreplace(char *dest,char *replace,int sub_length,int repl_length,int dest_length)
|
||||
{
|
||||
int offset=sub_length-repl_length;
|
||||
if (offset>0) { /* delete a section */
|
||||
memmove(dest,dest+offset,dest_length-offset);
|
||||
memset(dest+dest_length-offset,0xcc,offset); /* not needed, but for cleanlyness */
|
||||
} else if (offset<0) { /* insert a section */
|
||||
memmove(dest-offset, dest, dest_length);
|
||||
} /* if */
|
||||
memcpy(dest, replace, repl_length);
|
||||
}
|
||||
|
||||
/* stgopt
|
||||
*
|
||||
* Optimizes the staging buffer by checking for series of instructions that
|
||||
* can be coded more compact. The routine expects the lines in the staging
|
||||
* buffer to be separated with '\n' and '\0' characters.
|
||||
*
|
||||
* The longest sequences should probably be checked first.
|
||||
*/
|
||||
|
||||
static void stgopt(char *start,char *end,int (*outputfunc)(char *str))
|
||||
{
|
||||
char symbols[MAX_OPT_VARS][MAX_ALIAS+1];
|
||||
int seq,match_length,repl_length;
|
||||
int matches;
|
||||
char *debut=start; /* save original start of the buffer */
|
||||
|
||||
assert(sequences!=NULL);
|
||||
/* do not match anything if debug-level is maximum */
|
||||
if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE) {
|
||||
do {
|
||||
matches=0;
|
||||
start=debut;
|
||||
while (start<end) {
|
||||
seq=0;
|
||||
while (sequences[seq].find!=NULL) {
|
||||
assert(seq>=0);
|
||||
if (*sequences[seq].find=='\0') {
|
||||
if (pc_optimize==sOPTIMIZE_NOMACRO) {
|
||||
break; /* don't look further */
|
||||
} else {
|
||||
seq++; /* continue with next string */
|
||||
continue;
|
||||
} /* if */
|
||||
} /* if */
|
||||
if (matchsequence(start,end,sequences[seq].find,symbols,&match_length)) {
|
||||
char *replace=replacesequence(sequences[seq].replace,symbols,&repl_length);
|
||||
/* If the replacement is bigger than the original section, we may need
|
||||
* to "grow" the staging buffer. This is quite complex, due to the
|
||||
* re-ordering of expressions that can also happen in the staging
|
||||
* buffer. In addition, it should not happen: the peephole optimizer
|
||||
* must replace sequences with *shorter* sequences, not longer ones.
|
||||
* So, I simply forbid sequences that are longer than the ones they
|
||||
* are meant to replace.
|
||||
*/
|
||||
assert(match_length>=repl_length);
|
||||
if (match_length>=repl_length) {
|
||||
strreplace(start,replace,match_length,repl_length,(int)(end-start));
|
||||
end-=match_length-repl_length;
|
||||
free(replace);
|
||||
code_idx-=sequences[seq].savesize;
|
||||
seq=0; /* restart search for matches */
|
||||
matches++;
|
||||
} else {
|
||||
/* actually, we should never get here (match_length<repl_length) */
|
||||
assert(0);
|
||||
seq++;
|
||||
} /* if */
|
||||
} else {
|
||||
seq++;
|
||||
} /* if */
|
||||
} /* while */
|
||||
assert(sequences[seq].find==NULL || *sequences[seq].find=='\0' && pc_optimize==sOPTIMIZE_NOMACRO);
|
||||
start += strlen(start) + 1; /* to next string */
|
||||
} /* while (start<end) */
|
||||
} while (matches>0);
|
||||
} /* if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE) */
|
||||
|
||||
for (start=debut; start<end; start+=strlen(start)+1)
|
||||
outputfunc(start);
|
||||
}
|
||||
|
||||
#undef SCPACK_TABLE
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
/* expand.c -- Byte Pair Encoding decompression */
|
||||
/* Copyright 1996 Philip Gage */
|
||||
|
||||
/* Byte Pair Compression appeared in the September 1997
|
||||
* issue of C/C++ Users Journal. The original source code
|
||||
* may still be found at the web site of the magazine
|
||||
* (www.cuj.com).
|
||||
*
|
||||
* The decompressor has been modified by me (Thiadmer
|
||||
* Riemersma) to accept a string as input, instead of a
|
||||
* complete file.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "sc.h"
|
||||
|
||||
#define STACKSIZE 16
|
||||
|
||||
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2])
|
||||
{
|
||||
unsigned char stack[STACKSIZE];
|
||||
short c, top = 0;
|
||||
int len;
|
||||
|
||||
assert(maxlen > 0);
|
||||
len = 1; /* already 1 byte for '\0' */
|
||||
for (;;) {
|
||||
|
||||
/* Pop byte from stack or read byte from the input string */
|
||||
if (top)
|
||||
c = stack[--top];
|
||||
else if ((c = *(unsigned char *)source++) == '\0')
|
||||
break;
|
||||
|
||||
/* Push pair on stack or output byte to the output string */
|
||||
if (c > 127) {
|
||||
assert(top+2 <= STACKSIZE);
|
||||
stack[top++] = pairtable[c-128][1];
|
||||
stack[top++] = pairtable[c-128][0];
|
||||
}
|
||||
else {
|
||||
len++;
|
||||
if (maxlen > 1) { /* reserve one byte for the '\0' */
|
||||
*dest++ = (char)c;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dest = '\0';
|
||||
return len; /* return number of bytes decoded */
|
||||
}
|
||||
|
||||
#if 0 /*for testing*/
|
||||
#include "sc5.scp"
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char str[128];
|
||||
|
||||
for (i=0; i<58; i++) {
|
||||
strexpand(str, errmsg[i], sizeof str, SCPACK_TABLE);
|
||||
printf("%s", str);
|
||||
} /* for */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,428 @@
|
||||
/* Codepage translation to Unicode, and UTF-8 support
|
||||
*
|
||||
* The translation is based on codepage mapping files that are distributed
|
||||
* by the Unicode consortium, see ftp://ftp.unicode.org/Public/MAPPINGS/.
|
||||
*
|
||||
* Character sets with a maximum of 256 codes are translated via a lookup
|
||||
* table (these are Single-Byte Character Sets). Character sets like Shift-JIS
|
||||
* with single-byte characters and multi-byte characters (introduced by a
|
||||
* leader byte) are split into two tables: the 256-entry lookup table for
|
||||
* the single-byte characters and an extended table for the multi-byte
|
||||
* characters. The extended table is allocated dynamically; the lookup table
|
||||
* is allocated statically, so loading SBCS tables cannot fail (if the tables
|
||||
* themselves are valid, of course).
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2004-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
|
||||
#if !defined TRUE
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#if !defined _MAX_PATH
|
||||
#define _MAX_PATH 250
|
||||
#endif
|
||||
#if !defined DIRSEP_CHAR
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#define DIRSEP_CHAR '/'
|
||||
#elif defined macintosh
|
||||
#define DIRSEP_CHAR ':'
|
||||
#else
|
||||
#define DIRSEP_CHAR '\\'
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined ELEMENTS
|
||||
#define ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
|
||||
#endif
|
||||
|
||||
#if !defined NO_CODEPAGE
|
||||
|
||||
#if !defined MAXCODEPAGE
|
||||
#define MAXCODEPAGE 12 /* typically "cp" + 4 digits + ".txt" */
|
||||
#endif
|
||||
#define INVALID 0xffffu /* 0xffff and 0xfffe are invalid Unicode characters */
|
||||
#define LEADBYTE 0xfffeu
|
||||
|
||||
struct wordpair {
|
||||
unsigned short index;
|
||||
wchar_t code;
|
||||
};
|
||||
static char cprootpath[_MAX_PATH] = { DIRSEP_CHAR, '\0' };
|
||||
static wchar_t bytetable[256];
|
||||
static struct wordpair *wordtable = NULL;
|
||||
static unsigned wordtablesize = 0;
|
||||
static unsigned wordtabletop = 0;
|
||||
|
||||
|
||||
/* read in a line delimited by '\r' or '\n'; do NOT store the '\r' or '\n' into
|
||||
* the string and ignore empty lines
|
||||
* returns 1 for success and 0 for failure
|
||||
*/
|
||||
static int cp_readline(FILE *fp,char *string,size_t size)
|
||||
{
|
||||
size_t count=0;
|
||||
int c;
|
||||
assert(size>1);
|
||||
while ((c=fgetc(fp))!=EOF && count<size-1) {
|
||||
if (c=='\r' || c=='\n') {
|
||||
if (count>0) /* '\r' or '\n' ends a string */
|
||||
break;
|
||||
/* if count==0, the line started with a '\r' or '\n', or perhaps line
|
||||
* ends in the file are '\r\n' and we read and stopped on the '\r' of
|
||||
* the preceding line
|
||||
*/
|
||||
} else {
|
||||
string[count++]=(char)c;
|
||||
} /* if */
|
||||
} /* while */
|
||||
string[count]='\0';
|
||||
return count>0;
|
||||
}
|
||||
|
||||
/* cp_path() sets the directory where all codepage files must be found (if
|
||||
* the parameter to cp_set() specifies a full path, that is used instead).
|
||||
* The path is specified into two parts: root and directory; the full path
|
||||
* for the codepage direcory is just the concatenation of the two, with a
|
||||
* directory separator in between. The directory is given in two parts,
|
||||
* because often a program already retrieves its "home" directory and the
|
||||
* codepages are most conveniently stored in a subdirectory of this home
|
||||
* directory.
|
||||
*/
|
||||
SC_FUNC int cp_path(const char *root, const char *directory)
|
||||
{
|
||||
size_t len1,len2;
|
||||
int add_slash1,add_slash2;
|
||||
|
||||
len1= (root!=NULL) ? strlen(root) : 0;
|
||||
add_slash1= (len1==0 || root[len1-1]!=DIRSEP_CHAR);
|
||||
len2= (directory!=NULL) ? strlen(directory) : 0;
|
||||
add_slash2= (len2>0 && root[len2-1]!=DIRSEP_CHAR);
|
||||
if (len1+add_slash1+len2+add_slash2>=(_MAX_PATH-MAXCODEPAGE))
|
||||
return FALSE; /* full filename may not fit */
|
||||
if (root!=NULL)
|
||||
strcpy(cprootpath,root);
|
||||
if (add_slash1) {
|
||||
assert(len1==0 || cprootpath[len1]=='\0');
|
||||
cprootpath[len1]=DIRSEP_CHAR;
|
||||
cprootpath[len1+1]='\0';
|
||||
} /* if */
|
||||
if (directory!=NULL)
|
||||
strcat(cprootpath,directory);
|
||||
if (add_slash2) {
|
||||
assert(cprootpath[len1+add_slash1+len2]=='\0');
|
||||
cprootpath[len1+add_slash1+len2]=DIRSEP_CHAR;
|
||||
cprootpath[len1+add_slash1+len2+1]='\0';
|
||||
} /* if */
|
||||
cp_set(NULL); /* start with a "linear" table (no translation) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* cp_set() loads a codepage from a file. The name parameter may be a
|
||||
* filename (including a full path) or it may be a partial codepage name.
|
||||
* If the name parameter is NULL, the codepage is cleared to be a "linear"
|
||||
* table (no translation).
|
||||
* The following files are attempted to open (where <name> specifies the
|
||||
* value of the parameter):
|
||||
* <name>
|
||||
* <cprootpath>/<name>
|
||||
* <cprootpath>/<name>.txt
|
||||
* <cprootpath>/cp<name>
|
||||
* <cprootpath>/cp<name>.txt
|
||||
*/
|
||||
SC_FUNC int cp_set(const char *name)
|
||||
{
|
||||
char filename[_MAX_PATH];
|
||||
FILE *fp=NULL;
|
||||
unsigned index;
|
||||
|
||||
/* for name==NULL, set up an identity table */
|
||||
if (name==NULL || *name=='\0') {
|
||||
if (wordtable!=NULL) {
|
||||
free(wordtable);
|
||||
wordtable=NULL;
|
||||
wordtablesize=0;
|
||||
wordtabletop=0;
|
||||
} /* if */
|
||||
for (index=0; index<ELEMENTS(bytetable); index++)
|
||||
bytetable[index]=(wchar_t)index;
|
||||
return TRUE;
|
||||
} /* if */
|
||||
|
||||
/* try to open the file as-is */
|
||||
if (strchr(name,DIRSEP_CHAR)!=NULL)
|
||||
fp=fopen(name,"rt");
|
||||
if (fp==NULL) {
|
||||
/* try opening the file in the "root path" for codepages */
|
||||
if (strlen(name)>MAXCODEPAGE)
|
||||
return 0;
|
||||
assert(strlen(name)+strlen(cprootpath)<_MAX_PATH);
|
||||
strcpy(filename,cprootpath);
|
||||
strcat(filename,name);
|
||||
fp=fopen(filename,"rt");
|
||||
} /* if */
|
||||
if (fp==NULL) {
|
||||
/* try opening the file in the "root path" for codepages, with a ".txt" extension */
|
||||
if (strlen(name)+4>=MAXCODEPAGE)
|
||||
return 0;
|
||||
assert(strlen(filename)+4<_MAX_PATH);
|
||||
strcat(filename,".txt");
|
||||
fp=fopen(filename,"rt");
|
||||
} /* if */
|
||||
if (fp==NULL) {
|
||||
/* try opening the file in the "root path" for codepages, with "cp" prefixed before the name */
|
||||
if (strlen(name)+2>MAXCODEPAGE)
|
||||
return 0;
|
||||
assert(2+strlen(name)+strlen(cprootpath)<_MAX_PATH);
|
||||
strcpy(filename,cprootpath);
|
||||
strcat(filename,"cp");
|
||||
strcat(filename,name);
|
||||
fp=fopen(filename,"rt");
|
||||
} /* if */
|
||||
if (fp==NULL) {
|
||||
/* try opening the file in the "root path" for codepages, with "cp" prefixed an ".txt" appended */
|
||||
if (strlen(name)+2+4>MAXCODEPAGE)
|
||||
return 0;
|
||||
assert(strlen(filename)+4<_MAX_PATH);
|
||||
strcat(filename,".txt");
|
||||
fp=fopen(filename,"rt");
|
||||
} /* if */
|
||||
if (fp==NULL)
|
||||
return FALSE; /* all failed */
|
||||
|
||||
/* clear the tables */
|
||||
for (index=0; index<ELEMENTS(bytetable); index++)
|
||||
bytetable[index]=INVALID; /* special code meaning "not found" */
|
||||
assert(wordtablesize==0 && wordtabletop==0 && wordtable==NULL
|
||||
|| wordtablesize>0 && wordtable!=NULL);
|
||||
if (wordtable!=NULL) {
|
||||
free(wordtable);
|
||||
wordtable=NULL;
|
||||
wordtablesize=0;
|
||||
wordtabletop=0;
|
||||
} /* if */
|
||||
|
||||
/* read in the table */
|
||||
while (cp_readline(fp,filename,sizeof filename)) {
|
||||
char *ptr;
|
||||
if ((ptr=strchr(filename,'#'))!=NULL)
|
||||
*ptr='\0'; /* strip of comment */
|
||||
for (ptr=filename; *ptr>0 && *ptr<' '; ptr++)
|
||||
/* nothing */; /* skip leading whitespace */
|
||||
if (*ptr!='\0') {
|
||||
/* content on line */
|
||||
unsigned code=LEADBYTE;
|
||||
int num=sscanf(ptr,"%i %i",&index,&code);
|
||||
/* if sscanf() returns 1 and the index is in range 0..255, then the
|
||||
* code is a DBCS lead byte; if sscanf() returns 2 and index>=256, this
|
||||
* is a double byte pair (lead byte + follower)
|
||||
*/
|
||||
if (num>=1 && index<256) {
|
||||
bytetable[index]=(wchar_t)code;
|
||||
} else if (num==2 && index>=256 && index<LEADBYTE) {
|
||||
/* store the DBCS character in wordtable */
|
||||
if (wordtabletop>=wordtablesize) {
|
||||
/* grow the list */
|
||||
int newsize;
|
||||
struct wordpair *newblock;
|
||||
newsize= (wordtablesize==0) ? 128 : 2*wordtablesize;
|
||||
newblock=(struct wordpair *)malloc(newsize*sizeof(*wordtable));
|
||||
if (newblock!=NULL) {
|
||||
memcpy(newblock,wordtable,wordtabletop*sizeof(*wordtable));
|
||||
free(wordtable);
|
||||
wordtable=newblock;
|
||||
wordtablesize=newsize;
|
||||
} /* if */
|
||||
} /* if */
|
||||
if (wordtabletop<wordtablesize) {
|
||||
/* insert at sorted position */
|
||||
int pos=wordtabletop;
|
||||
assert(wordtable!=NULL);
|
||||
while (pos>0 && (unsigned)wordtable[pos-1].index>index) {
|
||||
wordtable[pos]=wordtable[pos-1];
|
||||
pos--;
|
||||
} /* while */
|
||||
wordtable[pos].index=(unsigned short)index;
|
||||
wordtable[pos].code=(wchar_t)code;
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* while */
|
||||
|
||||
fclose(fp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr)
|
||||
{
|
||||
wchar_t result;
|
||||
|
||||
result=bytetable[*string++];
|
||||
/* check whether this is a leader code */
|
||||
if ((unsigned)result==LEADBYTE && wordtable!=NULL) {
|
||||
/* look up the code via binary search */
|
||||
int low,high,mid;
|
||||
unsigned short index=(unsigned short)(((*(string-1)) << 8) | *string);
|
||||
string++;
|
||||
assert(wordtabletop>0);
|
||||
low=0;
|
||||
high=wordtabletop-1;
|
||||
while (low<high) {
|
||||
mid=(low+high)/2;
|
||||
assert(low<=mid && mid<high);
|
||||
if (index>wordtable[mid].index)
|
||||
low=mid+1;
|
||||
else
|
||||
high=mid;
|
||||
} /* while */
|
||||
assert(low==high);
|
||||
if (wordtable[low].index==index)
|
||||
result=wordtable[low].code;
|
||||
} /* if */
|
||||
|
||||
if (endptr!=NULL)
|
||||
*endptr=string;
|
||||
return (cell)result;
|
||||
}
|
||||
|
||||
#endif /* NO_CODEPAGE */
|
||||
|
||||
#if !defined NO_UTF8
|
||||
SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr)
|
||||
{
|
||||
int follow=0;
|
||||
long lowmark=0;
|
||||
unsigned char ch;
|
||||
cell result=0;
|
||||
|
||||
if (endptr!=NULL)
|
||||
*endptr=string;
|
||||
|
||||
for ( ;; ) {
|
||||
ch=*string++;
|
||||
|
||||
if (follow>0 && (ch & 0xc0)==0x80) {
|
||||
/* leader code is active, combine with earlier code */
|
||||
result=(result << 6) | (ch & 0x3f);
|
||||
if (--follow==0) {
|
||||
/* encoding a character in more bytes than is strictly needed,
|
||||
* is not really valid UTF-8; we are strict here to increase
|
||||
* the chance of heuristic dectection of non-UTF-8 text
|
||||
* (JAVA writes zero bytes as a 2-byte code UTF-8, which is invalid)
|
||||
*/
|
||||
if (result<lowmark)
|
||||
return -1;
|
||||
/* the code positions 0xd800--0xdfff and 0xfffe & 0xffff do not
|
||||
* exist in UCS-4 (and hence, they do not exist in Unicode)
|
||||
*/
|
||||
if (result>=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff)
|
||||
return -1;
|
||||
} /* if */
|
||||
break;
|
||||
} else if (follow==0 && (ch & 0x80)==0x80) {
|
||||
/* UTF-8 leader code */
|
||||
if ((ch & 0xe0)==0xc0) {
|
||||
/* 110xxxxx 10xxxxxx */
|
||||
follow=1;
|
||||
lowmark=0x80L;
|
||||
result=ch & 0x1f;
|
||||
} else if ((ch & 0xf0)==0xe0) {
|
||||
/* 1110xxxx 10xxxxxx 10xxxxxx (16 bits, BMP plane) */
|
||||
follow=2;
|
||||
lowmark=0x800L;
|
||||
result=ch & 0x0f;
|
||||
} else if ((ch & 0xf8)==0xf0) {
|
||||
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
follow=3;
|
||||
lowmark=0x10000L;
|
||||
result=ch & 0x07;
|
||||
} else if ((ch & 0xfc)==0xf8) {
|
||||
/* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
follow=4;
|
||||
lowmark=0x200000L;
|
||||
result=ch & 0x03;
|
||||
} else if ((ch & 0xfe)==0xfc) {
|
||||
/* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (32 bits) */
|
||||
follow=5;
|
||||
lowmark=0x4000000L;
|
||||
result=ch & 0x01;
|
||||
} else {
|
||||
/* this is invalid UTF-8 */
|
||||
return -1;
|
||||
} /* if */
|
||||
} else if (follow==0 && (ch & 0x80)==0x00) {
|
||||
/* 0xxxxxxx (US-ASCII) */
|
||||
result=ch;
|
||||
break;
|
||||
} else {
|
||||
/* this is invalid UTF-8 */
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
} /* for */
|
||||
|
||||
if (endptr!=NULL)
|
||||
*endptr=string;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
SC_FUNC int scan_utf8(FILE *fp,const char *filename)
|
||||
{
|
||||
#if defined NO_UTF8
|
||||
return 0;
|
||||
#else
|
||||
void *resetpos=pc_getpossrc(fp);
|
||||
int utf8=TRUE;
|
||||
int firstchar=TRUE,bom_found=FALSE;
|
||||
const unsigned char *ptr;
|
||||
|
||||
while (utf8 && pc_readsrc(fp,pline,sLINEMAX)!=NULL) {
|
||||
ptr=pline;
|
||||
if (firstchar) {
|
||||
/* check whether the very first character on the very first line
|
||||
* starts with a BYTE order mark
|
||||
*/
|
||||
cell c=get_utf8_char(ptr,&ptr);
|
||||
bom_found= (c==0xfeff);
|
||||
utf8= (c>=0);
|
||||
firstchar=FALSE;
|
||||
} /* if */
|
||||
while (utf8 && *ptr!='\0')
|
||||
utf8= (get_utf8_char(ptr,&ptr)>=0);
|
||||
} /* while */
|
||||
pc_resetsrc(fp,resetpos);
|
||||
if (bom_found) {
|
||||
unsigned char bom[3];
|
||||
if (!utf8)
|
||||
error(77,filename); /* malformed UTF-8 encoding */
|
||||
pc_readsrc(fp,bom,3);
|
||||
assert(bom[0]==0xef && bom[1]==0xbb && bom[2]==0xbf);
|
||||
} /* if */
|
||||
return utf8;
|
||||
#endif /* NO_UTF8 */
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Things needed to compile under linux.
|
||||
*
|
||||
* Should be reworked totally to use GNU's 'configure'
|
||||
*/
|
||||
#ifndef SCLINUX_H
|
||||
#define SCLINUX_H
|
||||
|
||||
/* getchar() is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the
|
||||
* controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling
|
||||
* terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must
|
||||
* be put back correctly when the function ends. See GETCH.C for an implementation.
|
||||
*
|
||||
* For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to
|
||||
* have a complete emacs/vi like line editing system.
|
||||
*/
|
||||
#include "getch.h"
|
||||
|
||||
#define stricmp(a,b) strcasecmp(a,b)
|
||||
#define strnicmp(a,b,c) strncasecmp(a,b,c)
|
||||
|
||||
/*
|
||||
* WinWorld wants '\'. Unices do not.
|
||||
*/
|
||||
#define DIRECTORY_SEP_CHAR '/'
|
||||
#define DIRECTORY_SEP_STR "/"
|
||||
|
||||
/*
|
||||
* SC assumes that a computer is Little Endian unless told otherwise. It uses
|
||||
* (and defines) the macros BYTE_ORDER and BIG_ENDIAN.
|
||||
* For Linux, we must overrule these settings with those defined in glibc.
|
||||
*/
|
||||
#if !defined __BYTE_ORDER
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined __OpenBSD__ || defined __FreeBSD__
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#if !defined __BYTE_ORDER
|
||||
# error "Can't figure computer byte order (__BYTE_ORDER macro not found)"
|
||||
#endif
|
||||
|
||||
#endif /* SCLINUX_H */
|
||||
@@ -0,0 +1,531 @@
|
||||
/* Pawn compiler - maintenance of various lists
|
||||
*
|
||||
* o Name list (aliases)
|
||||
* o Include path list
|
||||
* o Macro definitions (text substitutions)
|
||||
* o Documentation tags and automatic listings
|
||||
* o Debug strings
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2001-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
#include "lstring.h"
|
||||
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#endif
|
||||
|
||||
/* a "private" implementation of strdup(), so that porting
|
||||
* to other memory allocators becomes easier.
|
||||
* By Søren Hannibal.
|
||||
*/
|
||||
SC_FUNC char* duplicatestring(const char* sourcestring)
|
||||
{
|
||||
char* result=(char*)malloc(strlen(sourcestring)+1);
|
||||
strcpy(result,sourcestring);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
|
||||
{
|
||||
stringpair *cur,*pred;
|
||||
|
||||
assert(root!=NULL);
|
||||
assert(first!=NULL);
|
||||
assert(second!=NULL);
|
||||
/* create a new node, and check whether all is okay */
|
||||
if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
|
||||
return NULL;
|
||||
cur->first=duplicatestring(first);
|
||||
cur->second=duplicatestring(second);
|
||||
cur->matchlength=matchlength;
|
||||
cur->documentation=NULL;
|
||||
if (cur->first==NULL || cur->second==NULL) {
|
||||
if (cur->first!=NULL)
|
||||
free(cur->first);
|
||||
if (cur->second!=NULL)
|
||||
free(cur->second);
|
||||
free(cur);
|
||||
return NULL;
|
||||
} /* if */
|
||||
/* link the node to the tree, find the position */
|
||||
for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
|
||||
/* nothing */;
|
||||
cur->next=pred->next;
|
||||
pred->next=cur;
|
||||
return cur;
|
||||
}
|
||||
|
||||
static void delete_stringpairtable(stringpair *root)
|
||||
{
|
||||
stringpair *cur, *next;
|
||||
|
||||
assert(root!=NULL);
|
||||
cur=root->next;
|
||||
while (cur!=NULL) {
|
||||
next=cur->next;
|
||||
assert(cur->first!=NULL);
|
||||
assert(cur->second!=NULL);
|
||||
free(cur->first);
|
||||
free(cur->second);
|
||||
free(cur);
|
||||
cur=next;
|
||||
} /* while */
|
||||
memset(root,0,sizeof(stringpair));
|
||||
}
|
||||
|
||||
static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
|
||||
{
|
||||
int result=0;
|
||||
|
||||
assert(matchlength>0); /* the function cannot handle zero-length comparison */
|
||||
assert(first!=NULL);
|
||||
while (cur!=NULL && result<=0) {
|
||||
result=(int)*cur->first - (int)*first;
|
||||
if (result==0 && matchlength==cur->matchlength) {
|
||||
result=strncmp(cur->first,first,matchlength);
|
||||
if (result==0)
|
||||
return cur;
|
||||
} /* if */
|
||||
cur=cur->next;
|
||||
} /* while */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int delete_stringpair(stringpair *root,stringpair *item)
|
||||
{
|
||||
stringpair *cur;
|
||||
|
||||
assert(root!=NULL);
|
||||
cur=root;
|
||||
while (cur->next!=NULL) {
|
||||
if (cur->next==item) {
|
||||
cur->next=item->next; /* unlink from list */
|
||||
assert(item->first!=NULL);
|
||||
assert(item->second!=NULL);
|
||||
free(item->first);
|
||||
free(item->second);
|
||||
free(item);
|
||||
return TRUE;
|
||||
} /* if */
|
||||
cur=cur->next;
|
||||
} /* while */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ----- string list functions ----------------------------------- */
|
||||
static stringlist *insert_string(stringlist *root,char *string)
|
||||
{
|
||||
stringlist *cur;
|
||||
|
||||
assert(string!=NULL);
|
||||
if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
if ((cur->line=duplicatestring(string))==NULL)
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
/* insert as "last" */
|
||||
assert(root!=NULL);
|
||||
while (root->next!=NULL)
|
||||
root=root->next;
|
||||
cur->next=root->next;
|
||||
root->next=cur;
|
||||
return cur;
|
||||
}
|
||||
|
||||
static char *get_string(stringlist *root,int index)
|
||||
{
|
||||
stringlist *cur;
|
||||
|
||||
assert(root!=NULL);
|
||||
cur=root->next;
|
||||
while (cur!=NULL && index-->0)
|
||||
cur=cur->next;
|
||||
if (cur!=NULL) {
|
||||
assert(cur->line!=NULL);
|
||||
return cur->line;
|
||||
} /* if */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int delete_string(stringlist *root,int index)
|
||||
{
|
||||
stringlist *cur,*item;
|
||||
|
||||
assert(root!=NULL);
|
||||
for (cur=root; cur->next!=NULL && index>0; cur=cur->next,index--)
|
||||
/* nothing */;
|
||||
if (cur->next!=NULL) {
|
||||
item=cur->next;
|
||||
cur->next=item->next; /* unlink from list */
|
||||
assert(item->line!=NULL);
|
||||
free(item->line);
|
||||
free(item);
|
||||
return TRUE;
|
||||
} /* if */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_stringtable(stringlist *root)
|
||||
{
|
||||
stringlist *cur,*next;
|
||||
|
||||
assert(root!=NULL);
|
||||
cur=root->next;
|
||||
while (cur!=NULL) {
|
||||
next=cur->next;
|
||||
assert(cur->line!=NULL);
|
||||
free(cur->line);
|
||||
free(cur);
|
||||
cur=next;
|
||||
} /* while */
|
||||
memset(root,0,sizeof(stringlist));
|
||||
}
|
||||
|
||||
|
||||
/* ----- alias table --------------------------------------------- */
|
||||
static stringpair alias_tab = {NULL, NULL, NULL}; /* alias table */
|
||||
|
||||
SC_FUNC stringpair *insert_alias(char *name,char *alias)
|
||||
{
|
||||
stringpair *cur;
|
||||
|
||||
assert(name!=NULL);
|
||||
assert(strlen(name)<=sNAMEMAX);
|
||||
assert(alias!=NULL);
|
||||
assert(strlen(alias)<=sNAMEMAX);
|
||||
if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
return cur;
|
||||
}
|
||||
|
||||
SC_FUNC int lookup_alias(char *target,char *name)
|
||||
{
|
||||
stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
|
||||
if (cur!=NULL) {
|
||||
assert(strlen(cur->second)<=sNAMEMAX);
|
||||
strcpy(target,cur->second);
|
||||
} /* if */
|
||||
return cur!=NULL;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_aliastable(void)
|
||||
{
|
||||
delete_stringpairtable(&alias_tab);
|
||||
}
|
||||
|
||||
/* ----- include paths list -------------------------------------- */
|
||||
static stringlist includepaths = {NULL, NULL}; /* directory list for include files */
|
||||
|
||||
SC_FUNC stringlist *insert_path(char *path)
|
||||
{
|
||||
return insert_string(&includepaths,path);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_path(int index)
|
||||
{
|
||||
return get_string(&includepaths,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_pathtable(void)
|
||||
{
|
||||
delete_stringtable(&includepaths);
|
||||
assert(includepaths.next==NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ----- text substitution patterns ------------------------------ */
|
||||
#if !defined NO_DEFINE
|
||||
|
||||
static stringpair substpair = { NULL, NULL, NULL}; /* list of substitution pairs */
|
||||
|
||||
static stringpair *substindex['z'-PUBLIC_CHAR+1]; /* quick index to first character */
|
||||
static void adjustindex(char c)
|
||||
{
|
||||
stringpair *cur;
|
||||
assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_' || c==PUBLIC_CHAR);
|
||||
assert(PUBLIC_CHAR<'A' && 'A'<'_' && '_'<'z');
|
||||
|
||||
for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
|
||||
/* nothing */;
|
||||
substindex[(int)c-PUBLIC_CHAR]=cur;
|
||||
}
|
||||
|
||||
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
|
||||
{
|
||||
stringpair *cur;
|
||||
|
||||
assert(pattern!=NULL);
|
||||
assert(substitution!=NULL);
|
||||
if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
adjustindex(*pattern);
|
||||
|
||||
if (pc_deprecate!=NULL) {
|
||||
assert(cur!=NULL);
|
||||
cur->flags|=flgDEPRECATED;
|
||||
if (sc_status==statWRITE) {
|
||||
if (cur->documentation!=NULL) {
|
||||
free(cur->documentation);
|
||||
cur->documentation=NULL;
|
||||
} /* if */
|
||||
cur->documentation=pc_deprecate;
|
||||
} else {
|
||||
free(pc_deprecate);
|
||||
} /* if */
|
||||
pc_deprecate=NULL;
|
||||
} else {
|
||||
cur->flags = 0;
|
||||
cur->documentation = NULL;
|
||||
} /* if */
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
SC_FUNC stringpair *find_subst(char *name,int length)
|
||||
{
|
||||
stringpair *item;
|
||||
assert(name!=NULL);
|
||||
assert(length>0);
|
||||
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
|
||||
item=substindex[(int)*name-PUBLIC_CHAR];
|
||||
if (item!=NULL)
|
||||
item=find_stringpair(item,name,length);
|
||||
|
||||
if (item && (item->flags & flgDEPRECATED) != 0)
|
||||
{
|
||||
static char macro[128];
|
||||
char *rem, *msg = (item->documentation != NULL) ? item->documentation : "";
|
||||
strlcpy(macro, item->first, sizeof(macro));
|
||||
|
||||
/* If macro contains an opening parentheses and a percent sign, then assume that
|
||||
* it takes arguments and remove them from the warning message.
|
||||
*/
|
||||
if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem)
|
||||
{
|
||||
*rem = '\0';
|
||||
}
|
||||
|
||||
error(234, macro, msg); /* deprecated (macro/constant) */
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
SC_FUNC int delete_subst(char *name,int length)
|
||||
{
|
||||
stringpair *item;
|
||||
assert(name!=NULL);
|
||||
assert(length>0);
|
||||
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
|
||||
item=substindex[(int)*name-PUBLIC_CHAR];
|
||||
if (item!=NULL)
|
||||
item=find_stringpair(item,name,length);
|
||||
if (item==NULL)
|
||||
return FALSE;
|
||||
if (item->documentation)
|
||||
{
|
||||
free(item->documentation);
|
||||
item->documentation=NULL;
|
||||
}
|
||||
delete_stringpair(&substpair,item);
|
||||
adjustindex(*name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_substtable(void)
|
||||
{
|
||||
int i;
|
||||
delete_stringpairtable(&substpair);
|
||||
for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
|
||||
substindex[i]=NULL;
|
||||
}
|
||||
|
||||
#endif /* !defined NO_SUBST */
|
||||
|
||||
|
||||
/* ----- input file list ----------------------------------------- */
|
||||
static stringlist sourcefiles = {NULL, NULL};
|
||||
|
||||
SC_FUNC stringlist *insert_sourcefile(char *string)
|
||||
{
|
||||
return insert_string(&sourcefiles,string);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_sourcefile(int index)
|
||||
{
|
||||
return get_string(&sourcefiles,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_sourcefiletable(void)
|
||||
{
|
||||
delete_stringtable(&sourcefiles);
|
||||
assert(sourcefiles.next==NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ----- documentation tags -------------------------------------- */
|
||||
#if !defined SC_LIGHT
|
||||
static stringlist docstrings = {NULL, NULL};
|
||||
|
||||
SC_FUNC stringlist *insert_docstring(char *string)
|
||||
{
|
||||
return insert_string(&docstrings,string);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_docstring(int index)
|
||||
{
|
||||
return get_string(&docstrings,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_docstring(int index)
|
||||
{
|
||||
delete_string(&docstrings,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_docstringtable(void)
|
||||
{
|
||||
delete_stringtable(&docstrings);
|
||||
assert(docstrings.next==NULL);
|
||||
}
|
||||
#endif /* !defined SC_LIGHT */
|
||||
|
||||
|
||||
/* ----- autolisting --------------------------------------------- */
|
||||
static stringlist autolist = {NULL, NULL};
|
||||
|
||||
SC_FUNC stringlist *insert_autolist(char *string)
|
||||
{
|
||||
return insert_string(&autolist,string);
|
||||
}
|
||||
|
||||
SC_FUNC char *get_autolist(int index)
|
||||
{
|
||||
return get_string(&autolist,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_autolisttable(void)
|
||||
{
|
||||
delete_stringtable(&autolist);
|
||||
assert(autolist.next==NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ----- debug information --------------------------------------- */
|
||||
|
||||
/* These macros are adapted from LibDGG libdgg-int64.h, see
|
||||
* http://www.dennougedougakkai-ndd.org/pub/libdgg/
|
||||
*/
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#include <inttypes.h> /* automatically includes stdint.h */
|
||||
#elif (defined _MSC_VER || defined __BORLANDC__) && (defined _I64_MAX || defined HAVE_I64)
|
||||
#define PRId64 "I64d"
|
||||
#define PRIx64 "I64x"
|
||||
#else
|
||||
#define PRId64 "lld"
|
||||
#define PRIx64 "llx"
|
||||
#endif
|
||||
#if PAWN_CELL_SIZE==64
|
||||
#define PRIdC PRId64
|
||||
#define PRIxC PRIx64
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
#define PRIdC "ld"
|
||||
#define PRIxC "lx"
|
||||
#else
|
||||
#define PRIdC "d"
|
||||
#define PRIxC "x"
|
||||
#endif
|
||||
|
||||
static stringlist dbgstrings = {NULL, NULL};
|
||||
|
||||
SC_FUNC stringlist *insert_dbgfile(const char *filename)
|
||||
{
|
||||
|
||||
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
|
||||
char string[_MAX_PATH+40];
|
||||
assert(filename!=NULL);
|
||||
assert(strlen(filename)+40<sizeof string);
|
||||
sprintf(string,"F:%" PRIxC " %s",code_idx,filename);
|
||||
return insert_string(&dbgstrings,string);
|
||||
} /* if */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC stringlist *insert_dbgline(int linenr)
|
||||
{
|
||||
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
|
||||
char string[40];
|
||||
if (linenr>0)
|
||||
linenr--; /* line numbers are zero-based in the debug information */
|
||||
sprintf(string,"L:%" PRIxC " %x",code_idx,linenr);
|
||||
return insert_string(&dbgstrings,string);
|
||||
} /* if */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
|
||||
{
|
||||
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
|
||||
char string[2*sNAMEMAX+128];
|
||||
char symname[2*sNAMEMAX+16];
|
||||
|
||||
funcdisplayname(symname,sym->name);
|
||||
/* address tag:name codestart codeend ident vclass [tag:dim ...] */
|
||||
if (sym->ident==iFUNCTN) {
|
||||
sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
|
||||
sym->addr,sym->tag,symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass);
|
||||
} else {
|
||||
sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
|
||||
sym->addr,sym->tag,symname,sym->codeaddr,code_idx,sym->ident,sym->vclass);
|
||||
} /* if */
|
||||
if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
|
||||
#if !defined NDEBUG
|
||||
int count=sym->dim.array.level;
|
||||
#endif
|
||||
symbol *sub;
|
||||
strcat(string," [ ");
|
||||
for (sub=sym; sub!=NULL; sub=finddepend(sub)) {
|
||||
assert(sub->dim.array.level==count--);
|
||||
sprintf(string+strlen(string),"%x:%x ",sub->x.tags.index,sub->dim.array.length);
|
||||
} /* for */
|
||||
strcat(string,"]");
|
||||
} /* if */
|
||||
|
||||
return insert_string(&dbgstrings,string);
|
||||
} /* if */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC char *get_dbgstring(int index)
|
||||
{
|
||||
return get_string(&dbgstrings,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_dbgstringtable(void)
|
||||
{
|
||||
delete_stringtable(&dbgstrings);
|
||||
assert(dbgstrings.next==NULL);
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* Pawn compiler
|
||||
*
|
||||
* Routines to maintain a "text file" in memory.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2003-2006
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from the
|
||||
* use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "memfile.h"
|
||||
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#endif
|
||||
typedef memfile_t MEMFILE;
|
||||
#define tMEMFILE 1
|
||||
|
||||
#include "sc.h"
|
||||
|
||||
MEMFILE *mfcreate(const char *filename)
|
||||
{
|
||||
return memfile_creat(filename, 4096);
|
||||
}
|
||||
|
||||
void mfclose(MEMFILE *mf)
|
||||
{
|
||||
memfile_destroy(mf);
|
||||
}
|
||||
|
||||
int mfdump(MEMFILE *mf)
|
||||
{
|
||||
FILE *fp;
|
||||
int okay;
|
||||
|
||||
assert(mf!=NULL);
|
||||
/* create the file */
|
||||
fp=fopen(mf->name, "wb");
|
||||
if (fp==NULL)
|
||||
return 0;
|
||||
|
||||
okay=1;
|
||||
okay = okay & (fwrite(mf->base, mf->usedoffs, 1, fp)==(size_t)mf->usedoffs);
|
||||
|
||||
fclose(fp);
|
||||
return okay;
|
||||
}
|
||||
|
||||
long mflength(const MEMFILE *mf)
|
||||
{
|
||||
return mf->usedoffs;
|
||||
}
|
||||
|
||||
long mfseek(MEMFILE *mf,long offset,int whence)
|
||||
{
|
||||
long length;
|
||||
|
||||
assert(mf!=NULL);
|
||||
if (mf->usedoffs == 0)
|
||||
return 0L; /* early exit: not a single byte in the file */
|
||||
|
||||
/* find the size of the memory file */
|
||||
length=mflength(mf);
|
||||
|
||||
/* convert the offset to an absolute position */
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset+=mf->offs;
|
||||
break;
|
||||
case SEEK_END:
|
||||
assert(offset<=0);
|
||||
offset+=length;
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
/* clamp to the file length limit */
|
||||
if (offset<0)
|
||||
offset=0;
|
||||
else if (offset>length)
|
||||
offset=length;
|
||||
|
||||
/* set new position and return it */
|
||||
memfile_seek(mf, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size)
|
||||
{
|
||||
return (memfile_write(mf, buffer, size) ? size : 0);
|
||||
}
|
||||
|
||||
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size)
|
||||
{
|
||||
return memfile_read(mf, buffer, size);
|
||||
}
|
||||
|
||||
char *mfgets(MEMFILE *mf,char *string,unsigned int size)
|
||||
{
|
||||
char *ptr;
|
||||
unsigned int read;
|
||||
long seek;
|
||||
|
||||
assert(mf!=NULL);
|
||||
|
||||
read=mfread(mf,(unsigned char *)string,size);
|
||||
if (read==0)
|
||||
return NULL;
|
||||
seek=0L;
|
||||
|
||||
/* make sure that the string is zero-terminated */
|
||||
assert(read<=size);
|
||||
if (read<size) {
|
||||
string[read]='\0';
|
||||
} else {
|
||||
string[size-1]='\0';
|
||||
seek=-1; /* undo reading the character that gets overwritten */
|
||||
} /* if */
|
||||
|
||||
/* find the first '\n' */
|
||||
ptr=strchr(string,'\n');
|
||||
if (ptr!=NULL) {
|
||||
*(ptr+1)='\0';
|
||||
seek=(long)(ptr-string)+1-(long)read;
|
||||
} /* if */
|
||||
|
||||
/* undo over-read */
|
||||
assert(seek<=0); /* should seek backward only */
|
||||
if (seek!=0)
|
||||
mfseek(mf,seek,SEEK_CUR);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
int mfputs(MEMFILE *mf,const char *string)
|
||||
{
|
||||
unsigned int written,length;
|
||||
|
||||
assert(mf!=NULL);
|
||||
|
||||
length=strlen(string);
|
||||
written=mfwrite(mf,(unsigned char *)string,length);
|
||||
return written==length;
|
||||
}
|
||||
@@ -0,0 +1,450 @@
|
||||
/* compress.c -- Byte Pair Encoding compression */
|
||||
/* Copyright 1996 Philip Gage */
|
||||
|
||||
/* This program appeared in the September 1997 issue of
|
||||
* C/C++ Users Journal. The original source code may still
|
||||
* be found at the web site of the magazine (www.cuj.com).
|
||||
*
|
||||
* It has been modified by me (Thiadmer Riemersma) to
|
||||
* compress only a section of the input file and to store
|
||||
* the compressed output along with the input as "C" strings.
|
||||
*
|
||||
* Compiling instructions:
|
||||
* Borland C++ 16-bit (large memory model is required):
|
||||
* bcc -ml scpack.c
|
||||
*
|
||||
* Watcom C/C++ 32-bit:
|
||||
* wcl386 scpack.c
|
||||
*
|
||||
* GNU C (Linux), 32-bit:
|
||||
* gcc scpack.c -o scpack
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if UINT_MAX > 0xFFFFU
|
||||
#define MAXSIZE 1024*1024L
|
||||
#else
|
||||
#define MAXSIZE UINT_MAX /* Input file buffer size */
|
||||
#endif
|
||||
#define HASHSIZE 8192 /* Hash table size, power of 2 */
|
||||
#define THRESHOLD 3 /* Increase for speed, min 3 */
|
||||
|
||||
#define START_TOKEN "#ifdef SCPACK" /* start reading the buffer here */
|
||||
#define NAME_TOKEN "#define SCPACK_TABLE"
|
||||
#define SEP_TOKEN "#define SCPACK_SEPARATOR"
|
||||
#define TERM_TOKEN "#define SCPACK_TERMINATOR"
|
||||
#define TEMPFILE "~SCPACK.TMP"
|
||||
static char tablename[32+1] = "scpack_table";
|
||||
static char separator[16]=",";
|
||||
static char terminator[16]="";
|
||||
|
||||
int compress(unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2])
|
||||
{
|
||||
unsigned char *left, *right, *count;
|
||||
unsigned char a, b, bestcount;
|
||||
unsigned i, j, index, bestindex, code=128;
|
||||
|
||||
/* Dynamically allocate buffers and check for errors */
|
||||
left = (unsigned char *)malloc(HASHSIZE);
|
||||
right = (unsigned char *)malloc(HASHSIZE);
|
||||
count = (unsigned char *)malloc(HASHSIZE);
|
||||
if (left==NULL || right==NULL || count==NULL) {
|
||||
printf("Error allocating memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check for errors */
|
||||
for (i=0; i<buffersize; i++)
|
||||
if (buffer[i] > 127) {
|
||||
printf("This program works only on text files (7-bit ASCII)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(pairtable, 0, 128*2*sizeof(char));
|
||||
|
||||
do { /* Replace frequent pairs with bytes 128..255 */
|
||||
|
||||
/* Enter counts of all byte pairs into hash table */
|
||||
memset(count,0,HASHSIZE);
|
||||
for (i=0; i<buffersize-1; i++) {
|
||||
a = buffer[i];
|
||||
b = buffer[i+1];
|
||||
/* ignore any pair with a '\0' */
|
||||
if (a == 0 || b == 0)
|
||||
continue;
|
||||
index = (a ^ (b << 6)) & (HASHSIZE-1);
|
||||
while ((left[index] != a || right[index] != b) &&
|
||||
count[index] != 0)
|
||||
index = (index + 1) & (HASHSIZE-1);
|
||||
left[index] = a;
|
||||
right[index] = b;
|
||||
if (count[index] < 255)
|
||||
count[index] += (unsigned char)1;
|
||||
}
|
||||
|
||||
/* Search hash table for most frequent pair */
|
||||
bestcount = THRESHOLD - 1;
|
||||
for (i=0; i<HASHSIZE; i++) {
|
||||
if (count[i] > bestcount) {
|
||||
bestcount = count[i];
|
||||
bestindex = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compress if enough occurrences of pair */
|
||||
if (bestcount >= THRESHOLD) {
|
||||
|
||||
/* Add pair to table using code as index */
|
||||
a = pairtable[code-128][0] = left[bestindex];
|
||||
b = pairtable[code-128][1] = right[bestindex];
|
||||
|
||||
/* Replace all pair occurrences with unused byte */
|
||||
for (i=0, j=0; i<buffersize; i++, j++)
|
||||
if (a == buffer[i] && b == buffer[i+1]) {
|
||||
buffer[j] = (unsigned char)code;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
buffer[j] = buffer[i];
|
||||
buffersize = j;
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while (++code < 255);
|
||||
|
||||
/* done */
|
||||
free(left); free(right); free(count);
|
||||
return buffersize; /* return adjusted buffersize */
|
||||
}
|
||||
|
||||
static int strmatch(char *str, char *token, int *indent)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* skip whitespace */
|
||||
while (*str==' ' || *str=='\t') {
|
||||
str++;
|
||||
i++;
|
||||
} /* while */
|
||||
if (strncmp(str,token,strlen(token))!=0)
|
||||
return 0;
|
||||
if (indent != NULL)
|
||||
*indent = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void check_if(char *str,int linenr)
|
||||
{
|
||||
if (strmatch(str,"#if",NULL)) {
|
||||
printf("Error: \"#if...\" preprocessor statement should not be in SCPACK section "
|
||||
"(line %d)\n", linenr);
|
||||
exit(1);
|
||||
} /* if */
|
||||
}
|
||||
|
||||
static int check_tablename(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strmatch(str,NAME_TOKEN,NULL)) {
|
||||
str += strlen(NAME_TOKEN);
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
for (i=0; i<(sizeof tablename - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
|
||||
tablename[i] = *str;
|
||||
tablename[i] = '\0';
|
||||
return 1;
|
||||
} /* if */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_separator(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strmatch(str,SEP_TOKEN,NULL)) {
|
||||
str += strlen(SEP_TOKEN);
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
for (i=0; i<(sizeof separator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
|
||||
separator[i] = *str;
|
||||
separator[i] = '\0';
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (strmatch(str,TERM_TOKEN,NULL)) {
|
||||
str += strlen(TERM_TOKEN);
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
for (i=0; i<(sizeof terminator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
|
||||
terminator[i] = *str;
|
||||
terminator[i] = '\0';
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* readbuffer
|
||||
* Reads in the input file and stores all strings in the
|
||||
* section between "#ifdef SCPACK" and "#else" in a buffer.
|
||||
* Only text that is between double quotes is added to the
|
||||
* buffer; the \" escape code is handled. Multiple strings
|
||||
* on one line are handled.
|
||||
*/
|
||||
unsigned readbuffer(FILE *input, unsigned char *buffer)
|
||||
{
|
||||
char str[256];
|
||||
unsigned buffersize;
|
||||
int i,linenr;
|
||||
|
||||
linenr=0;
|
||||
buffersize=0;
|
||||
|
||||
rewind(input);
|
||||
while (!feof(input)) {
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
linenr++;
|
||||
check_tablename(str);
|
||||
check_separator(str);
|
||||
if (strmatch(str,START_TOKEN,NULL))
|
||||
break;
|
||||
} /* while */
|
||||
if (!strmatch(str,START_TOKEN,NULL))
|
||||
return buffersize; /* no (more) section found, quit */
|
||||
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
linenr++;
|
||||
check_if(str,linenr);
|
||||
if (check_tablename(str))
|
||||
printf("Error: table name definition should not be in SCPACK section (line %d)\n", linenr);
|
||||
check_separator(str);
|
||||
if (strmatch(str,"#else",NULL))
|
||||
break; /* done */
|
||||
/* add to the buffer only what is between double quotes */
|
||||
i=0;
|
||||
do {
|
||||
while (str[i]!='\0' && str[i]!='"')
|
||||
i++;
|
||||
if (str[i]=='"') {
|
||||
/* we are in a string */
|
||||
i++;
|
||||
while (str[i]!='\0' && str[i]!='"') {
|
||||
/* handle escape sequences */
|
||||
if (str[i]=='\\') {
|
||||
i++;
|
||||
switch (str[i]) {
|
||||
case 'a': /* alarm */
|
||||
buffer[buffersize++]='\a';
|
||||
i++;
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
buffer[buffersize++]='\b';
|
||||
i++;
|
||||
break;
|
||||
case 'f': /* form feed */
|
||||
buffer[buffersize++]='\f';
|
||||
i++;
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
buffer[buffersize++]='\n';
|
||||
i++;
|
||||
break;
|
||||
case 'r': /* carriage return */
|
||||
buffer[buffersize++]='\n';
|
||||
i++;
|
||||
break;
|
||||
case 't': /* tab */
|
||||
buffer[buffersize++]='\t';
|
||||
i++;
|
||||
break;
|
||||
case '\'':
|
||||
buffer[buffersize++]='\'';
|
||||
i++;
|
||||
break;
|
||||
case '"':
|
||||
buffer[buffersize++]='"';
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
// ??? octal character code escapes and hexadecimal escapes
|
||||
// not supported
|
||||
printf("Unknown escape sequence '\\%c' on line %d\n",
|
||||
str[i], linenr);
|
||||
} /* switch */
|
||||
} else {
|
||||
buffer[buffersize++]=str[i++];
|
||||
} /* if */
|
||||
} /* while */
|
||||
if (str[i]=='"') {
|
||||
buffer[buffersize++]='\0'; /* terminate each string */
|
||||
i++;
|
||||
} else {
|
||||
printf("Error: unterminated string on line %d\n",linenr);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} while (str[i]!='\0');
|
||||
} /* while - in SCPACK section */
|
||||
/* put in another '\0' to terminate the section */
|
||||
buffer[buffersize++]='\0';
|
||||
} /* while - !feof(input) */
|
||||
return buffersize;
|
||||
}
|
||||
|
||||
static void write_pairtable(FILE *output, unsigned char pairtable[128][2], char *tablename)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* dump the pair table */
|
||||
fprintf(output, "/*-*SCPACK start of pair table, do not change or remove this line */\n");
|
||||
fprintf(output, "unsigned char %s[][2] = {", tablename);
|
||||
for (i=0; i<128 && pairtable[i][0]!=0 && pairtable[i][1]!=0; i++) {
|
||||
if ((i % 16)==0)
|
||||
fprintf(output, "\n ");
|
||||
else
|
||||
fprintf(output, " ");
|
||||
fprintf(output, "{%d,%d}", pairtable[i][0], pairtable[i][1]);
|
||||
/* check if something follows this pair */
|
||||
if (i+1<128 && pairtable[i+1][0]!=0 && pairtable[i+1][1]!=0)
|
||||
fprintf(output, ",");
|
||||
} /* for */
|
||||
fprintf(output, "\n};\n");
|
||||
fprintf(output, "/*-*SCPACK end of pair table, do not change or remove this line */\n");
|
||||
}
|
||||
|
||||
void writefile(FILE *input, FILE *output, unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2])
|
||||
{
|
||||
char str[256];
|
||||
int insection, indent, needseparator;
|
||||
unsigned char *bufptr;
|
||||
|
||||
bufptr = buffer;
|
||||
insection = 0;
|
||||
|
||||
rewind(input);
|
||||
while (!feof(input)) {
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
fprintf(output,"%s",str);
|
||||
if (check_tablename(str)) {
|
||||
write_pairtable(output, pairtable, tablename);
|
||||
/* strip an existing pair table from the file */
|
||||
if (fgets(str,sizeof str,input)!=NULL) {
|
||||
if (strmatch(str,"/*-*SCPACK",NULL)) {
|
||||
while (fgets(str,sizeof str,input)!=NULL)
|
||||
if (strmatch(str,"/*-*SCPACK",NULL))
|
||||
break;
|
||||
} else {
|
||||
fprintf(output,"%s",str);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
if (strmatch(str,START_TOKEN,NULL))
|
||||
insection = 1;
|
||||
if (insection && strmatch(str,"#else",NULL))
|
||||
break;
|
||||
} /* while */
|
||||
if (!strmatch(str,"#else",&indent))
|
||||
return; /* no (more) section found, quit */
|
||||
insection=0;
|
||||
|
||||
/* dump the buffer as strings, separated with commas */
|
||||
needseparator = 0;
|
||||
while (*bufptr != '\0') {
|
||||
assert((unsigned)(bufptr-buffer) < buffersize);
|
||||
if (needseparator)
|
||||
fprintf(output, "%s\n",separator);
|
||||
fprintf(output, "%*c\"",indent+2,' ');
|
||||
/* loop over string */
|
||||
while (*bufptr != '\0') {
|
||||
if (*bufptr<' ' || *bufptr >= 128 || *bufptr == '"' || *bufptr == '\\')
|
||||
fprintf(output, "\\%03o", *bufptr);
|
||||
else
|
||||
fprintf(output, "%c", *bufptr);
|
||||
bufptr++;
|
||||
} /* while */
|
||||
fprintf(output, "\"");
|
||||
needseparator = 1;
|
||||
bufptr++; /* skip '\0' */
|
||||
} /* while */
|
||||
fprintf(output, "%s\n",terminator);
|
||||
bufptr++;
|
||||
|
||||
/* skip the input file until the #endif section */
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
if (strmatch(str,"#endif",NULL)) {
|
||||
fprintf(output,"%s",str);
|
||||
break; /* done */
|
||||
} /* if */
|
||||
} /* while */
|
||||
} /* while - !feof(input) */
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: scpack <filename> [output file]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *in, *out;
|
||||
unsigned char *buffer;
|
||||
unsigned buffersize, orgbuffersize;
|
||||
unsigned char pairtable[128][2];
|
||||
|
||||
if (argc < 2 || argc > 3)
|
||||
usage();
|
||||
if ((in=fopen(argv[1],"rt"))==NULL) {
|
||||
printf("SCPACK: error opening input %s\n",argv[1]);
|
||||
usage();
|
||||
} /* if */
|
||||
if (argc == 2) {
|
||||
if ((out=fopen(TEMPFILE,"wt"))==NULL) {
|
||||
printf("SCPACK: error opening temporary file %s\n",TEMPFILE);
|
||||
usage();
|
||||
} /* if */
|
||||
} else {
|
||||
if ((out=fopen(argv[2],"wt"))==NULL) {
|
||||
printf("SCPACK: error opening output file %s\n",argv[2]);
|
||||
usage();
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
buffer = (unsigned char *)malloc(MAXSIZE);
|
||||
if (buffer == NULL) {
|
||||
printf("SCPACK: error allocating memory\n");
|
||||
return 1;
|
||||
} /* if */
|
||||
/* 1. read the buffer
|
||||
* 2. compress the buffer
|
||||
* 3. copy the file, insert the compressed buffer
|
||||
*/
|
||||
buffersize = readbuffer(in, buffer);
|
||||
orgbuffersize = buffersize;
|
||||
if (buffersize > 0) {
|
||||
buffersize = compress(buffer, buffersize, pairtable);
|
||||
writefile(in, out, buffer, buffersize, pairtable);
|
||||
printf("SCPACK: compression ratio: %ld%% (%d -> %d)\n",
|
||||
100L-(100L*buffersize)/orgbuffersize, orgbuffersize, buffersize);
|
||||
} else {
|
||||
printf("SCPACK: no SCPACK section found, nothing to do\n");
|
||||
} /* if */
|
||||
fclose(out);
|
||||
fclose(in);
|
||||
/* let the new file replace the old file */
|
||||
if (buffersize == 0) {
|
||||
if (argc == 2)
|
||||
remove(TEMPFILE);
|
||||
else
|
||||
remove(argv[2]);
|
||||
} else if (argc == 2) {
|
||||
remove(argv[1]);
|
||||
rename(TEMPFILE,argv[1]);
|
||||
} /* if */
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
/* Pawn compiler
|
||||
*
|
||||
* Machine and state maintenance.
|
||||
*
|
||||
* Three lists are maintained here:
|
||||
* - A list of automatons (state machines): these hold a name, a unique id
|
||||
* (in the "index" field) and the memory address of a cell that holds the
|
||||
* current state of the automaton (in the "value" field).
|
||||
* - A list of states for each automaton: a name, an automaton id (in the
|
||||
* "index" field) and a unique id for the state (unique in the automaton;
|
||||
* states belonging to different automatons may have the same id).
|
||||
* - A list of state combinations. Each function may belong to a set of states.
|
||||
* This list assigns a unique id to the combination of the automaton and all
|
||||
* states.
|
||||
*
|
||||
* For a function/variable that has states, there is a fourth list, which is
|
||||
* attached to the "symbol" structure. This list contains the code label (in
|
||||
* the "name" field, only for functions), the id of the state combinations (the
|
||||
* state list id; it is stored in the "index" field) and the code address at
|
||||
* which the function starts. The latter is currently unused.
|
||||
*
|
||||
* At the start of the compiled code, a set of stub functions is generated.
|
||||
* Each stub function looks up the value of the "state selector" value for the
|
||||
* automaton, and goes with a "switch" instruction to the start address of the
|
||||
* function. This happens in SC4.C.
|
||||
*
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2005-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#endif
|
||||
|
||||
typedef struct s_statelist {
|
||||
struct s_statelist *next;
|
||||
int *states; /* list of states in this combination */
|
||||
int numstates; /* number of items in the above list */
|
||||
int fsa; /* automaton id */
|
||||
int listid; /* unique id for this combination list */
|
||||
} statelist;
|
||||
|
||||
static statelist statelist_tab = { NULL, NULL, 0, 0, 0}; /* state combinations table */
|
||||
|
||||
|
||||
static constvalue *find_automaton(const char *name,int *last)
|
||||
{
|
||||
constvalue *ptr;
|
||||
|
||||
assert(last!=NULL);
|
||||
*last=0;
|
||||
ptr=sc_automaton_tab.next;
|
||||
while (ptr!=NULL) {
|
||||
if (strcmp(name,ptr->name)==0)
|
||||
return ptr;
|
||||
if (ptr->index>*last)
|
||||
*last=ptr->index;
|
||||
ptr=ptr->next;
|
||||
} /* while */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *automaton_add(const char *name)
|
||||
{
|
||||
constvalue *ptr;
|
||||
int last;
|
||||
|
||||
assert(strlen(name)<sizeof(ptr->name));
|
||||
ptr=find_automaton(name,&last);
|
||||
if (ptr==NULL) {
|
||||
assert(last+1 <= SHRT_MAX);
|
||||
ptr=append_constval(&sc_automaton_tab,name,(cell)0,(short)(last+1));
|
||||
} /* if */
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *automaton_find(const char *name)
|
||||
{
|
||||
int last;
|
||||
return find_automaton(name,&last);
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *automaton_findid(int id)
|
||||
{
|
||||
constvalue *ptr;
|
||||
for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next)
|
||||
/* nothing */;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
static constvalue *find_state(const char *name,int fsa,int *last)
|
||||
{
|
||||
constvalue *ptr;
|
||||
|
||||
assert(last!=NULL);
|
||||
*last=0;
|
||||
ptr=sc_state_tab.next;
|
||||
while (ptr!=NULL) {
|
||||
if (ptr->index==fsa) {
|
||||
if (strcmp(name,ptr->name)==0)
|
||||
return ptr;
|
||||
if ((int)ptr->value>*last)
|
||||
*last=(int)ptr->value;
|
||||
} /* if */
|
||||
ptr=ptr->next;
|
||||
} /* while */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *state_add(const char *name,int fsa)
|
||||
{
|
||||
constvalue *ptr;
|
||||
int last;
|
||||
|
||||
assert(strlen(name)<sizeof(ptr->name));
|
||||
ptr=find_state(name,fsa,&last);
|
||||
if (ptr==NULL) {
|
||||
assert(fsa <= SHRT_MAX);
|
||||
ptr=append_constval(&sc_state_tab,name,(cell)(last+1),(short)fsa);
|
||||
} /* if */
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *state_find(const char *name,int fsa_id)
|
||||
{
|
||||
int last; /* dummy */
|
||||
return find_state(name,fsa_id,&last);
|
||||
}
|
||||
|
||||
SC_FUNC constvalue *state_findid(int id)
|
||||
{
|
||||
constvalue *ptr;
|
||||
for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next)
|
||||
/* nothing */;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid)
|
||||
{
|
||||
int idx;
|
||||
|
||||
assert(list!=NULL);
|
||||
assert(listsize!=NULL);
|
||||
assert(*listsize>=0);
|
||||
assert(count!=NULL);
|
||||
assert(*count>=0);
|
||||
assert(*count<=*listsize);
|
||||
|
||||
if (*count==*listsize) {
|
||||
/* To avoid constantly calling malloc(), the list is grown by 4 states at
|
||||
* a time.
|
||||
*/
|
||||
*listsize+=4;
|
||||
*list=(int*)realloc(*list,*listsize*sizeof(int));
|
||||
if (*list==NULL)
|
||||
error(103); /* insufficient memory */
|
||||
} /* if */
|
||||
|
||||
/* find the insertion point (the list has to stay sorted) */
|
||||
for (idx=0; idx<*count && *list[idx]<stateid; idx++)
|
||||
/* nothing */;
|
||||
if (idx<*count)
|
||||
memmove(&(*list)[idx+1],&(*list)[idx],(int)((*count-idx+1)*sizeof(int)));
|
||||
(*list)[idx]=stateid;
|
||||
*count+=1;
|
||||
}
|
||||
|
||||
static statelist *state_findlist(int *list,int count,int fsa,int *last)
|
||||
{
|
||||
statelist *ptr;
|
||||
int i;
|
||||
|
||||
assert(count>0);
|
||||
assert(last!=NULL);
|
||||
*last=0;
|
||||
ptr=statelist_tab.next;
|
||||
while (ptr!=NULL) {
|
||||
if (ptr->listid>*last)
|
||||
*last=ptr->listid;
|
||||
if (ptr->fsa==fsa && ptr->numstates==count) {
|
||||
/* compare all states */
|
||||
for (i=0; i<count && ptr->states[i]==list[i]; i++)
|
||||
/* nothing */;
|
||||
if (i==count)
|
||||
return ptr;
|
||||
} /* if */
|
||||
ptr=ptr->next;
|
||||
} /* while */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static statelist *state_getlist_ptr(int listid)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
assert(listid>0);
|
||||
for (ptr=statelist_tab.next; ptr!=NULL && ptr->listid!=listid; ptr=ptr->next)
|
||||
/* nothing */;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SC_FUNC int state_addlist(int *list,int count,int fsa)
|
||||
{
|
||||
statelist *ptr;
|
||||
int last;
|
||||
|
||||
assert(list!=NULL);
|
||||
assert(count>0);
|
||||
ptr=state_findlist(list,count,fsa,&last);
|
||||
if (ptr==NULL) {
|
||||
if ((ptr=(statelist*)malloc(sizeof(statelist)))==NULL)
|
||||
error(103); /* insufficient memory */
|
||||
if ((ptr->states=(int*)malloc(count*sizeof(int)))==NULL) {
|
||||
free(ptr);
|
||||
error(103); /* insufficient memory */
|
||||
} /* if */
|
||||
memcpy(ptr->states,list,count*sizeof(int));
|
||||
ptr->numstates=count;
|
||||
ptr->fsa=fsa;
|
||||
ptr->listid=last+1;
|
||||
ptr->next=statelist_tab.next;
|
||||
statelist_tab.next=ptr;
|
||||
} /* if */
|
||||
assert(ptr!=NULL);
|
||||
return ptr->listid;
|
||||
}
|
||||
|
||||
SC_FUNC void state_deletetable(void)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
while (statelist_tab.next!=NULL) {
|
||||
ptr=statelist_tab.next;
|
||||
/* unlink first */
|
||||
statelist_tab.next=ptr->next;
|
||||
/* then delete */
|
||||
assert(ptr->states!=NULL);
|
||||
free(ptr->states);
|
||||
free(ptr);
|
||||
} /* while */
|
||||
}
|
||||
|
||||
SC_FUNC int state_getfsa(int listid)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
assert(listid>=0);
|
||||
if (listid==0)
|
||||
return -1;
|
||||
|
||||
ptr=state_getlist_ptr(listid);
|
||||
return (ptr!=NULL) ? ptr->fsa : -1; /* fsa 0 exists */
|
||||
}
|
||||
|
||||
SC_FUNC int state_count(int listid)
|
||||
{
|
||||
statelist *ptr=state_getlist_ptr(listid);
|
||||
if (ptr==NULL)
|
||||
return 0; /* unknown list, no states in it */
|
||||
return ptr->numstates;
|
||||
}
|
||||
|
||||
SC_FUNC int state_inlist(int listid,int state)
|
||||
{
|
||||
statelist *ptr;
|
||||
int i;
|
||||
|
||||
ptr=state_getlist_ptr(listid);
|
||||
if (ptr==NULL)
|
||||
return FALSE; /* unknown list, state not in it */
|
||||
for (i=0; i<ptr->numstates; i++)
|
||||
if (ptr->states[i]==state)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SC_FUNC int state_listitem(int listid,int index)
|
||||
{
|
||||
statelist *ptr;
|
||||
|
||||
ptr=state_getlist_ptr(listid);
|
||||
assert(ptr!=NULL);
|
||||
assert(index>=0 && index<ptr->numstates);
|
||||
return ptr->states[index];
|
||||
}
|
||||
|
||||
static int checkconflict(statelist *psrc,statelist *ptgt)
|
||||
{
|
||||
int s,t;
|
||||
|
||||
assert(psrc!=NULL);
|
||||
assert(ptgt!=NULL);
|
||||
for (s=0; s<psrc->numstates; s++)
|
||||
for (t=0; t<ptgt->numstates; t++)
|
||||
if (psrc->states[s]==ptgt->states[t])
|
||||
return 1; /* state conflict */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function searches whether one of the states in the list of statelist id's
|
||||
* of a symbol exists in any other statelist id's of the same function; it also
|
||||
* verifies that all definitions of the symbol are in the same automaton.
|
||||
*/
|
||||
SC_FUNC void state_conflict(symbol *root)
|
||||
{
|
||||
statelist *psrc,*ptgt;
|
||||
constvalue *srcptr,*tgtptr;
|
||||
symbol *sym;
|
||||
|
||||
assert(root!=NULL);
|
||||
for (sym=root->next; sym!=NULL; sym=sym->next) {
|
||||
if (sym->parent!=NULL || sym->ident!=iFUNCTN)
|
||||
continue; /* hierarchical data type or no function */
|
||||
if (sym->states==NULL)
|
||||
continue; /* this function has no states */
|
||||
for (srcptr=sym->states->next; srcptr!=NULL; srcptr=srcptr->next) {
|
||||
if (srcptr->index==-1)
|
||||
continue; /* state list id -1 is a special case */
|
||||
psrc=state_getlist_ptr(srcptr->index);
|
||||
assert(psrc!=NULL);
|
||||
for (tgtptr=srcptr->next; tgtptr!=NULL; tgtptr=tgtptr->next) {
|
||||
if (tgtptr->index==-1)
|
||||
continue; /* state list id -1 is a special case */
|
||||
ptgt=state_getlist_ptr(tgtptr->index);
|
||||
assert(ptgt!=NULL);
|
||||
if (psrc->fsa!=ptgt->fsa && strcmp(sym->name,uENTRYFUNC)!=0)
|
||||
error(83,sym->name); /* this function is part of another machine */
|
||||
if (checkconflict(psrc,ptgt))
|
||||
error(84,sym->name); /* state conflict */
|
||||
} /* for (tgtptr) */
|
||||
} /* for (srcptr) */
|
||||
} /* for (sym) */
|
||||
}
|
||||
|
||||
/* check whether the two state lists (whose ids are passed in) share any
|
||||
* states
|
||||
*/
|
||||
SC_FUNC int state_conflict_id(int listid1,int listid2)
|
||||
{
|
||||
statelist *psrc,*ptgt;
|
||||
|
||||
psrc=state_getlist_ptr(listid1);
|
||||
assert(psrc!=NULL);
|
||||
ptgt=state_getlist_ptr(listid2);
|
||||
assert(ptgt!=NULL);
|
||||
return checkconflict(psrc,ptgt);
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sc.h"
|
||||
#include "sctracker.h"
|
||||
|
||||
memuse_list_t *heapusage = NULL;
|
||||
memuse_list_t *stackusage = NULL;
|
||||
funcenum_t *firstenum = NULL;
|
||||
funcenum_t *lastenum = NULL;
|
||||
pstruct_t *firststruct = NULL;
|
||||
pstruct_t *laststruct = NULL;
|
||||
|
||||
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<pstruct->argcount; i++)
|
||||
{
|
||||
if (strcmp(pstruct->args[i]->name, member) == 0)
|
||||
{
|
||||
return pstruct->args[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pstruct_t *pstructs_add(const char *name)
|
||||
{
|
||||
pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
|
||||
|
||||
memset(p, 0, sizeof(pstruct_t));
|
||||
strcpy(p->name, name);
|
||||
|
||||
if (!firststruct)
|
||||
{
|
||||
firststruct = p;
|
||||
laststruct = p;
|
||||
} else {
|
||||
laststruct->next = p;
|
||||
laststruct = p;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void pstructs_free()
|
||||
{
|
||||
pstruct_t *p, *next;
|
||||
|
||||
p = firststruct;
|
||||
while (p)
|
||||
{
|
||||
while (p->argcount--)
|
||||
{
|
||||
free(p->args[p->argcount]);
|
||||
}
|
||||
free(p->args);
|
||||
next = p->next;
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
firststruct = NULL;
|
||||
laststruct = NULL;
|
||||
}
|
||||
|
||||
pstruct_t *pstructs_find(const char *name)
|
||||
{
|
||||
pstruct_t *p = firststruct;
|
||||
|
||||
while (p)
|
||||
{
|
||||
if (strcmp(p->name, name) == 0)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
|
||||
{
|
||||
structarg_t *newarg;
|
||||
int i;
|
||||
|
||||
for (i=0; i<pstruct->argcount; i++)
|
||||
{
|
||||
if (strcmp(pstruct->args[i]->name, arg->name) == 0)
|
||||
{
|
||||
/* Don't allow dup names */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
newarg = (structarg_t *)malloc(sizeof(structarg_t));
|
||||
|
||||
memcpy(newarg, arg, sizeof(structarg_t));
|
||||
|
||||
if (pstruct->argcount == 0)
|
||||
{
|
||||
pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
|
||||
} else {
|
||||
pstruct->args = (structarg_t **)realloc(
|
||||
pstruct->args,
|
||||
sizeof(structarg_t *) * (pstruct->argcount + 1));
|
||||
}
|
||||
|
||||
newarg->offs = pstruct->argcount * sizeof(cell);
|
||||
newarg->index = pstruct->argcount;
|
||||
pstruct->args[pstruct->argcount++] = newarg;
|
||||
|
||||
return newarg;
|
||||
}
|
||||
|
||||
void funcenums_free()
|
||||
{
|
||||
funcenum_t *e, *next;
|
||||
|
||||
e = firstenum;
|
||||
while (e)
|
||||
{
|
||||
functag_t *tag, *nexttag;
|
||||
tag = e->first;
|
||||
while (tag)
|
||||
{
|
||||
nexttag = tag->next;
|
||||
free(tag);
|
||||
tag = nexttag;
|
||||
}
|
||||
next = e->next;
|
||||
free(e);
|
||||
e = next;
|
||||
}
|
||||
|
||||
firstenum = NULL;
|
||||
lastenum = NULL;
|
||||
}
|
||||
|
||||
funcenum_t *funcenums_find_byval(int value)
|
||||
{
|
||||
funcenum_t *e = firstenum;
|
||||
|
||||
while (e)
|
||||
{
|
||||
if (e->value == value)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
funcenum_t *funcenums_add(const char *name)
|
||||
{
|
||||
funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
|
||||
|
||||
memset(e, 0, sizeof(funcenum_t));
|
||||
|
||||
if (firstenum == NULL)
|
||||
{
|
||||
firstenum = e;
|
||||
lastenum = e;
|
||||
} else {
|
||||
lastenum->next = e;
|
||||
lastenum = e;
|
||||
}
|
||||
|
||||
strcpy(e->name, name);
|
||||
e->value = pc_addfunctag((char *)name);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
functag_t *functags_add(funcenum_t *en, functag_t *src)
|
||||
{
|
||||
functag_t *t = (functag_t *)malloc(sizeof(functag_t));
|
||||
|
||||
memcpy(t, src, sizeof(functag_t));
|
||||
|
||||
t->next = NULL;
|
||||
|
||||
if (en->first == NULL)
|
||||
{
|
||||
en->first = t;
|
||||
en->last = t;
|
||||
} else {
|
||||
en->last->next = t;
|
||||
en->last = t;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new mem usage tracker entry
|
||||
*/
|
||||
void _push_memlist(memuse_list_t **head)
|
||||
{
|
||||
memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t));
|
||||
if (*head != NULL)
|
||||
{
|
||||
newlist->list_id = (*head)->list_id + 1;
|
||||
} else {
|
||||
newlist->list_id = 0;
|
||||
}
|
||||
newlist->prev = *head;
|
||||
newlist->head = NULL;
|
||||
*head = newlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a heap list but does not free it.
|
||||
*/
|
||||
memuse_list_t *_pop_save_memlist(memuse_list_t **head)
|
||||
{
|
||||
memuse_list_t *oldlist = *head;
|
||||
*head = (*head)->prev;
|
||||
return oldlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a memory usage on a memory list
|
||||
*/
|
||||
int _mark_memlist(memuse_list_t *head, int type, int size)
|
||||
{
|
||||
memuse_t *use;
|
||||
if (type==MEMUSE_STATIC && size==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
use=head->head;
|
||||
if (use && (type==MEMUSE_STATIC)
|
||||
&& (use->type == type))
|
||||
{
|
||||
use->size += size;
|
||||
} else {
|
||||
use=(memuse_t *)malloc(sizeof(memuse_t));
|
||||
use->type=type;
|
||||
use->size=size;
|
||||
use->prev=head->head;
|
||||
head->head=use;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void _reset_memlist(memuse_list_t **head)
|
||||
{
|
||||
memuse_list_t *curlist = *head;
|
||||
memuse_list_t *tmplist;
|
||||
while (curlist) {
|
||||
memuse_t *curuse = curlist->head;
|
||||
memuse_t *tmpuse;
|
||||
while (curuse) {
|
||||
tmpuse = curuse->prev;
|
||||
free(curuse);
|
||||
curuse = tmpuse;
|
||||
}
|
||||
tmplist = curlist->prev;
|
||||
free(curlist);
|
||||
curlist = tmplist;
|
||||
}
|
||||
*head = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for pushing the heap list
|
||||
*/
|
||||
void pushheaplist()
|
||||
{
|
||||
_push_memlist(&heapusage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for popping and saving the heap list
|
||||
*/
|
||||
memuse_list_t *popsaveheaplist()
|
||||
{
|
||||
return _pop_save_memlist(&heapusage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for marking the heap
|
||||
*/
|
||||
int markheap(int type, int size)
|
||||
{
|
||||
return _mark_memlist(heapusage, type, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for pushing the stack list
|
||||
*/
|
||||
void pushstacklist()
|
||||
{
|
||||
_push_memlist(&stackusage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for marking the stack
|
||||
*/
|
||||
int markstack(int type, int size)
|
||||
{
|
||||
return _mark_memlist(stackusage, type, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates code to free all heap allocations on a tracker
|
||||
*/
|
||||
void _heap_freeusage(memuse_list_t *heap, int dofree)
|
||||
{
|
||||
memuse_t *cur=heap->head;
|
||||
memuse_t *tmp;
|
||||
while (cur)
|
||||
{
|
||||
if (cur->type == MEMUSE_STATIC)
|
||||
{
|
||||
modheap((-1)*cur->size*sizeof(cell));
|
||||
} else {
|
||||
modheap_i();
|
||||
}
|
||||
if (dofree)
|
||||
{
|
||||
tmp=cur->prev;
|
||||
free(cur);
|
||||
cur=tmp;
|
||||
} else {
|
||||
cur=cur->prev;
|
||||
}
|
||||
}
|
||||
if (dofree)
|
||||
{
|
||||
heap->head=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void _stack_genusage(memuse_list_t *stack, int dofree)
|
||||
{
|
||||
memuse_t *cur = stack->head;
|
||||
memuse_t *tmp;
|
||||
while (cur)
|
||||
{
|
||||
if (cur->type == MEMUSE_DYNAMIC)
|
||||
{
|
||||
/* no idea yet */
|
||||
assert(0);
|
||||
} else {
|
||||
modstk(cur->size * sizeof(cell));
|
||||
}
|
||||
if (dofree)
|
||||
{
|
||||
tmp = cur->prev;
|
||||
free(cur);
|
||||
cur = tmp;
|
||||
} else {
|
||||
cur = cur->prev;
|
||||
}
|
||||
}
|
||||
if (dofree)
|
||||
{
|
||||
stack->head = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a heap list and frees it.
|
||||
*/
|
||||
void popheaplist()
|
||||
{
|
||||
memuse_list_t *oldlist;
|
||||
assert(heapusage!=NULL);
|
||||
|
||||
_heap_freeusage(heapusage, 1);
|
||||
assert(heapusage->head==NULL);
|
||||
|
||||
oldlist=heapusage->prev;
|
||||
free(heapusage);
|
||||
heapusage=oldlist;
|
||||
}
|
||||
|
||||
void genstackfree(int stop_id)
|
||||
{
|
||||
memuse_list_t *curlist = stackusage;
|
||||
while (curlist && curlist->list_id > stop_id)
|
||||
{
|
||||
_stack_genusage(curlist, 0);
|
||||
curlist = curlist->prev;
|
||||
}
|
||||
}
|
||||
|
||||
void genheapfree(int stop_id)
|
||||
{
|
||||
memuse_list_t *curlist = heapusage;
|
||||
while (curlist && curlist->list_id > stop_id)
|
||||
{
|
||||
_heap_freeusage(curlist, 0);
|
||||
curlist = curlist->prev;
|
||||
}
|
||||
}
|
||||
|
||||
void popstacklist(int codegen)
|
||||
{
|
||||
memuse_list_t *oldlist;
|
||||
assert(stackusage != NULL);
|
||||
|
||||
if (codegen)
|
||||
{
|
||||
_stack_genusage(stackusage, 1);
|
||||
assert(stackusage->head==NULL);
|
||||
}
|
||||
|
||||
oldlist = stackusage->prev;
|
||||
free(stackusage);
|
||||
stackusage = oldlist;
|
||||
}
|
||||
|
||||
void resetstacklist()
|
||||
{
|
||||
_reset_memlist(&stackusage);
|
||||
}
|
||||
|
||||
void resetheaplist()
|
||||
{
|
||||
_reset_memlist(&heapusage);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#ifndef _INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
|
||||
#define _INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
|
||||
|
||||
#define MEMUSE_STATIC 0
|
||||
#define MEMUSE_DYNAMIC 1
|
||||
|
||||
typedef struct memuse_s {
|
||||
int type; /* MEMUSE_STATIC or MEMUSE_DYNAMIC */
|
||||
int size; /* size of array for static (0 for dynamic) */
|
||||
struct memuse_s *prev; /* previous block on the list */
|
||||
} memuse_t;
|
||||
|
||||
typedef struct memuse_list_s {
|
||||
struct memuse_list_s *prev; /* last used list */
|
||||
int list_id;
|
||||
memuse_t *head; /* head of the current list */
|
||||
} memuse_list_t;
|
||||
|
||||
typedef struct funcarg_s
|
||||
{
|
||||
int tagcount;
|
||||
int tags[sTAGS_MAX];
|
||||
int dimcount;
|
||||
cell dims[sDIMEN_MAX];
|
||||
int ident;
|
||||
int fconst;
|
||||
int ommittable;
|
||||
} funcarg_t;
|
||||
|
||||
typedef struct functag_s
|
||||
{
|
||||
int ret_tag;
|
||||
int type;
|
||||
int argcount;
|
||||
int ommittable;
|
||||
funcarg_t args[sARGS_MAX];
|
||||
struct functag_s *next;
|
||||
} functag_t;
|
||||
|
||||
typedef struct funcenum_s
|
||||
{
|
||||
int value;
|
||||
char name[sNAMEMAX+1];
|
||||
functag_t *first;
|
||||
functag_t *last;
|
||||
struct funcenum_s *next;
|
||||
} funcenum_t;
|
||||
|
||||
typedef struct structarg_s
|
||||
{
|
||||
int tag;
|
||||
int dimcount;
|
||||
cell dims[sDIMEN_MAX];
|
||||
char name[sNAMEMAX+1];
|
||||
int fconst;
|
||||
int ident;
|
||||
unsigned int offs;
|
||||
int index;
|
||||
} structarg_t;
|
||||
|
||||
typedef struct pstruct_s
|
||||
{
|
||||
int argcount;
|
||||
char name[sNAMEMAX+1];
|
||||
structarg_t **args;
|
||||
struct pstruct_s *next;
|
||||
} pstruct_t;
|
||||
|
||||
/**
|
||||
* Pawn Structs
|
||||
*/
|
||||
pstruct_t *pstructs_add(const char *name);
|
||||
void pstructs_free();
|
||||
pstruct_t *pstructs_find(const char *name);
|
||||
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg);
|
||||
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member);
|
||||
|
||||
/**
|
||||
* Function enumeration tags
|
||||
*/
|
||||
void funcenums_free();
|
||||
funcenum_t *funcenums_add(const char *name);
|
||||
funcenum_t *funcenums_find_byval(int value);
|
||||
functag_t *functags_add(funcenum_t *en, functag_t *src);
|
||||
|
||||
/**
|
||||
* Heap functions
|
||||
*/
|
||||
void pushheaplist();
|
||||
memuse_list_t *popsaveheaplist();
|
||||
void popheaplist();
|
||||
int markheap(int type, int size);
|
||||
|
||||
/**
|
||||
* Stack functions
|
||||
*/
|
||||
void pushstacklist();
|
||||
void popstacklist(int codegen);
|
||||
int markstack(int type, int size);
|
||||
/**
|
||||
* Generates code to free mem usage, but does not pop the list.
|
||||
* This is used for code like dobreak()/docont()/doreturn().
|
||||
* stop_id is the list at which to stop generating.
|
||||
*/
|
||||
void genstackfree(int stop_id);
|
||||
void genheapfree(int stop_id);
|
||||
|
||||
/**
|
||||
* Resets a mem list by freeing everything
|
||||
*/
|
||||
void resetstacklist();
|
||||
void resetheaplist();
|
||||
|
||||
extern memuse_list_t *heapusage;
|
||||
extern memuse_list_t *stackusage;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
|
||||
@@ -0,0 +1,113 @@
|
||||
/* Pawn compiler
|
||||
*
|
||||
* Global (cross-module) variables.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for _MAX_PATH */
|
||||
#include "sc.h"
|
||||
|
||||
/* global variables
|
||||
*
|
||||
* All global variables that are shared amongst the compiler files are
|
||||
* declared here.
|
||||
*/
|
||||
SC_VDEFINE symbol loctab; /* local symbol table */
|
||||
SC_VDEFINE symbol glbtab; /* global symbol table */
|
||||
SC_VDEFINE cell *litq; /* the literal queue */
|
||||
SC_VDEFINE unsigned char pline[sLINEMAX+1]; /* the line read from the input file */
|
||||
SC_VDEFINE const unsigned char *lptr; /* points to the current position in "pline" */
|
||||
SC_VDEFINE constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */
|
||||
SC_VDEFINE constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */
|
||||
SC_VDEFINE constvalue *curlibrary = NULL; /* current library */
|
||||
SC_VDEFINE int pc_addlibtable = TRUE; /* is the library table added to the AMX file? */
|
||||
SC_VDEFINE symbol *curfunc; /* pointer to current function */
|
||||
SC_VDEFINE char *inpfname; /* pointer to name of the file currently read from */
|
||||
SC_VDEFINE char outfname[_MAX_PATH]; /* intermediate (assembler) file name */
|
||||
SC_VDEFINE char binfname[_MAX_PATH]; /* binary file name */
|
||||
SC_VDEFINE char errfname[_MAX_PATH]; /* error file name */
|
||||
SC_VDEFINE char sc_ctrlchar = CTRL_CHAR; /* the control character (or escape character)*/
|
||||
SC_VDEFINE char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */
|
||||
SC_VDEFINE int litidx = 0; /* index to literal table */
|
||||
SC_VDEFINE int litmax = sDEF_LITMAX; /* current size of the literal table */
|
||||
SC_VDEFINE int stgidx = 0; /* index to the staging buffer */
|
||||
SC_VDEFINE int sc_labnum = 0; /* number of (internal) labels */
|
||||
SC_VDEFINE int staging = 0; /* true if staging output */
|
||||
SC_VDEFINE cell declared = 0; /* number of local cells declared */
|
||||
SC_VDEFINE cell glb_declared=0; /* number of global cells declared */
|
||||
SC_VDEFINE cell code_idx = 0; /* number of bytes with generated code */
|
||||
SC_VDEFINE int ntv_funcid= 0; /* incremental number of native function */
|
||||
SC_VDEFINE int errnum = 0; /* number of errors */
|
||||
SC_VDEFINE int warnnum = 0; /* number of warnings */
|
||||
SC_VDEFINE int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */
|
||||
SC_VDEFINE int sc_packstr= FALSE; /* strings are packed by default? */
|
||||
SC_VDEFINE int sc_asmfile= FALSE; /* create .ASM file? */
|
||||
SC_VDEFINE int sc_listing= FALSE; /* create .LST file? */
|
||||
SC_VDEFINE int sc_compress=TRUE; /* compress bytecode? */
|
||||
SC_VDEFINE int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */
|
||||
SC_VDEFINE int sc_dataalign=sizeof(cell);/* data alignment value */
|
||||
SC_VDEFINE int sc_alignnext=FALSE; /* must frame of the next function be aligned? */
|
||||
SC_VDEFINE int pc_docexpr=FALSE; /* must expression be attached to documentation comment? */
|
||||
SC_VDEFINE int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */
|
||||
SC_VDEFINE cell pc_stksize=sDEF_AMXSTACK;/* default stack size */
|
||||
SC_VDEFINE cell pc_amxlimit=0; /* default abstract machine size limit = none */
|
||||
SC_VDEFINE cell pc_amxram=0; /* default abstract machine data size limit = none */
|
||||
SC_VDEFINE int freading = FALSE; /* Is there an input file ready for reading? */
|
||||
SC_VDEFINE int fline = 0; /* the line number in the current file */
|
||||
SC_VDEFINE short fnumber = 0; /* the file number in the file table (debugging) */
|
||||
SC_VDEFINE short fcurrent= 0; /* current file being processed (debugging) */
|
||||
SC_VDEFINE short sc_intest=FALSE; /* true if inside a test */
|
||||
SC_VDEFINE int sideeffect= 0; /* true if an expression causes a side-effect */
|
||||
SC_VDEFINE int stmtindent= 0; /* current indent of the statement */
|
||||
SC_VDEFINE int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */
|
||||
SC_VDEFINE int sc_tabsize=8; /* number of spaces that a TAB represents */
|
||||
SC_VDEFINE short sc_allowtags=TRUE; /* allow/detect tagnames in lex() */
|
||||
SC_VDEFINE int sc_status; /* read/write status */
|
||||
SC_VDEFINE int sc_rationaltag=0; /* tag for rational numbers */
|
||||
SC_VDEFINE int rational_digits=0; /* number of fractional digits */
|
||||
SC_VDEFINE int sc_allowproccall=0; /* allow/detect tagnames in lex() */
|
||||
SC_VDEFINE short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */
|
||||
SC_VDEFINE char *pc_deprecate=NULL;/* if non-null, mark next declaration as deprecated */
|
||||
SC_VDEFINE int sc_curstates=0; /* ID of the current state list */
|
||||
SC_VDEFINE int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */
|
||||
SC_VDEFINE int pc_memflags=0; /* special flags for the stack/heap usage */
|
||||
|
||||
SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
|
||||
SC_VDEFINE constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */
|
||||
|
||||
SC_VDEFINE FILE *inpf = NULL; /* file read from (source or include) */
|
||||
SC_VDEFINE FILE *inpf_org= NULL; /* main source file */
|
||||
SC_VDEFINE FILE *outf = NULL; /* (intermediate) text file written to */
|
||||
|
||||
SC_VDEFINE jmp_buf errbuf;
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */
|
||||
#endif
|
||||
|
||||
#if defined __WATCOMC__ && !defined NDEBUG
|
||||
/* Watcom's CVPACK dislikes .OBJ files without functions */
|
||||
static int dummyfunc(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,276 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "sp_file.h"
|
||||
#include "memfile.h"
|
||||
|
||||
void *mf_open(const char *name);
|
||||
void mf_close(void *handle);
|
||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle);
|
||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle);
|
||||
size_t mf_getpos(void *handle);
|
||||
int mf_setpos(void *handle, size_t pos);
|
||||
|
||||
sp_writefuncs_t cstd_funcs =
|
||||
{
|
||||
mf_open,
|
||||
mf_close,
|
||||
mf_write,
|
||||
mf_read,
|
||||
mf_getpos,
|
||||
mf_setpos
|
||||
};
|
||||
|
||||
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
|
||||
{
|
||||
sp_file_t file;
|
||||
sp_file_t *pFile;
|
||||
|
||||
if (!optfuncs)
|
||||
{
|
||||
optfuncs = &cstd_funcs;
|
||||
}
|
||||
|
||||
file.handle = optfuncs->fnOpen(name);
|
||||
if (!file.handle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFile = (sp_file_t *)malloc(sizeof(sp_file_t));
|
||||
|
||||
pFile->handle = file.handle;
|
||||
memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t));
|
||||
pFile->curoffs = 0;
|
||||
pFile->header.magic = SPFILE_MAGIC;
|
||||
pFile->header.sections = 0;
|
||||
pFile->header.stringtab = 0;
|
||||
pFile->header.version = SPFILE_VERSION;
|
||||
pFile->header.imagesize = 0;
|
||||
pFile->header.disksize = 0;
|
||||
pFile->header.compression = SPFILE_COMPRESSION_NONE;
|
||||
pFile->header.dataoffs = 0;
|
||||
pFile->lastsection = 0;
|
||||
pFile->offsets = NULL;
|
||||
pFile->sections = NULL;
|
||||
pFile->state = -1;
|
||||
pFile->nametab = NULL;
|
||||
pFile->nametab_idx = 0;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
void spfw_destroy(sp_file_t *spf)
|
||||
{
|
||||
free(spf->sections);
|
||||
free(spf->nametab);
|
||||
free(spf->offsets);
|
||||
spf->funcs.fnClose(spf->handle);
|
||||
free(spf);
|
||||
}
|
||||
|
||||
uint8_t spfw_add_section(sp_file_t *spf, const char *name)
|
||||
{
|
||||
size_t namelen;
|
||||
uint8_t s;
|
||||
if (spf->state != -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
namelen = strlen(name) + 1;
|
||||
|
||||
if (spf->header.sections == 0)
|
||||
{
|
||||
/** allocate for first section */
|
||||
spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t));
|
||||
spf->offsets = (size_t *)malloc(sizeof(size_t));
|
||||
spf->nametab = (char *)malloc(namelen);
|
||||
} else {
|
||||
uint16_t num = spf->header.sections + 1;
|
||||
spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num);
|
||||
spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num);
|
||||
spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen);
|
||||
}
|
||||
|
||||
s = spf->header.sections;
|
||||
|
||||
spf->sections[s].nameoffs = spf->nametab_idx;
|
||||
/**
|
||||
* "fix" offset will be the second uint2 slot, which is after the previous sections after the header.
|
||||
*/
|
||||
spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t);
|
||||
strcpy(&spf->nametab[spf->nametab_idx], name);
|
||||
spf->nametab_idx += namelen;
|
||||
|
||||
return ++spf->header.sections;
|
||||
}
|
||||
|
||||
int spfw_finalize_header(sp_file_t *spf)
|
||||
{
|
||||
uint32_t size;
|
||||
if (spf->state != -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = sizeof(sp_file_section_t) * spf->header.sections;
|
||||
|
||||
spf->header.stringtab = sizeof(spf->header) + size;
|
||||
spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx;
|
||||
if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) !=
|
||||
spf->header.sections)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->lastsection = spf->curoffs;
|
||||
spf->state++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spfw_next_section(sp_file_t *spf)
|
||||
{
|
||||
uint8_t s;
|
||||
uint32_t rest[2];
|
||||
|
||||
if (spf->state < 0 || spf->state > spf->header.sections)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spf->state == (int)spf->header.sections)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = (uint8_t)spf->state;
|
||||
|
||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, spf->offsets[s]);
|
||||
|
||||
rest[0] = spf->lastsection;
|
||||
rest[1] = spf->curoffs - spf->lastsection;
|
||||
if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
spf->funcs.fnSetPos(spf->handle, spf->curoffs);
|
||||
spf->lastsection = spf->curoffs;
|
||||
|
||||
spf->state++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int spfw_finalize_all(sp_file_t *spf)
|
||||
{
|
||||
uint8_t offs;
|
||||
|
||||
if (spf->state < spf->header.sections)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
offs = offsetof(sp_file_hdr_t, imagesize);
|
||||
spf->header.disksize = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, offs);
|
||||
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle);
|
||||
spf->funcs.fnSetPos(spf->handle, spf->header.imagesize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* More memory file operations
|
||||
*/
|
||||
|
||||
void *mf_open(const char *name)
|
||||
{
|
||||
return memfile_creat(name, 1024);
|
||||
}
|
||||
|
||||
void mf_close(void *handle)
|
||||
{
|
||||
memfile_destroy((memfile_t *)handle);
|
||||
}
|
||||
|
||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
if (!count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memfile_write((memfile_t *)handle, buf, size*count))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return memfile_read((memfile_t *)handle, buf, size*count) / count;
|
||||
}
|
||||
|
||||
size_t mf_getpos(void *handle)
|
||||
{
|
||||
return (long)memfile_tell((memfile_t *)handle);
|
||||
}
|
||||
|
||||
int mf_setpos(void *handle, size_t pos)
|
||||
{
|
||||
memfile_seek((memfile_t *)handle, (long)pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if UNUSED_FOR_NOW
|
||||
/**
|
||||
* Default file operations...
|
||||
* Based on C standard library calls.
|
||||
*/
|
||||
|
||||
void *fp_open(const char *name)
|
||||
{
|
||||
return fopen(name, "wb");
|
||||
}
|
||||
|
||||
void fp_close(void *handle)
|
||||
{
|
||||
fclose((FILE *)handle);
|
||||
}
|
||||
|
||||
size_t fp_write(const void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return fwrite(buf, size, count, (FILE *)handle);
|
||||
}
|
||||
|
||||
size_t fp_read(void *buf, size_t size, size_t count, void *handle)
|
||||
{
|
||||
return fread(buf, size, count, (FILE *)handle);
|
||||
}
|
||||
|
||||
size_t fp_getpos(void *handle)
|
||||
{
|
||||
return (size_t)ftell((FILE *)handle);
|
||||
}
|
||||
|
||||
int fp_setpos(void *handle, size_t pos)
|
||||
{
|
||||
return fseek((FILE *)handle, (long)pos, SEEK_SET);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef _INCLUDE_SPFILE_H
|
||||
#define _INCLUDE_SPFILE_H
|
||||
|
||||
#include "sp_file_headers.h"
|
||||
|
||||
/**
|
||||
* Used for overwriting writing routines.
|
||||
*/
|
||||
typedef struct sp_writefuncs_s
|
||||
{
|
||||
void *(*fnOpen)(const char *); /* filename, returns handle */
|
||||
void (*fnClose)(void *); /* handle */
|
||||
/* buffer, size, count, handle, returns count written */
|
||||
size_t (*fnWrite)(const void *, size_t, size_t, void *);
|
||||
/* buffer, size, count, handle, returns count read */
|
||||
size_t (*fnRead)(void *, size_t, size_t, void *);
|
||||
/* returns current position from start */
|
||||
size_t (*fnGetPos)(void *);
|
||||
/* sets current position from start, return 0 for success, nonzero for error */
|
||||
int (*fnSetPos)(void *, size_t);
|
||||
} sp_writefuncs_t;
|
||||
|
||||
typedef struct sp_file_s
|
||||
{
|
||||
sp_file_hdr_t header;
|
||||
sp_file_section_t *sections;
|
||||
size_t *offsets;
|
||||
sp_writefuncs_t funcs;
|
||||
size_t lastsection;
|
||||
size_t curoffs;
|
||||
void *handle;
|
||||
int state;
|
||||
char *nametab;
|
||||
size_t nametab_idx;
|
||||
} sp_file_t;
|
||||
|
||||
/**
|
||||
* Creates a new SourcePawn binary file.
|
||||
* You may optionally specify alternative writing functions.
|
||||
*/
|
||||
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs);
|
||||
|
||||
/**
|
||||
* Closes file handle and frees memory.
|
||||
*/
|
||||
void spfw_destroy(sp_file_t *spf);
|
||||
|
||||
/**
|
||||
* Adds a section name to the header.
|
||||
* Only valid BEFORE finalization.
|
||||
* Returns the number of sections, or 0 on failure.
|
||||
*/
|
||||
uint8_t spfw_add_section(sp_file_t *spf, const char *name);
|
||||
|
||||
/**
|
||||
* Finalizes the section header.
|
||||
* This means no more sections can be added after this call.
|
||||
* Also, aligns the writer to the first section.
|
||||
* Returns 0 on success, nonzero on error.
|
||||
*/
|
||||
int spfw_finalize_header(sp_file_t *spf);
|
||||
|
||||
/**
|
||||
* Finalizes the current section and advances to the next.
|
||||
* In order for this to be accurate, the file pointer must
|
||||
* reside at the end before calling this, because the size
|
||||
* is calculated by differencing with the last known offset.
|
||||
* Returns 1 if there are more sections left, 0 otherwise.
|
||||
* Returns -1 if the file state is wrong.
|
||||
*/
|
||||
int spfw_next_section(sp_file_t *spf);
|
||||
|
||||
/**
|
||||
* Finalizes all sections.
|
||||
* Cannot be called until all sections are used.
|
||||
* Must be called with the file pointer at the end.
|
||||
* Also does compression!
|
||||
*/
|
||||
int spfw_finalize_all(sp_file_t *spf);
|
||||
|
||||
#endif //_INCLUDE_SPFILE_H
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* ===============================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit
|
||||
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||
* in whole or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
#define _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
|
||||
/**
|
||||
* @file Contains SourceMod version information.
|
||||
*/
|
||||
|
||||
#define SVN_FULL_VERSION "1.0.0.1874"
|
||||
#define SVN_FILE_VERSION 1,0,0,1874
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VERSION_H_
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* ===============================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit
|
||||
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||
* in whole or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
#define _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
|
||||
/**
|
||||
* @file Contains SourceMod version information.
|
||||
*/
|
||||
|
||||
#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$.$LOCAL_BUILD$"
|
||||
#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,$LOCAL_BUILD$
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VERSION_H_
|
||||
@@ -0,0 +1,149 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2004 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD4(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD4(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == Z_NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD4(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
rem = (unsigned)(len2 % BASE);
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 > BASE) sum1 -= BASE;
|
||||
if (sum1 > BASE) sum1 -= BASE;
|
||||
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 > BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <[email protected]> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "zutil.h" /* for STDC and FAR definitions */
|
||||
|
||||
#define local static
|
||||
|
||||
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||
#ifndef NOBYFOUR
|
||||
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||
# include <limits.h>
|
||||
# define BYFOUR
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
typedef unsigned int u4;
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
typedef unsigned long u4;
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
typedef unsigned short u4;
|
||||
# else
|
||||
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif /* STDC */
|
||||
#endif /* !NOBYFOUR */
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#ifdef BYFOUR
|
||||
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
|
||||
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
#endif /* BYFOUR */
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local unsigned long FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const unsigned long FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
unsigned long c;
|
||||
int n, k;
|
||||
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0UL;
|
||||
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||
poly |= 1UL << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = REV(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = REV(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
/* write out CRC tables to crc32.h */
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const unsigned long FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
fprintf(out, "#ifdef BYFOUR\n");
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k]);
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
# endif /* BYFOUR */
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const unsigned long FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const unsigned long FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const unsigned long FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
u4 endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
return crc32_little(crc, buf, len);
|
||||
else
|
||||
return crc32_big(crc, buf, len);
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = (u4)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)c;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *++buf4; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = REV((u4)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf4++;
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(REV(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case */
|
||||
if (len2 == 0)
|
||||
return crc1;
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
/* crc32.h -- tables for rapid CRC calculation
|
||||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const unsigned long FAR crc_table[TBLS][256] =
|
||||
{
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
|
||||
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
|
||||
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
|
||||
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
|
||||
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
|
||||
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
|
||||
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
|
||||
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
|
||||
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
|
||||
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
|
||||
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
|
||||
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
|
||||
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
|
||||
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
|
||||
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
|
||||
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
|
||||
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
|
||||
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
|
||||
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
|
||||
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
|
||||
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
|
||||
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
|
||||
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
|
||||
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
|
||||
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
|
||||
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
|
||||
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
|
||||
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
|
||||
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
|
||||
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
|
||||
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
|
||||
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
|
||||
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
|
||||
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
|
||||
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
|
||||
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
|
||||
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
|
||||
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
|
||||
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
|
||||
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
|
||||
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
|
||||
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
|
||||
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
|
||||
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
|
||||
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
|
||||
0x2d02ef8dUL
|
||||
#ifdef BYFOUR
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
|
||||
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
|
||||
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
|
||||
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
|
||||
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
|
||||
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
|
||||
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
|
||||
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
|
||||
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
|
||||
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
|
||||
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
|
||||
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
|
||||
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
|
||||
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
|
||||
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
|
||||
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
|
||||
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
|
||||
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
|
||||
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
|
||||
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
|
||||
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
|
||||
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
|
||||
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
|
||||
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
|
||||
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
|
||||
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
|
||||
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
|
||||
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
|
||||
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
|
||||
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
|
||||
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
|
||||
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
|
||||
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
|
||||
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
|
||||
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
|
||||
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
|
||||
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
|
||||
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
|
||||
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
|
||||
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
|
||||
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
|
||||
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
|
||||
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
|
||||
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
|
||||
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
|
||||
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
|
||||
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
|
||||
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
|
||||
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
|
||||
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
|
||||
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
|
||||
0x9324fd72UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
|
||||
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
|
||||
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
|
||||
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
|
||||
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
|
||||
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
|
||||
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
|
||||
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
|
||||
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
|
||||
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
|
||||
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
|
||||
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
|
||||
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
|
||||
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
|
||||
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
|
||||
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
|
||||
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
|
||||
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
|
||||
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
|
||||
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
|
||||
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
|
||||
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
|
||||
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
|
||||
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
|
||||
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
|
||||
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
|
||||
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
|
||||
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
|
||||
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
|
||||
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
|
||||
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
|
||||
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
|
||||
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
|
||||
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
|
||||
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
|
||||
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
|
||||
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
|
||||
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
|
||||
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
|
||||
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
|
||||
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
|
||||
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
|
||||
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
|
||||
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
|
||||
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
|
||||
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
|
||||
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
|
||||
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
|
||||
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
|
||||
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
|
||||
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
|
||||
0xbe9834edUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
|
||||
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
|
||||
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
|
||||
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
|
||||
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
|
||||
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
|
||||
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
|
||||
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
|
||||
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
|
||||
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
|
||||
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
|
||||
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
|
||||
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
|
||||
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
|
||||
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
|
||||
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
|
||||
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
|
||||
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
|
||||
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
|
||||
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
|
||||
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
|
||||
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
|
||||
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
|
||||
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
|
||||
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
|
||||
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
|
||||
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
|
||||
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
|
||||
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
|
||||
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
|
||||
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
|
||||
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
|
||||
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
|
||||
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
|
||||
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
|
||||
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
|
||||
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
|
||||
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
|
||||
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
|
||||
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
|
||||
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
|
||||
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
|
||||
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
|
||||
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
|
||||
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
|
||||
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
|
||||
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
|
||||
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
|
||||
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
|
||||
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
|
||||
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
|
||||
0xde0506f1UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
|
||||
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
|
||||
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
|
||||
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
|
||||
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
|
||||
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
|
||||
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
|
||||
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
|
||||
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
|
||||
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
|
||||
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
|
||||
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
|
||||
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
|
||||
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
|
||||
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
|
||||
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
|
||||
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
|
||||
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
|
||||
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
|
||||
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
|
||||
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
|
||||
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
|
||||
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
|
||||
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
|
||||
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
|
||||
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
|
||||
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
|
||||
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
|
||||
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
|
||||
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
|
||||
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
|
||||
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
|
||||
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
|
||||
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
|
||||
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
|
||||
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
|
||||
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
|
||||
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
|
||||
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
|
||||
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
|
||||
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
|
||||
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
|
||||
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
|
||||
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
|
||||
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
|
||||
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
|
||||
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
|
||||
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
|
||||
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
|
||||
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
|
||||
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
|
||||
0x8def022dUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
|
||||
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
|
||||
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
|
||||
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
|
||||
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
|
||||
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
|
||||
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
|
||||
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
|
||||
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
|
||||
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
|
||||
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
|
||||
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
|
||||
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
|
||||
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
|
||||
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
|
||||
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
|
||||
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
|
||||
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
|
||||
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
|
||||
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
|
||||
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
|
||||
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
|
||||
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
|
||||
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
|
||||
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
|
||||
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
|
||||
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
|
||||
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
|
||||
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
|
||||
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
|
||||
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
|
||||
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
|
||||
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
|
||||
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
|
||||
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
|
||||
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
|
||||
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
|
||||
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
|
||||
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
|
||||
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
|
||||
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
|
||||
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
|
||||
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
|
||||
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
|
||||
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
|
||||
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
|
||||
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
|
||||
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
|
||||
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
|
||||
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
|
||||
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
|
||||
0x72fd2493UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
|
||||
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
|
||||
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
|
||||
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
|
||||
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
|
||||
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
|
||||
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
|
||||
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
|
||||
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
|
||||
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
|
||||
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
|
||||
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
|
||||
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
|
||||
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
|
||||
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
|
||||
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
|
||||
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
|
||||
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
|
||||
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
|
||||
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
|
||||
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
|
||||
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
|
||||
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
|
||||
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
|
||||
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
|
||||
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
|
||||
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
|
||||
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
|
||||
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
|
||||
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
|
||||
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
|
||||
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
|
||||
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
|
||||
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
|
||||
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
|
||||
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
|
||||
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
|
||||
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
|
||||
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
|
||||
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
|
||||
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
|
||||
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
|
||||
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
|
||||
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
|
||||
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
|
||||
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
|
||||
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
|
||||
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
|
||||
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
|
||||
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
|
||||
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
|
||||
0xed3498beUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
|
||||
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
|
||||
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
|
||||
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
|
||||
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
|
||||
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
|
||||
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
|
||||
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
|
||||
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
|
||||
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
|
||||
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
|
||||
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
|
||||
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
|
||||
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
|
||||
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
|
||||
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
|
||||
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
|
||||
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
|
||||
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
|
||||
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
|
||||
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
|
||||
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
|
||||
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
|
||||
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
|
||||
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
|
||||
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
|
||||
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
|
||||
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
|
||||
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
|
||||
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
|
||||
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
|
||||
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
|
||||
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
|
||||
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
|
||||
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
|
||||
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
|
||||
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
|
||||
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
|
||||
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
|
||||
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
|
||||
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
|
||||
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
|
||||
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
|
||||
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
|
||||
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
|
||||
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
|
||||
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
|
||||
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
|
||||
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
|
||||
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
|
||||
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
|
||||
0xf10605deUL
|
||||
#endif
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,331 @@
|
||||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2004 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef DEFLATE_H
|
||||
#define DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip encoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GZIP
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2*L_CODES+1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define EXTRA_STATE 69
|
||||
#define NAME_STATE 73
|
||||
#define COMMENT_STATE 91
|
||||
#define HCRC_STATE 103
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s {
|
||||
union {
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union {
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef *pending_buf; /* output still pending */
|
||||
ulg pending_buf_size; /* size of pending_buf */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
uInt pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
uInt gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef *window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MSDOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf *prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf *head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
# define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS+1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2*L_CODES+1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
|
||||
#ifdef DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
/* in trees.c */
|
||||
void _tr_init OF((deflate_state *s));
|
||||
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
void _tr_align OF((deflate_state *s));
|
||||
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
|
||||
#define d_code(dist) \
|
||||
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
|
||||
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||
* used.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG
|
||||
/* Inline versions of _tr_tally for speed: */
|
||||
|
||||
#if defined(GEN_TREES_H) || !defined(STDC)
|
||||
extern uch _length_code[];
|
||||
extern uch _dist_code[];
|
||||
#else
|
||||
extern const uch _length_code[];
|
||||
extern const uch _dist_code[];
|
||||
#endif
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (length); \
|
||||
ush dist = (distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
flush = _tr_tally(s, distance, length)
|
||||
#endif
|
||||
|
||||
#endif /* DEFLATE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,623 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
This code is largely copied from inflate.c. Normally either infback.o or
|
||||
inflate.o would be linked into an application--not both. The interface
|
||||
with inffast.c is retained so that optimized assembler-coded versions of
|
||||
inflate_fast() can be used with either inflate.c or infback.c.
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
Z_NULL to use the library memory allocation functions.
|
||||
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
unsigned char FAR *window;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != (int)(sizeof(z_stream)))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == Z_NULL || window == Z_NULL ||
|
||||
windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->write = 0;
|
||||
state->whave = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||
first time it's called, and returns those tables the first time and
|
||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||
exchange for a little execution time. However, BUILDFIXED should not be
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(state)
|
||||
struct inflate_state FAR *state;
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
static code *lenfix, *distfix;
|
||||
static code fixed[544];
|
||||
|
||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||
if (virgin) {
|
||||
unsigned sym, bits;
|
||||
static code *next;
|
||||
|
||||
/* literal/length table */
|
||||
sym = 0;
|
||||
while (sym < 144) state->lens[sym++] = 8;
|
||||
while (sym < 256) state->lens[sym++] = 9;
|
||||
while (sym < 280) state->lens[sym++] = 7;
|
||||
while (sym < 288) state->lens[sym++] = 8;
|
||||
next = fixed;
|
||||
lenfix = next;
|
||||
bits = 9;
|
||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||
|
||||
/* distance table */
|
||||
sym = 0;
|
||||
while (sym < 32) state->lens[sym++] = 5;
|
||||
distfix = next;
|
||||
bits = 5;
|
||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||
|
||||
/* do this just once */
|
||||
virgin = 0;
|
||||
}
|
||||
#else /* !BUILDFIXED */
|
||||
# include "inffixed.h"
|
||||
#endif /* BUILDFIXED */
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
/* Macros for inflateBack(): */
|
||||
|
||||
/* Load returned state from inflate_fast() */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Set state from registers for inflate_fast() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some input is available. If input is requested, but denied,
|
||||
then return a Z_BUF_ERROR from inflateBack(). */
|
||||
#define PULL() \
|
||||
do { \
|
||||
if (have == 0) { \
|
||||
have = in(in_desc, &next); \
|
||||
if (have == 0) { \
|
||||
next = Z_NULL; \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||
with an error if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
PULL(); \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflateBack() with
|
||||
an error. */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some output space is available, by writing out the window
|
||||
if it's full. If the write fails, return from inflateBack() with a
|
||||
Z_BUF_ERROR. */
|
||||
#define ROOM() \
|
||||
do { \
|
||||
if (left == 0) { \
|
||||
put = state->window; \
|
||||
left = state->wsize; \
|
||||
state->whave = left; \
|
||||
if (out(out_desc, put, left)) { \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
strm provides the memory allocation functions and window buffer on input,
|
||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||
returns, strm will also provide an error message.
|
||||
|
||||
in() and out() are the call-back input and output functions. When
|
||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||
filled the window with output, or when it completes with data in the
|
||||
window, it calls out() to write out the data. The application must not
|
||||
change the provided input until in() is called again or inflateBack()
|
||||
returns. The application must not change the window/output buffer until
|
||||
inflateBack() returns.
|
||||
|
||||
in() and out() are called with a descriptor parameter provided in the
|
||||
inflateBack() call. This parameter can be a structure that provides the
|
||||
information required to do the read or write, as well as accumulated
|
||||
information on the input and output such as totals and check values.
|
||||
|
||||
in() should return zero on failure. out() should return non-zero on
|
||||
failure. If either in() or out() fails, than inflateBack() returns a
|
||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||
z_streamp strm;
|
||||
in_func in;
|
||||
void FAR *in_desc;
|
||||
out_func out;
|
||||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char FAR *from; /* where to copy match bytes from */
|
||||
code this; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Check that the strm exists and that the state was initialized */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = Z_NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != Z_NULL ? strm->avail_in : 0;
|
||||
hold = 0;
|
||||
bits = 0;
|
||||
put = state->window;
|
||||
left = state->wsize;
|
||||
|
||||
/* Inflate until end of block marked as last */
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case TYPE:
|
||||
/* determine and dispatch block type */
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
Tracev((stderr, "inflate: stored block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
|
||||
case STORED:
|
||||
/* get and verify stored block length */
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
Tracev((stderr, "inflate: stored length %u\n",
|
||||
state->length));
|
||||
INITBITS();
|
||||
|
||||
/* copy stored block from input to output */
|
||||
while (state->length != 0) {
|
||||
copy = state->length;
|
||||
PULL();
|
||||
ROOM();
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
zmemcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
}
|
||||
Tracev((stderr, "inflate: stored end\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
|
||||
case TABLE:
|
||||
/* get dynamic table entries descriptor */
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
|
||||
/* get code length code lengths (not a typo) */
|
||||
state->have = 0;
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
|
||||
/* get length and distance code code lengths */
|
||||
state->have = 0;
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
this = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (this.val < 16) {
|
||||
NEEDBITS(this.bits);
|
||||
DROPBITS(this.bits);
|
||||
state->lens[state->have++] = this.val;
|
||||
}
|
||||
else {
|
||||
if (this.val == 16) {
|
||||
NEEDBITS(this.bits + 2);
|
||||
DROPBITS(this.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = (unsigned)(state->lens[state->have - 1]);
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (this.val == 17) {
|
||||
NEEDBITS(this.bits + 3);
|
||||
DROPBITS(this.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(this.bits + 7);
|
||||
DROPBITS(this.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* build code tables */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
if (state->whave < state->wsize)
|
||||
state->whave = state->wsize - left;
|
||||
inflate_fast(strm, state->wsize);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get a literal, length, or end-of-block code */
|
||||
for (;;) {
|
||||
this = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (this.op && (this.op & 0xf0) == 0) {
|
||||
last = this;
|
||||
for (;;) {
|
||||
this = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(this.bits);
|
||||
state->length = (unsigned)this.val;
|
||||
|
||||
/* process literal */
|
||||
if (this.op == 0) {
|
||||
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", this.val));
|
||||
ROOM();
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* process end of block */
|
||||
if (this.op & 32) {
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* invalid code */
|
||||
if (this.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* length code -- get extra bits, if any */
|
||||
state->extra = (unsigned)(this.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
|
||||
/* get distance code */
|
||||
for (;;) {
|
||||
this = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((this.op & 0xf0) == 0) {
|
||||
last = this;
|
||||
for (;;) {
|
||||
this = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(this.bits);
|
||||
if (this.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)this.val;
|
||||
|
||||
/* get distance extra bits, if any */
|
||||
state->extra = (unsigned)(this.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||
left : 0)) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
|
||||
/* copy match from window to output */
|
||||
do {
|
||||
ROOM();
|
||||
copy = state->wsize - state->offset;
|
||||
if (copy < left) {
|
||||
from = put + copy;
|
||||
copy = left - copy;
|
||||
}
|
||||
else {
|
||||
from = put - state->offset;
|
||||
copy = left;
|
||||
}
|
||||
if (copy > state->length) copy = state->length;
|
||||
state->length -= copy;
|
||||
left -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
} while (state->length != 0);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
/* inflate stream terminated properly -- write leftover output */
|
||||
ret = Z_STREAM_END;
|
||||
if (left < state->wsize) {
|
||||
if (out(out_desc, state->window, state->wsize - left))
|
||||
ret = Z_BUF_ERROR;
|
||||
}
|
||||
goto inf_leave;
|
||||
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
|
||||
default: /* can't happen, but makes compilers happy */
|
||||
ret = Z_STREAM_ERROR;
|
||||
goto inf_leave;
|
||||
}
|
||||
|
||||
/* Return unused input */
|
||||
inf_leave:
|
||||
strm->next_in = next;
|
||||
strm->avail_in = have;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = Z_NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2004 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
#ifndef ASMINF
|
||||
|
||||
/* Allow machine dependent optimization for post-increment or pre-increment.
|
||||
Based on testing to date,
|
||||
Pre-increment preferred for:
|
||||
- PowerPC G3 (Adler)
|
||||
- MIPS R5000 (Randers-Pehrson)
|
||||
Post-increment preferred for:
|
||||
- none
|
||||
No measurable difference:
|
||||
- Pentium III (Anderson)
|
||||
- M68060 (Nikl)
|
||||
*/
|
||||
#ifdef POSTINC
|
||||
# define OFF 0
|
||||
# define PUP(a) *(a)++
|
||||
#else
|
||||
# define OFF 1
|
||||
# define PUP(a) *++(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Decode literal, length, and distance codes and write out the resulting
|
||||
literal and match bytes until either not enough input or output is
|
||||
available, an end-of-block is encountered, or a data error is encountered.
|
||||
When large enough input and output buffers are supplied to inflate(), for
|
||||
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
||||
inflate execution time is spent in this routine.
|
||||
|
||||
Entry assumptions:
|
||||
|
||||
state->mode == LEN
|
||||
strm->avail_in >= 6
|
||||
strm->avail_out >= 258
|
||||
start >= strm->avail_out
|
||||
state->bits < 8
|
||||
|
||||
On return, state->mode is one of:
|
||||
|
||||
LEN -- ran out of enough output space or enough available input
|
||||
TYPE -- reached end of block code, inflate() to interpret next block
|
||||
BAD -- error in block data
|
||||
|
||||
Notes:
|
||||
|
||||
- The maximum input bits used by a length/distance pair is 15 bits for the
|
||||
length code, 5 bits for the length extra, 15 bits for the distance code,
|
||||
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
||||
Therefore if strm->avail_in >= 6, then there is enough input to avoid
|
||||
checking for available input while decoding.
|
||||
|
||||
- The maximum bytes that a single length/distance pair can output is 258
|
||||
bytes, which is the maximum length that can be coded. inflate_fast()
|
||||
requires strm->avail_out >= 258 for each loop to avoid checking for
|
||||
output space.
|
||||
*/
|
||||
void inflate_fast(strm, start)
|
||||
z_streamp strm;
|
||||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *in; /* local strm->next_in */
|
||||
unsigned char FAR *last; /* while in < last, enough input available */
|
||||
unsigned char FAR *out; /* local strm->next_out */
|
||||
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||
unsigned char FAR *end; /* while out < end, enough space available */
|
||||
#ifdef INFLATE_STRICT
|
||||
unsigned dmax; /* maximum distance from zlib header */
|
||||
#endif
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned write; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
|
||||
unsigned long hold; /* local strm->hold */
|
||||
unsigned bits; /* local strm->bits */
|
||||
code const FAR *lcode; /* local strm->lencode */
|
||||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code this; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
unsigned dist; /* match distance */
|
||||
unsigned char FAR *from; /* where to copy match from */
|
||||
|
||||
/* copy state to local variables */
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
in = strm->next_in - OFF;
|
||||
last = in + (strm->avail_in - 5);
|
||||
out = strm->next_out - OFF;
|
||||
beg = out - (start - strm->avail_out);
|
||||
end = out + (strm->avail_out - 257);
|
||||
#ifdef INFLATE_STRICT
|
||||
dmax = state->dmax;
|
||||
#endif
|
||||
wsize = state->wsize;
|
||||
whave = state->whave;
|
||||
write = state->write;
|
||||
window = state->window;
|
||||
hold = state->hold;
|
||||
bits = state->bits;
|
||||
lcode = state->lencode;
|
||||
dcode = state->distcode;
|
||||
lmask = (1U << state->lenbits) - 1;
|
||||
dmask = (1U << state->distbits) - 1;
|
||||
|
||||
/* decode literals and length/distances until end-of-block or not enough
|
||||
input data or output space */
|
||||
do {
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
this = lcode[hold & lmask];
|
||||
dolen:
|
||||
op = (unsigned)(this.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(this.op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", this.val));
|
||||
PUP(out) = (unsigned char)(this.val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(this.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
len += (unsigned)hold & ((1U << op) - 1);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
this = dcode[hold & dmask];
|
||||
dodist:
|
||||
op = (unsigned)(this.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(this.op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(this.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
}
|
||||
dist += (unsigned)hold & ((1U << op) - 1);
|
||||
#ifdef INFLATE_STRICT
|
||||
if (dist > dmax) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
Tracevv((stderr, "inflate: distance %u\n", dist));
|
||||
op = (unsigned)(out - beg); /* max distance in output */
|
||||
if (dist > op) { /* see if copy from window */
|
||||
op = dist - op; /* distance back in window */
|
||||
if (op > whave) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
from = window - OFF;
|
||||
if (write == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
else if (write < op) { /* wrap around window */
|
||||
from += wsize + write - op;
|
||||
op -= write;
|
||||
if (op < len) { /* some from end of window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = window - OFF;
|
||||
if (write < len) { /* some from start of window */
|
||||
op = write;
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* contiguous in window */
|
||||
from += write - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
while (len > 2) {
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
len -= 3;
|
||||
}
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
}
|
||||
}
|
||||
else {
|
||||
from = out - dist; /* copy direct from output */
|
||||
do { /* minimum length is three */
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
len -= 3;
|
||||
} while (len > 2);
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
this = dcode[this.val + (hold & ((1U << op) - 1))];
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
this = lcode[this.val + (hold & ((1U << op) - 1))];
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
} while (in < last && out < end);
|
||||
|
||||
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
||||
len = bits >> 3;
|
||||
in -= len;
|
||||
bits -= len << 3;
|
||||
hold &= (1U << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in + OFF;
|
||||
strm->next_out = out + OFF;
|
||||
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
||||
strm->avail_out = (unsigned)(out < end ?
|
||||
257 + (end - out) : 257 - (out - end));
|
||||
state->hold = hold;
|
||||
state->bits = bits;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
|
||||
- Using bit fields for code structure
|
||||
- Different op definition to avoid & for extra bits (do & for table bits)
|
||||
- Three separate decoding do-loops for direct, window, and write == 0
|
||||
- Special case for distance > 1 copies to do overlapped load and store copy
|
||||
- Explicit branch predictions (based on measured branch probabilities)
|
||||
- Deferring match copy and interspersed it with decoding subsequent codes
|
||||
- Swapping literal/length else
|
||||
- Swapping window/direct else
|
||||
- Larger unrolled copy loops (three is about right)
|
||||
- Moving len -= 3 statement into middle of loop
|
||||
*/
|
||||
|
||||
#endif /* !ASMINF */
|
||||
@@ -0,0 +1,11 @@
|
||||
/* inffast.h -- header to use inffast.c
|
||||
* Copyright (C) 1995-2003 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
void inflate_fast OF((z_streamp strm, unsigned start));
|
||||
@@ -0,0 +1,94 @@
|
||||
/* inffixed.h -- table for decoding fixed codes
|
||||
* Generated automatically by makefixed().
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It
|
||||
is part of the implementation of the compression library and
|
||||
is subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
static const code lenfix[512] = {
|
||||
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
|
||||
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
|
||||
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
|
||||
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
|
||||
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
|
||||
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
|
||||
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
|
||||
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
|
||||
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
|
||||
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
|
||||
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
|
||||
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
|
||||
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
|
||||
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
|
||||
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
|
||||
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
|
||||
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
|
||||
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
|
||||
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
|
||||
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
|
||||
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
|
||||
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
|
||||
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
|
||||
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
|
||||
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
|
||||
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
|
||||
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
|
||||
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
|
||||
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
|
||||
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
|
||||
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
|
||||
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
|
||||
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
|
||||
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
|
||||
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
|
||||
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
|
||||
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
|
||||
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
|
||||
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
|
||||
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
|
||||
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
|
||||
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
|
||||
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
|
||||
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
|
||||
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
|
||||
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
|
||||
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
|
||||
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
|
||||
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
|
||||
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
|
||||
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
|
||||
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
|
||||
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
|
||||
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
|
||||
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
|
||||
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
|
||||
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
|
||||
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
|
||||
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
|
||||
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
|
||||
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
|
||||
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
|
||||
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
|
||||
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
|
||||
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
|
||||
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
|
||||
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
|
||||
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
|
||||
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
|
||||
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
|
||||
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
|
||||
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
|
||||
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
|
||||
{0,9,255}
|
||||
};
|
||||
|
||||
static const code distfix[32] = {
|
||||
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
|
||||
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
|
||||
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
|
||||
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
|
||||
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
|
||||
{22,5,193},{64,5,0}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,115 @@
|
||||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2004 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip decoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GUNZIP
|
||||
#endif
|
||||
|
||||
/* Possible inflate modes between inflate() calls */
|
||||
typedef enum {
|
||||
HEAD, /* i: waiting for magic header */
|
||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||
TIME, /* i: waiting for modification time (gzip) */
|
||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||
EXLEN, /* i: waiting for extra length (gzip) */
|
||||
EXTRA, /* i: waiting for extra bytes (gzip) */
|
||||
NAME, /* i: waiting for end of file name (gzip) */
|
||||
COMMENT, /* i: waiting for end of comment (gzip) */
|
||||
HCRC, /* i: waiting for header crc (gzip) */
|
||||
DICTID, /* i: waiting for dictionary check value */
|
||||
DICT, /* waiting for inflateSetDictionary() call */
|
||||
TYPE, /* i: waiting for type bits, including last-flag bit */
|
||||
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
||||
STORED, /* i: waiting for stored size (length and complement) */
|
||||
COPY, /* i/o: waiting for input or output to copy stored block */
|
||||
TABLE, /* i: waiting for dynamic block table lengths */
|
||||
LENLENS, /* i: waiting for code length code lengths */
|
||||
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
||||
LEN, /* i: waiting for length/lit code */
|
||||
LENEXT, /* i: waiting for length extra bits */
|
||||
DIST, /* i: waiting for distance code */
|
||||
DISTEXT, /* i: waiting for distance extra bits */
|
||||
MATCH, /* o: waiting for output space to copy string */
|
||||
LIT, /* o: waiting for output space to write literal */
|
||||
CHECK, /* i: waiting for 32-bit check value */
|
||||
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
||||
DONE, /* finished check, done -- remain here until reset */
|
||||
BAD, /* got a data error -- remain here until reset */
|
||||
MEM, /* got an inflate() memory error -- remain here until reset */
|
||||
SYNC /* looking for synchronization bytes to restart inflate() */
|
||||
} inflate_mode;
|
||||
|
||||
/*
|
||||
State transitions between above modes -
|
||||
|
||||
(most modes can go to the BAD or MEM mode -- not shown for clarity)
|
||||
|
||||
Process header:
|
||||
HEAD -> (gzip) or (zlib)
|
||||
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
|
||||
NAME -> COMMENT -> HCRC -> TYPE
|
||||
(zlib) -> DICTID or TYPE
|
||||
DICTID -> DICT -> TYPE
|
||||
Read deflate blocks:
|
||||
TYPE -> STORED or TABLE or LEN or CHECK
|
||||
STORED -> COPY -> TYPE
|
||||
TABLE -> LENLENS -> CODELENS -> LEN
|
||||
Read deflate codes:
|
||||
LEN -> LENEXT or LIT or TYPE
|
||||
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
|
||||
LIT -> LEN
|
||||
Process trailer:
|
||||
CHECK -> LENGTH -> DONE
|
||||
*/
|
||||
|
||||
/* state maintained between inflate() calls. Approximately 7K bytes. */
|
||||
struct inflate_state {
|
||||
inflate_mode mode; /* current inflate mode */
|
||||
int last; /* true if processing last block */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
gz_headerp head; /* where to save gzip header information */
|
||||
/* sliding window */
|
||||
unsigned wbits; /* log base 2 of requested window size */
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned write; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if needed */
|
||||
/* bit accumulator */
|
||||
unsigned long hold; /* input bit accumulator */
|
||||
unsigned bits; /* number of bits in "in" */
|
||||
/* for string and stored block copying */
|
||||
unsigned length; /* literal or length of data to copy */
|
||||
unsigned offset; /* distance back to copy string from */
|
||||
/* for table and code decoding */
|
||||
unsigned extra; /* extra bits needed */
|
||||
/* fixed and dynamic code tables */
|
||||
code const FAR *lencode; /* starting table for length/literal codes */
|
||||
code const FAR *distcode; /* starting table for distance codes */
|
||||
unsigned lenbits; /* index bits for lencode */
|
||||
unsigned distbits; /* index bits for distcode */
|
||||
/* dynamic table building */
|
||||
unsigned ncode; /* number of code length code lengths */
|
||||
unsigned nlen; /* number of length code lengths */
|
||||
unsigned ndist; /* number of distance code lengths */
|
||||
unsigned have; /* number of code lengths in lens[] */
|
||||
code FAR *next; /* next available space in codes[] */
|
||||
unsigned short lens[320]; /* temporary storage for code lengths */
|
||||
unsigned short work[288]; /* work area for code table building */
|
||||
code codes[ENOUGH]; /* space for code tables */
|
||||
};
|
||||
@@ -0,0 +1,329 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
|
||||
/*
|
||||
Build a set of tables to decode the provided canonical Huffman code.
|
||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||
lens shorts, which is used as a work area. type is the type of code
|
||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||
on return points to the next available entry's address. bits is the
|
||||
requested root table index bits, and on return it is the actual root
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
unsigned min, max; /* minimum and maximum code lengths */
|
||||
unsigned root; /* number of index bits for root table */
|
||||
unsigned curr; /* number of index bits for current table */
|
||||
unsigned drop; /* code bits to drop for sub-table */
|
||||
int left; /* number of prefix codes available */
|
||||
unsigned used; /* code entries in table used */
|
||||
unsigned huff; /* Huffman code */
|
||||
unsigned incr; /* for incrementing code, index */
|
||||
unsigned fill; /* index for replicating entries */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low root bits */
|
||||
code this; /* table entry for duplication */
|
||||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
int end; /* use base and extra for symbol > end */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577, 0, 0};
|
||||
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||
28, 28, 29, 29, 64, 64};
|
||||
|
||||
/*
|
||||
Process a set of code lengths to create a canonical Huffman code. The
|
||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||
symbols by length from short to long, and retaining the symbol order
|
||||
for codes with equal lengths. Then the code starts with all zero bits
|
||||
for the first code of the shortest length, and the codes are integer
|
||||
increments for the same length, and zeros are appended as the length
|
||||
increases. For the deflate format, these bits are stored backwards
|
||||
from their more natural integer increment ordering, and so when the
|
||||
decoding tables are built in the large loop below, the integer codes
|
||||
are incremented backwards.
|
||||
|
||||
This routine assumes, but does not check, that all of the entries in
|
||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||
1..MAXBITS is interpreted as that code length. zero means that that
|
||||
symbol does not occur in this code.
|
||||
|
||||
The codes are sorted by computing a count of codes for each length,
|
||||
creating from that a table of starting indices for each length in the
|
||||
sorted table, and then entering the symbols in order in the sorted
|
||||
table. The sorted table is work[], with that space being provided by
|
||||
the caller.
|
||||
|
||||
The length counts are used for other purposes as well, i.e. finding
|
||||
the minimum and maximum length codes, determining if there are any
|
||||
codes at all, checking for a valid set of lengths, and looking ahead
|
||||
at length counts to determine sub-table sizes when building the
|
||||
decoding tables.
|
||||
*/
|
||||
|
||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
count[len] = 0;
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
count[lens[sym]]++;
|
||||
|
||||
/* bound code lengths, force root to be within code lengths */
|
||||
root = *bits;
|
||||
for (max = MAXBITS; max >= 1; max--)
|
||||
if (count[max] != 0) break;
|
||||
if (root > max) root = max;
|
||||
if (max == 0) { /* no symbols to code at all */
|
||||
this.op = (unsigned char)64; /* invalid code marker */
|
||||
this.bits = (unsigned char)1;
|
||||
this.val = (unsigned short)0;
|
||||
*(*table)++ = this; /* make a table to force an error */
|
||||
*(*table)++ = this;
|
||||
*bits = 1;
|
||||
return 0; /* no symbols, but wait for decoding to report error */
|
||||
}
|
||||
for (min = 1; min <= MAXBITS; min++)
|
||||
if (count[min] != 0) break;
|
||||
if (root < min) root = min;
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1;
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1;
|
||||
left -= count[len];
|
||||
if (left < 0) return -1; /* over-subscribed */
|
||||
}
|
||||
if (left > 0 && (type == CODES || max != 1))
|
||||
return -1; /* incomplete set */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + count[len];
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||
|
||||
/*
|
||||
Create and fill in decoding tables. In this loop, the table being
|
||||
filled is at next and has curr index bits. The code being used is huff
|
||||
with length len. That code is converted to an index by dropping drop
|
||||
bits off of the bottom. For codes where len is less than drop + curr,
|
||||
those top drop + curr - len bits are incremented through all values to
|
||||
fill the table with replicated entries.
|
||||
|
||||
root is the number of index bits for the root table. When len exceeds
|
||||
root, sub-tables are created pointed to by the root entry with an index
|
||||
of the low root bits of huff. This is saved in low to check for when a
|
||||
new sub-table should be started. drop is zero when the root table is
|
||||
being filled, and drop is root when sub-tables are being filled.
|
||||
|
||||
When a new sub-table is needed, it is necessary to look ahead in the
|
||||
code lengths to determine what size sub-table is needed. The length
|
||||
counts are used for this, and so count[] is decremented as codes are
|
||||
entered in the tables.
|
||||
|
||||
used keeps track of how many table entries have been allocated from the
|
||||
provided *table space. It is checked when a LENS table is being made
|
||||
against the space in *table, ENOUGH, minus the maximum space needed by
|
||||
the worst case distance code, MAXD. This should never happen, but the
|
||||
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
|
||||
This assumes that when type == LENS, bits == 9.
|
||||
|
||||
sym increments through all symbols, and the loop terminates when
|
||||
all codes of length max, i.e. all codes, have been processed. This
|
||||
routine permits incomplete codes, so another loop after this one fills
|
||||
in the rest of the decoding tables with invalid code markers.
|
||||
*/
|
||||
|
||||
/* set up for code type */
|
||||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
end = 19;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
base -= 257;
|
||||
extra = lext;
|
||||
extra -= 257;
|
||||
end = 256;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
end = -1;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
huff = 0; /* starting code */
|
||||
sym = 0; /* starting code symbol */
|
||||
len = min; /* starting code length */
|
||||
next = *table; /* current table to fill in */
|
||||
curr = root; /* current table index bits */
|
||||
drop = 0; /* current bits to drop from code for index */
|
||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||
used = 1U << root; /* use root table entries */
|
||||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if (type == LENS && used >= ENOUGH - MAXD)
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
this.bits = (unsigned char)(len - drop);
|
||||
if ((int)(work[sym]) < end) {
|
||||
this.op = (unsigned char)0;
|
||||
this.val = work[sym];
|
||||
}
|
||||
else if ((int)(work[sym]) > end) {
|
||||
this.op = (unsigned char)(extra[work[sym]]);
|
||||
this.val = base[work[sym]];
|
||||
}
|
||||
else {
|
||||
this.op = (unsigned char)(32 + 64); /* end of block */
|
||||
this.val = 0;
|
||||
}
|
||||
|
||||
/* replicate for those indices with low len bits equal to huff */
|
||||
incr = 1U << (len - drop);
|
||||
fill = 1U << curr;
|
||||
min = fill; /* save offset to next table */
|
||||
do {
|
||||
fill -= incr;
|
||||
next[(huff >> drop) + fill] = this;
|
||||
} while (fill != 0);
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
|
||||
/* go to next symbol, update count, len */
|
||||
sym++;
|
||||
if (--(count[len]) == 0) {
|
||||
if (len == max) break;
|
||||
len = lens[work[sym]];
|
||||
}
|
||||
|
||||
/* create new sub-table if needed */
|
||||
if (len > root && (huff & mask) != low) {
|
||||
/* if first time, transition to sub-tables */
|
||||
if (drop == 0)
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += min; /* here min is 1 << curr */
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
left = (int)(1 << curr);
|
||||
while (curr + drop < max) {
|
||||
left -= count[curr + drop];
|
||||
if (left <= 0) break;
|
||||
curr++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if (type == LENS && used >= ENOUGH - MAXD)
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
low = huff & mask;
|
||||
(*table)[low].op = (unsigned char)curr;
|
||||
(*table)[low].bits = (unsigned char)root;
|
||||
(*table)[low].val = (unsigned short)(next - *table);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
this.op = (unsigned char)64; /* invalid code marker */
|
||||
this.bits = (unsigned char)(len - drop);
|
||||
this.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
this.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = this;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
*table += used;
|
||||
*bits = root;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/* inftrees.h -- header to use inftrees.c
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* Structure for decoding tables. Each entry provides either the
|
||||
information needed to do the operation requested by the code that
|
||||
indexed that table entry, or it provides a pointer to another
|
||||
table that indexes more bits of the code. op indicates whether
|
||||
the entry is a pointer to another table, a literal, a length or
|
||||
distance, an end-of-block, or an invalid code. For a table
|
||||
pointer, the low four bits of op is the number of index bits of
|
||||
that table. For a length or distance, the low four bits of op
|
||||
is the number of extra bits to get after the code. bits is
|
||||
the number of bits in this code or part of the code to drop off
|
||||
of the bit buffer. val is the actual byte to output in the case
|
||||
of a literal, the base length or distance, or the offset from
|
||||
the current table to the next table. Each entry is four bytes. */
|
||||
typedef struct {
|
||||
unsigned char op; /* operation, extra bits, table bits */
|
||||
unsigned char bits; /* bits in this part of the code */
|
||||
unsigned short val; /* offset in table or code value */
|
||||
} code;
|
||||
|
||||
/* op values as set by inflate_table():
|
||||
00000000 - literal
|
||||
0000tttt - table link, tttt != 0 is the number of table index bits
|
||||
0001eeee - length or distance, eeee is the number of extra bits
|
||||
01100000 - end of block
|
||||
01000000 - invalid code
|
||||
*/
|
||||
|
||||
/* Maximum size of dynamic tree. The maximum found in a long but non-
|
||||
exhaustive search was 1444 code structures (852 for length/literals
|
||||
and 592 for distances, the latter actually the result of an
|
||||
exhaustive search). The true maximum is not known, but the value
|
||||
below is more than safe. */
|
||||
#define ENOUGH 2048
|
||||
#define MAXD 592
|
||||
|
||||
/* Type of code to build for inftable() */
|
||||
typedef enum {
|
||||
CODES,
|
||||
LENS,
|
||||
DISTS
|
||||
} codetype;
|
||||
|
||||
extern int inflate_table OF((codetype type, unsigned short FAR *lens,
|
||||
unsigned codes, code FAR * FAR *table,
|
||||
unsigned FAR *bits, unsigned short FAR *work));
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,128 @@
|
||||
/* header created automatically with -DGEN_TREES_H */
|
||||
|
||||
local const ct_data static_ltree[L_CODES+2] = {
|
||||
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
|
||||
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
|
||||
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
|
||||
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
|
||||
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
|
||||
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
|
||||
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
|
||||
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
|
||||
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
|
||||
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
|
||||
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
|
||||
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
|
||||
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
|
||||
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
|
||||
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
|
||||
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
|
||||
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
|
||||
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
|
||||
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
|
||||
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
|
||||
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
|
||||
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
|
||||
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
|
||||
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
|
||||
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
|
||||
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
|
||||
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
|
||||
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
|
||||
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
|
||||
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
|
||||
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
|
||||
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
|
||||
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
|
||||
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
|
||||
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
|
||||
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
|
||||
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
|
||||
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
|
||||
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
|
||||
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
|
||||
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
|
||||
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
|
||||
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
|
||||
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
|
||||
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
|
||||
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
|
||||
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
|
||||
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
|
||||
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
|
||||
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
|
||||
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
|
||||
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
|
||||
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
|
||||
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
|
||||
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
|
||||
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
|
||||
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
|
||||
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
|
||||
};
|
||||
|
||||
local const ct_data static_dtree[D_CODES] = {
|
||||
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
|
||||
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
|
||||
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
|
||||
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
|
||||
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
|
||||
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
|
||||
};
|
||||
|
||||
const uch _dist_code[DIST_CODE_LEN] = {
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
||||
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||
};
|
||||
|
||||
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||
};
|
||||
|
||||
local const int base_length[LENGTH_CODES] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
||||
64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||
};
|
||||
|
||||
local const int base_dist[D_CODES] = {
|
||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
||||
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||
};
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* uncompr.c -- decompress a memory buffer
|
||||
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be large enough to hold the
|
||||
entire uncompressed data. (The size of the uncompressed data must have
|
||||
been saved previously by the compressor and transmitted to the decompressor
|
||||
by some mechanism outside the scope of this compression library.)
|
||||
Upon exit, destLen is the actual size of the compressed buffer.
|
||||
This function can be used to decompress a whole file at once if the
|
||||
input file is mmap'ed.
|
||||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||
*/
|
||||
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
return Z_DATA_ERROR;
|
||||
return err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
|
||||
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||
# define MSDOS
|
||||
#endif
|
||||
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
|
||||
# define OS2
|
||||
#endif
|
||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||
# ifndef SYS16BIT
|
||||
# define SYS16BIT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# define MAXSEG_64K
|
||||
#endif
|
||||
#ifdef MSDOS
|
||||
# define UNALIGNED_OK
|
||||
#endif
|
||||
|
||||
#ifdef __STDC_VERSION__
|
||||
# ifndef STDC
|
||||
# define STDC
|
||||
# endif
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# ifndef STDC99
|
||||
# define STDC99
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#ifndef STDC
|
||||
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||
# define const /* note: need a more gentle solution here */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
#endif
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
#ifndef MAX_MEM_LEVEL
|
||||
# ifdef MAXSEG_64K
|
||||
# define MAX_MEM_LEVEL 8
|
||||
# else
|
||||
# define MAX_MEM_LEVEL 9
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
||||
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
||||
* created by gzip. (Files created by minigzip can still be extracted by
|
||||
* gzip.)
|
||||
*/
|
||||
#ifndef MAX_WBITS
|
||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||
#endif
|
||||
|
||||
/* The memory requirements for deflate are (in bytes):
|
||||
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||
the default memory requirements from 256K to 128K, compile with
|
||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
/* Type declarations */
|
||||
|
||||
#ifndef OF /* function prototypes */
|
||||
# ifdef STDC
|
||||
# define OF(args) args
|
||||
# else
|
||||
# define OF(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||
* just define FAR to be empty.
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# if defined(M_I86SM) || defined(M_I86MM)
|
||||
/* MSC small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef _MSC_VER
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
# if (defined(__SMALL__) || defined(__MEDIUM__))
|
||||
/* Turbo C small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef __BORLANDC__
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(WINDOWS) || defined(WIN32)
|
||||
/* If building or using zlib as a DLL, define ZLIB_DLL.
|
||||
* This is not mandatory, but it offers a little performance increase.
|
||||
*/
|
||||
# ifdef ZLIB_DLL
|
||||
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXTERN extern __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXTERN extern __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# endif /* ZLIB_DLL */
|
||||
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
|
||||
* define ZLIB_WINAPI.
|
||||
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
|
||||
*/
|
||||
# ifdef ZLIB_WINAPI
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# endif
|
||||
# include <windows.h>
|
||||
/* No need for _export, use ZLIB.DEF instead. */
|
||||
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
|
||||
# define ZEXPORT WINAPI
|
||||
# ifdef WIN32
|
||||
# define ZEXPORTVA WINAPIV
|
||||
# else
|
||||
# define ZEXPORTVA FAR CDECL
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__BEOS__)
|
||||
# ifdef ZLIB_DLL
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXPORT __declspec(dllexport)
|
||||
# define ZEXPORTVA __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXPORT __declspec(dllimport)
|
||||
# define ZEXPORTVA __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZEXTERN
|
||||
# define ZEXTERN extern
|
||||
#endif
|
||||
#ifndef ZEXPORT
|
||||
# define ZEXPORT
|
||||
#endif
|
||||
#ifndef ZEXPORTVA
|
||||
# define ZEXPORTVA
|
||||
#endif
|
||||
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
#if !defined(__MACTYPES__)
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
#endif
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
typedef unsigned long uLong; /* 32 bits or more */
|
||||
|
||||
#ifdef SMALL_MEDIUM
|
||||
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
|
||||
# define Bytef Byte FAR
|
||||
#else
|
||||
typedef Byte FAR Bytef;
|
||||
#endif
|
||||
typedef char FAR charf;
|
||||
typedef int FAR intf;
|
||||
typedef uInt FAR uIntf;
|
||||
typedef uLong FAR uLongf;
|
||||
|
||||
#ifdef STDC
|
||||
typedef void const *voidpc;
|
||||
typedef void FAR *voidpf;
|
||||
typedef void *voidp;
|
||||
#else
|
||||
typedef Byte const *voidpc;
|
||||
typedef Byte FAR *voidpf;
|
||||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# define z_off_t off_t
|
||||
#endif
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
#endif
|
||||
#ifndef z_off_t
|
||||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
# define NO_vsnprintf
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
||||
#if defined(__MVS__)
|
||||
# pragma map(deflateInit_,"DEIN")
|
||||
# pragma map(deflateInit2_,"DEIN2")
|
||||
# pragma map(deflateEnd,"DEEND")
|
||||
# pragma map(deflateBound,"DEBND")
|
||||
# pragma map(inflateInit_,"ININ")
|
||||
# pragma map(inflateInit2_,"ININ2")
|
||||
# pragma map(inflateEnd,"INEND")
|
||||
# pragma map(inflateSync,"INSY")
|
||||
# pragma map(inflateSetDictionary,"INSEDI")
|
||||
# pragma map(compressBound,"CMBND")
|
||||
# pragma map(inflate_table,"INTABL")
|
||||
# pragma map(inflate_fast,"INFA")
|
||||
# pragma map(inflate_copyright,"INCOPY")
|
||||
#endif
|
||||
|
||||
#endif /* ZCONF_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,318 @@
|
||||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#ifndef NO_DUMMY_DECL
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
#endif
|
||||
|
||||
const char * const z_errmsg[10] = {
|
||||
"need dictionary", /* Z_NEED_DICT 2 */
|
||||
"stream end", /* Z_STREAM_END 1 */
|
||||
"", /* Z_OK 0 */
|
||||
"file error", /* Z_ERRNO (-1) */
|
||||
"stream error", /* Z_STREAM_ERROR (-2) */
|
||||
"data error", /* Z_DATA_ERROR (-3) */
|
||||
"insufficient memory", /* Z_MEM_ERROR (-4) */
|
||||
"buffer error", /* Z_BUF_ERROR (-5) */
|
||||
"incompatible version",/* Z_VERSION_ERROR (-6) */
|
||||
""};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion()
|
||||
{
|
||||
return ZLIB_VERSION;
|
||||
}
|
||||
|
||||
uLong ZEXPORT zlibCompileFlags()
|
||||
{
|
||||
uLong flags;
|
||||
|
||||
flags = 0;
|
||||
switch (sizeof(uInt)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1; break;
|
||||
case 8: flags += 2; break;
|
||||
default: flags += 3;
|
||||
}
|
||||
switch (sizeof(uLong)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 2; break;
|
||||
case 8: flags += 2 << 2; break;
|
||||
default: flags += 3 << 2;
|
||||
}
|
||||
switch (sizeof(voidpf)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 4; break;
|
||||
case 8: flags += 2 << 4; break;
|
||||
default: flags += 3 << 4;
|
||||
}
|
||||
switch (sizeof(z_off_t)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 6; break;
|
||||
case 8: flags += 2 << 6; break;
|
||||
default: flags += 3 << 6;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
flags += 1 << 8;
|
||||
#endif
|
||||
#if defined(ASMV) || defined(ASMINF)
|
||||
flags += 1 << 9;
|
||||
#endif
|
||||
#ifdef ZLIB_WINAPI
|
||||
flags += 1 << 10;
|
||||
#endif
|
||||
#ifdef BUILDFIXED
|
||||
flags += 1 << 12;
|
||||
#endif
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
flags += 1 << 13;
|
||||
#endif
|
||||
#ifdef NO_GZCOMPRESS
|
||||
flags += 1L << 16;
|
||||
#endif
|
||||
#ifdef NO_GZIP
|
||||
flags += 1L << 17;
|
||||
#endif
|
||||
#ifdef PKZIP_BUG_WORKAROUND
|
||||
flags += 1L << 20;
|
||||
#endif
|
||||
#ifdef FASTEST
|
||||
flags += 1L << 21;
|
||||
#endif
|
||||
#ifdef STDC
|
||||
# ifdef NO_vsnprintf
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_vsprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
flags += 1L << 24;
|
||||
# ifdef NO_snprintf
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_sprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_snprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
# ifndef verbose
|
||||
# define verbose 0
|
||||
# endif
|
||||
int z_verbose = verbose;
|
||||
|
||||
void z_error (m)
|
||||
char *m;
|
||||
{
|
||||
fprintf(stderr, "%s\n", m);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* exported to allow conversion of error code to string for compress() and
|
||||
* uncompress()
|
||||
*/
|
||||
const char * ZEXPORT zError(err)
|
||||
int err;
|
||||
{
|
||||
return ERR_MSG(err);
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
* errno. We define it as a global variable to simplify porting.
|
||||
* Its value is always 0 and should not be used.
|
||||
*/
|
||||
int errno = 0;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMCPY
|
||||
|
||||
void zmemcpy(dest, source, len)
|
||||
Bytef* dest;
|
||||
const Bytef* source;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = *source++; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
|
||||
int zmemcmp(s1, s2, len)
|
||||
const Bytef* s1;
|
||||
const Bytef* s2;
|
||||
uInt len;
|
||||
{
|
||||
uInt j;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zmemzero(dest, len)
|
||||
Bytef* dest;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = 0; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SYS16BIT
|
||||
|
||||
#ifdef __TURBOC__
|
||||
/* Turbo C in 16-bit mode */
|
||||
|
||||
# define MY_ZCALLOC
|
||||
|
||||
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
|
||||
* and farmalloc(64K) returns a pointer with an offset of 8, so we
|
||||
* must fix the pointer. Warning: the pointer must be put back to its
|
||||
* original form in order to free it, use zcfree().
|
||||
*/
|
||||
|
||||
#define MAX_PTR 10
|
||||
/* 10*64K = 640K */
|
||||
|
||||
local int next_ptr = 0;
|
||||
|
||||
typedef struct ptr_table_s {
|
||||
voidpf org_ptr;
|
||||
voidpf new_ptr;
|
||||
} ptr_table;
|
||||
|
||||
local ptr_table table[MAX_PTR];
|
||||
/* This table is used to remember the original form of pointers
|
||||
* to large buffers (64K). Such pointers are normalized with a zero offset.
|
||||
* Since MSDOS is not a preemptive multitasking OS, this table is not
|
||||
* protected from concurrent access. This hack doesn't work anyway on
|
||||
* a protected system like OS/2. Use Microsoft C instead.
|
||||
*/
|
||||
|
||||
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
{
|
||||
voidpf buf = opaque; /* just to make some compilers happy */
|
||||
ulg bsize = (ulg)items*size;
|
||||
|
||||
/* If we allocate less than 65520 bytes, we assume that farmalloc
|
||||
* will return a usable pointer which doesn't have to be normalized.
|
||||
*/
|
||||
if (bsize < 65520L) {
|
||||
buf = farmalloc(bsize);
|
||||
if (*(ush*)&buf != 0) return buf;
|
||||
} else {
|
||||
buf = farmalloc(bsize + 16L);
|
||||
}
|
||||
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
|
||||
table[next_ptr].org_ptr = buf;
|
||||
|
||||
/* Normalize the pointer to seg:0 */
|
||||
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
|
||||
*(ush*)&buf = 0;
|
||||
table[next_ptr++].new_ptr = buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
int n;
|
||||
if (*(ush*)&ptr != 0) { /* object < 64K */
|
||||
farfree(ptr);
|
||||
return;
|
||||
}
|
||||
/* Find the original pointer */
|
||||
for (n = 0; n < next_ptr; n++) {
|
||||
if (ptr != table[n].new_ptr) continue;
|
||||
|
||||
farfree(table[n].org_ptr);
|
||||
while (++n < next_ptr) {
|
||||
table[n-1] = table[n];
|
||||
}
|
||||
next_ptr--;
|
||||
return;
|
||||
}
|
||||
ptr = opaque; /* just to make some compilers happy */
|
||||
Assert(0, "zcfree: ptr not found");
|
||||
}
|
||||
|
||||
#endif /* __TURBOC__ */
|
||||
|
||||
|
||||
#ifdef M_I86
|
||||
/* Microsoft C in 16-bit mode */
|
||||
|
||||
# define MY_ZCALLOC
|
||||
|
||||
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
|
||||
# define _halloc halloc
|
||||
# define _hfree hfree
|
||||
#endif
|
||||
|
||||
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
return _halloc((long)items, size);
|
||||
}
|
||||
|
||||
void zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
_hfree(ptr);
|
||||
}
|
||||
|
||||
#endif /* M_I86 */
|
||||
|
||||
#endif /* SYS16BIT */
|
||||
|
||||
|
||||
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
|
||||
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern voidp calloc OF((uInt items, uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
voidpf zcalloc (opaque, items, size)
|
||||
voidpf opaque;
|
||||
unsigned items;
|
||||
unsigned size;
|
||||
{
|
||||
if (opaque) items += size - size; /* make compiler happy */
|
||||
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
|
||||
(voidpf)calloc(items, size);
|
||||
}
|
||||
|
||||
void zcfree (opaque, ptr)
|
||||
voidpf opaque;
|
||||
voidpf ptr;
|
||||
{
|
||||
free(ptr);
|
||||
if (opaque) return; /* make compiler happy */
|
||||
}
|
||||
|
||||
#endif /* MY_ZCALLOC */
|
||||
@@ -0,0 +1,269 @@
|
||||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef ZUTIL_H
|
||||
#define ZUTIL_H
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
# ifndef _WIN32_WCE
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef NO_ERRNO_H
|
||||
# ifdef _WIN32_WCE
|
||||
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
* errno. We define it as a global variable to simplify porting.
|
||||
* Its value is always 0 and should not be used. We rename it to
|
||||
* avoid conflict with other libraries that use the same workaround.
|
||||
*/
|
||||
# define errno z_errno
|
||||
# endif
|
||||
extern int errno;
|
||||
#else
|
||||
# ifndef _WIN32_WCE
|
||||
# include <errno.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef uch FAR uchf;
|
||||
typedef unsigned short ush;
|
||||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
|
||||
|
||||
#define ERR_RETURN(strm,err) \
|
||||
return (strm->msg = (char*)ERR_MSG(err), (err))
|
||||
/* To be used only when the state is known to be valid */
|
||||
|
||||
/* common constants */
|
||||
|
||||
#ifndef DEF_WBITS
|
||||
# define DEF_WBITS MAX_WBITS
|
||||
#endif
|
||||
/* default windowBits for decompression. MAX_WBITS is for compression only */
|
||||
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
/* default memLevel */
|
||||
|
||||
#define STORED_BLOCK 0
|
||||
#define STATIC_TREES 1
|
||||
#define DYN_TREES 2
|
||||
/* The three kinds of block type */
|
||||
|
||||
#define MIN_MATCH 3
|
||||
#define MAX_MATCH 258
|
||||
/* The minimum and maximum match lengths */
|
||||
|
||||
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
|
||||
|
||||
/* target dependencies */
|
||||
|
||||
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
|
||||
# define OS_CODE 0x00
|
||||
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||
/* Allow compilation with ANSI keywords only enabled */
|
||||
void _Cdecl farfree( void *block );
|
||||
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||
# else
|
||||
# include <alloc.h>
|
||||
# endif
|
||||
# else /* MSC or DJGPP */
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef AMIGA
|
||||
# define OS_CODE 0x01
|
||||
#endif
|
||||
|
||||
#if defined(VAXC) || defined(VMS)
|
||||
# define OS_CODE 0x02
|
||||
# define F_OPEN(name, mode) \
|
||||
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
|
||||
#endif
|
||||
|
||||
#if defined(ATARI) || defined(atarist)
|
||||
# define OS_CODE 0x05
|
||||
#endif
|
||||
|
||||
#ifdef OS2
|
||||
# define OS_CODE 0x06
|
||||
# ifdef M_I86
|
||||
#include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||
# define OS_CODE 0x07
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef TOPS20
|
||||
# define OS_CODE 0x0a
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
|
||||
# define OS_CODE 0x0b
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __50SERIES /* Prime/PRIMOS */
|
||||
# define OS_CODE 0x0f
|
||||
#endif
|
||||
|
||||
#if defined(_BEOS_) || defined(RISCOS)
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER > 600))
|
||||
# if defined(_WIN32_WCE)
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# ifndef _PTRDIFF_T_DEFINED
|
||||
typedef int ptrdiff_t;
|
||||
# define _PTRDIFF_T_DEFINED
|
||||
# endif
|
||||
# else
|
||||
# define fdopen(fd,type) _fdopen(fd,type)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* common defaults */
|
||||
|
||||
#ifndef OS_CODE
|
||||
# define OS_CODE 0x03 /* assume Unix */
|
||||
#endif
|
||||
|
||||
#ifndef F_OPEN
|
||||
# define F_OPEN(name, mode) fopen((name), (mode))
|
||||
#endif
|
||||
|
||||
/* functions */
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
#ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(pyr)
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
|
||||
/* Use our own functions for small and medium model with MSC <= 5.0.
|
||||
* You may have to use the same strategy for Borland C (untested).
|
||||
* The __SC__ check is for Symantec.
|
||||
*/
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
|
||||
# define HAVE_MEMCPY
|
||||
#endif
|
||||
#ifdef HAVE_MEMCPY
|
||||
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
|
||||
# define zmemcpy _fmemcpy
|
||||
# define zmemcmp _fmemcmp
|
||||
# define zmemzero(dest, len) _fmemset(dest, 0, len)
|
||||
# else
|
||||
# define zmemcpy memcpy
|
||||
# define zmemcmp memcmp
|
||||
# define zmemzero(dest, len) memset(dest, 0, len)
|
||||
# endif
|
||||
#else
|
||||
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
|
||||
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
|
||||
extern void zmemzero OF((Bytef* dest, uInt len));
|
||||
#endif
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
extern int z_verbose;
|
||||
extern void z_error OF((char *m));
|
||||
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
|
||||
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
|
||||
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
|
||||
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
|
||||
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
|
||||
void zcfree OF((voidpf opaque, voidpf ptr));
|
||||
|
||||
#define ZALLOC(strm, items, size) \
|
||||
(*((strm)->zalloc))((strm)->opaque, (items), (size))
|
||||
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
|
||||
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
|
||||
|
||||
#endif /* ZUTIL_H */
|
||||
@@ -0,0 +1,69 @@
|
||||
#(C)2004-2008 Metamod:Source Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
SRCDS = ~/srcds
|
||||
SMSDK = ../../..
|
||||
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
|
||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
|
||||
GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
DEBUG_FLAGS = -g -ggdb3
|
||||
CPP = gcc-4.1
|
||||
BINARY = sourcepawn.jit.x86.so
|
||||
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/linux_sdk
|
||||
|
||||
OBJECTS = dll_exports.cpp jit_x86.cpp opcode_helpers.cpp
|
||||
|
||||
LINK = -static-libgcc
|
||||
|
||||
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn \
|
||||
-I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS = $(DEBUG_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS = $(OPT_FLAGS)
|
||||
endif
|
||||
|
||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
|
||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \
|
||||
-Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \
|
||||
-Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fno-exceptions -fno-rtti \
|
||||
-DHAVE_STDINT_H -m32
|
||||
|
||||
ifeq "$(GCC_VERSION)" "4"
|
||||
CFLAGS += $(GCC4_FLAGS)
|
||||
endif
|
||||
|
||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)
|
||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
||||
$(MAKE) binary
|
||||
rm -rf $(BINARY)
|
||||
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
|
||||
|
||||
binary: $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf Release/*.o
|
||||
rm -rf Release/$(BINARY)
|
||||
rm -rf Debug/*.o
|
||||
rm -rf Debug/$(BINARY)
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <malloc.h>
|
||||
#include "jit_x86.h"
|
||||
#include "dll_exports.h"
|
||||
|
||||
SourcePawn::ISourcePawnEngine *engine = NULL;
|
||||
JITX86 g_jit;
|
||||
|
||||
EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsigned int api_version)
|
||||
{
|
||||
engine = engine_p;
|
||||
|
||||
if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
|
||||
{
|
||||
return SP_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
EXPORTFUNC unsigned int GetExportCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORTFUNC SourcePawn::IVirtualMachine *GetExport(unsigned int exportnum)
|
||||
{
|
||||
/* Don't return anything if we're not initialized yet */
|
||||
if (!engine)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We only have one export - 0 */
|
||||
if (exportnum)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &g_jit;
|
||||
}
|
||||
|
||||
#if defined __linux__
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_DLL_H_
|
||||
#define _INCLUDE_SOURCEPAWN_JIT_X86_DLL_H_
|
||||
|
||||
#include <sp_vm_base.h>
|
||||
|
||||
#if defined WIN32
|
||||
#define EXPORTFUNC extern "C" __declspec(dllexport)
|
||||
#elif defined __GNUC__
|
||||
#if __GNUC__ >= 3
|
||||
#define EXPORTFUNC extern "C" __attribute__((visibility("default")))
|
||||
#else
|
||||
#define EXPORTFUNC extern "C"
|
||||
#endif //__GNUC__ >= 3
|
||||
#endif //defined __GNUC__
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_DLL_H_
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_JIT_VERSION_H_
|
||||
#define _INCLUDE_JIT_VERSION_H_
|
||||
|
||||
#define SVN_FULL_VERSION "1.0.0.1919"
|
||||
#define SVN_FILE_VERSION 1,0,0,1919
|
||||
|
||||
#endif //_INCLUDE_JIT_VERSION_H_
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_JIT_VERSION_H_
|
||||
#define _INCLUDE_JIT_VERSION_H_
|
||||
|
||||
#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$.$LOCAL_BUILD$"
|
||||
#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,$LOCAL_BUILD$
|
||||
|
||||
#endif //_INCLUDE_JIT_VERSION_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||
#define _INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||
|
||||
#include <sp_vm_types.h>
|
||||
#include <sp_vm_api.h>
|
||||
#include <jit_helpers.h>
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
#define JIT_INLINE_ERRORCHECKS (1<<0)
|
||||
#define JIT_INLINE_NATIVES (1<<1)
|
||||
#define STACK_MARGIN 64 //8 parameters of safety, I guess
|
||||
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
|
||||
|
||||
#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
|
||||
#define JITVARS_FUNCINFO 1 //important: don't change this aWOAWOGJQG I LIKE HAM
|
||||
#define JITVARS_REBASE 2 //important: hi, i'm bail
|
||||
|
||||
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
|
||||
|
||||
typedef struct tracker_s
|
||||
{
|
||||
size_t size;
|
||||
ucell_t *pBase;
|
||||
ucell_t *pCur;
|
||||
} tracker_t;
|
||||
|
||||
typedef struct funcinfo_s
|
||||
{
|
||||
unsigned int magic;
|
||||
unsigned int index;
|
||||
} funcinfo_t;
|
||||
|
||||
typedef struct functracker_s
|
||||
{
|
||||
unsigned int num_functions;
|
||||
unsigned int code_size;
|
||||
} functracker_t;
|
||||
|
||||
struct floattbl_t
|
||||
{
|
||||
floattbl_t()
|
||||
{
|
||||
found = false;
|
||||
index = 0;
|
||||
}
|
||||
bool found;
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
class CompData : public ICompilation
|
||||
{
|
||||
public:
|
||||
CompData() : plugin(NULL),
|
||||
debug(false), profile(0), inline_level(0), rebase(NULL),
|
||||
error_set(SP_ERROR_NONE), func_idx(0)
|
||||
{
|
||||
};
|
||||
public:
|
||||
sp_plugin_t *plugin; /* plugin handle */
|
||||
bool debug; /* whether to compile debug mode */
|
||||
int profile; /* profiling flags */
|
||||
int inline_level; /* inline optimization level */
|
||||
jitcode_t rebase; /* relocation map */
|
||||
int error_set; /* error code to halt process */
|
||||
unsigned int func_idx; /* current function index */
|
||||
jitoffs_t jit_return; /* point in main call to return to */
|
||||
jitoffs_t jit_verify_addr_eax;
|
||||
jitoffs_t jit_verify_addr_edx;
|
||||
jitoffs_t jit_break; /* call to op.break */
|
||||
jitoffs_t jit_sysreq_n; /* call version of op.sysreq.n */
|
||||
jitoffs_t jit_genarray; /* call to genarray intrinsic */
|
||||
jitoffs_t jit_error_bounds;
|
||||
jitoffs_t jit_error_divzero;
|
||||
jitoffs_t jit_error_stacklow;
|
||||
jitoffs_t jit_error_stackmin;
|
||||
jitoffs_t jit_error_memaccess;
|
||||
jitoffs_t jit_error_heaplow;
|
||||
jitoffs_t jit_error_heapmin;
|
||||
jitoffs_t jit_error_array_too_big;
|
||||
jitoffs_t jit_extern_error; /* returning generic error */
|
||||
jitoffs_t jit_sysreq_c; /* old version! */
|
||||
jitoffs_t jit_rounding_table;
|
||||
floattbl_t *jit_float_table;
|
||||
uint32_t codesize; /* total codesize */
|
||||
};
|
||||
|
||||
class JITX86 : public IVirtualMachine
|
||||
{
|
||||
public:
|
||||
const char *GetVMName();
|
||||
ICompilation *StartCompilation(sp_plugin_t *plugin);
|
||||
bool SetCompilationOption(ICompilation *co, const char *key, const char *val);
|
||||
sp_context_t *CompileToContext(ICompilation *co, int *err);
|
||||
void AbortCompilation(ICompilation *co);
|
||||
void FreeContext(sp_context_t *ctx);
|
||||
int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result);
|
||||
unsigned int GetAPIVersion();
|
||||
bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
|
||||
bool FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
|
||||
unsigned int FunctionCount(const sp_context_t *ctx);
|
||||
const char *GetVersionString();
|
||||
const char *GetCPUOptimizations();
|
||||
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
|
||||
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
|
||||
};
|
||||
|
||||
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
|
||||
cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
|
||||
cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
|
||||
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
|
||||
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
|
||||
|
||||
#define AMX_REG_PRI REG_EAX
|
||||
#define AMX_REG_ALT REG_EDX
|
||||
#define AMX_REG_STK REG_EDI
|
||||
#define AMX_REG_DAT REG_EBP
|
||||
#define AMX_REG_TMP REG_ECX
|
||||
#define AMX_REG_INFO REG_ESI
|
||||
#define AMX_REG_FRM REG_EBX
|
||||
|
||||
#define AMX_INFO_FRM AMX_REG_INFO //not relocated
|
||||
#define AMX_INFO_FRAME 0 //(same thing as above)
|
||||
#define AMX_INFO_HEAP 4 //not relocated
|
||||
#define AMX_INFO_RETVAL 8 //physical
|
||||
#define AMX_INFO_CONTEXT 12 //physical
|
||||
#define AMX_INFO_STACKTOP 16 //relocated
|
||||
|
||||
extern ISourcePawnEngine *engine;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jit-x86", "jit-x86.vcproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,296 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="jit-x86"
|
||||
ProjectGUID="{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
RootNamespace="jitx86"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\public\jit;..\..\..\..\public\jit\x86;..\..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..\..\..\..\public\jit;..\..\..\..\public\jit\x86;..\..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\dll_exports.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\jit_x86.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opcode_helpers.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\dll_exports.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\jit\jit_helpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\jit_version.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\jit_x86.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opcode_helpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ungen_opcodes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\jit\x86\x86_macros.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\jit_version.tpl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opcode_switch.inc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ungen_opcode_switch.inc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\version.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="SDK"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\jit_helpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_file_headers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_typeutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_api.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_types.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,893 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "jit_x86.h"
|
||||
#include "opcode_helpers.h"
|
||||
#include "x86_macros.h"
|
||||
|
||||
#define NUM_INFO_PARAMS 5
|
||||
|
||||
jitoffs_t Write_Execute_Function(JitWriter *jit)
|
||||
{
|
||||
/**
|
||||
* The variables we're passed in:
|
||||
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
|
||||
*/
|
||||
|
||||
/**
|
||||
* !NOTE!
|
||||
* Currently, we do not accept ctx->frm as the new frame pointer.
|
||||
* Instead, we copy the frame from the stack pointer.
|
||||
* This is because we do not support resuming or sleeping!
|
||||
*/
|
||||
|
||||
//push ebp
|
||||
//mov ebp, esp
|
||||
IA32_Push_Reg(jit, REG_EBP);
|
||||
IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
|
||||
|
||||
//push esi
|
||||
//push edi
|
||||
//push ebx
|
||||
IA32_Push_Reg(jit, REG_ESI);
|
||||
IA32_Push_Reg(jit, REG_EDI);
|
||||
IA32_Push_Reg(jit, REG_EBX);
|
||||
|
||||
//sub esp, 4*n - reserve info array
|
||||
//mov esi, esp - save info pointer
|
||||
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4*NUM_INFO_PARAMS, MOD_REG);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_INFO, REG_ESP, MOD_REG);
|
||||
|
||||
/* Initial memory setup */
|
||||
//mov eax, [ebp+16] - get result pointer
|
||||
//mov [esi+8], eax - store into info pointer
|
||||
//mov eax, [ebp+8] - get context
|
||||
//mov [esi+12], eax - store context into info pointer
|
||||
//mov ecx, [eax+<offs>] - get heap pointer
|
||||
//mov [esi+4], ecx - store heap into info pointer
|
||||
//mov ebp, [eax+<offs>] - get data pointer
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, memory));
|
||||
|
||||
/* Frame setup */
|
||||
//mov edi, [eax+<offs>] - get stack pointer
|
||||
//add edi, ebp - relocate to data section
|
||||
//mov ebx, edi - copy sp to frm
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_STK, REG_EAX, offsetof(sp_context_t, sp));
|
||||
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
|
||||
|
||||
/* Info memory setup */
|
||||
//mov ecx, [eax+<offs>] - copy memsize to temp var
|
||||
//add ecx, ebp - relocate
|
||||
//mov [esi+x], ecx - store relocated
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, mem_size));
|
||||
IA32_Add_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP);
|
||||
|
||||
/* Remaining needed vars */
|
||||
//mov ecx, [esp+(4*(NUM_INFO_PARAMS+3))+12] - get code index (normally esp+12, but we have another array on the stack)
|
||||
//add ecx, [eax+<offs>] - add code base to index
|
||||
IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3)));
|
||||
IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase));
|
||||
|
||||
/* by now, everything is set up, so we can call into the plugin */
|
||||
//call ecx
|
||||
IA32_Call_Reg(jit, REG_ECX);
|
||||
|
||||
/* if the code flow gets to here, there was a normal return */
|
||||
//mov ecx, [esi+8] - get retval pointer
|
||||
//mov [ecx], eax - store retval from PRI
|
||||
//mov eax, SP_ERROR_NONE - set no error
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, AMX_REG_INFO, AMX_INFO_RETVAL);
|
||||
IA32_Mov_Rm_Reg(jit, REG_ECX, AMX_REG_PRI, MOD_MEM_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, REG_EAX, SP_ERROR_NONE);
|
||||
|
||||
/* save where error checking/halting functions should go to */
|
||||
jitoffs_t offs_return = jit->get_outputpos();
|
||||
//mov esp, esi - restore stack pointer
|
||||
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_ESI, MOD_REG);
|
||||
|
||||
/* _FOR NOW_ ...
|
||||
* We are going to restore SP, HP, and FRM for now. This is for
|
||||
* debugging only, to check for alignment errors. As such:
|
||||
* :TODO: probably remove this.
|
||||
*/
|
||||
//mov ecx, [esi+context]
|
||||
//sub edi, ebp
|
||||
//mov edx, [esi+heap]
|
||||
//mov [ecx+sp], edi
|
||||
//mov [ecx+hp], edx
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_ESI, AMX_INFO_CONTEXT);
|
||||
IA32_Sub_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_ESI, AMX_INFO_HEAP);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_ECX, REG_EDI, offsetof(sp_context_t, sp));
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_ECX, REG_EDX, offsetof(sp_context_t, hp));
|
||||
|
||||
//add esp, 4*NUM_INFO_PARAMS
|
||||
//pop ebx
|
||||
//pop edi
|
||||
//pop esi
|
||||
//pop ebp
|
||||
//ret
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*NUM_INFO_PARAMS, MOD_REG);
|
||||
IA32_Pop_Reg(jit, REG_EBX);
|
||||
IA32_Pop_Reg(jit, REG_EDI);
|
||||
IA32_Pop_Reg(jit, REG_ESI);
|
||||
IA32_Pop_Reg(jit, REG_EBP);
|
||||
IA32_Return(jit);
|
||||
|
||||
return offs_return;
|
||||
}
|
||||
|
||||
void Write_BreakDebug(JitWriter *jit)
|
||||
{
|
||||
//push edi
|
||||
//mov edi, ecx
|
||||
//mov ecx, [esi+ctx]
|
||||
//cmp [ecx+dbreak], 0
|
||||
//jnz :nocall
|
||||
IA32_Push_Reg(jit, REG_EDI);
|
||||
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_ECX, MOD_REG);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, dbreak), 0);
|
||||
jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_Z, 0);
|
||||
|
||||
//:TODO: align the stack to 16bytes like in sysreq.x
|
||||
/* NOTE, Hack! PUSHAD pushes EDI last which still has the CIP */
|
||||
//pushad
|
||||
//push [esi+frm]
|
||||
//push ctx
|
||||
//mov ecx, [ecx+dbreak]
|
||||
//call ecx
|
||||
//add esp, 8
|
||||
//popad
|
||||
IA32_Pushad(jit);
|
||||
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0
|
||||
IA32_Push_Reg(jit, AMX_REG_TMP);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak));
|
||||
IA32_Call_Reg(jit, AMX_REG_TMP);
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG);
|
||||
IA32_Popad(jit);
|
||||
|
||||
//:nocall
|
||||
//pop edi
|
||||
//ret
|
||||
IA32_Pop_Reg(jit, REG_EDI);
|
||||
IA32_Send_Jump8_Here(jit, jmp);
|
||||
IA32_Return(jit);
|
||||
}
|
||||
|
||||
void Write_GetError(JitWriter *jit)
|
||||
{
|
||||
CompData *data = (CompData *)jit->data;
|
||||
|
||||
//mov eax, [esi+info.context]
|
||||
//mov eax, [eax+ctx.error]
|
||||
//jmp [jit_return]
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EAX, offsetof(sp_context_t, n_err));
|
||||
IA32_Jump_Imm32_Abs(jit, data->jit_return);
|
||||
}
|
||||
|
||||
void Write_SetError(JitWriter *jit, int error)
|
||||
{
|
||||
CompData *data = (CompData *)jit->data;
|
||||
|
||||
//mov eax, <error>
|
||||
//jmp [jit_return]
|
||||
IA32_Mov_Reg_Imm32(jit, REG_EAX, error);
|
||||
IA32_Jump_Imm32_Abs(jit, data->jit_return);
|
||||
}
|
||||
|
||||
void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg)
|
||||
{
|
||||
//test reg, reg
|
||||
//jz :error
|
||||
IA32_Test_Rm_Reg(jit, reg, reg, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, ((CompData *)jit->data)->jit_error_divzero);
|
||||
}
|
||||
|
||||
void Write_CheckHeap_Min(JitWriter *jit)
|
||||
{
|
||||
/* Check if the stack went beyond the heap low.
|
||||
* This usually means there was a compiler error.
|
||||
* NOTE: Special optimization here.
|
||||
* The heap low is always known ahead of time! :)
|
||||
*/
|
||||
CompData *data = (CompData *)jit->data;
|
||||
//cmp [esi+info.heap], <heaplow>
|
||||
//jb :error
|
||||
IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, data->plugin->data_size);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_B, data->jit_error_heapmin);
|
||||
}
|
||||
|
||||
void Write_CheckHeap_Low(JitWriter *jit)
|
||||
{
|
||||
/* Check if the heap is trying to grow beyond the stack.
|
||||
*/
|
||||
//mov ecx, [esi+info.heap]
|
||||
//lea ecx, [ebp+ecx+STACK_MARGIN]
|
||||
//cmp ecx, edi
|
||||
//ja :error ; I think this is right
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN);
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_heaplow);
|
||||
}
|
||||
|
||||
void Write_CheckStack_Min(JitWriter *jit)
|
||||
{
|
||||
/* Check if the stack went beyond the stack top
|
||||
* This usually means there was a compiler error.
|
||||
*/
|
||||
//cmp edi, [esi+info.stacktop]
|
||||
//jae :error
|
||||
IA32_Cmp_Reg_Rm_Disp8(jit, AMX_REG_STK, AMX_REG_INFO, AMX_INFO_STACKTOP);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_stackmin);
|
||||
}
|
||||
|
||||
void Write_CheckStack_Low(JitWriter *jit)
|
||||
{
|
||||
/* Check if the stack went beyond the heap boundary.
|
||||
* Unfortunately this one isn't as quick as the other check.
|
||||
* The stack margin check is important for sysreq.n having space.
|
||||
*/
|
||||
//mov ecx, [esi+info.heap]
|
||||
//lea ecx, [ebp+ecx+STACK_MARGIN]
|
||||
//cmp edi, ecx
|
||||
//jb :error ; I think this is right
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN);
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_STK, AMX_REG_TMP, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_B, ((CompData *)jit->data)->jit_error_stacklow);
|
||||
}
|
||||
|
||||
void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
|
||||
{
|
||||
CompData *data = (CompData *)jit->data;
|
||||
|
||||
/* :TODO: Should this be checking for below heaplow?
|
||||
* The old JIT did not.
|
||||
*/
|
||||
|
||||
bool call = false;
|
||||
if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
|
||||
{
|
||||
/* If we're not in the initial generation phase,
|
||||
* Write a call to the actual routine instead.
|
||||
*/
|
||||
if ((reg == REG_EAX) && data->jit_verify_addr_eax)
|
||||
{
|
||||
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||
IA32_Write_Jump32(jit, call, data->jit_verify_addr_eax);
|
||||
return;
|
||||
} else if ((reg == REG_EDX) && data->jit_verify_addr_edx) {
|
||||
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||
IA32_Write_Jump32(jit, call, data->jit_verify_addr_edx);
|
||||
return;
|
||||
}
|
||||
call = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* :TODO: If we can't find a nicer way of doing this,
|
||||
* then scrap it on high optimizations. The second portion is not needed at all!
|
||||
*/
|
||||
|
||||
/* Part 1: Check if we're in the memory bounds */
|
||||
//cmp <reg>, <stpu>
|
||||
//jae :error
|
||||
IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->memory);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
|
||||
|
||||
/* Part 2: Check if we're in the invalid region between HP and SP */
|
||||
jitoffs_t jmp;
|
||||
//cmp <reg>, [esi+info.heap]
|
||||
//jb :continue
|
||||
//lea ecx, [ebp+<reg>]
|
||||
//cmp edi, ecx
|
||||
//jb :error
|
||||
//:continue
|
||||
IA32_Cmp_Reg_Rm_Disp8(jit, reg, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
jmp = IA32_Jump_Cond_Imm8(jit, CC_B, 0);
|
||||
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, reg, NOSCALE, 0);
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_B, ((CompData *)jit->data)->jit_error_memaccess);
|
||||
IA32_Send_Jump8_Here(jit, jmp);
|
||||
|
||||
if (call)
|
||||
{
|
||||
IA32_Return(jit);
|
||||
}
|
||||
}
|
||||
|
||||
void Macro_PushN_Addr(JitWriter *jit, int i)
|
||||
{
|
||||
//push eax
|
||||
//mov eax, [esi+frm]
|
||||
//loop i times:
|
||||
// lea ecx, [eax+<val>]
|
||||
// mov [edi-4*i], ecx
|
||||
//sub edi, 4*N
|
||||
//pop eax
|
||||
|
||||
cell_t val;
|
||||
int n = 1;
|
||||
IA32_Push_Reg(jit, AMX_REG_PRI);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
|
||||
do
|
||||
{
|
||||
val = jit->read_cell();
|
||||
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
||||
IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, (jit_int8_t)val);
|
||||
else
|
||||
IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, val);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
|
||||
} while (n++ < i);
|
||||
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
|
||||
IA32_Pop_Reg(jit, AMX_REG_PRI);
|
||||
}
|
||||
|
||||
void Macro_PushN_S(JitWriter *jit, int i)
|
||||
{
|
||||
//loop i times:
|
||||
// mov ecx, [ebx+<val>]
|
||||
// mov [edi-4*i], ecx
|
||||
//sub edi, 4*N
|
||||
|
||||
cell_t val;
|
||||
int n = 1;
|
||||
do
|
||||
{
|
||||
val = jit->read_cell();
|
||||
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
|
||||
else
|
||||
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
|
||||
} while (n++ < i);
|
||||
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
|
||||
}
|
||||
|
||||
void Macro_PushN_C(JitWriter *jit, int i)
|
||||
{
|
||||
//loop i times:
|
||||
// mov [edi-4*i], <val>
|
||||
//sub edi, 4*N
|
||||
|
||||
int n = 1;
|
||||
do
|
||||
{
|
||||
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, jit->read_cell(), -4*n);
|
||||
} while (n++ < i);
|
||||
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
|
||||
}
|
||||
|
||||
void Macro_PushN(JitWriter *jit, int i)
|
||||
{
|
||||
//loop i times:
|
||||
// mov ecx, [ebp+<val>]
|
||||
// mov [edi-4*i], ecx
|
||||
//sub edi, 4*N
|
||||
|
||||
cell_t val;
|
||||
int n = 1;
|
||||
do
|
||||
{
|
||||
val = jit->read_cell();
|
||||
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
|
||||
else
|
||||
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
|
||||
} while (n++ < i);
|
||||
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
|
||||
}
|
||||
|
||||
void WriteOp_Sysreq_C_Function(JitWriter *jit)
|
||||
{
|
||||
/* The small daddy of the big daddy of opcodes.
|
||||
* ecx - native index
|
||||
*/
|
||||
CompData *data = (CompData *)jit->data;
|
||||
|
||||
/* save registers we will need */
|
||||
//push edx
|
||||
IA32_Push_Reg(jit, AMX_REG_ALT);
|
||||
|
||||
/* Align the stack to 16 bytes */
|
||||
//push ebx
|
||||
//mov ebx, esp
|
||||
//and esp, 0xFFFFFF0
|
||||
//sub esp, 4
|
||||
IA32_Push_Reg(jit, REG_EBX);
|
||||
IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
|
||||
IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
|
||||
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
|
||||
|
||||
/* push some callback stuff */
|
||||
//push edi ; stack
|
||||
//push ecx ; native index
|
||||
IA32_Push_Reg(jit, AMX_REG_STK);
|
||||
IA32_Push_Reg(jit, REG_ECX);
|
||||
|
||||
/* Relocate stack, heap, frm information, then store back */
|
||||
//mov eax, [esi+context]
|
||||
//mov ecx, [esi+hea]
|
||||
//sub edi, ebp
|
||||
//mov [eax+hp], ecx
|
||||
//mov ecx, [esi]
|
||||
//mov [eax+sp], edi
|
||||
//mov [eax+frm], ecx
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
|
||||
|
||||
/* finally, push the last parameter and make the call */
|
||||
//push eax ; context
|
||||
//call NativeCallback
|
||||
IA32_Push_Reg(jit, REG_EAX);
|
||||
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||
if (!data->debug)
|
||||
{
|
||||
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
|
||||
} else {
|
||||
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
|
||||
}
|
||||
|
||||
/* Test for error */
|
||||
//mov ecx, [esi+context]
|
||||
//cmp [ecx+err], 0
|
||||
//jnz :error
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
|
||||
|
||||
/* restore what we damaged */
|
||||
//mov esp, ebx
|
||||
//pop ebx
|
||||
//add edi, ebp
|
||||
//pop edx
|
||||
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
|
||||
IA32_Pop_Reg(jit, REG_EBX);
|
||||
IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Pop_Reg(jit, AMX_REG_ALT);
|
||||
|
||||
//ret
|
||||
IA32_Return(jit);
|
||||
}
|
||||
|
||||
typedef struct array_creation_s
|
||||
{
|
||||
const cell_t *dim_list; /* Dimension sizes */
|
||||
cell_t dim_count; /* Number of dimensions */
|
||||
cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */
|
||||
cell_t *base; /* array base */
|
||||
} array_creation_t;
|
||||
|
||||
cell_t _GenerateArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs)
|
||||
{
|
||||
cell_t write_offs = cur_offs;
|
||||
cell_t *data_offs = ar->data_offs;
|
||||
|
||||
cur_offs += ar->dim_list[dim];
|
||||
|
||||
/**
|
||||
* Dimension n-x where x > 2 will have sub-vectors.
|
||||
* Otherwise, we just need to reference the data section.
|
||||
*/
|
||||
if (ar->dim_count > 2 && dim < ar->dim_count - 2)
|
||||
{
|
||||
/**
|
||||
* For each index at this dimension, write offstes to our sub-vectors.
|
||||
* After we write one sub-vector, we generate its sub-vectors recursively.
|
||||
* At the end, we're given the next offset we can use.
|
||||
*/
|
||||
for (int i = 0; i < ar->dim_list[dim]; i++)
|
||||
{
|
||||
ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t);
|
||||
write_offs++;
|
||||
cur_offs = _GenerateArrayIndirectionVectors(ar, dim + 1, cur_offs);
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* In this section, there are no sub-vectors, we need to write offsets
|
||||
* to the data. This is separate so the data stays in one big chunk.
|
||||
* The data offset will increment by the size of the last dimension,
|
||||
* because that is where the data is finally computed as.
|
||||
*/
|
||||
for (int i = 0; i < ar->dim_list[dim]; i++)
|
||||
{
|
||||
ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t);
|
||||
write_offs++;
|
||||
*data_offs = *data_offs + ar->dim_list[dim + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return cur_offs;
|
||||
}
|
||||
|
||||
static cell_t calc_indirection(const array_creation_t *ar, cell_t dim)
|
||||
{
|
||||
cell_t size = ar->dim_list[dim];
|
||||
|
||||
if (dim < ar->dim_count - 2)
|
||||
{
|
||||
size += ar->dim_list[dim] * calc_indirection(ar, dim + 1);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero)
|
||||
{
|
||||
array_creation_t ar;
|
||||
cell_t data_offs;
|
||||
|
||||
/* Reverse the dimensions */
|
||||
cell_t dim_list[sDIMEN_MAX];
|
||||
int cur_dim = 0;
|
||||
for (int i = _dimcount - 1; i >= 0; i--)
|
||||
{
|
||||
dim_list[cur_dim++] = dims[i];
|
||||
}
|
||||
|
||||
ar.base = arraybase;
|
||||
ar.dim_list = dim_list;
|
||||
ar.dim_count = _dimcount;
|
||||
ar.data_offs = &data_offs;
|
||||
|
||||
data_offs = calc_indirection(&ar, 0);
|
||||
|
||||
_GenerateArrayIndirectionVectors(&ar, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A few notes about this function.
|
||||
* I was more concerned about efficient use of registers here, rather than
|
||||
* fine-tuned optimization. The reason is that the code is already complicated,
|
||||
* and it is very easy to mess up.
|
||||
*/
|
||||
void WriteIntrinsic_GenArray(JitWriter *jit)
|
||||
{
|
||||
/**
|
||||
* save important values
|
||||
*/
|
||||
//push ebx
|
||||
//push eax
|
||||
//push edx
|
||||
//push ecx ;value is referenced on stack
|
||||
IA32_Push_Reg(jit, REG_EBX);
|
||||
IA32_Push_Reg(jit, REG_EAX);
|
||||
IA32_Push_Reg(jit, REG_EDX);
|
||||
IA32_Push_Reg(jit, REG_ECX);
|
||||
|
||||
/**
|
||||
* Calculate how many cells will be needed.
|
||||
*/
|
||||
//mov edx, [edi] ;get last dimension's count
|
||||
//mov eax, 1 ;position at second to last dimension
|
||||
//:loop
|
||||
//cmp eax, [esp] ;compare to # of params
|
||||
//jae :done ;end loop if done
|
||||
//mov ecx, [edi+eax*4] ;get dimension size
|
||||
//imul edx, ecx ;multiply by size
|
||||
//add eax, 1 ;increment
|
||||
//add edx, ecx ;add size (indirection vector)
|
||||
//jmp :loop ;jump back
|
||||
//:done
|
||||
IA32_Mov_Reg_Rm(jit, REG_EDX, AMX_REG_STK, MOD_MEM_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, REG_EAX, 1);
|
||||
jitoffs_t loop1 = jit->get_outputpos();
|
||||
IA32_Cmp_Reg_Rm_ESP(jit, REG_EAX);
|
||||
jitoffs_t done1 = IA32_Jump_Cond_Imm8(jit, CC_AE, 0);
|
||||
IA32_Mov_Reg_Rm_Disp_Reg(jit, REG_ECX, AMX_REG_STK, REG_EAX, SCALE4);
|
||||
IA32_IMul_Reg_Rm(jit, REG_EDX, REG_ECX, MOD_REG);
|
||||
IA32_Add_Rm_Imm8(jit, REG_EAX, 1, MOD_REG);
|
||||
IA32_Add_Reg_Rm(jit, REG_EDX, REG_ECX, MOD_REG);
|
||||
IA32_Write_Jump8(jit, IA32_Jump_Imm8(jit, loop1), loop1);
|
||||
IA32_Send_Jump8_Here(jit, done1);
|
||||
|
||||
/* Test if we have heap space for this */
|
||||
//mov eax, [esi+info.heap] ;get heap pointer
|
||||
//lea eax, [eax+edx*4] ;new heap pointer
|
||||
//cmp eax, <hlw> ;compare to heap low
|
||||
//jbe :error ;die if we hit this (it should always be >)
|
||||
//add eax, ebp ;relocate to stack
|
||||
//cmp eax, edi ;die if above the stack pointer
|
||||
//jae :error
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
IA32_Lea_Reg_DispRegMult(jit, REG_EAX, REG_EAX, REG_EDX, SCALE4);
|
||||
IA32_Cmp_Rm_Imm32(jit, MOD_REG, REG_EAX, ((CompData *)jit->data)->plugin->data_size);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_BE, ((CompData *)jit->data)->jit_error_array_too_big);
|
||||
IA32_Add_Reg_Rm(jit, REG_EAX, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Cmp_Reg_Rm(jit, REG_EAX, AMX_REG_STK, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_array_too_big);
|
||||
|
||||
/* Prepare for indirection iteration */
|
||||
//mov eax, [esi+info.heap] ;get heap pointer
|
||||
//lea ebx, [eax+edx*4] ;new heap pointer
|
||||
//mov [esi+info.heap], ebx ;store back
|
||||
//push eax ;save heap pointer - we need it
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
IA32_Lea_Reg_DispRegMult(jit, REG_EBX, REG_EAX, REG_EDX, SCALE4);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EBX, AMX_INFO_HEAP);
|
||||
IA32_Push_Reg(jit, REG_EAX);
|
||||
|
||||
WriteOp_Tracker_Push_Reg(jit, REG_EDX);
|
||||
|
||||
/* This part is too messy to do in straight assembly.
|
||||
* I'm letting the compiler handle it and thus it's in C.
|
||||
*/
|
||||
//lea ebx, [ebp+eax] ;get base pointer
|
||||
//push dword [esp-8] ;push autozero
|
||||
//push dword [esp-8] ;push dimension count
|
||||
//push edi ;push dim array
|
||||
//push ebx
|
||||
//call GenerateArrayIndirectionVectors
|
||||
//add esp, 4*4
|
||||
IA32_Lea_Reg_DispRegMult(jit, REG_EBX, REG_EAX, REG_EBP, NOSCALE);
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 8);
|
||||
IA32_Push_Rm_Disp8_ESP(jit, 8);
|
||||
IA32_Push_Reg(jit, REG_EDI);
|
||||
IA32_Push_Reg(jit, REG_EBX);
|
||||
IA32_Write_Jump32_Abs(jit, IA32_Call_Imm32(jit, 0), (void *)&GenerateArrayIndirectionVectors);
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*4, MOD_REG);
|
||||
|
||||
/* Store the heap pointer back into the stack */
|
||||
//pop eax ;restore heap pointer
|
||||
//pop ecx ;restore param count
|
||||
//lea edi, [edi+ecx*4-4] ;pop params-4 off the stack
|
||||
//mov [edi], eax ;store back the heap pointer
|
||||
IA32_Pop_Reg(jit, REG_EAX);
|
||||
IA32_Pop_Reg(jit, REG_ECX);
|
||||
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, REG_ECX, SCALE4, -4);
|
||||
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, REG_EAX, MOD_MEM_REG);
|
||||
|
||||
/* Return to caller */
|
||||
//pop edx
|
||||
//pop eax
|
||||
//pop ebx
|
||||
//ret
|
||||
IA32_Pop_Reg(jit, REG_ECX);
|
||||
IA32_Pop_Reg(jit, REG_EAX);
|
||||
IA32_Pop_Reg(jit, REG_EBX);
|
||||
IA32_Return(jit);
|
||||
}
|
||||
|
||||
void WriteOp_Sysreq_N_Function(JitWriter *jit)
|
||||
{
|
||||
/* The big daddy of opcodes.
|
||||
* eax - num_params
|
||||
* ecx - native index
|
||||
*/
|
||||
CompData *data = (CompData *)jit->data;
|
||||
|
||||
/* store the number of parameters on the stack */
|
||||
//mov [edi-4], eax
|
||||
//sub edi, 4
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, REG_EAX, -4);
|
||||
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
||||
|
||||
/* save registers we will need */
|
||||
//push eax ; num_params for stack popping
|
||||
//push edx
|
||||
IA32_Push_Reg(jit, REG_EAX);
|
||||
IA32_Push_Reg(jit, AMX_REG_ALT);
|
||||
|
||||
/* Align the stack to 16 bytes */
|
||||
//push ebx
|
||||
//mov ebx, esp
|
||||
//and esp, 0xFFFFFF0
|
||||
//sub esp, 4
|
||||
IA32_Push_Reg(jit, REG_EBX);
|
||||
IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
|
||||
IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
|
||||
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
|
||||
|
||||
/* push some callback stuff */
|
||||
//push edi ; stack
|
||||
//push ecx ; native index
|
||||
IA32_Push_Reg(jit, AMX_REG_STK);
|
||||
IA32_Push_Reg(jit, REG_ECX);
|
||||
|
||||
/* Relocate stack, heap, frm information, then store back */
|
||||
//mov eax, [esi+context]
|
||||
//mov ecx, [esi+hea]
|
||||
//sub edi, ebp
|
||||
//mov [eax+hp], ecx
|
||||
//mov ecx, [esi]
|
||||
//mov [eax+sp], edi
|
||||
//mov [eax+frm], ecx
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
|
||||
|
||||
/* finally, push the last parameter and make the call */
|
||||
//push eax ; context
|
||||
//call NativeCallback
|
||||
IA32_Push_Reg(jit, REG_EAX);
|
||||
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||
if (!data->debug)
|
||||
{
|
||||
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
|
||||
} else {
|
||||
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
|
||||
}
|
||||
|
||||
/* Test for error */
|
||||
//mov ecx, [esi+context]
|
||||
//cmp [ecx+err], 0
|
||||
//jnz :error
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
|
||||
|
||||
/* restore what we damaged */
|
||||
//mov esp, ebx
|
||||
//pop ebx
|
||||
//add edi, ebp
|
||||
//pop edx
|
||||
//pop ecx ; num_params
|
||||
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
|
||||
IA32_Pop_Reg(jit, REG_EBX);
|
||||
IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Pop_Reg(jit, AMX_REG_ALT);
|
||||
IA32_Pop_Reg(jit, REG_ECX);
|
||||
|
||||
/* pop the AMX stack. do not check the margins.
|
||||
* Note that this is not a true macro - we don't bother to
|
||||
* set ALT here because nothing will be using it.
|
||||
*/
|
||||
//lea edi, [edi+ecx*4+4]
|
||||
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, REG_ECX, SCALE4, 4);
|
||||
|
||||
//ret
|
||||
IA32_Return(jit);
|
||||
}
|
||||
|
||||
void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg)
|
||||
{
|
||||
CompData *data = (CompData *)jit->data;
|
||||
|
||||
/* Save registers that may be damaged by the call */
|
||||
//push eax
|
||||
//push ecx
|
||||
//push edi
|
||||
//lea edi, [<reg>*4] ; we want the count in bytes not in cells
|
||||
IA32_Push_Reg(jit, AMX_REG_PRI);
|
||||
if (reg == REG_ECX)
|
||||
{
|
||||
IA32_Push_Reg(jit, AMX_REG_TMP);
|
||||
}
|
||||
IA32_Push_Reg(jit, AMX_REG_STK);
|
||||
IA32_Lea_Reg_RegMultImm32(jit, REG_EDI, reg, SCALE4, 0);
|
||||
|
||||
/* Get the context ptr, push it and call the check */
|
||||
//mov eax, [esi+context]
|
||||
//push eax
|
||||
//call JIT_VerifyOrAllocateTracker
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Push_Reg(jit, REG_EAX);
|
||||
jitoffs_t call = IA32_Call_Imm32(jit, 0);
|
||||
IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
|
||||
|
||||
/* Check for errors */
|
||||
//cmp eax, 0
|
||||
//jnz :error
|
||||
IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
|
||||
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
|
||||
|
||||
/* Restore */
|
||||
//pop eax
|
||||
IA32_Pop_Reg(jit, REG_EAX);
|
||||
|
||||
/* Push the register into the stack and increment pCur */
|
||||
//mov edx, [eax+vm[]]
|
||||
//mov eax, [edx+pcur]
|
||||
//add [edx+pcur], 4
|
||||
//mov [eax], edi
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EDX, offsetof(tracker_t, pCur));
|
||||
IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
|
||||
IA32_Mov_Rm_Reg(jit, REG_EAX, REG_EDI, MOD_MEM_REG);
|
||||
|
||||
/* Restore PRI, ALT and STK */
|
||||
//pop edi
|
||||
//pop ecx
|
||||
//pop eax
|
||||
IA32_Pop_Reg(jit, AMX_REG_STK);
|
||||
if (reg == REG_ECX)
|
||||
{
|
||||
IA32_Pop_Reg(jit, AMX_REG_TMP);
|
||||
}
|
||||
IA32_Pop_Reg(jit, AMX_REG_PRI);
|
||||
}
|
||||
|
||||
int JIT_VerifyOrAllocateTracker(sp_context_t *ctx)
|
||||
{
|
||||
tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
|
||||
|
||||
if ((size_t)(trk->pCur - trk->pBase) >= trk->size)
|
||||
{
|
||||
return SP_ERROR_TRACKER_BOUNDS;
|
||||
}
|
||||
|
||||
if (trk->pCur+1 - (trk->pBase + trk->size) == 0)
|
||||
{
|
||||
size_t disp = trk->size - 1;
|
||||
trk->size *= 2;
|
||||
trk->pBase = (ucell_t *)realloc(trk->pBase, trk->size * sizeof(cell_t));
|
||||
|
||||
if (!trk->pBase)
|
||||
{
|
||||
return SP_ERROR_TRACKER_BOUNDS;
|
||||
}
|
||||
|
||||
trk->pCur = trk->pBase + disp;
|
||||
}
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int JIT_VerifyLowBoundTracker(sp_context_t *ctx)
|
||||
{
|
||||
tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
|
||||
|
||||
if (trk->pCur <= trk->pBase)
|
||||
{
|
||||
return SP_ERROR_TRACKER_BOUNDS;
|
||||
}
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
void Write_RoundingTable(JitWriter *jit)
|
||||
{
|
||||
jit->write_int32(-1);
|
||||
jit->write_int32(0);
|
||||
jit->write_int32(1);
|
||||
}
|
||||
|
||||
void AlignMe(JitWriter *jit)
|
||||
{
|
||||
jitoffs_t cur_offs = jit->get_outputpos();
|
||||
jitoffs_t offset = ((cur_offs & 0xFFFFFFF0) + 16) - cur_offs;
|
||||
|
||||
if (offset)
|
||||
{
|
||||
for (jit_uint32_t i=0; i<offset; i++)
|
||||
{
|
||||
jit->write_ubyte(IA32_INT3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
|
||||
#define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
|
||||
|
||||
#include "../jit_helpers.h"
|
||||
|
||||
/**
|
||||
* This outputs the execution function for a plugin.
|
||||
* It also returns the 'return' offset, which is used for
|
||||
* breaking out of the JIT during runtime.
|
||||
*/
|
||||
jitoffs_t Write_Execute_Function(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Writes the Sysreq.* opcodes as a function call.
|
||||
*/
|
||||
void WriteOp_Sysreq_N_Function(JitWriter *jit);
|
||||
void WriteOp_Sysreq_C_Function(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Write the GENARRAY intrinsic function.
|
||||
*/
|
||||
void WriteIntrinsic_GenArray(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Generates code to set an error state in the VM and return.
|
||||
* This is used for generating the error set points in the VM.
|
||||
* GetError writes the error from the context. SetError hardcodes.
|
||||
*/
|
||||
void Write_GetError(JitWriter *jit);
|
||||
void Write_SetError(JitWriter *jit, int error);
|
||||
|
||||
/**
|
||||
* Checks the stacks for min and low errors.
|
||||
* :TODO: Should a variation of this go in the pushN opcodes?
|
||||
*/
|
||||
void Write_CheckStack_Min(JitWriter *jit);
|
||||
void Write_CheckStack_Low(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Checks the heap for min and low errors.
|
||||
*/
|
||||
void Write_CheckHeap_Min(JitWriter *jit);
|
||||
void Write_CheckHeap_Low(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Verifies an address by register. The address must reside
|
||||
* between DAT and HP and SP and STP.
|
||||
*/
|
||||
void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg);
|
||||
|
||||
/**
|
||||
* Checks for division by zero.
|
||||
*/
|
||||
void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg);
|
||||
|
||||
/**
|
||||
* Writes the break debug function.
|
||||
*/
|
||||
void Write_BreakDebug(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* These are for writing the PushN opcodes.
|
||||
*/
|
||||
void Macro_PushN_Addr(JitWriter *jit, int i);
|
||||
void Macro_PushN_S(JitWriter *jit, int i);
|
||||
void Macro_PushN_C(JitWriter *jit, int i);
|
||||
void Macro_PushN(JitWriter *jit, int i);
|
||||
|
||||
/**
|
||||
* Bound checking for the tracker stack,
|
||||
*/
|
||||
int JIT_VerifyLowBoundTracker(sp_context_t *ctx);
|
||||
int JIT_VerifyOrAllocateTracker(sp_context_t *ctx);
|
||||
|
||||
/**
|
||||
* Writes the push into tracker function.
|
||||
*/
|
||||
void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg);
|
||||
|
||||
/**
|
||||
* Writes the rounding table for the float compare opcode.
|
||||
*/
|
||||
void Write_RoundingTable(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Aligns the current code position to 16 bytes.
|
||||
*/
|
||||
void AlignMe(JitWriter *jit);
|
||||
|
||||
/**
|
||||
* Legend for Statuses:
|
||||
* ****** *** ********
|
||||
* DONE -> code generation is done
|
||||
* !GEN -> code generation is deliberate skipped because:
|
||||
* (default): compiler does not generate
|
||||
* DEPRECATED: this feature no longer exists/supported
|
||||
* UNSUPPORTED: this opcode is not supported
|
||||
* TODO: done in case needed
|
||||
* VERIFIED -> code generation is checked as run-time working. prefixes:
|
||||
* ! errors are not checked yet.
|
||||
* - non-inline errors are not checked yet.
|
||||
* ~ assumed checked because of related variation, but not actually checked
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OP_NONE, /* invalid opcode */
|
||||
OP_LOAD_PRI, //!VERIFIED
|
||||
OP_LOAD_ALT, //~!VERIFIED (load.pri)
|
||||
OP_LOAD_S_PRI, //VERIFIED
|
||||
OP_LOAD_S_ALT, //VERIFIED
|
||||
OP_LREF_PRI, //VERIFIED
|
||||
OP_LREF_ALT, //~VERIFIED
|
||||
OP_LREF_S_PRI, //VERIFIED
|
||||
OP_LREF_S_ALT, //~VERIFIED (lref.s.pri)
|
||||
OP_LOAD_I, //VERIFIED
|
||||
OP_LODB_I, //VERIFIED
|
||||
OP_CONST_PRI, //VERIFIED
|
||||
OP_CONST_ALT, //~VERIFIED (const.pri)
|
||||
OP_ADDR_PRI, //VERIFIED
|
||||
OP_ADDR_ALT, //VERIFIED
|
||||
OP_STOR_PRI, //VERIFIED
|
||||
OP_STOR_ALT, //~VERIFIED (stor.pri)
|
||||
OP_STOR_S_PRI, //VERIFIED
|
||||
OP_STOR_S_ALT, //~VERIFIED (stor.s.pri)
|
||||
OP_SREF_PRI, //VERIFIED
|
||||
OP_SREF_ALT, //~VERIFIED
|
||||
OP_SREF_S_PRI, //VERIFIED
|
||||
OP_SREF_S_ALT, //~VERIFIED (stor.s.alt)
|
||||
OP_STOR_I, //VERIFIED
|
||||
OP_STRB_I, //VERIFIED
|
||||
OP_LIDX, //VERIFIED
|
||||
OP_LIDX_B, //DONE
|
||||
OP_IDXADDR, //VERIFIED
|
||||
OP_IDXADDR_B, //DONE
|
||||
OP_ALIGN_PRI, // !GEN :TODO: - only used for pack access, drop support in compiler first
|
||||
OP_ALIGN_ALT, // !GEN :TODO: - only used for pack access, drop support in compiler first
|
||||
OP_LCTRL, // !GEN
|
||||
OP_SCTRL, // !GEN
|
||||
OP_MOVE_PRI, //~VERIFIED (move.alt)
|
||||
OP_MOVE_ALT, //VERIFIED
|
||||
OP_XCHG, //DONE
|
||||
OP_PUSH_PRI, //DONE
|
||||
OP_PUSH_ALT, //DONE
|
||||
OP_PUSH_R, // !GEN DEPRECATED
|
||||
OP_PUSH_C, //VERIFIED
|
||||
OP_PUSH, //DONE
|
||||
OP_PUSH_S, //VERIFIED
|
||||
OP_POP_PRI, //VERIFIED
|
||||
OP_POP_ALT, //VERIFIED
|
||||
OP_STACK, //VERIFIED
|
||||
OP_HEAP, //VERIFIED
|
||||
OP_PROC, //VERIFIED
|
||||
OP_RET, // !GEN
|
||||
OP_RETN, //VERIFIED
|
||||
OP_CALL, //VERIFIED
|
||||
OP_CALL_PRI, // !GEN
|
||||
OP_JUMP, //VERIFIED
|
||||
OP_JREL, // !GEN
|
||||
OP_JZER, //VERIFIED
|
||||
OP_JNZ, //DONE
|
||||
OP_JEQ, //VERIFIED
|
||||
OP_JNEQ, //VERIFIED
|
||||
OP_JLESS, // !GEN
|
||||
OP_JLEQ, // !GEN
|
||||
OP_JGRTR, // !GEN
|
||||
OP_JGEQ, // !GEN
|
||||
OP_JSLESS, //VERIFIED
|
||||
OP_JSLEQ, //VERIFIED
|
||||
OP_JSGRTR, //VERIFIED
|
||||
OP_JSGEQ, //VERIFIED
|
||||
OP_SHL, //VERIFIED
|
||||
OP_SHR, //VERIFIED (Note: operator >>>)
|
||||
OP_SSHR, //VERIFIED (Note: operator >>)
|
||||
OP_SHL_C_PRI, //DONE
|
||||
OP_SHL_C_ALT, //DONE
|
||||
OP_SHR_C_PRI, //DONE
|
||||
OP_SHR_C_ALT, //DONE
|
||||
OP_SMUL, //VERIFIED
|
||||
OP_SDIV, //DONE
|
||||
OP_SDIV_ALT, //VERIFIED
|
||||
OP_UMUL, // !GEN
|
||||
OP_UDIV, // !GEN
|
||||
OP_UDIV_ALT, // !GEN
|
||||
OP_ADD, //VERIFIED
|
||||
OP_SUB, //DONE
|
||||
OP_SUB_ALT, //VERIFIED
|
||||
OP_AND, //VERIFIED
|
||||
OP_OR, //VERIFIED
|
||||
OP_XOR, //VERIFIED
|
||||
OP_NOT, //VERIFIED
|
||||
OP_NEG, //VERIFIED
|
||||
OP_INVERT, //VERIFIED
|
||||
OP_ADD_C, //VERIFIED
|
||||
OP_SMUL_C, //VERIFIED
|
||||
OP_ZERO_PRI, //VERIFIED
|
||||
OP_ZERO_ALT, //~VERIFIED
|
||||
OP_ZERO, //VERIFIED
|
||||
OP_ZERO_S, //VERIFIED
|
||||
OP_SIGN_PRI, //DONE
|
||||
OP_SIGN_ALT, //DONE
|
||||
OP_EQ, //VERIFIED
|
||||
OP_NEQ, //VERIFIED
|
||||
OP_LESS, // !GEN
|
||||
OP_LEQ, // !GEN
|
||||
OP_GRTR, // !GEN
|
||||
OP_GEQ, // !GEN
|
||||
OP_SLESS, //VERIFIED
|
||||
OP_SLEQ, //VERIFIED
|
||||
OP_SGRTR, //VERIFIED
|
||||
OP_SGEQ, //VERIFIED
|
||||
OP_EQ_C_PRI, //DONE
|
||||
OP_EQ_C_ALT, //DONE
|
||||
OP_INC_PRI, //VERIFIED
|
||||
OP_INC_ALT, //~VERIFIED (inc.pri)
|
||||
OP_INC, //VERIFIED
|
||||
OP_INC_S, //VERIFIED
|
||||
OP_INC_I, //VERIFIED
|
||||
OP_DEC_PRI, //VERIFIED
|
||||
OP_DEC_ALT, //~VERIFIED (dec.pri)
|
||||
OP_DEC, //VERIFIED
|
||||
OP_DEC_S, //VERIFIED
|
||||
OP_DEC_I, //VERIFIED
|
||||
OP_MOVS, //VERIFIED
|
||||
OP_CMPS, // !GEN
|
||||
OP_FILL, //VERIFIED
|
||||
OP_HALT, //DONE
|
||||
OP_BOUNDS, //VERIFIED
|
||||
OP_SYSREQ_PRI, // !GEN
|
||||
OP_SYSREQ_C, //VERIFIED
|
||||
OP_FILE, // !GEN DEPRECATED
|
||||
OP_LINE, // !GEN DEPRECATED
|
||||
OP_SYMBOL, // !GEN DEPRECATED
|
||||
OP_SRANGE, // !GEN DEPRECATED
|
||||
OP_JUMP_PRI, // !GEN
|
||||
OP_SWITCH, //VERIFIED
|
||||
OP_CASETBL, //VERIFIED
|
||||
OP_SWAP_PRI, //VERIFIED
|
||||
OP_SWAP_ALT, //~VERIFIED (swap.alt)
|
||||
OP_PUSH_ADR, //VERIFIED
|
||||
OP_NOP, //VERIFIED (lol)
|
||||
OP_SYSREQ_N, //VERIFIED
|
||||
OP_SYMTAG, // !GEN DEPRECATED
|
||||
OP_BREAK, //DONE
|
||||
OP_PUSH2_C, //~VERIFIED (push3.c)
|
||||
OP_PUSH2, //VERIFIED
|
||||
OP_PUSH2_S, //VERIFIED
|
||||
OP_PUSH2_ADR, //VERIFIED
|
||||
OP_PUSH3_C, //VERIFIED
|
||||
OP_PUSH3, //~VERIFIED (push2)
|
||||
OP_PUSH3_S, //~VERIFIED (push2.s)
|
||||
OP_PUSH3_ADR, //~VERIFIED (push2.adr)
|
||||
OP_PUSH4_C, //~VERIFIED (push3.c)
|
||||
OP_PUSH4, //~VERIFIED (push2)
|
||||
OP_PUSH4_S, //~VERIFIED (push2.s)
|
||||
OP_PUSH4_ADR, //~VERIFIED (push2.adr)
|
||||
OP_PUSH5_C, //~VERIFIED (push3.c)
|
||||
OP_PUSH5, //~VERIFIED (push2)
|
||||
OP_PUSH5_S, //~VERIFIED (push2.s)
|
||||
OP_PUSH5_ADR, //~VERIFIED (push2.adr)
|
||||
OP_LOAD_BOTH, //VERIFIED
|
||||
OP_LOAD_S_BOTH, //VERIFIED
|
||||
OP_CONST, //VERIFIED
|
||||
OP_CONST_S, //DONE
|
||||
/* ----- */
|
||||
OP_SYSREQ_D, // !GEN UNSUPPORT
|
||||
OP_SYSREQ_ND, // !GEN UNSUPPORT
|
||||
/* ----- */
|
||||
OP_TRACKER_PUSH_C, //DONE
|
||||
OP_TRACKER_POP_SETHEAP, //VERIFIED
|
||||
OP_GENARRAY, //VERIFIED
|
||||
OP_GENARRAY_Z, //-VERIFIED (not tested for 1D arrays)
|
||||
OP_STRADJUST_PRI, //VERIFIED
|
||||
OP_STACKADJUST, //:TODO: VERIFY
|
||||
OP_FABS, //VERIFIED
|
||||
OP_FLOAT, //VERIFIED
|
||||
OP_FLOATADD, //VERIFIED
|
||||
OP_FLOATSUB, //VERIFIED
|
||||
OP_FLOATMUL, //VERIFIED
|
||||
OP_FLOATDIV, //VERIFIED
|
||||
OP_RND_TO_NEAREST, //VERIFIED
|
||||
OP_RND_TO_FLOOR, //VERIFIED
|
||||
OP_RND_TO_CEIL, //VERIFIED
|
||||
OP_RND_TO_ZERO, //VERIFIED
|
||||
OP_FLOATCMP, //VERIFIED
|
||||
/* ----- */
|
||||
OP_NUM_OPCODES
|
||||
} OPCODE;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
|
||||
@@ -0,0 +1,763 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
case OP_MOVE_PRI:
|
||||
{
|
||||
WriteOp_Move_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_MOVE_ALT:
|
||||
{
|
||||
WriteOp_Move_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_XCHG:
|
||||
{
|
||||
WriteOp_Xchg(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH:
|
||||
{
|
||||
WriteOp_Push(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH_S:
|
||||
{
|
||||
WriteOp_Push_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH2_C:
|
||||
{
|
||||
WriteOp_Push2_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH3_C:
|
||||
{
|
||||
WriteOp_Push3_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH4_C:
|
||||
{
|
||||
WriteOp_Push4_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH5_C:
|
||||
{
|
||||
WriteOp_Push5_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH2_ADR:
|
||||
{
|
||||
WriteOp_Push2_Adr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH3_ADR:
|
||||
{
|
||||
WriteOp_Push3_Adr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH4_ADR:
|
||||
{
|
||||
WriteOp_Push4_Adr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH5_ADR:
|
||||
{
|
||||
WriteOp_Push5_Adr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH2_S:
|
||||
{
|
||||
WriteOp_Push2_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH3_S:
|
||||
{
|
||||
WriteOp_Push3_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH4_S:
|
||||
{
|
||||
WriteOp_Push4_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH5_S:
|
||||
{
|
||||
WriteOp_Push5_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH5:
|
||||
{
|
||||
WriteOp_Push5(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH4:
|
||||
{
|
||||
WriteOp_Push4(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH3:
|
||||
{
|
||||
WriteOp_Push3(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH2:
|
||||
{
|
||||
WriteOp_Push2(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ZERO_PRI:
|
||||
{
|
||||
WriteOp_Zero_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ZERO_ALT:
|
||||
{
|
||||
WriteOp_Zero_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PROC:
|
||||
{
|
||||
WriteOp_Proc(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SHL:
|
||||
{
|
||||
WriteOp_Shl(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SHR:
|
||||
{
|
||||
WriteOp_Shr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SSHR:
|
||||
{
|
||||
WriteOp_Sshr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SHL_C_PRI:
|
||||
{
|
||||
WriteOp_Shl_C_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SHL_C_ALT:
|
||||
{
|
||||
WriteOp_Shl_C_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SHR_C_PRI:
|
||||
{
|
||||
WriteOp_Shr_C_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SHR_C_ALT:
|
||||
{
|
||||
WriteOp_Shr_C_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SMUL:
|
||||
{
|
||||
WriteOp_SMul(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ADD:
|
||||
{
|
||||
WriteOp_Add(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SUB:
|
||||
{
|
||||
WriteOp_Sub(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SUB_ALT:
|
||||
{
|
||||
WriteOp_Sub_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_NOP:
|
||||
{
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
case OP_NOT:
|
||||
{
|
||||
WriteOp_Not(jit);
|
||||
break;
|
||||
}
|
||||
case OP_NEG:
|
||||
{
|
||||
WriteOp_Neg(jit);
|
||||
break;
|
||||
}
|
||||
case OP_XOR:
|
||||
{
|
||||
WriteOp_Xor(jit);
|
||||
break;
|
||||
}
|
||||
case OP_OR:
|
||||
{
|
||||
WriteOp_Or(jit);
|
||||
break;
|
||||
}
|
||||
case OP_AND:
|
||||
{
|
||||
WriteOp_And(jit);
|
||||
break;
|
||||
}
|
||||
case OP_INVERT:
|
||||
{
|
||||
WriteOp_Invert(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ADD_C:
|
||||
{
|
||||
WriteOp_Add_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SMUL_C:
|
||||
{
|
||||
WriteOp_SMul_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SIGN_PRI:
|
||||
{
|
||||
WriteOp_Sign_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SIGN_ALT:
|
||||
{
|
||||
WriteOp_Sign_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_EQ:
|
||||
{
|
||||
WriteOp_Eq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_NEQ:
|
||||
{
|
||||
WriteOp_Neq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SLESS:
|
||||
{
|
||||
WriteOp_Sless(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SLEQ:
|
||||
{
|
||||
WriteOp_Sleq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SGRTR:
|
||||
{
|
||||
WriteOp_Sgrtr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SGEQ:
|
||||
{
|
||||
WriteOp_Sgeq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_EQ_C_PRI:
|
||||
{
|
||||
WriteOp_Eq_C_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_EQ_C_ALT:
|
||||
{
|
||||
WriteOp_Eq_C_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_INC_PRI:
|
||||
{
|
||||
WriteOp_Inc_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_INC_ALT:
|
||||
{
|
||||
WriteOp_Inc_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_INC:
|
||||
{
|
||||
WriteOp_Inc(jit);
|
||||
break;
|
||||
}
|
||||
case OP_INC_S:
|
||||
{
|
||||
WriteOp_Inc_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_INC_I:
|
||||
{
|
||||
WriteOp_Inc_I(jit);
|
||||
break;
|
||||
}
|
||||
case OP_DEC_PRI:
|
||||
{
|
||||
WriteOp_Dec_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_DEC_ALT:
|
||||
{
|
||||
WriteOp_Dec_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_DEC:
|
||||
{
|
||||
WriteOp_Dec(jit);
|
||||
break;
|
||||
}
|
||||
case OP_DEC_S:
|
||||
{
|
||||
WriteOp_Dec_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_DEC_I:
|
||||
{
|
||||
WriteOp_Dec_I(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_PRI:
|
||||
{
|
||||
WriteOp_Load_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_ALT:
|
||||
{
|
||||
WriteOp_Load_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_S_PRI:
|
||||
{
|
||||
WriteOp_Load_S_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_S_ALT:
|
||||
{
|
||||
WriteOp_Load_S_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LREF_PRI:
|
||||
{
|
||||
WriteOp_Lref_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LREF_ALT:
|
||||
{
|
||||
WriteOp_Lref_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LREF_S_PRI:
|
||||
{
|
||||
WriteOp_Lref_S_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LREF_S_ALT:
|
||||
{
|
||||
WriteOp_Lref_S_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CONST_PRI:
|
||||
{
|
||||
WriteOp_Const_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CONST_ALT:
|
||||
{
|
||||
WriteOp_Const_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ADDR_PRI:
|
||||
{
|
||||
WriteOp_Addr_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ADDR_ALT:
|
||||
{
|
||||
WriteOp_Addr_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STOR_PRI:
|
||||
{
|
||||
WriteOp_Stor_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STOR_ALT:
|
||||
{
|
||||
WriteOp_Stor_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STOR_S_PRI:
|
||||
{
|
||||
WriteOp_Stor_S_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STOR_S_ALT:
|
||||
{
|
||||
WriteOp_Stor_S_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_IDXADDR:
|
||||
{
|
||||
WriteOp_Idxaddr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SREF_PRI:
|
||||
{
|
||||
WriteOp_Sref_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SREF_ALT:
|
||||
{
|
||||
WriteOp_Sref_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SREF_S_PRI:
|
||||
{
|
||||
WriteOp_Sref_S_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SREF_S_ALT:
|
||||
{
|
||||
WriteOp_Sref_S_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_POP_PRI:
|
||||
{
|
||||
WriteOp_Pop_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_POP_ALT:
|
||||
{
|
||||
WriteOp_Pop_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SWAP_PRI:
|
||||
{
|
||||
WriteOp_Swap_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SWAP_ALT:
|
||||
{
|
||||
WriteOp_Swap_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH_ADR:
|
||||
{
|
||||
WriteOp_PushAddr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_MOVS:
|
||||
{
|
||||
WriteOp_Movs(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FILL:
|
||||
{
|
||||
WriteOp_Fill(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH_C:
|
||||
{
|
||||
WriteOp_Push_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ZERO:
|
||||
{
|
||||
WriteOp_Zero(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ZERO_S:
|
||||
{
|
||||
WriteOp_Zero_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH_PRI:
|
||||
{
|
||||
WriteOp_Push_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_PUSH_ALT:
|
||||
{
|
||||
WriteOp_Push_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_BOTH:
|
||||
{
|
||||
WriteOp_Load_Both(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_S_BOTH:
|
||||
{
|
||||
WriteOp_Load_S_Both(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CONST:
|
||||
{
|
||||
WriteOp_Const(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CONST_S:
|
||||
{
|
||||
WriteOp_Const_S(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LOAD_I:
|
||||
{
|
||||
WriteOp_Load_I(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LODB_I:
|
||||
{
|
||||
WriteOp_Lodb_I(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STOR_I:
|
||||
{
|
||||
WriteOp_Stor_I(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STRB_I:
|
||||
{
|
||||
WriteOp_Strb_I(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LIDX:
|
||||
{
|
||||
WriteOp_Lidx(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LIDX_B:
|
||||
{
|
||||
WriteOp_Lidx_B(jit);
|
||||
break;
|
||||
}
|
||||
case OP_IDXADDR_B:
|
||||
{
|
||||
WriteOp_Idxaddr_B(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STACK:
|
||||
{
|
||||
WriteOp_Stack(jit);
|
||||
break;
|
||||
}
|
||||
case OP_HEAP:
|
||||
{
|
||||
WriteOp_Heap(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SDIV:
|
||||
{
|
||||
WriteOp_SDiv(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SDIV_ALT:
|
||||
{
|
||||
WriteOp_SDiv_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_RETN:
|
||||
{
|
||||
WriteOp_Retn(jit);
|
||||
break;
|
||||
}
|
||||
case OP_BOUNDS:
|
||||
{
|
||||
WriteOp_Bounds(jit);
|
||||
break;
|
||||
}
|
||||
case OP_HALT:
|
||||
{
|
||||
WriteOp_Halt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_BREAK:
|
||||
{
|
||||
WriteOp_Break(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JUMP:
|
||||
{
|
||||
WriteOp_Jump(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JZER:
|
||||
{
|
||||
WriteOp_Jzer(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JNZ:
|
||||
{
|
||||
WriteOp_Jnz(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JEQ:
|
||||
{
|
||||
WriteOp_Jeq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JNEQ:
|
||||
{
|
||||
WriteOp_Jneq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JSLESS:
|
||||
{
|
||||
WriteOp_Jsless(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JSGRTR:
|
||||
{
|
||||
WriteOp_JsGrtr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JSGEQ:
|
||||
{
|
||||
WriteOp_JsGeq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JSLEQ:
|
||||
{
|
||||
WriteOp_Jsleq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SWITCH:
|
||||
{
|
||||
WriteOp_Switch(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CASETBL:
|
||||
{
|
||||
WriteOp_Casetbl(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CALL:
|
||||
{
|
||||
WriteOp_Call(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SYSREQ_C:
|
||||
{
|
||||
WriteOp_Sysreq_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SYSREQ_N:
|
||||
{
|
||||
if (data->inline_level & JIT_INLINE_NATIVES)
|
||||
{
|
||||
WriteOp_Sysreq_N(jit);
|
||||
} else {
|
||||
WriteOp_Sysreq_N_NoInline(jit);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_TRACKER_PUSH_C:
|
||||
{
|
||||
WriteOp_Tracker_Push_C(jit);
|
||||
break;
|
||||
}
|
||||
case OP_TRACKER_POP_SETHEAP:
|
||||
{
|
||||
WriteOp_Tracker_Pop_SetHeap(jit);
|
||||
break;
|
||||
}
|
||||
case OP_GENARRAY:
|
||||
{
|
||||
WriteOp_GenArray(jit, false);
|
||||
break;
|
||||
}
|
||||
case OP_GENARRAY_Z:
|
||||
{
|
||||
WriteOp_GenArray(jit, true);
|
||||
break;
|
||||
}
|
||||
case OP_STRADJUST_PRI:
|
||||
{
|
||||
WriteOp_Stradjust_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FABS:
|
||||
{
|
||||
WriteOp_FloatAbs(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FLOAT:
|
||||
{
|
||||
WriteOp_Float(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FLOATADD:
|
||||
{
|
||||
WriteOp_FloatAdd(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FLOATSUB:
|
||||
{
|
||||
WriteOp_FloatSub(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FLOATMUL:
|
||||
{
|
||||
WriteOp_FloatMul(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FLOATDIV:
|
||||
{
|
||||
WriteOp_FloatDiv(jit);
|
||||
break;
|
||||
}
|
||||
case OP_RND_TO_NEAREST:
|
||||
{
|
||||
WriteOp_RountToNearest(jit);
|
||||
break;
|
||||
}
|
||||
case OP_RND_TO_FLOOR:
|
||||
{
|
||||
WriteOp_RoundToFloor(jit);
|
||||
break;
|
||||
}
|
||||
case OP_RND_TO_ZERO:
|
||||
{
|
||||
WriteOp_RoundToZero(jit);
|
||||
break;
|
||||
}
|
||||
case OP_RND_TO_CEIL:
|
||||
{
|
||||
WriteOp_RoundToCeil(jit);
|
||||
break;
|
||||
}
|
||||
case OP_FLOATCMP:
|
||||
{
|
||||
WriteOp_FloatCompare(jit);
|
||||
break;
|
||||
}
|
||||
case OP_STACKADJUST:
|
||||
{
|
||||
WriteOp_StackAdjust(jit);
|
||||
break;
|
||||
}
|
||||
#if defined USE_UNGEN_OPCODES
|
||||
#include "ungen_opcode_switch.inc"
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
data->error_set = SP_ERROR_INVALID_INSTRUCTION;
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
case OP_UMUL:
|
||||
{
|
||||
WriteOp_UMul(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LESS:
|
||||
{
|
||||
WriteOp_Less(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LEQ:
|
||||
{
|
||||
WriteOp_Leq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_GRTR:
|
||||
{
|
||||
WriteOp_Grtr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_GEQ:
|
||||
{
|
||||
WriteOp_Geq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ALIGN_PRI:
|
||||
{
|
||||
WriteOp_Align_Pri(jit);
|
||||
break;
|
||||
}
|
||||
case OP_ALIGN_ALT:
|
||||
{
|
||||
WriteOp_Align_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_LCTRL:
|
||||
{
|
||||
WriteOp_Lctrl(jit);
|
||||
break;
|
||||
}
|
||||
case OP_SCTRL:
|
||||
{
|
||||
WriteOp_Sctrl(jit);
|
||||
break;
|
||||
}
|
||||
case OP_UDIV:
|
||||
{
|
||||
WriteOp_UDiv(jit);
|
||||
break;
|
||||
}
|
||||
case OP_UDIV_ALT:
|
||||
{
|
||||
WriteOp_UDiv_Alt(jit);
|
||||
break;
|
||||
}
|
||||
case OP_RET:
|
||||
{
|
||||
WriteOp_Ret(jit);
|
||||
break;
|
||||
}
|
||||
case OP_CMPS:
|
||||
{
|
||||
WriteOp_Cmps(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JREL:
|
||||
{
|
||||
WriteOp_JRel(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JLESS:
|
||||
{
|
||||
WriteOp_Jless(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JLEQ:
|
||||
{
|
||||
WriteOp_Jeq(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JGRTR:
|
||||
{
|
||||
WriteOp_Jgrtr(jit);
|
||||
break;
|
||||
}
|
||||
case OP_JGEQ:
|
||||
{
|
||||
WriteOp_Jgeq(jit);
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn JIT
|
||||
* Copyright (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This file is not open source and may not be copied without explicit wriiten
|
||||
* permission of AlliedModders LLC. This file may not be redistributed in whole
|
||||
* or significant part.
|
||||
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
|
||||
#define _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
|
||||
|
||||
inline void WriteOp_UMul(JitWriter *jit)
|
||||
{
|
||||
//mov ecx, edx
|
||||
//mul edx
|
||||
//mov edx, ecx
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
|
||||
}
|
||||
|
||||
inline void WriteOp_Less(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx ; PRI < ALT ? (unsigned)
|
||||
//mov eax, 0
|
||||
//setb al
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
||||
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B);
|
||||
}
|
||||
|
||||
inline void WriteOp_Leq(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx ; PRI <= ALT ? (unsigned)
|
||||
//mov eax, 0
|
||||
//setbe al
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
||||
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE);
|
||||
}
|
||||
|
||||
inline void WriteOp_Grtr(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx ; PRI > ALT ? (unsigned)
|
||||
//mov eax, 0
|
||||
//seta al
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
||||
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A);
|
||||
}
|
||||
|
||||
inline void WriteOp_Geq(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx ; PRI >= ALT ? (unsigned)
|
||||
//mov eax, 0
|
||||
//setae al
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
||||
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE);
|
||||
}
|
||||
|
||||
inline void WriteOp_Align_Pri(JitWriter *jit)
|
||||
{
|
||||
//xor eax, <cellsize - val>
|
||||
cell_t val = sizeof(cell_t) - jit->read_cell();
|
||||
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
||||
{
|
||||
IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
|
||||
} else {
|
||||
IA32_Xor_Eax_Imm32(jit, val);
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteOp_Align_Alt(JitWriter *jit)
|
||||
{
|
||||
//xor edx, <cellsize - val>
|
||||
cell_t val = sizeof(cell_t) - jit->read_cell();
|
||||
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
||||
{
|
||||
IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val);
|
||||
} else {
|
||||
IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val);
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteOp_Cmps(JitWriter *jit)
|
||||
{
|
||||
//push edi
|
||||
//push esi
|
||||
//lea esi, [ebp+edx]
|
||||
//lea edi, [ebp+eax]
|
||||
//mov ecx, <val>
|
||||
unsigned int val = jit->read_cell();
|
||||
|
||||
IA32_Push_Reg(jit, REG_EDI);
|
||||
IA32_Push_Reg(jit, REG_ESI);
|
||||
IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
|
||||
IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
||||
IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
|
||||
|
||||
//xor eax, eax
|
||||
//repe cmpsb
|
||||
//je :cmps1
|
||||
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
||||
IA32_Rep(jit);
|
||||
IA32_Cmpsb(jit);
|
||||
jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0);
|
||||
|
||||
//sbb eax, eax
|
||||
//sbb eax, -1
|
||||
IA32_Sbb_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
||||
IA32_Sbb_Rm_Imm8(jit, AMX_REG_PRI, -1, MOD_REG);
|
||||
|
||||
//:cmps1
|
||||
//pop esi
|
||||
//pop edi
|
||||
IA32_Send_Jump8_Here(jit, jmp);
|
||||
IA32_Pop_Reg(jit, REG_ESI);
|
||||
IA32_Pop_Reg(jit, REG_EDI);
|
||||
}
|
||||
|
||||
inline void WriteOp_Lctrl(JitWriter *jit)
|
||||
{
|
||||
cell_t val = jit->read_cell();
|
||||
switch (val)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
//mov ecx, [esi+ctx]
|
||||
//mov eax, [ecx+ctx.codebase]
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, codebase));
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
//mov eax, ebp
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
//mov eax, [esi+hea]
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
//mov ecx, [esi+ctx]
|
||||
//mov eax, [ecx+ctx.memory]
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory));
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
//mov eax, edi
|
||||
//sub eax, ebp - unrelocate
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG);
|
||||
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
//mov eax, [esi+frm]
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
//mov eax, [cip]
|
||||
jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
||||
jitoffs_t save = jit->get_outputpos();
|
||||
jit->set_outputpos(imm32);
|
||||
jit->write_int32((uint32_t)(jit->outbase + save));
|
||||
jit->set_outputpos(save);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteOp_Sctrl(JitWriter *jit)
|
||||
{
|
||||
cell_t val = jit->read_cell();
|
||||
switch (val)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
//mov [esi+hea], eax
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_PRI, AMX_INFO_HEAP);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
//lea edi, [ebp+eax]
|
||||
IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
//lea ebx, [ebp+eax] - overwrite frm
|
||||
//mov [esi+frm], eax - overwrite stacked frame
|
||||
IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_FRM, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
||||
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_PRI, MOD_MEM_REG);
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
IA32_Jump_Reg(jit, AMX_REG_PRI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteOp_UDiv(JitWriter *jit)
|
||||
{
|
||||
//mov ecx, edx
|
||||
//xor edx, edx
|
||||
//div ecx
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
|
||||
Write_Check_DivZero(jit, AMX_REG_TMP);
|
||||
IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
|
||||
}
|
||||
|
||||
inline void WriteOp_UDiv_Alt(JitWriter *jit)
|
||||
{
|
||||
//mov ecx, eax
|
||||
//mov eax, edx
|
||||
//xor edx, edx
|
||||
//div ecx
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
|
||||
Write_Check_DivZero(jit, AMX_REG_TMP);
|
||||
IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
|
||||
}
|
||||
|
||||
inline void WriteOp_Ret(JitWriter *jit)
|
||||
{
|
||||
//mov ebx, [edi] - get old FRM
|
||||
//add edi, 4 - pop stack
|
||||
//mov [esi+frm], ebx - restore
|
||||
//add ebx, ebp - relocate
|
||||
//ret
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
|
||||
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
||||
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
|
||||
IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
|
||||
IA32_Return(jit);
|
||||
}
|
||||
|
||||
inline void WriteOp_JRel(JitWriter *jit)
|
||||
{
|
||||
//jmp <offs> ;relative jump
|
||||
cell_t cip_offs = jit->read_cell();
|
||||
|
||||
/* Note that since code size calculation has to be done in the same
|
||||
* phase as building relocation information, we cannot know the jump size
|
||||
* beforehand. Thus, we always write full 32bit jumps for safety.
|
||||
*/
|
||||
jitoffs_t jmp = IA32_Jump_Imm32(jit, 0);
|
||||
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs));
|
||||
}
|
||||
|
||||
inline void WriteOp_Jless(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx
|
||||
//jb <target>
|
||||
cell_t target = jit->read_cell();
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false));
|
||||
}
|
||||
|
||||
inline void WriteOp_Jleq(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx
|
||||
//jbe <target>
|
||||
cell_t target = jit->read_cell();
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false));
|
||||
}
|
||||
|
||||
inline void WriteOp_Jgrtr(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx
|
||||
//ja <target>
|
||||
cell_t target = jit->read_cell();
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false));
|
||||
}
|
||||
|
||||
inline void WriteOp_Jgeq(JitWriter *jit)
|
||||
{
|
||||
//cmp eax, edx
|
||||
//jae <target>
|
||||
cell_t target = jit->read_cell();
|
||||
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
||||
IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false));
|
||||
}
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
|
||||
@@ -0,0 +1,103 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
#include "jit_version.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SVN_FILE_VERSION
|
||||
PRODUCTVERSION SVN_FILE_VERSION
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "SourcePawn JIT"
|
||||
VALUE "FileDescription", "SourcePawn JIT/Virtual Machine"
|
||||
VALUE "FileVersion", SVN_FULL_VERSION
|
||||
VALUE "InternalName", "sourcemod"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2004-2008, AlliedModders LLC"
|
||||
VALUE "OriginalFilename", "sourcepawn.jit.x86.dll"
|
||||
VALUE "ProductName", "SourcePawn JIT"
|
||||
VALUE "ProductVersion", SVN_FULL_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
Reference in New Issue
Block a user