LINUX.ORG.RU

Библиотека для форматирования текста в Си

 ,


1

2

Привет, ЛОР!

Скажи, а есть ли что-то типа https://fmt.dev, но на чистом Си? Об printf() я слегка задолбался. Из требований: никаких внешних вызовов (будет работать без ОС), хочу тупо форматирование в строку а-ля snprintf(), но без сраных процентов и угадывания строчки к типу.

Традиционные касты @firkax @Iron_Bug

★★★★★

Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от Iron_Bug

программы на сишке никогда не были интерпретатором.

программа с printf – это интерпретатор форматных строк. этот интерпретатор сидит в рантайме, в реализации printf. и вместо обычного компилируемого кода типа отдельными функциями как в модуле-2 – мы получаем интерпретатор форматных printf-выражений, а не одну простую конкретную функцию.

терминал

а зачем например, реализация всего этого интерпретататора ESC-кодов в ядре? вот в plan9 например, её в userland перенесли. в ядре никаких tty консолей нету, в чистом юзерленде.

сама графическая библиотека, rio вместо иксов – тоже написана как мультиплексор и запускается сама в себе типа Xnest. и не требует какого-то (если вообще) сложно кода в ядре.

а в инферно интерпретатор VT100 и telnet вообще на tk/rc шелле сделали: inferno-os/appl/wm/vt.b и inferno-os/appl/wm/telnet.b

а вот например, многопользовательская рисовалка метапроговая : inferno-os/appl/demo/whiteboard и ещё что-то такое клиент-серверное здесь: appl/wm/drawmux , inferno-os/appl/spree https://github.com/bhgv/Inferno-OS_Android/tree/master/inferno-os/appl/demo/spree

а вот например, простой чятик клиент-сервер: inferno-os/appl/demo/chat

впрочем, из практичного Plan9 надо наверное смотреть Harvey OS. они там перепортировали его чтобы оно из-под clang или gcc из-под линакса собиралось, и APEX posix-окружение Plan9 под это дело немного допилили. это наверное самый практичный Plan9 дистрибутив после самобытного Plan9front сейчас будет.

правда, дальше они совсем упоролись и решили всё на Rust-е переписать в R9 OS

anonymous
()
Ответ на: комментарий от Iron_Bug

кстати, вот веб-браузер под Inferno: Charon inferno-os/appl/charon на Limbo. ещё есть читалка eBook OEBS.xml inferno-os/appl/ebook

современный мутный HTML5 со спецификацией на 10500 страниц оно не поддерживает, разумеется – чуть более чем полностью.

там местами кажется на lexx/yacc парсер HTML4 strict DTD.

полагаю что кучку quirk-ов в современном браузере тупо не реализовывали.

в общем, в целом парсер довольно компактный и аккуратный.

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

допилил бы его кто. до ACID тестов, например.

хотя там JS вылезет или CSS или DOM или ещё что-то подобное.

anonymous
()
Ответ на: комментарий от anonymous

я тоже собираю из сорцов, и тоже под void. под hermes и janet.

я его не просто собираю. я его патчу. и у меня очень многие библиотеки/софтины довольно мощно пропатчены. много чего вырезано, кое-то добавлено. это кастомная сборка системы под свои хотелки. поэтому у меня нет времени собирать что-то ещё. да и не нужно: на рабочих машинах и моих серверах стоит моя сборка и меня это устраивает.

про лисп мне больше не надо. для меня вопрос с ним закрыт и не стоит вообще никаким образом. и план9 мне неинтересен. я с ним не работаю и я ни разу не видела, чтобы кто-то с ним работал.

про паскаль - да, я ещё в детстве возненавидела begin-end'ы (в лицее преподавали какой-то паскалеобразный язык) и когда на горизонте появился Си, я вздохнула с облегчением и сразу перешла на него. это просто огромная экономия ресурсов и гораздо лучшая читабельность кода. ну и в паскале много странностей типа нумерации массивов с 1 (это ужасно) и неудобной работы с указателями и адресами. в общем, Си рулит и именно поэтому столько софта написано на нём, а не на паскале.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от Shushundr

как в паскале же. то есть, как в модуле-2. то есть, по одной конкретной функции на каждый тип. кажется, был какой-то итальянский конпелятор модулы-2 который в сишку всё кроссконпелировал. там и tk без tcl, и sdl и ч0рт лысый в комплекте – все сишные библиотечки. так вот, они там если и делали какой-то принтф то в итоге все в конкретные типы во время конпеляции конпелировалось.

вот в D например, printf правильный. на CTFE функциях. безо всякого недоинтерпретатора.

а допустим у тебя ещё sscanf есть. и срыв стека. и нету никакого typeinfo во время конпеляции. тогда это уже конпелятор недоинтерпретатора непонятно чего получаеццо. чистая брейнфак машина на срывах стекофф.

…и конпелируемые подфункции метапроговыя, переписывающще саоё себя на себе…

anonymous
()
Ответ на: комментарий от Shushundr

собсно, дапустим printf недоинтерпретатор (вкупе вместе со sscanf конпелятором) являеццо конпелятором какой-то весьма конкретной блямбды. тогда энта блямбда является метациклическим недоинтерпретатором какой-то недоделанной лисп-машины метапроговой, самоё себя на себе — и туда можно пропихнуть что угодно, даже невпихуемое.

anonymous
()
Ответ на: комментарий от Iron_Bug

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

