![]() |
Ответ: создание MIDletPascal compiler'a
satan как успехи? наш раздел по посещаемости такими темпами скоро будет бить рекорды - всем интересно...
жаль если не получим готорого продукта, а именно публичные исходники простого Pascal byte-code компилятора. Мне итак приходиться выкладывать сырые исходники, как говориться - только из под пера... чтобы не уводить разработку компилятора не потому пути.. на данный момент времени на эксперименты мало, сейчас главное получить полностью работающий java-asm компилятор и попутно разобраться в сложных командах языка java, поэтому в исходниках так много комментариев напротив java-комманд. ______ нужно сделать разбор таблицы локальных переменных и таблицу обработчика исключений, поиграться с byte-code командами и том, что не написанно в документации |
Re: создание MIDletPascal compiler'a
Я корочь ужо составляю BNF (вернее лекс организовал), тута тормоза в том, что хочу извратицо и сделать совместимость не токма с oPascal но и с Delphi, ну тоесть что бы прога работала и на том и на том.
Кстати сложного с Java командами в принципе никаких, вот только синтаксис не знаю какой, классику или ООП выбрать. Мне ООП больше прикалывает, хотя и класика тож ничо. Пилгрим - если не трудно закинь в оркестр инфу о том как в Мидлетах ООП организовываеца! Типа простенький пример инклюда объектов. Так то структуру я понимаю, а вот как инклюдить это??? ЗЫ... Ча ребят чутка потерпите, я проект один добью... Первый компилер с поддержкой рус яз... мля... перспективы... Причом по ходу, что бы была полная поддержка Java вырисовывается следующаа схема Pascal->Java (*.pas->*.java транслятор) это очень легко Java -> Class (*.java->*.class) посложнее... Причом пример соответствия Program LaLaLa; -> Class LaLaLa begin - end; соответственно {} procedure AnaHono; -> public static void AnaHono() И самый прикол, что можно сделать классически, тоесть на Pas написать пару библиотек и включить поддержку INLINE, тогда функции приобретут клёвый вид Program HelloWord; -> class HelloWorld uses System; -> подключим нашу библиотеку ..... begin -> { writeln ('Hello World!'); end; -> } Где в модуле System оформим фукцию procedure writeln(S: String); -> public static void writeln(String [] args) begin -> { inline System.out.println(S); // Вставиться без изменения end; end; -> } Короче это тока наметки но в итоге получца шойта вроде Код:
class HelloWorld{ Другой метод, сразу переводить в байт код, тоесть делать на прямую компилятор Pascal - VM ByteCode но тогда мы не сможем подключать библиотеки написанные на Java или придеца извращатся как с МП!!! |
Ответ: создание MIDletPascal compiler'a
satan, все можно сделать гораздо проще, об этом говорил еще в начале:
делаем файл, на каждой строке в котором будет полное название класса, метода и его параметры. При компиляции в байт-код будет искаться метод и проверятся параметры. т.о. можно напрямую вызывать java, будет еще список сопоставлений где команде языка Pascal ставится аналогичный Java-метод. этап Pascal->byte-code будет создавать список констант и асм-код, который обращается к ним по поводу организации ООП в java все завязано на подмене индекса класса на наш, в котором мы что-нить меняем |
Re: создание MIDletPascal compiler'a
Вложений: 1
Вот накатал сканер, пригодица для дальнейшей работы...
ЗЫ... Исправил косяки... |
Re: создание MIDletPascal compiler'a
Пора на форум ставить капчу и подтверждалку администрацией! А то уже спамеры виагру толкать начали!!! :-D:-D:-D
|
Re: создание MIDletPascal compiler'a
Вложений: 1
Народ видю заскучал...
Забрасываю начальный парсер... Парсит строки вида 1+22- 44.5678 / 44*2.345 тоесть пока без кавычек. Сканер сдвинул в отдельный модуль, кто хочет может его дорабатывать на свое усмотрение |
Ответ: создание MIDletPascal compiler'a
Вложений: 2
выбрал свободное время доработал java-decompiler, сделан в TurboPacsal7.1.
правда остались сомнения насчет разбора tableswitch и lookupswitch; также необходимо сделать разбор структуры StackMap. файл JD.ZIP (исходник, exe, пример_использования) файл JCC.ZIP - наброски java class-assembler после декомпиляции примера из архива JD.ZIP получаем структуру для ассемблируемых файлов, т.е. примерно так будет выглядеть файл для перевода в class-файл JCC.ZIP/j.txt cделал наброски общей структуры разбора и работы с константами, теперь нужно проработать формирование блока METHOD... исходники java-asseblera написанные на java (3.1 MB) можно посмотреть по адресу: http://sourceforge.net/project/showf...ease_id=438525 home page: http://jasmin.sourceforge.net/ и еще: http://sourceforge.net/project/showf...ease_id=391215 home page: http://sourceforge.net/projects/tinapoc оттуда можно подсмотреть реализацию некоторых алгоритмов, но делать как там мы не будем.. слишком раздуто.. наш ассеблер будет не хуже, но проще _____ p.s. народ не стесняемся,.. подключаемся к проекту.. |
Ответ: создание MIDletPascal compiler'a
Вложений: 1
вот, усиленно посидел пару-тройку вечеров и родил java-assembler
полностью разбирает и компилирует в hello.class собранный нами дизассемблер разбирает его, а вот NMI's Java Code Viewer 6.0 не хочет, и соответственно не хочет запускаться в эмуляторе. Возможно это из-за того что забита нулями какая-нибудь служебная переменная или не хватает еще дополнительных констант в заголовке... что не сделано, так это генерирование StackMap - структуры.. ___ в архиве так же лежит доработанный java-decompiler (перекомпилирован с дерективами проверки переменных и кое-где изменен алгоритм) т.к. компилятор TurboPascal7.1 то длина UTF8 - строчек в разбираемых классах не должна превышать 255 символов, чтобы снять это ограничение нужно перекомпилировать в Delphi ___ p.s. satan поэкспериментируй с assembler'ом, нужно немножко поправить... |
Ответ: создание MIDletPascal compiler'a
Ыыыы... А я немного въехал в тему. Хотя по-началу нифига не понял, потом стал сам классы расковыривать. За утро нашёл там всякие закономерности, байты по группам разложил. Но толком не мог понять, какой байт что значит. Только разобрался со строками. Потом зашёл снова в эту тему и резко многое понял. Я ща прямо фигею, как я всё в кассе по группам разделил, как у меня ума хватило, гг. Ну так вот. Я целей глобальных не ставлю. Мне всего лишь надо генерировать класс, в котором будет массив объявляться со значениями. На php. Короче, надо, чтобы сервер кое-чего в java проге менял. Просто сервер будет генерировать класс с объявленным массивом и запаковывать его в архив с прогой. А в проге уже другие классы, которые будут брать значение массива из того класса. Ах да, ещё нужно будет генерировать имена методов. Думаю, смогу это сделать. Всем спасибо за тему =)
|
Re: создание MIDletPascal compiler'a
Phantom_wc
Могу подкинуть на PHP создание экзешника, а там уже сам переделаешь в Java Class ЗЫ... Ща прорабатываю оптимизированый компилер (на expression уровне) |
Ответ: создание MIDletPascal compiler'a
satan, давай, буду признателен. Надеюсь пригодится. Только вопрос, несколько тупой... Что такое "экзешник"? гг
|
Ответ: создание MIDletPascal compiler'a
Вложений: 1
Вчера в спешке откомпилил и скинул старую версию дизассемблера, вот последняя.
Исправленны некоторые ошибки, возникающие при разборе определенных классов. Для удобства дизассемблирования можно применить bat-файл, он преобразует длинные пути и имена с пробелами и длинными расширениями в короткие-dos. Использование: выделить мышкой группу "*.class" файлов (до 255 шт.) и перетащить на этот батник или его ярлык. bat-файл должен находиться в каталоге с программой jd.exe. также можно поставить настройку на "*.class" файлы "Открыть с помощью" и указываем этот bat. ____ jdisasm.bat Код:
echo off В случае замены константы можно поступить способом как предлогал в самом начале: -Т.е. берем и делим бинарный *.class-файл, в месте где у нас находиться необходимая константа. -Должно получится два кусочка: до константы и после константы. -В проге генерируем серединку (строку-массив) и сохраняем в файл. -И завершении склеиваем все три файла: НАЧАЛО + НАШ_КУСОЧЕК + ОСТАЛЬНАЯ_ЧАСТЬ ___ Народ! половина работы почти сделана, теперь нужно доработать java-assembler. и сделать генератор-конвертировщик с языка Pascal в asm-текстовый-исходник предоставленного формата. Написанный ассемблер позволяет размещать структурные единицы в произвольных местах, но желательно придерживаться предложенного формата: объявление классов объявление имен_и_типов прочие переменные интерфейсы поля методы ___ p.s.: не откажусь от помощи, т.к. мало времени и много дел... просьба админам добавить default-пользователя с которого можно было-бы скачивать выложенные архивы и резместить имя и логин на страничке скачивания |
Re: создание MIDletPascal compiler'a
Вложений: 1
Цитата:
как ток допишу, останецо токма разобрать структуры и контекстный пул заполнить!!! ЗЫ... Экзешник - исполняемый файл для Windows( типа Notepad.exe ) вот файл, написан коряво, так как надо было общюю суть передать, но работает и компилит вроде... :rolleyes: |
Ответ: создание MIDletPascal compiler'a
Ггггг... Я так и подумал... Только вот какое он имеет отношение к Java? Я для компа никогда ничего не писал. Я Java-то толком не знаю. =) Как он мне поможет?
|
Re: создание MIDletPascal compiler'a
Поможет разобраться как делать файл по его описанию...
Тоесть берёте описание Class файла и с помощью php собираете его в рабочий код, почитайте с начала темы, и поймете, что это не так уж и трудно, по смещению (не по адресу) который виден в редакторах, а по смещению от этих адресов, находить и модифицировать код какой вам нужен. В примере создаётся файл при запуске которого вылетает ОКНО СООБЩЕНИЯ (вроде Hello Word) откройте его HEX редактором и сравните с кодом на PHP как происходит процесс записи байтов в файл, так же там комменты для того, что бы знать для чего те или иные байты в файле служат... Ну и т.д.... |
Ответ: создание MIDletPascal compiler'a
Спасибо, поковыряю. Но мне ведь не надо писать компилятор или ассемблер. Мне вообще минимум надо реализовать. Хотя... Если азарт возьмёт верх... Особенно если быстро въеду как это делается.
|
Ответ: создание MIDletPascal compiler'a
Вложений: 1
Доработал некоторые структуры - теперь полученный class-файл дизассемблируется и декомпилиться в NMI's Java Code Viewer 6.0, но WTK 2.5 отказывается его запускать... видимо где-то несоответствие типов, выложил в архиве последнюю версию java-assembler'a адаптированную для компиляции как в TurboPascal так и Delphi.
В архиве также оригинальный class-файл сделанный в WTK 2.5, и компилированный в нашем ассемблере... ___ satan сравни-ка, теперь нужно немножко добрать, чтоб запускался... в MidpX не пробуй, почему-то не работает даже оригинальны hello.class, хотя WTK-эмулятор запускает нормально |
Ответ: создание MIDletPascal compiler'a
нужно создавать структуру StackMap_attribute в ней записываются типы переменных которые лежат в стеке и параметров метода. это записывается на стадии верификации (проверки) класса. кто-нить найдите подробное описание, похоже там структура переменного размера
|
Ответ: создание MIDletPascal compiler'a
Вложений: 2
нашел пару интересных сайтов по java-bytecode.
доработал java-bytecode assembler и java-bytecode disassembler. теперь разбирают структуру StackMap_attribute, также доработал вычисление размера стека max_stack для компилируемого метода. Теперь созданные программы запускаются в эмуляторе WTK 2.5 ___ общие принципы и методы создания java-программ. инфа для начинающих http://www.uran.donetsk.ua/~students...s/pro/2/2.html грамотное описание формата класса и работы и ним на примере исходника, жаль не попадалось раньше.. тогда б несколько по иному спроектировал алгоритм java - ассемблера http://devdaily.com/java/jwarehouse/...sm/index.shtml ___ LearnJavaByExample.zip - сохраненные страницы с представленных сайтов java_.zip - последнии версии java ассемблера/дизассемблера. ___ p.s. необходимо проверить работу алгоритмов и профиксить погрешности. сюда заглядывают java-програмисты?.. необходима помощь в тестировании |
Ответ: создание MIDletPascal compiler'a
теперь немножко о формате asm-файла для компиляции.
Файл компилируется без каких либо проверок на корректность объявленных структур, синтаксиса описания команд - частично. Первая строка файла - команда объявление текущего класса. команды ассемблера: class внутренне_имя_класса его_строковый_тип nameandtype имя_переменной его_строковый_тип другие_константы_(string, int и т.д.) внутренне_имя строка_или_число interface строковое_имя_ранее_объявленнго_класса field "указываем_атрибуты" имя_переменной_nameandtype method "указываем_атрибуты" имя_метода его_строковый_тип между блоками method ... endmethod указываются java-bytecode команды и объявляются блоки localvariabletable stackmap, которые обнуляются при выходе из текушего метода командой endmethod синтаксис описания bytecode можно получить дизассемблированием программой jd.exe любого class-файла localvariabletable имя_переменной "ее_строковый_тип" stackmap "строковый_тип" смещение_в_стеке:_ 0_или_1, где 0_это_параметр_локальной_переменной; 1_параметр_стековой_переменной _____ вот пример asm-файл j2me программы hello.java Код:
import javax.microedition.lcdui.*; Код:
class hello "hello" |
Re: создание MIDletPascal compiler'a
Вобчем хоть убей я всеравно мысли не улавливаю...
Давай обьясню чо я мутю... Итак, делаю 4 (пока) модуля global.pas scaner.pas parser.pas codegen.pas В первом вынес все переменные и константы. Второй отвечает за разбор исходного текста Третий по разобраному лепит class файл четвертый как раз функции генерации class файла. Принцип следующий. scaner.pas разбирает исходный текст на слова и возвращает нам тип слова (оператор, переменная, функция...) парсеру, парсер в зависимоста от типа вырабатывает вызов функции кодогенератора который в свою очередь и лепит байт к байту в соответствии с правилами построения class файла. Пример program HelloWord; begin writeln('HelloWord'); end. Парсер запрашивает у сканера тип первого слова Сканер возвращает program - > оператор - начало программы Парсер проверяет что бы за этим оператором шло название программы и точка с запятой, если ошибок не было, парсер делает следующий запрос... И т.д. и т.п. рекурсивно. В итоге любой язык можно транслировать в другой, не взирая на синтаксис программиста (переносы строк и т.д) и более того, к компилятору можно прикрутить любой выходной файл, в принципе повторить Турбо паскаль не сложно, или бэйсик или яву... Так как функции рекурсивны, то вызов их может быть выполнен из любой точки кода... Допустим имеем код a:= 22+ 12.3/45 - (a+b); За операцию присваевания будет отвечать функция assignment() за разбор выражения - expression(); В итоге у нас наше присваевание сведется к минимальному разбору типа assignment( expression()); и рекурсия позволит учитывать приоритет операций. Просто у меня пока запарка с работой, а так я уже пишу помалень оптимизированый на этом уровне код, который из строки a:= 2+3 -1/2 +(a*2-4); сразу же просчитает все смысловые выражения и странслирует только a:= 4.5 + (a*2 - 4); дальше пока не иду.... Вот где самый затор - в оптимизации, остальное все просто дело техники... А у тебя я поверь, не могу смысла уловить? На кой декомпилировать class файл и потом из этого что получилось опять лепить class файл??? Ты опиши хотя б в двух словах, что хоть на этапах построения или компиляции будет? Типа вот так Компилер рекурсивный Исходный код на Pascal транслирует в JavaAsm создаст контекстный пул исходя из записей таблиц переменных, функций и констант, которые возникнут при работе парсера и сканера. Для дальнейшего расширения, можно будет копировать сканер с анализом Java синтаксиса и сделать транслятор Pascal - Java (для разработчиков библиотек и Java кодеров) таким образом подключив всю яву... Я хоть немного впилюсь в тему... |
Ответ: создание MIDletPascal compiler'a
Вложений: 2
эх, наверное скоро язык намозолю, ... задача pascal-компилятора подготовить текстовый javaAsm-исходник.
_________ "...А у тебя я поверь, не могу смысла уловить? На кой декомпилировать class файл и потом из этого что получилось опять лепить class файл???..." - я думаю все поняли, мне например лень разбирать class-файлы в hex-редакторе, ну можно поковырять парочку, но сотню-другую ни за что... дизассемблер нужен для разбора/экспериментов с class-файлами, чтоб лучше уяснить их структуру и возможные вариации. Поле деятельности огромное: бери любую игрушку и декомпиль,.. а потом смотри сможет ли асссемблер сделать также, если нет - смотри в чем ошибка алгоритма. Возможные применения java-decompiler'a: Если для компиляции простенькой библиотеки для MIDletPascal нужно писать кучу заглушек, то можно с помощью decompiler'а сделать заготовку, изменить ее и скомпилировать библиотеку. Или же нужно изменить логику программы (подправить несколько байт в коде), то decompiler'ом можно пользоваться как инструментом анализа class-файлов. _________ "...Ты опиши хотя б в двух словах, что хоть на этапах построения или компиляции будет? Типа вот так Компилер рекурсивный..." -я думал это и так ясно, тем более что предложил переработать исходник <pascals.zip>, в который нужно немного изменить кодо-генератор для вывода java-bytecode команд, а также добавить структуру переменных/функций и их параметров под названием Constant Pool. :) В предложенном исходнике уже создана оптимизация константных выражений (над которой ты сейчас работаешь), проверка типов при вычислении и многое другое, а также все необходимые структурные единицы языка Pascal. _________ "...и сделать транслятор Pascal - Java (для разработчиков библиотек и Java кодеров) таким образом подключив всю яву..." -как думаю уже стало ясно, то в данном паскале можно будет вызвать любой java-метод, даже тот которого нет и ни будет,.. поэтому нужно определить стандартные функции языка pascal и сопоставить им таблицу с аналогичными java-методами, чтоб проверялся тип параметров и при разборе синтаксиса. Выглядеть pascal-исходник будет примерно так: Код:
TYPE -если очень нужен java исходник, то его можно получить и путем дизассемблирования готового class-файла с помощью программы NMI's Java Code Viewer 6.0. Сейчас главное определиться с необходимым набором java-команд для pascal-компилятора. И созданием необходимых структур для оформления class-файла. _________________________________ файл stackmap_works.zip - немного доки файл JD_.ZIP - декомпилер для экспериментов.. Опять загвоздка с разбором StackMap его структура такова: Код:
StackMap_attribute { здесь работает нормально Код:
attribute_name: [1175] -> {utf8}StackMap Код:
attribute_name: [1175] -> {utf8}StackMap Код:
function decodeutf8 : word; |
Ответ: создание MIDletPascal compiler'a
Вложений: 1
Доработал java decompiler, разбирает почти все структуры, добавлен алгоритм декодирования utf8, распознавание stackMap и т.д.
Если какой-либо из работающих class-файлов будет декомпилироваться с ошибками, присылайте его в упакованном виде на почтовый ящик: [email protected] с темой сообшения "class file error" _____ нашел еще неплохой сборник исходников по разбору java-class файлов http://svn.apache.org/viewvc/jakarta...pathrev=694866 _____ вот страничка с исходниками pascal-компиляторов http://exmortis.narod.ru/src_pcode.html для начальных экспериментов по генерации текстового asm-файла предлагаю посмотреть исходник http://exmortis.narod.ru/pcode_src/sc.zip на его базе можно создать пробную модель простого компилятора, а после экспериментов приступить к переработке pascals-компилятора. |
Re: создание MIDletPascal compiler'a
Вложений: 1
Ну наконец то подошли к компиляторам!!! Гы... Я поетому и молчал немножко!!!
На http://exmortis.narod.ru/ я изучил и скачал почти все компилеры (Интерес представляли тока пара 32 битных) Тут по шагам как сделать компилер на ПАСКАЛЕ http://kit.kulichki.net/crenshaw/crenshaw.html Советую изучить внимательно статьи и (кстати код вполне там рабочий если поправить пару строк кода) компилятор Inno Pascal - 32 бит с отладчиком по мойму и дебаггером и оптимизацией.... ЗЫ... Кстати а линуксоиды чево не подключаются... FreePascal тож в исходниках идет!!! Вот прикрепляю исходник базового компилятора для любого языка (кто какой потом кодоген сделает и сканер прикрутит)... Реализована функция разбора выражений... наглядная пока, тоесть попросту калькулятор (оптимизация с шагом назад), потом мож прикручу полную с заглядыванием вперед. Разбор выражений вида 22.44 + ((((33.66 - 5*12.5) - 4+12)-(1+5.7)/2)+11); Ну то есть ядро любого компилера, то есть вычисления, затем, если не будет вопросов прикручу присваивание и формирование таблицы переменных и таблицы вызовов функций... Далее булевы операции и управляющие конструкции типа for-next if-then-else ... И останетцо самая малая часть - разбор прецедур-функций и типизация переменных...:crazy: |
Ответ: создание MIDletPascal compiler'a
Вложений: 1
Переработал простой компилятор http://exmortis.narod.ru/pcode_src/sc.zip для генерации простого текстового java-asm листинга. Который затем компилируется в class-файл.
_________ Принцип постороения программы: имеется простой class-файл (prog.class) - эмулятор консоли, работая с методами которого созданный java-код выводит на экран: константный_текст, символ или число и получает числа с поля ввода. Это минимально рабочий компилятор для создания java-class файлов. Файлы созданные в полной версии должны работать без дополнительных библиотек и реализовывать все возможности java. _________ В архиве имеется asm.bat при перетаскивании на который pascal'e-подобного исходника, (примеры: 1.txt; 2.txt; 3.txt; 4.txt) автоматически собирается файл *.cla, его переименовываем в jc.class и добавляем в архив prog.zip, который переименовываем в prog.jar и запускаем _________ Порядок работы в ручном режиме: compile.exe list < входной_файл_pas_листинга > выходной_asm_файл параметр list говорит чтоб выводился только листинг, а программа не запускалась на внутреннем эмуляторе jcc.exe выходной_class_файл.cla < входной_asm_файл jd.exe входной_class_файл.cla > выходной_дизассемблированный_файл_для_проверки _________ Примечание: компилятор не генерирует структуру StackMap, она необходима если в методе встречаются команды перехода, поэтому если программа не линейная (циклы,условия) - необходимо запистить утилиту preverify.exe которая проверит class-файл на корректность и добавит структуру StackMap. В архиве также имеется bat-файл с параметрами вызова утилиты preverify.exe, если будете использовать то создайте структуру каталогов c:\wtk25\bin\preverify.exe c:\wtk25\lib\midpapi10.jar; c:\wtk25\lib\cldcapi10.jar; c:\wtk25\lib\midpapi10.jar; c:\wtk25\lib\cldcapi10.jar c:\wtk25\apps\prog\classes c:\wtk25\apps\prog\tmpclasses и положите в tmpclasses файл jc.class |
Re: создание MIDletPascal compiler'a
Вложений: 1
Воопче бросай хреновиной занимаца! Оч хорошо что народ разобрался со строением классов, но сейчас требуется копать не байт код компилеры, а в сторону оптимизации!
Для примеру закидываю перевод строки в ОПЗ (потому что тогда генерация в асм идет напрямую без всяких выпендрезов с рекурсией) http://decoding.narod.ru/practic/pol...ishrecord.html Во вторых прикрепляю наработку (считает тока целые... пока) но немного надо доточить напильником что бы полностью просчитывала строку. Как только создадим оптимизатор, мля он станет КОНКУРЕНТНОСПОСОБНЫМ, и более того, потом паскаль просто тупо распарсим и в пул запихнем. Вообще щас копаю модулу и компилер "странник", достал самокомпилируемые исходники и пробую перевести на паскаль с модулы... |
Ответ: создание MIDletPascal compiler'a
создаваемый компилятор итак будет конкурентно-способным потому что на фоне шаблонно-сделанного MIDletPascal'я, который спотыкается при разборе программы (не дай бог вы забудете поставить точку с запятой или кавычку) помнится даже в хелпе в примерах перед else стояли запятые. по поводу другого Pascal'я о котором говорилось на форуме сказать не чего не могу, совместимость с Delphi эт не плохо, но все базируется на встроенных библиотеках а компиляция происходит по огромному шаблону функций в которых нужно еще разобраться. и здесь вроде нет оптимизации.
satan если оптимизация затрагивает только пересчет выражений то это оч. легко реализовать и в моем переделанном компиляторе: в генераторе кода смотреть на две инструкции назад, если константы- то объединять. Уже вообще-то можно приступать полностью к созданию компилятора. алгоритм оптимизации затронет изменение только 4-х функций разбора. давай свои предложения/работающие исходники. просто именно для паскаля лучший вариант все-таки от создателя (Никалус Вирт) |
Re: создание MIDletPascal compiler'a
Вложений: 1
Начну с начала.
Компиляторами я занимаюсь давно. (Вообще я давно перешел на уровень создания того, на чем люди делают что-то, редакторы, IDE, конструкторы...) но не в этом суть. Суть в том, что после 3-го или 4-го компилера я понял где основные грабли. Вспомни первый свой декомпилер. На разбор пула ушло 2 дня, и неделя на ассемблер. Почему? Потому что это основа или нижний уровень, которых в компиляторе два - лекс. ан. и кодлгенератор. Так как все языки семантически схожи только в одном, именно в выражениях, то и нижний уровень - ассемблер. А значит и начинать надо с него. Креншоу поэтому правильно сделал и написал с чего надо начинать. Возмем например строку a=b+c b и посмотрим её представление в различных асмах. Fasm: mov eax, [esp -4] - переменная b mov ebx, [esp -8] - переменная c add eax, ebx - сложение mov [esp -0], eax - приравнивание a код относительный - от балды, теперь на Java асм bipush 2 bipush 3 iadd iload 1 код тоже по памяти и от вола! Что мы видим? Похоже, очень даже... Ну да и иначе не могло и быть, асм он и в рассеи асм. Ладно, надеюсь с этим понятно. Тоесть любое выражение можно перевести (не важно на какой ассемблер) а потом перевести с асм на асм дело всего лишь техники! (Вернее дело рук в переписывании операторов). Теперь рассмотрим ОПЗ ( http://www.wl.unn.ru/~ragozin/compiler/compil/g11.htm http://decoding.narod.ru/practic/pol...ishrecord.html ) Из статей понятно, что этим алгоритмом мы по сути готовим строку под ассемблер, не просто готовим, а уже получаем готовый годогенератор для ассемблера безо всяких там рекурсий и вставкой кода... Сравним строку a = b + c в ОПЗ и ассемблером? b c + a = mov eax, [esp -4] - переменная b mov ebx, [esp -8] - переменная c add eax, ebx - сложение mov [esp -0], eax - приравнивание a тут по моему становится ясным мысль о ОПЗ, но тут опять грабли, строка вида 1+a+2+b+3+c Может вырасти в очень длинный код на ассемблере, поэтому её надо оптимизировать, тобишь привести к виду a+b+c +6, что бы уменьшить код конечного файла, что бы не падал компилятор от переполнения да и наконец - это сложно и круто! Ну и приятно... Так вот я предлагаю, пока оставить на время верхний уровень, он нам ни черта не нужен пока и заняться нижним уровнем, а именно функцией ВЫРАЖЕНИЕ (Expression), потому что как только мы сделаем эту функцию или набор функций остальное просто останется банальностью, а именно работой сканера и вызов соответствующих функций. Кстати когда и если мы ето замутим форум может просто лечь от наплыва студентов - курсовиков!!! ЗЫ... Никлаус мужик умный, тока он делал свои компилеры под свою Р-машину. Но выкладываю его Оберон (Модула 2) переделаный для виндовс и сам себя компилящий без глюков. Сайт с документацией и описаловом http://home.perm.ru/strannik/ Сдесь реализована поддержка 3х языков, Модула-Си-Паскаль (к стати в Оберон я влюбляюсь все более и более) И по исходникам можно глянуть реализацию сканера и т.д. Да и сам язык - это крутой паскаль!!! Сдесь уже готовый компилер на Обероне http://www.uni-vologda.ac.ru/job/rus/ связаться с автором пока не удалось, но буду искать Ну вообщем вот пока мысли...................... Да совсем забыл... Этот модуль будет базовым для ЛЮБОГО компилятора... |
Ответ: создание MIDletPascal compiler'a
Вложений: 1
satan, плюсик за хорошее сообщение, Спасибо за ссылки на интернет-ресурсы и исходник.. буду смотреть.. думаю с такой информационной поддержкой проект по созданию компилятора успешно завершится.
___ java-ассемблер завершен на 90% нужно добавить таблицу переходов на метки, генерацию структуры обработчика исключений и авто-генерацию структуры StackMap (сейчас пока вручную на уровне команд). Код компилятора значительно упростится, когда эти задачи будут переложенны в java-ассемблер. ___ Нашел на просторах жеского диска не рекурсивный алгоритм разбора строкового выражения. Когда-то немножко переделывал. Применялся для построения графиков и т.д. satan посмотри может появятся идеи по оптимизации константных выражений.. |
Re: создание MIDletPascal compiler'a
До кучи добавляю полноценный Pascal компилятор
http://66.196.80.202/babelfish/trans...rotinyp ascal Компилит сам себя, синтаксис полный (походу), Гы... единственная проблема - ща деобфускацией его занимаюсь!!! |
Ответ: создание MIDletPascal compiler'a
если исходник на pascal'е не форматированный как в этом примере, то примени 3-и утилитки, которые я ранее выкладывал - они должены разобрать и привести исходный код в читабельный вид.
главное компилируй в delphi, а то в pascal'e длина строки не более 255 символов в примере отдельные строки слишком длинные из-за применения символов "#c" |
Re: создание MIDletPascal compiler'a
Вложений: 1
Уже на 50% перевел в боле мене нормуль вид и восстановил переменные некоторые и функции
|
Re: создание MIDletPascal compiler'a
Вложений: 1
В жисти нету справедливости!!! Ковырял 2 дня паскаль, написал автору и он мне выдал полон код:-D
|
Ответ: создание MIDletPascal compiler'a
добавил структуру и алгоритм вычисления и постороения переходов с использованием меток, теперь pascal-компилятору практически ни чего не нужно знать о командах java-assembler'а, не вести пересчет смещений и т.д.
вот структура для организации переходов: _______ const maxlab=1024*5; {кол-во ячеек для сохранения} typemp=0; {пустой элемент таблицы} typlab=1; {метка} typmod2=2; {элемент коррекции 2-х байтового смещения} typmod4=2; {элемент коррекции 4-х байтового смещения} var lab:array[0..maxlab] of record typ:byte; {тип элемента} name:string[6]; {название метки} adr:word; {адрес в коде} end; lmax:integer; {кол-во элементов} _______ логика работы: метка выглядит так ":имя" в командах перехода если следующий символ не число, то прочитать имя метки и получить смещение к ней. Если метка еще не добавлена (т.е. переход вперед), то записать элемет как элемент_коррекции. В завершении метода просматриваем таблицу меток и правим элементы_коррекции на смещение к нужным меткам. Если метка не найдена, то генерировать ошибку. __ т.к. размер таблицы переходов ограничен, то рекомендую сделать в pascal'e генератор имён_меток так: метка - число, конвертируется в текст только при сохранении в выходной файл например так write(':l'+hex2(label)+' '); где label:integer - инкриментируемое число. Т.к. таблица перехода в ассемблере имеет ограниченный размер, то: в подпрограмме генерации метки сохраняем номер строки предыдущей метки oldStrNum, а при создании новой: if currentStrNum<>oldStrNum then begin inc(label); oldStrNum:=currentStrNum; end; т.е. не создаем лишних меток... |
Ответ: создание MIDletPascal compiler'a
satan, просмотрел компиляторы, Pascal 32bit неплохо сделан, и идеи реализации интересные, правда не вооруженным взглядом видно что это модификация старого доброго PASCALS. а реализации java компиляторов несколько ограниченные. всё-таки лучше изменить pascals, чем корректировать другие. - работы, а самое главное ошибок будет меньше. и не надо изобретать велосипед...
насчет многоязыкового компилятора вспоминается со студенческих времен поговорка нашего профессора: -если при езде на автомобиле обнимать девушку, то не получится ни хорошо вести машину, ни хорошо обнимать девушку. Поэтому лучше сделать простой и не большой Pascals компилятор, чем гору кода и кучу правил, типа: в этом языке это так, а в другом эдак, и ни как иначе, а то не откомпилит. Лучше сделать отдельную версию под другой синтаксис. так что? переделываем PASCALS? |
Re: создание MIDletPascal compiler'a
Согласен, только луче BeroPascal там уже все готово... Я толко распишу в комментах где что находица, уберу PE ассемблер (вместо него Java asm вставим) а место под пул там уже есть, более того он так же делает байт код промежуточный, поэтому допустим модули можно будет распространять защищёнными...
Кстати все эти паскали (в том числе и BeRo) - это улучшеные модификации PascalS а он в всвою очередь сделан по эпусам Креншоу... Вопчем ща смотрю и комментю... Вечером приаттачу расписаную версию паскаля единственное что там нужно будет ввести - это типы string и real |
Ответ: создание MIDletPascal compiler'a
Если честно, была сегодня идея переделать BeRoPascal, но взглянул, и сразу стало лень- эт столько переделывать табулировать, условия if менять на case и др, а еще в нем много переменных, не слишком экономно сделан, а мне б хотелось сделать реализацию и на pascal'e. сложил всё вместе и решил что PASCALS. лучше для нормальной работы добавить только цикл FOR. а промежуточный код есть и в pascals, Только он не нужен, программу ж можно декомпилировать
|
Re: создание MIDletPascal compiler'a
Вложений: 1
abcdef
Ты наверно издеваесся... PASCALS и BERO одно и то же, разница в том, что у Беро уже готовый модуль ассемблирования убери его и получиться полный со всеми паскалевыми выпендрезами компилятор в байт код, прикрепляю закоментированую версию, сравни их и увидиш, даже функции одни и те же... Гы... Там где в Ассемблере я закоментил можно прочитать закоментировать Header вызов (это в нашем случае функция системного пула) и раскоментить создание байт кода... Осталось в Беро сделать только одно перевести с МакроАссемблера на ява ассемблер (прямо тупо заменяя строки типа Код:
OPMul: Код:
OPMul: Код:
OPMul: Единственная доработка в подключении типа string и real а так как он компилит сам себя, то и отладка происходит сразу (единственная неудобство, что он ошибки если есть тоже в себя пишет, поэтому приходица типа test.exe переименовывать в test.txt и читать в какой строке ошибка!!!) Посмори, если какие функции иль ещё чиво не понятно, я опишу их поподробнее, а так получица что из PASCALS мы просто тупо сделаем BERO и прикрутим JAsm... Гы... нафига мартышкин труд, если уже все готово... Переменные в таблице переменных Типы в таблице типов Массивы описаны Вызовы функций и т.д т.п можно сразу запихивать в пул в функции Header после ассемблера нам доступен размер кода и смещения... Короче уже все есть, надо просто сесть и перевести с одного асма на другой!!! И получим систему круче чем МР так как исходники будут открыты... Если хочешь поэксперементируй с функцией Header типа запиши вместо: Код:
OCP:=0; Код:
OCP:=0; |
Re: создание MIDletPascal compiler'a
Кстати не могу никак понять где студенты (им уже готовая дипломная тут написана)
где хакеры им уже готовый код для инжекции готов просто в функции Код:
procedure AssembleAndLink; Где фанаты МР тоже не понятно... |
Ответ: создание MIDletPascal compiler'a
Цитата:
|
Re: создание MIDletPascal compiler'a
interesno, esli'b eto bilo 3 goda nazad to ja pervim studentom bil :)
eto tak offtop :) a po teme jdu datu reliza :) |
Re: создание MIDletPascal compiler'a
|
Ответ: создание MIDletPascal compiler'a
Пеплохой проект. странно, что за файлами лезет именно на "e/zam". Порадовала реализация парсера на flex. Может стать альтернативой MobileBASIC
|
Re: создание MIDletPascal compiler'a
Вложений: 1
Ну вот, начальный код компилятора...
Разбирается верхний уровень и константы, файл testj.java и альтернатива на Pascal test.pas в архиве, так же два скриншота сравнения оригинала testj.class и test.class(нашего компилятора) Компилер разбил на 4 модуля В модуле Codegen реализация формирования кода Файл test.bat запускает компилирование... Такс, скоро прикручу DOOBLE типы и останеццо тупое разбирательство кода в пул... А потом уже будем думать нижний уровень(ASM)... А то затишье такое мля аж страшна...:-D ЗЫ... Откомментил все что можно... |
Ответ: создание MIDletPascal compiler'a
Ребяты ,а есть где нибуть более подробное описание,спецификации JVM
на русском кроме как на http://www.uni-vologda.ac.ru/java/jvm/outline.htm ? |
Ответ: создание MIDletPascal compiler'a
Вложений: 1
scimitar хочешь помочь?
ссылки на сайты с исходниками разбора java-bytecode (которые здесь были) смотри.. так лучше разберешься. ____ выкладываю последние исходники, к которым пока руки не доходят, из-за лени и отсутствия времени. 1. немножко переделанный простой компилятор pascal'я "compile" (в конце строк ';' присваивание ':=' и еще что-то непомню..) 2. версия компиятора "jcc" с поддержкой переходов на метки, нужно добавить обработчик ошибок, и стековую карту.. 3. добавил 40 строк кода в файл "pascals" и он стал генерировать приблизительный код в формате java, только все переменные и имена получают нечитабельные названия.. нужно добавлять таблицу имен.. |
Re: создание MIDletPascal compiler'a
2abcdef
Вот ты повторяешь мои ошибки 3-4 летней давности.... во первых надо в PascalS исправить strcpy(word[procsym], 'procedur'); на strcpy(word[procsym], 'procedurе'); во вторых ввести тип string в третьих надо сделать для начала что бы он корректно разбирал переменные так как типа REAL там никогда не было, а с о сканером PASCALS это немного проблематично, и короче дохрена всего чего надо в этом паскал... У меня тормоза не из-за того, что я не могу компилер написать (я их уже переписал дай бог), а из-за того, что я дорабатываю IDE свою, а потом уже к ней буду прикручивать компилеры всякие, причом интегрировать прямо внутрю... В четвертых Java код строится на стеке, когда как PascalS на регистрах о.н. поэтому когда выражения простые, то все прокатывает на ура, как только дойдешь до сложных вычислений твой код просто начнет расти диким образом и в конце концов не поместится в памяти В пятых скачай JavaByte... Ну и т.д. Хотя для понимания процесса пойдет и PascalS |
Ответ: создание MIDletPascal compiler'a
в файле pascals есть ссылка на первую версию, в ней есть поддержка типа Real. Таблица слов в pascals 8-ми символьная, поэтому в слове "procedure" обрезает последнию букву. Вообще трудно найти более оптимизированный и простой компилятор паскаля, чем pascals, просто в нем оставили только самые необходимые функции для разбора полного синтаксиса стандартного паскаля и больше ничего
|
Ответ: создание MIDletPascal compiler'a
ПАрни можно сделать classi на мобилу, Т.Е Создать компилятор на мобилу, а уж потом добавить оформление, можно реально создать паскаль на мобилу
|
Re: создание MIDletPascal compiler'a
TEMNED
В принципе можно как нибуть потом, в свободное время занятся созданием компилятора на мобилу, но мы ведь в этой теме занимаемся совсем другими вещами то!!! |
Re: создание MIDletPascal compiler'a
abcdef дружище, кидани ссылку на паскаль с REAL, и внимательно сравни то что я наковырял с PascalS...
Кстати там уже пул и код собирается... |
Ответ: создание MIDletPascal compiler'a
мона добавить оформление, либо самим сделать, либо попросить братьев из комнат "программирование для компов", добавить все библиотеки, т.е не надо дополнительних либ, все будет уже вкл. И мона випускать новую версию MP.
|
Ответ: создание MIDletPascal compiler'a
Да. Парни надо би добавить оформление, окно, кнопки, все такое, запоковать в инсталятор, дать всем, штоб разкладивали везде по инету, и готов MIDLETPASCAL 2.04 например, тока надо шо-нить уникальное, т.е новое. Говорите, што бы кто хотел видеть новое в новой версии мидлетпаскаль.
|
Ответ: создание MIDletPascal compiler'a
===
а существует ли какой java-aссемблер- компилятор в байт код для мобильного? и существует уже для МПкомпилера какоенить ИДЕ? |
Ответ: создание MIDletPascal compiler'a
а тема ещё актуальна?
предлагаю обсудить Среду разработки нового Мпаскаля... например окно редактора может выглядеть так ============================ меню ============================ толбар ============================ |____|____________________|_____| |____|____________________|_____| |____|____________________|__3__| |____|_________2__________|_____| |__1_|____________________|=====| |____|____________________|_____| |____|____________________|__4__| |____|____________________|_____| |____|____________________|_____| ============================ 5 ============================ 1 окно - 2две панели - как и в редакторе, панель работы с ресурсами и панель описания манифеста.... 2 окно собстевенно текстовый редактор - с подсветкой синтаксиса -с нумерами строк-со сворачиваемыми "структурами" языка 3 окно - при редактировании текста после ввода 2х-3х и более символов показывает встроенные наименования функций - с возможностью выбора нужной мышой.. 4 окно - шаблонная структура(редактируемая) для определённых операторов... (например) я набираю в текстовом редакторе FOR в 3третьем окне появляется список операторов встроенных в МП и возможно уже написанные пользователем процедуры называющиеся на FOR... - типа FOR FormAddChoice FormAddGauge FormAddImage и тд в 4ом окне появляется шаблон для оператора FOR // for Index := НачальноеЗначение to КонечноеЗначение do begin // Операторы; end; //EndFor я решаю выбрать оператор FOR нажимаю Ctrl+Space и в редактор переносится текст из шаблона - который я подредактирую.. 5 окно - 2 панели - 1 панель Хелп пооператорный(т.е. когда в редакторе курсор находится в слове имеющемся в словар(редактируемомо) - там высвечивается описание.. например: в редакторе курсор в слове DrawEllipse( в 5 окне 1ой панели procedure DrawEllipse(x, y, width, height: integer); Рисует эллипс, вписанный в указанный прямоугольник. Example: begin drawEllipse(0, 0, getWidth, getHeight); repaint; delay(1000); end. См. также: fillEllipse, getWidth, getHeight, setColor, repaint во второй панели ведётся лог комплилятора .... типа такое виденье... может кто сможет типа такое заделать? ну и конечно просьба дополнить.... PS - в панель ресурсов добавить возможность просмотра содержимого - картинок-воспроизведение муз файлов - вставить опцию "обработать рисунок утилитой" pngout.exe .... |
Ответ: создание MIDletPascal compiler'a
Будет компилятор - написать IDE не проблема.
|
Ответ: создание MIDletPascal compiler'a
эээээ... а существует ли какой уже готовый компилятор(типа Джавового ассемблера) - небольшой по размеру - типа жасмина или какого в ехе варианте...
тогда можно будет написать промежуточный транслятор Паскаля в JavaАссемблер - и на этот асм вызывать Сторонний компилятор (из батников) - хотябы на первое время.... --- по IDE это чисто идеи.. пожелания.. то - что было бы удобно пользователю... например чтоб неписать begin end; постоянно - в редакторе сделать подстановку на символ {+Ctrl+Space.... и чтоб люди идей сюда побольше отписали.... (например в 3-4 окно добавить 6ую анализ-панель - где былибы описаны Из текущего модуля все Uses Var integer string image command Procedure Function ну и тд - сразу визуально видишь что уже написано - тык мышкой и перешёл в редакторе на ту строчку.... удобно... :=) добавить операции сдвига для Integer.... сделать макроподстановки #define с текстом процедур на паскале добавить, вероятно - типа визуального редактора Форм и меню для распространённых типов экранов - чтоб он генерировал паскалькод... |
Ответ: создание MIDletPascal compiler'a
компилятор будет, если все понемножку приложим усилия, мне вот надоело все тянуть за уши, для общего дела старался, на чистом энтузиазме, а все наверное ждали готового результата. Вот satan'у спасибо, помог с отладкой/тестированием дизассемблера, а как дошло до компилятора - что-то не заладилось...
Думаю лучше вместо нашлепок на существующий MP делать другую, схожую но расширенную систему, тем более что обновлений не предвидется, а посему: MP обречен на вымирание, с его то ограничениями и ошибками. Все необходимые исходники уже имеются в этой теме... кто ещё будет участвовать в проекте? ____ вопрос про IDE на текущем этапе похож на деление неиспекшегося пирога, хотя могу сказать что где-то вроде были у меня исходники на delphi спец.редактора с подсветкой синтаксиса "notepad++" |
Ответ: создание MIDletPascal compiler'a
глянь исходники - я может попробую часть Редактора на Дельфях написать....
--- надо описать Структуру МПного языка - операторы-функции (хотябы начало) - сделать Основу транслятора - хотябы чтоб выводил Листинг на Jave... в общем я за проект.... что смогу то помогу :=) |
Ответ: создание MIDletPascal compiler'a
В общем-то, поучавствовать в проекте не откажусь, могу писать различные вспомогательные утилиты, заниматься IDE, но в компиляторах я ничерта не смыслю. А так - готов помочь.
|
Re: создание MIDletPascal compiler'a
Вложений: 1
Господа...
К чему эмоции??? Гы.... Вообщем увлекся я и написал компилятор для винды... О_о... Ну да ладно, меняем линкер и получаецо для явы... В архиве расплантованый по категориям проект(расписал все что нужно) Синтаксис Delphi+ BPascal типы пока 3 integer, char, boolean остальные вытекают из базовых поддерживаюца массивы (надо прикрутить открытые) поддерживаюцо переходы, упр конструкции и методы (в case надо добавить обработку [xx]..[xx]: Разбил на модули, что бы удобнее было работать группой, оно как ассемблер и т.д. мож хто и не знает, а структуры и форматы тож мож хто не знает... ЛОГИКА КОМПИЛЯТОРА -------------------------------------- 1. Входной файл загружается в переменную CurChar и с помощью СКАНЕРА посимвольно считывается 2. Сканер (Scaner.pas) проводит синтаксический анализ и возвращает ID текущего символа или строки в переменную CurTok 3. Парсер (Parser.pas) начинает лексический анализ используя функцию сканера GetToken для возвращения типа текущего оператора или команды и на основании этого генерирует объектный код который записывает в стек (разделен на без параметров, 1 параметр, 2 и 3) вида [ID команды]___[ID параметра[,параметров]] То есть по сути дела стек (Code[]) - это массив из значений комманд и параметров которые потом переведутся в асм код 3.1 Попутно парсер записывает в таблицу идентификаторов имена функций, процедур, констант и массивов, и т.д. 4. После работы парсера (если в коде не обнаружено ошибок) массив передается функции AssembleAndLink (CodeGen.pas) которая на основании стекового кода уже генерирует ассемблерный код 5. После работы Кодогенератора у нас получается массив объектного кода (без заголовков, секций и т.д.) по сути дела это и есть код ассемблерной секции, а в IdentTab - готовый код для КОНТЕНТНОГО ПУЛА 6. После этого код передается в линкеру(Linker.pas) функцией WriteOpCode (пока не прикрутил) и линкер должен сформировать пул и код Вообщем осталось всего чуть чуть, проработать Linker.pas Так же оставил место для ASM вставок вида asm ....... ....... end; и обработку его в модуле Assembl.pas (пока просто тупо пропускает как коментарии) В архиве пример для парсинга, попробуйте свои файлы (на выходе пока ничо не будет) просто в консоле должны появиться сообщения об ошибках если они есть так же прикрутил счотчик (для генерации ява кода дебаггера) Далее... IDE уже есть, исходники кому надо предоставим, компоненты к ней и контролы тоже, подсветка в ней уже есть, как и функции сворачивания кода, нумерация строк и т.д т.п. Кто хочет заняться милости просим... По адресу http://www.kirov.fm/pascal.zip прикрепил компилятор Java (Jikes) с библиотеками, примерами и параметрами коммандной строки.... УФ... |
Ответ: создание MIDletPascal compiler'a
А возможность вставки java-кода будет?
|
Ответ: создание MIDletPascal compiler'a
>>Далее... IDE уже есть, исходники кому надо предоставим...
а на каком языке исходники? если для дельфей, то выложи для "доработки"? >>>А возможность вставки java-кода будет? мгмгм... тут надо порешить... наверное вставки либо в JavaAsm либо в JavaCode - но с какими нибудь ограничениями (неопределять переменные или функции..... хз.... ЗЫ - перечитал ветку.... в итоге должен получится JaPscal для мобильного телефона? который будет делать типа: JaPscal --> JavaCode --> JavaAsm --> Class; Class + resurs --> Jar приложение; а также Jar приложение --> Class + resurs; --> JavaAsm --> JaPscal; (или JamPascal)... типо того??? всё в одно флаконе? :=) |
Ответ: создание MIDletPascal compiler'a
satan, а что не хочешь использовать уже готовый ассемблер? генерация кода компилятора Pascal сводится только к выдачи в текстовом виде константного пула и оформлении попрограмм, тем более, появляется возможность вручную проредить код будующей программы (ну и те-же самые ассемблерные вставки, но только на другом уровне)... а в монолитной версии компилятора в генерированный код уже не вмешаешься...
___ p.s. Serg153 ошибся редактор написан на VC++ 7 если интересно здесь глянь http://cbuilder.ru/index.php?topic=1771.0 |
Часовой пояс GMT +4, время: 17:11. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot