1 /*
2 
3 Try TEXMFVAR as a head directory, if not defined try TEXMFMAIN next.
4 
5 
6 fmtutil.c   (2002/10/06 --ak)
7 Web2C-7.3.9 (2002/10/25 --ak)
8 Web2C-7.4.2 (2002/12/27 --ak)
9 Web2C-7.4.3 (2003/01/12 --ak)
10 Web2C-7.5.2 (2003/11/09 --ak)
11 Web2C-7.5.3 (2004/05/09 --ak)
12 Web2C-7.5.3 (2004/06/11 --ak)
13 Web2C-7.5.5 (2005/12/23 --ak)
14 Web2C-7.5.5 (2006/11/25 --ak)
15 Web2C-7.5.6 (2007/06/01 --ak) save log files.
16 Web2C-7.5.6 (2008/01/20 --ak) Create necessary directories.
17 Web2C-2009  (2009/06/11 --ak) error handling.
18 Web2C-2009  (2009/08/13 Nobert) new option --byengine
19 Web2C-2009  (2009/10/10 --ak) creates mplib-luatex.mem.
20 Web2C-2010  (2010/05/31 --ak) multiple language files.
21 Web2C-2010  (2010/07/03 --ak) new options.
22 */
23 
24 #include <kpathsea/kpathsea.h>
25 
26 #include "dirutil.h"
27 #include "mktexupd.h"
28 
29 #define BLEN       512
30 #define SLEN       256
31 #define MAXFMT     128
32 #define SIXTY4     64
33 #define SIXTEEN    16
34 #define DEFAULTCNF "fmtutil.cnf"
35 #define REVISION   "fmtutil (C version 0.7) 2002-2010 --ak"
36 
37 typedef struct {
38 char *format;
39 char *engine;
40 char *hyphen;
41 char *args;
42 } cmd_t;
43 
44 /*
45 Global variables
46 */
47 cmd_t K[MAXFMT];
48 int   Fmtnum = 0;
49 char  Buff[BLEN];
50 char  Programname[BLEN];
51 char  Enginename[BLEN];
52 char  Realenginename[BLEN];
53 char  Destdir[BLEN];
54 char  Currdir[BLEN];
55 char  *Exefile[MAXFMT];
56 unsigned char  Exenum = 0;
57 int   Errorcnt = 0;
58 int   UserDestdir = 0;
59 int   QQQ = 0; /* quiet */
60 
61 static void
revision(void)62 revision(void)
63 {
64   printf(REVISION "\n");
65 }
66 
67 static void
usage(void)68 usage(void)
69 {
70   printf(
71 "Commands:\n"
72 " --all                     recreate all format, base, mem files\n"
73 " --missing                 create all missing format, base, mem files\n"
74 " --refresh                 recreate existing format, base, mem files\n"
75 " --byfmt FORMATNAME        (re)create format for `FORMATNAME'\n"
76 "                           `base' and `mem' files can also be created\n"
77 " --byhyphen HYPHENFILE     (re)create formats that depend on `HYPHENFILE'\n"
78 " --byengine ENGINENAME     (re)create formats that depend on `ENGINENAME'\n"
79 " --showhyphen FORMATNAME   print name of hyphenfile for format `FORMATNAME'\n"
80 " --version                 show revision number\n"
81 " --help                    show this message\n"
82 " --enablefmt FORMATNAME    (not implemented)\n"
83 " --disablefmt FORMATNAME   (not implemented)\n"
84 " --listcfg                 (not implemented)\n"
85 " --catcfg                  (not implemented)\n"
86 " --edit                    (not implemented)\n"
87 "\n"
88 "Options:\n"
89 " --cnffile FILE            set configfile for fmtutil\n"
90 "                           default is `fmtutil.cnf'\n"
91 " --fmtdir DIRECTORY        set destination directory for format files\n"
92 "                           `DIRECTORY' must be an absolute path\n"
93 "                           default is $TEXMFVAR/web2c/$engine\n"
94 "                           or $TEXMFMAIN/web2c/$engine if TEXMFVAR is undefined\n"
95 " --engine TEXENGINE        specify the TeX engine (with --byfmt fmtname)\n"
96 " --quiet                   be silent\n"
97 " --no-error-if-no-format   (just for compatibility)\n"
98 " --no-engine-subdir        (not implemented)\n"
99 " --test                    (not implemented)\n"
100 " --dolinks                 (not implemented)\n"
101 " --force                   (not implemented)\n");
102 }
103 
104 static void
freeK(void)105 freeK(void)
106 {
107   int i;
108   for(i=0; i < MAXFMT; i++) {
109     free(K[i].format);
110     free(K[i].engine);
111     free(K[i].hyphen);
112     free(K[i].args);
113     free(Exefile[i]);
114   }
115 }
116 
117 static int
do_initex(char * fm,char * en,char * args)118 do_initex(char *fm, char *en, char *args)
119 {
120   int  ret, lsrflag;
121   char fmt[BLEN];
122   char ext[SIXTEEN];
123   char cmd[BLEN];
124   char progn[BLEN];
125   char progn2[BLEN];
126   char enginesubdir[BLEN];
127   char src[BLEN];
128   char dst[BLEN];
129   char logdst[BLEN];
130   char log[BLEN];
131   char fullbin[256], *pp;
132 
133   if(!strnicmp(fm, "cont", 4)) strcpy(progn, "context");
134   else if(!strnicmp(fm, "ptex-", 5)) strcpy(progn, "ptex");
135   else if(!strnicmp(fm, "platex-", 7)) strcpy(progn, "platex");
136   else strcpy(progn, fm);
137 
138   strcpy(enginesubdir, en);
139 
140   if(!strcasecmp(enginesubdir, "mf-nowin"))
141     strcpy(enginesubdir, "metafont");
142   if(!strcasecmp(enginesubdir, "mf"))
143     strcpy(enginesubdir, "metafont");
144   if(!strcasecmp(enginesubdir, "mpost"))
145     strcpy(enginesubdir, "metapost");
146 
147   if(!strcasecmp(en, "mf-nowin")) {
148     strcpy(fmt, "--jobname=");
149     strcpy(ext, ".base");
150   }
151   else if(!strcasecmp(en, "mf")) {
152     strcpy(fmt, "--jobname=");
153     strcpy(ext, ".base");
154   }
155   else if(!strcasecmp(en, "mpost")) {
156     strcpy(fmt, "--jobname=");
157     strcpy(ext, ".mem");
158   }
159   else if(!strcasecmp(en, "pmpost")) {
160     strcpy(fmt, "--jobname=");
161     strcpy(ext, ".mem");
162   }
163   else if(!strcasecmp(en, "upmpost")) {
164     strcpy(fmt, "--jobname=");
165     strcpy(ext, ".mem");
166   }
167   else if(!strcasecmp(en, "mp641")) {
168     strcpy(fmt, "--jobname=");
169     strcpy(ext, ".mem");
170   }
171   else if(!strcasecmp(en, "nts")) {
172     strcpy(fmt, "--fmt=");
173     strcpy(ext, ".nfmt");
174   }
175   else {
176     strcpy(fmt, "--jobname=");
177     strcpy(ext, ".fmt");
178   }
179 
180   if(!strcasecmp(en, "pmpost") || !strcasecmp(en, "mpost")
181      || !strcasecmp(en, "upmpost") || !strcasecmp(en, "mp641"))
182     strcpy(progn2, "mpost");
183   else if(!strcasecmp(en, "mf-nowin"))
184     strcpy(progn2, "mf");
185   else if(!strcasecmp(en, "nts"))
186     strcpy(progn2, "tex");
187   else strcpy(progn2, progn);
188 
189   pp = kpse_var_value("SELFAUTOLOC");
190   if(pp == NULL) {
191      fprintf(stderr, "I cannot get SELFAUTOLOC\n");
192      exit(100);
193   }
194   fullbin[0] = '\"';
195   fullbin[1] = '\0';
196   strcat(fullbin, pp);
197   free(pp);
198   for(pp=fullbin; *pp; pp++) {
199      if(*pp == '/') *pp = '\\';
200   }
201   strcat(fullbin, "\\");
202   strcat(fullbin, en);
203   strcat(fullbin, "\"");
204 
205   if(!strcasecmp(en, "nts"))
206     sprintf(cmd, "%s --ini --progname=%s %s <nul",
207             fullbin, progn2, args);
208   else
209     sprintf(cmd, "%s --ini %s%s --progname=%s %s <nul",
210             fullbin, fmt, fm, progn2, args);
211 
212   if(QQQ == 0)
213     fprintf(stderr, "Running: %s\n", cmd);
214   ret = system(cmd);
215   strcpy(src, fm);
216   strcpy(log, fm);
217   strcat(log, ".log");
218   strcat(src, ext);
219   strcpy(dst, Destdir);
220 
221   if((UserDestdir == 0) && strcasecmp(enginesubdir, "nts")) {
222     strcat(dst, enginesubdir);
223     if(!is_dir(dst)) {
224       if(make_dir(dst)) {
225         fprintf(stderr, "Failed to make format in %s.\n", dst);
226         return (-100);
227       }
228     }
229     strcat(dst, "/");
230   }
231 
232   strcpy(logdst, dst);
233   strcat(logdst, log);
234   strcat(dst, src);
235   if(_access(dst, 0) == 0)
236     lsrflag = 0;
237   else
238     lsrflag = 1;
239 
240   if((_access(src, 0) == 0) && ret == 0) {
241     CopyFile(src, dst, FALSE);
242     if(lsrflag) mktexupd(dst);
243     if(strcasecmp(src, "mpost.mem") == 0) {
244        int len;
245        char *tmpstr;
246        len = strlen(dst);
247        tmpstr = (char *)malloc(len + 10);
248        strcpy(tmpstr, dst);
249        tmpstr[len-9] = '\0';
250        strcat(tmpstr, "mplib-luatex.mem");
251        if(_access(tmpstr, 0) == 0)
252           free(tmpstr);
253        else {
254          CopyFile(src, tmpstr, FALSE);
255          mktexupd(tmpstr);
256          free(tmpstr);
257       }
258     }
259     remove(src);
260     if(_access(logdst, 0) == 0)
261        lsrflag = 0;
262     else
263        lsrflag = 1;
264     if(_access(log, 0) == 0) {
265        CopyFile(log, logdst, FALSE);
266        if(lsrflag) mktexupd(logdst);
267        remove(log);
268     }
269     if(QQQ == 0)
270       fprintf(stderr, "The file %s%s was created.\n", fm, ext);
271     if(!strcmp(progn, "context"))
272       strcpy(Exefile[Exenum], "texexec");
273     else if(!strcmp(en, "nts"))
274       strcpy(Exefile[Exenum], "nts");
275     else
276       strcpy(Exefile[Exenum], fm);
277 
278     Exenum++;
279   } else {
280     if(_access(src, 0) == 0)
281        remove(src);
282     if(_access(logdst, 0) == 0)
283        lsrflag = 0;
284     else
285        lsrflag = 1;
286     if(_access(log, 0) == 0) {
287        CopyFile(log, logdst, FALSE);
288        if(lsrflag) mktexupd(logdst);
289        remove(log);
290     }
291     if(QQQ == 0) {
292        fprintf(stderr, "\nThe file %s%s was not created due to some errors.\n",
293                fm, ext);
294        fprintf(stderr, "See the log file %s for details.\n", logdst);
295     }
296     Errorcnt++;
297     ret = -100;
298   }
299   return ret;
300 }
301 
302 static void
do_all(void)303 do_all(void)
304 {
305   int i;
306 
307   for(i = 0; i < Fmtnum; i++)
308     do_initex(K[i].format, K[i].engine, K[i].args);
309 }
310 
311 static void
show_hyphen(char * fm,char * hfile)312 show_hyphen(char *fm, char *hfile)
313 {
314   char *p, *q, *r;
315   int  cont;
316   char progn[BLEN];
317 
318   if(!strcmp(hfile, "-")) {
319     printf("%s\n", hfile);
320     return;
321   }
322 
323   if(!strnicmp(fm, "cont", 4)) strcpy(progn, "context");
324   else strcpy(progn, fm);
325   if(QQQ == 0)
326     fprintf(stderr, "Searching ... \n");
327   kpse_reset_program_name(progn);
328   q = hfile;
329   cont = 1;
330   while(cont) {
331     for(r=q; *r && *r != ','; r++)
332       ;
333     if(*r == '\0') cont = 0;
334     *r = '\0';
335     r++;
336     p = kpse_find_file(q, kpse_tex_format, 0);
337     if(!p) {
338       if(QQQ == 0)
339         fprintf(stderr, "%s not found.\n", q);
340       q = r;
341       continue;
342     }
343     printf("%s\n", p);
344     free(p);
345     q = r;
346   }
347   kpse_reset_program_name(Programname);
348   return;
349 }
350 
351 static int
testexe(char * name,const char * suffix)352 testexe(char *name, const char *suffix)
353 {
354   char buffer[BLEN];
355   char *p;
356 
357   if(SearchPath(NULL, name, suffix, BLEN, buffer, &p))
358     return 1;
359   else
360     return 0;
361 }
362 
363 int
main(int ac,char ** av)364 main(int ac, char **av)
365 {
366   FILE *in;
367 
368   int  i, j, k;
369   char *cnfname;
370   char *p;
371   char cnffile[BLEN];
372   char fmtname[BLEN];
373   char hyphenfile[BLEN];
374   char byenginename[BLEN];
375   char kpsedot[BLEN];
376   char enginesubdir[BLEN];
377   char *tmp;
378   int  cdrive, tdrive;
379 
380   int  flag;
381 
382 /*
383 flag = 1 : --all
384        2 : --missing
385        3 : --byfmt formatname
386        4 : --byhyphen hyphenfile
387        5 : --showhyphen formatname
388        6 : --refresh
389        7 : --byengine engine
390 */
391 
392   flag = 0;
393   cnffile[0] = '\0';
394   fmtname[0] = '\0';
395   hyphenfile[0] = '\0';
396   byenginename[0] = '\0';
397   Destdir[0] = '\0';
398   Currdir[0] = '\0';
399   Enginename[0] = '\0';
400   Realenginename[0] = '\0';
401 
402   kpse_set_program_name(av[0], NULL);
403   strcpy(Programname, kpse_invocation_short_name);
404   if ((tmp = strrchr(Programname, '.'))) {
405     if (strcasecmp (tmp, ".exe") == 0)
406        *tmp = '\0';
407   }
408 
409   tmp = getenv("TEMP");
410   if(!tmp) tmp = getenv("TMP");
411   if(!tmp) tmp = getenv("TMPDIR");
412   if(!tmp) {
413     fprintf(stderr, "Please define TEMP | TMP | TMPDIR.\n");
414     return (100);
415   }
416 
417   tmp = xstrdup(tmp);
418   for(p = tmp; *p; p++) {
419     if(*p == '\\')
420       *p = '/';
421     else if (IS_KANJI(p))
422       p++;
423   }
424 
425   i = strlen(tmp);
426   if(tmp[i-1] == '/') tmp[i-1] = '\0';
427 
428   for(i = 1; i < ac; i++) {
429     if(strlen(av[i]) > BLEN-1) {
430       fprintf(stderr, "\nToo long a string.\n");
431       return 100;
432     }
433     /* --cnffile FILE */
434 
435     if(!strncmp(av[i],"--cn", 4) || !strncmp(av[i], "-cn", 3)) {
436       i++;
437       if(i >= ac) {
438         fprintf(stderr, "Invalid argument.\n");
439         exit (100);
440       }
441       strcpy(cnffile, av[i]);
442       continue;
443     }
444     /* --engine  TEXENGINE */
445 
446     else if(!strncmp(av[i],"--eng", 5) || !strncmp(av[i], "-eng", 4)) {
447       i++;
448       if(i >= ac) {
449         fprintf(stderr, "Invalid argument.\n");
450         exit (100);
451       }
452       strcpy(Enginename, av[i]);
453       continue;
454     }
455     /* --fmtdir  DIRCTORY */
456 
457     else if(!strncmp(av[i],"--fm", 4) || !strncmp(av[i], "-fm", 3)) {
458       i++;
459       if(i >= ac) {
460         fprintf(stderr, "Invalid argument.\n");
461         exit (100);
462       }
463       strcpy(Destdir, av[i]);
464       UserDestdir = 1;
465       continue;
466     }
467     /* --all */
468 
469     else if(!strncmp(av[i],"--a", 3) || !strncmp(av[i], "-a", 2)) {
470       flag = 1;
471       continue;
472     }
473     /* --missing */
474 
475     else if(!strncmp(av[i],"--m", 3) || !strncmp(av[i], "-m", 2)) {
476       flag = 2;
477       continue;
478     }
479     /* --refresh */
480 
481     else if(!strncmp(av[i],"--r", 3) || !strncmp(av[i], "-r", 2)) {
482       flag = 6;
483       continue;
484     }
485     /* --byfmt FORMATNAME */
486 
487     else if(!strncmp(av[i],"--byf", 5) || !strncmp(av[i], "-byf", 4)) {
488       i++;
489       if(i >= ac) {
490         fprintf(stderr, "Invalid argument.\n");
491         exit (100);
492       }
493       flag = 3;
494       strcpy(fmtname, av[i]);
495       continue;
496     }
497     /* --byhyphen HYPHENFILE */
498 
499     else if(!strncmp(av[i],"--byh", 5) || !strncmp(av[i], "-byh", 4)) {
500       i++;
501       if(i >= ac) {
502         fprintf(stderr, "Invalid argument.\n");
503         exit (100);
504       }
505       flag = 4;
506       strcpy(hyphenfile, av[i]);
507       for(p=hyphenfile; *p; p++) {
508 	if(*p == '\\')
509 	  *p = '/';
510         else if (IS_KANJI(p))
511           p++;
512       }
513       p = strrchr(hyphenfile, '/');
514       if(p) {
515 	p++;
516 	strcpy(hyphenfile, p);
517       }
518       continue;
519     }
520     /* --byengine ENGINENAME */
521 
522     else if(!strncmp(av[i],"--bye", 5) || !strncmp(av[i], "-bye", 4)) {
523       i++;
524       if(i >= ac) {
525         fprintf(stderr, "Invalid argument.\n");
526         exit (100);
527       }
528       flag = 7;
529       strcpy(byenginename, av[i]);
530       continue;
531     }
532     /* --showhyphen FORMATNAME */
533 
534     else if(!strncmp(av[i],"--s", 3) || !strncmp(av[i], "-s", 2)) {
535       i++;
536       if(i >= ac) {
537         fprintf(stderr, "Invalid argument.\n");
538         exit (100);
539       }
540       flag = 5;
541       strcpy(fmtname, av[i]);
542       continue;
543     }
544     /* --version */
545 
546     else if(!strncmp(av[i],"--v", 3) || !strncmp(av[i], "-v", 2)) {
547       revision();
548       return 0;
549     }
550     /* --help */
551 
552     else if(!strncmp(av[i],"--h", 3) || !strncmp(av[i], "-h", 2)) {
553       usage();
554       return 0;
555     }
556     /* --enablefmt FORMATNAME */
557 
558     else if(!strncmp(av[i],"--ena", 5) || !strncmp(av[i], "-ena", 4)) {
559       i++;
560       if(i >= ac) {
561         fprintf(stderr, "Invalid argument.\n");
562         exit (100);
563       }
564       fprintf(stderr, "`--enablefmt FORMATNAME' is not implemented.\n");
565       continue;
566     }
567     /* --disablefmt FORMATNAME */
568 
569     else if(!strncmp(av[i],"--di", 4) || !strncmp(av[i], "-di", 3)) {
570       i++;
571       if(i >= ac) {
572         fprintf(stderr, "Invalid argument.\n");
573         exit (100);
574       }
575       fprintf(stderr, "`--disablefmt FORMATNAME' is not implemented.\n");
576       continue;
577     }
578     /* --listcfg */
579 
580     else if(!strncmp(av[i],"--l", 3) || !strncmp(av[i], "-l", 2)) {
581       fprintf(stderr, "`--listcfg' is not implemented.\n");
582       continue;
583     }
584     /* --catcfg */
585 
586     else if(!strncmp(av[i],"--ca", 4) || !strncmp(av[i], "-ca", 3)) {
587       fprintf(stderr, "`--catcfg' is not implemented.\n");
588       continue;
589     }
590     /* --edit */
591 
592     else if(!strncmp(av[i],"--ed", 4) || !strncmp(av[i], "-ed", 3)) {
593       fprintf(stderr, "`--edit' is not implemented.\n");
594       continue;
595     }
596     /* --test */
597 
598     else if(!strncmp(av[i],"--t", 3) || !strncmp(av[i], "-t", 2)) {
599       fprintf(stderr, "`--test' is not implemented.\n");
600       continue;
601     }
602     /* --dolinks */
603 
604     else if(!strncmp(av[i],"--do", 4) || !strncmp(av[i], "-do", 3)) {
605       fprintf(stderr, "`--dolinks' is not implemented.\n");
606       continue;
607     }
608     /* --force */
609 
610     else if(!strncmp(av[i],"--fo", 4) || !strncmp(av[i], "-fo", 3)) {
611       fprintf(stderr, "`--force' is not implemented.\n");
612       continue;
613     }
614     /* --no-engine-subdir */
615 
616     else if(!strncmp(av[i],"--no-en", 7) || !strncmp(av[i], "-no-en", 6)) {
617       fprintf(stderr, "`--no-engine-subdir' is not implemented.\n");
618       continue;
619     }
620     /* --no-error-if-no-format */
621 
622     else if(!strncmp(av[i],"--no-er", 7) || !strncmp(av[i], "-no-er", 6)) {
623       continue;
624     }
625     /* --quiet */
626 
627     else if(!strncmp(av[i],"--q", 3) || !strncmp(av[i], "-q", 2)) {
628       QQQ = 1;
629       continue;
630     }
631     else {
632       fprintf(stderr, "%s: Invalid argument.\n\n", av[0]);
633       usage();
634       return 100;
635     }
636   }
637 
638   if(flag == 0) {
639     usage();
640     return 100;
641   }
642 
643 
644   if(!cnffile[0]) strcpy(cnffile, DEFAULTCNF);
645   cnfname = kpse_find_file(cnffile, kpse_web2c_format, 0);
646   if(!cnfname) {
647     fprintf(stderr, "Failed to find cnffile %s.\n", cnffile);
648     exit (100);
649   }
650 
651   in = fopen(cnfname, "r");
652   free(cnfname);
653   if(!in) {
654     fprintf(stderr, "Failed to open %s.\n", cnffile);
655     exit (100);
656   }
657 
658   for(i=0; i < MAXFMT; i++) {
659     K[i].format = (char *)malloc(BLEN);
660     K[i].engine = (char *)malloc(BLEN);
661     K[i].hyphen = (char *)malloc(BLEN);
662     K[i].args = (char *)malloc(BLEN);
663     Exefile[i] = (char *)malloc(BLEN);
664   }
665 
666   i = 0;
667   while(fgets(Buff, BLEN, in)) {
668     if(Buff[0] == '#' ||
669        Buff[0] == '\n' ||
670        Buff[0] == 0x25)
671       continue;
672     p = strtok(Buff, " \t");
673     if(p)
674       strcpy(K[i].format, p);
675     else
676       K[i].format[0] = '\0';
677     p = strtok(NULL, " \t");
678     if(p)
679       strcpy(K[i].engine, p);
680     else
681       K[i].engine[0] = '\0';
682     p = strtok(NULL, " \t");
683     if(p)
684       strcpy(K[i].hyphen, p);
685     else
686       K[i].hyphen[0] = '\0';
687     p = strtok(NULL, "\n");
688     if(p) {
689       while(*p == ' ' || *p == '\t')
690         p++;
691       j = strlen(p);
692       if(*(p+j-1) == '\n')
693         *(p+j-1) = '\0';
694       strcpy(K[i].args, p);
695     }
696     else
697       K[i].args[0] = '\0';
698 
699     if(!K[i].format[0] ||
700        !K[i].engine[0] ||
701        !K[i].hyphen[0] ||
702        !K[i].args) {
703       fprintf(stderr, "Invalid line in %s.\n", cnffile);
704       freeK();
705       return (100);
706     }
707     i++;
708     if(i > MAXFMT) {
709       fprintf(stderr, "Too many lines in %s.\n", cnffile);
710       freeK();
711       return (100);
712     }
713   }
714 
715   Fmtnum = i;
716   fclose(in);
717 
718   j = 0;
719   if(flag == 5) {
720     for(i = 0; i < Fmtnum; i++) {
721       if(!strcasecmp(K[i].format, fmtname)) {
722         show_hyphen(K[i].format, K[i].hyphen);
723         j++;
724       }
725     }
726     if(j == 0)
727       fprintf(stderr, "argument of --showhyphen must be a format name.\n");
728     freeK();
729     return 1;
730   }
731 
732   if(strcasecmp(Programname, "fmtutil-sys") == 0) {
733     char *px = kpse_var_value("TEXMFSYSVAR");
734     if(px) {
735       xputenv("TEXMFVAR", px);
736     }
737   }
738 
739   if(UserDestdir == 0) {
740     p = kpse_var_value("TEXMFVAR");
741     if(!p)
742       p = kpse_var_value("TEXMFMAIN");
743     if(!p) {
744       fprintf(stderr, "TEXMFMAIN not defined.\n");
745       freeK();
746       return 100;
747     }
748     strcpy(Destdir, p);
749     free(p);
750     for(p = Destdir; *p ; p++) {
751       if(*p == '\\')
752         *p = '/';
753       else if (IS_KANJI(p))
754         p++;
755     }
756 
757     i = strlen(Destdir);
758     while (Destdir[i-1] == '/')
759       i--;
760     Destdir[i] = '\0';
761     strcat(Destdir, "/web2c");
762   }
763 
764   if(!is_dir(Destdir)) {
765     if(make_dir_p(Destdir)) {
766       fprintf(stderr, "Failed to make a format under %s.\n", Destdir);
767       return (-100);
768     }
769   }
770 
771   strcat(Destdir, "/");
772   p = _getcwd(Currdir, BLEN);
773   if(p) {
774     for(p = Currdir; *p ; p++) {
775       if(*p == '\\')
776         *p = '/';
777       else if (IS_KANJI(p))
778         p++;
779     }
780     i = strlen(Currdir);
781     if(Currdir[i-1] == '/') Currdir[i-1] = '\0';
782     strcpy(kpsedot, "KPSE_DOT=.;");
783     strcat(kpsedot, Currdir);
784     _putenv(kpsedot);
785   }
786 
787   cdrive = _getdrive();
788   if(tmp[1] == ':') {
789     tdrive = tolower(*tmp) -'a' + 1;
790     _chdrive(tdrive);
791   }
792   _chdir(tmp);
793 
794   j = 0;
795 
796   if(flag == 4) {
797     char *p, *q;
798     int  cont;
799     for(i = 0; i < Fmtnum; i++) {
800       p = K[i].hyphen;
801       cont = 1;
802       while(cont) {
803 	for(q = p; *q && *q != ','; q++)
804 	  ;
805 	if(*q == '\0') cont = 0;
806 	*q = '\0';
807 	q++;
808 	if(!strcasecmp(p, hyphenfile)) {
809 	  do_initex(K[i].format, K[i].engine, K[i].args);
810 	  j++;
811 	  cont = 0;
812 	}
813 	p = q;
814       }
815     }
816     if(j == 0)
817       fprintf(stderr, "hyphen pattern %s not written in %s.\n",hyphenfile,cnffile);
818   }
819 
820   else if(flag == 7) {
821     if(strcasecmp(byenginename, "metafont") == 0)
822       strcpy(byenginename, "mf-nowin");
823     if(strcasecmp(byenginename, "metapost") == 0)
824       strcpy(byenginename, "mpost");
825     for(i = 0; i < Fmtnum; i++) {
826       if(!strcasecmp(K[i].engine, byenginename)) {
827         do_initex(K[i].format, K[i].engine, K[i].args);
828         j++;
829       }
830     }
831     if(j == 0) {
832       fprintf(stderr, "engine name %s not written in %s.\n", byenginename, cnffile);
833     }
834   }
835 
836   else if(flag == 3) {
837     for(i = 0; i < Fmtnum; i++) {
838       if(Enginename[0]) {
839 	if(!strcasecmp(Enginename, "metafont"))
840 	  strcpy(Realenginename, "mf-nowin");
841 	else if(!strcasecmp(Enginename, "metapost"))
842 	  strcpy(Realenginename, "mpost");
843 	else
844 	  strcpy(Realenginename, Enginename);
845         if(!strcasecmp(K[i].format, fmtname) &&
846            !strcasecmp(K[i].engine, Realenginename)) {
847           do_initex(K[i].format, K[i].engine, K[i].args);
848           j++;
849         }
850       }
851       else {
852         if(!strcasecmp(K[i].format, fmtname)) {
853           do_initex(K[i].format, K[i].engine, K[i].args);
854           j++;
855         }
856       }
857     }
858     if(j == 0) {
859       if(Enginename[0])
860         fprintf(stderr, "format name %s with engine %s not written in %s.\n",
861                fmtname, Realenginename, cnffile);
862       else
863         fprintf(stderr, "format name %s not written in %s.\n", fmtname, cnffile);
864     }
865   }
866 
867   else if((flag == 2) || (flag == 6)) {
868     for(i = 0; i < Fmtnum; i++) {
869       strcpy(Buff, Destdir);
870 
871       strcpy(enginesubdir, K[i].engine);
872       if(!strcasecmp(enginesubdir, "mf-nowin"))
873         strcpy(enginesubdir, "metafont");
874       if(!strcasecmp(enginesubdir, "mf"))
875         strcpy(enginesubdir, "metafont");
876       if(!strcasecmp(enginesubdir, "mpost"))
877         strcpy(enginesubdir, "metapost");
878       if(strcasecmp(enginesubdir, "nts"))
879         strcat(Buff, enginesubdir);
880       strcat(Buff, "/");
881 
882       strcat(Buff, K[i].format);
883       if(!strcasecmp(K[i].engine, "nts"))
884         strcat(Buff, ".nfmt");
885       else if(!strcasecmp(K[i].engine, "mf"))
886         strcat(Buff, ".base");
887       else if(!strcasecmp(K[i].engine, "mf-nowin"))
888         strcat(Buff, ".base");
889       else if(!strcasecmp(K[i].engine, "mpost"))
890         strcat(Buff, ".mem");
891       else if(!strcasecmp(K[i].engine, "pmpost"))
892         strcat(Buff, ".mem");
893       else if(!strcasecmp(K[i].engine, "upmpost"))
894         strcat(Buff, ".mem");
895       else
896         strcat(Buff, ".fmt");
897       if(flag == 2) {
898 	if(_access(Buff, 0) != 0)
899 	  do_initex(K[i].format, K[i].engine, K[i].args);
900 	else if(QQQ == 0)
901 	  fprintf(stderr, "%s exists.\n", Buff);
902       } else if(flag == 6) {
903 	if(_access(Buff, 0) == 0)
904 	  do_initex(K[i].format, K[i].engine, K[i].args);
905 	else if(QQQ == 0)
906 	  fprintf(stderr, "%s does not exist.\n", Buff);
907       }
908     }
909   }
910 
911   else if(flag == 1)
912     do_all();
913 
914   _chdrive(cdrive);
915   _chdir(Currdir);
916 
917 /*
918 Check executable files. (ignore "Batch" or "Script" files (case 'x'))
919 */
920   if(Exenum && QQQ == 0) {
921     fprintf(stderr, "\n\nNow I check executable files...\n");
922     fprintf(stderr, "If some executable files do not exist, you must make them\n");
923     fprintf(stderr, "by hard link (Windows NT/2000/XP/Vista/7),"
924                     " symbolic link (Vista/7)\n"
925                     "or copying (Windows 95/98/Me).\n\n");
926 
927     for(i = 0; i < Exenum; i++) {
928       if(testexe(Exefile[i], ".exe"))
929         sprintf(Buff, "OK. %s.exe exists.", Exefile[i]);
930       else if(testexe(Exefile[i], ".bat"))
931         sprintf(Buff, "OK. %s.bat exists.", Exefile[i]);
932       else if(testexe(Exefile[i], ".sh"))
933         sprintf(Buff, "OK. %s.sh exists.", Exefile[i]);
934       else
935         sprintf(Buff, "I cannot find %s.", Exefile[i]);
936       j = strlen(Buff);
937 
938       if((i+1) % 2) {
939         for(k = j; k < 36; k++)
940           Buff[k] = ' ';
941         Buff[k] = '\0';
942         fprintf(stderr, "%s", Buff);
943       }
944       else {
945         fprintf(stderr, "%s", Buff);
946         fprintf(stderr, "\n");
947       }
948     }
949     fprintf(stderr, "\n");
950   }
951 
952   freeK();
953   if(Errorcnt && QQQ == 0) {
954     fprintf(stderr, "\n\nI could not create %d of format (base/mem) file(s).\n",
955             Errorcnt);
956     fprintf(stderr, "For details, see log file(s) in the (fmt/base/mem) dir(s).\n");
957   }
958   return Errorcnt != 0;
959 }
960