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
24 #pragma warning(disable:4115) // kill rpcasync.h complaint
26 #define MYLIBAPI __declspec(dllexport)
29 #pragma warning(disable:4996)
30 #pragma warning(disable:4131) // old style declarator
31 #pragma warning(disable:4135) // conversion between different integral types
32 #pragma warning(disable:4127) // conditional expression is constant
34 #include <kpathsea/config.h>
35 #include <kpathsea/c-ctype.h>
36 #include <kpathsea/line.h>
37 #include <kpathsea/readable.h>
38 #include <kpathsea/variable.h>
39 #include <kpathsea/absolute.h>
47 /* Most Y & Y changes are localized here -- init() */
49 #define USEOUREALLOC /* 96/Jan/20 */
51 #define USEMEMSET /* 98/Jan/23 */
54 #define REALLOC ourrealloc
56 #define REALLOC realloc
60 #include <malloc.h> /* _msize, _expand, HEAPOK et.c */
61 #include <direct.h> /* for _getcwd() */
63 #pragma warning(disable:4032) // different type when promoted
65 #include <conio.h> /* for _getch() */
67 #pragma warning(default:4032) // different type when promoted
71 char *compiletime = __TIME__;
72 char *compiledate = __DATE__;
73 char *www = "http://www.tug.org/yandy";
74 char *rights = "All Rights Reserved.";
75 char *copyright = "\nCopyright (C) 1993--2000 Y&Y, Inc.\n"
76 "Copyright (C) 2007 TeX Users Group.\n"
77 "Copyright (C) 2014 Clerk Ma.\n\n"
78 "This program is free software; you can redistribute it and/or modify\n"
79 "it under the terms of the GNU General Public License as published by\n"
80 "the Free Software Foundation; either version 2 of the License, or\n"
81 "(at your option) any later version.\n\n ";
82 char *yandyversion = "2.2.3";
83 char *application = "Y&Y TeX"; /* 96/Jan/17 */
84 char *tex_version = "This is TeX, Version 3.14159265";
86 clock_t start_time, main_time, finish_time;
88 char * dvi_directory = "";
89 char * log_directory = "";
90 char * aux_directory = "";
91 char * fmt_directory = "";
92 char * pdf_directory = "";
94 char * texpath = ""; /* path to executable - used if env vars not set */
96 char log_line[MAXLINE]; // used also in tex9.c
98 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
99 int format_spec = 0; /* non-zero if a format specified on command line */
100 int closed_already = 0; /* make sure we don't try this more than once */
101 bool reorder_arg_flag = true; /* put command line flags/arguments first */
103 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
104 /* Used in tex0.c with wintodos[c-128] */
106 unsigned char wintodos[128] =
108 0, 0, 0, 159, 0, 0, 0, 0,
109 94, 0, 0, 0, 0, 0, 0, 0,
110 0, 96, 39, 0, 0, 7, 0, 0,
111 126, 0, 0, 0, 0, 0, 0, 0,
112 32, 173, 189, 156, 207, 190, 221, 21,
113 0, 184, 166, 174, 170, 45, 169, 0,
114 248, 241, 253, 252, 0, 230, 20, 250,
115 0, 251, 167, 175, 172, 171, 243, 168,
116 183, 181, 182, 199, 142, 143, 146, 128,
117 212, 144, 210, 211, 222, 214, 215, 216,
118 209, 165, 227, 224, 226, 229, 153, 158,
119 157, 235, 233, 234, 154, 237, 232, 225,
120 133, 160, 131, 198, 132, 134, 145, 135,
121 138, 130, 136, 137, 141, 161, 140, 139,
122 208, 164, 149, 162, 147, 228, 148, 246,
123 155, 151, 163, 150, 129, 236, 231, 152
126 void show_usage (void)
131 " yandytex [-?ivnwdrzpK] [-m=ini_mem] [-e=hyph_size] [-h=trie_size]\n"
132 " [-x=xchr_file] [-k=key_file] [-o=dvi_dir] [-l=log_dir] [-a=aux_dir]\n"
133 " [+format_file] [tex_file]\n\n"
134 " -? show this usage summary\n"
135 " -i start up as iniTeX (create format file)\n"
136 " -v be verbose (show implementation version number)\n"
137 " -n do not allow `non ASCII' characters in input files (complain instead)\n"
138 " -w do not show `non ASCII' characters in hexadecimal (show as is)\n"
139 " -d do not allow DOS style file names - i.e. do not convert \\ to /\n"
140 " -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n"
141 " -p allow use of \\patterns after loading format (iniTeX only)\n"
142 " -K disable all extensions to basic TeX\n"
143 " -m initial main memory size in kilo words (iniTeX only)\n"
144 " -e hyphenation exception dictionary size (iniTeX only)\n"
145 " -h hyphenation pattern trie size (iniTeX only)\n"
146 " -x use `non ASCII' character mapping (xchr[]) defined in file\n"
147 " -k use `key replacement' defined in file\n"
148 " -o write DVI file in specified directory (default current directory)\n"
149 " -l write LOG file in specified directory (default current directory)\n"
150 " -a write AUX file in specified directory (default current directory)\n");
151 show_line(log_line, 1);
154 uexit(1); // has this been setup yet ???
158 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
160 /* -c prepend current directory (.) to TFM directory list\n\ */
161 /* -b check that files with read access are not actually directories\n\ */
163 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
164 /* \t\t(applies to file name and format file name, if present)\n\ */
165 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
167 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
169 // Sep 27 1990 => 1990 Sep 27
170 // 012456789 0123456789
171 void scivilize (char * date)
176 strcpy (pyear, date + 7);
178 for (k = 5; k >= 0; k--)
179 date[k + 5] = date[k];
181 for (k = 0; k < 4; k++)
187 date[9] = '0'; /* replace space by '0' */
192 // Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35
193 void lcivilize (char * date)
198 strcpy (pyear, date + 20);
200 for (k = 18; k >= 0; k--)
205 for (k = 0; k < 4; k++)
213 // now writes result into given buffer
214 void stamp_it (char *s)
218 strcpy(date, compiledate);
220 sprintf(s, "%s %s ", application, yandyversion);
222 sprintf(s, "(compiled time: %s %s)", date, compiletime);
226 void stampcopy (char *s)
230 sprintf(s, "%s %s", copyright, www);
234 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
239 void read_xchr_sub (FILE * xchr_input)
241 char buffer[PATH_MAX];
242 int k, from, to, count = 0;
246 memset (xchr, NOTDEF, MAXCHRS); /* mark unused */
248 for (k = 0; k < MAXCHRS; k++)
249 xchr[k] = -1; /* mark unused */
253 memset (xord, NOTDEF, MAXCHRS); /* mark unused */
255 for (k = 0; k < MAXCHRS; k++)
256 xord[k] = -1; /* mark unused */
259 #ifdef ALLOCATEBUFFER
260 while (fgets(buffer, current_buf_size, xchr_input) != NULL)
262 while (fgets(buffer, sizeof(buffer), xchr_input) != NULL)
265 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
268 from = (int) strtol (buffer, &s, 0);
269 to = (int) strtol (s, NULL, 0);
271 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS)
273 if (xchr[from]== (unsigned char) NOTDEF)
275 xchr[from]= (unsigned char) to;
279 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
280 show_line(log_line, 0);
283 if (xord[to]== NOTDEF)
285 xord[to]= (unsigned char) from;
289 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xord", to, xord[to], from);
290 show_line(log_line, 0);
296 /* now fill in the gaps */ /* not clear this is a good idea ... */
297 for (k = 0; k < MAXCHRS; k++)
299 if (xchr[k]== NOTDEF) /* if it has not been filled */
301 if (xord[k]== NOTDEF) /* see whether used already */
303 xchr[k]= (unsigned char) k; /* no, so make identity */
304 xord[k]= (unsigned char) k; /* no, so make identity */
309 xchr[NOTDEF]= NOTDEF; /* fixed point of mapping */
313 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
314 show_line(log_line, 0);
316 for (k = 0; k < MAXCHRS; k++)
318 if (xchr[k]!= NOTDEF)
320 sprintf(log_line, "%d => %d\n", k, xchr[k]);
321 show_line(log_line, 0);
327 char *replacement[MAXCHRS]; /* pointers to replacement strings */
329 void read_repl_sub (FILE * repl_input)
332 char buffer[PATH_MAX];
338 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
340 for (k = 0; k < MAXCHRS; k++)
341 replacement[k] = NULL;
344 while (fgets(buffer, PATH_MAX, repl_input) != NULL) {
345 if (*buffer == '%' || *buffer == ';' || *buffer == '\n')
348 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
351 if (*charname == '"') { /* deal with quoted string "..." */
354 while (*s != '"' && *s != '\0') s++; /* step up to " */
355 if (*s++ == '\0') continue; /* sanity check */
358 s++; /* is it "" perhaps ? */
359 if (*s != '"') break; /* no, end of string */
361 *t++ = *s++; /* copy over */
363 *t = '\0'; /* and terminate */
365 if (chrs >= 0 && chrs < MAXCHRS)
366 replacement[chrs] = xstrdup(charname);
368 /* presently the following can never get triggered */
369 /* which is good, because it is perhaps not right ... */
370 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
371 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
372 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
373 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
374 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
376 if (chrs >= 0 && chrs < MAXCHRS)
377 replacement[chrs] = xstrdup(charname);
380 sprintf(log_line, "ERROR: don't understand %s", buffer);
381 show_line(log_line, 1);
384 if (trace_flag) { /* debugging output */
385 show_line("Key replacement table\n", 0);
386 for (k = 0; k < MAXCHRS; k++) {
387 if (replacement[k] != NULL) {
388 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
389 show_line(log_line, 0);
395 /* Following used both to read xchr[] file and key replacement file */
396 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
397 int read_xchr_file (char *filename, int flag, char *argv[])
400 char infile[PATH_MAX];
403 if (filename == NULL)
408 sprintf(log_line, "Reading xchr/repl %s\n", filename);
409 show_line(log_line, 0);
412 /* first try using file as specified */
413 strcpy(infile, filename);
417 sprintf(log_line, "Trying %s\n", infile);
418 show_line(log_line, 0);
422 pinput = fopen (infile, "r");
424 pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
428 if (strrchr(infile, '.') == NULL)
431 strcat(infile, ".map");
433 strcat(infile, ".key");
437 sprintf(log_line, "Trying %s\n", infile);
438 show_line(log_line, 0);
442 pinput = fopen (infile, "r");
444 pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
450 strcpy (infile, argv[0]); /* try TeX program path */
452 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
453 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
454 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
456 strcat (infile, filename);
460 sprintf(log_line, "Trying %s\n", infile);
461 show_line(log_line, 0);
465 pinput = fopen (infile, "r");
467 pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
471 if (strchr(infile, '.') == NULL)
474 strcat(infile, ".map");
476 strcat(infile, ".key");
480 sprintf(log_line, "Trying %s\n", infile);
481 show_line(log_line, 0);
485 pinput = fopen (infile, "r");
487 pinput = _fsopen (infile, "r", share_flag); /* 94/July/12 */
492 if (pinput == NULL) /* 97/July/31 */
494 strcpy (infile, argv[0]); /* try TeX program path */
496 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
497 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
498 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
500 strcat (infile, "keyboard\\");
501 strcat (infile, filename);
505 sprintf(log_line, "Trying %s\n", infile);
506 show_line(log_line, 0);
510 pinput = fopen (infile, "r");
512 pinput = _fsopen (infile, "r", share_flag);
516 if (strchr(infile, '.') == NULL)
519 strcat(infile, ".map");
521 strcat(infile, ".key");
525 sprintf(log_line, "Trying %s\n", infile);
526 show_line(log_line, 0);
530 pinput = fopen (infile, "r");
532 pinput = _fsopen (infile, "r", share_flag);
536 /* Note: can't look in TeX source file dir, since that is not known yet */
539 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
540 flag ? " xchr[]" : "key mapping", filename);
541 show_line(log_line, 1);
542 perrormod (filename);
547 read_xchr_sub (pinput);
549 read_repl_sub (pinput);
551 (void) fclose (pinput);
555 /* need to also set `key_replace' here based on command line */
556 /* need to also allocate `buffercopy' here and free at end */
557 /* need to call `readreplace' in appropriate place */
559 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
561 /* Following may be useful if link without floating point emulation */
564 void testfloating (void)
570 while (1.0 + dx != 1.0)
576 sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
577 show_line(log_line, 0);
583 /* ad hoc default minimum growth in memory realloc is 62% */
584 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
585 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
586 int total_allocated = 0; /* total memory allocated so far */
587 int ini_max_address = 0; /* maximum address when starting */
588 int max_address = 0; /* maximum address seen in allocated memory */
591 void show_maximums (FILE *output)
593 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
594 // if (output != NULL) fputs(log_line, output); // log file
595 // else if (flag == 0) show_line(log_line, 0); // informative
596 // else if (flag == 1) show_line(log_line, 1); // error
597 if (output == stderr)
598 show_line(log_line, 1);
599 else if (output == stdout)
600 show_line(log_line, 0);
602 fputs(log_line, output);
605 /* our own version of realloc --- avoid supposed MicroSoft version bug */
606 /* also tries _expand first, which can avoid address growth ... */
609 void *ourrealloc (void *old, size_t new_size)
612 size_t old_size, overlap;
614 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
615 if ((new_size % 4) != 0)
616 new_size = ((new_size / 4) + 1) * 4;
619 return malloc (new_size); /* no old block - use malloc */
621 old_size = _msize (old);
623 if (old_size >= new_size && old_size < new_size + 4)
626 mnew = _expand (old, new_size); /* first try and expand in place */
632 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
633 mnew, new_size, old, old_size);
634 show_line(log_line, 0);
638 /* *********************************************************************** */
639 /* do this if you want to call the real realloc next - */
640 mnew = realloc (old, new_size);
644 /* we are screwed typically if we ever drop through here - no more space */
645 /* *********************************************************************** */
646 mnew = malloc (new_size); /* otherwise find new space */
649 return mnew; /* if unable to allocate */
651 if (old_size < new_size)
656 memcpy (mnew, old, overlap); /* copy old data to new area */
657 free(old); /* free the old area */
662 void memory_error (char *s, int n)
666 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
667 show_maximums(log_file);
670 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
671 show_line(log_line, 1);
672 show_maximums(stderr);
674 /* exit (1); */ /* 94/Jan/22 */
675 /* return to let TeX do its thing (such as complain about runaway) */
676 /* don't set abort_flag here */
679 void trace_memory (char *s, int n)
681 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
682 show_line(log_line, 0);
685 void update_statistics (int address, int size, int oldsize)
687 if (address + size > max_address)
688 max_address = address + size;
690 total_allocated = total_allocated + size - oldsize;
693 void probe_memory (void)
697 s = (char *) malloc (4); /* get current top address */
699 update_statistics ((int) s, 0, 0); /* show where we are */
702 void probe_show (void)
705 show_maximums(stdout);
708 size_t roundup (size_t n)
713 return ((n / 4) + 1) * 4;
717 /* using allocating hyphenation trie slows things down maybe 1% */
718 /* but saves typically (270k - 55k) = 215k of memory */
719 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
720 /* since hyphenation trie cannot be extended (after iniTeX) */
721 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
723 /* NOTE: we don't ever reallocate these */
724 /* returns -1 if it fails */
726 int allocate_tries (int trie_max)
729 /* if (trie_max > trie_size) {
730 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
731 trie_max, trie_size);
732 show_line(log_line, 1);
734 } */ /* ??? removed 1993/dec/17 */
735 if (trie_max > 1000000)
736 trie_max = 1000000; /* some sort of sanity limit */
737 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
738 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
739 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
740 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
744 trace_memory("hyphen trie", n);
746 trie_trl = (halfword *) malloc (roundup(nl));
747 trie_tro = (halfword *) malloc (roundup(no));
748 trie_trc = (quarterword *) malloc (roundup(nc));
750 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL)
752 memory_error("hyphen trie", n);
758 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
759 show_line(log_line, 0);
762 update_statistics ((int) trie_trl, nl, 0);
763 update_statistics ((int) trie_tro, no, 0);
764 update_statistics ((int) trie_trc, nc, 0);
765 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
766 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
769 probe_show(); /* 94/Mar/25 */
774 #ifdef ALLOCATEHYPHEN
775 bool prime (int); /* test function later in this file */
777 int current_prime = 0; /* remember in case reallocated later */
779 /* we don't return an address here, since TWO memory regions allocated */
780 /* plus, we don't really reallocate, we FLUSH the old information totally */
781 /* returns -1 if it fails */
783 int realloc_hyphen (int hyphen_prime)
787 if (!prime(hyphen_prime))
789 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
790 show_line(log_line, 1);
793 /* need not/cannot preserve old contents when hyphen prime is changed */
794 /* if (hyph_list != NULL) free(hyph_list); */
795 /* if (hyph_word != NULL) free(hyph_word); */
796 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
797 nw = (hyphen_prime + 1) * sizeof(str_number);
798 nl = (hyphen_prime + 1) * sizeof(halfword);
802 trace_memory("hyphen exception", n);
804 /* initially hyph_word will be NULL so this acts like malloc */
805 /* hyph_word = (str_number *) malloc (nw); */
806 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
807 /* initially hyph_list will be NULL so this acts like malloc */
808 /* hyph_list = (halfword *) malloc (nl); */
809 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
811 if (hyph_word == NULL || hyph_list == NULL)
813 memory_error("hyphen exception", n);
819 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n", hyph_word, hyph_list);
820 show_line(log_line, 0);
822 /* cannot preserve old contents when hyphen prime is changed */
824 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
826 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
830 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
832 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
834 hyph_count = 0; /* or use reset_hyphen() in itex.c */
836 if (current_prime != 0)
838 update_statistics ((int) hyph_word, nw, (current_prime + 1) * sizeof(str_number));
839 update_statistics ((int) hyph_list, nl, (current_prime + 1) * sizeof(halfword));
843 update_statistics ((int) hyph_word, nw, 0);
844 update_statistics ((int) hyph_list, nl, 0);
846 current_prime = hyphen_prime;
849 probe_show(); /* 94/Mar/25 */
855 int current_mem_size = 0; /* current total words in main mem allocated -1 */
857 /* this gets called from itex.c when it figures out what mem_top is */
858 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
859 /* initial allocation only, may get expanded later */
860 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
861 /* returns NULL if it fails */
864 /* initial main memory alloc - mem_top */
865 memory_word *allocate_main_memory (int size)
869 /* Using -i *and* pre-loading format */ /* in this case get called twice */
870 /* Get rid of initial blank memory again or use realloc ... */
871 /* Could we avoid this by detecting presence of & before allocating ? */
872 /* Also, if its already large enough, maybe we can avoid this ? */
873 /* don't bother if current_mem_size == mem_max - mem_start ? */
874 if (mainmemory != NULL)
877 show_line("Reallocating initial memory allocation\n", 1);
880 mem_top = mem_bot + size;
882 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
883 if (mem_extra_high != 0 && !is_initex)
884 mem_max = mem_top + mem_extra_high;
889 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
890 if (mem_extra_low != 0 && !is_initex)
891 mem_start = mem_bot - mem_extra_low; /* increase main memory */
894 mem_start = 0; /* bottom of memory allocated by system */
895 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
896 mem_min = 0; /* bottom of area made available to TeX */
897 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
900 trace_memory("main memory", n);
902 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
903 /* normally mainmemory == NULL here so acts like malloc ... */
904 mainmemory = (memory_word *) REALLOC (mainmemory, n);
906 if (mainmemory == NULL)
908 memory_error("initial main memory", n);
909 // exit (1); /* serious error */
915 sprintf(log_line, "Address main memory == %d\n", mainmemory);
916 show_line(log_line, 0);
921 if (mem_start != 0 && !is_initex)
922 zzzaa = mainmemory - mem_start;
926 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
927 show_line(log_line, 0);
930 update_statistics ((int) mainmemory, n,
931 (current_mem_size + 1) * sizeof (memory_word));
932 /* current_mem_size = (mem_max - mem_start + 1); */
933 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
936 probe_show(); /* 94/Mar/25 */
938 return zzzaa; /* same as zmem, mem 94/Jan/24 */
940 #endif /* end of ALLOCATEMAIN */
943 /* int firstallocation = 1; */
945 /* increase main memory allocation at low end and high end */
946 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
947 /* returns NULL if it fails */
949 memory_word *realloc_main (int losize, int hisize)
952 int newsize = 0; /* to quieten compiler */
953 int n = 0; /* to quieten compiler */
954 memory_word * newmemory = NULL; /* to quieten compiler */
956 /* if (losize == 0 && hisize > 0) runawayflag = 1;
957 else runawayflag = 0; */ /* 94/Jan/22 */
961 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
962 show_line(log_line, 0);
967 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
970 show_line("Please use `-m=...' on command line\n", 0);
971 // abort_flag++; // ???
977 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
978 show_line(log_line, 0);
981 if (current_mem_size + 1 == max_mem_size) /* if we REALLY run up to limit ! */
983 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
984 // abort_flag++; // ???
987 /* first allocation should expand *both* lo and hi */
988 if (hisize == 0 && mem_end == mem_max)
991 if (losize == 0 && mem_start == mem_min)
994 /* try and prevent excessive frequent reallocations */
995 /* while avoiding over allocation by too much */
996 minsize = current_mem_size / 100 * percent_grow;
998 if (losize + hisize < minsize)
1000 if (losize > 0 && hisize > 0)
1002 losize = minsize / 2;
1003 hisize = minsize / 2;
1005 else if (losize > 0)
1007 else if (hisize > 0)
1011 if (losize > 0 && losize < mem_top / 2)
1012 losize = mem_top / 2;
1014 if (hisize > 0 && hisize < mem_top / 2)
1015 hisize = mem_top / 2;
1017 for (k = 0; k < MAXSPLITS; k++)
1019 newsize = current_mem_size + losize + hisize;
1021 if (newsize >= max_mem_size) /* bump against limit - ha ha ha */
1023 while (newsize >= max_mem_size) {
1024 losize = losize / 2; hisize = hisize / 2;
1025 newsize = current_mem_size + losize + hisize;
1029 n = (newsize + 1) * sizeof (memory_word);
1032 trace_memory("main memory", n);
1034 newmemory = (memory_word *) REALLOC (mainmemory, n);
1036 if (newmemory != NULL)
1037 break; /* did we get it ? */
1039 if (current_mem_size == 0)
1040 break; /* in case we ever use for initial */
1042 losize = losize / 2; hisize = hisize / 2;
1045 if (newmemory == NULL)
1047 memory_error("main memory", n);
1048 return zzzaa; /* try and continue with TeX !!! */
1053 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1054 show_line(log_line, 0);
1059 /* shift everything upward to make space for new low area */
1062 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1063 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1064 show_line(log_line, 0);
1066 memmove (newmemory + losize, newmemory,
1067 (current_mem_size + 1) * sizeof(memory_word));
1068 /* could reduce words moved by (mem_max - mem_end) */
1070 mainmemory = newmemory; /* remember for free later */
1073 mem_start = mem_start - losize; /* update lower limit */
1076 mem_max = mem_max + hisize; /* update upper limit */
1078 update_statistics ((int) mainmemory, n,
1079 (current_mem_size + 1) * sizeof (memory_word));
1080 current_mem_size = newsize;
1082 if (current_mem_size != mem_max - mem_start)
1084 show_line("ERROR: Impossible Memory Error\n", 1);
1088 zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1093 probe_show(); /* 94/Mar/25 */
1100 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1102 int current_font_mem_size = 0;
1104 /* fmemoryword can be either halfword or memory_word */
1105 fmemoryword * realloc_font_info (int size)
1107 fmemoryword *newfontinfo = NULL;
1109 int newsize = 0; /* to quieten compiler */
1110 int n = 0; /* to quieten compiler */
1114 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1115 show_line(log_line, 0);
1117 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1118 /* during initial allocation current_font_mem_size == 0 */
1119 if (current_font_mem_size == font_mem_size) /* if we REALLY run up to limit */
1121 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1122 return font_info; /* pass it back to TeX 99/Fabe/4 */
1124 /* try and prevent excessive frequent reallocations */
1125 /* while avoiding over allocation by too much */
1126 /* minsize = current_font_mem_size / 2; */
1127 minsize = current_font_mem_size / 100 * percent_grow;
1132 if (size < initial_font_mem_size)
1133 size = initial_font_mem_size;
1135 for (k=0; k < MAXSPLITS; k++)
1137 newsize = current_font_mem_size + size;
1139 if (newsize > font_mem_size)
1140 newsize = font_mem_size; /* bump against limit */
1142 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1143 n = (newsize + 1) * sizeof (fmemoryword);
1146 trace_memory("font_info", n);
1148 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1150 if (newfontinfo != NULL)
1151 break; /* did we get it ? */
1153 if (current_font_mem_size == 0)
1154 break; /* initial allocation must work */
1159 if (newfontinfo == NULL)
1161 memory_error("font", n);
1162 return font_info; /* try and continue !!! */
1165 font_info = newfontinfo;
1169 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1170 show_line(log_line, 0);
1173 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1174 current_font_mem_size = newsize;
1177 probe_show(); /* 94/Mar/25 */
1182 #ifdef ALLOCATESTRING
1183 int current_pool_size = 0;
1185 packed_ASCII_code * realloc_str_pool (int size)
1190 packed_ASCII_code *newstrpool = NULL;
1194 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1195 show_line(log_line, 0);
1198 if (current_pool_size == pool_size)
1200 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1202 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1204 /* minsize = current_pool_size / 2; */
1205 minsize = current_pool_size / 100 * percent_grow;
1206 if (size < minsize) size = minsize;
1207 if (size < initial_pool_size) size = initial_pool_size;
1209 for (k = 0; k < MAXSPLITS; k++) {
1210 newsize = current_pool_size + size;
1211 if (newsize > pool_size) newsize = pool_size;
1212 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1213 n = (newsize + 1) * sizeof (packed_ASCII_code);
1214 if (trace_flag) trace_memory("str_pool", n);
1215 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1216 if (newstrpool != NULL) break; /* did we get it ? */
1217 if (current_pool_size == 0) break; /* initial allocation must work */
1218 size = size / 2; /* else can retry smaller */
1221 if (newstrpool == NULL)
1223 memory_error("string pool", n);
1224 return str_pool; /* try and continue !!! */
1227 str_pool = newstrpool;
1228 update_statistics ((int) str_pool, n, current_pool_size);
1229 current_pool_size = newsize;
1233 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1234 show_line(log_line, 0);
1238 probe_show(); /* 94/Mar/25 */
1244 #ifdef ALLOCATESTRING
1245 int current_max_strings = 0;
1247 pool_pointer *realloc_str_start (int size)
1252 pool_pointer *newstrstart=NULL;
1256 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1257 show_line(log_line, 0);
1260 if (current_max_strings == max_strings)
1262 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1264 return str_start; /* pass it back to TeX 99/Fabe/4 */
1266 /* minsize = current_max_strings / 2; */
1267 minsize = current_max_strings / 100 * percent_grow;
1268 if (size < minsize) size = minsize;
1269 if (size < initial_max_strings) size = initial_max_strings;
1271 for (k = 0; k < MAXSPLITS; k++)
1273 newsize = current_max_strings + size;
1274 if (newsize > max_strings) newsize = max_strings;
1275 /* important + 1 since str_start[maxstring + 1] originally */
1276 n = (newsize + 1) * sizeof (pool_pointer);
1277 if (trace_flag) trace_memory("str_start", n);
1278 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1279 if (newstrstart != NULL) break; /* did we get it ? */
1280 if (current_max_strings == 0) break; /* initial allocation must work */
1281 size = size / 2; /* otherwise can try smaller */
1284 if (newstrstart == NULL) {
1285 memory_error("string pointer", n);
1286 return str_start; /* try and continue */
1288 str_start = newstrstart;
1289 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1290 current_max_strings = newsize;
1292 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1293 show_line(log_line, 0);
1295 if (trace_flag) probe_show(); /* 94/Mar/25 */
1302 /* returns -1 if it fails */
1303 /* size == trie_size */
1304 int allocate_ini (int size)
1306 int n, nl, no, nc, nr, nh, nt;
1307 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1308 no = (size + 1) * sizeof(trie_op_code);
1309 nc = (size + 1) * sizeof(packed_ASCII_code);
1310 /* nt = (size + 1) * sizeof(bool); */
1311 nt = (size + 1) * sizeof(char);
1312 n = nl + no + nc + nr + nh + nt;
1313 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1314 3 * sizeof(trie_pointer) + sizeof (char)); */
1315 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1316 trie_l = (trie_pointer *) malloc (roundup(nl));
1317 trie_o = (trie_op_code *) malloc (roundup(no));
1318 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1319 trie_r = (trie_pointer *) malloc (roundup(nr));
1320 trie_hash = (trie_pointer *) malloc (roundup(nh));
1321 /* trie_taken = (bool *) malloc (nt); */
1322 trie_taken = (char *) malloc (roundup(nt));
1323 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1324 trie_hash == NULL || trie_taken == NULL) {
1325 memory_error("iniTeX hyphen trie", n);
1326 // exit (1); /* serious error */
1330 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1331 trie_l, trie_o, trie_c);
1332 show_line(log_line, 0);
1333 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1334 trie_r, trie_hash, trie_taken);
1335 show_line(log_line, 0);
1337 update_statistics ((int) trie_l, nl, 0);
1338 update_statistics ((int) trie_o, no, 0);
1339 update_statistics ((int) trie_c, nc, 0);
1340 update_statistics ((int) trie_r, nr, 0);
1341 update_statistics ((int) trie_hash, nh, 0);
1342 update_statistics ((int) trie_taken, nt, 0);
1343 /* trie_size = size; */ /* ??? */
1344 if (trace_flag) probe_show(); /* 94/Mar/25 */
1345 return 0; // success
1349 #ifdef ALLOCATESAVESTACK
1350 int current_save_size = 0;
1352 memory_word *realloc_save_stack (int size)
1356 memory_word *newsave_stack=NULL;
1360 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1361 show_line(log_line, 0);
1364 if (current_save_size == save_size) /* arbitrary limit */
1366 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1368 return save_stack; /* let TeX handle the error */
1371 minsize = current_save_size / 100 * percent_grow;
1376 if (size < initial_save_size)
1377 size = initial_save_size;
1379 for (k = 0; k < MAXSPLITS; k++)
1381 newsize = current_save_size + size;
1382 if (newsize > save_size) newsize = save_size;
1383 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1384 if (trace_flag) trace_memory("save_stack", n);
1385 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1386 if (newsave_stack != NULL) break; /* did we get it ? */
1387 if (current_save_size == 0) break; /* initial allocation must work */
1388 size = size / 2; /* else can retry smaller */
1391 if (newsave_stack == NULL)
1393 memory_error("save stack", n);
1394 return save_stack; /* try and continue !!! */
1397 save_stack = newsave_stack;
1398 update_statistics ((int) save_stack, n, current_save_size);
1399 current_save_size = newsize;
1403 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1404 show_line(log_line, 0);
1405 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1406 show_line(log_line, 0);
1409 if (trace_flag) probe_show(); /* 94/Mar/25 */
1414 #ifdef ALLOCATEINPUTSTACK
1415 int current_stack_size = 0; /* input stack size */
1417 in_state_record *realloc_input_stack (int size)
1421 in_state_record *newinputstack=NULL;
1424 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1425 show_line(log_line, 0);
1427 if (current_stack_size == stack_size) { /* arbitrary limit */
1428 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1432 minsize = current_stack_size / 100 * percent_grow;
1433 if (size < minsize) size = minsize;
1434 if (size < initial_stack_size) size = initial_stack_size;
1436 for (k = 0; k < MAXSPLITS; k++) {
1437 newsize = current_stack_size + size;
1438 if (newsize > stack_size) newsize = stack_size;
1439 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1440 if (trace_flag) trace_memory("input_stack", n);
1441 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1442 if (newinputstack != NULL) break; /* did we get it ? */
1443 if (current_stack_size == 0) break; /* initial allocation must work */
1444 size = size / 2; /* else can retry smaller */
1447 if (newinputstack == NULL) {
1448 memory_error("input stack", n);
1449 return input_stack; /* try and continue !!! */
1451 input_stack = newinputstack;
1452 update_statistics ((int) input_stack, n, current_stack_size);
1453 current_stack_size = newsize;
1455 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1456 show_line(log_line, 0);
1457 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1458 show_line(log_line, 0);
1460 if (trace_flag) probe_show(); /* 94/Mar/25 */
1465 #ifdef ALLOCATENESTSTACK
1466 int current_nest_size = 0; /* current nest size */
1468 list_state_record *realloc_nest_stack (int size)
1472 list_state_record *newnest=NULL;
1475 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1476 show_line(log_line, 0);
1478 if (current_nest_size == nest_size) { /* arbitrary limit */
1479 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1481 return nest; /* let TeX handle the error */
1483 minsize = current_nest_size / 100 * percent_grow;
1484 if (size < minsize) size = minsize;
1485 if (size < initial_nest_size) size = initial_nest_size;
1487 for (k = 0; k < MAXSPLITS; k++) {
1488 newsize = current_nest_size + size;
1489 if (newsize > nest_size) newsize = nest_size;
1490 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1491 if (trace_flag) trace_memory("nest stack", n);
1492 newnest = (list_state_record *) REALLOC (nest, n);
1493 if (newnest != NULL) break; /* did we get it ? */
1494 if (current_nest_size == 0) break; /* initial allocation must work */
1495 size = size / 2; /* else can retry smaller */
1498 if (newnest == NULL) {
1499 memory_error("nest stack", n);
1500 return nest; /* try and continue !!! */
1503 update_statistics ((int) nest, n, current_nest_size);
1504 current_nest_size = newsize;
1506 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1507 show_line(log_line, 0);
1508 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1509 show_line(log_line, 0);
1511 if (trace_flag) probe_show(); /* 94/Mar/25 */
1516 #ifdef ALLOCATEPARAMSTACK
1517 int current_param_size=0; /* current param size */
1519 halfword *realloc_param_stack (int size)
1523 halfword *newparam=NULL;
1526 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1527 show_line(log_line, 0);
1529 if (current_param_size == param_size) { /* arbitrary limit */
1530 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1532 return param_stack; /* let TeX handle the error */
1534 minsize = current_param_size / 100 * percent_grow;
1535 if (size < minsize) size = minsize;
1536 if (size < initial_param_size) size = initial_param_size;
1538 for (k = 0; k < MAXSPLITS; k++) {
1539 newsize = current_param_size + size;
1540 if (newsize > param_size) newsize = param_size;
1541 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1542 if (trace_flag) trace_memory("param stack", n);
1543 newparam = (halfword *) REALLOC (param_stack, n);
1544 if (newparam != NULL) break; /* did we get it ? */
1545 if (current_param_size == 0) break; /* initial allocation must work */
1546 size = size / 2; /* else can retry smaller */
1549 if (newparam == NULL) {
1550 memory_error("param stack", n);
1551 return param_stack; /* try and continue !!! */
1553 param_stack = newparam;
1554 update_statistics ((int) param_stack, n, current_param_size);
1555 current_param_size = newsize;
1557 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1558 show_line(log_line, 0);
1559 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1560 show_line(log_line, 0);
1562 if (trace_flag) probe_show(); /* 94/Mar/25 */
1567 #ifdef ALLOCATEBUFFER
1568 int current_buf_size = 0;
1570 ASCII_code *realloc_buffer (int size)
1574 ASCII_code *newbuffer=NULL;
1577 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1578 show_line(log_line, 0);
1580 if (current_buf_size == buf_size) { /* arbitrary limit */
1581 /* memory_error ("buffer", buf_size); */
1583 return buffer; /* pass it back to TeX 99/Fabe/4 */
1585 minsize = current_buf_size / 100 * percent_grow;
1586 if (size < minsize) size = minsize;
1587 if (size < initial_buf_size) size = initial_buf_size;
1589 for (k = 0; k < MAXSPLITS; k++) {
1590 newsize = current_buf_size + size;
1591 if (newsize > buf_size) newsize = buf_size;
1592 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1593 if (trace_flag) trace_memory("buffer", n);
1594 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1595 if (newbuffer != NULL) break; /* did we get it ? */
1596 if (current_buf_size == 0) break; /* initial allocation must work */
1597 size = size / 2; /* else can retry smaller */
1600 if (newbuffer == NULL) {
1601 memory_error("buffer", n);
1602 return buffer; /* try and continue !!! */
1605 update_statistics ((int) buffer, n, current_buf_size);
1607 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1609 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1611 current_buf_size = newsize;
1613 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1614 show_line(log_line, 0);
1615 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1616 show_line(log_line, 0);
1618 if (trace_flag) probe_show(); /* 94/Mar/25 */
1623 /* here is the main memory allocation routine -- calls the above */
1624 /* returns -1 if it fails */
1625 /* allocate rather than static 93/Nov/26 */
1626 int allocate_memory (void)
1630 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1634 #error ERROR: Not ready for ALLOCATEHASH...
1637 /* probably not worth while/not a good idea allocating following */
1638 /* they are all rather small, and typically don't need expansion */
1639 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1641 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1642 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1643 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1645 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1646 zzzae = (htwohalves *) malloc (roundup(n));
1648 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1649 zzzae = (twohalves *) malloc (roundup(n));
1651 if (trace_flag) trace_memory("hash table", n);
1652 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1655 memory_error("hash table", n);
1656 // exit (1); /* serious error */
1657 return -1; /* serious error */
1660 n = (inputsize + 1) * sizeof(memory_word);
1663 trace_memory("input_stack", n);
1665 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1666 input_stack = (memory_word *) malloc (roundup(n));
1668 if (input_stack == NULL)
1670 memory_error("input_stack", n);
1671 // exit (1); /* serious error */
1672 return -1; /* serious error */
1676 /* no real reason to allocate dvi_buf - no need to ever grow it */
1677 #ifdef ALLOCATEDVIBUF
1678 /* zdvibuf = NULL; */
1679 zdvibuf = allocatedvibuf (dvi_buf_size);
1680 if (zdvibuf == NULL) return -1;
1683 #ifdef ALLOCATEZEQTB
1685 #ifdef INCREASEFONTS
1686 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1687 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1689 /* zeqtb = allocatezeqtb (13507); */
1690 zeqtb = allocatezeqtb (hash_size + 4007);
1694 #ifdef ALLOCATEINPUTSTACK
1695 input_stack = NULL; /* new 1999/Jan/21 */
1696 current_stack_size = 0;
1697 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1700 #ifdef ALLOCATENESTSTACK
1701 nest = NULL; /* new 1999/Jan/21 */
1702 current_nest_size = 0;
1703 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1706 #ifdef ALLOCATEPARAMSTACK
1707 param_stack = NULL; /* new 1999/Jan/21 */
1708 current_param_size = 0;
1709 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1712 #ifdef ALLOCATESAVESTACK
1713 save_stack = NULL; /* new 1999/Jan/7 */
1714 current_save_size = 0;
1715 save_stack = realloc_save_stack (initial_save_size);
1719 buffer = NULL; /* need to do earlier */
1720 current_buf_size = 0;
1721 buffer = realloc_buffer (initial_buf_size);
1724 #ifdef ALLOCATESTRING
1726 current_pool_size = 0;
1728 current_max_strings = 0;
1729 /* need to create space because iniTeX writes in before reading pool file */
1730 /* for a start, puts in strings for 256 characters */
1731 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1733 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1734 str_pool = realloc_str_pool (initial_pool_size);
1735 str_start = realloc_str_start (initial_max_strings);
1739 /* the following can save a lot of the usual 800k fixed allocation */
1742 current_font_mem_size = 0;
1743 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1744 /* if ini-TeX we need to do it here - no format file read later */
1745 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1751 mem_min = mem_bot; /* just to avoid complaints in texbody */
1752 mem_top = mem_initex;
1754 /* allocate main memory here if this is iniTeX */
1755 /* otherwise wait for format undumping in itex.c ... */
1757 /* avoid this if format specified on command line ??? */
1758 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1759 mem = allocate_main_memory(mem_initex); /* made variable ! */
1762 return -1; /* serious error */
1766 /* now for the hyphenation exception stuff */
1767 #ifdef ALLOCATEHYPHEN
1770 /* this will be overridden later by what is in format file */
1771 hyphen_prime = default_hyphen_prime;
1772 /* non ini-TeX use assumes format will be read and that specifies size */
1775 if (new_hyphen_prime)
1776 hyphen_prime = new_hyphen_prime;
1777 if (realloc_hyphen(hyphen_prime)) /* allocate just in case no format */
1782 /* now for memory for the part of the hyphenation stuff that always needed */
1783 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1784 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1785 #ifdef ALLOCATETRIES
1788 if (allocate_tries (trie_size))
1793 /* now for memory for hyphenation stuff needed only when running iniTeX */
1797 if (allocate_ini(trie_size))
1802 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1803 trie_c = NULL; /* (trie_size + 1) * char */
1804 trie_taken = NULL; /* (trie_size + 1) * bool */
1808 free(holeadr); /* create the hole */
1810 return 0; // success
1813 /* returns non-zero if error - done to test integrity of stack mostly */
1814 /* free in reverse order 93/Nov/26 */
1815 int free_memory (void)
1818 unsigned heaptotal = 0;
1819 /* unsigned total; */
1821 if (trace_flag) show_line("free_memory ", 0);
1823 if (verbose_flag || trace_flag)
1824 show_maximums(stdout);
1828 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1829 heaptotal, max_address);
1830 show_line(log_line, 0);
1834 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1835 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1836 show_line(log_line, 0);
1838 /* following only needed to check consistency of heap ... useful debugging */
1839 if (trace_flag) show_line("Freeing memory again\n", 0);
1842 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1844 /* the following checks the heap integrity */
1846 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1848 #ifdef SHOWHEAPERROR
1850 if (n != _HEAPOK) { /* 94/Feb/18 */
1851 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1852 show_line(log_line, 1);
1853 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1854 show_line(log_line, 0);
1855 return n; /* non-zero and negative */ /* unreachable ??? */
1858 /* only free memory if safe ... additional check */
1862 if (trie_taken != NULL) free(trie_taken);
1863 if (trie_hash != NULL) free(trie_hash);
1864 if (trie_r != NULL) free(trie_r);
1865 if (trie_c != NULL) free(trie_c);
1866 if (trie_o != NULL) free(trie_o);
1867 if (trie_l != NULL) free(trie_l);
1869 trie_hash = trie_l = trie_r = NULL;
1874 #ifdef ALLOCATETRIES
1875 if (trie_trc != NULL) free (trie_trc);
1876 if (trie_tro != NULL) free (trie_tro);
1877 if (trie_trl != NULL) free (trie_trl);
1879 trie_tro = trie_trl = NULL;
1881 #ifdef ALLOCATEHYPHEN
1882 if (hyph_list != NULL) free(hyph_list);
1883 if (hyph_word != NULL) free(hyph_word);
1888 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1889 if (mainmemory != NULL) free(mainmemory);
1893 if (font_info != NULL) free(font_info);
1896 #ifdef ALLOCATESTRING
1897 if (str_start != NULL) free(str_start);
1898 if (str_pool != NULL) free(str_pool);
1904 if (zzzae != NULL) free(zzzae);
1908 #ifdef ALLOCATEDVIBUF
1909 if (zdvibuf != NULL) free(zdvibuf);
1912 #ifdef ALLOCATEZEQTB
1913 if (zeqtb != NULL) free(zeqtb);
1917 #ifdef ALLOCATEPARAMSTACK
1918 if (param_stack != NULL) free(param_stack);
1921 #ifdef ALLOCATENESTSTACK
1922 if (nest != NULL) free(nest);
1925 #ifdef ALLOCATEINPUTSTACK
1926 if (input_stack != NULL) free(input_stack);
1929 #ifdef ALLOCATESAVESTACK
1930 if (save_stack != NULL) free(save_stack);
1933 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1934 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1935 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1936 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1937 format_file = string_file = source_direct = NULL;
1938 if (dvi_file_name != NULL) free(dvi_file_name);
1939 if (log_file_name != NULL) free(log_file_name);
1940 if (pdf_file_name != NULL) free(pdf_file_name);
1941 pdf_file_name = log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1948 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1949 if (x % 2 == 0) return false;
1950 for (k = 3; k < x; k = k + 2) {
1951 if (x % k == 0) return false;
1952 /* if (k * k > x) return true; */
1953 if (sum * 4 > x) return true;
1960 bool show_use = false;
1961 bool floating = false;
1963 void complainarg (int c, char *s)
1965 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1966 show_line(log_line, 1);
1967 show_use = 1; // 2000 June 21
1970 /* following is list of allowed command line flags and args */
1972 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1974 /* only 01234567.9 still left to take ... maybe recycle u */
1976 char *allowedargs = "+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ023456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1978 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1980 void reorderargs (int ac, char **av)
1981 { /* put in 1993/Dec/28 */
1984 // char takeargs[128]; /* large enough for all command line arg chars */
1985 char takeargs[256]; /* large enough for all command line arg chars */
1987 /* assumes arg pointers av[] are writeable */
1988 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1990 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1991 /* show_line("No arguments?\n", 0); */ /* debugging */
1992 return; /* no args ! */
1996 t = takeargs; /* list of those that take args */
1997 while (*s != '\0' && *(s+1) != '\0') {
1998 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
2003 show_line(takeargs, 0);
2008 for (;;) { /* scan to end of command line args */
2009 if (*av[n] != '-') break;
2010 /* does it take an argument ? and is this argument next ? */
2012 *(av[n]+2) == '\0' &&
2013 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
2014 strchr(takeargs, *(av[n]+1)) != NULL)
2015 n += 2; /* step over it */
2020 for (;;) { /* look for more command line args */
2023 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
2024 while (m < ac && *av[m] != '-') m++; /* first command */
2026 /* does it take an argument ? and is this argument next ? */
2027 /* check first whether the `-x' is isolated, or arg follows directly */
2028 /* then check whether this is one of those that takes an argument */
2030 *(av[m]+2) == '\0' &&
2031 strchr(takeargs, *(av[m]+1)) != NULL) {
2032 s = av[m]; /* move command down before non-command */
2034 for (; m > n; m--) av[m+1] = av[m-1];
2037 n += 2; /* step over moved args */
2040 s = av[m]; /* move command down before non-command */
2041 for (; m > n; m--) av[m] = av[m-1];
2043 n++; /* step over moved args */
2048 int test_align (int address, int size, char *name)
2051 if (size > 4) n = address % 4;
2052 else n = address % size;
2054 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
2055 show_line(log_line, 0);
2060 /* activate detailed checking of alignment when trace_flag is set */
2062 void check_fixed_align (int flag)
2064 if (test_align ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
2065 show_line("PLEASE RECOMPILE ME!\n", 1);
2067 #ifdef CHECKALIGNMENT
2069 test_align ((int) &mem_top, 4, "mem_top");
2070 test_align ((int) &mem_max, 4, "mem_max");
2071 test_align ((int) &mem_min, 4, "mem_min");
2072 test_align ((int) &bad, 4, "bad");
2073 test_align ((int) &trie_size, 4, "trie_size");
2074 test_align ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2075 test_align ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2076 test_align ((int) &name_length, 4, "name_length");
2077 test_align ((int) &first, 4, "first");
2078 test_align ((int) &last, 4, "last");
2079 test_align ((int) &max_buf_stack, 4, "max_buf_stack");
2080 test_align ((int) &pool_ptr, 4, "pool_ptr");
2081 test_align ((int) &str_ptr, 4, "str_ptr");
2082 test_align ((int) &init_pool_ptr, 4, "init_pool_ptr");
2083 test_align ((int) &init_str_ptr, 4, "init_str_ptr");
2084 test_align ((int) &log_file, 4, "log_file");
2085 test_align ((int) &tally, 4, "tally");
2086 test_align ((int) &term_offset, 4, "term_offset");
2087 test_align ((int) &file_offset, 4, "file_offset");
2088 test_align ((int) &trick_count, 4, "trick_count");
2089 test_align ((int) &first_count, 4, "first_count");
2090 test_align ((int) &deletions_allowed, 4, "deletions_allowed");
2091 test_align ((int) &set_box_allowed, 4, "set_box_allowed");
2092 test_align ((int) &help_line, sizeof(help_line[0]), "help_line");
2093 test_align ((int) &use_err_help, 4, "use_err_help");
2094 test_align ((int) &interrupt, 4, "interrupt");
2095 test_align ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2096 test_align ((int) &arith_error, 4, "arith_error");
2097 test_align ((int) &tex_remainder, 4, "tex_remainder");
2098 test_align ((int) &temp_ptr, 4, "temp_ptr");
2099 test_align ((int) &lo_mem_max, 4, "lo_mem_max");
2100 test_align ((int) &hi_mem_min, 4, "hi_mem_min");
2101 test_align ((int) &var_used, 4, "var_used");
2102 test_align ((int) &dyn_used, 4, "dyn_used");
2103 test_align ((int) &avail, 4, "avail");
2104 test_align ((int) &mem_end, 4, "mem_end");
2105 test_align ((int) &mem_start, 4, "mem_start");
2106 test_align ((int) &rover, 4, "rover");
2107 test_align ((int) &font_in_short_display, 4, "font_in_short_display");
2108 test_align ((int) &depth_threshold, 4, "depth_threshold");
2109 test_align ((int) &breadth_max, 4, "breadth_max");
2110 test_align ((int) &nest, sizeof(nest[0]), "nest");
2113 test_align ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2115 /* test_align ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2116 test_align ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2117 /* test_align ((int) &hash, sizeof(hash[0]), "hash"); */
2118 test_align ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2120 test_align ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2121 test_align ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2122 test_align ((int) &input_file, sizeof(input_file[0]), "input_file");
2123 test_align ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2124 test_align ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2125 test_align ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2126 test_align ((int) &pstack, sizeof(pstack[0]), "pstack");
2127 test_align ((int) &read_file, sizeof(read_file[0]), "read_file");
2129 test_align ((int) &font_check, sizeof(font_check[0]), "font_check");
2130 test_align ((int) &font_size, sizeof(font_size[0]), "font_size");
2131 test_align ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2132 test_align ((int) &font_params, sizeof(font_params[0]), "font_params");
2133 test_align ((int) &font_name, sizeof(font_name[0]), "font_name");
2134 test_align ((int) &font_area, sizeof(font_area[0]), "font_area");
2135 test_align ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2136 test_align ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2137 test_align ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2138 test_align ((int) &font_used, sizeof(font_used[0]), "font_used");
2139 test_align ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2140 test_align ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2141 test_align ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2142 test_align ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2143 test_align ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2144 test_align ((int) &char_base, sizeof(char_base[0]), "char_base");
2145 test_align ((int) &width_base, sizeof(width_base[0]), "width_base");
2146 test_align ((int) &height_base, sizeof(height_base[0]), "height_base");
2147 test_align ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2148 test_align ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2149 test_align ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2150 test_align ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2151 test_align ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2152 test_align ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2154 #ifdef ALLOCATEDVIBUF
2155 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2157 test_align ((int) &total_stretch, sizeof(total_stretch[0]), "total_stretch");
2158 test_align ((int) &total_shrink, sizeof(total_shrink[0]), "total_shrink");
2159 test_align ((int) &active_width, sizeof(active_width[0]), "active_width");
2160 test_align ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2161 test_align ((int) &background, sizeof(background[0]), "background");
2162 test_align ((int) &break_width, sizeof(break_width[0]), "break_width");
2163 test_align ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2164 test_align ((int) &best_place, sizeof(best_place[0]), "best_place");
2165 test_align ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2166 test_align ((int) &hc, sizeof(hc[0]), "hc");
2167 test_align ((int) &hu, sizeof(hu[0]), "hu");
2168 test_align ((int) &hyf, sizeof(hyf[0]), "hyf");
2169 /* test_align ((int) &x, sizeof(x[0]), "x"); */
2171 test_align ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2172 test_align ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2173 test_align ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2174 test_align ((int) &op_start, sizeof(op_start[0]), "op_start");
2176 /* test_align ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2177 test_align ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2178 test_align ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2179 /* test_align ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2180 test_align ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2182 test_align ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2183 test_align ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2184 test_align ((int) &write_file, sizeof(write_file[0]), "write_file");
2185 test_align ((int) &write_open, sizeof(write_open[0]), "write_open");
2189 void check_alloc_align (int flag)
2191 if (test_align ((int) eqtb, sizeof(eqtb[0]), "ALLOCATED ALIGNMENT"))
2192 show_line("PLEASE RECOMPILE ME!\n", 1);
2193 #ifdef CHECKALIGNMENT
2196 test_align ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2198 #ifndef ALLOCATEDVIBUF
2199 test_align ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2201 test_align ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2202 test_align ((int) str_start, sizeof(str_start[0]), "str_start");
2203 test_align ((int) zmem, sizeof(zmem[0]), "main memory");
2204 test_align ((int) font_info, sizeof(font_info[0]), "font memory");
2205 test_align ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2206 test_align ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2207 test_align ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2208 test_align ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2209 test_align ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2210 /* test_align ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2211 test_align ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2212 test_align ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2213 test_align ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2214 test_align ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2215 test_align ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2219 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2221 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2222 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2224 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2225 bool backwardflag = false; /* don't cripple all advanced features */
2226 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2227 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2228 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2229 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2230 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2231 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2232 bool usesourcedirectory = true; /* use source file directory as local when WorkingDirectory is set */
2233 bool workingdirectory = false; /* if working directory set in ini */
2235 /* cache to prevent allocating twice in a row */
2237 char *lastname=NULL, *lastvalue=NULL;
2239 /* get value of env var - try first in dviwindo.ini then DOS env */
2240 /* returns allocated string -- these strings are not freed again */
2241 /* is it safe to do that now ? 98/Jan/31 */
2242 char *grabenv (char *varname)
2244 char line[PATH_MAX];
2249 if (varname == NULL) return NULL; /* sanity check */
2250 if (*varname == '\0') return NULL; /* sanity check */
2251 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2252 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2253 if (lastname != NULL && _strcmpi(lastname, varname) == 0)
2257 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2258 show_line(log_line, 0);
2260 /* return lastvalue; */ /* save some time here */
2261 return xstrdup(lastvalue);
2262 /* duplicate so can free safely 98/Jan/31 */
2265 /* hmm, following was not xstrdup(...) */ /* not cached */
2266 if (usedviwindo == 0 || *dviwindo == '\0') {
2267 /* return getenv(varname); */
2268 s = getenv(varname);
2269 if (s == NULL) return NULL;
2270 else return xstrdup(s); /* make safe 98/Jan/31 */
2273 if (share_flag == 0) pinput = fopen(dviwindo, "r");
2274 else pinput = _fsopen(dviwindo, "r", share_flag);
2276 if (pinput != NULL) {
2277 m = strlen(envsection);
2278 /* search for [Environment] section */ /* should be case insensitive */
2279 while (fgets (line, sizeof(line), pinput) != NULL) {
2280 if (*line == ';') continue;
2281 if (*line == '\n') continue;
2282 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2283 /* search for varname=... */ /* should be case sensitive ? */
2284 n = strlen(varname);
2285 while (fgets (line, sizeof(line), pinput) != NULL) {
2286 if (*line == ';') continue;
2287 if (*line == '[') break;
2288 /* if (*line == '\n') break; */ /* ??? */
2289 if (*line <= ' ') continue; /* 95/June/23 */
2290 /* if (strncmp(line, varname, n) == 0 && */
2291 if (_strnicmp(line, varname, n) == 0 &&
2292 *(line+n) == '=') { /* found it ? */
2293 (void) fclose (pinput);
2294 /* flush trailing white space */
2295 s = line + strlen(line) - 1;
2296 while (*s <= ' ' && s > line) *s-- = '\0';
2297 if (trace_flag) { /* DEBUGGING ONLY */
2298 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2299 show_line(log_line, 0);
2302 if (lastname != NULL) free(lastname);
2303 lastname = xstrdup (varname);
2304 if (lastvalue != NULL) free(lastvalue);
2305 lastvalue = xstrdup(s);
2306 return xstrdup(s); /* 98/Jan/31 */
2307 } /* end of matching varname */
2308 } /* end of while fgets */
2309 /* break; */ /* ? not found in designated section */
2310 } /* end of search for [Environment] section */
2312 (void) fclose (pinput);
2313 } /* end of if fopen */
2314 s = getenv(varname); /* failed, so try and get from environment */
2315 /* if (s != NULL) return s; */
2317 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2318 if (lastname != NULL) free(lastname);
2319 lastname = xstrdup (varname);
2320 if (lastvalue != NULL) free(lastvalue);
2321 lastvalue = xstrdup(s); /* remember in case asked again ... */
2323 return xstrdup(s); /* 98/Jan/31 */
2325 else return NULL; /* return NULL if not found anywhere */
2328 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2330 void flush_trailing_slash (char *directory)
2333 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2334 if (strcmp(directory, "") != 0) {
2335 s = directory + strlen(directory) - 1;
2336 if (*s == '\\' || *s == '/') *s = '\0';
2340 void knuthify (void)
2342 /* show_current = false; */ /* show ultimate limits */
2343 /* reorder_arg_flag = false; */ /* don't reorder command line */
2344 /* deslash = false; */ /* don't unixify file names */
2345 /* return_flag = false; */ /* don't allow just ^^M termination */
2346 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2347 restrict_to_ascii = false; /* don't complain non ASCII */
2348 allow_patterns = false; /* don't allow pattern redefinition */
2349 show_in_hex = true; /* show character code in hex */
2350 show_in_dos = false; /* redundant with previous */
2351 show_numeric = false; /* don't show character code decimal */
2352 show_missing = false; /* don't show missing characters */
2353 civilize_flag = false; /* don't reorder date fields */
2354 c_style_flag = false; /* don't add file name to error msg */
2355 show_fmt_flag = false; /* don't show format file in log */
2356 show_tfm_flag = false; /* don't show metric file in log */
2357 /* font_max = 255; */ /* revert to TeX 82 limit */
2358 /* if you want this, change in tex.h definition of font_max to `int' */
2359 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2361 show_line_break_stats = false; /* do not show line break stats */
2362 show_fonts_used = false;
2363 default_rule = 26214; /* revert to default rule thickness */
2364 pseudo_tilde = false;
2365 pseudo_space = false;
2366 show_texinput_flag = false;
2367 truncate_long_lines = false;
2368 allow_quoted_names = false;
2369 show_cs_names = false;
2370 font_dimen_zero = false; /* 98/Oct/5 */
2371 ignore_frozen = false; /* 98/Oct/5 */
2372 suppress_f_ligs = false; /* 99/Jan/5 */
2373 full_file_name_flag = false; // 00 Jun 18
2374 save_strings_flag = false; // 00 Aug 15
2375 knuth_flag = true; /* so other code can know about this */
2376 } /* end of knuthify */
2378 /* following have already been used up */
2380 /* abcdefghijklmnopqrstuvwxyz */
2382 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2386 int nohandler = 0; /* experiment to avoid Ctrl-C interrupt handler */
2388 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2390 /* following made global so analyze_flag can be made separate procedure */
2392 // char *xchrfile=""; /* save space use xstrdup */
2393 char *xchrfile = NULL; /* save space use xstrdup */
2394 // char *replfile="";/* save space use xstrdup */
2395 char *replfile = NULL;/* save space use xstrdup */
2397 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2399 /* analyze command line flag or argument */
2400 /* c is the flag letter itself, while optarg is start of arg if any */
2402 /* when making changes, revise allowedargs */
2405 int analyze_flag (int c, char *optarg)
2410 want_version = true;
2411 verbose_flag = true;
2417 interaction = batch_mode; /* quiet mode */
2420 interaction = nonstop_mode; /* run mode */
2423 interaction = scroll_mode; /* scroll mode */
2426 interaction = error_stop_mode; /* tex mode */
2429 backwardflag = true; /* 94/Jun/15 */
2430 knuthify(); /* revert to `standard' Knuth TeX */
2433 c_style_flag = true; /* C style error msg 94/Mar/21 */
2436 show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2439 current_tfm = false; /* not look current dir for TFM */
2442 current_flag = false; /* not look current dir for files */
2445 show_missing = false; /* do not show missing 94/June/10 */
2448 deslash = false; /* flipped 93/Nov/18 */
2449 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2452 allow_patterns = true; /* 93/Nov/26 */
2453 /* reset_exceptions = true; */ /* 93/Dec/23 */
2455 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2457 show_in_hex = true; /* flipped 00/Jun/18 */
2460 show_in_dos = true; /* 96/Jan/26 */
2463 restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2466 workingdirectory = true; /* use source dir 98/Sep/29 */
2469 usesourcedirectory = false; /* use working dir 98/Sep/29 */
2472 show_fonts_used = false; /* 97/Dec/24 */
2475 shorten_file_name = true; /* 95/Feb/20 */
2478 show_cs_names = true; /* 98/Mar/31 */
2481 ignore_frozen = true; /* 98/Oct/5 */
2484 font_dimen_zero = false; /* 98/Oct/5 */
2487 show_texinput_flag = false; /* 98/Jan/28 */
2489 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2492 usedviwindo = false; /* 94/May/19 */
2495 show_line_break_stats = false; /* 96/Feb/8 */
2498 show_fmt_flag = false; /* 94/Jun/21 */
2501 format_specific = false; /* 95/Jan/7 */
2504 encoding_specific = false; /* 98/Oct/5 */
2507 suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2509 /* following are pretty obscure */
2510 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2512 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2514 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2517 full_file_name_flag = false; // 00 Jun 18
2520 save_strings_flag = false; // 00 Aug 15
2522 /* following are unannounced options */ /* some may be recycled ... */
2527 quitflag++; /* 93/Dec/16 */
2529 /* The following are really obscure and should not be advertized */
2531 show_current = false; /* tex8 93/Dec/14 */
2534 show_numeric = false; /* 93/Dec/21 */
2537 civilize_flag = false; /* 93/Dec/16 */
2540 open_trace_flag = true; /* openinou 1994/Jan/8 */
2543 reorder_arg_flag = false; /* local */
2546 test_dir_access = false; /* 94/Feb/10 */
2549 dir_method = false; /* 94/Feb/10 */
2552 file_method = false; /* 94/Feb/13 */
2554 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2555 /* case 'X': nohandler++; break; */
2556 /* case 'f': waitflush = false; break; */
2557 /* case 'F': floating = true; break; */
2558 /* *********** following command line options take arguments ************** */
2561 mem_initex = mem_top;
2563 mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2564 if (mem_initex == 0)
2565 complainarg(c, optarg);
2568 #ifdef VARIABLETRIESIZE
2571 trie_size = default_trie_size;
2573 trie_size = atoi(optarg); /* 93 Dec/1 */
2575 complainarg(c, optarg);
2578 #ifdef ALLOCATEHYPHEN
2581 new_hyphen_prime = hyphen_prime * 2;
2583 new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2584 if (new_hyphen_prime == 0)
2585 complainarg(c, optarg);
2588 #ifdef ALLOCATEDVIBUF
2591 dvi_buf_size = default_dvi_buf_size;
2593 dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2594 if (dvi_buf_size == 0)
2595 complainarg(c, optarg);
2602 percent_grow = atoi(optarg); /* 93/Dec/11 */
2603 if (percent_grow == 0)
2604 complainarg(c, optarg);
2610 pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2611 if (pseudo_tilde > 255)
2613 else if (pseudo_tilde < 128)
2616 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2617 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2623 tab_step = atoi(optarg); /* 94/July/3 */
2625 complainarg(c, optarg);
2629 xchrfile = xstrdup("xchr.map");
2631 xchrfile = xstrdup(optarg);
2632 if (xchrfile == NULL || *xchrfile == '\0')
2633 complainarg(c, optarg);
2637 replfile = xstrdup("repl.key");
2639 replfile = xstrdup(optarg);
2640 if (replfile == NULL || *replfile == '\0')
2641 complainarg(c, optarg);
2643 /* more obscure stuff - ppssibly recycle */
2646 default_rule = 26214; /* 95/Oct/9 */
2648 default_rule = atoi(optarg); /* 95/Oct/9 */
2649 if (default_rule == 0)
2650 complainarg(c, optarg);
2656 complainarg(c, optarg);
2662 dvi_directory = xstrdup(optarg);
2663 if (strcmp(dvi_directory, "") == 0)
2664 complainarg(c, optarg);
2668 pdf_output_flag = true;
2674 log_directory = xstrdup(optarg);
2675 if (strcmp(log_directory, "") == 0)
2676 complainarg(c, optarg);
2682 aux_directory = xstrdup(optarg);
2683 if (strcmp(aux_directory, "") == 0)
2684 complainarg(c, optarg);
2689 return -1; // failed to recognize
2695 /* Try and read default command file - YANDYTEX.CMD */
2696 /* in current directory and then in directory of YANDYTEX */
2697 /* (does not make sense in TeX file directory) */
2698 /* since we don't yet know where that is ! */
2699 /* can't conveniently include this in output file either - not open yet */
2701 /* used both for yytex.cmd and @ indirect command line files */
2702 /* can this be reentered ? */
2704 /* supply extension if none */
2705 void yy_extension (char *fname, char *ext)
2708 if ((s = strrchr(fname, '.')) == NULL ||
2709 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2715 /* remove file name - keep only path - inserts '\0' to terminate */
2717 void strip_name (char *pathname)
2720 if ((s = strrchr(pathname, '\\')) != NULL);
2721 else if ((s = strrchr(pathname, '/')) != NULL);
2722 else if ((s = strrchr(pathname, ':')) != NULL) s++;
2727 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2729 char *programpath = ""; /* pathname of program */
2730 /* redundant with texpath ? */
2732 /* The following does not deslashify arguments ? Do we need to ? */
2734 int read_commands (char *filename)
2736 char commandfile[PATH_MAX];
2738 char line[PATH_MAX];
2739 char *linedup; /* need to copy line to preserve args */
2745 /* Try first in current directory (or use full name as specified) */
2746 strcpy(commandfile, filename);
2747 yy_extension(commandfile, "cmd");
2748 if (share_flag == 0)
2749 command = fopen(commandfile, "r");
2751 command = _fsopen(commandfile, "r", share_flag);
2752 if (command == NULL) {
2753 /* If that fails, try in YANDYTeX program directory */
2754 strcpy(commandfile, programpath);
2755 /* don't need fancy footwork, since programpath non-empty */
2756 strcat(commandfile, "\\");
2757 strcat(commandfile, filename);
2758 yy_extension(commandfile, "cmd");
2759 if (share_flag == 0)
2760 command = fopen(commandfile, "r");
2762 command = _fsopen(commandfile, "r", share_flag);
2763 if (command == NULL) {
2764 /* perrormod(commandfile); */ /* debugging only */
2765 /* strcpy(commandfile, ""); */ /* indicate failed */
2766 return 0; /* no command line file YYTEX.CMD */
2770 /* allow for multiple lines --- ignore args that don't start with `-' */
2771 while (fgets(line, PATH_MAX, command) != NULL) {
2772 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2773 /* skip over comment lines and blank lines */
2774 if (*line == '%' || *line == ';' || *line == '\n') continue;
2775 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2776 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2777 linedup = xstrdup (line); /* 93/Nov/15 */
2778 if (linedup == NULL) {
2779 show_line("ERROR: out of memory\n", 1); /* read_commands */
2781 return -1; // failure
2783 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2785 if (*s == '-' || *s == '/') {
2788 /* if (*optarg = '=') optarg++; */
2789 if (*optarg == '=') optarg++;
2790 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2792 /* else break; */ /* ignore non-flag items */
2793 s = strtok(NULL, " \t\n\r"); /* go to next token */
2795 /* If you want to see command lines in file - put -v in the file */
2796 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2798 (void) fclose(command); /* no longer needed */
2799 return 1; // success
2802 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2804 /* try and read commands on command line */
2805 int read_command_line (int ac, char **av)
2808 char *optargnew; /* equal to optarg, unless that starts with `=' */
2809 /* in which case it is optarg+1 to step over the `=' */
2810 /* if optarg = 0, then optargnew = 0 also */
2812 // show_line("read_command_line\n", 0);
2813 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2815 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2816 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2817 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2818 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2819 if (optarg != 0 && *optarg == '=')
2820 optargnew = optarg+1;
2823 analyze_flag (c, optargnew);
2825 if (show_use || quitflag == 3) {
2826 // showversion (stdout);
2828 strcat(log_line, "\n");
2829 show_line(log_line, 0);
2830 stampcopy(log_line);
2831 strcat(log_line, "\n");
2832 show_line(log_line, 0);
2833 if (show_use) show_usage();
2834 else if (quitflag == 3) {
2835 strcat(log_line, "\n");
2836 show_line(log_line, 0);
2839 return -1; // failure
2842 if (floating) testfloating(); /* debugging */
2845 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2846 if (read_xchr_file(replfile, 1, av)) {
2847 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2851 /* key_replace used in texmf.c (input_line) */
2852 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2853 if (read_xchr_file(xchrfile, 0, av)) {
2854 if (trace_flag) show_line("NON ASCII ON\n", 0);
2858 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2859 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2863 int init_commands (int ac, char **av)
2865 /* NOTE: some defaults changed 1993/Nov/18 */
2866 /* want_version = show_use = switchflag = return_flag = false;
2867 is_initex = trace_flag = deslash = non_ascii = false; */
2868 pdf_output_flag = false;
2869 is_initex = false; /* check for dumping format file */
2870 allow_patterns = false; /* using \pattern after format file loaded */
2871 reset_exceptions = false;
2873 key_replace = false;
2874 want_version = false;
2875 open_trace_flag = false;
2877 verbose_flag = false;
2879 restrict_to_ascii = false;
2880 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2881 show_in_dos = false; /* default is not to translate to DOS 850 */
2882 return_flag = true; // hard wired now
2883 trimeof = true; // hard wired now
2885 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2886 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2887 default_rule = 26214; /* default rule variable 95/Oct/9 */
2888 show_current = true;
2889 civilize_flag = true;
2890 show_numeric = true;
2891 show_missing = true;
2892 current_flag = true;
2893 current_tfm = true; /* search for TFMs in current dir as well */
2894 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2895 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2896 file_method = true; /* use file_p (_findfirst) not readable (access) */
2897 /* waitflush = true; */ /* flushed 97/Dec/24 */
2898 c_style_flag = false; /* use c-style error output */
2899 show_fmt_flag = true; /* show format file in log */
2900 show_tfm_flag = false; /* don't show metric file in log */
2901 shorten_file_name = false; /* don't shorten file names to 8+3 */
2902 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2903 truncate_long_lines = true; /* truncate long lines */
2904 tab_step = 0; /* do not replace tabs with spaces */
2905 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2906 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2907 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2908 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2909 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2910 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2911 knuth_flag = false; /* allow extensions to TeX */
2912 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2913 full_file_name_flag = true; /* new default 2000 June 18 */
2914 save_strings_flag = true; // 2000 Aug 15
2915 errout = stdout; /* as opposed to stderr say --- used ??? */
2916 abort_flag = 0; // not yet hooked up ???
2917 err_level = 0; // not yet hooked up ???
2918 new_hyphen_prime = 0;
2919 #ifdef VARIABLETRIESIZE
2920 /* trie_size = default_trie_size; */
2926 #ifdef ALLOCATEDVIBUF
2929 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
2930 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
2931 share_flag = 0; /* revert to fopen for now */
2933 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
2934 programpath = xstrdup(av[0]); /* extract path executable */
2935 strip_name(programpath); /* strip off yandytex.exe */
2937 format_name = "plain"; /* format name if specified on command line */
2941 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
2942 return -1; // in case of error
2950 strcat(log_line, "\n");
2951 show_line(log_line, 0);
2952 stampcopy(log_line);
2953 strcat(log_line, "\n");
2954 show_line(log_line, 0);
2957 /* if we aren't including current directory in any directory lists */
2958 /* then makes no sense to avoid them separately for TFM files ... */
2959 /* (that is, the ./ is already omitted from the dir list in that case */
2960 if (!current_flag && !current_tfm)
2961 current_tfm = true; /* 94/Jan/24 */
2966 /* E sets environment variable ? */
2968 void initial_memory (void)
2970 /* set initial memory allocations */
2971 if (mem_extra_high < 0)
2974 if (mem_extra_low < 0)
2982 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2983 if (mem_extra_high != 0 || mem_extra_low != 0)
2985 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
2986 mem_extra_high = 0; mem_extra_low = 0;
2992 if (mem_initex != 0)
2994 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
3000 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
3001 /* trie_size = 0; */
3004 if (mem_initex == 0)
3005 mem_initex = default_mem_top;
3007 trie_size = default_trie_size;
3008 /* Just in case user mistakenly specified words instead of kilo words */
3009 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
3010 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
3011 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
3012 #ifdef ALLOCATEHIGH /* not used anymore */
3013 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
3014 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3015 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
3018 #ifdef ALLOCATELOW /* not used anymore */
3019 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
3020 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3021 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
3024 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
3025 show_line("WARNING: There may be no benefit to asking for so much memory\n", 0);
3026 /* mem_initex = 2048 * 1024; */
3028 #ifdef ALLOCATEDVIBUF
3029 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
3030 /* if less than 1024 assume user specified kilo-bytes, not bytes */
3031 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
3032 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
3033 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
3035 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
3036 if (new_hyphen_prime > 0) {
3038 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
3040 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
3041 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
3043 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
3044 show_line(log_line, 0);
3048 if (percent_grow > 100) percent_grow = percent_grow - 100;
3049 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
3050 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
3053 /**********************************************************************/
3055 void perrormod (char *s)
3057 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
3058 show_line(log_line, 1);
3064 fflush(stdout); /* ??? */
3065 fflush(stderr); /* ??? */
3066 (void) _getch(); /* ??? */
3070 void checkpause (int flag)
3073 int debug_pause = 0;
3074 /* don't stop if in Q (quiet) or R (run) mode */
3075 /* stop only in S (scroll) and T (TeX) mode */
3076 if (interaction >= 0 && interaction < 2)
3077 flag = 0; /* 98/Jun/30 */
3078 s = grabenv("DEBUGPAUSE");
3079 if (s != NULL) sscanf(s, "%d", &debug_pause);
3080 if (flag < 0) return;
3082 if (debug_pause || flag > 0) {
3085 show_line("Press any key to continue . . .\n", 0);
3093 /*************************************************************************/
3095 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3096 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3097 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3098 /* this is then undone in tex3.c both for fopen input and output */
3099 /* not ideal, since pseudo name appears in log and in error messages ... */
3101 void hidetwiddle (char *name)
3108 sprintf(log_line, "Hidetwiddle %s", name);
3109 show_line(log_line, 0);
3112 /* while (*s != '\0' && *s != ' ') { */
3115 if (*s == '~' && pseudo_tilde != 0)
3116 *s = (char) pseudo_tilde; /* typically 254 */
3117 else if (*s == ' ' && pseudo_space != 0)
3118 *s = (char) pseudo_space; /* typically 255 */
3124 sprintf(log_line, "=> %s\n", name);
3125 show_line(log_line, 0);
3130 void deslash_all (int ac, char **av)
3132 char buffer[PATH_MAX];
3135 /* environment variables for output directories (as in PC TeX) */
3137 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3138 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3139 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3140 if ((s = grabenv("TEXFMT")) != NULL) fmt_directory = s;
3141 if ((s = grabenv("TEXPDF")) != NULL) pdf_directory = s;
3143 strcpy(buffer, av[0]); /* get path to executable */
3145 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3146 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3147 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3148 s = buffer + strlen(buffer) - 1;
3149 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3150 texpath = xstrdup(buffer);
3152 /* Hmm, we may be operating on DOS environment variables here !!! */
3154 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3155 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3156 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3157 if (strcmp(fmt_directory, "") != 0) flush_trailing_slash (fmt_directory);
3158 if (strcmp(pdf_directory, "") != 0) flush_trailing_slash (pdf_directory);
3162 unixify (texpath); /* 94/Jan/25 */
3163 /* if output directories given, deslashify them also 1993/Dec/12 */
3164 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3165 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3166 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3167 if (strcmp(fmt_directory, "") != 0) unixify(fmt_directory);
3168 if (strcmp(pdf_directory, "") != 0) unixify(pdf_directory);
3171 /* deslash TeX source file (and format, if format specified) */
3172 /* and check args to see whether format was specified */
3174 /* NOTE: assuming that command line arguments are in writable memory ! */
3175 /* if (trace_flag || debug_flag)
3176 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3177 /* if (optind < ac) { */ /* bkph */
3178 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3180 if (trace_flag || debug_flag) {
3181 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3182 optind, av[optind], ac);
3183 show_line(log_line, 0);
3185 unixify(av[optind]);
3187 if (pseudo_tilde != 0 || pseudo_space != 0)
3188 hidetwiddle (av[optind]); /* 95/Sep/25 */
3189 /* For Windows NT, lets allow + instead of & for format specification */
3190 if (*av[optind] == '&' || *av[optind] == '+') {
3191 format_spec = 1; /* format file specified */
3192 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3193 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3194 if (optind + 1 < ac) {
3196 if (trace_flag || debug_flag) {
3197 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3198 optind+1, av[optind+1], ac);
3199 show_line(log_line, 0);
3201 unixify(av[optind+1]);
3203 if (pseudo_tilde != 0 || pseudo_space != 0)
3204 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3210 /* The above seems to assume that arguments that don't start with '-' */
3211 /* are file names or format names - what if type in control sequences? */
3213 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3215 /* main entry point follows */
3217 /* this gets called pretty much right away in `main' in texmf.c */
3219 /* note: those optarg == 0 test don't really work ... */
3220 /* note: optarg starts at = in case of x=... */
3222 int main_init (int ac, char **av)
3224 char initbuffer[PATH_MAX];
3227 kpse_set_program_name(av[0], NULL);
3229 if (sizeof(memory_word) != 8) /* compile time test */
3231 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3232 show_line(log_line, 1);
3235 start_time = clock(); /* get time */
3236 main_time = start_time; /* fill in, in case file never opened */
3238 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3240 /* reset all allocatable memory pointers to NULL - in case we drop out */
3246 #ifdef ALLOCATESAVESTACK
3250 #ifdef ALLOCATEBUFFER
3251 buffer = NULL; /* new 1999/Jan/7 need to do early */
3252 current_buf_size = 0;
3253 buffer = realloc_buffer (initial_buf_size);
3268 log_opened = false; /* so can tell whether opened */
3269 interaction = -1; /* default state => 3 */
3270 missing_characters = 0; /* none yet! */
3271 workingdirectory = false; /* set from dviwindo.ini & command line */
3272 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3273 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3274 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3276 if (ac > 1 && !strncmp(av[1], "-Y", 2))
3277 reorder_arg_flag = false;
3279 if (reorder_arg_flag)
3280 reorderargs(ac, av);
3282 if (init_commands(ac, av))
3283 return -1; // failure
3285 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3289 source_direct = NULL;
3290 dvi_file_name = NULL;
3291 log_file_name = NULL;
3292 pdf_file_name = NULL;
3294 first_pass_count = 0;
3295 second_pass_count = 0;
3296 final_pass_count = 0;
3297 paragraph_failed = 0;
3304 closed_already=0; // so can only do once
3307 show_line("Entering init (local)\n", 0);
3309 /* Print version *after* banner ? */ /* does this get in log file ? */
3311 probe_memory(); /* show top address */
3312 ini_max_address = max_address; /* initial max address */
3315 show_maximums(stdout);
3319 deslash_all(ac, av); /* deslash and note if format specified */
3323 if (format_spec && mem_spec_flag)
3325 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3328 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3329 return -1; // if failed to allocate
3331 /* following is more or less useless since most all things not yet alloc */
3332 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3335 show_line("Leaving init (local)\n", 0);
3337 return 0; // success
3340 #define CLK_TCK CLOCKS_PER_SEC
3342 void show_inter_val (clock_t interval)
3344 int seconds, tenths, hundredth, thousands;
3346 if (interval >= CLK_TCK * 10)
3348 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3349 seconds = tenths / 10;
3350 tenths = tenths % 10;
3351 sprintf(log_line, "%d.%d", seconds, tenths);
3352 show_line(log_line, 0);
3355 if (interval >= CLK_TCK) /* 94/Feb/25 */
3357 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3358 seconds = hundredth / 100;
3359 hundredth = hundredth % 100;
3360 sprintf(log_line, "%d.%02d", seconds, hundredth);
3361 show_line(log_line, 0);
3364 if (interval > 0) /* 94/Oct/4 */
3366 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3367 seconds = thousands / 1000;
3368 thousands = thousands % 1000;
3369 sprintf(log_line, "%d.%03d", seconds, thousands);
3370 show_line(log_line, 0);
3373 show_line("0", 0); /* 95/Mar/1 */
3376 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3377 /* shows various times, warning about missing chars */
3379 int endit (int flag)
3381 finish_time = clock();
3383 if (missing_characters != 0)
3386 if (missing_characters)
3388 sprintf(log_line, "! There %s %d missing character%s --- see log file\n",
3389 (missing_characters == 1) ? "was" : "were", missing_characters,
3390 (missing_characters == 1) ? "" : "s");
3391 show_line(log_line, 0);
3394 if (free_memory() != 0)
3399 show_line("Total ", 0);
3400 show_inter_val(finish_time - start_time);
3401 show_line(" sec (", 0);
3402 show_inter_val(main_time - start_time);
3403 show_line(" format load + ", 0);
3404 show_inter_val(finish_time - main_time);
3405 show_line(" processing) ", 0);
3407 if (total_pages > 0)
3409 show_inter_val ((finish_time - main_time) / total_pages);
3410 show_line(" sec per page", 0);
3421 /********************************************************************************/
3423 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3425 #define MAXCOLUMN 78
3427 void print_cs_name (FILE *output, int h)
3431 memset(log_line, 0, sizeof(log_line));
3433 textof = hash[h].v.RH;
3438 c = sprintf(log_line, "(%d), ", h);
3441 memmove(log_line + c, str_pool + str_start[textof], n);
3442 memmove(log_line + c + n, "\n", 2);
3444 if (output == stderr)
3446 show_line(log_line, 1);
3450 if (output == stdout)
3451 show_line(log_line, 0);
3453 fprintf(output, log_line);
3458 int compare_strn (int, int, int, int); /* in tex9.c */
3460 /* compare two csnames in qsort */
3462 int compare_cs (const void *cp1, const void *cp2)
3464 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3468 textof1 = hash[c1].v.RH;
3469 textof2 = hash[c2].v.RH;
3470 l1 = length(textof1);
3471 l2 = length(textof2);
3472 k1 = str_start[textof1];
3473 k2 = str_start[textof2];
3475 return compare_strn (k1, l1, k2, l2);
3478 char *csused = NULL;
3480 /* Allocate table of indeces to allow sorting on csname */
3481 /* Allocate flags to remember which ones already listed at start */
3482 /* pass = 0 --> fmt */
3483 /* pass = 1 --> after */
3484 void print_cs_names (FILE *output, int pass)
3486 int h, k, ccount, repeatflag;
3488 int nfcs = frozen_control_sequence;
3490 if (pass == 0 && csused == NULL)
3492 csused = (char *) malloc (nfcs);
3498 memset(csused, 0, nfcs);
3500 for (h = 0; h < (hash_size + 780); h++)
3507 for (h = hash_base + 1; h < nfcs; h++)
3509 if (pass == 1 && csused[h])
3512 if (hash[h].v.RH != 0)
3521 sprintf(log_line, "\n%d %s multiletter control sequences:\n",
3522 ccount, (pass == 1) ? "new" : "");
3524 if (output == stderr)
3526 show_line(log_line, 1);
3530 if (output == stdout)
3531 show_line(log_line, 0);
3533 fprintf(output, log_line);
3536 if (ccount > 0) /* don't bother to get into trouble */
3538 cnumtable = (int *) malloc (ccount * sizeof(int));
3540 if (cnumtable == NULL)
3544 /* for (h = 515; h < (hash_size + 780); h++) { */
3545 for (h = hash_base + 1; h < nfcs; h++)
3547 if (pass == 1 && csused[h])
3550 if (hash[h].v.RH != 0)
3551 cnumtable[ccount++] = h;
3554 //qsort ((void *)cnumtable, ccount, sizeof (int), &compare_cs);
3558 for (k = 0; k < ccount; k++)
3562 if (pass == 1 && csused[h])
3565 print_cs_name(output, h);
3568 sprintf(log_line, "\n");
3570 if (output == stderr)
3572 show_line(log_line, 1);
3576 if (output == stdout)
3577 show_line(log_line, 0);
3579 fprintf(output, log_line);
3582 free((void *)cnumtable);
3585 if (pass == 1 && csused != NULL)
3592 /***************** font info listing moved from TEX9.C ******************/
3593 /* compare two strings in str_pool (not null terminated) */
3594 /* k1 and k2 are positions in string pool */
3595 /* l1 and l2 are lengths of strings */
3597 int compare_strn (int k1, int l1, int k2, int l2)
3601 while (l1 > 0 && l2 > 0)
3616 return 1; /* first string longer */
3618 return -1; /* second string longer */
3620 return 0; /* strings match */
3623 /* compare two font names and their at sizes in qsort */
3625 int compare_fnt (const void *fp1, const void *fp2)
3627 int f1, f2, l1, l2, k1, k2, s;
3631 l1 = length(font_name[f1]);
3632 l2 = length(font_name[f2]);
3633 k1 = str_start[font_name[f1]];
3634 k2 = str_start[font_name[f2]];
3636 s = compare_strn (k1, l1, k2, l2);
3641 if (font_size[f1] > font_size[f2])
3643 else if (font_size[f1] < font_size[f2])
3646 return 0; /* should not ever get here */
3649 /* compare two font names */
3651 int compare_fnt_name (int f1, int f2)
3653 int l1, l2, k1, k2, s;
3655 l1 = length(font_name[f1]);
3656 l2 = length(font_name[f2]);
3657 k1 = str_start[font_name[f1]];
3658 k2 = str_start[font_name[f2]];
3660 s = compare_strn (k1, l1, k2, l2);
3665 /* decode checksum information */
3667 unsigned long checkdefault = 0x59265920; /* default signature */
3669 int decode_fourty (unsigned long checksum, char *codingvector)
3673 /* char codingvector[6+1]; */
3677 strcpy(codingvector, "unknwn");
3681 if ((checksum >> 8) == (checkdefault >> 8)) /* last byte random */
3683 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3684 strcpy (codingvector, "fixed "); /* if not specified ... */
3685 return 1; /* no info available */
3689 for (k = 0; k < 6; k++)
3691 c = (int) (checksum % 40);
3692 checksum = checksum / 40;
3693 if (c <= 'z' - 'a') c = c + 'a';
3694 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3695 else if (c == 36) c = '-';
3696 else if (c == 37) c = '&';
3697 else if (c == 38) c = '_';
3698 else c = '.'; /* unknown */
3699 codingvector[5-k] = (char) c;
3701 codingvector[6] = '\0';
3703 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3704 return 0; /* encoding info returned in codingvector */
3707 double sclpnt (long x)
3711 pt = (double) x / 65536.0;
3712 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3717 // Shows list of fonts in log file
3719 void dvi_font_show(internal_font_number f, int suppressname)
3722 unsigned long checksum;
3723 char checksumvector[8];
3726 putc(' ', log_file);
3728 if (suppressname == 0)
3730 a = length(font_area[f]);
3731 l = length(font_name[f]);
3733 k = str_start[font_area[f]];
3735 memcpy(buffer, str_pool + k, length(font_area[f]));
3736 fwrite(buffer, sizeof(char), length(font_area[f]), log_file);
3738 k = str_start[font_name[f]];
3740 memcpy(buffer, str_pool + k, length(font_name[f]));
3741 fwrite(buffer, sizeof(char), length(font_name[f]), log_file);
3745 for (k = a + l; k < 16; k++)
3746 putc(' ', log_file);
3748 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3749 fputs(buffer, log_file);
3751 if (suppressname == 0)
3755 for (k = n; k < 16; k++)
3756 putc(' ', log_file);
3758 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 | font_check[f].b2) << 8 | font_check[f].b3;
3759 decode_fourty(checksum, checksumvector);
3760 fprintf(log_file, "encoding: %s..", checksumvector);
3763 putc('\n', log_file);
3766 /* Allocate table of indeces to allow sorting on font name */
3768 void show_font_info (void)
3770 int k, m, fcount, repeatflag;
3775 for (k = 1; k <= font_ptr; k++)
3782 fnumtable = (short *) malloc (fcount * sizeof(short));
3784 fprintf(log_file, "\nUsed %d font%s:\n", fcount, (fcount == 1) ? "" : "s");
3788 for (k = 1; k <= font_ptr; k++)
3790 fnumtable[fcount++] = (short) k;
3792 qsort ((void *)fnumtable, fcount, sizeof (short), &compare_fnt);
3796 for (m = 0; m < fcount; m++)
3800 if (compare_fnt_name(fnumtable[m-1], fnumtable[m]) == 0)
3806 dvi_font_show(fnumtable[m], repeatflag);
3809 free((void *)fnumtable);
3812 /* NOTE: current_tfm = false (-c)
3813 not checking for TFM in current directory saves 0.1 sec
3814 (0.2 if file_method = false (-G) */
3816 /* NOTE: test_dir_access = false (-b):
3817 not checking whether readable file is a directory saves maybe 0.5 sec
3818 BUT only if file_method = false (-G) - otherwise its irrelevant */
3820 /* NOTE: dir_method = false (-D) --- method for checking whether directory
3821 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
3822 BUT not if current_tfm = false (-c) */
3824 /* NOTE: file_method = false (-G) --- method for checking file accessible
3825 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
3827 /* Fast flag combinations: nothing, bG, bcG, bcDG */
3829 /* buffercopy no longer used */
3831 /* To Knuthian reset right when command line interpreted */