PDA

Просмотр полной версии : [Урок] Отличия Pawn 4.x от Pawn 3.2



Daniel_Cortez
24.08.2016, 01:56
Всем привет.

Я хотел опубликовать эту статью чуть позже, приурочив её к другому событию, но с выходом плагина nPawn (http://pro-pawn.ru/showthread.php?14174) думаю, сейчас самое время.
В названии указано Pawn 4.x вместо 4.0, поскольку в статье приведены отличия не только версии 4.0, но и экспериментальной ветки, в которой исправлены баги, оставшиеся в 4.0, и добавлено ещё несколько новых фич.
К сведению, nPawn использует именно экспериментальную ветку. ИМХО, она даже более стабильна, чем "стабильный" релиз 4.0.

Условные обозначения:
(+) Новый функционал.
(*) Изменение.
(FIX) Багфикс.
(4.x) Нет в релизе 4.0, т.к. реализовано позже и пока что находится в экспериментальной ветке.

Список отличий:
(*) Ключевое слово enum заменено на const.
Теперь для того, чтобы сделать перечисление из нескольких поименованных констант, нужно использовать const. Также у первой константы обязательно должно быть указано значение.
Рассмотрим это на примере объявления ID диалогов в SA-MP. Вот как это объявление выглядело бы в Pawn 4.0:


const
{
DIALOG_NONE = 0,
DIALOG_REGISTER,
DIALOG_LOGIN,
DIALOG_EMAIL,
DIALOG_EDIT_EMAIL,
};

Запятая после завершающей константы теперь не является ошибкой. Вы уже могли видеть это в модифицированном компиляторе от Zeex, но этого не было в Pawn 3.2.
По умолчанию константам задаётся целочисленный тег, но можно указать любой другой тег при объявлении:


const Float: // По умолчанию константам в списке будет задан тег Float, если не будет указан другой тег.
{
x = 2.0, // const Float:x = 2.0;
y = 3.0, // const Float:y = 3.0;
bool:b = true; // const bool:b = true;
z = 4.0, // const Float:z = 4.0;
};



(+) Появилась возможность создавать структуры с Си-подобным синтаксисом обращения к их полям.
Рассмотрим это на примере структуры данных о студенте какого-нибудь ВУЗа:


const MAX_STUDENTS = 1000;
new student[MAX_STUDENTS][.ID, .name[16], .surname[32]];

Обращение к полю "ID" будет выглядеть следующим образом:


student[0].ID = random(-1);
printf("Student ID: %d\n", student[0].ID);

Также можно отдельно описать саму структуру, чтобы иметь возможность использовать её в нескольких переменных.
Для этого в директиву #define добавлен синтаксис с квадратными скобками, позволяющий объявить макрос из нескольких строк без использования символа переноса строки "\".


#define s_Student [
.ID,
.name[16],
.surname[32]
]
new student[MAX_STUDENTS][s_Student];

Тем не менее, можно объявить структуру и с помощью старого синтаксиса #define:


#define s_Student\
.ID,\
.name[16],\
.surname[32]

или даже так:


#define s_Student .ID, .name[16], .surname[32]

Во всех перечисленных выше вариантах можно добавить запятую после ".surname[32]", это не будет считаться ошибкой.


(*) Упразднён оператор char, теперь массивы могут объявляться как массивы байт и массивы ячеек.


// массив из ячеек
new cell_array[10];

// массив из байтов
// (фигурные скобки нужны, чтобы указать, что это массив байтов)
new byte_array{10};


Для инициализации массивов начальными значениями используется новый синтаксис.
Какие скобки были использованы при указании размера массива (квадратные/фигурные), в такие и заключаются значения.


new byte_array{10} = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
new cell_array[10] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

Оператор "..." всё ещё можно использовать для инициализации массивов, но теперь, если нужно задать список значений с инкрементом, следует указать, как минимум, два элемента макссива, а не один, как в предыдущих версиях.


new some_array[4] = [ 1, 2, ... ]; // В Pawn 3.2 можно было написать "[ 1, ... ]", но в 4.0 это заполнит весь массив единицами.

Также доступна прогрессивная инициализация для многомерных массивов:


new some_array[4][4] = [ [ 1 ], [ 2, ... ], [ 3, 4, ... ], [ 5, 6, 9, ... ] ];

Этот массив будет инициализирован следующими значениями:


// [ 1 0 0 0 ] - в 1-й строке указано значение лишь для 1-го столбца, остальные заполняются нулями.
// [ 2 2 2 2 ] - использован оператор "...", но указано только одно значение "2", поэтому вся строка заполнена двойками.
// [ 3 4 5 6 ] - использован "..." и указаны значения "3" и "4" - по ним компилятор поймёт, что каждый следующий элемент массива должен быть на 1 больше предыдущего.
// [ 5, 6, 9, 12 ] - следует помнить, что компилятор учитывает только 2 последних значения перед "...", поэтому здесь инкремент равен трём (9 - 6 = 3).



(*) Изменения в синтаксисе строк.
Начиная с Pawn 4.0, все строки по умолчанию упакованные - теперь не нужно ставить восклицательный знак перед каждой строкой, чтобы она занимала меньше места в памяти.


"Это упакованная строка" // 22 символа -> 23 байта -> 8 ячеек (при размере ячейки в 4 байта)

Если вы хотите явным образом объявить массив для хранения упакованной строки, то вам понадобится массив байтов:


new packed_string{} = "Это упакованная строка";

Для неупакованных строк доступны сразу 2 варианта синтаксиса:


new unpacked_string1[] = ''Это неупакованная строка''; // обратите внимание: вместо кавычек используются двойные апострофы.
new unpacked_string2[] = ``И это тоже неупакованная строка''; // альтернативный синтаксис: для открытия строки вместо апострофов используется удвоенный гравис.

Об апострофах и грависах можете узнать из википедии: апостроф (https://ru.wikipedia.org/wiki/%D0%90%D0%BF%D0%BE%D1%81%D1%82%D1%80%D0%BE%D1%84), гравис (https://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%B2%D0%B8%D1%81).

При объявлении упакованной строки в неупакованном массиве и наоборот компилятор выдаст варнинг:


// на всех этих строках компилятор выдаст предупреждение
// "warning 229: mixing packed and unpacked array indexing or array assignment"
new packed_string1[] = "Sample text";
new packed_string2{} = ''Sample text'';
new unpacked_string1[] = "Sample text";
new unpacked_string2{} = ''Sample text'';



(*) В Pawn 3.2 строки можно было разделять на отрывки следующим образом:


new str[] = "Отрывок1" "Отрывок2" "Отрывок3";

В версии 4.0 для этого требуется использовать оператор конкатенации "...":


new str[] = "Отрывок1" ... "Отрывок2" ... "Отрывок3";

По аналогии оператор конкатенации теперь нужен и для переноса отрывков на следующую строку:


new str[] =
"Отрывок1\n" ...
"Отрывок2\n" ...
"Отрывок3";



(*) Теперь чтобы использовать знак ":" в макросах, он должен находиться внутри круглых "()" или угловых "<>" скобок.
Например, следующий макрос будет считаться неправильным:


#define fpub:%0(%1) forward %0(%1);public %0(%1) // Работает в Pawn 3.2, в 4.0 компилятор выдаёт синтаксическую ошибку.

Тем не менее, это ограничение можно обойти:


#define fpub%0(%1) forward%0(%1);public%0(%1)

Пока что я не знаю точно, было ли так задумано, или это баг.


(*) В Pawn 3.2 можно было вставлять в запись числа знак нижнего подчёркивания, чтобы число было удобнее читать:


new x = 10_000_000;

В Pawn 4.0 для тех же целей следует использовать апостроф, при попытке записи числа через нижнее подчёркивание компилятор выдаст ошибку.


new x = 10'000'000;



(+) (4.x) Добавлены директивы #ifdef и #ifndef для большей совместимости с языком C.
К тому же, они просто удобнее, чем "#if defined".


(+) (4.x) Добавлены директивы #warning и #pragma warning (push|pop|disable).
Они уже были доступны в форке Zeex (https://github.com/Zeex/pawn/wiki/What's-new#pragma-warning), теперь они есть и в 4.x.


(+) (4.x) Для инклудов в дополнение к расширению ".inc" теперь доступно расширение ".i" по аналогии с расширением ".p" в дополнение к ".pawn".
(Расширение ".pwn" не является стандартным, оно используется только в скриптах для SA-MP.)
Рассмотрим следующий пример:


#include "my_inc"
main(){}

Расширение инклуда "my_inc" не указано, поэтому компилятор попробует открыть файлы со следуюшими расширениями: ".i", ".inc", ".p", ".pawn".
Поиск файла будет произведён строго в том порядке, который указан выше. Если в папке со скриптом есть файлы "my_inc.i" и "my_inc.inc", то компилятор найдёт первым и откроет файл с расширением ".i", проигнорировав "my_inc.inc".
Если же у инклуда такое расширение, которого нет в списке, в директиве #include это расширение нужно указывать в явном виде (т.е. не "my_inc", а, например, "my_inc.h").


(+) (4.x) Компилятор сам объединяет одинаковые константные массивы.
Вы наверняка видели раньше тот трюк с объявлением массивов/строк вручную, чтобы они не дублировались в памяти:


static const string[] = "qwertyuiop\n";
printf(string);
printf(string);

В Pawn 4.0 этот приём устарел, поскольку теперь компилятор сам умеет объединять константные строки и массивы.


printf("qwertyuiop\n");
printf("qwertyuiop\n"); // здесь будет обращение к тому же самому экземпляру строки



(*) Удалены директивы #emit и #endscript.


(*) (4.x) Также удалены операторы *begin, *end и *then. Паскальщики негодуют.


(+) Проведена ревизия всего набора инструкций AMX. Добавлены упакованные инструкции, в которых код операции и 1-й операнд умещаются в одну ячейку, благодаря чему достигается большая компактность кода и потенциал к более быстрой работе интерпретатора.
Например, при конфигурации размера ячейки в 4 байта код операции располагается в младших 2 байтах, а операнд - в старших. Разумеется, это работает только если операнд умещается в те старшие 2 байта, иначе компилятор сгенерирует неупакованный вариант инструкции.


(+) Помимо упакованных опкодов в поле flags заголовка AMX добавлен флаг AMX_FLAG_CRYPT, который сигнализирует о том, что скрипт зашифрован.
По умолчанию предлагается использовать алгоритм шифрования KeeLoq (https://ru.wikipedia.org/wiki/KeeLoq), но можно вручную добавить любой другой алгоритм.


(+) (4.x) Кроме main() в Pawn 4.0 точкой входа в скрипт могут считаться функции entry() и @start(). Впрочем, в скрипте разрешается использовать только одну из них, т.к. точка входа может быть лишь одна.
Также теперь можно использовать exit() для указания точки выхода. Эти функции могут вызываться при загрузке и выгрузке скрипта соответственно (могут, но не обязаны, всё зависит от того, где используется интерпретатор Pawn и предусмотрен ли там вызов main/@start/entry/exit).


(FIX) (4.x) Исправлен баг в strcmp, из-за которого функция возвращала 0, если одна из сравниваемых строк была пустая.


(FIX) (4.x) Исправлен баг в strins, из-за которого был возможен выход за пределы буфера (функция игнорировала аргумент maxlength).


(FIX) (4.x) Теперь функции printf и strformat правильно выводят число -2147483647 (раньше вместо этого числа выводился только знак "-").


(FIX) (4.x) Исправлен баг, из-за которого оператор tagof нельзя было использовать со скобками в метках конструкции switch.


(FIX) (4.x) Оператор tagof больше не возвращает разные ID для целых чисел и тега "_".


(FIX) (4.x) Исправлена проблема, связанная с неправильным генерированием инструкций из кода, находящегося внутри условно компилируемых секций #if ... #else ... #endif.



Это весь список отличий, который мне удалось вспомнить. Если вы знаете что-то ещё, что есть в Pawn 4.x, но чего нет в Pawn 3.2, буду рад услышать об этом в комментариях.


Автор: Daniel_Cortez (http://pro-pawn.ru/member.php?100-Daniel_Cortez)


Специально для Pro-Pawn.ru (http://www.pro-pawn.ru)
Копирование данной статьи на других ресурсах без разрешения автора запрещено!

ziggi
24.08.2016, 08:00
Ещё добавили прогрессивную инициализацию многомерных массивов:

new c[3][3] = [ [ 1 ], [ 2, ...], [ 3, 4, ... ] ]
Ещё добавили удобную директиву __line.
Но это есть в Pawn от Zeex. Хотя не нашёл #warning и #pragma warning, видимо это было добавлено Zeex, но штука довольно удобная.

Ещё можно тэги объявлять с помощью const (но это не обязательно):

const tagname { constant list }

P.S. Мне не очень нравятся такие удвоенные кавычки, да и в качестве разделителя чисел они смотрятся странно.

vovandolg
24.08.2016, 11:26
По 12 пункту хочу уточнить, защиты от DeAMX не будет для этой версий?:help:
Или придется юзать старую традиционную что при включении мода запускается-_-

Daniel_Cortez
24.08.2016, 11:38
Ещё добавили прогрессивную инициализацию многомерных массивов:

new c[3][3] = [ [ 1 ], [ 2, ...], [ 3, 4, ... ] ]
Да, спасибо, что напомнил. Я ещё забыл написать, что для инициализации с инкрементом значений необходимо указать, как минимум, 2 элемента массива, а не 1, как раньше.
Добавил это всё в 4-й пункт, твой пример пришлось немного изменить.



Ещё добавили удобную директиву __line.
Но это есть в Pawn от Zeex.
Даже не знаю, стоит ли об этом вообще упоминать - всё равно те немногие, кому нужна эта константа, отнюдь не первый день пишут код и уже давно пользуются компилятором от Zeex.



Хотя не нашёл #warning и #pragma warning, видимо это было добавлено Zeex, но штука довольно удобная.
Да, действительно. Можно попросить разработчика Pawn (Thiadmer Riemersma) добавить эти директивы (он уже добавил #ifdef и #ifndef, так что не думаю, что это будет сильно сложно для него).
Но только не от моего имени. Впрочем, если нужно, могу помочь с составлением текста (хоть и не могу сказать, что так уж хорошо знаю инглиш).
Я бы и сам рад спросить его, но не хочу, чтобы это выглядело, как будто я перегружаю его работой - он и без того ей завален (https://github.com/compuphase/pawn/issues/18#issuecomment-236529799) в последнее время, из-за чего поздно отвечает на багрепорты (которых я, наверное, уже насоздавал предостаточно, и ещё несколько собираюсь сделать).



Ещё можно тэги объявлять с помощью const (но это не обязательно):

const tagname { constant list }
Это не теги, а список констант с тегом, отличным от целочисленного. Я добавил ещё один пример в 1-й пункт.



P.S. Мне не очень нравятся такие удвоенные кавычки, да и в качестве разделителя чисел они смотрятся странно.
Удвоенный апостроф нужен только для того, чтобы объявлять неупакованные строки, а строки в обычных кавычках теперь являются упакованными. Похоже, что это было сделано с расчётом на то, что неупакованные строки почти нигде не нужны и синтаксис для них не сильно критичен.
А по поводу чисел - да, хороший вопрос, я и сам ума не приложу, зачем он так сделал. Можно в том же feature request попросить его вернуть возможность разделять цифры нижними подчёркиваниями.



По 12 пункту хочу уточнить, защиты от DeAMX не будет для этой версий?:help:
Или придется юзать старую традиционную что при включении мода запускается-_-
Для нового набора инструкций ещё нет никакого DeAMX. А если даже и сделают, то в 4.0 предусмотрена возможность для шифрования скриптов. Я добавил более подробную информацию в 1-й пост 15-м пунктом.

ziggi
24.08.2016, 15:16
Да, действительно. Можно попросить разработчика Pawn (Thiadmer Riemersma) добавить эти директивы (он уже добавил #ifdef и #ifndef, так что не думаю, что это будет сильно сложно для него).
Но только не от моего имени. Впрочем, если нужно, могу помочь с составлением текста (хоть и не могу сказать, что так уж хорошо знаю инглиш).
Я бы и сам рад спросить его, но не хочу, чтобы это выглядело, как будто я перегружаю его работой - он и без того ей завален (https://github.com/compuphase/pawn/issues/18#issuecomment-236529799) в последнее время, из-за чего поздно отвечает на багрепорты (которых я, наверное, уже насоздавал предостаточно, и ещё несколько собираюсь сделать).

Сделано (https://github.com/compuphase/pawn/issues/24).


Удвоенный апостроф нужен только для того, чтобы объявлять неупакованные строки, а строки в обычных кавычках теперь являются упакованными. Похоже, что это было сделано с расчётом на то, что неупакованные строки почти нигде не нужны и синтаксис для них не сильно критичен.
Этого я не учёл. И правда, трудно придумать случай, где может потребоваться не упакованная строка (разве что для расширенного набора символов, но не уверен, что это поддерживается).


А по поводу чисел - да, хороший вопрос, я и сам ума не приложу, зачем он так сделал. Можно в том же feature request попросить его вернуть возможность разделять цифры нижними подчёркиваниями.
Позже создам, если никто не захочет опередить.

ziggi
12.09.2016, 02:47
ALS не работает? У меня компилятор зацикливается.

.\default.pwn(49) : warning 208: function "Prefix2_OnGameModeInit" is used before definition, a forward declaration is recommended
.\default.pwn(36) : warning 208: function "Prefix2_OnGameModeInit" is used before definition, a forward declaration is recommended
.\default.pwn(24) : warning 208: function "Prefix_OnGameModeInit" is used before definition, a forward declaration is recommended

Daniel_Cortez
12.09.2016, 13:09
ALS не работает? У меня компилятор зацикливается.

.\default.pwn(49) : warning 208: function "Prefix2_OnGameModeInit" is used before definition, a forward declaration is recommended
.\default.pwn(36) : warning 208: function "Prefix2_OnGameModeInit" is used before definition, a forward declaration is recommended
.\default.pwn(24) : warning 208: function "Prefix_OnGameModeInit" is used before definition, a forward declaration is recommended
Да, действительно.
Как будто потери настраиваемого инкремента в enum и замены на const было мало... -_-

Что интересно, перехват функций работает в Pawn 4.0, зацикливание проявляется только в последней разрабатываемой версии.
И я так понимаю, началось это всё после коммита 6de1822 (https://github.com/compuphase/pawn/commit/6de1822ac1625451bf151159bb0178c09f087bea).

Мне сообщить об этом баге или ты сам?


UPD: Буквально 20 минут назад были добавлены директивы #error и #pragma warning (https://github.com/compuphase/pawn/issues/24). Ура, товарищи!

TheMallard
12.09.2016, 17:00
Написал о возврате поведения препроцессора (ALS): https://github.com/compuphase/pawn/issues/28

ziggi
12.09.2016, 17:31
UPD: Буквально 20 минут назад были добавлены директивы #error и #pragma warning (https://github.com/compuphase/pawn/issues/24). Ура, товарищи!

Да и теги пофиксили, красота)


Написал о возврате поведения препроцессора (ALS): https://github.com/compuphase/pawn/issues/28

Отлично, надеюсь пофиксят.

Daniel_Cortez
12.09.2016, 19:34
Написал о возврате поведения препроцессора (ALS): https://github.com/compuphase/pawn/issues/28
В следующий раз прилагайте к отчёту примеры кода и сообщений компилятора, дабы разработчику Pawn было проще разобраться - у него и так почти не остаётся свободного времени из-за работы.

P.S.: Добавил #warning и #pragma warning в 1-й пост 10-м пунктом.

TheMallard
13.09.2016, 03:17
ALS4 method 7, вот как это называется.

Daniel_Cortez
13.09.2016, 06:00
ALS4 method 7, вот как это называется.
"method 7" указано в скобках, поскольку ещё 3-x методов перехвата не было в ALS (оказались неприемлемыми по тем или иным критериям). Среди ALS же это 4-й способ, отсюда и название ALS4.

Daniel_Cortez
29.10.2016, 13:52
Спустя 4 года после предыдущего релиза Pawn (4.0.4733), выпущена новая стабильная версия: 4.0.5588.
Обновлена документация, теперь в ней описаны если не все, то многие новые фичи с момента предыдущего релиза (+ новый стильный шрифт).
Скачать пакет для разработки под Windows можно здесь: http://www.compuphase.com/pawn/pawn.htm#DOWNLOAD_WIN

Проблема с перехватами исправлена (https://github.com/compuphase/pawn/issues/28#issuecomment-256745254), но компилятор всё ещё выдаёт варнинги, если функция не объявлена перед выражением "#if defined <имя функции>".
Решается эта проблема очень просто: нужно всего лишь переместить предварительное объявление (forward) перехваченной функции из самого конца перехвата в начало, чтобы она была объявлена до #if defined.
Например, так будет выглядеть перехват OnGameModeInit:


forward my_library__OnGameModeInit(); // Теперь строка с forward должна быть здесь.
public OnGameModeInit()
{
/* Ваши действия. */ print("OnGameModeInit() hook");
#if defined my_library__OnGameModeInit
my_library__OnGameModeInit();
#endif
return 1;
}
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit my_library__OnGameModeInit

Кстати говоря, в SA-MP (Pawn 3.2) такой подход тоже работает (более того, он совместим с "традиционным" ALS4, в котором строка с forward ставится в конце перехвата), поэтому есть смысл использовать его и там для обратной совместимости.


P.S. Кто-нибудь пробовал собрать компилятор под Linux из последних исходников? Как-то это подозрительно, что файл process.h, который обычно присущ только для DOS, Windows и QNX, используется в sc1.c для всех целевых платформ.

Redsan
29.10.2016, 14:57
Спустя 4 года после предыдущего релиза Pawn (4.0.4733), выпущена новая стабильная версия: 4.0.5588.
Обновлена документация, теперь в ней описаны если не все, то многие новые фичи с момента предыдущего релиза (+ новый стильный шрифт).
Скачать пакет для разработки под Windows можно здесь: http://www.compuphase.com/pawn/pawn.htm#DOWNLOAD_WIN

Проблема с перехватами исправлена (https://github.com/compuphase/pawn/issues/28#issuecomment-256745254), но компилятор всё ещё выдаёт варнинги, если функция не объявлена перед выражением "#if defined <имя функции>".
Решается эта проблема очень просто: нужно всего лишь переместить предварительное объявление (forward) перехваченной функции из самого конца перехвата в начало, чтобы она была объявлена до #if defined.
Например, так будет выглядеть перехват OnGameModeInit:


forward my_library__OnGameModeInit(); // Теперь строка с forward должна быть здесь.
public OnGameModeInit()
{
/* Ваши действия. */ print("OnGameModeInit() hook");
#if defined my_library__OnGameModeInit
my_library__OnGameModeInit();
#endif
return 1;
}
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit my_library__OnGameModeInit

Кстати говоря, такой подход работает и в SA-MP (Pawn 3.2), поэтому есть смысл использовать его и там для обратной совместимости.


P.S. Кто-нибудь пробовал собрать компилятор под Linux из последних исходников? Как-то это подозрительно, что файл process.h, который обычно присущ только для DOS, Windows и QNX, используется в sc1.c для всех целевых платформ.

При установке полного пакета инструментов для Windows, в пуске создается ярлык "Pawn IDE (Quincy)" ссылающийся на "quincy.exe", хотя он должен называться "wxQuincy.exe". Не удивлюсь, если разработчики что-то напутали и с другими платформами.

ziggi
29.10.2016, 15:36
P.S. Кто-нибудь пробовал собрать компилятор под Linux из последних исходников? Как-то это подозрительно, что файл process.h, который обычно присущ только для DOS, Windows и QNX, используется в sc1.c для всех целевых платформ.

Не работает, тем более там запускается некий *stategraph.exe. Свой Pull Request я обновил, но что-то сомневаюсь, что его когда-либо сольют с основной ветвью.

Daniel_Cortez
29.10.2016, 17:21
Не работает, тем более там запускается некий *stategraph.exe. Свой Pull Request я обновил, но что-то сомневаюсь, что его когда-либо сольют с основной ветвью.
Только сейчас заметил, что тот запускаемый файл оканчивается на ".exe". В таком случае это явно баг.
Твой Pull Request примут не скоро (если примут вообще) по очень простой причине: разработчику Pawn наверняка придётся протестировать внесённые тобой изменения на нескольких целевых платформах, на что у него вряд ли есть время - он сам говорил, что у него много работы и почти нет времени на собственные проекты.

ИМХО, по-хорошему следовало бы создать issue и в нём отрепортить проблему (заодно упомянув про битый ярлык на quincy.exe) или сделать отдельный PR с исправлением той проблемы с process.h - не пришлось бы ждать проверки всей кучи изменений, которая всё равно вряд ли будет принята.

ziggi
29.10.2016, 23:54
Только сейчас заметил, что тот запускаемый файл оканчивается на ".exe". В таком случае это явно баг.
Твой Pull Request примут не скоро (если примут вообще) по очень простой причине: разработчику Pawn наверняка придётся протестировать внесённые тобой изменения на нескольких целевых платформах, на что у него вряд ли есть время - он сам говорил, что у него много работы и почти нет времени на собственные проекты.

ИМХО, по-хорошему следовало бы создать issue и в нём отрепортить проблему (заодно упомянув про битый ярлык на quincy.exe) или сделать отдельный PR с исправлением той проблемы с process.h - не пришлось бы ждать проверки всей кучи изменений, которая всё равно вряд ли будет принята.

Он половину проблем исправил, теперь PR довольно мал: 4 изменённых файла, ~30 изменённых строк.

Daniel_Cortez
30.10.2016, 16:15
Он половину проблем исправил, теперь PR довольно мал: 4 изменённых файла, ~30 изменённых строк.
Да, действительно, немного поторопился с выводами.

Присмотрелся к твоим изменениям и несколько моментов вызвало вопросы.
Во-первых, сразу бросается в глаза такая попытка приведения типа (правильнее было бы сказать "каламбур типизации", но я не уверен, знает ли кто-нибудь здесь о таком понятии):

return fclose((FILE*)&params[1]) == 0;
Вместо указателя на структуру FILE будет передан указатель на ячейку params[1], которая должна содержать указатель на FILE - в итоге вместо просто указателя получаем... указатель на указатель.
Возможно, правильнее было бы вот так:

return fclose(*(FILE*)&params[1]) == 0;

Во-вторых, описанный выше метод приведения типа безопасен только если размеры типов совпадают - например, если размер указателя и ячейки Pawn по 32 бита. Если же собрать Pawn с 64-битным размером ячейки под 32-разрядной платформой, результат конверсии может оказаться неправильным.
Рассмотрим такой пример:


FILE *f = fopen(...);
cell x = *(cell *)&f;

Поскольку размер ячейки 64 бита, то по адресу, где расположен указатель f, будет считано не 32 бита, а 64, т.е. кроме указателя будут считаны ещё и следующие 32 бита и в x будет неправильное значение.
Проще скрыть предупреждения компилятора с помощью #pragma GCC diagnostic ignored, как это уже было сделано в последнем коммите перед релизом 5588. Возможно даже, что после того коммита никаких предупреждений с приведением типов уже не будет и часть изменений в PR можно убрать.

И да, раз уж ты взялся за обновление того реквеста, не мог бы внести изменение, которое я описал в комментарии к PR?

ziggi
30.10.2016, 20:53
Сделал.

Daniel_Cortez
31.10.2016, 20:06
Ок, ещё один интересный момент:


#if !defined toupper
#define toupper(c) ( (c)>='A' && (c)<='Z' ? (c) + 'A' - 'a' : (c) )
#endif

Такой подход прокатил бы в Pawn, но в C и C++ оператор defined работает только в директивах #if/#elif и только с названиями макросов (если это только не какое-то нестандартное расширение, специфичное для какого-то одного или нескольких компиляторов).
Даже если функция toupper была объявлена в одном из заголовочных файлов, выражение "defined toupper" вернёт false и твой макрос в любом случае заменит эту функцию.
Должно быть какое-то решение получше, чем это. ИМХО, даже просто ничего не делать, оставив предупреждение компилятора о необъявленной функции, будет лучше, т.к. функция toupper всё равно есть в стандартной библиотеке (libc.so или как ещё она должна называться).

ziggi
31.10.2016, 21:07
Ок, ещё один интересный момент:


#if !defined toupper
#define toupper(c) ( (c)>='A' && (c)<='Z' ? (c) + 'A' - 'a' : (c) )
#endif

Такой подход прокатил бы в Pawn, но в C и C++ оператор defined работает только в директивах #if/#elif и только с названиями макросов (если это только не какое-то нестандартное расширение, специфичное для какого-то одного или нескольких компиляторов).
Даже если функция toupper была объявлена в одном из заголовочных файлов, выражение "defined toupper" вернёт false и твой макрос в любом случае заменит эту функцию.
Должно быть какое-то решение получше, чем это. ИМХО, даже просто ничего не делать, оставив предупреждение компилятора о необъявленной функции, будет лучше, т.к. функция toupper всё равно есть в стандартной библиотеке (libc.so или как ещё она должна называться).

Там (https://github.com/compuphase/pawn/blob/09070ba7da3c032892287f6a7068ec60e0d39f02/amx/fpattern.c#L101-L103) tolower реализован точно также, поэтому я так и сделал.

Daniel_Cortez
27.11.2016, 16:36
Немного обновил свой PR (https://github.com/compuphase/pawn/pull/27) с исправлением нескольких уязвимостей (https://github.com/compuphase/pawn/issues/26) в интерпретаторе. Правда, настораживает скорость рассмотрения патчей - почти 3 месяца с открытия PR и до сих пор ни одного комментария от разработчика Pawn. Надеюсь, не придётся ждать ещё полгода.

Кстати, об уязвимостях, интересно, как к ним относятся в SA-MP Team. В 2009-м Kye отключил опкоды JUMP.PRI и CALL.PRI, чтобы устранить уязвимость с выполнением непроверенного байт-кода. С тех пор вместо JUMP.PRI научились получать аналогичный эффект от SCTRL 6 (т.е. выполнение "левого" кода всё ещё возможно) и открыта ещё одна уязвимость в LREF.S.PRI/ALT и SREF.S.PRI/ALT - чтение и запись данных за пределами скриптовой песочницы. Но никто и не торопится исправлять эти уязвимости. Более того, их даже используют в некоторых работах, таких как YSI (https://github.com/Misiur/YSI-Includes/blob/YSI.tl/YSI_Storage/y_amx.inc#L135) или SmartCMD (https://github.com/YashasSamaga/SmartCMD) (следует отдать должное, работы на самом деле очень хорошие, авторы вложили в них много сил, но их практика с использованием багов, ИМХО, сомнительная).
Вся эта идея с принятием багов за фичи отнюдь не нова для SA-MP, но всё же факт интересный. Многое говорит о "серьёзности" в разработке как самого SA-MP, так и связанных с ним работ.

UPD: Добавил больше ссылок в пост.

JohnConor
19.06.2017, 18:27
Как я понял появилась новая версия, данные с сайта https://www.compuphase.com/pawn/
Current version 4.0.5691 (2017-06-14)