Новшества в компиляторе и препроцессоре


Многозначные/многоязычные строки в RUN-TIME
CLIP предоставляет средства для разработки многоязычных программ и контролирования значений строк в RUN_TIME. Здесь и ниже под термином "language" подразумеваются не только "язык", а и другие причины, по которым необходимо организовать перегрузку строк. Например это может быть: "пользователь","время дня","квалификация пользователя" (бухгалтерам желательно выдавать сообщение "нажмите самую большую клавишу", а остальным "Нажмите любую клавишу"), а также другие критерии по вашему усмотрению.

В качестве примера приводится часть исходников из prg/samples с комментариями. //file: prg/samples/multilang.prg #define s1 [Hello world] // keyword1 #define s2 [Good bye world] // keyword2 // All strings enclosed in [] delimiters are localized keywords ? "Locale module name is:",__CLIP_MODULE__ // __CLIP_MODULE__ is compile time predefined, it depends on -E compile switch ? "Default string1 is:",s1 ? "Default string2 is:",s2 ? ? "Install external data from lang1/ml1.mo:" ?? loadModuleMsg(__CLIP_MODULE__,"./locale.mo/lang1/"+__CLIP_MODULE__+".mo") ? "String1 for lang1 is:",s1 ? "String2 for lang1 is:",s2 ? ? "Install external data from lang2/ml1.mo:" ?? loadModuleMsg(__CLIP_MODULE__,"./locale.mo/lang2/"+__CLIP_MODULE__+".mo") ? "String1 for lang2 is:",s1 ? "String2 for lang2 is:",s2 ? return #file: prg/samples/Makefile # [ some defines skipped ] # CLIP_LOCALE_ROOT defines path where to save modules CLIP_LOCALE_ROOT=./ export CLIP_LOCALE_ROOT # [ other targets skipped ] multilang: multilang.prg $(CLIP) $(CLIPFLAGS) -e -M -E CLIP_MODULE="ml1" multilang.prg $(CLIPLIBS) clip_msgmerge clip_msgfmt #output from make processing /home/uri/prg/samples > make multilang /m2/uri/cliproot/bin/clip -a -O -b -e -M -E CLIP_MODULE="ml1" multilang.prg parsing file 'multilang.prg' .. open locale file './/locale.pot/ml1/multilang.pot' # at this moment keyword1 and keyword2 are moved to external pot-file .. done (23/2643 lines, 0 warnings, 1.47s) writing file 'multilang.c' .... done, 3546 bytes ,0.00s compile file 'multilang.c' .... done, 0.21s generate reference file 'multilang_ref.c' .... done, 0.04s make file 'multilang' .... done, 0.33s clip: 2 files, 2.05s # at this moment we create two or more directories (one per language) # compiler does not know how many languages will your app support, # so we need do it once. A new target language could be added at any time. # mkdir ./locale.po/lang1 # mkdir ./locale.po/lang2 clip_msgmerge # generate editable po-modules templates from pot-files use locale root ./ module ml1 locale lang1 ... OK. locale lang2 ... OK. # at this moment we edit files (translate keywords from english to # desired language). You will need to edit them next time as soon # as new keywords will be added to application. # vi ./locale.po/lang1/ml1.po # vi ./locale.po/lang2/ml1.po clip_msgfmt # generate loadable mo-modules use locale root ./ locale lang1 module ml1 locale lang2 module ml1
Все слова начинающиеся на HASH_, препроцессор переводит в hashstr("HASH_....."). Нам это нужно, для того чтобы уменьшить количество включаемых (#include) файлов. И вместо того чтобы писать #define HASH_asdf 12345678 #define HASH_qwerty 231423534 и т.п., теперь можно просто в тексте программы использовать ключевые слова HASH_...., например: do case case HASH_asdf case HASH_qwerty .... endcase И, при этом, можно быть уверенным, что если в разных prg-файлах попадется набор символов HASH_asdf, то результат будет одинаков, как если бы это слово было бы объявлено через #define.
Препроцессор умеет доставать данные из окружения, например:
#define $USER будет фактически странслировано в #define uri В частности, можно использовать переменную окружения CLIP_LANG для изменения языка, на котором говорят clip-библиотеки. Например:
export CLIP_LANG=LANG_RUSSIAN
имеются предопределенные препроцессором #define: __FILE__ __BASE_FILE__ __LINE__ __VERSION__ __CLIP__ __SYSTEM__ __DATE__ __TIME__
Появилась команда препроцессора #xdefine - это то же самое, что и #define, но не чувствительна к регистру объявляемого имени макроса.
Конфигурацию ключиков можно прописать в файл .cliprc, и положить этот файл в домашний или текущий каталог.
В дополнение к std.ch можно прописать еще несколько автоматически подключаемых заголовочных файлов, прописав в .cliprc-файле строчки типа: -U std.ch -U clip.ch -U config.ch
Ключики компилятора не совсем соответствуют стандартному Клиппер-компилятору. Формулировки ошибок и предупреждений компилятора совсем не соответствуют. Но я не думаю, что это несоответсвие доставит большие неприятности.
Компилятор умеет перекодировать исходные тексты в разные русские кодировки во время компиляции. Т.е. вы можете писать программы в DOS, и без всяких ухищрений собирать программы в UNIX. Единственное ограничение - имена файлов должны быть в нижнем регистре.
Компилятор умеет генерировать

O-файлы собираются в библиотеки стандартными библиотекарями.
PO-файлы собираются в библиотеки утилитой clipar.
Изменена формулировка команды GET, раньше она вызывала встроенную функцию _GET_, а теперь GETNEW с добавленными параметрами.
Теперь можно в run-time загружать псевдокод (кодовые блоки) из файлов, например делается файл mylib.prg, в котором func myfunc1 return 1 func myfunc2 return 2 делается команда clip -p mylib.prg, в результате рождается файл mylib.po с псевдокодом внутри.
А во время работы любой программы можно написать: load("mylib.po") ? myfunc1() ? myfunc2()
В довесок к outdev, outerr сделан еще один поток вывода информации - в log-файл. SET(_SET_LOGLEVEL,num_level) // задает уровень отладки SET(_SET_LOGFILE,filename) // задает имя log-файла, если не задано, то весь вывод будет направлен в <имя_программы>.log OUTLOG(level, <list ,,,>) // если level не указан или первым параметром указано не число, то данная информация будет выводиться в log-файл ВСЕГДА не зависимо от текущего уровня отладки. Для прикладного логгирования используйте уровни 1-3, 4 уровень дает информацию о вызываемых функциях, скомпилированные как байт-код, 5 уровень выводит информацию о всех вызываемых функциях.
Примечание - log-файл не удаляется, так что позаботьтесь об этом сами.

Для пояснения и в качестве рекомендаций - я бы использовал