OSDN Git Service

makefile of clang.
[putex/putex.git] / src / texsourc / yandytex.c
1 /* Copyright 1992 Karl Berry
2    Copyright 2007 TeX Users Group
3    Copyright 2014 Clerk Ma
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301 USA.  */
19
20 #define EXTERN
21
22 #include "texd.h"
23
24 #define dump_ext_length     4
25 #define edit_value          tex_edit_value
26
27 extern char * replacement[];
28 int    gargc;   /* number of args - set to zero after initialization */
29 char **gargv;
30
31 int jump_used = 0;
32
33 jmp_buf jumpbuffer;
34
35 int main (int ac, char *av[])
36 {
37   int flag = 0, ret = 0;
38
39   gargc = ac;
40   gargv = av;
41
42   if (main_init(gargc, gargv))
43     return -1;
44
45   TEX_format_default = " plain.fmt";
46   format_default_length = strlen(TEX_format_default + 1);
47
48   jump_used = 0;
49
50   ret = setjmp(jumpbuffer);
51
52   if (ret == 0)
53   {
54     flag = main_program();
55
56     if (trace_flag)
57       printf("EXITING at %s: flag = %d, ret = %d, jump_used = %d\n", "main", flag, ret, jump_used);
58   }
59   else
60   {
61     if (trace_flag)
62       printf("EXITING at %s: flag = %d, ret = %d, jump_used =  %d\n", "jump_out", flag, ret, jump_used);
63   }
64
65   if (endit(flag) != 0)
66     flag = 1; /* do final clean up in local.c */
67
68   if (flag == 0)
69     return 0;
70   else
71     exit (flag);
72 }
73
74 /* texk/web2c/lib/texmfmp.c */
75 void t_open_in (void)
76 {
77   int i;
78
79   buffer[first] = 0;  /* In case there are no arguments.  */
80
81 #ifdef MSDOS
82   if (gargc > optind && optind > 0)
83   {
84     for (i = optind; i < gargc; i++)
85 #else
86   if (gargc > 1)
87   {
88     for (i = 1; i < gargc; i++)
89 #endif
90     {
91       if (allow_quoted_names && strchr(gargv[i], ' ') != NULL)
92       {
93         (void) strcat ((char *) &buffer[first], "\"");
94         (void) strcat ((char *) &buffer[first], gargv[i]);
95         (void) strcat ((char *) &buffer[first], "\"");
96       }
97       else
98         (void) strcat ((char *) &buffer[first], gargv[i]);
99
100       (void) strcat ((char *) &buffer[first], " ");
101     }
102     
103     gargc = 0;
104   }
105
106   /* Find the end of the buffer.  */
107   for (last = first; buffer[last]; ++last)
108     ;
109
110   for (--last; last >= first && ISBLANK (buffer[last]) && buffer[last] != '\r'; --last)
111     ;
112
113   last++;
114
115 /* One more time, this time converting to TeX's internal character
116    representation.  */ /* for command line input in this case */
117   if (non_ascii)
118   {
119     for (i = first; i < last; i++)
120       buffer[i] = xord[buffer[i]];
121   }
122 }
123
124 static void catch_interrupt(int err)
125 {
126   (void) err;
127   (void) signal(SIGINT, SIG_IGN);
128
129   if (interrupt++ >= 3)
130     exit(1);
131
132   (void) signal(SIGINT, catch_interrupt);
133 }
134
135 void fix_date_and_time (void)
136 {
137   time_t clock;
138   struct tm *tmptr;
139
140   (void) time(&clock);
141
142   if (trace_flag)
143     printf("The time is %lld\n", clock);
144
145   if (clock < 0)
146     puts("Time not available!");
147
148   tmptr = localtime (&clock);
149
150   if (tmptr == NULL)
151   {
152     printf("Cannot convert time (%0lld)!\n", clock);
153     year     = 2038;
154     month    = 1;
155     day      = 18;
156     tex_time = 22 * 60 + 14;
157   }
158   else
159   {
160     tex_time = tmptr->tm_hour * 60 + tmptr->tm_min;
161     day      = tmptr->tm_mday;
162     month    = tmptr->tm_mon + 1;
163     year     = tmptr->tm_year + 1900;
164
165     if (trace_flag)
166       printf("%d-%d-%d %d:%d\n",
167         tmptr->tm_year + 1900,
168         tmptr->tm_mon + 1,
169         tmptr->tm_mday,
170         tmptr->tm_hour,
171         tmptr->tm_min);
172   }
173
174   {
175 #ifdef MSDOS
176     if (!no_interrupts)
177     {
178       if (signal(SIGINT, catch_interrupt) == SIG_ERR)
179       {
180         puts(" CTRL-C handler not installed\n");
181 #ifndef _WINDOWS
182         uexit(EXIT_FAILURE);  /* do we care when run as DLL ? */
183 #endif
184       }
185     }
186 #else
187     void (*old_handler)();
188
189     if ((old_handler = signal (SIGINT, catch_interrupt)) != SIG_DFL)
190       (void) signal (SIGINT, old_handler);
191 #endif
192   }
193 }
194
195 /* I/O for TeX and Metafont.  */
196 void complain_line (FILE *output)
197 {
198   show_line("\n", 0);
199
200 #ifdef ALLOCATEBUFFER
201   sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", current_buf_size);
202 #else
203   sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", buf_size);
204 #endif
205
206   fputs(log_line, output);
207   puts("  (File may have a line termination problem.)");
208 }
209
210 void show_bad_line (FILE *output, int first, int last)
211 {
212   int i, c, d, ch;
213   char *s = log_line;
214
215   for (i = first; i <= last; i++)
216   {
217     ch = buffer[i];
218
219     if (show_in_hex && (ch > 127))
220     {
221       c = ch >> 4;
222       d = ch & 15;
223
224       if (c > 9)
225         c = c + 'a' - 10;
226       else
227         c = c + '0';
228
229       if (d > 9)
230         d = d + 'a' - 10;
231       else
232         d = d + '0';
233
234       *s++ = '^';
235       *s++ = '^';
236
237       *s++ = (char) c;
238       *s++ = (char) d;
239     }
240     else if (ch < 32)
241     {
242       *s++ = '^';
243       *s++ = '^';
244       *s++ = (char) (ch + 64);
245     }
246     else if (ch == 127)
247     {
248       *s++ = '^';
249       *s++ = '^';
250       *s++ = (char) (ch - 64);
251     }
252     else
253     {
254       *s++ = (char) ch;
255     }
256   }
257
258   *s++ = ' ';
259   *s++ = '\0';
260
261   fputs(log_line, output);   // log_file
262 }
263
264 boolean input_line_finish (void)
265 {
266   int i = '\0';
267   int ch, flag;
268
269   buffer[last] = ' ';
270
271   if (last >= max_buf_stack)
272     max_buf_stack = last;
273
274   while (last > first)
275   {
276     i = buffer[last - 1];
277
278     if (i == ' ' || i == '\t')
279       --last;
280     else
281       break;
282   }
283
284   if (restrict_to_ascii)
285   {
286     flag = 0;
287
288     for (i = first; i <= last; i++)
289     {
290       ch = buffer[i];
291
292       if (ch > 126 ||  (ch < ' ' && ch != '\t' && ch != '\f' && ch != '\r' && ch != '\n'))
293       {
294         sprintf(log_line, "\n! non ASCII char (%d) in line: ", ch);
295         show_line(log_line, 1);
296
297         if (log_opened)
298           fprintf(log_file, "\n! non ASCII char (%d) in line: ", ch);
299
300         flag = 1;
301         break;
302       }
303     }
304
305     if (flag)
306     {
307       show_bad_line(errout, first, last);
308
309       if (log_opened)
310         show_bad_line(log_file, first, last);
311     }
312   }
313
314   if (non_ascii)
315   {
316     for (i = first; i <= last; i++)
317       buffer[i] = xord[buffer[i]];
318   }
319
320   return true;
321 }
322
323 /* Read a line of input into buffer as efficiently as possible (ha ha)
324    while still looking like Pascal.
325    We set `last' to `first' and return `false' if we get to eof.
326    Otherwise, we return `true' and set last = first +
327    length(line except trailing whitespace).  */
328 /* texmfmp.c */
329
330 boolean input_line (FILE *f)
331 {
332 //  int ch, flag;         /* for restrict_to_ascii case 94/Jan/21 */
333   char *u;            /* 1994/July/3 for key_replace */
334   int i = '\0';
335
336 /*  and here is the long way of doing this */
337   last = first;
338 /*  following is new version with tab expansion and key replacement */
339 /*  may want to expand out separately for speed 1994/July/3 */
340 /*  different versions depending on return_flag / tabexpand / key_replace */
341 /*  while (last < buf_size && (i = getc (f)) != EOF)  */
342 #ifdef ALLOCATEBUFFER
343   for ( ; ; ) 
344 #else
345   while (last < buf_size) 
346 #endif
347   {
348     i = getc(f);
349
350     if (i < ' ')
351     {
352       if (i == EOF || i == '\n' || (i == '\r' && return_flag))
353         break;
354       else if (i == '\t' && tab_step != 0)
355       {
356         buffer[last++] = (ASCII_code) ' ';
357
358 #ifdef ALLOCATEBUFFER
359         if (last >= current_buf_size)
360         {
361           buffer = realloc_buffer(increment_buf_size);  
362
363           if (last >= current_buf_size)
364             break;
365         }
366 #endif
367
368 #ifdef ALLOCATEBUFFER
369         while ((last - first) % tab_step != 0) 
370 #else
371         while (last < buf_size && (last - first) % tab_step != 0)
372 #endif
373         {
374
375           buffer[last++] = (ASCII_code) ' ';
376
377 #ifdef ALLOCATEBUFFER
378           if (last >= current_buf_size)
379           {
380             buffer = realloc_buffer(increment_buf_size);
381
382             if (last >= current_buf_size)
383               break;
384           }
385 #endif
386         }
387
388         continue;
389       }
390     }
391
392     if (key_replace && (u = replacement[i]) != NULL)
393     {
394 #ifdef ALLOCATEBUFFER
395       while (*u != '\0') 
396 #else
397       while (last < buf_size && *u != '\0')  
398 #endif
399       {
400         buffer[last++] = (ASCII_code) *u++;
401 #ifdef ALLOCATEBUFFER
402         if (last >= current_buf_size)
403         {
404           buffer = realloc_buffer(increment_buf_size);
405
406           if (last >= current_buf_size)
407             break;
408         }
409 #endif
410       }
411     }
412     else       /* normal case */
413     {
414       buffer[last++] = (ASCII_code) i;
415
416 #ifdef ALLOCATEBUFFER
417       if (last >= current_buf_size)
418       {
419         buffer = realloc_buffer(increment_buf_size);
420
421         if (last >= current_buf_size)
422           break;
423       }
424 #endif
425     }
426   }
427
428   if (return_flag)    /* let return terminate line as well as newline */
429   {
430     if (i == '\r')      /* see whether return followed by newline */
431     {
432       i = getc (f);       /* in which case throw away the newline */
433
434       if (i != '\n')
435       {
436         ungetc (i, f);
437         i = '\r';
438       }
439 /*      else  buffer[last-1] = (ASCII_code) i; */
440     }
441   }
442
443   //  Turn Ctrl-Z at end of file into newline 2000 June 22
444   if (i == EOF && trimeof && buffer[last - 1] == 26)
445   {
446     last--;
447   }
448
449   if (i == EOF && last == first)
450     return false;
451
452 /*  Didn't get the whole line because buffer was too small?  */
453 /*  This shouldn't happen anymore 99/Jan/23 */
454   if (i != EOF && i != '\n' && i != '\r')
455   {
456     complain_line(errout);
457
458     if (log_opened)
459       complain_line(log_file);
460
461     /* This may no longer be needed ... now that we grow it */
462     if (truncate_long_lines)
463     {
464       while (i != EOF && i != '\n' && i != '\r')
465       {
466         i = getc (f);     // discard rest of line
467       }
468
469       last--;       /* just in case */
470     }
471     else
472       uexit(EXIT_FAILURE);      /* line too long */
473   }
474
475   return input_line_finish();
476 }
477
478 /* This string specifies what the `e' option does in response to an
479    error message.  */
480
481 static char *edit_value = "c:\\yandy\\WinEdt\\WinEdt.exe [Open('%s');SelLine(%d,7)]";
482
483 /* This procedure is due to sjc@s1-c.  TeX (or Metafont) calls it when
484    the user types `e' in response to an error, invoking a text editor on
485    the erroneous source file.  FNSTART is how far into STRINGPOOL the
486    actual filename starts; FNLENGTH is how long the filename is.
487    
488    See ../site.h for how to set the default, and how to override it.  */
489
490 /* called from close_files_and_terminate in  tex9.c */
491
492 void call_edit (ASCII_code *stringpool, pool_pointer fnstart, integer fnlength, integer linenumber)
493 {
494   char *command, *s, *t, *u;
495   char c;
496   int sdone, ddone, ldone;
497   int i, n;
498   unsigned int commandlen;
499   ASCII_code *texfilename;
500   ASCII_code *log_file_name;
501   pool_pointer lgstart;
502   integer lglength;
503
504   if (log_opened)
505   {
506     lgstart = str_start[texmf_log_name];
507     lglength = length(texmf_log_name);
508     log_file_name = stringpool + lgstart;
509   }
510   else
511   {
512     lglength = 0;
513     log_file_name = (unsigned char *) "";
514   }
515
516   sdone = ddone = ldone = 0;
517   texfilename = stringpool + fnstart;
518
519   for (i = 1; i <= in_open; i++)
520     (void) fclose (input_file[i]);
521
522   n = fcloseall();
523
524   if (n > 0 && verbose_flag)
525   {
526     sprintf(log_line, "Closed %d streams\n", n);
527     show_line(log_line, 0);
528   }
529
530   s = kpse_var_value(edit_value);  
531
532   if (s != NULL)
533     edit_value = s;
534
535   commandlen = strlen (edit_value) + fnlength + lglength + 10 + 1 + 2;
536   command = (string) xmalloc (commandlen); 
537
538   s = command;
539
540   u = edit_value;
541
542   while ((c = *u++) != 0)
543   {
544     if (c == '%')
545     {
546       switch (c = *u++)
547       {
548         case 'd':
549           if (ddone)
550           {
551 #ifdef _WIN32
552             sprintf(log_line, "! bad command syntax (%c).\n", 'd');
553             show_line(log_line, 1);
554 #else
555             sprintf(log_line, "! `%%d' cannot appear twice in editor command.\n");
556             show_line(log_line, 1);
557 #endif
558             uexit(EXIT_FAILURE); 
559           }
560
561           (void) sprintf (s, "%lld", linenumber);
562
563           while (*s != '\0')
564             s++;
565
566           ddone = 1;
567           break;
568
569         case 's':
570           if (sdone)
571           {
572 #ifdef __WIN32
573             sprintf(log_line, "! bad command syntax (%c).\n", 's'); 
574             show_line(log_line, 1);
575 #else
576             sprintf(log_line, "! `%%s' cannot appear twice in editor command.\n");
577             show_line(log_line, 1);
578 #endif
579             uexit(EXIT_FAILURE); 
580           }
581
582           t = (char *) texfilename;
583           n = fnlength;
584
585           if (non_ascii)
586             for (i = 0; i < n; i++)
587               *s++ = xchr [*t++];
588           else
589             for (i = 0; i < n; i++)
590               *s++ = (char) *t++;
591
592           sdone = 1;
593           break;
594
595         case 'l':
596           if (ldone)
597           {
598 #ifdef __WIN32
599             sprintf(log_line, "! bad command syntax (%c).\n", 'l'); 
600             show_line(log_line, 1);
601 #else
602             sprintf(log_line, "! `%%l' cannot appear twice in editor command.\n");
603             show_line(log_line, 1);
604 #endif
605             uexit(EXIT_FAILURE); 
606           }
607
608           t = (char *) log_file_name;
609           n = lglength;
610
611           if (non_ascii)
612             for (i = 0; i < n; i++)
613               *s++ = xchr [*t++];
614           else
615             for (i = 0; i < n; i++)
616               *s++ = (char) *t++;
617
618           ldone = 1;
619           break;
620
621         case '\0':
622           *s++ = '%'; 
623           u--;
624           break;
625
626         default:
627           *s++ = '%';
628           *s++ = c;
629           break;
630       }
631     }
632     else
633       *s++ = c;
634   }
635
636   *s = 0; /* terminate the command string */
637
638   if (strlen(command) + 1 >= commandlen)
639   {
640     sprintf(log_line, "Command too long (%d > %d)\n", strlen(command) + 1, commandlen);
641     show_line(log_line, 1);
642     uexit(EXIT_FAILURE);
643   }
644
645   //flushall();
646   fflush(NULL);
647
648   if (system (command) != 0)
649   {
650     show_line("\n", 0);
651     sprintf(log_line, "! Error in call: %s\n", command);
652     show_line(log_line, 1);
653
654 #ifdef __WIN32
655     if (errno != 0)
656       perrormod("! DOS says");
657 #endif
658
659     sprintf(log_line, "  (TEXEDIT=%s)\n", edit_value);
660     show_line(log_line, 0);
661     puts("  (Editor specified may be missing or path may be wrong)\n");
662     puts("  (or there may be missing -- or extraneous -- quotation signs)\n");
663   }
664
665   uexit(EXIT_FAILURE);
666 }
667
668
669 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
670
671 /* We don't REALLY care what `endian' the machine is after all ! */
672 /* But we do care about speed - so check exe file for following - bkph */
673
674 // #ifdef MYDEBUG
675 // char swapmarkerstring="ERROR: SWAPPING - NOT BigEndian AND NOT NoFmtBaseSwap";
676 // #endif
677
678 /* This macro is always invoked as a statement.  It assumes a variable
679    `temp'.  */
680    
681 #define SWAP(x, y) temp = (x); (x) = (y); (y) = temp;
682
683
684 /* Make the NITEMS items pointed at by P, each of size SIZE, be the
685    opposite-endianness of whatever they are now.  */
686
687 static int swap_items (char *p, int nitems, int size)
688 {
689   char temp;
690
691   /* Since `size' does not change, we can write a while loop for each
692      case, and avoid testing `size' for each time.  */
693   switch (size)
694   {
695     case 8:
696       while (nitems--)
697       {
698         SWAP (p[0], p[7]);
699         SWAP (p[1], p[6]);
700         SWAP (p[2], p[5]);
701         SWAP (p[3], p[4]);
702         p += size;
703       }
704       break;
705
706     case 4:
707       while (nitems--)
708       {
709         SWAP (p[0], p[3]);
710         SWAP (p[1], p[2]);
711         p += size;
712       }
713       break;
714
715     case 2:
716       while (nitems--)
717       {
718         SWAP (p[0], p[1]);
719         p += size;
720       }
721       break;
722
723     case 1:
724     /* Nothing to do.  */
725       break;
726
727     default:
728       show_line("\n", 0);
729       sprintf(log_line, "! I can't (un)dump a %d byte item.\n", size);
730       show_line(log_line, 1);
731       uexit(EXIT_FAILURE);
732   }
733   return 0;
734 }
735 #endif /* not WORDS_BIGENDIAN and not NO_FMTBASE_SWAP */
736
737 #ifdef COMPACTFORMAT
738 int do_dump(char *p, int item_size, int nitems, gzFile out_file)
739 #else
740 int do_dump(char *p, int item_size, int nitems, FILE *out_file)
741 #endif
742 {
743 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
744   swap_items (p, nitems, item_size);
745 #endif
746
747 #ifdef COMPACTFORMAT
748   if (gzwrite(out_file, p, (item_size * nitems)) != (item_size * nitems))
749 #else
750   if ((int) fwrite(p, item_size, nitems, out_file) != nitems)
751 #endif
752   {
753     show_line("\n", 0);
754     sprintf(log_line, "! Could not write %d %d-byte item%s.\n",
755                nitems, item_size, (nitems > 1) ? "s" : "");
756     show_line(log_line, 1);
757     uexit(EXIT_FAILURE);
758   }
759
760 /* Have to restore the old contents of memory, since some of it might get used again.  */
761 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
762   swap_items (p, nitems, item_size);
763 #endif
764
765   return 0;
766 }
767
768 #ifdef COMPACTFORMAT
769 int do_undump(char *p, int item_size, int nitems, gzFile in_file)
770 #else
771 int do_undump(char *p, int item_size, int nitems, FILE *in_file)
772 #endif
773 {
774 #ifdef COMPACTFORMAT
775   if (gzread(in_file, (void *) p, (unsigned int) (item_size * nitems)) <= 0)
776 #else
777   if ((int) fread((void *) p, item_size, nitems, in_file) != nitems)
778 #endif
779   {
780     show_line("\n", 0);
781     sprintf(log_line, "! Could not read %d %d-byte item%s.\n",
782                nitems, item_size, (nitems > 1) ? "s" : "");
783     show_line(log_line, 1);
784     uexit(EXIT_FAILURE);
785   }
786
787 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
788   swap_items (p, nitems, item_size);
789 #endif
790
791   return 0;
792 }
793
794 #ifdef FUNNY_CORE_DUMP
795
796 void funny_core_dump (void)
797 {
798   int pid, w;
799   union wait status;
800
801   switch (pid = vfork ())
802   {
803     case -1:
804       perrormod ("vfork");
805       exit (-1);
806
807     case 0:
808        (void) signal (SIGQUIT, SIG_DFL);
809        (void) kill (getpid (), SIGQUIT);
810        (void) write (2, "how did we get here?\n", 21);
811        exit (1);
812
813     default:
814       while ((w = wait (&status)) != pid && w != -1)
815         ;
816
817       if (status.w_coredump)
818         exit (0);
819
820       (void) write (2, "attempt to dump core failed\n", 28);
821       exit (1);
822   }
823 }
824 #endif /* FUNNY_CORE_DUMP */