pyLCDstringУтилита для подготовки русских строк к выдаче на символьные ЖКИ
| Версия: |
2.7 |
| Автор: |
Александр Бельченко |
| Дата: |
28 января 2005 |
Главная цель в разработке такого рода утилиты — получить удобный механизм, который можно будет использовать в batch или make файлах для генерации из некоторого исходного файла (с набором строк) двух файлов: файла с Си-кодом и соответствующего ему заголовочного файла с декларацией всех строковых констант.
Утилита pyLCDstring работает с текстовыми файлами. На вход утилите вы подаете свой исходный файл с набором строк, которые необходимо перекодировать. Утилита на его основе строит два файла: исходный Си-файл с объявлениями строк, как глобальных переменных, и заголовочный h-файл с декларациями этих строк.
Выделение всех строк в один файл с одной стороны облегчает работу с набором логически связанных строк, с другой стороны позволяет избегать дублирования одинаковых строк в разных местах программы. Но самое главное — корректировать строки в случае необходимости становится очень легко. Вам необходимо будет только перекомпилировать исходный файл утилитой pyLCDstring и вы получите обновленный Си-файл.
Кроме того, в утилиту включена возможность указывать кодировку русских букв , задавать выравнивание строки в поле заданной ширины, и задавать свои правила перекодировки. Плюс к этому, задав соответствующую опцию в командной строке, можно заставить утилиту проверять файлы по дате, и перекомпилировать исходный файл только в случае, если его содержимое изменилось.
Утилита pyLCDstring запускается следующей командой:
pylcdstr.exe [options] source.lcd
Здесь
- pylcdstr.exe — имя программы;
- [options] — необязательные опции;
- source.lcd — имя входного файла, предназначенного для обработки.
Расширение входного файла не имеет существенного значения, но оно не может быть *.h или *.c. Базовая часть имени (без расширения) используется для построения имен c- и h-файлов. Например, при обработке файла source.lcd будут сгенерированы файлы source.c и source.h. Для определённости в дальнейшем полагаем, что расширение исходного файла *.lcd.
Необязательные опции командной строки:
--smart — smart mode (мудрый режим) — обработка входного файла и генерация новых c- и h-файлов производится только в случае, если содержимое исходного файла изменилось;
--q — quiet mode (молчаливый режим); на консоль не выводится никаких сообщений. (В будущих версиях опция будет скорректирована в соответствии со стандартом де-факто: необходимо будет использовать -q или --quiet).
--warnings — если при обработке текста будут обнаружены некритические ошибки (предупреждения), то информация о них не только будет выведена на консоль, но еще и код, возвращаемый утилитой, будет равен 1. Этот режим включен по умолчанию. (В будущих версиях опция будет удалена).
--nowarnings — принудительно устанавливает код, возвращаемый утилитой, равным 0. Даже если при обработке текста были предупреждения.
Заметьте, что если задан ключ --q, то он только подавляет вывод сообщений на консоль, но никак не влияет на возвращаемый код.
Краткую справку о синтаксисе вызова утилиты можно получить, вызвав утилиту без параметров или с опцией --help:
pylcdstr.exe --help
Утилита pyLCDstring распространяется в виде консольной программы для Windows и в виде скрипт-программы на языке Python. Запуск Python-скрипта аналогичен запуску exe-файла:
python pylcdstring.py [options] source.lcd
На вход утилите подается текстовый файл, в каждой строке которого может содержаться или одно объявление строки, или одна управляющая директива.
Строки в исходном файле (.lcd) записываются в обычном виде:
name = "исходная_строка"
При обработке исходного файла формируется Си-файл с соответствующими определениями вида:
char name[] = "перекодированная_строка"; /* "исходная_строка" */
Как видно, текст исходной строки указывается в Си-комментарии.
Параллельно формируется заголовочный (.h) файл с соответствующими декларациями:
extern char name[]; /* "исходная_строка" */
В настоящее время активно используется 5 различных кодировок русских букв — фактически на каждой платформе используется своя кодировка. По умолчанию утилита использует кодировку cp1251 (Windows) для обработки русских букв. Вы можете явно указать другую кодировку, используя директиву Coding:
//// Coding = тип_кодировки
Где тип_кодировки может быть следующим:
- win2lcd — для перекодировки русских букв в кодировке Windows cp1251 в кодировку символьных ЖКИ;
- koi2lcd — для перекодировки русских букв в кодировке КОИ-8 в кодировку символьных ЖКИ;
- dos2lcd — для перекодировки русских букв в кодировке ДОС cp866 в кодировку символьных ЖКИ;
- mac2lcd — для перекодировки русских букв в кодировке Macintosh в кодировку символьных ЖКИ;
- iso2lcd — для перекодировки русских букв в кодировке ISO 8859-5 в кодировку символьных ЖКИ;
- none — отсутствие любой перекодировки; все символы остаются сами собой;
- keil — все русские буквы из кодировки cp1251 остаются сами собой за исключением букв "ю" и "я" (0xFD и 0xFF), которые перекодируются в соответствующие восьмеричные коды (\375 и \377);
- win2dos — для перекодировки русских букв из кодировки cp1251 (Windows) в cp866 (DOS);
- dos2win — для перекодировки русских букв из кодировки cp866 (DOS) в cp1251 (Windows);
- koi2win — для перекодировки русских букв из кодировки КОИ-8 в cp1251 (Windows).
- iso2win — для перекодировки русских букв из кодировки ISO 8859-5 в cp1251 (Windows).
Многие Си-компиляторы для микроконтроллеров имеют специфические расширения синтаксиса языка в плане определений строковых констант, что позволяет задавать область памяти размещения константных строк. Если вас не устраивает декларация строки как char[], то вы можете указать утилите желаемую форму декларации.
Для этого в начале исходного lcd-файла необходимо указать следующее объявление:
//// Declaration = желаемая_декларация_строки
Например:
//// Declaration = char code
//// Declaration = char __flash
Вы можете для каждой строки (или для диапазона строк) задать выравнивание. Это может облегчить вам жизнь в случаях, когда необходимо, чтобы текст полностью занимал все пространство одной строки ЖКИ. Допускается выравнивать по левому или правому краю, а также по центру.
Для одиночной строки выравнивание задается в виде префикса при записи строки. Используются следующие префиксы (регистр букв значения не имеет):
- lNN, LNN — выравнивание по левому краю внутри поля NN символов
- rNN, RNN — выравнивание по правому краю внутри поля NN символов
- cNN, CNN — выравнивание по центру внутри поля NN символов
- mNN, MNN — выравнивание по центру внутри поля NN символов, с отбрасыванием пробелов справа ("полуцентрирование")
- #NN — не производить выравнивание, только контролировать длину строки
При выравнивании строка дополняется пробелами до указанной длины поля. Если ширина поля выравнивания задана нулем (т.е. #0 или L0, C0, R0), то никакой обработки выравнивания производится не будет.
Примечание: Разница между префиксами C и M заключается в том, что в первом случае
строка будет выравнена по центру указанного поля и дополнена пробелами с обеих сторон. Во втором же случае строка также будет выравнена по центру поля, но пробелы справа (в конце строки) будут отброшены.
Если исходная строка длиннее заданного размера поля, то выравнивание не производится.
Кроме того, программа выдает предупреждение на консоль и в выходной Си-файл об этом факте в виде следующей строки:
String too long for field size=NN (MM)
где
- NN — заданная ширина поля в символах,
- MM — реальная длина строки.
На консоль также выводится и исходная строка, превысившая лимит. В выходном Си-файле данное предупреждение помещается как комментарий перед строкой. Вывод сообщений на консоль производится, только если не задан режим quiet mode. Вывод сообщений в Си-файл, производится всегда. Подробнее о предупреждениях читайте ниже в разделе Типы предупреждений и ошибок.
Примеры указания выравнивания:
name1 = L16"Строка1"
name2 = R16"Строка2"
name3 = C16"Строка3"
name5 = M16"Строка5"
name4 = #8"Очень длинная строка"
В результате обработки получится:
char name1[] = "Строка1 "; /* L16"Строка1" */
char name2[] = " Строка2"; /* R16"Строка2" */
char name3[] = " Строка3 "; /* C16"Строка3" */
char name5[] = " Строка5"; /* M16"Строка5" */
/* String too long for field size=8 ! */
char name4[] = "Очень длинная строка" /* #8"Очень длинная строка" */
Для некоторого диапазона строк можно задать выравнивание всех строк "по умолчанию".
Это делается следующим объявлением в начале каждой секции:
//// Align = префикс_выравнивания
Префиксы выравнивания lNN (LNN), rNN (RNN), cNN (CNN), mNN (MNN) и #NN (контроль длины строки без выравнивания) описаны выше.
Для указания того, что не следует производить выравнивание и контролировать длину строки, в качестве префикса выравнивания укажите ключевое слово none (None):
//// Align = none
//// Align = None
Как уже было сказано ранее, аналогичного эффекта можно добиться если в непосредственном префиксе выравнивания ширину поля задать нулем (т.е. #0 или L0, C0, R0), — при этом никакой обработки выравнивания производится не будет.
Выравнивание, заданное директивой Align, будет действовать на все строки, для которых не указан явно префикс выравнивания. Действие объявления Align распространяется до тех пор, пока не встретится другое объявление Align.
При обработке текста производится контроль префиксов выравнивания на синтаксические ошибки.
Если синтаксическая ошибка будет обнаружена в явно указанном префиксе выравнивания для конкретной строки, то будет выведено соответствующее предупреждение, этот ошибочный префикс будет проигнорирован и при обработки строки будет использовано выравнивание по умолчанию.
Если синтаксическая ошибка будет обнаружена в директиве Align, то будет выведено соответствующее предупреждение, ошибочное указание выравнивания будет проигнорировано и выравнивание по умолчанию останется прежним.
В отдельных случаях вам может понадобиться задать свои правила по перекодировке некоторых символов. Это можно сделать, указав соответствующее объявление в своем исходном lcd-файле:
//// Map = карта_перекодировки
где карта_перекодировки задается ввиде списка пар символов. Пары разделяются запятыми, элементы внутри каждой пары — двоеточием:
'оригинальный_символ':'во_что_перекодировать'
Допускается использовать указание символов в виде символьных констант ('a'), в десятичном (65) или шестнадцатеричном представлении (0x4F).
Пример:
//// Map = 'a':'b', 'b':65, 97:0x30
При обработке строк используется словарь перекодировки символов. Часть букв кириллицы заменяется на похожие по начертанию латинские буквы. Оставшаяся часть кодируется восьмеричными литеральными константами вида \ooo.
Когда вы задаете свою карту перекодировки, то в словарь перекодировки заносится код оригинального символа и соответствующее ему представление во_что_перекодировать. При этом, если перекодированный результат задан как символьная константа, то он запоминается в словаре перекодировки как символьная константа. В случае, когда перекодированный результат задан числом, то в словарь перекодировки записывается восьмеричный код. С точки зрения здравого смысла следует избегать перекодирования в символ с кодом 0.
Известно, что в ЖКИ с контроллером, совместимым с HD44780, существует возможность загрузить до 8-ми своих собственных символов. И их коды будут или 0x00...0x07 или 0x08...0x0F. Причём в обоих случаях адресуется одни и те же символы. Опять же, с точки зрения здравого смысла более разумно использовать коды от 0x08 до 0x0F (им будут соответствовать восьмеричные константы 010...017).
Для автоматического построения массива указателей на строки, можно воспользоваться следующим синтаксисом:
array = [
"string1",
"string2",
]
Здесь:
- array — имя результирующего массива; в строке с именем массива должен находиться знак равенства и открывающая квадратная скобка;
- строка с закрывающей квадратной скобкой означает конец описания массива;
- все строки, находящиеся между квадратными скобками, представляют собой список элементов-массива. Эти строки будут обработаны по всем правилам утилитой, для них будут сгенерированы специальные определения строковых переменных.
Имена таких переменных генерируются автоматически по следующему принципу:
'_' + имя массива + '_' + порядковый номер строки (с нуля).
В декларациях строк, содержащихся в массиве, допускается использовать префиксы яного выравнивания.
Для указания утилиты, какого вида должна быть декларация массива, используется синтаксис:
//// Array_ptr = желаемая_декларация
При задании своего варианта декларации массива указателей не забудьте добавить звездочку (*). Примеры:
//// Array_ptr = unsigned char code* code
//// Array_ptr = char __flash *
При обработке исходного файла распознаются несколько видов некритических ошибок, о которых выдаются соответствующие предупреждения на консоль и в выходной Си-файл.
Предупреждения выдаются в форме следующей строки:
Имя_исходного_файла (номер_строки_в_исходном_файле): тип_предупреждения: исходная_строка
По умолчанию, при возникновении предупреждений утилита возвращает код 1. Если же при вызове утилиты указать опцию --nowarnings, то даже при возникновении предупреждений всегда будет возвращаться код 0. Если предупреждения не возникали, то всегда возвращается код 0.
В исходном файле встречен строковый литерал, длина которого (MM) превышает заданную ширину поля выравнивания (NN).
Это предупреждение позволит вам легко контролировать, что все ваши строковые сообщения всегда поместятся на отведенное им место на экране ЖКИ. Заметьте, что длинная строка будет обработана по всем правилам, и лишь предупреждение поможет вам отследить наличие таких длинных строк.
В директиве Align задано неправильное выравнивание. Это может быть следствием синтаксической ошибки в записи.
При обнаружении неверного выравнивания ошибочное указание будет проигнорировано и выравнивание по умолчанию останется прежним. Исходная строка попадет в выходной файл.
Непосредственный префикс выравнивания, заданный для конкретной строки, не распознан. Это может быть следствием синтаксической ошибки в записи.
При обнаружении неверного непосредственного префикса выравнивания этот ошибочный префикс будет проигнорирован и при обработки строки будет использовано выравнивание по умолчанию. В выходной файл будет помещен комментарий, содержащий текст предупреждения.
Заданная кодировка в директиве //// Coding = название_кодировки не поддерживается утилитой. Это предупреждение может возникнуть, если вы неверно указали название кодировки, или указали несуществующую кодировку, или об этой кодировке утилите ничего не известно.
При возникновении ситуации с неверной кодировкой, эта директива Coding просто игнорируется. А вся исходная строка попадает в выходной файл.
Неверная директива или ошибка в синтаксисе директивы.
Строка, начинающаяся с четырех косых линий, считается строкой с указанием специальной директивы для утилиты. На сегодняшний момент распознаются следующие директивы: Align, Coding, Declaration, Map. Любые другие слова, следующие после //// будут вызывать появление этого предупреждения. Нарушения в синтаксисе записи директив также вызывают появления этого предупреждения.
Нарушения синтаксиса записи приводят к тому, что эта директива игнорируется, а вся исходная строка попадает в выходной файл.
При обработке опций командной строки и имени исходного файла могут возникнуть ошибки: опция может быть указана неверно или заданный файл может не существовать. В этом случае работа утилиты прерывается, возвращаемый код равен 2.
Обработка исходного файла подчиняется строгим правилам, описанным выше. Все строки исходного файла с точки зрения утилиты pyLCDstring делятся на:
- определение строкового литерала, который необходимо перекодировать и поместить в выходной файл;
- указание специальной управляющей директивы (Align, Coding, Declaration, Map), которая влияет на обработку исходного файла; строка со специальной директивой в выходной файл никак не переносится;
- и всех остальных строк, которые без изменений переносятся в выходной файл.
Поскольку последний вид строк переносится без малейших изменений в выходной *.c и *.h файл, то позаботьтесь, чтобы эти строки были корректно восприняты вашим Си-компилятором.
Кроме этого всего существует возможность задавать некоторые комментарии в строках первого типа: любой текст, следующий после строкового литерала, отбрасывается, и в выходной файл не попадает. Вы можете использовать этот эффект для записи поясняющих комментариев для своих строковых литералов. Старайтесь, чтобы текст вашего комментария был отделен хотя бы одним пробелом от строковых литералов.
Специальные управляющие директивы (Align, Coding, Declaration, Map) могут встречаться в исходном тексте любое число раз в любом месте — никаких ограничений на это не накладывается. Действие каждой директивы простирается до тех пор, пока не будет встречена эта же директива с другими параметрами. Наиболее актуально это для директивы Align, которая позволяет задать выравнивание по умолчанию для группы строк, перед которыми она объявлена.
Однако, другие директивы также могут встречаться в исходном файле по несколько раз. В каких-то случаях это может оказаться очень полезным, хотя зачастую в этом нет необходимости. Пользуйтесь этой возможностью осторожно.
Отдельное замечание касается директивы Map: каждый раз при обработке параметров директивы Map словарь перекодировки обновляется в соответствии с указанной картой перекодировки. Это значит, что для двух групп строк одни и те же символы могут быть перекодированы по разным правилам. Опять же, старайтесь пользоваться этим мудро, иначе вы можете получить не тот результат, на который рассчитывали.
В утилиту заложен механизм контроля длины исходной строки. Это свойство очень полезно при подготовке набора строк для вывода на ЖКИ с малым размером строки.
Если вы хотите, чтобы ваша строка полностью уместилась в одной строке индикатора 16*2, то воспользовавшись механизмом проверки длины строки вы сможете облегчить себе работу. Вы можете избавиться от необходимости ручного подсчета длины каждой строки, чтобы проверить "умещается или нет". Просто задайте директивой Align один из префиксов выравнивания с длиной строки вашего индикатора. При обработке lcd-файла утилитой все строки будут проверены по длине автоматически, и для очень длинных строк будут выведены предупреждающие сообщения.
Использование префикса выравнивания M позволяет делать центрирование исходной строки в поле указанной ширины, но при этом все пробелы справа удаляются. Полуцентрирование может быть полезно в тех случаях, когда вам нужно отцентрировать строку, в конце которой стоит символ \n (перевод строки).
При помощи непосредственного префикса выравнивания можно сформировать строку необходимой длины, состоящей только из пробелов:
name = LN""
В результате обработки будет сформирована строка, состоящая из N пробелов.
В версии 2.4 добавлена корректная обработка строк, в которых содержатся комбинации форматирования, начинающиеся со знака процента (%). Эти комбинации форматирования используются при формировании строк при помощи printf/sprintf.
Если в комбинациях форматирования явно задана ширина поля для вывода данных (например, %5d), то именно эта ширина будет использоваться при подсчете длины результирующей строки при операциях выравнивания строк. Если же ширина поля для вывода данных не задана (например, %d), то никаких предположений о длине не делается.
Комбинация форматирования должна начинаться о знака процента %
затем может идти один необязательный знак минуса (выравнивание по левому краю)
затем может (необязательно) присутствовать один из символов: +, # или пробел
затем может (необязательно) присутствовать указание ширины поля
затем может (необязательно) присутствовать указание точности вывода
затем могут (необязательно) пристуствовать модификаторы l или L (указание длинного целого), или b или B (указание байтового целого, в компиляторе кейла)
завершается эта комбинация одним символом, задающим тип — это один из следующих символов:
c, d, s, u, o, x, X, f, e, E, g, G, p
Кодировка none — в действительно это совсем не кодировка. Скорее ее следует рассматривать, как указание утилите pyLCDstring на то, что все правила перекодировок необходимо отменить. В результате обработки директивы //// Coding = none будет проведена полная очистка словаря перекодировки.
Это значит, что если вы ранее задали свои правила перекодировки при помощи директивы Map, а затем указали Coding = none, то результаты вашей директивы Map будут утрачены после очистки словаря перекодировки.
На сегодняшнем рынке символьных ЖКИ западные производители предлагают модели только с русским знакогенератором (хотя и называют это кириллицей). Однако, в этом знакогенераторе отсутствуют символы ґ, є, ї и ў, которые используются в украинском и белорусском языках. Единственным решением остается загрузка своих шрифтов в соответствующую область памяти контроллера и последующее использование соответствующих кодов.
Для задания соответствия между этими символами и кодами контроллера используйте директиву Map. О тонкостях использования этой директивы см. пункт Словарь перекодировки символов.
Автор программы: Александр Бельченко, 2004, 2005 год
|
|