2019年5月13日月曜日

e2ps の修正パッチを一段落させた

 Linux などで日本語テキストファイルをPostScript形式に変換するソフトウェアの一つに e2ps があるのですが、いろいろバグが多くて困っており、一昨年くらいからちまちまと直したりしていました。
http://taraijpn.blogspot.com/2017/06/e2pspatch.html

 とりあえず Debian BTS で公開されているバグを直すところまで出来たので改めて紹介します。修正点は以下の通り。
  • フォントリストの文字型配列がコンパイル不能な書き方だった点を修正。
    • 各ディストリビューションで対応されています。
  • 用紙サイズのポイント数を PostScript の仕様で使われている数に合わせて修正。
    • 一部ディストリビューションで対応されています。
  • 生成される PostScript が EPS だった問題などを修正。
    • これでようやく fixps に怒られずに済みます。
  • 出力したページ数が誤っていた問題を修正。
    • ja_JP.EUC-JP 環境以外で動いているときに起こる問題でした。
  • ヌル文字から始まるテキストファイルが与えられるとクラッシュする問題を修正。
    • これは  https://bugs.debian.org/715852 で報告されていたものです。ヌル文字しかない、もしくはヌル文字から始まる(という意地の悪い)テキストファイルを印刷しようとすると起こる問題です。
  • 複数のファイルをまとめて変換すると、他のファイルの印刷末尾に余計な文字列が含まれる問題を修正。malloc を全て calloc に書き換えた。
    • e2ps README.euc README.english などとして出来たファイルを見たとき気づきました。環境依存?
  • Letterサイズで2面付け(-p2, -l2)を行うと用紙をオーバーする問題を修正。
    • 用紙のアスペクト比を維持するか、アスペクト比を歪めて紙面を広く使うか、どちらか悩んだ結果、前者を取りました。本来であればマージンを調整すべきところなのですが、それは全ての用紙サイズで考えないといけないことなので棚上げ。
  • PostScript の作者 ( %%Creator: ) は e2ps であるものとした。
    • CREATOR は help で使ってたので手を入れました。

 以上の内容を、patch1 として公開しました。(2019/5/14 patch1タグを打ってあります。
https://gist.githubusercontent.com/taraijpn/ea10ff9e908befafab7cff719f26dd20/raw/9a4a6fd502958a0e87db364174cbc331d07055be/e2ps-4.34.patch

diff -urN e2ps-4.34.orig/e2ps.c e2ps-4.34/e2ps.c
--- e2ps-4.34.orig/e2ps.c 2002-08-21 17:50:02.000000000 +0900
+++ e2ps-4.34/e2ps.c 2019-05-14 00:12:35.434084200 +0900
@@ -32,6 +32,7 @@
float gfFontSize, gfNlRate;
float gfAsciiWidth, gfAsciiHeight;
float gfKanjiWidth, gfKanjiHeight;
+float gfDXscale=SQRT, gfDYscale=SQRT;
char gsNowTime[STRMAX], gsHeadStr[STRMAX], gsPageStr[STRMAX];
uchar guJapanese = 1;
@@ -67,6 +68,7 @@
long lFileSize;
float fMaxWidth;
float ftmp;
+ int pFileNum=0; /* Number of processing files */
#ifdef TEKTRO
uchar uCopy = 1; /* Number of paper */
uchar uDup = 0; /* Both side */
@@ -328,18 +330,24 @@
strcpy(sPaper, "A4");
giWidth = A4WIDTH;
giHeight = A4HEIGHT;
+ gfDXscale = SQRT; /* 1.0/sqrt(2)=sqrt(0.5) */
+ gfDYscale = SQRT; /* 1.0/sqrt(2) */
}
else if ( strcmp(argv[i], "-b4") == 0 ) {
/* B4 */
strcpy(sPaper, "B4");
giWidth = B4WIDTH;
giHeight = B4HEIGHT;
+ gfDXscale = SQRT; /* 1.0/sqrt(2) */
+ gfDYscale = SQRT; /* 1.0/sqrt(2) */
}
else if ( strcmp(argv[i], "-le") == 0 ) {
/* Letter */
- strcpy(sPaper, "LETTER");
+ strcpy(sPaper, "Letter");
giWidth = LEWIDTH;
giHeight = LEHEIGHT;
+ gfDXscale = 0.647; /* if set (612/792)=0.772, it change aspect ratio and fill in areas of the paper. */
+ gfDYscale = 0.647; /* min(396/612,612/792) */
}
else if ( strcmp(argv[i], "-tm") == 0 ) {
/* Top margin */
@@ -485,7 +493,7 @@
/* Print Font List */
if ( guJapanese ) {
printf("\nフォントリスト\n");
- printf("%s", ps_font(NULL, NULL));
+ printf("%s\n", ps_font(NULL, NULL));
/* printf("Ryumin-Light-H\n"); */
/* printf("Ryumin-Light-H-Italic\n"); */
/* printf("Ryumin-Light-EUC-H\n"); */
@@ -497,7 +505,7 @@
}
else {
printf("\nFont Lists\n");
- printf("%s", ps_font(NULL, NULL));
+ printf("%s\n", ps_font(NULL, NULL));
/* printf("Ryumin-Light-H\n"); */
/* printf("Ryumin-Light-H-Italic\n"); */
/* printf("Ryumin-Light-EUC-H\n"); */
@@ -630,13 +638,13 @@
/* Start Input and Output */
/* Header */
- fprintf(gpfOut, "%%!PS-Adobe-2.0 EPSF-1.2\n");
+ fprintf(gpfOut, "%%!PS-Adobe-2.0\n");
fprintf(gpfOut, "%%%%Title:");
for ( iFileNum = 0 ; iFileNum < iFiles ; iFileNum++ ) {
fprintf(gpfOut, " %s", sFileNames[iFileNum]);
}
fprintf(gpfOut, "\n");
- fprintf(gpfOut, "%%%%Creator: %s\n", CREATOR);
+ fprintf(gpfOut, "%%%%Creator: %s Version %.02f\n", gsCommand, VERSION/100.0);
fprintf(gpfOut, "%%%%CreationDate: %s\n", gsNowTime);
fprintf(gpfOut, "%%%%Pages: (atend)\n");
fprintf(gpfOut, "%%%%PageOrder: Ascend\n");
@@ -647,13 +655,16 @@
fprintf(gpfOut, "%%%%Requirements: numcopies(%d) collate\n", uCopy);
#endif
fprintf(gpfOut, "%%%%EndComments\n\n");
+
+ /* Begin Setup */
+ fprintf(gpfOut, "%%%%BeginSetup\n\n");
#ifdef TEKTRO
/* Number of Paper */
fprintf(gpfOut, "/#copies %d def\n\n", uCopy);
/* Both side */
if ( uDup ) {
- fprintf(gpfOut, "[{\n");
- fprintf(gpfOut, "%%%%BeginFeature: *Duplex DuplexTumble\n\n");
+ fprintf(gpfOut, "mark {\n");
+ fprintf(gpfOut, "%%%%BeginFeature: *Duplex DuplexTumble\n");
fprintf(gpfOut, " <</Duplex true /Tumble false>> setpagedevice\n");
fprintf(gpfOut, "%%%%EndFeature\n");
fprintf(gpfOut, "} stopped cleartomark\n\n");
@@ -729,7 +740,9 @@
fprintf(gpfOut, "/HEAD-KANJI-BOLD { /GothicBBB-Medium-H } bind def\n");
}
fprintf(gpfOut, "\n\n");
-
+ /* End Setup */
+ fprintf(gpfOut, "%%%%EndSetup\n\n");
+
/* Page */
giPsPage = 0;
@@ -775,6 +788,11 @@
/* If file has no data, go to next file */
if ( sFileData == NULL ) continue;
+ /* If sFileData has enpty, go to next file */
+ if ( strlen(sFileData) == 0 ) continue;
+
+ /* processing file */
+ ++pFileNum;
/* Change to EUC */
sTmp = change2euc(sFileData);
@@ -916,8 +934,13 @@
fprintf(gpfOut, "\n\ngrestore\n\nshowpage\n\n");
free(sFileData);
}
+ /* make blank page for invalid files */
+ if (pFileNum == 0){
+ fprintf(gpfOut, "\n\nshowpage\n\n");
+ ++giPsPage;
+ }
/* Finish */
- fprintf(gpfOut, "%%%%Trailer\n");
+ fprintf(gpfOut, "%%%%Trailer\n%%%%EOF\n");
if ( uLpr ) {
pclose(gpfOut);
@@ -931,11 +954,11 @@
fprintf(stderr, "%% %d ページ出力しました\n", giPsPage);
}
else {
- if ( giPsPage == 1 ) {
- fprintf(stderr, "%% %d pages were outputed.\n", giPsPage);
+ if ( giPsPage != 1 ) {
+ fprintf(stderr, "%% %d pages were outputted.\n", giPsPage);
}
else {
- fprintf(stderr, "%% One page was outputed.\n");
+ fprintf(stderr, "%% One page was outputted.\n");
}
}
@@ -949,7 +972,12 @@
if ( gsBoldItalicKanjiFont != NULL ) free(gsBoldItalicKanjiFont);
if ( sPrinter != NULL ) free(sPrinter);
- return 0;
+ if (pFileNum > 0){
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "%% invalid files. blank page maybe outputted.\n");
+ return EXIT_FAILURE;
+ }
}
@@ -1103,7 +1131,7 @@
fprintf(stderr, "%% %d ページ目出力中\n", giPsPage);
}
else {
- fprintf(stderr, "%% Page %d is being outputed...\n", giPsPage);
+ fprintf(stderr, "%% Page %d is being outputted...\n", giPsPage);
}
}
}
@@ -1117,7 +1145,7 @@
break;
case 0x01:
/* Landscape Double */
- fprintf(gpfOut, "%.2f %.2f scale\n", SQRT, SQRT);
+ fprintf(gpfOut, "%.3f %.3f scale\n", gfDXscale, gfDYscale);
if ( ( giPage % 2 ) == 1 ) {
/* Odd page */
fprintf(gpfOut, "0 %d translate\n", giHeight);
@@ -1167,7 +1195,7 @@
break;
case 0x11:
/* Portrait Double */
- fprintf(gpfOut, "%.2f %.2f scale\n", SQRT, SQRT);
+ fprintf(gpfOut, "%.3f %.3f scale\n", gfDXscale, gfDYscale);
fprintf(gpfOut, "90 rotate\n");
switch ( giPage % 2 ) {
case 1:
@@ -1497,13 +1525,13 @@
}
-/* malloc string area */
+/* calloc string area */
char *setstring(char *sStr) {
char *sMalloc;
if ( sStr == NULL || *sStr == '\0' ) return NULL;
- if ( ( sMalloc = (char *)malloc(sizeof(char)*(strlen(sStr)+1)) ) == NULL ) {
+ if ( ( sMalloc = (char *)calloc((strlen(sStr)+1),sizeof(char)) ) == NULL ) {
if ( guJapanese ) {
fprintf(stderr, "メモリが足りません。\n");
}
@@ -1519,13 +1547,13 @@
}
-/* malloc string area2 */
+/* calloc string area2 */
char *setstringsize(int iSize) {
char *sMalloc;
if ( iSize <= 0 ) return NULL;
- if ( ( sMalloc = (char *)malloc(sizeof(char)*iSize) ) == NULL ) {
+ if ( ( sMalloc = (char *)calloc(iSize,sizeof(char)) ) == NULL ) {
if ( guJapanese ) {
fprintf(stderr, "メモリが足りません。\n");
}
@@ -1675,7 +1703,7 @@
fprintf(stderr, " -ls nlrate : space ratio between lines (%0.1f)\n", NLRATE);
fprintf(stderr, " -line line : max lines (%d)\n", MAXLINE);
fprintf(stderr, " -a4 : A4 paper (default)\n");
- fprintf(stderr, " -b4 : B4 paper\n");
+ fprintf(stderr, " -b4 : B4(JIS) paper\n");
fprintf(stderr, " -le : letter paper\n");
fprintf(stderr, " -ohp : OHP printing (font size:%0.1f)\n", OHPFONTSIZE);
fprintf(stderr, " -box : print page frame-line (looks like a2ps)\n");
diff -urN e2ps-4.34.orig/e2ps.h e2ps-4.34/e2ps.h
--- e2ps-4.34.orig/e2ps.h 2002-08-21 17:50:05.000000000 +0900
+++ e2ps-4.34/e2ps.h 2019-05-14 00:12:48.678862800 +0900
@@ -31,12 +31,12 @@
#define ESC (0x1b) /* Escape */
/* Paper */
-#define A4WIDTH (594)
-#define A4HEIGHT (840)
+#define A4WIDTH (595)
+#define A4HEIGHT (842)
#define LEWIDTH (612)
-#define LEHEIGHT (796)
-#define B4WIDTH (730)
-#define B4HEIGHT (1030)
+#define LEHEIGHT (792)
+#define B4WIDTH (729) /*B4(JIS)*/
+#define B4HEIGHT (1032) /*B4(JIS)*/
/* sqrt(0.5) */
#define SQRT (0.707106781186548)
diff -urN e2ps-4.34.orig/ps-font.c e2ps-4.34/ps-font.c
--- e2ps-4.34.orig/ps-font.c 2002-02-05 00:25:38.000000000 +0900
+++ e2ps-4.34/ps-font.c 2019-05-14 00:11:34.045277000 +0900
@@ -11,47 +11,7 @@
#include "e2ps.h"
-char *gsFonts = "Times-Roman
-Times-Italic
-Times-Bold
-Times-BoldItalic
-Helvetica
-Helvetica-Oblique
-Helvetica-Bold
-Helvetica-BoldOblique
-Courier
-Courier-Oblique
-Courier-Bold
-Courier-BoldOblique
-Symbol
-AvantGarde-Book
-AvantGarde_BookOblique
-AvantGarde_Demi
-AvantGarde_DemiOblique
-Bookman-Light
-Bookman-LightItalic
-Bookman-Demi
-Bookman-DemiItalic
-Helvetica-Narrow
-Helvetica-Narrow-Oblique
-Helvetica-Narrow-Bold
-Helvetica-Narrow-BoldObliqeu
-NewCenturySchlbl-Roman
-NewCenturySchlbl-Italic
-NewCenturySchlbl-Bold
-NewCenturySchlbl-BoldItalic
-Palatino-Roman
-Palatino-Italic
-Palatino-Bold
-Palatino-BoldItalic
-Zapfchancery-MediumItalic
-ZapfDingbats
-Ryumin-Light.Hiragana
-Ryumin-Light.Katakana
-Gothic-Meduim.Hiragana
-Gothic-Medium.Katakana
-";
-
+char *gsFonts = "Times-Roman Times-Italic Times-Bold Times-BoldItalic Helvetica Helvetica-Oblique Helvetica-Bold Helvetica-BoldOblique Courier Courier-Oblique Courier-Bold Courier-BoldOblique Symbol AvantGarde-Book AvantGarde_BookOblique AvantGarde_Demi AvantGarde_DemiOblique Bookman-Light Bookman-LightItalic Bookman-Demi Bookman-DemiItalic Helvetica-Narrow Helvetica-Narrow-Oblique Helvetica-Narrow-Bold Helvetica-Narrow-BoldObliqeu NewCenturySchlbl-Roman NewCenturySchlbl-Italic NewCenturySchlbl-Bold NewCenturySchlbl-BoldItalic Palatino-Roman Palatino-Italic Palatino-Bold Palatino-BoldItalic Zapfchancery-MediumItalic ZapfDingbats Ryumin-Light.Hiragana Ryumin-Light.Katakana Gothic-Meduim.Hiragana Gothic-Medium.Katakana";
/* Set PostScript Font Width */
char *ps_font(char *font, float f[256]) {
diff -urN e2ps-4.34.orig/wtkf.c e2ps-4.34/wtkf.c
--- e2ps-4.34.orig/wtkf.c 2002-02-05 00:25:38.000000000 +0900
+++ e2ps-4.34/wtkf.c 2019-05-14 00:11:34.049276400 +0900
@@ -137,7 +137,7 @@
/* Temporary area */
size = WT_JP_CODE_STRMAX;
- if ( ( tmp = (unsigned char *)malloc(sizeof(unsigned char)*size) ) == NULL ) {
+ if ( ( tmp = (unsigned char *)calloc(size,sizeof(unsigned char)) ) == NULL ) {
return NULL;
}
@@ -222,7 +222,7 @@
/* Temporary area */
size = WT_JP_CODE_STRMAX;
- if ( ( tmp = (unsigned char *)malloc(sizeof(unsigned char)*size) ) == NULL ) {
+ if ( ( tmp = (unsigned char *)calloc(size,sizeof(unsigned char)) ) == NULL ) {
return NULL;
}
@@ -333,7 +333,7 @@
length = strlen(string) + 1;
- if ( ( ret = (unsigned char *)malloc(sizeof(unsigned char)*length) ) == NULL ) {
+ if ( ( ret = (unsigned char *)calloc(length,sizeof(unsigned char)) ) == NULL ) {
return NULL;
}
view raw e2ps-4.34.patch hosted with ❤ by GitHub

 実はもう少しやらないといけないことがあって、
  • 変数の型を整理する。
    • unsigned char を使わないようにする。そもそも string.h で読んでいる関数と合わず warning が出ます。
    • unsigned char や signed char といった型は使わないようにして、コンパイラの警告をなくす。
  • 読み込めるファイルサイズを制限する。(2GB程度の予定)
    • unsigned long を size_t に直したらえらいことになったので。
 機械的な置き換えで問題ないかと思ったのですが、そんなに甘くなかった。sjisの変換に失敗する、とか、READMEにある他アーキテクチャ対応に悪影響が及びそうな気がするので、ちょっと止めてあります。とりあえず patch1 の上流での採用を目指したいところ。

 なお上流への連絡は、WebページにあるCGIで掲示板への書き込みやメールの送信を試みましたがいずれもエラーで動かず、2015年に公開されていたWindowsのプログラムにあるreadmeにメールアドレスが掲載されていたので、そこに送っています。果たして無事届いていますでしょうか……

0 件のコメント: