GithubHelp home page GithubHelp logo

alliedmodders / sourcepawn Goto Github PK

View Code? Open in Web Editor NEW
353.0 353.0 64.0 7.21 MB

A small, statically typed scripting language.

License: Other

C 0.83% C++ 51.74% SourcePawn 39.56% Python 2.39% PHP 1.36% JavaScript 0.08% CSS 0.11% Batchfile 0.02% Shell 0.07% C# 3.56% Pawn 0.23% Smarty 0.05%

sourcepawn's People

Contributors

amaroq7 avatar asherkin avatar bara avatar c0rp3n avatar collinsmith avatar crazyhackgut avatar deathreus avatar dvander avatar elymination avatar fortytwofortytwo avatar fyren avatar headline avatar joinedsenses avatar kailo97 avatar kgns avatar kylesanderson avatar maxijabase avatar maximsmol avatar peace-maker avatar perfectlaugh avatar pheubel avatar psychonic avatar rsklippy avatar rumblefrog avatar slidybat avatar theds avatar vanz666 avatar voided avatar wildcard65 avatar xpaw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sourcepawn's Issues

spcomp assertion on malformed if

thanks to shavit for reporting this one.

Gave it a shot myself, but a solution wasn't obvious to me. Here's how to replicate

int main(){
    if(
    {
        int b = c();
    }
}
C:\Users\Micha\Desktop\alliedmodders\sourcemod\sourcepawn\build\compiler\spcomp>spcomp test.sp
SourcePawn Compiler 1.10
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC

Assertion failed: lval1->sym!=NULL, file C:\Users\Micha\Desktop\alliedmodders\sourcemod\sourcepawn\compiler\expressions.cpp, line 1057

Docgen display issue with some typeset params

I haven't narrowed down the difference between which ones display fine and which ones have the issue, but for some typeset parameters of functions, the typeset definition is displayed as the type, instead of the typeset name. Some examples are below.

Include:
typedef SQLTCallback = function void (Handle owner, Handle hndl, const char[] error, any data);

Display:
void SQL_TQuery(Handle database, SQLTCallback callback, const char[] query, any data, DBPriority prio)

Include:

typedef MsgPostHook = function void (UserMsg msg_id, bool sent);

native void HookUserMessage(UserMsg msg_id, MsgHook hook, bool intercept=false, MsgPostHook post=INVALID_FUNCTION);

Display:
void HookUserMessage(UserMsg msg_id, MsgHook hook, bool intercept, function void(UserMsg msg_id, bool sent) post)

Compiler asserts if static methodmap function is used before declaration

Friend catched this case while coding plugin. Here my example for demonstrating it.
crash1.sp

#include "crash2.sp"
public void OnPluginStart()
{
	DoIt(); // - Shia LaBeouf
}

crash2.sp

#include "crash3.sp"
methodmap Shia
{
	public static Speak()
	{
		PrintToServer("Do it! - Shia LaBeouf");
	}
};

crash3.sp

void DoIt()
{
	Shia.Speak();
}

log

crash3.sp(3) : error 017: undefined symbol "Shia"

Compiler crashed while compilation.
If move #include "crash3.sp" below mathodmap - everything ok.
Test environment: Windows 10, SM 1.8.0.6041 & 1.9.0.6226

Sleep and Exit

I wrote about this feature in Discord and IRC. And retry here, in issue.
Code like:

public void OnPluginStart() {
    sleep;
}

cause the server to crash.
Accelerator: https://crash.limetech.org/uhqigne5rpie

SM Version:

 SourceMod Version Information:
    SourceMod Version: 1.8.0.6036
    SourcePawn Engine: SourcePawn 1.8, jit-x86 (build 1.8.0.6036)
    SourcePawn API: v1 = 4, v2 = 11
    Compiled on: Nov  3 2017 19:06:38
    Built from: https://github.com/alliedmodders/sourcemod/commit/fef5583
    Build ID: 6036:fef5583
    http://www.sourcemod.net/

Code with this "feature":

sourcepawn/compiler/sc1.cpp

Lines 5434 to 5437 in a1c9bfb

case tEXIT:
doexit();
lastst=tEXIT;
break;

sourcepawn/compiler/sc1.cpp

Lines 5442 to 5445 in a1c9bfb

case tSLEEP:
dosleep();
lastst=tSLEEP;
break;

"Lambda" functions

Add support for lambda functions. Like this:

void DisplayDBTablesInServerConsole() {
    g_hDB.Query( [] (Database hDB, DBResultSet hResults, const char[] szError, any data) -> void {
        char szTable[64];
        while (hResults.FetchRow()) {
            hResults.FetchString(0, szTable, sizeof(szTable));
            PrintToServer("Found table in DB: %s", szTable);
        }
    }, "SHOW TABLES;", 0, DBPrio_Low);
}

Methodmaps: if constructor is omitted, call parent constructor

Currently the following throws a compiler error:

methodmap Foo < StringMap {};

Foo foo = new Foo(); // error 172: methodmap 'Foo' does not have a constructor

Is this by design? It would be great if the compiler called the parent constructor (if there is one) and cast the return type.

Bad error reporting when exceeding stack size with a local array

If you do something like public void OnPluginStart() { char arr[1024 * 64]; }, then the VM (at least in recent versions) will report "instruction contained invalid parameter" (SP_ERROR_INSTRUCTION_PARAM) at runtime. This gets triggered by the verifier because an operand used when constructing the array is too large for the stack.

It'd be nice if the compiler errored instead where the size is fixed. Alternatively, SP_ERROR_STACKLOW at runtime instead.

(If you do something like int x = 64; char[] arr = new char[1024 * 64]; you get a much more helpful "not enough space on the heap" (SP_ERROR_HEAPLOW).)

Spurious variable shadowing warning

Commit bb83d1b seems to sometimes cause the compiler to incorrectly warn that a variable is being shadowed. Here's a test case:

stock unused() {
    buffer
}

public void main() {
    char buffer[2];
    buffer[0] = 2;
}

Compiling this results in warning 219: local variable "buffer" shadows a variable at a preceding level. Prior to this commit, no warning is emitted.
The unused stock appears to have to have an error of some kind involving an identifier with the code later using the same identifier. For example, stock unused() { char buffer[2]; foo } does not cause the warning to be emitted.

Tag Mismatch On Char Literal Assignment

Test case:

int main()
{
	char a = 'a';
}

Warning:

SourcePawn Compiler 1.8.0.6014
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2015 AlliedModders LLC

C:\Users\Micha\Desktop\test2.sp(3) : warning 213: tag mismatch

IRC discussion:

<dvander> you'd have to step through matchtag() to figure out why
<dvander> but asherkin's right
<dvander> char resolves to the deprecated "String" tag, which is a big, big hack
<dvander> that technically only applies to arrays
<dvander> so probably it's just some archaic mess up
<dvander> i think that assignment should be supported though

sqlite database creation bug

SourceMod Forums Thread: https://forums.alliedmods.net/showthread.php?p=2529668#post2529668

I am using the latest SourceMod, Linux Server, Half-Life 2: DM. This is driving me absolutely crazy! I am simply trying to create a database, and it does, but for some reason, if I use a timer, and then call StrEqual...it makes a SECOND empty database with whatever name is in the first field of "StrEqual"

Here is an image from FTP showing the two files being made:
http://imgur.com/GFSrYC2l.png

Compile the code below to reproduce it; the databases can be found here
addons/sourcemod/data/sqlite

#include <sourcemod> 

new Handle:g_hDB = INVALID_HANDLE; 

public OnPluginStart() 
{ 
    InitDB(); 
    CreateTimer(3.0, wtf_is_going_on); 
} 

stock Action:wtf_is_going_on(Handle:timer) 
{ 
    if(StrEqual("it_makes_an_empty_database_named_with_whatever_is_here", "")) {} 
} 

stock InitDB() 
{ 
    new String:error[255]; 
    g_hDB = SQLite_UseDatabase("my_database", error, sizeof(error)); 
} 

Function accessibility issue

Error output from SourceMod:

L 12/10/2017 - 02:02:55: SourceMod error session started
L 12/10/2017 - 02:02:55: Info (map "de_nuke") (file "errors_20171210.log")
L 12/10/2017 - 02:02:55: [SM] Exception reported: Fatal error creating dynamic native!
L 12/10/2017 - 02:02:55: [SM] Blaming: testcase.smx
L 12/10/2017 - 02:02:55: [SM] Call stack trace:
L 12/10/2017 - 02:02:55: [SM]   [0] CreateNative
L 12/10/2017 - 02:02:55: [SM]   [1] Line 6, E:\scripting\testcase.sp::AskPluginLoad2
L 12/10/2017 - 02:02:55: [SM]   [2] Line 21, E:\scripting\testcase.sp::GetClientButtons

Minimal test case:

#include <sourcemod>
#include <sdkhooks>

public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
	CreateNative("FakeNative_1", Native_Fake1);
}