например, кодогенерировали бы на лиспе, а не на пистоне (ну хоть Nim взяли бы конпелируемый через сишку, а не пистон, же ну!) или например cl-python или подобное.

вообче, там символического калькулюсе теории даже и не пахнет. немодно и немолодечно типа.

например, был такой Cyc / OpenCyc. где формат представления фреймов KLIF очень даже лисповый. или вот например, attempto на прологе.

с парсером по онтологиям.

а современное чятжпт – энто из пушки по воробьям. сколько там 100 B или уже 1000B параметров в этой порнонейросети нужно сделат ть чтобы оно научилось классифицировать? не лучше ли изначально задавать онтологии на каком-то нечте типа того же KLIF, OpenCyc, CLIPS, например.

не, я поне – маю что была какая-то теорема о фильтре блума булевом и о эквивалентности клеточным автоматам, и о том что как и изомофизм карри-говарда оно всё эквивалентно какой-то рекуррентной нейросети.

то есть, парсер нормального языка программирования даже такого формального скобканутого как лисп или например, пистон можно и на нейросетях напейсать.

я лишь утверждаю что проще и зело полезнее взять нормальный парсер – META II, OMETA, PEG, lex/yacc, LALR, LL(n) ANLTR, например.

а парсить нейросетями – это из пушки по воробьям. может быть конечно, оно и само каким-то непонятным науке образов может всё это нащупать – правильный вариант парсинга, представления знаний. но до этого оно перепробует все остальные (и к цели так и не прийдёт, начнёт бредить. спросишь так его, напиши крестики нолики. а оно тебе кучу бреда вывалит, выпроставшись своими исподниками, в своём нижнем белье – нюхай, разбирай, выродилось вот такое типа. у него типа две представления доски реальности не соответствующие, а ему фсё божья роса, они для него одинаковы. а человек взглянет – и сразу этот бред заметит).

в общем, без нормальной theory of mind, теории представления знаний о мире – фсе эти векторные и почему-то ещё не гипертекстовые биде, фсе эти модели знаний с контекстом пропмта в 4000 токенов професси-анального маразматика — так и будут впадать в маразм и поэтапно начинать бредить.

я вот тут читал некоего про представление психических процессов в p-адических числах. там зело любопытно: тут и фракталы в самоподобных психофизческих процессах, и диски ципфа, и навязчивые состояния типа влюблённости.

и что занятно, для всей этой асинхронной психофизики – хватило всего лишь адельных p-адических для моделирования процессов сознания.

а нейробот и искусственный нейроидиот. он ведь и того же самого – и не могёт.

он ведь гораздо тупее. тупо что вижу – о том и пою.

простых даже логических законов аристотеля типа модусов BARBARA – выводить не могёт.

ну вот и генерирует фсякий бредд.

я вот как то попросил товарищя чятжпт чтобы он мне WG-грамматики алгола-68 сгенерировал. так он бредил обо всём кроме конкретно этого формализма. и LALR, и ANTLR, и чего только не предлагал.

нет, тупо дурак. вот смотри, вот конкретная спецификация алгол-68. прочитай тупо и пойми что написано. реферируй и мне перескажи.

а потом прочитай ещё одну публикацию про грамматику WG-вейнгардена для ады. и по аналогии с логикой этой публикации – роди мне из формальной спеки алгола-68 парсер на сишке, например. или ещё хоть на чём, хоть на том же PL/1 или самом алголе.

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

пару грамматик он попытался исправить но потом замусорился и впал в маразм – начал генерить BNF, ANTLR чё угодно только не то что нужно.

в общем, без адекватной модели представления знаний и модели рассуждений о мире – все эти нейроидиоты такими вот дураками копипастерами и остануца.

исправить тут конечно уже ничего невозможно – жги господь. это да. просто из пушки по воробьям и заколачивание гвоздей микроскопом.
потому что лисп это не модно и не молодечно.

anonymous
()
Ответ на: комментарий от anonymous

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

а что касается всего этого мыльного пузыря с генераторами бреда, то и он лопнет. все мыльные пузыри, сколько бы их ни накачивали, лопались. это лишь вопрос времени. я не тороплюсь, история идёт своим ходом.

Iron_Bug ★★★★★
()
Ответ на: комментарий от anonymous

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

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 2)
Ответ на: комментарий от Iron_Bug

вредоносными как максимум

бредоносным. нейросети – это бредоносное ПО.

хайпим, паймим нефть. типа того.

заметь, что продать это под знаменем лиспа или там форта — сами понимают что не получицца, будет интересно 1.5 анонимусам, примерно как с лисп машинами и зимой искусственного интеллекта или компами пятого поколения когда внезапно халява кончилась, а родили – ну параллельный пролог типа меркьюри, ну типа kyoto embedded common lisp, конпелируемый в сишку, тот же opencyc, например.

а понту-то было – на несколько порядков больше.

поэтому сейчас это впаривают под «современными, молодёжными технологиями». типа пистона и с++. просто это максимум того что современная хипстота сумеет осилить.

в общем-то в reasoning сети экспертов и мультимодальности есть какие-то подвижки, но в целом, блин, как же глупо это всё выглядит даже по сравнению с тем же opencyc, лисп-машинами и прочими форматами представления знаний типа того же ISO 10303 например.

пока на вайбе какой-то хайп попытаются впаривать – там таких существенных прорывов и не будет.

я вот например, даже про нейрофизиологию и естественного идиота не совсем всё понимаю. ну есть какие-то фоновые процессы типа того же олега бахтиярова с психонетикой например, или вот например этот ю. хренников с адельными p-адическими числами психофизических процессов.

но это всё всего лишь модель. тело думает по другому, мозг думает по всякому. а все эти теории это лишь карта а не территория.

и всё равно, даже если двигаться без всякой карты, тупо перебирая очередной хреннилиард параметров – вслепую тут не нащупать.

вот есть например книжка по квантовым контуперам – сет ллойд «программируем вселенную» не привлекая внимания санитаров

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

но там хоть какая-то модель процессов, экспериментов, наблюдателей (которые влияют на эксперимент и декогерируют, лол. ещё у елайзера юдковски про парадоксы квантовой механики на lesswrong.org про это наглядно написано. и у девида дойча в структуре реальности, но там полный мультиверс).

в общем, есть какая-то модель процесса.

а тут модель процесса – типа тупо «суп из топора chatgpt».

типа напиши ему промпт типа SQL запроса только догадайся мол сама как оно его недопонимает, ну вообще ч0рный ящик.

например, тот же грёбаный SQL умеет показать план запроса. умеет показать что случиццо если индексы оптимизировать.

а эта дура с промпт инженерами и того не умеет.

anonymous
()
Ответ на: комментарий от Shushundr

printf по-мне просто идиотская идея изначально

Да? И как надо было правильно?

Я же не гений, откуда я знаю. Я вижу, что получилось плохо. А как надо сделать хорошо - это вопрос на порядок сложней.

vbr ★★★★★
()
Ответ на: комментарий от Shushundr

printf по-мне просто идиотская идея изначально

Да? И как надо было правильно?

Ну, для начала, сделать нормальные строки (в Си их нет). Дальше можно было бы выводить правила форматирования аргумента из его типа, как это делает библиотечка STC, но это потребовало бы хотя бы статического полиморфизма, который в Си прилепили сбоку только в 2010 году (_Generic в C11).

В принципе, это всё можно сделать в Си сегодня – STC тому пример – но проще уже забить и взять Rust, если речь не идёт о коде, доставшемся в наследство.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от vbr

printf(argv[1], i1, i2) - давай, проверяй в рантайме, ага.

Потому что printf исходно пытается решать две разные задачи, и решает их обе плохо.

Первая задача - когда у нас в compile-time известно, что и как нужно отформатировать.

Для решения этой задачи требуются адекватные compile-time макросы, которых в сишечке никогда не было.

Вторая задача - когда форматная строка известна только в run-time. (Это на самом деле основной кейс, а первый - маргинальный.)

У этой задачи два пути, в зависимости от того, умеет ли язык в макросы. Если умеет, то правила верфикации форматной строки выводятся макросами, аналогично как в первом случае.

Если же не умеет, то через костыли, а ля:

safe_printf("%s,%d%,%d", format_string, str, i1, i2);

В библиотеке языка же всё сделано через жопу.

wandrien ★★★
()
Ответ на: комментарий от vbr

Compile safety должно начинаться с дизайна API. А printf по-мне просто идиотская идея изначально, хотя и снискала немалую популярность по непонятной мне причине…

Причина как раз понятна: карго-культ сишечки и синдром утёнка вокруг неё. Посмотри что тут наша Железная Багина пишет: Си – лучший язык, ничего лучше нет, а кто не осилил – тот идиот. Любые аргументы о том, что Си довольно херово спроектирован и полон костылей, которые имели смысл разве что 50 лет назад, отметаются воплями о неосиляторстве. При этом, это уже второе – если не третье – поколение сишников, и они PDP-11 никогда в жизни не видели и не программировали. Т.е. это просто культ страданий, переданный им от дедов-пердедов в маразме.

Вот примерно поэтому printf() и живёт.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от wandrien

Отказываюсь считать себя сишником. Я просто неплохо знаю этот язык и часто на нём пишу. Но по факту, если взять историю из гита всех моих работодателей, я удалил больше кода на Си (и ++) чем написал. Можно ли назвать меня антисишником?

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Я не только про C, printf-подобные функции есть практически во всех языках программирования. Я про эту популярность. То бишь сама идея в массы зашла. А я не понимаю, что в этой идее такого хорошего. Точней понимаю - типа разделение шаблона и данных и всё такое, но неужели нельзя это было получше сделать. Это как регулярные выражения - write-only лапша, которая везде, хотя никто не мешал сделать нормальный DSL.

То, что в C эту идею ещё и невозможно реализовать безопасно, это отдельная проблема…

vbr ★★★★★
()
Последнее исправление: vbr (всего исправлений: 1)
Ответ на: комментарий от vbr

Я не только про C, printf-подобные функции есть практически во всех языках программирования.

Они есть, но они так широко не используются. Сейчас проверил наш жирнейший проект на хачкеле: на 250 килострок кода всего 15 вызовов printf, т.е. один вызов на ~16.5 килострок. В Си этот показатель куда выше будет.

То бишь сама идея в массы зашла. А я не понимаю, что в этой идее такого хорошего.

Ничего хорошего, просто такой интерфейс по началу был многим привычен. Сейчас от него отходят, и форматные строки уже не требуют указания типа.

То, что в C эту идею ещё и невозможно реализовать безопасно, это отдельная проблема…

Ну вот в STC смогли сделать чуть лучше. Уже прогресс. Но в стандартную библиотеку это не попадёт, и подавляющее большинство сишников об этом никогда не узнают, потому как отрицают сторонние библиотеки в принципе.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от vbr

