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)
31 #pragma warning(disable:4996)
32 #pragma warning(disable:4131) // old style declarator
33 #pragma warning(disable:4135) // conversion between different integral types
34 #pragma warning(disable:4127) // conditional expression is constant
42 /* Most Y & Y changes are localized here -- init() */
44 /* Note int main (int ac, char *av[]) is in texmf.c */
45 /* and that calls main_program = texbody in itex.c => initialize */
46 /* which in turn calls init here in local.c */
47 /* which then calls init_commands here in local.c */
49 #define USEOUREALLOC /* 96/Jan/20 */
51 #define USEMEMSET /* 98/Jan/23 */
53 /* #define PREALLOCHOLE */ /* make hole in heap at bottom debugging */
55 /* #define CHECKALIGNMENT */ /* reactivated 95/Jan/7 */
57 /* #define HEAPSHOW */ /* debugging 96/Jan/20 */
59 /* #ifdef TRYANDOPEN */ /* debugging only */
61 /* #define SHOWHEAPERROR */ /* debugging 96/Jan/10 */
64 /* #define HEAPWALK */ /* debugging 96/Oct/22 */
68 #define REALLOC ourrealloc
70 #define REALLOC realloc
74 #include <malloc.h> /* _msize, _expand, HEAPOK et.c */
75 #include <direct.h> /* for _getcwd() */
77 #pragma warning(disable:4032) // different type when promoted
79 #include <conio.h> /* for _getch() */
81 #pragma warning(default:4032) // different type when promoted`
84 /* Argument handling, etc. */ /* from common.h - setup `main' in texmf.c */
85 /* extern int gargc; */
86 /* extern char **gargv; */
90 /* appears in reverse order in EXE file */
92 char *compiletime = __TIME__;
93 char *compiledate = __DATE__;
94 char *www = "http://www.tug.org/yandy";
95 char *rights = "All Rights Reserved.";
96 char *copyright = "Copyright (C) 2007--2014 TeX Users Group.";
97 char *yandyversion = "2.2.3"; /* 00/Jun/18 */
98 char *application = "Y & Y TeX"; /* 96/Jan/17 */
99 char *tex_version = "This is TeX, Version 3.14159265"; /* change with upgrade */
101 /* #define COPYHASH 1890382 */
102 /* #define COPYHASH 13862905 */
103 /* #define COPYHASH 10558802 */
104 /* #define COPYHASH 7254699 */
105 /* #define COPYHASH 3950596 */
106 /* #define COPYHASH 646493 */
107 #define COPYHASH 12905299
109 clock_t start_time, main_time, finish_time;
111 char *dvi_directory = ""; /* user specified directory for dvi file */
112 char *log_directory = ""; /* user specified directory for log file */
113 char *aux_directory = ""; /* user specified directory for aux file */
115 char *texpath = ""; /* path to executable - used if env vars not set */
117 // #define MAXLINE 256
119 char log_line[MAXLINE]; // used also in tex9.c
121 int mem_spec_flag = 0; /* non-zero if `-m=...' was used */
122 int format_spec = 0; /* non-zero if a format specified on command line */
123 int closed_already = 0; /* make sure we don't try this more than once */
124 bool reorder_arg_flag = true; /* put command line flags/arguments first */
126 /* Mapping from Windows ANSI to DOS code page 850 96/Jan/20 */
127 /* Used in tex0.c with wintodos[c-128] */
129 unsigned char wintodos[128] = {
130 0, 0, 0, 159, 0, 0, 0, 0,
131 94, 0, 0, 0, 0, 0, 0, 0,
132 0, 96, 39, 0, 0, 7, 0, 0,
133 126, 0, 0, 0, 0, 0, 0, 0,
134 32, 173, 189, 156, 207, 190, 221, 21,
135 0, 184, 166, 174, 170, 45, 169, 0,
136 248, 241, 253, 252, 0, 230, 20, 250,
137 0, 251, 167, 175, 172, 171, 243, 168,
138 183, 181, 182, 199, 142, 143, 146, 128,
139 212, 144, 210, 211, 222, 214, 215, 216,
140 209, 165, 227, 224, 226, 229, 153, 158,
141 157, 235, 233, 234, 154, 237, 232, 225,
142 133, 160, 131, 198, 132, 134, 145, 135,
143 138, 130, 136, 137, 141, 161, 140, 139,
144 208, 164, 149, 162, 147, 228, 148, 246,
145 155, 151, 163, 150, 129, 236, 231, 152
148 void show_usage (char * program) {
151 %s [-?ivnwdrzpK] [-m=ini_mem] [-e=hyph_size] [-h=trie_size]\n\
152 \t[-x=xchr_file] [-k=key_file] [-o=dvi_dir] [-l=log_dir] [-a=aux_dir]\n\
153 \t[+format_file] [tex_file]\n\
157 -? show this usage summary\n\
158 -i start up as iniTeX (create format file)\n\
159 -v be verbose (show implementation version number)\n\
160 -n do not allow `non ASCII' characters in input files (complain instead)\n\
161 -w do not show `non ASCII' characters in hexadecimal (show as is)\n\
162 -d do not allow DOS style file names - i.e. do not convert \\ to /\n\
163 -r do not allow Mac style termination - i.e. do not convert \\r to \\n\n\
164 -p allow use of \\patterns after loading format (iniTeX only)\n\
165 -K disable all extensions to basic TeX\n\
166 -m initial main memory size in kilo words (iniTeX only)\n\
167 -e hyphenation exception dictionary size (iniTeX only)\n\
168 -h hyphenation pattern trie size (iniTeX only)\n\
169 -x use `non ASCII' character mapping (xchr[]) defined in file\n\
170 -k use `key replacement' defined in file\n\
171 -o write DVI file in specified directory (default current directory)\n\
172 -l write LOG file in specified directory (default current directory)\n\
173 -a write AUX file in specified directory (default current directory)");
175 show_line(log_line, 1);
177 uexit(1); // has this been setup yet ???
181 /* -z do not discard control-Z at end of input file (treat as character)\n\ */
183 /* -c prepend current directory (.) to TFM directory list\n\ */
184 /* -b check that files with read access are not actually directories\n\ */
186 /* \t-d\tallow DOS style file names - i.e. convert \\ to / \n\ */
187 /* \t\t(applies to file name and format file name, if present)\n\ */
188 /* \t-r\tallow Mac style line termination - i.e. convert \\r to \\n \n\ */
190 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
192 /* Sep 27 1990 => 1990 Sep 27 */
193 /* 012456789 0123456789 */
195 void scivilize (char * date)
199 strcpy (pyear, date + 7);
200 for (k = 5; k >= 0; k--) date[k + 5] = date[k];
201 for (k = 0; k < 4; k++) date[k] = pyear[k];
203 if (date[9] == ' ') date[9] = '0'; /* replace space by '0' */
207 /* Thu Sep 27 06:26:35 1990 => 1990 Sep 27 06:26:35 */
209 void lcivilize (char * date)
214 strcpy (pyear, date + 20);
215 for (k = 18; k >= 0; k--) date[k+1] = date[k];
216 /* date[20] = '\n'; */
217 /* date[21] = '\0'; */
219 for (k = 0; k < 4; k++) date[k] = pyear[k];
224 // void stamp_it (FILE *outfile)
225 // now writes result into given buffer
226 void stamp_it (char *s)
230 strcpy(date, compiledate);
232 sprintf(s, "%s %s ", application, yandyversion);
234 sprintf(s, "(compiled time: %s %s)", date, compiletime);
238 void stampcopy (char *s)
241 sprintf(s, "%s %s", copyright, www); /* 99/Oct/25 */
245 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
250 void read_xchr_sub (FILE *input)
252 char buffer[PATH_MAX];
253 int k, from, to, count = 0;
257 memset (xchr, NOTDEF, MAXCHRS); /* mark unused */
259 for (k = 0; k < MAXCHRS; k++) xchr[k]= -1; */ /* mark unused */
262 memset (xord, NOTDEF, MAXCHRS); /* mark unused */
264 for (k = 0; k < MAXCHRS; k++) xord[k]= -1; */ /* mark unused */
267 #ifdef ALLOCATEBUFFER
268 while (fgets(buffer, current_buf_size, input) != NULL)
270 while (fgets(buffer, sizeof(buffer), input) != NULL)
273 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
274 /* if (sscanf (buffer, "%d %d", &from, &to) < 2)
275 sprintf(log_line, "Do not understand: %s", buffer); */
276 from = (int) strtol (buffer, &s, 0);
277 to = (int) strtol (s, NULL, 0);
278 /* what if line is bad ? do we just get from = 0 and to = 0 ? */
279 if (from >= 0 && from < MAXCHRS && to >= 0 && to < MAXCHRS) {
280 if (xchr[from]== (unsigned char) NOTDEF)
281 xchr[from]= (unsigned char) to;
283 sprintf(log_line, "NOTE: %s collision: %d => %d, %d\n", "xchr", from, xchr[from], to);
284 show_line(log_line, 0);
286 if (xord[to]== NOTDEF)
287 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);
295 /* now fill in the gaps */ /* not clear this is a good idea ... */
296 for (k = 0; k < MAXCHRS; k++) {
297 if (xchr[k]== NOTDEF) { /* if it has not been filled */
298 if (xord[k]== NOTDEF) { /* see whether used already */
299 xchr[k]= (unsigned char) k; /* no, so make identity */
300 xord[k]= (unsigned char) k; /* no, so make identity */
304 xchr[NOTDEF]= NOTDEF; /* fixed point of mapping */
306 sprintf(log_line, "Read %d xchr[] pairs:\n", count);
307 show_line(log_line, 0);
308 for (k = 0; k < MAXCHRS; k++) {
309 if (xchr[k]!= NOTDEF) {
310 sprintf(log_line, "%d => %d\n", k, xchr[k]);
311 show_line(log_line, 0);
317 char *replacement[MAXCHRS]; /* pointers to replacement strings */
319 void read_repl_sub (FILE *input)
322 char buffer[PATH_MAX];
328 memset(replacement, 0, MAXCHRS * sizeof(replacement[ 0]));
330 for (k = 0; k < MAXCHRS; k++) replacement[k] = NULL;
333 while (fgets(buffer, PATH_MAX, input) != NULL) {
334 if (*buffer == '%' || *buffer == ';' || *buffer == '\n') continue;
335 if ((m = sscanf (buffer, "%d%n %s", &chrs, &n, &charname)) == 0)
338 if (*charname == '"') { /* deal with quoted string "..." */
341 while (*s != '"' && *s != '\0') s++; /* step up to " */
342 if (*s++ == '\0') continue; /* sanity check */
345 s++; /* is it "" perhaps ? */
346 if (*s != '"') break; /* no, end of string */
348 *t++ = *s++; /* copy over */
350 *t = '\0'; /* and terminate */
352 if (chrs >= 0 && chrs < MAXCHRS)
353 replacement[chrs] = xstrdup(charname);
355 /* presently the following can never get triggered */
356 /* which is good, because it is perhaps not right ... */
357 else if ((m = sscanf (buffer, "%d %d %d %d %d %d %d %d %d %d %d",
358 &chrs, charnum, charnum+1, charnum+2, charnum+3, charnum+4,
359 charnum+5, charnum+6, charnum+7, charnum+8, charnum+9)) > 1) {
360 /* for (k = 0; k < n-1; k++) charname[k] = (char) charnum; */
361 for (k = 0; k < n-1; k++) charname[k] = (char) charnum[k];
363 if (chrs >= 0 && chrs < MAXCHRS)
364 replacement[chrs] = xstrdup(charname);
367 sprintf(log_line, "ERROR: don't understand %s", buffer);
368 show_line(log_line, 1);
371 if (trace_flag) { /* debugging output */
372 show_line("Key replacement table\n", 0);
373 for (k = 0; k < MAXCHRS; k++) {
374 if (replacement[k] != NULL) {
375 sprintf(log_line, "%d\t%s\n", k, replacement[k]);
376 show_line(log_line, 0);
382 /* Following used both to read xchr[] file and key replacement file */
383 /* the flag is 0 for -x=... and the flag is 1 for -k=... */
385 int read_xchr_file (char *filename, int flag, char *argv[])
388 char infile[PATH_MAX];
391 if (filename == NULL) return -1;
393 sprintf(log_line, "Reading xchr/repl %s\n", filename);
394 show_line(log_line, 0);
397 /* first try using file as specified */
398 strcpy(infile, filename);
400 sprintf(log_line, "Trying %s\n", infile);
401 show_line(log_line, 0);
403 if (share_flag == 0) input = fopen (infile, "r");
404 else input = _fsopen (infile, "r", share_flag); /* 94/July/12 */
406 if (strrchr(infile, '.') == NULL) {
407 if (flag == 0) strcat(infile, ".map");
408 else strcat(infile, ".key");
410 sprintf(log_line, "Trying %s\n", infile);
411 show_line(log_line, 0);
413 if (share_flag == 0) input = fopen (infile, "r");
414 else input = _fsopen (infile, "r", share_flag); /* 94/July/12 */
418 /* strcpy (infile, gargv[0]); */ /* try TeX program path */
419 strcpy (infile, argv[0]); /* try TeX program path */
420 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
421 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
422 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
423 strcat (infile, filename);
425 sprintf(log_line, "Trying %s\n", infile);
426 show_line(log_line, 0);
428 if (share_flag == 0) input = fopen (infile, "r");
429 else input = _fsopen (infile, "r", share_flag); /* 94/July/12 */
431 if (strchr(infile, '.') == NULL) {
432 if (flag == 0) strcat(infile, ".map");
433 else strcat(infile, ".key");
435 sprintf(log_line, "Trying %s\n", infile);
436 show_line(log_line, 0);
438 if (share_flag == 0) input = fopen (infile, "r");
439 else input = _fsopen (infile, "r", share_flag); /* 94/July/12 */
443 if (input == NULL) { /* 97/July/31 */
444 /* strcpy (infile, gargv[0]); */ /* try TeX program path\keyboard */
445 strcpy (infile, argv[0]); /* try TeX program path */
446 if ((s = strrchr (infile, '\\')) != NULL) *(s+1) = '\0';
447 else if ((s = strrchr (infile, '/')) != NULL) *(s+1) = '\0';
448 else if ((s = strrchr (infile, ':')) != NULL) *(s+1) = '\0';
449 strcat (infile, "keyboard\\");
450 strcat (infile, filename);
452 sprintf(log_line, "Trying %s\n", infile);
453 show_line(log_line, 0);
455 if (share_flag == 0) input = fopen (infile, "r");
456 else input = _fsopen (infile, "r", share_flag);
458 if (strchr(infile, '.') == NULL) {
459 if (flag == 0) strcat(infile, ".map");
460 else strcat(infile, ".key");
462 sprintf(log_line, "Trying %s\n", infile);
463 show_line(log_line, 0);
465 if (share_flag == 0) input = fopen (infile, "r");
466 else input = _fsopen (infile, "r", share_flag);
470 /* Note: can't look in TeX source file dir, since that is not known yet */
472 sprintf(log_line, "ERROR: Sorry, cannot find %s file %s",
473 flag ? " xchr[]" : "key mapping", filename);
474 show_line(log_line, 1);
475 perrormod (filename);
480 read_xchr_sub (input);
482 read_repl_sub (input);
484 (void) fclose (input);
488 /* need to also set `key_replace' here based on command line */
489 /* need to also allocate `buffercopy' here and free at end */
490 /* need to call `readreplace' in appropriate place */
492 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
494 /* Following may be useful if link without floating point emulation */
497 void testfloating (void) {
498 /* double x = 1.0; */
499 /* double dx = DBL_EPSILON; */
503 /* while (x + dx != 1.0) { */
504 while (1.0 + dx != 1.0) {
509 sprintf(log_line, "Floating test: dx = %lg (k = %d)\n", dxold, k - 1);
510 show_line(log_line, 0);
514 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
516 char *debugfile; /* NULL or name of file to try and open */
519 char *heapstrings[] = {
520 "", "Empty", "OK", "Bad Begin", "Bad Node", "End", "Bad Pointer"
524 /* Attempt to get at problem with eqtb ... temporarily abandoned */
527 void check_eqtb (char *act) {
529 memory_word *eqtb = zeqtb;
530 /* for (k = 10280 + hash_extra; k < 10280 + eqtb_extra; k++) { */
531 for (k = hash_size + 780 + hash_extra; k < hash_size + 780 + eqtb_extra; k++) {
532 if (eqtb[k].cint != 0) {
535 show_line("EQTB ", 0);
537 sprintf(log_line, "%d ", k);
538 show_line(log_line, 0);
539 if (count++ > 256) break;
542 if (count != 0) show_char('\n');
546 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
550 /* ad hoc default minimum growth in memory realloc is 62% */
551 /* golden ratio (1 + \sqrt{5}) / 2 = 1.618033989... */
552 int percent_grow = 62; /* default minimum growth in memory realloc is 62% */
553 int total_allocated = 0; /* total memory allocated so far */
554 int ini_max_address = 0; /* maximum address when starting */
555 int max_address = 0; /* maximum address seen in allocated memory */
559 // DON'T USE THIS in DLL VERSION
563 unsigned int heapthreshold=0; /* smallest size block interested in ... */
565 unsigned int heap_dump (FILE *output, int verbose)
567 unsigned int total=0;
568 struct _heapinfo hinfo;
573 if (verbose) fprintf(output, "HEAP DUMP:\n");
575 /* if ((n = _heapchk ()) != _HEAPOK) { */
581 fprintf(stderr, "WARNING: Heap corrupted (%d)\n", n);
583 fprintf(stderr, "HEAP %s (%s)\n", heapstrings[-n], "heap_dump");
586 hinfo._pentry = NULL;
587 while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) {
588 if (end_block > 0 && (int) hinfo._pentry > end_block + 1024) {
589 // if (verbose) printf("GAP of %d bytes!\n", (int) hinfo._pentry - end_block);
591 end_block = (int) hinfo._pentry + hinfo._size;
592 if (hinfo._useflag == _USEDENTRY) total += hinfo._size;
593 if (hinfo._size >= heapthreshold && verbose)
594 fprintf(output, "%6s block at %p (%7d) of size %6X (%7d) => (%7d)\n",
595 (hinfo._useflag == _USEDENTRY ? "USED" : "...."),
596 hinfo._pentry, hinfo._pentry, hinfo._size, hinfo._size,
599 switch (heapstatus) {
601 if (verbose) fprintf(output, "OK - empty heap\n");
604 if (verbose) fprintf(output, "OK - end of heap (%u bytes used)\n", total);
607 fprintf(output, "ERROR - %s\n", "bad pointer to heap");
610 fprintf(output, "ERROR - %s\n", "bad start of heap");
613 fprintf(output, "ERROR - %s\n", "bad node in heap");
621 void show_maximums (FILE *output)
624 unsigned heaptotal=0; /* no longer used */
625 heaptotal = heap_dump(stdout, 0); /* 94/Apr/3 */
627 sprintf(log_line, "Max allocated %d --- max address %d\n", total_allocated, max_address);
628 // if (output != NULL) fputs(log_line, output); // log file
629 // else if (flag == 0) show_line(log_line, 0); // informative
630 // else if (flag == 1) show_line(log_line, 1); // error
631 if (output == stderr) show_line(log_line, 1);
632 else if (output == stdout) show_line(log_line, 0);
633 else fputs(log_line, output);
636 /* our own version of realloc --- avoid supposed MicroSoft version bug */
637 /* also tries _expand first, which can avoid address growth ... */
640 void *ourrealloc (void *old, size_t new_size)
643 size_t old_size, overlap;
645 /* round up to nearest multiple of four bytes *//* avoid unlikely alignment */
646 if ((new_size % 4) != 0) new_size = ((new_size / 4) + 1) * 4;
648 if (old == NULL) return malloc (new_size); /* no old block - use malloc */
650 old_size = _msize (old);
651 if (old_size >= new_size && old_size < new_size + 4) return old;
652 /* _heapmin(); */ /* release unused heap space to the system - no op ? */
655 show_line("BEFORE REALLOC: \n", 0);
657 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
661 mnew = _expand (old, new_size); /* first try and expand in place */
664 sprintf(log_line, "EXPANDED! %d (%d) == %d (%d)\n",
665 mnew, new_size, old, old_size);
666 show_line(log_line, 0);
670 /* *********************************************************************** */
671 /* do this if you want to call the real realloc next - */
672 mnew = realloc (old, new_size);
675 show_line("AFTER REALLOC: \n", 0);
677 (void) heap_dump(stdout, 1); /* debugging 96/Jan/18 */
681 if (mnew != NULL) return mnew;
682 /* we are screwed typically if we ever drop through here - no more space */
683 /* *********************************************************************** */
684 mnew = malloc (new_size); /* otherwise find new space */
685 if (mnew == NULL) return mnew; /* if unable to allocate */
686 if (old_size < new_size) overlap = old_size;
687 else overlap = new_size;
688 memcpy (mnew, old, overlap); /* copy old data to new area */
689 free(old); /* free the old area */
694 void memory_error (char *s, int n)
697 fprintf(log_file, "\n! Unable to allocate %d bytes for %s\n", n, s);
698 show_maximums(log_file);
700 if (heap_flag) (void) heap_dump(log_file, 1);
703 sprintf(log_line, "\n! Unable to allocate %d bytes for %s\n", n, s);
704 show_line(log_line, 1);
705 show_maximums(stderr);
707 if (heap_flag) (void) heap_dump(stderr, 1);
709 /* exit (1); */ /* 94/Jan/22 */
710 /* return to let TeX do its thing (such as complain about runaway) */
711 /* don't set abort_flag here */
714 void trace_memory (char *s, int n)
716 sprintf(log_line, "Allocating %d bytes for %s\n", n, s);
717 show_line(log_line, 0);
720 void update_statistics (int address, int size, int oldsize)
722 if (address + size > max_address) max_address = address + size;
723 total_allocated = total_allocated + size - oldsize;
726 void probe_memory (void)
729 s = (char *) malloc (4); /* get current top address */
731 update_statistics ((int) s, 0, 0); /* show where we are */
734 void probe_show (void)
737 show_maximums(stdout);
739 if (heap_flag) (void) heap_dump(stdout, 1);
743 size_t roundup (size_t n)
745 if ((n % 4) == 0) return n;
746 else return ((n / 4) + 1) * 4;
750 /* using allocating hyphenation trie slows things down maybe 1% */
751 /* but saves typically (270k - 55k) = 215k of memory */
752 /* NOTE: it's safe to allocate based on the trie_max read from fmt file */
753 /* since hyphenation trie cannot be extended (after iniTeX) */
754 /* for iniTeX, however, we need to allocate the full trie_size ahead of time */
756 /* NOTE: we don't ever reallocate these */
757 /* returns -1 if it fails */
759 int allocate_tries (int trie_max)
762 /* if (trie_max > trie_size) {
763 sprintf(log_line, "ERROR: invalid trie size (%d > %d)\n",
764 trie_max, trie_size);
765 show_line(log_line, 1);
767 } */ /* ??? removed 1993/dec/17 */
768 if (trie_max > 1000000) trie_max = 1000000; /* some sort of sanity limit */
769 /* important + 1 because original was halfword trie_trl[trie_size + 1] etc. */
770 nl = (trie_max + 1) * sizeof(halfword); /* trie_trl[trie_size + 1] */
771 no = (trie_max + 1) * sizeof(halfword); /* trie_tro[trie_size + 1] */
772 nc = (trie_max + 1) * sizeof(quarterword); /* trie_trc[trie_size + 1] */
774 if (trace_flag) trace_memory("hyphen trie", n);
775 trie_trl = (halfword *) malloc (roundup(nl));
776 trie_tro = (halfword *) malloc (roundup(no));
777 trie_trc = (quarterword *) malloc (roundup(nc));
778 if (trie_trl == NULL || trie_tro == NULL || trie_trc == NULL) {
779 memory_error("hyphen trie", n);
783 sprintf(log_line, "Addresses trie_trl %d trie_tro %d trie_trc %d\n", trie_trl, trie_tro, trie_trc);
784 show_line(log_line, 0);
786 update_statistics ((int) trie_trl, nl, 0);
787 update_statistics ((int) trie_tro, no, 0);
788 update_statistics ((int) trie_trc, nc, 0);
789 /* sprintf(log_line, "trie_size %d trie_max %d\n", trie_size, trie_max); */ /* debug */
790 trie_size = trie_max; /* BUG FIX 98/Jan/5 */
791 if (trace_flag) probe_show (); /* 94/Mar/25 */
796 #ifdef ALLOCATEHYPHEN
797 bool prime (int); /* test function later in this file */
799 int currentprime = 0; /* remember in case reallocated later */
801 /* we don't return an address here, since TWO memory regions allocated */
802 /* plus, we don't really reallocate, we FLUSH the old information totally */
803 /* returns -1 if it fails */
805 int realloc_hyphen (int hyphen_prime)
808 if (!prime(hyphen_prime)) {
809 sprintf(log_line, "ERROR: non-prime hyphen exception number (%d)\n", hyphen_prime);
810 show_line(log_line, 1);
814 /* need not/cannot preserve old contents when hyphen prime is changed */
815 /* if (hyph_list != NULL) free(hyph_list); */
816 /* if (hyph_word != NULL) free(hyph_word); */
817 /* important + 1 since str_number hyph_word[hyphen_prime + 1] in original etc. */
818 nw = (hyphen_prime + 1) * sizeof(str_number);
819 nl = (hyphen_prime + 1) * sizeof(halfword);
821 if (trace_flag) trace_memory("hyphen exception", n);
822 /* initially hyph_word will be NULL so this acts like malloc */
823 /* hyph_word = (str_number *) malloc (nw); */
824 hyph_word = (str_number *) REALLOC (hyph_word, nw); /* 94/Mar/24 */
825 /* initially hyph_list will be NULL so this acts like malloc */
826 /* hyph_list = (halfword *) malloc (nl); */
827 hyph_list = (halfword *) REALLOC (hyph_list, nl); /* 94/Mar/24 */
828 if (hyph_word == NULL || hyph_list == NULL) {
829 memory_error("hyphen exception", n);
833 sprintf(log_line, "Addresses hyph_word %d hyph_list %d\n",
834 hyph_word, hyph_list);
835 show_line(log_line, 0);
837 /* cannot preserve old contents when hyphen prime is changed */
839 memset(hyph_word, 0, (hyphen_prime + 1) * sizeof (hyph_word[0]));
841 for (k = 0; k <= hyphen_prime; k++) hyph_word[k]= 0;
844 memset(hyph_list, 0, (hyphen_prime + 1) * sizeof (hyph_list[0]));
846 for (k = 0; k <= hyphen_prime; k++) hyph_list[k]= 0;
848 hyph_count = 0; /* or use reset_hyphen() in itex.c */
849 if (currentprime != 0) {
850 update_statistics ((int) hyph_word, nw,
851 (currentprime + 1) * sizeof(str_number));
852 update_statistics ((int) hyph_list, nl,
853 (currentprime + 1) * sizeof(halfword));
856 update_statistics ((int) hyph_word, nw, 0);
857 update_statistics ((int) hyph_list, nl, 0);
859 currentprime = hyphen_prime;
860 if (trace_flag) probe_show (); /* 94/Mar/25 */
865 int current_mem_size=0; /* current total words in main mem allocated -1 */
867 /* this gets called from itex.c when it figures out what mem_top is */
868 /* or gets called from here when in ini_TeX mode */ /* and nowhere else */
869 /* initial allocation only, may get expanded later */
870 /* NOTE: we DON't use ALLOCATEHIGH & ALLOCATELOW anymore */
871 /* returns NULL if it fails */
874 /* initial main memory alloc - mem_top */
875 memory_word *allocate_main_memory (int size)
879 /* Using -i *and* pre-loading format */ /* in this case get called twice */
880 /* Get rid of initial blank memory again or use realloc ... */
881 /* Could we avoid this by detecting presence of & before allocating ? */
882 /* Also, if its already large enough, maybe we can avoid this ? */
883 /* don't bother if current_mem_size == mem_max - mem_start ? */
884 if (mainmemory != NULL) {
885 /* free(mainmemory); */
886 /* mainmemory = NULL; */
887 if (trace_flag) show_line("Reallocating initial memory allocation\n", 1);
888 /* if (mem_spec_flag)
889 show_line("Cannot change initial main memory size when format is read\n", 1);*/
892 mem_top = mem_bot + size;
893 #ifdef ALLOCATEHIGH /* NOT USED ANYMORE */
894 if (mem_extra_high != 0 && !is_initex) mem_max = mem_top + mem_extra_high;
897 #ifdef ALLOCATELOW /* NOT USED ANYMORE */
898 if (mem_extra_low != 0 && !is_initex)
899 mem_start = mem_bot - mem_extra_low; /* increase main memory */
901 mem_start = 0; /* bottom of memory allocated by system */
902 /* mem_min = mem_start; */ /* bottom of area made available to TeX */
903 mem_min = 0; /* bottom of area made available to TeX */
904 n = (mem_max - mem_start + 1) * sizeof (memory_word); /* 256k * 8 = 2000 k */
905 if (trace_flag) trace_memory("main memory", n);
906 /* mainmemory = (memory_word *) malloc (n); */ /* 94/March/24 */
907 /* normally mainmemory == NULL here so acts like malloc ... */
908 mainmemory = (memory_word *) REALLOC (mainmemory, n);
909 if (mainmemory == NULL) {
910 memory_error("initial main memory", n);
911 // exit (1); /* serious error */
915 sprintf(log_line, "Address main memory == %d\n", mainmemory);
916 show_line(log_line, 0);
919 if (mem_start != 0 && !is_initex) zzzaa = mainmemory - mem_start;
921 sprintf(log_line, "Offset address main memory == %d\n", zzzaa);
922 show_line(log_line, 0);
924 update_statistics ((int) mainmemory, n,
925 (current_mem_size + 1) * sizeof (memory_word));
926 /* current_mem_size = (mem_max - mem_start + 1); */
927 current_mem_size = mem_max - mem_start; /* total number of words - 1 */
928 if (trace_flag) probe_show (); /* 94/Mar/25 */
929 return zzzaa; /* same as zmem, mem 94/Jan/24 */
931 #endif /* end of ALLOCATEMAIN */
934 /* int firstallocation = 1; */
936 /* increase main memory allocation at low end and high end */
937 /* called only from tex0.c *//* called with one of losize or hisize == 0 */
938 /* returns NULL if it fails */
940 memory_word *realloc_main (int losize, int hisize)
943 int newsize=0; /* to quieten compiler */
944 int n=0; /* to quieten compiler */
945 memory_word *newmemory=NULL; /* to quieten compiler */
947 /* if (losize == 0 && hisize > 0) runawayflag = 1;
948 else runawayflag = 0; */ /* 94/Jan/22 */
951 sprintf(log_line, "WARNING: Entering realloc_main lo %d hi %d\n", losize, hisize);
952 show_line(log_line, 0);
955 show_line("ERROR: Cannot extent main memory in iniTeX\n", 1);
957 show_line("Please use `-m=...' on command line\n", 0);
958 // abort_flag++; // ???
962 sprintf(log_line, "Old Address %s == %d\n", "main memory", mainmemory);
963 show_line(log_line, 0);
965 if (current_mem_size + 1 == max_mem_size) {/* if we REALLY run up to limit ! */
966 memory_error("main memory", (max_mem_size + 1) * sizeof(memory_word));
967 // abort_flag++; // ???
970 /* first allocation should expand *both* lo and hi */
971 if (hisize == 0 && mem_end == mem_max) hisize = losize;
972 if (losize == 0 && mem_start == mem_min) losize = hisize;
973 /* try and prevent excessive frequent reallocations */
974 /* while avoiding over allocation by too much */
975 minsize = current_mem_size / 100 * percent_grow;
976 if (losize + hisize < minsize) {
977 if (losize > 0 && hisize > 0) {
978 losize = minsize / 2;
979 hisize = minsize / 2;
981 else if (losize > 0) losize = minsize;
982 else if (hisize > 0) hisize = minsize;
984 if (losize > 0 && losize < mem_top / 2) losize = mem_top / 2;
985 if (hisize > 0 && hisize < mem_top / 2) hisize = mem_top / 2;
987 for (k = 0; k < MAXSPLITS; k++) {
988 newsize = current_mem_size + losize + hisize;
989 if (newsize >= max_mem_size) { /* bump against limit - ha ha ha */
990 while (newsize >= max_mem_size) {
991 losize = losize / 2; hisize = hisize / 2;
992 newsize = current_mem_size + losize + hisize;
995 n = (newsize + 1) * sizeof (memory_word);
996 if (trace_flag) trace_memory("main memory", n);
997 newmemory = (memory_word *) REALLOC (mainmemory, n);
998 if (newmemory != NULL) break; /* did we get it ? */
999 if (current_mem_size == 0) break; /* in case we ever use for initial */
1000 losize = losize / 2; hisize = hisize / 2;
1003 if (newmemory == NULL) {
1004 memory_error("main memory", n);
1005 return zzzaa; /* try and continue with TeX !!! */
1008 sprintf(log_line, "New Address %s == %d\n", "main memory", newmemory);
1009 show_line(log_line, 0);
1012 /* shift everything upward to make space for new low area */
1014 sprintf(log_line, "memmove %d %d %d \n", newmemory + losize,
1015 newmemory, (current_mem_size + 1) * sizeof(memory_word));
1016 show_line(log_line, 0);
1018 memmove (newmemory + losize, newmemory,
1019 /* current_mem_size * sizeof(memory_word)); */
1020 (current_mem_size + 1) * sizeof(memory_word));
1021 /* could reduce words moved by (mem_max - mem_end) */
1023 mainmemory = newmemory; /* remember for free later */
1024 if (losize > 0) mem_start = mem_start - losize; /* update lower limit */
1025 if (hisize > 0) mem_max = mem_max + hisize; /* update upper limit */
1026 update_statistics ((int) mainmemory, n,
1027 (current_mem_size + 1) * sizeof (memory_word));
1028 current_mem_size = newsize;
1029 if (current_mem_size != mem_max - mem_start) {
1030 show_line("ERROR: Impossible Memory Error\n", 1);
1032 if (mem_start != 0) zzzaa = mainmemory - mem_start; /* ??? sign ??? */
1033 else zzzaa = mainmemory;
1034 if (trace_flag) probe_show (); /* 94/Mar/25 */
1040 /* font_mem_size = 10000L ==> font_info array 100k * 8 = 800 kilobytes */
1042 int current_font_mem_size=0;
1044 /* fmemoryword can be either halfword or memory_word */
1045 fmemoryword *realloc_font_info (int size)
1046 { /* number of memorywords */
1047 fmemoryword *newfontinfo=NULL;
1049 int newsize=0; /* to quieten compiler */
1050 int n=0; /* to quieten compiler */
1053 sprintf(log_line, "Old Address %s == %d\n", "font_info", font_info);
1054 show_line(log_line, 0);
1056 /* during initial allocation, font_info == NULL - realloc acts like malloc */
1057 /* during initial allocation current_font_mem_size == 0 */
1058 if (current_font_mem_size == font_mem_size) { /* if we REALLY run up to limit */
1059 /* memory_error("font", (font_mem_size + 1) * sizeof(memory_word)); */
1060 return font_info; /* pass it back to TeX 99/Fabe/4 */
1062 /* try and prevent excessive frequent reallocations */
1063 /* while avoiding over allocation by too much */
1064 /* minsize = current_font_mem_size / 2; */
1065 minsize = current_font_mem_size / 100 * percent_grow;
1066 if (size < minsize) size = minsize;
1067 if (size < initial_font_mem_size) size = initial_font_mem_size;
1069 for (k=0; k < MAXSPLITS; k++) {
1070 newsize = current_font_mem_size + size;
1071 if (newsize > font_mem_size) newsize = font_mem_size; /* bump against limit */
1072 /* important + 1 since fmemoryword font_info[font_mem_size + 1] original */
1073 n = (newsize + 1) * sizeof (fmemoryword);
1074 if (trace_flag) trace_memory("font_info", n);
1075 newfontinfo = (fmemoryword *) REALLOC (font_info, n);
1076 if (newfontinfo != NULL) break; /* did we get it ? */
1077 if (current_font_mem_size == 0) break; /* initial allocation must work */
1081 if (newfontinfo == NULL) {
1082 memory_error("font", n);
1083 return font_info; /* try and continue !!! */
1085 font_info = newfontinfo;
1087 sprintf(log_line, "New Address %s == %d\n", "font_info", font_info);
1088 show_line(log_line, 0);
1090 update_statistics ((int) font_info, n, current_font_mem_size * sizeof(fmemoryword));
1091 current_font_mem_size = newsize;
1092 if (trace_flag) probe_show (); /* 94/Mar/25 */
1097 #ifdef ALLOCATESTRING
1098 int current_pool_size=0;
1100 packed_ASCII_code *realloc_str_pool (int size)
1105 packed_ASCII_code *newstrpool=NULL;
1108 sprintf(log_line, "Old Address %s == %d\n", "string pool", str_pool);
1109 show_line(log_line, 0);
1111 if (current_pool_size == pool_size) {
1112 /* memory_error ("string pool", (pool_size + 1) * sizeof(packed_ASCII_code)); */
1114 return str_pool; /* pass it back to TeX 99/Fabe/4 */
1116 /* minsize = current_pool_size / 2; */
1117 minsize = current_pool_size / 100 * percent_grow;
1118 if (size < minsize) size = minsize;
1119 if (size < initial_pool_size) size = initial_pool_size;
1121 for (k = 0; k < MAXSPLITS; k++) {
1122 newsize = current_pool_size + size;
1123 if (newsize > pool_size) newsize = pool_size;
1124 /* important + 1 since packed_ASCII_code str_pool[pool_size + 1]; in original */
1125 n = (newsize + 1) * sizeof (packed_ASCII_code);
1126 if (trace_flag) trace_memory("str_pool", n);
1127 newstrpool = (packed_ASCII_code *) REALLOC (str_pool, n); /* 95/Sep/24 */
1128 if (newstrpool != NULL) break; /* did we get it ? */
1129 if (current_pool_size == 0) break; /* initial allocation must work */
1130 size = size / 2; /* else can retry smaller */
1133 if (newstrpool == NULL) {
1134 memory_error("string pool", n);
1135 return str_pool; /* try and continue !!! */
1137 str_pool = newstrpool;
1138 update_statistics ((int) str_pool, n, current_pool_size);
1139 current_pool_size = newsize;
1141 sprintf(log_line, "New Address %s == %d\n", "string pool", str_pool);
1142 show_line(log_line, 0);
1144 if (trace_flag) probe_show (); /* 94/Mar/25 */
1149 #ifdef ALLOCATESTRING
1150 int current_max_strings=0;
1152 pool_pointer *realloc_str_start (int size)
1157 pool_pointer *newstrstart=NULL;
1160 sprintf(log_line, "Old Address %s == %d\n", "string start", str_start);
1161 show_line(log_line, 0);
1163 if (current_max_strings == max_strings) {
1164 /* memory_error ("string pointer", (max_strings + 1) * sizeof(pool_pointer)); */
1166 return str_start; /* pass it back to TeX 99/Fabe/4 */
1168 /* minsize = current_max_strings / 2; */
1169 minsize = current_max_strings / 100 * percent_grow;
1170 if (size < minsize) size = minsize;
1171 if (size < initial_max_strings) size = initial_max_strings;
1173 for (k = 0; k < MAXSPLITS; k++) {
1174 newsize = current_max_strings + size;
1175 if (newsize > max_strings) newsize = max_strings;
1176 /* important + 1 since str_start[maxstring + 1] originally */
1177 n = (newsize + 1) * sizeof (pool_pointer);
1178 if (trace_flag) trace_memory("str_start", n);
1179 newstrstart = (pool_pointer *) REALLOC (str_start, n);
1180 if (newstrstart != NULL) break; /* did we get it ? */
1181 if (current_max_strings == 0) break; /* initial allocation must work */
1182 size = size / 2; /* otherwise can try smaller */
1185 if (newstrstart == NULL) {
1186 memory_error("string pointer", n);
1187 return str_start; /* try and continue */
1189 str_start = newstrstart;
1190 update_statistics((int) str_start, n, current_max_strings * sizeof (pool_pointer));
1191 current_max_strings = newsize;
1193 sprintf(log_line, "New Address %s == %d\n", "string start", str_start);
1194 show_line(log_line, 0);
1196 if (trace_flag) probe_show (); /* 94/Mar/25 */
1203 /* returns -1 if it fails */
1205 int allocate_ini (int size)
1206 { /* size == trie_size */
1207 int n, nl, no, nc, nr, nh, nt;
1208 nh = nr = nl = (size + 1) * sizeof(trie_pointer);
1209 no = (size + 1) * sizeof(trie_op_code);
1210 nc = (size + 1) * sizeof(packed_ASCII_code);
1211 /* nt = (size + 1) * sizeof(bool); */
1212 nt = (size + 1) * sizeof(char);
1213 n = nl + no + nc + nr + nh + nt;
1214 /* n = (size + 1) * (sizeof(packed_ASCII_code) + sizeof(trie_op_code) +
1215 3 * sizeof(trie_pointer) + sizeof (char)); */
1216 if (trace_flag) trace_memory ("iniTeX hyphen trie", n);
1217 trie_l = (trie_pointer *) malloc (roundup(nl));
1218 trie_o = (trie_op_code *) malloc (roundup(no));
1219 trie_c = (packed_ASCII_code *) malloc (roundup(nc));
1220 trie_r = (trie_pointer *) malloc (roundup(nr));
1221 trie_hash = (trie_pointer *) malloc (roundup(nh));
1222 /* trie_taken = (bool *) malloc (nt); */
1223 trie_taken = (char *) malloc (roundup(nt));
1224 if (trie_c == NULL || trie_o == NULL || trie_l == NULL || trie_r == NULL ||
1225 trie_hash == NULL || trie_taken == NULL) {
1226 memory_error("iniTeX hyphen trie", n);
1227 // exit (1); /* serious error */
1231 sprintf(log_line, "Addresses trie_l %d trie_o %d trie_c %d\n",
1232 trie_l, trie_o, trie_c);
1233 show_line(log_line, 0);
1234 sprintf(log_line, "Addresses trie_r %d trie_hash %d trie_taken %d\n",
1235 trie_r, trie_hash, trie_taken);
1236 show_line(log_line, 0);
1238 update_statistics ((int) trie_l, nl, 0);
1239 update_statistics ((int) trie_o, no, 0);
1240 update_statistics ((int) trie_c, nc, 0);
1241 update_statistics ((int) trie_r, nr, 0);
1242 update_statistics ((int) trie_hash, nh, 0);
1243 update_statistics ((int) trie_taken, nt, 0);
1244 /* trie_size = size; */ /* ??? */
1245 if (trace_flag) probe_show (); /* 94/Mar/25 */
1246 return 0; // success
1250 #ifdef ALLOCATESAVESTACK
1251 int current_save_size=0;
1253 memory_word *realloc_save_stack (int size)
1257 memory_word *newsave_stack=NULL;
1260 sprintf(log_line, "Old Address %s == %d\n", "save stack", save_stack);
1261 show_line(log_line, 0);
1263 if (current_save_size == save_size) { /* arbitrary limit */
1264 /* memory_error ("save stack", (save_size + 1) * sizeof(memory_word)); */
1266 return save_stack; /* let TeX handle the error */
1268 minsize = current_save_size / 100 * percent_grow;
1269 if (size < minsize) size = minsize;
1270 if (size < initial_save_size) size = initial_save_size;
1272 for (k = 0; k < MAXSPLITS; k++) {
1273 newsize = current_save_size + size;
1274 if (newsize > save_size) newsize = save_size;
1275 n = (newsize + 1) * sizeof (memory_word); /* save_stack[save_size + 1] */
1276 if (trace_flag) trace_memory("save_stack", n);
1277 newsave_stack = (memory_word *) REALLOC (save_stack, n);
1278 if (newsave_stack != NULL) break; /* did we get it ? */
1279 if (current_save_size == 0) break; /* initial allocation must work */
1280 size = size / 2; /* else can retry smaller */
1283 if (newsave_stack == NULL) {
1284 memory_error("save stack", n);
1285 return save_stack; /* try and continue !!! */
1287 save_stack = newsave_stack;
1288 update_statistics ((int) save_stack, n, current_save_size);
1289 current_save_size = newsize;
1291 sprintf(log_line, "Current%s %d\n", "save_size", current_save_size);
1292 show_line(log_line, 0);
1293 sprintf(log_line, "New Address %s == %d\n", "save stack", save_stack);
1294 show_line(log_line, 0);
1296 if (trace_flag) probe_show (); /* 94/Mar/25 */
1301 #ifdef ALLOCATEINPUTSTACK
1302 int current_stack_size=0; /* input stack size */
1304 in_state_record *realloc_input_stack (int size)
1308 in_state_record *newinputstack=NULL;
1311 sprintf(log_line, "Old Address %s == %d\n", "input stack", input_stack);
1312 show_line(log_line, 0);
1314 if (current_stack_size == stack_size) { /* arbitrary limit */
1315 /* memory_error ("input stack", (stack_size + 1) * sizeof(in_state_record)); */
1319 minsize = current_stack_size / 100 * percent_grow;
1320 if (size < minsize) size = minsize;
1321 if (size < initial_stack_size) size = initial_stack_size;
1323 for (k = 0; k < MAXSPLITS; k++) {
1324 newsize = current_stack_size + size;
1325 if (newsize > stack_size) newsize = stack_size;
1326 n = (newsize + 1) * sizeof (in_state_record); /* input_stack[stack_size + 1] */
1327 if (trace_flag) trace_memory("input_stack", n);
1328 newinputstack = (in_state_record *) REALLOC (input_stack, n);
1329 if (newinputstack != NULL) break; /* did we get it ? */
1330 if (current_stack_size == 0) break; /* initial allocation must work */
1331 size = size / 2; /* else can retry smaller */
1334 if (newinputstack == NULL) {
1335 memory_error("input stack", n);
1336 return input_stack; /* try and continue !!! */
1338 input_stack = newinputstack;
1339 update_statistics ((int) input_stack, n, current_stack_size);
1340 current_stack_size = newsize;
1342 sprintf(log_line, "Current%s %d\n", "stack_size", current_stack_size);
1343 show_line(log_line, 0);
1344 sprintf(log_line, "New Address %s == %d\n", "input stack", input_stack);
1345 show_line(log_line, 0);
1347 if (trace_flag) probe_show (); /* 94/Mar/25 */
1352 #ifdef ALLOCATENESTSTACK
1353 int current_nest_size=0; /* current nest size */
1355 list_state_record *realloc_nest_stack (int size)
1359 list_state_record *newnest=NULL;
1362 sprintf(log_line, "Old Address %s == %d\n", "nest stack", nest);
1363 show_line(log_line, 0);
1365 if (current_nest_size == nest_size) { /* arbitrary limit */
1366 /* memory_error ("nest stack", (nest_size + 1) * sizeof(list_state_record)); */
1368 return nest; /* let TeX handle the error */
1370 minsize = current_nest_size / 100 * percent_grow;
1371 if (size < minsize) size = minsize;
1372 if (size < initial_nest_size) size = initial_nest_size;
1374 for (k = 0; k < MAXSPLITS; k++) {
1375 newsize = current_nest_size + size;
1376 if (newsize > nest_size) newsize = nest_size;
1377 n = (newsize + 1) * sizeof (list_state_record); /* nest[nest_size + 1] */
1378 if (trace_flag) trace_memory("nest stack", n);
1379 newnest = (list_state_record *) REALLOC (nest, n);
1380 if (newnest != NULL) break; /* did we get it ? */
1381 if (current_nest_size == 0) break; /* initial allocation must work */
1382 size = size / 2; /* else can retry smaller */
1385 if (newnest == NULL) {
1386 memory_error("nest stack", n);
1387 return nest; /* try and continue !!! */
1390 update_statistics ((int) nest, n, current_nest_size);
1391 current_nest_size = newsize;
1393 sprintf(log_line, "Current%s %d\n", "nest_size", current_nest_size);
1394 show_line(log_line, 0);
1395 sprintf(log_line, "New Address %s == %d\n", "nest stack", nest);
1396 show_line(log_line, 0);
1398 if (trace_flag) probe_show (); /* 94/Mar/25 */
1403 #ifdef ALLOCATEPARAMSTACK
1404 int current_param_size=0; /* current param size */
1406 halfword *realloc_param_stack (int size)
1410 halfword *newparam=NULL;
1413 sprintf(log_line, "Old Address %s == %d\n", "param stack", param_stack);
1414 show_line(log_line, 0);
1416 if (current_param_size == param_size) { /* arbitrary limit */
1417 /* memory_error ("param stack", (param_size + 1) * sizeof(halfword)); */
1419 return param_stack; /* let TeX handle the error */
1421 minsize = current_param_size / 100 * percent_grow;
1422 if (size < minsize) size = minsize;
1423 if (size < initial_param_size) size = initial_param_size;
1425 for (k = 0; k < MAXSPLITS; k++) {
1426 newsize = current_param_size + size;
1427 if (newsize > param_size) newsize = param_size;
1428 n = (newsize + 1) * sizeof (halfword); /* param_stack[param_size + 1] */
1429 if (trace_flag) trace_memory("param stack", n);
1430 newparam = (halfword *) REALLOC (param_stack, n);
1431 if (newparam != NULL) break; /* did we get it ? */
1432 if (current_param_size == 0) break; /* initial allocation must work */
1433 size = size / 2; /* else can retry smaller */
1436 if (newparam == NULL) {
1437 memory_error("param stack", n);
1438 return param_stack; /* try and continue !!! */
1440 param_stack = newparam;
1441 update_statistics ((int) param_stack, n, current_param_size);
1442 current_param_size = newsize;
1444 sprintf(log_line, "Current%s %d\n", "param_size", current_param_size);
1445 show_line(log_line, 0);
1446 sprintf(log_line, "New Address %s == %d\n", "param stack", param_stack);
1447 show_line(log_line, 0);
1449 if (trace_flag) probe_show (); /* 94/Mar/25 */
1454 #ifdef ALLOCATEBUFFER
1455 int current_buf_size=0;
1457 ASCII_code *realloc_buffer (int size)
1461 ASCII_code *newbuffer=NULL;
1464 sprintf(log_line, "Old Address %s == %d\n", "buffer", buffer);
1465 show_line(log_line, 0);
1467 if (current_buf_size == buf_size) { /* arbitrary limit */
1468 /* memory_error ("buffer", buf_size); */
1470 return buffer; /* pass it back to TeX 99/Fabe/4 */
1472 minsize = current_buf_size / 100 * percent_grow;
1473 if (size < minsize) size = minsize;
1474 if (size < initial_buf_size) size = initial_buf_size;
1476 for (k = 0; k < MAXSPLITS; k++) {
1477 newsize = current_buf_size + size;
1478 if (newsize > buf_size) newsize = buf_size;
1479 n = (newsize + 1) * sizeof(ASCII_code); /* buffer[buf_size + 1] */
1480 if (trace_flag) trace_memory("buffer", n);
1481 newbuffer = (ASCII_code *) REALLOC (buffer, n);
1482 if (newbuffer != NULL) break; /* did we get it ? */
1483 if (current_buf_size == 0) break; /* initial allocation must work */
1484 size = size / 2; /* else can retry smaller */
1487 if (newbuffer == NULL) {
1488 memory_error("buffer", n);
1489 return buffer; /* try and continue !!! */
1492 update_statistics ((int) buffer, n, current_buf_size);
1494 memset(buffer + current_buf_size, 0, newsize - current_buf_size);
1496 for (k = current_buf_size; k < newsize; k++) buffer[k]= 0;
1498 current_buf_size = newsize;
1500 sprintf(log_line, "Current%s %d\n", "buffer", current_buf_size);
1501 show_line(log_line, 0);
1502 sprintf(log_line, "New Address %s == %d\n", "buffer", buffer);
1503 show_line(log_line, 0);
1505 if (trace_flag) probe_show (); /* 94/Mar/25 */
1510 /* we used to allocate this one only to reduce the size of the PE file */
1511 /* not used anymore - NO advantage */
1513 #ifdef ALLOCATEDVIBUF
1514 eight_bits *allocatedvibuf (int size)
1516 eight_bits *dvi_buf;
1519 n = (size + 1) * sizeof(eight_bits);
1520 if (trace_flag) trace_memory("dvi_buf", n);
1521 dvi_buf = (eight_bits *) malloc (roundup(n));
1522 if (dvi_buf == NULL) {
1523 memory_error("dvi_buf", n);
1527 sprintf(log_line, "Address dvi_buf %d\n", dvi_buf);
1528 show_line(log_line, 0);
1530 update_statistics ((int) dvi_buf, n, 0);
1531 if (trace_flag) probe_show (); /* 94/Mar/25 */
1536 /* we used to allocate this one only to reduce the size of the PE file */
1537 /* it can be done without loss in performance, since register eqtb = zeqtb */
1538 #ifdef ALLOCATEZEQTB
1539 memory_word *allocatezeqtb (int k)
1544 n = k * sizeof (memory_word); /* 13507 * 8 = 108 kilobytes */
1545 if (trace_flag) trace_memory("eqtb", n);
1546 zeqtb = (memory_word *) malloc (roundup(n));
1547 if (zeqtb == NULL) {
1548 memory_error("eqtb", n);
1549 // exit (1); /* serious error */
1553 sprintf(log_line, "Address zeqtb %d\n", zeqtb);
1554 show_line(log_line, 0);
1556 update_statistics ((int) zeqtb, n, 0);
1557 if (trace_flag) probe_show (); /* 94/Mar/25 */
1562 /* here is the main memory allocation routine -- calls the above */
1563 /* returns -1 if it fails */
1565 int allocate_memory (void)
1566 { /* allocate rather than static 93/Nov/26 */
1569 char *holeadr = malloc (300000); /* testing - preallocate 95/Jan/20 */
1573 #error ERROR: Not ready for ALLOCATEHASH...
1576 /* probably not worth while/not a good idea allocating following */
1577 /* they are all rather small, and typically don't need expansion */
1578 /* WE ASSUME THIS DOESN'T HAPPEN, SO WON'T BOTHER WITH UPDATESTATISTICS */
1580 /* n = 9767 * sizeof (twohalves); *//* 60 kilo bytes */
1581 /* n = (hash_size + 267) * sizeof (twohalves); */ /* 60 kilo bytes */
1582 /* n = (9767 + eqtb_extra) * sizeof (twohalves); */
1584 n = (hash_size + 267 + eqtb_extra) * sizeof (htwohalves); /* 95/Feb/19 */
1586 n = (hash_size + 267 + eqtb_extra) * sizeof (twohalves); /* 95/Feb/19 */
1588 if (trace_flag) trace_memory("hash table", n);
1590 zzzae = (htwohalves *) malloc (roundup(n));
1592 zzzae = (twohalves *) malloc (roundup(n));
1594 /* zzzae = (twohalves *) malloc ((hash_size + 267) * sizeof (twohalves)); */
1595 if (zzzae == NULL) {
1596 memory_error("hash table", n);
1597 // exit (1); /* serious error */
1598 return -1; /* serious error */
1601 n = (inputsize + 1) * sizeof(memory_word);
1602 if (trace_flag) trace_memory("input_stack", n);
1603 /* input_stack = (memory_word *) malloc ((inputsize + 1) * sizeof (memory_word)); */
1604 input_stack = (memory_word *) malloc (roundup(n));
1605 if (input_stack == NULL) {
1606 memory_error("input_stack", n);
1607 // exit (1); /* serious error */
1608 return -1; /* serious error */
1612 /* no real reason to allocate dvi_buf - no need to ever grow it */
1613 #ifdef ALLOCATEDVIBUF
1614 /* zdvibuf = NULL; */
1615 zdvibuf = allocatedvibuf (dvi_buf_size);
1616 if (zdvibuf == NULL) return -1;
1619 #ifdef ALLOCATEZEQTB
1621 #ifdef INCREASEFONTS
1622 /* zeqtb = allocatezeqtb (13507 + eqtb_extra); */ /* 94/Mar/29 */
1623 zeqtb = allocatezeqtb (hash_size + 4007 + eqtb_extra); /* 94/Mar/29 */
1625 /* zeqtb = allocatezeqtb (13507); */
1626 zeqtb = allocatezeqtb (hash_size + 4007);
1630 #ifdef ALLOCATEINPUTSTACK
1631 input_stack = NULL; /* new 1999/Jan/21 */
1632 current_stack_size = 0;
1633 input_stack = realloc_input_stack (initial_stack_size); /* + 1 */
1636 #ifdef ALLOCATENESTSTACK
1637 nest = NULL; /* new 1999/Jan/21 */
1638 current_nest_size = 0;
1639 nest = realloc_nest_stack (initial_nest_size); /* + 1 */
1642 #ifdef ALLOCATEPARAMSTACK
1643 param_stack = NULL; /* new 1999/Jan/21 */
1644 current_param_size = 0;
1645 param_stack = realloc_param_stack (initial_param_size); /* + 1 */
1648 #ifdef ALLOCATESAVESTACK
1649 save_stack = NULL; /* new 1999/Jan/7 */
1650 current_save_size = 0;
1651 save_stack = realloc_save_stack (initial_save_size);
1655 buffer = NULL; /* need to do earlier */
1656 current_buf_size = 0;
1657 buffer = realloc_buffer (initial_buf_size);
1660 #ifdef ALLOCATESTRING
1662 current_pool_size = 0;
1664 current_max_strings = 0;
1665 /* need to create space because iniTeX writes in before reading pool file */
1666 /* for a start, puts in strings for 256 characters */
1667 /* maybe taylor allocations to actual pool file 1300 strings 27000 bytes ? */
1669 if (trace_flag) show_line("ini TeX pool and string allocation\n", 0);
1670 str_pool = realloc_str_pool (initial_pool_size);
1671 str_start = realloc_str_start (initial_max_strings);
1675 /* the following can save a lot of the usual 800k fixed allocation */
1678 current_font_mem_size = 0;
1679 /* if not iniTeX, then do initial allocation on fmt file read in itex.c */
1680 /* if ini-TeX we need to do it here - no format file read later */
1681 if (is_initex) font_info = realloc_font_info (initial_font_mem_size);
1687 mem_min = mem_bot; /* just to avoid complaints in texbody */
1688 mem_top = mem_initex;
1690 /* allocate main memory here if this is iniTeX */
1691 /* otherwise wait for format undumping in itex.c ... */
1693 /* avoid this if format specified on command line ??? */
1694 /* allocate_main_memory(mem_initex); */ /* made variable ! */
1695 mem = allocate_main_memory(mem_initex); /* made variable ! */
1698 return -1; /* serious error */
1702 /* now for the hyphenation exception stuff */
1703 #ifdef ALLOCATEHYPHEN
1706 /* this will be overridden later by what is in format file */
1707 hyphen_prime = default_hyphen_prime;
1708 /* non ini-TeX use assumes format will be read and that specifies size */
1710 if (new_hyphen_prime) hyphen_prime = new_hyphen_prime;
1711 if (realloc_hyphen (hyphen_prime)) /* allocate just in case no format */
1716 /* now for memory for the part of the hyphenation stuff that always needed */
1717 /* if iniTeX, need to allocate pre-determined fixed amount - trie_size */
1718 /* if iniTeX not selected, allocate only enough later - undump in itex.c ! */
1719 #ifdef ALLOCATETRIES
1721 if (allocate_tries (trie_size)) return -1;
1725 /* now for memory for hyphenation stuff needed only when running iniTeX */
1728 if (allocate_ini(trie_size)) return -1;
1731 trie_l = trie_r = trie_o = trie_hash = NULL; /* (trie_size + 1) * integer */
1732 trie_c = NULL; /* (trie_size + 1) * char */
1733 trie_taken = NULL; /* (trie_size + 1) * bool */
1737 free(holeadr); /* create the hole */
1739 return 0; // success
1742 /* returns non-zero if error - done to test integrity of stack mostly */
1744 int free_memory (void)
1745 { /* free in reverse order 93/Nov/26 */
1747 unsigned heaptotal=0;
1748 /* unsigned total; */
1750 if (trace_flag) show_line("free_memory ", 0);
1753 if (debug_flag) check_eqtb("free_memory");
1755 if (verbose_flag || trace_flag) show_maximums(stdout);
1757 if (heap_flag) (void) heap_dump(stdout, 1);
1761 heaptotal = (void) heap_dump(stdout, 0);
1763 sprintf(log_line, "Heap total: %u bytes --- max address %u\n",
1764 heaptotal, max_address);
1765 show_line(log_line, 0);
1768 sprintf(log_line, "Main Memory: variable node %d (%d - %d) one word %d (%d - %d)\n",
1769 lo_mem_max - mem_min, mem_min, lo_mem_max, mem_end - hi_mem_min, hi_mem_min, mem_end);
1770 show_line(log_line, 0);
1772 /* following only needed to check consistency of heap ... useful debugging */
1773 if (trace_flag) show_line("Freeing memory again\n", 0);
1776 show_line(log_line, "Zero Glue Reference Count %d\n", mem[0].hh.v.RH); */
1778 /* the following checks the heap integrity */
1780 /* if ((n = _heapchk ()) != _HEAPOK) { */ /* 94/Feb/18 */
1782 #ifdef SHOWHEAPERROR
1784 if (n != _HEAPOK) { /* 94/Feb/18 */
1785 sprintf(log_line, "WARNING: Heap corrupted (%d)\n", n);
1786 show_line(log_line, 1);
1787 sprintf(log_line, "HEAP %s (%s)\n", heapstrings[-n], "free_memory");
1788 show_line(log_line, 0);
1789 return n; /* non-zero and negative */ /* unreachable ??? */
1792 /* only free memory if safe ... additional check */
1795 if (trie_taken != NULL) free(trie_taken);
1796 if (trie_hash != NULL) free(trie_hash);
1797 if (trie_r != NULL) free(trie_r);
1798 if (trie_c != NULL) free(trie_c);
1799 if (trie_o != NULL) free(trie_o);
1800 if (trie_l != NULL) free(trie_l);
1802 trie_hash = trie_l = trie_r = NULL;
1807 #ifdef ALLOCATETRIES
1808 if (trie_trc != NULL) free (trie_trc);
1809 if (trie_tro != NULL) free (trie_tro);
1810 if (trie_trl != NULL) free (trie_trl);
1812 trie_tro = trie_trl = NULL;
1814 #ifdef ALLOCATEHYPHEN
1815 if (hyph_list != NULL) free(hyph_list);
1816 if (hyph_word != NULL) free(hyph_word);
1821 /* if (zzzaa != NULL) free(zzzaa); */ /* NO: zzzaa may be offset ! */
1822 if (mainmemory != NULL) free(mainmemory);
1826 if (font_info != NULL) free(font_info);
1829 #ifdef ALLOCATESTRING
1830 if (str_start != NULL) free(str_start);
1831 if (str_pool != NULL) free(str_pool);
1837 if (zzzae != NULL) free(zzzae);
1841 #ifdef ALLOCATEDVIBUF
1842 if (zdvibuf != NULL) free(zdvibuf);
1845 #ifdef ALLOCATEZEQTB
1846 if (zeqtb != NULL) free(zeqtb);
1850 #ifdef ALLOCATEPARAMSTACK
1851 if (param_stack != NULL) free(param_stack);
1854 #ifdef ALLOCATENESTSTACK
1855 if (nest != NULL) free(nest);
1858 #ifdef ALLOCATEINPUTSTACK
1859 if (input_stack != NULL) free(input_stack);
1862 #ifdef ALLOCATESAVESTACK
1863 if (save_stack != NULL) free(save_stack);
1866 /* if (buffercopy != NULL) free (buffercopy); */ /* 94/Jun/27 */
1867 if (format_file != NULL) free(format_file); /* 96/Jan/16 */
1868 if (string_file != NULL) free(string_file); /* 96/Jan/16 */
1869 if (source_direct != NULL) free(source_direct); /* 98/Sep/29 */
1870 format_file = string_file = source_direct = NULL;
1871 if (dvi_file_name != NULL) free(dvi_file_name);
1872 if (log_file_name != NULL) free(log_file_name);
1873 log_file_name = dvi_file_name = NULL; /* 00/Jun/18 */
1880 int sum = 1; /* 1 + 3 + 5 + k = (k + 1) * (k + 1) / 4 */
1881 if (x % 2 == 0) return false;
1882 for (k = 3; k < x; k = k + 2) {
1883 if (x % k == 0) return false;
1884 /* if (k * k > x) return true; */
1885 if (sum * 4 > x) return true;
1892 bool show_use=false;
1893 bool floating=false;
1895 void complainarg (int c, char *s)
1897 sprintf(log_line, "ERROR: Do not understand `%c' argument value `%s'\n", c, s);
1898 show_line(log_line, 1);
1899 show_use = 1; // 2000 June 21
1902 /* following is list of allowed command line flags and args */
1904 /* char *allowedargs="+vitrdcyzpsqnwbfXABCDFGKLMNOQRSTYWZ?g=m=u=e=o=a=x=k=h=l=u=E=H="; */
1906 /* only 01234567.9 still left to take ... maybe recycle u */
1908 char *allowedargs="+bcdfijnpqrstvwyzABCDFGIJKLMNOPQRSTVWXYZ23456789?a=e=g=h=k=l=m=o=u=x=E=H=P=U=";
1910 /* char takeargs="gmueoazhluEH"; */ /* subset that takes args! needed here */
1912 void reorderargs (int ac, char **av)
1913 { /* put in 1993/Dec/28 */
1916 // char takeargs[128]; /* large enough for all command line arg chars */
1917 char takeargs[256]; /* large enough for all command line arg chars */
1919 /* assumes arg pointers av[] are writeable */
1920 /* for (n = 1; n < ac; n++) sprintf(log_line, "%s ", av[n]); */
1922 if (ac < 3) { /* need more than one arg to reorder anything 94/Feb/25 */
1923 /* show_line("No arguments?\n", 0); */ /* debugging */
1924 return; /* no args ! */
1928 t = takeargs; /* list of those that take args */
1929 while (*s != '\0' && *(s+1) != '\0') {
1930 if (*(s+1) == '=') *t++ = *s++; /* copy over --- without the = */
1935 show_line(takeargs, 0);
1940 for (;;) { /* scan to end of command line args */
1941 if (*av[n] != '-') break;
1942 /* does it take an argument ? and is this argument next ? */
1944 *(av[n]+2) == '\0' &&
1945 /* strchr("gmuhleoxE", *(av[n]+1)) != NULL) */
1946 strchr(takeargs, *(av[n]+1)) != NULL)
1947 n += 2; /* step over it */
1952 for (;;) { /* look for more command line args */
1955 /* while (*av[m] != '-' && m < ac) m++; */ /* first command */
1956 while (m < ac && *av[m] != '-') m++; /* first command */
1958 /* does it take an argument ? and is this argument next ? */
1959 /* check first whether the `-x' is isolated, or arg follows directly */
1960 /* then check whether this is one of those that takes an argument */
1962 *(av[m]+2) == '\0' &&
1963 strchr(takeargs, *(av[m]+1)) != NULL) {
1964 s = av[m]; /* move command down before non-command */
1966 for (; m > n; m--) av[m+1] = av[m-1];
1969 n += 2; /* step over moved args */
1972 s = av[m]; /* move command down before non-command */
1973 for (; m > n; m--) av[m] = av[m-1];
1975 n++; /* step over moved args */
1980 int testalign (int address, int size, char *name)
1983 if (size > 4) n = address % 4;
1984 else n = address % size;
1986 sprintf(log_line, "OFFSET %d (ELEMENT %d) in %s\n", n, size, name);
1987 show_line(log_line, 0);
1992 /* activate detailed checking of alignment when trace_flag is set */
1994 void check_fixed_align (int flag)
1996 if (testalign ((int) &mem_top, 4, "FIXED ALIGNMENT")) {
1997 show_line("PLEASE RECOMPILE ME!\n", 1);
1999 #ifdef CHECKALIGNMENT
2001 testalign ((int) &mem_top, 4, "mem_top");
2002 testalign ((int) &mem_max, 4, "mem_max");
2003 testalign ((int) &mem_min, 4, "mem_min");
2004 testalign ((int) &bad, 4, "bad");
2005 testalign ((int) &trie_size, 4, "trie_size");
2006 testalign ((int) &xord, sizeof(xord[0]), "xord"); /* no op */
2007 testalign ((int) &xchr, sizeof(xchr[0]), "xchr"); /* no op */
2008 testalign ((int) &name_length, 4, "name_length");
2009 testalign ((int) &first, 4, "first");
2010 testalign ((int) &last, 4, "last");
2011 testalign ((int) &max_buf_stack, 4, "max_buf_stack");
2012 testalign ((int) &pool_ptr, 4, "pool_ptr");
2013 testalign ((int) &str_ptr, 4, "str_ptr");
2014 testalign ((int) &init_pool_ptr, 4, "init_pool_ptr");
2015 testalign ((int) &init_str_ptr, 4, "init_str_ptr");
2016 testalign ((int) &log_file, 4, "log_file");
2017 testalign ((int) &tally, 4, "tally");
2018 testalign ((int) &term_offset, 4, "term_offset");
2019 testalign ((int) &file_offset, 4, "file_offset");
2020 testalign ((int) &trick_count, 4, "trick_count");
2021 testalign ((int) &first_count, 4, "first_count");
2022 testalign ((int) &deletions_allowed, 4, "deletions_allowed");
2023 testalign ((int) &set_box_allowed, 4, "set_box_allowed");
2024 testalign ((char *) &help_line, sizeof(help_line[0]), "help_line");
2025 testalign ((int) &use_err_help, 4, "use_err_help");
2026 testalign ((int) &interrupt, 4, "interrupt");
2027 testalign ((int) &OK_to_interrupt, 4, "OK_to_interrupt");
2028 testalign ((int) &arith_error, 4, "arith_error");
2029 testalign ((int) &tex_remainder, 4, "tex_remainder");
2030 testalign ((int) &temp_ptr, 4, "temp_ptr");
2031 testalign ((int) &lo_mem_max, 4, "lo_mem_max");
2032 testalign ((int) &hi_mem_min, 4, "hi_mem_min");
2033 testalign ((int) &var_used, 4, "var_used");
2034 testalign ((int) &dyn_used, 4, "dyn_used");
2035 testalign ((int) &avail, 4, "avail");
2036 testalign ((int) &mem_end, 4, "mem_end");
2037 testalign ((int) &mem_start, 4, "mem_start");
2038 testalign ((int) &rover, 4, "rover");
2039 testalign ((int) &font_in_short_display, 4, "font_in_short_display");
2040 testalign ((int) &depth_threshold, 4, "depth_threshold");
2041 testalign ((int) &breadth_max, 4, "breadth_max");
2042 testalign ((int) &nest, sizeof(nest[0]), "nest");
2045 testalign ((int) &zeqtb, sizeof(zeqtb[0]), "zeqtb"); /* not any more ? */
2047 /* testalign ((int) &xeq_level, sizeof(xeq_level[0]), "xeq_level"); */
2048 testalign ((int) &zzzad, sizeof(zzzad[0]), "zzzad");
2049 /* testalign ((int) &hash, sizeof(hash[0]), "hash"); */
2050 testalign ((int) &zzzae, sizeof(zzzae[0]), "zzzae");
2052 testalign ((int) &save_stack, sizeof(save_stack[0]), "save_stack");
2053 testalign ((int) &input_stack, sizeof(input_stack[0]), "input_stack");
2054 testalign ((int) &input_file, sizeof(input_file[0]), "input_file");
2055 testalign ((int) &line_stack, sizeof(line_stack[0]), "line_stack");
2056 testalign ((int) ¶m_stack, sizeof(param_stack[0]), "param_stack");
2057 testalign ((int) &cur_mark, sizeof(cur_mark[0]), "cur_mark");
2058 testalign ((int) &pstack, sizeof(pstack[0]), "pstack");
2059 testalign ((int) &read_file, sizeof(read_file[0]), "read_file");
2061 testalign ((int) &font_check, sizeof(font_check[0]), "font_check");
2062 testalign ((int) &font_size, sizeof(font_size[0]), "font_size");
2063 testalign ((int) &font_dsize, sizeof(font_dsize[0]), "font_dsize");
2064 testalign ((int) &font_params, sizeof(font_params[0]), "font_params");
2065 testalign ((int) &font_name, sizeof(font_name[0]), "font_name");
2066 testalign ((int) &font_area, sizeof(font_area[0]), "font_area");
2067 testalign ((int) &font_bc, sizeof(font_bc[0]), "font_bc");
2068 testalign ((int) &font_ec, sizeof(font_ec[0]), "font_ec");
2069 testalign ((int) &font_glue, sizeof(font_glue[0]), "font_glue");
2070 testalign ((int) &font_used, sizeof(font_used[0]), "font_used");
2071 testalign ((int) &hyphen_char, sizeof(hyphen_char[0]), "hyphen_char");
2072 testalign ((int) &skew_char, sizeof(skew_char[0]), "skew_char");
2073 testalign ((int) &bchar_label, sizeof(bchar_label[0]), "bchar_label");
2074 testalign ((int) &font_bchar, sizeof(font_bchar[0]), "font_bchar");
2075 testalign ((int) &font_false_bchar, sizeof(font_false_bchar[0]), "font_false_bchar");
2076 testalign ((int) &char_base, sizeof(char_base[0]), "char_base");
2077 testalign ((int) &width_base, sizeof(width_base[0]), "width_base");
2078 testalign ((int) &height_base, sizeof(height_base[0]), "height_base");
2079 testalign ((int) &depth_base, sizeof(depth_base[0]), "depth_base");
2080 testalign ((int) &italic_base, sizeof(italic_base[0]), "italic_base");
2081 testalign ((int) &lig_kern_base, sizeof(lig_kern_base[0]), "lig_kern_base");
2082 testalign ((int) &kern_base, sizeof(kern_base[0]), "kern_base");
2083 testalign ((int) &exten_base, sizeof(exten_base[0]), "exten_base");
2084 testalign ((int) ¶m_base, sizeof(param_base[0]), "param_base");
2086 #ifdef ALLOCATEDVIBUF
2087 testalign ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2089 testalign ((int) &totalstretch, sizeof(totalstretch[0]), "totalstretch");
2090 testalign ((int) &totalshrink, sizeof(totalshrink[0]), "totalshrink");
2091 testalign ((int) &active_width, sizeof(active_width[0]), "active_width");
2092 testalign ((int) &cur_active_width, sizeof(cur_active_width[0]), "cur_active_width");
2093 testalign ((int) &background, sizeof(background[0]), "background");
2094 testalign ((int) &break_width, sizeof(break_width[0]), "break_width");
2095 testalign ((int) &minimal_demerits, sizeof(minimal_demerits[0]), "minimal_demerits");
2096 testalign ((int) &best_place, sizeof(best_place[0]), "best_place");
2097 testalign ((int) &best_pl_line, sizeof(best_pl_line[0]), "best_pl_line");
2098 testalign ((int) &hc, sizeof(hc[0]), "hc");
2099 testalign ((int) &hu, sizeof(hu[0]), "hu");
2100 testalign ((int) &hyf, sizeof(hyf[0]), "hyf");
2101 /* testalign ((int) &x, sizeof(x[0]), "x"); */
2103 testalign ((int) &hyf_distance, sizeof(hyf_distance[0]), "hyf_distance");
2104 testalign ((int) &hyf_num, sizeof(hyf_num[0]), "hyf_num");
2105 testalign ((int) &hyf_next, sizeof(hyf_next[0]), "hyf_next");
2106 testalign ((int) &op_start, sizeof(op_start[0]), "op_start");
2108 /* testalign ((int) &trie_op_hash, sizeof(trie_op_hash[0]), "trie_op_hash"); */
2109 testalign ((int) &zzzaf, sizeof(zzzaf[0]), "zzzaf");
2110 testalign ((int) &trie_used, sizeof(trie_used[0]), "trie_used");
2111 /* testalign ((int) &trie_op_lang, sizeof(trie_op_lang[0]), "trie_op_lang");*/
2112 testalign ((int) &trie_op_val, sizeof(trie_op_val[0]), "trie_op_val");
2114 testalign ((int) &trie_min, sizeof(trie_min[0]), "trie_min");
2115 testalign ((int) &page_so_far, sizeof(page_so_far[0]), "page_so_far");
2116 testalign ((int) &write_file, sizeof(write_file[0]), "write_file");
2117 testalign ((int) &write_open, sizeof(write_open[0]), "write_open");
2121 void check_alloc_align (int flag) {
2122 if (testalign ((int) zeqtb, sizeof(zeqtb[0]), "ALLOCATED ALIGNMENT"))
2123 show_line("PLEASE RECOMPILE ME!\n", 1);
2124 #ifdef CHECKALIGNMENT
2127 testalign ((int) zeqtb, sizeof(zeqtb[0]), "zeqtb");
2129 #ifndef ALLOCATEDVIBUF
2130 testalign ((int) &zdvibuf, sizeof(zdvibuf[0]), "zdvibuf"); /* no op */
2132 testalign ((int) str_pool, sizeof(str_pool[0]), "str_pool"); /* no op */
2133 testalign ((int) str_start, sizeof(str_start[0]), "str_start");
2134 testalign ((int) zmem, sizeof(zmem[0]), "main memory");
2135 testalign ((int) font_info, sizeof(font_info[0]), "font memory");
2136 testalign ((int) trie_trl, sizeof(trie_trl[0]), "trie_trl");
2137 testalign ((int) trie_tro, sizeof(trie_tro[0]), "trie_tro");
2138 testalign ((int) trie_trc, sizeof(trie_trc[0]), "trie_trc");
2139 testalign ((int) hyph_word, sizeof(hyph_word[0]), "hyph_word");
2140 testalign ((int) hyph_list, sizeof(hyph_list[0]), "hyph_list");
2141 /* testalign ((int) trie_c, sizeof(trie_c[0]), "trie_c"); *//* no op */
2142 testalign ((int) trie_o, sizeof(trie_o[0]), "trie_o");
2143 testalign ((int) trie_l, sizeof(trie_l[0]), "trie_l");
2144 testalign ((int) trie_r, sizeof(trie_r[0]), "trie_r");
2145 testalign ((int) trie_hash, sizeof(trie_hash[0]), "trie_hash");
2146 testalign ((int) trie_taken, sizeof(trie_taken[0]), "trie_taken");
2151 void showaddresses (void)
2155 sprintf(log_line, "STACK %d %d (grows %s) ", &c, &d, (&d > &c) ? "upward" : "downward");
2156 show_line(log_line, 0);
2157 sprintf(log_line, "eqtb %d hash %d ", zeqtb, zzzae);
2158 show_line(log_line, 0);
2159 sprintf(log_line, "dvi_buf %d xchr %d xord %d nest %d\n",
2160 zdvibuf, xchr, xord, nest);
2161 show_line(log_line, 0);
2162 sprintf(log_line, "save_stack %d input_stack %d line_stack %d param_stack %d\n",
2163 save_stack, input_stack, line_stack, param_stack);
2164 show_line(log_line, 0);
2165 sprintf(log_line, "font_check %d font_size %d font_dsize %d font_params %d font_name %d\n",
2166 font_check, font_size, font_dsize, font_params, font_name);
2167 show_line(log_line, 0);
2168 sprintf(log_line, "main %d font_info %d str_pool %d str_start %d hyph_word %d hyph_list %d\n",
2169 zmem, font_info, str_pool, str_start, hyph_word, hyph_list);
2170 show_line(log_line, 0);
2174 /* *** *** *** *** *** *** *** NEW APPROACH TO `ENV VARS' *** *** *** *** */
2176 /* grab `env var' from `dviwindo.ini' - or from DOS environment 94/May/19 */
2177 /* controlled by USEDVIWINDOINI environment variable 94/June/19 */
2179 bool usedviwindo = true; /* use [Environment] section in `dviwindo.ini' */
2180 bool backwardflag = false; /* don't cripple all advanced features */
2181 bool shorten_file_name = false; /* don't shorten file names to 8+3 for DOS */
2182 char *inifilename = "dviwindo.ini"; /* name of ini file we look for */
2183 char *dviwindo = ""; /* full file name for dviwindo.ini with path */
2184 char *envsection = "[Environment]"; /* Env var section in `dviwindo.ini' */
2185 char *wndsection = "[Window]"; /* Window section in `dviwindo.ini' */
2186 char *workdirect = "WorkingDirectory"; /* key in [Window] section */
2187 bool usesourcedirectory = true; /* use source file directory as local */
2188 /* when WorkingDirectory is set */
2189 bool workingdirectory = false; /* if working directory set in ini */
2190 /* set up full file name for dviwindo.ini and check for [Environment] */
2192 bool setupdviwindo (void)
2193 { /* set up full file name for dviwindo.ini */
2194 char dviwindoini[PATH_MAX];
2195 char line[PATH_MAX];
2198 int em = strlen(envsection);
2199 int wm = strlen(wndsection);
2200 int dm = strlen(workdirect);
2204 /* Easy to find Windows directory if Windows runs */
2205 /* Or if user kindly set WINDIR environment variable */
2206 /* Or if running in Windows NT */
2207 if ((windir = getenv("windir")) != NULL || /* 94/Jan/22 */
2208 (windir = getenv("WINDIR")) != NULL ||
2209 (windir = getenv("winbootdir")) != NULL || /* 95/Aug/14 */
2210 (windir = getenv("SystemRoot")) != NULL || /* 95/Jun/23 */
2211 (windir = getenv("SYSTEMROOT")) != NULL) { /* 95/Jun/23 */
2212 strcpy(dviwindoini, windir);
2213 strcat(dviwindoini, "\\");
2214 strcat(dviwindoini, inifilename);
2215 /* sprintf(log_line, "Using WINDIR %s\n", dviwindoini); */
2218 _searchenv (inifilename, "PATH", dviwindoini);
2219 /* sprintf(log_line, "Using SEARCHENV %s\n", dviwindoini); */
2222 wndflag = envflag = 0;
2223 /* workingdirectory = false; */
2224 if (*dviwindoini != '\0') {
2225 dviwindo = xstrdup(dviwindoini); /* avoid PATH_MAX string */
2226 /* check whether dviwindo.ini actually has [Environment] section */
2227 if (share_flag == 0) input = fopen(dviwindo, "r");
2228 else input = _fsopen(dviwindo, "r", share_flag);
2229 if (input != NULL) {
2230 while (fgets (line, sizeof(line), input) != NULL) {
2231 if (*line == ';') continue;
2232 if (*line == '\n') continue;
2234 if (wndflag && envflag) break; /* escape early */
2236 if (_strnicmp(line, wndsection, wm) == 0) {
2238 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2239 show_line(log_line, 0);
2243 else if (_strnicmp(line, envsection, em) == 0) {
2245 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2246 show_line(log_line, 0);
2248 /* fclose(input); */
2251 } else if (wndflag && _strnicmp(line, workdirect, dm) == 0) {
2253 sprintf(log_line, "Found %s", line); /* DEBUGGING */
2254 show_line(log_line, 0);
2256 workingdirectory = true;
2260 (void) fclose(input);
2264 show_line("Failed to find [Environment]", 1); /* DEBUGGING */
2265 (void) fclose(input);
2267 else if (trace_flag) perrormod(dviwindo); /* DEBUGGING */
2268 strcpy(dviwindo, ""); /* failed, for one reason or another */
2273 /* cache to prevent allocating twice in a row */
2275 char *lastname=NULL, *lastvalue=NULL;
2277 /* get value of env var - try first in dviwindo.ini then DOS env */
2278 /* returns allocated string -- these strings are not freed again */
2279 /* is it safe to do that now ? 98/Jan/31 */
2280 char *grabenv (char *varname)
2282 char line[PATH_MAX];
2286 /* int m = strlen(envsection); */
2287 /* int n = strlen(varname); */
2289 if (varname == NULL) return NULL; /* sanity check */
2290 if (*varname == '\0') return NULL; /* sanity check */
2291 /* speedup to avoid double lookup when called from set_paths in ourpaths.c */
2292 /* if (lastname != NULL && strcmp(lastname, varname) == 0) { */
2293 if (lastname != NULL && _strcmpi(lastname, varname) == 0) {
2295 sprintf(log_line, "Cache hit: %s=%s\n", lastname, lastvalue);
2296 show_line(log_line, 0);
2298 /* return lastvalue; */ /* save some time here */
2299 return xstrdup(lastvalue);
2300 /* duplicate so can free safely 98/Jan/31 */
2303 /* hmm, following was not xstrdup(...) */ /* not cached */
2304 if (usedviwindo == 0 || *dviwindo == '\0') {
2305 /* return getenv(varname); */
2306 s = getenv(varname);
2307 if (s == NULL) return NULL;
2308 else return xstrdup(s); /* make safe 98/Jan/31 */
2311 if (share_flag == 0) input = fopen(dviwindo, "r");
2312 else input = _fsopen(dviwindo, "r", share_flag);
2314 if (input != NULL) {
2315 m = strlen(envsection);
2316 /* search for [Environment] section */ /* should be case insensitive */
2317 while (fgets (line, sizeof(line), input) != NULL) {
2318 if (*line == ';') continue;
2319 if (*line == '\n') continue;
2320 if (_strnicmp(line, envsection, m) == 0) { /* 98/Jan/31 */
2321 /* search for varname=... */ /* should be case sensitive ? */
2322 n = strlen(varname);
2323 while (fgets (line, sizeof(line), input) != NULL) {
2324 if (*line == ';') continue;
2325 if (*line == '[') break;
2326 /* if (*line == '\n') break; */ /* ??? */
2327 if (*line <= ' ') continue; /* 95/June/23 */
2328 /* if (strncmp(line, varname, n) == 0 && */
2329 if (_strnicmp(line, varname, n) == 0 &&
2330 *(line+n) == '=') { /* found it ? */
2331 (void) fclose (input);
2332 /* flush trailing white space */
2333 s = line + strlen(line) - 1;
2334 while (*s <= ' ' && s > line) *s-- = '\0';
2335 if (trace_flag) { /* DEBUGGING ONLY */
2336 sprintf(log_line, "%s=%s\n", varname, line+n+1);
2337 show_line(log_line, 0);
2340 if (lastname != NULL) free(lastname);
2341 lastname = xstrdup (varname);
2342 if (lastvalue != NULL) free(lastvalue);
2343 lastvalue = xstrdup(s);
2344 return xstrdup(s); /* 98/Jan/31 */
2345 } /* end of matching varname */
2346 } /* end of while fgets */
2347 /* break; */ /* ? not found in designated section */
2348 } /* end of search for [Environment] section */
2350 (void) fclose (input);
2351 } /* end of if fopen */
2352 s = getenv(varname); /* failed, so try and get from environment */
2353 /* if (s != NULL) return s; */
2355 /* sdup = xstrdup(s); */ /* just to be safe --- 1995/Jan/31 */
2356 if (lastname != NULL) free(lastname);
2357 lastname = xstrdup (varname);
2358 if (lastvalue != NULL) free(lastvalue);
2359 lastvalue = xstrdup(s); /* remember in case asked again ... */
2361 return xstrdup(s); /* 98/Jan/31 */
2363 else return NULL; /* return NULL if not found anywhere */
2366 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2368 void flush_trailing_slash (char *directory){
2370 /* flush trailing \ or / in directory, if any 1993/Dec/12 */
2371 if (strcmp(directory, "") != 0) {
2372 s = directory + strlen(directory) - 1;
2373 if (*s == '\\' || *s == '/') *s = '\0';
2377 void knuthify (void)
2379 /* show_current = false; */ /* show ultimate limits */
2380 /* reorder_arg_flag = false; */ /* don't reorder command line */
2381 /* deslash = false; */ /* don't unixify file names */
2382 /* return_flag = false; */ /* don't allow just ^^M termination */
2383 /* trimeof = false; */ /* don't trim ^^Z Ctrl-Z at end of file */
2384 restrict_to_ascii = false; /* don't complain non ASCII */
2385 allow_patterns = false; /* don't allow pattern redefinition */
2386 show_in_hex = true; /* show character code in hex */
2387 show_in_dos = false; /* redundant with previous */
2388 show_numeric = false; /* don't show character code decimal */
2389 show_missing = false; /* don't show missing characters */
2390 civilize_flag = false; /* don't reorder date fields */
2391 c_style_flag = false; /* don't add file name to error msg */
2392 show_fmt_flag = false; /* don't show format file in log */
2393 show_tfm_flag = false; /* don't show metric file in log */
2394 /* font_max = 255; */ /* revert to TeX 82 limit */
2395 /* if you want this, change in tex.h definition of font_max to `int' */
2396 /* and add define FONTMAX 511, and in local.c add font_max = FONTMAX; */
2398 show_line_break_stats = false; /* do not show line break stats */
2399 show_fonts_used = false;
2400 default_rule = 26214; /* revert to default rule thickness */
2401 pseudo_tilde = false;
2402 pseudo_space = false;
2403 show_texinput_flag = false;
2404 truncate_long_lines = false;
2405 allow_quoted_names = false;
2406 show_cs_names = false;
2407 font_dimen_zero = false; /* 98/Oct/5 */
2408 ignore_frozen = false; /* 98/Oct/5 */
2409 suppress_f_ligs = false; /* 99/Jan/5 */
2410 full_file_name_flag = false; // 00 Jun 18
2411 save_strings_flag = false; // 00 Aug 15
2412 knuth_flag = true; /* so other code can know about this */
2413 } /* end of knuthify */
2415 /* following have already been used up */
2417 /* abcdefghijklmnopqrstuvwxyz */
2419 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2423 int nohandler=0; /* experiment to avoid Ctrl-C interrupt handler */
2425 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2427 /* following made global so analyze_flag can be made separate procedure */
2429 // char *xchrfile=""; /* save space use xstrdup */
2430 char *xchrfile = NULL; /* save space use xstrdup */
2431 // char *replfile="";/* save space use xstrdup */
2432 char *replfile = NULL;/* save space use xstrdup */
2434 /* abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ */
2436 /* analyze command line flag or argument */
2437 /* c is the flag letter itself, while optarg is start of arg if any */
2439 /* when making changes, revise allowedargs */
2442 int analyze_flag (int c, char *optarg)
2445 case 'v': want_version = true;
2446 verbose_flag = true;
2448 case 'i': is_initex = true;
2450 case 'Q': interaction = 0; /* quiet mode */
2452 case 'R': interaction = 1; /* run mode */
2454 case 'S': interaction = 2; /* scroll mode */
2456 case 'T': interaction = 3; /* tex mode */
2458 case 'K': backwardflag = true; /* 94/Jun/15 */
2459 knuthify (); /* revert to `standard' Knuth TeX */
2461 case 'L': c_style_flag = true; /* C style error msg 94/Mar/21 */
2463 case 'Z': show_tfm_flag = true; /* show TFM in log file 94/Jun/21 */
2465 case 'c': current_tfm = false; /* not look current dir for TFM */
2467 case 'C': current_flag = false; /* not look current dir for files */
2469 case 'M': show_missing = false; /* do not show missing 94/June/10 */
2471 case 'd': deslash = false; /* flipped 93/Nov/18 */
2472 /* pseudo_tilde = 0; */ /* new 95/Sep/26 */
2474 case 'p': allow_patterns = true; /* 93/Nov/26 */
2475 /* reset_exceptions = true; */ /* 93/Dec/23 */
2477 /* case 'w': show_in_hex = false; */ /* 94/Jan/26 */
2478 case 'w': show_in_hex = true; /* flipped 00/Jun/18 */
2480 case 'j': show_in_dos = true; /* 96/Jan/26 */
2482 case 'n': restrict_to_ascii = true; /* 0 - 127 1994/Jan/21 */
2484 case '6': workingdirectory = true; /* use source dir 98/Sep/29 */
2486 case '7': usesourcedirectory = false; /* use working dir 98/Sep/29 */
2488 case 'f': show_fonts_used = false; /* 97/Dec/24 */
2490 case '8': shorten_file_name = true; /* 95/Feb/20 */
2492 case '9': show_cs_names = true; /* 98/Mar/31 */
2494 case '4': ignore_frozen = true; /* 98/Oct/5 */
2496 case '5': font_dimen_zero = false; /* 98/Oct/5 */
2498 case 'F': show_texinput_flag = false; /* 98/Jan/28 */
2500 /* case 'X': truncate_long_lines = false; */ /* 98/Feb/2 */
2502 case 'W': usedviwindo = false; /* 94/May/19 */
2504 case 'J': show_line_break_stats = false; /* 96/Feb/8 */
2506 case 'O': show_fmt_flag = false; /* 94/Jun/21 */
2508 case 'I': format_specific = false; /* 95/Jan/7 */
2510 case '3': encoding_specific = false; /* 98/Oct/5 */
2512 case '2': suppress_f_ligs = true; /* 99/Jan/5 f-lig */
2514 /* following are pretty obscure */
2515 /* case 'y': cache_file_flag = false; */ /* 96/Nov/16 */
2517 /* case 'r': return_flag = false; */ /* flipped 93/Nov/18 */
2519 /* case 'z': trimeof = false; */ /* 93/Nov/24 */
2521 case 'z': full_file_name_flag = false; // 00 Jun 18
2523 case 'X': save_strings_flag = false; // 00 Aug 15
2525 /* following are unannounced options */ /* some may be recycled ... */
2526 case 't': trace_flag = true;
2528 case 'q': quitflag++; /* 93/Dec/16 */
2530 /* The following are really obscure and should not be advertized */
2531 case 's': show_current = false; /* tex8 93/Dec/14 */
2533 case 'N': show_numeric = false; /* 93/Dec/21 */
2535 case 'A': civilize_flag = false; /* 93/Dec/16 */
2537 case 'B': open_trace_flag = true; /* openinou 1994/Jan/8 */
2539 case 'Y': reorder_arg_flag = false; /* local */
2541 case 'b': test_dir_access = false; /* 94/Feb/10 */
2543 case 'D': dir_method = false; /* 94/Feb/10 */
2545 case 'G': file_method = false; /* 94/Feb/13 */
2547 // case 'V': share_flag = _SH_DENYNO; break; /* 0x40 - deny none mode */
2548 /* case 'X': nohandler++; break; */
2549 /* case 'f': waitflush = false; break; */
2550 /* case 'F': floating = true; break; */
2551 /* *********** following command line options take arguments ************** */
2552 case 'm': if (optarg == 0) mem_initex = mem_top; else mem_initex = atoi(optarg) * 1024; /* 93 Dec/1 */
2553 if (mem_initex == 0) complainarg(c, optarg);
2556 #ifdef VARIABLETRIESIZE
2557 case 'h': if (optarg == 0) trie_size = default_trie_size; else trie_size = atoi(optarg); /* 93 Dec/1 */
2558 if (trie_size == 0) complainarg(c, optarg);
2561 #ifdef ALLOCATEHYPHEN
2562 case 'e': if (optarg == 0) new_hyphen_prime = hyphen_prime * 2; else new_hyphen_prime = atoi(optarg); /* 93/Nov/26 */
2563 if (new_hyphen_prime == 0) complainarg(c, optarg);
2566 #ifdef ALLOCATEDVIBUF
2567 case 'u': if (optarg == 0) dvi_buf_size = default_dvi_buf_size; else dvi_buf_size = atoi(optarg); /* 94/Mar/24 */
2568 if (dvi_buf_size == 0) complainarg(c, optarg);
2571 case 'g': if (optarg == 0) percent_grow = 62; else percent_grow = atoi(optarg); /* 93/Dec/11 */
2572 if (percent_grow == 0) complainarg(c, optarg);
2574 case 'U': if (optarg == 0) pseudo_tilde = 0; else pseudo_tilde = atoi(optarg); /* 95/Sep/26 */
2575 if (pseudo_tilde > 255) pseudo_tilde = 255; else if (pseudo_tilde < 128) pseudo_tilde = 128;
2577 /* case 'H': if (optarg == 0) heapthreshold = 1024; else heapthreshold = atoi(optarg);
2578 * if (heapthreshold == 0) complainarg(c, optarg); else heap_flag = 1;
2580 case 'H': if (optarg == 0) tab_step = 8; else tab_step = atoi(optarg); /* 94/July/3 */
2581 if (tab_step == 0) complainarg(c, optarg);
2583 case 'x': if (optarg == 0) xchrfile=xstrdup("xchr.map"); else xchrfile = xstrdup(optarg);
2584 if (xchrfile == NULL || *xchrfile == '\0') complainarg(c, optarg);
2586 case 'k': if (optarg == 0) replfile =xstrdup("repl.key"); else replfile = xstrdup(optarg);
2587 if (replfile == NULL || *replfile == '\0')
2588 complainarg(c, optarg);
2590 /* more obscure stuff - ppssibly recycle */
2591 case 'P': if (optarg == 0) default_rule = 26214; /* 95/Oct/9 */
2592 else default_rule = atoi(optarg); /* 95/Oct/9 */
2593 if (default_rule == 0) complainarg(c, optarg);
2595 case 'E': if (optarg != 0) putenv(optarg); else complainarg(c, optarg);
2597 case 'o': if (optarg == 0) dvi_directory = ""; else dvi_directory = xstrdup(optarg);
2598 if (strcmp(dvi_directory, "") == 0) complainarg(c, optarg);
2600 case 'l': if (optarg == 0) log_directory = ""; else log_directory = xstrdup(optarg);
2601 if (strcmp(log_directory, "") == 0) complainarg(c, optarg);
2603 case 'a': if (optarg == 0) aux_directory = ""; else aux_directory = xstrdup(optarg);
2604 if (strcmp(aux_directory, "") == 0) complainarg(c, optarg);
2607 default : show_use = true;
2608 return -1; // failed to recognize
2614 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2615 //char *yytexcmd="yandytex.cmd";
2616 char *yytexcmd="YANDYTEX.CMD"; /* name of command line file */
2618 /* Try and read default command file - YANDYTEX.CMD */
2619 /* in current directory and then in directory of YANDYTEX */
2620 /* (does not make sense in TeX file directory) */
2621 /* since we don't yet know where that is ! */
2622 /* can't conveniently include this in output file either - not open yet */
2624 /* used both for yytex.cmd and @ indirect command line files */
2625 /* can this be reentered ? */
2627 /* supply extension if none */
2628 void extension (char *fname, char *ext)
2631 if ((s = strrchr(fname, '.')) == NULL ||
2632 ((t = strrchr(fname, '\\')) != NULL && s < t)) {
2638 /* remove file name - keep only path - inserts '\0' to terminate */
2640 void strip_name (char *pathname)
2643 if ((s=strrchr(pathname, '\\')) != NULL);
2644 else if ((s=strrchr(pathname, '/')) != NULL);
2645 else if ((s=strrchr(pathname, ':')) != NULL) s++;
2650 /* char commandfile[PATH_MAX]; */ /* keep around so can open later */
2652 char *programpath = ""; /* pathname of program */
2653 /* redundant with texpath ? */
2655 /* The following does not deslashify arguments ? Do we need to ? */
2657 int read_commands (char *filename)
2659 char commandfile[PATH_MAX];
2661 char line[PATH_MAX];
2662 char *linedup; /* need to copy line to preserve args */
2668 /* Try first in current directory (or use full name as specified) */
2669 strcpy(commandfile, filename);
2670 extension(commandfile, "cmd");
2671 if (share_flag == 0)
2672 command = fopen(commandfile, "r");
2674 command = _fsopen(commandfile, "r", share_flag);
2675 if (command == NULL) {
2676 /* If that fails, try in YANDYTeX program directory */
2677 strcpy(commandfile, programpath);
2678 /* don't need fancy footwork, since programpath non-empty */
2679 strcat(commandfile, "\\");
2680 strcat(commandfile, filename);
2681 extension(commandfile, "cmd");
2682 if (share_flag == 0)
2683 command = fopen(commandfile, "r");
2685 command = _fsopen(commandfile, "r", share_flag);
2686 if (command == NULL) {
2687 /* perrormod(commandfile); */ /* debugging only */
2688 /* strcpy(commandfile, ""); */ /* indicate failed */
2689 return 0; /* no command line file YYTEX.CMD */
2693 /* allow for multiple lines --- ignore args that don't start with `-' */
2694 while (fgets(line, PATH_MAX, command) != NULL) {
2695 /* sprintf(log_line, "From %s:\t%s", commandfile, line); */
2696 /* skip over comment lines and blank lines */
2697 if (*line == '%' || *line == ';' || *line == '\n') continue;
2698 if (strchr(line, '\n') == NULL) strcat(line, "\n");
2699 /* sfplogline, rintf("From %s:\t%s", commandfile, line); */
2700 linedup = xstrdup (line); /* 93/Nov/15 */
2701 if (linedup == NULL) {
2702 show_line("ERROR: out of memory\n", 1); /* read_commands */
2704 return -1; // failure
2706 s = strtok(linedup, " \t\n\r"); /* 93/Nov/15 */
2708 if (*s == '-' || *s == '/') {
2711 /* if (*optarg = '=') optarg++; */
2712 if (*optarg == '=') optarg++;
2713 if (analyze_flag(c, optarg) < 0) return -1; // failure ???
2715 /* else break; */ /* ignore non-flag items */
2716 s = strtok(NULL, " \t\n\r"); /* go to next token */
2718 /* If you want to see command lines in file - put -v in the file */
2719 /* if (verbose_flag != 0) sprintf(log_line, "From %s:\t%s", commandfile, line); */
2721 (void) fclose(command); /* no longer needed */
2722 return 1; // success
2725 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2727 /* try and read commands on command line */
2728 int read_command_line (int ac, char **av)
2731 char *optargnew; /* equal to optarg, unless that starts with `=' */
2732 /* in which case it is optarg+1 to step over the `=' */
2733 /* if optarg = 0, then optargnew = 0 also */
2735 // show_line("read_command_line\n", 0);
2736 if (ac < 2) return 0; /* no args to analyze ? 94/Apr/10 */
2738 /* while ((c = getopt(ac, av, "+vitrdczp?m:h:x:E:")) != EOF) { */
2739 /* NOTE: keep `Y' in there for `do not reorder arguments ! */
2740 /* WARNING: if adding flags, change also `allowedargs' and `takeargs' !!!! */
2741 while ((c = getopt(ac, av, allowedargs)) != EOF) {
2742 if (optarg != 0 && *optarg == '=')
2743 optargnew = optarg+1;
2746 analyze_flag (c, optargnew);
2748 if (show_use || quitflag == 3) {
2749 // showversion (stdout);
2751 strcat(log_line, "\n");
2752 show_line(log_line, 0);
2753 stampcopy(log_line);
2754 strcat(log_line, "\n");
2755 show_line(log_line, 0);
2756 if (show_use) show_usage(av[0]);
2757 else if (quitflag == 3) {
2758 strcat(log_line, "\n");
2759 show_line(log_line, 0);
2762 return -1; // failure
2765 if (floating) testfloating(); /* debugging */
2768 if (replfile != NULL && *replfile != '\0') { /* read user defined replacement */
2769 if (read_xchr_file(replfile, 1, av)) {
2770 if (trace_flag) show_line("KEY REPLACE ON\n", 0);
2774 /* key_replace used in texmf.c (input_line) */
2775 if (xchrfile != NULL && *xchrfile != '\0') { /* read user defined xchr[] */
2776 if (read_xchr_file(xchrfile, 0, av)) {
2777 if (trace_flag) show_line("NON ASCII ON\n", 0);
2781 /* non_ascii used in texmf.c (t_open_in & input_line & call_edit) */
2782 /* see also xchr [] & xord [] use in tex3.c and itex.c */
2787 void uppercase (char *s) {
2789 while ((c = *s) != '\0') {
2790 /* if (islower(c)) *s = toupper (*s); */
2797 int init_commands (int ac, char **av)
2799 /* NOTE: some defaults changed 1993/Nov/18 */
2800 /* want_version = show_use = switchflag = return_flag = false;
2801 is_initex = trace_flag = deslash = non_ascii = false; */
2802 is_initex = false; /* check for dumping format file */
2803 allow_patterns = false; /* using \pattern after format file loaded */
2804 reset_exceptions = false;
2806 key_replace = false;
2807 want_version = false;
2808 open_trace_flag = false;
2810 verbose_flag = false;
2812 restrict_to_ascii = false;
2813 show_in_hex = false; /* default is not to show as hex code ^^ 00/Jun/18 */
2814 show_in_dos = false; /* default is not to translate to DOS 850 */
2815 return_flag = true; // hard wired now
2816 trimeof = true; // hard wired now
2818 pseudo_tilde = 254; /* default '~' replace 95/Sep/26 filledbox DOS 850 */
2819 pseudo_space = 255; /* default ' ' replace 97/June/5 nbspace DOS 850 */
2820 default_rule = 26214; /* default rule variable 95/Oct/9 */
2821 show_current = true;
2822 civilize_flag = true;
2823 show_numeric = true;
2824 show_missing = true;
2825 current_flag = true;
2826 current_tfm = true; /* search for TFMs in current dir as well */
2827 test_dir_access = true; /* test if readable item is perhaps a sub-dir */
2828 dir_method = true; /* in dir_p: _findfirst instead of use fopen (nul) */
2829 file_method = true; /* use file_p (_findfirst) not readable (access) */
2830 /* waitflush = true; */ /* flushed 97/Dec/24 */
2831 c_style_flag = false; /* use c-style error output */
2832 show_fmt_flag = true; /* show format file in log */
2833 show_tfm_flag = false; /* don't show metric file in log */
2834 shorten_file_name = false; /* don't shorten file names to 8+3 */
2835 show_texinput_flag = true; /* show TEXINPUTS and TEXFONTS */
2836 truncate_long_lines = true; /* truncate long lines */
2837 tab_step = 0; /* do not replace tabs with spaces */
2838 format_specific = true; /* do format specific TEXINPUTS 95/Jan/7 */
2839 encoding_specific = true; /* do encoding specific TEXFONTS 98/Jan/31 */
2840 show_line_break_stats = true; /* show line break statistics 96/Feb/8 */
2841 show_fonts_used = true; /* show fonts used in LOG file 97/Dec/24 */
2842 allow_quoted_names = true; /* allow quoted names with spaces 98/Mar/15 */
2843 show_cs_names = false; /* don't show csnames on start 98/Mar/31 */
2844 knuth_flag = false; /* allow extensions to TeX */
2845 cache_file_flag = true; /* default is to cache full file names 96/Nov/16 */
2846 full_file_name_flag = true; /* new default 2000 June 18 */
2847 save_strings_flag = true; // 2000 Aug 15
2848 errout = stdout; /* as opposed to stderr say --- used ??? */
2849 abort_flag = 0; // not yet hooked up ???
2850 err_level = 0; // not yet hooked up ???
2852 new_hyphen_prime = 0;
2853 #ifdef VARIABLETRIESIZE
2854 /* trie_size = default_trie_size; */
2860 #ifdef ALLOCATEDVIBUF
2863 /* share_flag = _SH_DENYNO; */ /* 0x40 - deny none mode */
2864 /* share_flag = _SH_COMPAT; */ /* 0x00 - compatability mode */
2865 share_flag = 0; /* revert to fopen for now */
2867 /* strncpy(programpath, argv[0], PATH_MAX); */ /* 94/July/12 */
2868 programpath = xstrdup(av[0]); /* extract path executable */
2869 strip_name(programpath); /* strip off yandytex.exe */
2871 //format_name = "yandytex";
2872 format_name = "plain"; /* format name if specified on command line */
2876 if (read_commands(yytexcmd) < 0) /* read yandytex.cmd 1994/July/12 */
2877 return -1; // in case of error
2879 if (read_command_line(ac, av) < 0) /* move out to subr 94/Apr/10 */
2880 return -1; // in case of error
2882 if (optind == 0) optind = ac; /* no arg case paranoia 94/Apr/10 */
2884 /* Print version *after* banner ? */ /* does this get in log file ? */
2886 // showversion (stdout);
2887 // showversion (log_line);
2889 strcat(log_line, "\n");
2890 show_line(log_line, 0);
2891 stampcopy(log_line);
2892 strcat(log_line, "\n");
2893 show_line(log_line, 0);
2895 /* if (show_use) show_usage(av[0]); */ /* show usage and quit */
2897 /* if we aren't including current directory in any directory lists */
2898 /* then makes no sense to avoid them separately for TFM files ... */
2899 /* (that is, the ./ is already omitted from the dir list in that case */
2900 if (!current_flag && !current_tfm) current_tfm = true; /* 94/Jan/24 */
2901 return 0; // success
2904 /* E sets environment variable ? */
2906 void initial_memory (void)
2907 { /* set initial memory allocations */
2908 if (mem_extra_high < 0) mem_extra_high = 0;
2909 if (mem_extra_low < 0) mem_extra_low = 0;
2910 if (mem_initex < 0) mem_initex = 0;
2912 #if defined(ALLOCATEHIGH) || defined(ALLOCATELOW)
2913 if (mem_extra_high != 0 || mem_extra_low != 0) {
2914 show_line("ERROR: Cannot extend main memory in iniTeX\n", 1);
2915 mem_extra_high = 0; mem_extra_low = 0;
2920 if (mem_initex != 0) {
2921 show_line("ERROR: Can only set initial main memory size in iniTeX\n", 1);
2924 if (trie_size != 0) {
2925 show_line("ERROR: Need only set hyphenation trie size in iniTeX\n", 1);
2926 /* trie_size = 0; */
2929 if (mem_initex == 0) mem_initex = default_mem_top;
2930 if (trie_size == 0) trie_size = default_trie_size;
2931 /* Just in case user mistakenly specified words instead of kilo words */
2932 if (mem_extra_high > 10000L * 1024L) mem_extra_high = mem_extra_high / 1024;
2933 if (mem_extra_low > 10000L * 1024L) mem_extra_low = mem_extra_low / 1024;
2934 if (mem_initex > 10000L * 1024L) mem_initex = mem_initex / 1024;
2935 #ifdef ALLOCATEHIGH /* not used anymore */
2936 if (mem_extra_high > 2048L * 1024L) { /* extend SW area by 16 mega byte! */
2938 "WARNING: There may be no benefit to asking for so much memory\n", 0);
2939 mem_extra_high = 2048 * 1024; /* limit to SW to 4 x VLR */
2942 #ifdef ALLOCATELOW /* not used anymore */
2943 if (mem_extra_low > 2048L * 1024L) { /* extend VL area by 16 mega byte! */
2945 "WARNING: There may be no benefit to asking for so much memory\n", 0);
2946 mem_extra_low = 2048 * 1024; /* limit VLR to 4 x SW */
2949 if (mem_initex > 2048L * 1024L) { /* extend main memory by 16 mega byte! */
2951 "WARNING: There may be no benefit to asking for so much memory\n", 0);
2952 /* mem_initex = 2048 * 1024; */
2954 #ifdef ALLOCATEDVIBUF
2955 if (dvi_buf_size == 0) dvi_buf_size = default_dvi_buf_size;
2956 /* if less than 1024 assume user specified kilo-bytes, not bytes */
2957 if (dvi_buf_size < 1024) dvi_buf_size = dvi_buf_size * 1024;
2958 if (dvi_buf_size % 8 != 0) /* check multiple of eight */
2959 dvi_buf_size = (dvi_buf_size / 8 + 1) * 8;
2961 if (new_hyphen_prime < 0) new_hyphen_prime = 0;
2962 if (new_hyphen_prime > 0) {
2964 show_line("ERROR: Can only set hyphen prime in iniTeX\n", 1);
2966 if (new_hyphen_prime % 2 == 0) new_hyphen_prime++;
2967 while (!prime(new_hyphen_prime)) new_hyphen_prime = new_hyphen_prime+2;
2969 sprintf(log_line, "Using %d as hyphen prime\n", new_hyphen_prime);
2970 show_line(log_line, 0);
2975 if (percent_grow > 100) percent_grow = percent_grow - 100;
2976 if (percent_grow > 100) percent_grow = 100; /* upper limit - double */
2977 if (percent_grow < 10) percent_grow = 10; /* lower limit - 10% */
2980 /**********************************************************************/
2982 void perrormod (char *s)
2984 sprintf(log_line, "`%s': %s\n", s, strerror(errno));
2985 show_line(log_line, 1);
2991 fflush(stdout); /* ??? */
2992 fflush(stderr); /* ??? */
2993 (void) _getch(); /* ??? */
2997 void checkpause (int flag)
3000 int debug_pause = 0;
3001 /* don't stop if in Q (quiet) or R (run) mode */
3002 /* stop only in S (scroll) and T (TeX) mode */
3003 if (interaction >= 0 && interaction < 2) flag = 0; /* 98/Jun/30 */
3004 s = grabenv("DEBUGPAUSE");
3005 if (s != NULL) sscanf(s, "%d", &debug_pause);
3006 if (flag < 0) return;
3008 if (debug_pause || flag > 0) {
3011 show_line("Press any key to continue . . .\n", 0);
3018 void check_enter (int argc, char *argv[])
3021 char current[FILENAME_MAX];
3022 if (grabenv("DEBUGPAUSE") != NULL) {
3023 (void) _getcwd(current, sizeof(current));
3024 sprintf(log_line, "Current directory: `%s'\n", current);
3025 show_line(log_line, 0);
3026 for (m = 0; m < argc; m++) {
3027 sprintf(log_line, "%2d: `%s'\n", m, argv[m]);
3028 show_line(log_line, 0);
3035 void checkexit (int n) { /* 95/Oct/28 */
3041 /*************************************************************************/
3043 /* convert tilde to pseudo_tilde to hide it from TeX --- 95/Sep/26 */
3044 /* convert space to pseudo_space to hide it from TeX --- 97/Jun/5 */
3045 /* called only if pseudo_tilde != 0 or pseudo_space != 0 */
3046 /* this is then undone in tex3.c both for fopen input and output */
3047 /* not ideal, since pseudo name appears in log and in error messages ... */
3049 void hidetwiddle (char *name)
3054 sprintf(log_line, "Hidetwiddle %s", name);
3055 show_line(log_line, 0);
3058 /* while (*s != '\0' && *s != ' ') { */
3059 while (*s != '\0') {
3060 if (*s == '~' && pseudo_tilde != 0)
3061 *s = (char) pseudo_tilde; /* typically 254 */
3062 else if (*s == ' ' && pseudo_space != 0)
3063 *s = (char) pseudo_space; /* typically 255 */
3068 sprintf(log_line, "=> %s\n", name);
3069 show_line(log_line, 0);
3074 void deslash_all (int ac, char **av)
3076 char buffer[PATH_MAX];
3079 if ((s = getenv("USEDVIWINDOINI")) != NULL)
3080 sscanf(s, "%d", &usedviwindo); /* 94/June/14 */
3082 if (usedviwindo) setupdviwindo(); // moved to yandytex ?
3084 check_enter(ac, av); /* 95/Oct/28 */
3086 /* environment variables for output directories (as in PC TeX) */
3088 if ((s = grabenv("TEXDVI")) != NULL) dvi_directory = s;
3089 if ((s = grabenv("TEXLOG")) != NULL) log_directory = s;
3090 if ((s = grabenv("TEXAUX")) != NULL) aux_directory = s;
3092 strcpy(buffer, av[0]); /* get path to executable */
3093 if ((s = strrchr(buffer, '\\')) != NULL) *(s+1) = '\0';
3094 else if ((s = strrchr(buffer, '/')) != NULL) *(s+1) = '\0';
3095 else if ((s = strrchr(buffer, ':')) != NULL) *(s+1) = '\0';
3096 s = buffer + strlen(buffer) - 1;
3097 if (*s == '\\' || *s == '/') *s = '\0'; /* flush trailing PATH_SEP */
3098 texpath = xstrdup(buffer);
3100 /* Hmm, we may be operating on DOS environment variables here !!! */
3102 if (strcmp(dvi_directory, "") != 0) flush_trailing_slash (dvi_directory);
3103 if (strcmp(log_directory, "") != 0) flush_trailing_slash (log_directory);
3104 if (strcmp(aux_directory, "") != 0) flush_trailing_slash (aux_directory);
3107 unixify (texpath); /* 94/Jan/25 */
3108 /* if output directories given, deslashify them also 1993/Dec/12 */
3109 if (strcmp(dvi_directory, "") != 0) unixify(dvi_directory);
3110 if (strcmp(log_directory, "") != 0) unixify(log_directory);
3111 if (strcmp(aux_directory, "") != 0) unixify(aux_directory);
3114 /* deslash TeX source file (and format, if format specified) */
3115 /* and check args to see whether format was specified */
3118 /* NOTE: assuming that command line arguments are in writable memory ! */
3119 /* if (trace_flag || debug_flag)
3120 sprintf(log_line, "optind %d ac %d\n", optind, ac); */ /* debugging */
3121 /* if (optind < ac) { */ /* bkph */
3122 if (optind < ac && optind > 0) { /* paranoia 94/Apr/10 */
3124 if (trace_flag || debug_flag) {
3125 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3126 optind, av[optind], ac);
3127 show_line(log_line, 0);
3129 unixify(av[optind]);
3131 if (pseudo_tilde != 0 || pseudo_space != 0)
3132 hidetwiddle (av[optind]); /* 95/Sep/25 */
3133 /* For Windows NT, lets allow + instead of & for format specification */
3134 if (*av[optind] == '&' || *av[optind] == '+') {
3135 format_spec = 1; /* format file specified */
3136 format_name = xstrdup(av[optind]+1); /* 94/Oct/25 */
3137 /* uppercase (format_name); */ /* why ? 98/Jan/31 */
3138 if (optind + 1 < ac) {
3140 if (trace_flag || debug_flag) {
3141 sprintf(log_line, "deslash: k %d argv[k] %s (argc %d)\n",
3142 optind+1, av[optind+1], ac);
3143 show_line(log_line, 0);
3145 unixify(av[optind+1]);
3147 if (pseudo_tilde != 0 || pseudo_space != 0)
3148 hidetwiddle (av[optind+1]); /* 95/Sep/25 */
3154 /* The above seems to assume that arguments that don't start with '-' */
3155 /* are file names or format names - what if type in control sequences? */
3157 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3159 /* interaction == 0 => batch mode (omit all stops and omit terminal output) */
3160 /* interaction == 1 => nonstop mode (omit all stops) */
3161 /* interaction == 2 => scroll mode (omit error stops) */
3162 /* interaction == 3 => error_stop mode (stops at every opportunity) */
3164 /* main entry point follows */
3166 /* this gets called pretty much right away in `main' in texmf.c */
3168 /* note: those optarg == 0 test don't really work ... */
3169 /* note: optarg starts at = in case of x=... */
3171 int init (int ac, char **av)
3173 char initbuffer[PATH_MAX];
3176 debugfile = getenv("TEXDEBUG"); /* 94/March/28 */
3183 show_line("TEXDEBUG\n", 0);
3184 trace_flag = 1; /* 94/April/14 */
3187 if (sizeof(memory_word) != 8) { /* compile time test */
3188 sprintf(log_line, "ERROR: Bad word size %d!\n", sizeof(memory_word));
3189 show_line(log_line, 1);
3192 start_time = clock(); /* get time */
3193 main_time = start_time; /* fill in, in case file never opened */
3195 initbuffer[0] = '\0'; /* paranoia 94/Apr/10 */
3197 /* reset all allocatable memory pointers to NULL - in case we drop out */
3202 #ifdef ALLOCATEZEQTB
3208 #ifdef ALLOCATESAVESTACK
3211 #ifdef ALLOCATEDVIBUF
3214 #ifdef ALLOCATEBUFFER
3215 buffer = NULL; /* new 1999/Jan/7 need to do early */
3216 current_buf_size = 0;
3217 buffer = realloc_buffer (initial_buf_size);
3218 /* sprintf(log_line, "buffer %x, current_buf_size %d\n", buffer, current_buf_size); */
3220 hyph_list = NULL; hyph_word = NULL;
3221 trie_taken = NULL; trie_hash = NULL;
3222 trie_r = NULL; trie_c = NULL; trie_o = NULL; trie_l = NULL;
3223 trie_trc = NULL; trie_tro = NULL; trie_trl = NULL;
3225 log_opened = false; /* so can tell whether opened */
3226 interaction = -1; /* default state => 3 */
3227 missing_characters = 0; /* none yet! */
3228 workingdirectory = false; /* set from dviwindo.ini & command line */
3229 font_dimen_zero = true; /* \fontdimen0 for checksum 98/Oct/5 */
3230 ignore_frozen = false; /* default is not to ignore 98/Oct/5 */
3231 suppress_f_ligs = false; /* default is not to ignore f-ligs */
3232 /* if (*av[1] == '-Y') reorder_arg_flag = false; */ /* 94/April/14 */
3233 if (ac > 1 && *av[1] == '-Y') reorder_arg_flag = false;
3235 if (reorder_arg_flag) reorderargs(ac, av);
3237 if (init_commands(ac, av))
3238 return -1; // failure
3240 check_fixed_align(trace_flag); /* sanity check 1994/Jan/8 */
3242 format_file = NULL; /* to be set in openinou.c 94/Jun/21 */
3243 string_file = NULL; /* to be set in openinou.c 96/Jan/15 */
3244 source_direct = NULL; /* to be set in openinou.c 98/Sep/29 */
3245 dvi_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3246 log_file_name = NULL; /* to be set in openinou.c 00/Jun/18 */
3248 first_pass_count = 0;
3249 second_pass_count = 0;
3250 final_pass_count = 0;
3251 paragraph_failed = 0;
3258 closed_already=0; // so can only do once
3260 if (trace_flag) show_line("Entering init (local)\n", 0);
3262 /* Print version *after* banner ? */ /* does this get in log file ? */
3264 probe_memory (); /* show top address */
3265 ini_max_address = max_address; /* initial max address */
3266 if (trace_flag) show_maximums(stdout);
3268 if (heap_flag) (void) heap_dump(stdout, 1);
3273 deslash_all(ac, av); /* deslash and note if format specified */
3275 /* sprintf(log_line, "%s\n", initbuffer); */ /* debugging, remove later */
3279 if (format_spec && mem_spec_flag) {
3280 show_line("WARNING: Cannot change initial main memory size when format specified", 1);
3283 if (allocate_memory() != 0) /* NOW, try and ALLOCATE MEMORY if needed */
3284 return -1; // if failed to allocate
3286 /* following is more or less useless since most all things not yet alloc */
3287 check_alloc_align(trace_flag); /* sanity check 1994/Jan/8 */
3289 if (trace_flag) showaddresses(); /* debugging only 1996/Jan/20 */
3293 /* if (heap_flag) heap_dump(stdout, 1); */ /* redundant ? */
3296 if (trace_flag) show_line("Leaving init (local)\n", 0);
3297 return 0; // success
3300 /* #define CLOCKS_PER_SEC 1000 */ /* #define CLK_TCK CLOCKS_PER_SEC */
3302 /* void show_inter_val (clock_t start, clock_t end) { */
3303 void show_inter_val (clock_t interval)
3305 /* clock_t interval; */
3306 /* int seconds, tenths; */
3307 /* int seconds, tenths, hundredth; */
3308 int seconds, tenths, hundredth, thousands;
3309 /* interval = end - start; */
3310 /* sanity check whether positive ? */
3311 if (interval >= CLK_TCK * 10) {
3312 tenths = (interval * 10 + CLK_TCK / 2) / CLK_TCK;
3313 seconds = tenths / 10;
3314 tenths = tenths % 10;
3315 sprintf(log_line, "%d.%d", seconds, tenths);
3316 show_line(log_line, 0);
3318 else if (interval >= CLK_TCK) { /* 94/Feb/25 */
3319 hundredth = (interval * 100 + CLK_TCK / 2) / CLK_TCK;
3320 seconds = hundredth / 100;
3321 hundredth = hundredth % 100;
3322 sprintf(log_line, "%d.%02d", seconds, hundredth);
3323 show_line(log_line, 0);
3325 else if (interval > 0) { /* 94/Oct/4 */
3326 thousands = (interval * 1000 + CLK_TCK / 2) / CLK_TCK;
3327 seconds = thousands / 1000;
3328 thousands = thousands % 1000;
3329 sprintf(log_line, "%d.%03d", seconds, thousands);
3330 show_line(log_line, 0);
3332 else show_line("0", 0); /* 95/Mar/1 */
3335 /* final cleanup opportunity */ /* flag is non-zero if error exit */
3336 /* shows various times, warning about missing chars */
3338 int endit (int flag)
3341 finish_time = clock();
3342 if (missing_characters != 0) flag = 1;
3343 if (missing_characters) {
3345 "! There %s %d missing character%s --- see log file\n",
3346 (missing_characters == 1) ? "was" : "were", missing_characters,
3347 (missing_characters == 1) ? "" : "s");
3348 show_line(log_line, 0);
3350 if (free_memory() != 0) flag++;
3352 /* show per page time also ? */
3354 /* sprintf(log_line, "start %ld main %ld finish %ld\n",
3355 start_time, main_time, finish_time); */
3356 show_line("Total ", 0);
3357 /* show_inter_val(start_time, finish_time); */
3358 show_inter_val(finish_time - start_time);
3359 show_line(" sec (", 0);
3360 /* show_inter_val(start_time, main_time); */
3361 show_inter_val(main_time - start_time);
3362 show_line(" format load + ", 0);
3363 /* show_inter_val(main_time, finish_time); */
3364 show_inter_val(finish_time - main_time);
3365 show_line(" processing) ", 0);
3366 if (total_pages > 0) {
3367 /* msec = (finish_time - main_time) * 1000 / (CLK_TCK * total_pages); */
3368 /* sprintf(log_line, " %d.%d sec per page", msec / 1000, msec % 1000); */
3369 /* sprintf(log_line, " %d.%03d sec per page", msec / 1000, msec % 1000); */
3370 show_inter_val ((finish_time - main_time) / total_pages);
3371 show_line(" sec per page", 0);
3381 /********************************************************************************/
3383 /* addition 98/Mar/31 print_csnames Frank Mittelbach */
3387 #define MAXCOLUMN 78
3389 void print_cs_name (FILE *output, int h)
3394 textof = hash[h].v.RH;
3395 if (textof == 0) return; /* ignore if text() == 0 */
3396 n = str_start[textof + 1] - str_start[textof];
3397 if (textcolumn != 0) {
3398 sprintf(log_line, ", ");
3399 if (output != NULL) fprintf(output, log_line);
3400 else show_line(log_line, 0);
3403 if (textcolumn + n + 2 >= MAXCOLUMN) {
3404 sprintf(log_line, "\n");
3405 if (output == stderr) show_line(log_line, 1);
3406 else if (output == stdout) show_line(log_line, 0);
3407 else fputs(log_line, output);
3411 for (c = str_start[textof]; c < str_start[textof+1]; c++) {
3414 if (output == stderr) show_line(log_line, 1);
3415 else if (output == stdout) show_line(log_line, 0);
3416 else fprintf(output, log_line);
3420 int comparestrn (int, int, int, int); /* in tex9.c */
3422 /* compare two csnames in qsort */
3424 int comparecs (const void *cp1, const void *cp2)
3426 int c1, c2, l1, l2, k1, k2, textof1, textof2;
3429 textof1 = hash[c1].v.RH;
3430 textof2 = hash[c2].v.RH;
3431 l1 =(str_start[textof1 + 1] - str_start[textof1]);
3432 l2 =(str_start[textof2 + 1] - str_start[textof2]);
3433 k1 = str_start[textof1];
3434 k2 = str_start[textof2];
3435 /* showstring (k1, l1); */
3436 /* showstring (k2, l2); */
3437 return comparestrn (k1, l1, k2, l2);
3442 /* Allocate table of indeces to allow sorting on csname */
3443 /* Allocate flags to remember which ones already listed at start */
3445 void print_cs_names (FILE *output, int pass)
3447 int h, k, ccount, repeatflag;
3449 int nfcs = hash_base + hash_size + hash_extra; /* frozen_control_sequence */
3451 if (pass == 0 && csused == NULL) {
3452 csused = (char *) malloc (nfcs);
3453 if (csused == NULL) return;
3455 memset(csused, 0, nfcs);
3457 for (h = 0; h < (hash_size+780); h++) csused[h] = 0;
3462 for (h = hash_base + 1; h < nfcs; h++) {
3463 if (pass == 1 && csused[h]) continue;
3464 if(hash[h].v.RH != 0) {
3465 if (pass == 0) csused[h] = 1;
3470 sprintf(log_line, "\n%d %s multiletter control sequences:\n\n",
3471 ccount, (pass == 1) ? "new" : "");
3472 if (output == stderr) show_line(log_line, 1);
3473 else if (output == stdout) show_line(log_line, 0);
3474 else fprintf(output, log_line);
3476 if (ccount > 0) { /* don't bother to get into trouble */
3478 cnumtable = (int *) malloc (ccount * sizeof(int));
3479 if (cnumtable == NULL) return;
3482 /* for (h = 515; h < (hash_size + 780); h++) { */
3483 for (h = hash_base+1; h < nfcs; h++) {
3484 if (pass == 1 && csused[ h]) continue;
3485 if(hash[h].v.RH != 0) cnumtable[ccount++] = h;
3488 qsort ((void *)cnumtable, ccount, sizeof (int), &comparecs);
3491 for (k = 0; k < ccount; k++) {
3493 if (pass == 1 && csused[ h]) continue;
3494 print_cs_name(output, h);
3496 sprintf(log_line, "\n");
3497 if (output == stderr) show_line(log_line, 1);
3498 else if (output == stdout) show_line(log_line, 0);
3499 else fprintf(output, log_line);
3500 free((void *)cnumtable);
3503 if (pass == 1 && csused != NULL) {
3509 /***************** font info listing moved from TEX9.C ******************/
3511 void showstring (int k, int l)
3514 while (l-- > 0) *s++ = str_pool[k++];
3517 show_line(log_line, 0);
3520 /* compare two strings in str_pool (not null terminated) */
3521 /* k1 and k2 are positions in string pool */
3522 /* l1 and l2 are lengths of strings */
3524 int comparestrn (int k1, int l1, int k2, int l2)
3527 /* while (l1-- > 0 && l2-- > 0) { */
3528 while (l1 > 0 && l2 > 0) {
3531 /* sprintf(log_line, "%c%d%c%d ", c1, l1, c2, l2); */
3532 if (c1 > c2) return 1;
3533 else if (c2 > c1) return -1;
3537 if (l1 > 0) return 1; /* first string longer */
3538 else if (l2 > 0) return -1; /* second string longer */
3539 return 0; /* strings match */
3542 /* compare two font names and their at sizes in qsort */
3544 int comparefnt (const void *fp1, const void *fp2)
3546 int f1, f2, l1, l2, k1, k2, s;
3549 l1 =(str_start[font_name[f1]+ 1] - str_start[font_name[f1]]);
3550 l2 =(str_start[font_name[f2]+ 1] - str_start[font_name[f2]]);
3551 k1 = str_start[font_name[f1]];
3552 k2 = str_start[font_name[f2]];
3553 /* showstring (k1, l1); */
3554 /* showstring (k2, l2); */
3555 s = comparestrn (k1, l1, k2, l2);
3556 /* sprintf(log_line, "%d\n", s); */
3557 if (s != 0) return s;
3558 if (font_size[f1]> font_size[f2]) return 1;
3559 else if (font_size[f1]< font_size[f2]) return -1;
3560 return 0; /* should not ever get here */
3563 /* compare two font names */
3565 int comparefntname (int f1, int f2)
3567 int l1, l2, k1, k2, s;
3568 l1 =(str_start[font_name[f1]+ 1] - str_start[font_name[f1]]);
3569 l2 =(str_start[font_name[f2]+ 1] - str_start[font_name[f2]]);
3570 k1 = str_start[font_name[f1]];
3571 k2 = str_start[font_name[f2]];
3572 /* showstring (k1, l1); */
3573 /* showstring (k2, l2); */
3574 s = comparestrn (k1, l1, k2, l2);
3575 /* sprintf(log_line, "%d\n", s); */
3579 /* decode checksum information */
3581 unsigned long checkdefault = 0x59265920; /* default signature */
3583 int decode_fourty (unsigned long checksum, char *codingvector)
3587 /* char codingvector[6+1]; */
3589 /* if (checksum == checkdefault) { */
3590 if (checksum == 0) {
3591 /* strcpy(codingvector, "unknown"); */
3592 strcpy(codingvector, "unknwn");
3595 else if ((checksum >> 8) == (checkdefault >> 8)) { /* last byte random */
3596 /* strcpy (codingvector, "native"); */ /* if not specified ... */
3597 strcpy (codingvector, "fixed "); /* if not specified ... */
3598 return 1; /* no info available */
3601 for (k = 0; k < 6; k++) {
3602 c = (int) (checksum % 40);
3603 checksum = checksum / 40;
3604 if (c <= 'z' - 'a')c = c + 'a';
3605 else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
3606 else if (c == 36) c = '-';
3607 else if (c == 37) c = '&';
3608 else if (c == 38) c = '_';
3609 else c = '.'; /* unknown */
3610 codingvector[5-k] = (char) c;
3612 codingvector[6] = '\0';
3614 /* sprintf(log_line, "Reconstructed vector %s\n", codingvector); */
3615 return 0; /* encoding info returned in codingvector */
3618 double sclpnt (long x)
3621 pt = (double) x / 65536.0;
3622 pt = (double) ((int) (pt * 1000.0 + 0.5)) / 1000.0;
3626 // Shows list of fonts in log file
3628 void dvi_font_show(internal_font_number f, int suppressname)
3630 int a, l, k, n, for_end;
3631 unsigned long checksum;
3632 char checksumvector[8];
3635 /* fprintf (log_file, "DAMN! %d ", suppressname); */
3636 /* fprintf (log_file, "%d ", suppressname); */
3637 /* suppressname = 0; */
3638 putc(' ', log_file);
3639 if (suppressname == 0) {
3640 a = (str_start[font_area[f]+ 1]- str_start[font_area[f]]);
3641 l = (str_start[font_name[f]+ 1]- str_start[font_name[f]]);
3642 k = str_start[font_area[f]];
3643 for_end = str_start[font_area[f]+ 1]- 1;
3644 if(k <= for_end) do {
3645 putc(str_pool[k], log_file);
3646 } while(k++ < for_end, stdout);
3647 k = str_start[font_name[f]];
3648 for_end = str_start[font_name[f]+ 1]- 1;
3649 if(k <= for_end) do {
3650 putc(str_pool[k], log_file);
3651 } while(k++ < for_end);
3654 for (k = a+l; k < 16; k++) putc(' ', log_file);
3655 sprintf(buffer, "at %lgpt ", sclpnt(font_size[f]));
3656 fputs(buffer, log_file);
3657 // fprintf(log_file, "at %lgpt ", sclpnt(font_size[f]));
3658 if (suppressname == 0) {
3660 // n = strlen(log_file);
3661 for (k = n; k < 16; k++) putc(' ', log_file);
3662 checksum = (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
3663 font_check[f].b2) << 8 | font_check[f].b3;
3664 decode_fourty(checksum, checksumvector);
3665 fprintf(log_file, "encoding: %s..", checksumvector);
3667 putc('\n', log_file);
3670 /* Allocate table of indeces to allow sorting on font name */
3672 void show_font_info (void)
3674 int k, m, fcount, repeatflag;
3678 for (k = 1; k <= font_ptr; k++)
3679 if(font_used[k])fcount++;
3681 if (fcount == 0) return; /* don't bother to get into trouble */
3683 fnumtable = (short *) malloc (fcount * sizeof(short));
3685 /* if (verbose_flag) sprintf(log_line, "\nUsed %d fonts:\n", fcount); */
3687 fprintf(log_file, "\nUsed %d font%s:\n",
3688 fcount, (fcount == 1) ? "" : "s");
3691 for (k = 1; k <= font_ptr; k++)
3692 if(font_used[k])fnumtable[fcount++] = (short) k;
3694 qsort ((void *)fnumtable, fcount, sizeof (short), &comparefnt);
3697 for (m = 0; m < fcount; m++) {
3699 if (comparefntname(fnumtable[m-1], fnumtable[m]) == 0)
3701 else repeatflag = 0;
3703 dvi_font_show(fnumtable[ m], repeatflag);
3706 free((void *)fnumtable);
3709 ////////////////////////////////////////////////////////////////////////////
3711 // Here follows the new stuff for the DLL version
3717 #define SHOWLINEBUFLEN 256
3719 char showlinebuf[SHOWLINEBUFLEN];
3721 // char log_line[MAXLINE];
3723 #define WHITESPACE " \t\n\r"
3725 HINSTANCE hInstanceDLL=NULL; /* remember for this DLL */
3727 /* This is the callback function for the EDITTEXT Control in CONSOLETEXT */
3729 #define GET_WM_COMMAND_CMD(wParam, lParam) (HIWORD(wParam))
3730 #define GET_WM_COMMAND_ID(wParam, lParam) (LOWORD(wParam))
3731 #define GET_WM_COMMAND_HWND(wParam, lParam) ((HWND)lParam)
3733 HWND hConsoleWnd=NULL; /* Console Text Window Handle passed from DVIWindo */
3735 void ClearShowBuffer (void)
3737 showlinebuf[showlineinx++] = '\0'; // clear out accumulated stuff
3738 if (hConsoleWnd != NULL)
3739 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) showlinebuf, 0L);
3743 // communicate with DVIWindo (for yandytex.dll)
3745 void show_line (char *line, int errflag) { /* 99/June/11 */
3748 if (IsWindow(hConsoleWnd) == 0) { // in case the other end died
3749 sprintf(line, "NO CONSOLE WINDOW? %08X %s", hConsoleWnd, line);
3750 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3752 // abort_flag++; // kill job in this case ???
3756 if (showlineinx > 0) ClearShowBuffer();
3758 if (hConsoleWnd != NULL)
3759 SendMessage(hConsoleWnd, ICN_ADDTEXT, (WPARAM) line, 0L);
3763 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3764 if (ret == IDCANCEL) {
3766 uexit(1); // dangerous reentry possibility ?
3771 // Provide means for buffering up individual characters
3773 void show_char (int chr) {
3774 if (showlineinx +2 >= SHOWLINEBUFLEN) ClearShowBuffer();
3775 showlinebuf[showlineinx++] = (char) chr;
3776 if (chr == '\n') ClearShowBuffer();
3779 void winshow(char *line) {
3780 (void) MessageBox(NULL, line, "YandYTeX", MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
3783 void winerror (char *line) {
3785 ret = MessageBox(NULL, line, "YandYTeX", MB_ICONSTOP | MB_OKCANCEL | MB_TASKMODAL);
3786 if (ret == IDCANCEL) abort_flag++;
3789 // argument info constructed from command line
3795 // need to be careful here because of quoted args with spaces in them
3796 // e.g. -d="G:\Program Files\Adobe\Acrobat\*.pdf"
3798 int makecommandargs (char *line)
3802 unsigned char *s, *t; // fix 2000 June 18
3804 if (line == NULL) return -1; /* sanity check */
3806 // winerror(line); // debugging only
3808 // s = strtok(line, WHITESPACE);
3809 // while (s != NULL) { /* count arguments */
3811 // s = strtok(NULL, WHITESPACE);
3816 while (*s != '\0') {
3817 while (*s <= 32 && *s > 0) s++;
3818 if (*s == '\0') break;
3820 while (*t > 32 && *t != '\"') t++;
3823 while (*t > 0 && *t != '\"') t++;
3824 if (*t == '\0') break;
3827 // xargv[xargc] = s;
3829 if (*t == '\0') break;
3834 if (xargc == 0) return -1; /* nothing to do */
3836 xargv = (char **) malloc(xargc * sizeof(char *));
3837 if (xargv == NULL) {
3838 sprintf(log_line, "ERROR: Unable to allocate memory for %s\n", "arguments");
3845 while (*s != '\0') {
3846 while (*s <= ' ' && *s > '\0') s++; /* eat white space */
3847 if (*s == '\0') break;
3849 while (*t > ' ' && *t != '\"') t++;
3852 while (*t > 0 && *t != '\"') t++;
3853 if (*t == '\0') break;
3856 // winerror(s); // debugging only
3859 if (*t == '\0') break;
3865 // for (k = 0; k < xargc; k++) { /* create pointers to args */
3866 // while (*s > '\0' && *s <= ' ') s++; /* eat white space */
3868 // s += strlen(s) +1;
3874 for (k = 0; k < xargc; k++) {
3875 sprintf(s, "%d\t%s\n", k, xargv[k]);
3883 // refers to TeXAsk in dviwindo.c
3885 // int (* AskUserCall) (char *, char *) = NULL; // callback for user questions
3886 int (* AskUserCall) (char *, char *, char *) = NULL; // callback for user questions
3888 // called from tex0.c only --- by initterm and term_input
3890 //int ConsoleInput (char *question, char *buffer)
3891 int ConsoleInput (char *question, char *help, char *buffer)
3895 if (AskUserCall == NULL) return 0;
3896 // sprintf(log_line, "str_start %x %x\n", str_start, str_start [831]);
3897 // show_line(log_line, 1);
3900 ret = AskUserCall (question, help, buffer); // value returned by dialogbox
3901 // strcpy(buffer, "x");
3902 // strcat(buffer, " "); // ???
3903 // sprintf(log_line, "str_start %x %x\n", str_start, str_start[831]);
3904 // show_line(log_line, 1);
3905 // input_line_finish(); // ???
3906 // s = buffer + strlen(buffer);
3907 // *s++ = ' '; // space terminate
3908 // *s++ = '\0'; // and null terminate
3909 // returning != 0 means EOF or ^Z
3913 // This is the new entry point of DLL called from DVIWindo
3914 // ARGS: console window to send messages to, command line, callback fun
3915 // no console window output if hConsole is NULL
3916 // returns -1 if it fails --- returns 0 if it succeeds
3918 // MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *)) {
3919 MYLIBAPI int yandytex (HWND hConsole, char *line, int (* AskUser) (char *, char *, char *))
3923 abort_flag = 0; // redundant
3924 hConsoleWnd = NULL; // redundant
3926 AskUserCall = AskUser; // remember callback
3928 hConsoleWnd = hConsole; // remember console window handle
3930 // can't getenv("DEBUGPAUSE") cause setupdviwindo not called yet
3931 // if (grabenv("DEBUGPAUSE") != NULL) {
3932 // show_line(line, 0); // debugging - show command line
3933 // show_line("\n", 0);
3936 xargc = makecommandargs(line); // sets up global *xargv[]
3938 if (xargc < 0) return -1; // sanity check
3940 if (hConsoleWnd != NULL)
3941 SendMessage(hConsoleWnd, ICN_SETTITLE, (WPARAM) "YandYTeX", 0L);
3942 // SendMessage(hConsoleWnd, ICN_RESET, 0, 0L); // if want to clear window
3945 (void) main(xargc, xargv); // now run YandYTeX proper in texmf.c
3947 if (err_level > 0 || abort_flag > 0) {
3948 // sprintf(log_line, "ERRORS in Processing (err %d abort %d)\n",
3949 // err_level, abort_flag);
3950 // winerror(log_line);
3953 // if (psbufpos > 0) sendpsbuffer(output); // empty out PS buffer
3954 // if (psbufpos > 0) PSputs("", output); // output already closed
3956 if (hConsoleWnd != NULL) {
3957 if (err_level > 0 || abort_flag > 0) flag = 1;
3958 else flag = 0; // pass along error indication
3959 SendMessage(hConsoleWnd, ICN_DONE, flag, 0); // flush out console buffer
3961 // PScallback = NULL;
3964 if (xargv != NULL) free(xargv);
3965 if (abort_flag) return -1;
3969 BOOL WINAPI DllMain (HINSTANCE hInstDll, DWORD fdwReason, LPVOID fImpLoad)
3972 switch (fdwReason) {
3973 case DLL_PROCESS_ATTACH:
3974 // The DLL is being mapped into the process's address space
3975 // place to allocate memory ???
3976 // return FALSE if this fails
3977 hInstanceDLL = hInstDll; /* remember it */
3980 case DLL_THREAD_ATTACH:
3981 // A thread is being created
3984 case DLL_THREAD_DETACH:
3985 // A thread is exiting cleanly
3988 case DLL_PROCESS_DETACH:
3989 // The DLL is being unmapped from the process's address space
3990 // place to free any memory allocated
3991 // but make sure it in fact *was* allocated
3992 hInstanceDLL = NULL; /* forget it */
3995 return(TRUE); // used only for DLL_PROCESS_ATTACH
3997 #endif // end of new stuff for DLL version
3999 //////////////////////////////////////////////////////////////////////////////
4003 /* NOTE: current_tfm = false (-c)
4004 not checking for TFM in current directory saves 0.1 sec
4005 (0.2 if file_method = false (-G) */
4007 /* NOTE: test_dir_access = false (-b):
4008 not checking whether readable file is a directory saves maybe 0.5 sec
4009 BUT only if file_method = false (-G) - otherwise its irrelevant */
4011 /* NOTE: dir_method = false (-D) --- method for checking whether directory
4012 using fopen instead of _findfirst in dir_p slows job maybe 0.05 sec
4013 BUT not if current_tfm = false (-c) */
4015 /* NOTE: file_method = false (-G) --- method for checking file accessible
4016 using _access (readable) instead of _findfirst (file_p) costs 0.5 sec */
4018 /* Fast flag combinations: nothing, bG, bcG, bcDG */
4020 /* constants for _heapchk/_heapset/_heapwalk routines */
4021 /* #define _HEAPEMPTY (-1) */
4022 /* #define _HEAPOK (-2) */
4023 /* #define _HEAPBADBEGIN (-3) */
4024 /* #define _HEAPBADNODE (-4) */
4025 /* #define _HEAPEND (-5) */
4026 /* #define _HEAPBADPTR (-6) */
4028 /* new arg -H=8 for horizontal tab *//* tab_step = 0 means no tab replacement */
4030 /* buffercopy no longer used */
4032 /* To Knuthian reset right when command line interpreted */