Длинное обсуждение про UTF-8 без BOM и Free Pascal

Да кому нужен старый код с DOS? Я понимаю, что на Западе почему-то озаботились меньшинствами, но работающие с DOS - это даже не меньшинства, это просто сектанты. Еще не хватало их ублажать.

Не являются. По крайней мере там, где могут начинаться с РАВС. А где нужны указатели, с первого же семестра дают С.

Да? А примеры можно, когда в современном программировании" есть нужда писать паскалевский код с указателями? Или это так, поговорить?

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

Если вам дадут файл видео, с кодеком, не установленным у вас, что будет адекватнее - просить ещё одно видео, другого формата, или установить кодек?

И то что UTF8 сивместимо с ASCII если использовать только первые 127 символов - это приятная плюшка, но в какой серьёзной ситуации вам понадобится читать текстовый файл кодировкой, которая может неправильно прочитать некоторые символы файла?

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

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

Так делать нельзя. То, что такая возможность теоретически где-то существует, не значит, что её допустимо использовать.

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

Компилятору языка программирования в общем случае вообще нет дела, в какой кодировке файл с программой. Он знает, например, что файл может содержать такие-то ключевые слова и прочие токены (в ASCII естественно), разделенные пробельными символами (только ASCII, естественно. В UTF-8 их слишком много, чтобы все распознавать).

Теперь представьте себе что он видит вместо директивы var a: integer что-то вроде \xEF\xBB\xBFvar a: integer:

Слово \xEF\xBB\xBFvar он не знает и возвращает синтаксическую ошибку. Делает он это абсолютно правильно и справедливо, поскольку он не какой-то текстовый редактор, а компилятор, то есть его задача — это распознавать синтаксис конкретного языка программирования, в который всякий не-ASCII бинарный мусор не входит.

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

С учётом этого, текстовые редакторы, работающие с кодом ни в коем случае не должны пихать BOM в UTF-8 файлы, поскольку они этим создают синтаксические ошибки на ровном месте. Может MS VS так делает, поскольку она прибита гвоздями к компилятору той же фирмы, где мелкомягкие могли специально прописать исключение, чтобы \xEF\xBB\xBF пропускался, но это никак не делает это допустимым для других текстовых редакторов, поскольку другие компиляторы не обязаны пропускать эти байты и далеко не всегда это делают.

Например, если вы работаете не с одним компилятором паскаля, а с несколькими, что мешает открыть в редакторе PascalABC.net файл, изначально предназначенный для Borland Pascal, подредактировать там что-то, а затем попытаться скомпилировать в Borland Pascal?

Из-за существующего на данный момент бага в итоге файл не скомпилируется ни в PascalABC.net — потому что он не поддерживает некоторые возможности нормального паскаля, ни в Borland Pascal — потому что добавлены мусорные байты в начало файла.

Да и вообще, что мешает пользователю открыть в редакторе код на любом языке программирования, хоть на C, хоть на Python? Может у него уже открыт PascalABC.net и ему не хочется загружать какой-то ещё редактор для того чтобы быстренько добавить точку с запятой или ещё что-то подобное?

Это нормально, когда текстовый редактор портит код? По-моему, нет. А по-вашему?

я спросил в чём ценность конкретно pabc. Вы осознаёте, что несмотря на нахождение в семействе паскаль-языков, pabc.net всё таки ОТДЕЛЬНЫЙ и САМОСТОЯТЕЛЬНЫЙ язык, а не утилита для компиляции всего подряд?

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

В наше время это уже не оправдано. Компилятор, который знает только про ASCII - это устаревший мусор.

char.IsWhiteSpace именно этим занимается.

Да, такие проверки затратнее чем ch.Code=32, но для разделения на токены они вполне подходят - первая стадия компиляции всё равно обычно самая быстрая.

А что мешает написать программу на Java, а затем попытаться запустить её как JavaScrips? Может то, что это языки, не имеющие общей спецификации и похожие только в самых базовых моментах синтаксиса?