А я не понимаю, что в этой идее такого хорошего.

В какой именно идее? printf-подобные функции это простейший вариант шаблонизатора, который востребован буквально везде.

Без него ты банально не сделаешь поддержку локализации программы.

Дальше в зависимости от возникающих задач, этот шаблонизатор либо обрастает фичами/костылями, либо просто берётся готовый более фичастый шаблонизатор.

Но что в стандартной библиотеке разных ЯП есть базовый шаблонизатор - это хорошо.

Плохо - когда тупо делают копию printf со всем её легаси и ограничениями исходного языка.

wandrien ★★★
()
Ответ на: комментарий от hateyoufeel

Сейчас от него отходят, и форматные строки уже не требуют указания типа.

Да: от форматной строки требует не «тип», а собственно формат. То есть, сколько там нулей после запятой надо в числе и т.п.

А что указывается тип аргумента, это всё от безблагодатности при разработке сишечки и его либы.

wandrien ★★★
()
Ответ на: комментарий от wandrien

У printf() в стиле Си две проблемы:

  • Необходимость указания типа;
  • Невозможность проверить количество аргументов в общем случае.

Про первое я написал выше. Со вторым в сишечке так и останется всё тухло, поскольку нормальных макросов нет.

В общем-то, поэтому сишечку и хочется закопать. С одной стороны это чудовищно примитивный говноязычок с ограничениями из 70х. С другой, в него напихан выгон костылей, которые каждый создаёт ещё проблем (UB кхе кхе).

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от wandrien

Да просто убогий этот шаблонизатор. Зачем мне писать %d, если питон и так знает, что там - число или не число? Почему вообще символ процента? Это же довольно часто встречающийся символ в сообщениях. А лапша вида %2$*1$s вообще введёт в задумчивость любого.

Ты хороший пример выше показал. printf(format, "ds", x, s) - вот так должна выглядеть функция printf на C. Второй параметр обязан быть строковым литералом, который будет проверен компилятором на соответствие последующим типам и будет информацией, которую будет использовать реализация printf для последующего использования аргументов. И это должно быть единственным способом использовать функции с переменным числом аргументов в C.

vbr ★★★★★
()
Ответ на: комментарий от vbr

Да просто убогий этот шаблонизатор.

Между прочим, это Тьюринг-полный шаблонизатор. Крестики-нолики на одном только вызове printf в цикле (ладно, там scanf для ввода ещё есть).

https://github.com/carlini/printf-tac-toe

#include <stdio.h> 

#define N(a)       "%"#a"$hhn"
#define O(a,b)     "%10$"#a"d"N(b)
#define U          "%10$.*37$d"
#define G(a)       "%"#a"$s"
#define H(a,b)     G(a)G(b)
#define T(a)       a a 
#define s(a)       T(a)T(a)
#define A(a)       s(a)T(a)a
#define n(a)       A(a)a
#define D(a)       n(a)A(a)
#define C(a)       D(a)a
#define R          C(C(N(12)G(12)))
#define o(a,b,c)   C(H(a,a))D(G(a))C(H(b,b)G(b))n(G(b))O(32,c)R
#define SS         O(78,55)R "\n\033[2J\n%26$s";
#define E(a,b,c,d) H(a,b)G(c)O(253,11)R G(11)O(255,11)R H(11,d)N(d)O(253,35)R
#define S(a,b)     O(254,11)H(a,b)N(68)R G(68)O(255,68)N(12)H(12,68)G(67)N(67)

char* fmt = O(10,39)N(40)N(41)N(42)N(43)N(66)N(69)N(24)O(22,65)O(5,70)O(8,44)N(
            45)N(46)N    (47)N(48)N(    49)N( 50)N(     51)N(52)N(53    )O( 28,
            54)O(5,        55) O(2,    56)O(3,57)O(      4,58 )O(13,    73)O(4,
            71 )N(   72)O   (20,59    )N(60)N(61)N(       62)N (63)N    (64)R R
            E(1,2,   3,13   )E(4,    5,6,13)E(7,8,9        ,13)E(1,4    ,7,13)E
            (2,5,8,        13)E(    3,6,9,13)E(1,5,         9,13)E(3    ,5,7,13
            )E(14,15,    16,23)    E(17,18,19,23)E(          20, 21,    22,23)E
            (14,17,20,23)E(15,    18,21,23)E(16,19,    22     ,23)E(    14, 18,
            22,23)E(16,18,20,    23)R U O(255 ,38)R    G (     38)O(    255,36)
            R H(13,23)O(255,    11)R H(11,36) O(254    ,36)     R G(    36 ) O(
            255,36)R S(1,14    )S(2,15)S(3, 16)S(4,    17 )S     (5,    18)S(6,
            19)S(7,20)S(8,    21)S(9    ,22)H(13,23    )H(36,     67    )N(11)R
            G(11)""O(255,    25 )R        s(C(G(11)    ))n (G(          11) )G(
            11)N(54)R C(    "aa")   s(A(   G(25)))T    (G(25))N         (69)R o
            (14,1,26)o(    15, 2,   27)o   (16,3,28    )o( 17,4,        29)o(18
            ,5,30)o(19    ,6,31)o(        20,7,32)o    (21,8,33)o       (22 ,9,
            34)n(C(U)    )N( 68)R H(    36,13)G(23)    N(11)R C(D(      G(11)))
            D(G(11))G(68)N(68)R G(68)O(49,35)R H(13,23)G(67)N(11)R C(H(11,11)G(
            11))A(G(11))C(H(36,36)G(36))s(G(36))O(32,58)R C(D(G(36)))A(G(36))SS

