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
32 #if defined(__clang__)
33 const char * compiler = "Clang/LLVM";
34 #elif defined(__GNUC__) || defined(__GNUG__)
35 const char * compiler = "GCC";
36 #elif defined(_MSC_VER)
37 const char * compiler = "MSVC";
40 const char * compiletime = __TIME__;
41 const char * compiledate = __DATE__;
42 const char * yandyversion = "2.3.0";
43 const char * application = "Y&Y TeX";
44 const char * banner = "This is TeX, Version 3.14159265";
46 void print_banner (void)
51 sprintf(dist_ver, "%s (%s %s/Win64)", banner, application, yandyversion);
53 sprintf(dist_ver, "%s (%s %s/Win32)", banner, application, yandyversion);
56 sprintf(dist_ver, "%s (%s %s/Linux)", banner, application, yandyversion);
61 clock_t start_time, main_time, finish_time;
63 char * dvi_directory = "";
64 char * log_directory = "";
65 char * aux_directory = "";
66 char * fmt_directory = "";
67 char * pdf_directory = "";
71 boolean mem_spec_flag = false;
72 boolean format_spec = false;
73 int closed_already = 0; /* make sure we don't try this more than once */
74 boolean reorder_arg_flag = true; /* put command line flags/arguments first */
76 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
78 unsigned char wintodos[128] =
80 0, 0, 0, 159, 0, 0, 0, 0,
81 94, 0, 0, 0, 0, 0, 0, 0,
82 0, 96, 39, 0, 0, 7, 0, 0,
83 126, 0, 0, 0, 0, 0, 0, 0,
84 32, 173, 189, 156, 207, 190, 221, 21,
85 0, 184, 166, 174, 170, 45, 169, 0,
86 248, 241, 253, 252, 0, 230, 20, 250,
87 0, 251, 167, 175, 172, 171, 243, 168,
88 183, 181, 182, 199, 142, 143, 146, 128,
89 212, 144, 210, 211, 222, 214, 215, 216,
90 209, 165, 227, 224, 226, 229, 153, 158,
91 157, 235, 233, 234, 154, 237, 232, 225,
92 133, 160, 131, 198, 132, 134, 145, 135,
93 138, 130, 136, 137, 141, 161, 140, 139,
94 208, 164, 149, 162, 147, 228, 148, 246,
95 155, 151, 163, 150, 129, 236, 231, 152
98 void show_usage (void)
101 "Useage: yanytex [OPTION]... [+format_file] [tex_file]\n\n"
102 "--help -? show this usage summary\n"
103 "--initex -i start up as initex (create format file)\n"
104 "--verbose -v be verbose (show implementation version number)\n"
105 "--ascii -n do not allow `non ASCII' characters in input files\n"
106 " (complain instead)\n"
107 "--showhex -w do not show `non ASCII' characters in hexadecimal\n"
109 "--nodos -d do not allow DOS style file names - i.e. do not convert\n"
111 "--nomac -r do not allow Mac style termination - i.e. do not convert\n"
113 "--patterns -p allow use of \\patterns after loading format (initex only)\n"
114 "--knuthify -K disable all extensions to basic TeX\n"
115 "--main-mem -m initial main memory size in kilo words (initex only)\n"
116 "--hyph-size -e hyphenation exception dictionary size (initex only)\n"
117 "--trie-size -h hyphenation pattern trie size (initex only)\n"
118 "--xchr-file -x use `non ASCII' character mapping (xchr[]) defined in file\n"
119 "--key-file -k use `key replacement' defined in file\n"
120 "--dvi-dir -o write DVI file in specified directory (default '.')\n"
121 "--log-dir -l write LOG file in specified directory (default '.')\n"
122 "--aux-dir -a write AUX file in specified directory (default '.')\n");
126 // Sep 27 1990 => 1990 Sep 27
127 // 0123456789 0123456789
128 void scivilize (char * date)
133 strcpy (pyear, date + 7);
135 for (k = 5; k >= 0; k--)
136 date[k + 5] = date[k];
138 for (k = 0; k < 4; k++)
147 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35
148 void lcivilize (char * date)
153 strcpy(pyear, date + 20);
155 for (k = 18; k >= 0; k--)
156 date[k + 1] = date[k];
160 for (k = 0; k < 4; k++)
166 void stamp_it (char * s)
170 strcpy(date, compiledate);
172 sprintf(s, "%s %s (compiled time: %s %s with %s)",
173 application, yandyversion, date, compiletime, compiler);
180 void read_xchr_sub (FILE * xchr_input)
182 char buffer[file_name_size];
183 int k, from, to, count = 0;
186 memset(xchr, NOTDEF, MAXCHRS);
187 memset(xord, NOTDEF, MAXCHRS);
189 #ifdef ALLOCATEBUFFER
190 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
192 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
195 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
198 from = (int) strtol (buffer, &s, 0);
199 to = (int) strtol (s, NULL, 0);
201 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
203 if (xchr[from] == (unsigned char) NOTDEF)
204 xchr[from] = (unsigned char) to;
206 printf("NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
208 if (xord[to] == NOTDEF)
209 xord[to] = (unsigned char) from;
211 printf("NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
217 for (k = 0; k < MAXCHRS; k++)
219 if (xchr[k] == NOTDEF) /* if it has not been filled */
221 if (xord[k] == NOTDEF) /* see whether used already */
223 xchr[k] = (unsigned char) k; /* no, so make identity */
224 xord[k] = (unsigned char) k; /* no, so make identity */
229 xchr[NOTDEF] = NOTDEF; /* fixed point of mapping */
233 printf("Read %d xchr[] pairs:\n", count);
235 for (k = 0; k < MAXCHRS; k++)
237 if (xchr[k] != NOTDEF)
238 printf("%d => %d\n", k, xchr[k]);
243 char * replacement[MAXCHRS]; /* pointers to replacement strings */
245 void read_repl_sub (FILE * repl_input)
248 char buffer[file_name_size];
253 memset(replacement, 0, MAXCHRS * sizeof(replacement[0]));
255 while (fgets(buffer, file_name_size, repl_input) != NULL)
257 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
260 if ((m = sscanf(buffer, "%d%n %s", &chrs, &n, (char *)&charname)) == 0)
264 if (*charname == '"') /* deal with quoted string "..." */
269 while (*s != '"' && *s != '\0')
270 s++; /* step up to " */
273 continue; /* sanity check */
279 s++; /* is it "" perhaps ? */
282 break; /* no, end of string */
285 *t++ = *s++; /* copy over */
288 *t = '\0'; /* and terminate */
291 if (chrs >= 0 && chrs < MAXCHRS)
292 replacement[chrs] = xstrdup(charname);
294 /* presently the following can never get triggered */
295 /* which is good, because it is perhaps not right ... */
296 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
297 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
298 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
299 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
300 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
302 if (chrs >= 0 && chrs < MAXCHRS)
303 replacement[chrs] = xstrdup(charname);
306 printf("ERROR: don't understand %s", buffer);
311 puts("Key replacement table");
313 for (k = 0; k < MAXCHRS; k++)
315 if (replacement[k] != NULL)
316 printf("%d\t%s\n", k, replacement[k]);
321 /* Following used both to read xchr[] file and key replacement file */
322 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
323 int read_xchr_file (char *filename, int flag, char *argv[])
326 char infile[file_name_size];
329 if (filename == NULL)
333 printf("Reading xchr/repl %s\n", filename);
335 /* first try using file as specified */
336 strcpy(infile, filename);
339 printf("Trying %s\n", infile);
341 xchr_input = fopen (infile, "r");
343 if (xchr_input == NULL)
345 if (strrchr(infile, '.') == NULL)
348 strcat(infile, ".map");
350 strcat(infile, ".key");
353 printf("Trying %s\n", infile);
355 xchr_input = fopen(infile, "r");
359 if (xchr_input == NULL)
361 strcpy(infile, argv[0]); /* try TeX program path */
363 if ((s = strrchr (infile, '\\')) != NULL)
365 else if ((s = strrchr (infile, '/')) != NULL)
367 else if ((s = strrchr (infile, ':')) != NULL)
370 strcat (infile, filename);
373 printf("Trying %s\n", infile);
375 xchr_input = fopen (infile, "r");
377 if (xchr_input == NULL)
379 if (strchr(infile, '.') == NULL)
382 strcat(infile, ".map");
384 strcat(infile, ".key");
387 printf("Trying %s\n", infile);
389 xchr_input = fopen (infile, "r");
394 if (xchr_input == NULL)
396 strcpy(infile, argv[0]); /* try TeX program path */
398 if ((s = strrchr (infile, '\\')) != NULL)
400 else if ((s = strrchr (infile, '/')) != NULL)
402 else if ((s = strrchr (infile, ':')) != NULL)
405 strcat(infile, "keyboard\\");
406 strcat(infile, filename);
409 printf("Trying %s\n", infile);
411 xchr_input = fopen (infile, "r");
413 if (xchr_input == NULL)
415 if (strchr(infile, '.') == NULL)
418 strcat(infile, ".map");
420 strcat(infile, ".key");
423 printf("Trying %s\n", infile);
425 xchr_input = fopen (infile, "r");
430 /* Note: can't look in TeX source file dir, since that is not known yet */
431 if (xchr_input == NULL)
433 printf("ERROR: Sorry, cannot find %s file %s",
434 flag ? " xchr[]" : "key mapping", filename);
435 perrormod (filename);
440 read_xchr_sub(xchr_input);
442 read_repl_sub(xchr_input);
444 (void) fclose(xchr_input);
449 /* need to also set `key_replace' here based on command line */
450 /* need to also allocate `buffercopy' here and free at end */
451 /* need to call `readreplace' in appropriate place */
455 /* ad hoc default minimum growth in memory realloc is 62% */
456 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
457 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
458 int total_allocated = 0; /* total memory allocated so far */
459 int ini_max_address = 0; /* maximum address when starting */
460 int max_address = 0; /* maximum address seen in allocated memory */
463 void show_maximums (FILE * output)
465 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
466 fputs(log_line, output);
469 /* our own version of realloc --- avoid supposed MicroSoft version bug */
470 /* also tries _expand first, which can avoid address growth ... */
473 void * ourrealloc (void * old, size_t new_size)
476 size_t old_size, overlap;
478 /* round up to nearest multiple of four bytes */
479 /* avoid unlikely alignment */
480 if ((new_size % 4) != 0)
481 new_size = ((new_size / 4) + 1) * 4;
484 return malloc (new_size); /* no old block - use malloc */
487 old_size = _msize (old);
489 old_size = malloc_usable_size (old);
492 if (old_size >= new_size && old_size < new_size + 4)
496 mnew = _expand (old, new_size); /* first try and expand in place MSVC */
498 mnew = realloc (old, new_size);
504 printf("EXPANDED! %p (%ld) == %p (%ld)\n",
505 mnew, new_size, old, old_size);
510 /* do this if you want to call the real realloc next - */
511 mnew = realloc (old, new_size);
516 /* we are screwed typically if we ever drop through here - no more space */
517 mnew = malloc (new_size); /* otherwise find new space */
520 return mnew; /* if unable to allocate */
522 if (old_size < new_size)
527 memcpy (mnew, old, overlap); /* copy old data to new area */
528 free(old); /* free the old area */
534 void memory_error (const char * s, int n)
538 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
539 show_maximums(log_file);
542 printf("\n! Unable to allocate %d bytes for %s\n", n, s);
543 show_maximums(stderr);
546 void trace_memory (const char * s, int n)
548 printf("Allocating %d bytes for %s\n", n, s);
551 void update_statistics (long address, int size, int old_size)
553 if (address + size > max_address)
554 max_address = address + size;
556 total_allocated = total_allocated + size - old_size;
559 void probe_memory (void)
561 char * s = (char *) malloc(sizeof(void *));
563 update_statistics ((long) s, 0, 0);
566 void probe_show (void)
569 show_maximums(stdout);
572 size_t roundup (size_t n)
574 if ((n % sizeof(void *)) == 0)
577 return ((n / sizeof(void *)) + 1) * sizeof(void *);
581 /* returns -1 if it fails */
583 int allocate_tries (int trie_max)
587 if (trie_max > 1000000)
590 nl = (trie_max + 1) * sizeof(halfword);
591 no = (trie_max + 1) * sizeof(halfword);
592 nc = (trie_max + 1) * sizeof(quarterword);
596 trace_memory("hyphen trie", n);
598 trie_trl = (halfword *) malloc(roundup(nl));
599 trie_tro = (halfword *) malloc(roundup(no));
600 trie_trc = (quarterword *) malloc(roundup(nc));
602 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
604 memory_error("hyphen trie", n);
609 printf("Addresses trie_trl %p trie_tro %p trie_trc %p\n", trie_trl, trie_tro, trie_trc);
611 update_statistics((long) trie_trl, nl, 0);
612 update_statistics((long) trie_tro, no, 0);
613 update_statistics((long) trie_trc, nc, 0);
615 trie_size = trie_max;
624 #ifdef ALLOCATEHYPHEN
625 int current_prime = 0; /* remember in case reallocated later */
627 /* we don't return an address here, since TWO memory regions allocated */
628 /* plus, we don't really reallocate, we FLUSH the old information totally */
629 /* returns -1 if it fails */
631 int realloc_hyphen (int hyphen_prime)
635 if (!prime(hyphen_prime))
637 printf("ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
641 /* need not/cannot preserve old contents when hyphen prime is changed */
642 /* if (hyph_list != NULL) free(hyph_list); */
643 /* if (hyph_word != NULL) free(hyph_word); */
644 nw = (hyphen_prime + 1) * sizeof(str_number);
645 nl = (hyphen_prime + 1) * sizeof(halfword);
649 trace_memory("hyphen exception", n);
651 hyph_word = (str_number *) REALLOC (hyph_word, nw);
652 hyph_list = (halfword *) REALLOC (hyph_list, nl);
654 if (hyph_word == NULL || hyph_list == NULL)
656 memory_error("hyphen exception", n);
661 printf("Addresses hyph_word %p hyph_list %p\n", hyph_word, hyph_list);
663 /* cannot preserve old contents when hyphen prime is changed */
665 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
667 for (k = 0; k <= hyphen_prime; k++)
672 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
674 for (k = 0; k <= hyphen_prime; k++)
680 if (current_prime != 0)
682 update_statistics((long) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
683 update_statistics((long) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
687 update_statistics((long) hyph_word, nw, 0);
688 update_statistics((long) hyph_list, nl, 0);
691 current_prime = hyphen_prime;
700 int current_mem_size = 0; /* current total words in main mem allocated -1 */
702 /* this gets called from itex.c when it figures out what mem_top is */
703 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
704 /* initial allocation only, may get expanded later */
705 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
706 /* returns NULL if it fails */
709 /* initial main memory alloc - mem_top */
710 memory_word * allocate_main_memory (int size)
714 if (main_memory != NULL)
717 puts("Reallocating initial memory allocation");
720 mem_top = mem_bot + size;
722 mem_start = 0; /* bottom of memory allocated by system */
723 mem_min = 0; /* bottom of area made available to TeX */
724 n = (mem_max - mem_start + 1) * sizeof (memory_word);
727 trace_memory("main memory", n);
729 main_memory = (memory_word *) REALLOC (main_memory, n);
731 if (main_memory == NULL)
733 memory_error("initial main memory", n);
738 printf("Address main memory == %p\n", main_memory);
742 if (mem_start != 0 && !is_initex)
743 mem = main_memory - mem_start;
746 printf("Offset address main memory == %p\n", mem);
748 update_statistics((long) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));
749 /* current_mem_size = (mem_max - mem_start + 1); */
750 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
760 /* int firstallocation = 1; */
762 /* increase main memory allocation at low end and high end */
763 /* called only from tex0.c *//* called with one of lo_size or hi_size == 0 */
764 /* returns NULL if it fails */
766 memory_word * realloc_main (int lo_size, int hi_size)
771 memory_word * new_memory = NULL;
774 printf("WARNING: Entering realloc_main lo %d hi %d\n", lo_size, hi_size);
778 puts("ERROR: Cannot extent main memory in initex");
781 puts("Please use `-m=...' on command line");
787 printf("Old Address %s == %p\n", "main memory", main_memory);
789 /* if we REALLY run up to limit ! */
790 if (current_mem_size + 1 == max_mem_size)
792 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
796 /* first allocation should expand *both* lo and hi */
797 if (hi_size == 0 && mem_end == mem_max)
800 if (lo_size == 0 && mem_start == mem_min)
803 /* try and prevent excessive frequent reallocations */
804 /* while avoiding over allocation by too much */
805 min_size = current_mem_size / 100 * percent_grow;
807 if (lo_size + hi_size < min_size)
809 if (lo_size > 0 && hi_size > 0)
811 lo_size = min_size / 2;
812 hi_size = min_size / 2;
814 else if (lo_size > 0)
816 else if (hi_size > 0)
820 if (lo_size > 0 && lo_size < mem_top / 2)
821 lo_size = mem_top / 2;
823 if (hi_size > 0 && hi_size < mem_top / 2)
824 hi_size = mem_top / 2;
826 for (k = 0; k < MAXSPLITS; k++)
828 new_size = current_mem_size + lo_size + hi_size;
830 if (new_size >= max_mem_size) /* bump against limit - ha ha ha */
832 while (new_size >= max_mem_size)
834 lo_size = lo_size / 2;
835 hi_size = hi_size / 2;
836 new_size = current_mem_size + lo_size + hi_size;
840 n = (new_size + 1) * sizeof (memory_word);
843 trace_memory("main memory", n);
845 new_memory = (memory_word *) REALLOC (main_memory, n);
847 if (new_memory != NULL)
848 break; /* did we get it ? */
850 if (current_mem_size == 0)
851 break; /* in case we ever use for initial */
853 lo_size = lo_size / 2; hi_size = hi_size / 2;
856 if (new_memory == NULL)
858 memory_error("main memory", n);
863 printf("New Address %s == %p\n", "main memory", new_memory);
867 /* shift everything upward to make space for new low area */
869 printf("memmove %p %p %ld \n", new_memory + lo_size,
870 new_memory, (current_mem_size + 1) * sizeof(memory_word));
872 memmove (new_memory + lo_size, new_memory,
873 (current_mem_size + 1) * sizeof(memory_word));
874 /* could reduce words moved by (mem_max - mem_end) */
877 main_memory = new_memory; /* remember for free later */
880 mem_start = mem_start - lo_size; /* update lower limit */
883 mem_max = mem_max + hi_size; /* update upper limit */
885 update_statistics ((long) main_memory, n,
886 (current_mem_size + 1) * sizeof (memory_word));
887 current_mem_size = new_size;
889 if (current_mem_size != mem_max - mem_start)
890 puts("ERROR: Impossible Memory Error");
893 mem = main_memory - mem_start;
905 int current_font_mem_size = 0;
907 memory_word * realloc_font_info (int size)
909 memory_word * new_font_info = NULL;
915 printf("Old Address %s == %p\n", "font_info", font_info);
917 /* during initial allocation, font_info == NULL - realloc acts like malloc */
918 /* during initial allocation current_font_mem_size == 0 */
919 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
921 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
922 return font_info; /* pass it back to TeX 99/Fabe/4 */
924 /* try and prevent excessive frequent reallocations */
925 /* while avoiding over allocation by too much */
926 /* min_size = current_font_mem_size / 2; */
927 min_size = current_font_mem_size / 100 * percent_grow;
932 if (size < initial_font_mem_size)
933 size = initial_font_mem_size;
935 for (k=0; k < MAXSPLITS; k++)
937 new_size = current_font_mem_size + size;
939 if (new_size > font_mem_size)
940 new_size = font_mem_size; /* bump against limit */
942 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
943 n = (new_size + 1) * sizeof (memory_word);
946 trace_memory("font_info", n);
948 new_font_info = (memory_word *) REALLOC (font_info, n);
950 if (new_font_info != NULL)
951 break; /* did we get it ? */
953 if (current_font_mem_size == 0)
954 break; /* initial allocation must work */
959 if (new_font_info == NULL)
961 memory_error("font", n);
962 return font_info; /* try and continue !!! */
965 font_info = new_font_info;
968 printf("New Address %s == %p\n", "font_info", font_info);
970 update_statistics ((long) font_info, n, current_font_mem_size * sizeof(memory_word));
971 current_font_mem_size = new_size;
980 #ifdef ALLOCATESTRING
981 int current_pool_size = 0;
983 packed_ASCII_code * realloc_str_pool (int size)
988 packed_ASCII_code * new_str_pool = NULL;
991 printf("Old Address %s == %p\n", "string pool", str_pool);
993 if (current_pool_size == pool_size)
995 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
997 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1000 min_size = current_pool_size / 100 * percent_grow;
1002 if (size < min_size)
1005 if (size < initial_pool_size)
1006 size = initial_pool_size;
1008 for (k = 0; k < MAXSPLITS; k++)
1010 new_size = current_pool_size + size;
1012 if (new_size > pool_size)
1013 new_size = pool_size;
1014 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1015 n = (new_size + 1) * sizeof (packed_ASCII_code);
1018 trace_memory("str_pool", n);
1020 new_str_pool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1022 if (new_str_pool != NULL)
1023 break; /* did we get it ? */
1025 if (current_pool_size == 0)
1026 break; /* initial allocation must work */
1028 size = size / 2; /* else can retry smaller */
1031 if (new_str_pool == NULL)
1033 memory_error("string pool", n);
1034 return str_pool; /* try and continue !!! */
1037 str_pool = new_str_pool;
1038 update_statistics ((long) str_pool, n, current_pool_size);
1039 current_pool_size = new_size;
1042 printf("New Address %s == %p\n", "string pool", str_pool);
1051 #ifdef ALLOCATESTRING
1052 int current_max_strings = 0;
1054 pool_pointer * realloc_str_start (int size)
1059 pool_pointer * new_str_start = NULL;
1062 printf("Old Address %s == %p\n", "string start", str_start);
1064 if (current_max_strings == max_strings)
1066 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1068 return str_start; /* pass it back to TeX 99/Fabe/4 */
1071 min_size = current_max_strings / 100 * percent_grow;
1073 if (size < min_size)
1076 if (size < initial_max_strings)
1077 size = initial_max_strings;
1079 for (k = 0; k < MAXSPLITS; k++)
1081 new_size = current_max_strings + size;
1083 if (new_size > max_strings)
1084 new_size = max_strings;
1085 /* important + 1 since str_start[maxstring + 1] originally */
1086 n = (new_size + 1) * sizeof (pool_pointer);
1089 trace_memory("str_start", n);
1091 new_str_start = (pool_pointer *) REALLOC (str_start, n);
1093 if (new_str_start != NULL)
1094 break; /* did we get it ? */
1096 if (current_max_strings == 0)
1097 break; /* initial allocation must work */
1099 size = size / 2; /* otherwise can try smaller */
1102 if (new_str_start == NULL)
1104 memory_error("string pointer", n);
1105 return str_start; /* try and continue */
1108 str_start = new_str_start;
1109 update_statistics((long) str_start, n, current_max_strings * sizeof (pool_pointer));
1110 current_max_strings = new_size;
1113 printf("New Address %s == %p\n", "string start", str_start);
1123 /* returns -1 if it fails */
1124 /* size == trie_size */
1125 int allocate_ini (int size)
1127 int n, nl, no, nc, nr, nh, nt;
1129 nh = (size + 1) * sizeof(trie_pointer);
1130 nr = (size + 1) * sizeof(trie_pointer);
1131 nl = (size + 1) * sizeof(trie_pointer);
1132 no = (size + 1) * sizeof(trie_op_code);
1133 nc = (size + 1) * sizeof(packed_ASCII_code);
1134 nt = (size + 1) * sizeof(char);
1135 n = nl + no + nc + nr + nh + nt;
1138 trace_memory ("initex hyphen trie", n);
1140 trie_l = (trie_pointer *) malloc (roundup(nl));
1141 trie_o = (trie_op_code *) malloc (roundup(no));
1142 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1143 trie_r = (trie_pointer *) malloc (roundup(nr));
1144 trie_hash = (trie_pointer *) malloc (roundup(nh));
1145 trie_taken = (char *) malloc (roundup(nt));
1147 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1148 trie_hash == NULL || trie_taken == NULL)
1150 memory_error("initex hyphen trie", n);
1156 printf("Addresses: trie_l %p trie_o %p trie_c %p\n", trie_l, trie_o, trie_c);
1157 printf("Addresses: trie_r %p trie_hash %p trie_taken %p\n", trie_r, trie_hash, trie_taken);
1160 update_statistics ((long) trie_l, nl, 0);
1161 update_statistics ((long) trie_o, no, 0);
1162 update_statistics ((long) trie_c, nc, 0);
1163 update_statistics ((long) trie_r, nr, 0);
1164 update_statistics ((long) trie_hash, nh, 0);
1165 update_statistics ((long) trie_taken, nt, 0);
1170 return 0; // success
1174 #ifdef ALLOCATESAVESTACK
1175 int current_save_size = 0;
1177 memory_word * realloc_save_stack (int size)
1180 int n = 0, new_size = 0;
1181 memory_word * new_save_stack = NULL;
1184 printf("Old Address %s == %p\n", "save stack", save_stack);
1186 if (current_save_size == save_size)
1188 return save_stack; /* let TeX handle the error */
1191 min_size = current_save_size / 100 * percent_grow;
1193 if (size < min_size)
1196 if (size < initial_save_size)
1197 size = initial_save_size;
1199 for (k = 0; k < MAXSPLITS; k++)
1201 new_size = current_save_size + size;
1203 if (new_size > save_size)
1204 new_size = save_size;
1206 n = (new_size + 1) * sizeof (memory_word);
1209 trace_memory("save_stack", n);
1211 new_save_stack = (memory_word *) REALLOC (save_stack, n);
1213 if (new_save_stack != NULL)
1214 break; /* did we get it ? */
1216 if (current_save_size == 0)
1217 break; /* initial allocation must work */
1219 size = size / 2; /* else can retry smaller */
1222 if (new_save_stack == NULL)
1224 memory_error("save_stack", n);
1225 return save_stack; /* try and continue !!! */
1228 save_stack = new_save_stack;
1229 update_statistics ((long) save_stack, n, current_save_size);
1230 current_save_size = new_size;
1234 printf("Current %s %d\n", "save_size", current_save_size);
1235 printf("New Address %s == %p\n", "save stack", save_stack);
1245 #ifdef ALLOCATEINPUTSTACK
1246 int current_stack_size = 0; /* input stack size */
1248 in_state_record * realloc_input_stack (int size)
1251 int n = 0, new_size = 0;
1252 in_state_record * new_input_stack = NULL;
1255 printf("Old Address %s == %p\n", "input stack", input_stack);
1257 if (current_stack_size == stack_size)
1262 min_size = current_stack_size / 100 * percent_grow;
1264 if (size < min_size)
1267 if (size < initial_stack_size)
1268 size = initial_stack_size;
1270 for (k = 0; k < MAXSPLITS; k++)
1272 new_size = current_stack_size + size;
1274 if (new_size > stack_size)
1275 new_size = stack_size;
1277 n = (new_size + 1) * sizeof(in_state_record);
1280 trace_memory("input_stack", n);
1282 new_input_stack = (in_state_record *) REALLOC (input_stack, n);
1284 if (new_input_stack != NULL)
1285 break; /* did we get it ? */
1287 if (current_stack_size == 0)
1288 break; /* initial allocation must work */
1290 size = size / 2; /* else can retry smaller */
1293 if (new_input_stack == NULL)
1295 memory_error("input stack", n);
1296 return input_stack; /* try and continue !!! */
1299 input_stack = new_input_stack;
1300 update_statistics ((long) input_stack, n, current_stack_size);
1301 current_stack_size = new_size;
1305 printf("Current %s %d\n", "stack_size", current_stack_size);
1306 printf("New Address %s == %p\n", "input stack", input_stack);
1316 #ifdef ALLOCATENESTSTACK
1317 int current_nest_size = 0; /* current nest size */
1319 list_state_record * realloc_nest_stack (int size)
1322 int n = 0, new_size = 0;
1323 list_state_record * new_nest = NULL;
1326 printf("Old Address %s == %p\n", "nest stack", nest);
1328 if (current_nest_size == nest_size)
1333 min_size = current_nest_size / 100 * percent_grow;
1335 if (size < min_size)
1338 if (size < initial_nest_size)
1339 size = initial_nest_size;
1341 for (k = 0; k < MAXSPLITS; k++)
1343 new_size = current_nest_size + size;
1345 if (new_size > nest_size)
1346 new_size = nest_size;
1348 n = (new_size + 1) * sizeof (list_state_record);
1351 trace_memory("nest stack", n);
1353 new_nest = (list_state_record *) REALLOC (nest, n);
1355 if (new_nest != NULL)
1356 break; /* did we get it ? */
1358 if (current_nest_size == 0)
1359 break; /* initial allocation must work */
1361 size = size / 2; /* else can retry smaller */
1364 if (new_nest == NULL)
1366 memory_error("nest stack", n);
1367 return nest; /* try and continue !!! */
1371 update_statistics ((long) nest, n, current_nest_size);
1372 current_nest_size = new_size;
1376 printf("Current %s %d\n", "nest_size", current_nest_size);
1377 printf("New Address %s == %p\n", "nest stack", nest);
1387 #ifdef ALLOCATEPARAMSTACK
1388 int current_param_size = 0;
1390 halfword *realloc_param_stack (int size)
1393 int n = 0, new_size = 0;
1394 halfword * new_param = NULL;
1397 printf("Old Address %s == %p\n", "param stack", param_stack);
1399 if (current_param_size == param_size)
1404 min_size = current_param_size / 100 * percent_grow;
1406 if (size < min_size)
1409 if (size < initial_param_size)
1410 size = initial_param_size;
1412 for (k = 0; k < MAXSPLITS; k++)
1414 new_size = current_param_size + size;
1416 if (new_size > param_size)
1417 new_size = param_size;
1419 n = (new_size + 1) * sizeof(pointer);
1422 trace_memory("param stack", n);
1424 new_param = (pointer *) REALLOC (param_stack, n);
1426 if (new_param != NULL)
1427 break; /* did we get it ? */
1429 if (current_param_size == 0)
1430 break; /* initial allocation must work */
1432 size = size / 2; /* else can retry smaller */
1435 if (new_param == NULL)
1437 memory_error("param stack", n);
1438 return param_stack; /* try and continue !!! */
1441 param_stack = new_param;
1442 update_statistics((long) param_stack, n, current_param_size);
1443 current_param_size = new_size;
1447 printf("Current %s %d\n", "param_size", current_param_size);
1448 printf("New Address %s == %p\n", "param stack", param_stack);
1458 #ifdef ALLOCATEBUFFER
1459 int current_buf_size = 0;
1461 ASCII_code * realloc_buffer (int size)
1464 int n = 0, new_size = 0;
1465 ASCII_code * new_buffer = NULL;
1468 printf("Old Address %s == %p\n", "buffer", buffer);
1470 if (current_buf_size == buf_size)
1475 min_size = current_buf_size / 100 * percent_grow;
1477 if (size < min_size)
1480 if (size < initial_buf_size)
1481 size = initial_buf_size;
1483 for (k = 0; k < MAXSPLITS; k++)
1485 new_size = current_buf_size + size;
1487 if (new_size > buf_size)
1488 new_size = buf_size;
1490 n = (new_size + 1) * sizeof(ASCII_code);
1493 trace_memory("buffer", n);
1495 new_buffer = (ASCII_code *) REALLOC (buffer, n);
1497 if (new_buffer != NULL)
1498 break; /* did we get it ? */
1500 if (current_buf_size == 0)
1501 break; /* initial allocation must work */
1506 if (new_buffer == NULL)
1508 memory_error("buffer", n);
1509 return buffer; /* try and continue !!! */
1512 buffer = new_buffer;
1513 update_statistics ((long) buffer, n, current_buf_size);
1516 memset(buffer + current_buf_size, 0, new_size - current_buf_size);
1518 for (k = current_buf_size; k < new_size; k++)
1522 current_buf_size = new_size;
1526 printf("Current %s %d\n", "buffer", current_buf_size);
1527 printf("New Address %s == %p\n", "buffer", buffer);
1537 /* here is the main memory allocation routine -- calls the above */
1538 /* returns -1 if it fails */
1539 /* allocate rather than static 93/Nov/26 */
1540 int allocate_memory (void)
1542 #ifdef ALLOCATEINPUTSTACK
1544 current_stack_size = 0;
1545 input_stack = realloc_input_stack(initial_stack_size);
1548 #ifdef ALLOCATENESTSTACK
1550 current_nest_size = 0;
1551 nest = realloc_nest_stack(initial_nest_size);
1554 #ifdef ALLOCATEPARAMSTACK
1556 current_param_size = 0;
1557 param_stack = realloc_param_stack(initial_param_size);
1560 #ifdef ALLOCATESAVESTACK
1562 current_save_size = 0;
1563 save_stack = realloc_save_stack (initial_save_size);
1567 buffer = NULL; /* need to do earlier */
1568 current_buf_size = 0;
1569 buffer = realloc_buffer (initial_buf_size);
1572 #ifdef ALLOCATESTRING
1574 current_pool_size = 0;
1576 current_max_strings = 0;
1578 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1582 puts("ini TeX pool and string allocation");
1584 str_pool = realloc_str_pool(initial_pool_size);
1585 str_start = realloc_str_start(initial_max_strings);
1589 /* the following can save a lot of the usual 800k fixed allocation */
1592 current_font_mem_size = 0;
1593 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1594 /* if ini-TeX we need to do it here - no format file read later */
1596 font_info = realloc_font_info(initial_font_mem_size);
1602 mem_min = mem_bot; /* just to avoid complaints in texbody */
1603 mem_top = mem_initex;
1605 /* allocate main memory here if this is iniTeX */
1606 /* otherwise wait for format undumping in itex.c ... */
1609 /* avoid this if format specified on command line ??? */
1610 mem = allocate_main_memory(mem_initex); /* made variable ! */
1617 /* now for the hyphenation exception stuff */
1618 #ifdef ALLOCATEHYPHEN
1621 /* this will be overridden later by what is in format file */
1622 hyphen_prime = default_hyphen_prime;
1623 /* non ini-TeX use assumes format will be read and that specifies size */
1626 if (new_hyphen_prime)
1627 hyphen_prime = new_hyphen_prime;
1629 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1634 /* now for memory for the part of the hyphenation stuff that always needed */
1635 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1636 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1637 #ifdef ALLOCATETRIES
1640 if (allocate_tries (trie_size))
1645 /* now for memory for hyphenation stuff needed only when running iniTeX */
1649 if (allocate_ini(trie_size))
1663 return 0; // success
1666 /* returns non-zero if error - done to test integrity of stack mostly */
1667 int free_memory (void)
1669 unsigned int heap_total = 0;
1672 puts("free_memory ");
1674 if (verbose_flag || trace_flag)
1675 show_maximums(stdout);
1679 printf("Heap total: %u bytes --- max address %u\n",
1680 heap_total, max_address);
1681 printf("Main Memory: variable node %lld (%lld - %d);\n"
1682 " one word %d (%d - %d)\n",
1683 lo_mem_max - mem_min, mem_min, lo_mem_max,
1684 mem_end - hi_mem_min, hi_mem_min, mem_end);
1685 puts("Freeing memory again");
1688 /* only free memory if safe ... additional check */
1692 if (trie_taken != NULL)
1695 if (trie_hash != NULL)
1719 #ifdef ALLOCATETRIES
1720 if (trie_trc != NULL)
1723 if (trie_tro != NULL)
1726 if (trie_trl != NULL)
1734 #ifdef ALLOCATEHYPHEN
1735 if (hyph_list != NULL)
1738 if (hyph_word != NULL)
1746 if (main_memory != NULL)
1753 if (font_info != NULL)
1759 #ifdef ALLOCATESTRING
1760 if (str_start != NULL)
1763 if (str_pool != NULL)
1770 #ifdef ALLOCATEPARAMSTACK
1771 if (param_stack != NULL)
1777 #ifdef ALLOCATENESTSTACK
1784 #ifdef ALLOCATEINPUTSTACK
1785 if (input_stack != NULL)
1791 #ifdef ALLOCATESAVESTACK
1792 if (save_stack != NULL)
1798 if (format_file != NULL)
1801 if (source_direct != NULL)
1802 free(source_direct);
1805 source_direct = NULL;
1807 if (dvi_file_name != NULL)
1808 free(dvi_file_name);
1810 if (log_file_name != NULL)
1811 free(log_file_name);
1813 if (pdf_file_name != NULL)
1814 free(pdf_file_name);
1816 pdf_file_name = NULL;
1817 log_file_name = NULL;
1818 dvi_file_name = NULL;
1823 boolean prime (int x)
1826 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1831 for (k = 3; k < x; k = k + 2)
1846 boolean show_use = false;
1848 void complainarg (int c, char *s)
1850 printf("ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1854 /* following is list of allowed command line flags and args */
1856 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1858 void reorderargs (int ac, char **av)
1862 char takeargs[256]; /* large enough for all command line arg chars */
1866 return; /* no args ! */
1870 t = takeargs; /* list of those that take args */
1872 while (*s != '\0' && *(s + 1) != '\0')
1874 if (*(s + 1) == '=')
1875 *t++ = *s++; /* copy over --- without the = */
1884 show_line(takeargs, 0);
1895 if (n + 1 < ac && *(av[n] + 2) == '\0' &&
1896 strchr(takeargs, *(av[n] + 1)) != NULL)
1897 n += 2; /* step over it */
1912 while (m < ac && *av[m] != '-')
1913 m++; /* first command */
1917 /* does it take an argument ? and is this argument next ? */
1918 /* check first whether the `-x' is isolated, or arg follows directly */
1919 /* then check whether this is one of those that takes an argument */
1920 if (m+1 < ac && *(av[m] + 2) == '\0' &&
1921 strchr(takeargs, *(av[m] + 1)) != NULL)
1923 s = av[m]; /* move command down before non-command */
1927 av[m + 1] = av[m - 1];
1931 n += 2; /* step over moved args */
1935 s = av[m]; /* move command down before non-command */
1941 n++; /* step over moved args */
1946 int test_align (long address, int size, const char *str)
1950 if (size > sizeof(void *))
1951 n = address % sizeof(void *);
1956 printf("OFFSET %d (ELEMENT %d) in %s\n", n, size, str);
1961 /* activate detailed checking of alignment when trace_flag is set */
1963 void check_fixed_align (int flag)
1967 if (test_align ((long) &mem_top, 4, "FIXED ALIGNMENT"))
1969 puts("PLEASE RECOMPILE ME!");
1972 #ifdef CHECKALIGNMENT
1976 test_align ((long) &mem_top, 4, "mem_top");
1977 test_align ((long) &mem_max, 4, "mem_max");
1978 test_align ((long) &mem_min, 4, "mem_min");
1979 test_align ((long) &bad, 4, "bad");
1980 test_align ((long) &trie_size, 4, "trie_size");
1981 test_align ((long) &xord, sizeof(xord[0]), "xord");
1982 test_align ((long) &xchr, sizeof(xchr[0]), "xchr");
1983 test_align ((long) &name_length, 4, "name_length");
1984 test_align ((long) &first, 4, "first");
1985 test_align ((long) &last, 4, "last");
1986 test_align ((long) &max_buf_stack, 4, "max_buf_stack");
1987 test_align ((long) &pool_ptr, 4, "pool_ptr");
1988 test_align ((long) &str_ptr, 4, "str_ptr");
1989 test_align ((long) &init_pool_ptr, 4, "init_pool_ptr");
1990 test_align ((long) &init_str_ptr, 4, "init_str_ptr");
1991 test_align ((long) &log_file, 4, "log_file");
1992 test_align ((long) &tally, 4, "tally");
1993 test_align ((long) &term_offset, 4, "term_offset");
1994 test_align ((long) &file_offset, 4, "file_offset");
1995 test_align ((long) &trick_count, 4, "trick_count");
1996 test_align ((long) &first_count, 4, "first_count");
1997 test_align ((long) &deletions_allowed, 4, "deletions_allowed");
1998 test_align ((long) &set_box_allowed, 4, "set_box_allowed");
1999 test_align ((long) &help_line, sizeof(help_line[0]), "help_line");
2000 test_align ((long) &use_err_help, 4, "use_err_help");
2001 test_align ((long) &interrupt, 4, "interrupt");
2002 test_align ((long) &OK_to_interrupt, 4, "OK_to_interrupt");
2003 test_align ((long) &arith_error, 4, "arith_error");
2004 test_align ((long) &tex_remainder, 4, "tex_remainder");
2005 test_align ((long) &temp_ptr, 4, "temp_ptr");
2006 test_align ((long) &lo_mem_max, 4, "lo_mem_max");
2007 test_align ((long) &hi_mem_min, 4, "hi_mem_min");
2008 test_align ((long) &var_used, 4, "var_used");
2009 test_align ((long) &dyn_used, 4, "dyn_used");
2010 test_align ((long) &avail, 4, "avail");
2011 test_align ((long) &mem_end, 4, "mem_end");
2012 test_align ((long) &mem_start, 4, "mem_start");
2013 test_align ((long) &rover, 4, "rover");
2014 test_align ((long) &font_in_short_display, 4, "font_in_short_display");
2015 test_align ((long) &depth_threshold, 4, "depth_threshold");
2016 test_align ((long) &breadth_max, 4, "breadth_max");
2017 test_align ((long) &nest, sizeof(nest[0]), "nest");
2018 // test_align ((long) &xeq_level, sizeof(xeq_level[0]), "xeq_level");
2019 test_align ((long) &zzzad, sizeof(zzzad[0]), "zzzad");
2020 // test_align ((long) &hash, sizeof(hash[0]), "hash");
2021 test_align ((long) &zzzae, sizeof(zzzae[0]), "zzzae");
2022 test_align ((long) &save_stack, sizeof(save_stack[0]), "save_stack");
2023 test_align ((long) &input_stack, sizeof(input_stack[0]), "input_stack");
2024 test_align ((long) &input_file, sizeof(input_file[0]), "input_file");
2025 test_align ((long) &line_stack, sizeof(line_stack[0]), "line_stack");
2026 test_align ((long) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2027 test_align ((long) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2028 test_align ((long) &pstack, sizeof(pstack[0]), "pstack");
2029 test_align ((long) &read_file, sizeof(read_file[0]), "read_file");
2030 test_align ((long) &font_check, sizeof(font_check[0]), "font_check");
2031 test_align ((long) &font_size, sizeof(font_size[0]), "font_size");
2032 test_align ((long) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2033 test_align ((long) &font_params, sizeof(font_params[0]), "font_params");
2034 test_align ((long) &font_name, sizeof(font_name[0]), "font_name");
2035 test_align ((long) &font_area, sizeof(font_area[0]), "font_area");
2036 test_align ((long) &font_bc, sizeof(font_bc[0]), "font_bc");
2037 test_align ((long) &font_ec, sizeof(font_ec[0]), "font_ec");
2038 test_align ((long) &font_glue, sizeof(font_glue[0]), "font_glue");
2039 test_align ((long) &font_used, sizeof(font_used[0]), "font_used");
2040 test_align ((long) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2041 test_align ((long) &skew_char, sizeof(skew_char[0]), "skew_char");
2042 test_align ((long) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2043 test_align ((long) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2044 test_align ((long) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2045 test_align ((long) &char_base, sizeof(char_base[0]), "char_base");
2046 test_align ((long) &width_base, sizeof(width_base[0]), "width_base");
2047 test_align ((long) &height_base, sizeof(height_base[0]), "height_base");
2048 test_align ((long) &depth_base, sizeof(depth_base[0]), "depth_base");
2049 test_align ((long) &italic_base, sizeof(italic_base[0]), "italic_base");
2050 test_align ((long) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2051 test_align ((long) &kern_base, sizeof(kern_base[0]), "kern_base");
2052 test_align ((long) &exten_base, sizeof(exten_base[0]), "exten_base");
2053 test_align ((long) ¶m_base, sizeof(param_base[0]), "param_base");
2054 test_align ((long) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2055 test_align ((long) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2056 test_align ((long) &active_width, sizeof(active_width[0]), "active_width");
2057 test_align ((long) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2058 test_align ((long) &background, sizeof(background[0]), "background");
2059 test_align ((long) &break_width, sizeof(break_width[0]), "break_width");
2060 test_align ((long) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2061 test_align ((long) &best_place, sizeof(best_place[0]), "best_place");
2062 test_align ((long) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2063 test_align ((long) &hc, sizeof(hc[0]), "hc");
2064 test_align ((long) &hu, sizeof(hu[0]), "hu");
2065 test_align ((long) &hyf, sizeof(hyf[0]), "hyf");
2066 // test_align ((long) &x, sizeof(x[0]), "x");
2067 test_align ((long) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2068 test_align ((long) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2069 test_align ((long) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2070 test_align ((long) &op_start, sizeof(op_start[0]), "op_start");
2071 // test_align ((long) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash");
2072 test_align ((long) &trie_used, sizeof(trie_used[0]), "trie_used");
2073 /* test_align ((long) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2074 test_align ((long) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2075 test_align ((long) &trie_min, sizeof(trie_min[0]), "trie_min");
2076 test_align ((long) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2077 test_align ((long) &write_file, sizeof(write_file[0]), "write_file");
2078 test_align ((long) &write_open, sizeof(write_open[0]), "write_open");
2082 void check_alloc_align (int flag)
2086 if (test_align((long) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2087 puts("PLEASE RECOMPILE ME!");
2089 #ifdef CHECKALIGNMENT
2094 test_align ((long) eqtb, sizeof(eqtb[0]), "eqtb");
2097 test_align ((long) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2098 test_align ((long) str_start, sizeof(str_start[0]), "str_start");
2099 test_align ((long) mem, sizeof(mem[0]), "main memory");
2100 test_align ((long) font_info, sizeof(font_info[0]), "font memory");
2101 test_align ((long) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2102 test_align ((long) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2103 test_align ((long) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2104 test_align ((long) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2105 test_align ((long) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2106 /* test_align ((long) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2107 test_align ((long) trie_o, sizeof(trie_o[0]), "trie_o");
2108 test_align ((long) trie_l, sizeof(trie_l[0]), "trie_l");
2109 test_align ((long) trie_r, sizeof(trie_r[0]), "trie_r");
2110 test_align ((long) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2111 test_align ((long) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2115 boolean shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2117 /* cache to prevent allocating twice in a row */
2119 char * lastname = NULL;
2120 char * lastvalue = NULL;
2122 /* returns allocated string -- these strings are not freed again */
2123 /* is it safe to do that now ? 98/Jan/31 */
2124 char * grabenv (const char * varname)
2128 if (varname == NULL)
2131 if (*varname == '\0')
2134 if (lastname != NULL && strcasecmp(lastname, varname) == 0)
2137 printf("Cache hit: %s=%s\n", lastname, lastvalue);
2139 return xstrdup(lastvalue);
2142 s = getenv(varname);
2146 if (lastname != NULL)
2149 lastname = xstrdup(varname);
2151 if (lastvalue != NULL)
2154 lastvalue = xstrdup(s);
2162 void flush_trailing_slash (char * directory)
2166 if (strcmp(directory, "") != 0)
2168 s = directory + strlen(directory) - 1;
2170 if (*s == '\\' || *s == '/')
2175 void knuthify (void)
2177 restrict_to_ascii = false; /* don't complain non ASCII */
2178 allow_patterns = false; /* don't allow pattern redefinition */
2179 show_in_hex = true; /* show character code in hex */
2180 show_in_dos = false; /* redundant with previous */
2181 show_numeric = false; /* don't show character code decimal */
2182 show_missing = false; /* don't show missing characters */
2183 civilize_flag = false; /* don't reorder date fields */
2184 c_style_flag = false; /* don't add file name to error msg */
2185 show_fmt_flag = false; /* don't show format file in log */
2186 show_tfm_flag = false; /* don't show metric file in log */
2188 show_line_break_stats = false; /* do not show line break stats */
2189 show_fonts_used = false;
2190 default_rule = 26214; /* revert to default rule thickness */
2191 pseudo_tilde = false;
2192 pseudo_space = false;
2193 truncate_long_lines = false;
2194 allow_quoted_names = false;
2195 show_cs_names = false;
2196 ignore_frozen = false;
2197 suppress_f_ligs = false;
2198 full_file_name_flag = false;
2199 knuth_flag = true; /* so other code can know about this */
2202 /* following made global so analyze_flag can be made separate procedure */
2204 char * xchr_file = NULL;
2205 char * repl_file = NULL;
2207 const char * short_options = "m:e:h:0:H:g:P:o:l:a:r:kwvpiKLZMd2t?u";
2209 static struct option long_options[] =
2211 {"main-memory", required_argument, NULL, 'm'},
2212 {"hyph-size", required_argument, NULL, 'e'},
2213 {"trie-size", required_argument, NULL, 'h'},
2214 {"backend", required_argument, NULL, '0'},
2215 {"tab-step", required_argument, NULL, 'H'},
2216 {"percent-grow", required_argument, NULL, 'g'},
2217 {"default-rule", required_argument, NULL, 'P'},
2218 {"dvi-dir", required_argument, NULL, 'o'},
2219 {"log-dir", required_argument, NULL, 'l'},
2220 {"aux-dir", required_argument, NULL, 'a'},
2221 {"key-file", required_argument, NULL, 'k'},
2222 {"jobname", required_argument, NULL, 'r'},
2223 {"showhex", no_argument, NULL, 'w'},
2224 {"verbose", no_argument, NULL, 'v'},
2225 {"patterns", no_argument, NULL, 'p'},
2226 {"initex", no_argument, NULL, 'i'},
2227 {"knuthify", no_argument, NULL, 'K'},
2228 {"cstyle", no_argument, NULL, 'L'},
2229 {"showtfm", no_argument, NULL, 'Z'},
2230 {"showmissing", no_argument, NULL, 'M'},
2231 {"deslash", no_argument, NULL, 'd'},
2232 {"suppressflig", no_argument, NULL, '2'},
2233 {"trace", no_argument, NULL, 't'},
2234 {"help", no_argument, NULL, '?'},
2235 {"usage", no_argument, NULL, 'u'},
2239 int analyze_flag (int c, char * optarg)
2244 c_job_name = optarg;
2247 verbose_flag = true;
2253 interaction = batch_mode;
2256 interaction = nonstop_mode;
2259 interaction = scroll_mode;
2262 interaction = error_stop_mode;
2268 c_style_flag = true;
2271 show_tfm_flag = true;
2274 show_missing = false;
2280 allow_patterns = true;
2289 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2292 show_fonts_used = false;
2295 shorten_file_name = true;
2298 show_cs_names = true;
2301 ignore_frozen = true;
2304 show_line_break_stats = false; /* 96/Feb/8 */
2307 show_fmt_flag = false; /* 94/Jun/21 */
2310 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2313 full_file_name_flag = false; // 00 Jun 18
2319 quitflag++; /* 93/Dec/16 */
2321 /* The following are really obscure and should not be advertized */
2323 show_current = false;
2326 show_numeric = false;
2329 civilize_flag = false;
2332 open_trace_flag = true;
2335 reorder_arg_flag = false; /* local */
2340 mem_initex = mem_top;
2342 mem_initex = atoi(optarg) * 1024;
2344 if (mem_initex == 0)
2345 complainarg(c, optarg);
2347 mem_spec_flag = true;
2350 #ifdef VARIABLETRIESIZE
2354 //trie_size = atoi(kpse_var_value("trie_size"));
2355 trie_size = default_trie_size;
2358 trie_size = atoi(optarg);
2361 complainarg(c, optarg);
2365 #ifdef ALLOCATEHYPHEN
2368 new_hyphen_prime = hyphen_prime * 2;
2370 new_hyphen_prime = atoi(optarg);
2372 if (new_hyphen_prime == 0)
2373 complainarg(c, optarg);
2381 percent_grow = atoi(optarg);
2383 if (percent_grow == 0)
2384 complainarg(c, optarg);
2392 pseudo_tilde = atoi(optarg);
2394 if (pseudo_tilde > 255)
2396 else if (pseudo_tilde < 128)
2405 tab_step = atoi(optarg);
2407 complainarg(c, optarg);
2412 xchr_file = xstrdup("xchr.map");
2414 xchr_file = xstrdup(optarg);
2416 if (xchr_file == NULL || *xchr_file == '\0')
2417 complainarg(c, optarg);
2422 repl_file = xstrdup("repl.key");
2424 repl_file = xstrdup(optarg);
2426 if (repl_file == NULL || *repl_file == '\0')
2427 complainarg(c, optarg);
2432 default_rule = 26214;
2434 default_rule = atoi(optarg);
2436 if (default_rule == 0)
2437 complainarg(c, optarg);
2444 complainarg(c, optarg);
2451 dvi_directory = xstrdup(optarg);
2453 if (strcmp(dvi_directory, "") == 0)
2454 complainarg(c, optarg);
2462 log_directory = xstrdup(optarg);
2464 if (strcmp(log_directory, "") == 0)
2465 complainarg(c, optarg);
2473 aux_directory = xstrdup(optarg);
2475 if (strcmp(aux_directory, "") == 0)
2476 complainarg(c, optarg);
2490 void strip_name (char *pathname)
2494 if ((s = strrchr(pathname, '\\')) != NULL)
2496 else if ((s = strrchr(pathname, '/')) != NULL)
2498 else if ((s = strrchr(pathname, ':')) != NULL)
2506 int read_command_line (int ac, char **av)
2515 while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)
2517 if (optarg != 0 && *optarg == '=')
2518 optargnew = optarg + 1;
2522 analyze_flag(c, optargnew);
2525 if (show_use || quitflag == 3)
2528 strcat(log_line, "\n");
2529 show_line(log_line, 0);
2533 else if (quitflag == 3)
2535 strcat(log_line, "\n");
2536 show_line(log_line, 0);
2539 return -1; // failure
2542 if (repl_file != NULL && *repl_file != '\0')
2544 if (read_xchr_file(repl_file, 1, av))
2547 puts("KEY REPLACE ON");
2553 if (xchr_file != NULL && *xchr_file != '\0')
2555 if (read_xchr_file(xchr_file, 0, av))
2558 puts("NON ASCII ON");
2567 int init_commands (int ac, char **av)
2569 shipout_flag = out_dvi_flag;
2571 allow_patterns = false;
2572 reset_exceptions = false;
2574 key_replace = false;
2575 open_trace_flag = false;
2577 verbose_flag = false;
2578 restrict_to_ascii = false;
2579 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2580 show_in_dos = false; /* default is not to translate to DOS 850 */
2581 return_flag = true; // hard wired now
2582 trimeof = true; // hard wired now
2584 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2585 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2586 default_rule = 26214;
2587 show_current = true;
2588 civilize_flag = true;
2589 show_numeric = true;
2590 show_missing = true;
2591 c_style_flag = false;
2592 show_fmt_flag = true;
2593 show_tfm_flag = false; /* don't show metric file in log */
2594 shorten_file_name = false; /* don't shorten file names to 8+3 */
2595 truncate_long_lines = true; /* truncate long lines */
2596 tab_step = 0; /* do not replace tabs with spaces */
2597 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2598 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2599 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2600 show_cs_names = false;
2602 full_file_name_flag = true; /* new default 2000 June 18 */
2603 errout = stdout; /* as opposed to stderr say --- used ??? */
2604 new_hyphen_prime = 0;
2606 #ifdef VARIABLETRIESIZE
2607 // trie_size = default_trie_size;
2614 format_name = "plain";
2616 if (read_command_line(ac, av) < 0)
2625 void initial_memory (void)
2627 /* set initial memory allocations */
2628 if (mem_extra_high < 0)
2631 if (mem_extra_low < 0)
2639 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2640 if (mem_extra_high != 0 || mem_extra_low != 0)
2642 puts("ERROR: Cannot extend main memory in initex");
2650 if (mem_initex != 0)
2652 puts("ERROR: Can only set initial main memory size in initex");
2658 puts("ERROR: Need only set hyphenation trie size in initex");
2659 /* trie_size = 0; */
2662 if (mem_initex == 0)
2663 mem_initex = default_mem_top;
2666 trie_size = default_trie_size;
2668 /* Just in case user mistakenly specified words instead of kilo words */
2669 if (mem_extra_high > 10000L * 1024L)
2670 mem_extra_high = mem_extra_high / 1024;
2672 if (mem_extra_low > 10000L * 1024L)
2673 mem_extra_low = mem_extra_low / 1024;
2675 if (mem_initex > 10000L * 1024L)
2676 mem_initex = mem_initex / 1024;
2678 if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */
2680 puts("WARNING: There may be no benefit to asking for so much memory");
2681 /* mem_initex = 2048 * 1024; */
2684 if (new_hyphen_prime < 0)
2685 new_hyphen_prime = 0;
2687 if (new_hyphen_prime > 0)
2690 puts("ERROR: Can only set hyphen prime in initex");
2693 if (new_hyphen_prime % 2 == 0)
2696 while (!prime(new_hyphen_prime))
2697 new_hyphen_prime = new_hyphen_prime + 2;
2700 printf("Using %d as hyphen prime\n", new_hyphen_prime);
2704 if (percent_grow > 100)
2705 percent_grow = percent_grow - 100;
2707 if (percent_grow > 100)
2708 percent_grow = 100; /* upper limit - double */
2710 if (percent_grow < 10)
2711 percent_grow = 10; /* lower limit - 10% */
2714 void perrormod (const char * s)
2716 printf("`%s': %s\n", s, strerror(errno));
2719 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
2720 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
2721 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
2722 /* this is then undone in tex3.c both for fopen input and output */
2723 /* not ideal, since pseudo name appears in log and in error messages ... */
2725 void hidetwiddle (char *tname)
2731 printf("Hidetwiddle %s", tname);
2736 if (*s == '~' && pseudo_tilde != 0)
2737 *s = (char) pseudo_tilde; /* typically 254 */
2738 else if (*s == ' ' && pseudo_space != 0)
2739 *s = (char) pseudo_space; /* typically 255 */
2745 printf("=> %s\n", tname);
2749 void deslash_all (int ac, char **av)
2751 char buffer[file_name_size];
2754 if ((s = grabenv("TEXDVI")) != NULL)
2757 if ((s = grabenv("TEXLOG")) != NULL)
2760 if ((s = grabenv("TEXAUX")) != NULL)
2763 if ((s = grabenv("TEXFMT")) != NULL)
2766 if ((s = grabenv("TEXPDF")) != NULL)
2769 strcpy(buffer, av[0]);
2771 if ((s = strrchr(buffer, '\\')) != NULL)
2773 else if ((s = strrchr(buffer, '/')) != NULL)
2775 else if ((s = strrchr(buffer, ':')) != NULL)
2778 s = buffer + strlen(buffer) - 1;
2780 if (*s == '\\' || *s == '/')
2783 if (strcmp(dvi_directory, "") != 0)
2784 flush_trailing_slash(dvi_directory);
2786 if (strcmp(log_directory, "") != 0)
2787 flush_trailing_slash(log_directory);
2789 if (strcmp(aux_directory, "") != 0)
2790 flush_trailing_slash(aux_directory);
2792 if (strcmp(fmt_directory, "") != 0)
2793 flush_trailing_slash(fmt_directory);
2795 if (strcmp(pdf_directory, "") != 0)
2796 flush_trailing_slash(pdf_directory);
2800 if (strcmp(dvi_directory, "") != 0)
2801 unixify(dvi_directory);
2803 if (strcmp(log_directory, "") != 0)
2804 unixify(log_directory);
2806 if (strcmp(aux_directory, "") != 0)
2807 unixify(aux_directory);
2809 if (strcmp(fmt_directory, "") != 0)
2810 unixify(fmt_directory);
2812 if (strcmp(pdf_directory, "") != 0)
2813 unixify(pdf_directory);
2816 format_spec = false;
2818 if (optind < ac && optind > 0)
2823 printf("deslash: k %d argv[k] %s (argc %d)\n", optind, av[optind], ac);
2825 unixify(av[optind]);
2828 if (pseudo_tilde != 0 || pseudo_space != 0)
2829 hidetwiddle(av[optind]);
2831 if (*av[optind] == '&' || *av[optind] == '+')
2834 format_name = xstrdup(av[optind] + 1);
2836 if (optind + 1 < ac)
2841 printf("deslash: k %d argv[k] %s (argc %d)\n", optind + 1, av[optind + 1], ac);
2843 unixify(av[optind + 1]);
2846 if (pseudo_tilde != 0 || pseudo_space != 0)
2847 hidetwiddle(av[optind + 1]);
2853 int main_init (int ac, char ** av)
2855 kpse_set_program_name(av[0], NULL);
2856 xputenv("engine", "yandytex");
2858 if (sizeof(memory_word) != sizeof(halfword) * 2)
2859 printf("ERROR: Bad word size %ld!\n", sizeof(memory_word));
2861 start_time = clock();
2862 main_time = start_time;
2864 /* reset all allocatable memory pointers to NULL - in case we drop out */
2870 #ifdef ALLOCATESAVESTACK
2874 #ifdef ALLOCATEBUFFER
2876 current_buf_size = 0;
2877 buffer = realloc_buffer(initial_buf_size);
2892 log_opened = false; /* so can tell whether opened */
2893 interaction = -1; /* default state => 3 */
2894 missing_characters = 0; /* none yet! */
2895 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
2896 suppress_f_ligs = false; /* default is not to ignore f-ligs */
2898 if (ac > 1 && !strncmp(av[1], "-Y", 2))
2899 reorder_arg_flag = false;
2901 if (reorder_arg_flag)
2902 reorderargs(ac, av);
2904 if (init_commands(ac, av))
2907 check_fixed_align(trace_flag);
2910 source_direct = NULL;
2911 dvi_file_name = NULL;
2912 log_file_name = NULL;
2913 pdf_file_name = NULL;
2915 first_pass_count = 0;
2916 second_pass_count = 0;
2917 final_pass_count = 0;
2918 paragraph_failed = 0;
2927 puts("Entering main_init() (local.c).");
2930 ini_max_address = max_address;
2933 show_maximums(stdout);
2936 deslash_all(ac, av);
2938 if (format_spec && mem_spec_flag)
2939 puts("WARNING: Cannot change initial main_memory size when format specified");
2941 if (allocate_memory() != 0)
2944 check_alloc_align(trace_flag);
2947 puts("Leaving main_init() (local.c).");
2952 #define CLK_TCK CLOCKS_PER_SEC
2954 void show_inter_val (clock_t inter_val)
2956 int seconds, tenths, hundredth, thousands;
2958 if (inter_val >= CLK_TCK * 10)
2960 tenths = (inter_val * 10 + CLK_TCK / 2) / CLK_TCK;
2961 seconds = tenths / 10;
2962 tenths = tenths % 10;
2963 printf("%d.%d", seconds, tenths);
2965 else if (inter_val >= CLK_TCK)
2967 hundredth = (inter_val * 100 + CLK_TCK / 2) / CLK_TCK;
2968 seconds = hundredth / 100;
2969 hundredth = hundredth % 100;
2970 printf("%d.%02d", seconds, hundredth);
2972 else if (inter_val > 0)
2974 thousands = (inter_val * 1000 + CLK_TCK / 2) / CLK_TCK;
2975 seconds = thousands / 1000;
2976 thousands = thousands % 1000;
2977 printf("%d.%03d", seconds, thousands);
2985 finish_time = clock();
2987 if (missing_characters != 0)
2990 if (missing_characters)
2991 printf("! There %s %d missing character%s --- see log file\n",
2992 (missing_characters == 1) ? "was" : "were", missing_characters,
2993 (missing_characters == 1) ? "" : "s");
2995 if (free_memory() != 0)
3001 show_inter_val(finish_time - start_time);
3003 show_inter_val(main_time - start_time);
3004 printf(" format load + ");
3005 show_inter_val(finish_time - main_time);
3006 printf(" processing) ");
3008 if (total_pages > 0)
3010 show_inter_val((finish_time - main_time) / total_pages);
3011 printf(" sec per page.\n");
3017 // printf control sequences' name
3018 void print_cs_name (FILE * output, int h)
3022 memset(log_line, 0, sizeof(log_line));
3024 textof = hash[h].rh;
3029 c = sprintf(log_line, "(%d), ", h);
3032 memmove(log_line + c, str_pool + str_start[textof], n);
3033 memmove(log_line + c + n, "\n", 2);
3035 if (output == stderr)
3036 show_line(log_line, 1);
3037 else if (output == stdout)
3038 show_line(log_line, 0);
3040 fprintf(output, "%s", log_line);
3043 int compare_strn (int, int, int, int);
3044 /* compare two csnames in qsort */
3045 int compare_cs (const void *cp1, const void *cp2)
3047 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3051 textof1 = hash[c1].rh;
3052 textof2 = hash[c2].rh;
3053 l1 = length(textof1);
3054 l2 = length(textof2);
3055 k1 = str_start[textof1];
3056 k2 = str_start[textof2];
3058 return compare_strn(k1, l1, k2, l2);
3061 char * csused = NULL;
3063 /* Allocate table of indeces to allow sorting on csname */
3064 /* Allocate flags to remember which ones already listed at start */
3065 /* pass = 0 --> fmt */
3066 /* pass = 1 --> after */
3067 void print_cs_names (FILE *output, int pass)
3069 int h, k, ccount, repeatflag;
3071 int nfcs = frozen_control_sequence;
3073 if (pass == 0 && csused == NULL)
3075 csused = (char *) malloc (nfcs);
3081 memset(csused, 0, nfcs);
3083 for (h = 0; h < (hash_size + 780); h++)
3090 for (h = hash_base + 1; h < nfcs; h++)
3092 if (pass == 1 && csused[h])
3104 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
3105 ccount, (pass == 1) ? "new" : "");
3107 if (output == stderr)
3108 show_line(log_line, 1);
3109 else if (output == stdout)
3110 show_line(log_line, 0);
3112 fprintf(output, "%s", log_line);
3116 cnumtable = (int *) malloc (ccount * sizeof(int));
3118 if (cnumtable == NULL)
3123 for (h = hash_base + 1; h < nfcs; h++)
3125 if (pass == 1 && csused[h])
3128 if (hash[h].rh != 0)
3129 cnumtable[ccount++] = h;
3132 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3136 for (k = 0; k < ccount; k++)
3140 if (pass == 1 && csused[h])
3143 print_cs_name(output, h);
3146 sprintf(log_line, "\n");
3148 if (output == stderr)
3149 show_line(log_line, 1);
3150 else if (output == stdout)
3151 show_line(log_line, 0);
3153 fprintf(output, "%s", log_line);
3155 free((void *)cnumtable);
3158 if (pass == 1 && csused != NULL)
3165 /* k1 and k2 are positions in string pool */
3166 /* l1 and l2 are lengths of strings */
3167 int compare_strn (int k1, int l1, int k2, int l2)
3171 while (l1 > 0 && l2 > 0)
3186 return 1; /* first string longer */
3188 return -1; /* second string longer */
3190 return 0; /* strings match */
3192 /* compare two font names and their at sizes in qsort */
3193 int compare_fnt (const void * fp1, const void * fp2)
3195 int f1, f2, l1, l2, k1, k2, s;
3199 l1 = length(font_name[f1]);
3200 l2 = length(font_name[f2]);
3201 k1 = str_start[font_name[f1]];
3202 k2 = str_start[font_name[f2]];
3204 s = compare_strn (k1, l1, k2, l2);
3209 if (font_size[f1] > font_size[f2])
3211 else if (font_size[f1] < font_size[f2])
3214 return 0; /* should not ever get here */
3216 /* compare two font names */
3217 int compare_fnt_name (int f1, int f2)
3219 int l1, l2, k1, k2, s;
3221 l1 = length(font_name[f1]);
3222 l2 = length(font_name[f2]);
3223 k1 = str_start[font_name[f1]];
3224 k2 = str_start[font_name[f2]];
3226 s = compare_strn (k1, l1, k2, l2);
3230 /* decode checksum information */
3231 const unsigned long checkdefault = 0x59265920;
3232 int decode_fourty (unsigned long checksum, char *codingvector)
3239 strcpy(codingvector, "unknwn");
3242 else if ((checksum >> 8) == (checkdefault >> 8))
3244 strcpy (codingvector, "fixed ");
3249 for (k = 0; k < 6; k++)
3251 c = (int) (checksum % 40);
3252 checksum = checksum / 40;
3257 c = (c + '0') - ('z' - 'a') - 1;
3267 codingvector[5-k] = (char) c;
3270 codingvector[6] = '\0';
3276 double sclpnt (long x)
3280 pt = (double) x / 65536.0;
3281 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3286 void dvi_font_show (internal_font_number f, int suppressname)
3289 unsigned long checksum;
3290 char checksumvector[8];
3293 putc(' ', log_file);
3295 if (suppressname == 0)
3297 a = length(font_area[f]);
3298 l = length(font_name[f]);
3300 k = str_start[font_area[f]];
3302 memcpy(buffer, str_pool + k, length(font_area[f]));
3303 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
3305 k = str_start[font_name[f]];
3307 memcpy(buffer, str_pool + k, length(font_name[f]));
3308 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
3312 for (k = a + l; k < 16; k++)
3313 putc(' ', log_file);
3315 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3316 fputs(buffer, log_file);
3318 if (suppressname == 0)
3322 for (k = n; k < 16; k++)
3323 putc(' ', log_file);
3325 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
3326 decode_fourty(checksum, checksumvector);
3327 fprintf(log_file, "encoding: %s..", checksumvector);
3330 putc('\n', log_file);
3332 /* Allocate table of indeces to allow sorting on font name */
3333 void show_font_info (void)
3335 int k, m, fcount, repeatflag;
3340 for (k = 1; k <= font_ptr; k++)
3347 fnumtable = (short *) malloc(fcount * sizeof(short));
3349 fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
3353 for (k = 1; k <= font_ptr; k++)
3355 fnumtable[fcount++] = (short) k;
3357 qsort ((void *)fnumtable, fcount, sizeof(short), &compare_fnt);
3361 for (m = 0; m < fcount; m++)
3365 if (compare_fnt_name(fnumtable[m - 1], fnumtable[m]) == 0)
3371 dvi_font_show(fnumtable[m], repeatflag);
3374 free((void *)fnumtable);