1 /* Copyright 2007 TeX Users Group
2 Copyright 2014 Clerk Ma
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #define REALLOC ourrealloc
29 #define REALLOC realloc
34 char *compiletime = __TIME__;
35 char *compiledate = __DATE__;
36 char *www = "http://www.tug.org/yandy";
37 char *copyright = "\nCopyright (C) 1993--2000 Y&Y, Inc.\n"
38 "Copyright (C) 2007 TeX Users Group.\n"
39 "Copyright (C) 2014 Clerk Ma.\n\n"
40 "This program is free software; you can redistribute it and/or modify\n"
41 "it under the terms of the GNU General Public License as published by\n"
42 "the Free Software Foundation; either version 2 of the License, or\n"
43 "(at your option) any later version.\n\n ";
44 char *yandyversion = "2.3.0";
45 char *application = "Y&Y TeX";
46 char *tex_version = "This is TeX, Version 3.14159265";
48 clock_t start_time, main_time, finish_time;
50 char * dvi_directory = "";
51 char * log_directory = "";
52 char * aux_directory = "";
53 char * fmt_directory = "";
54 char * pdf_directory = "";
56 char * texpath = ""; /* path to executable - used if env vars not set */
58 char log_line[MAXLINE]; // used also in tex9.c
60 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
61 int format_spec = 0; /* non-zero if a format specified on command line */
62 int closed_already = 0; /* make sure we don't try this more than once */
63 bool reorder_arg_flag = true; /* put command line flags/arguments first */
65 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
66 /* Used in tex0.c with wintodos[c-128] */
68 unsigned char wintodos[128] =
70 0, 0, 0, 159, 0, 0, 0, 0,
71 94, 0, 0, 0, 0, 0, 0, 0,
72 0, 96, 39, 0, 0, 7, 0, 0,
73 126, 0, 0, 0, 0, 0, 0, 0,
74 32, 173, 189, 156, 207, 190, 221, 21,
75 0, 184, 166, 174, 170, 45, 169, 0,
76 248, 241, 253, 252, 0, 230, 20, 250,
77 0, 251, 167, 175, 172, 171, 243, 168,
78 183, 181, 182, 199, 142, 143, 146, 128,
79 212, 144, 210, 211, 222, 214, 215, 216,
80 209, 165, 227, 224, 226, 229, 153, 158,
81 157, 235, 233, 234, 154, 237, 232, 225,
82 133, 160, 131, 198, 132, 134, 145, 135,
83 138, 130, 136, 137, 141, 161, 140, 139,
84 208, 164, 149, 162, 147, 228, 148, 246,
85 155, 151, 163, 150, 129, 236, 231, 152
88 void show_usage (void)
93 " Useage: yanytex [OPTION]... [+format_file] [tex_file]\n\n"
95 " show this usage summary\n"
97 " start up as iniTeX (create format file)\n"
99 " be verbose (show implementation version number)\n"
100 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
102 " do not show `non ASCII' characters in hexadecimal (show as is)\n"
103 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
104 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
106 " allow use of \\patterns after loading format (iniTeX only)\n"
108 " disable all extensions to basic TeX\n"
109 " --main-memory -m\n"
110 " initial main memory size in kilo words (iniTeX only)\n"
112 " hyphenation exception dictionary size (iniTeX only)\n"
114 " hyphenation pattern trie size (iniTeX only)\n"
116 " use `non ASCII' character mapping (xchr[]) defined in file\n"
118 " use `key replacement' defined in file\n"
120 " write DVI file in specified directory (default current directory)\n"
122 " write LOG file in specified directory (default current directory)\n"
124 " write AUX file in specified directory (default current directory)\n");
125 show_line(log_line, 1);
128 uexit(1); // has this been setup yet ???
132 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
134 /* -c prepend current directory (.) to TFM directory list\n\ */
135 /* -b check that files with read access are not actually directories\n\ */
137 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
138 /* \t\t(applies to file name and format file name, if present)\n\ */
139 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
141 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
143 // Sep 27 1990 => 1990 Sep 27
144 // 012456789 0123456789
145 void scivilize (char * date)
150 strcpy (pyear, date + 7);
152 for (k = 5; k >= 0; k--)
153 date[k + 5] = date[k];
155 for (k = 0; k < 4; k++)
161 date[9] = '0'; /* replace space by '0' */
166 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35
167 void lcivilize (char * date)
172 strcpy (pyear, date + 20);
174 for (k = 18; k >= 0; k--)
179 for (k = 0; k < 4; k++)
187 // now writes result into given buffer
188 void stamp_it (char *s)
192 strcpy(date, compiledate);
194 sprintf(s, "%s %s ", application, yandyversion);
196 sprintf(s, "(compiled time: %s %s)", date, compiletime);
200 void stampcopy (char *s)
204 sprintf(s, "%s %s", copyright, www);
208 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
213 void read_xchr_sub (FILE * xchr_input)
215 char buffer[PATH_MAX];
216 int k, from, to, count = 0;
219 memset (xchr, NOTDEF, MAXCHRS);
220 memset (xord, NOTDEF, MAXCHRS);
222 #ifdef ALLOCATEBUFFER
223 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
225 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
228 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
231 from = (int) strtol (buffer, &s, 0);
232 to = (int) strtol (s, NULL, 0);
234 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
236 if (xchr[from] == (unsigned char) NOTDEF)
238 xchr[from] = (unsigned char) to;
242 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
243 show_line(log_line, 0);
246 if (xord[to] == NOTDEF)
248 xord[to] = (unsigned char) from;
252 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
253 show_line(log_line, 0);
260 for (k = 0; k < MAXCHRS; k++)
262 if (xchr[k] == NOTDEF) /* if it has not been filled */
264 if (xord[k] == NOTDEF) /* see whether used already */
266 xchr[k] = (unsigned char) k; /* no, so make identity */
267 xord[k] = (unsigned char) k; /* no, so make identity */
272 xchr[NOTDEF] = NOTDEF; /* fixed point of mapping */
276 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
277 show_line(log_line, 0);
279 for (k = 0; k < MAXCHRS; k++)
281 if (xchr[k] != NOTDEF)
283 sprintf(log_line, "%d => %d\n", k, xchr[k]);
284 show_line(log_line, 0);
290 char *replacement[MAXCHRS]; /* pointers to replacement strings */
292 void read_repl_sub (FILE * repl_input)
295 char buffer[PATH_MAX];
300 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
303 while (fgets(buffer, PATH_MAX, repl_input) != NULL)
305 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
308 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
312 if (*charname == '"') /* deal with quoted string "..." */
317 while (*s != '"' && *s != '\0')
318 s++; /* step up to " */
321 continue; /* sanity check */
327 s++; /* is it "" perhaps ? */
330 break; /* no, end of string */
333 *t++ = *s++; /* copy over */
336 *t = '\0'; /* and terminate */
339 if (chrs >= 0 && chrs < MAXCHRS)
340 replacement[chrs] = xstrdup(charname);
342 /* presently the following can never get triggered */
343 /* which is good, because it is perhaps not right ... */
344 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
345 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
346 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
347 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
348 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
350 if (chrs >= 0 && chrs < MAXCHRS)
351 replacement[chrs] = xstrdup(charname);
354 sprintf(log_line, "ERROR: don't understand %s", buffer);
355 show_line(log_line, 1);
361 show_line("Key replacement table\n", 0);
363 for (k = 0; k < MAXCHRS; k++)
365 if (replacement[k] != NULL)
367 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
368 show_line(log_line, 0);
374 /* Following used both to read xchr[] file and key replacement file */
375 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
376 int read_xchr_file (char *filename, int flag, char *argv[])
379 char infile[PATH_MAX];
382 if (filename == NULL)
387 sprintf(log_line, "Reading xchr/repl %s\n", filename);
388 show_line(log_line, 0);
391 /* first try using file as specified */
392 strcpy(infile, filename);
396 sprintf(log_line, "Trying %s\n", infile);
397 show_line(log_line, 0);
400 pinput = fopen (infile, "r");
404 if (strrchr(infile, '.') == NULL)
407 strcat(infile, ".map");
409 strcat(infile, ".key");
413 sprintf(log_line, "Trying %s\n", infile);
414 show_line(log_line, 0);
417 pinput = fopen (infile, "r");
423 strcpy(infile, argv[0]); /* try TeX program path */
425 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
426 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
427 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
429 strcat (infile, filename);
433 sprintf(log_line, "Trying %s\n", infile);
434 show_line(log_line, 0);
437 pinput = fopen (infile, "r");
441 if (strchr(infile, '.') == NULL)
444 strcat(infile, ".map");
446 strcat(infile, ".key");
450 sprintf(log_line, "Trying %s\n", infile);
451 show_line(log_line, 0);
454 pinput = fopen (infile, "r");
459 if (pinput == NULL) /* 97/July/31 */
461 strcpy (infile, argv[0]); /* try TeX program path */
463 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
464 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
465 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
467 strcat (infile, "keyboard\\");
468 strcat (infile, filename);
472 sprintf(log_line, "Trying %s\n", infile);
473 show_line(log_line, 0);
476 pinput = fopen (infile, "r");
480 if (strchr(infile, '.') == NULL)
483 strcat(infile, ".map");
485 strcat(infile, ".key");
489 sprintf(log_line, "Trying %s\n", infile);
490 show_line(log_line, 0);
493 pinput = fopen (infile, "r");
497 /* Note: can't look in TeX source file dir, since that is not known yet */
500 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
501 flag ? " xchr[]" : "key mapping", filename);
502 show_line(log_line, 1);
503 perrormod (filename);
508 read_xchr_sub (pinput);
510 read_repl_sub (pinput);
512 (void) fclose (pinput);
516 /* need to also set `key_replace' here based on command line */
517 /* need to also allocate `buffercopy' here and free at end */
518 /* need to call `readreplace' in appropriate place */
520 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
524 /* ad hoc default minimum growth in memory realloc is 62% */
525 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
526 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
527 int total_allocated = 0; /* total memory allocated so far */
528 int ini_max_address = 0; /* maximum address when starting */
529 int max_address = 0; /* maximum address seen in allocated memory */
532 void show_maximums (FILE *output)
534 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
535 // if (output != NULL) fputs(log_line, output); // log file
536 // else if (flag == 0) show_line(log_line, 0); // informative
537 // else if (flag == 1) show_line(log_line, 1); // error
538 if (output == stderr)
539 show_line(log_line, 1);
540 else if (output == stdout)
541 show_line(log_line, 0);
543 fputs(log_line, output);
546 /* our own version of realloc --- avoid supposed MicroSoft version bug */
547 /* also tries _expand first, which can avoid address growth ... */
550 void *ourrealloc (void *old, size_t new_size)
553 size_t old_size, overlap;
555 /* round up to nearest multiple of four bytes */
556 /* avoid unlikely alignment */
557 if ((new_size % 4) != 0)
558 new_size = ((new_size / 4) + 1) * 4;
561 return malloc (new_size); /* no old block - use malloc */
564 old_size = _msize (old);
566 old_size = malloc_usable_size (old);
569 if (old_size >= new_size && old_size < new_size + 4)
573 mnew = _expand (old, new_size); /* first try and expand in place MSVC */
575 mnew = realloc (old, new_size);
582 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
583 mnew, new_size, old, old_size);
584 show_line(log_line, 0);
588 /* *********************************************************************** */
589 /* do this if you want to call the real realloc next - */
590 mnew = realloc (old, new_size);
594 /* we are screwed typically if we ever drop through here - no more space */
595 /* *********************************************************************** */
596 mnew = malloc (new_size); /* otherwise find new space */
599 return mnew; /* if unable to allocate */
601 if (old_size < new_size)
606 memcpy (mnew, old, overlap); /* copy old data to new area */
607 free(old); /* free the old area */
612 void memory_error (char *s, int n)
616 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
617 show_maximums(log_file);
620 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
621 show_line(log_line, 1);
622 show_maximums(stderr);
625 void trace_memory (char *s, int n)
627 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
628 show_line(log_line, 0);
631 void update_statistics (int address, int size, int oldsize)
633 if (address + size > max_address)
634 max_address = address + size;
636 total_allocated = total_allocated + size - oldsize;
639 void probe_memory (void)
643 s = (char *) malloc (4); /* get current top address */
645 update_statistics ((int) s, 0, 0); /* show where we are */
648 void probe_show (void)
651 show_maximums(stdout);
654 size_t roundup (size_t n)
659 return ((n / 4) + 1) * 4;
663 /* using allocating hyphenation trie slows things down maybe 1% */
664 /* but saves typically (270k - 55k) = 215k of memory */
665 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
666 /* since hyphenation trie cannot be extended (after iniTeX) */
667 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
669 /* NOTE: we don't ever reallocate these */
670 /* returns -1 if it fails */
672 int allocate_tries (int trie_max)
676 /* if (trie_max > trie_size)
678 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
679 trie_max, trie_size);
680 show_line(log_line, 1);
682 } */ /* ??? removed 1993/dec/17 */
683 if (trie_max > 1000000)
684 trie_max = 1000000; /* some sort of sanity limit */
686 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
687 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
688 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
689 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
693 trace_memory("hyphen trie", n);
695 trie_trl = (halfword *) malloc (roundup(nl));
696 trie_tro = (halfword *) malloc (roundup(no));
697 trie_trc = (quarterword *) malloc (roundup(nc));
699 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
701 memory_error("hyphen trie", n);
707 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
708 show_line(log_line, 0);
711 update_statistics ((int) trie_trl, nl, 0);
712 update_statistics ((int) trie_tro, no, 0);
713 update_statistics ((int) trie_trc, nc, 0);
715 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
716 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
719 probe_show(); /* 94/Mar/25 */
725 #ifdef ALLOCATEHYPHEN
726 bool prime (int); /* test function later in this file */
728 int current_prime = 0; /* remember in case reallocated later */
730 /* we don't return an address here, since TWO memory regions allocated */
731 /* plus, we don't really reallocate, we FLUSH the old information totally */
732 /* returns -1 if it fails */
734 int realloc_hyphen (int hyphen_prime)
738 if (!prime(hyphen_prime))
740 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
741 show_line(log_line, 1);
745 /* need not/cannot preserve old contents when hyphen prime is changed */
746 /* if (hyph_list != NULL) free(hyph_list); */
747 /* if (hyph_word != NULL) free(hyph_word); */
748 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
749 nw = (hyphen_prime + 1) * sizeof(str_number);
750 nl = (hyphen_prime + 1) * sizeof(halfword);
754 trace_memory("hyphen exception", n);
756 /* initially hyph_word will be NULL so this acts like malloc */
757 /* hyph_word = (str_number *) malloc (nw); */
758 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
759 /* initially hyph_list will be NULL so this acts like malloc */
760 /* hyph_list = (halfword *) malloc (nl); */
761 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
763 if (hyph_word == NULL || hyph_list == NULL)
765 memory_error("hyphen exception", n);
771 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
772 show_line(log_line, 0);
775 /* cannot preserve old contents when hyphen prime is changed */
777 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
779 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
783 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
785 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
790 if (current_prime != 0)
792 update_statistics ((int) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
793 update_statistics ((int) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
797 update_statistics ((int) hyph_word, nw, 0);
798 update_statistics ((int) hyph_list, nl, 0);
801 current_prime = hyphen_prime;
804 probe_show(); /* 94/Mar/25 */
810 int current_mem_size = 0; /* current total words in main mem allocated -1 */
812 /* this gets called from itex.c when it figures out what mem_top is */
813 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
814 /* initial allocation only, may get expanded later */
815 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
816 /* returns NULL if it fails */
819 /* initial main memory alloc - mem_top */
820 memory_word *allocate_main_memory (int size)
824 /* Using -i *and* pre-loading format */
825 /* in this case get called twice */
826 /* Get rid of initial blank memory again or use realloc ... */
827 /* Could we avoid this by detecting presence of & before allocating ? */
828 /* Also, if its already large enough, maybe we can avoid this ? */
829 /* don't bother if current_mem_size == mem_max - mem_start ? */
830 if (main_memory != NULL)
833 show_line("Reallocating initial memory allocation\n", 1);
836 mem_top = mem_bot + size;
838 mem_start = 0; /* bottom of memory allocated by system */
839 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
840 mem_min = 0; /* bottom of area made available to TeX */
841 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
844 trace_memory("main memory", n);
846 /* main_memory = (memory_word *) malloc (n); */ /* 94/March/24 */
847 /* normally main_memory == NULL here so acts like malloc ... */
848 main_memory = (memory_word *) REALLOC (main_memory, n);
850 if (main_memory == NULL)
852 memory_error("initial main memory", n);
853 // exit (1); /* serious error */
859 sprintf(log_line, "Address main memory == %d\n", main_memory);
860 show_line(log_line, 0);
865 if (mem_start != 0 && !is_initex)
866 mem = main_memory - mem_start;
870 sprintf(log_line, "Offset address main memory == %d\n", mem);
871 show_line(log_line, 0);
874 update_statistics ((int) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));
875 /* current_mem_size = (mem_max - mem_start + 1); */
876 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
879 probe_show(); /* 94/Mar/25 */
886 /* int firstallocation = 1; */
888 /* increase main memory allocation at low end and high end */
889 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
890 /* returns NULL if it fails */
892 memory_word *realloc_main (int losize, int hisize)
897 memory_word * newmemory = NULL;
901 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
902 show_line(log_line, 0);
907 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
910 show_line("Please use `-m=...' on command line\n", 0);
911 // abort_flag++; // ???
917 sprintf(log_line, "Old Address %s == %d\n", "main memory", main_memory);
918 show_line(log_line, 0);
921 /* if we REALLY run up to limit ! */
922 if (current_mem_size + 1 == max_mem_size)
924 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
925 // abort_flag++; // ???
929 /* first allocation should expand *both* lo and hi */
930 if (hisize == 0 && mem_end == mem_max)
933 if (losize == 0 && mem_start == mem_min)
936 /* try and prevent excessive frequent reallocations */
937 /* while avoiding over allocation by too much */
938 minsize = current_mem_size / 100 * percent_grow;
940 if (losize + hisize < minsize)
942 if (losize > 0 && hisize > 0)
944 losize = minsize / 2;
945 hisize = minsize / 2;
953 if (losize > 0 && losize < mem_top / 2)
954 losize = mem_top / 2;
956 if (hisize > 0 && hisize < mem_top / 2)
957 hisize = mem_top / 2;
959 for (k = 0; k < MAXSPLITS; k++)
961 newsize = current_mem_size + losize + hisize;
963 if (newsize >= max_mem_size) /* bump against limit - ha ha ha */
965 while (newsize >= max_mem_size) {
966 losize = losize / 2; hisize = hisize / 2;
967 newsize = current_mem_size + losize + hisize;
971 n = (newsize + 1) * sizeof (memory_word);
974 trace_memory("main memory", n);
976 newmemory = (memory_word *) REALLOC (main_memory, n);
978 if (newmemory != NULL)
979 break; /* did we get it ? */
981 if (current_mem_size == 0)
982 break; /* in case we ever use for initial */
984 losize = losize / 2; hisize = hisize / 2;
987 if (newmemory == NULL)
989 memory_error("main memory", n);
995 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
996 show_line(log_line, 0);
1001 /* shift everything upward to make space for new low area */
1004 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1005 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1006 show_line(log_line, 0);
1008 memmove (newmemory + losize, newmemory,
1009 (current_mem_size + 1) * sizeof(memory_word));
1010 /* could reduce words moved by (mem_max - mem_end) */
1012 main_memory = newmemory; /* remember for free later */
1015 mem_start = mem_start - losize; /* update lower limit */
1018 mem_max = mem_max + hisize; /* update upper limit */
1020 update_statistics ((int) main_memory, n,
1021 (current_mem_size + 1) * sizeof (memory_word));
1022 current_mem_size = newsize;
1024 if (current_mem_size != mem_max - mem_start)
1026 show_line("ERROR: Impossible Memory Error\n", 1);
1030 mem = main_memory - mem_start;
1042 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1044 int current_font_mem_size = 0;
1046 /* fmemoryword can be either halfword or memory_word */
1047 fmemoryword * realloc_font_info (int size)
1049 fmemoryword *newfontinfo = NULL;
1056 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1057 show_line(log_line, 0);
1059 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1060 /* during initial allocation current_font_mem_size == 0 */
1061 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
1063 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1064 return font_info; /* pass it back to TeX 99/Fabe/4 */
1066 /* try and prevent excessive frequent reallocations */
1067 /* while avoiding over allocation by too much */
1068 /* minsize = current_font_mem_size / 2; */
1069 minsize = current_font_mem_size / 100 * percent_grow;
1074 if (size < initial_font_mem_size)
1075 size = initial_font_mem_size;
1077 for (k=0; k < MAXSPLITS; k++)
1079 newsize = current_font_mem_size + size;
1081 if (newsize > font_mem_size)
1082 newsize = font_mem_size; /* bump against limit */
1084 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1085 n = (newsize + 1) * sizeof (fmemoryword);
1088 trace_memory("font_info", n);
1090 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1092 if (newfontinfo != NULL)
1093 break; /* did we get it ? */
1095 if (current_font_mem_size == 0)
1096 break; /* initial allocation must work */
1101 if (newfontinfo == NULL)
1103 memory_error("font", n);
1104 return font_info; /* try and continue !!! */
1107 font_info = newfontinfo;
1111 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1112 show_line(log_line, 0);
1115 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1116 current_font_mem_size = newsize;
1125 #ifdef ALLOCATESTRING
1126 int current_pool_size = 0;
1128 packed_ASCII_code * realloc_str_pool (int size)
1133 packed_ASCII_code *newstrpool = NULL;
1137 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1138 show_line(log_line, 0);
1141 if (current_pool_size == pool_size)
1143 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1145 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1148 minsize = current_pool_size / 100 * percent_grow;
1153 if (size < initial_pool_size)
1154 size = initial_pool_size;
1156 for (k = 0; k < MAXSPLITS; k++)
1158 newsize = current_pool_size + size;
1160 if (newsize > pool_size)
1161 newsize = pool_size;
1162 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1163 n = (newsize + 1) * sizeof (packed_ASCII_code);
1166 trace_memory("str_pool", n);
1168 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1170 if (newstrpool != NULL)
1171 break; /* did we get it ? */
1173 if (current_pool_size == 0)
1174 break; /* initial allocation must work */
1176 size = size / 2; /* else can retry smaller */
1179 if (newstrpool == NULL)
1181 memory_error("string pool", n);
1182 return str_pool; /* try and continue !!! */
1185 str_pool = newstrpool;
1186 update_statistics ((int) str_pool, n, current_pool_size);
1187 current_pool_size = newsize;
1191 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1192 show_line(log_line, 0);
1202 #ifdef ALLOCATESTRING
1203 int current_max_strings = 0;
1205 pool_pointer *realloc_str_start (int size)
1210 pool_pointer *newstrstart=NULL;
1214 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1215 show_line(log_line, 0);
1218 if (current_max_strings == max_strings)
1220 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1222 return str_start; /* pass it back to TeX 99/Fabe/4 */
1225 minsize = current_max_strings / 100 * percent_grow;
1230 if (size < initial_max_strings)
1231 size = initial_max_strings;
1233 for (k = 0; k < MAXSPLITS; k++)
1235 newsize = current_max_strings + size;
1237 if (newsize > max_strings)
1238 newsize = max_strings;
1239 /* important + 1 since str_start[maxstring + 1] originally */
1240 n = (newsize + 1) * sizeof (pool_pointer);
1243 trace_memory("str_start", n);
1245 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1247 if (newstrstart != NULL)
1248 break; /* did we get it ? */
1250 if (current_max_strings == 0)
1251 break; /* initial allocation must work */
1253 size = size / 2; /* otherwise can try smaller */
1256 if (newstrstart == NULL)
1258 memory_error("string pointer", n);
1259 return str_start; /* try and continue */
1262 str_start = newstrstart;
1263 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1264 current_max_strings = newsize;
1268 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1269 show_line(log_line, 0);
1280 /* returns -1 if it fails */
1281 /* size == trie_size */
1282 int allocate_ini (int size)
1284 int n, nl, no, nc, nr, nh, nt;
1286 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1287 no = (size + 1) * sizeof(trie_op_code);
1288 nc = (size + 1) * sizeof(packed_ASCII_code);
1289 /* nt = (size + 1) * sizeof(bool); */
1290 nt = (size + 1) * sizeof(char);
1291 n = nl + no + nc + nr + nh + nt;
1292 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1293 3 * sizeof(trie_pointer) + sizeof (char)); */
1295 trace_memory ("iniTeX hyphen trie", n);
1297 trie_l = (trie_pointer *) malloc (roundup(nl));
1298 trie_o = (trie_op_code *) malloc (roundup(no));
1299 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1300 trie_r = (trie_pointer *) malloc (roundup(nr));
1301 trie_hash = (trie_pointer *) malloc (roundup(nh));
1302 trie_taken = (char *) malloc (roundup(nt));
1304 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1305 trie_hash == NULL || trie_taken == NULL)
1307 memory_error("iniTeX hyphen trie", n);
1308 // exit (1); /* serious error */
1314 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1315 trie_l, trie_o, trie_c);
1316 show_line(log_line, 0);
1317 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1318 trie_r, trie_hash, trie_taken);
1319 show_line(log_line, 0);
1322 update_statistics ((int) trie_l, nl, 0);
1323 update_statistics ((int) trie_o, no, 0);
1324 update_statistics ((int) trie_c, nc, 0);
1325 update_statistics ((int) trie_r, nr, 0);
1326 update_statistics ((int) trie_hash, nh, 0);
1327 update_statistics ((int) trie_taken, nt, 0);
1328 /* trie_size = size; */ /* ??? */
1332 return 0; // success
1336 #ifdef ALLOCATESAVESTACK
1337 int current_save_size = 0;
1339 memory_word *realloc_save_stack (int size)
1342 int n = 0, newsize = 0;
1343 memory_word *newsave_stack = NULL;
1347 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1348 show_line(log_line, 0);
1351 if (current_save_size == save_size) /* arbitrary limit */
1353 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1355 return save_stack; /* let TeX handle the error */
1358 minsize = current_save_size / 100 * percent_grow;
1363 if (size < initial_save_size)
1364 size = initial_save_size;
1366 for (k = 0; k < MAXSPLITS; k++)
1368 newsize = current_save_size + size;
1370 if (newsize > save_size)
1371 newsize = save_size;
1373 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1376 trace_memory("save_stack", n);
1378 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1380 if (newsave_stack != NULL)
1381 break; /* did we get it ? */
1383 if (current_save_size == 0)
1384 break; /* initial allocation must work */
1386 size = size / 2; /* else can retry smaller */
1389 if (newsave_stack == NULL)
1391 memory_error("save stack", n);
1392 return save_stack; /* try and continue !!! */
1395 save_stack = newsave_stack;
1396 update_statistics ((int) save_stack, n, current_save_size);
1397 current_save_size = newsize;
1401 sprintf(log_line, "Current %s %d\n", "save_size", current_save_size);
1402 show_line(log_line, 0);
1403 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1404 show_line(log_line, 0);
1414 #ifdef ALLOCATEINPUTSTACK
1415 int current_stack_size = 0; /* input stack size */
1417 in_state_record *realloc_input_stack (int size)
1420 int n = 0, newsize = 0;
1421 in_state_record *newinputstack = NULL;
1425 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1426 show_line(log_line, 0);
1429 if (current_stack_size == stack_size) /* arbitrary limit */
1431 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1436 minsize = current_stack_size / 100 * percent_grow;
1441 if (size < initial_stack_size)
1442 size = initial_stack_size;
1444 for (k = 0; k < MAXSPLITS; k++)
1446 newsize = current_stack_size + size;
1448 if (newsize > stack_size)
1449 newsize = stack_size;
1451 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1454 trace_memory("input_stack", n);
1456 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1458 if (newinputstack != NULL)
1459 break; /* did we get it ? */
1461 if (current_stack_size == 0)
1462 break; /* initial allocation must work */
1464 size = size / 2; /* else can retry smaller */
1467 if (newinputstack == NULL)
1469 memory_error("input stack", n);
1470 return input_stack; /* try and continue !!! */
1473 input_stack = newinputstack;
1474 update_statistics ((int) input_stack, n, current_stack_size);
1475 current_stack_size = newsize;
1479 sprintf(log_line, "Current %s %d\n", "stack_size", current_stack_size);
1480 show_line(log_line, 0);
1481 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1482 show_line(log_line, 0);
1486 probe_show(); /* 94/Mar/25 */
1492 #ifdef ALLOCATENESTSTACK
1493 int current_nest_size = 0; /* current nest size */
1495 list_state_record *realloc_nest_stack (int size)
1498 int n = 0, newsize = 0;
1499 list_state_record *newnest = NULL;
1503 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1504 show_line(log_line, 0);
1507 if (current_nest_size == nest_size) /* arbitrary limit */
1509 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1511 return nest; /* let TeX handle the error */
1514 minsize = current_nest_size / 100 * percent_grow;
1519 if (size < initial_nest_size)
1520 size = initial_nest_size;
1522 for (k = 0; k < MAXSPLITS; k++)
1524 newsize = current_nest_size + size;
1526 if (newsize > nest_size)
1527 newsize = nest_size;
1529 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1532 trace_memory("nest stack", n);
1534 newnest = (list_state_record *) REALLOC (nest, n);
1536 if (newnest != NULL)
1537 break; /* did we get it ? */
1539 if (current_nest_size == 0)
1540 break; /* initial allocation must work */
1542 size = size / 2; /* else can retry smaller */
1545 if (newnest == NULL)
1547 memory_error("nest stack", n);
1548 return nest; /* try and continue !!! */
1552 update_statistics ((int) nest, n, current_nest_size);
1553 current_nest_size = newsize;
1557 sprintf(log_line, "Current %s %d\n", "nest_size", current_nest_size);
1558 show_line(log_line, 0);
1559 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1560 show_line(log_line, 0);
1570 #ifdef ALLOCATEPARAMSTACK
1571 int current_param_size = 0;
1573 halfword *realloc_param_stack (int size)
1576 int n = 0, newsize = 0;
1577 halfword *newparam = NULL;
1581 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1582 show_line(log_line, 0);
1585 if (current_param_size == param_size) /* arbitrary limit */
1587 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1589 return param_stack; /* let TeX handle the error */
1592 minsize = current_param_size / 100 * percent_grow;
1597 if (size < initial_param_size)
1598 size = initial_param_size;
1600 for (k = 0; k < MAXSPLITS; k++)
1602 newsize = current_param_size + size;
1604 if (newsize > param_size)
1605 newsize = param_size;
1607 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1610 trace_memory("param stack", n);
1612 newparam = (halfword *) REALLOC (param_stack, n);
1614 if (newparam != NULL)
1615 break; /* did we get it ? */
1617 if (current_param_size == 0)
1618 break; /* initial allocation must work */
1620 size = size / 2; /* else can retry smaller */
1623 if (newparam == NULL)
1625 memory_error("param stack", n);
1626 return param_stack; /* try and continue !!! */
1629 param_stack = newparam;
1630 update_statistics ((int) param_stack, n, current_param_size);
1631 current_param_size = newsize;
1635 sprintf(log_line, "Current %s %d\n", "param_size", current_param_size);
1636 show_line(log_line, 0);
1637 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1638 show_line(log_line, 0);
1642 probe_show(); /* 94/Mar/25 */
1648 #ifdef ALLOCATEBUFFER
1649 int current_buf_size = 0;
1651 ASCII_code *realloc_buffer (int size)
1654 int n = 0, newsize = 0;
1655 ASCII_code *newbuffer = NULL;
1659 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1660 show_line(log_line, 0);
1663 if (current_buf_size == buf_size) /* arbitrary limit */
1665 /* memory_error ("buffer", buf_size); */
1667 return buffer; /* pass it back to TeX 99/Fabe/4 */
1670 minsize = current_buf_size / 100 * percent_grow;
1675 if (size < initial_buf_size)
1676 size = initial_buf_size;
1678 for (k = 0; k < MAXSPLITS; k++)
1680 newsize = current_buf_size + size;
1682 if (newsize > buf_size)
1685 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1688 trace_memory("buffer", n);
1690 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1692 if (newbuffer != NULL)
1693 break; /* did we get it ? */
1695 if (current_buf_size == 0)
1696 break; /* initial allocation must work */
1698 size = size / 2; /* else can retry smaller */
1701 if (newbuffer == NULL)
1703 memory_error("buffer", n);
1704 return buffer; /* try and continue !!! */
1708 update_statistics ((int) buffer, n, current_buf_size);
1711 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1713 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1716 current_buf_size = newsize;
1720 sprintf(log_line, "Current %s %d\n", "buffer", current_buf_size);
1721 show_line(log_line, 0);
1722 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1723 show_line(log_line, 0);
1733 /* here is the main memory allocation routine -- calls the above */
1734 /* returns -1 if it fails */
1735 /* allocate rather than static 93/Nov/26 */
1736 int allocate_memory (void)
1740 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1744 #error ERROR: Not ready for ALLOCATEHASH...
1747 /* probably not worth while/not a good idea allocating following */
1748 /* they are all rather small, and typically don't need expansion */
1749 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1751 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1752 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1753 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1755 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1756 zzzae = (htwohalves *) malloc (roundup(n));
1758 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1759 zzzae = (twohalves *) malloc (roundup(n));
1761 if (trace_flag) trace_memory("hash table", n);
1762 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1765 memory_error("hash table", n);
1766 // exit (1); /* serious error */
1767 return -1; /* serious error */
1770 n = (inputsize + 1) * sizeof(memory_word);
1773 trace_memory("input_stack", n);
1775 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1776 input_stack = (memory_word *) malloc (roundup(n));
1778 if (input_stack == NULL)
1780 memory_error("input_stack", n);
1781 // exit (1); /* serious error */
1782 return -1; /* serious error */
1786 #ifdef ALLOCATEINPUTSTACK
1788 current_stack_size = 0;
1789 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1792 #ifdef ALLOCATENESTSTACK
1794 current_nest_size = 0;
1795 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1798 #ifdef ALLOCATEPARAMSTACK
1800 current_param_size = 0;
1801 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1804 #ifdef ALLOCATESAVESTACK
1806 current_save_size = 0;
1807 save_stack = realloc_save_stack (initial_save_size);
1811 buffer = NULL; /* need to do earlier */
1812 current_buf_size = 0;
1813 buffer = realloc_buffer (initial_buf_size);
1816 #ifdef ALLOCATESTRING
1818 current_pool_size = 0;
1820 current_max_strings = 0;
1821 /* need to create space because iniTeX writes in before reading pool file */
1822 /* for a start, puts in strings for 256 characters */
1823 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1827 show_line("ini TeX pool and string allocation\n", 0);
1829 str_pool = realloc_str_pool (initial_pool_size);
1830 str_start = realloc_str_start (initial_max_strings);
1834 /* the following can save a lot of the usual 800k fixed allocation */
1837 current_font_mem_size = 0;
1838 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1839 /* if ini-TeX we need to do it here - no format file read later */
1841 font_info = realloc_font_info (initial_font_mem_size);
1847 mem_min = mem_bot; /* just to avoid complaints in texbody */
1848 mem_top = mem_initex;
1850 /* allocate main memory here if this is iniTeX */
1851 /* otherwise wait for format undumping in itex.c ... */
1854 /* avoid this if format specified on command line ??? */
1855 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1856 mem = allocate_main_memory(mem_initex); /* made variable ! */
1859 return -1; /* serious error */
1863 /* now for the hyphenation exception stuff */
1864 #ifdef ALLOCATEHYPHEN
1867 /* this will be overridden later by what is in format file */
1868 hyphen_prime = default_hyphen_prime;
1869 /* non ini-TeX use assumes format will be read and that specifies size */
1872 if (new_hyphen_prime)
1873 hyphen_prime = new_hyphen_prime;
1875 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1880 /* now for memory for the part of the hyphenation stuff that always needed */
1881 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1882 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1883 #ifdef ALLOCATETRIES
1886 if (allocate_tries (trie_size))
1891 /* now for memory for hyphenation stuff needed only when running iniTeX */
1895 if (allocate_ini(trie_size))
1900 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1901 trie_c = NULL; /* (trie_size + 1) * char */
1902 trie_taken = NULL; /* (trie_size + 1) * bool */
1906 free(holeadr); /* create the hole */
1908 return 0; // success
1911 /* returns non-zero if error - done to test integrity of stack mostly */
1912 /* free in reverse order 93/Nov/26 */
1913 int free_memory (void)
1915 unsigned int heap_total = 0;
1918 show_line("free_memory ", 0);
1920 if (verbose_flag || trace_flag)
1921 show_maximums(stdout);
1925 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1926 heap_total, max_address);
1927 show_line(log_line, 0);
1932 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1933 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1934 show_line(log_line, 0);
1937 /* following only needed to check consistency of heap ... useful debugging */
1939 show_line("Freeing memory again\n", 0);
1941 /* only free memory if safe ... additional check */
1945 if (trie_taken != NULL)
1948 if (trie_hash != NULL)
1964 trie_hash = trie_l = trie_r = NULL;
1970 #ifdef ALLOCATETRIES
1971 if (trie_trc != NULL)
1974 if (trie_tro != NULL)
1977 if (trie_trl != NULL)
1981 trie_tro = trie_trl = NULL;
1984 #ifdef ALLOCATEHYPHEN
1985 if (hyph_list != NULL)
1988 if (hyph_word != NULL)
1996 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1997 if (main_memory != NULL)
2004 if (font_info != NULL)
2010 #ifdef ALLOCATESTRING
2011 if (str_start != NULL)
2014 if (str_pool != NULL)
2021 #ifdef ALLOCATEPARAMSTACK
2022 if (param_stack != NULL)
2028 #ifdef ALLOCATENESTSTACK
2035 #ifdef ALLOCATEINPUTSTACK
2036 if (input_stack != NULL)
2042 #ifdef ALLOCATESAVESTACK
2043 if (save_stack != NULL)
2048 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
2049 if (format_file != NULL)
2052 if (source_direct != NULL)
2053 free(source_direct);
2055 format_file = source_direct = NULL;
2057 if (dvi_file_name != NULL)
2058 free(dvi_file_name);
2060 if (log_file_name != NULL)
2061 free(log_file_name);
2063 if (pdf_file_name != NULL)
2064 free(pdf_file_name);
2066 pdf_file_name = log_file_name = dvi_file_name = NULL;
2074 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
2079 for (k = 3; k < x; k = k + 2)
2094 bool show_use = false;
2095 bool floating = false;
2097 void complainarg (int c, char *s)
2099 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
2100 show_line(log_line, 1);
2104 /* following is list of allowed command line flags and args */
2106 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
2108 void reorderargs (int ac, char **av)
2112 char takeargs[256]; /* large enough for all command line arg chars */
2116 return; /* no args ! */
2120 t = takeargs; /* list of those that take args */
2122 while (*s != '\0' && *(s+1) != '\0')
2125 *t++ = *s++; /* copy over --- without the = */
2134 show_line(takeargs, 0);
2145 if (n + 1 < ac && *(av[n] + 2) == '\0' &&
2146 strchr(takeargs, *(av[n]+1)) != NULL)
2147 n += 2; /* step over it */
2162 while (m < ac && *av[m] != '-')
2163 m++; /* first command */
2167 /* does it take an argument ? and is this argument next ? */
2168 /* check first whether the `-x' is isolated, or arg follows directly */
2169 /* then check whether this is one of those that takes an argument */
2170 if (m+1 < ac && *(av[m]+2) == '\0' &&
2171 strchr(takeargs, *(av[m]+1)) != NULL)
2173 s = av[m]; /* move command down before non-command */
2177 av[m + 1] = av[m - 1];
2181 n += 2; /* step over moved args */
2185 s = av[m]; /* move command down before non-command */
2191 n++; /* step over moved args */
2196 int test_align (int address, int size, char *name)
2207 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
2208 show_line(log_line, 0);
2214 /* activate detailed checking of alignment when trace_flag is set */
2216 void check_fixed_align (int flag)
2218 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT"))
2220 show_line("PLEASE RECOMPILE ME!\n", 1);
2223 #ifdef CHECKALIGNMENT
2227 test_align ((int) &mem_top, 4, "mem_top");
2228 test_align ((int) &mem_max, 4, "mem_max");
2229 test_align ((int) &mem_min, 4, "mem_min");
2230 test_align ((int) &bad, 4, "bad");
2231 test_align ((int) &trie_size, 4, "trie_size");
2232 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2233 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2234 test_align ((int) &name_length, 4, "name_length");
2235 test_align ((int) &first, 4, "first");
2236 test_align ((int) &last, 4, "last");
2237 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2238 test_align ((int) &pool_ptr, 4, "pool_ptr");
2239 test_align ((int) &str_ptr, 4, "str_ptr");
2240 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2241 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2242 test_align ((int) &log_file, 4, "log_file");
2243 test_align ((int) &tally, 4, "tally");
2244 test_align ((int) &term_offset, 4, "term_offset");
2245 test_align ((int) &file_offset, 4, "file_offset");
2246 test_align ((int) &trick_count, 4, "trick_count");
2247 test_align ((int) &first_count, 4, "first_count");
2248 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2249 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2250 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2251 test_align ((int) &use_err_help, 4, "use_err_help");
2252 test_align ((int) &interrupt, 4, "interrupt");
2253 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2254 test_align ((int) &arith_error, 4, "arith_error");
2255 test_align ((int) &tex_remainder, 4, "tex_remainder");
2256 test_align ((int) &temp_ptr, 4, "temp_ptr");
2257 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2258 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2259 test_align ((int) &var_used, 4, "var_used");
2260 test_align ((int) &dyn_used, 4, "dyn_used");
2261 test_align ((int) &avail, 4, "avail");
2262 test_align ((int) &mem_end, 4, "mem_end");
2263 test_align ((int) &mem_start, 4, "mem_start");
2264 test_align ((int) &rover, 4, "rover");
2265 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2266 test_align ((int) &depth_threshold, 4, "depth_threshold");
2267 test_align ((int) &breadth_max, 4, "breadth_max");
2268 test_align ((int) &nest, sizeof(nest[0]), "nest");
2269 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2270 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2271 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2272 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2274 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2275 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2276 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2277 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2278 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2279 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2280 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2281 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2283 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2284 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2285 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2286 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2287 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2288 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2289 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2290 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2291 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2292 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2293 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2294 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2295 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2296 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2297 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2298 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2299 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2300 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2301 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2302 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2303 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2304 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2305 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2306 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2308 #ifdef ALLOCATEDVIBUF
2309 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2311 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2312 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2313 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2314 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2315 test_align ((int) &background, sizeof(background[0]), "background");
2316 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2317 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2318 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2319 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2320 test_align ((int) &hc, sizeof(hc[0]), "hc");
2321 test_align ((int) &hu, sizeof(hu[0]), "hu");
2322 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2323 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2325 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2326 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2327 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2328 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2330 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2331 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2332 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2333 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2334 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2336 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2337 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2338 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2339 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2343 void check_alloc_align (int flag)
2345 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2346 show_line("PLEASE RECOMPILE ME!\n", 1);
2348 #ifdef CHECKALIGNMENT
2351 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2353 #ifndef ALLOCATEDVIBUF
2354 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2356 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2357 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2358 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2359 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2360 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2361 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2362 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2363 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2364 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2365 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2366 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2367 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2368 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2369 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2370 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2374 bool backwardflag = false; /* don't cripple all advanced features */
2375 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2376 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2377 bool workingdirectory = false; /* if working directory set in ini */
2379 /* cache to prevent allocating twice in a row */
2381 char *lastname = NULL, *lastvalue = NULL;
2383 /* returns allocated string -- these strings are not freed again */
2384 /* is it safe to do that now ? 98/Jan/31 */
2385 char *grabenv (char *varname)
2389 if (varname == NULL)
2392 if (*varname == '\0')
2395 if (lastname != NULL && strcasecmp(lastname, varname) == 0)
2399 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2400 show_line(log_line, 0);
2403 return xstrdup(lastvalue);
2406 s = getenv(varname);
2410 if (lastname != NULL)
2413 lastname = xstrdup (varname);
2415 if (lastvalue != NULL)
2418 lastvalue = xstrdup(s);
2426 void flush_trailing_slash (char *directory)
2430 if (strcmp(directory, "") != 0)
2432 s = directory + strlen(directory) - 1;
2434 if (*s == '\\' || *s == '/')
2439 void knuthify (void)
2441 restrict_to_ascii = false; /* don't complain non ASCII */
2442 allow_patterns = false; /* don't allow pattern redefinition */
2443 show_in_hex = true; /* show character code in hex */
2444 show_in_dos = false; /* redundant with previous */
2445 show_numeric = false; /* don't show character code decimal */
2446 show_missing = false; /* don't show missing characters */
2447 civilize_flag = false; /* don't reorder date fields */
2448 c_style_flag = false; /* don't add file name to error msg */
2449 show_fmt_flag = false; /* don't show format file in log */
2450 show_tfm_flag = false; /* don't show metric file in log */
2452 show_line_break_stats = false; /* do not show line break stats */
2453 show_fonts_used = false;
2454 default_rule = 26214; /* revert to default rule thickness */
2455 pseudo_tilde = false;
2456 pseudo_space = false;
2457 show_texinput_flag = false;
2458 truncate_long_lines = false;
2459 allow_quoted_names = false;
2460 show_cs_names = false;
2461 font_dimen_zero = false;
2462 ignore_frozen = false;
2463 suppress_f_ligs = false;
2464 full_file_name_flag = false;
2465 save_strings_flag = false;
2466 knuth_flag = true; /* so other code can know about this */
2469 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2471 /* following made global so analyze_flag can be made separate procedure */
2473 char * xchrfile = NULL;
2474 char * replfile = NULL;
2476 char * short_options = "m:e:h:0:H:g:P:o:l:a:wvpiKLZMdp2t?u";
2478 static struct option long_options[] =
2480 {"main-memory", 1, 0, 'm'},
2481 {"hyph-size", 1, 0, 'e'},
2482 {"trie-size", 1, 0, 'h'},
2483 {"output-format", 1, 0, '0'},
2484 {"tab-step", 1, 0, 'H'},
2485 {"percent-grow", 1, 0, 'g'},
2486 {"default-rule", 1, 0, 'P'},
2487 {"dvi-dir", 1, 0, 'o'},
2488 {"log-dir", 1, 0, 'l'},
2489 {"aux-dir", 1, 0, 'a'},
2490 {"showhex", 0, 0, 'w'},
2491 {"verbose", 0, 0, 'v'},
2492 {"patterns", 0, 0, 'p'},
2493 {"initex", 0, 0, 'i'},
2494 {"knuthify", 0, 0, 'K'},
2495 {"cstyle", 0, 0, 'L'},
2496 {"showtfm", 0, 0, 'Z'},
2497 {"showmissing", 0, 0, 'M'},
2498 {"deslash", 0, 0, 'd'},
2499 {"patterns", 0, 0, 'p'},
2500 {"suppressflig", 0, 0, '2'},
2501 {"trace", 0, 0, 't'},
2502 {"help", 0, 0, '?'},
2503 {"usage", 0, 0, 'u'},
2507 int analyze_flag (int c, char *optarg)
2512 want_version = true;
2513 verbose_flag = true;
2519 interaction = batch_mode; /* quiet mode */
2522 interaction = nonstop_mode; /* run mode */
2525 interaction = scroll_mode; /* scroll mode */
2528 interaction = error_stop_mode; /* tex mode */
2531 backwardflag = true; /* 94/Jun/15 */
2532 knuthify(); /* revert to `standard' Knuth TeX */
2535 c_style_flag = true; /* C style error msg 94/Mar/21 */
2538 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2541 current_tfm = false; /* not look current dir for TFM */
2544 current_flag = false; /* not look current dir for files */
2547 show_missing = false; /* do not show missing 94/June/10 */
2550 deslash = false; /* flipped 93/Nov/18 */
2551 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2554 allow_patterns = true; /* 93/Nov/26 */
2555 /* reset_exceptions = true; */ /* 93/Dec/23 */
2557 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2559 show_in_hex = true; /* flipped 00/Jun/18 */
2562 show_in_dos = true; /* 96/Jan/26 */
2565 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2568 workingdirectory = true; /* use source dir 98/Sep/29 */
2571 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2574 show_fonts_used = false; /* 97/Dec/24 */
2577 shorten_file_name = true; /* 95/Feb/20 */
2580 show_cs_names = true; /* 98/Mar/31 */
2583 ignore_frozen = true; /* 98/Oct/5 */
2586 font_dimen_zero = false; /* 98/Oct/5 */
2589 show_texinput_flag = false; /* 98/Jan/28 */
2591 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2594 show_line_break_stats = false; /* 96/Feb/8 */
2597 show_fmt_flag = false; /* 94/Jun/21 */
2600 format_specific = false; /* 95/Jan/7 */
2603 encoding_specific = false; /* 98/Oct/5 */
2606 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2609 full_file_name_flag = false; // 00 Jun 18
2612 save_strings_flag = false; // 00 Aug 15
2614 /* following are unannounced options */ /* some may be recycled ... */
2619 quitflag++; /* 93/Dec/16 */
2621 /* The following are really obscure and should not be advertized */
2623 show_current = false; /* tex8 93/Dec/14 */
2626 show_numeric = false; /* 93/Dec/21 */
2629 civilize_flag = false; /* 93/Dec/16 */
2632 open_trace_flag = true; /* openinou 1994/Jan/8 */
2635 reorder_arg_flag = false; /* local */
2638 test_dir_access = false; /* 94/Feb/10 */
2641 dir_method = false; /* 94/Feb/10 */
2644 file_method = false; /* 94/Feb/13 */
2646 /* *********** following command line options take arguments ************** */
2649 mem_initex = mem_top;
2651 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2652 if (mem_initex == 0)
2653 complainarg(c, optarg);
2656 #ifdef VARIABLETRIESIZE
2659 trie_size = default_trie_size;
2661 trie_size = atoi(optarg); /* 93 Dec/1 */
2663 complainarg(c, optarg);
2666 #ifdef ALLOCATEHYPHEN
2669 new_hyphen_prime = hyphen_prime * 2;
2671 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2672 if (new_hyphen_prime == 0)
2673 complainarg(c, optarg);
2680 percent_grow = atoi(optarg); /* 93/Dec/11 */
2681 if (percent_grow == 0)
2682 complainarg(c, optarg);
2688 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2689 if (pseudo_tilde > 255)
2691 else if (pseudo_tilde < 128)
2698 tab_step = atoi(optarg); /* 94/July/3 */
2700 complainarg(c, optarg);
2704 xchrfile = xstrdup("xchr.map");
2706 xchrfile = xstrdup(optarg);
2708 if (xchrfile == NULL || *xchrfile == '\0')
2709 complainarg(c, optarg);
2713 replfile = xstrdup("repl.key");
2715 replfile = xstrdup(optarg);
2717 if (replfile == NULL || *replfile == '\0')
2718 complainarg(c, optarg);
2722 default_rule = 26214;
2724 default_rule = atoi(optarg);
2726 if (default_rule == 0)
2727 complainarg(c, optarg);
2733 complainarg(c, optarg);
2739 dvi_directory = xstrdup(optarg);
2741 if (strcmp(dvi_directory, "") == 0)
2742 complainarg(c, optarg);
2747 char * format_spec = NULL;
2750 format_spec = xstrdup(optarg);
2752 if (!strcmp(format_spec, "pdf"))
2753 pdf_output_flag = true;
2754 else if (!strcmp(format_spec, "dvi"))
2755 pdf_output_flag = false;
2758 sprintf(log_line, "ERROR: Do not understand argument value `%s'\n", format_spec);
2759 show_line(log_line, 1);
2767 log_directory = xstrdup(optarg);
2769 if (strcmp(log_directory, "") == 0)
2770 complainarg(c, optarg);
2776 aux_directory = xstrdup(optarg);
2777 if (strcmp(aux_directory, "") == 0)
2778 complainarg(c, optarg);
2783 return -1; // failed to recognize
2789 void strip_name (char *pathname)
2793 if ((s = strrchr(pathname, '\\')) != NULL)
2795 else if ((s = strrchr(pathname, '/')) != NULL)
2797 else if ((s = strrchr(pathname, ':')) != NULL)
2805 int read_command_line (int ac, char **av)
2814 while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)
2816 if (optarg != 0 && *optarg == '=')
2817 optargnew = optarg + 1;
2821 analyze_flag (c, optargnew);
2824 if (show_use || quitflag == 3)
2827 strcat(log_line, "\n");
2828 show_line(log_line, 0);
2829 //stampcopy(log_line);
2830 //strcat(log_line, "\n");
2831 //show_line(log_line, 0);
2835 else if (quitflag == 3)
2837 strcat(log_line, "\n");
2838 show_line(log_line, 0);
2841 return -1; // failure
2844 if (replfile != NULL && *replfile != '\0')
2846 if (read_xchr_file(replfile, 1, av))
2849 show_line("KEY REPLACE ON\n", 0);
2855 if (xchrfile != NULL && *xchrfile != '\0')
2857 if (read_xchr_file(xchrfile, 0, av))
2860 show_line("NON ASCII ON\n", 0);
2869 int init_commands (int ac, char **av)
2871 pdf_output_flag = false;
2873 allow_patterns = false;
2874 reset_exceptions = false;
2876 key_replace = false;
2877 want_version = false;
2878 open_trace_flag = false;
2880 verbose_flag = false;
2882 restrict_to_ascii = false;
2883 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2884 show_in_dos = false; /* default is not to translate to DOS 850 */
2885 return_flag = true; // hard wired now
2886 trimeof = true; // hard wired now
2888 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2889 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2890 default_rule = 26214; /* default rule variable 95/Oct/9 */
2891 show_current = true;
2892 civilize_flag = true;
2893 show_numeric = true;
2894 show_missing = true;
2895 current_flag = true;
2896 current_tfm = true; /* search for TFMs in current dir as well */
2897 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2898 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2899 file_method = true; /* use file_p (_findfirst) not readable (access) */
2900 c_style_flag = false; /* use c-style error output */
2901 show_fmt_flag = true; /* show format file in log */
2902 show_tfm_flag = false; /* don't show metric file in log */
2903 shorten_file_name = false; /* don't shorten file names to 8+3 */
2904 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2905 truncate_long_lines = true; /* truncate long lines */
2906 tab_step = 0; /* do not replace tabs with spaces */
2907 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2908 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2909 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2910 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2911 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2912 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2913 knuth_flag = false; /* allow extensions to TeX */
2914 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2915 full_file_name_flag = true; /* new default 2000 June 18 */
2916 save_strings_flag = true;
2917 errout = stdout; /* as opposed to stderr say --- used ??? */
2918 abort_flag = 0; // not yet hooked up ???
2919 err_level = 0; // not yet hooked up ???
2920 new_hyphen_prime = 0;
2921 #ifdef VARIABLETRIESIZE
2922 /* trie_size = default_trie_size; */
2929 //format_name = xstrdup(av[0]);
2930 format_name = "plain";
2934 if (read_command_line(ac, av) < 0)
2943 strcat(log_line, "\n");
2944 show_line(log_line, 0);
2945 stampcopy(log_line);
2946 strcat(log_line, "\n");
2947 show_line(log_line, 0);
2950 /* if we aren't including current directory in any directory lists */
2951 /* then makes no sense to avoid them separately for TFM files ... */
2952 /* (that is, the ./ is already omitted from the dir list in that case */
2953 if (!current_flag && !current_tfm)
2959 void initial_memory (void)
2961 /* set initial memory allocations */
2962 if (mem_extra_high < 0)
2965 if (mem_extra_low < 0)
2973 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2974 if (mem_extra_high != 0 || mem_extra_low != 0)
2976 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
2977 mem_extra_high = 0; mem_extra_low = 0;
2983 if (mem_initex != 0)
2985 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
2991 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
2992 /* trie_size = 0; */
2995 if (mem_initex == 0)
2996 mem_initex = default_mem_top;
2999 trie_size = default_trie_size;
3000 /* Just in case user mistakenly specified words instead of kilo words */
3001 if (mem_extra_high > 10000L * 1024L)
3002 mem_extra_high = mem_extra_high / 1024;
3004 if (mem_extra_low > 10000L * 1024L)
3005 mem_extra_low = mem_extra_low / 1024;
3007 if (mem_initex > 10000L * 1024L)
3008 mem_initex = mem_initex / 1024;
3010 if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */
3012 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3013 /* mem_initex = 2048 * 1024; */
3016 if (new_hyphen_prime < 0)
3017 new_hyphen_prime = 0;
3019 if (new_hyphen_prime > 0)
3022 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3025 if (new_hyphen_prime % 2 == 0)
3028 while (!prime(new_hyphen_prime))
3029 new_hyphen_prime = new_hyphen_prime + 2;
3033 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3034 show_line(log_line, 0);
3039 if (percent_grow > 100)
3040 percent_grow = percent_grow - 100;
3042 if (percent_grow > 100)
3043 percent_grow = 100; /* upper limit - double */
3045 if (percent_grow < 10)
3046 percent_grow = 10; /* lower limit - 10% */
3049 /**********************************************************************/
3051 void perrormod (char *s)
3053 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3054 show_line(log_line, 1);
3057 /*************************************************************************/
3059 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3060 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3061 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3062 /* this is then undone in tex3.c both for fopen input and output */
3063 /* not ideal, since pseudo name appears in log and in error messages ... */
3065 void hidetwiddle (char *name)
3072 sprintf(log_line, "Hidetwiddle %s", name);
3073 show_line(log_line, 0);
3076 /* while (*s != '\0' && *s != ' ') { */
3079 if (*s == '~' && pseudo_tilde != 0)
3080 *s = (char) pseudo_tilde; /* typically 254 */
3081 else if (*s == ' ' && pseudo_space != 0)
3082 *s = (char) pseudo_space; /* typically 255 */
3088 sprintf(log_line, "=> %s\n", name);
3089 show_line(log_line, 0);
3094 void deslash_all (int ac, char **av)
3096 char buffer[PATH_MAX];
3099 if ((s = grabenv("TEXDVI")) != NULL)
3102 if ((s = grabenv("TEXLOG")) != NULL)
3105 if ((s = grabenv("TEXAUX")) != NULL)
3108 if ((s = grabenv("TEXFMT")) != NULL)
3111 if ((s = grabenv("TEXPDF")) != NULL)
3114 strcpy(buffer, av[0]); /* get path to executable */
3116 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3117 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3118 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3120 s = buffer + strlen(buffer) - 1;
3122 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3124 texpath = xstrdup(buffer);
3126 /* Hmm, we may be operating on DOS environment variables here !!! */
3128 if (strcmp(dvi_directory, "") != 0)
3129 flush_trailing_slash (dvi_directory);
3131 if (strcmp(log_directory, "") != 0)
3132 flush_trailing_slash (log_directory);
3134 if (strcmp(aux_directory, "") != 0)
3135 flush_trailing_slash (aux_directory);
3137 if (strcmp(fmt_directory, "") != 0)
3138 flush_trailing_slash (fmt_directory);
3140 if (strcmp(pdf_directory, "") != 0)
3141 flush_trailing_slash (pdf_directory);
3147 if (strcmp(dvi_directory, "") != 0)
3148 unixify(dvi_directory);
3150 if (strcmp(log_directory, "") != 0)
3151 unixify(log_directory);
3153 if (strcmp(aux_directory, "") != 0)
3154 unixify(aux_directory);
3156 if (strcmp(fmt_directory, "") != 0)
3157 unixify(fmt_directory);
3159 if (strcmp(pdf_directory, "") != 0)
3160 unixify(pdf_directory);
3163 /* deslash TeX source file (and format, if format specified) */
3164 /* and check args to see whether format was specified */
3166 /* NOTE: assuming that command line arguments are in writable memory ! */
3167 /* if (trace_flag || debug_flag)
3168 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3169 /* if (optind < ac) { */ /* bkph */
3170 if (optind < ac && optind > 0)
3174 if (trace_flag || debug_flag)
3176 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3177 optind, av[optind], ac);
3178 show_line(log_line, 0);
3181 unixify(av[optind]);
3184 if (pseudo_tilde != 0 || pseudo_space != 0)
3185 hidetwiddle (av[optind]);
3187 /* For Windows NT, lets allow + instead of & for format specification */
3188 if (*av[optind] == '&' || *av[optind] == '+')
3191 format_name = xstrdup(av[optind] + 1);
3193 if (optind + 1 < ac)
3197 if (trace_flag || debug_flag)
3199 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3200 optind+1, av[optind+1], ac);
3201 show_line(log_line, 0);
3204 unixify(av[optind + 1]);
3207 if (pseudo_tilde != 0 || pseudo_space != 0)
3208 hidetwiddle (av[optind+1]);
3214 /* The above seems to assume that arguments that don't start with '-' */
3215 /* are file names or format names - what if type in control sequences? */
3217 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3218 /* main entry point follows */
3219 /* this gets called pretty much right away in `main' in texmf.c */
3220 /* note: those optarg == 0 test don't really work ... */
3221 /* note: optarg starts at = in case of x=... */
3223 int main_init (int ac, char **av)
3225 char initbuffer[PATH_MAX];
3228 kpse_set_program_name(av[0], NULL);
3230 if (sizeof(memory_word) != sizeof(integer) * 2)
3232 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3233 show_line(log_line, 1);
3236 start_time = clock();
3237 main_time = start_time;
3239 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3241 /* reset all allocatable memory pointers to NULL - in case we drop out */
3247 #ifdef ALLOCATESAVESTACK
3251 #ifdef ALLOCATEBUFFER
3253 current_buf_size = 0;
3254 buffer = realloc_buffer (initial_buf_size);
3269 log_opened = false; /* so can tell whether opened */
3270 interaction = -1; /* default state => 3 */
3271 missing_characters = 0; /* none yet! */
3272 workingdirectory = false; /* set from dviwindo.ini & command line */
3273 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3274 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3275 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3277 if (ac > 1 && !strncmp(av[1], "-Y", 2))
3278 reorder_arg_flag = false;
3280 if (reorder_arg_flag)
3281 reorderargs(ac, av);
3283 if (init_commands(ac, av))
3286 check_fixed_align(trace_flag);
3289 source_direct = NULL;
3290 dvi_file_name = NULL;
3291 log_file_name = NULL;
3292 pdf_file_name = NULL;
3294 first_pass_count = 0;
3295 second_pass_count = 0;
3296 final_pass_count = 0;
3297 paragraph_failed = 0;
3307 show_line("Entering init (local)\n", 0);
3309 probe_memory(); /* show top address */
3310 ini_max_address = max_address; /* initial max address */
3313 show_maximums(stdout);
3317 deslash_all(ac, av); /* deslash and note if format specified */
3321 if (format_spec && mem_spec_flag)
3323 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3326 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3327 return -1; // if failed to allocate
3329 /* following is more or less useless since most all things not yet alloc */
3330 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3333 show_line("Leaving init (local)\n", 0);
3338 #define CLK_TCK CLOCKS_PER_SEC
3340 void show_inter_val (clock_t interval)
3342 int seconds, tenths, hundredth, thousands;
3344 if (interval >= CLK_TCK * 10)
3346 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3347 seconds = tenths / 10;
3348 tenths = tenths % 10;
3349 sprintf(log_line, "%d.%d", seconds, tenths);
3350 show_line(log_line, 0);
3353 if (interval >= CLK_TCK) /* 94/Feb/25 */
3355 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3356 seconds = hundredth / 100;
3357 hundredth = hundredth % 100;
3358 sprintf(log_line, "%d.%02d", seconds, hundredth);
3359 show_line(log_line, 0);
3362 if (interval > 0) /* 94/Oct/4 */
3364 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3365 seconds = thousands / 1000;
3366 thousands = thousands % 1000;
3367 sprintf(log_line, "%d.%03d", seconds, thousands);
3368 show_line(log_line, 0);
3374 int endit (int flag)
3376 finish_time = clock();
3378 if (missing_characters != 0)
3381 if (missing_characters)
3383 sprintf(log_line, "! There %s %d missing character%s --- see log file\n",
3384 (missing_characters == 1) ? "was" : "were", missing_characters,
3385 (missing_characters == 1) ? "" : "s");
3386 show_line(log_line, 0);
3389 if (free_memory() != 0)
3394 show_line("Total ", 0);
3395 show_inter_val(finish_time - start_time);
3396 show_line(" sec (", 0);
3397 show_inter_val(main_time - start_time);
3398 show_line(" format load + ", 0);
3399 show_inter_val(finish_time - main_time);
3400 show_line(" processing) ", 0);
3402 if (total_pages > 0)
3404 show_inter_val ((finish_time - main_time) / total_pages);
3405 show_line(" sec per page", 0);
3413 // printf control sequences' name
3414 void print_cs_name (FILE *output, int h)
3418 memset(log_line, 0, sizeof(log_line));
3420 textof = hash[h].v.RH;
3425 c = sprintf(log_line, "(%d), ", h);
3428 memmove(log_line + c, str_pool + str_start[textof], n);
3429 memmove(log_line + c + n, "\n", 2);
3431 if (output == stderr)
3433 show_line(log_line, 1);
3437 if (output == stdout)
3438 show_line(log_line, 0);
3440 fprintf(output, log_line);
3445 int compare_strn (int, int, int, int);
3446 /* compare two csnames in qsort */
3447 int compare_cs (const void *cp1, const void *cp2)
3449 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3453 textof1 = hash[c1].v.RH;
3454 textof2 = hash[c2].v.RH;
3455 l1 = length(textof1);
3456 l2 = length(textof2);
3457 k1 = str_start[textof1];
3458 k2 = str_start[textof2];
3460 return compare_strn (k1, l1, k2, l2);
3463 char * csused = NULL;
3465 /* Allocate table of indeces to allow sorting on csname */
3466 /* Allocate flags to remember which ones already listed at start */
3467 /* pass = 0 --> fmt */
3468 /* pass = 1 --> after */
3469 void print_cs_names (FILE *output, int pass)
3471 int h, k, ccount, repeatflag;
3473 int nfcs = frozen_control_sequence;
3475 if (pass == 0 && csused == NULL)
3477 csused = (char *) malloc (nfcs);
3483 memset(csused, 0, nfcs);
3485 for (h = 0; h < (hash_size + 780); h++)
3492 for (h = hash_base + 1; h < nfcs; h++)
3494 if (pass == 1 && csused[h])
3497 if (hash[h].v.RH != 0)
3506 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
3507 ccount, (pass == 1) ? "new" : "");
3509 if (output == stderr)
3511 show_line(log_line, 1);
3515 if (output == stdout)
3516 show_line(log_line, 0);
3518 fprintf(output, log_line);
3523 cnumtable = (int *) malloc (ccount * sizeof(int));
3525 if (cnumtable == NULL)
3530 for (h = hash_base + 1; h < nfcs; h++)
3532 if (pass == 1 && csused[h])
3535 if (hash[h].v.RH != 0)
3536 cnumtable[ccount++] = h;
3539 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3543 for (k = 0; k < ccount; k++)
3547 if (pass == 1 && csused[h])
3550 print_cs_name(output, h);
3553 sprintf(log_line, "\n");
3555 if (output == stderr)
3557 show_line(log_line, 1);
3561 if (output == stdout)
3562 show_line(log_line, 0);
3564 fprintf(output, log_line);
3567 free((void *)cnumtable);
3570 if (pass == 1 && csused != NULL)
3577 /***************** font info listing moved from TEX9.C ******************/
3578 /* compare two strings in str_pool (not null terminated) */
3579 /* k1 and k2 are positions in string pool */
3580 /* l1 and l2 are lengths of strings */
3581 int compare_strn (int k1, int l1, int k2, int l2)
3585 while (l1 > 0 && l2 > 0)
3600 return 1; /* first string longer */
3602 return -1; /* second string longer */
3604 return 0; /* strings match */
3606 /* compare two font names and their at sizes in qsort */
3607 int compare_fnt (const void *fp1, const void *fp2)
3609 int f1, f2, l1, l2, k1, k2, s;
3613 l1 = length(font_name[f1]);
3614 l2 = length(font_name[f2]);
3615 k1 = str_start[font_name[f1]];
3616 k2 = str_start[font_name[f2]];
3618 s = compare_strn (k1, l1, k2, l2);
3623 if (font_size[f1] > font_size[f2])
3625 else if (font_size[f1] < font_size[f2])
3628 return 0; /* should not ever get here */
3630 /* compare two font names */
3631 int compare_fnt_name (int f1, int f2)
3633 int l1, l2, k1, k2, s;
3635 l1 = length(font_name[f1]);
3636 l2 = length(font_name[f2]);
3637 k1 = str_start[font_name[f1]];
3638 k2 = str_start[font_name[f2]];
3640 s = compare_strn (k1, l1, k2, l2);
3644 /* decode checksum information */
3645 unsigned long checkdefault = 0x59265920; /* default signature */
3646 int decode_fourty (unsigned long checksum, char *codingvector)
3650 /* char codingvector[6+1]; */
3654 strcpy(codingvector, "unknwn");
3658 if ((checksum >> 8) == (checkdefault >> 8)) /* last byte random */
3660 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3661 strcpy (codingvector, "fixed "); /* if not specified ... */
3662 return 1; /* no info available */
3666 for (k = 0; k < 6; k++)
3668 c = (int) (checksum % 40);
3669 checksum = checksum / 40;
3670 if (c <= 'z' - 'a') c = c + 'a';
3671 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3672 else if (c == 36) c = '-';
3673 else if (c == 37) c = '&';
3674 else if (c == 38) c = '_';
3675 else c = '.'; /* unknown */
3676 codingvector[5-k] = (char) c;
3678 codingvector[6] = '\0';
3684 double sclpnt (long x)
3688 pt = (double) x / 65536.0;
3689 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3694 // Shows list of fonts in log file
3695 void dvi_font_show(internal_font_number f, int suppressname)
3698 unsigned long checksum;
3699 char checksumvector[8];
3702 putc(' ', log_file);
3704 if (suppressname == 0)
3706 a = length(font_area[f]);
3707 l = length(font_name[f]);
3709 k = str_start[font_area[f]];
3711 memcpy(buffer, str_pool + k, length(font_area[f]));
3712 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
3714 k = str_start[font_name[f]];
3716 memcpy(buffer, str_pool + k, length(font_name[f]));
3717 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
3721 for (k = a + l; k < 16; k++)
3722 putc(' ', log_file);
3724 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3725 fputs(buffer, log_file);
3727 if (suppressname == 0)
3731 for (k = n; k < 16; k++)
3732 putc(' ', log_file);
3734 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
3735 decode_fourty(checksum, checksumvector);
3736 fprintf(log_file, "encoding: %s..", checksumvector);
3739 putc('\n', log_file);
3741 /* Allocate table of indeces to allow sorting on font name */
3742 void show_font_info (void)
3744 int k, m, fcount, repeatflag;
3749 for (k = 1; k <= font_ptr; k++)
3756 fnumtable = (short *) malloc (fcount * sizeof(short));
3758 fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
3762 for (k = 1; k <= font_ptr; k++)
3764 fnumtable[fcount++] = (short) k;
3766 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3770 for (m = 0; m < fcount; m++)
3774 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3780 dvi_font_show(fnumtable[m], repeatflag);
3783 free((void *)fnumtable);