/* Russian encodings with care to letter YO from www.rusf.ru/books/yo */ /* Written in 2002--2004 by D.V.Khmelev */ /* !!!!!!!!!!!! BEFORE COMPILATION !!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* Please #define D_ALT for messages in cp866 */ /* Please #define D_WIN for messages in cp12151 */ /* Please #define D_KOI for messages in koi8-r */ /* You can also pass their definitions through compiler command line */ /* gcc -DD_KOI xcode.c -o xcode #GNU C compiler */ /* bcc.exe -DD_ALT xcode.c #Borland C compiler */ // Выходная кодировка по умолчанию // Output encoding by default #define __ENCLINE__ __LINE__ //#define D_ALT //#define D_WIN //#define D_KOI //#define D_ISO //#define D_MAC #ifdef D_ALT # define OUTPUT_ENC 0 // либо "альтернативная" (т.е. досовская) //either cp866 #elif defined(D_WIN) # define OUTPUT_ENC 1 // win=cp1251 #elif defined(D_KOI) # define OUTPUT_ENC 2 // либо "KOI". // or koi8 #elif defined(D_ISO) # define OUTPUT_ENC 3 // iso #elif defined(D_MAC) # define OUTPUT_ENC 4 // mac #else # error Please #define default output encoding D_ALT D_WIN D_KOI D_ISO D_MAC #endif #if defined(__MSDOS__) || defined(_WIN32) || defined(WIN32)|| defined(__WIN32__) || defined(__TURBOC__) #define STDOUT_PROBLEM_DOS 1 #endif #if defined(__MINGW__) #define STDOUT_PROBLEM_MINGW 2 #endif // Change Log: // $Log: xcode.c,v $ // Revision 4.1 2004/02/04 05:32:13 mamont // Добавлен переключатель -c, позволяющий // определять кодировку файла и выдавать её // на экран. Полная справка по -H содержит // инструкции по применению этой новой // возможности. При корректном // использовании переключателя -c программа // выходит с кодом ошибки // 6 --- ERROR_INFORM_ENCODING. // // Revision 4.0 2003/12/20 23:11:12 mamont // Добавлен ключ -d для определения // двойной перекодировки. Смена номера // версии на 4.0 // // Revision 3.7 2003/10/05 18:35:21 mamont // Исправлен глюк, возникавший при вызове // xcode in out // с отсутствующим файлом out (выдавалась // ошибка). // // Revision 3.6 2003/10/05 00:15:24 mamont // Заработал прозрачно бинарный стандартный // ввод/вывод под ДОС-окном. Версию mingw // не проверял, но, по идее тоже должна работать. // // Revision 3.5 2003/10/04 23:26:25 mamont // Теперь stdout устанавливается в бинарный // режим в DOS/WIN окружении. Иначе // добавлялся код \x0D в конце каждой // строки (\x0D\x0A). // // Revision 3.4 2003/10/04 23:02:54 mamont // Исправлена ошибка в выдаче диагностики // в предыдущей версии. // // Добавлены дополнительные коды выхода // (см. xcode -H, раздел КОДЫ ВЫХОДА) // // Добавлен переключатель --, по которому // прерывается разбор командной строки. // // Добавлено сообщение об ошибке в аргументах // программы, ежели такая просходит. // // Revision 3.3 2003/09/27 18:37:05 mamont // переформатировал комментарии // // Revision 3.2 2003/09/27 18:35:43 mamont // Совсем забыл: теперь программа выходит // с ненулевым кодом при какой-либо ошибке. // Сами ошибки можно посмотреть в тексте: // E_OK и т.д. // // Revision 3.1 2003/09/27 18:28:26 mamont // Теперь опции вида /h допустимы только при // выходной кодировке D_ALT // // По опции "--" сканирование аргументов // останавливается. Следующие аргументы // рассматриваются как имена файлов. // // Revision 3.0 2003/04/03 20:00:35 mamont // Смена версии на 3.0 // команда: ci -f3.0 xcode.c // // Revision 2.10 2003/04/03 19:47:12 mamont // Поправлена ошибка в кодировке "mac", на которую // любезно указал Сергей Скотников (неверный код // буквы ``я''). Используемая библиотека // перестановочной перекодировки с // http://www.rusf.ru/books/yo/encoding.html получила // название SRECODE.C и явно выделена в тексте // программы комментариями. // // Revision 2.9 2003/03/31 15:46:49 mamont // Текст приведён к стандарту C99 (по модулю предупреждений о конвертации // между знаковыми/беззнаковыми буквами). Бороться с этим можно явным // заданием преобразования указателей, но не нужно в силу усложнения // кода. // // Revision 2.8 2003/03/26 02:17:16 mamont // Поправлено предупреждение "suspicious pointer conversion" // // Revision 2.7 2003/03/26 02:14:13 mamont // Добавлено декодирование html-Уникоденных текстов // (вроде Дима) // // Revision 2.6 2003/03/10 17:36:26 mamont // Информация о режиме silent добавленая в справку // // Revision 2.5 2003/03/10 17:30:05 mamont // Добавлен режим silent по опции -s // // Revision 2.4 2003/03/09 01:42:47 mamont // Исправлено неправильное поведение при одном имени файла // // Revision 2.3 2003/03/08 19:57:28 mamont // Теперь программа компилируется bc 3.1 без предупреждений и ошибок. // // Revision 2.2 2003/03/08 19:33:27 mamont // Режим трубы теперь по умолчанию только в Досе/Виндах. (Дос/Win // определяется по переключателю D_ALT) // // Revision 2.1 2003/03/08 19:25:05 mamont // *** empty log message *** // // Revision 2.0 2003/03/08 19:23:31 mamont // Смена номера версии на 2.0 // // Revision 1.14 2003/03/08 19:13:24 mamont // Значительные улучшения по сравнению с предыдущей версией. Теперь // имеется опция с трубой -p, а под Досовской консолью по умолчанию // программа выводит краткую помощь. // // Если входная кодировка уже указана, то программа не определяет её // автоматически, а сразу производит перекодировку. Единственный тонкий // момент: когда надо перекодировать файл на месте. В этом случае // используется временный файл на диске, как и всегда. // // Revision 1.13 2003/03/08 16:24:13 mamont // Добавил Revision // // Revision 1.12 2003/03/08 16:17:35 mamont // Начат лог изменений // #include #include #include #include #include #include #ifdef STDOUT_PROBLEM_DOS #include #include #endif//STDOUT_PROBLEM_DOS #define XCODE "xcode" #define REVISION "$Revision: 4.1 $" static char * VERSIONR=REVISION; static char VERSION[100];//=VERSIONR+11 #define SELF_URL_BASE "http://www.rusf.ru/books/yo" #define SELF_URL SELF_URL_BASE "/src/xcode.c" /* Library SRECODE.C (Shuffle RECODE) ver. 1.0 * Автор кода: Д.В.Хмелёв, Март 2002--апрель 2003 * Подробности: http://www.rusf.ru/books/yo * Подпрограммы на языке Си, обеспечивающие * перестановочную перекодировку 14 кодировок * русских букв друг в друга. * Functions for Perl, providing exchange * transformation of 14 russian encodings to * each other. * Следующий код является Ё-ware, Именно, его можно * свободно распространять модифицировать, и даже * дизассемблировать как в двоичном виде, так и в * исходном тексте. Однако, используя этот код, вы * должны использовать букву Ё во всех текстах, * которые набираете на компьютерах: начиная с * электронных писем и заканчивая крупной * прозаической формой. * Автор воздерживается от всяческих гарантий * надёжности кода и снимает с себя ответственность * за возможную потерю данных при его * использовании. Тем не менее, автор постарался * сделать всё возможное, чтобы потери данных можно * было избежать. * Written by D.V. Khmelev, March 2002 -- April 2003 * More information at http://www.rusf.ru/books/yo * The following code is YO-ware. YO-ware means that * you can freely copy, modify and disassemble it in * binary and/or source text. However, if you use * this program code, you should use Russian letter * YO in all texts in Russian you type in computer * from e-mails to novels. * The author disclaims any responsibility for code * safety and holds no responsibility for the loss of * data, resulting the the use of the following * code. However, the author tried to do his best to * avoid loss of data. */ typedef enum { CP866=0, CP1251, KOI8_R, ISO8859_5, MAC, OSN, MOSHKOV, SORT, ALT_FIDO, KOI7, DKOI, CP500, EBCDIC, ASCII, TOTAL_ENCODING_NUMBER} encoding_t; char * encoding_name[]={ "cp866", /* CP866 */ "cp1251", /* CP1251 */ "koi8-r", /* KOI8_R */ "iso8859-5", /* ISO8859_5 */ "mac", /* MAC */ "osn", /* OSN */ "moshkov", /* MOSHKOV */ "sort", /* SORT */ "alt-fido", /* ALT_FIDO */ "koi7", /* KOI7 */ "dkoi", /* DKOI */ "cp500", /* CP500 */ "ebcdic", /* EBCDIC */ "ascii", /* ASCII */ }; unsigned char * encoding_alphabet[]={ /* CP866 */ (unsigned char*) "\240\241\242\243\244\245\361\246\247\250" "\251\252\253\254\255\256\257\340\341\342" "\343\344\345\346\347\350\351\352\353\354" "\355\356\357" "\200\201\202\203\204\205\360\206\207\210" "\211\212\213\214\215\216\217\220\221\222" "\223\224\225\226\227\230\231\232\233\234" "\235\236\237", /* CP1251 */ (unsigned char*) "\340\341\342\343\344\345\270\346\347\350" "\351\352\353\354\355\356\357\360\361\362" "\363\364\365\366\367\370\371\372\373\374" "\375\376\377" "\300\301\302\303\304\305\250\306\307\310" "\311\312\313\314\315\316\317\320\321\322" "\323\324\325\326\327\330\331\332\333\334" "\335\336\337", /* KOI8_R */ (unsigned char*) "\301\302\327\307\304\305\243\326\332\311" "\312\313\314\315\316\317\320\322\323\324" "\325\306\310\303\336\333\335\337\331\330" "\334\300\321" "\341\342\367\347\344\345\263\366\372\351" "\352\353\354\355\356\357\360\362\363\364" "\365\346\350\343\376\373\375\377\371\370" "\374\340\361", /* ISO8859_5 */ (unsigned char*) "\320\321\322\323\324\325\361\326\327\330" "\331\332\333\334\335\336\337\340\341\342" "\343\344\345\346\347\350\351\352\353\354" "\355\356\357" "\260\261\262\263\264\265\241\266\267\270" "\271\272\273\274\275\276\277\300\301\302" "\303\304\305\306\307\310\311\312\313\314" "\315\316\317", /* MAC */ (unsigned char*) "\340\341\342\343\344\345\336\346\347\350" "\351\352\353\354\355\356\357\360\361\362" "\363\364\365\366\367\370\371\372\373\374" "\375\376\337" "\200\201\202\203\204\205\335\206\207\210" "\211\212\213\214\215\216\217\220\221\222" "\223\224\225\226\227\230\231\232\233\234" "\235\236\237", /* OSN */ (unsigned char*) "\320\321\322\323\324\325\361\326\327\330" "\331\332\333\334\335\336\337\340\341\342" "\343\344\345\346\347\350\351\352\353\354" "\355\356\357" "\260\261\262\263\264\265\360\266\267\270" "\271\272\273\274\275\276\277\300\301\302" "\303\304\305\306\307\310\311\312\313\314" "\315\316\317", /* MOSHKOV */ (unsigned char*) "\341\342\367\347\344\345\243\366\372\351" "\352\353\354\355\356\357\360\362\363\364" "\365\346\350\343\376\373\375\256\371\370" "\374\340\361" "\301\302\327\307\304\305\263\326\332\311" "\312\313\314\315\316\317\320\322\323\324" "\325\306\310\303\336\333\335\254\331\330" "\334\300\321", /* SORT */ (unsigned char*) "\241\242\243\244\245\246\247\250\251\252" "\253\254\255\256\257\260\261\262\263\264" "\265\266\267\270\271\272\273\274\275\276" "\277\300\301" "\200\201\202\203\204\205\206\207\210\211" "\212\213\214\215\216\217\220\221\222\223" "\224\225\226\227\230\231\232\233\234\235" "\236\237\240", /* ALT_FIDO */ (unsigned char*) "\240\241\242\243\244\245\361\246\247\250" "\251\252\253\254\255\256\257\160\341\342" "\343\344\345\346\347\350\351\352\353\354" "\355\356\357" "\200\201\202\203\204\205\360\206\207\210" "\211\212\213\214\110\216\217\220\221\222" "\223\224\225\226\227\230\231\232\233\234" "\235\236\237", /* KOI7 */ (unsigned char*) "\101\102\127\107\104\105\43\126\132\111" "\112\113\114\115\116\117\120\122\123\124" "\125\106\110\103\136\133\135\137\131\130" "\134\100\121" "\141\142\167\147\144\145\44\166\172\151" "\152\153\154\155\156\157\160\162\163\164" "\165\146\150\143\176\173\175\42\171\170" "\174\140\161", /* DKOI */ (unsigned char*) "\167\170\257\215\212\213\131\256\262\217" "\220\232\233\234\235\236\237\252\253\254" "\255\214\216\200\266\263\265\267\261\260" "\264\166\240" "\271\272\355\277\274\275\102\354\372\313" "\314\315\316\317\332\333\334\336\337\352" "\353\276\312\273\376\373\375\165\357\356" "\374\270\335", /* CP500 */ (unsigned char*) "\254\151\355\356\353\357\111\354\277\200" "\375\376\373\374\255\256\131\104\105\102" "\106\103\107\234\110\124\121\122\123\130" "\125\126\127" "\220\217\352\372\276\240\252\266\263\235" "\332\233\213\267\270\271\253\144\145\142" "\146\143\147\236\150\164\161\162\163\170" "\165\166\167", /* EBCDIC */ (unsigned char*) "\237\240\252\253\254\255\335\256\257\260" "\261\262\263\264\265\266\267\270\271\272" "\273\274\275\276\277\312\313\314\315\316" "\317\332\333" "\130\131\142\143\144\145\102\146\147\150" "\151\160\161\162\163\164\165\166\167\170" "\200\212\213\214\215\216\217\220\232\233" "\234\235\236", /* ASCII */ (unsigned char*) "\141\142\167\147\144\145\136\166\172\151" "\152\153\154\155\156\157\160\162\163\164" "\165\146\150\143\75\133\135\43\171\170" "\134\140\161" "\101\102\127\107\104\105\46\126\132\111" "\112\113\114\115\116\117\120\122\123\124" "\125\106\110\103\53\173\175\44\131\130" "\174\176\121", }; int *full_encoding_list(encoding_t encoding, int table[]){ int i,j; static int exists[256]; for(i=0;i<256;i++) exists[i]=0; for(i=0;i<66;i++) { table[i]=encoding_alphabet[encoding][i]; exists[table[i]]=1; } for(j=66,i=0;i<256;i++){ if(exists[i]) continue; table[j++]=i; } return table; } int *fill_recode_table(int table[], encoding_t from, encoding_t to){ static int full_enc_from[256]; static int full_enc_to[256]; int i; full_encoding_list(from,full_enc_from); full_encoding_list(to,full_enc_to); for(i=0;i<256;i++) table[full_enc_from[i]]=full_enc_to[i]; return table; } unsigned char *srecode(unsigned char *s, encoding_t from, encoding_t to){ static int prev_from=-1, prev_to=-1; static int recode_table[256]; int i; if((from!=prev_from)||(to!=prev_to)){ prev_from=from; prev_to=to; fill_recode_table(recode_table,from,to); } for(i=0;s[i];i++) s[i]=recode_table[s[i]]; return s; } unsigned char *srecode2(unsigned char *s, unsigned char *t, encoding_t from, encoding_t to){ static int prev_from=-1, prev_to=-1; static int recode_table[256]; int i; if((from!=prev_from)||(to!=prev_to)){ prev_from=from; prev_to=to; fill_recode_table(recode_table,from,to); } for(i=0;t[i];i++) s[i]=recode_table[t[i]]; s[i]=0; return s; } /* конец кода библиотеки SRECODE.C * * end of the code of the library SRECODE.C */ /*************************************************/ /**** ERROR_LIST ********/ /*************************************************/ // Внимание!!! Программа возвращает 0 тогда и только тогда, когда // успешно перекодировала файл (т.е. сделала то, для чего // предназначена). Выдача версии, или справки рассматриваются как // ошибки: такого при использовании в пакетном режиме происходить не // должно. // Список введён по просьбе Владислава Носова (nvv@mail^primorye^ru) enum{ ERROR_OK=0, ERROR_VERSION, ERROR_HELP, ERROR_DESCRIPTION, ERROR_NO_ARGUMENT, ERROR_WRONG_ARGUMENT, ERROR_INFORM_ENCODING, ERROR_SERIOUS=16, ERROR_INTERNAL=ERROR_SERIOUS, ERROR_MALLOC, ERROR_STAT_FILE, ERROR_EMPTY_FILE, ERROR_OPEN_FILE_READ, ERROR_OPEN_FILE_WRITE, ERROR_OPEN_FILE_TMP, ERROR_WRITE_FILE, }; #define NUMCOD 5 char encLetter[]={'a','w','k','i','m'}; int enc=OUTPUT_ENC; int program_output_encoding=OUTPUT_ENC; int Russian=1; unsigned char *alphabet= "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; int self_encoding=2; // по умолчанию --- собственная кодировка есть koi void determine_self_encoding(char *selfname){ for(self_encoding=0; self_encoding=16.\n" "In future versions other exit codes might be added, but current shall\n" "not be changed." "\n" " THE TABLE OF EXIT CODES:\n" , /* msg_encodings */ "OTHER SWITCHES\n" "\n" "Switch -- stops parsing command line arguments and further parameters\n" "are considered as filenames (this way you can work with files, whose\n" "name begins with dash sign - ;).\n" "\n" "Switch -с changes xcode to the state of informing about encoding\n" "of the input. The program prints to output file the following string\n" " encoding: name_of_input_file\n" "If standard input was used, then the name of input file is <>.\n" "Combination with -d leads to printing 3 encodings: \n" " from->to, result: имя_входного_файла\n" "where 'from->to' is the recommended transform to get the file suggestively\n" "in encoding 'result'.\n" "Using -c automatically implies -s, i.e. the information on encodings\n" "is not duplicated to standard errors stream.\n" "In order to view encodings of html-files in current directory\n" "under bash in GNU type in the following one-comman-line script:\n" " for f in *.html; do xcode -c $f; done\n" "To carry out the similar action in file manager Far under Win32 (and in\n" "all other childs of Commander Norton), select files, press Ctrl-G, and\n" "type in command\n" " xcode -c !.!\n" "\n" "The following switches could be used for input " "and output encoding. \nHowever, " "automatic recognition is supported for first 5 encodings only.\n" "More information can be found at \n" " " SELF_URL_BASE "/xcode.html\n", /* msg_version */ "Program "XCODE" version %s written by D.V.Khmelev\n" "(see http://www.rusf.ru/books/yo/xcode.html for details)\n" "\n" "The author disclaims any responsibility for program\n" "safety and holds no responsibility for the loss of\n" "data, resulting the the use of the program.\n" "However, the author tried to do his best to\n" "avoid loss of data.\n", /* msg_help */ "Usage: " XCODE" -E -[hH?] -[wkaim1234567890] +[wkaim1234567890] [-q] " "[in [out]]\n" "-E -h in English (don't forget to add -h or -H switch!)\n" "-v print version information\n" "-H manual, list of 14 encodings supported, and view YO-ware license\n" "-d double recoding (try if simple '"XCODE"' failed)\n" "-q quoted-printable decoding (useful for decoding MIME-files)\n" "-l decode html Unicoded text (like Дима)\n" "-c determine encoding and print it to the output (see details by -H)\n" "-t do unix2dos transformation (convert LF to CR/LF) in DOS/Win only\n" "-p pipe mode (applies to DOS/Win environment only)\n" "-s silent mode (no information on encodings displayed)\n" "If input/output files are not specified, the standard input/output is used.\n", /* msg_out */ "-%c to set %-10s output", /* msg_forc */ "+%c to force %-10s input\n", /* msg_defl */ " (default)\n", /* msg_info */ "-%d to set %-10s output +%d to set %-10s input\n", /* msg_err_temp_file */ "Unable to create temporary file. No free space on disk?\n", /* msg_guessinp */ "Guessed input encoding: %s\n", /* msg_forceinp */ "Forced input encoding: %s\n", /* msg_outpenc */ "Output encoding: %s\n", /* msg_double_recode */ "Double recode: %s->%s, %s->%s\n", /* msg_erropenfile */ "Unable to open output file %s\n", /* msg_err_in_file */ "Unable to open input file %s\n", /* msg_cant_write_temp_file */ "Can't write to temporary file. Disk full?\n", /* msg_pipe */ "To use pipe mode run the program with option -p\n", /* msg_tryhelp */ "Try `xcode -e -h' for more information.\n", /* msg_uni_qp */ "You can not use -q and -l switches simultaneously.\n" "Try pipe 'xcode -l|xcode -q' to get desired result.\n", /* msg_conflict_force_inform */ "You can not use -c and any of -l, +[awikm] or +1, +2, ...\n" "switches simultaneously.\n", /* msg_wrong_argument */ "*** ERROR IN A PROGRAM ARGUMENT ***\n", }; char *msgs_rus[]={ /* msg_descr */ "(Основано на программе, которую написал Андрей В. Лукьянов 14.05.1997,\n" "и которую потом правили Кирилл Ротмистровский и Игорь В. Красиков)\n" "\n" "ОПИСАНИЕ\n" "\n" "Эта программа автоматически определяет кодировку входного\n" "документа и преобразует документ в кодировку, Вам нужную.\n" "Важной особенностью программы является взаимно однозначная перекодировка,\n" "которая предохраняет от повреждений Ваш файл. Если преобразование прошло\n" "некорректно, или даже если вы преобразовали двоичный файл, Вы всегда можете\n" "ВОССТАНОВИТЬ исходный файл обратным преобразованием (если, конечно, Вы\n" "не воспользовались дополнительными опциями -l, -q или -t).\n" "\n" "ЛИЦЕНЗИЯ\n" "\n" "Программа является Ё-ware, Именно, её можно свободно распространять\n" "модифицировать, и даже дизассемблировать как в двоичном виде, так и в\n" "исходном тексте. Однако, используя эту программу, вы должны\n" "использовать букву Ё во всех текстах, которые набираете на компьютерах:\n" "начиная с электронных писем и заканчивая крупной прозаической формой.\n" "\n" "КОДЫ ВЫХОДА\n" "\n" "Программа выходит с кодом 0 только при условии, что она\n" "действительно выполнила то, для чего предназначалась: перекодировала\n" "файл. Во всех остальных случаях код возврата ненулевой.\n" "В частности, выдача подсказки возвращает ненулевой код ERROR_HELP.\n" "Ошибки, связанные со взаимодействием с операционной системой имеют\n" "код >=16. В будущих версиях могут добавляться другие коды выхода, но\n" "текущие изменяться не будут." "\n" " ТАБЛИЦА КОДОВ ВЫХОДА:\n" , /* msg_encodings */ "ДРУГИЕ ПЕРЕКЛЮЧАТЕЛИ\n" "\n" "Переключатель -- останавливает разбор аргументов командной строки\n" "и следующие параметры рассматриваются уже как имена файлов.\n" "(таким образом можно обрабатывать файлы, названия которых начинаются\n" "со знака дефиса - ;)\n" "\n" "Переключатель -с переводит xcode в режим выдачи информации о кодировке\n" "файла. Программа тогда выдаёт в выходной файл строку вида\n" " кодировка: имя_входного_файла\n" "Если использовался стандартный ввод, то имя входного файла <>.\n" "При комбинировании с -d выдаётся 3 кодировки: \n" " from->to, result: имя_входного_файла\n" "где from->to --- рекомендуемое преобразование, чтобы получить файл\n" "предположительно в кодировке result.\n" "Использование переключателя -c приводит к включению переключателя -s,\n" "т.е. информация о кодировках в поток ошибок не дублируется.\n" "Для просмотра информации о кодировке html-файлов в текущей директории\n" "под bash в GNU наберите следующий скрипт в командной строке:\n" " for f in *.html; do xcode -c $f; done\n" "Для выполнения аналогичной задачи в файловом менеджере Far под Win32\n" "(и прочих детях командира Нортона), выделите файлы, нажмите Ctrl-G и\n" "наберите команду\n" " xcode -c !.!\n" "\n" "Следующими переключателями можно установить входную и выходную " "кодировки. \nОднако, " "автоматическое определение кодировки работает только для первых 5.\n" "Дальнейшую информацию см. на странице \n" " " SELF_URL_BASE "/xcode.html\n", /* msg_version */ "Программу "XCODE" версия %s написал Д.В.Хмелёв\n" "(подробности см. http://www.rusf.ru/books/yo/xcode.html)\n" "\n" "Автор воздерживается от всяческих гарантий\n" "надёжности программы и снимает с себя \n" "ответственность за возможную потерю данных при её\n" "использовании. Тем не менее, автор постарался\n" "сделать всё возможное, чтобы потери данных можно\n" "было избежать.\n", /* msg_help */ "Вызов: " XCODE" -E -[hH?] -[wkaim1234567890] +[wkaim1234567890] [-q] " "[in [out]]\n" "-E -h in English (don't forget to add -h or -H switch!)\n" "-v информация о версии\n" "-H Полная справка, список 14 поддерживаемых кодировок и лицензия Ё-ware\n" "-d двойная перекодировка (пробуйте, если просто команда '"XCODE"' не сработала)\n" "-q декодирование \"quoted-pritable\" символов, используемых в MIME\n" "-l декодирование html-Уникод текста (вроде Дима)\n" "-c определить кодировку и выдать её в выходной файл (подробная справка по -H)\n" "-t произвести unix2dos преобразование (превратить LF в CR/LF) в DOS/WIN\n" "-p режим трубы (требуется только в DOS/Win окружении)\n" "-s режим silent --- не выводить информацию о кодировках\n" "Если входной/выходной файл не указан, используется стандартный ввод/вывод.\n", /* msg_out */ "-%c выводим в кодировке %-10s ", /* msg_forc */ "+%c на входе кодировка %-10s \n", /* msg_defl */ " (по умолчанию) \n", /* msg_info */ "-%d вывод в кодировке %-10s +%d входная кодировка %-10s\n", /* msg_err_temp_file */ "Не могу создать временный файл. Нет места на диске?\n", /* msg_guessinp */ "Угадана входная кодировка %s\n", /* msg_forceinp */ "В качестве входной установлена кодировка %s\n", /* msg_outpenc */ "Выходная кодировка %s\n", /* msg_double_recode */ "Двойная перекодировка: %s->%s, %s->%s\n", /* msg_erropenfile */ "Не могу открыть выходной файл %s\n", /* msg_err_in_file */ "Не могу открыть входной файл %s\n", /* msg_cant_write_temp_file */ "Не могу писать во временный файл. Диск полон?\n", /* msg_pipe */ "Для использования в режиме трубы запустите программу с опцией -p\n", /* msg_tryhelp */ "Попробуйте запустить `"XCODE" -h' для справки по программе.\n", /* msg_uni_qp */ "Нельзя использовать переключатели -q и -l совместно.\n" "Воспользуйтесь трубой 'xcode -l|xcode -q' для получения желаемого результата.\n", /* msg_conflict_force_inform */ "Недопустимо использование ключа -c совместно с любым\n" "из ключей -l, +[awikm], +1, +2, ...\n", /* msg_wrong_argument */ "*** ОШИБКА В АРГУМЕНТЕ ПРОГРАММЫ ***\n", }; typedef enum{msg_descr, msg_encodings,msg_version,msg_help,msg_out, msg_forc,msg_defl,msg_info, msg_err_temp_file, msg_guessinp, msg_forceinp, msg_outpenc, msg_double_recode, msg_erropenfile,msg_err_in_file, msg_cant_write_temp_file, msg_pipe, msg_tryhelp,msg_uni_qp, msg_conflict_force_inform, msg_wrong_argument, msg_last} msg_id; char *msg(msg_id id){ assert(id=192) rating[i]+=(0.0+input_freq[c]) *letter_frequency[((int)to_koi_recode_table[i][c-128]-192)%32]; for(i=0; i=0; i--) if(decide[i]){ if(bestrating) *bestrating=rating[i]; return i; } return 0; } void compute_rating_two(unsigned long * input_freq, int resenc, int *res_recode_table, int *res_fr,int *res_to,int *res_a){ int c,from,to,b_from,b_to,j; double rating[NUMCOD][NUMCOD]; int a[NUMCOD][NUMCOD]; static int wt[256]; static int wt1[256]; static unsigned long in_freq[256]; for(from=0;from=4) goto dropdigs; digs[dignum++]=c; state=dig; continue; } if(c==';'){ int num; if(dignum<4) goto dropdigs; digs[dignum]=0; num=atoi(digs); if((num<0x401)||(num>0x451)) goto dropdigs; if(!is_iso_russian_letter[num-0x400+0xA0]) goto dropdigs; putc(recode_table[num-0x400+0xA0],out); dignum=0; state=scan; continue; } dropdigs: putc('&', out); putc('#', out); for(i=0;i=0){ fill_recode_table(fput_recode_table,force,enc); if(!silent){ if(!unicode_html){ fprintf(stderr,msg(msg_forceinp),encoding_name[force]); fprintf(stderr,msg(msg_outpenc),encoding_name[enc]); } if(unicode_html){ fprintf(stderr,msg(msg_forceinp),"html-unicode"); fprintf(stderr,msg(msg_outpenc),encoding_name[enc]); } } if(samefile){ if(NULL==(f=tmpfile())){ fprintf(stderr,msg(msg_err_temp_file)); return ERROR_OPEN_FILE_WRITE; } if(chkQP) read_qp(in,f); else if(unicode_html) read_unicode_html(in,f,enc); else read_file(in,f); fclose(in); rewind(f); out=openout(outfname,out,wt); while((c=getc(f))!=EOF){ putc(c,out); } fclose(f); fclose(out); }else { out=openout(outfname,out,wt); if(chkQP) read_qp(in,out); else if(unicode_html) read_unicode_html(in,out,enc); else read_file(in,out); fclose(in); fclose(out); } return ERROR_OK; } f=tmpfile(); if(f==NULL){ fprintf(stderr,msg(msg_err_temp_file)); return ERROR_OPEN_FILE_WRITE; } if(chkQP) read_qp(in,f); else read_file(in,f); fclose(in); if(double_recode){ compute_rating_two(input_freq,enc,work_recode_table,&fr,&to,&a); if(!silent){ fprintf(stderr,msg(msg_double_recode),encoding_name[fr],encoding_name[to], encoding_name[a],encoding_name[enc]); } }else{ a=compute_rating(input_freq,NULL); if(!silent){ fprintf(stderr,msg(msg_guessinp),encoding_name[a]); fprintf(stderr,msg(msg_outpenc),encoding_name[enc]); } fill_recode_table(work_recode_table,a,enc); } rewind(f); out=openout(outfname,out,wt); if(inform_encoding_only){ char *displayfname=fname?fname:"<>"; if(double_recode) fprintf(out, "%s->%s, %s: %s\n", encoding_name[fr],encoding_name[to], encoding_name[a], displayfname); else fprintf(out, "%s: %s\n", encoding_name[a], displayfname); fclose(f); fclose(out); return ERROR_INFORM_ENCODING; } while((c=getc(f))!=EOF){ putc(work_recode_table[c],out); } fclose(f); fclose(out); return ERROR_OK; } int samebuf(struct stat *a,struct stat *b){ return (a->st_size==b->st_size) && (a->st_mtime==b->st_mtime); } int main(int argc,char ** argv) { char *wt="wb"; int force=-1; int chkQP=0; int samefile; int do_pipe=0; int inform_encoding_only=0; int silent=0; int double_recode=0; char *filename; char *outfname; int version=0,help=0,Help=0; int unicode_html=0; int I=0; determine_self_encoding(argv[0]); for(I=1;argc>I&& (*argv[I]=='+'||*argv[I]=='-' # ifdef D_ALT ||*argv[I]=='/' # endif //D_ALT );I++) { if(isdigit(argv[I][1])){ int code; if(sscanf(argv[I]+1,"%d",&code)!=1){ printf(msg(msg_wrong_argument)); print_short_help(); return ERROR_WRONG_ARGUMENT; } if((code<1)||(code>TOTAL_ENCODING_NUMBER)){ printf(msg(msg_wrong_argument)); print_short_help(); return ERROR_WRONG_ARGUMENT; } if(*argv[I]=='+') force=code-1; else enc=code-1; continue; } switch(argv[I][1]) { default: help=2; printf(msg(msg_wrong_argument)); goto exit_commad_line_parser; case 'e': case 'E': Russian=0; break; case 'v': version=1; break; case 'h': case '?': help=1; break; case 'H': Help=1; break; case 't': wt="wt"; break; case 'p': do_pipe=1; break; case 's': silent=1; break; case 'l': unicode_html=1; break; case 'd': double_recode=1; break; case 'c': inform_encoding_only=1; silent=1; break; case 'a': case 'A': if(*argv[I]=='+') force=0; else enc=0; break; case 'w': case 'W': if(*argv[I]=='+') force=1; else enc=1; break; case 'k': case 'K': if(*argv[I]=='+') force=2; else enc=2; break; case 'i': case 'I': if(*argv[I]=='+') force=3; else enc=3; break; case 'm': case 'M': if(*argv[I]=='+') force=4; else enc=4; break; case 'q': case 'Q': chkQP = 1; break; /* По опции -- прекращаем сканировать список аргументов */ case '-': if(strcmp(argv[I],"--")==0) I++; else { printf(msg(msg_wrong_argument)); help=2; } goto exit_commad_line_parser; } if(argv[I][2]) help=2; } exit_commad_line_parser: if(help) { print_short_help(); if(help==1) return ERROR_HELP; else return ERROR_WRONG_ARGUMENT; } if(Help) { print_long_help(); if(help==1) return ERROR_HELP; else return ERROR_WRONG_ARGUMENT; } if(version) print_version(); if(unicode_html&&chkQP){ fprintf(stderr,msg(msg_uni_qp)); return ERROR_WRONG_ARGUMENT; } if(unicode_html) force=ISO8859_5; if(inform_encoding_only&&(force>=0)){ fprintf(stderr,msg(msg_conflict_force_inform)); return ERROR_WRONG_ARGUMENT; } if (I + 2 < argc) { print_short_help(); } else if(I == argc){ # ifdef D_ALT if(!do_pipe){ fprintf(stderr,msg(msg_pipe)); fprintf(stderr,msg(msg_tryhelp)); return ERROR_HELP; } # endif filename=NULL; outfname=NULL; samefile=0; }else if (I + 1 == argc) { filename=argv[I]; outfname=NULL; samefile=0; }else if (I + 2 == argc) { struct stat inbuf; struct stat outbuf; filename=argv[I]; outfname=argv[I+1]; if(stat(filename,&inbuf)<0){ perror(filename); return ERROR_STAT_FILE; } if(stat(outfname,&outbuf)<0) samefile=0; else samefile=samebuf(&inbuf,&outbuf); } return do_recode(filename,outfname, enc,force,chkQP,unicode_html,double_recode,wt, samefile,inform_encoding_only,silent); }