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 (__ANDROID__)
33 #define malloc_usable_size dlmalloc_usable_size
34 #elif defined (__APPLE__)
35 #define malloc_usable_size malloc_size
38 #if defined (__clang__)
39 const char * compiler = "Clang/LLVM";
40 #elif defined (__GNUC__) || defined(__GNUG__)
41 const char * compiler = "GCC";
42 #elif defined (_MSC_VER)
43 const char * compiler = "MSVC";
47 const char * dist = "Win64";
48 #elif defined (_WIN32)
49 const char * dist = "Win32";
50 #elif defined (__ANDROID__)
51 const char * dist = "Android";
52 #elif defined (__APPLE__)
53 const char * dist = "Darwin";
54 #elif defined (__gnu_linux__)
55 const char * dist = "Linux";
57 const char * dist = "Unknown";
60 const char * compiletime = __TIME__;
61 const char * compiledate = __DATE__;
62 const char * yandyversion = "2.3.0";
63 const char * application = "Y&Y TeX";
64 const char * banner = "This is TeX, Version 3.14159265";
66 void print_banner (void)
69 sprintf(dist_ver, "%s (%s %s/%s)", banner, application, yandyversion, dist);
73 clock_t start_time, main_time, finish_time;
75 char * dvi_directory = "";
76 char * log_directory = "";
77 char * aux_directory = "";
78 char * fmt_directory = "";
79 char * pdf_directory = "";
83 boolean mem_spec_flag = false;
84 boolean format_spec = false;
85 int closed_already = 0; /* make sure we don't try this more than once */
86 boolean reorder_arg_flag = true; /* put command line flags/arguments first */
88 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
90 unsigned char wintodos[128] =
92 0, 0, 0, 159, 0, 0, 0, 0,
93 94, 0, 0, 0, 0, 0, 0, 0,
94 0, 96, 39, 0, 0, 7, 0, 0,
95 126, 0, 0, 0, 0, 0, 0, 0,
96 32, 173, 189, 156, 207, 190, 221, 21,
97 0, 184, 166, 174, 170, 45, 169, 0,
98 248, 241, 253, 252, 0, 230, 20, 250,
99 0, 251, 167, 175, 172, 171, 243, 168,
100 183, 181, 182, 199, 142, 143, 146, 128,
101 212, 144, 210, 211, 222, 214, 215, 216,
102 209, 165, 227, 224, 226, 229, 153, 158,
103 157, 235, 233, 234, 154, 237, 232, 225,
104 133, 160, 131, 198, 132, 134, 145, 135,
105 138, 130, 136, 137, 141, 161, 140, 139,
106 208, 164, 149, 162, 147, 228, 148, 246,
107 155, 151, 163, 150, 129, 236, 231, 152
110 void show_usage (void)
113 "Useage: yandytex [OPTION]... [+format_file] [tex_file]\n\n"
114 "--help -? show this usage summary\n"
115 "--initex -i start up as initex (create format file)\n"
116 "--verbose -v be verbose (show implementation version number)\n"
117 "--ascii -n do not allow `non ASCII' characters in input files\n"
118 " (complain instead)\n"
119 "--showhex -w do not show `non ASCII' characters in hexadecimal\n"
121 "--nodos -d do not allow DOS style file names - i.e. do not convert\n"
123 "--nomac -r do not allow Mac style termination - i.e. do not convert\n"
125 "--patterns -p allow use of \\patterns after loading format (initex only)\n"
126 "--knuthify -K disable all extensions to basic TeX\n"
127 "--main-mem -m initial main memory size in kilo words (initex only)\n"
128 "--hyph-size -e hyphenation exception dictionary size (initex only)\n"
129 "--trie-size -h hyphenation pattern trie size (initex only)\n"
130 "--xchr-file -x use `non ASCII' character mapping (xchr[]) defined in file\n"
131 "--key-file -k use `key replacement' defined in file\n"
132 "--dvi-dir -o write DVI file in specified directory (default '.')\n"
133 "--log-dir -l write LOG file in specified directory (default '.')\n"
134 "--aux-dir -a write AUX file in specified directory (default '.')\n");
138 // Sep 27 1990 => 1990 Sep 27
139 // 0123456789 0123456789
140 void scivilize (char * date)
145 strcpy (pyear, date + 7);
147 for (k = 5; k >= 0; k--)
148 date[k + 5] = date[k];
150 for (k = 0; k < 4; k++)
159 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35
160 void lcivilize (char * date)
165 strcpy(pyear, date + 20);
167 for (k = 18; k >= 0; k--)
168 date[k + 1] = date[k];
172 for (k = 0; k < 4; k++)
178 void stamp_it (char * s)
182 strcpy(date, compiledate);
184 sprintf(s, "%s %s (compiled time: %s %s with %s)",
185 application, yandyversion, date, compiletime, compiler);
192 void read_xchr_sub (FILE * xchr_input)
194 char buffer[file_name_size];
195 int k, from, to, count = 0;
198 memset(xchr, NOTDEF, MAXCHRS);
199 memset(xord, NOTDEF, MAXCHRS);
201 #ifdef ALLOCATEBUFFER
202 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
204 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
207 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
210 from = (int) strtol (buffer, &s, 0);
211 to = (int) strtol (s, NULL, 0);
213 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
215 if (xchr[from] == (unsigned char) NOTDEF)
216 xchr[from] = (unsigned char) to;
218 printf("NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
220 if (xord[to] == NOTDEF)
221 xord[to] = (unsigned char) from;
223 printf("NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
229 for (k = 0; k < MAXCHRS; k++)
231 if (xchr[k] == NOTDEF) /* if it has not been filled */
233 if (xord[k] == NOTDEF) /* see whether used already */
235 xchr[k] = (unsigned char) k; /* no, so make identity */
236 xord[k] = (unsigned char) k; /* no, so make identity */
241 xchr[NOTDEF] = NOTDEF; /* fixed point of mapping */
245 printf("Read %d xchr[] pairs:\n", count);
247 for (k = 0; k < MAXCHRS; k++)
249 if (xchr[k] != NOTDEF)
250 printf("%d => %d\n", k, xchr[k]);
255 char * replacement[MAXCHRS]; /* pointers to replacement strings */
257 void read_repl_sub (FILE * repl_input)
260 char buffer[file_name_size];
265 memset(replacement, 0, MAXCHRS * sizeof(replacement[0]));
267 while (fgets(buffer, file_name_size, repl_input) != NULL)
269 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
272 if ((m = sscanf(buffer, "%d%n %s", &chrs, &n, (char *)&charname)) == 0)
276 if (*charname == '"') /* deal with quoted string "..." */
281 while (*s != '"' && *s != '\0')
282 s++; /* step up to " */
285 continue; /* sanity check */
291 s++; /* is it "" perhaps ? */
294 break; /* no, end of string */
297 *t++ = *s++; /* copy over */
300 *t = '\0'; /* and terminate */
303 if (chrs >= 0 && chrs < MAXCHRS)
304 replacement[chrs] = xstrdup(charname);
306 /* presently the following can never get triggered */
307 /* which is good, because it is perhaps not right ... */
308 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
309 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
310 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
311 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
312 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
314 if (chrs >= 0 && chrs < MAXCHRS)
315 replacement[chrs] = xstrdup(charname);
318 printf("ERROR: don't understand %s", buffer);
323 puts("Key replacement table");
325 for (k = 0; k < MAXCHRS; k++)
327 if (replacement[k] != NULL)
328 printf("%d\t%s\n", k, replacement[k]);
333 /* Following used both to read xchr[] file and key replacement file */
334 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
335 int read_xchr_file (char *filename, int flag, char *argv[])
338 char infile[file_name_size];
341 if (filename == NULL)
345 printf("Reading xchr/repl %s\n", filename);
347 /* first try using file as specified */
348 strcpy(infile, filename);
351 printf("Trying %s\n", infile);
353 xchr_input = fopen (infile, "r");
355 if (xchr_input == NULL)
357 if (strrchr(infile, '.') == NULL)
360 strcat(infile, ".map");
362 strcat(infile, ".key");
365 printf("Trying %s\n", infile);
367 xchr_input = fopen(infile, "r");
371 if (xchr_input == NULL)
373 strcpy(infile, argv[0]); /* try TeX program path */
375 if ((s = strrchr (infile, '\\')) != NULL)
377 else if ((s = strrchr (infile, '/')) != NULL)
379 else if ((s = strrchr (infile, ':')) != NULL)
382 strcat (infile, filename);
385 printf("Trying %s\n", infile);
387 xchr_input = fopen (infile, "r");
389 if (xchr_input == NULL)
391 if (strchr(infile, '.') == NULL)
394 strcat(infile, ".map");
396 strcat(infile, ".key");
399 printf("Trying %s\n", infile);
401 xchr_input = fopen (infile, "r");
406 if (xchr_input == NULL)
408 strcpy(infile, argv[0]); /* try TeX program path */
410 if ((s = strrchr (infile, '\\')) != NULL)
412 else if ((s = strrchr (infile, '/')) != NULL)
414 else if ((s = strrchr (infile, ':')) != NULL)
417 strcat(infile, "keyboard\\");
418 strcat(infile, filename);
421 printf("Trying %s\n", infile);
423 xchr_input = fopen (infile, "r");
425 if (xchr_input == NULL)
427 if (strchr(infile, '.') == NULL)
430 strcat(infile, ".map");
432 strcat(infile, ".key");
435 printf("Trying %s\n", infile);
437 xchr_input = fopen (infile, "r");
442 /* Note: can't look in TeX source file dir, since that is not known yet */
443 if (xchr_input == NULL)
445 printf("ERROR: Sorry, cannot find %s file %s",
446 flag ? " xchr[]" : "key mapping", filename);
447 perrormod (filename);
452 read_xchr_sub(xchr_input);
454 read_repl_sub(xchr_input);
456 (void) fclose(xchr_input);
461 /* need to also set `key_replace' here based on command line */
462 /* need to also allocate `buffercopy' here and free at end */
463 /* need to call `readreplace' in appropriate place */
467 /* ad hoc default minimum growth in memory realloc is 62% */
468 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
469 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
470 int total_allocated = 0; /* total memory allocated so far */
471 int ini_max_address = 0; /* maximum address when starting */
472 int max_address = 0; /* maximum address seen in allocated memory */
475 void show_maximums (FILE * output)
477 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
478 fputs(log_line, output);
481 /* our own version of realloc --- avoid supposed MicroSoft version bug */
482 /* also tries _expand first, which can avoid address growth ... */
485 void * ourrealloc (void * old, size_t new_size)
488 size_t old_size, overlap;
490 /* round up to nearest multiple of four bytes */
491 /* avoid unlikely alignment */
492 if ((new_size % 4) != 0)
493 new_size = ((new_size / 4) + 1) * 4;
496 return malloc (new_size); /* no old block - use malloc */
499 old_size = _msize (old);
501 old_size = malloc_usable_size (old);
504 if (old_size >= new_size && old_size < new_size + 4)
508 mnew = _expand (old, new_size); /* first try and expand in place MSVC */
510 mnew = realloc (old, new_size);
516 printf("EXPANDED! %p (%ld) == %p (%ld)\n",
517 mnew, new_size, old, old_size);
522 /* do this if you want to call the real realloc next - */
523 mnew = realloc (old, new_size);
528 /* we are screwed typically if we ever drop through here - no more space */
529 mnew = malloc (new_size); /* otherwise find new space */
532 return mnew; /* if unable to allocate */
534 if (old_size < new_size)
539 memcpy (mnew, old, overlap); /* copy old data to new area */
540 free(old); /* free the old area */
546 void memory_error (const char * s, int n)
550 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
551 show_maximums(log_file);
554 printf("\n! Unable to allocate %d bytes for %s\n", n, s);
555 show_maximums(stderr);
558 void trace_memory (const char * s, int n)
560 printf("Allocating %d bytes for %s\n", n, s);
563 void update_statistics (long address, int size, int old_size)
565 if (address + size > max_address)
566 max_address = address + size;
568 total_allocated = total_allocated + size - old_size;
571 void probe_memory (void)
573 char * s = (char *) malloc(sizeof(void *));
575 update_statistics ((long) s, 0, 0);
578 void probe_show (void)
581 show_maximums(stdout);
584 size_t roundup (size_t n)
586 if ((n % sizeof(void *)) == 0)
589 return ((n / sizeof(void *)) + 1) * sizeof(void *);
593 /* returns -1 if it fails */
595 int allocate_tries (int trie_max)
599 if (trie_max > 1000000)
602 nl = (trie_max + 1) * sizeof(halfword);
603 no = (trie_max + 1) * sizeof(halfword);
604 nc = (trie_max + 1) * sizeof(quarterword);
608 trace_memory("hyphen trie", n);
610 trie_trl = (halfword *) malloc(roundup(nl));
611 trie_tro = (halfword *) malloc(roundup(no));
612 trie_trc = (quarterword *) malloc(roundup(nc));
614 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
616 memory_error("hyphen trie", n);
621 printf("Addresses trie_trl %p trie_tro %p trie_trc %p\n", trie_trl, trie_tro, trie_trc);
623 update_statistics((long) trie_trl, nl, 0);
624 update_statistics((long) trie_tro, no, 0);
625 update_statistics((long) trie_trc, nc, 0);
627 trie_size = trie_max;
636 #ifdef ALLOCATEHYPHEN
637 int current_prime = 0; /* remember in case reallocated later */
639 /* we don't return an address here, since TWO memory regions allocated */
640 /* plus, we don't really reallocate, we FLUSH the old information totally */
641 /* returns -1 if it fails */
643 int realloc_hyphen (int hyphen_prime)
647 if (!prime(hyphen_prime))
649 printf("ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
653 /* need not/cannot preserve old contents when hyphen prime is changed */
654 /* if (hyph_list != NULL) free(hyph_list); */
655 /* if (hyph_word != NULL) free(hyph_word); */
656 nw = (hyphen_prime + 1) * sizeof(str_number);
657 nl = (hyphen_prime + 1) * sizeof(halfword);
661 trace_memory("hyphen exception", n);
663 hyph_word = (str_number *) REALLOC (hyph_word, nw);
664 hyph_list = (halfword *) REALLOC (hyph_list, nl);
666 if (hyph_word == NULL || hyph_list == NULL)
668 memory_error("hyphen exception", n);
673 printf("Addresses hyph_word %p hyph_list %p\n", hyph_word, hyph_list);
675 /* cannot preserve old contents when hyphen prime is changed */
677 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
679 for (k = 0; k <= hyphen_prime; k++)
684 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
686 for (k = 0; k <= hyphen_prime; k++)
692 if (current_prime != 0)
694 update_statistics((long) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
695 update_statistics((long) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
699 update_statistics((long) hyph_word, nw, 0);
700 update_statistics((long) hyph_list, nl, 0);
703 current_prime = hyphen_prime;
712 int current_mem_size = 0; /* current total words in main mem allocated -1 */
714 /* this gets called from itex.c when it figures out what mem_top is */
715 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
716 /* initial allocation only, may get expanded later */
717 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
718 /* returns NULL if it fails */
721 /* initial main memory alloc - mem_top */
722 memory_word * allocate_main_memory (int size)
726 if (main_memory != NULL)
729 puts("Reallocating initial memory allocation");
732 mem_top = mem_bot + size;
734 mem_start = 0; /* bottom of memory allocated by system */
735 mem_min = 0; /* bottom of area made available to TeX */
736 n = (mem_max - mem_start + 1) * sizeof (memory_word);
739 trace_memory("main memory", n);
741 main_memory = (memory_word *) REALLOC (main_memory, n);
743 if (main_memory == NULL)
745 memory_error("initial main memory", n);
750 printf("Address main memory == %p\n", main_memory);
754 if (mem_start != 0 && !is_initex)
755 mem = main_memory - mem_start;
758 printf("Offset address main memory == %p\n", mem);
760 update_statistics((long) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));
761 /* current_mem_size = (mem_max - mem_start + 1); */
762 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
772 /* int firstallocation = 1; */
774 /* increase main memory allocation at low end and high end */
775 /* called only from tex0.c *//* called with one of lo_size or hi_size == 0 */
776 /* returns NULL if it fails */
778 memory_word * realloc_main (int lo_size, int hi_size)
783 memory_word * new_memory = NULL;
786 printf("WARNING: Entering realloc_main lo %d hi %d\n", lo_size, hi_size);
790 puts("ERROR: Cannot extent main memory in initex");
793 puts("Please use `-m=...' on command line");
799 printf("Old Address %s == %p\n", "main memory", main_memory);
801 /* if we REALLY run up to limit ! */
802 if (current_mem_size + 1 == max_mem_size)
804 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
808 /* first allocation should expand *both* lo and hi */
809 if (hi_size == 0 && mem_end == mem_max)
812 if (lo_size == 0 && mem_start == mem_min)
815 /* try and prevent excessive frequent reallocations */
816 /* while avoiding over allocation by too much */
817 min_size = current_mem_size / 100 * percent_grow;
819 if (lo_size + hi_size < min_size)
821 if (lo_size > 0 && hi_size > 0)
823 lo_size = min_size / 2;
824 hi_size = min_size / 2;
826 else if (lo_size > 0)
828 else if (hi_size > 0)
832 if (lo_size > 0 && lo_size < mem_top / 2)
833 lo_size = mem_top / 2;
835 if (hi_size > 0 && hi_size < mem_top / 2)
836 hi_size = mem_top / 2;
838 for (k = 0; k < MAXSPLITS; k++)
840 new_size = current_mem_size + lo_size + hi_size;
842 if (new_size >= max_mem_size) /* bump against limit - ha ha ha */
844 while (new_size >= max_mem_size)
846 lo_size = lo_size / 2;
847 hi_size = hi_size / 2;
848 new_size = current_mem_size + lo_size + hi_size;
852 n = (new_size + 1) * sizeof (memory_word);
855 trace_memory("main memory", n);
857 new_memory = (memory_word *) REALLOC (main_memory, n);
859 if (new_memory != NULL)
860 break; /* did we get it ? */
862 if (current_mem_size == 0)
863 break; /* in case we ever use for initial */
865 lo_size = lo_size / 2; hi_size = hi_size / 2;
868 if (new_memory == NULL)
870 memory_error("main memory", n);
875 printf("New Address %s == %p\n", "main memory", new_memory);
879 /* shift everything upward to make space for new low area */
881 printf("memmove %p %p %ld \n", new_memory + lo_size,
882 new_memory, (current_mem_size + 1) * sizeof(memory_word));
884 memmove (new_memory + lo_size, new_memory,
885 (current_mem_size + 1) * sizeof(memory_word));
886 /* could reduce words moved by (mem_max - mem_end) */
889 main_memory = new_memory; /* remember for free later */
892 mem_start = mem_start - lo_size; /* update lower limit */
895 mem_max = mem_max + hi_size; /* update upper limit */
897 update_statistics ((long) main_memory, n,
898 (current_mem_size + 1) * sizeof (memory_word));
899 current_mem_size = new_size;
901 if (current_mem_size != mem_max - mem_start)
902 puts("ERROR: Impossible Memory Error");
905 mem = main_memory - mem_start;
917 int current_font_mem_size = 0;
919 memory_word * realloc_font_info (int size)
921 memory_word * new_font_info = NULL;
927 printf("Old Address %s == %p\n", "font_info", font_info);
929 /* during initial allocation, font_info == NULL - realloc acts like malloc */
930 /* during initial allocation current_font_mem_size == 0 */
931 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
933 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
934 return font_info; /* pass it back to TeX 99/Fabe/4 */
936 /* try and prevent excessive frequent reallocations */
937 /* while avoiding over allocation by too much */
938 /* min_size = current_font_mem_size / 2; */
939 min_size = current_font_mem_size / 100 * percent_grow;
944 if (size < initial_font_mem_size)
945 size = initial_font_mem_size;
947 for (k=0; k < MAXSPLITS; k++)
949 new_size = current_font_mem_size + size;
951 if (new_size > font_mem_size)
952 new_size = font_mem_size; /* bump against limit */
954 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
955 n = (new_size + 1) * sizeof (memory_word);
958 trace_memory("font_info", n);
960 new_font_info = (memory_word *) REALLOC (font_info, n);
962 if (new_font_info != NULL)
963 break; /* did we get it ? */
965 if (current_font_mem_size == 0)
966 break; /* initial allocation must work */
971 if (new_font_info == NULL)
973 memory_error("font", n);
974 return font_info; /* try and continue !!! */
977 font_info = new_font_info;
980 printf("New Address %s == %p\n", "font_info", font_info);
982 update_statistics ((long) font_info, n, current_font_mem_size * sizeof(memory_word));
983 current_font_mem_size = new_size;
992 #ifdef ALLOCATESTRING
993 int current_pool_size = 0;
995 packed_ASCII_code * realloc_str_pool (int size)
1000 packed_ASCII_code * new_str_pool = NULL;
1003 printf("Old Address %s == %p\n", "string pool", str_pool);
1005 if (current_pool_size == pool_size)
1007 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1009 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1012 min_size = current_pool_size / 100 * percent_grow;
1014 if (size < min_size)
1017 if (size < initial_pool_size)
1018 size = initial_pool_size;
1020 for (k = 0; k < MAXSPLITS; k++)
1022 new_size = current_pool_size + size;
1024 if (new_size > pool_size)
1025 new_size = pool_size;
1026 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1027 n = (new_size + 1) * sizeof (packed_ASCII_code);
1030 trace_memory("str_pool", n);
1032 new_str_pool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1034 if (new_str_pool != NULL)
1035 break; /* did we get it ? */
1037 if (current_pool_size == 0)
1038 break; /* initial allocation must work */
1040 size = size / 2; /* else can retry smaller */
1043 if (new_str_pool == NULL)
1045 memory_error("string pool", n);
1046 return str_pool; /* try and continue !!! */
1049 str_pool = new_str_pool;
1050 update_statistics ((long) str_pool, n, current_pool_size);
1051 current_pool_size = new_size;
1054 printf("New Address %s == %p\n", "string pool", str_pool);
1063 #ifdef ALLOCATESTRING
1064 int current_max_strings = 0;
1066 pool_pointer * realloc_str_start (int size)
1071 pool_pointer * new_str_start = NULL;
1074 printf("Old Address %s == %p\n", "string start", str_start);
1076 if (current_max_strings == max_strings)
1078 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1080 return str_start; /* pass it back to TeX 99/Fabe/4 */
1083 min_size = current_max_strings / 100 * percent_grow;
1085 if (size < min_size)
1088 if (size < initial_max_strings)
1089 size = initial_max_strings;
1091 for (k = 0; k < MAXSPLITS; k++)
1093 new_size = current_max_strings + size;
1095 if (new_size > max_strings)
1096 new_size = max_strings;
1097 /* important + 1 since str_start[maxstring + 1] originally */
1098 n = (new_size + 1) * sizeof (pool_pointer);
1101 trace_memory("str_start", n);
1103 new_str_start = (pool_pointer *) REALLOC (str_start, n);
1105 if (new_str_start != NULL)
1106 break; /* did we get it ? */
1108 if (current_max_strings == 0)
1109 break; /* initial allocation must work */
1111 size = size / 2; /* otherwise can try smaller */
1114 if (new_str_start == NULL)
1116 memory_error("string pointer", n);
1117 return str_start; /* try and continue */
1120 str_start = new_str_start;
1121 update_statistics((long) str_start, n, current_max_strings * sizeof (pool_pointer));
1122 current_max_strings = new_size;
1125 printf("New Address %s == %p\n", "string start", str_start);
1135 /* returns -1 if it fails */
1136 /* size == trie_size */
1137 int allocate_ini (int size)
1139 int n, nl, no, nc, nr, nh, nt;
1141 nh = (size + 1) * sizeof(trie_pointer);
1142 nr = (size + 1) * sizeof(trie_pointer);
1143 nl = (size + 1) * sizeof(trie_pointer);
1144 no = (size + 1) * sizeof(trie_op_code);
1145 nc = (size + 1) * sizeof(packed_ASCII_code);
1146 nt = (size + 1) * sizeof(char);
1147 n = nl + no + nc + nr + nh + nt;
1150 trace_memory ("initex hyphen trie", n);
1152 trie_l = (trie_pointer *) malloc (roundup(nl));
1153 trie_o = (trie_op_code *) malloc (roundup(no));
1154 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1155 trie_r = (trie_pointer *) malloc (roundup(nr));
1156 trie_hash = (trie_pointer *) malloc (roundup(nh));
1157 trie_taken = (char *) malloc (roundup(nt));
1159 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1160 trie_hash == NULL || trie_taken == NULL)
1162 memory_error("initex hyphen trie", n);
1168 printf("Addresses: trie_l %p trie_o %p trie_c %p\n", trie_l, trie_o, trie_c);
1169 printf("Addresses: trie_r %p trie_hash %p trie_taken %p\n", trie_r, trie_hash, trie_taken);
1172 update_statistics ((long) trie_l, nl, 0);
1173 update_statistics ((long) trie_o, no, 0);
1174 update_statistics ((long) trie_c, nc, 0);
1175 update_statistics ((long) trie_r, nr, 0);
1176 update_statistics ((long) trie_hash, nh, 0);
1177 update_statistics ((long) trie_taken, nt, 0);
1182 return 0; // success
1186 #ifdef ALLOCATESAVESTACK
1187 int current_save_size = 0;
1189 memory_word * realloc_save_stack (int size)
1192 int n = 0, new_size = 0;
1193 memory_word * new_save_stack = NULL;
1196 printf("Old Address %s == %p\n", "save stack", save_stack);
1198 if (current_save_size == save_size)
1200 return save_stack; /* let TeX handle the error */
1203 min_size = current_save_size / 100 * percent_grow;
1205 if (size < min_size)
1208 if (size < initial_save_size)
1209 size = initial_save_size;
1211 for (k = 0; k < MAXSPLITS; k++)
1213 new_size = current_save_size + size;
1215 if (new_size > save_size)
1216 new_size = save_size;
1218 n = (new_size + 1) * sizeof (memory_word);
1221 trace_memory("save_stack", n);
1223 new_save_stack = (memory_word *) REALLOC (save_stack, n);
1225 if (new_save_stack != NULL)
1226 break; /* did we get it ? */
1228 if (current_save_size == 0)
1229 break; /* initial allocation must work */
1231 size = size / 2; /* else can retry smaller */
1234 if (new_save_stack == NULL)
1236 memory_error("save_stack", n);
1237 return save_stack; /* try and continue !!! */
1240 save_stack = new_save_stack;
1241 update_statistics ((long) save_stack, n, current_save_size);
1242 current_save_size = new_size;
1246 printf("Current %s %d\n", "save_size", current_save_size);
1247 printf("New Address %s == %p\n", "save stack", save_stack);
1257 #ifdef ALLOCATEINPUTSTACK
1258 int current_stack_size = 0; /* input stack size */
1260 in_state_record * realloc_input_stack (int size)
1263 int n = 0, new_size = 0;
1264 in_state_record * new_input_stack = NULL;
1267 printf("Old Address %s == %p\n", "input stack", input_stack);
1269 if (current_stack_size == stack_size)
1274 min_size = current_stack_size / 100 * percent_grow;
1276 if (size < min_size)
1279 if (size < initial_stack_size)
1280 size = initial_stack_size;
1282 for (k = 0; k < MAXSPLITS; k++)
1284 new_size = current_stack_size + size;
1286 if (new_size > stack_size)
1287 new_size = stack_size;
1289 n = (new_size + 1) * sizeof(in_state_record);
1292 trace_memory("input_stack", n);
1294 new_input_stack = (in_state_record *) REALLOC (input_stack, n);
1296 if (new_input_stack != NULL)
1297 break; /* did we get it ? */
1299 if (current_stack_size == 0)
1300 break; /* initial allocation must work */
1302 size = size / 2; /* else can retry smaller */
1305 if (new_input_stack == NULL)
1307 memory_error("input stack", n);
1308 return input_stack; /* try and continue !!! */
1311 input_stack = new_input_stack;
1312 update_statistics ((long) input_stack, n, current_stack_size);
1313 current_stack_size = new_size;
1317 printf("Current %s %d\n", "stack_size", current_stack_size);
1318 printf("New Address %s == %p\n", "input stack", input_stack);
1328 #ifdef ALLOCATENESTSTACK
1329 int current_nest_size = 0; /* current nest size */
1331 list_state_record * realloc_nest_stack (int size)
1334 int n = 0, new_size = 0;
1335 list_state_record * new_nest = NULL;
1338 printf("Old Address %s == %p\n", "nest stack", nest);
1340 if (current_nest_size == nest_size)
1345 min_size = current_nest_size / 100 * percent_grow;
1347 if (size < min_size)
1350 if (size < initial_nest_size)
1351 size = initial_nest_size;
1353 for (k = 0; k < MAXSPLITS; k++)
1355 new_size = current_nest_size + size;
1357 if (new_size > nest_size)
1358 new_size = nest_size;
1360 n = (new_size + 1) * sizeof (list_state_record);
1363 trace_memory("nest stack", n);
1365 new_nest = (list_state_record *) REALLOC (nest, n);
1367 if (new_nest != NULL)
1368 break; /* did we get it ? */
1370 if (current_nest_size == 0)
1371 break; /* initial allocation must work */
1373 size = size / 2; /* else can retry smaller */
1376 if (new_nest == NULL)
1378 memory_error("nest stack", n);
1379 return nest; /* try and continue !!! */
1383 update_statistics ((long) nest, n, current_nest_size);
1384 current_nest_size = new_size;
1388 printf("Current %s %d\n", "nest_size", current_nest_size);
1389 printf("New Address %s == %p\n", "nest stack", nest);
1399 #ifdef ALLOCATEPARAMSTACK
1400 int current_param_size = 0;
1402 halfword *realloc_param_stack (int size)
1405 int n = 0, new_size = 0;
1406 halfword * new_param = NULL;
1409 printf("Old Address %s == %p\n", "param stack", param_stack);
1411 if (current_param_size == param_size)
1416 min_size = current_param_size / 100 * percent_grow;
1418 if (size < min_size)
1421 if (size < initial_param_size)
1422 size = initial_param_size;
1424 for (k = 0; k < MAXSPLITS; k++)
1426 new_size = current_param_size + size;
1428 if (new_size > param_size)
1429 new_size = param_size;
1431 n = (new_size + 1) * sizeof(pointer);
1434 trace_memory("param stack", n);
1436 new_param = (pointer *) REALLOC (param_stack, n);
1438 if (new_param != NULL)
1439 break; /* did we get it ? */
1441 if (current_param_size == 0)
1442 break; /* initial allocation must work */
1444 size = size / 2; /* else can retry smaller */
1447 if (new_param == NULL)
1449 memory_error("param stack", n);
1450 return param_stack; /* try and continue !!! */
1453 param_stack = new_param;
1454 update_statistics((long) param_stack, n, current_param_size);
1455 current_param_size = new_size;
1459 printf("Current %s %d\n", "param_size", current_param_size);
1460 printf("New Address %s == %p\n", "param stack", param_stack);
1470 #ifdef ALLOCATEBUFFER
1471 int current_buf_size = 0;
1473 ASCII_code * realloc_buffer (int size)
1476 int n = 0, new_size = 0;
1477 ASCII_code * new_buffer = NULL;
1480 printf("Old Address %s == %p\n", "buffer", buffer);
1482 if (current_buf_size == buf_size)
1487 min_size = current_buf_size / 100 * percent_grow;
1489 if (size < min_size)
1492 if (size < initial_buf_size)
1493 size = initial_buf_size;
1495 for (k = 0; k < MAXSPLITS; k++)
1497 new_size = current_buf_size + size;
1499 if (new_size > buf_size)
1500 new_size = buf_size;
1502 n = (new_size + 1) * sizeof(ASCII_code);
1505 trace_memory("buffer", n);
1507 new_buffer = (ASCII_code *) REALLOC (buffer, n);
1509 if (new_buffer != NULL)
1510 break; /* did we get it ? */
1512 if (current_buf_size == 0)
1513 break; /* initial allocation must work */
1518 if (new_buffer == NULL)
1520 memory_error("buffer", n);
1521 return buffer; /* try and continue !!! */
1524 buffer = new_buffer;
1525 update_statistics ((long) buffer, n, current_buf_size);
1528 memset(buffer + current_buf_size, 0, new_size - current_buf_size);
1530 for (k = current_buf_size; k < new_size; k++)
1534 current_buf_size = new_size;
1538 printf("Current %s %d\n", "buffer", current_buf_size);
1539 printf("New Address %s == %p\n", "buffer", buffer);
1549 /* here is the main memory allocation routine -- calls the above */
1550 /* returns -1 if it fails */
1551 /* allocate rather than static 93/Nov/26 */
1552 int allocate_memory (void)
1554 #ifdef ALLOCATEINPUTSTACK
1556 current_stack_size = 0;
1557 input_stack = realloc_input_stack(initial_stack_size);
1560 #ifdef ALLOCATENESTSTACK
1562 current_nest_size = 0;
1563 nest = realloc_nest_stack(initial_nest_size);
1566 #ifdef ALLOCATEPARAMSTACK
1568 current_param_size = 0;
1569 param_stack = realloc_param_stack(initial_param_size);
1572 #ifdef ALLOCATESAVESTACK
1574 current_save_size = 0;
1575 save_stack = realloc_save_stack (initial_save_size);
1579 buffer = NULL; /* need to do earlier */
1580 current_buf_size = 0;
1581 buffer = realloc_buffer (initial_buf_size);
1584 #ifdef ALLOCATESTRING
1586 current_pool_size = 0;
1588 current_max_strings = 0;
1590 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1594 puts("ini TeX pool and string allocation");
1596 str_pool = realloc_str_pool(initial_pool_size);
1597 str_start = realloc_str_start(initial_max_strings);
1601 /* the following can save a lot of the usual 800k fixed allocation */
1604 current_font_mem_size = 0;
1605 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1606 /* if ini-TeX we need to do it here - no format file read later */
1608 font_info = realloc_font_info(initial_font_mem_size);
1614 mem_min = mem_bot; /* just to avoid complaints in texbody */
1615 mem_top = mem_initex;
1617 /* allocate main memory here if this is iniTeX */
1618 /* otherwise wait for format undumping in itex.c ... */
1621 /* avoid this if format specified on command line ??? */
1622 mem = allocate_main_memory(mem_initex); /* made variable ! */
1629 /* now for the hyphenation exception stuff */
1630 #ifdef ALLOCATEHYPHEN
1633 /* this will be overridden later by what is in format file */
1634 hyphen_prime = default_hyphen_prime;
1635 /* non ini-TeX use assumes format will be read and that specifies size */
1638 if (new_hyphen_prime)
1639 hyphen_prime = new_hyphen_prime;
1641 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1646 /* now for memory for the part of the hyphenation stuff that always needed */
1647 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1648 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1649 #ifdef ALLOCATETRIES
1652 if (allocate_tries (trie_size))
1657 /* now for memory for hyphenation stuff needed only when running iniTeX */
1661 if (allocate_ini(trie_size))
1675 return 0; // success
1678 /* returns non-zero if error - done to test integrity of stack mostly */
1679 int free_memory (void)
1681 unsigned int heap_total = 0;
1684 puts("free_memory ");
1686 if (verbose_flag || trace_flag)
1687 show_maximums(stdout);
1691 printf("Heap total: %u bytes --- max address %u\n",
1692 heap_total, max_address);
1693 printf("Main Memory: variable node %lld (%lld - %d);\n"
1694 " one word %d (%d - %d)\n",
1695 lo_mem_max - mem_min, mem_min, lo_mem_max,
1696 mem_end - hi_mem_min, hi_mem_min, mem_end);
1697 puts("Freeing memory again");
1700 /* only free memory if safe ... additional check */
1704 if (trie_taken != NULL)
1707 if (trie_hash != NULL)
1731 #ifdef ALLOCATETRIES
1732 if (trie_trc != NULL)
1735 if (trie_tro != NULL)
1738 if (trie_trl != NULL)
1746 #ifdef ALLOCATEHYPHEN
1747 if (hyph_list != NULL)
1750 if (hyph_word != NULL)
1758 if (main_memory != NULL)
1765 if (font_info != NULL)
1771 #ifdef ALLOCATESTRING
1772 if (str_start != NULL)
1775 if (str_pool != NULL)
1782 #ifdef ALLOCATEPARAMSTACK
1783 if (param_stack != NULL)
1789 #ifdef ALLOCATENESTSTACK
1796 #ifdef ALLOCATEINPUTSTACK
1797 if (input_stack != NULL)
1803 #ifdef ALLOCATESAVESTACK
1804 if (save_stack != NULL)
1810 if (format_file != NULL)
1813 if (source_direct != NULL)
1814 free(source_direct);
1817 source_direct = NULL;
1819 if (dvi_file_name != NULL)
1820 free(dvi_file_name);
1822 if (log_file_name != NULL)
1823 free(log_file_name);
1825 if (pdf_file_name != NULL)
1826 free(pdf_file_name);
1828 pdf_file_name = NULL;
1829 log_file_name = NULL;
1830 dvi_file_name = NULL;
1835 boolean prime (int x)
1838 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1843 for (k = 3; k < x; k = k + 2)
1858 boolean show_use = false;
1860 void complainarg (int c, char *s)
1862 printf("ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1866 /* following is list of allowed command line flags and args */
1868 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1870 void reorderargs (int ac, char **av)
1874 char takeargs[256]; /* large enough for all command line arg chars */
1878 return; /* no args ! */
1882 t = takeargs; /* list of those that take args */
1884 while (*s != '\0' && *(s + 1) != '\0')
1886 if (*(s + 1) == '=')
1887 *t++ = *s++; /* copy over --- without the = */
1896 show_line(takeargs, 0);
1907 if (n + 1 < ac && *(av[n] + 2) == '\0' &&
1908 strchr(takeargs, *(av[n] + 1)) != NULL)
1909 n += 2; /* step over it */
1924 while (m < ac && *av[m] != '-')
1925 m++; /* first command */
1929 /* does it take an argument ? and is this argument next ? */
1930 /* check first whether the `-x' is isolated, or arg follows directly */
1931 /* then check whether this is one of those that takes an argument */
1932 if (m+1 < ac && *(av[m] + 2) == '\0' &&
1933 strchr(takeargs, *(av[m] + 1)) != NULL)
1935 s = av[m]; /* move command down before non-command */
1939 av[m + 1] = av[m - 1];
1943 n += 2; /* step over moved args */
1947 s = av[m]; /* move command down before non-command */
1953 n++; /* step over moved args */
1958 int test_align (long address, int size, const char *str)
1962 if (size > sizeof(void *))
1963 n = address % sizeof(void *);
1968 printf("OFFSET %d (ELEMENT %d) in %s\n", n, size, str);
1973 /* activate detailed checking of alignment when trace_flag is set */
1975 void check_fixed_align (int flag)
1979 if (test_align ((long) &mem_top, 4, "FIXED ALIGNMENT"))
1981 puts("PLEASE RECOMPILE ME!");
1984 #ifdef CHECKALIGNMENT
1988 test_align ((long) &mem_top, 4, "mem_top");
1989 test_align ((long) &mem_max, 4, "mem_max");
1990 test_align ((long) &mem_min, 4, "mem_min");
1991 test_align ((long) &bad, 4, "bad");
1992 test_align ((long) &trie_size, 4, "trie_size");
1993 test_align ((long) &xord, sizeof(xord[0]), "xord");
1994 test_align ((long) &xchr, sizeof(xchr[0]), "xchr");
1995 test_align ((long) &name_length, 4, "name_length");
1996 test_align ((long) &first, 4, "first");
1997 test_align ((long) &last, 4, "last");
1998 test_align ((long) &max_buf_stack, 4, "max_buf_stack");
1999 test_align ((long) &pool_ptr, 4, "pool_ptr");
2000 test_align ((long) &str_ptr, 4, "str_ptr");
2001 test_align ((long) &init_pool_ptr, 4, "init_pool_ptr");
2002 test_align ((long) &init_str_ptr, 4, "init_str_ptr");
2003 test_align ((long) &log_file, 4, "log_file");
2004 test_align ((long) &tally, 4, "tally");
2005 test_align ((long) &term_offset, 4, "term_offset");
2006 test_align ((long) &file_offset, 4, "file_offset");
2007 test_align ((long) &trick_count, 4, "trick_count");
2008 test_align ((long) &first_count, 4, "first_count");
2009 test_align ((long) &deletions_allowed, 4, "deletions_allowed");
2010 test_align ((long) &set_box_allowed, 4, "set_box_allowed");
2011 test_align ((long) &help_line, sizeof(help_line[0]), "help_line");
2012 test_align ((long) &use_err_help, 4, "use_err_help");
2013 test_align ((long) &interrupt, 4, "interrupt");
2014 test_align ((long) &OK_to_interrupt, 4, "OK_to_interrupt");
2015 test_align ((long) &arith_error, 4, "arith_error");
2016 test_align ((long) &tex_remainder, 4, "tex_remainder");
2017 test_align ((long) &temp_ptr, 4, "temp_ptr");
2018 test_align ((long) &lo_mem_max, 4, "lo_mem_max");
2019 test_align ((long) &hi_mem_min, 4, "hi_mem_min");
2020 test_align ((long) &var_used, 4, "var_used");
2021 test_align ((long) &dyn_used, 4, "dyn_used");
2022 test_align ((long) &avail, 4, "avail");
2023 test_align ((long) &mem_end, 4, "mem_end");
2024 test_align ((long) &mem_start, 4, "mem_start");
2025 test_align ((long) &rover, 4, "rover");
2026 test_align ((long) &font_in_short_display, 4, "font_in_short_display");
2027 test_align ((long) &depth_threshold, 4, "depth_threshold");
2028 test_align ((long) &breadth_max, 4, "breadth_max");
2029 test_align ((long) &nest, sizeof(nest[0]), "nest");
2030 // test_align ((long) &xeq_level, sizeof(xeq_level[0]), "xeq_level");
2031 test_align ((long) &zzzad, sizeof(zzzad[0]), "zzzad");
2032 // test_align ((long) &hash, sizeof(hash[0]), "hash");
2033 test_align ((long) &zzzae, sizeof(zzzae[0]), "zzzae");
2034 test_align ((long) &save_stack, sizeof(save_stack[0]), "save_stack");
2035 test_align ((long) &input_stack, sizeof(input_stack[0]), "input_stack");
2036 test_align ((long) &input_file, sizeof(input_file[0]), "input_file");
2037 test_align ((long) &line_stack, sizeof(line_stack[0]), "line_stack");
2038 test_align ((long) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2039 test_align ((long) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2040 test_align ((long) &pstack, sizeof(pstack[0]), "pstack");
2041 test_align ((long) &read_file, sizeof(read_file[0]), "read_file");
2042 test_align ((long) &font_check, sizeof(font_check[0]), "font_check");
2043 test_align ((long) &font_size, sizeof(font_size[0]), "font_size");
2044 test_align ((long) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2045 test_align ((long) &font_params, sizeof(font_params[0]), "font_params");
2046 test_align ((long) &font_name, sizeof(font_name[0]), "font_name");
2047 test_align ((long) &font_area, sizeof(font_area[0]), "font_area");
2048 test_align ((long) &font_bc, sizeof(font_bc[0]), "font_bc");
2049 test_align ((long) &font_ec, sizeof(font_ec[0]), "font_ec");
2050 test_align ((long) &font_glue, sizeof(font_glue[0]), "font_glue");
2051 test_align ((long) &font_used, sizeof(font_used[0]), "font_used");
2052 test_align ((long) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2053 test_align ((long) &skew_char, sizeof(skew_char[0]), "skew_char");
2054 test_align ((long) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2055 test_align ((long) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2056 test_align ((long) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2057 test_align ((long) &char_base, sizeof(char_base[0]), "char_base");
2058 test_align ((long) &width_base, sizeof(width_base[0]), "width_base");
2059 test_align ((long) &height_base, sizeof(height_base[0]), "height_base");
2060 test_align ((long) &depth_base, sizeof(depth_base[0]), "depth_base");
2061 test_align ((long) &italic_base, sizeof(italic_base[0]), "italic_base");
2062 test_align ((long) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2063 test_align ((long) &kern_base, sizeof(kern_base[0]), "kern_base");
2064 test_align ((long) &exten_base, sizeof(exten_base[0]), "exten_base");
2065 test_align ((long) ¶m_base, sizeof(param_base[0]), "param_base");
2066 test_align ((long) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2067 test_align ((long) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2068 test_align ((long) &active_width, sizeof(active_width[0]), "active_width");
2069 test_align ((long) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2070 test_align ((long) &background, sizeof(background[0]), "background");
2071 test_align ((long) &break_width, sizeof(break_width[0]), "break_width");
2072 test_align ((long) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2073 test_align ((long) &best_place, sizeof(best_place[0]), "best_place");
2074 test_align ((long) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2075 test_align ((long) &hc, sizeof(hc[0]), "hc");
2076 test_align ((long) &hu, sizeof(hu[0]), "hu");
2077 test_align ((long) &hyf, sizeof(hyf[0]), "hyf");
2078 // test_align ((long) &x, sizeof(x[0]), "x");
2079 test_align ((long) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2080 test_align ((long) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2081 test_align ((long) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2082 test_align ((long) &op_start, sizeof(op_start[0]), "op_start");
2083 // test_align ((long) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash");
2084 test_align ((long) &trie_used, sizeof(trie_used[0]), "trie_used");
2085 /* test_align ((long) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2086 test_align ((long) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2087 test_align ((long) &trie_min, sizeof(trie_min[0]), "trie_min");
2088 test_align ((long) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2089 test_align ((long) &write_file, sizeof(write_file[0]), "write_file");
2090 test_align ((long) &write_open, sizeof(write_open[0]), "write_open");
2094 void check_alloc_align (int flag)
2098 if (test_align((long) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2099 puts("PLEASE RECOMPILE ME!");
2101 #ifdef CHECKALIGNMENT
2106 test_align ((long) eqtb, sizeof(eqtb[0]), "eqtb");
2109 test_align ((long) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2110 test_align ((long) str_start, sizeof(str_start[0]), "str_start");
2111 test_align ((long) mem, sizeof(mem[0]), "main memory");
2112 test_align ((long) font_info, sizeof(font_info[0]), "font memory");
2113 test_align ((long) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2114 test_align ((long) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2115 test_align ((long) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2116 test_align ((long) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2117 test_align ((long) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2118 /* test_align ((long) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2119 test_align ((long) trie_o, sizeof(trie_o[0]), "trie_o");
2120 test_align ((long) trie_l, sizeof(trie_l[0]), "trie_l");
2121 test_align ((long) trie_r, sizeof(trie_r[0]), "trie_r");
2122 test_align ((long) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2123 test_align ((long) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2127 boolean shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2129 /* cache to prevent allocating twice in a row */
2131 char * lastname = NULL;
2132 char * lastvalue = NULL;
2134 /* returns allocated string -- these strings are not freed again */
2135 /* is it safe to do that now ? 98/Jan/31 */
2136 char * grabenv (const char * varname)
2140 if (varname == NULL)
2143 if (*varname == '\0')
2146 if (lastname != NULL && strcasecmp(lastname, varname) == 0)
2149 printf("Cache hit: %s=%s\n", lastname, lastvalue);
2151 return xstrdup(lastvalue);
2154 s = getenv(varname);
2158 if (lastname != NULL)
2161 lastname = xstrdup(varname);
2163 if (lastvalue != NULL)
2166 lastvalue = xstrdup(s);
2174 void flush_trailing_slash (char * directory)
2178 if (strcmp(directory, "") != 0)
2180 s = directory + strlen(directory) - 1;
2182 if (*s == '\\' || *s == '/')
2187 void knuthify (void)
2189 restrict_to_ascii = false; /* don't complain non ASCII */
2190 allow_patterns = false; /* don't allow pattern redefinition */
2191 show_in_hex = true; /* show character code in hex */
2192 show_in_dos = false; /* redundant with previous */
2193 show_numeric = false; /* don't show character code decimal */
2194 show_missing = false; /* don't show missing characters */
2195 civilize_flag = false; /* don't reorder date fields */
2196 c_style_flag = false; /* don't add file name to error msg */
2197 show_fmt_flag = false; /* don't show format file in log */
2198 show_tfm_flag = false; /* don't show metric file in log */
2200 show_line_break_stats = false; /* do not show line break stats */
2201 show_fonts_used = false;
2202 default_rule = 26214; /* revert to default rule thickness */
2203 pseudo_tilde = false;
2204 pseudo_space = false;
2205 truncate_long_lines = false;
2206 allow_quoted_names = false;
2207 show_cs_names = false;
2208 ignore_frozen = false;
2209 suppress_f_ligs = false;
2210 full_file_name_flag = false;
2211 knuth_flag = true; /* so other code can know about this */
2214 /* following made global so analyze_flag can be made separate procedure */
2216 char * xchr_file = NULL;
2217 char * repl_file = NULL;
2219 const char * short_options = "m:e:h:0:H:g:P:o:l:a:r:kwvpiKLZMd2t?u";
2221 static struct option long_options[] =
2223 {"main-memory", required_argument, NULL, 'm'},
2224 {"hyph-size", required_argument, NULL, 'e'},
2225 {"trie-size", required_argument, NULL, 'h'},
2226 {"backend", required_argument, NULL, '0'},
2227 {"tab-step", required_argument, NULL, 'H'},
2228 {"percent-grow", required_argument, NULL, 'g'},
2229 {"default-rule", required_argument, NULL, 'P'},
2230 {"dvi-dir", required_argument, NULL, 'o'},
2231 {"log-dir", required_argument, NULL, 'l'},
2232 {"aux-dir", required_argument, NULL, 'a'},
2233 {"key-file", required_argument, NULL, 'k'},
2234 {"jobname", required_argument, NULL, 'r'},
2235 {"showhex", no_argument, NULL, 'w'},
2236 {"verbose", no_argument, NULL, 'v'},
2237 {"patterns", no_argument, NULL, 'p'},
2238 {"initex", no_argument, NULL, 'i'},
2239 {"knuthify", no_argument, NULL, 'K'},
2240 {"cstyle", no_argument, NULL, 'L'},
2241 {"showtfm", no_argument, NULL, 'Z'},
2242 {"showmissing", no_argument, NULL, 'M'},
2243 {"deslash", no_argument, NULL, 'd'},
2244 {"suppressflig", no_argument, NULL, '2'},
2245 {"trace", no_argument, NULL, 't'},
2246 {"help", no_argument, NULL, '?'},
2247 {"usage", no_argument, NULL, 'u'},
2251 int analyze_flag (int c, char * optarg)
2256 c_job_name = optarg;
2259 verbose_flag = true;
2265 interaction = batch_mode;
2268 interaction = nonstop_mode;
2271 interaction = scroll_mode;
2274 interaction = error_stop_mode;
2280 c_style_flag = true;
2283 show_tfm_flag = true;
2286 show_missing = false;
2292 allow_patterns = true;
2301 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2304 show_fonts_used = false;
2307 shorten_file_name = true;
2310 show_cs_names = true;
2313 ignore_frozen = true;
2316 show_line_break_stats = false; /* 96/Feb/8 */
2319 show_fmt_flag = false; /* 94/Jun/21 */
2322 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2325 full_file_name_flag = false; // 00 Jun 18
2331 quitflag++; /* 93/Dec/16 */
2333 /* The following are really obscure and should not be advertized */
2335 show_current = false;
2338 show_numeric = false;
2341 civilize_flag = false;
2344 open_trace_flag = true;
2347 reorder_arg_flag = false; /* local */
2352 mem_initex = mem_top;
2354 mem_initex = atoi(optarg) * 1024;
2356 if (mem_initex == 0)
2357 complainarg(c, optarg);
2359 mem_spec_flag = true;
2362 #ifdef VARIABLETRIESIZE
2366 //trie_size = atoi(kpse_var_value("trie_size"));
2367 trie_size = default_trie_size;
2370 trie_size = atoi(optarg);
2373 complainarg(c, optarg);
2377 #ifdef ALLOCATEHYPHEN
2380 new_hyphen_prime = hyphen_prime * 2;
2382 new_hyphen_prime = atoi(optarg);
2384 if (new_hyphen_prime == 0)
2385 complainarg(c, optarg);
2393 percent_grow = atoi(optarg);
2395 if (percent_grow == 0)
2396 complainarg(c, optarg);
2404 pseudo_tilde = atoi(optarg);
2406 if (pseudo_tilde > 255)
2408 else if (pseudo_tilde < 128)
2417 tab_step = atoi(optarg);
2419 complainarg(c, optarg);
2424 xchr_file = xstrdup("xchr.map");
2426 xchr_file = xstrdup(optarg);
2428 if (xchr_file == NULL || *xchr_file == '\0')
2429 complainarg(c, optarg);
2434 repl_file = xstrdup("repl.key");
2436 repl_file = xstrdup(optarg);
2438 if (repl_file == NULL || *repl_file == '\0')
2439 complainarg(c, optarg);
2444 default_rule = 26214;
2446 default_rule = atoi(optarg);
2448 if (default_rule == 0)
2449 complainarg(c, optarg);
2456 complainarg(c, optarg);
2463 dvi_directory = xstrdup(optarg);
2465 if (strcmp(dvi_directory, "") == 0)
2466 complainarg(c, optarg);
2474 log_directory = xstrdup(optarg);
2476 if (strcmp(log_directory, "") == 0)
2477 complainarg(c, optarg);
2485 aux_directory = xstrdup(optarg);
2487 if (strcmp(aux_directory, "") == 0)
2488 complainarg(c, optarg);
2502 void strip_name (char *pathname)
2506 if ((s = strrchr(pathname, '\\')) != NULL)
2508 else if ((s = strrchr(pathname, '/')) != NULL)
2510 else if ((s = strrchr(pathname, ':')) != NULL)
2518 int read_command_line (int ac, char **av)
2527 while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)
2529 if (optarg != 0 && *optarg == '=')
2530 optargnew = optarg + 1;
2534 analyze_flag(c, optargnew);
2537 if (show_use || quitflag == 3)
2540 strcat(log_line, "\n");
2541 show_line(log_line, 0);
2545 else if (quitflag == 3)
2547 strcat(log_line, "\n");
2548 show_line(log_line, 0);
2551 return -1; // failure
2554 if (repl_file != NULL && *repl_file != '\0')
2556 if (read_xchr_file(repl_file, 1, av))
2559 puts("KEY REPLACE ON");
2565 if (xchr_file != NULL && *xchr_file != '\0')
2567 if (read_xchr_file(xchr_file, 0, av))
2570 puts("NON ASCII ON");
2579 int init_commands (int ac, char **av)
2581 shipout_flag = out_dvi_flag;
2583 allow_patterns = false;
2584 reset_exceptions = false;
2586 key_replace = false;
2587 open_trace_flag = false;
2589 verbose_flag = false;
2590 restrict_to_ascii = false;
2591 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2592 show_in_dos = false; /* default is not to translate to DOS 850 */
2593 return_flag = true; // hard wired now
2594 trimeof = true; // hard wired now
2596 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2597 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2598 default_rule = 26214;
2599 show_current = true;
2600 civilize_flag = true;
2601 show_numeric = true;
2602 show_missing = true;
2603 c_style_flag = false;
2604 show_fmt_flag = true;
2605 show_tfm_flag = false; /* don't show metric file in log */
2606 shorten_file_name = false; /* don't shorten file names to 8+3 */
2607 truncate_long_lines = true; /* truncate long lines */
2608 tab_step = 0; /* do not replace tabs with spaces */
2609 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2610 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2611 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2612 show_cs_names = false;
2614 full_file_name_flag = true; /* new default 2000 June 18 */
2615 errout = stdout; /* as opposed to stderr say --- used ??? */
2616 new_hyphen_prime = 0;
2618 #ifdef VARIABLETRIESIZE
2619 // trie_size = default_trie_size;
2626 format_name = "plain";
2628 if (read_command_line(ac, av) < 0)
2637 void initial_memory (void)
2639 /* set initial memory allocations */
2640 if (mem_extra_high < 0)
2643 if (mem_extra_low < 0)
2651 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2652 if (mem_extra_high != 0 || mem_extra_low != 0)
2654 puts("ERROR: Cannot extend main memory in initex");
2662 if (mem_initex != 0)
2664 puts("ERROR: Can only set initial main memory size in initex");
2670 puts("ERROR: Need only set hyphenation trie size in initex");
2671 /* trie_size = 0; */
2674 if (mem_initex == 0)
2675 mem_initex = default_mem_top;
2678 trie_size = default_trie_size;
2680 /* Just in case user mistakenly specified words instead of kilo words */
2681 if (mem_extra_high > 10000L * 1024L)
2682 mem_extra_high = mem_extra_high / 1024;
2684 if (mem_extra_low > 10000L * 1024L)
2685 mem_extra_low = mem_extra_low / 1024;
2687 if (mem_initex > 10000L * 1024L)
2688 mem_initex = mem_initex / 1024;
2690 if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */
2692 puts("WARNING: There may be no benefit to asking for so much memory");
2693 /* mem_initex = 2048 * 1024; */
2696 if (new_hyphen_prime < 0)
2697 new_hyphen_prime = 0;
2699 if (new_hyphen_prime > 0)
2702 puts("ERROR: Can only set hyphen prime in initex");
2705 if (new_hyphen_prime % 2 == 0)
2708 while (!prime(new_hyphen_prime))
2709 new_hyphen_prime = new_hyphen_prime + 2;
2712 printf("Using %d as hyphen prime\n", new_hyphen_prime);
2716 if (percent_grow > 100)
2717 percent_grow = percent_grow - 100;
2719 if (percent_grow > 100)
2720 percent_grow = 100; /* upper limit - double */
2722 if (percent_grow < 10)
2723 percent_grow = 10; /* lower limit - 10% */
2726 void perrormod (const char * s)
2728 printf("`%s': %s\n", s, strerror(errno));
2731 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
2732 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
2733 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
2734 /* this is then undone in tex3.c both for fopen input and output */
2735 /* not ideal, since pseudo name appears in log and in error messages ... */
2737 void hidetwiddle (char *tname)
2743 printf("Hidetwiddle %s", tname);
2748 if (*s == '~' && pseudo_tilde != 0)
2749 *s = (char) pseudo_tilde; /* typically 254 */
2750 else if (*s == ' ' && pseudo_space != 0)
2751 *s = (char) pseudo_space; /* typically 255 */
2757 printf("=> %s\n", tname);
2761 void deslash_all (int ac, char **av)
2763 char buffer[file_name_size];
2766 if ((s = grabenv("TEXDVI")) != NULL)
2769 if ((s = grabenv("TEXLOG")) != NULL)
2772 if ((s = grabenv("TEXAUX")) != NULL)
2775 if ((s = grabenv("TEXFMT")) != NULL)
2778 if ((s = grabenv("TEXPDF")) != NULL)
2781 strcpy(buffer, av[0]);
2783 if ((s = strrchr(buffer, '\\')) != NULL)
2785 else if ((s = strrchr(buffer, '/')) != NULL)
2787 else if ((s = strrchr(buffer, ':')) != NULL)
2790 s = buffer + strlen(buffer) - 1;
2792 if (*s == '\\' || *s == '/')
2795 if (strcmp(dvi_directory, "") != 0)
2796 flush_trailing_slash(dvi_directory);
2798 if (strcmp(log_directory, "") != 0)
2799 flush_trailing_slash(log_directory);
2801 if (strcmp(aux_directory, "") != 0)
2802 flush_trailing_slash(aux_directory);
2804 if (strcmp(fmt_directory, "") != 0)
2805 flush_trailing_slash(fmt_directory);
2807 if (strcmp(pdf_directory, "") != 0)
2808 flush_trailing_slash(pdf_directory);
2812 if (strcmp(dvi_directory, "") != 0)
2813 unixify(dvi_directory);
2815 if (strcmp(log_directory, "") != 0)
2816 unixify(log_directory);
2818 if (strcmp(aux_directory, "") != 0)
2819 unixify(aux_directory);
2821 if (strcmp(fmt_directory, "") != 0)
2822 unixify(fmt_directory);
2824 if (strcmp(pdf_directory, "") != 0)
2825 unixify(pdf_directory);
2828 format_spec = false;
2830 if (optind < ac && optind > 0)
2835 printf("deslash: k %d argv[k] %s (argc %d)\n", optind, av[optind], ac);
2837 unixify(av[optind]);
2840 if (pseudo_tilde != 0 || pseudo_space != 0)
2841 hidetwiddle(av[optind]);
2843 if (*av[optind] == '&' || *av[optind] == '+')
2846 format_name = xstrdup(av[optind] + 1);
2848 if (optind + 1 < ac)
2853 printf("deslash: k %d argv[k] %s (argc %d)\n", optind + 1, av[optind + 1], ac);
2855 unixify(av[optind + 1]);
2858 if (pseudo_tilde != 0 || pseudo_space != 0)
2859 hidetwiddle(av[optind + 1]);
2865 int main_init (int ac, char ** av)
2867 kpse_set_program_name(av[0], NULL);
2868 xputenv("engine", "yandytex");
2870 if (sizeof(memory_word) != sizeof(halfword) * 2)
2871 printf("ERROR: Bad word size %ld!\n", sizeof(memory_word));
2873 start_time = clock();
2874 main_time = start_time;
2876 /* reset all allocatable memory pointers to NULL - in case we drop out */
2882 #ifdef ALLOCATESAVESTACK
2886 #ifdef ALLOCATEBUFFER
2888 current_buf_size = 0;
2889 buffer = realloc_buffer(initial_buf_size);
2904 log_opened = false; /* so can tell whether opened */
2905 interaction = -1; /* default state => 3 */
2906 missing_characters = 0; /* none yet! */
2907 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
2908 suppress_f_ligs = false; /* default is not to ignore f-ligs */
2910 if (ac > 1 && !strncmp(av[1], "-Y", 2))
2911 reorder_arg_flag = false;
2913 if (reorder_arg_flag)
2914 reorderargs(ac, av);
2916 if (init_commands(ac, av))
2919 check_fixed_align(trace_flag);
2922 source_direct = NULL;
2923 dvi_file_name = NULL;
2924 log_file_name = NULL;
2925 pdf_file_name = NULL;
2927 first_pass_count = 0;
2928 second_pass_count = 0;
2929 final_pass_count = 0;
2930 paragraph_failed = 0;
2939 puts("Entering main_init() (local.c).");
2942 ini_max_address = max_address;
2945 show_maximums(stdout);
2948 deslash_all(ac, av);
2950 if (format_spec && mem_spec_flag)
2951 puts("WARNING: Cannot change initial main_memory size when format specified");
2953 if (allocate_memory() != 0)
2956 check_alloc_align(trace_flag);
2959 puts("Leaving main_init() (local.c).");
2964 #define CLK_TCK CLOCKS_PER_SEC
2966 void show_inter_val (clock_t inter_val)
2968 int seconds, tenths, hundredth, thousands;
2970 if (inter_val >= CLK_TCK * 10)
2972 tenths = (inter_val * 10 + CLK_TCK / 2) / CLK_TCK;
2973 seconds = tenths / 10;
2974 tenths = tenths % 10;
2975 printf("%d.%d", seconds, tenths);
2977 else if (inter_val >= CLK_TCK)
2979 hundredth = (inter_val * 100 + CLK_TCK / 2) / CLK_TCK;
2980 seconds = hundredth / 100;
2981 hundredth = hundredth % 100;
2982 printf("%d.%02d", seconds, hundredth);
2984 else if (inter_val > 0)
2986 thousands = (inter_val * 1000 + CLK_TCK / 2) / CLK_TCK;
2987 seconds = thousands / 1000;
2988 thousands = thousands % 1000;
2989 printf("%d.%03d", seconds, thousands);
2997 finish_time = clock();
2999 if (missing_characters != 0)
3002 if (missing_characters)
3003 printf("! There %s %d missing character%s --- see log file\n",
3004 (missing_characters == 1) ? "was" : "were", missing_characters,
3005 (missing_characters == 1) ? "" : "s");
3007 if (free_memory() != 0)
3013 show_inter_val(finish_time - start_time);
3015 show_inter_val(main_time - start_time);
3016 printf(" format load + ");
3017 show_inter_val(finish_time - main_time);
3018 printf(" processing) ");
3020 if (total_pages > 0)
3022 show_inter_val((finish_time - main_time) / total_pages);
3023 printf(" sec per page.\n");
3029 // printf control sequences' name
3030 void print_cs_name (FILE * output, int h)
3034 memset(log_line, 0, sizeof(log_line));
3036 textof = hash[h].rh;
3041 c = sprintf(log_line, "(%d), ", h);
3044 memmove(log_line + c, str_pool + str_start[textof], n);
3045 memmove(log_line + c + n, "\n", 2);
3047 if (output == stderr)
3048 show_line(log_line, 1);
3049 else if (output == stdout)
3050 show_line(log_line, 0);
3052 fprintf(output, "%s", log_line);
3055 int compare_strn (int, int, int, int);
3056 /* compare two csnames in qsort */
3057 int compare_cs (const void *cp1, const void *cp2)
3059 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3063 textof1 = hash[c1].rh;
3064 textof2 = hash[c2].rh;
3065 l1 = length(textof1);
3066 l2 = length(textof2);
3067 k1 = str_start[textof1];
3068 k2 = str_start[textof2];
3070 return compare_strn(k1, l1, k2, l2);
3073 char * csused = NULL;
3075 /* Allocate table of indeces to allow sorting on csname */
3076 /* Allocate flags to remember which ones already listed at start */
3077 /* pass = 0 --> fmt */
3078 /* pass = 1 --> after */
3079 void print_cs_names (FILE *output, int pass)
3081 int h, k, ccount, repeatflag;
3083 int nfcs = frozen_control_sequence;
3085 if (pass == 0 && csused == NULL)
3087 csused = (char *) malloc (nfcs);
3093 memset(csused, 0, nfcs);
3095 for (h = 0; h < (hash_size + 780); h++)
3102 for (h = hash_base + 1; h < nfcs; h++)
3104 if (pass == 1 && csused[h])
3116 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
3117 ccount, (pass == 1) ? "new" : "");
3119 if (output == stderr)
3120 show_line(log_line, 1);
3121 else if (output == stdout)
3122 show_line(log_line, 0);
3124 fprintf(output, "%s", log_line);
3128 cnumtable = (int *) malloc (ccount * sizeof(int));
3130 if (cnumtable == NULL)
3135 for (h = hash_base + 1; h < nfcs; h++)
3137 if (pass == 1 && csused[h])
3140 if (hash[h].rh != 0)
3141 cnumtable[ccount++] = h;
3144 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3148 for (k = 0; k < ccount; k++)
3152 if (pass == 1 && csused[h])
3155 print_cs_name(output, h);
3158 sprintf(log_line, "\n");
3160 if (output == stderr)
3161 show_line(log_line, 1);
3162 else if (output == stdout)
3163 show_line(log_line, 0);
3165 fprintf(output, "%s", log_line);
3167 free((void *)cnumtable);
3170 if (pass == 1 && csused != NULL)
3177 /* k1 and k2 are positions in string pool */
3178 /* l1 and l2 are lengths of strings */
3179 int compare_strn (int k1, int l1, int k2, int l2)
3183 while (l1 > 0 && l2 > 0)
3198 return 1; /* first string longer */
3200 return -1; /* second string longer */
3202 return 0; /* strings match */
3204 /* compare two font names and their at sizes in qsort */
3205 int compare_fnt (const void * fp1, const void * fp2)
3207 int f1, f2, l1, l2, k1, k2, s;
3211 l1 = length(font_name[f1]);
3212 l2 = length(font_name[f2]);
3213 k1 = str_start[font_name[f1]];
3214 k2 = str_start[font_name[f2]];
3216 s = compare_strn (k1, l1, k2, l2);
3221 if (font_size[f1] > font_size[f2])
3223 else if (font_size[f1] < font_size[f2])
3226 return 0; /* should not ever get here */
3228 /* compare two font names */
3229 int compare_fnt_name (int f1, int f2)
3231 int l1, l2, k1, k2, s;
3233 l1 = length(font_name[f1]);
3234 l2 = length(font_name[f2]);
3235 k1 = str_start[font_name[f1]];
3236 k2 = str_start[font_name[f2]];
3238 s = compare_strn (k1, l1, k2, l2);
3242 /* decode checksum information */
3243 const unsigned long checkdefault = 0x59265920;
3244 int decode_fourty (unsigned long checksum, char *codingvector)
3251 strcpy(codingvector, "unknwn");
3254 else if ((checksum >> 8) == (checkdefault >> 8))
3256 strcpy (codingvector, "fixed ");
3261 for (k = 0; k < 6; k++)
3263 c = (int) (checksum % 40);
3264 checksum = checksum / 40;
3269 c = (c + '0') - ('z' - 'a') - 1;
3279 codingvector[5-k] = (char) c;
3282 codingvector[6] = '\0';
3288 double sclpnt (long x)
3292 pt = (double) x / 65536.0;
3293 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3298 void dvi_font_show (internal_font_number f, int suppressname)
3301 unsigned long checksum;
3302 char checksumvector[8];
3305 putc(' ', log_file);
3307 if (suppressname == 0)
3309 a = length(font_area[f]);
3310 l = length(font_name[f]);
3312 k = str_start[font_area[f]];
3314 memcpy(buffer, str_pool + k, length(font_area[f]));
3315 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
3317 k = str_start[font_name[f]];
3319 memcpy(buffer, str_pool + k, length(font_name[f]));
3320 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
3324 for (k = a + l; k < 16; k++)
3325 putc(' ', log_file);
3327 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3328 fputs(buffer, log_file);
3330 if (suppressname == 0)
3334 for (k = n; k < 16; k++)
3335 putc(' ', log_file);
3337 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
3338 decode_fourty(checksum, checksumvector);
3339 fprintf(log_file, "encoding: %s..", checksumvector);
3342 putc('\n', log_file);
3344 /* Allocate table of indeces to allow sorting on font name */
3345 void show_font_info (void)
3347 int k, m, fcount, repeatflag;
3352 for (k = 1; k <= font_ptr; k++)
3359 fnumtable = (short *) malloc(fcount * sizeof(short));
3361 fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
3365 for (k = 1; k <= font_ptr; k++)
3367 fnumtable[fcount++] = (short) k;
3369 qsort ((void *)fnumtable, fcount, sizeof(short), &compare_fnt);
3373 for (m = 0; m < fcount; m++)
3377 if (compare_fnt_name(fnumtable[m - 1], fnumtable[m]) == 0)
3383 dvi_font_show(fnumtable[m], repeatflag);
3386 free((void *)fnumtable);