Статья посвящена системному программированию на русском языке с C-подобным синтаксисом. Компилятор для языков программирования РУСИ, РУСИ++ и объектный-РУСИ создан путём модификации и пересборки компилятора GCC 14й версии с превращением его в полноценный русско-английский билингвальный компилятор. Отдельно дана инструкция модификации русской раскладки клавиатуры для добавления в неё фигурных, угловых и квадратных скобок - дабы не переключаться и не терять поток.
Оглавление
Предыстория
В предыдущей статье был описан концепт билингвального самособирающегося компилятора языка Си, в котором кириллица уравнялась с оригинальным синтаксисом и можно писать на русском и английском Си одновременно. Код, напомню, выглядит так:
// Английский main с русским типом и оператором int main() { int x = 42; if (x == 42) { возврат 0; } return 1; } // Полностью русский синтаксис цел главн() { цел ъ = 42; если (ъ == 42) { возврат 0; } возврат 1; } // Смешанный стиль цел main() { printf("Легкоступов! Ты чего написал?"); возврат 0; }
Создан он был на базе chibicc для написания на нём кириллического ассемблера КВС https://xn–d1alm1bt.xn–p1ai/administrator/kvs. По сути, это был путь к своеобразной концептуальной полноте: кириллический ассемблер на кириллическом же Си. И для той задачи это было идеальным решением. Минималистичный русский компилятор под Linux. Ничего лишнего. Байты в бинарь складывать может. Задачу свою решает.
Но далее пошли предсказуемые комментарии со сравнениями с бухгалтерским программированием, предложением добавить падежи и пожеланиями не использовать это в продакшене. Обоснование последнего не осталось без внимания.
И действительно: во «взрослых» компиляторах есть ряд преимуществ как маркеров качества - множественное покрытие тестами и 40 лет ассемблерных оптимизаций. И как человек, пишущий свой ассемблер, я на это обратил внимание. Это тысячи человеко-лет работы, сотни оптимизационных проходов, отладка на миллионах строк кода.
Гипотетически: каким бы был полноценный продакшеновый русский Си?
Из спортивного интереса я решил попробовать. Смогу ли оседлать GCC и сделать его билингвом? Ранее мне поддались pascalABC.NET, Blaise и PHP. Вшивал я в них великий и могучий с целью поизучать на практике компиляторостроение. Отличный метод обучаться, кстати.
Получилось. Компилятор, в котором русские и английские ключевые слова - синонимы. Можно использовать любой язык или их гибрид. Реализовано так же, как в исходной статье. Даже тесты взял из русифицированного chibicc.
GCC сложнее, чем chibicc. Множество стандартов Си, поддерживаемых им, не могли не наложить свой отпечаток на его внутреннюю архитектуру.
Что получилось: RUSI на GCC 14.2.0. Русский Си, который компилируется в тот же самый машинный код, что и английский Си. С теми же оптимизациями. С той же производительностью.
Побочными продуктами получились РУСИ++ и объектный-РУСИ.
Зачем это всё
Эрик Рэймонд, «Собор и Базар» (1997), предисловие:
«Every good work of software starts by scratching a developer’s personal itch.»
Точный перевод: «Каждая хорошая программа начинается с того, что разработчик почесал свою личную нужду».
И где-то в России программист решил создать то, что считает нужным. И создаёт.
Линус Торвальдс, предисловие к книге Пекки Химанена «Хакерская этика и дух информационной эры» (2001):
«Linux был в значительной степени хобби (но серьёзным, лучшим из всех).»
Это не «продукт». Не «стартап». Не «проект для галочки». Хобби, но серьёзное. Работа, которая является игрой. Не потому, что «надо», а потому что интересно. Внутренний ребёнок радуется в процессе творчества.
Химанен в книге формулирует суть этики так:
«Хакер - это тот, кто решает проблему, а не тот, кто пользуется готовым решением. Если машина не делает то, что нужно, - хакер открывает её. Если система неудобна - хакер меняет её. Не потому, что заплатили, а потому что интересно. Не потому, что велели, а потому что сам захотел.»
И ведь можно открыть и переделать всё. Компилятор, раскладку, стандарт, технологию, чьё-то мнение.
RUSI - ровно это. Личное творчество. Захотел - переделал. Сделал. Сам захотел - и получилось.
Частично взгляды описаны в предыдущей статье Программисты на Руси программируют на Си. RUSI: Концепт билингвального компилятора.
В конце статьи есть список промптов для анализа текста статьи через призму различных подходов и взглядов.
Где взять и что внутри
Репозиторий: https://github.com/artradeskz/rgcc
Что внутри: GCC 14.2.0 с патчами для русского синтаксиса. Полный diff огромен - здесь не привожу. Но он есть в конце статьи под спойлером.
Краткая выжимка: что именно изменено и зачем.
1. UTF-8 в лексере (libcpp/lex.cc)
Традиционно работая с исходниками, GCC читает не по буквам, а по байтам. Так сложилось исторически. В интернете можно встретить утверждение, что GCC умеет работать с идентификаторами на UTF-8. Про то, что он может так же работать со служебными словами, там не будет сказано. Одна английская буква - один байт. Кириллица же в UTF-8 - это 2 байта на букву. И прежние алгоритмы чтения уже не сработают. Для русификации добавлена обработка UTF-8-последовательностей в forms_identifier_p, чтобы лексер парсил посимвольно, а не побайтово.
if (*buffer->cur == 0xD0 || *buffer->cur == 0xD1) { unsigned char first = *buffer->cur; unsigned char second = *(buffer->cur + 1); if (first == 0xD0 && second >= 0x90 && second <= 0xBF) { buffer->cur += 2; return true; } if (first == 0xD1 && second >= 0x80 && second <= 0x8F) { buffer->cur += 2; return true; } }
2. Синонимы ключевых слов (gcc/c-family/c-common.cc)
Добавлено ~250 русских синонимов в таблицу c_common_reswords[]:
{ "int", RID_INT, 0 }, { "цел", RID_INT_RU, 0 }, { "if", RID_IF, 0 }, { "если", RID_IF, 0 }, { "return", RID_RETURN, 0 }, { "возврат", RID_RETURN, 0 }, { "char", RID_CHAR, 0 }, { "символ", RID_CHAR, 0 },
3. Русские встроенные макросы (libcpp/init.cc)
B("__ФАЙЛ__", BT_FILE, false), B("__ЛИНИЯ__", BT_SPECLINE, true), B("__ДАТА__", BT_DATE, false), B("__СЧЁТЧИК__", BT_COUNTER, true), B("__ВРЕМЯ_ФАЙЛА__", BT_TIMESTAMP, false),
4. Русские директивы препроцессора (libcpp/directives.cc и libcpp/expr.cc)
Директивы препроцессора - это команды, которые начинаются с #. Они не являются частью языка C в том смысле, что парсер их не видит. Их обрабатывает libcpp до того, как парсер получит лексемы. Именно поэтому удалось добавить русские директивы без изменения парсера: достаточно было добавить синонимы в таблицу директив.
В libcpp/directives.cc есть таблица dtable[] - список всех директив. Туда добавлены русские аналоги:
{ do_define, UC"определить", sizeof "определить" - 1, KANDR, IN_I }, { do_include, UC"включить", sizeof "включить" - 1, KANDR, INCL | EXPAND }, { do_if, UC"если", sizeof "если" - 1, KANDR, COND | IF_COND | EXPAND }, { do_endif, UC"конецесли", sizeof "конецесли" - 1, KANDR, COND },
Теперь #включить <stdio.h> работает так же, как #include <stdio.h>. #определить - как #define. #если - как #if. И так далее.
Теперь можно писать:
#если определено(ОТЛАДКА) printf("Отладка включена\n"); #конецесли
Это полный русский аналог английского:
#if defined(DEBUG) printf("Отладка включена\n"); #endif
Немного хулиганства
Чтоб не перепутать стандартный и патченный компиляторы, было бы неплохо иметь возможность различать русифицированный GCC и обычный. Для этого можно доработать вывод команды с информацией о версии компилятора.
Где пропатчить команду gcc --version:
Файл: gcc/gcc.cc, 8900-я строка.
Там зашиты строка копирайта и текст про гарантию. Их можно заменить на свой текст.
if (print_version) { printf (_("%s %s%s\n"), progname, pkgversion_string, version_string); printf ("Copyright %s 2026 Coded by @artrades.\n", _("(C)")); fputs (_("Использовать можно и нужно. Но никто ни за что ответственность не несет(очевидно). This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), stdout); if (! verbose_flag) return 0;
После сборки:
$ gcc --version gcc (GCC) 14.2.0 Copyright (C) 2026 Coded by @artrades. Использовать можно и нужно. Но никто ни за что ответственность не несет(очевидно). This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
В репозитории в данный участок кода - оригинальный. Текст можно менять на свое усмотрение.
Теория: почему русский синтаксис работает
Компилятор - это цепочка преобразований
Компилятор - это сложный многоэтапный механизм превращения слов в исполняемый файл. Это конвейер преобразователей, где каждый этап - это обособленная знаково-логическая система, словно свой отдельный язык программирования.
Упрощённая схема для любого компилятора высокого уровня:
Исходник → лексемы → AST → ассемблер → лексемы → AST → исполняемый файл
Между каждым этапом работает преобразователь со своей логикой.
Что такое «знаково-логическая система»
На каждом этапе есть:
Алфавит - набор допустимых символов
Правила - как из символов строить конструкции
Семантика - что эти конструкции означают
Примеры:
Этап | Алфавит | Что описывает |
|---|---|---|
Исходник | ASCII + UTF-8 | текст программы |
Лексемы | TK_INT, TK_IF, TK_RETURN | ключевые слова, операторы, идентификаторы |
AST | VarDecl, IfStmt, ReturnStmt | структура программы |
Ассемблер | mov, add, call | инструкции процессора |
Лексемы | MOV, ADD, CALL, REG_EAX, IMM, MEM | мнемоники, регистры, непосредственные значения, адреса памяти |
AST | Instruction(mov, src=REG, dst=REG), Label, Directive(.text) | инструкции, метки, директивы |
Бинарь | байты | готовая программа |
Что изменено
Только первые два преобразования:
Исходник → лексемы (лексер
libcpp)Лексемы → AST (парсер
c-parser.cc)
На этапе первого AST компилятору уже безразлично, как выглядели слова на человеческом языке.
Вот два исходника:
int x = 42;
цел x = 42;
После преобразований оба превращаются в один и тот же узел AST:
VarDecl(name="x", type=Int, init=42)
Дальше компилятор работает только с абстрактным синтаксическим деревом: оптимизирует его, преобразует в ассемблер, в объектный код. Информация о том, что ты написал int или цел, была актуальна лишь на этапе парсера.
Почему производительность идентична
Именно потому, что после AST всё одинаково:
int x = 42; ─┐ ├─ AST - ассемблер - объектный код - линкер - бинарь цел x = 42; ─┘
Русский и английский исходники дают идентичный AST, значит, идентичный ассемблер, идентичный объектный код, идентичный бинарь.
Это подтверждено экспериментально: секция .text (исполняемый код) русского и английского исходников побайтово идентична.
Ключевой вывод
RUSI - это не «новый язык». Это билингвальный фасад к существующему языку C.
GCC научили понимать русские слова на входе, на этапе лексера и парсера. Всё остальное - стандартный GCC 14.2.
Русский синтаксис не добавляет ни одной инструкции в машинный код. Потому что после парсера разницы между русским и английским C не существует, есть только AST.
Сборка: от исходников до установки
Проверено на Ubuntu 26 с установленным в систему GCC 12 или с GCC 15.
Качаем:
git clone --depth 1 https://github.com/artradeskz/rgcc.git
Зависимости:
sudo apt install flex bison libgmp-dev libmpfr-dev libmpc-dev
Или, если не хочется ставить dev-пакеты, используется встроенный скрипт:
cd rgcc ./contrib/download_prerequisites
Он скачает GMP, MPFR, MPC, ISL в дерево исходников:
2026-10-03 18:13:45 URL:https://gcc.gnu.org/pub/gcc/infrastructure/gettext-0.22.tar.gz [26105696/26105696] -> "gettext-0.22.tar.gz" [1] 2026-10-03 18:13:47 URL:http://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.2.1.tar.bz2 [2493916/2493916] -> "gmp-6.2.1.tar.bz2" [1] 2026-10-03 18:13:49 URL:http://gcc.gnu.org/pub/gcc/infrastructure/mpfr-4.1.0.tar.bz2 [1747243/1747243] -> "mpfr-4.1.0.tar.bz2" [1] 2026-10-03 18:13:50 URL:http://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.2.1.tar.gz [838731/838731] -> "mpc-1.2.1.tar.gz" [1] 2026-10-03 18:13:52 URL:http://gcc.gnu.org/pub/gcc/infrastructure/isl-0.24.tar.bz2 [2261594/2261594] -> "isl-0.24.tar.bz2" [1] gettext-0.22.tar.gz: OK gmp-6.2.1.tar.bz2: OK mpfr-4.1.0.tar.bz2: OK mpc-1.2.1.tar.gz: OK isl-0.24.tar.bz2: OK All prerequisites downloaded successfully.
Конфигурация:
mkdir build && cd build ../configure \ --enable-languages=c,c++ \ --disable-multilib \ --disable-nls \ --disable-libgomp \ --disable-libquadmath \ --disable-libssp \ --disable-libvtv \ --disable-libcc1 \ --disable-libmpx \ --disable-libcilkrts \ --disable-libsanitizer \ --disable-isl \ --disable-bootstrap \ --disable-graphite \ --prefix=/usr/local/gcc-rus
Пояснения:
--enable-languages=c,c++- собираем только C и C++--disable-isl- отключает ISL и Graphite--disable-bootstrap- отключен автоматический самосбор(об этом ниже)--prefix=/usr/local/gcc-rus- изолированная установка
Сборка (2 потока, можно и быстрее):
make -j2 2>&1 | tee build.log
На Aspire 5742G - около часа. На современной машине - 15–20 минут.
Установка:
sudo make install
Проверка:
/usr/local/gcc-rus/bin/gcc --version
Добавление в PATH:
echo 'export PATH=/usr/local/gcc-rus/bin:$PATH' >> ~/.bashrc source ~/.bashrc
Тесты из chibicc-rusi
Методика
Взяты тесты из chibicc-RUSI без изменений. Прогнаны на RUSI-GCC.
cd тесты python3 run_tests.py \ --compiler ~/Документы/RUSI++/rgcc/build-full/gcc/xgcc \ --build-dir ~/Документы/RUSI++/rgcc/build-full/gcc \ --dir test_ru \ --verbose
Результат: 63 из 65 (96.9%).
Полный вывод тестов
📌 Результат прогона тестов
============================================================ ЗАПУСК РУССКИХ ТЕСТОВ ДЛЯ RUSI ============================================================ Найдено тестов: 65 Компилятор: /home/me/Документы/RUSI++/rgcc/build-full/gcc/xgcc Папка сборки (-B): /home/me/Документы/RUSI++/rgcc/build-full/gcc Папка тестов: test_ru [1/65] #else ✓ ОК (код 0) [2/65] alignas ✓ ОК (код 0) [3/65] alignof ✓ ОК (код 0) [4/65] asm ✓ ОК (код 0) [5/65] asm2 ✓ ОК (код 0) [6/65] atomic ✓ ОК (код 0) [7/65] auto ✓ ОК (код 0) [8/65] bool ✓ ОК (код 0) [9/65] break ✓ ОК (код 0) [10/65] case ✓ ОК (код 0) [11/65] char ✓ ОК (код 65) [12/65] const ✓ ОК (код 0) [13/65] continue ✓ ОК (код 0) [14/65] counter_ru ✓ ОК (код 0) [15/65] cyrillic_ident ✓ ОК (код 0) [16/65] cyrillic_ptr ✓ ОК (код 0) [17/65] date_ru ✓ ОК (код 0) [18/65] default ✓ ОК (код 0) [19/65] define ✓ ОК (код 0) [20/65] defined ✓ ОК (код 0) [21/65] do ✓ ОК (код 0) [22/65] double ✓ ОК (код 2) [23/65] elif ✓ ОК (код 0) [24/65] else ✓ ОК (код 0) [25/65] endif ✓ ОК (код 0) [26/65] enum ✓ ОК (код 0) [27/65] extern ✓ ОК (код 0) [28/65] file_ru ✓ ОК (код 0) [29/65] float ✓ ОК (код 3) [30/65] for ✓ ОК (код 0) [31/65] func_ru ✓ ОК (код 0) [32/65] function_ru ✓ ОК (код 0) [33/65] generic ✓ ОК (код 0) [34/65] goto ✓ ОК (код 0) [35/65] if ✓ ОК (код 0) [36/65] ifdef ✓ ОК (код 0) [37/65] ifndef ✓ ОК (код 0) [38/65] include ✓ ОК (код 0) [39/65] inline ОШИБКА КОМПИЛЯЦИИ /usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccvZ6sZh.o: в функции «main»: /home/me/Документы/RUSI++/rgcc/тесты/test_ru/inline.c:7:(.text+0xe): undefined reference to `квадрат' collect2: error: ld returned 1 exit status [40/65] int ✓ ОК (код 0) [41/65] line ✓ ОК (код 0) [42/65] line_ru ✓ ОК (код 0) [43/65] long ✓ ОК (код 0) [44/65] main ✓ ОК (код 0) [45/65] noreturn ✗ ОШИБКА ожидался 0, получен -11 [46/65] once ✓ ОК (код 0) [47/65] register ✓ ОК (код 0) [48/65] restrict ✓ ОК (код 0) [49/65] return ✓ ОК (код 0) [50/65] short ✓ ОК (код 123) [51/65] signed ✓ ОК (код 0) [52/65] sizeof ✓ ОК (код 0) [53/65] static ✓ ОК (код 0) [54/65] struct ✓ ОК (код 0) [55/65] switch ✓ ОК (код 0) [56/65] test_import ✓ ОК (код 0) [57/65] thread_local ✓ ОК (код 0) [58/65] time_ru ✓ ОК (код 0) [59/65] typedef ✓ ОК (код 0) [60/65] typeof ✓ ОК (код 0) [61/65] undef ✓ ОК (код 0) [62/65] union ✓ ОК (код 0) [63/65] unsigned ✓ ОК (код 0) [64/65] volatile ✓ ОК (код 0) [65/65] while ✓ ОК (код 0) ============================================================ РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ ============================================================ Итого: Пройдено: 63 Провалено: 2 Ошибок компиляции: 1 Всего: 65 Успешность: 96.9%
Два «провала» и почему это не баг GCC
inline.c:
// inline.c - Проверка ключевого слова inline инлайн цел квадрат(цел х) { возврат х * х; } цел главн(){ цел рез = квадрат(5); если (рез == 25) { возврат 0; } возврат 1; }
Ошибка линковки: undefined reference to 'квадрат'.
Причина: в C99 inline без static/extern - это внутренняя функция, которая может не создаваться как внешняя. chibicc игнорирует inline и создаёт функцию. GCC следует стандарту и не создаёт. GCC прав.
noreturn.c:
// noreturn.c - Проверка _Безвозврат _Безвозврат пусто завершение() { // Функция помечена как _Безвозврат, но на самом деле возвращается возврат; } цел главн(){ завершение(); возврат 0; }
Падение с SIGSEGV (-11).
Причина: _Noreturn - это обещание компилятору, что функция не вернётся. Если она возвращается, это неопределённое поведение (согласно C11 §6.7.4). chibicc игнорирует _Noreturn. GCC применяет его для оптимизации (выбрасывает недостижимый код). Программа падает. GCC прав.
Вывод
Два «провала» - это не баги GCC, а разница семантики между chibicc и GCC. chibicc не проверяет типы и игнорирует атрибуты. GCC следует стандарту C. RUSI-GCC работает корректнее, чем chibicc-RUSI.
Самосбор
Лучшим способом проверить, что оригинальный Си и Си++ не отвалились, будет сбор GCC самим же собой. После установки в систему это делается аналогичной командой с аналогичной же конфигурацией(см.выше). Затем можно прогнать тесты. Для уверенности можно собрать еще раз.
В отличие от компилятора chibbic, GCC я не стал переписывать на русифицированном Си. Это огромный объем кодовой базы. Однако испытать РУСИ путем вкрапления в исходный код компилятора сам факт выполняемой задачи обязывает. Нужный компилятор в системе есть - можно приступать. Для испытания я выбрал файл gcc/c-family/c-common.cc (таблица ключевых слов).
Две директивы в начале.
#определить GCC_C_COMMON_C #включить "config.h" #include "system.h"
И функцию c_addr_space_name().
/* Return identifier for address space AS. */ конст char * c_addr_space_name (addr_space_t as) { цел rid = RID_FIRST_ADDR_SPACE + as; gcc_assert (ridpointers [rid]); возврат IDENTIFIER_POINTER (ridpointers [rid]); }
С такими изменениями собирать это стандартным компилятором уже не получится!
После сборки можно снова прогнать тесты. И для верности собрать и протестировать еще раз.
При желании можно русифицировать весь код компилятора таким образом, но с практической точки зрения лучше всего начинать переводить стандартные библиотеки: ввод-вывод, работа со строками, математический модуль.
В статье приведена команда для сборки с отключенным бутстрапом. Каждый этап запускается вручную приведенный выше командой. Это сделано чтоб не сломать сборку внутренними тестами, не рассчитанными на задвоенные ключевые слова(-fself-test не даст запустить Stage 2 и Stage 3).
Сравнительные сборки
«Привет, мир»
Исходник у нас будет один, но соберём мы его двумя компиляторами. Содержимое файла:
#включить <stdio.h> цел главн(пусто) { printf("Привет, мир!\n"); возврат 0; }
Обратите внимание: здесь смешанный синтаксис. Директива #включить - русская. Тип цел - русский. Ключевое слово возврат - русское. А printf и stdio.h - латиница, потому что это имена из стандартной библиотеки, их мы не переводим.
Сохраним файл в двух вариантах: привет.си для chibicc (он понимает расширение .си) и привет.c для GCC (он понимает .c). Содержимое одинаковое.
Собираем через chibicc-RUSI:
./rusi.elf -o привет_chibicc привет.си
Собираем через GCC-RUSI (с оптимизацией -O2):
/usr/local/gcc-rus-full/bin/gcc -O2 привет.c -o привет_gcc
Сравнение размеров:
$ stat -c '%n %s байт' привет_chibicc привет_gcc привет_chibicc 17640 байт привет_gcc 15688 байт
$ size привет_chibicc привет_gcc text data bss dec hex filename 1623 933 3 2559 9ff привет_chibicc 949 544 8 1501 5dd привет_gcc
Сведём в таблицу:
Метрика | chibicc | GCC -O2 | Разница |
|---|---|---|---|
Размер файла | 17 640 байт | 15 688 байт | −11% |
.text (код) | 1 623 байт | 949 байт | −42% |
.data | 933 байта | 544 байта | −42% |
.bss | 3 байта | 8 байт | +5 байт |
Итог (dec) | 2 559 | 1 501 | −41% |
Файл от GCC на 11% меньше. Но самое интересное - секция .text: код от GCC почти в 2 раза компактнее. .bss чуть больше у GCC, но это 8 байт против 3 - несущественно.
Проверим, что оба работают:
$ ./привет_chibicc Привет, мир! $ ./привет_gcc Привет, мир!
Ответ одинаковый. Теперь посмотрим, почему код от GCC компактнее.
Дизассемблер chibicc-RUSI
0000000000401106 <главн>: 401106: 55 push %rbp 401107: 48 89 e5 mov %rsp,%rbp 40110a: 48 83 ec 10 sub $0x10,%rsp 40110e: 48 89 65 f8 mov %rsp,-0x8(%rbp) 401112: 48 8d 05 f7 2e 00 00 lea 0x2ef7(%rip),%rax 401119: 50 push %rax 40111a: 48 8b 05 b7 2e 00 00 mov 0x2eb7(%rip),%rax 401121: 5f pop %rdi 401122: 49 89 c2 mov %rax,%r10 401125: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40112c: 41 ff d2 call *%r10 40112f: 48 83 c4 00 add $0x0,%rsp 401133: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40113a: eb 07 jmp 401143 <главн+0x3d> 40113c: 48 c7 c0 00 00 00 00 mov $0x0,%rax 401143: 48 89 ec mov %rbp,%rsp 401146: 5d pop %rbp 401147: c3 ret
Дизассемблер GCC-RUSI
0000000000401040 <main>: 401040: 48 83 ec 08 sub $0x8,%rsp 401044: bf 04 20 40 00 mov $0x402004,%edi 401049: e8 e2 ff ff ff call 401030 <puts@plt> 40104e: 31 c0 xor %eax,%eax 401050: 48 83 c4 08 add $0x8,%rsp 401054: c3 ret
Что видно
Разница драматическая. Пройдёмся по пунктам.
1. Передача аргумента.
chibicc:
lea 0x2ef7(%rip),%rax push %rax ... pop %rdi
Адрес строки сначала кладётся в rax, потом пушится в стек, потом вытаскивается в rdi. Три инструкции вместо одной.
GCC:
mov $0x402004,%edi
Адрес строки сразу попадает в edi (младшие 32 бита rdi). Одна инструкция.
2. Вызов функции.
chibicc:
mov 0x2eb7(%rip),%rax mov %rax,%r10 mov $0x0,%rax call *%r10
Адрес printf загружается из GOT в регистр, потом перекладывается в r10, потом вызов через указатель. Ещё и rax обнуляется (для variadic-функций).
GCC:
call 401030 <puts@plt>
Прямой вызов puts через PLT. Одна инструкция.
3. printf против puts.
GCC заменил printf("Привет, мир!\n") на puts("Привет, мир!"). Это классическая оптимизация: если строка заканчивается на \n и нет форматирования, puts работает быстрее. chibicc не делает этого - вызывает printf напрямую.
4. Возврат значения.
chibicc:
mov $0x0,%rax jmp 401143 ... mov $0x0,%rax
Два mov $0x0,%rax и лишний jmp.
GCC:
xor %eax,%eax
Одна инструкция. xor регистра с самим собой - идиоматический способ обнуления, работает быстрее, чем mov.
5. Frame pointer.
chibicc:
push %rbp mov %rsp,%rbp ... pop %rbp
Сохраняет frame pointer, потому что chibicc не оптимизирует. GCC в -O2 выбрасывает его: sub $0x8,%rsp вместо push %rbp; mov %rsp,%rbp. Меньше инструкций, меньше стекового фрейма.
6. Лишние инструкции.
chibicc:
sub $0x10,%rsp mov %rsp,-0x8(%rbp) ... add $0x0,%rsp
Выделяет 16 байт стека, сохраняет указатель стека в память (зачем?), потом прибавляет 0 к rsp. Безсмысленные операции.
GCC:
sub $0x8,%rsp ... add $0x8,%rsp
Выделяет ровно столько, сколько нужно для выравнивания стека. Никаких лишних операций.
Итог
Что | chibicc | GCC |
|---|---|---|
Передача аргумента | через стек (push/pop) | прямо в регистр (mov … %edi) |
Вызов функции | через указатель (call *%r10) | напрямую (call puts@plt) |
printf vs puts | printf | puts (оптимизация) |
return 0 | mov $0x0,%rax + jmp | xor %eax,%eax |
Frame pointer | есть (push %rbp) | нет |
Лишние инструкции | add $0x0,%rsp, mov %rsp,-0x8(%rbp) | нет |
Размер кода | ~66 байт | ~21 байт |
Именно поэтому секция .text от GCC в 1.7 раза меньше. chibicc генерирует наивный код: каждая операция через стек, вызов через указатель, лишние jmp и mov. GCC оптимизирует: аргументы в регистрах, прямой вызов, puts вместо printf.
И самое главное: это тот же самый исходник. Один и тот же русский C. Разница только в компиляторе. В конце статьи под спойлером полные дизассемблерные тексты.
Простые числа до 100 000
Исходник (prost.c):
#включить <stdio.h> цел простые(цел н) { цел счёт = 0; для (цел и = 2; и <= н; и++) { цел флаг = 1; для (цел й = 2; й * й <= и; й++) { если (и % й == 0) { флаг = 0; прерви; } } если (флаг) счёт++; } возврат счёт; } цел главн(пусто) { printf("Простых до 100000: %d\n", простые(100000)); возврат 0; }
Тот же алгоритм на английском C для проверки, что ответ идентичен:
#include <stdio.h> int simple(int n) { int count = 0; for (int i = 2; i <= n; i++) { int flag = 1; for (int j = 2; j * j <= i; j++) { if (i % j == 0) { flag = 0; break; } } if (flag) count++; } return count; } int main(void) { printf("Простых до 100000: %d\n", simple(100000)); return 0; }
Собираем тремя способами:
./rusi.elf -o prost_chibicc prost.c /usr/local/gcc-rus-full/bin/gcc -O0 prost.c -o prost_gcc_O0 /usr/local/gcc-rus-full/bin/gcc -O2 prost.c -o prost_gcc_O2
Запускаем и проверяем, что ответ одинаковый:
$ ./prost_chibicc Простых до 100000: 9592 $ ./prost_gcc_O0 Простых до 100000: 9592 $ ./prost_gcc_O2 Простых до 100000: 9592
Все три дают одинаковый ответ.
Сравнение размеров:
$ stat -c '%n %s байт' prost_chibicc prost_gcc_O0 prost_gcc_O2 prost_chibicc 17872 байт prost_gcc_O0 15728 байт prost_gcc_O2 15728 байт
$ size prost_chibicc prost_gcc_O0 prost_gcc_O2 text data bss dec hex filename 2139 997 3 3139 c43 prost_chibicc 1125 544 8 1677 68d prost_gcc_O0 1106 544 8 1658 67a prost_gcc_O2
Замер скорости:
$ time ./prost_chibicc === chibicc === Простых до 100000: 9592 real 0m0,039s user 0m0,038s sys 0m0,002s $ time ./prost_gcc_O0 === gcc -O0 === Простых до 100000: 9592 real 0m0,016s user 0m0,012s sys 0m0,002s $ time ./prost_gcc_O2 === gcc -O2 === Простых до 100000: 9592 real 0m0,015s user 0m0,011s sys 0m0,004s
Итоговая таблица:
Метрика | chibicc | gcc -O0 | gcc -O2 | Разница (chibicc → gcc -O2) |
|---|---|---|---|---|
Размер файла | 17 872 байт | 15 728 байт | 15 728 байт | −12% |
.text (код) | 2 139 байт | 1 125 байт | 1 106 байт | −48% (почти в 2 раза!) |
.data | 997 байт | 544 байта | 544 байта | −45% |
Итог (dec) | 3 139 | 1 677 | 1 658 | −47% |
Время (real) | 0,039 с | 0,016 с | 0,015 с | −62% (в 2,6 раза!) |
Время (user) | 0,038 с | 0,012 с | 0,011 с | −71% (в 3,5 раза!) |
Ответ | 9592 | 9592 | 9592 | одинаковый |
Почему так
GCC:
Держит переменные в регистрах, а не в стеке
Оптимизирует условие
й * й <= иРазматывает циклы
Инлайнит мелкие функции
Заменяет
printfнаputs, где возможно
chibicc:
Каждая операция через стек
Нет оптимизаций
Наивный код
Ассемблерные оптимизации работают.
РУСИ++: побочный продукт
Если перебирать компилятор, который парсит не только Си, а еще и Си++, то есть смысл сделать билингвальный построитель AST полностью. Были добавлены синонимы для всех слов.
Что это
RUSI++ - это C++ с русским синтаксисом. Работают:
Классы (
класс)Конструкторы
private/public(без перевода, оставлено как есть)Шаблоны (
шаблон<имя_типа T>)Наследование
Виртуальные функции
Пример
#включить <iostream> #включить <string> класс Приветствие { закрыт: std::string имя; открыт: Приветствие(конст std::string& н) : имя(н) {} пусто поздороваться() конст { std::cout << "Привет, " << имя << "!" << std::endl; } }; цел главн() { Приветствие п("мир"); п.поздороваться(); возврат 0; }
Сравнение с английским C++
#include <iostream> #include <string> class Greeting { private: std::string name; public: Greeting(const std::string& n) : name(n) {} void greet() const { std::cout << "Привет, " << name << "!" << std::endl; } }; int main() { Greeting g("мир"); g.greet(); return 0; }
Собран тот же код на английском C++ через тот же RUSI++:
/usr/local/gcc-rus-full/bin/g++ -O2 привет_класс.cpp -o привет_класс /usr/local/gcc-rus-full/bin/g++ -O2 privet_class_en.cpp -o privet_class_en
Проверка запуска:
$ ./привет_класс Привет, мир! $ ./privet_class_en Привет, мир!
Сравнение размеров:
$ stat -c '%n %s байт' привет_класс privet_class_en привет_класс 16672 байт privet_class_en 16664 байт
$ size привет_класс privet_class_en text data bss dec hex filename 2690 656 280 3626 e2a привет_класс 2690 656 280 3626 e2a privet_class_en
Сравнение кода:
$ objcopy -O binary --only-section=.text привет_класс /tmp/ru.bin $ objcopy -O binary --only-section=.text privet_class_en /tmp/en.bin $ cmp /tmp/ru.bin /tmp/en.bin && echo "✅ КОД ИДЕНТИЧЕН" || echo "❌ РАЗЛИЧАЕТСЯ" ✅ КОД ИДЕНТИЧЕН
Таблица:
Метрика | привет_класс (рус) | privet_class_en (англ) | Разница |
|---|---|---|---|
Размер файла | 16 672 байт | 16 664 байта | 8 байт (0,05%) |
.text (код) | 2 690 байт | 2 690 байт | 0 |
.data | 656 байт | 656 байт | 0 |
.bss | 280 байт | 280 байт | 0 |
Машинный код | идентичен | идентичен | 0 |
Разница в 8 байт - это имена функций и классов в таблице символов (главн() vs main(), Приветствие vs Greeting). Сам код один и тот же.
Вывод
RUSI++ - это не переопределение слов через дефайны. Это полноценный C++ с русским синтаксисом. Классы, шаблоны, ООП - всё работает и компилируется в тот же машинный код, что и английский C++. Это побочный продукт работы над РУСИ: раз GCC поддерживает C++, а фронтенд русифицирован, C++ тоже стал русским.
Итог: форк chibicc породил три более совершенных языка
Что было: RUSI на chibicc - учебный компилятор для русского C.
Что стало:
Компилятор | База | Что умеет |
|---|---|---|
РУСИ (GCC) | GCC 14.2 | Русский C, оптимизации, все архитектуры |
РУСИ++ | GCC 14.2 | Русский C++, классы, шаблоны, ООП |
Объектный-РУСИ | GCC 14.2 | Русский Objective-C (не тестировался) |
Ключевое: все три - не «перевод ключевых слов», а полноценные фронтенды GCC с русским синтаксисом. После парсера AST идентичен английскому, дальше работает стандартный бэкенд GCC.
Перспективы применения
Куда можно применить технологию, с помощью которой создано почти всё? Преимуществом тут будет факт того, что Си все знают. Никого переучивать не нужно. Билингвальность же даёт обратную совместимость: всё, что написано ранее, можно без проблем применять. Да и переписывание такого компилятора на кириллическом Си - способ быстро прокачать инженерную школу.
Операционные системы
Linux - можно писать модули ядра
Windows - MinGW / Cygwin
macOS - через кросс-компиляцию
FreeBSD - нативная поддержка
Экзотические системы - всё, что поддерживает GCC
Встроенные системы
Прошивки для микроконтроллеров
Контроллеры (ARM Cortex-M, RISC-V)
Arduino (AVR)
Bare-metal
Процессоры
x86, x86-64
ARM, ARM64
RISC-V
MIPS
PowerPC
AVR
Всё, что поддерживает GCC
Отрасли
Приборостроение - уникальные приборы, измерительная техника
Робототехника - управление роботами
Системы связи - телекоммуникационное оборудование
Транспорт - встроенные системы автомобилей, поездов, самолётов
Образование
КуМир - школьный язык для обучения. RUSI может заменить его профессиональным инструментом с тем же русским синтаксисом, но с реальными возможностями GCC.
Экспорт в страны с кириллическим алфавитом
Болгария, Монголия, Сербия, Северная Македония, Казахстан, Кыргызстан - страны, где кириллица является официальной или широко используемой письменностью.
Создание отечественного стандарта ЯП Си
РУСИ может стать основой для отечественного стандарта языка системного программирования. Не «новый язык с нуля», а билингвальный стандарт:
Полная совместимость с международным стандартом C (ISO/IEC 9899)
Кириллический синтаксис как равноправный с латинским
Промышленная база GCC 14.2, а не учебный компилятор
Такой стандарт может быть принят для использования в … - везде, где требуется русскоязычная документация и код.
Появление нового стандарта раскладки.
Новая ru-раскладка с фигурными, квадратными и угловыми скобками однозначно продвинет применение русского языка в различных технологиях.
СПбГУ. RuC. Интерпретатор Терехова
До появления проекта RUSI в СПбГУ зародился свой Си с русскими словами - RuC. Виртуальная машина. Не сборщик в бинарь.
RuC - компилятор русского C в байт-код виртуальной машины. Автор - Андрей Терехов (СПбГУ). Проект остановился в 2023 году.
Почему остановился? Академический проект. Всё держалось на профессоре.
Названия похожи. Наверняка найдутся желающие столкнуть проекты по части именования. Оба могут сосуществовать со своими именами как Java и JavaScript.
Но есть идея даже концептуально развить RuC Терехова. И тут скорее win/win получится.
RuC написан на C++. RUSI++ - это C++ с русским синтаксисом. Значит:
Берём исходники RuC
Заменяем ключевые слова на русские (
class→класс,int→цел,return→возврат)Собираем через РУСИ++
Получаем тот же самый RuC, но с исходниками на русском
И возможно, в процессе появятся идеи развития проекта.
Заключение
Что сделано:
GCC 14.2.0 русифицирован
Тесты chibicc-RUSI проходят на 96.9% (два «провала» - баги chibicc, не RUSI)
RUSI-GCC быстрее и компактнее chibicc-RUSI в 2–3.5 раза
RUSI++ работает: классы, шаблоны, ООП
Что дальше:
Кросс-компиляция под ARM, RISC-V
Bare-metal поддержка (newlib, linker scripts)
Русификация стандартной библиотеки
Написание документации
Если кто размышлял о создании кириллического системного ЯП, то вот он - готовый, рабочий, всамделишный. Бонусом - инструкция по настройке раскладки, чтоб не переключать язык для скобок.
Ссылки
Программисты на Руси программируют на Си. RUSI: Концепт билингвального компилятора
Сфера - полностью кириллический язык программирования: от «Привет, мир» до HTTP-сервера и bare-metal
Бонус: фигурные скобки в русской раскладке
Проблема
Стандартная русская раскладка в Ubuntu 26 не имеет {, }, [, ], <, >. Клавиши, где они лежат в английской (Shift + [, Shift + ], Shift + ,, Shift + .), в русской заняты буквами х, ъ, б, ю.
Без фигурных скобок в C не написать ни функцию, ни блок, ни структуру. Без квадратных - не объявить массив или не обратиться к элементу. Без угловых - не подключить заголовок или не использовать шаблон. Переключать раскладку каждый раз - убивать поток.
Решение: задействуем правый Alt (AltGr). Он даёт третий уровень клавиатуры, специально созданный для ввода дополнительных символов. Он не конфликтует с Ctrl+X, Ctrl+C и другими системными сокращениями.
Что получится:
AltGr + х → { AltGr + ъ → } AltGr + щ → [ AltGr + з → ] AltGr + б → < AltGr + ю → > Левый Alt, оба Ctrl, Shift → работают как обычно
Почему именно щ и з для квадратных скобок: это самый простой способ. Можно, конечно, заморочиться и на правый Ctrl сделать комбинацию с кнопками «х» и «ъ» - путь сложный. Зато теперь конструкция вида если (щ[ы] < щ[ю]) { } не представляет никаких сложностей.
Патчим раскладку
Шаг 1. Резервная копия
sudo cp /usr/share/X11/xkb/symbols/ru /usr/share/X11/xkb/symbols/ru.orig
Шаг 2. Открыть файл раскладки
sudo nano /usr/share/X11/xkb/symbols/ru
Шаг 3. Найти блок winkeys
В самом начале файла:
// Windows layout default partial alphanumeric_keys xkb_symbols "winkeys" { include "ru(common)" name[Group1]= "Russian"; key <AE03> {[ 3, numerosign ]}; key <AE04> {[ 4, semicolon ]}; ... key <AB10> {[ period, comma ]}; key <BKSL> {[ backslash, slash ]}; };
Шаг 4. Заменить блок winkeys целиком
// Windows layout default partial alphanumeric_keys xkb_symbols "winkeys" { include "ru(common)" name[Group1]= "Russian"; key <AE03> {[ 3, numerosign ]}; key <AE04> {[ 4, semicolon ]}; key <AE05> {[ 5, percent ]}; key <AE06> {[ 6, colon ]}; key <AE07> {[ 7, question ]}; key <AE08> {[ 8, asterisk, U20BD ]}; // ruble key <AB10> {[ period, comma ]}; key <BKSL> {[ backslash, slash ]}; // --- добавлено для C-подобных языков --- key <AD11> { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_ha, Cyrillic_HA, braceleft, braceleft ] }; key <AD12> { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_hardsign, Cyrillic_HARDSIGN, braceright, braceright ] }; // --- квадратные скобки на AltGr: щ → [, з → ] --- key <AD09> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_shcha, Cyrillic_SHCHA, bracketleft, bracketleft ] }; key <AD10> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_ze, Cyrillic_ZE, bracketright, bracketright ] }; // --- угловые скобки на AltGr: б → <, ю → > --- key <AB08> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_be, Cyrillic_BE, less, less ] }; key <AB09> { type = "FOUR_LEVEL", symbols[Group1] = [ Cyrillic_yu, Cyrillic_YU, greater, greater ] }; include "level3(ralt_switch)" };
Пояснения:
<AD11>- физическая клавиша[, в русской раскладкех<AD12>- физическая клавиша], в русской раскладкеъ<AD09>- физическая клавишаO, в русской раскладкещ<AD10>- физическая клавишаP, в русской раскладкез<AB08>- физическая клавиша,, в русской раскладкеб<AB09>- физическая клавиша., в русской раскладкеюFOUR_LEVEL- четыре уровня: без модификатора, Shift, AltGr, Shift+AltGrbraceleft/braceright-{и}bracketleft/bracketright-[и]less/greater-<и>level3(ralt_switch)- включает правый Alt как AltGr
Шаг 5. Перезагрузить систему
sudo reboot
Шаг 6. Проверить
Открыть любой текстовый редактор:
х → х, Shift + х → Х, AltGr + х → { ъ → ъ, Shift + ъ → Ъ, AltGr + ъ → } щ → щ, Shift + щ → Щ, AltGr + щ → [ з → з, Shift + з → З, AltGr + з → ] б → б, Shift + б → Б, AltGr + б → < ю → ю, Shift + ю → Ю, AltGr + ю → >
Если AltGr + х даёт { - всё готово.
Кастомная XKB-раскладка работает на уровне системы, без конфликтов. Левый Alt, оба Ctrl, Shift - как обычно.
Спойлеры
Ниже приведены спойлеры для тех, кто хочет вникнуть в детали.
📌 Git diff
[diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index aae998d0f73..6c12d22fc17 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -383,245 +383,465 @@ static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); reserved word too, but only if it follows an '@' sign. */ const struct c_common_resword c_common_reswords[] = -{ +{ { "_Alignas", RID_ALIGNAS, D_CONLY }, + { "_Выравнивание", RID_ALIGNAS, D_CONLY }, { "_Alignof", RID_ALIGNOF, D_CONLY }, + { "_Выравнивание_типа", RID_ALIGNOF, D_CONLY }, { "_Atomic", RID_ATOMIC, D_CONLY }, + { "_Атом", RID_ATOMIC, D_CONLY }, { "_BitInt", RID_BITINT, D_CONLY }, + { "_бит_цел", RID_BITINT, D_CONLY }, { "_Bool", RID_BOOL, D_CONLY }, + { "_лог", RID_BOOL, D_CONLY }, { "_Complex", RID_COMPLEX, 0 }, + { "_комплекс", RID_COMPLEX, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, + { "_мнимое", RID_IMAGINARY, D_CONLY }, { "_Float16", RID_FLOAT16, 0 }, + { "_вещ16", RID_FLOAT16, 0 }, { "_Float32", RID_FLOAT32, 0 }, + { "_вещ32", RID_FLOAT32, 0 }, { "_Float64", RID_FLOAT64, 0 }, + { "_вещ64", RID_FLOAT64, 0 }, { "_Float128", RID_FLOAT128, 0 }, + { "_вещ128", RID_FLOAT128, 0 }, { "_Float32x", RID_FLOAT32X, 0 }, + { "_вещ32x", RID_FLOAT32X, 0 }, { "_Float64x", RID_FLOAT64X, 0 }, + { "_вещ64x", RID_FLOAT64X, 0 }, { "_Float128x", RID_FLOAT128X, 0 }, + { "_вещ128x", RID_FLOAT128X, 0 }, { "_Decimal32", RID_DFLOAT32, D_CONLY }, + { "_десят32", RID_DFLOAT32, D_CONLY }, { "_Decimal64", RID_DFLOAT64, D_CONLY }, + { "_десят64", RID_DFLOAT64, D_CONLY }, { "_Decimal128", RID_DFLOAT128, D_CONLY }, + { "_десят128", RID_DFLOAT128, D_CONLY }, { "_Fract", RID_FRACT, D_CONLY | D_EXT }, + { "_дробь", RID_FRACT, D_CONLY | D_EXT }, { "_Accum", RID_ACCUM, D_CONLY | D_EXT }, + { "_аккум", RID_ACCUM, D_CONLY | D_EXT }, { "_Sat", RID_SAT, D_CONLY | D_EXT }, + { "_насыщ", RID_SAT, D_CONLY | D_EXT }, { "_Static_assert", RID_STATIC_ASSERT, D_CONLY }, + { "_стат_проверка", RID_STATIC_ASSERT, D_CONLY }, { "_Noreturn", RID_NORETURN, D_CONLY }, + { "_Безвозврат", RID_NORETURN, D_CONLY }, { "_Generic", RID_GENERIC, D_CONLY }, + { "_Обобщ", RID_GENERIC, D_CONLY }, { "_Thread_local", RID_THREAD, D_CONLY }, + { "_Поток_лок", RID_THREAD, D_CONLY }, { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, + { "__ФУНКЦИЯ__", RID_FUNCTION_NAME, 0 }, { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, + { "__КРАСИВАЯ_ФУНКЦИЯ__", RID_PRETTY_FUNCTION_NAME, 0 }, { "__alignof", RID_ALIGNOF, 0 }, + { "__выравн_от", RID_ALIGNOF, 0 }, { "__alignof__", RID_ALIGNOF, 0 }, + { "__выравн_от__", RID_ALIGNOF, 0 }, { "__asm", RID_ASM, 0 }, + { "__ассемблер", RID_ASM, 0 }, { "__asm__", RID_ASM, 0 }, + { "__ассемблер__", RID_ASM, 0 }, { "__attribute", RID_ATTRIBUTE, 0 }, + { "__атрибут", RID_ATTRIBUTE, 0 }, { "__attribute__", RID_ATTRIBUTE, 0 }, + { "__атрибут__", RID_ATTRIBUTE, 0 }, { "__auto_type", RID_AUTO_TYPE, D_CONLY }, + { "__авто_тип", RID_AUTO_TYPE, D_CONLY }, { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY }, + { "__встр_адрес_от", RID_ADDRESSOF, D_CXXONLY }, { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, + { "__встр_барьер_ассоц", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY }, + { "__встр_бит_преобр", RID_BUILTIN_BIT_CAST, D_CXXONLY }, { "__builtin_call_with_static_chain", RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, + { "__встр_вызов_со_стат_цепью", + RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY }, + { "__встр_выбор_выраж", RID_CHOOSE_EXPR, D_CONLY }, { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY }, + { "__встр_комплекс", RID_BUILTIN_COMPLEX, D_CONLY }, { "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 }, + { "__встр_преобр_вектор", RID_BUILTIN_CONVERTVECTOR, 0 }, { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, + { "__встр_имеет_атрибут", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, + { "__встр_очистка", RID_BUILTIN_LAUNDER, D_CXXONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, + { "__встр_перемешать", RID_BUILTIN_SHUFFLE, 0 }, { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, + { "__встр_перемешать_вектор", RID_BUILTIN_SHUFFLEVECTOR, 0 }, { "__builtin_stdc_bit_ceil", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_бит_потолок", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_bit_floor", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_бит_пол", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_bit_width", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_бит_ширина", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_count_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_считать_единицы", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_count_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_считать_нули", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_leading_one", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_ведущий_один", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_leading_zero", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_ведущий_нуль", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_trailing_one", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_хвостовой_один", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_first_trailing_zero", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_первый_хвостовой_нуль", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_has_single_bit", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_имеет_один_бит", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_ведущие_единицы", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_leading_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_ведущие_нули", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_хвостовые_единицы", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_stdc_trailing_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__встр_stdc_хвостовые_нули", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, + { "__встр_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, + { "__встр_смещение", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, + { "__встр_типы_совместимы", RID_TYPES_COMPATIBLE_P, D_CONLY }, { "__builtin_va_arg", RID_VA_ARG, 0 }, + { "__встр_va_arg", RID_VA_ARG, 0 }, { "__complex", RID_COMPLEX, 0 }, + { "__комплекс", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 }, + { "__комплекс__", RID_COMPLEX, 0 }, { "__const", RID_CONST, 0 }, + { "конст", RID_CONST, 0 }, { "__const__", RID_CONST, 0 }, + { "__неизм__", RID_CONST, 0 }, { "__constinit", RID_CONSTINIT, D_CXXONLY }, + { "__конст_иниц", RID_CONSTINIT, D_CXXONLY }, { "__decltype", RID_DECLTYPE, D_CXXONLY }, + { "__тип_выраж", RID_DECLTYPE, D_CXXONLY }, { "__extension__", RID_EXTENSION, 0 }, + { "__расширение__", RID_EXTENSION, 0 }, { "__func__", RID_C99_FUNCTION_NAME, 0 }, + { "__функ__", RID_C99_FUNCTION_NAME, 0 }, { "__imag", RID_IMAGPART, 0 }, + { "__мнимая", RID_IMAGPART, 0 }, { "__imag__", RID_IMAGPART, 0 }, + { "__мнимая__", RID_IMAGPART, 0 }, { "__inline", RID_INLINE, 0 }, + { "__встр", RID_INLINE, 0 }, { "__inline__", RID_INLINE, 0 }, + { "__встр__", RID_INLINE, 0 }, { "__label__", RID_LABEL, 0 }, + { "__метка__", RID_LABEL, 0 }, { "__null", RID_NULL, 0 }, + { "__нуль", RID_NULL, 0 }, { "__real", RID_REALPART, 0 }, + { "__действ", RID_REALPART, 0 }, { "__real__", RID_REALPART, 0 }, + { "__действ__", RID_REALPART, 0 }, { "__restrict", RID_RESTRICT, 0 }, + { "__огран", RID_RESTRICT, 0 }, { "__restrict__", RID_RESTRICT, 0 }, + { "__огран__", RID_RESTRICT, 0 }, { "__signed", RID_SIGNED, 0 }, + { "__знак", RID_SIGNED, 0 }, { "__signed__", RID_SIGNED, 0 }, + { "__знак__", RID_SIGNED, 0 }, { "__thread", RID_THREAD, 0 }, + { "__поток", RID_THREAD, 0 }, { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 }, + { "__транзакция_атомарн", RID_TRANSACTION_ATOMIC, 0 }, { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 }, + { "__транзакция_расслабл", RID_TRANSACTION_RELAXED, 0 }, { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 }, + { "__транзакция_отмена", RID_TRANSACTION_CANCEL, 0 }, { "__typeof", RID_TYPEOF, 0 }, + { "__тип_от", RID_TYPEOF, 0 }, { "__typeof__", RID_TYPEOF, 0 }, + { "__тип_от__", RID_TYPEOF, 0 }, { "__typeof_unqual", RID_TYPEOF_UNQUAL, D_CONLY }, + { "__тип_от_без_квал", RID_TYPEOF_UNQUAL, D_CONLY }, { "__typeof_unqual__", RID_TYPEOF_UNQUAL, D_CONLY }, + { "__тип_от_без_квал__", RID_TYPEOF_UNQUAL, D_CONLY }, { "__volatile", RID_VOLATILE, 0 }, + { "__неуст", RID_VOLATILE, 0 }, { "__volatile__", RID_VOLATILE, 0 }, + { "__неуст__", RID_VOLATILE, 0 }, { "__GIMPLE", RID_GIMPLE, D_CONLY }, - { "__PHI", RID_PHI, D_CONLY }, + { "__PHI", RID_PHI, D_CONLY }, // { "__RTL", RID_RTL, D_CONLY }, { "alignas", RID_ALIGNAS, D_C23 | D_CXX11 | D_CXXWARN }, + { "выравн_как", RID_ALIGNAS, D_C23 | D_CXX11 | D_CXXWARN }, { "alignof", RID_ALIGNOF, D_C23 | D_CXX11 | D_CXXWARN }, + { "выравн_от", RID_ALIGNOF, D_C23 | D_CXX11 | D_CXXWARN }, { "asm", RID_ASM, D_ASM }, + { "асм", RID_ASM, D_ASM }, { "auto", RID_AUTO, 0 }, + { "авто", RID_AUTO, 0 }, { "bool", RID_BOOL, D_C23 | D_CXXWARN }, + //{ "бул", RID_BOOL, D_C23 | D_CXXWARN }, + { "бул", RID_BOOL, 0 }, { "break", RID_BREAK, 0 }, + { "прерви", RID_BREAK, 0 }, { "case", RID_CASE, 0 }, + { "случай", RID_CASE, 0 }, { "catch", RID_CATCH, D_CXX_OBJC | D_CXXWARN }, + { "поймать", RID_CATCH, D_CXX_OBJC | D_CXXWARN }, { "char", RID_CHAR, 0 }, + { "символ", RID_CHAR, 0 }, { "char8_t", RID_CHAR8, D_CXX_CHAR8_T_FLAGS | D_CXXWARN }, + { "симв8_t", RID_CHAR8, D_CXX_CHAR8_T_FLAGS | D_CXXWARN }, { "char16_t", RID_CHAR16, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "симв16_t", RID_CHAR16, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "char32_t", RID_CHAR32, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "симв32_t", RID_CHAR32, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN }, + { "класс", RID_CLASS, D_CXX_OBJC | D_CXXWARN }, + { "__конст", RID_CONST, 0 }, { "consteval", RID_CONSTEVAL, D_CXXONLY | D_CXX20 | D_CXXWARN }, + { "конст_вычисл", RID_CONSTEVAL, D_CXXONLY | D_CXX20 | D_CXXWARN }, { "constexpr", RID_CONSTEXPR, D_C23 | D_CXX11 | D_CXXWARN }, + { "конст_выраж", RID_CONSTEXPR, D_C23 | D_CXX11 | D_CXXWARN }, { "constinit", RID_CONSTINIT, D_CXXONLY | D_CXX20 | D_CXXWARN }, + { "конст_иниц", RID_CONSTINIT, D_CXXONLY | D_CXX20 | D_CXXWARN }, { "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN }, + { "конст_преобр", RID_CONSTCAST, D_CXXONLY | D_CXXWARN }, { "continue", RID_CONTINUE, 0 }, + { "продолжи", RID_CONTINUE, 0 }, { "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "тип_выраж", RID_DECLTYPE, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "default", RID_DEFAULT, 0 }, + { "умолч", RID_DEFAULT, 0 }, { "delete", RID_DELETE, D_CXXONLY | D_CXXWARN }, + { "удалить", RID_DELETE, D_CXXONLY | D_CXXWARN }, { "do", RID_DO, 0 }, + { "делай", RID_DO, 0 }, { "double", RID_DOUBLE, 0 }, + { "двойн", RID_DOUBLE, 0 }, { "dynamic_cast", RID_DYNCAST, D_CXXONLY | D_CXXWARN }, + { "динам_преобр", RID_DYNCAST, D_CXXONLY | D_CXXWARN }, { "else", RID_ELSE, 0 }, + { "иначе", RID_ELSE, 0 }, { "enum", RID_ENUM, 0 }, + { "переч", RID_ENUM, 0 }, { "explicit", RID_EXPLICIT, D_CXXONLY | D_CXXWARN }, + { "явный", RID_EXPLICIT, D_CXXONLY | D_CXXWARN }, { "export", RID_EXPORT, D_CXXONLY | D_CXXWARN }, + { "экспорт", RID_EXPORT, D_CXXONLY | D_CXXWARN }, { "extern", RID_EXTERN, 0 }, + { "внеш", RID_EXTERN, 0 }, { "false", RID_FALSE, D_C23 | D_CXXWARN }, + { "ложь", RID_FALSE, 0 }, { "float", RID_FLOAT, 0 }, + { "плав", RID_FLOAT, 0 }, { "for", RID_FOR, 0 }, + { "для", RID_FOR, 0 }, { "friend", RID_FRIEND, D_CXXONLY | D_CXXWARN }, + { "друг", RID_FRIEND, D_CXXONLY | D_CXXWARN }, { "goto", RID_GOTO, 0 }, + { "перейти", RID_GOTO, 0 }, { "if", RID_IF, 0 }, + { "если", RID_IF, 0 }, { "inline", RID_INLINE, D_EXT89 }, + { "инлайн", RID_INLINE, D_EXT89 }, { "int", RID_INT, 0 }, + { "цел", RID_INT_RU, 0 }, { "long", RID_LONG, 0 }, + { "длин", RID_LONG, 0 }, { "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN }, + { "измен", RID_MUTABLE, D_CXXONLY | D_CXXWARN }, { "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN }, + { "пространство", RID_NAMESPACE, D_CXXONLY | D_CXXWARN }, { "new", RID_NEW, D_CXXONLY | D_CXXWARN }, + { "новый", RID_NEW, D_CXXONLY | D_CXXWARN }, { "noexcept", RID_NOEXCEPT, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "без_искл", RID_NOEXCEPT, D_CXXONLY | D_CXX11 | D_CXXWARN }, { "nullptr", RID_NULLPTR, D_C23 | D_CXX11 | D_CXXWARN }, + { "пуст_указ", RID_NULLPTR, D_C23 | D_CXX11 | D_CXXWARN }, { "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN }, + { "оператор", RID_OPERATOR, D_CXXONLY | D_CXXWARN }, { "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN }, + { "закрыт", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN }, { "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN }, + { "защищ", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN }, { "public", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN }, + { "открыт", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN }, { "register", RID_REGISTER, 0 }, + { "регистр", RID_REGISTER, 0 }, { "reinterpret_cast", RID_REINTCAST, D_CXXONLY | D_CXXWARN }, + { "переинт_преобр", RID_REINTCAST, D_CXXONLY | D_CXXWARN }, { "restrict", RID_RESTRICT, D_CONLY | D_C99 }, + { "огранич", RID_RESTRICT, D_CONLY | D_C99 }, { "return", RID_RETURN, 0 }, + { "возврат", RID_RETURN, 0 }, { "short", RID_SHORT, 0 }, + { "корот", RID_SHORT, 0 }, { "signed", RID_SIGNED, 0 }, + { "знак", RID_SIGNED, 0 }, { "sizeof", RID_SIZEOF, 0 }, + { "размер", RID_SIZEOF, 0 }, { "static", RID_STATIC, 0 }, + { "стат", RID_STATIC, 0 }, { "static_assert", RID_STATIC_ASSERT, D_C23 | D_CXX11 | D_CXXWARN }, + { "стат_проверка", RID_STATIC_ASSERT, D_C23 | D_CXX11 | D_CXXWARN }, { "static_cast", RID_STATCAST, D_CXXONLY | D_CXXWARN }, + { "стат_преобр", RID_STATCAST, D_CXXONLY | D_CXXWARN }, { "struct", RID_STRUCT, 0 }, + { "структ", RID_STRUCT, 0 }, { "switch", RID_SWITCH, 0 }, + { "выбор", RID_SWITCH, 0 }, { "template", RID_TEMPLATE, D_CXXONLY | D_CXXWARN }, + { "шаблон", RID_TEMPLATE, D_CXXONLY | D_CXXWARN }, { "this", RID_THIS, D_CXXONLY | D_CXXWARN }, + { "этот", RID_THIS, D_CXXONLY | D_CXXWARN }, { "thread_local", RID_THREAD, D_C23 | D_CXX11 | D_CXXWARN }, + { "_Поток_лок", RID_THREAD, D_C23 | D_CXX11 | D_CXXWARN }, { "throw", RID_THROW, D_CXX_OBJC | D_CXXWARN }, + { "бросить", RID_THROW, D_CXX_OBJC | D_CXXWARN }, { "true", RID_TRUE, D_C23 | D_CXXWARN }, + { "истина", RID_TRUE, 0 }, { "try", RID_TRY, D_CXX_OBJC | D_CXXWARN }, + { "попытка", RID_TRY, D_CXX_OBJC | D_CXXWARN }, { "typedef", RID_TYPEDEF, 0 }, + { "типдеф", RID_TYPEDEF, 0 }, { "typename", RID_TYPENAME, D_CXXONLY | D_CXXWARN }, + { "имя_типа", RID_TYPENAME, D_CXXONLY | D_CXXWARN }, { "typeid", RID_TYPEID, D_CXXONLY | D_CXXWARN }, + { "ид_типа", RID_TYPEID, D_CXXONLY | D_CXXWARN }, { "typeof", RID_TYPEOF, D_EXT11 }, + { "типоф", RID_TYPEOF, D_EXT11 }, { "typeof_unqual", RID_TYPEOF_UNQUAL, D_CONLY | D_C23 }, + { "тип_от_без_квал", RID_TYPEOF_UNQUAL, D_CONLY | D_C23 }, { "union", RID_UNION, 0 }, + { "объед", RID_UNION, 0 }, { "unsigned", RID_UNSIGNED, 0 }, + { "беззнак", RID_UNSIGNED, 0 }, { "using", RID_USING, D_CXXONLY | D_CXXWARN }, + { "используя", RID_USING, D_CXXONLY | D_CXXWARN }, { "virtual", RID_VIRTUAL, D_CXXONLY | D_CXXWARN }, + { "вирт", RID_VIRTUAL, D_CXXONLY | D_CXXWARN }, { "void", RID_VOID, 0 }, + { "пусто", RID_VOID, 0 }, { "volatile", RID_VOLATILE, 0 }, + { "летуч", RID_VOLATILE, 0 }, { "wchar_t", RID_WCHAR, D_CXXONLY }, + { "ш_симв", RID_WCHAR, D_CXXONLY }, { "while", RID_WHILE, 0 }, + { "пока", RID_WHILE, 0 }, /* C++ transactional memory. */ { "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, + { "синхрон", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, { "atomic_noexcept", RID_ATOMIC_NOEXCEPT, D_CXXONLY | D_TRANSMEM }, + { "атомарн_без_искл", RID_ATOMIC_NOEXCEPT, D_CXXONLY | D_TRANSMEM }, { "atomic_cancel", RID_ATOMIC_CANCEL, D_CXXONLY | D_TRANSMEM }, + { "атомарн_отмена", RID_ATOMIC_CANCEL, D_CXXONLY | D_TRANSMEM }, { "atomic_commit", RID_TRANSACTION_ATOMIC, D_CXXONLY | D_TRANSMEM }, + { "атомарн_фиксация", RID_TRANSACTION_ATOMIC, D_CXXONLY | D_TRANSMEM }, /* Concepts-related keywords */ { "concept", RID_CONCEPT, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, + { "концепт", RID_CONCEPT, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, { "requires", RID_REQUIRES, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, + { "требует", RID_REQUIRES, D_CXX_CONCEPTS_FLAGS | D_CXXWARN }, /* Modules-related keywords, these are internal unspellable tokens, created by the preprocessor. */ { "module ", RID__MODULE, D_CXX_MODULES_FLAGS | D_CXXWARN }, + { "модуль ", RID__MODULE, D_CXX_MODULES_FLAGS | D_CXXWARN }, { "import ", RID__IMPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, + { "импорт ", RID__IMPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, { "export ", RID__EXPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, + { "экспорт ", RID__EXPORT, D_CXX_MODULES_FLAGS | D_CXXWARN }, /* Coroutines-related keywords */ { "co_await", RID_CO_AWAIT, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, + { "со_ждать", RID_CO_AWAIT, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, { "co_yield", RID_CO_YIELD, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, + { "со_уступить", RID_CO_YIELD, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, { "co_return", RID_CO_RETURN, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, + { "со_возврат", RID_CO_RETURN, D_CXX_COROUTINES_FLAGS | D_CXXWARN }, /* These Objective-C keywords are recognized only immediately after an '@'. */ { "compatibility_alias", RID_AT_ALIAS, D_OBJC }, + { "совместим_псевдоним", RID_AT_ALIAS, D_OBJC }, { "defs", RID_AT_DEFS, D_OBJC }, + { "описания", RID_AT_DEFS, D_OBJC }, { "encode", RID_AT_ENCODE, D_OBJC }, + { "кодировать", RID_AT_ENCODE, D_OBJC }, { "end", RID_AT_END, D_OBJC }, + { "конец", RID_AT_END, D_OBJC }, { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, + { "реализация", RID_AT_IMPLEMENTATION, D_OBJC }, { "interface", RID_AT_INTERFACE, D_OBJC }, + { "интерфейс", RID_AT_INTERFACE, D_OBJC }, { "protocol", RID_AT_PROTOCOL, D_OBJC }, + { "протокол", RID_AT_PROTOCOL, D_OBJC }, { "selector", RID_AT_SELECTOR, D_OBJC }, + { "селектор", RID_AT_SELECTOR, D_OBJC }, { "finally", RID_AT_FINALLY, D_OBJC }, + { "наконец", RID_AT_FINALLY, D_OBJC }, { "optional", RID_AT_OPTIONAL, D_OBJC }, + { "необязат", RID_AT_OPTIONAL, D_OBJC }, { "required", RID_AT_REQUIRED, D_OBJC }, + { "обязат", RID_AT_REQUIRED, D_OBJC }, { "property", RID_AT_PROPERTY, D_OBJC }, + { "свойство", RID_AT_PROPERTY, D_OBJC }, { "package", RID_AT_PACKAGE, D_OBJC }, + { "пакет", RID_AT_PACKAGE, D_OBJC }, { "synthesize", RID_AT_SYNTHESIZE, D_OBJC }, + { "синтез", RID_AT_SYNTHESIZE, D_OBJC }, { "dynamic", RID_AT_DYNAMIC, D_OBJC }, + { "динам", RID_AT_DYNAMIC, D_OBJC }, /* These are recognized only in protocol-qualifier context (see above) */ { "bycopy", RID_BYCOPY, D_OBJC }, + { "копировать", RID_BYCOPY, D_OBJC }, { "byref", RID_BYREF, D_OBJC }, + { "по_ссылке", RID_BYREF, D_OBJC }, { "in", RID_IN, D_OBJC }, + { "вход", RID_IN, D_OBJC }, { "inout", RID_INOUT, D_OBJC }, + { "вход_выход", RID_INOUT, D_OBJC }, { "oneway", RID_ONEWAY, D_OBJC }, + { "однонапр", RID_ONEWAY, D_OBJC }, { "out", RID_OUT, D_OBJC }, + { "выход", RID_OUT, D_OBJC }, /* These are recognized inside a property attribute list */ { "assign", RID_ASSIGN, D_OBJC }, + { "присвоить", RID_ASSIGN, D_OBJC }, { "atomic", RID_PROPATOMIC, D_OBJC }, + { "атомарн", RID_PROPATOMIC, D_OBJC }, { "copy", RID_COPY, D_OBJC }, + { "копия", RID_COPY, D_OBJC }, { "getter", RID_GETTER, D_OBJC }, + { "получатель", RID_GETTER, D_OBJC }, { "nonatomic", RID_NONATOMIC, D_OBJC }, + { "не_атомарн", RID_NONATOMIC, D_OBJC }, { "readonly", RID_READONLY, D_OBJC }, + { "только_чтение", RID_READONLY, D_OBJC }, { "readwrite", RID_READWRITE, D_OBJC }, + { "чтение_запись", RID_READWRITE, D_OBJC }, { "retain", RID_RETAIN, D_OBJC }, + { "удержать", RID_RETAIN, D_OBJC }, { "setter", RID_SETTER, D_OBJC }, + { "установщик", RID_SETTER, D_OBJC }, /* These are Objective C implementation of nullability, accepted only in specific contexts. */ { "null_unspecified", RID_NULL_UNSPECIFIED, D_OBJC }, + { "нуль_не_указан", RID_NULL_UNSPECIFIED, D_OBJC }, { "nullable", RID_NULLABLE, D_OBJC }, + { "может_быть_нуль", RID_NULLABLE, D_OBJC }, { "nonnull", RID_NONNULL, D_OBJC }, + { "не_нуль", RID_NONNULL, D_OBJC }, { "null_resettable", RID_NULL_RESETTABLE, D_OBJC }, + { "нуль_сбрасываемый",RID_NULL_RESETTABLE, D_OBJC }, }; const unsigned int num_c_common_reswords = ARRAY_SIZE (c_common_reswords); @@ -4792,6 +5012,7 @@ c_common_nodes_and_builtins (void) c_define_builtins (va_list_ref_type_node, va_list_arg_type_node); main_identifier_node = get_identifier ("main"); + main_ru_identifier_node = get_identifier ("главн"); /* Create the built-in __null node. It is important that this is not shared. */ @@ -8802,6 +9023,7 @@ keyword_begins_type_specifier (enum rid keyword) { case RID_AUTO_TYPE: case RID_INT: + case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -8847,6 +9069,7 @@ keyword_is_type_qualifier (enum rid keyword) switch (keyword) { case RID_CONST: + //case RID_CONST_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_VOLATILE: case RID_RESTRICT: case RID_ATOMIC: diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 2d5f5399885..d94ebf3fe89 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -260,7 +260,11 @@ enum rid RID_FIRST_PQ = RID_IN, RID_LAST_PQ = RID_ONEWAY, RID_FIRST_PATTR = RID_GETTER, - RID_LAST_PATTR = RID_NULL_RESETTABLE + RID_LAST_PATTR = RID_NULL_RESETTABLE, + + RID_INT_RU, + RID_CONST_RU, + RID_MAIN_RU }; #define OBJC_IS_AT_KEYWORD(rid) \ diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 0e52f217618..cbb738b142b 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -10502,6 +10502,14 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, &attributes, &expr, NULL, DEPRECATED_NORMAL); invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1); + /* === ДОБАВЛЕНО: замена "главн" на "main" === */ + if (decl1 != NULL_TREE && TREE_CODE (decl1) == FUNCTION_DECL) + { + if (DECL_NAME (decl1) == main_ru_identifier_node) + DECL_NAME (decl1) = main_identifier_node; + } + /* === КОНЕЦ ДОБАВЛЕННОГО БЛОКА === */ + /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == NULL_TREE @@ -12466,6 +12474,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, } return specs; case RID_INT: + case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! if (specs->saturating_p) error_at (loc, ("both %<_Sat%> and %<int%> in " diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 5fcfff7134a..1e1a68eb1b8 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -588,6 +588,7 @@ c_keyword_starts_typename (enum rid keyword) case RID_SIGNED: case RID_COMPLEX: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -792,6 +793,7 @@ c_token_starts_declspecs (c_token *token) case RID_SIGNED: case RID_COMPLEX: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -3446,6 +3448,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, case RID_SIGNED: case RID_COMPLEX: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -5173,6 +5176,7 @@ c_parser_gnu_attribute_any_word (c_parser *parser) case RID_COMPLEX: case RID_THREAD: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: @@ -13901,6 +13905,7 @@ c_parser_objc_selector (c_parser *parser) case RID_BYREF: case RID_ONEWAY: case RID_INT: +case RID_INT_RU: // ДОБАВИТЬ ЗДЕСЬ! case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc index 1110db7f8d0..d29f5c20100 100644 --- a/gcc/cp/lex.cc +++ b/gcc/cp/lex.cc @@ -262,17 +262,33 @@ init_reswords (void) /* The Objective-C keywords are all context-dependent. */ mask |= D_OBJC; - ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX); - for (i = 0; i < num_c_common_reswords; i++) - { - if (c_common_reswords[i].disable & D_CONLY) - continue; - id = get_identifier (c_common_reswords[i].word); - C_SET_RID_CODE (id, c_common_reswords[i].rid); - ridpointers [(int) c_common_reswords[i].rid] = id; - if (! (c_common_reswords[i].disable & mask)) - set_identifier_kind (id, cik_keyword); - } +// В gcc/cp/lex.cc (или gcc/c-family/c-common.cc для C) +// Добавить специальную обработку после основного цикла + +ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX); +for (i = 0; i < num_c_common_reswords; i++) +{ + if (c_common_reswords[i].disable & D_CONLY) + continue; + id = get_identifier (c_common_reswords[i].word); + C_SET_RID_CODE (id, c_common_reswords[i].rid); + ridpointers [(int) c_common_reswords[i].rid] = id; + if (! (c_common_reswords[i].disable & mask)) + set_identifier_kind (id, cik_keyword); +} + +// ✅ ДОБАВИТЬ: сделать RID_INT_RU и RID_INT эквивалентными +// Делаем так, чтобы оба ключевых слова указывали на ОДИН идентификатор +if (ridpointers[RID_INT] && ridpointers[RID_INT_RU]) +{ + // Вариант 1: переиспользовать идентификатор RID_INT для RID_INT_RU + ridpointers[RID_INT_RU] = ridpointers[RID_INT]; + + // ИЛИ вариант 2: сделать оба указателя на идентификатор "цел" + // ridpointers[RID_INT] = ridpointers[RID_INT_RU]; +} + + for (i = 0; i < NUM_INT_N_ENTS; i++) { diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 9fa74342919..a5be6ec6955 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -754,6 +754,7 @@ enum tree_index { TI_VOID_LIST_NODE, TI_MAIN_IDENTIFIER, + TI_MAIN_RU_IDENTIFIER, TI_SAT_SFRACT_TYPE, TI_SAT_FRACT_TYPE, diff --git a/gcc/tree.h b/gcc/tree.h index ee2aae332a4..b3336250935 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4606,9 +4606,11 @@ tree_strip_any_location_wrapper (tree exp) #define void_list_node global_trees[TI_VOID_LIST_NODE] #define main_identifier_node global_trees[TI_MAIN_IDENTIFIER] +#define main_ru_identifier_node global_trees[TI_MAIN_RU_IDENTIFIER] #define MAIN_NAME_P(NODE) \ (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node) - +#define MAIN_RU_NAME_P(NODE) \ + (IDENTIFIER_NODE_CHECK (NODE) == main_ru_identifier_node) // ← ДОБАВИТЬ /* Optimization options (OPTIMIZATION_NODE) to use for default and current functions. */ #define optimization_default_node global_trees[TI_OPTIMIZATION_DEFAULT] diff --git a/libcpp/directives.cc b/libcpp/directives.cc index 479f8c716e8..aed62174ab0 100644 --- a/libcpp/directives.cc +++ b/libcpp/directives.cc @@ -190,6 +190,23 @@ enum static const directive dtable[] = { DIRECTIVE_TABLE + + /* Русские синонимы для директив */ + { do_define, UC"определить", sizeof "определить" - 1, KANDR, IN_I }, + { do_include, UC"включить", sizeof "включить" - 1, KANDR, INCL | EXPAND }, + { do_if, UC"если", sizeof "если" - 1, KANDR, COND | IF_COND | EXPAND }, + { do_ifdef, UC"еслиопр", sizeof "еслиопр" - 1, KANDR, COND | IF_COND }, + { do_ifndef, UC"еслинеопр", sizeof "еслинеопр" - 1, KANDR, COND | IF_COND }, + { do_elif, UC"иначеесли", sizeof "иначеесли" - 1, STDC89, COND | EXPAND }, + { do_else, UC"иначе", sizeof "иначе" - 1, KANDR, COND }, + { do_endif, UC"конецесли", sizeof "конецесли" - 1, KANDR, COND }, + { do_undef, UC"отменить", sizeof "отменить" - 1, KANDR, IN_I }, + { do_error, UC"ошибка", sizeof "ошибка" - 1, STDC89, 0 }, + { do_warning, UC"предупреждение", sizeof "предупреждение" - 1, STDC23, 0 }, + { do_pragma, UC"прагма", sizeof "прагма" - 1, STDC89, IN_I }, + { do_line, UC"строка", sizeof "строка" - 1, KANDR, EXPAND }, + { do_include_next, UC"включить_след", sizeof "включить_след" - 1, EXTENSION, INCL | EXPAND }, + { do_import, UC"импорт", sizeof "импорт" - 1, EXTENSION, INCL | EXPAND }, }; #undef D @@ -197,7 +214,25 @@ DIRECTIVE_TABLE when suggesting corrections for misspelled directives. */ #define D(name, t, origin, flags) #name, static const char * const directive_names[] = { -DIRECTIVE_TABLE + DIRECTIVE_TABLE + + /* Русские синонимы для подсказок */ + "определить", + "включить", + "если", + "если_определен", + "если_не_определен", + "иначе_если", + "иначе", + "конец_если", + "отменить", + "ошибка", + "предупреждение", + "прагма", + "строка", + "включить_след", + "импорт", + NULL }; #undef D @@ -459,6 +494,7 @@ _cpp_handle_directive (cpp_reader *pfile, bool indented) if (dname->type == CPP_NAME) { + /* Сначала проверяем стандартные директивы по is_directive. */ if (dname->val.node.node->is_directive) { dir = &dtable[dname->val.node.node->directive_index]; @@ -469,6 +505,31 @@ _cpp_handle_directive (cpp_reader *pfile, bool indented) && CPP_OPTION (pfile, std)) dir = 0; } +else + { + /* Если не нашли по is_directive, ищем русский синоним в dtable. */ + const uchar *name = NODE_NAME (dname->val.node.node); + size_t len = NODE_LEN (dname->val.node.node); + + /* ОТЛАДКА: выводим имя и длину искомой директивы */ + fprintf (stderr, "DEBUG: Looking for directive '%.*s' (len=%zu)\n", + (int)len, name, len); + + for (unsigned int i = 0; i < ARRAY_SIZE (dtable); i++) + { + /* ОТЛАДКА: выводим каждую запись в dtable */ + fprintf (stderr, "DEBUG: dtable[%u] = '%.*s' (len=%hu)\n", + i, (int)dtable[i].length, dtable[i].name, dtable[i].length); + + if (dtable[i].length == len + && memcmp (dtable[i].name, name, len) == 0) + { + fprintf (stderr, "DEBUG: FOUND! i=%u\n", i); + dir = &dtable[i]; + break; + } + } + } } /* We do not recognize the # followed by a number extension in assembler code. */ @@ -2171,8 +2232,9 @@ do_elif (cpp_reader *pfile) } else { - if (pfile->directive == &dtable[T_ELIF]) - pfile->state.skipping = !_cpp_parse_expr (pfile, false); + if (pfile->directive == &dtable[T_ELIF] + || pfile->directive->handler == do_elif) + pfile->state.skipping = !_cpp_parse_expr (pfile, false); else { cpp_hashnode *node = lex_macro_node (pfile, false); @@ -2813,6 +2875,16 @@ _cpp_init_directives (cpp_reader *pfile) node->is_directive = 1; node->directive_index = i; } + + /* Добавляем русские синонимы в хеш-таблицу. + Они не должны иметь is_directive, потому что мы будем + искать их напрямую в dtable[] по имени. */ + const char *russian_aliases[] = { + "определить", "включить", "если", "если_определен", + "если_не_определен", "иначе_если", "иначе", + "конец_если", "отменить", "ошибка", "предупреждение", + "прагма", "строка", "включить_след", "импорт" + }; } /* Extract header file from a bracket include. Parsing starts after '<'. diff --git a/libcpp/expr.cc b/libcpp/expr.cc index 815eb137a99..4008d222560 100644 --- a/libcpp/expr.cc +++ b/libcpp/expr.cc @@ -1174,6 +1174,16 @@ parse_defined (cpp_reader *pfile) return result; } +/* Handle meeting "определено" in a preprocessor expression (Russian synonym). */ +static cpp_num +parse_defined_ru (cpp_reader *pfile) +{ + /* Просто вызываем parse_defined, так как логика обработки идентична. + Разница только в имени оператора, которое используется только в + сообщениях об ошибках, поэтому переиспользуем существующую функцию. */ + return parse_defined (pfile); +} + /* Convert a token into a CPP_NUMBER (an interpreted preprocessing number or character constant, or the result of the "defined" or "#" operators). */ @@ -1241,6 +1251,9 @@ eval_token (cpp_reader *pfile, const cpp_token *token, case CPP_NAME: if (token->val.node.node == pfile->spec_nodes.n_defined) return parse_defined (pfile); + /* Русский синоним "определено" */ + else if (token->val.node.node == pfile->spec_nodes.n_defined_ru) + return parse_defined (pfile); else if (CPP_OPTION (pfile, true_false) && (token->val.node.node == pfile->spec_nodes.n_true || token->val.node.node == pfile->spec_nodes.n_false)) diff --git a/libcpp/init.cc b/libcpp/init.cc index 54fc9236d38..ea647e5b544 100644 --- a/libcpp/init.cc +++ b/libcpp/init.cc @@ -309,6 +309,9 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, _cpp_init_hashtable (pfile, table, extra_table); + pfile->spec_nodes.n_defined_ru = cpp_lookup (pfile, UC"определено", + sizeof "определено" - 1); + return pfile; } @@ -418,14 +421,22 @@ struct builtin_macro static const struct builtin_macro builtin_array[] = { B("__TIMESTAMP__", BT_TIMESTAMP, false), + B("__ВРЕМЯ_ФАЙЛА__", BT_TIMESTAMP, false), B("__TIME__", BT_TIME, false), + B("__ВРЕМЯ__", BT_TIME, false), B("__DATE__", BT_DATE, false), + B("__ДАТА__", BT_DATE, false), B("__FILE__", BT_FILE, false), + B("__ФАЙЛ__", BT_FILE, false), B("__FILE_NAME__", BT_FILE_NAME, false), B("__BASE_FILE__", BT_BASE_FILE, false), + B("__БАЗОВЫЙ_ФАЙЛ__", BT_BASE_FILE, false), B("__LINE__", BT_SPECLINE, true), + B("__ЛИНИЯ__", BT_SPECLINE, true), B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true), B("__COUNTER__", BT_COUNTER, true), + B("__СЧЁТЧИК__", BT_COUNTER, true), + B("__СЧЕТЧИК__", BT_COUNTER, true), /* Make sure to update the list of built-in function-like macros in traditional.cc: fun_like_macro() when adding more following */ diff --git a/libcpp/internal.h b/libcpp/internal.h index a20215c5709..538013d980f 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -297,6 +297,7 @@ struct lexer_state struct spec_nodes { cpp_hashnode *n_defined; /* defined operator */ + cpp_hashnode *n_defined_ru; /* русский синоним "определено" */ cpp_hashnode *n_true; /* C++ keyword true */ cpp_hashnode *n_false; /* C++ keyword false */ cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ diff --git a/libcpp/lex.cc b/libcpp/lex.cc index c9e44e6cccc..e6743393116 100644 --- a/libcpp/lex.cc +++ b/libcpp/lex.cc @@ -2085,6 +2085,40 @@ forms_identifier_p (cpp_reader *pfile, int first, return true; } + /* ================================================================ + ДОБАВЛЕНО: Проверка на русские буквы в UTF-8 + ================================================================ */ + if (*buffer->cur == 0xD0 || *buffer->cur == 0xD1) + { + unsigned char first = *buffer->cur; + unsigned char second = *(buffer->cur + 1); + + /* Диапазоны русских букв в UTF-8: + А-Я: D0 90 - D0 AF + а-я: D1 80 - D1 8F + Ё: D0 81 + ё: D1 91 + */ + if (first == 0xD0 && second >= 0x90 && second <= 0xBF) + { + buffer->cur += 2; + return true; + } + if (first == 0xD1 && second >= 0x80 && second <= 0x8F) + { + buffer->cur += 2; + return true; + } + if (first == 0xD0 && (second == 0x81 || second == 0x91)) + { + buffer->cur += 2; + return true; + } + } + /* ================================================================ + КОНЕЦ ДОБАВЛЕННОГО БЛОКА + ================================================================ */ + /* Is this a syntactically valid UCN or a valid UTF-8 char? */ if (CPP_OPTION (pfile, extended_identifiers)) {
📌 Дизассемблированные привет мир
me@me-Aspire-5742G:~/Документы/rusi/rusi$ objdump -d привет_chibicc привет_chibicc: формат файла elf64-x86-64 Дизассемблирование раздела .init: 0000000000401000 <_init>: 401000: f3 0f 1e fa endbr64 401004: 48 83 ec 08 sub $0x8,%rsp 401008: 48 8b 05 d1 2f 00 00 mov 0x2fd1(%rip),%rax # 403fe0 <__gmon_start__> 40100f: 48 85 c0 test %rax,%rax 401012: 74 02 je 401016 <_init+0x16> 401014: ff d0 call *%rax 401016: 48 83 c4 08 add $0x8,%rsp 40101a: c3 ret Дизассемблирование раздела .text: 0000000000401020 <_start>: 401020: f3 0f 1e fa endbr64 401024: 31 ed xor %ebp,%ebp 401026: 49 89 d1 mov %rdx,%r9 401029: 5e pop %rsi 40102a: 48 89 e2 mov %rsp,%rdx 40102d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 401031: 50 push %rax 401032: 54 push %rsp 401033: 45 31 c0 xor %r8d,%r8d 401036: 31 c9 xor %ecx,%ecx 401038: 48 c7 c7 06 11 40 00 mov $0x401106,%rdi 40103f: ff 15 8b 2f 00 00 call *0x2f8b(%rip) # 403fd0 <__libc_start_main@GLIBC_2.34> 401045: f4 hlt 401046: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40104d: 00 00 00 0000000000401050 <_dl_relocate_static_pie>: 401050: f3 0f 1e fa endbr64 401054: c3 ret 401055: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40105c: 00 00 00 40105f: 90 nop 0000000000401060 <deregister_tm_clones>: 401060: b8 d8 41 40 00 mov $0x4041d8,%eax 401065: 48 3d d8 41 40 00 cmp $0x4041d8,%rax 40106b: 74 13 je 401080 <deregister_tm_clones+0x20> 40106d: b8 00 00 00 00 mov $0x0,%eax 401072: 48 85 c0 test %rax,%rax 401075: 74 09 je 401080 <deregister_tm_clones+0x20> 401077: bf d8 41 40 00 mov $0x4041d8,%edi 40107c: ff e0 jmp *%rax 40107e: 66 90 xchg %ax,%ax 401080: c3 ret 401081: 0f 1f 40 00 nopl 0x0(%rax) 401085: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 40108c: 00 00 00 00 0000000000401090 <register_tm_clones>: 401090: be d8 41 40 00 mov $0x4041d8,%esi 401095: 48 81 ee d8 41 40 00 sub $0x4041d8,%rsi 40109c: 48 89 f0 mov %rsi,%rax 40109f: 48 c1 ee 3f shr $0x3f,%rsi 4010a3: 48 c1 f8 03 sar $0x3,%rax 4010a7: 48 01 c6 add %rax,%rsi 4010aa: 48 d1 fe sar $1,%rsi 4010ad: 74 11 je 4010c0 <register_tm_clones+0x30> 4010af: b8 00 00 00 00 mov $0x0,%eax 4010b4: 48 85 c0 test %rax,%rax 4010b7: 74 07 je 4010c0 <register_tm_clones+0x30> 4010b9: bf d8 41 40 00 mov $0x4041d8,%edi 4010be: ff e0 jmp *%rax 4010c0: c3 ret 4010c1: 0f 1f 40 00 nopl 0x0(%rax) 4010c5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 4010cc: 00 00 00 00 00000000004010d0 <__do_global_dtors_aux>: 4010d0: f3 0f 1e fa endbr64 4010d4: 80 3d fa 30 00 00 00 cmpb $0x0,0x30fa(%rip) # 4041d5 <completed.0> 4010db: 75 13 jne 4010f0 <__do_global_dtors_aux+0x20> 4010dd: 55 push %rbp 4010de: 48 89 e5 mov %rsp,%rbp 4010e1: e8 7a ff ff ff call 401060 <deregister_tm_clones> 4010e6: c6 05 e8 30 00 00 01 movb $0x1,0x30e8(%rip) # 4041d5 <completed.0> 4010ed: 5d pop %rbp 4010ee: c3 ret 4010ef: 90 nop 4010f0: c3 ret 4010f1: 0f 1f 40 00 nopl 0x0(%rax) 4010f5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 4010fc: 00 00 00 00 0000000000401100 <frame_dummy>: 401100: f3 0f 1e fa endbr64 401104: eb 8a jmp 401090 <register_tm_clones> 0000000000401106 <главн>: 401106: 55 push %rbp 401107: 48 89 e5 mov %rsp,%rbp 40110a: 48 83 ec 10 sub $0x10,%rsp 40110e: 48 89 65 f8 mov %rsp,-0x8(%rbp) 401112: 48 8d 05 f7 2e 00 00 lea 0x2ef7(%rip),%rax # 404010 <__dso_handle+0x8> 401119: 50 push %rax 40111a: 48 8b 05 b7 2e 00 00 mov 0x2eb7(%rip),%rax # 403fd8 <printf@GLIBC_2.2.5> 401121: 5f pop %rdi 401122: 49 89 c2 mov %rax,%r10 401125: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40112c: 41 ff d2 call *%r10 40112f: 48 83 c4 00 add $0x0,%rsp 401133: 48 c7 c0 00 00 00 00 mov $0x0,%rax 40113a: eb 07 jmp 401143 <главн+0x3d> 40113c: 48 c7 c0 00 00 00 00 mov $0x0,%rax 401143: 48 89 ec mov %rbp,%rsp 401146: 5d pop %rbp 401147: c3 ret 0000000000401148 <__va_read_from_fp>: 401148: 55 push %rbp 401149: 48 89 e5 mov %rsp,%rbp 40114c: 48 83 ec 30 sub $0x30,%rsp 401150: 48 89 65 e8 mov %rsp,-0x18(%rbp) 401154: 48 89 7d e0 mov %rdi,-0x20(%rbp) 401158: 89 75 dc mov %esi,-0x24(%rbp) 40115b: 89 55 d8 mov %edx,-0x28(%rbp) 40115e: 48 8d 45 e0 lea -0x20(%rbp),%rax 401162: 48 8b 00 mov (%rax),%rax 401165: 48 83 c0 04 add $0x4,%rax 401169: 48 63 00 movslq (%rax),%rax 40116c: 50 push %rax 40116d: 48 c7 c0 70 00 00 00 mov $0x70,%rax 401174: 5f pop %rdi 401175: 39 f8 cmp %edi,%eax 401177: 0f 96 c0 setbe %al 40117a: 48 0f b6 c0 movzbq %al,%rax 40117e: 83 f8 00 cmp $0x0,%eax 401181: 74 3a je 4011bd <__va_read_from_fp+0x75> 401183: 48 8d 45 d8 lea -0x28(%rbp),%rax 401187: 48 63 00 movslq (%rax),%rax 40118a: 50 push %rax 40118b: 48 8d 45 dc lea -0x24(%rbp),%rax 40118f: 48 63 00 movslq (%rax),%rax 401192: 50 push %rax 401193: 48 8d 45 e0 lea -0x20(%rbp),%rax 401197: 48 8b 00 mov (%rax),%rax 40119a: 50 push %rax 40119b: 48 8d 05 ac 01 00 00 lea 0x1ac(%rip),%rax # 40134e <__va_read_from_stack> 4011a2: 5f pop %rdi 4011a3: 5e pop %rsi 4011a4: 5a pop %rdx 4011a5: 49 89 c2 mov %rax,%r10 4011a8: 48 c7 c0 00 00 00 00 mov $0x0,%rax 4011af: 41 ff d2 call *%r10 4011b2: 48 83 c4 00 add $0x0,%rsp 4011b6: e9 8b 00 00 00 jmp 401246 <__va_read_from_fp+0xfe> 4011bb: eb 00 jmp 4011bd <__va_read_from_fp+0x75> 4011bd: 48 c7 c1 08 00 00 00 mov $0x8,%rcx 4011c4: 48 8d 7d f0 lea -0x10(%rbp),%rdi 4011c8: b0 00 mov $0x0,%al 4011ca: f3 aa rep stos %al,(%rdi) 4011cc: 48 8d 45 f0 lea -0x10(%rbp),%rax 4011d0: 50 push %rax 4011d1: 48 c7 c0 01 00 00 00 mov $0x1,%rax 4011d8: 50 push %rax 4011d9: 48 8d 45 e0 lea -0x20(%rbp),%rax 4011dd: 48 8b 00 mov (%rax),%rax 4011e0: 48 83 c0 04 add $0x4,%rax 4011e4: 48 63 00 movslq (%rax),%rax 4011e7: 89 c0 mov %eax,%eax 4011e9: 5f pop %rdi 4011ea: 48 0f af c7 imul %rdi,%rax 4011ee: 50 push %rax 4011ef: 48 8d 45 e0 lea -0x20(%rbp),%rax 4011f3: 48 8b 00 mov (%rax),%rax 4011f6: 48 83 c0 10 add $0x10,%rax 4011fa: 48 8b 00 mov (%rax),%rax 4011fd: 5f pop %rdi 4011fe: 48 01 f8 add %rdi,%rax 401201: 5f pop %rdi 401202: 48 89 07 mov %rax,(%rdi) 401205: 48 8d 45 f8 lea -0x8(%rbp),%rax 401209: 50 push %rax 40120a: 48 8d 45 e0 lea -0x20(%rbp),%rax 40120e: 48 8b 00 mov (%rax),%rax 401211: 5f pop %rdi 401212: 48 89 07 mov %rax,(%rdi) 401215: 48 8d 45 f8 lea -0x8(%rbp),%rax 401219: 48 8b 00 mov (%rax),%rax 40121c: 48 83 c0 04 add $0x4,%rax 401220: 50 push %rax 401221: 48 c7 c0 08 00 00 00 mov $0x8,%rax 401228: 50 push %rax 401229: 48 8d 45 f8 lea -0x8(%rbp),%rax 40122d: 48 8b 00 mov (%rax),%rax 401230: 48 83 c0 04 add $0x4,%rax 401234: 48 63 00 movslq (%rax),%rax 401237: 5f pop %rdi 401238: 01 f8 add %edi,%eax 40123a: 5f pop %rdi 40123b: 89 07 mov %eax,(%rdi) 40123d: 48 8d 45 f0 lea -0x10(%rbp),%rax 401241: 48 8b 00 mov (%rax),%rax 401244: eb 00 jmp 401246 <__va_read_from_fp+0xfe> 401246: 48 89 ec mov %rbp,%rsp 401249: 5d pop %rbp 40124a: c3 ret 000000000040124b <__va_read_from_gp>: 40124b: 55 push %rbp 40124c: 48 89 e5 mov %rsp,%rbp 40124f: 48 83 ec 30 sub $0x30,%rsp 401253: 48 89 65 e8 mov %rsp,-0x18(%rbp) 401257: 48 89 7d e0 mov %rdi,-0x20(%rbp) 40125b: 89 75 dc mov %esi,-0x24(%rbp) 40125e: 89 55 d8 mov %edx,-0x28(%rbp) 401261: 48 8d 45 e0 lea -0x20(%rbp),%rax 401265: 48 8b 00 mov (%rax),%rax 401268: 48 83 c0 00 add $0x0,%rax 40126c: 48 63 00 movslq (%rax),%rax 40126f: 50 push %rax 401270: 48 c7 c0 30 00 00 00 mov $0x30,%rax 401277: 5f pop %rdi 401278: 39 f8 cmp %edi,%eax 40127a: 0f 96 c0 setbe %al 40127d: 48 0f b6 c0 movzbq %al,%rax 401281: 83 f8 00 cmp $0x0,%eax 401284: 74 3a je 4012c0 <__va_read_from_gp+0x75> 401286: 48 8d 45 d8 lea -0x28(%rbp),%rax 40128a: 48 63 00 movslq (%rax),%rax 40128d: 50 push %rax 40128e: 48 8d 45 dc lea -0x24(%rbp),%rax 401292: 48 63 00 movslq (%rax),%rax 401295: 50 push %rax 401296: 48 8d 45 e0 lea -0x20(%rbp),%rax 40129a: 48 8b 00 mov (%rax),%rax 40129d: 50 push %rax 40129e: 48 8d 05 a9 00 00 00 lea 0xa9(%rip),%rax # 40134e <__va_read_from_stack> 4012a5: 5f pop %rdi 4012a6: 5e pop %rsi 4012a7: 5a pop %rdx 4012a8: 49 89 c2 mov %rax,%r10 4012ab: 48 c7 c0 00 00 00 00 mov $0x0,%rax 4012b2: 41 ff d2 call *%r10 4012b5: 48 83 c4 00 add $0x0,%rsp 4012b9: e9 8b 00 00 00 jmp 401349 <__va_read_from_gp+0xfe> 4012be: eb 00 jmp 4012c0 <__va_read_from_gp+0x75> 4012c0: 48 c7 c1 08 00 00 00 mov $0x8,%rcx 4012c7: 48 8d 7d f0 lea -0x10(%rbp),%rdi 4012cb: b0 00 mov $0x0,%al 4012cd: f3 aa rep stos %al,(%rdi) 4012cf: 48 8d 45 f0 lea -0x10(%rbp),%rax 4012d3: 50 push %rax 4012d4: 48 c7 c0 01 00 00 00 mov $0x1,%rax 4012db: 50 push %rax 4012dc: 48 8d 45 e0 lea -0x20(%rbp),%rax 4012e0: 48 8b 00 mov (%rax),%rax 4012e3: 48 83 c0 00 add $0x0,%rax 4012e7: 48 63 00 movslq (%rax),%rax 4012ea: 89 c0 mov %eax,%eax 4012ec: 5f pop %rdi 4012ed: 48 0f af c7 imul %rdi,%rax 4012f1: 50 push %rax 4012f2: 48 8d 45 e0 lea -0x20(%rbp),%rax 4012f6: 48 8b 00 mov (%rax),%rax 4012f9: 48 83 c0 10 add $0x10,%rax 4012fd: 48 8b 00 mov (%rax),%rax 401300: 5f pop %rdi 401301: 48 01 f8 add %rdi,%rax 401304: 5f pop %rdi 401305: 48 89 07 mov %rax,(%rdi) 401308: 48 8d 45 f8 lea -0x8(%rbp),%rax 40130c: 50 push %rax 40130d: 48 8d 45 e0 lea -0x20(%rbp),%rax 401311: 48 8b 00 mov (%rax),%rax 401314: 5f pop %rdi 401315: 48 89 07 mov %rax,(%rdi) 401318: 48 8d 45 f8 lea -0x8(%rbp),%rax 40131c: 48 8b 00 mov (%rax),%rax 40131f: 48 83 c0 00 add $0x0,%rax 401323: 50 push %rax 401324: 48 c7 c0 08 00 00 00 mov $0x8,%rax 40132b: 50 push %rax 40132c: 48 8d 45 f8 lea -0x8(%rbp),%rax 401330: 48 8b 00 mov (%rax),%rax 401333: 48 83 c0 00 add $0x0,%rax 401337: 48 63 00 movslq (%rax),%rax 40133a: 5f pop %rdi 40133b: 01 f8 add %edi,%eax 40133d: 5f pop %rdi 40133e: 89 07 mov %eax,(%rdi) 401340: 48 8d 45 f0 lea -0x10(%rbp),%rax 401344: 48 8b 00 mov (%rax),%rax 401347: eb 00 jmp 401349 <__va_read_from_gp+0xfe> 401349: 48 89 ec mov %rbp,%rsp 40134c: 5d pop %rbp 40134d: c3 ret 000000000040134e <__va_read_from_stack>: 40134e: 55 push %rbp 40134f: 48 89 e5 mov %rsp,%rbp 401352: 48 83 ec 20 sub $0x20,%rsp 401356: 48 89 65 f0 mov %rsp,-0x10(%rbp) 40135a: 48 89 7d e8 mov %rdi,-0x18(%rbp) 40135e: 89 75 e4 mov %esi,-0x1c(%rbp) 401361: 89 55 e0 mov %edx,-0x20(%rbp) 401364: 48 c7 c1 08 00 00 00 mov $0x8,%rcx 40136b: 48 8d 7d f8 lea -0x8(%rbp),%rdi 40136f: b0 00 mov $0x0,%al 401371: f3 aa rep stos %al,(%rdi) 401373: 48 8d 45 f8 lea -0x8(%rbp),%rax 401377: 50 push %rax 401378: 48 8d 45 e8 lea -0x18(%rbp),%rax 40137c: 48 8b 00 mov (%rax),%rax 40137f: 48 83 c0 08 add $0x8,%rax 401383: 48 8b 00 mov (%rax),%rax 401386: 5f pop %rdi 401387: 48 89 07 mov %rax,(%rdi) 40138a: 48 8d 45 e0 lea -0x20(%rbp),%rax 40138e: 48 63 00 movslq (%rax),%rax 401391: 50 push %rax 401392: 48 c7 c0 08 00 00 00 mov $0x8,%rax 401399: 5f pop %rdi 40139a: 39 f8 cmp %edi,%eax 40139c: 0f 9c c0 setl %al 40139f: 48 0f b6 c0 movzbq %al,%rax 4013a3: 83 f8 00 cmp $0x0,%eax 4013a6: 74 54 je 4013fc <__va_read_from_stack+0xae> 4013a8: 48 8d 45 f8 lea -0x8(%rbp),%rax 4013ac: 50 push %rax 4013ad: 48 c7 c0 10 00 00 00 mov $0x10,%rax 4013b4: 48 63 c0 movslq %eax,%rax 4013b7: 50 push %rax 4013b8: 48 c7 c0 10 00 00 00 mov $0x10,%rax 4013bf: 48 63 c0 movslq %eax,%rax 4013c2: 50 push %rax 4013c3: 48 c7 c0 01 00 00 00 mov $0x1,%rax 4013ca: 50 push %rax 4013cb: 48 c7 c0 0f 00 00 00 mov $0xf,%rax 4013d2: 48 63 c0 movslq %eax,%rax 4013d5: 5f pop %rdi 4013d6: 48 0f af c7 imul %rdi,%rax 4013da: 50 push %rax 4013db: 48 8d 45 f8 lea -0x8(%rbp),%rax 4013df: 48 8b 00 mov (%rax),%rax 4013e2: 5f pop %rdi 4013e3: 48 01 f8 add %rdi,%rax 4013e6: 5f pop %rdi 4013e7: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 4013ee: 48 f7 f7 div %rdi 4013f1: 5f pop %rdi 4013f2: 48 0f af c7 imul %rdi,%rax 4013f6: 5f pop %rdi 4013f7: 48 89 07 mov %rax,(%rdi) 4013fa: eb 00 jmp 4013fc <__va_read_from_stack+0xae> 4013fc: 48 8d 45 e8 lea -0x18(%rbp),%rax 401400: 48 8b 00 mov (%rax),%rax 401403: 48 83 c0 08 add $0x8,%rax 401407: 50 push %rax 401408: 48 c7 c0 08 00 00 00 mov $0x8,%rax 40140f: 48 63 c0 movslq %eax,%rax 401412: 50 push %rax 401413: 48 c7 c0 08 00 00 00 mov $0x8,%rax 40141a: 48 63 c0 movslq %eax,%rax 40141d: 50 push %rax 40141e: 48 c7 c0 07 00 00 00 mov $0x7,%rax 401425: 48 63 c0 movslq %eax,%rax 401428: 50 push %rax 401429: 48 8d 45 e4 lea -0x1c(%rbp),%rax 40142d: 48 63 00 movslq (%rax),%rax 401430: 48 63 c0 movslq %eax,%rax 401433: 50 push %rax 401434: 48 8d 45 f8 lea -0x8(%rbp),%rax 401438: 48 8b 00 mov (%rax),%rax 40143b: 5f pop %rdi 40143c: 48 01 f8 add %rdi,%rax 40143f: 5f pop %rdi 401440: 48 01 f8 add %rdi,%rax 401443: 5f pop %rdi 401444: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 40144b: 48 f7 f7 div %rdi 40144e: 5f pop %rdi 40144f: 48 0f af c7 imul %rdi,%rax 401453: 5f pop %rdi 401454: 48 89 07 mov %rax,(%rdi) 401457: 48 8d 45 f8 lea -0x8(%rbp),%rax 40145b: 48 8b 00 mov (%rax),%rax 40145e: eb 00 jmp 401460 <__va_read_from_stack+0x112> 401460: 48 89 ec mov %rbp,%rsp 401463: 5d pop %rbp 401464: c3 ret Дизассемблирование раздела .fini: 0000000000401468 <_fini>: 401468: f3 0f 1e fa endbr64 40146c: 48 83 ec 08 sub $0x8,%rsp 401470: 48 83 c4 08 add $0x8,%rsp 401474: c3 ret me@me-Aspire-5742G:~/Документы/rusi/rusi$
me@me-Aspire-5742G:~/Документы/rusi/rusi$ objdump -d привет_gcc привет_gcc: формат файла elf64-x86-64 Дизассемблирование раздела .init: 0000000000401000 <_init>: 401000: f3 0f 1e fa endbr64 401004: 48 83 ec 08 sub $0x8,%rsp 401008: 48 8b 05 d1 2f 00 00 mov 0x2fd1(%rip),%rax # 403fe0 <__gmon_start__> 40100f: 48 85 c0 test %rax,%rax 401012: 74 02 je 401016 <_init+0x16> 401014: ff d0 call *%rax 401016: 48 83 c4 08 add $0x8,%rsp 40101a: c3 ret Дизассемблирование раздела .plt: 0000000000401020 <puts@plt-0x10>: 401020: ff 35 ca 2f 00 00 push 0x2fca(%rip) # 403ff0 <_GLOBAL_OFFSET_TABLE_+0x8> 401026: ff 25 cc 2f 00 00 jmp *0x2fcc(%rip) # 403ff8 <_GLOBAL_OFFSET_TABLE_+0x10> 40102c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000401030 <puts@plt>: 401030: ff 25 ca 2f 00 00 jmp *0x2fca(%rip) # 404000 <puts@GLIBC_2.2.5> 401036: 68 00 00 00 00 push $0x0 40103b: e9 e0 ff ff ff jmp 401020 <_init+0x20> Дизассемблирование раздела .text: 0000000000401040 <main>: 401040: 48 83 ec 08 sub $0x8,%rsp 401044: bf 04 20 40 00 mov $0x402004,%edi 401049: e8 e2 ff ff ff call 401030 <puts@plt> 40104e: 31 c0 xor %eax,%eax 401050: 48 83 c4 08 add $0x8,%rsp 401054: c3 ret 401055: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40105c: 00 00 00 40105f: 90 nop 0000000000401060 <_start>: 401060: f3 0f 1e fa endbr64 401064: 31 ed xor %ebp,%ebp 401066: 49 89 d1 mov %rdx,%r9 401069: 5e pop %rsi 40106a: 48 89 e2 mov %rsp,%rdx 40106d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 401071: 50 push %rax 401072: 54 push %rsp 401073: 45 31 c0 xor %r8d,%r8d 401076: 31 c9 xor %ecx,%ecx 401078: 48 c7 c7 40 10 40 00 mov $0x401040,%rdi 40107f: ff 15 53 2f 00 00 call *0x2f53(%rip) # 403fd8 <__libc_start_main@GLIBC_2.34> 401085: f4 hlt 401086: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40108d: 00 00 00 0000000000401090 <_dl_relocate_static_pie>: 401090: f3 0f 1e fa endbr64 401094: c3 ret 401095: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 40109c: 00 00 00 40109f: 90 nop 00000000004010a0 <deregister_tm_clones>: 4010a0: b8 18 40 40 00 mov $0x404018,%eax 4010a5: 48 3d 18 40 40 00 cmp $0x404018,%rax 4010ab: 74 13 je 4010c0 <deregister_tm_clones+0x20> 4010ad: b8 00 00 00 00 mov $0x0,%eax 4010b2: 48 85 c0 test %rax,%rax 4010b5: 74 09 je 4010c0 <deregister_tm_clones+0x20> 4010b7: bf 18 40 40 00 mov $0x404018,%edi 4010bc: ff e0 jmp *%rax 4010be: 66 90 xchg %ax,%ax 4010c0: c3 ret 4010c1: 0f 1f 40 00 nopl 0x0(%rax) 4010c5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 4010cc: 00 00 00 00 00000000004010d0 <register_tm_clones>: 4010d0: be 18 40 40 00 mov $0x404018,%esi 4010d5: 48 81 ee 18 40 40 00 sub $0x404018,%rsi 4010dc: 48 89 f0 mov %rsi,%rax 4010df: 48 c1 ee 3f shr $0x3f,%rsi 4010e3: 48 c1 f8 03 sar $0x3,%rax 4010e7: 48 01 c6 add %rax,%rsi 4010ea: 48 d1 fe sar $1,%rsi 4010ed: 74 11 je 401100 <register_tm_clones+0x30> 4010ef: b8 00 00 00 00 mov $0x0,%eax 4010f4: 48 85 c0 test %rax,%rax 4010f7: 74 07 je 401100 <register_tm_clones+0x30> 4010f9: bf 18 40 40 00 mov $0x404018,%edi 4010fe: ff e0 jmp *%rax 401100: c3 ret 401101: 0f 1f 40 00 nopl 0x0(%rax) 401105: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 40110c: 00 00 00 00 0000000000401110 <__do_global_dtors_aux>: 401110: f3 0f 1e fa endbr64 401114: 80 3d fd 2e 00 00 00 cmpb $0x0,0x2efd(%rip) # 404018 <__TMC_END__> 40111b: 75 13 jne 401130 <__do_global_dtors_aux+0x20> 40111d: 55 push %rbp 40111e: 48 89 e5 mov %rsp,%rbp 401121: e8 7a ff ff ff call 4010a0 <deregister_tm_clones> 401126: c6 05 eb 2e 00 00 01 movb $0x1,0x2eeb(%rip) # 404018 <__TMC_END__> 40112d: 5d pop %rbp 40112e: c3 ret 40112f: 90 nop 401130: c3 ret 401131: 0f 1f 40 00 nopl 0x0(%rax) 401135: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 40113c: 00 00 00 00 0000000000401140 <frame_dummy>: 401140: f3 0f 1e fa endbr64 401144: eb 8a jmp 4010d0 <register_tm_clones> Дизассемблирование раздела .fini: 0000000000401148 <_fini>: 401148: f3 0f 1e fa endbr64 40114c: 48 83 ec 08 sub $0x8,%rsp 401150: 48 83 c4 08 add $0x8,%rsp 401154: c3 ret me@me-Aspire-5742G:~/Документы/rusi/rusi$
📌 Еще один тестовый пример на плюсах
класс Фигура { открыт: вирт пусто описать() { std::cout << "Фигура" << std::endl; } вирт ~Фигура() {} }; класс Круг : открыт Фигура { открыт: двойн радиус; Круг(двойн р) : радиус(р) {} пусто описать() override { std::cout << "Круг радиусом " << радиус << std::endl; } }; шаблон<имя_типа T> T удвоить(T значение) { возврат значение * 2; } цел главн() { Круг к(5.0); к.описать(); std::cout << "Удвоенное 21 = " << удвоить(21) << std::endl; std::cout << "Удвоенное 1.5 = " << удвоить(1.5) << std::endl; возврат 0; }
me@me-Aspire-5742G:/usr/local/gcc-rus/bin/g++ -std=c++20 /tmp/руси_плюс_плюс.cpp -o /tmp/руси_плюс_плюс 2>&1 | head -30 me@me-Aspire-5742G:~/RUSI-build/rgcc/тесты$ /tmp/руси_плюс_плюс Круг радиусом 5 Удвоенное 21 = 42 Удвоенное 1.5 = 3
Промпты для анализа статьи
Тем, кто хочет извлечь дополнительную информацию для размышлений или почерпнуть филосовских и технических взглядов на проект. Загружаем текст статьи в контекст и просим:
Оценку с позиции кибернетики.
Анализ с позиции ТРИЗ.
Провести анализ текста с позиций эвристики.
Анализ написанного с позиции теории систем.
Оценить написанное с позиции философии open source.
Оценка с позиций аналитической философии техники.
Послесловие
Этот проект начинался как спортивный интерес. «Смогу ли я одолеть GCC?» Смог, получилось, заработало. И результат радует.
Из нишевого форка chibicc выросли три оригинальных синтаксиса: Руси (Си), Руси++ (C++), Объектный-Руси (Objective-C). Все три - промышленного уровня, на базе GCC 14.2.
Это не «русский язык программирования с нуля». Это теперь двойной Си. Это билингвальный интерфейс к существующему языку. Не «вместо», а «вместе».