Не только в трурбо-паскале нет большинства .Net фич - в PascalABC.Net тоже нет кучи всего из турбо-паскаля, к примеру многих устаревших директив. Написание кода, используя НОД фич таких разных языков - это мазохизм, хватит его тут пропагандировать.

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

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

Но пусть программист нарушит этот принцип и оставит строку с UTF-8 символами. Компилятор просто вставит байты этой строки в секцию данных как есть, без какой-либо интерпретации, ему вообще не важно, UTF-8 там, CP1251 или вообще CP437 досовская какая-нибудь. А уже дело программиста знать кодировку строки и вызывать строковые функции, которые работают именно с этой кодировкой. Например можно проверить локаль, и если она *.UTF-8 то выкинуть строку на stdout как есть, а если нет, то вначале вызвать iconv и перевести в другую кодировку. Если программа запущена на Windows, то дело программиста найти и подключить dll или самому написать конвертер из UTF-8 в UTF-16 прежде чем передавать функциям Windows API, но в любом из этих случаев компилятору не требуется знать в какой кодировке исходный файл. И это хорошо, что он её не знает, поскольку это позволит работать с любой кодировкой, не меняя и не трогая компилятор. Мало ли может вы захотите тем же компилятором собрать программу для другой ОС, где нет поддержки UTF-8 или вообще модуль для начального загрузчика.

Заметьте что это никак не запрещает использовать в программе любые библиотеки, в том числе и работающие с UTF-8 и другими кодировками.

char.IsWhiteSpace именно этим занимается.

Усложнение компилятора — это плохо. Кроме того, внезапное изменение поведения существующей программы — это вообще недопустимо, а с появлением новых стандартов юникода это может произойти. Набор базовых элементов языка программирования должен быть строго фиксированным. Например за пробелы он должен считать собственно пробелы, табы, переводы строк и может быть ещё \r \v \f всякие и всё. Список должен быть закрытым на момент появления спецификации языка.

Может то, что это языки, не имеющие общей спецификации и похожие только в самых базовых моментах синтаксиса?

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

Это что за директивы такие, если не секрет?

@Admin , если вас аргументы на словах не убеждают, то вот вам пример где наличие BOM в UTF-8 файле откровенно вредно:

flat assembler version 1.73.27 (1089705 kilobytes memory)
wow64chs.asm [1]:
;
processed: 
error: illegal instruction.

Так себя ведёт не только fasm, но и большинство других компиляторов.

Это баги других компиляторов. Мы то тут причем?

Это не баг, а фича: BOM не является заранее определенным элементом синтаксиса языка, поэтому вызывает синтаксическую ошибку. Вот другое поведение было бы как раз багом.

Речь идёт о PascalABC.net IDE, то есть не о компиляторе, а о текстовом редакторе. Как видим из вышесказанного, в его теперешнем состоянии он плохо пригоден для написания кода на других языках, поскольку вставляет мусорные байты при сохранении.

Я предлагаю это исправить. Нужно всего одно маленькое изменение — не вставлять BOM при сохранении файла в UTF-8 и тем более в чистом ASCII.

Кстати, fasm поддерживает метки и прочие символы из юникодных символов (а на самом деле, вообще любых символов — он encoding agnostic). Например некоторые так маскируют BOM, вставляя эту строчку в начало файла (перед знаком = есть невидимый символ):

="utf-8"

Таким образом объявляется мусорная переменная с именем  <BOM> и значением utf-8, которая потом нигде не используется и BOM больше не вызывает синтаксическую ошибку. Но на мой взгляд, гораздо разумнее всё-таки не ставить такие костыли, а поменять настройки текстового редактора так, чтобы он никогда не вставлял BOM в UTF-8, если его явно об этом не попросить.

Вы сами правильно сказали, то что вы объяснили о fasm - это костыль.
Вместо исправления проблемы - речь идёт про её обходы. Это неправильно, не зависимо от правильности BOM.

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

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

Вам так трудно исправить баг, про который вам подробно рассказали и на сто рядов доказали, что это именно баг? Если такой же баг есть в Visual Studio, это что, значит, что его исправлять нельзя?!

Чем плохо использовать ABC IDE для редактирования кода на паскале, если этот код потом предполагается компилировать Free Pascal? Подсветка синтаксиса паскаля, хоть и не идеальна совместима с fpc, но ведь лучше чем никакой, правильно? В идеале в IDE вообще должна быть опция, какой компилятор вызывать при нажатии F9, чтобы можно было сделать полную интеграцию ABC IDE с компилятором FPC.

Вместо исправления проблемы - речь идёт про её обходы.

Ну да. правильный способ исправления проблемы — изменить текстовый редактор так, чтобы он не вставлял BOM в UTF-8. Но для некоторых редакторов (MS Notepad, PascalABC.net IDE и тд) это невозможно или сложно. поскольку такой настройки нету.

Если до MS вряд ли реально достучаться, то у ABC есть хотя бы форум.

Вообще стандарт Unicode не запрещает BOM, хотя и не советует его добавлять. Просто он бесполезен, но не значит, что запрещен. В стандарте также есть рекомендация не добавлять / не убирать его при редактировании.

Фактически BOM — экзотический пробел нулевой ширины. То есть мусорный символ. В обычном тексте он особо не помешает, а вот в коде на любом языке — очень даже вреден.

В некоторые компиляторы добавлены костыли для пропуска BOM, но ведь не во все, поэтому в коде он категорически не рекомендуется.

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

Фактически BOM в начале потока это BOM и ничто другое. Это в середине он так воспринимается в виде костыля, для случаев когда например два файла конкатенировали.

В спецификации языка и не должно быть написано ничего про BOM. Компилятор должен открыть и прочитать файл. Компилятор в целом может требовать что-то, что не определено в спецификации. Например, gcc нормально работает с файлами UTF-8 и BOM, но не переваривает переменные в UTF-8.

А у MS с этим проблемы, потому что они изначально все через ж делают и не осилили определение кодировки и например в VS2019 с этим проблемы… опять. Просто системной кодировки UTF-8 там до сих пор нет, поэтому он им всегда нужен как маркер кодировки.

Я посмотрел код текстового редактора. В принципе, я Вас понимаю.

К сожалению, редактор взят As is из Sharp Developа. И - увы - сохранение с BOM там запаяно. Если бы была какая-то опция, мы бы каким-то образом сделали чтобы это можно было переключать.

Я также посмотрел редактор последнего Lazarus. Он нормально открывает файлы с BOM и если их изменить и сохранить, то тоже сохраняет с BOM. К чести сказать, новые файлы он сохраняет без BOM.

А, то есть виджет редактора кода вы не сами писали, а взяли готовый?

Ну так что мешает найти там где вставляется BOM и закомментировать эту строку? Наверное наиболее правильное поведение будет не трогать BOM, и всегда считать файлы за UTF-8 если нет явных признаков иного, а BOM считать обычным символом и желательно ещё и сделать его видимым, хотя в норме он и рендерится как пробел нулевой ширины.

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

Все работают с BOM. Вы хотите без BOM. Нужна опция. И нужен кто-то кто аккуратно это сделает.

Как показывает практика, эта универсальная фраза в 100% случаев приводит к тому, что вопрос снимается с повестки дня. Никто не хочет что-то делать, но все готовы без устали обвинять и критиковать.

В смысле, вы хотите сказать, что кому-то этот BOM нужен и полезен?

Тогда вопросов нет,

Но вы уверены, что им действительно кто-то пользуется в том смысле, что у кого-то есть use-case, где, если ABC IDE начнёт сохранять без BOM, придётся ставить другую программу и его добавлять?

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

BOM

Тот же fpc судя по документации использует BOM для определения кодировки исходников: “if the file starts with an UTF-8 BOM, then the source file codepage is UTF-8, otherwise … the source file codepage is set to CP_ACP (for backward compatibility with previous FPC versions)” (FPC Unicode support - Free Pascal wiki). :laughing:

1 лайк