#define arg d+6,d+8,d+10,d+12,d+14,d+16,d+18,d+20,d+22,0,d+46,d+52,d+48,d+24,d\
            +26,d+28,d+30,d+32,d+34,d+36,d+38,d+40,d+50,(scanf(d+126,d+4),d+(6\
            -2)+18*(1-d[2]%2)+d[4]*2),d,d+66,d+68,d+70, d+78,d+80,d+82,d+90,d+\
            92,d+94,d+97,d+54,d[2],d+2,d+71,d+77,d+83,d+89,d+95,d+72,d+73,d+74\
            ,d+75,d+76,d+84,d+85,d+86,d+87,d+88,d+100,d+101,d+96,d+102,d+99,d+\
            67,d+69,d+79,d+81,d+91,d+93,d+98,d+103,d+58,d+60,d+98,d+126,d+127,\
            d+128,d+129

char d[538] = {1,0,10,0,10};

int main() {
    while(*d) printf(fmt, arg);
}
hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

LLM: «Библиотека STC (Smart Template Containers) – это небольшая, быстрая и типобезопасная библиотека контейнеров и алгоритмов для языка Си, соответствующая стандарту C99.»
https://github.com/stclib/STC

Shushundr ★★★★★
()
Ответ на: комментарий от hateyoufeel

Невозможность проверить количество аргументов в общем случае.

Для этого есть костылики.

Вот тут в компиле тайме считают количество аргументов макроса:

https://stackoverflow.com/questions/2308243/macro-returning-the-number-of-arguments-it-is-given-in-c

Были вроде бы и другие варианты.

В общем-то, поэтому сишечку и хочется закопать.

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

Не в виде этого убогого препроцессора, но и не в виде нечитаемого языка шаблонов крестов.

А библиотеки-то можно заменить на более адекватные. Проблема в отсутствии средств в ЯП.

А вообще насчёт несовершенств этого мира. У меня тут сегодня телефон получил мажорный апгрейд версии Андроида, в результате чего:

  • Шторка с переключателями выглядит как говно.
  • В уведомлениях и кое-где еще поехала вёрстка.
  • Тайминги анимации съехали, и теперь переключение между приложениями стало в два раза медленнее, что дико бесит. Особенно на фоне того, что большая часть других таймингов адекватная.

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

С ЯП и либами зачастую так же, только их обычно не ломают, а они сразу сделаны через жопу.

К сожалению, большая часть этого нашего айти - страдания и костыли.

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

Не, хруст другую задачу решал.

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

Тогда уж Циклон вспомнить.

Толку-то его вспоминать? Можно тогда C++ вспомнить. Это буквально апгрейд Си.

Если ты под «апгрейдом» имеешь ввиду с сохранением обратной совместимости, то это не имеет большого смысла. Си уже существует, код на Си можно писать на Си.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

На каком из си? Есть с89, с99, с11. Это разные ЯП каг бэ. Точнее, разные диалекты с хорошим уровнем совместимости.

Как _Generic и импорт бинарных значений не создали принципиально новый язык, так и новая макросистема не создаст. Просто поддерживать старые залежи кода станет удобнее.

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

Каждый своё в это вкладывает.

Стопицот альтернатив Си тоже делают «лучший си», и как видно по результатам, у всех своё видение этой ниши.

Впрочем, с телефона неудобно ща писать много текста про своё видение.

wandrien ★★★
()
Ответ на: комментарий от wandrien

На каком из си? Есть с89, с99, с11. Это разные ЯП каг бэ.

Да нет, изменения минимальны. Куда меньше чем между C++98 и 11, например.

Как _Generic и импорт бинарных значений не создали принципиально новый язык, так и новая макросистема не создаст. Просто поддерживать старые залежи кода станет удобнее.

Что значит «поддерживать»? Если мы говорим про код, над которым не ведётся активной разработки, то его не надо сильно поддерживать. Он не упадёт. Если ведётся активная разработка, то лучше сразу другой язык взять.

Стопицот альтернатив Си тоже делают «лучший си», и как видно по результатам, у всех своё видение этой ниши.

Всё так. Только в моём мире это плюс, а не минус. Естественный отбор работает и для языков программирования в том числе. Одна из этих альтернатив в итоге выстрелит. Вот Rust выстрелил, например. Наслаждаемся и машем ручками.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от wandrien

Есть с89, с99, с11

И с23.

Впрочем, с телефона неудобно ща писать много текста

А читать? :)

https://lemire.me/blog/2024/01/21/c23-a-slightly-better-c/

My thoughts so far:

The introduction of constexpr in C will probably help reduce the dependency on macros, which is a good idea generally. Macros work well in C, but when a bug is introduced, it can be difficult get meaningful error messages. It does not happen too often, but in large code bases, it can be a problem.

dataman ★★★★★
()
Ответ на: комментарий от vbr

printf-подобные функции есть практически во всех языках программирования. Я про эту популярность. То бишь сама идея в массы зашла. А я не понимаю, что в этой идее такого хорошего.

Потому что не в сферической вакуумной теории на форуме в интернете, а в реальножизненной ежедневной практике программистам нужен механизм форматирования текстового вывода.

Форматная строка printf’а сотоварищи - это DSL решающий именно эту задачу. Поэтому его притаранили даже в жаву.

Зачем мне писать %d, если питон и так знает, что там - число или не число?

Потому что в реальности нужны не %d и не %s, а % -*.*f% *.5f

Форматная строка printfа - это фактически старший брат-близнец регулярок.

LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Если ты под «апгрейдом» имеешь ввиду с сохранением обратной совместимости, то это не имеет большого смысла. Си уже существует, код на Си можно писать на Си.

Так можно улучшать код на С, переводя его на C++. Просто компиляция компилятором С++ уже увеличивает строгость, не дает поместить в enum a, перечисления из enum b, конверсии строже. Потом уже можно добавлять фишки из С++.

Одна из проблем с Rust у Google, это как раз интеграция с уже существующим кодом.

MOPKOBKA ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Одна из проблем с Rust у Google, это как раз интеграция с уже существующим кодом.

У гугла это код на C++, не на Си. К Си у Rust достаточно простой и приятный FFI, поэтому можно новый код в проект писать на Rust без проблем. А вот интеграция с кодом на C++, особенно где вагоны темплейтов, это ад.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от anonymous

бредоносным. нейросети – это бредоносное ПО.

просто в точку. это слово я возьму на вооружение.

поэтому сейчас это впаривают под «современными, молодёжными технологиями». типа пистона и с++. просто это максимум того что современная хипстота сумеет осилить.

да не могут они осилить плюсы. плюсы в полном объёме - это достаточно страшный зверь. не то, чтобы там что-то непонятно. но там бывает такой синтаксис, что глаза ломаются. на нём можно такое написать, что сам через полгода не поймёшь без долгого вникания. куда там хипстерам. вот пистон - это да, говнокод для говнокодеров, эталонное ненужно в вакууме. и все эти бредоносные сетки написаны на этом жручем УГ. неудивительно, что это жрёт... сколько там? мегаватты уже, наверное, электричества. но я не буду помогать им это оптимизировать. пусть оно горит синим пламенем.

но это всё всего лишь модель. тело думает по другому, мозг думает по всякому. а все эти теории это лишь карта а не территория.

вот именно. когда-то очень давно, когда ещё не было всего этого хайпа вокруг бредоносного софта, я заинтересовалась теорией «обучающихся» нейросетей и стала рыться. сначала я рылась в компьютерной и математической литературе. но быстро поняла, что эти абстракции никак не напоминают работу мозга человека. поэтому я решила углубить свои познания в биологии и начала читать анатомию ЦНС, нейрофизиологию и нейропсихологию. чтобы примерно понять, как вообще работает мозг. и то, то я поняла, - это то, что даже медики и биологи не знают ещё до конца, как именно он работает. настолько сложный объект изучения. там и тут постоянно проводят исследования, уточняют устройство мозга в мелочах. но цельной картины нет и я думаю, что не будет в ближайшие лет сто, наверное. там так много связей всего со всем, что бесполезно это пытаться эмулировать. а дешёвые модельки на нейронках - это просто прикладная математика и немного программирования. это никакой не «интеллект» даже близко. натасканные не мусоре из интернета, и даже на вторичном мусоре, который они же и сгенерили - это уже совсем полный бред. это раскручивается, как маховик - чем дальше, чем больше бреда и тем он хуже. поэтому я это всё считаю полной лажей и вредительством.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

я это всё считаю

Факт в том, что новое явление появилось, оно используется и помогает людям.

А лично ваше мнение не является ни авторитетным, ни компетентным по этой теме.

Shushundr ★★★★★
()
Ответ на: комментарий от Shushundr

вот насчёт «помогает» я совсем не уверена. точнее, уверена в обратном: дебилятор дебилирует. люди уже и так не совсем умные, мягко выражаясь. и они становятся ещё тупее за счёт этой фигни. а сети заполняются полным шлаком, который потом оттуда ещё долго придётся вычищать. плюс, конечно, огромная нагрузка на серверы и сети. я как админ и программист эту гадость просто люто ненавижу.

и самое худшее и опасное, что дебилятором пользуется школота. то есть, у них и так мозга нет. но они убивают те жалкие зачатки, которые были. а если мозг не развивать в этом возрасте - вырастет целое поколение дебилов. мы ещё увидим эти последствия в реальности.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 2)
Ответ на: комментарий от anonymous

и например, реализацию ассемблера на схеме (16-битного, для простоты): aasm

нет, не эта ссылка. сейчас так сразу не найду что-то, пропала с саванны – ссылка на 16-битный ассемблер под дос или биос, написанный на scheme. в вебархиве искать долго, что-то около 2003..2008 годов тот проект был и как-то похоже назывался

если коротко, то кодеген там был похож на ikarus scheme ikarus by Abdulaziz Ghuloum, он ещё книжку интересную написал о реализации компилятора схемы и ряд статей

где-то в районе ikarus.intel-assembler.ss , см. тесты x86-64-repl.ss

вот несколько реализаций схемы на files.scheme.org – см. например DreamOS

ещё в этом смысле интересна loko scheme: http://scheme.fail (скриншотик с думом ) и gerbil

в общем, ассемблер тот на схеме был похож на реализацию в ikarus

ещё есть вот такой цикл статей georgjz.github.io/wyvern-01/ georgjz.github.io/wyvern-02/ georgjz.github.io/wyvern-03/ georgjz.github.io/wyvern-04/ где пишут реализацию ассемблера на Racket Scheme

