1 /* Copyright 2007 TeX Users Group
2 Copyright 2014 Clerk Ma
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #define REALLOC ourrealloc
29 #define REALLOC realloc
34 char *compiletime = __TIME__;
35 char *compiledate = __DATE__;
36 char *www = "http://www.tug.org/yandy";
37 char *copyright = "\nCopyright (C) 1993--2000 Y&Y, Inc.\n"
38 "Copyright (C) 2007 TeX Users Group.\n"
39 "Copyright (C) 2014 Clerk Ma.\n\n"
40 "This program is free software; you can redistribute it and/or modify\n"
41 "it under the terms of the GNU General Public License as published by\n"
42 "the Free Software Foundation; either version 2 of the License, or\n"
43 "(at your option) any later version.\n\n ";
44 char *yandyversion = "2.3.0";
45 char *application = "Y&Y TeX";
46 char *tex_version = "This is TeX, Version 3.14159265";
48 clock_t start_time, main_time, finish_time;
50 char * dvi_directory = "";
51 char * log_directory = "";
52 char * aux_directory = "";
53 char * fmt_directory = "";
54 char * pdf_directory = "";
58 char log_line[MAXLINE]; // used also in tex9.c
60 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
61 int format_spec = 0; /* non-zero if a format specified on command line */
62 int closed_already = 0; /* make sure we don't try this more than once */
63 boolean reorder_arg_flag = true; /* put command line flags/arguments first */
65 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
66 /* Used in tex0.c with wintodos[c-128] */
68 unsigned char wintodos[128] =
70 0, 0, 0, 159, 0, 0, 0, 0,
71 94, 0, 0, 0, 0, 0, 0, 0,
72 0, 96, 39, 0, 0, 7, 0, 0,
73 126, 0, 0, 0, 0, 0, 0, 0,
74 32, 173, 189, 156, 207, 190, 221, 21,
75 0, 184, 166, 174, 170, 45, 169, 0,
76 248, 241, 253, 252, 0, 230, 20, 250,
77 0, 251, 167, 175, 172, 171, 243, 168,
78 183, 181, 182, 199, 142, 143, 146, 128,
79 212, 144, 210, 211, 222, 214, 215, 216,
80 209, 165, 227, 224, 226, 229, 153, 158,
81 157, 235, 233, 234, 154, 237, 232, 225,
82 133, 160, 131, 198, 132, 134, 145, 135,
83 138, 130, 136, 137, 141, 161, 140, 139,
84 208, 164, 149, 162, 147, 228, 148, 246,
85 155, 151, 163, 150, 129, 236, 231, 152
88 void show_usage (void)
91 " Useage: yanytex [OPTION]... [+format_file] [tex_file]\n\n"
93 " show this usage summary\n"
95 " start up as iniTeX (create format file)\n"
97 " be verbose (show implementation version number)\n"
98 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
100 " do not show `non ASCII' characters in hexadecimal (show as is)\n"
101 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
102 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
104 " allow use of \\patterns after loading format (iniTeX only)\n"
106 " disable all extensions to basic TeX\n"
107 " --main-memory -m\n"
108 " initial main memory size in kilo words (iniTeX only)\n"
110 " hyphenation exception dictionary size (iniTeX only)\n"
112 " hyphenation pattern trie size (iniTeX only)\n"
114 " use `non ASCII' character mapping (xchr[]) defined in file\n"
116 " use `key replacement' defined in file\n"
118 " write DVI file in specified directory (default current directory)\n"
120 " write LOG file in specified directory (default current directory)\n"
122 " write AUX file in specified directory (default current directory)\n");
125 uexit(EXIT_FAILURE); // has this been setup yet ???
129 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
131 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
132 /* \t\t(applies to file name and format file name, if present)\n\ */
133 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
135 // Sep 27 1990 => 1990 Sep 27
136 // 012456789 0123456789
137 void scivilize (char * date)
142 strcpy (pyear, date + 7);
144 for (k = 5; k >= 0; k--)
145 date[k + 5] = date[k];
147 for (k = 0; k < 4; k++)
153 date[9] = '0'; /* replace space by '0' */
156 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35
157 void lcivilize (char * date)
162 strcpy (pyear, date + 20);
164 for (k = 18; k >= 0; k--)
169 for (k = 0; k < 4; k++)
175 // now writes result into given buffer
176 void stamp_it (char *s)
180 strcpy(date, compiledate);
182 sprintf(s, "%s %s ", application, yandyversion);
184 sprintf(s, "(compiled time: %s %s)", date, compiletime);
188 void stampcopy (char *s)
192 sprintf(s, "%s %s", copyright, www);
199 void read_xchr_sub (FILE * xchr_input)
201 char buffer[file_name_size];
202 int k, from, to, count = 0;
205 memset(xchr, NOTDEF, MAXCHRS);
206 memset(xord, NOTDEF, MAXCHRS);
208 #ifdef ALLOCATEBUFFER
209 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
211 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
214 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
217 from = (int) strtol (buffer, &s, 0);
218 to = (int) strtol (s, NULL, 0);
220 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
222 if (xchr[from] == (unsigned char) NOTDEF)
224 xchr[from] = (unsigned char) to;
228 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
229 show_line(log_line, 0);
232 if (xord[to] == NOTDEF)
234 xord[to] = (unsigned char) from;
238 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
239 show_line(log_line, 0);
246 for (k = 0; k < MAXCHRS; k++)
248 if (xchr[k] == NOTDEF) /* if it has not been filled */
250 if (xord[k] == NOTDEF) /* see whether used already */
252 xchr[k] = (unsigned char) k; /* no, so make identity */
253 xord[k] = (unsigned char) k; /* no, so make identity */
258 xchr[NOTDEF] = NOTDEF; /* fixed point of mapping */
262 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
263 show_line(log_line, 0);
265 for (k = 0; k < MAXCHRS; k++)
267 if (xchr[k] != NOTDEF)
269 sprintf(log_line, "%d => %d\n", k, xchr[k]);
270 show_line(log_line, 0);
276 char *replacement[MAXCHRS]; /* pointers to replacement strings */
278 void read_repl_sub (FILE * repl_input)
281 char buffer[file_name_size];
286 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
289 while (fgets(buffer, file_name_size, repl_input) != NULL)
291 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
294 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
298 if (*charname == '"') /* deal with quoted string "..." */
303 while (*s != '"' && *s != '\0')
304 s++; /* step up to " */
307 continue; /* sanity check */
313 s++; /* is it "" perhaps ? */
316 break; /* no, end of string */
319 *t++ = *s++; /* copy over */
322 *t = '\0'; /* and terminate */
325 if (chrs >= 0 && chrs < MAXCHRS)
326 replacement[chrs] = xstrdup(charname);
328 /* presently the following can never get triggered */
329 /* which is good, because it is perhaps not right ... */
330 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
331 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
332 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
333 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
334 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
336 if (chrs >= 0 && chrs < MAXCHRS)
337 replacement[chrs] = xstrdup(charname);
340 sprintf(log_line, "ERROR: don't understand %s", buffer);
341 show_line(log_line, 1);
347 puts("Key replacement table\n");
349 for (k = 0; k < MAXCHRS; k++)
351 if (replacement[k] != NULL)
353 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
354 show_line(log_line, 0);
360 /* Following used both to read xchr[] file and key replacement file */
361 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
362 int read_xchr_file (char *filename, int flag, char *argv[])
365 char infile[file_name_size];
368 if (filename == NULL)
373 sprintf(log_line, "Reading xchr/repl %s\n", filename);
374 show_line(log_line, 0);
377 /* first try using file as specified */
378 strcpy(infile, filename);
382 sprintf(log_line, "Trying %s\n", infile);
383 show_line(log_line, 0);
386 pinput = fopen (infile, "r");
390 if (strrchr(infile, '.') == NULL)
393 strcat(infile, ".map");
395 strcat(infile, ".key");
399 sprintf(log_line, "Trying %s\n", infile);
400 show_line(log_line, 0);
403 pinput = fopen (infile, "r");
409 strcpy(infile, argv[0]); /* try TeX program path */
411 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
412 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
413 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
415 strcat (infile, filename);
419 sprintf(log_line, "Trying %s\n", infile);
420 show_line(log_line, 0);
423 pinput = fopen (infile, "r");
427 if (strchr(infile, '.') == NULL)
430 strcat(infile, ".map");
432 strcat(infile, ".key");
436 sprintf(log_line, "Trying %s\n", infile);
437 show_line(log_line, 0);
440 pinput = fopen (infile, "r");
445 if (pinput == NULL) /* 97/July/31 */
447 strcpy (infile, argv[0]); /* try TeX program path */
449 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
450 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
451 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
453 strcat (infile, "keyboard\\");
454 strcat (infile, filename);
458 sprintf(log_line, "Trying %s\n", infile);
459 show_line(log_line, 0);
462 pinput = fopen (infile, "r");
466 if (strchr(infile, '.') == NULL)
469 strcat(infile, ".map");
471 strcat(infile, ".key");
475 sprintf(log_line, "Trying %s\n", infile);
476 show_line(log_line, 0);
479 pinput = fopen (infile, "r");
483 /* Note: can't look in TeX source file dir, since that is not known yet */
486 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
487 flag ? " xchr[]" : "key mapping", filename);
488 show_line(log_line, 1);
489 perrormod (filename);
494 read_xchr_sub (pinput);
496 read_repl_sub (pinput);
498 (void) fclose (pinput);
502 /* need to also set `key_replace' here based on command line */
503 /* need to also allocate `buffercopy' here and free at end */
504 /* need to call `readreplace' in appropriate place */
506 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
510 /* ad hoc default minimum growth in memory realloc is 62% */
511 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
512 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
513 int total_allocated = 0; /* total memory allocated so far */
514 int ini_max_address = 0; /* maximum address when starting */
515 int max_address = 0; /* maximum address seen in allocated memory */
518 void show_maximums (FILE * output)
520 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
521 fputs(log_line, output);
524 /* our own version of realloc --- avoid supposed MicroSoft version bug */
525 /* also tries _expand first, which can avoid address growth ... */
528 void *ourrealloc (void *old, size_t new_size)
531 size_t old_size, overlap;
533 /* round up to nearest multiple of four bytes */
534 /* avoid unlikely alignment */
535 if ((new_size % 4) != 0)
536 new_size = ((new_size / 4) + 1) * 4;
539 return malloc (new_size); /* no old block - use malloc */
542 old_size = _msize (old);
544 old_size = malloc_usable_size (old);
547 if (old_size >= new_size && old_size < new_size + 4)
551 mnew = _expand (old, new_size); /* first try and expand in place MSVC */
553 mnew = realloc (old, new_size);
560 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
561 mnew, new_size, old, old_size);
562 show_line(log_line, 0);
568 /* do this if you want to call the real realloc next - */
569 mnew = realloc (old, new_size);
574 /* we are screwed typically if we ever drop through here - no more space */
575 mnew = malloc (new_size); /* otherwise find new space */
578 return mnew; /* if unable to allocate */
580 if (old_size < new_size)
585 memcpy (mnew, old, overlap); /* copy old data to new area */
586 free(old); /* free the old area */
592 void memory_error (char *s, int n)
596 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
597 show_maximums(log_file);
600 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
601 show_line(log_line, 1);
602 show_maximums(stderr);
605 void trace_memory (char *s, int n)
607 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
608 show_line(log_line, 0);
611 void update_statistics (int address, int size, int old_size)
613 if (address + size > max_address)
614 max_address = address + size;
616 total_allocated = total_allocated + size - old_size;
619 void probe_memory (void)
623 s = (char *) malloc(4); /* get current top address */
625 update_statistics ((int) s, 0, 0); /* show where we are */
628 void probe_show (void)
631 show_maximums(stdout);
634 size_t roundup (size_t n)
639 return ((n / 4) + 1) * 4;
643 /* using allocating hyphenation trie slows things down maybe 1% */
644 /* but saves typically (270k - 55k) = 215k of memory */
645 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
646 /* since hyphenation trie cannot be extended (after iniTeX) */
647 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
649 /* NOTE: we don't ever reallocate these */
650 /* returns -1 if it fails */
652 int allocate_tries (int trie_max)
656 if (trie_max > 1000000)
659 nl = (trie_max + 1) * sizeof(halfword);
660 no = (trie_max + 1) * sizeof(halfword);
661 nc = (trie_max + 1) * sizeof(quarterword);
665 trace_memory("hyphen trie", n);
667 trie_trl = (halfword *) malloc(roundup(nl));
668 trie_tro = (halfword *) malloc(roundup(no));
669 trie_trc = (quarterword *) malloc(roundup(nc));
671 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
673 memory_error("hyphen trie", n);
679 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
680 show_line(log_line, 0);
683 update_statistics((int) trie_trl, nl, 0);
684 update_statistics((int) trie_tro, no, 0);
685 update_statistics((int) trie_trc, nc, 0);
687 trie_size = trie_max;
696 #ifdef ALLOCATEHYPHEN
697 boolean prime(int); /* test function later in this file */
699 int current_prime = 0; /* remember in case reallocated later */
701 /* we don't return an address here, since TWO memory regions allocated */
702 /* plus, we don't really reallocate, we FLUSH the old information totally */
703 /* returns -1 if it fails */
705 int realloc_hyphen (int hyphen_prime)
709 if (!prime(hyphen_prime))
711 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
712 show_line(log_line, 1);
716 /* need not/cannot preserve old contents when hyphen prime is changed */
717 /* if (hyph_list != NULL) free(hyph_list); */
718 /* if (hyph_word != NULL) free(hyph_word); */
719 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
720 nw = (hyphen_prime + 1) * sizeof(str_number);
721 nl = (hyphen_prime + 1) * sizeof(halfword);
725 trace_memory("hyphen exception", n);
727 hyph_word = (str_number *) REALLOC (hyph_word, nw);
728 hyph_list = (halfword *) REALLOC (hyph_list, nl);
730 if (hyph_word == NULL || hyph_list == NULL)
732 memory_error("hyphen exception", n);
738 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
739 show_line(log_line, 0);
742 /* cannot preserve old contents when hyphen prime is changed */
744 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
746 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
750 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
752 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
757 if (current_prime != 0)
759 update_statistics((int) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
760 update_statistics((int) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
764 update_statistics((int) hyph_word, nw, 0);
765 update_statistics((int) hyph_list, nl, 0);
768 current_prime = hyphen_prime;
777 int current_mem_size = 0; /* current total words in main mem allocated -1 */
779 /* this gets called from itex.c when it figures out what mem_top is */
780 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
781 /* initial allocation only, may get expanded later */
782 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
783 /* returns NULL if it fails */
786 /* initial main memory alloc - mem_top */
787 memory_word *allocate_main_memory (int size)
791 if (main_memory != NULL)
794 puts("Reallocating initial memory allocation\n");
797 mem_top = mem_bot + size;
799 mem_start = 0; /* bottom of memory allocated by system */
800 mem_min = 0; /* bottom of area made available to TeX */
801 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
804 trace_memory("main memory", n);
806 main_memory = (memory_word *) REALLOC (main_memory, n);
808 if (main_memory == NULL)
810 memory_error("initial main memory", n);
817 sprintf(log_line, "Address main memory == %d\n", main_memory);
818 show_line(log_line, 0);
823 if (mem_start != 0 && !is_initex)
824 mem = main_memory - mem_start;
828 sprintf(log_line, "Offset address main memory == %d\n", mem);
829 show_line(log_line, 0);
832 update_statistics((int) main_memory, n, (current_mem_size + 1) * sizeof (memory_word));
833 /* current_mem_size = (mem_max - mem_start + 1); */
834 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
844 /* int firstallocation = 1; */
846 /* increase main memory allocation at low end and high end */
847 /* called only from tex0.c *//* called with one of lo_size or hi_size == 0 */
848 /* returns NULL if it fails */
850 memory_word * realloc_main (int lo_size, int hi_size)
855 memory_word * new_memory = NULL;
859 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", lo_size, hi_size);
860 show_line(log_line, 0);
865 puts("ERROR: Cannot extent main memory in iniTeX\n");
868 puts("Please use `-m=...' on command line\n");
875 sprintf(log_line, "Old Address %s == %d\n", "main memory", main_memory);
876 show_line(log_line, 0);
879 /* if we REALLY run up to limit ! */
880 if (current_mem_size + 1 == max_mem_size)
882 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
887 /* first allocation should expand *both* lo and hi */
888 if (hi_size == 0 && mem_end == mem_max)
891 if (lo_size == 0 && mem_start == mem_min)
894 /* try and prevent excessive frequent reallocations */
895 /* while avoiding over allocation by too much */
896 min_size = current_mem_size / 100 * percent_grow;
898 if (lo_size + hi_size < min_size)
900 if (lo_size > 0 && hi_size > 0)
902 lo_size = min_size / 2;
903 hi_size = min_size / 2;
905 else if (lo_size > 0)
907 else if (hi_size > 0)
911 if (lo_size > 0 && lo_size < mem_top / 2)
912 lo_size = mem_top / 2;
914 if (hi_size > 0 && hi_size < mem_top / 2)
915 hi_size = mem_top / 2;
917 for (k = 0; k < MAXSPLITS; k++)
919 new_size = current_mem_size + lo_size + hi_size;
921 if (new_size >= max_mem_size) /* bump against limit - ha ha ha */
923 while (new_size >= max_mem_size) {
924 lo_size = lo_size / 2; hi_size = hi_size / 2;
925 new_size = current_mem_size + lo_size + hi_size;
929 n = (new_size + 1) * sizeof (memory_word);
932 trace_memory("main memory", n);
934 new_memory = (memory_word *) REALLOC (main_memory, n);
936 if (new_memory != NULL)
937 break; /* did we get it ? */
939 if (current_mem_size == 0)
940 break; /* in case we ever use for initial */
942 lo_size = lo_size / 2; hi_size = hi_size / 2;
945 if (new_memory == NULL)
947 memory_error("main memory", n);
953 sprintf(log_line, "New Address %s == %d\n", "main memory", new_memory);
954 show_line(log_line, 0);
959 /* shift everything upward to make space for new low area */
962 sprintf(log_line, "memmove %d %d %d \n", new_memory + lo_size,
963 new_memory, (current_mem_size + 1) * sizeof(memory_word));
964 show_line(log_line, 0);
966 memmove (new_memory + lo_size, new_memory,
967 (current_mem_size + 1) * sizeof(memory_word));
968 /* could reduce words moved by (mem_max - mem_end) */
970 main_memory = new_memory; /* remember for free later */
973 mem_start = mem_start - lo_size; /* update lower limit */
976 mem_max = mem_max + hi_size; /* update upper limit */
978 update_statistics ((int) main_memory, n,
979 (current_mem_size + 1) * sizeof (memory_word));
980 current_mem_size = new_size;
982 if (current_mem_size != mem_max - mem_start)
984 puts("ERROR: Impossible Memory Error\n");
988 mem = main_memory - mem_start;
1000 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1002 int current_font_mem_size = 0;
1004 /* fmemoryword can be either halfword or memory_word */
1005 memory_word * realloc_font_info (int size)
1007 memory_word * new_font_info = NULL;
1014 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1015 show_line(log_line, 0);
1017 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1018 /* during initial allocation current_font_mem_size == 0 */
1019 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
1021 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1022 return font_info; /* pass it back to TeX 99/Fabe/4 */
1024 /* try and prevent excessive frequent reallocations */
1025 /* while avoiding over allocation by too much */
1026 /* min_size = current_font_mem_size / 2; */
1027 min_size = current_font_mem_size / 100 * percent_grow;
1029 if (size < min_size)
1032 if (size < initial_font_mem_size)
1033 size = initial_font_mem_size;
1035 for (k=0; k < MAXSPLITS; k++)
1037 new_size = current_font_mem_size + size;
1039 if (new_size > font_mem_size)
1040 new_size = font_mem_size; /* bump against limit */
1042 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1043 n = (new_size + 1) * sizeof (memory_word);
1046 trace_memory("font_info", n);
1048 new_font_info = (memory_word *) REALLOC (font_info, n);
1050 if (new_font_info != NULL)
1051 break; /* did we get it ? */
1053 if (current_font_mem_size == 0)
1054 break; /* initial allocation must work */
1059 if (new_font_info == NULL)
1061 memory_error("font", n);
1062 return font_info; /* try and continue !!! */
1065 font_info = new_font_info;
1069 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1070 show_line(log_line, 0);
1073 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(memory_word));
1074 current_font_mem_size = new_size;
1083 #ifdef ALLOCATESTRING
1084 int current_pool_size = 0;
1086 packed_ASCII_code * realloc_str_pool (int size)
1091 packed_ASCII_code *newstrpool = NULL;
1095 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1096 show_line(log_line, 0);
1099 if (current_pool_size == pool_size)
1101 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1103 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1106 min_size = current_pool_size / 100 * percent_grow;
1108 if (size < min_size)
1111 if (size < initial_pool_size)
1112 size = initial_pool_size;
1114 for (k = 0; k < MAXSPLITS; k++)
1116 new_size = current_pool_size + size;
1118 if (new_size > pool_size)
1119 new_size = pool_size;
1120 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1121 n = (new_size + 1) * sizeof (packed_ASCII_code);
1124 trace_memory("str_pool", n);
1126 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1128 if (newstrpool != NULL)
1129 break; /* did we get it ? */
1131 if (current_pool_size == 0)
1132 break; /* initial allocation must work */
1134 size = size / 2; /* else can retry smaller */
1137 if (newstrpool == NULL)
1139 memory_error("string pool", n);
1140 return str_pool; /* try and continue !!! */
1143 str_pool = newstrpool;
1144 update_statistics ((int) str_pool, n, current_pool_size);
1145 current_pool_size = new_size;
1149 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1150 show_line(log_line, 0);
1160 #ifdef ALLOCATESTRING
1161 int current_max_strings = 0;
1163 pool_pointer *realloc_str_start (int size)
1168 pool_pointer * new_str_start = NULL;
1172 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1173 show_line(log_line, 0);
1176 if (current_max_strings == max_strings)
1178 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1180 return str_start; /* pass it back to TeX 99/Fabe/4 */
1183 min_size = current_max_strings / 100 * percent_grow;
1185 if (size < min_size)
1188 if (size < initial_max_strings)
1189 size = initial_max_strings;
1191 for (k = 0; k < MAXSPLITS; k++)
1193 new_size = current_max_strings + size;
1195 if (new_size > max_strings)
1196 new_size = max_strings;
1197 /* important + 1 since str_start[maxstring + 1] originally */
1198 n = (new_size + 1) * sizeof (pool_pointer);
1201 trace_memory("str_start", n);
1203 new_str_start = (pool_pointer *) REALLOC (str_start, n);
1205 if (new_str_start != NULL)
1206 break; /* did we get it ? */
1208 if (current_max_strings == 0)
1209 break; /* initial allocation must work */
1211 size = size / 2; /* otherwise can try smaller */
1214 if (new_str_start == NULL)
1216 memory_error("string pointer", n);
1217 return str_start; /* try and continue */
1220 str_start = new_str_start;
1221 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1222 current_max_strings = new_size;
1226 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1227 show_line(log_line, 0);
1238 /* returns -1 if it fails */
1239 /* size == trie_size */
1240 int allocate_ini (int size)
1242 int n, nl, no, nc, nr, nh, nt;
1244 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1245 no = (size + 1) * sizeof(trie_op_code);
1246 nc = (size + 1) * sizeof(packed_ASCII_code);
1247 /* nt = (size + 1) * sizeof(boolean); */
1248 nt = (size + 1) * sizeof(char);
1249 n = nl + no + nc + nr + nh + nt;
1250 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1251 3 * sizeof(trie_pointer) + sizeof (char)); */
1253 trace_memory ("iniTeX hyphen trie", n);
1255 trie_l = (trie_pointer *) malloc (roundup(nl));
1256 trie_o = (trie_op_code *) malloc (roundup(no));
1257 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1258 trie_r = (trie_pointer *) malloc (roundup(nr));
1259 trie_hash = (trie_pointer *) malloc (roundup(nh));
1260 trie_taken = (char *) malloc (roundup(nt));
1262 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1263 trie_hash == NULL || trie_taken == NULL)
1265 memory_error("iniTeX hyphen trie", n);
1266 // exit (1); /* serious error */
1272 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n", trie_l, trie_o, trie_c);
1273 show_line(log_line, 0);
1274 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1275 trie_r, trie_hash, trie_taken);
1276 show_line(log_line, 0);
1279 update_statistics ((int) trie_l, nl, 0);
1280 update_statistics ((int) trie_o, no, 0);
1281 update_statistics ((int) trie_c, nc, 0);
1282 update_statistics ((int) trie_r, nr, 0);
1283 update_statistics ((int) trie_hash, nh, 0);
1284 update_statistics ((int) trie_taken, nt, 0);
1285 /* trie_size = size; */ /* ??? */
1289 return 0; // success
1293 #ifdef ALLOCATESAVESTACK
1294 int current_save_size = 0;
1296 memory_word *realloc_save_stack (int size)
1299 int n = 0, new_size = 0;
1300 memory_word * new_save_stack = NULL;
1304 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1305 show_line(log_line, 0);
1308 if (current_save_size == save_size) /* arbitrary limit */
1310 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1312 return save_stack; /* let TeX handle the error */
1315 min_size = current_save_size / 100 * percent_grow;
1317 if (size < min_size)
1320 if (size < initial_save_size)
1321 size = initial_save_size;
1323 for (k = 0; k < MAXSPLITS; k++)
1325 new_size = current_save_size + size;
1327 if (new_size > save_size)
1328 new_size = save_size;
1330 n = (new_size + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1333 trace_memory("save_stack", n);
1335 new_save_stack = (memory_word *) REALLOC (save_stack, n);
1337 if (new_save_stack != NULL)
1338 break; /* did we get it ? */
1340 if (current_save_size == 0)
1341 break; /* initial allocation must work */
1343 size = size / 2; /* else can retry smaller */
1346 if (new_save_stack == NULL)
1348 memory_error("save stack", n);
1349 return save_stack; /* try and continue !!! */
1352 save_stack = new_save_stack;
1353 update_statistics ((int) save_stack, n, current_save_size);
1354 current_save_size = new_size;
1358 sprintf(log_line, "Current %s %d\n", "save_size", current_save_size);
1359 show_line(log_line, 0);
1360 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1361 show_line(log_line, 0);
1371 #ifdef ALLOCATEINPUTSTACK
1372 int current_stack_size = 0; /* input stack size */
1374 in_state_record *realloc_input_stack (int size)
1377 int n = 0, new_size = 0;
1378 in_state_record * new_input_stack = NULL;
1382 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1383 show_line(log_line, 0);
1386 if (current_stack_size == stack_size) /* arbitrary limit */
1388 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1393 min_size = current_stack_size / 100 * percent_grow;
1395 if (size < min_size)
1398 if (size < initial_stack_size)
1399 size = initial_stack_size;
1401 for (k = 0; k < MAXSPLITS; k++)
1403 new_size = current_stack_size + size;
1405 if (new_size > stack_size)
1406 new_size = stack_size;
1408 n = (new_size + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1411 trace_memory("input_stack", n);
1413 new_input_stack = (in_state_record *) REALLOC (input_stack, n);
1415 if (new_input_stack != NULL)
1416 break; /* did we get it ? */
1418 if (current_stack_size == 0)
1419 break; /* initial allocation must work */
1421 size = size / 2; /* else can retry smaller */
1424 if (new_input_stack == NULL)
1426 memory_error("input stack", n);
1427 return input_stack; /* try and continue !!! */
1430 input_stack = new_input_stack;
1431 update_statistics ((int) input_stack, n, current_stack_size);
1432 current_stack_size = new_size;
1436 sprintf(log_line, "Current %s %d\n", "stack_size", current_stack_size);
1437 show_line(log_line, 0);
1438 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1439 show_line(log_line, 0);
1443 probe_show(); /* 94/Mar/25 */
1449 #ifdef ALLOCATENESTSTACK
1450 int current_nest_size = 0; /* current nest size */
1452 list_state_record *realloc_nest_stack (int size)
1455 int n = 0, new_size = 0;
1456 list_state_record * new_nest = NULL;
1460 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1461 show_line(log_line, 0);
1464 if (current_nest_size == nest_size) /* arbitrary limit */
1466 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1468 return nest; /* let TeX handle the error */
1471 min_size = current_nest_size / 100 * percent_grow;
1473 if (size < min_size)
1476 if (size < initial_nest_size)
1477 size = initial_nest_size;
1479 for (k = 0; k < MAXSPLITS; k++)
1481 new_size = current_nest_size + size;
1483 if (new_size > nest_size)
1484 new_size = nest_size;
1486 n = (new_size + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1489 trace_memory("nest stack", n);
1491 new_nest = (list_state_record *) REALLOC (nest, n);
1493 if (new_nest != NULL)
1494 break; /* did we get it ? */
1496 if (current_nest_size == 0)
1497 break; /* initial allocation must work */
1499 size = size / 2; /* else can retry smaller */
1502 if (new_nest == NULL)
1504 memory_error("nest stack", n);
1505 return nest; /* try and continue !!! */
1509 update_statistics ((int) nest, n, current_nest_size);
1510 current_nest_size = new_size;
1514 sprintf(log_line, "Current %s %d\n", "nest_size", current_nest_size);
1515 show_line(log_line, 0);
1516 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1517 show_line(log_line, 0);
1527 #ifdef ALLOCATEPARAMSTACK
1528 int current_param_size = 0;
1530 halfword *realloc_param_stack (int size)
1533 int n = 0, new_size = 0;
1534 halfword * new_param = NULL;
1538 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1539 show_line(log_line, 0);
1542 if (current_param_size == param_size) /* arbitrary limit */
1544 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1546 return param_stack; /* let TeX handle the error */
1549 min_size = current_param_size / 100 * percent_grow;
1551 if (size < min_size)
1554 if (size < initial_param_size)
1555 size = initial_param_size;
1557 for (k = 0; k < MAXSPLITS; k++)
1559 new_size = current_param_size + size;
1561 if (new_size > param_size)
1562 new_size = param_size;
1564 n = (new_size + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1567 trace_memory("param stack", n);
1569 new_param = (halfword *) REALLOC (param_stack, n);
1571 if (new_param != NULL)
1572 break; /* did we get it ? */
1574 if (current_param_size == 0)
1575 break; /* initial allocation must work */
1577 size = size / 2; /* else can retry smaller */
1580 if (new_param == NULL)
1582 memory_error("param stack", n);
1583 return param_stack; /* try and continue !!! */
1586 param_stack = new_param;
1587 update_statistics ((int) param_stack, n, current_param_size);
1588 current_param_size = new_size;
1592 sprintf(log_line, "Current %s %d\n", "param_size", current_param_size);
1593 show_line(log_line, 0);
1594 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1595 show_line(log_line, 0);
1599 probe_show(); /* 94/Mar/25 */
1605 #ifdef ALLOCATEBUFFER
1606 int current_buf_size = 0;
1608 ASCII_code * realloc_buffer (int size)
1611 int n = 0, new_size = 0;
1612 ASCII_code * new_buffer = NULL;
1616 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1617 show_line(log_line, 0);
1620 if (current_buf_size == buf_size)
1622 /* memory_error ("buffer", buf_size); */
1624 return buffer; /* pass it back to TeX 99/Fabe/4 */
1627 min_size = current_buf_size / 100 * percent_grow;
1629 if (size < min_size)
1632 if (size < initial_buf_size)
1633 size = initial_buf_size;
1635 for (k = 0; k < MAXSPLITS; k++)
1637 new_size = current_buf_size + size;
1639 if (new_size > buf_size)
1640 new_size = buf_size;
1642 n = (new_size + 1) * sizeof(ASCII_code);
1645 trace_memory("buffer", n);
1647 new_buffer = (ASCII_code *) REALLOC (buffer, n);
1649 if (new_buffer != NULL)
1650 break; /* did we get it ? */
1652 if (current_buf_size == 0)
1653 break; /* initial allocation must work */
1658 if (new_buffer == NULL)
1660 memory_error("buffer", n);
1661 return buffer; /* try and continue !!! */
1664 buffer = new_buffer;
1665 update_statistics ((int) buffer, n, current_buf_size);
1668 memset(buffer + current_buf_size, 0, new_size - current_buf_size);
1670 for (k = current_buf_size; k < new_size; k++) buffer[k]= 0;
1673 current_buf_size = new_size;
1677 sprintf(log_line, "Current %s %d\n", "buffer", current_buf_size);
1678 show_line(log_line, 0);
1679 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1680 show_line(log_line, 0);
1690 /* here is the main memory allocation routine -- calls the above */
1691 /* returns -1 if it fails */
1692 /* allocate rather than static 93/Nov/26 */
1693 int allocate_memory (void)
1695 #ifdef ALLOCATEINPUTSTACK
1697 current_stack_size = 0;
1698 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1701 #ifdef ALLOCATENESTSTACK
1703 current_nest_size = 0;
1704 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1707 #ifdef ALLOCATEPARAMSTACK
1709 current_param_size = 0;
1710 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1713 #ifdef ALLOCATESAVESTACK
1715 current_save_size = 0;
1716 save_stack = realloc_save_stack (initial_save_size);
1720 buffer = NULL; /* need to do earlier */
1721 current_buf_size = 0;
1722 buffer = realloc_buffer (initial_buf_size);
1725 #ifdef ALLOCATESTRING
1727 current_pool_size = 0;
1729 current_max_strings = 0;
1731 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1735 puts("ini TeX pool and string allocation\n");
1737 str_pool = realloc_str_pool(initial_pool_size);
1738 str_start = realloc_str_start(initial_max_strings);
1742 /* the following can save a lot of the usual 800k fixed allocation */
1745 current_font_mem_size = 0;
1746 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1747 /* if ini-TeX we need to do it here - no format file read later */
1749 font_info = realloc_font_info (initial_font_mem_size);
1755 mem_min = mem_bot; /* just to avoid complaints in texbody */
1756 mem_top = mem_initex;
1758 /* allocate main memory here if this is iniTeX */
1759 /* otherwise wait for format undumping in itex.c ... */
1762 /* avoid this if format specified on command line ??? */
1763 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1764 mem = allocate_main_memory(mem_initex); /* made variable ! */
1767 return -1; /* serious error */
1771 /* now for the hyphenation exception stuff */
1772 #ifdef ALLOCATEHYPHEN
1775 /* this will be overridden later by what is in format file */
1776 hyphen_prime = default_hyphen_prime;
1777 /* non ini-TeX use assumes format will be read and that specifies size */
1780 if (new_hyphen_prime)
1781 hyphen_prime = new_hyphen_prime;
1783 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1788 /* now for memory for the part of the hyphenation stuff that always needed */
1789 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1790 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1791 #ifdef ALLOCATETRIES
1794 if (allocate_tries (trie_size))
1799 /* now for memory for hyphenation stuff needed only when running iniTeX */
1803 if (allocate_ini(trie_size))
1808 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1809 trie_c = NULL; /* (trie_size + 1) * char */
1810 trie_taken = NULL; /* (trie_size + 1) * boolean */
1814 return 0; // success
1817 /* returns non-zero if error - done to test integrity of stack mostly */
1818 int free_memory (void)
1820 unsigned int heap_total = 0;
1823 puts("free_memory ");
1825 if (verbose_flag || trace_flag)
1826 show_maximums(stdout);
1830 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1831 heap_total, max_address);
1832 show_line(log_line, 0);
1837 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1838 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1839 show_line(log_line, 0);
1843 puts("Freeing memory again\n");
1845 /* only free memory if safe ... additional check */
1849 if (trie_taken != NULL)
1852 if (trie_hash != NULL)
1868 trie_hash = trie_l = trie_r = NULL;
1874 #ifdef ALLOCATETRIES
1875 if (trie_trc != NULL)
1878 if (trie_tro != NULL)
1881 if (trie_trl != NULL)
1885 trie_tro = trie_trl = NULL;
1888 #ifdef ALLOCATEHYPHEN
1889 if (hyph_list != NULL)
1892 if (hyph_word != NULL)
1900 if (main_memory != NULL)
1907 if (font_info != NULL)
1913 #ifdef ALLOCATESTRING
1914 if (str_start != NULL)
1917 if (str_pool != NULL)
1924 #ifdef ALLOCATEPARAMSTACK
1925 if (param_stack != NULL)
1931 #ifdef ALLOCATENESTSTACK
1938 #ifdef ALLOCATEINPUTSTACK
1939 if (input_stack != NULL)
1945 #ifdef ALLOCATESAVESTACK
1946 if (save_stack != NULL)
1952 if (format_file != NULL)
1955 if (source_direct != NULL)
1956 free(source_direct);
1958 format_file = source_direct = NULL;
1960 if (dvi_file_name != NULL)
1961 free(dvi_file_name);
1963 if (log_file_name != NULL)
1964 free(log_file_name);
1966 if (pdf_file_name != NULL)
1967 free(pdf_file_name);
1969 pdf_file_name = log_file_name = dvi_file_name = NULL;
1974 boolean prime (int x)
1977 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1982 for (k = 3; k < x; k = k + 2)
1997 boolean show_use = false;
1998 boolean floating = false;
2000 void complainarg (int c, char *s)
2002 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
2003 show_line(log_line, 1);
2007 /* following is list of allowed command line flags and args */
2009 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
2011 void reorderargs (int ac, char **av)
2015 char takeargs[256]; /* large enough for all command line arg chars */
2019 return; /* no args ! */
2023 t = takeargs; /* list of those that take args */
2025 while (*s != '\0' && *(s + 1) != '\0')
2027 if (*(s + 1) == '=')
2028 *t++ = *s++; /* copy over --- without the = */
2037 show_line(takeargs, 0);
2048 if (n + 1 < ac && *(av[n] + 2) == '\0' &&
2049 strchr(takeargs, *(av[n] + 1)) != NULL)
2050 n += 2; /* step over it */
2065 while (m < ac && *av[m] != '-')
2066 m++; /* first command */
2070 /* does it take an argument ? and is this argument next ? */
2071 /* check first whether the `-x' is isolated, or arg follows directly */
2072 /* then check whether this is one of those that takes an argument */
2073 if (m+1 < ac && *(av[m] + 2) == '\0' &&
2074 strchr(takeargs, *(av[m] + 1)) != NULL)
2076 s = av[m]; /* move command down before non-command */
2080 av[m + 1] = av[m - 1];
2084 n += 2; /* step over moved args */
2088 s = av[m]; /* move command down before non-command */
2094 n++; /* step over moved args */
2099 int test_align (int address, int size, char *name)
2110 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
2111 show_line(log_line, 0);
2117 /* activate detailed checking of alignment when trace_flag is set */
2119 void check_fixed_align (int flag)
2123 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT"))
2125 puts("PLEASE RECOMPILE ME!\n");
2128 #ifdef CHECKALIGNMENT
2132 test_align ((int) &mem_top, 4, "mem_top");
2133 test_align ((int) &mem_max, 4, "mem_max");
2134 test_align ((int) &mem_min, 4, "mem_min");
2135 test_align ((int) &bad, 4, "bad");
2136 test_align ((int) &trie_size, 4, "trie_size");
2137 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2138 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2139 test_align ((int) &name_length, 4, "name_length");
2140 test_align ((int) &first, 4, "first");
2141 test_align ((int) &last, 4, "last");
2142 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2143 test_align ((int) &pool_ptr, 4, "pool_ptr");
2144 test_align ((int) &str_ptr, 4, "str_ptr");
2145 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2146 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2147 test_align ((int) &log_file, 4, "log_file");
2148 test_align ((int) &tally, 4, "tally");
2149 test_align ((int) &term_offset, 4, "term_offset");
2150 test_align ((int) &file_offset, 4, "file_offset");
2151 test_align ((int) &trick_count, 4, "trick_count");
2152 test_align ((int) &first_count, 4, "first_count");
2153 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2154 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2155 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2156 test_align ((int) &use_err_help, 4, "use_err_help");
2157 test_align ((int) &interrupt, 4, "interrupt");
2158 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2159 test_align ((int) &arith_error, 4, "arith_error");
2160 test_align ((int) &tex_remainder, 4, "tex_remainder");
2161 test_align ((int) &temp_ptr, 4, "temp_ptr");
2162 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2163 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2164 test_align ((int) &var_used, 4, "var_used");
2165 test_align ((int) &dyn_used, 4, "dyn_used");
2166 test_align ((int) &avail, 4, "avail");
2167 test_align ((int) &mem_end, 4, "mem_end");
2168 test_align ((int) &mem_start, 4, "mem_start");
2169 test_align ((int) &rover, 4, "rover");
2170 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2171 test_align ((int) &depth_threshold, 4, "depth_threshold");
2172 test_align ((int) &breadth_max, 4, "breadth_max");
2173 test_align ((int) &nest, sizeof(nest[0]), "nest");
2174 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2175 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2176 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2177 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2179 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2180 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2181 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2182 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2183 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2184 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2185 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2186 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2188 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2189 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2190 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2191 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2192 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2193 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2194 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2195 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2196 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2197 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2198 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2199 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2200 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2201 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2202 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2203 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2204 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2205 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2206 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2207 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2208 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2209 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2210 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2211 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2213 #ifdef ALLOCATEDVIBUF
2214 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2217 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2218 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2219 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2220 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2221 test_align ((int) &background, sizeof(background[0]), "background");
2222 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2223 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2224 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2225 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2226 test_align ((int) &hc, sizeof(hc[0]), "hc");
2227 test_align ((int) &hu, sizeof(hu[0]), "hu");
2228 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2229 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2231 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2232 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2233 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2234 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2236 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2237 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2238 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2239 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2240 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2242 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2243 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2244 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2245 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2249 void check_alloc_align (int flag)
2253 if (test_align((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2254 puts("PLEASE RECOMPILE ME!\n");
2256 #ifdef CHECKALIGNMENT
2261 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2264 #ifndef ALLOCATEDVIBUF
2265 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2268 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2269 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2270 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2271 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2272 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2273 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2274 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2275 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2276 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2277 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2278 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2279 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2280 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2281 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2282 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2286 boolean backwardflag = false; /* don't cripple all advanced features */
2287 boolean shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2288 boolean usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2290 /* cache to prevent allocating twice in a row */
2292 char *lastname = NULL, *lastvalue = NULL;
2294 /* returns allocated string -- these strings are not freed again */
2295 /* is it safe to do that now ? 98/Jan/31 */
2296 char * grabenv (char * varname)
2300 if (varname == NULL)
2303 if (*varname == '\0')
2306 if (lastname != NULL && strcasecmp(lastname, varname) == 0)
2310 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2311 show_line(log_line, 0);
2314 return xstrdup(lastvalue);
2317 s = getenv(varname);
2321 if (lastname != NULL)
2324 lastname = xstrdup(varname);
2326 if (lastvalue != NULL)
2329 lastvalue = xstrdup(s);
2337 void flush_trailing_slash (char *directory)
2341 if (strcmp(directory, "") != 0)
2343 s = directory + strlen(directory) - 1;
2345 if (*s == '\\' || *s == '/')
2350 void knuthify (void)
2352 restrict_to_ascii = false; /* don't complain non ASCII */
2353 allow_patterns = false; /* don't allow pattern redefinition */
2354 show_in_hex = true; /* show character code in hex */
2355 show_in_dos = false; /* redundant with previous */
2356 show_numeric = false; /* don't show character code decimal */
2357 show_missing = false; /* don't show missing characters */
2358 civilize_flag = false; /* don't reorder date fields */
2359 c_style_flag = false; /* don't add file name to error msg */
2360 show_fmt_flag = false; /* don't show format file in log */
2361 show_tfm_flag = false; /* don't show metric file in log */
2363 show_line_break_stats = false; /* do not show line break stats */
2364 show_fonts_used = false;
2365 default_rule = 26214; /* revert to default rule thickness */
2366 pseudo_tilde = false;
2367 pseudo_space = false;
2368 show_texinput_flag = false;
2369 truncate_long_lines = false;
2370 allow_quoted_names = false;
2371 show_cs_names = false;
2372 font_dimen_zero = false;
2373 ignore_frozen = false;
2374 suppress_f_ligs = false;
2375 full_file_name_flag = false;
2376 knuth_flag = true; /* so other code can know about this */
2379 /* following made global so analyze_flag can be made separate procedure */
2381 char * xchr_file = NULL;
2382 char * repl_file = NULL;
2384 char * short_options = "m:e:h:0:H:g:P:o:l:a:wvpiKLZMdp2t?u";
2386 static struct option long_options[] =
2388 {"main-memory", 1, 0, 'm'},
2389 {"hyph-size", 1, 0, 'e'},
2390 {"trie-size", 1, 0, 'h'},
2391 {"backend", 1, 0, '0'},
2392 {"tab-step", 1, 0, 'H'},
2393 {"percent-grow", 1, 0, 'g'},
2394 {"default-rule", 1, 0, 'P'},
2395 {"dvi-dir", 1, 0, 'o'},
2396 {"log-dir", 1, 0, 'l'},
2397 {"aux-dir", 1, 0, 'a'},
2398 {"showhex", 0, 0, 'w'},
2399 {"verbose", 0, 0, 'v'},
2400 {"patterns", 0, 0, 'p'},
2401 {"initex", 0, 0, 'i'},
2402 {"knuthify", 0, 0, 'K'},
2403 {"cstyle", 0, 0, 'L'},
2404 {"showtfm", 0, 0, 'Z'},
2405 {"showmissing", 0, 0, 'M'},
2406 {"deslash", 0, 0, 'd'},
2407 {"patterns", 0, 0, 'p'},
2408 {"suppressflig", 0, 0, '2'},
2409 {"trace", 0, 0, 't'},
2410 {"help", 0, 0, '?'},
2411 {"usage", 0, 0, 'u'},
2415 int analyze_flag (int c, char *optarg)
2420 want_version = true;
2421 verbose_flag = true;
2427 interaction = batch_mode; /* quiet mode */
2430 interaction = nonstop_mode; /* run mode */
2433 interaction = scroll_mode; /* scroll mode */
2436 interaction = error_stop_mode; /* tex mode */
2439 backwardflag = true;
2440 knuthify(); /* revert to `standard' Knuth TeX */
2443 c_style_flag = true; /* C style error msg 94/Mar/21 */
2446 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2449 show_missing = false; /* do not show missing 94/June/10 */
2452 deslash = false; /* flipped 93/Nov/18 */
2453 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2456 allow_patterns = true; /* 93/Nov/26 */
2457 /* reset_exceptions = true; */ /* 93/Dec/23 */
2459 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2461 show_in_hex = true; /* flipped 00/Jun/18 */
2464 show_in_dos = true; /* 96/Jan/26 */
2467 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2470 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2473 show_fonts_used = false; /* 97/Dec/24 */
2476 shorten_file_name = true; /* 95/Feb/20 */
2479 show_cs_names = true; /* 98/Mar/31 */
2482 ignore_frozen = true; /* 98/Oct/5 */
2485 font_dimen_zero = false; /* 98/Oct/5 */
2488 show_texinput_flag = false; /* 98/Jan/28 */
2490 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2493 show_line_break_stats = false; /* 96/Feb/8 */
2496 show_fmt_flag = false; /* 94/Jun/21 */
2499 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2502 full_file_name_flag = false; // 00 Jun 18
2508 quitflag++; /* 93/Dec/16 */
2510 /* The following are really obscure and should not be advertized */
2512 show_current = false; /* tex8 93/Dec/14 */
2515 show_numeric = false; /* 93/Dec/21 */
2518 civilize_flag = false; /* 93/Dec/16 */
2521 open_trace_flag = true; /* openinou 1994/Jan/8 */
2524 reorder_arg_flag = false; /* local */
2529 mem_initex = mem_top;
2531 mem_initex = atoi(optarg) * 1024;
2533 if (mem_initex == 0)
2534 complainarg(c, optarg);
2539 #ifdef VARIABLETRIESIZE
2542 trie_size = default_trie_size;
2544 trie_size = atoi(optarg);
2547 complainarg(c, optarg);
2551 #ifdef ALLOCATEHYPHEN
2554 new_hyphen_prime = hyphen_prime * 2;
2556 new_hyphen_prime = atoi(optarg);
2558 if (new_hyphen_prime == 0)
2559 complainarg(c, optarg);
2567 percent_grow = atoi(optarg);
2569 if (percent_grow == 0)
2570 complainarg(c, optarg);
2578 pseudo_tilde = atoi(optarg);
2580 if (pseudo_tilde > 255)
2582 else if (pseudo_tilde < 128)
2591 tab_step = atoi(optarg);
2593 complainarg(c, optarg);
2597 xchr_file = xstrdup("xchr.map");
2599 xchr_file = xstrdup(optarg);
2601 if (xchr_file == NULL || *xchr_file == '\0')
2602 complainarg(c, optarg);
2606 repl_file = xstrdup("repl.key");
2608 repl_file = xstrdup(optarg);
2610 if (repl_file == NULL || *repl_file == '\0')
2611 complainarg(c, optarg);
2615 default_rule = 26214;
2617 default_rule = atoi(optarg);
2619 if (default_rule == 0)
2620 complainarg(c, optarg);
2626 complainarg(c, optarg);
2632 dvi_directory = xstrdup(optarg);
2634 if (strcmp(dvi_directory, "") == 0)
2635 complainarg(c, optarg);
2640 char * format_spec = NULL;
2643 format_spec = xstrdup(optarg);
2645 if (!strcmp(format_spec, "pdf"))
2646 shipout_flag = out_pdf_flag;
2647 else if (!strcmp(format_spec, "dvi"))
2648 shipout_flag = out_dvi_flag;
2649 else if (!strcmp(format_spec, "xdv"))
2650 shipout_flag = out_xdv_flag;
2653 sprintf(log_line, "ERROR: Do not understand shipout flag `%s'\n", format_spec);
2654 show_line(log_line, 1);
2662 log_directory = xstrdup(optarg);
2664 if (strcmp(log_directory, "") == 0)
2665 complainarg(c, optarg);
2673 aux_directory = xstrdup(optarg);
2675 if (strcmp(aux_directory, "") == 0)
2676 complainarg(c, optarg);
2690 void strip_name (char *pathname)
2694 if ((s = strrchr(pathname, '\\')) != NULL)
2696 else if ((s = strrchr(pathname, '/')) != NULL)
2698 else if ((s = strrchr(pathname, ':')) != NULL)
2706 int read_command_line (int ac, char **av)
2715 while ((c = getopt_long_only(ac, av, short_options, long_options, &option_idx)) != EOF)
2717 if (optarg != 0 && *optarg == '=')
2718 optargnew = optarg + 1;
2722 analyze_flag (c, optargnew);
2725 if (show_use || quitflag == 3)
2728 strcat(log_line, "\n");
2729 show_line(log_line, 0);
2730 //stampcopy(log_line);
2731 //strcat(log_line, "\n");
2732 //show_line(log_line, 0);
2736 else if (quitflag == 3)
2738 strcat(log_line, "\n");
2739 show_line(log_line, 0);
2742 return -1; // failure
2745 if (repl_file != NULL && *repl_file != '\0')
2747 if (read_xchr_file(repl_file, 1, av))
2750 puts("KEY REPLACE ON\n");
2756 if (xchr_file != NULL && *xchr_file != '\0')
2758 if (read_xchr_file(xchr_file, 0, av))
2761 puts("NON ASCII ON\n");
2770 int init_commands (int ac, char **av)
2772 shipout_flag = out_dvi_flag;
2774 allow_patterns = false;
2775 reset_exceptions = false;
2777 key_replace = false;
2778 want_version = false;
2779 open_trace_flag = false;
2781 verbose_flag = false;
2782 restrict_to_ascii = false;
2783 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2784 show_in_dos = false; /* default is not to translate to DOS 850 */
2785 return_flag = true; // hard wired now
2786 trimeof = true; // hard wired now
2788 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2789 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2790 default_rule = 26214; /* default rule variable 95/Oct/9 */
2791 show_current = true;
2792 civilize_flag = true;
2793 show_numeric = true;
2794 show_missing = true;
2795 c_style_flag = false; /* use c-style error output */
2796 show_fmt_flag = true; /* show format file in log */
2797 show_tfm_flag = false; /* don't show metric file in log */
2798 shorten_file_name = false; /* don't shorten file names to 8+3 */
2799 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2800 truncate_long_lines = true; /* truncate long lines */
2801 tab_step = 0; /* do not replace tabs with spaces */
2802 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2803 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2804 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2805 show_cs_names = false;
2806 knuth_flag = false; /* allow extensions to TeX */
2807 full_file_name_flag = true; /* new default 2000 June 18 */
2808 errout = stdout; /* as opposed to stderr say --- used ??? */
2809 new_hyphen_prime = 0;
2811 #ifdef VARIABLETRIESIZE
2812 /* trie_size = default_trie_size; */
2820 format_name = "plain";
2824 if (read_command_line(ac, av) < 0)
2834 strcat(log_line, "\n");
2835 show_line(log_line, 0);
2836 stampcopy(log_line);
2837 strcat(log_line, "\n");
2838 show_line(log_line, 0);
2845 void initial_memory (void)
2847 /* set initial memory allocations */
2848 if (mem_extra_high < 0)
2851 if (mem_extra_low < 0)
2859 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2860 if (mem_extra_high != 0 || mem_extra_low != 0)
2862 puts("ERROR: Cannot extend main memory in iniTeX\n");
2863 mem_extra_high = 0; mem_extra_low = 0;
2869 if (mem_initex != 0)
2871 puts("ERROR: Can only set initial main memory size in iniTeX\n");
2877 puts("ERROR: Need only set hyphenation trie size in iniTeX\n");
2878 /* trie_size = 0; */
2881 if (mem_initex == 0)
2882 mem_initex = default_mem_top;
2885 trie_size = default_trie_size;
2886 /* Just in case user mistakenly specified words instead of kilo words */
2887 if (mem_extra_high > 10000L * 1024L)
2888 mem_extra_high = mem_extra_high / 1024;
2890 if (mem_extra_low > 10000L * 1024L)
2891 mem_extra_low = mem_extra_low / 1024;
2893 if (mem_initex > 10000L * 1024L)
2894 mem_initex = mem_initex / 1024;
2896 if (mem_initex > 2048L * 1024L) /* extend main memory by 16 mega byte! */
2898 puts("WARNING: There may be no benefit to asking for so much memory\n");
2899 /* mem_initex = 2048 * 1024; */
2902 if (new_hyphen_prime < 0)
2903 new_hyphen_prime = 0;
2905 if (new_hyphen_prime > 0)
2908 puts("ERROR: Can only set hyphen prime in iniTeX\n");
2911 if (new_hyphen_prime % 2 == 0)
2914 while (!prime(new_hyphen_prime))
2915 new_hyphen_prime = new_hyphen_prime + 2;
2919 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
2920 show_line(log_line, 0);
2925 if (percent_grow > 100)
2926 percent_grow = percent_grow - 100;
2928 if (percent_grow > 100)
2929 percent_grow = 100; /* upper limit - double */
2931 if (percent_grow < 10)
2932 percent_grow = 10; /* lower limit - 10% */
2935 /**********************************************************************/
2937 void perrormod (char *s)
2939 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
2940 show_line(log_line, 1);
2943 /*************************************************************************/
2945 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
2946 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
2947 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
2948 /* this is then undone in tex3.c both for fopen input and output */
2949 /* not ideal, since pseudo name appears in log and in error messages ... */
2951 void hidetwiddle (char *name)
2958 sprintf(log_line, "Hidetwiddle %s", name);
2959 show_line(log_line, 0);
2965 if (*s == '~' && pseudo_tilde != 0)
2966 *s = (char) pseudo_tilde; /* typically 254 */
2967 else if (*s == ' ' && pseudo_space != 0)
2968 *s = (char) pseudo_space; /* typically 255 */
2975 sprintf(log_line, "=> %s\n", name);
2976 show_line(log_line, 0);
2981 void deslash_all (int ac, char **av)
2983 char buffer[file_name_size];
2986 if ((s = grabenv("TEXDVI")) != NULL)
2989 if ((s = grabenv("TEXLOG")) != NULL)
2992 if ((s = grabenv("TEXAUX")) != NULL)
2995 if ((s = grabenv("TEXFMT")) != NULL)
2998 if ((s = grabenv("TEXPDF")) != NULL)
3001 strcpy(buffer, av[0]);
3003 if ((s = strrchr(buffer, '\\')) != NULL)
3005 else if ((s = strrchr(buffer, '/')) != NULL)
3007 else if ((s = strrchr(buffer, ':')) != NULL)
3010 s = buffer + strlen(buffer) - 1;
3012 if (*s == '\\' || *s == '/')
3015 texpath = xstrdup(buffer);
3017 if (strcmp(dvi_directory, "") != 0)
3018 flush_trailing_slash(dvi_directory);
3020 if (strcmp(log_directory, "") != 0)
3021 flush_trailing_slash(log_directory);
3023 if (strcmp(aux_directory, "") != 0)
3024 flush_trailing_slash(aux_directory);
3026 if (strcmp(fmt_directory, "") != 0)
3027 flush_trailing_slash(fmt_directory);
3029 if (strcmp(pdf_directory, "") != 0)
3030 flush_trailing_slash(pdf_directory);
3036 if (strcmp(dvi_directory, "") != 0)
3037 unixify(dvi_directory);
3039 if (strcmp(log_directory, "") != 0)
3040 unixify(log_directory);
3042 if (strcmp(aux_directory, "") != 0)
3043 unixify(aux_directory);
3045 if (strcmp(fmt_directory, "") != 0)
3046 unixify(fmt_directory);
3048 if (strcmp(pdf_directory, "") != 0)
3049 unixify(pdf_directory);
3054 if (optind < ac && optind > 0)
3058 if (trace_flag || debug_flag)
3060 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3061 optind, av[optind], ac);
3062 show_line(log_line, 0);
3065 unixify(av[optind]);
3068 if (pseudo_tilde != 0 || pseudo_space != 0)
3069 hidetwiddle (av[optind]);
3071 if (*av[optind] == '&' || *av[optind] == '+')
3074 format_name = xstrdup(av[optind] + 1);
3076 if (optind + 1 < ac)
3080 if (trace_flag || debug_flag)
3082 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3083 optind + 1, av[optind + 1], ac);
3084 show_line(log_line, 0);
3087 unixify(av[optind + 1]);
3090 if (pseudo_tilde != 0 || pseudo_space != 0)
3091 hidetwiddle (av[optind + 1]);
3097 /* note: those optarg == 0 test don't really work ... */
3098 /* note: optarg starts at = in case of x=... */
3100 int main_init (int ac, char **av)
3102 kpse_set_program_name(av[0], NULL);
3103 xputenv("engine", "yandytex");
3105 if (sizeof(memory_word) != sizeof(halfword) * 2)
3106 printf("ERROR: Bad word size %d!\n", sizeof(memory_word));
3108 start_time = clock();
3109 main_time = start_time;
3111 /* reset all allocatable memory pointers to NULL - in case we drop out */
3117 #ifdef ALLOCATESAVESTACK
3121 #ifdef ALLOCATEBUFFER
3123 current_buf_size = 0;
3124 buffer = realloc_buffer (initial_buf_size);
3139 log_opened = false; /* so can tell whether opened */
3140 interaction = -1; /* default state => 3 */
3141 missing_characters = 0; /* none yet! */
3142 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3143 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3144 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3146 if (ac > 1 && !strncmp(av[1], "-Y", 2))
3147 reorder_arg_flag = false;
3149 if (reorder_arg_flag)
3150 reorderargs(ac, av);
3152 if (init_commands(ac, av))
3155 check_fixed_align(trace_flag);
3158 source_direct = NULL;
3159 dvi_file_name = NULL;
3160 log_file_name = NULL;
3161 pdf_file_name = NULL;
3163 first_pass_count = 0;
3164 second_pass_count = 0;
3165 final_pass_count = 0;
3166 paragraph_failed = 0;
3175 puts("Entering init (local.c)");
3178 ini_max_address = max_address;
3181 show_maximums(stdout);
3184 deslash_all(ac, av); /* deslash and note if format specified */
3187 if (format_spec && mem_spec_flag)
3188 puts("WARNING: Cannot change initial main memory size when format specified");
3190 if (allocate_memory() != 0)
3193 check_alloc_align(trace_flag);
3196 puts("Leaving init (local.c)");
3201 #define CLK_TCK CLOCKS_PER_SEC
3203 void show_inter_val (clock_t inter_val)
3205 int seconds, tenths, hundredth, thousands;
3207 if (inter_val >= CLK_TCK * 10)
3209 tenths = (inter_val * 10 + CLK_TCK / 2) / CLK_TCK;
3210 seconds = tenths / 10;
3211 tenths = tenths % 10;
3212 printf("%d.%d", seconds, tenths);
3214 else if (inter_val >= CLK_TCK)
3216 hundredth = (inter_val * 100 + CLK_TCK / 2) / CLK_TCK;
3217 seconds = hundredth / 100;
3218 hundredth = hundredth % 100;
3219 printf("%d.%02d", seconds, hundredth);
3221 else if (inter_val > 0)
3223 thousands = (inter_val * 1000 + CLK_TCK / 2) / CLK_TCK;
3224 seconds = thousands / 1000;
3225 thousands = thousands % 1000;
3226 printf("%d.%03d", seconds, thousands);
3234 finish_time = clock();
3236 if (missing_characters != 0)
3239 if (missing_characters)
3241 sprintf(log_line, "! There %s %d missing character%s --- see log file\n",
3242 (missing_characters == 1) ? "was" : "were", missing_characters,
3243 (missing_characters == 1) ? "" : "s");
3244 show_line(log_line, 0);
3247 if (free_memory() != 0)
3253 show_inter_val(finish_time - start_time);
3255 show_inter_val(main_time - start_time);
3256 printf(" format load + ");
3257 show_inter_val(finish_time - main_time);
3258 printf(" processing) ");
3260 if (total_pages > 0)
3262 show_inter_val((finish_time - main_time) / total_pages);
3263 printf(" sec per page.");
3269 // printf control sequences' name
3270 void print_cs_name (FILE *output, int h)
3274 memset(log_line, 0, sizeof(log_line));
3276 textof = hash[h].rh;
3281 c = sprintf(log_line, "(%d), ", h);
3284 memmove(log_line + c, str_pool + str_start[textof], n);
3285 memmove(log_line + c + n, "\n", 2);
3287 if (output == stderr)
3289 show_line(log_line, 1);
3293 if (output == stdout)
3294 show_line(log_line, 0);
3296 fprintf(output, log_line);
3301 int compare_strn (int, int, int, int);
3302 /* compare two csnames in qsort */
3303 int compare_cs (const void *cp1, const void *cp2)
3305 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3309 textof1 = hash[c1].rh;
3310 textof2 = hash[c2].rh;
3311 l1 = length(textof1);
3312 l2 = length(textof2);
3313 k1 = str_start[textof1];
3314 k2 = str_start[textof2];
3316 return compare_strn(k1, l1, k2, l2);
3319 char * csused = NULL;
3321 /* Allocate table of indeces to allow sorting on csname */
3322 /* Allocate flags to remember which ones already listed at start */
3323 /* pass = 0 --> fmt */
3324 /* pass = 1 --> after */
3325 void print_cs_names (FILE *output, int pass)
3327 int h, k, ccount, repeatflag;
3329 int nfcs = frozen_control_sequence;
3331 if (pass == 0 && csused == NULL)
3333 csused = (char *) malloc (nfcs);
3339 memset(csused, 0, nfcs);
3341 for (h = 0; h < (hash_size + 780); h++)
3348 for (h = hash_base + 1; h < nfcs; h++)
3350 if (pass == 1 && csused[h])
3353 if (hash[h].rh != 0)
3362 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
3363 ccount, (pass == 1) ? "new" : "");
3365 if (output == stderr)
3367 show_line(log_line, 1);
3371 if (output == stdout)
3372 show_line(log_line, 0);
3374 fprintf(output, log_line);
3379 cnumtable = (int *) malloc (ccount * sizeof(int));
3381 if (cnumtable == NULL)
3386 for (h = hash_base + 1; h < nfcs; h++)
3388 if (pass == 1 && csused[h])
3391 if (hash[h].rh != 0)
3392 cnumtable[ccount++] = h;
3395 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3399 for (k = 0; k < ccount; k++)
3403 if (pass == 1 && csused[h])
3406 print_cs_name(output, h);
3409 sprintf(log_line, "\n");
3411 if (output == stderr)
3413 show_line(log_line, 1);
3417 if (output == stdout)
3418 show_line(log_line, 0);
3420 fprintf(output, log_line);
3423 free((void *)cnumtable);
3426 if (pass == 1 && csused != NULL)
3433 /* k1 and k2 are positions in string pool */
3434 /* l1 and l2 are lengths of strings */
3435 int compare_strn (int k1, int l1, int k2, int l2)
3439 while (l1 > 0 && l2 > 0)
3454 return 1; /* first string longer */
3456 return -1; /* second string longer */
3458 return 0; /* strings match */
3460 /* compare two font names and their at sizes in qsort */
3461 int compare_fnt (const void *fp1, const void *fp2)
3463 int f1, f2, l1, l2, k1, k2, s;
3467 l1 = length(font_name[f1]);
3468 l2 = length(font_name[f2]);
3469 k1 = str_start[font_name[f1]];
3470 k2 = str_start[font_name[f2]];
3472 s = compare_strn (k1, l1, k2, l2);
3477 if (font_size[f1] > font_size[f2])
3479 else if (font_size[f1] < font_size[f2])
3482 return 0; /* should not ever get here */
3484 /* compare two font names */
3485 int compare_fnt_name (int f1, int f2)
3487 int l1, l2, k1, k2, s;
3489 l1 = length(font_name[f1]);
3490 l2 = length(font_name[f2]);
3491 k1 = str_start[font_name[f1]];
3492 k2 = str_start[font_name[f2]];
3494 s = compare_strn (k1, l1, k2, l2);
3498 /* decode checksum information */
3499 unsigned long checkdefault = 0x59265920; /* default signature */
3500 int decode_fourty (unsigned long checksum, char *codingvector)
3504 /* char codingvector[6+1]; */
3508 strcpy(codingvector, "unknwn");
3512 if ((checksum >> 8) == (checkdefault >> 8)) /* last byte random */
3514 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3515 strcpy (codingvector, "fixed "); /* if not specified ... */
3516 return 1; /* no info available */
3520 for (k = 0; k < 6; k++)
3522 c = (int) (checksum % 40);
3523 checksum = checksum / 40;
3524 if (c <= 'z' - 'a') c = c + 'a';
3525 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3526 else if (c == 36) c = '-';
3527 else if (c == 37) c = '&';
3528 else if (c == 38) c = '_';
3529 else c = '.'; /* unknown */
3530 codingvector[5-k] = (char) c;
3532 codingvector[6] = '\0';
3538 double sclpnt (long x)
3542 pt = (double) x / 65536.0;
3543 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3548 void dvi_font_show(internal_font_number f, int suppressname)
3551 unsigned long checksum;
3552 char checksumvector[8];
3555 putc(' ', log_file);
3557 if (suppressname == 0)
3559 a = length(font_area[f]);
3560 l = length(font_name[f]);
3562 k = str_start[font_area[f]];
3564 memcpy(buffer, str_pool + k, length(font_area[f]));
3565 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
3567 k = str_start[font_name[f]];
3569 memcpy(buffer, str_pool + k, length(font_name[f]));
3570 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
3574 for (k = a + l; k < 16; k++)
3575 putc(' ', log_file);
3577 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3578 fputs(buffer, log_file);
3580 if (suppressname == 0)
3584 for (k = n; k < 16; k++)
3585 putc(' ', log_file);
3587 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
3588 decode_fourty(checksum, checksumvector);
3589 fprintf(log_file, "encoding: %s..", checksumvector);
3592 putc('\n', log_file);
3594 /* Allocate table of indeces to allow sorting on font name */
3595 void show_font_info (void)
3597 int k, m, fcount, repeatflag;
3602 for (k = 1; k <= font_ptr; k++)
3609 fnumtable = (short *) malloc(fcount * sizeof(short));
3611 fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
3615 for (k = 1; k <= font_ptr; k++)
3617 fnumtable[fcount++] = (short) k;
3619 qsort ((void *)fnumtable, fcount, sizeof(short), &compare_fnt);
3623 for (m = 0; m < fcount; m++)
3627 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3633 dvi_font_show(fnumtable[m], repeatflag);
3636 free((void *)fnumtable);