public int Native_Fake1(Handle handler, int numParams)
{
	
}

public void OnClientPutInServer(int client)
{
	SDKHook(client, SDKHook_PostThinkPost, PostThinkPost);
}

void PostThinkPost(int client)
{
	GetClientButtons(client);
}

Changing PostThinkPost's accessibility to public gets rid of the error.
However, the stack trace outputted from SourceMod is terribly wrong and doesn't relate to the actual error in the code.

Tag mismatch on float array literals passed to functions

This code:

public void OnPluginStart()
{
	PrintFloatArray( { 0.0, 1.0, 2.0, 3.0 }, 4 );
}

void PrintFloatArray( float[] arr, int count )
{
	for( int i = 0; i < count; i++ )
	{
		PrintToServer( "%f\n", arr[i] );
	}
}

results in a tag mismatch error.
plugin.sp(3) : warning 213: tag mismatch

The current hack people use to fix this is to just wrap the array in a view_as<float> like so:
view_as<float>({ 0.0, 1.0, 2.0, 3.0 })

It'd be nice if the compiler was able to figure out the correct tag based on the contents to get the original code to work without warnings.

"" is not treated as a const when passed to natives.

#pragma semicolon 1
#include <sourcemod>

/* native bool:GetTrieString(Handle:map, const String:key[], String:value[], max_size, &size=0) */

public OnPluginStart()
{
	PrintToServer("%b", GetTrieString(INVALID_HANDLE, "pickles", "", 0));
}

/*
Your plugin successfully compiled!
Use the link below to download your plugin. It will be valid for ten minutes.

http://www.sourcemod.net/compiler.php?go=dl&id=685667
SourcePawn Compiler 1.7.1
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2014 AlliedModders LLC

Code size:             3044 bytes
Data size:             2240 bytes
Stack/heap size:      16384 bytes
Total requirements:   21668 bytes
*/

Add static property support for methodmaps.

Add static property support for methodmaps;

Example:

int g_val;

methodmap Test
{
	property static int TestVal
	{
		public get() { return g_val; }
		public set(int v) { g_val = v; }
	}
}

... //Later in code

Test.TestVal = 1;

Incorrect interaction delete and return array statements

If use "delete" on array that returned by function, you got "Invalid memory access" exception.
Because heap destroyed before zeroing variable.
Plugin example:

Handle g_handle[1];

public OnPluginStart()
{
    g_handle[0] = CreateDataPack();
    delete (GetHandle())[0];
}

Handle[] GetHandle()
{
    return g_handle;
}

Bytecode of delete:

3404: heap 8
3412: push.alt
3416: push.c 0
3424: call 2964
3432: pop.pri
3436: heap -8
3444: push.pri
3448: load.i
3452: push.pri
3456: sysreq.n 2 1
3468: pop.alt
3472: zero.pri
3476: stor.i

Error log:

L 02/07/2018 - 19:28:31: [SM] Exception reported: Invalid memory access
L 02/07/2018 - 19:28:31: [SM] Blaming: hb.smx
L 02/07/2018 - 19:28:31: [SM] Call stack trace:
L 02/07/2018 - 19:28:31: [SM]   [1] Line 6, H:\workdir\_Lab\hb.sp::OnPluginStart

P.S. I think no one ever will use statement like this and it doesn't matter, but Mr. asherkin says:
"Kailo, we'd still appreciate the bug report if you have a mo to file it"

Support for sizeof in function arguments

Original pawn supports this code.

public main()
{
	new a[5];
	test(a);
	new b[10];
	test(b);
}
test(a[], size = sizeof(a))
{
	printf("arr size %d\n", size);
}

Output

arr size 5
arr size 10

Would be great see this in sourcepawn.

Bad code generation after view_as on enum-struct array argument

Passing a reference to an array in an enum-struct is broken when the parameter requires a different tag than the array has in the enum-struct.
Tested in SourcePawn Compiler 1.9.0.6115.

Here's how I noticed it - the data written to the file was garbage after converting the plugin to the transitional syntax.

enum Test {
	Float:vec3[3],	
	Float:vec2[2]
};

public void main() {
	int test[Test];
	File hFile = OpenFile(..);
	WriteFile(hFile, test[vec3], 3, 4); // warning: tag mismatch but works
	WriteFile(hFile, _:test[vec3], 3, 4); // All fine
	WriteFile(hFile, view_as<int>(test[vec3]), 3, 4); // Writes random memory
}

testcase.zip
testcase_shell.zip

The attached testcase is a shorter version without the need of sourcemod natives.

The assembly of Bar and Bar2 is equivalent:

0xd90: break                           
0xd94: break                           
0xd98: push.c 0x2                       ; 2
0xda0: load.s.pri 0xc                   ; test
0xda8: add.c 0xc                        ; 12
0xdb0: push.pri                        
0xdb4: push.c 0x2                       ; 2
0xdbc: call 0xe50                       ; Foo
0xdc4: zero.pri                        
0xdc8: retn

Bar3 uses view_as<>() and generates an extra load.i in between:

0xe10: break                           
0xe14: break                           
0xe18: push.c 0x2                       ; 2
0xe20: load.s.pri 0xc                   ; test
0xe28: add.c 0xc                        ; 12
0xe30: load.i                          
0xe34: push.pri                        
0xe38: push.c 0x2                       ; 2
0xe40: call 0xe50                       ; Foo
0xe48: zero.pri                        
0xe4c: retn

Docgen doesn't show default param assignments

This has been a known issue for a long while, but documenting it here. Example below.

Include:
native KeyValues CreateKeyValues(const char[] name, const char[] firstKey="", const char[] firstValue="");

Output:
KeyValues CreateKeyValues(const char[] name, const char[] firstKey, const char[] firstValue)

Including files from withing sub directory with relative path is inconsistent/fails

Setup

I have a directory layout like this.

โ”‚   plugin.sp
โ””โ”€โ”€โ”€includes
    โ”‚   extension.inc
    โ””โ”€โ”€โ”€extension
            file.inc

plugin.sp includes extension.inc like this

#include "includes/extension"

extension.inc includes file.inc like this

#include "extension/file"

spcomp is in the PATH and i compile from the directory where plugin.sp is like this

spcomp plugin.sp

A test case that compiles on linux but fails on windows can be found here: includebug.zip.

The version i used were
Windows: 1.10.0.6336
Linux: 1.10.0.6335

Description

The error i get is this

SourcePawn Compiler 1.10.0.6336
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC

includes/extension.inc(1) : fatal error 183: cannot read from file: "extension/file"

Compilation aborted.
1 Error.

If i change the include inside extension.inc to

#include "includes/extension/file"

it works.

The problem is that this is inconsistent between windows and linux. If i make the change described here then it works on windows but not on linux.

Expected solution

Ideally one would expect that the include paths are always relative to the file that includes them
like in the attached includebug.zip.

Please let me know if you need more information.

Crash when using string as array index.

Hi,

I know that this code is not meant to be compiled, but I think that it should give a proper error instead of crashing.

My test case:

Broken code:

public void OnPluginStart()
{
        int arr[5];
        arr["hello"] = 0;
}

Compiled against sourcemod 1.9 windows 10

spcomp.exe spcrash.sp
SourcePawn Compiler 1.9.0.6245
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC

spcrash.sp(4) : error 033:

Compiled against sourcemod 1.10 windows10

spcomp.exe spcrash.sp
SourcePawn Compiler 1.10.0.6355
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC

Compiled against sourcemod 1.9 Linux(CentOS 7.2)

spcomp spcrash.sp
SourcePawn Compiler 1.9.0.6261
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC

Segmentation fault

Compiled against sourcemod 1.10 Linux(CentOS 7.2)

spcomp spcrash.sp
SourcePawn Compiler 1.10.0.6341
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC

Segmentation fault

docgen is broken

docgen is broken, had to use 4a09669 commit (edit: which crashes at handles.inc...).

chokes on clients.inc, most probably at public const int MaxClients;

Assertion failed: sym->isByRef() == type->isReference(), file D:\dev\sourcepawn\exp\compiler\sema\type-resolver.cpp, line 982

Wonky console output for compilation failure

Ever since 15d6c93, console output has been weird when plugins error out and compilations are aborted. Hereโ€™s what it looks like.

C:\Users\Micha\Desktop\New folder\sourcepawn\build\compiler\spcomp>spcomp test.sp
SourcePawn Compiler 1.10
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC

test.sp(2) : fatal error 194: user error: testing 1 2 3


Compilation aborted.Code size:                0 bytes
Data size:                0 bytes
Stack/heap size:      16384 bytes
Total requirements:   16384 bytes

Refactor variable reference pre incriment

Now pre incriment of variable reference give code like this:

public void MyFunc(int &a)
{
	++a;
}
push.pri
lref.s.pri 12
inc.pri
sref.s.pri 12
pop.pri
lref.s.pri 12

I think need to improve this.

DocParse: Segfault if some property don't have setter or getter

I found interesting behavior in the file parser.
If i try parse file with methodmaps with properties with setters/getters (datapack.inc for example), or without properies (regex.inc), he works correctly.

kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ ./docparse ~/alliedmodders/sourcemod/plugins/include/datapack.inc 2>&1 > /dev/null
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ echo $?
0
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ ./docparse ~/alliedmodders/sourcemod/plugins/include/regex.inc 2>&1 > /dev/null
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ echo $?
0

But if i try parse file with property without getter/setter (admin.inc and AdminId.GroupCount / GroupId.GroupImmunitiesCount), i receive segfault...

kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ ./docparse ~/alliedmodders/sourcemod/plugins/include/admin.inc 2>&1 > /dev/null
Segmentation fault (core dumped)
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ echo $?
139

P.S.: Sorry for my english. I'm from Russia.

overload [] operator

having this feature, especially for specific Handle types, would be a nice feature.
I figured it would require 2 kinds []= for setting and [] for simple getting.

The general gist of it could like

public void operator[]=(type ArrayType, type IndexType, type Valuetype);
public type operator[](type ArrayType, type IndexType);
// for setting
public void operator[]=(StringMap hMap, char []strIndex, any value)
{
    ...
}
// for getting
public any operator[](StringMap hMap, char []strIndex)
{
    any val; 
    // does this entry exist?
    if( !hMap.GetValue(strIndex, val) )
        return 0;
    return val;
}

StringMap hMyMap = new StringMap();
hMyMap["fvalue"] = 4.0;
hMyMap["ivalue"] = 5;
delete hMyMap;

another example using the dynamic array.

// for setting
public void operator[]=(ArrayList hArray, int Index, any value)
{
    hArray.Set(Index, value);
}
public void operator[]=(ArrayList hArray, int Index, char []StrVal)
{
    hArray.SetString(Index, StrVal);
}

// for getting
public any operator[](ArrayList hArray, int index)
{
    return hArray.Get(index);
}

ArrayList hArray = new ArrayList();
hArray.Push(5);
int i = hArray[0]; // sets 'i' to '5'
delete hArray;

Anonymous Instantiation Failure

Anonymous methodmap instantiation fails because spcomp expects an olddecl int declaration, but it's not.

/*
plugin.sp(14) : warning 219: local variable "ArrayList" shadows a variable at a preceding level
plugin.sp(14) : error 001: expected token: ";", but found "("
plugin.sp(14) : error 029: invalid expression, assumed zero
plugin.sp(14) : error 001: expected token: ")", but found ";"
plugin.sp(14) : fatal error 190: too many error messages on one line
*/
#include <sourcemod>

public void OnPluginStart()
{
	new ArrayList();
}

Interpreter incorrectly handling OP_RETN

See test in #114.

Correct output:

main.1
inner.1
main.2

Broken output:

main.1
inner.1
inner.2
inner.3
Exception thrown: Stack went below stack boundary
  [0] test.sp::inner, line 13
  [1] test.sp::main, line 19
[23:57:24] <dvander> asherkin: my guess is it's dumber than that: we never actually return from the interpreter
[23:58:32] <dvander> there doesn't appear to be any code that says "stop trying to run functions and exit"

I'm not sure it is actually that, this dumb patch seems to make everything work as expected, but I haven't tried more complex cases:

diff --git a/vm/interpreter.cpp b/vm/interpreter.cpp
index 578c1f6..b71e199 100644
--- a/vm/interpreter.cpp
+++ b/vm/interpreter.cpp
@@ -65,6 +65,13 @@ Interpreter::run()
   while (reader_.more()) {
     if (reader_.peekOpcode() == OP_PROC || reader_.peekOpcode() == OP_ENDPROC)
       break;
+
+    if (reader_.peekOpcode() == OP_RETN) {
+      if (!reader_.visitNext())
+        return false;
+      break;
+    }
+
     if (!reader_.visitNext())
       return false;
   }

But this looks really silly and I'm not sure how to factor it in properly.

I can't seem to get the compiler to ever emit OP_ENDPROC (or anywhere in the could where it would), what is it used for?

Drag + Drop = Segfault

Problem:
SaveMe.sp does not compile on SM1.10

Expected:
spcomp exports a .smx (or I guess with 1.8; prints a slew of errors).

str:
Drag and drop a .sp on spcomp.

problem space:
1.8 gives an error message; 1.10 instantly fails.

D:\Git\SourcePawn-Plugins>spcomp2.exe SaveMe.sp
SourcePawn Compiler 1.10.0.6334
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC


D:\Git\SourcePawn-Plugins>spcomp.exe SaveMe.sp
SourcePawn Compiler 1.8.0.6040
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2015 AlliedModders LLC