и от разработчика Guix – Germ Lisp, репо и блогозапись introducing-germ-lisp.html

там ещё более наглядно расписано. почему лисп, почему ассемблер.

даже есть ссылки на SectorLISP и Ribbit (схема на сишке через виртуальную машину размером в 7 килобайт):

Generate a simple 'hello world' program in 16 different languages

echo '(display "Hello from Ribbit!")' > hello.scm

Then, choose among 16 host languages :

$ ./rsc.exe -t asm   -l max hello.scm -o hello.asm

– понятное дело, что теперь на самой Ribbit схеме можно реализовать и свой ассемблер, а не использовать внешний. получится бутстрап сам на себе.

anonymous
()
Ответ на: комментарий от anonymous

вот как может выглядеть «более лучший printf» в реализации сисколлов:

(define %sys-write 4)
(define %stdout-handle 1)

(buf-set! 0 65)
(buf-set! 1 0)
(syscall "nnpn" %sys-write %stdout-handle 0 1)

здесь вот этот «nnpn» может контролироваться макросами – CTFE , во время компиляции

Self-hosting

Germ can build itself. The only script I’ve written for Germ (so far) is an x86 assembler, and a Lispified version of the Germ assembly code. The assembler constructs an embedded domain-specific language for writing assembly programs in Lisp. Here’s what the exit subroutine looks like:

