1 /*
2   Purpose: call LATEX after preprocessing of the .tex file by
3            the cjk conversion tool. The old f_name.bat script
4 	   is not working anymore.
5   Author : F. Popineau <Fabrice.Popineau@supelec.fr>
6   Date   : <29/06/2001>
7 */
8 
9 #ifndef LATEX
10 #define LATEX "latex"
11 #endif
12 
13 /*
14   Copyright (C) 2001-2015  F. Popineau <Fabrice.Popineau@supelec.fr>
15 
16   This program is free software; you can redistribute it and/or modify
17   it under the terms of the GNU General Public License as published by
18   the Free Software Foundation; either version 2 of the License, or
19   (at your option) any later version.
20 
21   This program is distributed in the hope that it will be useful,
22   but WITHOUT ANY WARRANTY; without even the implied warranty of
23   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24   GNU General Public License for more details.
25 
26   You should have received a copy of the GNU General Public License
27   along with this program in doc/COPYING; if not, write to the Free
28   Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
29   MA 02110-1301 USA
30 */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 
35 #include <kpathsea/config.h>
36 #include <kpathsea/lib.h>
37 #include <kpathsea/getopt.h>
38 
39 static const char *cjklatex_version_string = "1.0";
40 
41 static const char *usage_str[] = {
42   "Usage: %s OPTIONS FILE\n",
43   "Calls `" LATEX "' on FILE after conversion by the filter\n",
44   "specified by OPTIONS.\n",
45   "--conv=bg5\tfor traditional Chinese, encoding Big 5,\n",
46   "--conv=cef\tfor Chinese Encoding Framework, encoding CEF,\n",
47   "--conv=cef5\tidem CEF, also converts Big5 characters,\n",
48   "--conv=cefs\tidem CEF, also converts SJIS characters,\n",
49   "--conv=gbk\tfor Chinese, encoding GBK,\n",
50   "--conv=sjis\tfor Japanese, SJIS encoding.",
51   "\nAlternatively, for compatibility with the previous DOS batch files,\n",
52   "you can also copy this program to any of the following names:\n",
53   "bg5" LATEX ".exe, cef5" LATEX ".exe, cef" LATEX ".exe, cefs" LATEX ".exe,\n",
54   "gbk" LATEX ".exe and sjis" LATEX ".exe .\n",
55   "Then running one of these programs will be identical to specify\n",
56   "the corresponding option.\n",
57   "\nAdditional options:\n",
58   "--verbose\tbe a bit more verbose about what is happening,\n",
59   "--nocleanup\tdo not remove intermediate files,\n",
60   "--latex=engine\tuse `engine' instead of `" LATEX "' to process the file.\n",
61   NULL
62 };
63 
64 static char *progname = NULL;
65 
66 static struct _conv_table {
67   const char *progname;
68   const char *processor;
69 } CJKtable[] = {
70   { "cjk" LATEX, "" },
71   { "bg5" LATEX, "bg5conv" },
72   { "cef" LATEX, "cefconv" },
73   { "cef5" LATEX, "cef5conv" },
74   { "cefs" LATEX, "cefsconv" },
75   { "gbk" LATEX, "extconv" },
76   { "sjis" LATEX, "sjisconv" }
77 };
78 
79 #define PROGRAM_IS(p) FILESTRCASEEQ (p, progname)
80 #define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
81 
82 static int program_number = -1;
83 static int opt_verbose = 0;
84 static int opt_nocleanup = 0;
85 static char *texname, *cjkname, *texengine;
86 
87 static struct option long_options [] = {
88     { "debug",               1, 0, 0},
89     { "help",                0, 0, 0},
90     { "version",             0, 0, 0},
91     { "verbose",             0, 0, 0},
92     { "nocleanup",           0, 0, 0},
93     { "latex",               1, 0, 0},
94     { "conv",                1, 0, 0},
95     {0, 0, 0, 0}
96 };
97 
sigint_handler(DWORD dwCtrlType)98 static BOOL sigint_handler(DWORD dwCtrlType)
99 {
100   /* Fix me : there is a problem if a system() command is running.
101      We should wait for the son process to be interrupted.
102      Only way I can think of to do that : rewrite system() based on
103      spawn() with parsing of the command line and set a global pid
104      Next cwait(pid) in the HandlerRoutine.
105      */
106 
107   /* This is not that good, but else we would need to wait for
108      the child processes to finish ! */
109   Sleep(250);
110 
111   fprintf(stderr, "Sending Ctrl+Break!\n");
112   GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
113 
114   if (! opt_nocleanup)
115     unlink(cjkname);
116 
117   exit(1);
118 
119   return FALSE;			/* return value obligatory */
120 }
121 
usage(void)122 static void usage(void)
123 {
124   int i;
125   fprintf(stderr, "CJK" LATEX " version %s\n", cjklatex_version_string);
126   fprintf(stderr,usage_str[0], progname );
127   fputs("\n", stderr);
128   for(i = 1; usage_str[i]; ++i)
129     fputs(usage_str[i], stderr);
130 }
131 
do_process(const char * processor,const char * filename)132 static int do_process(const char *processor, const char *filename)
133 {
134   char *ext, *p;
135   char cmd[_MAX_PATH*3];
136   DWORD dwFA;
137   int ret;
138 
139   if (strlen(filename) > 4 && _strnicmp(filename + strlen(filename) - 4, ".tex", 4) == 0) {
140     texname = xstrdup(filename);
141   }
142   else {
143     texname = concat(filename, ".tex");
144   }
145   for (p = texname; p && *p; p++)
146     *p = (*p == '\\' ? '/' : *p);
147 
148   dwFA = GetFileAttributes(texname);
149   if (dwFA == 0xFFFFFFFF || (dwFA & FILE_ATTRIBUTE_DIRECTORY)) {
150     fprintf(stderr, "%s: %s is an invalid input file.\n",
151 	    progname, texname);
152     ret = 1;
153   }
154   else {
155     cjkname = xstrdup(texname);
156     ext = strrchr(cjkname, '.');
157     assert(ext != NULL);
158     strcpy(cjkname + (ext - cjkname), ".cjk");
159 
160     sprintf(cmd, "%s < %s > %s", processor, texname, cjkname);
161     if (opt_verbose)
162       fprintf(stderr, "%s: running command `%s'.\n", progname, cmd);
163     ret = system(cmd);
164     if (ret == 0) {
165       sprintf(cmd, "%s %s", texengine, cjkname);
166       if (opt_verbose)
167 	fprintf(stderr, "%s: running command `%s'.\n", progname, cmd);
168       ret = system(cmd);
169       if (! opt_nocleanup)
170 	unlink(cjkname);
171     }
172   }
173 
174   free(texname);
175   free(cjkname);
176 
177   return ret;
178 }
179 
main(int argc,char * argv[])180 int main(int argc, char *argv[])
181 {
182   int g; /* getopt return code */
183   int i;
184   int option_index;
185   char *filename;
186 
187   if (!progname)
188     progname = argv[0];
189 
190   kpse_set_program_name (progname, NULL);
191   progname = kpse_program_name;
192 
193   for (i = 0; i < sizeof(CJKtable)/sizeof(CJKtable[0]) && program_number < 0; i++) {
194     if (STREQ(progname, CJKtable[i].progname)
195 #if 0
196 	|| (STREQ(progname, CJKtable[i].progname)
197 	    && STREQ(progname+strlen(CJKtable[i].progname), ".exe"))
198 #endif
199 	) {
200       program_number = i;
201     }
202   }
203 
204   if (program_number == -1) {
205     fprintf(stderr, "%s: this program has been incorrecty copied to the name %s.\n", progname, progname);
206     usage();
207     exit(1);
208   }
209 
210   for(;;) {
211     g = getopt_long_only (argc, argv, "", long_options, &option_index);
212 
213     if (g == EOF)
214       break;
215 
216     if (g == '?') {
217       usage();			/* Unknown option.  */
218       exit(1);
219     }
220 
221     /* assert (g == 0); */ /* We have no short option names.  */
222     /*
223       FIXME : try 'mktexpk --mfmode --bdpi 600 ...'
224       */
225     if (ARGUMENT_IS ("debug")) {
226       kpathsea_debug |= atoi (optarg);
227     }
228     else if (ARGUMENT_IS ("help")) {
229       usage();
230       exit(0);
231     }
232     else if (ARGUMENT_IS ("verbose")) {
233       opt_verbose = 1;
234     }
235     else if (ARGUMENT_IS ("nocleanup")) {
236       opt_nocleanup = 1;
237     }
238     else if (ARGUMENT_IS ("latex")) {
239       texengine = xstrdup(optarg);
240     }
241     else if (ARGUMENT_IS ("version")) {
242       fprintf(stderr, "%s of %s.\n", progname, cjklatex_version_string);
243       exit(0);
244     }
245     else if (PROGRAM_IS("cjk" LATEX)) {
246       if (ARGUMENT_IS("conv")) {
247 	for (i = 1; i < sizeof(CJKtable)/sizeof(CJKtable[0]) && program_number <= 0; i++) {
248 	  if (STRNEQ(optarg, CJKtable[i].progname, strlen(optarg))) {
249 	    program_number = i;
250 	  }
251 	}
252       }
253     }
254   }
255 
256   /* shifting options from argv[] list */
257   for (i = 1; optind < argc; i++, optind++)
258     argv[i] = argv[optind];
259   argv[i] = NULL;
260 
261   argc = i;
262 
263   if (argc < 2) {
264     fprintf (stderr, "%s: Missing argument(s).\nTry `%s --help' for more information.\n", progname, kpse_program_name);
265     exit(1);
266   }
267 
268   if (argc > 2) {
269     fprintf(stderr, "%s: Extra arguments", progname);
270     for (i = 2; i < argc; i++)
271       fprintf (stderr, " \"%s\"", argv[i]);
272     fprintf (stderr, "\nTry `%s --help' for more information.\n",
273 	     kpse_program_name);
274     exit(1);
275   }
276 
277   SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE);
278 
279   filename = xstrdup(argv[1]);
280 
281   assert(program_number > 0);
282 
283   if (! texengine) {
284     texengine = xstrdup(LATEX);
285   }
286 
287   do_process(CJKtable[program_number].processor, filename);
288 
289   free(filename);
290   free(texengine);
291 
292   return 0;
293 }
294