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 * tex_version = "This is TeX, Version 3.14159265";
46 clock_t start_time, main_time, finish_time;
48 char * dvi_directory = "";
49 char * log_directory = "";
50 char * aux_directory = "";
51 char * fmt_directory = "";
52 char * pdf_directory = "";
54 char log_line[MAXLINE]; // used also in tex9.c
56 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
57 int format_spec = 0; /* non-zero if a format specified on command line */
58 int closed_already = 0; /* make sure we don't try this more than once */
59 boolean reorder_arg_flag = true; /* put command line flags/arguments first */
61 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
62 /* Used in tex0.c with wintodos[c-128] */
64 unsigned char wintodos[128] =
66 0, 0, 0, 159, 0, 0, 0, 0,
67 94, 0, 0, 0, 0, 0, 0, 0,
68 0, 96, 39, 0, 0, 7, 0, 0,
69 126, 0, 0, 0, 0, 0, 0, 0,
70 32, 173, 189, 156, 207, 190, 221, 21,
71 0, 184, 166, 174, 170, 45, 169, 0,
72 248, 241, 253, 252, 0, 230, 20, 250,
73 0, 251, 167, 175, 172, 171, 243, 168,
74 183, 181, 182, 199, 142, 143, 146, 128,
75 212, 144, 210, 211, 222, 214, 215, 216,
76 209, 165, 227, 224, 226, 229, 153, 158,
77 157, 235, 233, 234, 154, 237, 232, 225,
78 133, 160, 131, 198, 132, 134, 145, 135,
79 138, 130, 136, 137, 141, 161, 140, 139,
80 208, 164, 149, 162, 147, 228, 148, 246,
81 155, 151, 163, 150, 129, 236, 231, 152
84 void show_usage (void)
87 " Useage: yanytex [OPTION]... [+format_file] [tex_file]\n\n"
89 " show this usage summary\n"
91 " start up as iniTeX (create format file)\n"
93 " be verbose (show implementation version number)\n"
94 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
96 " do not show `non ASCII' characters in hexadecimal (show as is)\n"
97 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
98 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
100 " allow use of \\patterns after loading format (iniTeX only)\n"
102 " disable all extensions to basic TeX\n"
103 " --main-memory -m\n"
104 " initial main memory size in kilo words (iniTeX only)\n"
106 " hyphenation exception dictionary size (iniTeX only)\n"
108 " hyphenation pattern trie size (iniTeX only)\n"
110 " use `non ASCII' character mapping (xchr[]) defined in file\n"
112 " use `key replacement' defined in file\n"
114 " write DVI file in specified directory (default current directory)\n"
116 " write LOG file in specified directory (default current directory)\n"
118 " write AUX file in specified directory (default current directory)\n");
121 uexit(EXIT_FAILURE); // has this been setup yet ???
125 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
127 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
128 /* \t\t(applies to file name and format file name, if present)\n\ */
129 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
131 // Sep 27 1990 => 1990 Sep 27
132 // 012456789 0123456789
133 void scivilize (char * date)
138 strcpy (pyear, date + 7);
140 for (k = 5; k >= 0; k--)
141 date[k + 5] = date[k];
143 for (k = 0; k < 4; k++)
149 date[9] = '0'; /* replace space by '0' */
152 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35
153 void lcivilize (char * date)
158 strcpy (pyear, date + 20);
160 for (k = 18; k >= 0; k--)
165 for (k = 0; k < 4; k++)
171 // now writes result into given buffer
172 void stamp_it (char *s)
176 strcpy(date, compiledate);
178 sprintf(s, "%s %s ", application, yandyversion);
180 sprintf(s, "(compiled time: %s %s %s)", date, compiletime, compiler);
187 void read_xchr_sub (FILE * xchr_input)
189 char buffer[file_name_size];
190 int k, from, to, count = 0;
193 memset(xchr, NOTDEF, MAXCHRS);
194 memset(xord, NOTDEF, MAXCHRS);
196 #ifdef ALLOCATEBUFFER
197 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
199 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
202 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
205 from = (int) strtol (buffer, &s, 0);
206 to = (int) strtol (s, NULL, 0);
208 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
210 if (xchr[from] == (unsigned char) NOTDEF)
211 xchr[from] = (unsigned char) to;
213 printf("NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
215 if (xord[to] == NOTDEF)
216 xord[to] = (unsigned char) from;
218 printf("NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
224 for (k = 0; k < MAXCHRS; k++)
226 if (xchr[k] == NOTDEF) /* if it has not been filled */
228 if (xord[k] == NOTDEF) /* see whether used already */
230 xchr[k] = (unsigned char) k; /* no, so make identity */
231 xord[k] = (unsigned char) k; /* no, so make identity */
236 xchr[NOTDEF] = NOTDEF; /* fixed point of mapping */
240 printf("Read %d xchr[] pairs:\n", count);
242 for (k = 0; k < MAXCHRS; k++)
244 if (xchr[k] != NOTDEF)
245 printf("%d => %d\n", k, xchr[k]);
250 char *replacement[MAXCHRS]; /* pointers to replacement strings */
252 void read_repl_sub (FILE * repl_input)
255 char buffer[file_name_size];
260 memset(replacement, 0, MAXCHRS * sizeof(replacement[0]));
262 while (fgets(buffer, file_name_size, repl_input) != NULL)
264 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
267 if ((m = sscanf(buffer, "%d%n %s", &chrs, &n, (char *)&charname)) == 0)
271 if (*charname == '"') /* deal with quoted string "..." */
276 while (*s != '"' && *s != '\0')
277 s++; /* step up to " */
280 continue; /* sanity check */
286 s++; /* is it "" perhaps ? */
289 break; /* no, end of string */
292 *t++ = *s++; /* copy over */
295 *t = '\0'; /* and terminate */
298 if (chrs >= 0 && chrs < MAXCHRS)
299 replacement[chrs] = xstrdup(charname);
301 /* presently the following can never get triggered */
302 /* which is good, because it is perhaps not right ... */
303 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
304 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
305 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
306 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
307 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
309 if (chrs >= 0 && chrs < MAXCHRS)
310 replacement[chrs] = xstrdup(charname);
313 printf("ERROR: don't understand %s", buffer);
318 puts("Key replacement table");
320 for (k = 0; k < MAXCHRS; k++)
322 if (replacement[k] != NULL)
323 printf("%d\t%s\n", k, replacement[k]);
328 /* Following used both to read xchr[] file and key replacement file */
329 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
330 int read_xchr_file (char *filename, int flag, char *argv[])
333 char infile[file_name_size];
336 if (filename == NULL)
340 printf("Reading xchr/repl %s\n", filename);
342 /* first try using file as specified */
343 strcpy(infile, filename);
346 printf("Trying %s\n", infile);
348 xchr_input = fopen (infile, "r");
350 if (xchr_input == NULL)
352 if (strrchr(infile, '.') == NULL)
355 strcat(infile, ".map");
357 strcat(infile, ".key");
360 printf("Trying %s\n", infile);
362 xchr_input = fopen(infile, "r");
366 if (xchr_input == NULL)
368 strcpy(infile, argv[0]); /* try TeX program path */
370 if ((s = strrchr (infile, '\\')) != NULL)
372 else if ((s = strrchr (infile, '/')) != NULL)
374 else if ((s = strrchr (infile, ':')) != NULL)
377 strcat (infile, filename);
380 printf("Trying %s\n", infile);
382 xchr_input = fopen (infile, "r");
384 if (xchr_input == NULL)
386 if (strchr(infile, '.') == NULL)
389 strcat(infile, ".map");
391 strcat(infile, ".key");
394 printf("Trying %s\n", infile);
396 xchr_input = fopen (infile, "r");
401 if (xchr_input == NULL)
403 strcpy (infile, argv[0]); /* try TeX program path */
405 if ((s = strrchr (infile, '\\')) != NULL)
407 else if ((s = strrchr (infile, '/')) != NULL)
409 else if ((s = strrchr (infile, ':')) != NULL)
412 strcat(infile, "keyboard\\");
413 strcat(infile, filename);
416 printf("Trying %s\n", infile);
418 xchr_input = fopen (infile, "r");
420 if (xchr_input == NULL)
422 if (strchr(infile, '.') == NULL)
425 strcat(infile, ".map");
427 strcat(infile, ".key");
430 printf("Trying %s\n", infile);
432 xchr_input = fopen (infile, "r");
436 /* Note: can't look in TeX source file dir, since that is not known yet */
437 if (xchr_input == NULL)
439 printf("ERROR: Sorry, cannot find %s file %s",
440 flag ? " xchr[]" : "key mapping", filename);
441 perrormod (filename);
446 read_xchr_sub(xchr_input);
448 read_repl_sub(xchr_input);
450 (void) fclose(xchr_input);
455 /* need to also set `key_replace' here based on command line */
456 /* need to also allocate `buffercopy' here and free at end */
457 /* need to call `readreplace' in appropriate place */
459 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
463 /* ad hoc default minimum growth in memory realloc is 62% */
464 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
465 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
466 int total_allocated = 0; /* total memory allocated so far */
467 int ini_max_address = 0; /* maximum address when starting */
468 int max_address = 0; /* maximum address seen in allocated memory */
471 void show_maximums (FILE * output)
473 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
474 fputs(log_line, output);
477 /* our own version of realloc --- avoid supposed MicroSoft version bug */
478 /* also tries _expand first, which can avoid address growth ... */
481 void *ourrealloc (void *old, size_t new_size)
484 size_t old_size, overlap;
486 /* round up to nearest multiple of four bytes */
487 /* avoid unlikely alignment */
488 if ((new_size % 4) != 0)
489 new_size = ((new_size / 4) + 1) * 4;
492 return malloc (new_size); /* no old block - use malloc */
495 old_size = _msize (old);
497 old_size = malloc_usable_size (old);
500 if (old_size >= new_size && old_size < new_size + 4)
504 mnew = _expand (old, new_size); /* first try and expand in place MSVC */
506 mnew = realloc (old, new_size);
512 printf("EXPANDED! %p (%ld) == %p (%ld)\n",
513 mnew, new_size, old, old_size);
518 /* do this if you want to call the real realloc next - */
519 mnew = realloc (old, new_size);
524 /* we are screwed typically if we ever drop through here - no more space */
525 mnew = malloc (new_size); /* otherwise find new space */
528 return mnew; /* if unable to allocate */
530 if (old_size < new_size)
535 memcpy (mnew, old, overlap); /* copy old data to new area */
536 free(old); /* free the old area */
542 void memory_error (const char * s, int n)
546 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
547 show_maximums(log_file);
550 printf("\n! Unable to allocate %d bytes for %s\n", n, s);
551 show_maximums(stderr);
554 void trace_memory (const char * s, int n)
556 printf("Allocating %d bytes for %s\n", n, s);
559 void update_statistics (long address, int size, int old_size)
561 if (address + size > max_address)
562 max_address = address + size;
564 total_allocated = total_allocated + size - old_size;
567 void probe_memory (void)
569 char *s = (char *) malloc(sizeof(void *)); /* get current top address */
571 update_statistics ((long) s, 0, 0); /* show where we are */
574 void probe_show (void)
577 show_maximums(stdout);
580 size_t roundup (size_t n)
582 if ((n % sizeof(void *)) == 0)
585 return ((n / sizeof(void *)) + 1) * sizeof(void *);
589 /* returns -1 if it fails */
591 int allocate_tries (int trie_max)
595 if (trie_max > 1000000)
598 nl = (trie_max + 1) * sizeof(halfword);
599 no = (trie_max + 1) * sizeof(halfword);
600 nc = (trie_max + 1) * sizeof(quarterword);
604 trace_memory("hyphen trie", n);
606 trie_trl = (halfword *) malloc(roundup(nl));
607 trie_tro = (halfword *) malloc(roundup(no));
608 trie_trc = (quarterword *) malloc(roundup(nc));
610 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
612 memory_error("hyphen trie", n);
617 printf("Addresses trie_trl %p trie_tro %p trie_trc %p\n", trie_trl, trie_tro, trie_trc);
619 update_statistics((long) trie_trl, nl, 0);
620 update_statistics((long) trie_tro, no, 0);
621 update_statistics((long) trie_trc, nc, 0);
623 trie_size = trie_max;
632 #ifdef ALLOCATEHYPHEN
633 int current_prime = 0; /* remember in case reallocated later */
635 /* we don't return an address here, since TWO memory regions allocated */
636 /* plus, we don't really reallocate, we FLUSH the old information totally */
637 /* returns -1 if it fails */
639 int realloc_hyphen (int hyphen_prime)
643 if (!prime(hyphen_prime))
645 printf("ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
649 /* need not/cannot preserve old contents when hyphen prime is changed */
650 /* if (hyph_list != NULL) free(hyph_list); */
651 /* if (hyph_word != NULL) free(hyph_word); */
652 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
653 nw = (hyphen_prime + 1) * sizeof(str_number);
654 nl = (hyphen_prime + 1) * sizeof(halfword);
658 trace_memory("hyphen exception", n);
660 hyph_word = (str_number *) REALLOC (hyph_word, nw);
661 hyph_list = (halfword *) REALLOC (hyph_list, nl);
663 if (hyph_word == NULL || hyph_list == NULL)
665 memory_error("hyphen exception", n);
670 printf("Addresses hyph_word %p hyph_list %p\n", hyph_word, hyph_list);
672 /* cannot preserve old contents when hyphen prime is changed */
674 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
676 for (k = 0; k <= hyphen_prime; k++)
681 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
683 for (k = 0; k <= hyphen_prime; k++)
689 if (current_prime != 0)
691 update_statistics((long) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
692 update_statistics((long) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
696 update_statistics((long) hyph_word, nw, 0);
697 update_statistics((long) hyph_list, nl, 0);
700 current_prime = hyphen_prime;
709 int current_mem_size = 0; /* current total words in main mem allocated -1 */
711 /* this gets called from itex.c when it figures out what mem_top is */
712 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
713 /* initial allocation only, may get expanded later */
714 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
715 /* returns NULL if it fails */
718 /* initial main memory alloc - mem_top */
719 memory_word * allocate_main_memory (int size)
723 if (main_memory != NULL)
726 puts("Reallocating initial memory allocation");
729 mem_top = mem_bot + size;
731 mem_start = 0; /* bottom of memory allocated by system */
732 mem_min = 0; /* bottom of area made available to TeX */
733 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
736 trace_memory("main memory", n);
738 main_memory = (memory_word *) REALLOC (main_memory, n);
740 if (main_memory == NULL)
742 memory_error("initial main memory", n);
748 printf("Address main memory == %p\n", main_memory);
752 if (mem_start != 0 && !is_initex)
753 mem = main_memory - mem_start;
756 printf("Offset address main memory == %p\n", mem);
758 update_statistics((long) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));
759 /* current_mem_size = (mem_max - mem_start + 1); */
760 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
770 /* int firstallocation = 1; */
772 /* increase main memory allocation at low end and high end */
773 /* called only from tex0.c *//* called with one of lo_size or hi_size == 0 */
774 /* returns NULL if it fails */
776 memory_word * realloc_main (int lo_size, int hi_size)
781 memory_word * new_memory = NULL;
784 printf("WARNING: Entering realloc_main lo %d hi %d\n", lo_size, hi_size);
788 puts("ERROR: Cannot extent main memory in iniTeX");
791 puts("Please use `-m=...' on command line");
797 printf("Old Address %s == %p\n", "main memory", main_memory);
799 /* if we REALLY run up to limit ! */
800 if (current_mem_size + 1 == max_mem_size)
802 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
806 /* first allocation should expand *both* lo and hi */
807 if (hi_size == 0 && mem_end == mem_max)
810 if (lo_size == 0 && mem_start == mem_min)
813 /* try and prevent excessive frequent reallocations */
814 /* while avoiding over allocation by too much */
815 min_size = current_mem_size / 100 * percent_grow;
817 if (lo_size + hi_size < min_size)
819 if (lo_size > 0 && hi_size > 0)
821 lo_size = min_size / 2;
822 hi_size = min_size / 2;
824 else if (lo_size > 0)
826 else if (hi_size > 0)
830 if (lo_size > 0 && lo_size < mem_top / 2)
831 lo_size = mem_top / 2;
833 if (hi_size > 0 && hi_size < mem_top / 2)
834 hi_size = mem_top / 2;
836 for (k = 0; k < MAXSPLITS; k++)
838 new_size = current_mem_size + lo_size + hi_size;
840 if (new_size >= max_mem_size) /* bump against limit - ha ha ha */
842 while (new_size >= max_mem_size)
844 lo_size = lo_size / 2;
845 hi_size = hi_size / 2;
846 new_size = current_mem_size + lo_size + hi_size;
850 n = (new_size + 1) * sizeof (memory_word);
853 trace_memory("main memory", n);
855 new_memory = (memory_word *) REALLOC (main_memory, n);
857 if (new_memory != NULL)
858 break; /* did we get it ? */
860 if (current_mem_size == 0)
861 break; /* in case we ever use for initial */
863 lo_size = lo_size / 2; hi_size = hi_size / 2;
866 if (new_memory == NULL)
868 memory_error("main memory", n);
873 printf("New Address %s == %p\n", "main memory", new_memory);
877 /* shift everything upward to make space for new low area */
879 printf("memmove %p %p %ld \n", new_memory + lo_size,
880 new_memory, (current_mem_size + 1) * sizeof(memory_word));
882 memmove (new_memory + lo_size, new_memory,
883 (current_mem_size + 1) * sizeof(memory_word));
884 /* could reduce words moved by (mem_max - mem_end) */
887 main_memory = new_memory; /* remember for free later */
890 mem_start = mem_start - lo_size; /* update lower limit */
893 mem_max = mem_max + hi_size; /* update upper limit */
895 update_statistics ((long) main_memory, n,
896 (current_mem_size + 1) * sizeof (memory_word));
897 current_mem_size = new_size;
899 if (current_mem_size != mem_max - mem_start)
901 puts("ERROR: Impossible Memory Error");
905 mem = main_memory - mem_start;
917 int current_font_mem_size = 0;
919 /* fmemoryword can be either halfword or memory_word */
920 memory_word * realloc_font_info (int size)
922 memory_word * new_font_info = NULL;
928 printf("Old Address %s == %p\n", "font_info", font_info);
930 /* during initial allocation, font_info == NULL - realloc acts like malloc */
931 /* during initial allocation current_font_mem_size == 0 */
932 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
934 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
935 return font_info; /* pass it back to TeX 99/Fabe/4 */
937 /* try and prevent excessive frequent reallocations */
938 /* while avoiding over allocation by too much */
939 /* min_size = current_font_mem_size / 2; */
940 min_size = current_font_mem_size / 100 * percent_grow;
945 if (size < initial_font_mem_size)
946 size = initial_font_mem_size;
948 for (k=0; k < MAXSPLITS; k++)
950 new_size = current_font_mem_size + size;
952 if (new_size > font_mem_size)
953 new_size = font_mem_size; /* bump against limit */
955 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
956 n = (new_size + 1) * sizeof (memory_word);
959 trace_memory("font_info", n);
961 new_font_info = (memory_word *) REALLOC (font_info, n);
963 if (new_font_info != NULL)
964 break; /* did we get it ? */
966 if (current_font_mem_size == 0)
967 break; /* initial allocation must work */
972 if (new_font_info == NULL)
974 memory_error("font", n);
975 return font_info; /* try and continue !!! */
978 font_info = new_font_info;
981 printf("New Address %s == %p\n", "font_info", font_info);
983 update_statistics ((long) font_info, n, current_font_mem_size * sizeof(memory_word));
984 current_font_mem_size = new_size;
993 #ifdef ALLOCATESTRING
994 int current_pool_size = 0;
996 packed_ASCII_code * realloc_str_pool (int size)
1001 packed_ASCII_code *newstrpool = NULL;
1004 printf("Old Address %s == %p\n", "string pool", str_pool);
1006 if (current_pool_size == pool_size)
1008 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1010 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1013 min_size = current_pool_size / 100 * percent_grow;
1015 if (size < min_size)
1018 if (size < initial_pool_size)
1019 size = initial_pool_size;
1021 for (k = 0; k < MAXSPLITS; k++)
1023 new_size = current_pool_size + size;
1025 if (new_size > pool_size)
1026 new_size = pool_size;
1027 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1028 n = (new_size + 1) * sizeof (packed_ASCII_code);
1031 trace_memory("str_pool", n);
1033 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1035 if (newstrpool != NULL)
1036 break; /* did we get it ? */
1038 if (current_pool_size == 0)
1039 break; /* initial allocation must work */
1041 size = size / 2; /* else can retry smaller */
1044 if (newstrpool == NULL)
1046 memory_error("string pool", n);
1047 return str_pool; /* try and continue !!! */
1050 str_pool = newstrpool;
1051 update_statistics ((long) str_pool, n, current_pool_size);
1052 current_pool_size = new_size;
1055 printf("New Address %s == %p\n", "string pool", str_pool);
1064 #ifdef ALLOCATESTRING
1065 int current_max_strings = 0;
1067 pool_pointer *realloc_str_start (int size)
1072 pool_pointer * new_str_start = NULL;
1075 printf("Old Address %s == %p\n", "string start", str_start);
1077 if (current_max_strings == max_strings)
1079 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1081 return str_start; /* pass it back to TeX 99/Fabe/4 */
1084 min_size = current_max_strings / 100 * percent_grow;
1086 if (size < min_size)
1089 if (size < initial_max_strings)
1090 size = initial_max_strings;
1092 for (k = 0; k < MAXSPLITS; k++)
1094 new_size = current_max_strings + size;
1096 if (new_size > max_strings)
1097 new_size = max_strings;
1098 /* important + 1 since str_start[maxstring + 1] originally */
1099 n = (new_size + 1) * sizeof (pool_pointer);
1102 trace_memory("str_start", n);
1104 new_str_start = (pool_pointer *) REALLOC (str_start, n);
1106 if (new_str_start != NULL)
1107 break; /* did we get it ? */
1109 if (current_max_strings == 0)
1110 break; /* initial allocation must work */
1112 size = size / 2; /* otherwise can try smaller */
1115 if (new_str_start == NULL)
1117 memory_error("string pointer", n);
1118 return str_start; /* try and continue */
1121 str_start = new_str_start;
1122 update_statistics((long) str_start, n, current_max_strings * sizeof (pool_pointer));
1123 current_max_strings = new_size;
1126 printf("New Address %s == %p\n", "string start", str_start);
1136 /* returns -1 if it fails */
1137 /* size == trie_size */
1138 int allocate_ini (int size)
1140 int n, nl, no, nc, nr, nh, nt;
1142 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1143 no = (size + 1) * sizeof(trie_op_code);
1144 nc = (size + 1) * sizeof(packed_ASCII_code);
1145 /* nt = (size + 1) * sizeof(boolean); */
1146 nt = (size + 1) * sizeof(char);
1147 n = nl + no + nc + nr + nh + nt;
1148 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1149 3 * sizeof(trie_pointer) + sizeof (char)); */
1151 trace_memory ("iniTeX hyphen trie", n);
1153 trie_l = (trie_pointer *) malloc (roundup(nl));
1154 trie_o = (trie_op_code *) malloc (roundup(no));
1155 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1156 trie_r = (trie_pointer *) malloc (roundup(nr));
1157 trie_hash = (trie_pointer *) malloc (roundup(nh));
1158 trie_taken = (char *) malloc (roundup(nt));
1160 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1161 trie_hash == NULL || trie_taken == NULL)
1163 memory_error("iniTeX hyphen trie", n);
1164 // exit (1); /* serious error */
1170 printf("Addresses trie_l %p trie_o %p trie_c %p\n", trie_l, trie_o, trie_c);
1171 printf("Addresses trie_r %p trie_hash %p trie_taken %p\n", trie_r, trie_hash, trie_taken);
1174 update_statistics ((long) trie_l, nl, 0);
1175 update_statistics ((long) trie_o, no, 0);
1176 update_statistics ((long) trie_c, nc, 0);
1177 update_statistics ((long) trie_r, nr, 0);
1178 update_statistics ((long) trie_hash, nh, 0);
1179 update_statistics ((long) trie_taken, nt, 0);
1180 /* trie_size = size; */ /* ??? */
1184 return 0; // success
1188 #ifdef ALLOCATESAVESTACK
1189 int current_save_size = 0;
1191 memory_word *realloc_save_stack (int size)
1194 int n = 0, new_size = 0;
1195 memory_word * new_save_stack = NULL;
1198 printf("Old Address %s == %p\n", "save stack", save_stack);
1200 if (current_save_size == save_size) /* arbitrary limit */
1202 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1204 return save_stack; /* let TeX handle the error */
1207 min_size = current_save_size / 100 * percent_grow;
1209 if (size < min_size)
1212 if (size < initial_save_size)
1213 size = initial_save_size;
1215 for (k = 0; k < MAXSPLITS; k++)
1217 new_size = current_save_size + size;
1219 if (new_size > save_size)
1220 new_size = save_size;
1222 n = (new_size + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1225 trace_memory("save_stack", n);
1227 new_save_stack = (memory_word *) REALLOC (save_stack, n);
1229 if (new_save_stack != NULL)
1230 break; /* did we get it ? */
1232 if (current_save_size == 0)
1233 break; /* initial allocation must work */
1235 size = size / 2; /* else can retry smaller */
1238 if (new_save_stack == NULL)
1240 memory_error("save stack", n);
1241 return save_stack; /* try and continue !!! */
1244 save_stack = new_save_stack;
1245 update_statistics ((long) save_stack, n, current_save_size);
1246 current_save_size = new_size;
1250 printf("Current %s %d\n", "save_size", current_save_size);
1251 printf("New Address %s == %p\n", "save stack", save_stack);
1261 #ifdef ALLOCATEINPUTSTACK
1262 int current_stack_size = 0; /* input stack size */
1264 in_state_record *realloc_input_stack (int size)
1267 int n = 0, new_size = 0;
1268 in_state_record * new_input_stack = NULL;
1271 printf("Old Address %s == %p\n", "input stack", input_stack);
1273 if (current_stack_size == stack_size) /* arbitrary limit */
1275 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1280 min_size = current_stack_size / 100 * percent_grow;
1282 if (size < min_size)
1285 if (size < initial_stack_size)
1286 size = initial_stack_size;
1288 for (k = 0; k < MAXSPLITS; k++)
1290 new_size = current_stack_size + size;
1292 if (new_size > stack_size)
1293 new_size = stack_size;
1295 n = (new_size + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1298 trace_memory("input_stack", n);
1300 new_input_stack = (in_state_record *) REALLOC (input_stack, n);
1302 if (new_input_stack != NULL)
1303 break; /* did we get it ? */
1305 if (current_stack_size == 0)
1306 break; /* initial allocation must work */
1308 size = size / 2; /* else can retry smaller */
1311 if (new_input_stack == NULL)
1313 memory_error("input stack", n);
1314 return input_stack; /* try and continue !!! */
1317 input_stack = new_input_stack;
1318 update_statistics ((long) input_stack, n, current_stack_size);
1319 current_stack_size = new_size;
1323 printf("Current %s %d\n", "stack_size", current_stack_size);
1324 printf("New Address %s == %p\n", "input stack", input_stack);
1334 #ifdef ALLOCATENESTSTACK
1335 int current_nest_size = 0; /* current nest size */
1337 list_state_record *realloc_nest_stack (int size)
1340 int n = 0, new_size = 0;
1341 list_state_record * new_nest = NULL;
1344 printf("Old Address %s == %p\n", "nest stack", nest);
1346 if (current_nest_size == nest_size) /* arbitrary limit */
1348 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1350 return nest; /* let TeX handle the error */
1353 min_size = current_nest_size / 100 * percent_grow;
1355 if (size < min_size)
1358 if (size < initial_nest_size)
1359 size = initial_nest_size;
1361 for (k = 0; k < MAXSPLITS; k++)
1363 new_size = current_nest_size + size;
1365 if (new_size > nest_size)
1366 new_size = nest_size;
1368 n = (new_size + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1371 trace_memory("nest stack", n);
1373 new_nest = (list_state_record *) REALLOC (nest, n);
1375 if (new_nest != NULL)
1376 break; /* did we get it ? */
1378 if (current_nest_size == 0)
1379 break; /* initial allocation must work */
1381 size = size / 2; /* else can retry smaller */
1384 if (new_nest == NULL)
1386 memory_error("nest stack", n);
1387 return nest; /* try and continue !!! */
1391 update_statistics ((long) nest, n, current_nest_size);
1392 current_nest_size = new_size;
1396 printf("Current %s %d\n", "nest_size", current_nest_size);
1397 printf("New Address %s == %p\n", "nest stack", nest);
1407 #ifdef ALLOCATEPARAMSTACK
1408 int current_param_size = 0;
1410 halfword *realloc_param_stack (int size)
1413 int n = 0, new_size = 0;
1414 halfword * new_param = NULL;
1417 printf("Old Address %s == %p\n", "param stack", param_stack);
1419 if (current_param_size == param_size) /* arbitrary limit */
1421 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1423 return param_stack; /* let TeX handle the error */
1426 min_size = current_param_size / 100 * percent_grow;
1428 if (size < min_size)
1431 if (size < initial_param_size)
1432 size = initial_param_size;
1434 for (k = 0; k < MAXSPLITS; k++)
1436 new_size = current_param_size + size;
1438 if (new_size > param_size)
1439 new_size = param_size;
1441 n = (new_size + 1) * sizeof(pointer);
1444 trace_memory("param stack", n);
1446 new_param = (pointer *) REALLOC (param_stack, n);
1448 if (new_param != NULL)
1449 break; /* did we get it ? */
1451 if (current_param_size == 0)
1452 break; /* initial allocation must work */
1454 size = size / 2; /* else can retry smaller */
1457 if (new_param == NULL)
1459 memory_error("param stack", n);
1460 return param_stack; /* try and continue !!! */
1463 param_stack = new_param;
1464 update_statistics((long) param_stack, n, current_param_size);
1465 current_param_size = new_size;
1469 printf("Current %s %d\n", "param_size", current_param_size);
1470 printf("New Address %s == %p\n", "param stack", param_stack);
1480 #ifdef ALLOCATEBUFFER
1481 int current_buf_size = 0;
1483 ASCII_code * realloc_buffer (int size)
1486 int n = 0, new_size = 0;
1487 ASCII_code * new_buffer = NULL;
1490 printf("Old Address %s == %p\n", "buffer", buffer);
1492 if (current_buf_size == buf_size)
1494 /* memory_error ("buffer", buf_size); */
1496 return buffer; /* pass it back to TeX 99/Fabe/4 */
1499 min_size = current_buf_size / 100 * percent_grow;
1501 if (size < min_size)
1504 if (size < initial_buf_size)
1505 size = initial_buf_size;
1507 for (k = 0; k < MAXSPLITS; k++)
1509 new_size = current_buf_size + size;
1511 if (new_size > buf_size)
1512 new_size = buf_size;
1514 n = (new_size + 1) * sizeof(ASCII_code);
1517 trace_memory("buffer", n);
1519 new_buffer = (ASCII_code *) REALLOC (buffer, n);
1521 if (new_buffer != NULL)
1522 break; /* did we get it ? */
1524 if (current_buf_size == 0)
1525 break; /* initial allocation must work */
1530 if (new_buffer == NULL)
1532 memory_error("buffer", n);
1533 return buffer; /* try and continue !!! */
1536 buffer = new_buffer;
1537 update_statistics ((long) buffer, n, current_buf_size);
1540 memset(buffer + current_buf_size, 0, new_size - current_buf_size);
1542 for (k = current_buf_size; k < new_size; k++)
1546 current_buf_size = new_size;
1550 printf("Current %s %d\n", "buffer", current_buf_size);
1551 printf("New Address %s == %p\n", "buffer", buffer);
1561 /* here is the main memory allocation routine -- calls the above */
1562 /* returns -1 if it fails */
1563 /* allocate rather than static 93/Nov/26 */
1564 int allocate_memory (void)
1566 #ifdef ALLOCATEINPUTSTACK
1568 current_stack_size = 0;
1569 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1572 #ifdef ALLOCATENESTSTACK
1574 current_nest_size = 0;
1575 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1578 #ifdef ALLOCATEPARAMSTACK
1580 current_param_size = 0;
1581 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1584 #ifdef ALLOCATESAVESTACK
1586 current_save_size = 0;
1587 save_stack = realloc_save_stack (initial_save_size);
1591 buffer = NULL; /* need to do earlier */
1592 current_buf_size = 0;
1593 buffer = realloc_buffer (initial_buf_size);
1596 #ifdef ALLOCATESTRING
1598 current_pool_size = 0;
1600 current_max_strings = 0;
1602 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1606 puts("ini TeX pool and string allocation\n");
1608 str_pool = realloc_str_pool(initial_pool_size);
1609 str_start = realloc_str_start(initial_max_strings);
1613 /* the following can save a lot of the usual 800k fixed allocation */
1616 current_font_mem_size = 0;
1617 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1618 /* if ini-TeX we need to do it here - no format file read later */
1620 font_info = realloc_font_info (initial_font_mem_size);
1626 mem_min = mem_bot; /* just to avoid complaints in texbody */
1627 mem_top = mem_initex;
1629 /* allocate main memory here if this is iniTeX */
1630 /* otherwise wait for format undumping in itex.c ... */
1633 /* avoid this if format specified on command line ??? */
1634 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1635 mem = allocate_main_memory(mem_initex); /* made variable ! */
1638 return -1; /* serious error */
1642 /* now for the hyphenation exception stuff */
1643 #ifdef ALLOCATEHYPHEN
1646 /* this will be overridden later by what is in format file */
1647 hyphen_prime = default_hyphen_prime;
1648 /* non ini-TeX use assumes format will be read and that specifies size */
1651 if (new_hyphen_prime)
1652 hyphen_prime = new_hyphen_prime;
1654 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1659 /* now for memory for the part of the hyphenation stuff that always needed */
1660 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1661 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1662 #ifdef ALLOCATETRIES
1665 if (allocate_tries (trie_size))
1670 /* now for memory for hyphenation stuff needed only when running iniTeX */
1674 if (allocate_ini(trie_size))
1679 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1680 trie_c = NULL; /* (trie_size + 1) * char */
1681 trie_taken = NULL; /* (trie_size + 1) * boolean */
1685 return 0; // success
1688 /* returns non-zero if error - done to test integrity of stack mostly */
1689 int free_memory (void)
1691 unsigned int heap_total = 0;
1694 puts("free_memory ");
1696 if (verbose_flag || trace_flag)
1697 show_maximums(stdout);
1701 printf("Heap total: %u bytes --- max address %u\n",
1702 heap_total, max_address);
1703 printf("Main Memory: variable node %lld (%lld - %d);\n"
1704 " one word %d (%d - %d)\n",
1705 lo_mem_max - mem_min, mem_min, lo_mem_max,
1706 mem_end - hi_mem_min, hi_mem_min, mem_end);
1707 puts("Freeing memory again");
1710 /* only free memory if safe ... additional check */
1714 if (trie_taken != NULL)
1717 if (trie_hash != NULL)
1733 trie_hash = trie_l = trie_r = NULL;
1739 #ifdef ALLOCATETRIES
1740 if (trie_trc != NULL)
1743 if (trie_tro != NULL)
1746 if (trie_trl != NULL)
1750 trie_tro = trie_trl = NULL;
1753 #ifdef ALLOCATEHYPHEN
1754 if (hyph_list != NULL)
1757 if (hyph_word != NULL)
1765 if (main_memory != NULL)
1772 if (font_info != NULL)
1778 #ifdef ALLOCATESTRING
1779 if (str_start != NULL)
1782 if (str_pool != NULL)
1789 #ifdef ALLOCATEPARAMSTACK
1790 if (param_stack != NULL)
1796 #ifdef ALLOCATENESTSTACK
1803 #ifdef ALLOCATEINPUTSTACK
1804 if (input_stack != NULL)
1810 #ifdef ALLOCATESAVESTACK
1811 if (save_stack != NULL)
1817 if (format_file != NULL)
1820 if (source_direct != NULL)
1821 free(source_direct);
1824 source_direct = NULL;
1826 if (dvi_file_name != NULL)
1827 free(dvi_file_name);
1829 if (log_file_name != NULL)
1830 free(log_file_name);
1832 if (pdf_file_name != NULL)
1833 free(pdf_file_name);
1835 pdf_file_name = NULL;
1836 log_file_name = NULL;
1837 dvi_file_name = NULL;
1842 boolean prime (int x)
1845 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1850 for (k = 3; k < x; k = k + 2)
1865 boolean show_use = false;
1867 void complainarg (int c, char *s)
1869 printf("ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1873 /* following is list of allowed command line flags and args */
1875 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1877 void reorderargs (int ac, char **av)
1881 char takeargs[256]; /* large enough for all command line arg chars */
1885 return; /* no args ! */
1889 t = takeargs; /* list of those that take args */
1891 while (*s != '\0' && *(s + 1) != '\0')
1893 if (*(s + 1) == '=')
1894 *t++ = *s++; /* copy over --- without the = */
1903 show_line(takeargs, 0);
1914 if (n + 1 < ac && *(av[n] + 2) == '\0' &&
1915 strchr(takeargs, *(av[n] + 1)) != NULL)
1916 n += 2; /* step over it */
1931 while (m < ac && *av[m] != '-')
1932 m++; /* first command */
1936 /* does it take an argument ? and is this argument next ? */
1937 /* check first whether the `-x' is isolated, or arg follows directly */
1938 /* then check whether this is one of those that takes an argument */
1939 if (m+1 < ac && *(av[m] + 2) == '\0' &&
1940 strchr(takeargs, *(av[m] + 1)) != NULL)
1942 s = av[m]; /* move command down before non-command */
1946 av[m + 1] = av[m - 1];
1950 n += 2; /* step over moved args */
1954 s = av[m]; /* move command down before non-command */
1960 n++; /* step over moved args */
1965 int test_align (long address, int size, char *str)
1969 if (size > sizeof(void *))
1970 n = address % sizeof(void *);
1975 printf("OFFSET %d (ELEMENT %d) in %s\n", n, size, str);
1980 /* activate detailed checking of alignment when trace_flag is set */
1982 void check_fixed_align (int flag)
1986 if (test_align ((long) &mem_top, 4, "FIXED ALIGNMENT"))
1988 puts("PLEASE RECOMPILE ME!\n");
1991 #ifdef CHECKALIGNMENT
1995 test_align ((long) &mem_top, 4, "mem_top");
1996 test_align ((long) &mem_max, 4, "mem_max");
1997 test_align ((long) &mem_min, 4, "mem_min");
1998 test_align ((long) &bad, 4, "bad");
1999 test_align ((long) &trie_size, 4, "trie_size");
2000 test_align ((long) &xord, sizeof(xord[0]), "xord"); /* no op */
2001 test_align ((long) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2002 test_align ((long) &name_length, 4, "name_length");
2003 test_align ((long) &first, 4, "first");
2004 test_align ((long) &last, 4, "last");
2005 test_align ((long) &max_buf_stack, 4, "max_buf_stack");
2006 test_align ((long) &pool_ptr, 4, "pool_ptr");
2007 test_align ((long) &str_ptr, 4, "str_ptr");
2008 test_align ((long) &init_pool_ptr, 4, "init_pool_ptr");
2009 test_align ((long) &init_str_ptr, 4, "init_str_ptr");
2010 test_align ((long) &log_file, 4, "log_file");
2011 test_align ((long) &tally, 4, "tally");
2012 test_align ((long) &term_offset, 4, "term_offset");
2013 test_align ((long) &file_offset, 4, "file_offset");
2014 test_align ((long) &trick_count, 4, "trick_count");
2015 test_align ((long) &first_count, 4, "first_count");
2016 test_align ((long) &deletions_allowed, 4, "deletions_allowed");
2017 test_align ((long) &set_box_allowed, 4, "set_box_allowed");
2018 test_align ((long) &help_line, sizeof(help_line[0]), "help_line");
2019 test_align ((long) &use_err_help, 4, "use_err_help");
2020 test_align ((long) &interrupt, 4, "interrupt");
2021 test_align ((long) &OK_to_interrupt, 4, "OK_to_interrupt");
2022 test_align ((long) &arith_error, 4, "arith_error");
2023 test_align ((long) &tex_remainder, 4, "tex_remainder");
2024 test_align ((long) &temp_ptr, 4, "temp_ptr");
2025 test_align ((long) &lo_mem_max, 4, "lo_mem_max");
2026 test_align ((long) &hi_mem_min, 4, "hi_mem_min");
2027 test_align ((long) &var_used, 4, "var_used");
2028 test_align ((long) &dyn_used, 4, "dyn_used");
2029 test_align ((long) &avail, 4, "avail");
2030 test_align ((long) &mem_end, 4, "mem_end");
2031 test_align ((long) &mem_start, 4, "mem_start");
2032 test_align ((long) &rover, 4, "rover");
2033 test_align ((long) &font_in_short_display, 4, "font_in_short_display");
2034 test_align ((long) &depth_threshold, 4, "depth_threshold");
2035 test_align ((long) &breadth_max, 4, "breadth_max");
2036 test_align ((long) &nest, sizeof(nest[0]), "nest");
2037 /* test_align ((long) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2038 test_align ((long) &zzzad, sizeof(zzzad[0]), "zzzad");
2039 /* test_align ((long) &hash, sizeof(hash[0]), "hash"); */
2040 test_align ((long) &zzzae, sizeof(zzzae[0]), "zzzae");
2042 test_align ((long) &save_stack, sizeof(save_stack[0]), "save_stack");
2043 test_align ((long) &input_stack, sizeof(input_stack[0]), "input_stack");
2044 test_align ((long) &input_file, sizeof(input_file[0]), "input_file");
2045 test_align ((long) &line_stack, sizeof(line_stack[0]), "line_stack");
2046 test_align ((long) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2047 test_align ((long) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2048 test_align ((long) &pstack, sizeof(pstack[0]), "pstack");
2049 test_align ((long) &read_file, sizeof(read_file[0]), "read_file");
2051 test_align ((long) &font_check, sizeof(font_check[0]), "font_check");
2052 test_align ((long) &font_size, sizeof(font_size[0]), "font_size");
2053 test_align ((long) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2054 test_align ((long) &font_params, sizeof(font_params[0]), "font_params");
2055 test_align ((long) &font_name, sizeof(font_name[0]), "font_name");
2056 test_align ((long) &font_area, sizeof(font_area[0]), "font_area");
2057 test_align ((long) &font_bc, sizeof(font_bc[0]), "font_bc");
2058 test_align ((long) &font_ec, sizeof(font_ec[0]), "font_ec");
2059 test_align ((long) &font_glue, sizeof(font_glue[0]), "font_glue");
2060 test_align ((long) &font_used, sizeof(font_used[0]), "font_used");
2061 test_align ((long) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2062 test_align ((long) &skew_char, sizeof(skew_char[0]), "skew_char");
2063 test_align ((long) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2064 test_align ((long) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2065 test_align ((long) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2066 test_align ((long) &char_base, sizeof(char_base[0]), "char_base");
2067 test_align ((long) &width_base, sizeof(width_base[0]), "width_base");
2068 test_align ((long) &height_base, sizeof(height_base[0]), "height_base");
2069 test_align ((long) &depth_base, sizeof(depth_base[0]), "depth_base");
2070 test_align ((long) &italic_base, sizeof(italic_base[0]), "italic_base");
2071 test_align ((long) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2072 test_align ((long) &kern_base, sizeof(kern_base[0]), "kern_base");
2073 test_align ((long) &exten_base, sizeof(exten_base[0]), "exten_base");
2074 test_align ((long) ¶m_base, sizeof(param_base[0]), "param_base");
2076 #ifdef ALLOCATEDVIBUF
2077 test_align ((long) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2080 test_align ((long) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2081 test_align ((long) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2082 test_align ((long) &active_width, sizeof(active_width[0]), "active_width");
2083 test_align ((long) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2084 test_align ((long) &background, sizeof(background[0]), "background");
2085 test_align ((long) &break_width, sizeof(break_width[0]), "break_width");
2086 test_align ((long) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2087 test_align ((long) &best_place, sizeof(best_place[0]), "best_place");
2088 test_align ((long) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2089 test_align ((long) &hc, sizeof(hc[0]), "hc");
2090 test_align ((long) &hu, sizeof(hu[0]), "hu");
2091 test_align ((long) &hyf, sizeof(hyf[0]), "hyf");
2092 /* test_align ((long) &x, sizeof(x[0]), "x"); */
2094 test_align ((long) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2095 test_align ((long) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2096 test_align ((long) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2097 test_align ((long) &op_start, sizeof(op_start[0]), "op_start");
2099 /* test_align ((long) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2100 test_align ((long) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2101 test_align ((long) &trie_used, sizeof(trie_used[0]), "trie_used");
2102 /* test_align ((long) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2103 test_align ((long) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2105 test_align ((long) &trie_min, sizeof(trie_min[0]), "trie_min");
2106 test_align ((long) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2107 test_align ((long) &write_file, sizeof(write_file[0]), "write_file");
2108 test_align ((long) &write_open, sizeof(write_open[0]), "write_open");
2112 void check_alloc_align (int flag)
2116 if (test_align((long) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2117 puts("PLEASE RECOMPILE ME!");
2119 #ifdef CHECKALIGNMENT
2124 test_align ((long) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2127 #ifndef ALLOCATEDVIBUF
2128 test_align ((long) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2131 test_align ((long) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2132 test_align ((long) str_start, sizeof(str_start[0]), "str_start");
2133 test_align ((long) zmem, sizeof(zmem[0]), "main memory");
2134 test_align ((long) font_info, sizeof(font_info[0]), "font memory");
2135 test_align ((long) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2136 test_align ((long) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2137 test_align ((long) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2138 test_align ((long) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2139 test_align ((long) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2140 /* test_align ((long) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2141 test_align ((long) trie_o, sizeof(trie_o[0]), "trie_o");
2142 test_align ((long) trie_l, sizeof(trie_l[0]), "trie_l");
2143 test_align ((long) trie_r, sizeof(trie_r[0]), "trie_r");
2144 test_align ((long) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2145 test_align ((long) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2149 boolean backwardflag = false; /* don't cripple all advanced features */
2150 boolean shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2152 /* cache to prevent allocating twice in a row */
2154 char * lastname = NULL;
2155 char * lastvalue = NULL;
2157 /* returns allocated string -- these strings are not freed again */
2158 /* is it safe to do that now ? 98/Jan/31 */
2159 char * grabenv (const char * varname)
2163 if (varname == NULL)
2166 if (*varname == '\0')
2169 if (lastname != NULL && strcasecmp(lastname, varname) == 0)
2172 printf("Cache hit: %s=%s\n", lastname, lastvalue);
2174 return xstrdup(lastvalue);
2177 s = getenv(varname);
2181 if (lastname != NULL)
2184 lastname = xstrdup(varname);
2186 if (lastvalue != NULL)
2189 lastvalue = xstrdup(s);
2197 void flush_trailing_slash(char * directory)
2201 if (strcmp(directory, "") != 0)
2203 s = directory + strlen(directory) - 1;
2205 if (*s == '\\' || *s == '/')
2210 void knuthify (void)
2212 restrict_to_ascii = false; /* don't complain non ASCII */
2213 allow_patterns = false; /* don't allow pattern redefinition */
2214 show_in_hex = true; /* show character code in hex */
2215 show_in_dos = false; /* redundant with previous */
2216 show_numeric = false; /* don't show character code decimal */
2217 show_missing = false; /* don't show missing characters */
2218 civilize_flag = false; /* don't reorder date fields */
2219 c_style_flag = false; /* don't add file name to error msg */
2220 show_fmt_flag = false; /* don't show format file in log */
2221 show_tfm_flag = false; /* don't show metric file in log */
2223 show_line_break_stats = false; /* do not show line break stats */
2224 show_fonts_used = false;
2225 default_rule = 26214; /* revert to default rule thickness */
2226 pseudo_tilde = false;
2227 pseudo_space = false;
2228 truncate_long_lines = false;
2229 allow_quoted_names = false;
2230 show_cs_names = false;
2231 ignore_frozen = false;
2232 suppress_f_ligs = false;
2233 full_file_name_flag = false;
2234 knuth_flag = true; /* so other code can know about this */
2237 /* following made global so analyze_flag can be made separate procedure */
2239 char * xchr_file = NULL;
2240 char * repl_file = NULL;
2242 const char * short_options = "m:e:h:0:H:g:P:o:l:a:kwvpiKLZMdp2t?u";
2244 static struct option long_options[] =
2246 {"main-memory", required_argument, NULL, 'm'},
2247 {"hyph-size", required_argument, NULL, 'e'},
2248 {"trie-size", required_argument, NULL, 'h'},
2249 {"backend", required_argument, NULL, '0'},
2250 {"tab-step", required_argument, NULL, 'H'},
2251 {"percent-grow", required_argument, NULL, 'g'},
2252 {"default-rule", required_argument, NULL, 'P'},
2253 {"dvi-dir", required_argument, NULL, 'o'},
2254 {"log-dir", required_argument, NULL, 'l'},
2255 {"aux-dir", required_argument, NULL, 'a'},
2256 {"key-file", required_argument, NULL, 'k'},
2257 {"showhex", no_argument, NULL, 'w'},
2258 {"verbose", no_argument, NULL, 'v'},
2259 {"patterns", no_argument, NULL, 'p'},
2260 {"initex", no_argument, NULL, 'i'},
2261 {"knuthify", no_argument, NULL, 'K'},
2262 {"cstyle", no_argument, NULL, 'L'},
2263 {"showtfm", no_argument, NULL, 'Z'},
2264 {"showmissing", no_argument, NULL, 'M'},
2265 {"deslash", no_argument, NULL, 'd'},
2266 {"patterns", no_argument, NULL, 'p'},
2267 {"suppressflig", no_argument, NULL, '2'},
2268 {"trace", no_argument, NULL, 't'},
2269 {"help", no_argument, NULL, '?'},
2270 {"usage", no_argument, NULL, 'u'},
2274 int analyze_flag (int c, char *optarg)
2279 verbose_flag = true;
2285 interaction = batch_mode;
2288 interaction = nonstop_mode;
2291 interaction = scroll_mode;
2294 interaction = error_stop_mode;
2297 backwardflag = true;
2298 knuthify(); /* revert to `standard' Knuth TeX */
2301 c_style_flag = true;
2304 show_tfm_flag = true;
2307 show_missing = false;
2310 deslash = false; /* flipped 93/Nov/18 */
2311 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2314 allow_patterns = true; /* 93/Nov/26 */
2315 /* reset_exceptions = true; */ /* 93/Dec/23 */
2317 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2319 show_in_hex = true; /* flipped 00/Jun/18 */
2322 show_in_dos = true; /* 96/Jan/26 */
2325 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2328 show_fonts_used = false; /* 97/Dec/24 */
2331 shorten_file_name = true; /* 95/Feb/20 */
2334 show_cs_names = true; /* 98/Mar/31 */
2337 ignore_frozen = true; /* 98/Oct/5 */
2340 show_line_break_stats = false; /* 96/Feb/8 */
2343 show_fmt_flag = false; /* 94/Jun/21 */
2346 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2349 full_file_name_flag = false; // 00 Jun 18
2355 quitflag++; /* 93/Dec/16 */
2357 /* The following are really obscure and should not be advertized */
2359 show_current = false; /* tex8 93/Dec/14 */
2362 show_numeric = false; /* 93/Dec/21 */
2365 civilize_flag = false; /* 93/Dec/16 */
2368 open_trace_flag = true;
2371 reorder_arg_flag = false; /* local */
2376 mem_initex = mem_top;
2378 mem_initex = atoi(optarg) * 1024;
2380 if (mem_initex == 0)
2381 complainarg(c, optarg);
2386 #ifdef VARIABLETRIESIZE
2389 trie_size = default_trie_size;
2391 trie_size = atoi(optarg);
2394 complainarg(c, optarg);
2398 #ifdef ALLOCATEHYPHEN
2401 new_hyphen_prime = hyphen_prime * 2;
2403 new_hyphen_prime = atoi(optarg);
2405 if (new_hyphen_prime == 0)
2406 complainarg(c, optarg);
2414 percent_grow = atoi(optarg);
2416 if (percent_grow == 0)
2417 complainarg(c, optarg);
2425 pseudo_tilde = atoi(optarg);
2427 if (pseudo_tilde > 255)
2429 else if (pseudo_tilde < 128)
2438 tab_step = atoi(optarg);
2440 complainarg(c, optarg);
2445 xchr_file = xstrdup("xchr.map");
2447 xchr_file = xstrdup(optarg);
2449 if (xchr_file == NULL || *xchr_file == '\0')
2450 complainarg(c, optarg);
2455 repl_file = xstrdup("repl.key");
2457 repl_file = xstrdup(optarg);
2459 if (repl_file == NULL || *repl_file == '\0')
2460 complainarg(c, optarg);
2465 default_rule = 26214;
2467 default_rule = atoi(optarg);
2469 if (default_rule == 0)
2470 complainarg(c, optarg);
2477 complainarg(c, optarg);
2484 dvi_directory = xstrdup(optarg);
2486 if (strcmp(dvi_directory, "") == 0)
2487 complainarg(c, optarg);
2493 char * format_spec = NULL;
2496 format_spec = xstrdup(optarg);
2498 if (!strcmp(format_spec, "pdf"))
2499 shipout_flag = out_pdf_flag;
2500 else if (!strcmp(format_spec, "dvi"))
2501 shipout_flag = out_dvi_flag;
2502 else if (!strcmp(format_spec, "xdv"))
2503 shipout_flag = out_xdv_flag;
2505 printf("ERROR: Do not understand shipout flag `%s'\n", format_spec);
2513 log_directory = xstrdup(optarg);
2515 if (strcmp(log_directory, "") == 0)
2516 complainarg(c, optarg);
2524 aux_directory = xstrdup(optarg);
2526 if (strcmp(aux_directory, "") == 0)
2527 complainarg(c, optarg);
2541 void strip_name (char *pathname)
2545 if ((s = strrchr(pathname, '\\')) != NULL)
2547 else if ((s = strrchr(pathname, '/')) != NULL)
2549 else if ((s = strrchr(pathname, ':')) != NULL)
2557 int read_command_line (int ac, char **av)
2566 while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)
2568 if (optarg != 0 && *optarg == '=')
2569 optargnew = optarg + 1;
2573 analyze_flag(c, optargnew);
2576 if (show_use || quitflag == 3)
2579 strcat(log_line, "\n");
2580 show_line(log_line, 0);
2584 else if (quitflag == 3)
2586 strcat(log_line, "\n");
2587 show_line(log_line, 0);
2590 return -1; // failure
2593 if (repl_file != NULL && *repl_file != '\0')
2595 if (read_xchr_file(repl_file, 1, av))
2598 puts("KEY REPLACE ON");
2604 if (xchr_file != NULL && *xchr_file != '\0')
2606 if (read_xchr_file(xchr_file, 0, av))
2609 puts("NON ASCII ON");
2618 int init_commands (int ac, char **av)
2620 shipout_flag = out_dvi_flag;
2622 allow_patterns = false;
2623 reset_exceptions = false;
2625 key_replace = false;
2626 open_trace_flag = false;
2628 verbose_flag = false;
2629 restrict_to_ascii = false;
2630 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2631 show_in_dos = false; /* default is not to translate to DOS 850 */
2632 return_flag = true; // hard wired now
2633 trimeof = true; // hard wired now
2635 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2636 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2637 default_rule = 26214; /* default rule variable 95/Oct/9 */
2638 show_current = true;
2639 civilize_flag = true;
2640 show_numeric = true;
2641 show_missing = true;
2642 c_style_flag = false; /* use c-style error output */
2643 show_fmt_flag = true; /* show format file in log */
2644 show_tfm_flag = false; /* don't show metric file in log */
2645 shorten_file_name = false; /* don't shorten file names to 8+3 */
2646 truncate_long_lines = true; /* truncate long lines */
2647 tab_step = 0; /* do not replace tabs with spaces */
2648 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2649 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2650 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2651 show_cs_names = false;
2652 knuth_flag = false; /* allow extensions to TeX */
2653 full_file_name_flag = true; /* new default 2000 June 18 */
2654 errout = stdout; /* as opposed to stderr say --- used ??? */
2655 new_hyphen_prime = 0;
2657 #ifdef VARIABLETRIESIZE
2658 // trie_size = default_trie_size;
2665 format_name = "plain";
2667 if (read_command_line(ac, av) < 0)
2676 void initial_memory (void)
2678 /* set initial memory allocations */
2679 if (mem_extra_high < 0)
2682 if (mem_extra_low < 0)
2690 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2691 if (mem_extra_high != 0 || mem_extra_low != 0)
2693 puts("ERROR: Cannot extend main memory in iniTeX");
2701 if (mem_initex != 0)
2703 puts("ERROR: Can only set initial main memory size in iniTeX");
2709 puts("ERROR: Need only set hyphenation trie size in iniTeX");
2710 /* trie_size = 0; */
2713 if (mem_initex == 0)
2714 mem_initex = default_mem_top;
2717 trie_size = default_trie_size;
2719 /* Just in case user mistakenly specified words instead of kilo words */
2720 if (mem_extra_high > 10000L * 1024L)
2721 mem_extra_high = mem_extra_high / 1024;
2723 if (mem_extra_low > 10000L * 1024L)
2724 mem_extra_low = mem_extra_low / 1024;
2726 if (mem_initex > 10000L * 1024L)
2727 mem_initex = mem_initex / 1024;
2729 if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */
2731 puts("WARNING: There may be no benefit to asking for so much memory");
2732 /* mem_initex = 2048 * 1024; */
2735 if (new_hyphen_prime < 0)
2736 new_hyphen_prime = 0;
2738 if (new_hyphen_prime > 0)
2741 puts("ERROR: Can only set hyphen prime in iniTeX");
2744 if (new_hyphen_prime % 2 == 0)
2747 while (!prime(new_hyphen_prime))
2748 new_hyphen_prime = new_hyphen_prime + 2;
2751 printf("Using %d as hyphen prime\n", new_hyphen_prime);
2755 if (percent_grow > 100)
2756 percent_grow = percent_grow - 100;
2758 if (percent_grow > 100)
2759 percent_grow = 100; /* upper limit - double */
2761 if (percent_grow < 10)
2762 percent_grow = 10; /* lower limit - 10% */
2765 void perrormod (const char * s)
2767 printf("`%s': %s\n", s, strerror(errno));
2770 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
2771 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
2772 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
2773 /* this is then undone in tex3.c both for fopen input and output */
2774 /* not ideal, since pseudo name appears in log and in error messages ... */
2776 void hidetwiddle (char *tname)
2782 printf("Hidetwiddle %s", tname);
2787 if (*s == '~' && pseudo_tilde != 0)
2788 *s = (char) pseudo_tilde; /* typically 254 */
2789 else if (*s == ' ' && pseudo_space != 0)
2790 *s = (char) pseudo_space; /* typically 255 */
2796 printf("=> %s\n", tname);
2800 void deslash_all (int ac, char **av)
2802 char buffer[file_name_size];
2805 if ((s = grabenv("TEXDVI")) != NULL)
2808 if ((s = grabenv("TEXLOG")) != NULL)
2811 if ((s = grabenv("TEXAUX")) != NULL)
2814 if ((s = grabenv("TEXFMT")) != NULL)
2817 if ((s = grabenv("TEXPDF")) != NULL)
2820 strcpy(buffer, av[0]);
2822 if ((s = strrchr(buffer, '\\')) != NULL)
2824 else if ((s = strrchr(buffer, '/')) != NULL)
2826 else if ((s = strrchr(buffer, ':')) != NULL)
2829 s = buffer + strlen(buffer) - 1;
2831 if (*s == '\\' || *s == '/')
2834 if (strcmp(dvi_directory, "") != 0)
2835 flush_trailing_slash(dvi_directory);
2837 if (strcmp(log_directory, "") != 0)
2838 flush_trailing_slash(log_directory);
2840 if (strcmp(aux_directory, "") != 0)
2841 flush_trailing_slash(aux_directory);
2843 if (strcmp(fmt_directory, "") != 0)
2844 flush_trailing_slash(fmt_directory);
2846 if (strcmp(pdf_directory, "") != 0)
2847 flush_trailing_slash(pdf_directory);
2851 if (strcmp(dvi_directory, "") != 0)
2852 unixify(dvi_directory);
2854 if (strcmp(log_directory, "") != 0)
2855 unixify(log_directory);
2857 if (strcmp(aux_directory, "") != 0)
2858 unixify(aux_directory);
2860 if (strcmp(fmt_directory, "") != 0)
2861 unixify(fmt_directory);
2863 if (strcmp(pdf_directory, "") != 0)
2864 unixify(pdf_directory);
2869 if (optind < ac && optind > 0)
2874 printf("deslash: k %d argv[k] %s (argc %d)\n", optind, av[optind], ac);
2876 unixify(av[optind]);
2879 if (pseudo_tilde != 0 || pseudo_space != 0)
2880 hidetwiddle(av[optind]);
2882 if (*av[optind] == '&' || *av[optind] == '+')
2885 format_name = xstrdup(av[optind] + 1);
2887 if (optind + 1 < ac)
2892 printf("deslash: k %d argv[k] %s (argc %d)\n", optind + 1, av[optind + 1], ac);
2894 unixify(av[optind + 1]);
2897 if (pseudo_tilde != 0 || pseudo_space != 0)
2898 hidetwiddle(av[optind + 1]);
2904 /* note: those optarg == 0 test don't really work ... */
2905 /* note: optarg starts at = in case of x=... */
2907 int main_init (int ac, char **av)
2909 kpse_set_program_name(av[0], NULL);
2910 xputenv("engine", "yandytex");
2912 if (sizeof(memory_word) != sizeof(halfword) * 2)
2913 printf("ERROR: Bad word size %ld!\n", sizeof(memory_word));
2915 start_time = clock();
2916 main_time = start_time;
2918 /* reset all allocatable memory pointers to NULL - in case we drop out */
2924 #ifdef ALLOCATESAVESTACK
2928 #ifdef ALLOCATEBUFFER
2930 current_buf_size = 0;
2931 buffer = realloc_buffer(initial_buf_size);
2946 log_opened = false; /* so can tell whether opened */
2947 interaction = -1; /* default state => 3 */
2948 missing_characters = 0; /* none yet! */
2949 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
2950 suppress_f_ligs = false; /* default is not to ignore f-ligs */
2952 if (ac > 1 && !strncmp(av[1], "-Y", 2))
2953 reorder_arg_flag = false;
2955 if (reorder_arg_flag)
2956 reorderargs(ac, av);
2958 if (init_commands(ac, av))
2961 check_fixed_align(trace_flag);
2964 source_direct = NULL;
2965 dvi_file_name = NULL;
2966 log_file_name = NULL;
2967 pdf_file_name = NULL;
2969 first_pass_count = 0;
2970 second_pass_count = 0;
2971 final_pass_count = 0;
2972 paragraph_failed = 0;
2981 puts("Entering init (local.c)");
2984 ini_max_address = max_address;
2987 show_maximums(stdout);
2990 deslash_all(ac, av);
2993 if (format_spec && mem_spec_flag)
2994 puts("WARNING: Cannot change initial main memory size when format specified");
2996 if (allocate_memory() != 0)
2999 check_alloc_align(trace_flag);
3002 puts("Leaving init (local.c)");
3007 #define CLK_TCK CLOCKS_PER_SEC
3009 void show_inter_val (clock_t inter_val)
3011 int seconds, tenths, hundredth, thousands;
3013 if (inter_val >= CLK_TCK * 10)
3015 tenths = (inter_val * 10 + CLK_TCK / 2) / CLK_TCK;
3016 seconds = tenths / 10;
3017 tenths = tenths % 10;
3018 printf("%d.%d", seconds, tenths);
3020 else if (inter_val >= CLK_TCK)
3022 hundredth = (inter_val * 100 + CLK_TCK / 2) / CLK_TCK;
3023 seconds = hundredth / 100;
3024 hundredth = hundredth % 100;
3025 printf("%d.%02d", seconds, hundredth);
3027 else if (inter_val > 0)
3029 thousands = (inter_val * 1000 + CLK_TCK / 2) / CLK_TCK;
3030 seconds = thousands / 1000;
3031 thousands = thousands % 1000;
3032 printf("%d.%03d", seconds, thousands);
3040 finish_time = clock();
3042 if (missing_characters != 0)
3045 if (missing_characters)
3047 sprintf(log_line, "! There %s %d missing character%s --- see log file\n",
3048 (missing_characters == 1) ? "was" : "were", missing_characters,
3049 (missing_characters == 1) ? "" : "s");
3050 show_line(log_line, 0);
3053 if (free_memory() != 0)
3059 show_inter_val(finish_time - start_time);
3061 show_inter_val(main_time - start_time);
3062 printf(" format load + ");
3063 show_inter_val(finish_time - main_time);
3064 printf(" processing) ");
3066 if (total_pages > 0)
3068 show_inter_val((finish_time - main_time) / total_pages);
3069 printf(" sec per page.\n");
3075 // printf control sequences' name
3076 void print_cs_name (FILE *output, int h)
3080 memset(log_line, 0, sizeof(log_line));
3082 textof = hash[h].rh;
3087 c = sprintf(log_line, "(%d), ", h);
3090 memmove(log_line + c, str_pool + str_start[textof], n);
3091 memmove(log_line + c + n, "\n", 2);
3093 if (output == stderr)
3094 show_line(log_line, 1);
3095 else if (output == stdout)
3096 show_line(log_line, 0);
3098 fprintf(output, "%s", log_line);
3101 int compare_strn (int, int, int, int);
3102 /* compare two csnames in qsort */
3103 int compare_cs (const void *cp1, const void *cp2)
3105 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3109 textof1 = hash[c1].rh;
3110 textof2 = hash[c2].rh;
3111 l1 = length(textof1);
3112 l2 = length(textof2);
3113 k1 = str_start[textof1];
3114 k2 = str_start[textof2];
3116 return compare_strn(k1, l1, k2, l2);
3119 char * csused = NULL;
3121 /* Allocate table of indeces to allow sorting on csname */
3122 /* Allocate flags to remember which ones already listed at start */
3123 /* pass = 0 --> fmt */
3124 /* pass = 1 --> after */
3125 void print_cs_names (FILE *output, int pass)
3127 int h, k, ccount, repeatflag;
3129 int nfcs = frozen_control_sequence;
3131 if (pass == 0 && csused == NULL)
3133 csused = (char *) malloc (nfcs);
3139 memset(csused, 0, nfcs);
3141 for (h = 0; h < (hash_size + 780); h++)
3148 for (h = hash_base + 1; h < nfcs; h++)
3150 if (pass == 1 && csused[h])
3153 if (hash[h].rh != 0)
3162 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
3163 ccount, (pass == 1) ? "new" : "");
3165 if (output == stderr)
3166 show_line(log_line, 1);
3167 else if (output == stdout)
3168 show_line(log_line, 0);
3170 fprintf(output, "%s", log_line);
3174 cnumtable = (int *) malloc (ccount * sizeof(int));
3176 if (cnumtable == NULL)
3181 for (h = hash_base + 1; h < nfcs; h++)
3183 if (pass == 1 && csused[h])
3186 if (hash[h].rh != 0)
3187 cnumtable[ccount++] = h;
3190 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3194 for (k = 0; k < ccount; k++)
3198 if (pass == 1 && csused[h])
3201 print_cs_name(output, h);
3204 sprintf(log_line, "\n");
3206 if (output == stderr)
3207 show_line(log_line, 1);
3208 else if (output == stdout)
3209 show_line(log_line, 0);
3211 fprintf(output, "%s", log_line);
3213 free((void *)cnumtable);
3216 if (pass == 1 && csused != NULL)
3223 /* k1 and k2 are positions in string pool */
3224 /* l1 and l2 are lengths of strings */
3225 int compare_strn (int k1, int l1, int k2, int l2)
3229 while (l1 > 0 && l2 > 0)
3244 return 1; /* first string longer */
3246 return -1; /* second string longer */
3248 return 0; /* strings match */
3250 /* compare two font names and their at sizes in qsort */
3251 int compare_fnt (const void *fp1, const void *fp2)
3253 int f1, f2, l1, l2, k1, k2, s;
3257 l1 = length(font_name[f1]);
3258 l2 = length(font_name[f2]);
3259 k1 = str_start[font_name[f1]];
3260 k2 = str_start[font_name[f2]];
3262 s = compare_strn (k1, l1, k2, l2);
3267 if (font_size[f1] > font_size[f2])
3269 else if (font_size[f1] < font_size[f2])
3272 return 0; /* should not ever get here */
3274 /* compare two font names */
3275 int compare_fnt_name (int f1, int f2)
3277 int l1, l2, k1, k2, s;
3279 l1 = length(font_name[f1]);
3280 l2 = length(font_name[f2]);
3281 k1 = str_start[font_name[f1]];
3282 k2 = str_start[font_name[f2]];
3284 s = compare_strn (k1, l1, k2, l2);
3288 /* decode checksum information */
3289 unsigned long checkdefault = 0x59265920; /* default signature */
3290 int decode_fourty (unsigned long checksum, char *codingvector)
3297 strcpy(codingvector, "unknwn");
3300 else if ((checksum >> 8) == (checkdefault >> 8))
3302 strcpy (codingvector, "fixed ");
3307 for (k = 0; k < 6; k++)
3309 c = (int) (checksum % 40);
3310 checksum = checksum / 40;
3315 c = (c + '0') - ('z' - 'a') - 1;
3325 codingvector[5-k] = (char) c;
3327 codingvector[6] = '\0';
3333 double sclpnt (long x)
3337 pt = (double) x / 65536.0;
3338 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3343 void dvi_font_show(internal_font_number f, int suppressname)
3346 unsigned long checksum;
3347 char checksumvector[8];
3350 putc(' ', log_file);
3352 if (suppressname == 0)
3354 a = length(font_area[f]);
3355 l = length(font_name[f]);
3357 k = str_start[font_area[f]];
3359 memcpy(buffer, str_pool + k, length(font_area[f]));
3360 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
3362 k = str_start[font_name[f]];
3364 memcpy(buffer, str_pool + k, length(font_name[f]));
3365 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
3369 for (k = a + l; k < 16; k++)
3370 putc(' ', log_file);
3372 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3373 fputs(buffer, log_file);
3375 if (suppressname == 0)
3379 for (k = n; k < 16; k++)
3380 putc(' ', log_file);
3382 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
3383 decode_fourty(checksum, checksumvector);
3384 fprintf(log_file, "encoding: %s..", checksumvector);
3387 putc('\n', log_file);
3389 /* Allocate table of indeces to allow sorting on font name */
3390 void show_font_info (void)
3392 int k, m, fcount, repeatflag;
3397 for (k = 1; k <= font_ptr; k++)
3404 fnumtable = (short *) malloc(fcount * sizeof(short));
3406 fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
3410 for (k = 1; k <= font_ptr; k++)
3412 fnumtable[fcount++] = (short) k;
3414 qsort ((void *)fnumtable, fcount, sizeof(short), &compare_fnt);
3418 for (m = 0; m < fcount; m++)
3422 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3428 dvi_font_show(fnumtable[m], repeatflag);
3431 free((void *)fnumtable);