;;; exit
;;; Exit the program with the code in EAX.
(: 'exit)
(mov %eax %ebx)                       ; Use EAX for the exit code
(movst ($ sys-exit) %eax)             ; EAX := SYS_exit
(int ($ #x80))                        ; Call kernel

asm.scm

If you’re familiar with x86, GNU assembler, and Lisp this should be pretty easy to understand. (The movst instruction is like an assembler macro that does the move via the stack, which is one byte cheaper.) Basically, each instruction is a Lisp procedure that manipulates some global state in the assembler. When you are finished adding instructions, you can run assemble! to get a list of bytes corresponding to the assembled instructions. These bytes go on to write-elf, which adds an ELF header to the machine code. The resulting ELF file is bit-for-bit identical to Germ as built with the GNU assembler.

в общем-то, «почему ассемблер логично было бы реализовывать на лиспе, особенно на схеме» – и так понятно (примерно как на форте с immediate словами времени комплияции), но вот ещё пару аргументов:

  1. структурные выражения лиспа
  2. DSL макросами лиспа времени компиляции
  3. если именно схема с гигиеничными макросами через syntax-case, то все эти syntax->datum и datum->syntax дают логичную естественную модульность макросов
anonymous
()
Ответ на: комментарий от anonymous

Ещё, внезапно вспомнился HLA = High Level Assembler by Randall Hyde (ArtOfAssembly) и его более лучший препроцессор; и «Препроцессор GNU assembler-а = gasp» opennet

  1. HLA. сам по себе прикольный – выглядит как паскаль, семантика в духе С++ (есть шаблоны, STL, объекты, оконная библиотека), но по сути ассемблер.

к примеру, вот код из hlasrc_v1.99.zip/hlasrc/hladev/hlaasm.hla line 260 :

procedure printf1( fmt:string; v:dword ); @cdecl; @external( cPrefix "printf" );
procedure printf2
( 
	fmt:string; 
	v1:dword;
	v2:dword 
); 
	@cdecl; 
	@external( cPrefix "printf" );

procedure printff
( 
	fmt:string 
); 
	@cdecl; 
	@external( cPrefix "printf" );

#macro printf( fmt, args[] );
	
	pushad();
	
	#if( @elements( args ) = 1 )
	
		#if( @typename( @text( args[0] )) = "real32" )
		
			sub( 8, esp );
			fld( @text( args[0] ) );
			fstp( (type real64 [esp]));
			printff( fmt + #$d + #$a );
			add( 12, esp );
		
		#elseif( @typename( @text( args[0] )) = "real64" )
		
			sub( 8, esp );
			fld( @text( args[0] ) );
			fstp( (type real64 [esp]));
			printff( fmt + #$d + #$a );
			add( 12, esp );
		
		#else
		
			printf1( fmt + #$d + #$a, @text( args[0] ) );
			add( 8, esp );
			
		#endif
		
	#elseif( @elements( args ) = 2 )

	
		printf2( fmt + #$d + #$a, @text( args[0] ), @text( args[1] ) );
		add( 12, esp );
	
	#else
	
		#error( "unexpected # of arguments to printf" )
		
	#endif
	popad();
	
#endmacro;

здесь видим довольно мощный CTFE макропроцессор – есть рефлексия по @typename, подчёт длины массива в compile-time

  1. в gasp тоже есть что-то подобное.

Ещё, внезапно вспомнился HLA = High Level Assembler by Randall Hyde (ArtOfAssembly) и его более лучший препроцессор; и «Препроцессор GNU assembler-а = gasp» opennet

  1. HLA. сам по себе прикольный – выглядит как паскаль, семантика в духе С++ (есть шаблоны, STL, объекты, оконная библиотека), но по сути ассемблер.

к примеру, вот код из hlasrc_v1.99.zip/hlasrc/hladev/hlaasm.hla line 260 :

procedure printf1( fmt:string; v:dword ); @cdecl; @external( cPrefix "printf" );
procedure printf2
( 
	fmt:string; 
	v1:dword;
	v2:dword 
); 
	@cdecl; 
	@external( cPrefix "printf" );

procedure printff
( 
	fmt:string 
); 
	@cdecl; 
	@external( cPrefix "printf" );

#macro printf( fmt, args[] );
	
	pushad();
	
	#if( @elements( args ) = 1 )
	
		#if( @typename( @text( args[0] )) = "real32" )
		
			sub( 8, esp );
			fld( @text( args[0] ) );
			fstp( (type real64 [esp]));
			printff( fmt + #$d + #$a );
			add( 12, esp );
		
		#elseif( @typename( @text( args[0] )) = "real64" )
		
			sub( 8, esp );
			fld( @text( args[0] ) );
			fstp( (type real64 [esp]));
			printff( fmt + #$d + #$a );
			add( 12, esp );
		
		#else
		
			printf1( fmt + #$d + #$a, @text( args[0] ) );
			add( 8, esp );
			
		#endif
		
	#elseif( @elements( args ) = 2 )

	
		printf2( fmt + #$d + #$a, @text( args[0] ), @text( args[1] ) );
		add( 12, esp );
	
	#else
	
		#error( "unexpected # of arguments to printf" )
		
	#endif
	popad();
	
#endmacro;

здесь видим довольно мощный CTFE макропроцессор – есть рефлексия по @ typename , подчёт длины массива в compile-time, @ text для рефлексии опять же

реализовано через какие-то символьные таблицы, см. например, pType: enum в самом начале файла

  1. в gasp тоже есть что-то подобное.

  2. а что если использовать вместо gasp препроцессора препроцессор на макросах форта или вот например, лиспа… oh, shi~….

  3. тащем-та, ежели CTFE препроцесор достаточно мощный – например, как в том же HLA, gasp или вот лиспе – то есть, мощнее cpp – то нормальную рефлексию CTFE там сделать не сложно, аналогично D-шной CTFE по typename, typetuple и прочим typeinfo

anonymous
()
Ответ на: комментарий от anonymous

см. например DreamOS

загрузочный образ основан на интерпретаторе схемы dream, написанном на ассемблере.

но во-первых, можно взять и более самодостаточный и компактный интерпретатор типа Ribbit или Germ.

во-вторых, написать на такой схеме ассемблер как встроенный DSL лисповых макросов.

в-третьих, написать кодеген наподобие как в ikarus, loko, gerbil и сделать конпелятор схемы (в ассемблер), а не интерпретатор.

anonymous
()
Ответ на: комментарий от anonymous

нет, не эта ссылка. сейчас так сразу не найду что-то, пропала с саванны – ссылка на 16-битный ассемблер под дос или биос, написанный на scheme. в вебархиве искать долго, что-то около 2003..2008 годов тот проект был и как-то похоже назывался

вот, вспомнил. sassy он назывался. нашёл на гитхабе: carld/sassy , с саванны куда-то пропал

вот здесь например демо – загрузочная дискета demo/boot.sassy и статья в линуксгазете issue77/krishnakumar :

(bits 16)

(text
  (mov ax #xb800)         ; load address of video memory...
  (mov es ax)             ; ...into es
  (es (mov (& 0) #x41))   ; mov "A" to byte 0 of vid-mem
  (es (mov (& 1) #x1f))   ; mov blue to byte 1 of vid-mem
  (label loop
    (jmp loop)))          ; do nothing

в исходниках видно, что реализовали макросами через define-syntax и syntax-rules гигиеничными макросами. и какой-то макроассемблер там тоже также реализовали.

ещё есть вот такой ассемблер на схеме 2021-05-06-scheme-x86-assembler и схема на ассемблере sqrt57/x86-scheme

в общем, натуральная DreamOS получается: ос на схеме, схема на ассемблере, ассемблер на схеме

anonymous
()
Ответ на: комментарий от anonymous

ещё примеры там в test находятся, например:

tests/bye.scm и tests/libhello.scm

конвертор в nasm из лиспового представления tests/generate-nasm.scm

16,32-битный поддерживается, до 64-битного вроде бы не допилили этот ассемблер

а из «высокоуровневых ассемблеров» ещё uasm и asmc прикольные – поддерживают сишный синтаксис (занятно, что макросы там при этом всё ещё мощнее чем в сишке :))) )

anonymous
()
Ответ на: комментарий от anonymous

DreamOS

загрузочный образ основан на интерпретаторе схемы dream, написанном на ассемблере.

там ссылка на исходники интерпретатора поломана, но они нашлись нa гитхабе: DreamScheme

гы, зорк ОС: frotzos

a barebones bootable platform to run the frotz z-code interpreter inside a VM

This builds a .izo image that can be booted in a VM to run a .z5 program.

standalone image–only an x86 hypervisor required to play

instantly boots directly into game

воооот, а в качестве игрушки для него использовать Lists and lists desc с реализацией схемы на Inform 6 play in browser

lists.z5 и исходник lists.tar.Z IFDB:lists.tar.Z

во, вспоминается AdvSys из журнала Byte за 1985 год – лисп для Interactive Fiction

а также mdl lisp и

MDL_Programming_Language.pdf , MDL_Programming_Environment.pdf, MDL_Primer_and_Manual.pdf , confusion_mdlzork.tgz , confusion_0.2.tgz – MDL interpreter, if-archive/programming/mdl/interpreters/confusion , NZT-Zorkhistory.txt

anonymous
()