D:\Git\SourcePawn-Plugins\include\sourcemod.inc(43) : error 001: expected token: "public", but found "const"
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(44) : error 001: expected token: "}", but found "const"
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(45) : error 001: expected token: "=", but found "["
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(46) : error 001: expected token: "=", but found "["
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(47) : error 001: expected token: "=", but found "["
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(48) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(45) : error 001: expected token: "public", but found "-identifier-"
D:\Git\SourcePawn-Plugins\include\core.inc(49) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(56) : error 021: symbol already defined: "INVALID_FUNCTION"
D:\Git\SourcePawn-Plugins\include\core.inc(82) : error 096: could not find member "version" in struct "__version"
D:\Git\SourcePawn-Plugins\include\core.inc(122) : error 001: expected token: "public", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(123) : error 001: expected token: "}", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(126) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(133) : error 001: expected token: "public", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(134) : error 001: expected token: "}", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(136) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(146) : error 096: could not find member "name" in struct "__ext_core"
D:\Git\SourcePawn-Plugins\include\usermessages.inc(165) : warning 237: coercing functions to and from primitives is unsupported and will be removed in the future
D:\Git\SourcePawn-Plugins\include\menus.inc(503) : warning 219: local variable "time" shadows a variable at a preceding level
D:\Git\SourcePawn-Plugins\include\menus.inc(794) : warning 237: coercing functions to and from primitives is unsupported and will be removed in the future
D:\Git\SourcePawn-Plugins\include\halflife.inc(589) : warning 219: local variable "time" shadows a variable at a preceding level
SaveMe.sp(6) : error 096: could not find member "name" in struct "myinfo"
SaveMe.sp(126) : warning 203: symbol is never used: "__unknown__"
SaveMe.sp(124) : warning 203: symbol is never used: "autoload"
SaveMe.sp(47) : warning 203: symbol is never used: "date"
SaveMe.sp(46) : warning 203: symbol is never used: "filevers"
SaveMe.sp(125) : warning 203: symbol is never used: "required"
SaveMe.sp(49) : warning 203: symbol is never used: "time"

18 Errors.

D:\Git\SourcePawn-Plugins>

Switch statements default case not registered as guaranteed return

Seems like the default case on switches aren't seen by the compiler as a definite return, and gives us a warning. See testcase below

int main() {
	funct(2);
}
int funct(int input) {
	switch (input) {
		case 0:
			return 1;
		case 1:
			return 2;
		default:
			return 3;
	}
} // warning 209: function "funct" should return a value

Compiler define __FILE__

What about a implementing define with name __FILE__ which contains current included filename?

Support for #warning preprocessor directive

Just as it says on the tin, I'd like to see support for Pawn's #warning preprocessor directive implemented in a future version of Sourcepawn, as an alternative to the compilation-halting #error directive. This is obviously incredibly niche and would only really find use for a very small selection of those of us creating includes for use in others' plugins.

