OSDN Git Service

version 2.3.0-final.
[putex/putex.git] / src / texsourc / yandytex.c
1 /*\r
2    Copyright 1992 Karl Berry\r
3    Copyright 2007 TeX Users Group\r
4    Copyright 2014 Clerk Ma\r
5 \r
6    This program is free software; you can redistribute it and/or modify\r
7    it under the terms of the GNU General Public License as published by\r
8    the Free Software Foundation; either version 2 of the License, or\r
9    (at your option) any later version.\r
10 \r
11    This program is distributed in the hope that it will be useful, but\r
12    WITHOUT ANY WARRANTY; without even the implied warranty of\r
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
14    General Public License for more details.\r
15 \r
16    You should have received a copy of the GNU General Public License\r
17    along with this program; if not, write to the Free Software\r
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
19    02110-1301 USA.\r
20 */\r
21 \r
22 #define EXTERN\r
23 \r
24 #include "yandytex.h"\r
25 \r
26 #define dump_ext_length 4\r
27 #define edit_value      tex_edit_value\r
28 \r
29 extern char * replacement[];\r
30 int    gargc;\r
31 char **gargv;\r
32 \r
33 int jump_used = 0;\r
34 \r
35 jmp_buf jumpbuffer;\r
36 \r
37 int main (int ac, char *av[])\r
38 {\r
39   int flag = 0, ret = 0;\r
40 \r
41   gargc = ac;\r
42   gargv = av;\r
43 \r
44   if (main_init(gargc, gargv))\r
45     return -1;\r
46 \r
47   TEX_format_default = " plain.fmt";\r
48   format_default_length = strlen(TEX_format_default + 1);\r
49 \r
50   jump_used = 0;\r
51 \r
52   ret = setjmp(jumpbuffer);\r
53 \r
54   if (ret == 0)\r
55   {\r
56     flag = main_program();\r
57 \r
58     if (trace_flag)\r
59       printf("EXITING at %s: flag = %d, ret = %d, jump_used = %d\n", "main", flag, ret, jump_used);\r
60   }\r
61   else\r
62   {\r
63     if (trace_flag)\r
64       printf("EXITING at %s: flag = %d, ret = %d, jump_used =  %d\n", "jump_out", flag, ret, jump_used);\r
65   }\r
66 \r
67   if (endit(flag) != 0)\r
68     flag = 1; /* do final clean up in local.c */\r
69 \r
70   if (flag == 0)\r
71     return 0;\r
72   else\r
73     exit (flag);\r
74 }\r
75 \r
76 /* texk/web2c/lib/texmfmp.c */\r
77 void t_open_in (void)\r
78 {\r
79   int i;\r
80 \r
81   buffer[first] = 0;\r
82 \r
83   if (gargc > optind && optind > 0)\r
84   {\r
85     for (i = optind; i < gargc; i++)\r
86     {\r
87       if (allow_quoted_names && strchr(gargv[i], ' ') != NULL)\r
88       {\r
89         (void) strcat ((char *) &buffer[first], "\"");\r
90         (void) strcat ((char *) &buffer[first], gargv[i]);\r
91         (void) strcat ((char *) &buffer[first], "\"");\r
92       }\r
93       else\r
94         (void) strcat ((char *) &buffer[first], gargv[i]);\r
95 \r
96       (void) strcat ((char *) &buffer[first], " ");\r
97     }\r
98     \r
99     gargc = 0;\r
100   }\r
101 \r
102   /* Find the end of the buffer.  */\r
103   for (last = first; buffer[last]; ++last)\r
104     do_nothing();\r
105 \r
106   for (--last; last >= first && ISBLANK(buffer[last]) && buffer[last] != '\r'; --last)\r
107     do_nothing();\r
108 \r
109   last++;\r
110 \r
111   if (non_ascii)\r
112   {\r
113     for (i = first; i < last; i++)\r
114       buffer[i] = xord[buffer[i]];\r
115   }\r
116 }\r
117 \r
118 static void catch_interrupt (int err)\r
119 {\r
120   (void) err;\r
121   (void) signal(SIGINT, SIG_IGN);\r
122 \r
123   if (interrupt++ >= 3)\r
124     exit(1);\r
125 \r
126   (void) signal(SIGINT, catch_interrupt);\r
127 }\r
128 \r
129 void fix_date_and_time (void)\r
130 {\r
131   time_t clock;\r
132   struct tm *tmptr;\r
133 \r
134   (void) time(&clock);\r
135 \r
136   if (trace_flag)\r
137     printf("The time is %lld\n", (long long)clock);\r
138 \r
139   if (clock < 0)\r
140     puts("Time not available!");\r
141 \r
142   tmptr = localtime (&clock);\r
143 \r
144   if (tmptr == NULL)\r
145   {\r
146     printf("Cannot convert time (%0lld)!\n", (long long)clock);\r
147     year     = 2038;\r
148     month    = 1;\r
149     day      = 18;\r
150     tex_time = 22 * 60 + 14;\r
151   }\r
152   else\r
153   {\r
154     tex_time = tmptr->tm_hour * 60 + tmptr->tm_min;\r
155     day      = tmptr->tm_mday;\r
156     month    = tmptr->tm_mon + 1;\r
157     year     = tmptr->tm_year + 1900;\r
158 \r
159     if (trace_flag)\r
160       printf("%d-%d-%d %d:%d\n",\r
161         tmptr->tm_year + 1900,\r
162         tmptr->tm_mon + 1,\r
163         tmptr->tm_mday,\r
164         tmptr->tm_hour,\r
165         tmptr->tm_min);\r
166   }\r
167 \r
168   {\r
169 #ifdef _WIN32\r
170     if (signal(SIGINT, catch_interrupt) == SIG_ERR)\r
171     {\r
172       puts(" CTRL-C handler not installed");\r
173       uexit(EXIT_FAILURE);\r
174     }\r
175 #else\r
176     void (*old_handler)();\r
177 \r
178     old_handler = signal(SIGINT, catch_interrupt);\r
179 \r
180     if (old_handler != SIG_DFL)\r
181       (void) signal(SIGINT, old_handler);\r
182 #endif\r
183   }\r
184 }\r
185 \r
186 /* I/O for TeX and Metafont. */\r
187 void complain_line (FILE * output)\r
188 {\r
189   show_line("\n", 0);\r
190 \r
191 #ifdef ALLOCATEBUFFER\r
192   sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", current_buf_size);\r
193 #else\r
194   sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", buf_size);\r
195 #endif\r
196 \r
197   fputs(log_line, output);\r
198   puts("  (File may have a line termination problem.)");\r
199 }\r
200 \r
201 void show_bad_line (FILE * output, int first, int last)\r
202 {\r
203   int i, c, d, ch;\r
204   char *s = log_line;\r
205 \r
206   for (i = first; i <= last; i++)\r
207   {\r
208     ch = buffer[i];\r
209 \r
210     if (show_in_hex && (ch > 127))\r
211     {\r
212       c = ch >> 4;\r
213       d = ch & 15;\r
214 \r
215       if (c > 9)\r
216         c = c + 'a' - 10;\r
217       else\r
218         c = c + '0';\r
219 \r
220       if (d > 9)\r
221         d = d + 'a' - 10;\r
222       else\r
223         d = d + '0';\r
224 \r
225       *s++ = '^';\r
226       *s++ = '^';\r
227 \r
228       *s++ = (char) c;\r
229       *s++ = (char) d;\r
230     }\r
231     else if (ch < 32)\r
232     {\r
233       *s++ = '^';\r
234       *s++ = '^';\r
235       *s++ = (char) (ch + 64);\r
236     }\r
237     else if (ch == 127)\r
238     {\r
239       *s++ = '^';\r
240       *s++ = '^';\r
241       *s++ = (char) (ch - 64);\r
242     }\r
243     else\r
244     {\r
245       *s++ = (char) ch;\r
246     }\r
247   }\r
248 \r
249   *s++ = ' ';\r
250   *s++ = '\0';\r
251 \r
252   fputs(log_line, output);   // log_file\r
253 }\r
254 \r
255 boolean input_line_finish (void)\r
256 {\r
257   int i = '\0';\r
258   int ch, flag;\r
259 \r
260   buffer[last] = ' ';\r
261 \r
262   if (last >= max_buf_stack)\r
263     max_buf_stack = last;\r
264 \r
265   while (last > first)\r
266   {\r
267     i = buffer[last - 1];\r
268 \r
269     if (i == ' ' || i == '\t')\r
270       --last;\r
271     else\r
272       break;\r
273   }\r
274 \r
275   if (restrict_to_ascii)\r
276   {\r
277     flag = 0;\r
278 \r
279     for (i = first; i <= last; i++)\r
280     {\r
281       ch = buffer[i];\r
282 \r
283       if (ch > 126 ||  (ch < ' ' && ch != '\t' && ch != '\f' && ch != '\r' && ch != '\n'))\r
284       {\r
285         sprintf(log_line, "\n! non ASCII char (%d) in line: ", ch);\r
286         show_line(log_line, 1);\r
287 \r
288         if (log_opened)\r
289           fprintf(log_file, "\n! non ASCII char (%d) in line: ", ch);\r
290 \r
291         flag = 1;\r
292         break;\r
293       }\r
294     }\r
295 \r
296     if (flag)\r
297     {\r
298       show_bad_line(errout, first, last);\r
299 \r
300       if (log_opened)\r
301         show_bad_line(log_file, first, last);\r
302     }\r
303   }\r
304 \r
305   if (non_ascii)\r
306   {\r
307     for (i = first; i <= last; i++)\r
308       buffer[i] = xord[buffer[i]];\r
309   }\r
310 \r
311   return true;\r
312 }\r
313 /* sec 0031 */\r
314 boolean input_line (FILE * f)\r
315 {\r
316   char * u;        /* 1994/July/3 for key_replace */\r
317   int i = '\0';\r
318 \r
319   last = first;\r
320 /*  following is new version with tab expansion and key replacement */\r
321 /*  may want to expand out separately for speed 1994/July/3 */\r
322 /*  different versions depending on return_flag / tabexpand / key_replace */\r
323 /*  while (last < buf_size && (i = getc (f)) != EOF)  */\r
324 #ifdef ALLOCATEBUFFER\r
325   for ( ; ; ) \r
326 #else\r
327   while (last < buf_size) \r
328 #endif\r
329   {\r
330     i = getc(f);\r
331 \r
332     if (i < ' ')\r
333     {\r
334       if (i == EOF || i == '\n' || (i == '\r' && return_flag))\r
335         break;\r
336       else if (i == '\t' && tab_step != 0)\r
337       {\r
338         buffer[last++] = (ASCII_code) ' ';\r
339 \r
340 #ifdef ALLOCATEBUFFER\r
341         if (last >= current_buf_size)\r
342         {\r
343           buffer = realloc_buffer(increment_buf_size);  \r
344 \r
345           if (last >= current_buf_size)\r
346             break;\r
347         }\r
348 #endif\r
349 \r
350 #ifdef ALLOCATEBUFFER\r
351         while ((last - first) % tab_step != 0) \r
352 #else\r
353         while (last < buf_size && (last - first) % tab_step != 0)\r
354 #endif\r
355         {\r
356 \r
357           buffer[last++] = (ASCII_code) ' ';\r
358 \r
359 #ifdef ALLOCATEBUFFER\r
360           if (last >= current_buf_size)\r
361           {\r
362             buffer = realloc_buffer(increment_buf_size);\r
363 \r
364             if (last >= current_buf_size)\r
365               break;\r
366           }\r
367 #endif\r
368         }\r
369 \r
370         continue;\r
371       }\r
372     }\r
373 \r
374     if (key_replace && (u = replacement[i]) != NULL)\r
375     {\r
376 #ifdef ALLOCATEBUFFER\r
377       while (*u != '\0') \r
378 #else\r
379       while (last < buf_size && *u != '\0')  \r
380 #endif\r
381       {\r
382         buffer[last++] = (ASCII_code) *u++;\r
383 \r
384 #ifdef ALLOCATEBUFFER\r
385         if (last >= current_buf_size)\r
386         {\r
387           buffer = realloc_buffer(increment_buf_size);\r
388 \r
389           if (last >= current_buf_size)\r
390             break;\r
391         }\r
392 #endif\r
393       }\r
394     }\r
395     else       /* normal case */\r
396     {\r
397       buffer[last++] = (ASCII_code) i;\r
398 \r
399 #ifdef ALLOCATEBUFFER\r
400       if (last >= current_buf_size)\r
401       {\r
402         buffer = realloc_buffer(increment_buf_size);\r
403 \r
404         if (last >= current_buf_size)\r
405           break;\r
406       }\r
407 #endif\r
408     }\r
409   }\r
410 \r
411   if (return_flag)  /* let return terminate line as well as newline */\r
412   {\r
413     if (i == '\r')  /* see whether return followed by newline */\r
414     {\r
415       i = getc(f);  /* in which case throw away the newline */\r
416 \r
417       if (i != '\n')\r
418       {\r
419         ungetc(i, f);\r
420         i = '\r';\r
421       }\r
422 /*      else  buffer[last-1] = (ASCII_code) i; */\r
423     }\r
424   }\r
425 \r
426   //  Turn Ctrl-Z at end of file into newline 2000 June 22\r
427   if (i == EOF && trimeof && buffer[last - 1] == 26)\r
428   {\r
429     last--;\r
430   }\r
431 \r
432   if (i == EOF && last == first)\r
433     return false;\r
434 \r
435 /*  Didn't get the whole line because buffer was too small?  */\r
436 /*  This shouldn't happen anymore 99/Jan/23 */\r
437   if (i != EOF && i != '\n' && i != '\r')\r
438   {\r
439     complain_line(errout);\r
440 \r
441     if (log_opened)\r
442       complain_line(log_file);\r
443 \r
444     /* This may no longer be needed ... now that we grow it */\r
445     if (truncate_long_lines)\r
446     {\r
447       while (i != EOF && i != '\n' && i != '\r')\r
448       {\r
449         i = getc (f);     // discard rest of line\r
450       }\r
451 \r
452       last--;       /* just in case */\r
453     }\r
454     else\r
455       uexit(EXIT_FAILURE);      /* line too long */\r
456   }\r
457 \r
458   return input_line_finish();\r
459 }\r
460 \r
461 static char * edit_value = "c:\\yandy\\WinEdt\\WinEdt.exe [Open('%s');SelLine(%d,7)]";\r
462 \r
463 #ifdef WIN32\r
464 static inline int Isspace (char c)\r
465 {\r
466   return (c == ' ' || c == '\t');\r
467 }\r
468 #endif\r
469 \r
470 void call_edit (ASCII_code * filename, pool_pointer fnstart, integer fnlength, integer linenumber)\r
471 {\r
472   char *temp, *command, *fullcmd;\r
473   char c;\r
474   int sdone, ddone, i;\r
475 \r
476 #ifdef WIN32\r
477   char *fp, *ffp, *env, editorname[256], buffer[256];\r
478   int cnt = 0;\r
479   int dontchange = 0;\r
480 #endif\r
481 \r
482   sdone = ddone = 0;\r
483   filename += fnstart;\r
484 \r
485   /* Close any open input files, since we're going to kill the job. */\r
486   for (i = 1; i <= in_open; i++)\r
487 #ifdef XeTeX\r
488     xfclose(input_file[i]->f, "inputfile");\r
489 #else\r
490     xfclose(input_file[i], "inputfile");\r
491 #endif\r
492 \r
493   /* Replace the default with the value of the appropriate environment\r
494      variable or config file value, if it's set.  */\r
495   temp = kpse_var_value("TEXEDIT");\r
496 \r
497   if (temp != NULL)\r
498     edit_value = temp;\r
499 \r
500   /* Construct the command string.  The `11' is the maximum length an\r
501      integer might be.  */\r
502   command = (char *) xmalloc (strlen (edit_value) + fnlength + 11);\r
503 \r
504   /* So we can construct it as we go.  */\r
505   temp = command;\r
506 \r
507 #ifdef WIN32\r
508   fp = editorname;\r
509   if ((isalpha(*edit_value) && *(edit_value + 1) == ':'\r
510         && IS_DIR_SEP (*(edit_value + 2)))\r
511       || (*edit_value == '"' && isalpha(*(edit_value + 1))\r
512         && *(edit_value + 2) == ':'\r
513         && IS_DIR_SEP (*(edit_value + 3)))\r
514      )\r
515     dontchange = 1;\r
516 #endif\r
517 \r
518   while ((c = *edit_value++) != 0)\r
519   {\r
520     if (c == '%')\r
521     {\r
522       switch (c = *edit_value++)\r
523       {\r
524         case 'd':\r
525           if (ddone)\r
526             FATAL ("call_edit: `%%d' appears twice in editor command");\r
527           sprintf (temp, "%ld", (long int)linenumber);\r
528           while (*temp != '\0')\r
529             temp++;\r
530           ddone = 1;\r
531           break;\r
532         \r
533         case 's':\r
534           if (sdone)\r
535             FATAL ("call_edit: `%%s' appears twice in editor command");\r
536           for (i = 0; i < fnlength; i++)\r
537             *temp++ = xchr[(filename[i])];\r
538           sdone = 1;\r
539           break;\r
540         \r
541         case '\0':\r
542           *temp++ = '%';\r
543           /* Back up to the null to force termination.  */\r
544           edit_value--;\r
545           break;\r
546         \r
547         default:\r
548           *temp++ = '%';\r
549           *temp++ = c;\r
550           break;\r
551       }\r
552     }\r
553     else\r
554     {\r
555 #ifdef WIN32\r
556       if (dontchange)\r
557         *temp++ = c;\r
558       else \r
559       { \r
560         if(Isspace(c) && cnt == 0)\r
561         {\r
562           cnt++;\r
563           temp = command;\r
564           *temp++ = c;\r
565           *fp = '\0';\r
566         }\r
567         else if(!Isspace(c) && cnt == 0)\r
568         {\r
569           *fp++ = c;\r
570         }\r
571         else\r
572         {\r
573           *temp++ = c;\r
574         }\r
575       }\r
576 #else\r
577       *temp++ = c;\r
578 #endif\r
579     }\r
580   }\r
581 \r
582   *temp = 0;\r
583 \r
584 #ifdef WIN32\r
585   if (dontchange == 0) {\r
586     if(editorname[0] == '.' ||\r
587        editorname[0] == '/' ||\r
588        editorname[0] == '\\') {\r
589       fprintf(stderr, "%s is not allowed to execute.\n", editorname);\r
590       uexit(1);\r
591     }\r
592     env = (char *)getenv("PATH");\r
593     if(SearchPath(env, editorname, ".exe", 256, buffer, &ffp)==0) {\r
594       if(SearchPath(env, editorname, ".bat", 256, buffer, &ffp)==0) {\r
595         fprintf(stderr, "I cannot find %s in the PATH.\n", editorname);\r
596         uexit(1);\r
597       }\r
598     }\r
599     fullcmd = (char *)xmalloc(strlen(buffer)+strlen(command)+5);\r
600     strcpy(fullcmd, "\"");\r
601     strcat(fullcmd, buffer);\r
602     strcat(fullcmd, "\"");\r
603     strcat(fullcmd, command);\r
604   } else\r
605 #endif\r
606   fullcmd = command;\r
607 \r
608   /* Execute the command.  */\r
609   if (system (fullcmd) != 0)\r
610     fprintf(stderr, "! Trouble executing `%s'.\n", command);\r
611 \r
612   /* Quit, since we found an error.  */\r
613   uexit(1);\r
614 }\r
615 \r
616 \r
617 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)\r
618    \r
619 #define SWAP(x, y) temp = (x); (x) = (y); (y) = temp;\r
620 \r
621 \r
622 /* Make the NITEMS items pointed at by P, each of size SIZE, be the\r
623    opposite-endianness of whatever they are now.  */\r
624 \r
625 static int swap_items (char *p, int nitems, int size)\r
626 {\r
627   char temp;\r
628 \r
629   /* Since `size' does not change, we can write a while loop for each\r
630      case, and avoid testing `size' for each time.  */\r
631   switch (size)\r
632   {\r
633     case 8:\r
634       while (nitems--)\r
635       {\r
636         SWAP (p[0], p[7]);\r
637         SWAP (p[1], p[6]);\r
638         SWAP (p[2], p[5]);\r
639         SWAP (p[3], p[4]);\r
640         p += size;\r
641       }\r
642       break;\r
643 \r
644     case 4:\r
645       while (nitems--)\r
646       {\r
647         SWAP (p[0], p[3]);\r
648         SWAP (p[1], p[2]);\r
649         p += size;\r
650       }\r
651       break;\r
652 \r
653     case 2:\r
654       while (nitems--)\r
655       {\r
656         SWAP (p[0], p[1]);\r
657         p += size;\r
658       }\r
659       break;\r
660 \r
661     case 1:\r
662     /* Nothing to do.  */\r
663       break;\r
664 \r
665     default:\r
666       show_line("\n", 0);\r
667       sprintf(log_line, "! I can't (un)dump a %d byte item.\n", size);\r
668       show_line(log_line, 1);\r
669       uexit(EXIT_FAILURE);\r
670   }\r
671   return 0;\r
672 }\r
673 #endif /* not WORDS_BIGENDIAN and not NO_FMTBASE_SWAP */\r
674 \r
675 #ifdef COMPACTFORMAT\r
676 int do_dump (char *p, int item_size, int nitems, gzFile out_file)\r
677 #else\r
678 int do_dump (char *p, int item_size, int nitems, FILE *out_file)\r
679 #endif\r
680 {\r
681 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)\r
682   swap_items (p, nitems, item_size);\r
683 #endif\r
684 \r
685 #ifdef COMPACTFORMAT\r
686   if (gzwrite(out_file, p, (item_size * nitems)) != (item_size * nitems))\r
687 #else\r
688   if ((int) fwrite(p, item_size, nitems, out_file) != nitems)\r
689 #endif\r
690   {\r
691     printf("\n! Could not write %d %d-byte item%s.\n",\r
692                nitems, item_size, (nitems > 1) ? "s" : "");\r
693     uexit(EXIT_FAILURE);\r
694   }\r
695 \r
696 /* Have to restore the old contents of memory, since some of it might get used again.  */\r
697 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)\r
698   swap_items (p, nitems, item_size);\r
699 #endif\r
700 \r
701   return 0;\r
702 }\r
703 \r
704 #ifdef COMPACTFORMAT\r
705 int do_undump (char *p, int item_size, int nitems, gzFile in_file)\r
706 #else\r
707 int do_undump (char *p, int item_size, int nitems, FILE *in_file)\r
708 #endif\r
709 {\r
710 #ifdef COMPACTFORMAT\r
711   if (gzread(in_file, (void *) p, (unsigned int) (item_size * nitems)) <= 0)\r
712 #else\r
713   if ((int) fread((void *) p, item_size, nitems, in_file) != nitems)\r
714 #endif\r
715   {\r
716     printf("\n! Could not read %d %d-byte item%s.\n",\r
717                nitems, item_size, (nitems > 1) ? "s" : "");\r
718     uexit(EXIT_FAILURE);\r
719   }\r
720 \r
721 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)\r
722   swap_items (p, nitems, item_size);\r
723 #endif\r
724 \r
725   return 0;\r
726 }