2 Copyright 2007 TeX Users Group
\r
3 Copyright 2014 Clerk Ma
\r
5 This program is free software; you can redistribute it and/or modify
\r
6 it under the terms of the GNU General Public License as published by
\r
7 the Free Software Foundation; either version 2 of the License, or
\r
8 (at your option) any later version.
\r
10 This program is distributed in the hope that it will be useful, but
\r
11 WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
13 General Public License for more details.
\r
15 You should have received a copy of the GNU General Public License
\r
16 along with this program; if not, write to the Free Software
\r
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
\r
21 #if defined (__ANDROID__)
\r
22 #define malloc_usable_size dlmalloc_usable_size
\r
23 #elif defined (__APPLE__)
\r
24 #include <malloc/malloc.h>
\r
25 #define malloc_usable_size malloc_size
\r
28 #define EXTERN extern
\r
30 #include "yandytex.h"
\r
32 #define USEOUREALLOC
\r
36 #define REALLOC ourrealloc
\r
38 #define REALLOC realloc
\r
41 #if defined (__clang__)
\r
42 const char * compiler = "Clang";
\r
43 #elif defined (__GNUC__) || defined(__GNUG__)
\r
44 const char * compiler = "GCC";
\r
45 #elif defined (_MSC_VER)
\r
46 const char * compiler = "MSVC";
\r
48 const char * compiler = "Unknown";
\r
51 #if defined (_WIN64)
\r
52 const char * dist = "Win64";
\r
53 #elif defined (_WIN32)
\r
54 const char * dist = "Win32";
\r
55 #elif defined (__ANDROID__)
\r
56 const char * dist = "Android";
\r
57 #elif defined (__APPLE__)
\r
58 const char * dist = "Darwin";
\r
59 #elif defined (__gnu_linux__)
\r
60 const char * dist = "Linux";
\r
62 const char * dist = "Unknown";
\r
65 const char * compiletime = __TIME__;
\r
66 const char * compiledate = __DATE__;
\r
67 const char * yandyversion = "2.3.0";
\r
68 const char * application = "Y&Y TeX";
\r
69 const char * banner = "This is TeX, Version 3.14159265";
\r
71 void print_banner (void)
\r
74 memset(dist_ver, 0, sizeof(dist_ver));
\r
75 sprintf(dist_ver, "%s (%s %s)", banner, application, yandyversion);
\r
79 clock_t start_time, main_time, finish_time;
\r
81 char * dvi_directory = "";
\r
82 char * log_directory = "";
\r
83 char * aux_directory = "";
\r
84 char * fmt_directory = "";
\r
85 char * pdf_directory = "";
\r
89 boolean mem_spec_flag = false;
\r
90 boolean format_spec = false;
\r
91 boolean reorder_arg_flag = true; /* put command line flags/arguments first */
\r
93 void show_usage (void)
\r
96 "Useage: yandytex [OPTION]... [+format_file] [file]\n\n"
\r
97 "--help -? show this usage summary\n"
\r
98 "--initex -i start up as initex (create format file)\n"
\r
99 "--verbose -v be verbose (show implementation version number)\n"
\r
100 "--ascii -n do not allow `non ASCII' characters in input files\n"
\r
101 " (complain instead)\n"
\r
102 "--showhex -w do not show `non ASCII' characters in hexadecimal\n"
\r
104 "--patterns -p allow use of \\patterns after loading format (initex only)\n"
\r
105 "--knuthify -K disable all extensions to basic TeX\n"
\r
106 "--main-mem -m initial main memory size in kilo words (initex only)\n"
\r
107 "--hyph-size -e hyphenation exception dictionary size (initex only)\n"
\r
108 "--trie-size -h hyphenation pattern trie size (initex only)\n"
\r
109 "--xchr-file -x use `non ASCII' character mapping (xchr[]) defined in file\n"
\r
110 "--key-file -k use `key replacement' defined in file\n"
\r
111 "--dvi-dir -o write DVI file in specified directory (default '.')\n"
\r
112 "--log-dir -l write LOG file in specified directory (default '.')\n"
\r
113 "--aux-dir -a write AUX file in specified directory (default '.')\n");
\r
114 uexit(EXIT_FAILURE);
\r
117 // Sep 27 1990 => 1990 Sep 27
\r
118 // 0123456789 0123456789
\r
119 void scivilize (char * date)
\r
124 strcpy(pyear, date + 7);
\r
126 for (k = 5; k >= 0; k--)
\r
127 date[k + 5] = date[k];
\r
129 for (k = 0; k < 4; k++)
\r
130 date[k] = pyear[k];
\r
134 if (date[9] == ' ')
\r
138 void stamp_it (char * s)
\r
142 strcpy(date, compiledate);
\r
144 sprintf(s, "%s %s (compiled time: %s %s with %s/%s)",
\r
145 application, yandyversion, date, compiletime, dist, compiler);
\r
149 #define MAXCHRS 256
\r
152 void read_xchr_sub (FILE * xchr_input)
\r
154 char buffer[file_name_size];
\r
155 int k, from, to, count = 0;
\r
158 memset(xchr, NOTDEF, MAXCHRS);
\r
159 memset(xord, NOTDEF, MAXCHRS);
\r
161 #ifdef ALLOCATEBUFFER
\r
162 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
\r
164 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
\r
167 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
\r
170 from = (int) strtol (buffer, &s, 0);
\r
171 to = (int) strtol (s, NULL, 0);
\r
173 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
\r
175 if (xchr[from] == NOTDEF)
\r
176 xchr[from] = (unsigned char) to;
\r
178 printf("NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
\r
180 if (xord[to] == NOTDEF)
\r
181 xord[to] = (unsigned char) from;
\r
183 printf("NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
\r
189 for (k = 0; k < MAXCHRS; k++)
\r
191 if (xchr[k] == NOTDEF) /* if it has not been filled */
\r
193 if (xord[k] == NOTDEF) /* see whether used already */
\r
195 xchr[k] = (unsigned char) k; /* no, so make identity */
\r
196 xord[k] = (unsigned char) k; /* no, so make identity */
\r
201 xchr[NOTDEF] = NOTDEF; /* fixed point of mapping */
\r
205 printf("Read %d xchr[] pairs:\n", count);
\r
207 for (k = 0; k < MAXCHRS; k++)
\r
209 if (xchr[k] != NOTDEF)
\r
210 printf("%d => %d\n", k, xchr[k]);
\r
215 char * replacement[MAXCHRS]; /* pointers to replacement strings */
\r
217 void read_repl_sub (FILE * repl_input)
\r
220 char buffer[file_name_size];
\r
221 char charname[128];
\r
225 memset(replacement, 0, MAXCHRS * sizeof(replacement[0]));
\r
227 while (fgets(buffer, file_name_size, repl_input) != NULL)
\r
229 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
\r
232 if ((m = sscanf(buffer, "%d%n %s", &chrs, &n, (char *)&charname)) == 0)
\r
236 if (*charname == '"') /* deal with quoted string "..." */
\r
241 while (*s != '"' && *s != '\0')
\r
242 s++; /* step up to " */
\r
245 continue; /* sanity check */
\r
251 s++; /* is it "" perhaps ? */
\r
254 break; /* no, end of string */
\r
257 *t++ = *s++; /* copy over */
\r
260 *t = '\0'; /* and terminate */
\r
263 if (chrs >= 0 && chrs < MAXCHRS)
\r
264 replacement[chrs] = xstrdup(charname);
\r
266 /* presently the following can never get triggered */
\r
267 /* which is good, because it is perhaps not right ... */
\r
268 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
\r
269 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
\r
270 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
\r
271 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
\r
272 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
\r
273 charname[m] = '\0';
\r
274 if (chrs >= 0 && chrs < MAXCHRS)
\r
275 replacement[chrs] = xstrdup(charname);
\r
278 printf("ERROR: don't understand %s", buffer);
\r
283 puts("Key replacement table");
\r
285 for (k = 0; k < MAXCHRS; k++)
\r
287 if (replacement[k] != NULL)
\r
288 printf("%d\t%s\n", k, replacement[k]);
\r
293 /* Following used both to read xchr[] file and key replacement file */
\r
294 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
\r
295 int read_xchr_file (char *filename, int flag, char *argv[])
\r
298 char infile[file_name_size];
\r
301 if (filename == NULL)
\r
305 printf("Reading xchr/repl %s\n", filename);
\r
307 /* first try using file as specified */
\r
308 strcpy(infile, filename);
\r
311 printf("Trying %s\n", infile);
\r
313 xchr_input = fopen (infile, "r");
\r
315 if (xchr_input == NULL)
\r
317 if (strrchr(infile, '.') == NULL)
\r
320 strcat(infile, ".map");
\r
322 strcat(infile, ".key");
\r
325 printf("Trying %s\n", infile);
\r
327 xchr_input = fopen(infile, "r");
\r
331 if (xchr_input == NULL)
\r
333 strcpy(infile, argv[0]); /* try TeX program path */
\r
335 if ((s = strrchr (infile, '\\')) != NULL)
\r
337 else if ((s = strrchr (infile, '/')) != NULL)
\r
339 else if ((s = strrchr (infile, ':')) != NULL)
\r
342 strcat (infile, filename);
\r
345 printf("Trying %s\n", infile);
\r
347 xchr_input = fopen (infile, "r");
\r
349 if (xchr_input == NULL)
\r
351 if (strchr(infile, '.') == NULL)
\r
354 strcat(infile, ".map");
\r
356 strcat(infile, ".key");
\r
359 printf("Trying %s\n", infile);
\r
361 xchr_input = fopen (infile, "r");
\r
366 if (xchr_input == NULL)
\r
368 strcpy(infile, argv[0]); /* try TeX program path */
\r
370 if ((s = strrchr (infile, '\\')) != NULL)
\r
372 else if ((s = strrchr (infile, '/')) != NULL)
\r
374 else if ((s = strrchr (infile, ':')) != NULL)
\r
377 strcat(infile, "keyboard\\");
\r
378 strcat(infile, filename);
\r
381 printf("Trying %s\n", infile);
\r
383 xchr_input = fopen (infile, "r");
\r
385 if (xchr_input == NULL)
\r
387 if (strchr(infile, '.') == NULL)
\r
390 strcat(infile, ".map");
\r
392 strcat(infile, ".key");
\r
395 printf("Trying %s\n", infile);
\r
397 xchr_input = fopen (infile, "r");
\r
402 /* Note: can't look in TeX source file dir, since that is not known yet */
\r
403 if (xchr_input == NULL)
\r
405 printf("ERROR: Sorry, cannot find %s file %s",
\r
406 flag ? " xchr[]" : "key mapping", filename);
\r
407 perrormod (filename);
\r
412 read_xchr_sub(xchr_input);
\r
414 read_repl_sub(xchr_input);
\r
416 (void) fclose(xchr_input);
\r
421 /* need to also set `key_replace' here based on command line */
\r
422 /* need to also allocate `buffercopy' here and free at end */
\r
423 /* need to call `readreplace' in appropriate place */
\r
425 #define MAXSPLITS 3
\r
427 /* ad hoc default minimum growth in memory realloc is 62% */
\r
428 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
\r
429 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
\r
430 int total_allocated = 0; /* total memory allocated so far */
\r
431 int ini_max_address = 0; /* maximum address when starting */
\r
432 int max_address = 0; /* maximum address seen in allocated memory */
\r
435 void show_maximums (FILE * output)
\r
437 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
\r
438 fputs(log_line, output);
\r
441 /* our own version of realloc --- avoid supposed MicroSoft version bug */
\r
442 /* also tries _expand first, which can avoid address growth ... */
\r
444 #ifdef USEOUREALLOC
\r
445 void * ourrealloc (void * old, size_t new_size)
\r
448 size_t old_size, overlap;
\r
450 /* round up to nearest multiple of four bytes */
\r
451 /* avoid unlikely alignment */
\r
452 if ((new_size % 4) != 0)
\r
453 new_size = ((new_size / 4) + 1) * 4;
\r
456 return malloc (new_size); /* no old block - use malloc */
\r
459 old_size = _msize (old);
\r
461 old_size = malloc_usable_size (old);
\r
464 if (old_size >= new_size && old_size < new_size + 4)
\r
468 mnew = _expand (old, new_size); /* first try and expand in place MSVC */
\r
470 mnew = realloc (old, new_size);
\r
476 printf("EXPANDED! %p (%ld) == %p (%ld)\n",
\r
477 mnew, new_size, old, old_size);
\r
482 /* do this if you want to call the real realloc next - */
\r
483 mnew = realloc (old, new_size);
\r
488 /* we are screwed typically if we ever drop through here - no more space */
\r
489 mnew = malloc (new_size); /* otherwise find new space */
\r
492 return mnew; /* if unable to allocate */
\r
494 if (old_size < new_size)
\r
495 overlap = old_size;
\r
497 overlap = new_size;
\r
499 memcpy (mnew, old, overlap); /* copy old data to new area */
\r
500 free(old); /* free the old area */
\r
506 void memory_error (const char * s, int n)
\r
510 log_printf("\n! Unable to allocate %d bytes for %s\n", n, s);
\r
511 show_maximums(log_file);
\r
514 printf("\n! Unable to allocate %d bytes for %s\n", n, s);
\r
515 show_maximums(stderr);
\r
518 void trace_memory (const char * s, int n)
\r
520 printf("Allocating %d bytes for %s\n", n, s);
\r
523 void update_statistics (long address, int size, int old_size)
\r
525 if (address + size > max_address)
\r
526 max_address = address + size;
\r
528 total_allocated = total_allocated + size - old_size;
\r
531 void probe_memory (void)
\r
533 char * s = (char *) malloc(sizeof(void *));
\r
535 update_statistics ((long) s, 0, 0);
\r
538 void probe_show (void)
\r
541 show_maximums(stdout);
\r
544 size_t roundup (size_t n)
\r
546 if ((n % sizeof(void *)) == 0)
\r
549 return ((n / sizeof(void *)) + 1) * sizeof(void *);
\r
552 #ifdef ALLOCATETRIES
\r
553 /* returns -1 if it fails */
\r
555 int allocate_tries (int trie_max)
\r
559 if (trie_max > 1000000)
\r
560 trie_max = 1000000;
\r
562 nl = (trie_max + 1) * sizeof(halfword);
\r
563 no = (trie_max + 1) * sizeof(halfword);
\r
564 nc = (trie_max + 1) * sizeof(quarterword);
\r
568 trace_memory("hyphen trie", n);
\r
570 trie_trl = (halfword *) malloc(roundup(nl));
\r
571 trie_tro = (halfword *) malloc(roundup(no));
\r
572 trie_trc = (quarterword *) malloc(roundup(nc));
\r
574 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
\r
576 memory_error("hyphen trie", n);
\r
581 printf("Addresses trie_trl %p trie_tro %p trie_trc %p\n", trie_trl, trie_tro, trie_trc);
\r
583 update_statistics((long) trie_trl, nl, 0);
\r
584 update_statistics((long) trie_tro, no, 0);
\r
585 update_statistics((long) trie_trc, nc, 0);
\r
587 trie_size = trie_max;
\r
592 return 0; // success
\r
596 #ifdef ALLOCATEHYPHEN
\r
597 int current_prime = 0; /* remember in case reallocated later */
\r
599 /* we don't return an address here, since TWO memory regions allocated */
\r
600 /* plus, we don't really reallocate, we FLUSH the old information totally */
\r
601 /* returns -1 if it fails */
\r
603 int realloc_hyphen (int hyphen_prime)
\r
607 if (!prime(hyphen_prime))
\r
609 printf("ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
\r
613 /* need not/cannot preserve old contents when hyphen prime is changed */
\r
614 /* if (hyph_list != NULL) free(hyph_list); */
\r
615 /* if (hyph_word != NULL) free(hyph_word); */
\r
616 nw = (hyphen_prime + 1) * sizeof(str_number);
\r
617 nl = (hyphen_prime + 1) * sizeof(halfword);
\r
621 trace_memory("hyphen exception", n);
\r
623 hyph_word = (str_number *) REALLOC (hyph_word, nw);
\r
624 hyph_list = (halfword *) REALLOC (hyph_list, nl);
\r
626 if (hyph_word == NULL || hyph_list == NULL)
\r
628 memory_error("hyphen exception", n);
\r
633 printf("Addresses hyph_word %p hyph_list %p\n", hyph_word, hyph_list);
\r
635 /* cannot preserve old contents when hyphen prime is changed */
\r
637 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
\r
639 for (k = 0; k <= hyphen_prime; k++)
\r
644 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
\r
646 for (k = 0; k <= hyphen_prime; k++)
\r
652 if (current_prime != 0)
\r
654 update_statistics((long) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
\r
655 update_statistics((long) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
\r
659 update_statistics((long) hyph_word, nw, 0);
\r
660 update_statistics((long) hyph_list, nl, 0);
\r
663 current_prime = hyphen_prime;
\r
668 return 0; // success
\r
672 int current_mem_size = 0; /* current total words in main mem allocated -1 */
\r
674 /* this gets called from itex.c when it figures out what mem_top is */
\r
675 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
\r
676 /* initial allocation only, may get expanded later */
\r
677 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
\r
678 /* returns NULL if it fails */
\r
680 #ifdef ALLOCATEMAIN
\r
681 /* initial main memory alloc - mem_top */
\r
682 memory_word * allocate_main_memory (int size)
\r
686 if (main_memory != NULL)
\r
689 puts("Reallocating initial memory allocation");
\r
692 mem_top = mem_bot + size;
\r
694 mem_start = 0; /* bottom of memory allocated by system */
\r
695 mem_min = 0; /* bottom of area made available to TeX */
\r
696 n = (mem_max - mem_start + 1) * sizeof (memory_word);
\r
699 trace_memory("main memory", n);
\r
701 main_memory = (memory_word *) REALLOC (main_memory, n);
\r
703 if (main_memory == NULL)
\r
705 memory_error("initial main memory", n);
\r
710 printf("Address main memory == %p\n", main_memory);
\r
714 if (mem_start != 0 && !is_initex)
\r
715 mem = main_memory - mem_start;
\r
718 printf("Offset address main memory == %p\n", mem);
\r
720 update_statistics((long) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));
\r
721 /* current_mem_size = (mem_max - mem_start + 1); */
\r
722 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
\r
731 #ifdef ALLOCATEMAIN
\r
732 /* int firstallocation = 1; */
\r
734 /* increase main memory allocation at low end and high end */
\r
735 /* called only from tex0.c *//* called with one of lo_size or hi_size == 0 */
\r
736 /* returns NULL if it fails */
\r
738 memory_word * realloc_main (int lo_size, int hi_size)
\r
743 memory_word * new_memory = NULL;
\r
746 printf("WARNING: Entering realloc_main lo %d hi %d\n", lo_size, hi_size);
\r
750 puts("ERROR: Cannot extent main memory in initex");
\r
753 puts("Please use `-m=...' on command line");
\r
759 printf("Old Address %s == %p\n", "main memory", main_memory);
\r
761 /* if we REALLY run up to limit ! */
\r
762 if (current_mem_size + 1 == max_mem_size)
\r
764 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
\r
768 /* first allocation should expand *both* lo and hi */
\r
769 if (hi_size == 0 && mem_end == mem_max)
\r
772 if (lo_size == 0 && mem_start == mem_min)
\r
775 /* try and prevent excessive frequent reallocations */
\r
776 /* while avoiding over allocation by too much */
\r
777 min_size = current_mem_size / 100 * percent_grow;
\r
779 if (lo_size + hi_size < min_size)
\r
781 if (lo_size > 0 && hi_size > 0)
\r
783 lo_size = min_size / 2;
\r
784 hi_size = min_size / 2;
\r
786 else if (lo_size > 0)
\r
787 lo_size = min_size;
\r
788 else if (hi_size > 0)
\r
789 hi_size = min_size;
\r
792 if (lo_size > 0 && lo_size < mem_top / 2)
\r
793 lo_size = mem_top / 2;
\r
795 if (hi_size > 0 && hi_size < mem_top / 2)
\r
796 hi_size = mem_top / 2;
\r
798 for (k = 0; k < MAXSPLITS; k++)
\r
800 new_size = current_mem_size + lo_size + hi_size;
\r
802 if (new_size >= max_mem_size) /* bump against limit - ha ha ha */
\r
804 while (new_size >= max_mem_size)
\r
806 lo_size = lo_size / 2;
\r
807 hi_size = hi_size / 2;
\r
808 new_size = current_mem_size + lo_size + hi_size;
\r
812 n = (new_size + 1) * sizeof (memory_word);
\r
815 trace_memory("main memory", n);
\r
817 new_memory = (memory_word *) REALLOC (main_memory, n);
\r
819 if (new_memory != NULL)
\r
820 break; /* did we get it ? */
\r
822 if (current_mem_size == 0)
\r
823 break; /* in case we ever use for initial */
\r
825 lo_size = lo_size / 2; hi_size = hi_size / 2;
\r
828 if (new_memory == NULL)
\r
830 memory_error("main memory", n);
\r
835 printf("New Address %s == %p\n", "main memory", new_memory);
\r
839 /* shift everything upward to make space for new low area */
\r
841 printf("memmove %p %p %ld \n", new_memory + lo_size,
\r
842 new_memory, (current_mem_size + 1) * sizeof(memory_word));
\r
844 memmove (new_memory + lo_size, new_memory,
\r
845 (current_mem_size + 1) * sizeof(memory_word));
\r
846 /* could reduce words moved by (mem_max - mem_end) */
\r
849 main_memory = new_memory; /* remember for free later */
\r
852 mem_start = mem_start - lo_size; /* update lower limit */
\r
855 mem_max = mem_max + hi_size; /* update upper limit */
\r
857 update_statistics ((long) main_memory, n,
\r
858 (current_mem_size + 1) * sizeof (memory_word));
\r
859 current_mem_size = new_size;
\r
861 if (current_mem_size != mem_max - mem_start)
\r
862 puts("ERROR: Impossible Memory Error");
\r
864 if (mem_start != 0)
\r
865 mem = main_memory - mem_start;
\r
876 #ifdef ALLOCATEFONT
\r
877 int current_font_mem_size = 0;
\r
879 memory_word * realloc_font_info (int size)
\r
881 memory_word * new_font_info = NULL;
\r
887 printf("Old Address %s == %p\n", "font_info", font_info);
\r
889 /* during initial allocation, font_info == NULL - realloc acts like malloc */
\r
890 /* during initial allocation current_font_mem_size == 0 */
\r
891 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
\r
893 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
\r
894 return font_info; /* pass it back to TeX 99/Fabe/4 */
\r
896 /* try and prevent excessive frequent reallocations */
\r
897 /* while avoiding over allocation by too much */
\r
898 /* min_size = current_font_mem_size / 2; */
\r
899 min_size = current_font_mem_size / 100 * percent_grow;
\r
901 if (size < min_size)
\r
904 if (size < initial_font_mem_size)
\r
905 size = initial_font_mem_size;
\r
907 for (k=0; k < MAXSPLITS; k++)
\r
909 new_size = current_font_mem_size + size;
\r
911 if (new_size > font_mem_size)
\r
912 new_size = font_mem_size; /* bump against limit */
\r
914 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
\r
915 n = (new_size + 1) * sizeof (memory_word);
\r
918 trace_memory("font_info", n);
\r
920 new_font_info = (memory_word *) REALLOC (font_info, n);
\r
922 if (new_font_info != NULL)
\r
923 break; /* did we get it ? */
\r
925 if (current_font_mem_size == 0)
\r
926 break; /* initial allocation must work */
\r
931 if (new_font_info == NULL)
\r
933 memory_error("font", n);
\r
934 return font_info; /* try and continue !!! */
\r
937 font_info = new_font_info;
\r
940 printf("New Address %s == %p\n", "font_info", font_info);
\r
942 update_statistics ((long) font_info, n, current_font_mem_size * sizeof(memory_word));
\r
943 current_font_mem_size = new_size;
\r
952 #ifdef ALLOCATESTRING
\r
953 int current_pool_size = 0;
\r
955 packed_ASCII_code * realloc_str_pool (int size)
\r
960 packed_ASCII_code * new_str_pool = NULL;
\r
963 printf("Old Address %s == %p\n", "string pool", str_pool);
\r
965 if (current_pool_size == pool_size)
\r
967 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
\r
969 return str_pool; /* pass it back to TeX 99/Fabe/4 */
\r
972 min_size = current_pool_size / 100 * percent_grow;
\r
974 if (size < min_size)
\r
977 if (size < initial_pool_size)
\r
978 size = initial_pool_size;
\r
980 for (k = 0; k < MAXSPLITS; k++)
\r
982 new_size = current_pool_size + size;
\r
984 if (new_size > pool_size)
\r
985 new_size = pool_size;
\r
986 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
\r
987 n = (new_size + 1) * sizeof (packed_ASCII_code);
\r
990 trace_memory("str_pool", n);
\r
992 new_str_pool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
\r
994 if (new_str_pool != NULL)
\r
995 break; /* did we get it ? */
\r
997 if (current_pool_size == 0)
\r
998 break; /* initial allocation must work */
\r
1000 size = size / 2; /* else can retry smaller */
\r
1003 if (new_str_pool == NULL)
\r
1005 memory_error("string pool", n);
\r
1006 return str_pool; /* try and continue !!! */
\r
1009 str_pool = new_str_pool;
\r
1010 update_statistics ((long) str_pool, n, current_pool_size);
\r
1011 current_pool_size = new_size;
\r
1014 printf("New Address %s == %p\n", "string pool", str_pool);
\r
1023 #ifdef ALLOCATESTRING
\r
1024 int current_max_strings = 0;
\r
1026 pool_pointer * realloc_str_start (int size)
\r
1031 pool_pointer * new_str_start = NULL;
\r
1034 printf("Old Address %s == %p\n", "string start", str_start);
\r
1036 if (current_max_strings == max_strings)
\r
1038 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
\r
1040 return str_start; /* pass it back to TeX 99/Fabe/4 */
\r
1043 min_size = current_max_strings / 100 * percent_grow;
\r
1045 if (size < min_size)
\r
1048 if (size < initial_max_strings)
\r
1049 size = initial_max_strings;
\r
1051 for (k = 0; k < MAXSPLITS; k++)
\r
1053 new_size = current_max_strings + size;
\r
1055 if (new_size > max_strings)
\r
1056 new_size = max_strings;
\r
1057 /* important + 1 since str_start[maxstring + 1] originally */
\r
1058 n = (new_size + 1) * sizeof (pool_pointer);
\r
1061 trace_memory("str_start", n);
\r
1063 new_str_start = (pool_pointer *) REALLOC (str_start, n);
\r
1065 if (new_str_start != NULL)
\r
1066 break; /* did we get it ? */
\r
1068 if (current_max_strings == 0)
\r
1069 break; /* initial allocation must work */
\r
1071 size = size / 2; /* otherwise can try smaller */
\r
1074 if (new_str_start == NULL)
\r
1076 memory_error("string pointer", n);
\r
1077 return str_start; /* try and continue */
\r
1080 str_start = new_str_start;
\r
1081 update_statistics((long) str_start, n, current_max_strings * sizeof (pool_pointer));
\r
1082 current_max_strings = new_size;
\r
1085 printf("New Address %s == %p\n", "string start", str_start);
\r
1094 #ifdef ALLOCATEINI
\r
1095 /* returns -1 if it fails */
\r
1096 /* size == trie_size */
\r
1097 int allocate_ini (int size)
\r
1099 int n, nl, no, nc, nr, nh, nt;
\r
1101 nh = (size + 1) * sizeof(trie_pointer);
\r
1102 nr = (size + 1) * sizeof(trie_pointer);
\r
1103 nl = (size + 1) * sizeof(trie_pointer);
\r
1104 no = (size + 1) * sizeof(trie_op_code);
\r
1105 nc = (size + 1) * sizeof(packed_ASCII_code);
\r
1106 nt = (size + 1) * sizeof(char);
\r
1107 n = nl + no + nc + nr + nh + nt;
\r
1110 trace_memory ("initex hyphen trie", n);
\r
1112 trie_l = (trie_pointer *) malloc (roundup(nl));
\r
1113 trie_o = (trie_op_code *) malloc (roundup(no));
\r
1114 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
\r
1115 trie_r = (trie_pointer *) malloc (roundup(nr));
\r
1116 trie_hash = (trie_pointer *) malloc (roundup(nh));
\r
1117 trie_taken = (char *) malloc (roundup(nt));
\r
1119 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
\r
1120 trie_hash == NULL || trie_taken == NULL)
\r
1122 memory_error("initex hyphen trie", n);
\r
1128 printf("Addresses: trie_l %p trie_o %p trie_c %p\n", trie_l, trie_o, trie_c);
\r
1129 printf("Addresses: trie_r %p trie_hash %p trie_taken %p\n", trie_r, trie_hash, trie_taken);
\r
1132 update_statistics ((long) trie_l, nl, 0);
\r
1133 update_statistics ((long) trie_o, no, 0);
\r
1134 update_statistics ((long) trie_c, nc, 0);
\r
1135 update_statistics ((long) trie_r, nr, 0);
\r
1136 update_statistics ((long) trie_hash, nh, 0);
\r
1137 update_statistics ((long) trie_taken, nt, 0);
\r
1142 return 0; // success
\r
1146 #ifdef ALLOCATESAVESTACK
\r
1147 int current_save_size = 0;
\r
1149 memory_word * realloc_save_stack (int size)
\r
1152 int n = 0, new_size = 0;
\r
1153 memory_word * new_save_stack = NULL;
\r
1156 printf("Old Address %s == %p\n", "save stack", save_stack);
\r
1158 if (current_save_size == save_size)
\r
1160 return save_stack; /* let TeX handle the error */
\r
1163 min_size = current_save_size / 100 * percent_grow;
\r
1165 if (size < min_size)
\r
1168 if (size < initial_save_size)
\r
1169 size = initial_save_size;
\r
1171 for (k = 0; k < MAXSPLITS; k++)
\r
1173 new_size = current_save_size + size;
\r
1175 if (new_size > save_size)
\r
1176 new_size = save_size;
\r
1178 n = (new_size + 1) * sizeof (memory_word);
\r
1181 trace_memory("save_stack", n);
\r
1183 new_save_stack = (memory_word *) REALLOC (save_stack, n);
\r
1185 if (new_save_stack != NULL)
\r
1186 break; /* did we get it ? */
\r
1188 if (current_save_size == 0)
\r
1189 break; /* initial allocation must work */
\r
1191 size = size / 2; /* else can retry smaller */
\r
1194 if (new_save_stack == NULL)
\r
1196 memory_error("save_stack", n);
\r
1197 return save_stack; /* try and continue !!! */
\r
1200 save_stack = new_save_stack;
\r
1201 update_statistics ((long) save_stack, n, current_save_size);
\r
1202 current_save_size = new_size;
\r
1206 printf("Current %s %d\n", "save_size", current_save_size);
\r
1207 printf("New Address %s == %p\n", "save stack", save_stack);
\r
1213 return save_stack;
\r
1217 #ifdef ALLOCATEINPUTSTACK
\r
1218 int current_stack_size = 0; /* input stack size */
\r
1220 in_state_record * realloc_input_stack (int size)
\r
1223 int n = 0, new_size = 0;
\r
1224 in_state_record * new_input_stack = NULL;
\r
1227 printf("Old Address %s == %p\n", "input stack", input_stack);
\r
1229 if (current_stack_size == stack_size)
\r
1231 return input_stack;
\r
1234 min_size = current_stack_size / 100 * percent_grow;
\r
1236 if (size < min_size)
\r
1239 if (size < initial_stack_size)
\r
1240 size = initial_stack_size;
\r
1242 for (k = 0; k < MAXSPLITS; k++)
\r
1244 new_size = current_stack_size + size;
\r
1246 if (new_size > stack_size)
\r
1247 new_size = stack_size;
\r
1249 n = (new_size + 1) * sizeof(in_state_record);
\r
1252 trace_memory("input_stack", n);
\r
1254 new_input_stack = (in_state_record *) REALLOC (input_stack, n);
\r
1256 if (new_input_stack != NULL)
\r
1257 break; /* did we get it ? */
\r
1259 if (current_stack_size == 0)
\r
1260 break; /* initial allocation must work */
\r
1262 size = size / 2; /* else can retry smaller */
\r
1265 if (new_input_stack == NULL)
\r
1267 memory_error("input stack", n);
\r
1268 return input_stack; /* try and continue !!! */
\r
1271 input_stack = new_input_stack;
\r
1272 update_statistics ((long) input_stack, n, current_stack_size);
\r
1273 current_stack_size = new_size;
\r
1277 printf("Current %s %d\n", "stack_size", current_stack_size);
\r
1278 printf("New Address %s == %p\n", "input stack", input_stack);
\r
1284 return input_stack;
\r
1288 #ifdef ALLOCATENESTSTACK
\r
1289 int current_nest_size = 0; /* current nest size */
\r
1291 list_state_record * realloc_nest_stack (int size)
\r
1294 int n = 0, new_size = 0;
\r
1295 list_state_record * new_nest = NULL;
\r
1298 printf("Old Address %s == %p\n", "nest stack", nest);
\r
1300 if (current_nest_size == nest_size)
\r
1305 min_size = current_nest_size / 100 * percent_grow;
\r
1307 if (size < min_size)
\r
1310 if (size < initial_nest_size)
\r
1311 size = initial_nest_size;
\r
1313 for (k = 0; k < MAXSPLITS; k++)
\r
1315 new_size = current_nest_size + size;
\r
1317 if (new_size > nest_size)
\r
1318 new_size = nest_size;
\r
1320 n = (new_size + 1) * sizeof (list_state_record);
\r
1323 trace_memory("nest stack", n);
\r
1325 new_nest = (list_state_record *) REALLOC (nest, n);
\r
1327 if (new_nest != NULL)
\r
1328 break; /* did we get it ? */
\r
1330 if (current_nest_size == 0)
\r
1331 break; /* initial allocation must work */
\r
1333 size = size / 2; /* else can retry smaller */
\r
1336 if (new_nest == NULL)
\r
1338 memory_error("nest stack", n);
\r
1339 return nest; /* try and continue !!! */
\r
1343 update_statistics ((long) nest, n, current_nest_size);
\r
1344 current_nest_size = new_size;
\r
1348 printf("Current %s %d\n", "nest_size", current_nest_size);
\r
1349 printf("New Address %s == %p\n", "nest stack", nest);
\r
1359 #ifdef ALLOCATEPARAMSTACK
\r
1360 int current_param_size = 0;
\r
1362 halfword * realloc_param_stack (int size)
\r
1365 int n = 0, new_size = 0;
\r
1366 halfword * new_param = NULL;
\r
1369 printf("Old Address %s == %p\n", "param stack", param_stack);
\r
1371 if (current_param_size == param_size)
\r
1373 return param_stack;
\r
1376 min_size = current_param_size / 100 * percent_grow;
\r
1378 if (size < min_size)
\r
1381 if (size < initial_param_size)
\r
1382 size = initial_param_size;
\r
1384 for (k = 0; k < MAXSPLITS; k++)
\r
1386 new_size = current_param_size + size;
\r
1388 if (new_size > param_size)
\r
1389 new_size = param_size;
\r
1391 n = (new_size + 1) * sizeof(pointer);
\r
1394 trace_memory("param stack", n);
\r
1396 new_param = (pointer *) REALLOC (param_stack, n);
\r
1398 if (new_param != NULL)
\r
1399 break; /* did we get it ? */
\r
1401 if (current_param_size == 0)
\r
1402 break; /* initial allocation must work */
\r
1404 size = size / 2; /* else can retry smaller */
\r
1407 if (new_param == NULL)
\r
1409 memory_error("param stack", n);
\r
1410 return param_stack; /* try and continue !!! */
\r
1413 param_stack = new_param;
\r
1414 update_statistics((long) param_stack, n, current_param_size);
\r
1415 current_param_size = new_size;
\r
1419 printf("Current %s %d\n", "param_size", current_param_size);
\r
1420 printf("New Address %s == %p\n", "param stack", param_stack);
\r
1426 return param_stack;
\r
1430 #ifdef ALLOCATEBUFFER
\r
1431 int current_buf_size = 0;
\r
1433 ASCII_code * realloc_buffer (int size)
\r
1436 int n = 0, new_size = 0;
\r
1437 ASCII_code * new_buffer = NULL;
\r
1440 printf("Old Address %s == %p\n", "buffer", buffer);
\r
1442 if (current_buf_size == buf_size)
\r
1447 min_size = current_buf_size / 100 * percent_grow;
\r
1449 if (size < min_size)
\r
1452 if (size < initial_buf_size)
\r
1453 size = initial_buf_size;
\r
1455 for (k = 0; k < MAXSPLITS; k++)
\r
1457 new_size = current_buf_size + size;
\r
1459 if (new_size > buf_size)
\r
1460 new_size = buf_size;
\r
1462 n = (new_size + 1) * sizeof(ASCII_code);
\r
1465 trace_memory("buffer", n);
\r
1467 new_buffer = (ASCII_code *) REALLOC (buffer, n);
\r
1469 if (new_buffer != NULL)
\r
1470 break; /* did we get it ? */
\r
1472 if (current_buf_size == 0)
\r
1473 break; /* initial allocation must work */
\r
1478 if (new_buffer == NULL)
\r
1480 memory_error("buffer", n);
\r
1481 return buffer; /* try and continue !!! */
\r
1484 buffer = new_buffer;
\r
1485 update_statistics ((long) buffer, n, current_buf_size);
\r
1488 memset(buffer + current_buf_size, 0, new_size - current_buf_size);
\r
1490 for (k = current_buf_size; k < new_size; k++)
\r
1494 current_buf_size = new_size;
\r
1498 printf("Current %s %d\n", "buffer", current_buf_size);
\r
1499 printf("New Address %s == %p\n", "buffer", buffer);
\r
1509 /* here is the main memory allocation routine -- calls the above */
\r
1510 /* returns -1 if it fails */
\r
1511 /* allocate rather than static 93/Nov/26 */
\r
1512 int allocate_memory (void)
\r
1514 #ifdef ALLOCATEINPUTSTACK
\r
1515 input_stack = NULL;
\r
1516 current_stack_size = 0;
\r
1517 input_stack = realloc_input_stack(initial_stack_size);
\r
1520 #ifdef ALLOCATENESTSTACK
\r
1522 current_nest_size = 0;
\r
1523 nest = realloc_nest_stack(initial_nest_size);
\r
1526 #ifdef ALLOCATEPARAMSTACK
\r
1527 param_stack = NULL;
\r
1528 current_param_size = 0;
\r
1529 param_stack = realloc_param_stack(initial_param_size);
\r
1532 #ifdef ALLOCATESAVESTACK
\r
1533 save_stack = NULL;
\r
1534 current_save_size = 0;
\r
1535 save_stack = realloc_save_stack (initial_save_size);
\r
1539 buffer = NULL; /* need to do earlier */
\r
1540 current_buf_size = 0;
\r
1541 buffer = realloc_buffer (initial_buf_size);
\r
1544 #ifdef ALLOCATESTRING
\r
1546 current_pool_size = 0;
\r
1548 current_max_strings = 0;
\r
1550 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
\r
1554 puts("ini TeX pool and string allocation");
\r
1556 str_pool = realloc_str_pool(initial_pool_size);
\r
1557 str_start = realloc_str_start(initial_max_strings);
\r
1561 /* the following can save a lot of the usual 800k fixed allocation */
\r
1562 #ifdef ALLOCATEFONT
\r
1564 current_font_mem_size = 0;
\r
1565 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
\r
1566 /* if ini-TeX we need to do it here - no format file read later */
\r
1568 font_info = realloc_font_info(initial_font_mem_size);
\r
1571 #ifdef ALLOCATEMAIN
\r
1572 main_memory = NULL;
\r
1574 mem_min = mem_bot; /* just to avoid complaints in texbody */
\r
1575 mem_top = mem_initex;
\r
1576 mem_max = mem_top;
\r
1577 /* allocate main memory here if this is iniTeX */
\r
1578 /* otherwise wait for format undumping in itex.c ... */
\r
1581 /* avoid this if format specified on command line ??? */
\r
1582 mem = allocate_main_memory(mem_initex); /* made variable ! */
\r
1589 /* now for the hyphenation exception stuff */
\r
1590 #ifdef ALLOCATEHYPHEN
\r
1593 /* this will be overridden later by what is in format file */
\r
1594 hyphen_prime = default_hyphen_prime;
\r
1595 /* non ini-TeX use assumes format will be read and that specifies size */
\r
1598 if (new_hyphen_prime)
\r
1599 hyphen_prime = new_hyphen_prime;
\r
1601 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
\r
1606 /* now for memory for the part of the hyphenation stuff that always needed */
\r
1607 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
\r
1608 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
\r
1609 #ifdef ALLOCATETRIES
\r
1612 if (allocate_tries (trie_size))
\r
1617 /* now for memory for hyphenation stuff needed only when running iniTeX */
\r
1618 #ifdef ALLOCATEINI
\r
1621 if (allocate_ini(trie_size))
\r
1631 trie_taken = NULL;
\r
1635 return 0; // success
\r
1638 /* returns non-zero if error - done to test integrity of stack mostly */
\r
1639 int free_memory (void)
\r
1641 unsigned int heap_total = 0;
\r
1644 puts("free_memory ");
\r
1646 if (verbose_flag || trace_flag)
\r
1647 show_maximums(stdout);
\r
1651 printf("Heap total: %u bytes --- max address %u\n",
\r
1652 heap_total, max_address);
\r
1653 printf("Main Memory: variable node %lld (%lld - %d);\n"
\r
1654 " one word %d (%d - %d)\n",
\r
1655 lo_mem_max - mem_min, mem_min, lo_mem_max,
\r
1656 mem_end - hi_mem_min, hi_mem_min, mem_end);
\r
1657 puts("Freeing memory again");
\r
1660 /* only free memory if safe ... additional check */
\r
1661 #ifdef ALLOCATEINI
\r
1664 if (trie_taken != NULL)
\r
1667 if (trie_hash != NULL)
\r
1670 if (trie_r != NULL)
\r
1673 if (trie_c != NULL)
\r
1676 if (trie_o != NULL)
\r
1679 if (trie_l != NULL)
\r
1682 trie_taken = NULL;
\r
1691 #ifdef ALLOCATETRIES
\r
1692 if (trie_trc != NULL)
\r
1695 if (trie_tro != NULL)
\r
1698 if (trie_trl != NULL)
\r
1706 #ifdef ALLOCATEHYPHEN
\r
1707 if (hyph_list != NULL)
\r
1710 if (hyph_word != NULL)
\r
1717 #ifdef ALLOCATEMAIN
\r
1718 if (main_memory != NULL)
\r
1719 free(main_memory);
\r
1721 main_memory = NULL;
\r
1724 #ifdef ALLOCATEFONT
\r
1725 if (font_info != NULL)
\r
1731 #ifdef ALLOCATESTRING
\r
1732 if (str_start != NULL)
\r
1735 if (str_pool != NULL)
\r
1742 #ifdef ALLOCATEPARAMSTACK
\r
1743 if (param_stack != NULL)
\r
1744 free(param_stack);
\r
1746 param_stack = NULL;
\r
1749 #ifdef ALLOCATENESTSTACK
\r
1756 #ifdef ALLOCATEINPUTSTACK
\r
1757 if (input_stack != NULL)
\r
1758 free(input_stack);
\r
1760 input_stack = NULL;
\r
1763 #ifdef ALLOCATESAVESTACK
\r
1764 if (save_stack != NULL)
\r
1767 save_stack = NULL;
\r
1770 if (format_file != NULL)
\r
1771 free(format_file);
\r
1773 if (source_direct != NULL)
\r
1774 free(source_direct);
\r
1776 format_file = NULL;
\r
1777 source_direct = NULL;
\r
1779 if (dvi_file_name != NULL)
\r
1780 free(dvi_file_name);
\r
1782 if (log_file_name != NULL)
\r
1783 free(log_file_name);
\r
1785 if (pdf_file_name != NULL)
\r
1786 free(pdf_file_name);
\r
1788 pdf_file_name = NULL;
\r
1789 log_file_name = NULL;
\r
1790 dvi_file_name = NULL;
\r
1795 boolean prime (int x)
\r
1798 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
\r
1803 for (k = 3; k < x; k = k + 2)
\r
1817 boolean show_use = false;
\r
1819 void complainarg (int c, char *s)
\r
1821 printf("ERROR: Do not understand `%c' argument value `%s'\n", c, s);
\r
1825 /* following is list of allowed command line flags and args */
\r
1827 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
\r
1829 void reorderargs (int ac, char **av)
\r
1833 char takeargs[256]; /* large enough for all command line arg chars */
\r
1837 return; /* no args ! */
\r
1841 t = takeargs; /* list of those that take args */
\r
1843 while (*s != '\0' && *(s + 1) != '\0')
\r
1845 if (*(s + 1) == '=')
\r
1846 *t++ = *s++; /* copy over --- without the = */
\r
1855 show_line(takeargs, 0);
\r
1863 if (*av[n] != '-')
\r
1866 if (n + 1 < ac && *(av[n] + 2) == '\0' &&
\r
1867 strchr(takeargs, *(av[n] + 1)) != NULL)
\r
1868 n += 2; /* step over it */
\r
1883 while (m < ac && *av[m] != '-')
\r
1884 m++; /* first command */
\r
1888 /* does it take an argument ? and is this argument next ? */
\r
1889 /* check first whether the `-x' is isolated, or arg follows directly */
\r
1890 /* then check whether this is one of those that takes an argument */
\r
1891 if (m+1 < ac && *(av[m] + 2) == '\0' &&
\r
1892 strchr(takeargs, *(av[m] + 1)) != NULL)
\r
1894 s = av[m]; /* move command down before non-command */
\r
1897 for (; m > n; m--)
\r
1898 av[m + 1] = av[m - 1];
\r
1902 n += 2; /* step over moved args */
\r
1906 s = av[m]; /* move command down before non-command */
\r
1908 for (; m > n; m--)
\r
1909 av[m] = av[m - 1];
\r
1912 n++; /* step over moved args */
\r
1917 int test_align (long address, int size, const char *str)
\r
1921 if (size > sizeof(void *))
\r
1922 n = address % sizeof(void *);
\r
1924 n = address % size;
\r
1927 printf("OFFSET %d (ELEMENT %d) in %s\n", n, size, str);
\r
1932 /* activate detailed checking of alignment when trace_flag is set */
\r
1934 void check_fixed_align (int flag)
\r
1938 if (test_align ((long) &mem_top, 4, "FIXED ALIGNMENT"))
\r
1940 puts("PLEASE RECOMPILE ME!");
\r
1943 #ifdef CHECKALIGNMENT
\r
1947 test_align ((long) &mem_top, 4, "mem_top");
\r
1948 test_align ((long) &mem_max, 4, "mem_max");
\r
1949 test_align ((long) &mem_min, 4, "mem_min");
\r
1950 test_align ((long) &bad, 4, "bad");
\r
1951 test_align ((long) &trie_size, 4, "trie_size");
\r
1952 test_align ((long) &xord, sizeof(xord[0]), "xord");
\r
1953 test_align ((long) &xchr, sizeof(xchr[0]), "xchr");
\r
1954 test_align ((long) &name_length, 4, "name_length");
\r
1955 test_align ((long) &first, 4, "first");
\r
1956 test_align ((long) &last, 4, "last");
\r
1957 test_align ((long) &max_buf_stack, 4, "max_buf_stack");
\r
1958 test_align ((long) &pool_ptr, 4, "pool_ptr");
\r
1959 test_align ((long) &str_ptr, 4, "str_ptr");
\r
1960 test_align ((long) &init_pool_ptr, 4, "init_pool_ptr");
\r
1961 test_align ((long) &init_str_ptr, 4, "init_str_ptr");
\r
1962 test_align ((long) &log_file, 4, "log_file");
\r
1963 test_align ((long) &tally, 4, "tally");
\r
1964 test_align ((long) &term_offset, 4, "term_offset");
\r
1965 test_align ((long) &file_offset, 4, "file_offset");
\r
1966 test_align ((long) &trick_count, 4, "trick_count");
\r
1967 test_align ((long) &first_count, 4, "first_count");
\r
1968 test_align ((long) &deletions_allowed, 4, "deletions_allowed");
\r
1969 test_align ((long) &set_box_allowed, 4, "set_box_allowed");
\r
1970 test_align ((long) &help_line, sizeof(help_line[0]), "help_line");
\r
1971 test_align ((long) &use_err_help, 4, "use_err_help");
\r
1972 test_align ((long) &interrupt, 4, "interrupt");
\r
1973 test_align ((long) &OK_to_interrupt, 4, "OK_to_interrupt");
\r
1974 test_align ((long) &arith_error, 4, "arith_error");
\r
1975 test_align ((long) &tex_remainder, 4, "tex_remainder");
\r
1976 test_align ((long) &temp_ptr, 4, "temp_ptr");
\r
1977 test_align ((long) &lo_mem_max, 4, "lo_mem_max");
\r
1978 test_align ((long) &hi_mem_min, 4, "hi_mem_min");
\r
1979 test_align ((long) &var_used, 4, "var_used");
\r
1980 test_align ((long) &dyn_used, 4, "dyn_used");
\r
1981 test_align ((long) &avail, 4, "avail");
\r
1982 test_align ((long) &mem_end, 4, "mem_end");
\r
1983 test_align ((long) &mem_start, 4, "mem_start");
\r
1984 test_align ((long) &rover, 4, "rover");
\r
1985 test_align ((long) &font_in_short_display, 4, "font_in_short_display");
\r
1986 test_align ((long) &depth_threshold, 4, "depth_threshold");
\r
1987 test_align ((long) &breadth_max, 4, "breadth_max");
\r
1988 test_align ((long) &nest, sizeof(nest[0]), "nest");
\r
1989 // test_align ((long) &xeq_level, sizeof(xeq_level[0]), "xeq_level");
\r
1990 test_align ((long) &zzzad, sizeof(zzzad[0]), "zzzad");
\r
1991 // test_align ((long) &hash, sizeof(hash[0]), "hash");
\r
1992 test_align ((long) &zzzae, sizeof(zzzae[0]), "zzzae");
\r
1993 test_align ((long) &save_stack, sizeof(save_stack[0]), "save_stack");
\r
1994 test_align ((long) &input_stack, sizeof(input_stack[0]), "input_stack");
\r
1995 test_align ((long) &input_file, sizeof(input_file[0]), "input_file");
\r
1996 test_align ((long) &line_stack, sizeof(line_stack[0]), "line_stack");
\r
1997 test_align ((long) ¶m_stack, sizeof(param_stack[0]), "param_stack");
\r
1998 test_align ((long) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
\r
1999 test_align ((long) &pstack, sizeof(pstack[0]), "pstack");
\r
2000 test_align ((long) &read_file, sizeof(read_file[0]), "read_file");
\r
2001 test_align ((long) &font_check, sizeof(font_check[0]), "font_check");
\r
2002 test_align ((long) &font_size, sizeof(font_size[0]), "font_size");
\r
2003 test_align ((long) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
\r
2004 test_align ((long) &font_params, sizeof(font_params[0]), "font_params");
\r
2005 test_align ((long) &font_name, sizeof(font_name[0]), "font_name");
\r
2006 test_align ((long) &font_area, sizeof(font_area[0]), "font_area");
\r
2007 test_align ((long) &font_bc, sizeof(font_bc[0]), "font_bc");
\r
2008 test_align ((long) &font_ec, sizeof(font_ec[0]), "font_ec");
\r
2009 test_align ((long) &font_glue, sizeof(font_glue[0]), "font_glue");
\r
2010 test_align ((long) &font_used, sizeof(font_used[0]), "font_used");
\r
2011 test_align ((long) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
\r
2012 test_align ((long) &skew_char, sizeof(skew_char[0]), "skew_char");
\r
2013 test_align ((long) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
\r
2014 test_align ((long) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
\r
2015 test_align ((long) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
\r
2016 test_align ((long) &char_base, sizeof(char_base[0]), "char_base");
\r
2017 test_align ((long) &width_base, sizeof(width_base[0]), "width_base");
\r
2018 test_align ((long) &height_base, sizeof(height_base[0]), "height_base");
\r
2019 test_align ((long) &depth_base, sizeof(depth_base[0]), "depth_base");
\r
2020 test_align ((long) &italic_base, sizeof(italic_base[0]), "italic_base");
\r
2021 test_align ((long) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
\r
2022 test_align ((long) &kern_base, sizeof(kern_base[0]), "kern_base");
\r
2023 test_align ((long) &exten_base, sizeof(exten_base[0]), "exten_base");
\r
2024 test_align ((long) ¶m_base, sizeof(param_base[0]), "param_base");
\r
2025 test_align ((long) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
\r
2026 test_align ((long) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
\r
2027 test_align ((long) &active_width, sizeof(active_width[0]), "active_width");
\r
2028 test_align ((long) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
\r
2029 test_align ((long) &background, sizeof(background[0]), "background");
\r
2030 test_align ((long) &break_width, sizeof(break_width[0]), "break_width");
\r
2031 test_align ((long) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
\r
2032 test_align ((long) &best_place, sizeof(best_place[0]), "best_place");
\r
2033 test_align ((long) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
\r
2034 test_align ((long) &hc, sizeof(hc[0]), "hc");
\r
2035 test_align ((long) &hu, sizeof(hu[0]), "hu");
\r
2036 test_align ((long) &hyf, sizeof(hyf[0]), "hyf");
\r
2037 // test_align ((long) &x, sizeof(x[0]), "x");
\r
2038 test_align ((long) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
\r
2039 test_align ((long) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
\r
2040 test_align ((long) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
\r
2041 test_align ((long) &op_start, sizeof(op_start[0]), "op_start");
\r
2042 // test_align ((long) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash");
\r
2043 test_align ((long) &trie_used, sizeof(trie_used[0]), "trie_used");
\r
2044 /* test_align ((long) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
\r
2045 test_align ((long) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
\r
2046 test_align ((long) &trie_min, sizeof(trie_min[0]), "trie_min");
\r
2047 test_align ((long) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
\r
2048 test_align ((long) &write_file, sizeof(write_file[0]), "write_file");
\r
2049 test_align ((long) &write_open, sizeof(write_open[0]), "write_open");
\r
2053 void check_alloc_align (int flag)
\r
2057 if (test_align((long) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
\r
2058 puts("PLEASE RECOMPILE ME!");
\r
2060 #ifdef CHECKALIGNMENT
\r
2064 #ifndef ALLOCZEQTB
\r
2065 test_align ((long) eqtb, sizeof(eqtb[0]), "eqtb");
\r
2068 test_align ((long) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
\r
2069 test_align ((long) str_start, sizeof(str_start[0]), "str_start");
\r
2070 test_align ((long) mem, sizeof(mem[0]), "main memory");
\r
2071 test_align ((long) font_info, sizeof(font_info[0]), "font memory");
\r
2072 test_align ((long) trie_trl, sizeof(trie_trl[0]), "trie_trl");
\r
2073 test_align ((long) trie_tro, sizeof(trie_tro[0]), "trie_tro");
\r
2074 test_align ((long) trie_trc, sizeof(trie_trc[0]), "trie_trc");
\r
2075 test_align ((long) hyph_word, sizeof(hyph_word[0]), "hyph_word");
\r
2076 test_align ((long) hyph_list, sizeof(hyph_list[0]), "hyph_list");
\r
2077 /* test_align ((long) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
\r
2078 test_align ((long) trie_o, sizeof(trie_o[0]), "trie_o");
\r
2079 test_align ((long) trie_l, sizeof(trie_l[0]), "trie_l");
\r
2080 test_align ((long) trie_r, sizeof(trie_r[0]), "trie_r");
\r
2081 test_align ((long) trie_hash, sizeof(trie_hash[0]), "trie_hash");
\r
2082 test_align ((long) trie_taken, sizeof(trie_taken[0]), "trie_taken");
\r
2086 boolean shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
\r
2088 /* cache to prevent allocating twice in a row */
\r
2090 char * lastname = NULL;
\r
2091 char * lastvalue = NULL;
\r
2093 /* returns allocated string -- these strings are not freed again */
\r
2094 /* is it safe to do that now ? 98/Jan/31 */
\r
2095 char * grabenv (const char * varname)
\r
2099 if (varname == NULL)
\r
2102 if (*varname == '\0')
\r
2105 if (lastname != NULL && strcasecmp(lastname, varname) == 0)
\r
2108 printf("Cache hit: %s=%s\n", lastname, lastvalue);
\r
2110 return xstrdup(lastvalue);
\r
2113 s = getenv(varname);
\r
2117 if (lastname != NULL)
\r
2120 lastname = xstrdup(varname);
\r
2122 if (lastvalue != NULL)
\r
2125 lastvalue = xstrdup(s);
\r
2127 return xstrdup(s);
\r
2133 void flush_trailing_slash (char * directory)
\r
2137 if (strcmp(directory, "") != 0)
\r
2139 s = directory + strlen(directory) - 1;
\r
2141 if (*s == '\\' || *s == '/')
\r
2146 void knuthify (void)
\r
2148 restrict_to_ascii = false; /* don't complain non ASCII */
\r
2149 allow_patterns = false; /* don't allow pattern redefinition */
\r
2150 show_in_hex = true; /* show character code in hex */
\r
2151 show_numeric = false; /* don't show character code decimal */
\r
2152 show_missing = false; /* don't show missing characters */
\r
2153 civilize_flag = false; /* don't reorder date fields */
\r
2154 c_style_flag = false; /* don't add file name to error msg */
\r
2155 show_fmt_flag = false; /* don't show format file in log */
\r
2156 show_tfm_flag = false; /* don't show metric file in log */
\r
2157 tab_step = 0; /* tab's size of width */
\r
2158 show_line_break_stats = false; /* do not show line break stats */
\r
2159 show_fonts_used = false;
\r
2160 default_rule = 26214; /* revert to default rule thickness */
\r
2161 pseudo_tilde = false;
\r
2162 pseudo_space = false;
\r
2163 truncate_long_lines = false;
\r
2164 allow_quoted_names = false;
\r
2165 show_cs_names = false;
\r
2166 ignore_frozen = false;
\r
2167 suppress_f_ligs = false;
\r
2168 full_file_name_flag = false;
\r
2169 knuth_flag = true; /* so other code can know about this */
\r
2172 /* following made global so analyze_flag can be made separate procedure */
\r
2174 char * xchr_file = NULL;
\r
2175 char * repl_file = NULL;
\r
2177 const char * short_options = "m:e:h:0:H:g:P:o:l:a:r:kwvpiKLZMd2t?u";
\r
2179 static struct option long_options[] =
\r
2181 {"main-memory", required_argument, NULL, 'm'},
\r
2182 {"hyph-size", required_argument, NULL, 'e'},
\r
2183 {"trie-size", required_argument, NULL, 'h'},
\r
2184 {"backend", required_argument, NULL, '0'},
\r
2185 {"tab-step", required_argument, NULL, 'H'},
\r
2186 {"percent-grow", required_argument, NULL, 'g'},
\r
2187 {"default-rule", required_argument, NULL, 'P'},
\r
2188 {"dvi-dir", required_argument, NULL, 'o'},
\r
2189 {"log-dir", required_argument, NULL, 'l'},
\r
2190 {"aux-dir", required_argument, NULL, 'a'},
\r
2191 {"key-file", required_argument, NULL, 'k'},
\r
2192 {"jobname", required_argument, NULL, 'r'},
\r
2193 {"showhex", no_argument, NULL, 'w'},
\r
2194 {"verbose", no_argument, NULL, 'v'},
\r
2195 {"patterns", no_argument, NULL, 'p'},
\r
2196 {"initex", no_argument, NULL, 'i'},
\r
2197 {"knuthify", no_argument, NULL, 'K'},
\r
2198 {"cstyle", no_argument, NULL, 'L'},
\r
2199 {"showtfm", no_argument, NULL, 'Z'},
\r
2200 {"showmissing", no_argument, NULL, 'M'},
\r
2201 {"deslash", no_argument, NULL, 'd'},
\r
2202 {"suppressflig", no_argument, NULL, '2'},
\r
2203 {"trace", no_argument, NULL, 't'},
\r
2204 {"help", no_argument, NULL, '?'},
\r
2205 {"usage", no_argument, NULL, 'u'},
\r
2209 int analyze_flag (int c, char * optarg)
\r
2214 c_job_name = optarg;
\r
2217 verbose_flag = true;
\r
2223 interaction = batch_mode;
\r
2226 interaction = nonstop_mode;
\r
2229 interaction = scroll_mode;
\r
2232 interaction = error_stop_mode;
\r
2238 c_style_flag = true;
\r
2241 show_tfm_flag = true;
\r
2244 show_missing = false;
\r
2250 allow_patterns = true;
\r
2253 show_in_hex = true;
\r
2256 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
\r
2259 show_fonts_used = false;
\r
2262 shorten_file_name = true;
\r
2265 show_cs_names = true;
\r
2268 ignore_frozen = true;
\r
2271 show_line_break_stats = false; /* 96/Feb/8 */
\r
2274 show_fmt_flag = false; /* 94/Jun/21 */
\r
2277 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
\r
2280 full_file_name_flag = false; // 00 Jun 18
\r
2283 trace_flag = true;
\r
2285 /* The following are really obscure and should not be advertized */
\r
2287 show_current = false;
\r
2290 show_numeric = false;
\r
2293 civilize_flag = false;
\r
2296 open_trace_flag = true;
\r
2299 reorder_arg_flag = false; /* local */
\r
2304 mem_initex = mem_top;
\r
2306 mem_initex = atoi(optarg) * 1024;
\r
2308 if (mem_initex == 0)
\r
2309 complainarg(c, optarg);
\r
2311 mem_spec_flag = true;
\r
2314 #ifdef VARIABLETRIESIZE
\r
2318 //trie_size = atoi(kpse_var_value("trie_size"));
\r
2319 trie_size = default_trie_size;
\r
2322 trie_size = atoi(optarg);
\r
2324 if (trie_size == 0)
\r
2325 complainarg(c, optarg);
\r
2329 #ifdef ALLOCATEHYPHEN
\r
2332 new_hyphen_prime = hyphen_prime * 2;
\r
2334 new_hyphen_prime = atoi(optarg);
\r
2336 if (new_hyphen_prime == 0)
\r
2337 complainarg(c, optarg);
\r
2343 percent_grow = 62;
\r
2345 percent_grow = atoi(optarg);
\r
2347 if (percent_grow == 0)
\r
2348 complainarg(c, optarg);
\r
2356 pseudo_tilde = atoi(optarg);
\r
2358 if (pseudo_tilde > 255)
\r
2359 pseudo_tilde = 255;
\r
2360 else if (pseudo_tilde < 128)
\r
2361 pseudo_tilde = 128;
\r
2369 tab_step = atoi(optarg);
\r
2370 if (tab_step == 0)
\r
2371 complainarg(c, optarg);
\r
2376 xchr_file = xstrdup("xchr.map");
\r
2378 xchr_file = xstrdup(optarg);
\r
2380 if (xchr_file == NULL || *xchr_file == '\0')
\r
2381 complainarg(c, optarg);
\r
2386 repl_file = xstrdup("repl.key");
\r
2388 repl_file = xstrdup(optarg);
\r
2390 if (repl_file == NULL || *repl_file == '\0')
\r
2391 complainarg(c, optarg);
\r
2396 default_rule = 26214;
\r
2398 default_rule = atoi(optarg);
\r
2400 if (default_rule == 0)
\r
2401 complainarg(c, optarg);
\r
2408 complainarg(c, optarg);
\r
2413 dvi_directory = "";
\r
2415 dvi_directory = xstrdup(optarg);
\r
2417 if (strcmp(dvi_directory, "") == 0)
\r
2418 complainarg(c, optarg);
\r
2424 log_directory = "";
\r
2426 log_directory = xstrdup(optarg);
\r
2428 if (strcmp(log_directory, "") == 0)
\r
2429 complainarg(c, optarg);
\r
2435 aux_directory = "";
\r
2437 aux_directory = xstrdup(optarg);
\r
2439 if (strcmp(aux_directory, "") == 0)
\r
2440 complainarg(c, optarg);
\r
2454 void strip_name (char *pathname)
\r
2458 if ((s = strrchr(pathname, '\\')) != NULL)
\r
2460 else if ((s = strrchr(pathname, '/')) != NULL)
\r
2462 else if ((s = strrchr(pathname, ':')) != NULL)
\r
2470 int read_command_line (int ac, char **av)
\r
2474 int option_idx = 0;
\r
2479 while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)
\r
2481 if (optarg != 0 && *optarg == '=')
\r
2482 optargnew = optarg + 1;
\r
2484 optargnew = optarg;
\r
2486 analyze_flag(c, optargnew);
\r
2491 stamp_it(log_line);
\r
2492 strcat(log_line, "\n");
\r
2493 show_line(log_line, 0);
\r
2495 return -1; // failure
\r
2498 if (repl_file != NULL && *repl_file != '\0')
\r
2500 if (read_xchr_file(repl_file, 1, av))
\r
2503 puts("KEY REPLACE ON");
\r
2505 key_replace = true;
\r
2509 if (xchr_file != NULL && *xchr_file != '\0')
\r
2511 if (read_xchr_file(xchr_file, 0, av))
\r
2514 puts("NON ASCII ON");
\r
2523 int init_commands (int ac, char **av)
\r
2525 is_initex = false;
\r
2526 allow_patterns = false;
\r
2527 reset_exceptions = false;
\r
2528 non_ascii = false;
\r
2529 key_replace = false;
\r
2530 open_trace_flag = false;
\r
2531 trace_flag = false;
\r
2532 verbose_flag = false;
\r
2533 restrict_to_ascii = false;
\r
2534 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
\r
2535 return_flag = true; // hard wired now
\r
2536 trimeof = true; // hard wired now
\r
2538 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
\r
2539 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
\r
2540 default_rule = 26214;
\r
2541 show_current = true;
\r
2542 civilize_flag = true;
\r
2543 show_numeric = true;
\r
2544 show_missing = true;
\r
2545 c_style_flag = false;
\r
2546 show_fmt_flag = true;
\r
2547 show_tfm_flag = false; /* don't show metric file in log */
\r
2548 shorten_file_name = false; /* don't shorten file names to 8+3 */
\r
2549 truncate_long_lines = true; /* truncate long lines */
\r
2550 tab_step = 0; /* do not replace tabs with spaces */
\r
2551 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
\r
2552 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
\r
2553 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
\r
2554 show_cs_names = false;
\r
2555 knuth_flag = false;
\r
2556 full_file_name_flag = true; /* new default 2000 June 18 */
\r
2557 errout = stdout; /* as opposed to stderr say --- used ??? */
\r
2558 new_hyphen_prime = 0;
\r
2560 #ifdef VARIABLETRIESIZE
\r
2561 // trie_size = default_trie_size;
\r
2565 mem_extra_high = 0;
\r
2566 mem_extra_low = 0;
\r
2568 format_name = "plain";
\r
2570 if (read_command_line(ac, av) < 0)
\r
2579 void initial_memory (void)
\r
2581 /* set initial memory allocations */
\r
2582 if (mem_extra_high < 0)
\r
2583 mem_extra_high = 0;
\r
2585 if (mem_extra_low < 0)
\r
2586 mem_extra_low = 0;
\r
2588 if (mem_initex < 0)
\r
2593 if (mem_initex != 0)
\r
2595 puts("ERROR: Can only set initial main memory size in initex");
\r
2599 if (trie_size != 0)
\r
2601 puts("ERROR: Need only set hyphenation trie size in initex");
\r
2602 /* trie_size = 0; */
\r
2606 if (mem_initex == 0)
\r
2607 mem_initex = default_mem_top;
\r
2609 if (trie_size == 0)
\r
2610 trie_size = default_trie_size;
\r
2612 /* Just in case user mistakenly specified words instead of kilo words */
\r
2613 if (mem_extra_high > 10000L * 1024L)
\r
2614 mem_extra_high = mem_extra_high / 1024;
\r
2616 if (mem_extra_low > 10000L * 1024L)
\r
2617 mem_extra_low = mem_extra_low / 1024;
\r
2619 if (mem_initex > 10000L * 1024L)
\r
2620 mem_initex = mem_initex / 1024;
\r
2622 if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */
\r
2624 puts("WARNING: There may be no benefit to asking for so much memory");
\r
2625 /* mem_initex = 2048 * 1024; */
\r
2628 if (new_hyphen_prime < 0)
\r
2629 new_hyphen_prime = 0;
\r
2631 if (new_hyphen_prime > 0)
\r
2634 puts("ERROR: Can only set hyphen prime in initex");
\r
2637 if (new_hyphen_prime % 2 == 0)
\r
2638 new_hyphen_prime++;
\r
2640 while (!prime(new_hyphen_prime))
\r
2641 new_hyphen_prime = new_hyphen_prime + 2;
\r
2644 printf("Using %d as hyphen prime\n", new_hyphen_prime);
\r
2648 if (percent_grow > 100)
\r
2649 percent_grow = percent_grow - 100;
\r
2651 if (percent_grow > 100)
\r
2652 percent_grow = 100; /* upper limit - double */
\r
2654 if (percent_grow < 10)
\r
2655 percent_grow = 10; /* lower limit - 10% */
\r
2658 void perrormod (const char * s)
\r
2660 printf("`%s': %s\n", s, strerror(errno));
\r
2663 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
\r
2664 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
\r
2665 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
\r
2666 /* this is then undone in tex3.c both for fopen input and output */
\r
2667 /* not ideal, since pseudo name appears in log and in error messages ... */
\r
2669 void hidetwiddle (char *tname)
\r
2673 #ifdef DEBUGTWIDDLE
\r
2675 printf("Hidetwiddle %s", tname);
\r
2678 while (*s != '\0')
\r
2680 if (*s == '~' && pseudo_tilde != 0)
\r
2681 *s = (char) pseudo_tilde; /* typically 254 */
\r
2682 else if (*s == ' ' && pseudo_space != 0)
\r
2683 *s = (char) pseudo_space; /* typically 255 */
\r
2687 #ifdef DEBUGTWIDDLE
\r
2689 printf("=> %s\n", tname);
\r
2693 void deslash_all (int ac, char **av)
\r
2695 char buffer[file_name_size];
\r
2698 if ((s = grabenv("TEXDVI")) != NULL)
\r
2699 dvi_directory = s;
\r
2701 if ((s = grabenv("TEXLOG")) != NULL)
\r
2702 log_directory = s;
\r
2704 if ((s = grabenv("TEXAUX")) != NULL)
\r
2705 aux_directory = s;
\r
2707 if ((s = grabenv("TEXFMT")) != NULL)
\r
2708 fmt_directory = s;
\r
2710 if ((s = grabenv("TEXPDF")) != NULL)
\r
2711 pdf_directory = s;
\r
2713 strcpy(buffer, av[0]);
\r
2715 if ((s = strrchr(buffer, '\\')) != NULL)
\r
2717 else if ((s = strrchr(buffer, '/')) != NULL)
\r
2719 else if ((s = strrchr(buffer, ':')) != NULL)
\r
2722 s = buffer + strlen(buffer) - 1;
\r
2724 if (*s == '\\' || *s == '/')
\r
2727 if (strcmp(dvi_directory, "") != 0)
\r
2728 flush_trailing_slash(dvi_directory);
\r
2730 if (strcmp(log_directory, "") != 0)
\r
2731 flush_trailing_slash(log_directory);
\r
2733 if (strcmp(aux_directory, "") != 0)
\r
2734 flush_trailing_slash(aux_directory);
\r
2736 if (strcmp(fmt_directory, "") != 0)
\r
2737 flush_trailing_slash(fmt_directory);
\r
2739 if (strcmp(pdf_directory, "") != 0)
\r
2740 flush_trailing_slash(pdf_directory);
\r
2744 if (strcmp(dvi_directory, "") != 0)
\r
2745 unixify(dvi_directory);
\r
2747 if (strcmp(log_directory, "") != 0)
\r
2748 unixify(log_directory);
\r
2750 if (strcmp(aux_directory, "") != 0)
\r
2751 unixify(aux_directory);
\r
2753 if (strcmp(fmt_directory, "") != 0)
\r
2754 unixify(fmt_directory);
\r
2756 if (strcmp(pdf_directory, "") != 0)
\r
2757 unixify(pdf_directory);
\r
2760 format_spec = false;
\r
2762 if (optind < ac && optind > 0)
\r
2767 printf("deslash: k %d argv[k] %s (argc %d)\n", optind, av[optind], ac);
\r
2769 unixify(av[optind]);
\r
2772 if (pseudo_tilde != 0 || pseudo_space != 0)
\r
2773 hidetwiddle(av[optind]);
\r
2775 if (*av[optind] == '&' || *av[optind] == '+')
\r
2777 format_spec = true;
\r
2778 format_name = xstrdup(av[optind] + 1);
\r
2780 if (optind + 1 < ac)
\r
2785 printf("deslash: k %d argv[k] %s (argc %d)\n", optind + 1, av[optind + 1], ac);
\r
2787 unixify(av[optind + 1]);
\r
2790 if (pseudo_tilde != 0 || pseudo_space != 0)
\r
2791 hidetwiddle(av[optind + 1]);
\r
2797 int main_init (int ac, char ** av)
\r
2799 kpse_set_program_name(av[0], "dvipdfmx");
\r
2800 xputenv("engine", "yandytex");
\r
2802 if (sizeof(memory_word) != sizeof(halfword) * 2)
\r
2803 printf("ERROR: Bad word size %ld!\n", sizeof(memory_word));
\r
2805 start_time = clock();
\r
2806 main_time = start_time;
\r
2808 /* reset all allocatable memory pointers to NULL - in case we drop out */
\r
2809 main_memory = NULL;
\r
2814 #ifdef ALLOCATESAVESTACK
\r
2815 save_stack = NULL;
\r
2818 #ifdef ALLOCATEBUFFER
\r
2820 current_buf_size = 0;
\r
2821 buffer = realloc_buffer(initial_buf_size);
\r
2826 trie_taken = NULL;
\r
2836 log_opened = false; /* so can tell whether opened */
\r
2837 interaction = -1; /* default state => 3 */
\r
2838 missing_characters = 0; /* none yet! */
\r
2839 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
\r
2840 suppress_f_ligs = false; /* default is not to ignore f-ligs */
\r
2842 if (ac > 1 && !strncmp(av[1], "-Y", 2))
\r
2843 reorder_arg_flag = false;
\r
2845 if (reorder_arg_flag)
\r
2846 reorderargs(ac, av);
\r
2848 if (init_commands(ac, av))
\r
2851 check_fixed_align(trace_flag);
\r
2853 format_file = NULL;
\r
2854 source_direct = NULL;
\r
2855 dvi_file_name = NULL;
\r
2856 log_file_name = NULL;
\r
2857 pdf_file_name = NULL;
\r
2859 first_pass_count = 0;
\r
2860 second_pass_count = 0;
\r
2861 final_pass_count = 0;
\r
2862 paragraph_failed = 0;
\r
2864 overfull_hbox = 0;
\r
2865 underfull_hbox = 0;
\r
2866 overfull_vbox = 0;
\r
2867 underfull_vbox = 0;
\r
2870 puts("Entering main_init() (local.c).");
\r
2873 ini_max_address = max_address;
\r
2876 show_maximums(stdout);
\r
2879 deslash_all(ac, av);
\r
2881 if (format_spec && mem_spec_flag)
\r
2882 puts("WARNING: Cannot change initial main_memory size when format specified");
\r
2884 if (allocate_memory() != 0)
\r
2887 check_alloc_align(trace_flag);
\r
2890 puts("Leaving main_init() (local.c).");
\r
2898 #define CLK_TCK CLOCKS_PER_SEC
\r
2901 void show_inter_val (clock_t inter_val)
\r
2903 int seconds, tenths, hundredth, thousands;
\r
2905 if (inter_val >= CLK_TCK * 10)
\r
2907 tenths = (inter_val * 10 + CLK_TCK / 2) / CLK_TCK;
\r
2908 seconds = tenths / 10;
\r
2909 tenths = tenths % 10;
\r
2910 printf("%d.%d", seconds, tenths);
\r
2912 else if (inter_val >= CLK_TCK)
\r
2914 hundredth = (inter_val * 100 + CLK_TCK / 2) / CLK_TCK;
\r
2915 seconds = hundredth / 100;
\r
2916 hundredth = hundredth % 100;
\r
2917 printf("%d.%02d", seconds, hundredth);
\r
2919 else if (inter_val > 0)
\r
2921 thousands = (inter_val * 1000 + CLK_TCK / 2) / CLK_TCK;
\r
2922 seconds = thousands / 1000;
\r
2923 thousands = thousands % 1000;
\r
2924 printf("%d.%03d", seconds, thousands);
\r
2927 show_line("0", 0);
\r
2930 int endit (int flag)
\r
2932 finish_time = clock();
\r
2934 if (missing_characters != 0)
\r
2937 if (missing_characters)
\r
2938 printf("! There %s %d missing character%s --- see log file\n",
\r
2939 (missing_characters == 1) ? "was" : "were", missing_characters,
\r
2940 (missing_characters == 1) ? "" : "s");
\r
2942 if (free_memory() != 0)
\r
2948 show_inter_val(finish_time - start_time);
\r
2950 show_inter_val(main_time - start_time);
\r
2951 printf(" format load + ");
\r
2952 show_inter_val(finish_time - main_time);
\r
2953 printf(" processing) ");
\r
2955 if (total_pages > 0)
\r
2957 show_inter_val((finish_time - main_time) / total_pages);
\r
2958 printf(" sec per page.\n");
\r
2964 // printf control sequences' name
\r
2965 void print_cs_name (FILE * output, int h)
\r
2969 memset(log_line, 0, sizeof(log_line));
\r
2971 textof = hash[h].rh;
\r
2976 c = sprintf(log_line, "(%d), ", h);
\r
2977 n = length(textof);
\r
2979 memmove(log_line + c, str_pool + str_start[textof], n);
\r
2980 memmove(log_line + c + n, "\n", 2);
\r
2982 if (output == stderr)
\r
2983 show_line(log_line, 1);
\r
2984 else if (output == stdout)
\r
2985 show_line(log_line, 0);
\r
2987 fprintf(output, "%s", log_line);
\r
2990 int compare_strn (int, int, int, int);
\r
2991 /* compare two csnames in qsort */
\r
2992 int compare_cs (const void *cp1, const void *cp2)
\r
2994 int c1, c2, l1, l2, k1, k2, textof1, textof2;
\r
2998 textof1 = hash[c1].rh;
\r
2999 textof2 = hash[c2].rh;
\r
3000 l1 = length(textof1);
\r
3001 l2 = length(textof2);
\r
3002 k1 = str_start[textof1];
\r
3003 k2 = str_start[textof2];
\r
3005 return compare_strn(k1, l1, k2, l2);
\r
3008 char * csused = NULL;
\r
3010 /* Allocate table of indeces to allow sorting on csname */
\r
3011 /* Allocate flags to remember which ones already listed at start */
\r
3012 /* pass = 0 --> fmt */
\r
3013 /* pass = 1 --> after */
\r
3014 void print_cs_names (FILE *output, int pass)
\r
3016 int h, k, ccount, repeatflag;
\r
3018 int nfcs = frozen_control_sequence;
\r
3020 if (pass == 0 && csused == NULL)
\r
3022 csused = (char *) malloc (nfcs);
\r
3024 if (csused == NULL)
\r
3028 memset(csused, 0, nfcs);
\r
3030 for (h = 0; h < (hash_size + 780); h++)
\r
3037 for (h = hash_base + 1; h < nfcs; h++)
\r
3039 if (pass == 1 && csused[h])
\r
3051 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
\r
3052 ccount, (pass == 1) ? "new" : "");
\r
3054 if (output == stderr)
\r
3055 show_line(log_line, 1);
\r
3056 else if (output == stdout)
\r
3057 show_line(log_line, 0);
\r
3059 fprintf(output, "%s", log_line);
\r
3063 cnumtable = (int *) malloc (ccount * sizeof(int));
\r
3065 if (cnumtable == NULL)
\r
3070 for (h = hash_base + 1; h < nfcs; h++)
\r
3072 if (pass == 1 && csused[h])
\r
3075 if (hash[h].rh != 0)
\r
3076 cnumtable[ccount++] = h;
\r
3079 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
\r
3083 for (k = 0; k < ccount; k++)
\r
3087 if (pass == 1 && csused[h])
\r
3090 print_cs_name(output, h);
\r
3093 sprintf(log_line, "\n");
\r
3095 if (output == stderr)
\r
3096 show_line(log_line, 1);
\r
3097 else if (output == stdout)
\r
3098 show_line(log_line, 0);
\r
3100 fprintf(output, "%s", log_line);
\r
3102 free((void *)cnumtable);
\r
3105 if (pass == 1 && csused != NULL)
\r
3112 /* k1 and k2 are positions in string pool */
\r
3113 /* l1 and l2 are lengths of strings */
\r
3114 int compare_strn (int k1, int l1, int k2, int l2)
\r
3118 while (l1 > 0 && l2 > 0)
\r
3120 c1 = str_pool[k1];
\r
3121 c2 = str_pool[k2];
\r
3133 return 1; /* first string longer */
\r
3135 return -1; /* second string longer */
\r
3137 return 0; /* strings match */
\r
3139 /* compare two font names and their at sizes in qsort */
\r
3140 int compare_fnt (const void * fp1, const void * fp2)
\r
3142 int f1, f2, l1, l2, k1, k2, s;
\r
3144 f1 = *(short *)fp1;
\r
3145 f2 = *(short *)fp2;
\r
3146 l1 = length(font_name[f1]);
\r
3147 l2 = length(font_name[f2]);
\r
3148 k1 = str_start[font_name[f1]];
\r
3149 k2 = str_start[font_name[f2]];
\r
3151 s = compare_strn (k1, l1, k2, l2);
\r
3156 if (font_size[f1] > font_size[f2])
\r
3158 else if (font_size[f1] < font_size[f2])
\r
3161 return 0; /* should not ever get here */
\r
3163 /* compare two font names */
\r
3164 int compare_fnt_name (int f1, int f2)
\r
3166 int l1, l2, k1, k2, s;
\r
3168 l1 = length(font_name[f1]);
\r
3169 l2 = length(font_name[f2]);
\r
3170 k1 = str_start[font_name[f1]];
\r
3171 k2 = str_start[font_name[f2]];
\r
3173 s = compare_strn (k1, l1, k2, l2);
\r
3177 /* decode checksum information */
\r
3178 const unsigned long checkdefault = 0x59265920;
\r
3179 int decode_fourty (unsigned long checksum, char *codingvector)
\r
3184 if (checksum == 0)
\r
3186 strcpy(codingvector, "unknwn");
\r
3189 else if ((checksum >> 8) == (checkdefault >> 8))
\r
3191 strcpy (codingvector, "fixed ");
\r
3196 for (k = 0; k < 6; k++)
\r
3198 c = (int) (checksum % 40);
\r
3199 checksum = checksum / 40;
\r
3201 if (c <= 'z' - 'a')
\r
3204 c = (c + '0') - ('z' - 'a') - 1;
\r
3214 codingvector[5-k] = (char) c;
\r
3217 codingvector[6] = '\0';
\r
3223 double sclpnt (long x)
\r
3227 pt = (double) x / 65536.0;
\r
3228 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
\r
3233 void dvi_font_show (internal_font_number f, int suppressname)
\r
3236 unsigned long checksum;
\r
3237 char checksumvector[8];
\r
3240 putc(' ', log_file);
\r
3242 if (suppressname == 0)
\r
3244 a = length(font_area[f]);
\r
3245 l = length(font_name[f]);
\r
3247 k = str_start[font_area[f]];
\r
3249 memcpy(buffer, str_pool + k, length(font_area[f]));
\r
3250 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
\r
3252 k = str_start[font_name[f]];
\r
3254 memcpy(buffer, str_pool + k, length(font_name[f]));
\r
3255 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
\r
3259 for (k = a + l; k < 16; k++)
\r
3260 putc(' ', log_file);
\r
3262 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
\r
3263 fputs(buffer, log_file);
\r
3265 if (suppressname == 0)
\r
3267 n = strlen(buffer);
\r
3269 for (k = n; k < 16; k++)
\r
3270 putc(' ', log_file);
\r
3272 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
\r
3273 decode_fourty(checksum, checksumvector);
\r
3274 log_printf("encoding: %s..", checksumvector);
\r
3277 putc('\n', log_file);
\r
3279 /* Allocate table of indeces to allow sorting on font name */
\r
3280 void show_font_info (void)
\r
3282 int k, m, fcount, repeatflag;
\r
3287 for (k = 1; k <= font_ptr; k++)
\r
3294 fnumtable = (short *) malloc(fcount * sizeof(short));
\r
3296 log_printf("\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
\r
3300 for (k = 1; k <= font_ptr; k++)
\r
3302 fnumtable[fcount++] = (short) k;
\r
3304 qsort ((void *)fnumtable, fcount, sizeof(short), &compare_fnt);
\r
3308 for (m = 0; m < fcount; m++)
\r
3312 if (compare_fnt_name(fnumtable[m - 1], fnumtable[m]) == 0)
\r
3318 dvi_font_show(fnumtable[m], repeatflag);
\r
3321 free((void *)fnumtable);
\r