(I'm also not sure how to tag this as a feature request or enhancement, or if someone else has to do that for me.)

function closures/executable function pointers

another enhancement I think would benefit SP is having closures or at minimum function pointers of some sort.

I first tried to test if SP already had something like this in Asherkin's Spider but sadly the compiler bitched at me.

#include <sourcemod>
#pragma semicolon 1
#pragma newdecls required

public Plugin myinfo = {
        name = "",
        author="",
        description="",
        version="0.0.0",
        url=""
};

void myfunc()
{
        PrintToServer("myfunc called.\n");
}

public void OnPluginStart()
{
        Function func = myfunc;
        func();
}

I also tried doing this but it failed too.

public void OnPluginStart()
{
        function func = myfunc;
        func();
}

Example time!

in my VSH2 plugin, specific code from certain methodmaps are run on different players.
each action and event uses a switch construct to decide which methodmap and which method is called.

public void ManageBossHelp(const BaseBoss base)
{
	switch ( base.iType ) {
		case -1: {}
		case Hale:		ToCHale(base).Help();
		case Vagineer:		ToCVagineer(base).Help();
		case CBS:		ToCChristian(base).Help();
		case HHHjr:		ToCHHHJr(base).Help();
		case Bunny:		ToCBunny(base).Help();
		case PlagueDoc:		ToCPlague(base).Help();
	}
}

by having closures (or func pointers, which ever)
the code can be simplified into.

public void ManageBossHelp(const BaseBoss base)
{
	// this array wouldn't really be in this function !
	// just example
	function fnBossHelp[] = {
		ToCHale(base).Help,
		ToCVagineer(base).Help,
		ToCChristian(base).Help,
		ToCHHHJr(base).Help,
		ToCBunny(base).Help,
		ToCPlague(base).Help
	};
	// get func ptr of methodmap then call like method.
	base.fnBossHelp[base.iType]();
}

Compiler allows no arguments in forwards

Help us help you

  • [-] I have checked that my issue doesn't exist yet.
  • [v] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
  • [v] I can always reproduce the issue with the provided description below.

Environment

  • Operating System version: Windows
  • Game/AppID (with version if applicable):
  • Current SourceMod version: 1.10.0.6353
  • Current SourceMod snapshot: 1.10.0.6353
  • Current Metamod: Source snapshot:
  • [v] I have updated SourceMod to the latest version and it still happens.
  • [v] I have updated SourceMod to the latest snapshot and it still happens.
  • [-] I have updated SourceMM to the latest snapshot and it still happens.

Description

Compiler show no error when you try to compile forward with wrong prototype (without arguments).

Problematic Code (or Steps to Reproduce)

public void OnClientPostAdminCheck()
{
}

DocParse: Permission denied

I tried compile the doc from the sourcepawn repository, and everything was ok, but when i try to execute the generate.py i have a access permission problem. Anyone knows how to fix?


ushakov@thinkpad-x201s:~/Desktop/generate$ sudo python ./generate.py
[sudo] password for ushakov:
Failed to process ./include/sounds.inc:
./include/sounds.inc: 1: ./include/sounds.inc: ./docparse: Permission denied
Traceback (most recent call last):
File "./generate.py", line 621, in <module>
main()
File "./generate.py", line 598, in main
gen.generate()
File "./generate.py", line 189, in generate
self.parse_include(include)
File "./generate.py", line 209, in parse_include
raise Exception('failed to parse file')
Exception: failed to parse file

When i have include and docparse in the same folder of generate.py i have that error
``
Failed to process ./sounds.inc:
Usage: ./docparse [-h] filename
error: Missing value for 'filename'.
Traceback (most recent call last):
  File "./generate.py", line 621, in <module>
    main()
  File "./generate.py", line 598, in main
    gen.generate()
  File "./generate.py", line 189, in generate
    self.parse_include(include)
  File "./generate.py", line 209, in parse_include
    raise Exception('failed to parse file')
Exception: failed to parse file

I attached a includes and compiled docparse here
https://drive.google.com/file/d/1dni6O3gu-u1Wffvu5wsUb1cZ21CnhWmy/view
What i did wrong?

Error 135 uses wrong string in message

The following code:

native void Touhou_GetUserBullet(int client, bullet_t bullet);

results in the following error message:
error 135: cannot use enum struct type "Touhou_GetUserBullet" in natives

The native name is being used in the error message rather than the enum struct type name.

Docgen choking on SM topmenus.inc

Specifically https://github.com/alliedmodders/sourcemod/blob/74512575/plugins/include/topmenus.inc

I've not had luck in narrowing this down further. Output of generate.py is just:

Failed to process ../../../../sourcemod/plugins/include/topmenus.inc:

Traceback (most recent call last):
  File "generate.py", line 624, in <module>
    main()
  File "generate.py", line 601, in main
    gen.generate()
  File "generate.py", line 189, in generate
    self.parse_include(include)
  File "generate.py", line 208, in parse_include
    raise Exception('failed to parse file')
Exception: failed to parse file

Methodmap function recursion call compilation error

int g_a = 0;

methodmap CTest
{
	public static void A()
	{
		g_a++;
		if (g_a == 5)
			PrintToServer("Done");
		else
			CTest.A(); // error 105: cannot find method or property CTest.A
	}
}

public void OnPluginStart()
{
	CTest.A();
}

This is probably good test case

methodmap MM { public static void sFunc(int a = 0) { if (a < 5) MM.sFunc(a + 1); } };
public void main() { MM.sFunc(); }

Test environment: Windows 10, SM 1.9.0.6245 & 1.10.0.6316

Update: the same for non-static

methodmap MM < Handle
{
	public void sFunc(int a = 0)
	{
		if (a < 5)
			this.sFunc(a + 1); // error 105: cannot find method or property MM.sFunc
	}
}

public void OnPluginStart()
{
	view_as<MM>(GetMyHandle()).sFunc();
}

typedef'ing extended to identifiers/variables

'ello m8s, I would like to put an official request for typedefing to extend to variables.
I know that using "enum" with a name can technically do this by implicitly typedefing int to the enum's name but I'd like the option to typedef other names as well as arrays of these types.

EDIT: I've edited the examples to fit the grammar of 'typedef' which is typedef ::= "typedef" symbol "=" full-type-expr term

I'll just code in my examples

#include <sourcemod>

// makes declaring vec3 an array of float.
typedef vec3_t = float[3];
...
// is really 'float origin[3];'
vec3_t origin;

// this would be an error, functions can only return 'type[]'
vec3_t GetOrigin()
{
	return origin;
}
void SetOrigin(vec3_t origin)
{
	SetEntPropFloat(1, Prop_Send, "m_flOrigin", origin);
}

or another example case with strings

typedef StrNameBuffer_t = char[64];

// "char name[64];"
StrNameBuffer_t name;
strcopy(name, sizeof(name), "example typedef");

more complex example

typedef PlayerFields_t = StringMap;
...
PlayerFields_t fields;
fields = new PlayerFields_t();
methodmap Player {
	public Player() {
	}
	property int iEquipment
	{
		public get() {
			int i; fields.GetValue("iEquipment", i);
			return i;
		}
		public set(const int val) {
			fields.SetValue("iEquipment", val);
		}
	}
};
// player methodmap is defined, we can typedef it now
typedef Enemy_t, Friendly_t = Player;

another, more 'out of the wild' example

typedef color_t = int[4];
color_t color={ 255,255,255,255 };
SetEntityRenderColor(client, color[0], color[1], color[2], color[3]);

Faster method of creating convars!

enum {
    ...
    VersionNum
};
typedef Convars_t = ConVars[VersionNum+1];
Convars_t PluginConvars;

more practical example from an existing plugin called "projectile detector".
Original code.

stock void GetProjPosToScreen ( const int client, const float vecDelta[3], float& xpos, float& ypos )
{
	float playerAngles[3]; GetClientEyeAngles(client, playerAngles);

	float vecforward[3], right[3], up[3] = { 0.0, 0.0, 1.0 };
	GetAngleVectors(playerAngles, vecforward, nullvec, nullvec );
	vecforward[2] = 0.0;

	NormalizeVector(vecforward, vecforward);
	GetVectorCrossProduct(up, vecforward, right);

	float front = GetVectorDotProduct(vecDelta, vecforward);
	float side = GetVectorDotProduct(vecDelta, right);

	xpos = 360.0 * -front;
	ypos = 360.0 * -side;

	float flRotation = (ArcTangent2(xpos, ypos) + FLOAT_PI) * (57.29577951);

	float yawRadians = -flRotation * 0.017453293; //FLOAT_PI / 180.0; // Convert back to radians
	// Rotate it around the circle
	xpos = ( 500 + (360.0 * Cosine(yawRadians)) ) / 1000.0; // divide by 1000 to make it fit with HudTextParams
	ypos = ( 500 - (360.0 * Sine(yawRadians)) ) / 1000.0;
}

code using typedef

typedef vec3_t = float[3];
stock void GetProjPosToScreen ( const int client, const vec3_t vecDelta, float &xpos, float &ypos )
{
	vec3_t playerAngles;
        GetClientEyeAngles(client, playerAngles);

	vec3_t vecforward, right, up = { 0.0, 0.0, 1.0 };
	GetAngleVectors(playerAngles, vecforward, NULL_VECTOR, NULL_VECTOR );
	vecforward[2] = 0.0;

	NormalizeVector(vecforward, vecforward);
	GetVectorCrossProduct(up, vecforward, right);

	float front = GetVectorDotProduct(vecDelta, vecforward);
	float side = GetVectorDotProduct(vecDelta, right);

	xpos = 360.0 * -front;
	ypos = 360.0 * -side;

	float flRotation = (ArcTangent2(xpos, ypos) + FLOAT_PI) * (57.29577951);
	float yawRadians = -flRotation * 0.017453293;

	// Rotate it around the circle
        // divide by 1000 to make it fit with HudTextParams
	xpos = ( 500 + (360.0 * Cosine(yawRadians)) ) / 1000.0;
	ypos = ( 500 - (360.0 * Sine(yawRadians)) ) / 1000.0;
}

spcomp exits with no output for methodmap static function call

Help us help you

  • I have checked that my issue doesn't exist yet.
  • I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
  • I can always reproduce the issue with the provided description below.

Environment

  • Operating System version: Windows
  • Current SourceMod version: 1.9.0.6252
  • Current SourceMod snapshot: 1.10.6339

Description

Compiler exits prematurely with no errors or messages.

Problematic Code (or Steps to Reproduce)

methodmap B {
  public static void TestB() {
  	A.TestA();
  	PrintToServer("TestB");
  }
}

methodmap A {
  public static void TestA() {
  	PrintToServer("TestA");
  }
}

Logs

Output from Sublime:
[Finished in 0.9s with exit code 3221225477]
or
[Finished in 0.8s]

Output from spcomp:

Calling stock functions in global scope returns a terrible compiler error.

This is from the forums (also discussed in IRC)

When compiling
int test = ByteCountToCells(PLATFORM_MAX_PATH)

in the global scope you get this error
plugin.sp(3) : fatal error 195: compiler bug: calling stock "ByteCountToCells" that has no generated code

However, when calling a native instead
int test = GetMaxClients()

you get this

plugin.sp(3) : error 010: invalid function or declaration plugin.sp(3 -- 4) : error 008: must be a constant expression; assumed zero

As Fyren pointed out the error should probably be what the last one error'd with.

Add compile warnings for infinite while loops

If a while loop uses a counter and has no foreseeable exit condition, I would like a compile warning to be added. This way, the user can correct this error before it crashes their plugin.

void myInfiniteWhileLoop()
{
   int index = 20;
   while (index >=0)
   {
      PrintToChatAll("I like apples");
   }
}

This example may be better suited for a for-loop. But there are other use cases with multiple conditions.

Crash when playing around with methods as "virtuals"

I was screwing around with methodmaps as menu handlers and the sp compiler crashed when I moved the declaration of CTestMenu from line 28 to the bottom of the file. There are a lot of weird errors and warnings in there too, I hope this sample can help you discover more of the inconsistencies I encountered when working with methodmaps. I'll attach the source and the dmp file generated by vs.

dump.zip
source.zip

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.