DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 01.06.25 21:26
Оценка:
Здравствуйте!

В свои некоторые плюсовые либы и проекты хочу присунуть возможность отключать некоторые фичи при помощи препроцессора.

Напрашивается имя DISABLE_XXX, где 'XXX' — отключаемая фича или даже библиотека какая-то, со всеми её фичами.

С другой стороны в либе 'XXX' могут быть свои опции, с префиксом XXX_ЧЕГО_ТО_ТАМ.

DISABLE_XXX — универсальный формат макроса для всех проектов, условно говоря, в конфиге проекта пишем DISABLE_AAA, DISABLE_BBB, DISABLE_CCC — и сразу понятно, что фичи/либы 'AAA', 'BBB', 'CCC' отключены, понятно, что отключено (в смысле, что выкл), и понятно, что отключено ( в смысле, какая фича/либа).

Для фич, которые по умолчанию выключены, можно использовать макро ENABLE_XXX. В идеале, если пользователь фичи/библиотеки не хочет полагаться на умолчательное поведение, либа/фича должна обрабатывать как DISABLE_XXX, так и ENABLE_XXX, и проверять DISABLE_XXX и ENABLE_XXX на конфликтность.

В либах же, кроме отключения фич, могут быть и настройки каких-то опций, поэтому было бы логично сделать настроечные макро с именами вида XXX_*, где XXX — имя либы, а '*' — имя фичи и что делаем с ней — включаем/выключаем/как-то настраиваем.

Отдельно в прикладном проекте тоже могут быть какие-то настройки, их тоже было бы удобно настраивать через 'DISABLE_ФИЧА_ПРОЕКТА'.

Мне такая семантика вполне нравится, но, может, у кого-то есть 'контра' против такого подхода?


Пример:

Есть либа marty::BigInt для произвольной длины целых. Она умеет конвертировать marty::BigInt в marty::Decimal (и поэтому сама подключает соответствующие хидеры), но поддержку marty::Decimal в marty::BigInt можно отключить, задав макро DISABLE_MARTY_DECIMAL. Правда, это отключит marty::Decimal и по всему проекту, но я не очень понимаю, зачем в разных частях одного проекта так делать. Опции DISABLE_XXX/ENABLE_XXX предполагаются глобальными для проекта (конкретной цели, не обязательно для всего "solution").

Замечу, что раз либа marty::BigInt зависит от marty::Decimal, то обработать DISABLE_MARTY_DECIMAL/ENABLE_MARTY_DECIMAL должна она, как и их непротиворечивость.

Другой вариант — marty::Decimal сама обрабатывает DISABLE_MARTY_DECIMAL/ENABLE_MARTY_DECIMAL, и может подсовывать пустоту, если задан макрос DISABLE_MARTY_DECIMAL. Это удобно тем, что не надо самому в использующей marty::Decimal либе что-то проверять, но тогда надо безусловно инклюдить "marty_decimal/marty_decimal.h", а значит, тащить marty::Decimal в зависимости проекта, а этого хотелось бы избежать.

Есть либа marty::Decimal, она сама по себе, и ничего в ней отключать нет необходимости (но какими-то фичами было бы неплохо порулить через MARTY_DECIMAL_*, например: MARTY_DECIMAL_DEFAULT_PRECISION — количество десятичных знаков после запятой, которое будет использовано при делении — в остальных случаях точность не нужна).

Есть либа marty::format для форматирования, она поддерживает по умолчанию как marty::BigInt, так и marty::Decimal.
Она проверяет DISABLE_MARTY_DECIMAL/ENABLE_MARTY_DECIMAL, DISABLE_MARTY_BIGINT/ENABLE_MARTY_BIGINT на непротиворечивость, подключает при необходимости нужные хидеры, и имплементирует или нет необходимые фичи.

Есть идеи?
Маньяк Робокряк колесит по городу
Re: DISABLE_XXX vs XXX_DISABLE
От: Osaka  
Дата: 02.06.25 05:55
Оценка:
M>DISABLE_XXX — универсальный формат
Особенно универсально смотрится в узком комбобоксе.
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re[2]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 11:14
Оценка:
Здравствуйте, Osaka, Вы писали:

M>>DISABLE_XXX — универсальный формат

O>Особенно универсально смотрится в узком комбобоксе.

А зачем смотреть в узком комбобоксе? Смотри конфиги в текстовом редакторе
Маньяк Робокряк колесит по городу
Re[2]: DISABLE_XXX vs XXX_DISABLE
От: Нomunculus Россия  
Дата: 02.06.25 11:15
Оценка:
Здравствуйте, Osaka, Вы писали:

M>>DISABLE_XXX — универсальный формат

O>Особенно универсально смотрится в узком комбобоксе.

При длинном XXX любая комбинация будет проблемой в узком комбобоксе
Re[3]: DISABLE_XXX vs XXX_DISABLE
От: Osaka  
Дата: 02.06.25 11:21
Оценка:
M>А зачем смотреть в узком комбобоксе? Смотри конфиги в текстовом редакторе
И не только в комбобоксе, это же касается контекстых меню в редакторе иходника, поиска с клавиатуры во всяких TreeView и т. п.
Иногда заставляют что-то делать в чужой программе, и её невозможно поменять.
Поэтому начинать идентификаторы с одинаковой повторяющейся части — плохая практика.
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Отредактировано 02.06.2025 11:34 Osaka . Предыдущая версия . Еще …
Отредактировано 02.06.2025 11:33 Osaka . Предыдущая версия .
Re[3]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 11:25
Оценка:
Здравствуйте, Нomunculus, Вы писали:

M>>>DISABLE_XXX — универсальный формат

O>>Особенно универсально смотрится в узком комбобоксе.

Н>При длинном XXX любая комбинация будет проблемой в узком комбобоксе


Ещё один про комбобокс... Вот откуда он взялся? И чем лучше в узком комбобоксе [MARTY_DECI]MAL_DISABLE, чем [DISABLE_MA]RTY_DECIMAL?
Маньяк Робокряк колесит по городу
Re[4]: DISABLE_XXX vs XXX_DISABLE
От: Нomunculus Россия  
Дата: 02.06.25 11:26
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, Нomunculus, Вы писали:


M>>>>DISABLE_XXX — универсальный формат

O>>>Особенно универсально смотрится в узком комбобоксе.

Н>>При длинном XXX любая комбинация будет проблемой в узком комбобоксе


M>Ещё один про комбобокс... Вот откуда он взялся? И чем лучше в узком комбобоксе [MARTY_DECI]MAL_DISABLE, чем [DISABLE_MA]RTY_DECIMAL?


Я ж не тебе ответил, а ему. У него спрашивай что за комбобоксы у него
Re: DISABLE_XXX vs XXX_DISABLE
От: so5team https://stiffstream.com
Дата: 02.06.25 11:28
Оценка:
Здравствуйте, Marty

Есть подозрение, что в современных C++ных реалиях вся эта кухня с символами препроцессора DISABLE/ENABLE_XXX еще работает, когда все зависимости подключаются к проекту напрямую в виде исходников и вы полностью контролируете все параметры компиляции как проекта, так и всех его зависимостей.

Но вот когда в дело вступают инструменты вроде Conan и vcpkg, в которых библиотеки собираются с опциями, которые задает тот, кто опакечивает библиотеку, то все эти DISABLE/ENABLE_XXX могут стать палками в колесах. Не то, что бы обязательно будут, но могут.

Засунул кто-то вашу Marty::BigInt с неким ENABLE_XXX в vcpkg, а пользователь захотел задействовать DISABLE_XXX.

Особенно весело может быть когда в библиотеке в завсисимости от ENABLE_XXX меняются размеры каких-то полей у объектов.

Вот здесь интересные рассуждения на сей счет можно найти: https://vector-of-bool.github.io/2020/10/04/lib-configuration.html
Re[2]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 11:50
Оценка:
Здравствуйте, so5team, Вы писали:

S>Есть подозрение, что в современных C++ных реалиях вся эта кухня с символами препроцессора DISABLE/ENABLE_XXX еще работает, когда все зависимости подключаются к проекту напрямую в виде исходников и вы полностью контролируете все параметры компиляции как проекта, так и всех его зависимостей.


Да


S>Но вот когда в дело вступают инструменты вроде Conan и vcpkg, в которых библиотеки собираются с опциями, которые задает тот, кто опакечивает библиотеку, то все эти DISABLE/ENABLE_XXX могут стать палками в колесах. Не то, что бы обязательно будут, но могут.


Да


S>Засунул кто-то вашу Marty::BigInt с неким ENABLE_XXX в vcpkg, а пользователь захотел задействовать DISABLE_XXX.


Без проблем, она у меня хидер-онли


S>Особенно весело может быть когда в библиотеке в завсисимости от ENABLE_XXX меняются размеры каких-то полей у объектов.


Да


S>Вот здесь интересные рассуждения на сей счет можно найти: https://vector-of-bool.github.io/2020/10/04/lib-configuration.html


Да ничего особо интересного, всё то же самое.
И там нет предложения, как не настраивать библиотеки, а как управлять зависимостями библиотек, как это нужно мне

А что предлагаешь ты?
Маньяк Робокряк колесит по городу
Re[3]: DISABLE_XXX vs XXX_DISABLE
От: so5team https://stiffstream.com
Дата: 02.06.25 12:01
Оценка:
Здравствуйте, Marty, Вы писали:

M>А что предлагаешь ты?


Использовать голову, как минимум.

Но судя по примерам говнокода, который можно у видеть у вас в репозиториях, с этим возможны разные варианты, в том числе и не самые оптимистические.
Re: DISABLE_XXX vs XXX_DISABLE
От: RonWilson Россия  
Дата: 02.06.25 12:02
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>В свои некоторые плюсовые либы и проекты хочу присунуть возможность отключать некоторые фичи при помощи препроцессора.


M>Напрашивается имя DISABLE_XXX, где 'XXX' — отключаемая фича или даже библиотека какая-то, со всеми её фичами.


можно не изобретать enable/disable, а сделать как многие делают в configure/makefile: USE_SSL, USE_ZIP, USE_CHATGPT, USE_STACKOVERFLOW. Можно делать и как в cmake, например: cmake /DUSE_CHATGPT=1 /DUSE_STACKOVERFLOW=1 /DUSE_OWN_BRAIN=0
Re[4]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 12:04
Оценка:
Здравствуйте, so5team, Вы писали:

M>>А что предлагаешь ты?


S>Использовать голову, как минимум.


Конкретно есть что сказать, или лишь бы что ляпнуть?


S>Но судя по примерам говнокода, который можно у видеть у вас в репозиториях,


А что не так с кодом?
А где можно посмотреть на ваш божественный код?


S>с этим возможны разные варианты, в том числе и не самые оптимистические.


Давай, выкладывай
Маньяк Робокряк колесит по городу
Re[2]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 12:07
Оценка:
Здравствуйте, RonWilson, Вы писали:

M>>В свои некоторые плюсовые либы и проекты хочу присунуть возможность отключать некоторые фичи при помощи препроцессора.


M>>Напрашивается имя DISABLE_XXX, где 'XXX' — отключаемая фича или даже библиотека какая-то, со всеми её фичами.


RW>можно не изобретать enable/disable, а сделать как многие делают в configure/makefile: USE_SSL, USE_ZIP, USE_CHATGPT, USE_STACKOVERFLOW. Можно делать и как в cmake, например: cmake /DUSE_CHATGPT=1 /DUSE_STACKOVERFLOW=1 /DUSE_OWN_BRAIN=0


Я думал об этом, но есть такой нюанс — я хочу по умолчанию использовать библиотеки, чтобы ничего не требовалось задавать вообще, и отключать уже тогда, когда их использование мешает пользователю — например, он хочет запихать либу в контроллер, и часть зависимых либ там не нужна или даже мешает.
Маньяк Робокряк колесит по городу
Re[3]: DISABLE_XXX vs XXX_DISABLE
От: RonWilson Россия  
Дата: 02.06.25 12:15
Оценка:
Здравствуйте, Marty, Вы писали:

M>Я думал об этом, но есть такой нюанс — я хочу по умолчанию использовать библиотеки, чтобы ничего не требовалось задавать вообще, и отключать уже тогда, когда их использование мешает пользователю — например, он хочет запихать либу в контроллер, и часть зависимых либ там не нужна или даже мешает.


так никто же не мешает сделать в коде что-то вроде — будет по-умолчанию:
#ifndef USE_HUMAN_BRAIN
#define USE_HUMAN_BRAIN 1
#endif
Re[5]: DISABLE_XXX vs XXX_DISABLE
От: so5team https://stiffstream.com
Дата: 02.06.25 12:22
Оценка:
Здравствуйте, Marty, Вы писали:

S>>Использовать голову, как минимум.


M>Конкретно есть что сказать, или лишь бы что ляпнуть?


Есть: раз потенциально символы препроцессора могут вести к проблемам, то хорошо бы найти способ их вообще не использовать.

Например, если автоматическая конвертация marty::BigInt в marty::Decimal опциональна, то вынести это самую конвертацию куда-то отдельно. Хоть в отдельный заголовочный файл внутри marty::BigInt, хоть в отдельную библиотеку.

S>>Но судя по примерам говнокода, который можно у видеть у вас в репозиториях,


M>А что не так с кодом?


Местами он говно. Сопровождать такое можно пожелать только кровному врагу. Тащить такое к себе в проект с оглядкой на то, что если автор внезапно помрет от очередного ковида, то сопровождать придется самому не просто страшно, а очень страшно.

S>>с этим возможны разные варианты, в том числе и не самые оптимистические.


M>Давай, выкладывай


Варианты? Например, вы слишком сильно интеллектуально развиты, чтобы делать простые удобные вещи для простых людей. Вам не сложно написать и сопровождать шаблон функции на 700 строк. Значит ваша целевая аудитория такие же очень умные люди, как и вы, коих очень и очень мало.

Либо, напростив, вы недостаточно умны, чтобы понять, что не должно быть шаблона функции на 700 строк, и не смочь найти вариант от этого избавиться.

Оба варианта так себе.
Re[6]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 12:30
Оценка:
Здравствуйте, so5team, Вы писали:


S>Есть: раз потенциально символы препроцессора могут вести к проблемам, то хорошо бы найти способ их вообще не использовать.


Пример проблемы можно?


S>Например, если автоматическая конвертация marty::BigInt в marty::Decimal опциональна, то вынести это самую конвертацию куда-то отдельно. Хоть в отдельный заголовочный файл внутри marty::BigInt, хоть в отдельную библиотеку.


Каким образом? Вполне допускаю, что я плохо знаю плюсы, но как сделать автоматическое преобразование без конструкторов и/или оператором приведения типа — я не знаю. И не вижу способа вынести преобразование за пределы класса


S>>>Но судя по примерам говнокода, который можно у видеть у вас в репозиториях,


M>>А что не так с кодом?


S>Местами он говно. Сопровождать такое можно пожелать только кровному врагу. Тащить такое к себе в проект с оглядкой на то, что если автор внезапно помрет от очередного ковида, то сопровождать придется самому не просто страшно, а очень страшно.


В чем проблема? Ну, если совсем тупой, то можно разок пройтись отладчиком, и всё станет понятно


S>Варианты? Например, вы слишком сильно интеллектуально развиты, чтобы делать простые удобные вещи для простых людей. Вам не сложно написать и сопровождать шаблон функции на 700 строк. Значит ваша целевая аудитория такие же очень умные люди, как и вы, коих очень и очень мало.


S>Либо, напростив, вы недостаточно умны, чтобы понять, что не должно быть шаблона функции на 700 строк, и не смочь найти вариант от этого избавиться.


S>Оба варианта так себе.


Не вижу особых проблем с функцией на 700 строк. Ещё претензии есть?
Маньяк Робокряк колесит по городу
Re[4]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 12:32
Оценка:
Здравствуйте, RonWilson, Вы писали:

M>>Я думал об этом, но есть такой нюанс — я хочу по умолчанию использовать библиотеки, чтобы ничего не требовалось задавать вообще, и отключать уже тогда, когда их использование мешает пользователю — например, он хочет запихать либу в контроллер, и часть зависимых либ там не нужна или даже мешает.


RW>так никто же не мешает сделать в коде что-то вроде — будет по-умолчанию:

RW>
RW>#ifndef USE_HUMAN_BRAIN
RW>#define USE_HUMAN_BRAIN 1
RW>#endif
RW>


Не понял, получается, что USE_HUMAN_BRAIN включен всегда, чтобы ты в опциях сборки не задал
Маньяк Робокряк колесит по городу
Re[7]: DISABLE_XXX vs XXX_DISABLE
От: so5team https://stiffstream.com
Дата: 02.06.25 12:36
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>А что не так с кодом?


S>>Местами он говно. Сопровождать такое можно пожелать только кровному врагу. Тащить такое к себе в проект с оглядкой на то, что если автор внезапно помрет от очередного ковида, то сопровождать придется самому не просто страшно, а очень страшно.


M>В чем проблема?


В сложности.

M>Ну, если совсем тупой


то проще послать тов.Marty вдоль как с его разработками, так и с просьбой придумать как ему поступать в его разработках.

M>Не вижу особых проблем с функцией на 700 строк.


В этом нет сомнений.
Re[5]: DISABLE_XXX vs XXX_DISABLE
От: RonWilson Россия  
Дата: 02.06.25 12:46
Оценка:
Здравствуйте, Marty, Вы писали:

RW>>так никто же не мешает сделать в коде что-то вроде — будет по-умолчанию:

RW>>
RW>>#ifndef USE_HUMAN_BRAIN
RW>>#define USE_HUMAN_BRAIN 1
RW>>#endif
RW>>


M>Не понял, получается, что USE_HUMAN_BRAIN включен всегда, чтобы ты в опциях сборки не задал


давно на Сы не писал, ну как-то так см. OPENSSL_NO_ENGINE
Re[6]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 12:54
Оценка:
Здравствуйте, RonWilson, Вы писали:


RW>давно на Сы не писал, ну как-то так см. OPENSSL_NO_ENGINE


Ну так это и получается ровно то, что я предлагаю, только в моей нотации это будет выгладеть как
DISABLE_OPENSSL_ENGINE/OPENSSL_ENGINE_DISABLE
Маньяк Робокряк колесит по городу
Re[7]: DISABLE_XXX vs XXX_DISABLE
От: RonWilson Россия  
Дата: 02.06.25 12:56
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, RonWilson, Вы писали:



RW>>давно на Сы не писал, ну как-то так см. OPENSSL_NO_ENGINE


M>Ну так это и получается ровно то, что я предлагаю, только в моей нотации это будет выгладеть как

M>DISABLE_OPENSSL_ENGINE/OPENSSL_ENGINE_DISABLE

зачем это DISABLE? WITH_SSL, USE_HIGH_COMPRESSION, NO_MOVE_CTORS и так далее — сразу и по сути, без этих enable/disable/default
Re[8]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 13:15
Оценка:
Здравствуйте, RonWilson, Вы писали:

RW>>>давно на Сы не писал, ну как-то так см. OPENSSL_NO_ENGINE


M>>Ну так это и получается ровно то, что я предлагаю, только в моей нотации это будет выгладеть как

M>>DISABLE_OPENSSL_ENGINE/OPENSSL_ENGINE_DISABLE

RW>зачем это DISABLE? WITH_SSL, USE_HIGH_COMPRESSION, NO_MOVE_CTORS и так далее — сразу и по сути, без этих enable/disable/default


Да похрен, DISABLE или NO. Можно писать USE_XXX/NO_XXX — это не так counterpart, как ENABLE_XXX/DISABLE_XXX, но пофик. Просто хочу выработать единое для себя соглашение, чтобы не было чехарды в разных места
Маньяк Робокряк колесит по городу
Re[9]: DISABLE_XXX vs XXX_DISABLE
От: RonWilson Россия  
Дата: 02.06.25 13:53
Оценка:
Здравствуйте, Marty, Вы писали:

M>Да похрен, DISABLE или NO. Можно писать USE_XXX/NO_XXX — это не так counterpart, как ENABLE_XXX/DISABLE_XXX, но пофик. Просто хочу выработать единое для себя соглашение, чтобы не было чехарды в разных места


ну тогда уж ENABLE/DISABLE_FEATURE_000045 и табличку с фичами, будет единообразно
Re[10]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 14:20
Оценка:
Здравствуйте, RonWilson, Вы писали:

M>>Да похрен, DISABLE или NO. Можно писать USE_XXX/NO_XXX — это не так counterpart, как ENABLE_XXX/DISABLE_XXX, но пофик. Просто хочу выработать единое для себя соглашение, чтобы не было чехарды в разных места


RW>ну тогда уж ENABLE/DISABLE_FEATURE_000045 и табличку с фичами, будет единообразно


Зачем номер, просто название фичи
Маньяк Робокряк колесит по городу
Re[5]: DISABLE_XXX vs XXX_DISABLE
От: pilgrim_ Россия  
Дата: 02.06.25 19:51
Оценка: -1
Здравствуйте, Marty, Вы писали:

RW>>так никто же не мешает сделать в коде что-то вроде — будет по-умолчанию:

RW>>
RW>>#ifndef USE_HUMAN_BRAIN
RW>>#define USE_HUMAN_BRAIN 1
RW>>#endif
RW>>


M>Не понял, получается, что USE_HUMAN_BRAIN включен всегда, чтобы ты в опциях сборки не задал


3 состояния:
1) USE_HUMAN_BRAIN не определён — используется настройка по умолчанию (значение 0 или 1)
2) Определён с USE_HUMAN_BRAIN = 0 — отключено
3) Определён с USE_HUMAN_BRAIN = 1 — включено
Re[6]: DISABLE_XXX vs XXX_DISABLE
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.06.25 19:55
Оценка:
Здравствуйте, pilgrim_, Вы писали:

M>>Не понял, получается, что USE_HUMAN_BRAIN включен всегда, чтобы ты в опциях сборки не задал


_>3 состояния:

_>1) USE_HUMAN_BRAIN не определён — используется настройка по умолчанию (значение 0 или 1)
_>2) Определён с USE_HUMAN_BRAIN = 0 — отключено
_>3) Определён с USE_HUMAN_BRAIN = 1 — включено

Да, так получается, согласен. Просто как-то привык проверять наличие определенного макроса, а не наличие и его значение
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.